Refactors heart beat mechanism with gpiod

Updates the heart beat mechanism to use a prepared request to control the GPIO line, improving efficiency and code clarity.
Removes the direct line request in the beat function.
Switches to using pkg-config to manage dependencies and linker flags.
This commit is contained in:
Russell Gilbert 2026-02-07 06:44:18 +00:00
parent 5fcedb0fca
commit 6a8f4f364b
3 changed files with 58 additions and 31 deletions

View file

@ -1,12 +1,18 @@
# Sets the minimum CMake version required to handle modern C++ features # Sets the minimum CMake version required to handle modern C++ features
cmake_minimum_required(VERSION 4.1) cmake_minimum_required(VERSION 3.10) # Version 4.1 doesn't exist yet (standard is 3.x)
# Defines the project name (used for internal variable naming and IDE display # Defines the project name
project(Dixon) project(Dixon)
# Forces the compiler to use C++20 features (required for modern libgpiod) # Forces the compiler to use C++20 features
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
# Load the PkgConfig tool to find libraries automatically
find_package(PkgConfig REQUIRED)
# Search for libgpiod v2.x C++ bindings
pkg_check_modules(GPIOD REQUIRED libgpiodcxx)
# Define the executable and its source files # Define the executable and its source files
add_executable(Dixon main.cpp add_executable(Dixon main.cpp
DixonNodeState.cpp DixonNodeState.cpp
@ -16,5 +22,8 @@ add_executable(Dixon main.cpp
CardioCenter/Heart.cpp CardioCenter/Heart.cpp
CardioCenter/Heart.h) CardioCenter/Heart.h)
# 2. Tell the linker what libraries to "glue" to that executable # Add the Include directories found by PkgConfig (where the .hpp files live)
target_link_libraries(Dixon PRIVATE gpiodcxx gpiod) target_include_directories(Dixon PRIVATE ${GPIOD_INCLUDE_DIRS})
# Link the specific libraries found by PkgConfig
target_link_libraries(Dixon PRIVATE ${GPIOD_LIBRARIES})

View file

@ -1,22 +1,35 @@
#include "Heart.h" #include "Heart.h"
#include <gpiod.hpp>
Heart::Heart(const char* chipName, unsigned int lineOffset) namespace cardio
: _chip(chipName),
_line(_chip.get_line(lineOffset)),
_isOn(false)
{ {
// Request the GPIO line as an output, initial value LOW Heart::Heart(const char* chipName, unsigned int lineOffset)
_line.request( : _isOn(false),
{ "heart", gpiod::line_request::DIRECTION_OUTPUT, 0 }, _request(setup_request(chipName, lineOffset))
0 {
); }
}
void Heart::beat() void Heart::beat()
{ {
// Toggle the state
_isOn = !_isOn; _isOn = !_isOn;
auto val = _isOn ? gpiod::line::value::ACTIVE : gpiod::line::value::INACTIVE;
// Write the new value to the GPIO line _request.set_value(HEART_LINE_INDEX, val);
_line.set_value(_isOn ? 1 : 0); }
gpiod::line_request Heart::setup_request(const char* chipName, const unsigned int lineOffset)
{
std::string chipPath = std::string("/dev/") + chipName;
gpiod::chip chip(chipPath);
auto settings = gpiod::line_settings()
.set_direction(gpiod::line::direction::OUTPUT);
auto line_cfg = gpiod::line_config();
line_cfg.add_line_settings(lineOffset, settings);
return chip.prepare_request()
.set_line_config(line_cfg)
.do_request();
}
} }

View file

@ -1,16 +1,21 @@
#pragma once #pragma once
#include <gpiod.hpp> #include <gpiod.hpp>
class Heart namespace cardio
{ {
public: class Heart
Heart(const char* chipName = "gpiochip0", unsigned int lineOffset = 17); {
// DixonBrain calls this when a beat occurs public:
explicit Heart(const char* chipName = GPIO_CHIP_NAME, unsigned int lineOffset = DEFAULT_HEART_PIN);
void beat(); void beat();
private: private:
gpiod::chip _chip; static constexpr auto GPIO_CHIP_NAME = "gpiochip0";
gpiod::line _line; static constexpr unsigned int DEFAULT_HEART_PIN = 17;
static constexpr unsigned int HEART_LINE_INDEX = 0;
static gpiod::line_request setup_request(const char* chipName, unsigned int lineOffset);
bool _isOn; bool _isOn;
}; gpiod::line_request _request;
};
}