Программный модуль для кофеварки 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();
}
}