#include <atomic>
#include <chrono>
#include <csignal>
#include <cstddef>
#include <iostream>
#include <thread>
#include <lxmaster/lxmaster.hpp>
static std::atomic<bool> g_interrupted{false};
static void onSignal(int) { g_interrupted = true; }
static void installSignalHandler() {
struct sigaction sa{};
sa.sa_handler = onSignal;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, nullptr);
sigaction(SIGTERM, &sa, nullptr);
}
constexpr int kNumBits = 16;
constexpr double kBitIntervalS = 1.0;
static double elapsedS(std::chrono::steady_clock::time_point now,
std::chrono::steady_clock::time_point start) {
return std::chrono::duration<double>(now - start).count();
}
static int activeBitAt(std::chrono::steady_clock::time_point now,
std::chrono::steady_clock::time_point start) {
const int bit = static_cast<int>(elapsedS(now, start) / kBitIntervalS);
return bit < kNumBits ? bit : -1;
}
static void applyBit(lxmaster::IoModule* mod, int bit) {
for (int ch = 0; ch < kNumBits; ++ch) {
mod->writeDigital(static_cast<std::size_t>(ch), false);
}
mod->writeDigital(static_cast<std::size_t>(bit), true);
std::cout << "Bit " << bit << " ON\n";
}
int main() {
installSignalHandler();
lxmaster::NetworkConfig cfg = lxmaster::NetworkConfig::defaults();
if (cfg.bus.ifname.empty()) {
std::cerr << "No EtherCAT interface: set LXMASTER_RT_IFACE in /etc/profile.d/lxmaster-config.sh "
"(run lxmaster host setup first).\n";
return 1;
}
cfg.eni.eni_path = "/home/user/myenifolder/myenifile.xml";
lxmaster::EcNetwork net(cfg);
if (!net.prepare()) {
std::cerr << "EcNetwork::prepare() failed: " << net.lastError() << "\n";
return 1;
}
lxmaster::IoModule* mod = nullptr;
for (lxmaster::IoModule* m : net.ioModules()) {
if (m->digitalOutputCount() >= static_cast<std::size_t>(kNumBits)) {
mod = m;
break;
}
}
if (mod == nullptr) {
std::cerr << "No I/O module with >= " << kNumBits
<< " digital outputs found on the bus.\n";
return 1;
}
mod->configure();
if (!net.start()) {
std::cerr << "EcNetwork::start() failed: " << net.lastError() << "\n";
return 1;
}
std::cout << "Found I/O module: \"" << mod->name() << "\""
<< " (" << mod->digitalOutputCount() << " digital outputs)\n"
<< "Running " << kNumBits << "-bit left shift...\n";
for (int ch = 0; ch < kNumBits; ++ch) {
mod->writeDigital(static_cast<std::size_t>(ch), false);
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
const auto start = std::chrono::steady_clock::now();
int active_bit = -1;
while (net.isRunning() && !g_interrupted) {
const auto now = std::chrono::steady_clock::now();
const int bit = activeBitAt(now, start);
if (bit < 0) break;
if (bit != active_bit) {
active_bit = bit;
applyBit(mod, bit);
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
if (!net.isRunning() && !g_interrupted) {
std::cerr << "EtherCAT cyclic thread stopped mid-run: " << net.lastError() << "\n";
net.stop();
return 1;
}
for (int ch = 0; ch < kNumBits; ++ch) {
mod->writeDigital(static_cast<std::size_t>(ch), false);
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
net.stop();
std::cout << "Done.\n";
return 0;
}