@@ -14,27 +14,39 @@
// Interval of PID calculations
#define PID_PERIOD 120
// Pin settings
#define LED_POWER GPIOF,GPIO_PIN_0
#define MAX_CS GPIOA,GPIO_PIN_15
#define SW_BTN GPIOB, GPIO_PIN_4
#define SW_UP GPIOB, GPIO_PIN_7
#define SW_DOWN GPIOB, GPIO_PIN_3
#define SW_LEFT GPIOB, GPIO_PIN_5
#define SW_RIGHT GPIOB, GPIO_PIN_6
#define SSR_PIN GPIOA, GPIO_PIN_1
// Visual niceness
#define hal_init() HAL_Init()
// Add bootloader option to top of idle screen menu
#define BOOTLOADER_SHORTCUT
#define DEFAULT_BOOT_TO_BREW 0
#define DEFAULT_TEMP_UNITS TEMP_UNITS_FAHRENHEIT
#define DEFAULT_WINDUP_GUARD 10
#define DEFAULT_K_P 10
#define DEFAULT_K_I 1
#define DEFAULT_K_D 1
#define DEFAULT_IGNORE_ERROR 0
#define DEFAULT_SETPOINT_BREW 70
#define DEFAULT_SETPOINT_STEAM 70
#endif
// vim:softtabstop=4 shiftwidth=4 expandtab
@@ -316,49 +316,49 @@ void display_process(therm_settings_t* s
// Event Handler
// N/A
} break;
case STATE_SETTEMPOFFSET:
{
// Write text to OLED
// [ therm :: set temp offset ]
// [ g = 12 ]
ssd1306_drawstring("Temp Cal Offset", 0, 40);
ssd1306_drawlogo();
char tempstr[6];
itoa(set->val.temp_offset, tempstr, 10);
ssd1306_drawstring("O=", 1, 45);
ssd1306_drawstring(" ", 1, 57);
ssd1306_drawstring(tempstr, 1, 57);
ssd1306_drawstring("Press to accept", 3, 40);
// Button handler
if(SW_BTN_PRESSED) {
flash_save(&set);
flash_save(set);
status->state = STATE_IDLE;
}
else {
user_input_signed(&set->val.temp_offset);
case STATE_PREHEAT:
// [ therm : preheating brew ]
// [ 30 => 120 C ]
ssd1306_drawstring("Preheating...", 0, 0);
//ssd1306_drawlogo();
draw_setpoint(status);
status->pid_enabled = 1;
status->setpoint = set->val.setpoint_brew;
@@ -466,49 +466,50 @@ void display_process(therm_settings_t* s
ssd1306_drawstring("-> bootloader", 1, 40);
case RESET_EXIT:
ssd1306_drawstring("-> exit ", 1, 40);
switch(reset_mode) {
case RESET_BOOTLOADER:
ssd1306_clearscreen();
ssd1306_drawstring("Bootloader Entered", 0, 0);
ssd1306_drawstring("Device won't boot", 2, 0);
ssd1306_drawstring("until reflashed!", 3, 0);
HAL_Delay(1000);
bootloader_enter(); // Resets into bootloader
status->state = STATE_RESET; // Just in case
case RESET_RESET:
status->state = STATE_RESET;
//flash_erase();
flash_load_defaults(set);
NVIC_SystemReset();
else if(SW_DOWN_PRESSED && reset_mode < (RESET_SIZE-1)) {
reset_mode++;
else if(SW_UP_PRESSED && reset_mode > 0) {
reset_mode--;
// Something is terribly wrong
default:
#include "stm32f0xx_hal.h"
#include "ssd1306.h"
#include "stm32f0xx_hal_flash.h"
#include "flash.h"
__attribute__((__section__(".eeprom"))) uint16_t eeprom[512];
static void __flash_write(therm_settings_t* tosave);
#define EEPROM_MAGIC_INDEX 16
#define EEPROM_MAGIC_INDEX 0
#define EEPROM_MAGIC_VALUE 0xbeef
void flash_save(therm_settings_t* tosave)
ssd1306_drawstring("Erase...", 0, 0);
HAL_Delay(100);
ssd1306_drawstring("Save...", 1, 0);
__flash_write(tosave);
ssd1306_drawstring("Done!", 2, 0);
HAL_Delay(500);
void flash_restore(therm_settings_t *torestore)
ssd1306_drawstring("READING SAVE", 1, 0);
if(eeprom[EEPROM_MAGIC_INDEX] != EEPROM_MAGIC_VALUE)
if(eeprom[EEPROM_MAGIC_INDEX] == EEPROM_MAGIC_VALUE)
ssd1306_drawstring("No data to read!", 2, 0);
return;
for(uint8_t i = 1; i <= 20; i++) {
torestore->data[i] = *(eeprom+i);
// load default settings
flash_load_defaults(torestore);
uint16_t i;
for(i=0;i<128;i++)
void flash_load_defaults(therm_settings_t* torestore) {
ssd1306_drawstring("READ COMPLETE", 3, 0);
torestore->val.boottobrew = DEFAULT_BOOT_TO_BREW;
torestore->val.temp_units = DEFAULT_TEMP_UNITS;
torestore->val.windup_guard = DEFAULT_WINDUP_GUARD;
torestore->val.k_p = DEFAULT_K_P;
torestore->val.k_i = DEFAULT_K_I;
torestore->val.k_d = DEFAULT_K_D;
torestore->val.ignore_error = DEFAULT_IGNORE_ERROR;
torestore->val.setpoint_brew = DEFAULT_SETPOINT_BREW;
torestore->val.setpoint_steam = DEFAULT_SETPOINT_STEAM;
static void __flash_write(therm_settings_t* tosave)
// Erase mem
HAL_FLASH_Unlock();
//TODO: add checksum instead of magic value
//TODO: change checksum to invalidate flash instead of erase?
// Erase the FLASH pages
FLASH_EraseInitTypeDef erase;
erase.TypeErase = TYPEERASE_PAGES;
erase.PageAddress = eeprom;
erase.PageAddress = (uint32_t) eeprom;
erase.NbPages = 1;
uint32_t SectorError = 0;
HAL_FLASHEx_Erase(&erase, &SectorError);
CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
// for(i=1;i<20;i++)
// {
// HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, eeprom+i, tosave->data[i]);
// }
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, eeprom + EEPROM_MAGIC_INDEX, EEPROM_MAGIC_VALUE);
for(uint8_t i = 1; i <= (sizeof(therm_settings_t)/2); i++)
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, (uint32_t)(eeprom + i), tosave->data[i]);
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, (uint32_t)(eeprom + EEPROM_MAGIC_INDEX), EEPROM_MAGIC_VALUE);
HAL_FLASH_Lock();
#ifndef FLASH_H
#define FLASH_H
#include "states.h"
#define PAGE_SIZE ((uint16_t)0x400)
#define END_ADDR 0x08007FFF
void flash_save(therm_settings_t* tosave);
void flash_restore(therm_settings_t *tosave);
void flash_load_defaults(therm_settings_t* torestore);
void flash_erase(void);
@@ -36,59 +36,48 @@ int main(void)
// Init USB (TODO: Handle plugged/unplugged with external power)
MX_USB_DEVICE_Init();
// set.val.usb_plugged =
// USB startup delay
HAL_GPIO_WritePin(LED_POWER, 1);
// Enter into bootloader if up button pressed on boot
if(!HAL_GPIO_ReadPin(SW_UP))
bootloader_enter();
// Init SPI busses
spi_init();
#ifdef MAX31865_RTD_SENSOR
max31865_config(spi_get());
// Init OLED over SPI
ssd1306_init();
// Default settings
set.val.boottobrew = 0;
set.val.temp_units = TEMP_UNITS_FAHRENHEIT;
set.val.windup_guard = 10;
set.val.k_p = 10;
set.val.k_i = 1;
set.val.k_d = 1;
set.val.ignore_error = 0;
set.val.setpoint_brew = 70;
set.val.setpoint_steam = 70;
// Default status
status.temp = 0;
status.temp_frac = 0;
status.state_resume = 0;
status.state = STATE_IDLE;
status.setpoint = 70;
status.pid_enabled = 0;
// Go to brew instead of idle if configured thusly
if(set.val.boottobrew)
status.state = STATE_PREHEAT;
// Startup screen
ssd1306_drawstring("therm v0.2", 1, 40);
ssd1306_drawstring("protofusion.org/therm", 3, 0);
// Restore settings from flash memory
flash_restore(&set);
Status change: