27 #include "hardware/GPIO_odb.h"
31 #include "modules/pifacedigital/PFGPIO_odb.h"
34 #include "pifacedigital.h"
40 #include <boost/iterator/transform_iterator.hpp>
41 #include <boost/uuid/uuid_io.hpp>
44 #include <odb/schema-catalog.hxx>
55 zmqpp::socket *module_manager_pipe,
56 const boost::property_tree::ptree &config,
58 :
BaseModule(ctx, module_manager_pipe, config, utils)
59 , bus_push_(ctx_,
zmqpp::socket_type::push)
60 , ws_helper_thread_(utils)
61 , degraded_mode_(false)
63 if (pifacedigital_open(0) == -1)
67 ERROR(
"Cannot open PifaceDigital device. Are you running on device with SPI "
68 "bus and have SPI linux kernel module enabled ?");
72 for (uint8_t hw_addr = 1; hw_addr < 4; ++hw_addr)
74 if (pifacedigital_open(hw_addr) == -1)
76 ERROR(
"Failed to initialize pifacedigital with hardware address"
81 int ret = pifacedigital_enable_interrupts();
82 ASSERT_LOG(ret == 0,
"Failed to enable interrupt on piface board");
85 bus_push_.connect(
"inproc://zmq-bus-pull");
91 std::string path_to_gpio =
92 "/sys/class/gpio/gpio" + std::to_string(GPIO_INTERRUPT_PIN) +
"/value";
93 interrupt_fd_ = open(path_to_gpio.c_str(), O_RDONLY | O_NONBLOCK);
95 pifacedigital_read_reg(0x11, 0);
100 zmqpp::poller::poll_pri | zmqpp::poller::poll_error);
116 [](
const PFDigitalPin &p) -> std::chrono::system_clock::time_point {
117 return p.next_update();
121 boost::make_transform_iterator(
gpios_.begin(), itr_transform),
122 boost::make_transform_iterator(
gpios_.end(), itr_transform));
124 for (
auto &gpio_pin :
gpios_)
126 if (gpio_pin.next_update() < std::chrono::system_clock::now())
139 std::array<char, 64> buffer{};
144 "Reading on interrupt_fd gave unexpected return value: " << ret);
147 "Lseeking on interrupt_fd gave unexpected return value: " << ret);
149 for (uint8_t hwaddr = 0; hwaddr < 4; ++hwaddr)
151 uint8_t states = pifacedigital_read_reg(0x11, hwaddr);
152 for (
int i = 0; i < 8; ++i)
154 if (((states >> i) & 0x01) == 0)
157 std::string gpio_name;
161 << std::string(
"S_INT:" + gpio_name));
170 for (
const auto &gpio :
gpios_)
173 gpio.hardware_address_ == hw_addr)
184 boost::property_tree::ptree module_config = cfg.get_child(
"module_config");
186 for (
auto &node : module_config.get_child(
"gpios"))
188 boost::property_tree::ptree gpio_cfg = node.second;
190 std::string gpio_name = gpio_cfg.get<std::string>(
"name");
191 int gpio_no = gpio_cfg.get<uint8_t>(
"no");
192 std::string gpio_direction = gpio_cfg.get<std::string>(
"direction");
193 bool gpio_value = gpio_cfg.get<
bool>(
"value",
false);
194 uint8_t hw_addr = gpio_cfg.get<uint8_t>(
"hardware_address", 0);
196 INFO(
"Creating GPIO " << gpio_name <<
", with no " << gpio_no
197 <<
". direction = " << gpio_direction
198 <<
"Hardware address: " << (
int)hw_addr);
203 gpio_value, hw_addr);
205 if (gpio_direction !=
"in" && gpio_direction !=
"out")
206 throw GpioException(
"Direction (" + gpio_direction +
") is invalid");
207 gpios_.push_back(std::move(pin));
208 utils_->config_checker().register_object(gpio_name,
215 bool use_db =
config_.get<
bool>(
"module_config.use_database",
false);
218 throw LEOSACException(
"We failed to open piface digital device and wont "
219 "enable database support. There is nothing to do but "
235 ASSERT_LOG(hwd_service,
"No hardware service but we have database.");
249 using namespace odb::core;
250 auto db =
utils_->database();
251 schema_version v = db->schema_version(
"module_pifacedigital");
252 schema_version cv(schema_catalog::current_version(*db,
"module_pifacedigital"));
255 transaction t(db->begin());
256 schema_catalog::create_schema(*db,
"module_pifacedigital");
261 INFO(
"PIFACEDIGITAL_GPIO Module performing database migration. Going from "
263 << v <<
" to version " << cv);
264 transaction t(db->begin());
265 schema_catalog::migrate(*db, cv,
"module_pifacedigital");
272 using Result = odb::result<PFGPIO>;
274 odb::transaction t(db->begin());
280 INFO(
"Not creating GPIO object because the module is running in degraded "
284 for (
const auto &gpio : result)
288 if (gpio.number() > std::numeric_limits<uint8_t>::max())
290 WARN(
"Cannot create GPIO "
292 <<
" because its number is too big: " << gpio.number());
296 INFO(
"Creating GPIO "
297 << gpio.name() <<
", with no " << gpio.number() <<
". direction = "
300 gpio.default_value(), gpio.hardware_address());
301 gpios_.push_back(std::move(pin));
302 utils_->config_checker().register_object(gpio.name(),
318 if (parameters_.degraded_mode)
320 "Cannot test Piface Digital GPIO when running in degraded mode.");
323 odb::transaction t(db->begin());
324 auto gpio = db->find<
PFGPIO>(gpio_id);
333 if (!core_utils_->config_checker().has_object(gpio->name(),
337 "",
"GPIO doesn't exist in the runtime configuration checker. "
338 "This probably means that you need to restart Leosac to load the "
339 "new configuration");
343 Hardware::FGPIO gpio_facade(core_utils_->zmqpp_context(), gpio->name());
346 for (
int i = 0; i < 8; ++i)
349 std::this_thread::sleep_for(std::chrono::milliseconds(750));
357 json j{{
"mode", mode}};
360 "pfdigital.is_degraded_mode");
362 ws_service.register_handler(
368 this->test_output_pin(gpio_id);
371 "pfdigital.test_output_pin");