Add drum pad input handling

This commit is contained in:
Frederik Walk 2023-04-10 13:04:38 +02:00
parent f40566beee
commit 3d7a970dcc
7 changed files with 216 additions and 2 deletions

View File

@ -13,7 +13,8 @@ add_compile_options(-Wall -Wextra -Werror)
add_subdirectory(libs)
file(GLOB ${PROJECT_NAME}_SOURCES src/*.cpp)
file(GLOB ${PROJECT_NAME}_SOURCES src/*.cpp src/utils/*.cpp
src/peripherals/*.cpp)
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_SOURCES})

View File

@ -0,0 +1,26 @@
#ifndef _GLOBALCONFIGURATION_H_
#define _GLOBALCONFIGURATION_H_
#include "peripherals/Drum.h"
namespace Doncon::Config::Default {
const Peripherals::Drum::Config drum_config = {
// Pin config
{
4, // Don Left Weak
3, // Ka Left Weak
2, // Don Right Weak
1, // Ka Right Weak
6, // Don Left Strong
29, // Ka Left Strong
7, // Don Right Strong
0, // Ka Right Strong
},
10, // Debounce delay in milliseconds
};
} // namespace Doncon::Config::Default
#endif // _GLOBALCONFIGURATION_H_

View File

@ -0,0 +1,70 @@
#ifndef _PERIPHERALS_DRUM_H_
#define _PERIPHERALS_DRUM_H_
#include "utils/InputState.h"
#include <map>
#include <stdint.h>
namespace Doncon::Peripherals {
class Drum {
public:
struct Config {
struct {
uint8_t don_left_weak;
uint8_t ka_left_weak;
uint8_t don_right_weak;
uint8_t ka_right_weak;
uint8_t don_left_strong;
uint8_t ka_left_strong;
uint8_t don_right_strong;
uint8_t ka_right_strong;
} pins;
uint8_t debounce_delay_ms;
};
private:
enum class Id {
DON_LEFT_WEAK,
KA_LEFT_WEAK,
DON_RIGHT_WEAK,
KA_RIGHT_WEAK,
DON_LEFT_STRONG,
KA_LEFT_STRONG,
DON_RIGHT_STRONG,
KA_RIGHT_STRONG,
};
class Pad {
private:
uint8_t gpio_pin;
uint32_t gpio_mask;
uint32_t last_change;
bool active;
public:
Pad(uint8_t pin);
uint8_t getGpioPin() const { return gpio_pin; };
uint32_t getGpioMask() const { return gpio_mask; };
bool getState() const { return active; };
void setState(bool state, uint8_t debounce_delay);
};
Config m_config;
std::map<Id, Pad> m_pads;
public:
Drum(const Config &config);
void updateInputState(Utils::InputState &input_state);
};
} // namespace Doncon::Peripherals
#endif // _PERIPHERALS_DRUM_H_

View File

@ -0,0 +1,23 @@
#ifndef _UTILS_INPUTSTATE_H_
#define _UTILS_INPUTSTATE_H_
#include <stdint.h>
namespace Doncon::Utils {
struct InputState {
public:
struct Drum {
bool don_left, ka_left, don_right, ka_right;
};
public:
Drum drum;
public:
InputState();
};
} // namespace Doncon::Utils
#endif // _UTILS_INPUTSTATE_H_

View File

@ -1,11 +1,35 @@
#include "peripherals/Drum.h"
#include "GlobalConfiguration.h"
#include "pico/stdlib.h"
#include <stdio.h>
using namespace Doncon;
int main() {
Utils::InputState input_state;
Peripherals::Drum drum(Config::Default::drum_config);
stdio_init_all();
while (true) {
sleep_ms(1);
drum.updateInputState(input_state);
if (input_state.drum.don_left) {
printf("DON LEFT\n");
}
if (input_state.drum.don_right) {
printf("DON RIGHT\n");
}
if (input_state.drum.ka_left) {
printf("KA LEFT\n");
}
if (input_state.drum.ka_right) {
printf("KA RIGHT\n");
}
}
return 0;
}

63
src/peripherals/Drum.cpp Normal file
View File

@ -0,0 +1,63 @@
#include "peripherals/Drum.h"
#include "hardware/gpio.h"
#include "pico/time.h"
namespace Doncon::Peripherals {
Drum::Pad::Pad(uint8_t pin) : gpio_pin(pin), gpio_mask(1 << pin), last_change(0), active(false) {}
void Drum::Pad::setState(bool state, uint8_t debounce_delay) {
if (active == state) {
return;
}
// Immediately change the input state, but only allow a change every debounce_delay milliseconds.
uint32_t now = to_ms_since_boot(get_absolute_time());
if (last_change + debounce_delay <= now) {
active = state;
last_change = now;
}
}
Drum::Drum(const Config &config) : m_config(config) {
m_pads.emplace(Id::DON_LEFT_WEAK, config.pins.don_left_weak);
m_pads.emplace(Id::KA_LEFT_WEAK, config.pins.ka_left_weak);
m_pads.emplace(Id::DON_RIGHT_WEAK, config.pins.don_right_weak);
m_pads.emplace(Id::KA_RIGHT_WEAK, config.pins.ka_right_weak);
m_pads.emplace(Id::DON_LEFT_STRONG, config.pins.don_left_strong);
m_pads.emplace(Id::KA_LEFT_STRONG, config.pins.ka_left_strong);
m_pads.emplace(Id::DON_RIGHT_STRONG, config.pins.don_right_strong);
m_pads.emplace(Id::KA_RIGHT_STRONG, config.pins.ka_right_strong);
for (const auto &button : m_pads) {
gpio_init(button.second.getGpioPin());
gpio_set_dir(button.second.getGpioPin(), GPIO_IN);
gpio_pull_up(button.second.getGpioPin());
}
}
void Drum::updateInputState(Utils::InputState &input_state) {
uint32_t gpio_state = ~gpio_get_all();
for (auto &button : m_pads) {
button.second.setState(gpio_state & button.second.getGpioMask(), m_config.debounce_delay_ms);
}
input_state.drum.don_left = m_pads.at(Id::DON_LEFT_WEAK).getState() || //
m_pads.at(Id::DON_LEFT_STRONG).getState() || //
m_pads.at(Id::DON_RIGHT_STRONG).getState();
input_state.drum.ka_left = m_pads.at(Id::KA_LEFT_WEAK).getState() || //
m_pads.at(Id::KA_LEFT_STRONG).getState() || //
m_pads.at(Id::KA_RIGHT_STRONG).getState();
input_state.drum.don_right = m_pads.at(Id::DON_RIGHT_WEAK).getState() || //
m_pads.at(Id::DON_LEFT_STRONG).getState() || //
m_pads.at(Id::DON_RIGHT_STRONG).getState();
input_state.drum.ka_right = m_pads.at(Id::KA_RIGHT_WEAK).getState() || //
m_pads.at(Id::KA_LEFT_STRONG).getState() || //
m_pads.at(Id::KA_RIGHT_STRONG).getState();
}
} // namespace Doncon::Peripherals

7
src/utils/InputState.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "utils/InputState.h"
namespace Doncon::Utils {
InputState::InputState() : drum({false, false, false, false}) {}
} // namespace Doncon::Utils