Skip to content

Commit

Permalink
Refactor ADC configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
ravinrabbid committed Dec 1, 2024
1 parent a2cb89c commit 58cf743
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 63 deletions.
29 changes: 16 additions & 13 deletions include/GlobalConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,38 @@ const I2c i2c_config = {
};

const Peripherals::Drum::Config drum_config = {
// Pin config
{
1, // Don Left
0, // Ka Left
2, // Don Right
3, // Ka Right
},
// Trigger thresholds
{
30, // Don Left
10, // Ka Left
30, // Don Right
10, // Ka Right
},

16, // ADC sample count
25, // Debounce delay in milliseconds
500, // Roll Counter Timeout in Milliseconds

true, // Use external ADC
// SPI config for external ADC, unused if above is false
// ADC Channel config
{
1, // Don Left
0, // Ka Left
2, // Don Right
3, // Ka Right
},

// ADC Config, either InternalAdc or ExternalAdc
//
// Peripherals::Drum::Config::InternalAdc{
// 16, // ADC sample count
// },

Peripherals::Drum::Config::ExternalAdc{
spi0, // Block
2000000, // Speed
3, // MOSI Pin
4, // MISO Pin
2, // SCLK Pin
1, // SCSn Pin
0, // Level Shifter Enable Pin
spi0, // Block
2000000, // Speed
},
};

Expand Down
43 changes: 25 additions & 18 deletions include/peripherals/Drum.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <map>
#include <memory>
#include <stdint.h>
#include <variant>

namespace Doncon::Peripherals {

Expand All @@ -24,31 +25,34 @@ class Drum {
uint16_t ka_right;
};

struct AdcInputs {
struct AdcChannels {
uint8_t don_left;
uint8_t ka_left;
uint8_t don_right;
uint8_t ka_right;
};

AdcInputs adc_inputs;
Thresholds trigger_thresholds;
struct InternalAdc {
uint8_t sample_count;
};

struct ExternalAdc {
spi_inst_t *spi_block;
uint spi_speed_hz;
uint8_t spi_mosi_pin;
uint8_t spi_miso_pin;
uint8_t spi_sclk_pin;
uint8_t spi_scsn_pin;
uint8_t spi_level_shifter_enable_pin;
};

uint8_t sample_count;
Thresholds trigger_thresholds;
uint16_t debounce_delay_ms;

uint32_t roll_counter_timeout_ms;

bool use_external_adc;

struct Spi {
uint8_t mosi_pin;
uint8_t miso_pin;
uint8_t sclk_pin;
uint8_t scsn_pin;
uint8_t level_shifter_enable_pin;
spi_inst_t *block;
uint speed_hz;
} external_adc_spi_config;
AdcChannels adc_channels;
std::variant<InternalAdc, ExternalAdc> adc_config;
};

private:
Expand Down Expand Up @@ -80,8 +84,11 @@ class Drum {
};

class InternalAdc : public AdcInterface {
private:
Config::InternalAdc m_config;

public:
InternalAdc(const Config::AdcInputs &adc_inputs);
InternalAdc(const Config::InternalAdc &config);
virtual std::array<uint16_t, 4> read() final;
};

Expand All @@ -90,7 +97,7 @@ class Drum {
Mcp3204Dma m_mcp3204;

public:
ExternalAdc(const Config::Spi &spi_config);
ExternalAdc(const Config::ExternalAdc &config);
virtual std::array<uint16_t, 4> read() final;
};

Expand All @@ -102,7 +109,7 @@ class Drum {
void updateRollCounter(Utils::InputState &input_state);
void updateDigitalInputState(Utils::InputState &input_state, const std::map<Id, uint16_t> &raw_values);
void updateAnalogInputState(Utils::InputState &input_state, const std::map<Id, uint16_t> &raw_values);
std::map<Id, uint16_t> sampleInputs();
std::map<Id, uint16_t> readInputs();

public:
Drum(const Config &config);
Expand Down
79 changes: 47 additions & 32 deletions src/peripherals/Drum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,49 @@

namespace Doncon::Peripherals {

Drum::InternalAdc::InternalAdc(const Drum::Config::AdcInputs &adc_inputs) {
Drum::InternalAdc::InternalAdc(const Config::InternalAdc &config) : m_config(config) {
static const uint adc_base_pin = 26;

adc_gpio_init(adc_base_pin + adc_inputs.don_left);
adc_gpio_init(adc_base_pin + adc_inputs.don_right);
adc_gpio_init(adc_base_pin + adc_inputs.ka_left);
adc_gpio_init(adc_base_pin + adc_inputs.ka_right);
for (uint pin = adc_base_pin; pin < adc_base_pin + 4; ++pin) {
adc_gpio_init(pin);
}

adc_init();
}

std::array<uint16_t, 4> Drum::InternalAdc::read() {
// TODO: This should probably also use DMA

std::array<uint16_t, 4> result;
// Oversample ADC inputs to get rid of ADC noise
std::array<uint32_t, 4> values{};
for (uint8_t sample_number = 0; sample_number < m_config.sample_count; ++sample_number) {
for (size_t idx = 0; idx < values.size(); ++idx) {
adc_select_input(idx);
values[idx] += adc_read();
}
}

for (size_t idx = 0; idx < 4; ++idx) {
adc_select_input(idx);
result[idx] = adc_read();
// Take average of all samples
std::array<uint16_t, 4> result{};
for (size_t idx = 0; idx < values.size(); ++idx) {
result[idx] = values[idx] / m_config.sample_count;
}

return result;
}

Drum::ExternalAdc::ExternalAdc(const Drum::Config::Spi &spi_config) : m_mcp3204(spi_config.block, spi_config.scsn_pin) {
Drum::ExternalAdc::ExternalAdc(const Config::ExternalAdc &config) : m_mcp3204(config.spi_block, config.spi_scsn_pin) {
// Enable level shifter
gpio_init(spi_config.level_shifter_enable_pin);
gpio_set_dir(spi_config.level_shifter_enable_pin, GPIO_OUT);
gpio_put(spi_config.level_shifter_enable_pin, true);
gpio_init(config.spi_level_shifter_enable_pin);
gpio_set_dir(config.spi_level_shifter_enable_pin, GPIO_OUT);
gpio_put(config.spi_level_shifter_enable_pin, true);

gpio_set_function(spi_config.miso_pin, GPIO_FUNC_SPI);
gpio_set_function(spi_config.mosi_pin, GPIO_FUNC_SPI);
gpio_set_function(spi_config.sclk_pin, GPIO_FUNC_SPI);
spi_init(spi_config.block, spi_config.speed_hz);
// Set up SPI
gpio_set_function(config.spi_miso_pin, GPIO_FUNC_SPI);
gpio_set_function(config.spi_mosi_pin, GPIO_FUNC_SPI);
gpio_set_function(config.spi_sclk_pin, GPIO_FUNC_SPI);
spi_init(config.spi_block, config.spi_speed_hz);

gpio_init(spi_config.scsn_pin);
gpio_set_dir(spi_config.scsn_pin, GPIO_OUT);
gpio_init(config.spi_scsn_pin);
gpio_set_dir(config.spi_scsn_pin, GPIO_OUT);

m_mcp3204.run();
}
Expand All @@ -67,19 +73,28 @@ void Drum::Pad::setState(const bool state, const uint16_t debounce_delay) {
}

Drum::Drum(const Config &config) : m_config(config) {
if (m_config.use_external_adc) {
m_adc = std::make_unique<ExternalAdc>(config.external_adc_spi_config);
} else {
m_adc = std::make_unique<InternalAdc>(config.adc_inputs);
}

m_pads.emplace(Id::DON_LEFT, config.adc_inputs.don_left);
m_pads.emplace(Id::KA_LEFT, config.adc_inputs.ka_left);
m_pads.emplace(Id::DON_RIGHT, config.adc_inputs.don_right);
m_pads.emplace(Id::KA_RIGHT, config.adc_inputs.ka_right);
std::visit(
[this](auto &&config) {
using T = std::decay_t<decltype(config)>;

if constexpr (std::is_same_v<T, Config::InternalAdc>) {
m_adc = std::make_unique<InternalAdc>(config);
} else if constexpr (std::is_same_v<T, Config::ExternalAdc>) {
m_adc = std::make_unique<ExternalAdc>(config);
} else {
static_assert(false, "Unknown ADC type!");
}
},
m_config.adc_config);

m_pads.emplace(Id::DON_LEFT, config.adc_channels.don_left);
m_pads.emplace(Id::KA_LEFT, config.adc_channels.ka_left);
m_pads.emplace(Id::DON_RIGHT, config.adc_channels.don_right);
m_pads.emplace(Id::KA_RIGHT, config.adc_channels.ka_right);
}

std::map<Drum::Id, uint16_t> Drum::sampleInputs() {
std::map<Drum::Id, uint16_t> Drum::readInputs() {
std::map<Id, uint16_t> result;

const auto adc_values = m_adc->read();
Expand Down Expand Up @@ -270,7 +285,7 @@ void Drum::updateAnalogInputState(Utils::InputState &input_state, const std::map
}

void Drum::updateInputState(Utils::InputState &input_state) {
const auto raw_values = sampleInputs();
const auto raw_values = readInputs();

input_state.drum.don_left.raw = raw_values.at(Id::DON_LEFT);
input_state.drum.don_right.raw = raw_values.at(Id::DON_RIGHT);
Expand Down

0 comments on commit 58cf743

Please sign in to comment.