DonCon2040/include/peripherals/Drum.h
Frederik Walk 381d91e7bc Use DMA for reading external ADC
The external ADC will constantly convert, reading will give
the maximum value since the last read. This should avoid
missing any peaks.

The internal ADC will now only do one conversion upon read,
consider it abandoned for now.
2024-11-13 21:12:26 +01:00

118 lines
2.8 KiB
C++

#ifndef _PERIPHERALS_DRUM_H_
#define _PERIPHERALS_DRUM_H_
#include "utils/InputState.h"
#include "hardware/spi.h"
#include <mcp3204/Mcp3204Dma.h>
#include <array>
#include <map>
#include <memory>
#include <stdint.h>
namespace Doncon::Peripherals {
class Drum {
public:
struct Config {
struct Thresholds {
uint16_t don_left;
uint16_t ka_left;
uint16_t don_right;
uint16_t ka_right;
};
struct AdcInputs {
uint8_t don_left;
uint8_t ka_left;
uint8_t don_right;
uint8_t ka_right;
};
AdcInputs adc_inputs;
Thresholds trigger_thresholds;
uint8_t sample_count;
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;
};
private:
enum class Id {
DON_LEFT,
KA_LEFT,
DON_RIGHT,
KA_RIGHT,
};
class Pad {
private:
uint8_t channel;
uint32_t last_change;
bool active;
public:
Pad(const uint8_t channel);
uint8_t getChannel() const { return channel; };
bool getState() const { return active; };
void setState(const bool state, const uint16_t debounce_delay);
};
class AdcInterface {
public:
// Those are expected to be 12bit values
virtual std::array<uint16_t, 4> read() = 0;
};
class InternalAdc : public AdcInterface {
public:
InternalAdc(const Config::AdcInputs &adc_inputs);
virtual std::array<uint16_t, 4> read() final;
};
class ExternalAdc : public AdcInterface {
private:
Mcp3204Dma m_mcp3204;
public:
ExternalAdc(const Config::Spi &spi_config);
virtual std::array<uint16_t, 4> read() final;
};
Config m_config;
std::unique_ptr<AdcInterface> m_adc;
std::map<Id, Pad> m_pads;
private:
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();
public:
Drum(const Config &config);
void updateInputState(Utils::InputState &input_state);
void setDebounceDelay(const uint16_t delay);
void setThresholds(const Config::Thresholds &thresholds);
};
} // namespace Doncon::Peripherals
#endif // _PERIPHERALS_DRUM_H_