Changeset - 08c52ee196d1
[Not reviewed]
cortex-f0
0 3 1
Ethan Zonca - 10 years ago 2015-01-03 13:46:06
ez@ethanzonca.com
Added cube, etc
4 files changed with 188 insertions and 24 deletions:
0 comments (0 inline, 0 general)
eeprom_min.c
Show inline comments
 
#include <inttypes.h>
 

	
 
/*
 
void Minimal_EEPROM_Unlock(void)
 
{
 
  if((FLASH->PECR & FLASH_PECR_PELOCK) != RESET)
 
  {
 
    /* Unlocking the Data memory and FLASH_PECR register access*/
 
    // Unlocking the Data memory and FLASH_PECR register access
 
    FLASH->PEKEYR = FLASH_PEKEY1;
 
    FLASH->PEKEYR = FLASH_PEKEY2;
 
  }
 
}
 

	
 
void Minimal_EEPROM_Lock(void)
 
{
 
  /* Set the PELOCK Bit to lock the data memory and FLASH_PECR register access */
 

	
 
  // Set the PELOCK Bit to lock the data memory and FLASH_PECR register access 
 
  FLASH->PECR |= FLASH_PECR_PELOCK;
 
}
 

	
 
FLASH_Status Minimal_FLASH_GetStatus(void)
 
{
 
  FLASH_Status FLASHstatus = FLASH_COMPLETE;
 

	
 
  if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY)
 
  {
 
    FLASHstatus = FLASH_BUSY;
 
  }
 
  else
 
  {
 
    if((FLASH->SR & (uint32_t)FLASH_FLAG_WRPERR)!= (uint32_t)0x00)
 
    {
 
      FLASHstatus = FLASH_ERROR_WRP;
 
    }
 
    else
 
    {
 
      if((FLASH->SR & (uint32_t)0x1E00) != (uint32_t)0x00)
 
      {
 
        FLASHstatus = FLASH_ERROR_PROGRAM;
 
      }
 
      else
 
      {
 
        FLASHstatus = FLASH_COMPLETE;
 
      }
 
    }
 
  }
 
  /* Return the FLASH Status */
 
  // Return the FLASH Status 
 
  return FLASHstatus;
 
}
 

	
 
FLASH_Status Minimal_FLASH_WaitForLastOperation(uint32_t Timeout)
 
{
 
  __IO FLASH_Status status = FLASH_COMPLETE;
 

	
 
  /* Check for the FLASH Status */
 
  // Check for the FLASH Status 
 
  status = Minimal_FLASH_GetStatus();
 

	
 
  /* Wait for a FLASH operation to complete or a TIMEOUT to occur */
 
  // Wait for a FLASH operation to complete or a TIMEOUT to occur 
 
  while((status == FLASH_BUSY) && (Timeout != 0x00))
 
  {
 
    status = Minimal_FLASH_GetStatus();
 
    Timeout--;
 
  }
 

	
 
  if(Timeout == 0x00 )
 
  {
 
    status = FLASH_TIMEOUT;
 
  }
 
  /* Return the operation status */
 
  // Return the operation status 
 
  return status;
 
}
 

	
 

	
 
void Minimal_EEPROM_ProgramWord(uint32_t Address, uint32_t Data)
 
{
 
  // Wait for last operation to be completed 
 
  FLASH_Status status = FLASH_COMPLETE;
 
  status = Minimal_FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
 

	
 
  if(status == FLASH_COMPLETE)
 
  {
 
    *(__IO uint32_t *)Address = Data;
 

	
 
    // Wait for last operation to be completed 
 
    status = Minimal_FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
 
  }
 
  // Return the Write Status 
 
  return status;
 
}
 

	
 
*/
gpio.c
Show inline comments
 
#include "gpio.h"
 
#include "config.h"
 

	
 
extern volatile uint32_t ticks;
 

	
 
// Increase on each press, and increase at a fast rate after duration elapsed of continuously holding down... somehow...
 
uint32_t change_time_reset = 0;
 

	
 
void user_input(uint16_t* to_modify)
 
{
 
    if(CHANGE_ELAPSED) {
 
        if(!GPIO_ReadInputDataBit(SW_UP) ) {
 
            CHANGE_RESET;
 
            (*to_modify)++;
 
        }
 
        else if(!GPIO_ReadInputDataBit(SW_DOWN) && (*to_modify) > 0) {
 
            CHANGE_RESET;
 
            (*to_modify)--;
 
        }
 
    }
 
}
 

	
 

	
 
void init_gpio(void) {
 

	
 
 GPIO_InitTypeDef GPIO_InitStruct;
 
  GPIO_InitTypeDef GPIO_InitStruct;
 

	
 
  // Enable SPI clocks
 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
 
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
 

	
 
  // Enable GPIO clocks
 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC|RCC_AHBPeriph_GPIOB|RCC_AHBPeriph_GPIOA, ENABLE);
 

	
 
  // Enable DMA clocks (Is AHB even the right thing???)
 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // EMZ TODO get the right ones
 

	
 
  /*Configure GPIO pin : PC */
 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_400KHz;
 
  GPIO_Init(GPIOC, &GPIO_InitStruct);
 

	
 
  /*Configure GPIO pin : PB */
 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_10|GPIO_Pin_12 
 
                          |GPIO_Pin_9;
 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_400KHz;
 
  GPIO_Init(GPIOB, &GPIO_InitStruct);
 

	
 
  /*Configure GPIO pin : PA */
 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
 
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_400KHz;
 
  GPIO_Init(GPIOA, &GPIO_InitStruct);
 

	
 
  /*Configure GPIO pin : PB */
 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6 
 
                          |GPIO_Pin_7;
 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
 
  GPIO_Init(GPIOB, &GPIO_InitStruct);
 

	
 
  /** SPI1 GPIO Configuration  
 
  PA5   ------> SPI1_SCK
 
  PA7   ------> SPI1_MOSI
 
  */
 

	
 
  /*Enable or disable the AHB peripheral clock */
 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 

	
 
  /*Configure GPIO pin : PA: MOSI,SCK */
 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
 
  GPIO_Init(GPIOA, &GPIO_InitStruct);
 

	
 
  /*Configure GPIO pin alternate function */
 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
 

	
 
  /*Configure GPIO pin alternate function */
 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
 

	
 
  /** SPI2 GPIO Configuration  
 
  PB13   ------> SPI2_SCK
 
  PB14   ------> SPI2_MISO
 
  PB15   ------> SPI2_MOSI
 
  */
 

	
 
  /*Enable or disable the AHB peripheral clock */
 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
 

	
 
// SPI PINSSS
 
  // SPI PINSSS
 

	
 
  /*Configure GPIO pin : PB, MOSI, SCK */
 
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
 
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
 
  GPIO_Init(GPIOB, &GPIO_InitStruct);
 

	
 
 GPIO_InitTypeDef GPIO_InitStruct2;
 
// MISO
 
  GPIO_InitTypeDef GPIO_InitStruct2;
 
  // MISO
 
  GPIO_InitStruct2.GPIO_Pin = GPIO_Pin_14;
 
  GPIO_InitStruct2.GPIO_Mode = GPIO_Mode_AF;
 
  GPIO_InitStruct2.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStruct2.GPIO_Speed = GPIO_Speed_10MHz;
 
  GPIO_Init(GPIOB, &GPIO_InitStruct2);
 

	
 

	
 
  //Configure GPIO pin alternate function 
 
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);
 
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);
 
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);
 

	
 

	
 
  /** USB GPIO Configuration  
 
  PA11   ------> USB_DM
 
  PA12   ------> USB_DP
 
  */
 

	
 
  /*Enable or disable the AHB peripheral clock */
 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 
  //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 

	
 
  GPIO_InitTypeDef GPIO_InitStruct3;
 
  //GPIO_InitTypeDef GPIO_InitStruct3;
 
  
 
  /*Configure GPIO pin : PA */
 
  GPIO_InitStruct3.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
 
  GPIO_InitStruct3.GPIO_Mode = GPIO_Mode_AF;
 
  GPIO_InitStruct3.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStruct3.GPIO_Speed = GPIO_Speed_10MHz;
 
  GPIO_InitStruct3.GPIO_OType = GPIO_OType_PP;
 
  GPIO_Init(GPIOA, &GPIO_InitStruct3);
 
  GPIO_SetBits(GPIOA, GPIO_Pin_12); // emz test
 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_USB);
 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_USB);
 
  //GPIO_InitStruct3.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
 
  //GPIO_InitStruct3.GPIO_Mode = GPIO_Mode_AF;
 
  //GPIO_InitStruct3.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  //GPIO_InitStruct3.GPIO_Speed = GPIO_Speed_10MHz;
 
  //GPIO_InitStruct3.GPIO_OType = GPIO_OType_PP;
 
  //GPIO_Init(GPIOA, &GPIO_InitStruct3);
 
  //GPIO_SetBits(GPIOA, GPIO_Pin_12); // emz test
 
  //GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_USB);
 
  //GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_USB);
 
}
 

	
 
// vim:softtabstop=4 shiftwidth=4 expandtab 
main.c
Show inline comments
 
@@ -154,433 +154,437 @@ void update_temp() {
 
 
    // This may not clock at all... might need to send 16 bits first
 
    SPI_I2S_SendData(SPI2, 0xAAAA); // send dummy data
 
    //SPI_I2S_SendData(SPI2, 0xAA); // send dummy data
 
    uint16_t temp_pre = SPI_I2S_ReceiveData(SPI2);
 
 
    if(temp_pre & 0b0000000000000010) {
 
        ssd1306_DrawString("Fatal Error", 3, 35);
 
        state = STATE_TC_ERROR;
 
    }
 
    else if(temp_pre & 0b0000000000000001 && !ignore_tc_error) {
 
        state_resume = state;
 
        state = STATE_TC_ERROR;
 
        temp = 0;
 
        temp_frac = 0;
 
    }
 
    else 
 
    {
 
        if(state == STATE_TC_ERROR)
 
        {
 
            state = state_resume;
 
            ssd1306_clearscreen();
 
        }
 
 
        uint8_t sign = temp >> 15;// top bit is sign
 
 
        temp_pre = temp_pre >> 2; // Drop 2 lowest bits
 
        temp_frac = temp_pre & 0b11; // get fractional part
 
        temp_frac *= 25; // each bit is .25 a degree, up to fixed point
 
        temp_pre = temp_pre >> 2; // Drop 2 fractional bits 
 
 
        if(sign) {
 
            temp = -temp_pre;
 
        }
 
        else {
 
            temp = temp_pre;
 
        }
 
 
        if(temp_units == TEMP_UNITS_FAHRENHEIT) {
 
            temp *= 9; // fixed point mul by 1.8
 
            temp /= 5;
 
            temp += 32;
 
 
            temp_frac *= 9;
 
            temp_frac /= 5;
 
            temp_frac += 32;
 
            temp += temp_frac/100; // add overflow to above
 
            temp_frac %= 100;
 
        }
 
    }
 
 
    // Deassert CS
 
    delay(1);
 
    GPIO_SetBits(MAX_CS);
 
}
 
 
 
// PID implementation
 
// TODO: Make struct that has the last_temp and i_state in it, pass by ref. Make struct that has other input values maybe.
 
int16_t last_pid_temp = 0;
 
uint8_t last_pid_temp_frac = 0;
 
int16_t i_state = 0;
 
 
int16_t update_pid(uint16_t k_p, uint16_t k_i, uint16_t k_d, int16_t temp, uint8_t temp_frac, int16_t setpoint) 
 
{
 
  // Calculate instantaneous error
 
  int16_t error = (int16_t)setpoint - (int16_t)temp; // TODO: Use fixed point fraction
 
 
  // Proportional component
 
  int16_t p_term = k_p * error;
 
 
  // Error accumulator (integrator)
 
  i_state += error;
 
 
  // to prevent the iTerm getting huge despite lots of 
 
  //  error, we use a "windup guard" 
 
  // (this happens when the machine is first turned on and
 
  // it cant help be cold despite its best efforts)
 
  // not necessary, but this makes windup guard values 
 
  // relative to the current iGain
 
  int16_t windup_guard_res = windup_guard / k_i;  
 
 
  // Calculate integral term with windup guard 
 
  if (i_state > windup_guard_res) 
 
    i_state = windup_guard_res;
 
  else if (i_state < -windup_guard_res) 
 
    i_state = -windup_guard_res;
 
  int16_t i_term = k_i * i_state;
 
 
  // Calculate differential term (slope since last iteration)
 
  int16_t d_term = (k_d * (temp - last_pid_temp));
 
 
  // Save temperature for next iteration
 
  last_pid_temp = temp;
 
  last_pid_temp_frac = temp_frac;
 
 
  int16_t result = p_term + i_term - d_term;
 
 
  // Put out tenths of percent, 0-1000. 
 
  if(result > 1000)
 
    result = 1000;
 
  else if(result < -1000)
 
    result = -1000;
 
 
  // Return feedback
 
  return result;
 
}
 
 
 
uint32_t last_ssr_on = 0;
 
uint32_t last_led = 0;
 
int32_t setpoint = 0;
 
int16_t ssr_output = 0; // Duty cycle of ssr, 0 to SSR_PERIOD 
 
uint8_t pid_enabled = 0;
 
 
// Process things
 
void process()
 
{
 
    update_temp(); // Read MAX31855
 
 
    // TODO: Add calibration offset (linear)
 
 
    if(ticks - last_led > 400) 
 
    {
 
        GPIO_ToggleBits(LED_POWER);
 
        last_led = ticks;
 
    }
 
 
    // Every 200ms, set the SSR on unless output is 0
 
    if((ticks - last_ssr_on > SSR_PERIOD))
 
    {
 
        if(pid_enabled) 
 
        {
 
            // Get ssr output for next time
 
            int16_t power_percent = update_pid(k_p, k_i, k_d, temp, temp_frac, setpoint);
 
            //power-percent is 0-1000
 
            ssr_output = power_percent; //(((uint32_t)SSR_PERIOD * (uint32_t)10 * (uint32_t)100) * power_percent) / (uint32_t)1000000;
 
        }
 
        else 
 
        {
 
            ssr_output = 0;
 
        }
 
 
        // Only support heating (ssr_output > 0) right now
 
        if(ssr_output > 0) {
 
 
            char tempstr[6];
 
            itoa(ssr_output, tempstr);
 
            ssd1306_DrawString(tempstr, 0, 90);
 
 
            GPIO_SetBits(LED_STAT);
 
            GPIO_SetBits(SSR_PIN);
 
            last_ssr_on = ticks;
 
        }
 
    }
 
    
 
    // Kill SSR after elapsed period less than SSR_PERIOD 
 
    if(ticks - last_ssr_on > ssr_output || ssr_output == 0)
 
    {
 
        GPIO_ResetBits(LED_STAT);
 
        GPIO_ResetBits(SSR_PIN);
 
    }
 
}
 
 
void draw_setpoint() {
 
    char tempstr[3];
 
    itoa_fp(temp, temp_frac, tempstr);
 
    ssd1306_DrawStringBig("      ", 3, 0);
 
    ssd1306_DrawStringBig(tempstr, 3, 0);
 
    ssd1306_DrawStringBig(">", 3, 74);
 
    itoa(setpoint, tempstr);
 
    ssd1306_DrawStringBig("    ", 3, 90);
 
    ssd1306_DrawStringBig(tempstr, 3, 90);
 
}
 
 
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)
 
 
void save_settings()
 
{
 
/*
 
   Minimal_EEPROM_Unlock();
 
    // Try programming a word at an address divisible by 4
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_BOOTTOBREW, boottobrew);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_WINDUP_GUARD, windup_guard);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_K_P, k_p);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_K_I, k_i);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_K_D, k_d);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_UNITS, temp_units);
 
    Minimal_EEPROM_Lock();
 
*/
 
}
 
 
void save_setpoints()
 
{
 
/*
 
 
    Minimal_EEPROM_Unlock();
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_BREWTEMP, setpoint_brew);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_STEAMTEMP, setpoint_steam); 
 
    Minimal_EEPROM_Lock();
 
*/
 
}
 
 
 
// TODO: Make a struct that has all settings in it. Pass by ref to this func in a library.
 
void restore_settings()
 
{
 
    Minimal_EEPROM_Unlock();
 
/*    Minimal_EEPROM_Unlock();
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    boottobrew = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_BOOTTOBREW));
 
    
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    windup_guard = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_WINDUP_GUARD));
 
    
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    k_p = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_K_P));
 
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    k_i = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_K_I));
 
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    k_d = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_K_D));
 
    
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    setpoint_brew = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_BREWTEMP));
 
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    setpoint_steam = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_STEAMTEMP));    
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    temp_units = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_UNITS));    
 
 
    Minimal_EEPROM_Lock();
 
    Minimal_EEPROM_Lock(); */
 
}
 
 
int16_t last_temp = 21245;
 
 
 
///////////////////////////////////////////////////////////////////////////////////////
 
/// 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
 
 
////////////////////////////////////////////////////////////////////////////////////////////////
 
 
void machine()
 
{
 
    uint8_t last_state = state;
 
    
 
    uint8_t temp_changed = temp != last_temp;
 
    last_temp = temp;
 
 
    uint8_t sw_btn = !GPIO_ReadInputDataBit(SW_BTN);
 
    uint8_t sw_up = !GPIO_ReadInputDataBit(SW_UP);
 
    uint8_t sw_down = !GPIO_ReadInputDataBit(SW_DOWN);
 
    uint8_t sw_left = !GPIO_ReadInputDataBit(SW_LEFT);
 
    uint8_t sw_right = !GPIO_ReadInputDataBit(SW_RIGHT);
 
 
    switch(state)
 
    {
 
        // Idle state
 
        case STATE_IDLE:
 
        {
 
            // Write text to OLED
 
            // [ therm :: idle ]
 
            ssd1306_DrawString("therm :: idle ", 0, 40);
 
            pid_enabled = 0;
 
 
            if(temp_changed) {
 
                char tempstr[6];
 
                itoa_fp(temp, temp_frac, tempstr);
 
                ssd1306_DrawString("Temp: ", 3, 40);
 
                ssd1306_DrawString("    ", 3, 72);
 
                ssd1306_DrawString(tempstr, 3, 72);
 
            }
 
 
            ssd1306_drawlogo();
 
 
            switch(goto_mode) {
 
                case 2:
 
                {
 
                    ssd1306_DrawString("-> heat     ", 1, 40);
 
                } break;
 
 
                case 1:
 
                {
 
                    ssd1306_DrawString("-> setup    ", 1, 40);
 
                } break;
 
 
                case 0:
 
                {
 
                    ssd1306_DrawString("-> reset    ", 1, 40);
 
                } break;
 
            }
 
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                switch(goto_mode) {
 
                    case 2:
 
                        state = STATE_PREHEAT_BREW;
 
                        break;
 
                    case 1:
 
                        state = STATE_SETP;
 
                        break;
 
                    case 0:
 
                        state = STATE_IDLE;
 
                        break;
 
                    default:
 
                        state = STATE_PREHEAT_BREW;
 
                }
 
            }
 
            else if(SW_UP_PRESSED && goto_mode < 2) {
 
                goto_mode++;
 
            }
 
            else if(SW_DOWN_PRESSED && goto_mode > 0) {
 
                goto_mode--;
 
            }
 
 
 
            // Event Handler
 
            // N/A
 
 
        } break;
 
 
        case STATE_SETP:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set p ]
 
            // [ p = 12         ]
 
            ssd1306_DrawString("Proportional", 0, 40);
 
            ssd1306_drawlogo();
 
 
            char tempstr[6];
 
            itoa(k_p, tempstr);
 
            ssd1306_DrawString("P=", 1, 45);
 
            ssd1306_DrawString("    ", 1, 57);
 
            ssd1306_DrawString(tempstr, 1, 57);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
            
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                state = STATE_SETI;
 
            }
 
            else {
 
                user_input(&k_p);
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETI:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set i ]
 
            // [ i = 12         ]
 
            ssd1306_DrawString("Integral", 0, 40);
 
            ssd1306_drawlogo();
 
 
            char tempstr[6];
 
            itoa(k_i, tempstr);
 
            ssd1306_DrawString("I=", 1, 45);
 
            ssd1306_DrawString("    ", 1, 57);
 
            ssd1306_DrawString(tempstr, 1, 57);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
            
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                state = STATE_SETD;
 
            }
 
            else {
 
                user_input(&k_i);
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETD:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set d ]
 
            // [ d = 12         ]
 
            ssd1306_DrawString("Derivative", 0, 40);
 
            ssd1306_drawlogo();
 
 
            char tempstr[6];
 
            itoa(k_d, tempstr);
 
            ssd1306_DrawString("D=", 1, 45);
 
            ssd1306_DrawString("    ", 1, 57);
 
            ssd1306_DrawString(tempstr, 1, 57);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                state = STATE_SETWINDUP;
 
            }
 
            else {
 
                user_input(&k_d);
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETSTEPS:
 
        {
 
            // Write text to OLED
 
            // [ step #1:: Duration: ### ]
 
            // [           Setpoint: ### ]
 
            char tempstr[6];
 
 
            itoa(final_setpoint, tempstr);
therm-cube.ioc
Show inline comments
 
new file 100644
 
#MicroXplorer Configuration settings - do not modify
 
#Fri Nov 14 22:42:15 EST 2014
 
File.Version=4
 
KeepUserPlacement=false
 
Mcu.Family=STM32F0
 
Mcu.IP0=NVIC
 
Mcu.IP1=RCC
 
Mcu.IP2=SPI1
 
Mcu.IP3=SYS
 
Mcu.IP4=USART1
 
Mcu.IP5=USB
 
Mcu.IP6=USB_DEVICE
 
Mcu.IPNb=7
 
Mcu.Name=STM32F042K(4-6)Ux
 
Mcu.Package=UFQFPN32
 
Mcu.Pin0=PA1
 
Mcu.Pin1=PA2
 
Mcu.Pin10=PA12
 
Mcu.Pin11=PA13
 
Mcu.Pin12=PA14
 
Mcu.Pin13=PA15
 
Mcu.Pin14=PB3
 
Mcu.Pin15=PB4
 
Mcu.Pin16=PB5
 
Mcu.Pin17=PB6
 
Mcu.Pin18=PB7
 
Mcu.Pin19=PB8
 
Mcu.Pin2=PA3
 
Mcu.Pin20=VP_RCC_USB
 
Mcu.Pin21=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
 
Mcu.Pin3=PA4
 
Mcu.Pin4=PA5
 
Mcu.Pin5=PA6
 
Mcu.Pin6=PA7
 
Mcu.Pin7=PA9
 
Mcu.Pin8=PA10
 
Mcu.Pin9=PA11
 
Mcu.PinsNb=22
 
Mcu.UserName=STM32F042K6Ux
 
NVIC.SysTick_IRQn=true\:0\:0
 
NVIC.USB_IRQn=true\:0\:0
 
PA1.Locked=true
 
PA1.Signal=GPIO_Output
 
PA10.Locked=true
 
PA10.Mode=Asynchronous
 
PA10.Signal=USART1_RX
 
PA11.Locked=true
 
PA11.Mode=Device
 
PA11.Signal=USB_DM
 
PA12.Mode=Device
 
PA12.Signal=USB_DP
 
PA13.Locked=true
 
PA13.Mode=Serial-WireDebug
 
PA13.Signal=SYS_SWDIO
 
PA14.Mode=Serial-WireDebug
 
PA14.Signal=SYS_SWCLK
 
PA15.Locked=true
 
PA15.Signal=GPIO_Output
 
PA2.Locked=true
 
PA2.Signal=GPIO_Output
 
PA3.Locked=true
 
PA3.Signal=GPIO_Output
 
PA4.Locked=true
 
PA4.Signal=GPIO_Output
 
PA5.Locked=true
 
PA5.Mode=Full_Duplex_Master
 
PA5.Signal=SPI1_SCK
 
PA6.Locked=true
 
PA6.Mode=Full_Duplex_Master
 
PA6.Signal=SPI1_MISO
 
PA7.Locked=true
 
PA7.Mode=Full_Duplex_Master
 
PA7.Signal=SPI1_MOSI
 
PA9.Locked=true
 
PA9.Mode=Asynchronous
 
PA9.Signal=USART1_TX
 
PB3.Locked=true
 
PB3.Signal=GPIO_Input
 
PB4.Locked=true
 
PB4.Signal=GPIO_Input
 
PB5.Locked=true
 
PB5.Signal=GPIO_Input
 
PB6.Locked=true
 
PB6.Signal=GPIO_Input
 
PB7.Locked=true
 
PB7.Signal=GPIO_Input
 
PB8.Locked=true
 
PB8.Signal=GPIO_Output
 
PCC.Family=STM32F0
 
PCC.MCU=STM32F042K(4-6)Ux
 
PCC.MXVersion=4.4.0
 
PCC.PartNumber=STM32F042K6Ux
 
PCC.Seq0=0
 
PCC.SubFamily=STM32F0x2
 
PCC.Temperature=25
 
PCC.Vdd=3.6
 
RCC.CECEnable-ClockTree=false
 
RCC.EnableHSE-ClockTree=false
 
RCC.EnableHSERTCDevisor-ClockTree=false
 
RCC.EnableLSE-ClockTree=false
 
RCC.EnableLSERTC-ClockTree=false
 
RCC.EnableMCOMultDivisor-ClockTree=false
 
RCC.FLatency-AdvancedSettings=FLASH_LATENCY_0
 
RCC.FamilyName=M
 
RCC.HSEState-ClockTree=RCC_HSE_OFF
 
RCC.HSI14State-ClockTree=RCC_HSI14_OFF
 
RCC.HSI48State-ClockTree=RCC_HSI48_ON
 
RCC.HSIState-ClockTree=RCC_HSI_ON
 
RCC.I2C1Enable-ClockTree=false
 
RCC.IPParameters=OscillatorTypeHSE-ClockTree,RTCEnable-ClockTree,EnableLSE-ClockTree,CECEnable-ClockTree,ReloadValue-AdvancedSettings,PLLCLKFreq_Value,FamilyName,PREFETCH_ENABLE-AdvancedSettings,OscillatorTypeHSI48-ClockTree,USBEnable-ClockTree,HSI14State-ClockTree,PLLMCOFreq_Value,IWDGEnable-ClockTree,HSI48State-ClockTree,FLatency-AdvancedSettings,EnableLSERTC-ClockTree,USART2Enable-ClockTree,Source-AdvancedSettings,VCOOutput2Freq_Value,MCOEnable-ClockTree,OscillatorTypeHSI-ClockTree,EnableMCOMultDivisor-ClockTree,I2C1Enable-ClockTree,HSIState-ClockTree,LSIState-ClockTree,PLLState-ClockTree,RCC_PERIPHCLK_USART1Var-ClockTree,USART1Enable-ClockTree,HSEState-ClockTree,EnableHSE-ClockTree,EnableHSERTCDevisor-ClockTree,OscillatorTypeLSI-ClockTree
 
RCC.IWDGEnable-ClockTree=false
 
RCC.LSIState-ClockTree=RCC_LSI_OFF
 
RCC.MCOEnable-ClockTree=false
 
RCC.OscillatorTypeHSE-ClockTree=
 
RCC.OscillatorTypeHSI-ClockTree=RCC_OSCILLATORTYPE_HSI
 
RCC.OscillatorTypeHSI48-ClockTree=RCC_OSCILLATORTYPE_HSI48
 
RCC.OscillatorTypeLSI-ClockTree=
 
RCC.PLLCLKFreq_Value=16000000
 
RCC.PLLMCOFreq_Value=16000000
 
RCC.PLLState-ClockTree=RCC_PLL_OFF
 
RCC.PREFETCH_ENABLE-AdvancedSettings=0
 
RCC.RCC_PERIPHCLK_USART1Var-ClockTree=RCC_PERIPHCLK_USART1
 
RCC.RTCEnable-ClockTree=false
 
RCC.ReloadValue-AdvancedSettings=__HAL_RCC_CRS_CALCULATE_RELOADVALUE(48000000,
 
RCC.Source-AdvancedSettings=RCC_CRS_SYNC_SOURCE_USB
 
RCC.USART1Enable-ClockTree=true
 
RCC.USART2Enable-ClockTree=false
 
RCC.USBEnable-ClockTree=true
 
RCC.VCOOutput2Freq_Value=8000000
 
SPI1.DataSize-Full_Duplex_Master=SPI_DATASIZE_8BIT
 
SPI1.Direction-Full_Duplex_Master=SPI_DIRECTION_2LINES
 
SPI1.IPParameters=Direction-Full_Duplex_Master,VirtualType-Full_Duplex_Master,TIMode-Full_Duplex_Master,Mode-Full_Duplex_Master,DataSize-Full_Duplex_Master,NSS-Full_Duplex_Master
 
SPI1.Mode-Full_Duplex_Master=SPI_MODE_MASTER
 
SPI1.NSS-Full_Duplex_Master=SPI_NSS_SOFT
 
SPI1.TIMode-Full_Duplex_Master=SPI_TIMODE_DISABLED
 
SPI1.VirtualType-Full_Duplex_Master=VM_MASTER
 
USART1.BaudRate=115200
 
USART1.HwFlowCtl-Asynchronous=UART_HWCONTROL_NONE
 
USART1.IPParameters=VirtualMode-Asynchronous,BaudRate,HwFlowCtl-Asynchronous,WordLength-Asynchronous
 
USART1.VirtualMode-Asynchronous=VM_ASYNC
 
USART1.WordLength-Asynchronous=UART_WORDLENGTH_7B
 
USB.IPParameters=phy_itface-Device,speed-Device
 
USB.phy_itface-Device=PCD_PHY_EMBEDDED
 
USB.speed-Device=PCD_SPEED_FULL
 
USB_DEVICE.CLASS_NAME-CDC_FS=CDC
 
USB_DEVICE.IPParameters=CLASS_NAME-CDC_FS,VirtualModeFS,VirtualMode,USBD_HandleTypeDef,hUsbDevice-CDC_FS,USBD_HandleTypeDef-CDC_FS,VirtualModeFS-CDC_FS,VirtualMode-CDC_FS
 
USB_DEVICE.USBD_HandleTypeDef=hUsbDeviceFS
 
USB_DEVICE.USBD_HandleTypeDef-CDC_FS=hUsbDeviceFS
 
USB_DEVICE.VirtualMode=Cdc
 
USB_DEVICE.VirtualMode-CDC_FS=Cdc
 
USB_DEVICE.VirtualModeFS=Cdc_FS
 
USB_DEVICE.VirtualModeFS-CDC_FS=Cdc_FS
 
USB_DEVICE.hUsbDevice-CDC_FS=hDeviceDuSmolt
 
VP_RCC_USB.Mode=CRS SYNC Source USB
 
VP_RCC_USB.Signal=RCC_USB
 
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS
 
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS
0 comments (0 inline, 0 general)