diff --git a/CMakeLists.txt b/CMakeLists.txt index aab2c38..45c9cc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,10 @@ add_executable(${CMAKE_PROJECT_NAME} src/main.c src/sseg.c src/sseg.h + src/buzzer.c + src/buzzer.h + src/buttons.c + src/buttons.h src/pinout.h src/sseg.pio ) diff --git a/src/buttons.c b/src/buttons.c new file mode 100644 index 0000000..9c69971 --- /dev/null +++ b/src/buttons.c @@ -0,0 +1,64 @@ +#include + +#include "hardware/gpio.h" + +#include "pinout.h" + +#include "buttons.h" + +static const uint8_t m_pins[NUM_BUTTONS] = { + BTN_ON_PIN, + BTN_OFF_PIN +}; + +static uint8_t m_events[NUM_BUTTONS]; +static uint32_t m_last_change_time[NUM_BUTTONS]; +static uint32_t m_states; + +void buttons_init(void) +{ + for(int i = 0; i < NUM_BUTTONS; i++) { + gpio_init(m_pins[i]); + gpio_set_dir(m_pins[i], false); // true = output + gpio_set_pulls(m_pins[i], true, false); // enable pullup + } + + memset(m_events, 0, sizeof(m_events)); + memset(m_last_change_time, 0, sizeof(m_last_change_time)); + + m_states = 0; +} + +void buttons_update_state(uint32_t time_ms) +{ + for(int i = 0; i < NUM_BUTTONS; i++) { + bool is_pressed = gpio_get(m_pins[i]); + bool was_pressed = (m_states >> i) != 0; + + m_events[i] = 0; + if(is_pressed && !was_pressed) { + m_events[i] |= BTN_EVENT_PRESSED; + m_states |= (1 << i); + m_last_change_time[i] = time_ms; + } else if(!is_pressed && was_pressed) { + m_events[i] |= BTN_EVENT_RELEASED; + m_states &= ~(1 << i); + m_last_change_time[i] = time_ms; + } + } +} + +uint8_t buttons_get_events(button_id_t button) +{ + return m_events[button]; +} + +bool buttons_is_pressed(button_id_t button) +{ + return (m_states & (1 << button)) != 0; +} + +uint32_t buttons_get_last_change_time(button_id_t button) +{ + return m_last_change_time[button]; +} diff --git a/src/buttons.h b/src/buttons.h new file mode 100644 index 0000000..d814dc7 --- /dev/null +++ b/src/buttons.h @@ -0,0 +1,24 @@ +#ifndef BUTTONS_H +#define BUTTONS_H + +#include +#include + +#define BTN_EVENT_PRESSED (1 << 0) +#define BTN_EVENT_RELEASED (1 << 1) + +typedef enum { + BTN_ON, + BTN_OFF, + + NUM_BUTTONS +} button_id_t; + +void buttons_init(void); +void buttons_update_state(uint32_t time_ms); + +uint8_t buttons_get_events(button_id_t button); +bool buttons_is_pressed(button_id_t button); +uint32_t buttons_get_last_change_time(button_id_t button); + +#endif // BUTTONS_H diff --git a/src/buzzer.c b/src/buzzer.c new file mode 100644 index 0000000..e9a313c --- /dev/null +++ b/src/buzzer.c @@ -0,0 +1,41 @@ +#include "hardware/gpio.h" +#include "hardware/pwm.h" + +#include +#include + +#include "pinout.h" + +#include "buzzer.h" + +#define FREQ_BASE 24414063 // round(125 MHz [CPU frequency] * 100 [scaling] / 512 [PWM steps]) + +uint m_slice_num; + +void buzzer_init(void) +{ + gpio_init(BUZZER_PIN); + gpio_put(BUZZER_PIN, false); + gpio_set_dir(BUZZER_PIN, true); + + m_slice_num = pwm_gpio_to_slice_num(BUZZER_PIN); + + pwm_set_clkdiv_int_frac(m_slice_num, 244, (14 << 4) / 100); // 125 MHz / 244.14 / 512 = 1 kHz + gpio_set_function(BUZZER_PIN, GPIO_FUNC_PWM); + pwm_set_wrap(m_slice_num, 512); + pwm_set_chan_level(m_slice_num, PWM_CHAN_B, 1 * 512 / 100); +} + +void buzzer_on(uint16_t freq_hz) +{ + uint32_t divider_x100 = FREQ_BASE / freq_hz; // = 100 * 125e6 / 512 / freq_hz + + pwm_set_clkdiv_int_frac(m_slice_num, divider_x100 / 100, divider_x100 % 100); + pwm_set_enabled(m_slice_num, true); +} + +void buzzer_off(void) +{ + pwm_set_enabled(m_slice_num, false); + gpio_set_function(BUZZER_PIN, GPIO_FUNC_NULL); +} diff --git a/src/buzzer.h b/src/buzzer.h new file mode 100644 index 0000000..23d1dff --- /dev/null +++ b/src/buzzer.h @@ -0,0 +1,11 @@ +#ifndef BUZZER_H +#define BUZZER_H + +#include + +void buzzer_init(void); + +void buzzer_on(uint16_t freq_hz); +void buzzer_off(void); + +#endif // BUZZER_H