From 042645f6bfa374603d01c8cb169a93029caaabb9 Mon Sep 17 00:00:00 2001 From: Mark Zakharyan Date: Thu, 18 Jul 2024 19:49:47 -0700 Subject: [PATCH] Timer interrupts in God --- src/Config.h | 2 +- src/FunctionRegistryMacros.h | 122 +++++++++++++++++----------- src/Peripherals/ADC/ADCBoard.h | 34 ++++---- src/Peripherals/ADC/ADCController.h | 9 ++ src/Peripherals/DAC/DACController.h | 7 ++ src/Peripherals/God.h | 66 ++++++++++++--- src/main.cpp | 16 ++-- 7 files changed, 172 insertions(+), 84 deletions(-) diff --git a/src/Config.h b/src/Config.h index cf4fe21..8c94d13 100644 --- a/src/Config.h +++ b/src/Config.h @@ -10,7 +10,7 @@ // physical GPIO to software data names // /////////////////////////////////////////////////////////////// -const int adc_sync_pins[2] = {48, 42}; // SYNC for both 16-bit ADCs +const int adc_cs_pins[2] = {48, 42}; // SYNC for both 16-bit ADCs const int dac_cs_pins[4] = {24, 26, 38, 36}; // CS for 4x 20-bit DAC channels const int ldac = 22; // LDAC pin shared across all AD5791 -- used to synchronize DAC voltage output const int reset[2] = {46, 44}; // reset pins on ADC diff --git a/src/FunctionRegistryMacros.h b/src/FunctionRegistryMacros.h index 9a95cbc..8e22848 100644 --- a/src/FunctionRegistryMacros.h +++ b/src/FunctionRegistryMacros.h @@ -2,61 +2,89 @@ #include "FunctionRegistry.h" #include "Peripherals/OperationResult.h" -#define REGISTER_MEMBER_FUNCTION_VECTOR(registry, functionName, \ - commandName) \ - registry.registerFunction( \ - commandName, \ - [this](const std::vector& args) -> OperationResult { \ - return this->functionName(args); \ - }, \ +#define REGISTER_MEMBER_FUNCTION_VECTOR(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName(args); \ + }, \ -1) -#define REGISTER_MEMBER_FUNCTION_0(registry, functionName, \ - commandName) \ - registry.registerFunction( \ - commandName, \ - [this](const std::vector&) -> OperationResult { \ - return this->functionName(); \ - }, \ +#define REGISTER_MEMBER_FUNCTION_0(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector&) -> OperationResult { \ + return this->functionName(); \ + }, \ 0) -#define REGISTER_MEMBER_FUNCTION_1(registry, functionName, \ - commandName) \ - registry.registerFunction( \ - commandName, \ - [this](const std::vector& args) -> OperationResult { \ - return this->functionName(static_cast(args[0])); \ - }, \ +#define REGISTER_MEMBER_FUNCTION_1(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName(static_cast(args[0])); \ + }, \ 1) -#define REGISTER_MEMBER_FUNCTION_2(registry, functionName, \ - commandName) \ - registry.registerFunction( \ - commandName, \ - [this](const std::vector& args) -> OperationResult { \ - return this->functionName(static_cast(args[0]), \ - static_cast(args[1])); \ - }, \ +#define REGISTER_MEMBER_FUNCTION_2(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName(static_cast(args[0]), \ + static_cast(args[1])); \ + }, \ 2) -#define REGISTER_MEMBER_FUNCTION_3(registry, functionName, \ - commandName) \ - registry.registerFunction( \ - commandName, \ - [this](const std::vector& args) -> OperationResult { \ - return this->functionName(static_cast(args[0]), \ - static_cast(args[1]), \ - static_cast(args[2])); \ - }, \ +#define REGISTER_MEMBER_FUNCTION_3(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName(static_cast(args[0]), \ + static_cast(args[1]), \ + static_cast(args[2])); \ + }, \ 3) -#define REGISTER_MEMBER_FUNCTION_4(registry, functionName, \ - commandName) \ - registry.registerFunction( \ - commandName, \ - [this](const std::vector& args) -> OperationResult { \ - return this->functionName( \ - static_cast(args[0]), static_cast(args[1]), \ - static_cast(args[2]), static_cast(args[3])); \ - }, \ +#define REGISTER_MEMBER_FUNCTION_4(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName( \ + static_cast(args[0]), static_cast(args[1]), \ + static_cast(args[2]), static_cast(args[3])); \ + }, \ 4) + +#define REGISTER_MEMBER_FUNCTION_5(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName( \ + static_cast(args[0]), static_cast(args[1]), \ + static_cast(args[2]), static_cast(args[3]), \ + static_cast(args[4])); \ + }, \ + 5) + +#define REGISTER_MEMBER_FUNCTION_6(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName( \ + static_cast(args[0]), static_cast(args[1]), \ + static_cast(args[2]), static_cast(args[3]), \ + static_cast(args[4]), static_cast(args[5])); \ + }, \ + 6) + +#define REGISTER_MEMBER_FUNCTION_7(registry, functionName, commandName) \ + registry.registerFunction( \ + commandName, \ + [this](const std::vector& args) -> OperationResult { \ + return this->functionName( \ + static_cast(args[0]), static_cast(args[1]), \ + static_cast(args[2]), static_cast(args[3]), \ + static_cast(args[4]), static_cast(args[5]), \ + static_cast(args[6])); \ + }, \ + 7) \ No newline at end of file diff --git a/src/Peripherals/ADC/ADCBoard.h b/src/Peripherals/ADC/ADCBoard.h index 5fb1865..503d261 100644 --- a/src/Peripherals/ADC/ADCBoard.h +++ b/src/Peripherals/ADC/ADCBoard.h @@ -21,6 +21,8 @@ #define ADDR_ADCZEROSCALECAL 0x6 #define ADDR_ADCFULLSCALE 0x7 +#define DUMP_MODE 1 << 3 + // Address macro functions, returns address for desired register of selected // channel (0-3), Table 11 #define ADDR_CHANNELDATA(adc_channel) (0x8 + adc_channel) @@ -51,7 +53,7 @@ class ADCBoard { private: - int sync_pin; + int cs_pin; int data_ready_pin; int reset_pin; PeripheralCommsController &commsController; @@ -82,9 +84,9 @@ class ADCBoard { } public: - ADCBoard(PeripheralCommsController &commsController, int sync_pin, + ADCBoard(PeripheralCommsController &commsController, int cs_pin, int data_ready_pin, int reset_pin) - : sync_pin(sync_pin), + : cs_pin(cs_pin), data_ready_pin(data_ready_pin), reset_pin(reset_pin), commsController(commsController) {} @@ -92,8 +94,8 @@ class ADCBoard { void setup() { pinMode(reset_pin, OUTPUT); pinMode(data_ready_pin, INPUT); - pinMode(sync_pin, OUTPUT); - digitalWrite(sync_pin, HIGH); + pinMode(cs_pin, OUTPUT); + digitalWrite(cs_pin, HIGH); // Resets ADC on startup. digitalWrite(reset_pin, HIGH); @@ -155,28 +157,28 @@ class ADCBoard { } void sendByte(byte data) { - digitalWrite(sync_pin, LOW); + digitalWrite(cs_pin, LOW); commsController.sendByte(data); - digitalWrite(sync_pin, HIGH); + digitalWrite(cs_pin, HIGH); } byte receiveByte() { - digitalWrite(sync_pin, LOW); + digitalWrite(cs_pin, LOW); byte data = commsController.receiveByte(); - digitalWrite(sync_pin, HIGH); + digitalWrite(cs_pin, HIGH); return data; } void transfer(void *buf, size_t count) { - digitalWrite(sync_pin, LOW); + digitalWrite(cs_pin, LOW); commsController.transfer(buf, count); - digitalWrite(sync_pin, HIGH); + digitalWrite(cs_pin, HIGH); } void transfer(uint8_t data) { - digitalWrite(sync_pin, LOW); + digitalWrite(cs_pin, LOW); commsController.transfer(data); - digitalWrite(sync_pin, HIGH); + digitalWrite(cs_pin, HIGH); } // return ADC status register, pg. 16 @@ -237,18 +239,20 @@ class ADCBoard { } uint16_t getConversionData(int adc_channel) { - uint8_t data_array, upper, lower; + byte data_array, upper, lower; // setup communication register for reading channel data data_array = READ | ADDR_CHANNELDATA(adc_channel); // write to the communication register commsController.beginTransaction(); - transfer(data_array); + digitalWrite(cs_pin, LOW); + sendByte(data_array); // read upper and lower bytes of channel data register (16 bit mode) upper = commsController.receiveByte(); lower = commsController.receiveByte(); + digitalWrite(cs_pin, HIGH); commsController.endTransaction(); uint16_t result = upper << 8 | lower; diff --git a/src/Peripherals/ADC/ADCController.h b/src/Peripherals/ADC/ADCController.h index 79cf9a7..33b4f54 100644 --- a/src/Peripherals/ADC/ADCController.h +++ b/src/Peripherals/ADC/ADCController.h @@ -75,4 +75,13 @@ class ADCController : public Peripheral { return OperationResult::Failure("Invalid channel index"); } } + + uint16_t getConversionData(int adc_channel) { + return adc_boards[getBoardIndexFromGlobalIndex(adc_channel)] + ->getConversionData(getChannelIndexFromGlobalIndex(adc_channel)); + } + + float getVoltageData(int adc_channel) { + return ADC2DOUBLE(getConversionData(adc_channel)); + } }; \ No newline at end of file diff --git a/src/Peripherals/DAC/DACController.h b/src/Peripherals/DAC/DACController.h index 65e3c98..694c70e 100644 --- a/src/Peripherals/DAC/DACController.h +++ b/src/Peripherals/DAC/DACController.h @@ -54,6 +54,13 @@ class DACController : public Peripheral { } } + DACChannel* getChannel(int channel_index) { + if (!isChannelIndexValid(channel_index)) { + return nullptr; + } + return dac_channels[channel_index]; + } + bool isChannelIndexValid(int channelIndex) { return channelIndex >= 0 && static_cast(channelIndex) < dac_channels.size(); diff --git a/src/Peripherals/God.h b/src/Peripherals/God.h index e0b3a4e..bd857b1 100644 --- a/src/Peripherals/God.h +++ b/src/Peripherals/God.h @@ -3,32 +3,74 @@ #include #include #include +#include + +#include "Portenta_H7_ISR_Timer.hpp" class God { private: + FunctionRegistry& registry; DACController& dacController; ADCController& adcController; - FunctionRegistry& registry; - // Portenta_H7_Timer ITimer(TIM15); - // bool toggle = false; + Portenta_H7_Timer ITimer; - // void TimerHandler(void) { - // toggle = !toggle; - // digitalWrite(LED_BUILTIN, toggle); - // } + volatile int x; + + static God* instance; // Monotheistic public: God(FunctionRegistry& registry, DACController& dacController, ADCController& adcController) : registry(registry), dacController(dacController), - adcController(adcController) { + adcController(adcController), + ITimer(TIM15), + x(0) { + instance = this; + } + + void setup() { initializeRegistry(); - // pinMode(LED_BUILTIN, OUTPUT); - // ITimer.attachInterruptInterval(1000000, TimerHandler); + pinMode(LED_BUILTIN, OUTPUT); + } + + void initializeRegistry() { + REGISTER_MEMBER_FUNCTION_1(registry, thing, "THING"); + REGISTER_MEMBER_FUNCTION_0(registry, getX, "GETX"); + } + + OperationResult thing(float interval_ms) { + x = 0; + // Convert to microseconds and ensure it's within the valid range + uint32_t interval_us = static_cast(interval_ms * 1000); + if (interval_us < 1 || interval_us > 4294967295) { + return OperationResult::Failure("Invalid interval"); + } + + if (!ITimer.attachInterruptInterval(interval_us, God::staticTimerHandler)) { + return OperationResult::Failure("Failed to attach timer interrupt"); + } + + return OperationResult::Success("Timer interrupt attached"); } - void initializeRegistry() {} -}; \ No newline at end of file + void timerHandler() { + x += 1; + digitalWrite(LED_BUILTIN, x % 2); + } + + // Static wrapper for the timer handler + static void staticTimerHandler() { + if (instance) { + instance->timerHandler(); + } + } + + OperationResult getX() { return OperationResult::Success(String(x)); } + +}; + +// Only one God allowed, we're not heretics +God* God::instance = nullptr; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index eea1480..9f1ba50 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,14 +1,13 @@ #include -#include - #include "Config.h" #include "FunctionRegistry.h" #include "FunctionRegistryMacros.h" +#include "Peripherals/ADC/ADCController.h" #include "Peripherals/DAC/DACController.h" +#include "Peripherals/God.h" #include "Peripherals/PeripheralCommsController.h" #include "UserIOHandler.h" -#include "Peripherals/ADC/ADCController.h" FunctionRegistry registry; UserIOHandler userIOHandler(registry); @@ -16,24 +15,23 @@ PeripheralCommsController dacCommsController(DAC_SPI_SETTINGS); PeripheralCommsController adcCommsController(ADC_SPI_SETTINGS); DACController dacController(registry, dacCommsController); ADCController adcController(registry, adcCommsController); - +God god(registry, dacController, adcController); void setup() { userIOHandler.setup(); PeripheralCommsController::setup(); - for (int i : dac_cs_pins) { dacController.addChannel(i, ldac); } + adcController.addBoard(adc_cs_pins[0], drdy[0], reset[0]); + adcController.addBoard(adc_cs_pins[1], drdy[1], reset[1]); - adcController.addBoard(adc_sync_pins[0], drdy[0], reset[0]); - adcController.addBoard(adc_sync_pins[1], drdy[1], reset[1]); - - dacController.setup(); adcController.setup(); + + god.setup(); } void loop() { userIOHandler.handleUserIO(); } \ No newline at end of file