Программный модуль для кофеварки RCM-M1505S


ПО является неотъемлемой частью кофеварки RCM-M1505S, отдельно потребителю не поставляется и эксплуатируется только в составе устройства.

Фрагмент исходного кода
////////////////////////////////////////////////////////////////

//RCM-M1505S

//v2.1

//logic.c

////////////////////////////////////////////////////////////////

#include "logic.h"

#include "leds.h"
#include "buzzer.h"
#include "heater.h"
#include "motor.h"
#include "temperature.h"

#include "switcher.h"
#include "button.h"

#include "timer.h"
#include "timer_hw_defined.h"

#include "ble_commands.h"

#include "nrf.h"
// defines

/**
 * Макрос для установки состояния в машину состояний
 */
#define LOGIC_CHANGE(st)        {cm_state=st;}
#define LOGIC_STARTED_STATE(st) {cm_state_started=st;}
#define LOGIC_LOAD_STARTED(st)  {cm_state=cm_state_started;}
/**
 * Макрос для установки состояния в машину состояний
 */
#define IS_LOGIC_STATE(st)       (cm_state == st)

/**
 * Макрос для установки состояния в машину состояний
 */
#define IS_NOT_LOGIC_STATE(st)   (cm_state != st)

/**
 * Макрос для вызова состояние один раз при изменении состояния
 */
#define INIT_CHANGE_STATE()     if(cm_state_last != cm_state)

/**
 * Макрос для проверки предыдущего состояния
 */
#define IS_PRE_STATE(s)         if(cm_state == s)

/**
 * Макрос для проверки предыдущего состояния
 */
#define IS_NOT_PRE_STATE(s)     if(cm_state != s)

/**
 * Макрос для выхова постоянно состояния
 */
#define INIT_UPDATE_STATE()     if(1)
   
/**
 * Макрос для обноваления состояния
 */
#define UPDATE_CHANGE_STATE()   {cm_state_last = cm_state;}

#define LOGIC_RETURN_STATE()   {cm_state=cm_state_pause_saved;}
#define LOGIC_PAUSE_STATE()    {cm_state_pause_saved = cm_state; cm_state = STATE_PAUSE; }


#define BEEP()                 {buzzer_on();timer_create(TIMER_ONE_SHOT_DELETE_START, TIMER_MILLISECOND(100), timer_system_buzzer_off);}
#define BEEP_LONG()            {buzzer_on();timer_create(TIMER_ONE_SHOT_DELETE_START, TIMER_MILLISECOND(1000), timer_system_buzzer_off);}

#define LEDS_TIMER_ALL_OFF      {timer_stop(timer_system_led_blink);timer_stop(timer_system_led_pair);timer_stop(timer_system_led_blink_pause);}
   
#define LEDS_ON()               {LEDS_TIMER_ALL_OFF; leds_select(LED0,1); leds_select(LED1,1);}
#define LEDS_OFF()              {LEDS_TIMER_ALL_OFF; leds_select(LED0,0); leds_select(LED1,0);}

#define LEDS_BLINK()            {timer_start(timer_system_led_blink);}
#define LEDS_PAIR()             {timer_start(timer_system_led_pair);}
#define LEDS_BLINK_PAUSE()      {LEDS_TIMER_ALL_OFF;timer_start(timer_system_led_blink_pause);}
#define LEDS_BLINK_PAUSE_STOP() {timer_stop(timer_system_led_blink_pause);}

// types
typedef enum {
  STATE_OFF             =       0,
  STATE_WAIT_GRIND      =       1,
  STATE_WAIT_GROUND     =       2,
  STATE_GRIND           =       3,
  STATE_COOK            =       4,
  STATE_HEAT            =       5,
  STATE_PAUSE           =       6
} cm_state_t;

// states
static cm_state_t cm_state_started = STATE_OFF;
static cm_state_t cm_state = STATE_OFF;
static cm_state_t cm_state_last = STATE_OFF;
static cm_state_t cm_state_pause_saved = STATE_OFF;


/***
 * 
 */
#define HEATER_TIME_MAX         60*12
#define MOTOR_TIME_MAX          30
#define MOTOR_TIME_MIN          5

#define HEATER_TIME_DEFAULT     30
#define MOTOR_TIME_DEFAULT      23
static unsigned int heater_time = HEATER_TIME_DEFAULT;//minutes
static unsigned int motor_time  = MOTOR_TIME_DEFAULT;//seconds

static int pause_enable = 0;
static int go = 0;


void logic_pause(void);
void logic_continuation(void);

/******************************************************************************
 * TIMERS
 */
// timer update temperature measurement
timer_t timer_system_hardware_update            =       -1;
timer_t timer_system_temperature_update_measure =       -1;
timer_t timer_system_led_pair                   =       -1;
timer_t timer_system_led_blink                  =       -1;
timer_t timer_system_led_blink_pause            =       -1;
timer_t timer_system_unpair                     =       -1;
timer_t timer_system_pair                       =       -1;
timer_t timer_system_pair_stop                  =       -1;

timer_t timer_system_heater_off                 =       -1;
timer_t timer_system_motor_off                  =       -1;

timer_t timer_system_pause_auto_off             =       -1;
   
/******************************************************************************
 * TIMERS CALLBACKS
 */

static void pair_start(void);
static void pair_stop(void);
// timer system callback
void timer_system_callback(timer_t _timer)
{
  if( _timer == timer_system_hardware_update)
  {
    temperature_update();
    switcher_update();
    button_update();
    if(ble_commands_get_pairing() == 0)
    {
      if(cm_state == STATE_OFF)
      {
        if(go) 
        {
          pair_stop();
        }
      }
    }
  }
  else
  if( _timer == timer_system_temperature_update_measure)
  {
    temperature_update();
  }
  else
  if( _timer == timer_system_led_blink)
  {
    static int blink_led = 0;
    if(blink_led)
    {
      leds_select(LED0,1); leds_select(LED1,1);
    }
    else
    {
      leds_select(LED0,0); leds_select(LED1,0);
    }
    blink_led = (blink_led>0)?0:1;
  }
  else
  if( _timer == timer_system_led_blink_pause)
  {
    static int blink_led = 0;
    if(blink_led)
    {
      leds_select(LED0,1); leds_select(LED1,1);
    }
    else
    {
      leds_select(LED0,0); leds_select(LED1,0);
    }
    blink_led = (blink_led>0)?0:1;
  }
  if( _timer == timer_system_led_pair )
  {
    static int blink_led = 0;
    if(blink_led)
    {
      leds_select(LED0,1); leds_select(LED1,0);
    }
    else
    {
      leds_select(LED0,0); leds_select(LED1,1);
    }
    blink_led = (blink_led>0)?0:1;
  }
}

void timer_system_buzzer_off(timer_t _timer)
{
  buzzer_off();
}

static int timer_system_pair_ready = 0;
static int timer_system_unpair_ready = 0;

void timer_system_unpair_callback(timer_t _timer)
{
  BEEP_LONG();
  //ble_commands_unpairing_init();
  timer_system_unpair_ready = 1;
}

static void timer_system_pair_callback(timer_t _timer);
void pair_start(void)
{
  LEDS_PAIR();
  ble_commands_pairing_start();
  timer_system_pair_stop = timer_create(TIMER_ONE_SHOT_DELETE_START, TIMER_SECOND(10), timer_system_pair_callback);
}

void pair_stop(void)
{
  LEDS_OFF();
  ble_commands_pairing_stop();
  if(timer_enable(timer_system_pair_stop) == TIMER_OK)
  {
    timer_delete(&timer_system_pair_stop);
  }
}

void timer_system_pair_callback(timer_t _timer)
{
  if( _timer == timer_system_pair )
  {
    BEEP();
    timer_system_pair_ready = 1;
  }
  else
  if( _timer == timer_system_pair_stop )
  {
    BEEP();
    pair_stop();
    timer_system_pair_ready = 0;
  }
}

void timer_system_auto_off(timer_t _timer)
{
  if(_timer == timer_system_motor_off)
  {
    motor_off();
    LOGIC_CHANGE(STATE_COOK);
  }
  else
  if(_timer == timer_system_heater_off)
  {
    heater_off();
    LOGIC_CHANGE(STATE_OFF);
  }
  else
  if(_timer == timer_system_pause_auto_off)
  {
    motor_off();
    heater_off();
    LOGIC_CHANGE(STATE_OFF);
  }
}

/******************************************************************************
 * BUTTON CALLBACKS
 */
void button_press_callback(button_event_t _event)
{
  switch(_event)
  {
    case BUTTON_PRESS:
      {
        switch(cm_state)
        {
          case STATE_OFF :
            {
              timer_system_pair   = timer_create(TIMER_ONE_SHOT_START, TIMER_SECOND(10), timer_system_pair_callback);
              timer_system_unpair = timer_create(TIMER_ONE_SHOT_START, TIMER_SECOND(20), timer_system_unpair_callback);
            }
            break;
          case STATE_WAIT_GRIND :
            {
              BEEP();
              LOGIC_CHANGE(STATE_GRIND);
            }
            break;
          case STATE_WAIT_GROUND :
            {
              BEEP();
              LOGIC_CHANGE(STATE_COOK);
            }
            break;
          case STATE_PAUSE :
            {
              BEEP();
              logic_continuation();
            }
            break;
          case STATE_HEAT :
            {
            }
            break;
          default:
            {
              BEEP();
              logic_pause();
            }
            break;
        }
      }
      break;
    case BUTTON_RELEASE:
        switch(cm_state)
        {
          case STATE_OFF :
            {
              if(timer_system_pair_ready == 1 && 
                 timer_system_unpair_ready != 1) 
              {
                // pairing
                pair_start();
              }
              else
              if(timer_system_pair_ready == 1 && 
                 timer_system_unpair_ready == 1) 
              {
                // unpairing
                ble_commands_unpairing_init();
              }
              timer_system_pair_ready = 0;
              timer_system_unpair_ready = 0;
              timer_delete(&timer_system_pair);
              timer_delete(&timer_system_unpair);
            }
            break;
        }
      break;
  }
}

/******************************************************************************
 * SWITCHER CALLBACKS
 */

void logic_stop(void);
void switcher_change_callback(switcher_state_t _sw)
{
  logic_stop();
  switch(_sw)
  {  
    case SWITCHER_OFF :
      {
        BEEP();
        LOGIC_STARTED_STATE(STATE_OFF);
        LOGIC_CHANGE(STATE_OFF);
      }
      break;
    case SWITCHER_GRIND :
      {
        BEEP();
        LOGIC_STARTED_STATE(STATE_WAIT_GRIND);
        LOGIC_CHANGE(STATE_WAIT_GRIND);
      }
      break;
    case SWITCHER_GROUND :
      {
        BEEP();
        LOGIC_STARTED_STATE(STATE_WAIT_GROUND);
        LOGIC_CHANGE(STATE_WAIT_GROUND);
      }
      break;
  }
}


void logic_pause(void)
{
  if(pause_enable == 0)
  {
    pause_enable = 1;
    switch(cm_state)
    {
      case STATE_GRIND :
        {
          motor_off();
          timer_pause(timer_system_motor_off);
          timer_start(timer_system_pause_auto_off);
        }
        break;
      case STATE_COOK :
        {
          heater_off();
          timer_start(timer_system_pause_auto_off);
        }
        break;
      case STATE_HEAT :
        {
          heater_off();
          timer_pause(timer_system_heater_off);
          timer_start(timer_system_pause_auto_off);
        }
        break;
    }
    LEDS_BLINK_PAUSE();
    LOGIC_PAUSE_STATE();
  }
}
void logic_continuation(void)
{
  if(pause_enable == 1)
  {
    pause_enable = 0;
    LEDS_BLINK_PAUSE_STOP();
    LOGIC_RETURN_STATE();
    switch(cm_state)
    {
      case STATE_GRIND :
        {
          motor_on();
          LEDS_BLINK();
          timer_continuation(timer_system_motor_off);
          timer_stop(timer_system_pause_auto_off);
        }
        break;
      case STATE_COOK :
        {
          LEDS_BLINK();
          heater_on();
          timer_stop(timer_system_pause_auto_off);
        }
        break;
      case STATE_HEAT :
        {
          LEDS_ON();
          heater_on();
          timer_continuation(timer_system_heater_off);
          timer_stop(timer_system_pause_auto_off);
        }
        break;
    }
  }
}

void logic_stop(void)
{
  pause_enable = 0;
  LEDS_BLINK_PAUSE_STOP();
  LOGIC_RETURN_STATE();
  LOGIC_CHANGE(STATE_OFF);
  heater_off();
  motor_off();
  LEDS_OFF();
  timer_stop(timer_system_motor_off);
  timer_stop(timer_system_heater_off);
  timer_stop(timer_system_led_blink_pause);
  timer_stop(timer_system_led_blink);
  timer_stop(timer_system_led_pair);
  cm_state_last = cm_state_pause_saved = cm_state = STATE_OFF;
}

void logic_go(timer_t _timer)
{
  LEDS_OFF();
  go = 1;
}

void temperature_change_callback(temperature_state_t _state)
{
  switch(_state)
  {
    case TEMPERATURE_ON:
      {
        switch(cm_state)
        {
          case STATE_COOK:
            {
              BEEP();
              LOGIC_CHANGE(STATE_HEAT);
            }
            break;
        }
      }
      break;
    case TEMPERATURE_OFF:
      {
        switch(cm_state)
        {
          case STATE_COOK:
            {
            }
            break;
        }
      }
      break;
  }
}

void logic_init(void){
  leds_init();
  buzzer_init();
  heater_init();
  motor_init();
  temperature_init();
  temperature_callback_change(temperature_change_callback);
  
  switcher_init();
  switcher_callback_change(switcher_change_callback);
  
  button_init();  
  button_callback_press(button_press_callback);
  timer_system_hardware_update = 
    timer_create(TIMER_REPEAT_START, TIMER_MILLISECOND(10), timer_system_callback);
  timer_system_led_pair = 
    timer_create(TIMER_REPEAT, TIMER_MILLISECOND(250), timer_system_callback);
  timer_system_led_blink = 
    timer_create(TIMER_REPEAT, TIMER_MILLISECOND(500), timer_system_callback);
  timer_system_led_blink_pause = 
    timer_create(TIMER_REPEAT, TIMER_MILLISECOND(100), timer_system_callback);
  
  timer_system_motor_off = 
    timer_create(TIMER_ONE_SHOT, TIMER_SECOND(motor_time), timer_system_auto_off);
  timer_system_heater_off = 
    timer_create(TIMER_ONE_SHOT, TIMER_MINUTE(heater_time), timer_system_auto_off);
  timer_system_pause_auto_off = 
    timer_create(TIMER_ONE_SHOT, TIMER_MINUTE(30), timer_system_auto_off);
  // BEGIN
  LEDS_ON();
  BEEP();
  timer_create(TIMER_ONE_SHOT_DELETE_START, TIMER_SECOND(1), logic_go);
  
  TIMER_HW_INIT();
  ble_commands_init();
}

void logic_handler(void)
{
  if(go)
  {
    switch(cm_state)
    {
      case STATE_OFF :
        INIT_CHANGE_STATE()
        {
          UPDATE_CHANGE_STATE();
          LEDS_OFF();
          heater_time = HEATER_TIME_DEFAULT;//minutes
          motor_time  = MOTOR_TIME_DEFAULT;//seconds
          logic_stop();
        }
        INIT_UPDATE_STATE()
        {
        }
        break;
      case STATE_WAIT_GRIND :
        INIT_CHANGE_STATE()
        {
          UPDATE_CHANGE_STATE();
          LEDS_ON();
        }
        INIT_UPDATE_STATE()
        {
        }
        break;
      case STATE_WAIT_GROUND :
        INIT_CHANGE_STATE()
        {
          UPDATE_CHANGE_STATE();
          LEDS_ON();
        }
        INIT_UPDATE_STATE()
        {
        }
        break;
      case STATE_GRIND :
        INIT_CHANGE_STATE()
        {
          UPDATE_CHANGE_STATE();
          LEDS_BLINK();
          motor_on();
          timer_start(timer_system_motor_off);
        }
        INIT_UPDATE_STATE()
        {
        }
        break;
      case STATE_COOK :
        INIT_CHANGE_STATE()
        {
          UPDATE_CHANGE_STATE();
          LEDS_BLINK();
          heater_on();
        }
        INIT_UPDATE_STATE()
        {
          if(temperature_state())
          {
            LOGIC_CHANGE(STATE_HEAT);
          }
        }
        break;
      case STATE_HEAT :
        INIT_CHANGE_STATE()
        {
          UPDATE_CHANGE_STATE();
          LEDS_ON();
          timer_start(timer_system_heater_off);
        }
        INIT_UPDATE_STATE()
        {
        }
        break;
      case STATE_PAUSE :
        INIT_CHANGE_STATE()
        {
          //UPDATE_CHANGE_STATE();
        }
        INIT_UPDATE_STATE()
        {
        }
        break;  
    }
  
    ble_commands_handle();
  }
  if(1)
  {
    timer_handle();
  }
}

int get_state(void){
  if(cm_state != STATE_PAUSE)
  {
    return (int)cm_state;
  }
  else
  {
    return (int)cm_state_pause_saved;
  }
}

int logic_ext_command(logic_ext_commands_t command, ... ){
  int retVal = 0;
  if(cm_state == STATE_OFF &&
     command != CM_GG_GET_PROGRAM)
  {
    return retVal;
  }
  
  switch(command)
  {
    case CM_GG_START_PROGRAM :
      {
      }
      break;
    case CM_GG_SET_PROGRAM :
      {
        uint32_t time_grinding  =       *(((uint32_t*)&command)+1),
                 time_heat      =       *(((uint32_t*)&command)+2);
        
        static uint32_t time_grinding_ = 0;
        static uint32_t time_heat_ = 0;
        time_grinding_ = time_grinding;
        time_heat_ = time_heat;
        if(time_heat <= HEATER_TIME_MAX && 
           time_grinding <= MOTOR_TIME_MAX && 
           time_grinding >= MOTOR_TIME_MIN)
        {
          switch(cm_state)
          {
            case STATE_OFF :
              {
              }
              break;
            case STATE_WAIT_GRIND :
            case STATE_WAIT_GROUND :
            case STATE_GRIND :
            case STATE_COOK :
            case STATE_HEAT :
              {
                heater_time = time_heat;
                motor_time  = time_grinding;
                timer_set_time(timer_system_motor_off, TIMER_SECOND(motor_time) );
                timer_set_time(timer_system_heater_off, TIMER_MINUTE(heater_time) );
                retVal = 1;
              }
              break;
          }
        }
      }
      break;
    case CM_GG_GET_PROGRAM :
      {
          uint32_t      *time1 = (uint32_t*)*(((uint32_t*)&command)+1),
                        *time2 = (uint32_t*)*(((uint32_t*)&command)+2),
                        *state = (uint32_t*)*(((uint32_t*)&command)+3),
                        *sw    = (uint32_t*)*(((uint32_t*)&command)+4);
          static uint32_t time1_ = 0;
          static uint32_t time2_ = 0;
          static uint32_t state_ = 0;
          switch(cm_state){
            case STATE_GRIND:
              *time1 = timer_get_time(timer_system_motor_off)/TIMER_SECOND(1);
              *time2 = timer_remaining_time(timer_system_motor_off)/TIMER_SECOND(1);
              break;
            case STATE_COOK:
              *time1 = timer_get_time(timer_system_heater_off)/TIMER_MINUTE(1);
              *time2 = timer_get_time(timer_system_heater_off)/TIMER_MINUTE(1);
              break;
            case STATE_HEAT:
              *time1 = timer_get_time(timer_system_heater_off)/TIMER_MINUTE(1);
              *time2 = timer_remaining_time(timer_system_heater_off)/TIMER_MINUTE(1);
              break;
            default:
              *time1 = timer_get_time(timer_system_motor_off)/TIMER_SECOND(1);
              *time2 = timer_get_time(timer_system_heater_off)/TIMER_MINUTE(1);
              break;
          };
          *state = (uint32_t)get_state();
          *sw    = (cm_state == STATE_PAUSE)?1:0;
          time1_ = *time1;
          time2_ = *time2;
          state_ = *state;
          retVal = 1;
      }
      break;
    case CM_GG_START :
      {
        switch(cm_state)
        {
          case STATE_WAIT_GRIND :
          case STATE_WAIT_GROUND :
            {
              retVal = 1;
              button_press_callback(BUTTON_PRESS);
            }
            break;
        }
      }
      break;
    case CM_GG_START_GRIND :
      {
      }
      break;
    case CM_GG_START_GROUND :
      {
      }
      break;
    case CM_GG_STOP :
      {
        switch(cm_state)
        {
          case STATE_GRIND :
          case STATE_COOK :
          case STATE_HEAT :
          case STATE_PAUSE :
            {
              retVal = 1;
              logic_stop();
              LOGIC_LOAD_STARTED();
            }
            if(0){
              retVal = 1;
              cm_state = STATE_OFF;
            }
            break;
        }

      }
      break;
    case CM_GG_PAUSE :
      {
        uint32_t play_pause = *(((uint32_t*)&command)+1);
        if(play_pause > 0)
        {
          switch(cm_state)
          {
            case STATE_GRIND :
            case STATE_COOK :
              {
                retVal = 1;
                button_press_callback(BUTTON_PRESS);
              }
              break;
          }
        }
        else
        {
          switch(cm_state)
          {
            case STATE_PAUSE :
              {
                retVal = 1;
                button_press_callback(BUTTON_PRESS);
              }
              break;
          }
        }
      }
      break;
    case CM_GG_GET_STATE :
      {
        retVal = get_state();
      }
      break;
  }
  return retVal;
}

int get_ready_for_firmware(void){
  return 0;
}




//TIMER_HANDLE()
void TIMER2_IRQHandler(void)
{
  if (NRF_TIMER2->EVENTS_COMPARE[0] == 1) {
    NRF_TIMER2->EVENTS_COMPARE[0] = 0; //clear interrupt
    timer_tick();
  }
}
Made on
Tilda