Skip to content

Commit

Permalink
Timer interrupts in God
Browse files Browse the repository at this point in the history
  • Loading branch information
markzakharyan committed Jul 19, 2024
1 parent 9a8643e commit 042645f
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 84 deletions.
2 changes: 1 addition & 1 deletion src/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
122 changes: 75 additions & 47 deletions src/FunctionRegistryMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<float>& args) -> OperationResult { \
return this->functionName(args); \
}, \
#define REGISTER_MEMBER_FUNCTION_VECTOR(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName(args); \
}, \
-1)

#define REGISTER_MEMBER_FUNCTION_0(registry, functionName, \
commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>&) -> OperationResult { \
return this->functionName(); \
}, \
#define REGISTER_MEMBER_FUNCTION_0(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>&) -> OperationResult { \
return this->functionName(); \
}, \
0)

#define REGISTER_MEMBER_FUNCTION_1(registry, functionName, \
commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName(static_cast<float>(args[0])); \
}, \
#define REGISTER_MEMBER_FUNCTION_1(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName(static_cast<float>(args[0])); \
}, \
1)

#define REGISTER_MEMBER_FUNCTION_2(registry, functionName, \
commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName(static_cast<float>(args[0]), \
static_cast<float>(args[1])); \
}, \
#define REGISTER_MEMBER_FUNCTION_2(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName(static_cast<float>(args[0]), \
static_cast<float>(args[1])); \
}, \
2)

#define REGISTER_MEMBER_FUNCTION_3(registry, functionName, \
commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName(static_cast<float>(args[0]), \
static_cast<float>(args[1]), \
static_cast<float>(args[2])); \
}, \
#define REGISTER_MEMBER_FUNCTION_3(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName(static_cast<float>(args[0]), \
static_cast<float>(args[1]), \
static_cast<float>(args[2])); \
}, \
3)

#define REGISTER_MEMBER_FUNCTION_4(registry, functionName, \
commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName( \
static_cast<float>(args[0]), static_cast<float>(args[1]), \
static_cast<float>(args[2]), static_cast<float>(args[3])); \
}, \
#define REGISTER_MEMBER_FUNCTION_4(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName( \
static_cast<float>(args[0]), static_cast<float>(args[1]), \
static_cast<float>(args[2]), static_cast<float>(args[3])); \
}, \
4)

#define REGISTER_MEMBER_FUNCTION_5(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName( \
static_cast<float>(args[0]), static_cast<float>(args[1]), \
static_cast<float>(args[2]), static_cast<float>(args[3]), \
static_cast<float>(args[4])); \
}, \
5)

#define REGISTER_MEMBER_FUNCTION_6(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName( \
static_cast<float>(args[0]), static_cast<float>(args[1]), \
static_cast<float>(args[2]), static_cast<float>(args[3]), \
static_cast<float>(args[4]), static_cast<float>(args[5])); \
}, \
6)

#define REGISTER_MEMBER_FUNCTION_7(registry, functionName, commandName) \
registry.registerFunction( \
commandName, \
[this](const std::vector<float>& args) -> OperationResult { \
return this->functionName( \
static_cast<float>(args[0]), static_cast<float>(args[1]), \
static_cast<float>(args[2]), static_cast<float>(args[3]), \
static_cast<float>(args[4]), static_cast<float>(args[5]), \
static_cast<float>(args[6])); \
}, \
7)
34 changes: 19 additions & 15 deletions src/Peripherals/ADC/ADCBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -51,7 +53,7 @@

class ADCBoard {
private:
int sync_pin;
int cs_pin;
int data_ready_pin;
int reset_pin;
PeripheralCommsController &commsController;
Expand Down Expand Up @@ -82,18 +84,18 @@ 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) {}

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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions src/Peripherals/ADC/ADCController.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
};
7 changes: 7 additions & 0 deletions src/Peripherals/DAC/DACController.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<size_t>(channelIndex) < dac_channels.size();
Expand Down
66 changes: 54 additions & 12 deletions src/Peripherals/God.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,74 @@
#include <Arduino.h>
#include <Peripherals/ADC/ADCController.h>
#include <Peripherals/DAC/DACController.h>
#include <Portenta_H7_TimerInterrupt.h>

#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<uint32_t>(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() {}

};
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;
Loading

0 comments on commit 042645f

Please sign in to comment.