#include "stm32f0xx_hal.h"
#include "ssd1306.h"
#include "stringhelpers.h"
#include "display.h"
#include "config.h"
#include "states.h"
#include "bootlib.h"
#include "flash.h"
#include "gpio.h"
uint8_t goto_mode = 2;
// State machine
uint8_t sw_btn_last = 0;
uint8_t sw_up_last = 0;
uint8_t sw_down_last = 0;
uint8_t sw_left_last = 0;
uint8_t sw_right_last = 0;
#define SW_BTN_PRESSED (sw_btn_last == 0 && sw_btn == 1) // rising edge on buttonpress
#define SW_UP_PRESSED (sw_up_last == 0 && sw_up == 1)
#define SW_DOWN_PRESSED (sw_down_last == 0 && sw_down == 1)
#define SW_LEFT_PRESSED (sw_left_last == 0 && sw_left == 1)
#define SW_RIGHT_PRESSED (sw_right_last == 0 && sw_right == 1)
///////////////////////////////////////////////////////////////////////////////////////
/// freaking multiple setpoint support ///
uint8_t step_duration[10] = {0,0,0,0,0,0,0,0,0,0};
int16_t step_setpoint[10] = {0,0,0,0,0,0,0,0,0,0};
uint8_t final_setpoint = 0;
// Multiple screens to set setpoint and duration on each screen
// press center to go to the next one, and press left or right or something to confirm
// When executing, complete on time AND(?) temperature. Maybe allow switching to OR via settings
////////////////////////////////////////////////////////////////////////////////////////////////
uint8_t trigger_drawsetpoint = 1;
int16_t last_temp = 21245;
void display_process(therm_settings_t* set, therm_status_t* status)
{
uint8_t last_state = status->state;
uint8_t temp_changed = status->temp != last_temp;
last_temp = status->temp;
uint8_t sw_btn = !HAL_GPIO_ReadPin(SW_BTN);
uint8_t sw_up = !HAL_GPIO_ReadPin(SW_UP);
uint8_t sw_down = !HAL_GPIO_ReadPin(SW_DOWN);
uint8_t sw_left = !HAL_GPIO_ReadPin(SW_LEFT);
uint8_t sw_right = !HAL_GPIO_ReadPin(SW_RIGHT);
switch(status->state)
// Idle state
case STATE_IDLE:
// Write text to OLED
// [ therm :: idle ]
ssd1306_DrawString("therm :: idle ", 0, 40);
status->pid_enabled = 0;
if(temp_changed) {
char tempstr[6];
itoa_fp(status->temp, status->temp_frac, tempstr);
ssd1306_DrawString("Temp: ", 3, 40);
ssd1306_DrawString(" ", 3, 72);
ssd1306_DrawString(tempstr, 3, 72);
}
ssd1306_drawlogo();
switch(goto_mode) {
case 3:
ssd1306_DrawString("-> loader ", 1, 40);
} break;
case 2:
ssd1306_DrawString("-> heat ", 1, 40);
case 1:
ssd1306_DrawString("-> setup ", 1, 40);
case 0:
ssd1306_DrawString("-> reset ", 1, 40);
// Button handler
if(SW_BTN_PRESSED) {
status->state = STATE_IDLE;
flash_erase(set);
status->state = STATE_PREHEAT_BREW;
break;
status->state = STATE_SETP;
ssd1306_clearscreen();
ssd1306_DrawString("Bootloader Entered", 0, 0);
ssd1306_DrawString("Device won't boot", 2, 0);
ssd1306_DrawString("until reflashed!", 3, 0);
bootloader_enter(); // Resets into bootloader
status->state = STATE_IDLE; // Just in case
NVIC_SystemReset();
default:
else if(SW_UP_PRESSED && goto_mode < 3) {
goto_mode++;
else if(SW_DOWN_PRESSED && goto_mode > 0) {
goto_mode--;
// Event Handler
// N/A
case STATE_SETP:
// [ therm :: set p ]
// [ p = 12 ]
ssd1306_DrawString("Proportional", 0, 40);
itoa(set->k_p, tempstr, 10);
ssd1306_DrawString("P=", 1, 45);
ssd1306_DrawString(" ", 1, 57);
ssd1306_DrawString(tempstr, 1, 57);
ssd1306_DrawString("Press to accept", 3, 40);
status->state = STATE_SETI;
else {
user_input(&set->k_p);
case STATE_SETI:
// [ therm :: set i ]
// [ i = 12 ]
ssd1306_DrawString("Integral", 0, 40);
itoa(set->k_i, tempstr, 10);
ssd1306_DrawString("I=", 1, 45);
status->state = STATE_SETD;
user_input(&set->k_i);
case STATE_SETD:
// [ therm :: set d ]
// [ d = 12 ]
ssd1306_DrawString("Derivative", 0, 40);
itoa(set->k_d, tempstr, 10);
ssd1306_DrawString("D=", 1, 45);
status->state = STATE_SETWINDUP;
Status change: