From 6a8f4f364b05ed714943820a06c6e3109190ef5f Mon Sep 17 00:00:00 2001 From: Russell Gilbert Date: Sat, 7 Feb 2026 06:44:18 +0000 Subject: [PATCH] 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. --- src/RobotNode/CMakeLists.txt | 19 ++++++++---- src/RobotNode/CardioCenter/Heart.cpp | 45 ++++++++++++++++++---------- src/RobotNode/CardioCenter/Heart.h | 25 +++++++++------- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/src/RobotNode/CMakeLists.txt b/src/RobotNode/CMakeLists.txt index 65145f2..955da47 100644 --- a/src/RobotNode/CMakeLists.txt +++ b/src/RobotNode/CMakeLists.txt @@ -1,12 +1,18 @@ # 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) -# 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) +# 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 add_executable(Dixon main.cpp DixonNodeState.cpp @@ -16,5 +22,8 @@ add_executable(Dixon main.cpp CardioCenter/Heart.cpp CardioCenter/Heart.h) -# 2. Tell the linker what libraries to "glue" to that executable -target_link_libraries(Dixon PRIVATE gpiodcxx gpiod) \ No newline at end of file +# Add the Include directories found by PkgConfig (where the .hpp files live) +target_include_directories(Dixon PRIVATE ${GPIOD_INCLUDE_DIRS}) + +# Link the specific libraries found by PkgConfig +target_link_libraries(Dixon PRIVATE ${GPIOD_LIBRARIES}) \ No newline at end of file diff --git a/src/RobotNode/CardioCenter/Heart.cpp b/src/RobotNode/CardioCenter/Heart.cpp index fb3e3a9..49dc742 100644 --- a/src/RobotNode/CardioCenter/Heart.cpp +++ b/src/RobotNode/CardioCenter/Heart.cpp @@ -1,22 +1,35 @@ #include "Heart.h" +#include -Heart::Heart(const char* chipName, unsigned int lineOffset) - : _chip(chipName), - _line(_chip.get_line(lineOffset)), - _isOn(false) +namespace cardio { - // Request the GPIO line as an output, initial value LOW - _line.request( - { "heart", gpiod::line_request::DIRECTION_OUTPUT, 0 }, - 0 - ); -} + Heart::Heart(const char* chipName, unsigned int lineOffset) + : _isOn(false), + _request(setup_request(chipName, lineOffset)) + { + } -void Heart::beat() -{ - // Toggle the state - _isOn = !_isOn; + void Heart::beat() + { + _isOn = !_isOn; + auto val = _isOn ? gpiod::line::value::ACTIVE : gpiod::line::value::INACTIVE; - // Write the new value to the GPIO line - _line.set_value(_isOn ? 1 : 0); + _request.set_value(HEART_LINE_INDEX, val); + } + + 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(); + } } \ No newline at end of file diff --git a/src/RobotNode/CardioCenter/Heart.h b/src/RobotNode/CardioCenter/Heart.h index a76a30e..fe355bc 100644 --- a/src/RobotNode/CardioCenter/Heart.h +++ b/src/RobotNode/CardioCenter/Heart.h @@ -1,16 +1,21 @@ #pragma once #include -class Heart +namespace cardio { -public: - Heart(const char* chipName = "gpiochip0", unsigned int lineOffset = 17); + class Heart + { - // DixonBrain calls this when a beat occurs - void beat(); + public: + explicit Heart(const char* chipName = GPIO_CHIP_NAME, unsigned int lineOffset = DEFAULT_HEART_PIN); + void beat(); -private: - gpiod::chip _chip; - gpiod::line _line; - bool _isOn; -}; \ No newline at end of file + private: + static constexpr auto GPIO_CHIP_NAME = "gpiochip0"; + 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; + gpiod::line_request _request; + }; +}