Skip to content

Commit

Permalink
deuglified function registry helpers!
Browse files Browse the repository at this point in the history
  • Loading branch information
markzakharyan committed Sep 24, 2024
1 parent ca27a5c commit 7ade60f
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 151 deletions.
12 changes: 12 additions & 0 deletions m4/src/FunctionRegistry/CallFunctionHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// CallFunctionHelper.h
#pragma once
#include <vector>
#include <tuple>

// Helper function to cast and unpack arguments from the vector
template <typename Function, typename Tuple, size_t... Is>
auto callFunctionHelper(Function function, const std::vector<float>& args, std::index_sequence<Is...>)
-> decltype(function(static_cast<typename std::tuple_element<Is, Tuple>::type>(args[Is])...))
{
return function(static_cast<typename std::tuple_element<Is, Tuple>::type>(args[Is])...);
}
File renamed without changes.
54 changes: 54 additions & 0 deletions m4/src/FunctionRegistry/FunctionRegistryHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// RegisterFunctions.h
#pragma once
#include <cassert>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#include "CallFunctionHelper.h"
#include "FunctionRegistry/FunctionRegistry.h"
#include "FunctionTraits.h"
#include "Peripherals/OperationResult.h"

// Template function to register functions with automatically deduced number of
// arguments
template <typename Function>
void registerMemberFunction(Function function, const String& commandName) {
using Traits = FunctionTraits<Function>;
constexpr size_t argCountSizeT = Traits::arity;
static_assert(argCountSizeT <= 8,
"Too many arguments. Maximum supported is 8.");
constexpr int argCount = static_cast<int>(
argCountSizeT); // Ensure it matches FunctionRegistry's expected type

using ArgsTuple = typename Traits::args_tuple;

// Create a lambda that matches the expected signature for FunctionRegistry
auto wrapper = [function](const std::vector<float>& args) -> OperationResult {
// Ensure the number of arguments matches
assert(args.size() == Traits::arity &&
"Incorrect number of arguments provided.");

// Call the helper to invoke the function with unpacked and casted arguments
return callFunctionHelper<Function, ArgsTuple>(
function, args, std::make_index_sequence<Traits::arity>{});
};

// Register the function with FunctionRegistry
FunctionRegistry::registerFunction(
commandName, wrapper,
argCount // Ensure this matches the expected type (int)
);
}

// Template function to register functions that accept a vector of arguments
// directly
template <typename Function>
void registerMemberFunctionVector(Function function,
const String& commandName) {
FunctionRegistry::registerFunction(commandName, function,
-1 // Use -1 or another sentinel value to
// indicate variable argument count
);
}
36 changes: 36 additions & 0 deletions m4/src/FunctionRegistry/FunctionTraits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// FunctionTraits.h
#pragma once
#include <tuple>
#include <type_traits>

// Primary template for FunctionTraits (handles general callables)
template <typename T>
struct FunctionTraits;

// Specialization for function pointers
template <typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(*)(Args...)> {
using return_type = ReturnType;
using args_tuple = std::tuple<Args...>;
static constexpr size_t arity = sizeof...(Args);
};

// Specialization for member function pointers
template <typename ClassType, typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(ClassType::*)(Args...)> {
using return_type = ReturnType;
using args_tuple = std::tuple<Args...>;
static constexpr size_t arity = sizeof...(Args);
};

// Specialization for const member function pointers
template <typename ClassType, typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(ClassType::*)(Args...) const> {
using return_type = ReturnType;
using args_tuple = std::tuple<Args...>;
static constexpr size_t arity = sizeof...(Args);
};

// Specialization for functors (e.g., lambdas)
template <typename Functor>
struct FunctionTraits : public FunctionTraits<decltype(&Functor::operator())> {};
102 changes: 0 additions & 102 deletions m4/src/FunctionRegistryMacros.h

This file was deleted.

26 changes: 13 additions & 13 deletions m4/src/Peripherals/ADC/ADCController.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#include <vector>

#include "Config.h"
#include "FunctionRegistry.h"
#include "FunctionRegistryMacros.h"
#include "FunctionRegistry/FunctionRegistry.h"
#include "FunctionRegistry/FunctionRegistryHelpers.h"
#include "Peripherals/ADC/ADCBoard.h"
#include "Peripherals/OperationResult.h"
class ADCController {
Expand All @@ -29,19 +29,19 @@ class ADCController {
}

static void initializeRegistry() {
REGISTER_MEMBER_FUNCTION_1(readChannelVoltage, "GET_ADC");
REGISTER_MEMBER_FUNCTION_2(setConversionTime, "CONVERT_TIME");
REGISTER_MEMBER_FUNCTION_1(getConversionTime, "GET_CONVERT_TIME");
REGISTER_MEMBER_FUNCTION_3(continuousConvertRead,
registerMemberFunction(readChannelVoltage, "GET_ADC");
registerMemberFunction(setConversionTime, "CONVERT_TIME");
registerMemberFunction(getConversionTime, "GET_CONVERT_TIME");
registerMemberFunction(continuousConvertRead,
"CONTINUOUS_CONVERT_READ");
REGISTER_MEMBER_FUNCTION_1(idleMode, "IDLE_MODE");
REGISTER_MEMBER_FUNCTION_0(getChannelsActive, "GET_CHANNELS_ACTIVE");
REGISTER_MEMBER_FUNCTION_0(resetAllADCBoards, "RESET");
REGISTER_MEMBER_FUNCTION_1(talkADC, "TALK");
REGISTER_MEMBER_FUNCTION_0(adcZeroScaleCal, "ADC_ZERO_SC_CAL");
REGISTER_MEMBER_FUNCTION_0(adcChannelSystemZeroScaleCal,
registerMemberFunction(idleMode, "IDLE_MODE");
registerMemberFunction(getChannelsActive, "GET_CHANNELS_ACTIVE");
registerMemberFunction(resetAllADCBoards, "RESET");
registerMemberFunction(talkADC, "TALK");
registerMemberFunction(adcZeroScaleCal, "ADC_ZERO_SC_CAL");
registerMemberFunction(adcChannelSystemZeroScaleCal,
"ADC_CH_ZERO_SC_CAL");
REGISTER_MEMBER_FUNCTION_0(adcChannelSystemFullScaleCal,
registerMemberFunction(adcChannelSystemFullScaleCal,
"ADC_CH_FULL_SC_CAL");
}

Expand Down
24 changes: 12 additions & 12 deletions m4/src/Peripherals/DAC/DACController.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
#include <vector>

#include "DACChannel.h"
#include "FunctionRegistry.h"
#include "FunctionRegistryMacros.h"
#include "FunctionRegistry/FunctionRegistry.h"
#include "FunctionRegistry/FunctionRegistryHelpers.h"
#include "Peripherals/OperationResult.h"
#include "Utils/TimingUtil.h"
#include "Utils/shared_memory.h"
Expand All @@ -19,17 +19,17 @@ class DACController {

public:
inline static void initializeRegistry() {
REGISTER_MEMBER_FUNCTION_0(initialize, "INITIALIZE");
REGISTER_MEMBER_FUNCTION_0(initialize, "INIT");
REGISTER_MEMBER_FUNCTION_0(
registerMemberFunction(initialize, "INITIALIZE");
registerMemberFunction(initialize, "INIT");
registerMemberFunction(
initialize, "INNIT"); // oi bruv u got a loicense for that DAC? 🇬🇧
REGISTER_MEMBER_FUNCTION_2(setVoltage, "SET");
REGISTER_MEMBER_FUNCTION_1(getVoltage, "GET_DAC");
REGISTER_MEMBER_FUNCTION_2(sendCode, "SEND_CODE");
REGISTER_MEMBER_FUNCTION_2(setFullScale, "FULL_SCALE");
REGISTER_MEMBER_FUNCTION_0(inquiryOSG, "INQUIRY_OSG");
REGISTER_MEMBER_FUNCTION_5(autoRamp1, "RAMP1");
REGISTER_MEMBER_FUNCTION_8(autoRamp2, "RAMP2");
registerMemberFunction(setVoltage, "SET");
registerMemberFunction(getVoltage, "GET_DAC");
registerMemberFunction(sendCode, "SEND_CODE");
registerMemberFunction(setFullScale, "FULL_SCALE");
registerMemberFunction(inquiryOSG, "INQUIRY_OSG");
registerMemberFunction(autoRamp1, "RAMP1");
registerMemberFunction(autoRamp2, "RAMP2");
}

inline static void addChannel(int cs_pin) {
Expand Down
42 changes: 25 additions & 17 deletions m4/src/Peripherals/God.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ class God {
static void setup() { initializeRegistry(); }

static void initializeRegistry() {
REGISTER_MEMBER_FUNCTION_VECTOR(timeSeriesBufferRampWrapper,
"TIME_SERIES_BUFFER_RAMP");
REGISTER_MEMBER_FUNCTION_VECTOR(dacLedBufferRampWrapper,
"DAC_LED_BUFFER_RAMP");
REGISTER_MEMBER_FUNCTION_0(dacChannelCalibration, "DAC_CH_CAL");
REGISTER_MEMBER_FUNCTION_VECTOR(twoDimensionalFlexibleRampWrapper,
"2D_TIME_SERIES_RAMP");
registerMemberFunctionVector(timeSeriesBufferRampWrapper,
"TIME_SERIES_BUFFER_RAMP");
registerMemberFunctionVector(dacLedBufferRampWrapper,
"DAC_LED_BUFFER_RAMP");
registerMemberFunction(dacChannelCalibration, "DAC_CH_CAL");
registerMemberFunctionVector(twoDimensionalFlexibleRampWrapper,
"2D_TIME_SERIES_RAMP");
}

struct AxisChannel {
Expand Down Expand Up @@ -246,12 +246,14 @@ class God {
if (numDacChannels < 1 || numAdcChannels < 1) {
return OperationResult::Failure("Invalid number of channels");
}
// uint32_t adc_comms_period_us = (1.0/SPI_SPEED)*1e6*8*4; // 8 bits per byte, 4 bytes per ADC conversion
// if (adc_interval_us < adc_comms_period_us*numAdcChannels) {
// uint32_t adc_comms_period_us = (1.0/SPI_SPEED)*1e6*8*4; // 8 bits per
// byte, 4 bytes per ADC conversion if (adc_interval_us <
// adc_comms_period_us*numAdcChannels) {
// return OperationResult::Failure("ADC interval too short");
// }
// uint32_t dac_comms_period_us = (1.0/SPI_SPEED)*1e6*8*3; // 8 bits per byte, 3 bytes per DAC update
// if (dac_interval_us < dac_comms_period_us*numDacChannels) {
// uint32_t dac_comms_period_us = (1.0/SPI_SPEED)*1e6*8*3; // 8 bits per
// byte, 3 bytes per DAC update if (dac_interval_us <
// dac_comms_period_us*numDacChannels) {
// return OperationResult::Failure("DAC interval too short");
// }

Expand Down Expand Up @@ -407,13 +409,18 @@ class God {
return OperationResult::Failure("Invalid number of channels");
}
for (int i = 0; i < numAdcChannels; i++) {
if (dac_settling_time_us < ADCController::getConversionTimeFloat(adcChannels[i])) {
return OperationResult::Failure("DAC settling time too short for ADC conversion time");
if (dac_settling_time_us <
ADCController::getConversionTimeFloat(adcChannels[i])) {
return OperationResult::Failure(
"DAC settling time too short for ADC conversion time");
}
}
// uint32_t adc_comms_period_us = (1.0/SPI_SPEED)*1e6*8*4; // 8 bits per byte, 4 bytes per ADC conversion
// if (numAdcChannels*numAdcAverages*adc_comms_period_us > dac_interval_us - dac_settling_time_us) {
// return OperationResult::Failure("Buffer Ramp limited by ADC SPI comms");
// uint32_t adc_comms_period_us = (1.0/SPI_SPEED)*1e6*8*4; // 8 bits per
// byte, 4 bytes per ADC conversion if
// (numAdcChannels*numAdcAverages*adc_comms_period_us > dac_interval_us -
// dac_settling_time_us) {
// return OperationResult::Failure("Buffer Ramp limited by ADC SPI
// comms");
// }

int steps = 0;
Expand Down Expand Up @@ -452,7 +459,8 @@ class God {
for (int i = 0; i < numAdcChannels; i++) {
float total = 0.0;
for (int j = 0; j < numAdcAverages; j++) {
total += ADCController::getVoltageDataNoTransaction(adcChannels[i]);
total +=
ADCController::getVoltageDataNoTransaction(adcChannels[i]);
}
float v = total / numAdcAverages;
packets[i] = {static_cast<uint8_t>(adcChannels[i]),
Expand Down
10 changes: 5 additions & 5 deletions m4/src/UserIOHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

#include <vector>

#include "FunctionRegistry.h"
#include "FunctionRegistry/FunctionRegistry.h"
#include "Peripherals/OperationResult.h"

struct UserIOHandler {
static void setup() {
REGISTER_MEMBER_FUNCTION_0(nop, "NOP");
REGISTER_MEMBER_FUNCTION_0(id, "*IDN?");
REGISTER_MEMBER_FUNCTION_0(rdy, "*RDY?");
REGISTER_MEMBER_FUNCTION_0(serialNumber, "SERIAL_NUMBER");
registerMemberFunction(nop, "NOP");
registerMemberFunction(id, "*IDN?");
registerMemberFunction(rdy, "*RDY?");
registerMemberFunction(serialNumber, "SERIAL_NUMBER");
}

static OperationResult nop() { return OperationResult::Success("NOP"); }
Expand Down
4 changes: 2 additions & 2 deletions m4/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include <Arduino.h>

#include "Config.h"
#include "FunctionRegistry.h"
#include "FunctionRegistryMacros.h"
#include "FunctionRegistry/FunctionRegistry.h"
#include "FunctionRegistry/FunctionRegistryHelpers.h"
#include "Peripherals/ADC/ADCController.h"
#include "Peripherals/DAC/DACController.h"
#include "Peripherals/God.h"
Expand Down

0 comments on commit 7ade60f

Please sign in to comment.