WIP: started implementing the countdown state machine
This commit is contained in:
parent
0c95a27a3f
commit
7d36e71923
164
src/main.c
164
src/main.c
|
@ -1,16 +1,24 @@
|
|||
#include "hardware/gpio.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/irq.h"
|
||||
|
||||
#include "sseg.h"
|
||||
#include "buttons.h"
|
||||
#include "buzzer.h"
|
||||
#include "pinout.h"
|
||||
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
const uint8_t all_gpios[] = {
|
||||
OUTPUT_ENABLE_PIN,
|
||||
};
|
||||
typedef enum {
|
||||
COUNTDOWN_UNINITIALIZED,
|
||||
COUNTDOWN_STOPPED,
|
||||
COUNTDOWN_STARTING,
|
||||
COUNTDOWN_RUNNING
|
||||
} countdown_state_t;
|
||||
|
||||
static countdown_state_t m_countdown_state;
|
||||
static uint32_t m_last_state_change_time;
|
||||
|
||||
static uint32_t m_countdown_off_time;
|
||||
|
||||
static volatile bool m_ms_triggered;
|
||||
static uint32_t m_next_ms_trigger;
|
||||
|
@ -45,62 +53,139 @@ static void configure_ms_trig_alarm(void)
|
|||
m_next_ms_trigger = timer_hw->timelr + 10000;
|
||||
}
|
||||
|
||||
static void update_countdown_fsm(uint32_t time_ms)
|
||||
{
|
||||
countdown_state_t last_state = m_countdown_state;
|
||||
|
||||
// note: this calculation works even if time_ms overflows
|
||||
uint32_t time_in_state = time_ms - m_last_state_change_time;
|
||||
bool state_entered = (time_in_state == 1);
|
||||
|
||||
uint32_t countdown_time_remaining; // only used in COUNTDOWN_RUNNING state
|
||||
|
||||
switch(m_countdown_state) {
|
||||
case COUNTDOWN_UNINITIALIZED:
|
||||
m_countdown_state = COUNTDOWN_STOPPED;
|
||||
break;
|
||||
|
||||
case COUNTDOWN_STOPPED:
|
||||
if(state_entered) {
|
||||
sseg_set_char(0, 'o', false);
|
||||
sseg_set_char(1, 'f', false);
|
||||
sseg_set_char(2, 'f', false);
|
||||
}
|
||||
|
||||
if(buttons_get_events(BTN_ON) & BTN_EVENT_PRESSED) {
|
||||
m_countdown_state = COUNTDOWN_STARTING;
|
||||
}
|
||||
break;
|
||||
|
||||
case COUNTDOWN_STARTING:
|
||||
// TODO: show a fancy animation + beep code
|
||||
|
||||
if(buttons_get_events(BTN_ON) & BTN_EVENT_RELEASED) {
|
||||
// button released too early -> back to stopped state
|
||||
m_countdown_state = COUNTDOWN_STOPPED;
|
||||
}
|
||||
|
||||
if(time_in_state == 3000) {
|
||||
m_countdown_off_time = time_ms + 30 * 60 * 1000;
|
||||
m_countdown_state = COUNTDOWN_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
case COUNTDOWN_RUNNING:
|
||||
if(state_entered) {
|
||||
// countdown has been started -> switch on the load
|
||||
gpio_put(OUTPUT_ENABLE_PIN, true);
|
||||
}
|
||||
|
||||
countdown_time_remaining = m_countdown_off_time - time_ms;
|
||||
|
||||
// TODO: show time on display
|
||||
// TODO: off button handling
|
||||
// TODO: on button handling (extend time)
|
||||
|
||||
// beep codes
|
||||
switch(countdown_time_remaining) {
|
||||
case 300000: // short beep at 5 minutes remaining
|
||||
case 60000: // double beep at 1 minute remaining
|
||||
case 59600:
|
||||
case 10000: // triple beep at 10 seconds remaining
|
||||
case 9600:
|
||||
case 9200:
|
||||
case 5000: // count down the last 5 seconds
|
||||
case 4000:
|
||||
case 3000:
|
||||
case 2000:
|
||||
case 1000: // last second beep is longer
|
||||
buzzer_on(1000);
|
||||
break;
|
||||
|
||||
case 299800:
|
||||
case 59800:
|
||||
case 59400:
|
||||
case 9800:
|
||||
case 9400:
|
||||
case 9000:
|
||||
case 4800:
|
||||
case 3800:
|
||||
case 2800:
|
||||
case 1800:
|
||||
case 500:
|
||||
buzzer_off();
|
||||
break;
|
||||
}
|
||||
|
||||
if(countdown_time_remaining == 0) {
|
||||
// switch off the load
|
||||
gpio_put(OUTPUT_ENABLE_PIN, false);
|
||||
m_countdown_state = COUNTDOWN_STOPPED;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_countdown_state != last_state) {
|
||||
m_last_state_change_time = time_ms;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//stdio_init_all();
|
||||
//printf("Hello, world!\n");
|
||||
|
||||
bool power_switch_state = false;
|
||||
gpio_init(OUTPUT_ENABLE_PIN);
|
||||
gpio_put(OUTPUT_ENABLE_PIN, false);
|
||||
gpio_set_dir(OUTPUT_ENABLE_PIN, true);
|
||||
|
||||
for(size_t i = 0; i < sizeof(all_gpios); i++) {
|
||||
gpio_init(all_gpios[i]);
|
||||
gpio_put(all_gpios[i], false);
|
||||
gpio_set_dir(all_gpios[i], true);
|
||||
}
|
||||
buzzer_init();
|
||||
buttons_init();
|
||||
|
||||
gpio_put(OUTPUT_ENABLE_PIN, true);
|
||||
|
||||
// set up PWM for 50 kHz @ 512 steps resolution
|
||||
uint slice_num = pwm_gpio_to_slice_num(BUZZER_PIN);
|
||||
|
||||
pwm_set_clkdiv_int_frac(slice_num, 244, (14 << 4) / 100); // 125 MHz / 244.14 / 512 = 1 kHz
|
||||
gpio_set_function(BUZZER_PIN, GPIO_FUNC_PWM);
|
||||
pwm_set_wrap(slice_num, 512);
|
||||
pwm_set_chan_level(slice_num, PWM_CHAN_B, 1 * 512 / 100);
|
||||
pwm_set_enabled(slice_num, true);
|
||||
buzzer_on(1000);
|
||||
|
||||
sleep_ms(200);
|
||||
|
||||
pwm_set_enabled(slice_num, false);
|
||||
pwm_set_clkdiv_int_frac(slice_num, 122, (7 << 4) / 100); // 125 MHz / 122.07 / 512 = 2 kHz
|
||||
pwm_set_enabled(slice_num, true);
|
||||
|
||||
buzzer_off();
|
||||
buzzer_on(2000);
|
||||
|
||||
sleep_ms(200);
|
||||
|
||||
pwm_set_enabled(slice_num, false);
|
||||
pwm_set_clkdiv_int_frac(slice_num, 61, (3 << 4) / 100); // 125 MHz / 61.03 / 512 = 4 kHz
|
||||
pwm_set_enabled(slice_num, true);
|
||||
buzzer_off();
|
||||
buzzer_on(4000);
|
||||
|
||||
sleep_ms(200);
|
||||
|
||||
pwm_set_enabled(slice_num, false);
|
||||
gpio_init(BUZZER_PIN);
|
||||
gpio_put(BUZZER_PIN, false);
|
||||
gpio_set_dir(BUZZER_PIN, true);
|
||||
buzzer_off();
|
||||
|
||||
sleep_ms(2400);
|
||||
|
||||
pwm_set_enabled(slice_num, false);
|
||||
gpio_init(BUZZER_PIN);
|
||||
|
||||
gpio_put(OUTPUT_ENABLE_PIN, false);
|
||||
|
||||
sseg_init();
|
||||
|
||||
configure_ms_trig_alarm();
|
||||
arm_ms_trig_alarm();
|
||||
|
||||
m_countdown_state = COUNTDOWN_UNINITIALIZED;
|
||||
|
||||
uint32_t ms_counter = 0;
|
||||
while (true) {
|
||||
sseg_loop();
|
||||
|
@ -109,6 +194,11 @@ int main()
|
|||
m_ms_triggered = false;
|
||||
|
||||
ms_counter++;
|
||||
|
||||
buttons_update_state(ms_counter);
|
||||
|
||||
update_countdown_fsm(ms_counter);
|
||||
|
||||
sseg_set_char(2, '0' + (ms_counter / 100) % 10, false);
|
||||
sseg_set_char(1, '0' + (ms_counter / 1000) % 10, true);
|
||||
sseg_set_char(0, '0' + (ms_counter / 10000) % 10, false);
|
||||
|
|
Loading…
Reference in a new issue