Программный модуль для обогревателя RFH-C4522S. Версия 2.15
ПО является неотъемлемой частью обогревателя RFH-C4522S, отдельно потребителю не поставляется и эксплуатируется только в составе устройства.
/**
* @file application.c
* @brief application.c реализует функционал устройства RFH-C4522S
*
* @internal
* Revision: v2.15
* Compiler: armcc
*/
/********* HEADER FILE INCLUDES *************************************************/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "debug_info.h"
#include "nrf.h"
#include "nrf_delay.h"
#include "nrf_soc.h"
#include "nrf_gpio.h"
#include "app_timer.h"
#include "app_error.h"
#include "r4s_lib.h"
#include "r4s_slave.h"
#include "r4s_slave_external.h"
#include "com_slave.h"
#include "com_extansion.h"
#include "Application.h"
#include "Application_api.h"
#include "app_ind.h"
#include "adv_data.h"
#include "buz_ac.h"
#include "timers.h"
#include "timers_config.h"
#include "keyb.h"
#include "keyb_config.h"
#include "config.h"
#include "temperature_service.h"
#include "evcal.h"
#include "calendar.h"
#include "stderrnum.h"
/********* DEFINES **************************************************************/
/********* MACROS ***************************************************************/
#define APP_ANTI_FROST_TEMP 7
#define APP_MAX_TEMP 35
#define APP_OVERHEAT_TEMP 38
#define HOUR_TO_MINUTES(x) ((x)*60)
#define MINUTES_TO_HOUR(x) ((x)/60)
/********* VARIABLES *****************************************************/
static keyb_data_t app_keyboard_data[KEYB_BUTTON_COUNT]; /* данные кнопок*/
static app_flags_t app_flags; /* флаги application*/
static app_heater_t app_heater; /* флаги состояния нагревателя*/
static temp_serv_data_t app_temp_serv_data = { /* данные температурного сервиса*/
.event_lower = TEMP_NO_EVENT,
.event_higher = TEMP_NO_EVENT,
.state = TEMP_STATE_UNKNOWN
};
static volatile uint16_t app_sw_off_time_left_m = 0; /* текущее время */
static uint8_t app_target_temp = APP_MAX_TEMP; /* целевая температура */
static app_timer_id_t app_iteration_timer_id; /* таймер Итерации */
static volatile bool appIterStepAllowFl = true;
/********* FUNCTION PROTOTYPES **************************************************/
static void app_heat_off(void);
static void app_heat_low(void);
static void app_heat_turbo(void);
static void app_heat_fan(void);
static void app_heat_low_enable(void);
static void app_heat_turbo_enable(void);
static void app_heat_disable(void);
static void stateStandBy(void);
static void stateHeat(app_prog_t app_prog);
static void app_timeouts_timer_start(uint32_t timeout);
static void app_timeouts_timer_stop(void);
static void app_cool_timer_start(void);
static void app_cool_timer_stop(void);
static void app_sw_off_timer_start(void);
static void app_sw_off_timer_stop(void);
static void app_state_change(app_state_t new_state);
static void stateTest(void);
static void stateStandBy(void);
/********* FUNCTIONS IMPLEMENTATION *********************************************/
static void app_iteration_timer_handler(void* p_context)
{
appIterStepAllowFl = true;
}
/**@brief Обработчик таймера таймаута.
*
* @param none
*
* @return none
*/
static void app_timeouts_handler( void )
{
APP_ERROR_CHECK(timer_stop(TIMERS_APP_TIMEOUTS));
switch(app_heater.app_state)
{
case APP_PAIRING:
case APP_FW_UPDATE:
{
stateStandBy();
break;
}
default:
break;
}
return;
}
/**@brief Обработчик таймера охлаждения нагревателя.
*
* @param none
*
* @return none
*/
static void app_cool_timeout_handler( void )
{
APP_ERROR_CHECK(timer_stop(TIMERS_COOL_TIMEOUT));
switch(app_heater.app_state)
{
case APP_HEAT:
{
switch(app_heater.app_prog)
{
case PROG_HEAT_FAN:
{
app_heater.app_heater_enable.flags.cooling_en = 0;
break;
}
default:
break;
}
break;
}
case APP_STAND_BY:
case APP_STAND_BY_AUTO:
case APP_STAND_BY_AF:
case APP_FW_UPDATE:
case APP_PAIRING:
case APP_OVER_HEAT:
{
app_heater.app_heater_enable.flags.cooling_en = 0;
app_heat_off(); //выключаем обогрев и вентилятор
break;
}
default:
break;
}
return;
}
/**@brief Обработчик таймера отключения нагревателя через заданный промежуток времени.
*
* @param none
*
* @return none
*/
static void app_sw_off_timeout_handler( void )
{
if(--app_sw_off_time_left_m == 0)
{
stateStandBy();
}
else
{
app_sw_off_timer_start();
}
return;
}
/**
* @brief Функция вызывается при срабатывании часов (1 сек)
*
* @param none
* @return none
*
*/
static void calendar_timer_handle(void){
uint32_t err_code;
err_code = evcal_one_sec_handler();
APP_ERROR_CHECK(err_code);
}
/**
* @brief Функция вызывается при срабатывании событий из календаря
*
* @param none
* @return none
*
*/
static void evcal_calendar_task(evcal_info_packet_t const*p_data){
if(p_data == NULL) return;
uint8_t action_code = p_data->array[1];
if((app_heater.app_heater_state.bits & BIT_APP_LOCK ) == 0)
{
switch(action_code)
{
case AC_EXTANSION_START_CMD:
{
expan_req_start_t *p_in_exp_pckt = (expan_req_start_t *) &p_data->array[2];
if((p_in_exp_pckt->mask & 0x1) != 0){
app_set_sw_on();
}
break;
}
case AC_EXTANSION_STOP_CMD:
{
expan_req_stop_t *p_in_exp_pckt = (expan_req_stop_t *) &p_data->array[2];
if((p_in_exp_pckt->mask & 0x1) != 0){
app_set_sw_off();
}
break;
}
default:
break;
}
}
}
/**@brief Функция инициализации
*
* @param none
*
* @return none
*/
void application_init(void)
{
NRF_GPIO->PIN_CNF[MAIN_HEAT_L] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0H1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
NRF_GPIO->PIN_CNF[MAIN_HEAT_H] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
NRF_GPIO->PIN_CNF[MOTO] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0H1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
NRF_GPIO->PIN_CNF[FAN] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0H1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
APP_ERROR_CHECK(timer_create(TIMERS_APP_TIMEOUTS, NULL, (callback_t)app_timeouts_handler ));
APP_ERROR_CHECK(timer_create(TIMERS_COOL_TIMEOUT, NULL, (callback_t)app_cool_timeout_handler ));
APP_ERROR_CHECK(timer_create(TIMERS_SW_OFF_TIMEOUT, NULL, (callback_t)app_sw_off_timeout_handler ));
APP_ERROR_CHECK(app_timer_create( &app_iteration_timer_id, APP_TIMER_MODE_SINGLE_SHOT, app_iteration_timer_handler ));
APP_ERROR_CHECK(calendar_set_one_sec_callback(calendar_timer_handle)); //установка callback часов
APP_ERROR_CHECK(evcal_set_callback(evcal_calendar_task)); //установка callback при срабатывании расписания
app_ind_init();
stateTest();
return;
}
/**@brief Функция запускает таймер переходов
*
* @param none
*
* @return none
*/
static void app_timeouts_timer_start(uint32_t timeout)
{
APP_ERROR_CHECK(timer_write_period(TIMERS_APP_TIMEOUTS,TIMERS_MILLISECOND(timeout)));
APP_ERROR_CHECK(timer_reset(TIMERS_APP_TIMEOUTS));
APP_ERROR_CHECK(timer_start(TIMERS_APP_TIMEOUTS));
}
/**@brief Функция останавливает таймер переходов
*
* @param none
*
* @return none
*/
static void app_timeouts_timer_stop(void)
{
APP_ERROR_CHECK(timer_stop(TIMERS_APP_TIMEOUTS));
}
/**@brief Функция зупускает таймер отключения
*
* @param none
*
* @return none
*/
static void app_sw_off_timer_start(void)
{
app_heater.app_heater_state.flags.APP_TIMER = 1;
APP_ERROR_CHECK(timer_stop(TIMERS_SW_OFF_TIMEOUT));
APP_ERROR_CHECK(timer_write_period(TIMERS_SW_OFF_TIMEOUT,TIMERS_MILLISECOND(APP_SW_OFF_TIMEOUT_MS)));
APP_ERROR_CHECK(timer_reset(TIMERS_SW_OFF_TIMEOUT));
APP_ERROR_CHECK(timer_start(TIMERS_SW_OFF_TIMEOUT));
}
/**@brief Функция останавливает таймер отключения
*
* @param none
*
* @return none
*/
static void app_sw_off_timer_stop(void)
{
app_heater.app_heater_state.flags.APP_TIMER = 0;
APP_ERROR_CHECK(timer_stop(TIMERS_SW_OFF_TIMEOUT));
app_sw_off_time_left_m = 0; //обнуляем текущее время
}
/**@brief Функция запускает таймер охлаждения
*
* @param none
*
* @return none
*/
static void app_cool_timer_start(void)
{
uint8_t enable;
APP_ERROR_CHECK(timer_read_enable_flag(TIMERS_COOL_TIMEOUT,&enable));
if(enable) //если уже был запущен (в APP_HEAT_FAN) выходим, не перезапускаем
{
return;
}
APP_ERROR_CHECK(timer_write_period(TIMERS_COOL_TIMEOUT,TIMERS_MILLISECOND(APP_COOL_TIMEOUT_MS)));
APP_ERROR_CHECK(timer_reset(TIMERS_COOL_TIMEOUT));
APP_ERROR_CHECK(timer_start(TIMERS_COOL_TIMEOUT));
}
/**@brief Функция останавливает таймер охлаждения
*
* @param none
*
* @return none
*/
static void app_cool_timer_stop(void)
{
app_heater.app_heater_enable.flags.cooling_en = 0;
APP_ERROR_CHECK(timer_stop(TIMERS_COOL_TIMEOUT));
}
static void stateTest(void)
{
if(app_heater.app_state == APP_TEST) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_TEST\r\n"RTT_CTRL_RESET);
app_state_change(APP_TEST);
app_set_sound(1);
stateStandBy();
}
static void stateStandBy(void)
{
if(app_heater.app_state == APP_STAND_BY) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_STAND_BY\r\n"RTT_CTRL_RESET);
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
app_state_change(APP_STAND_BY);
app_heat_disable();
if((app_heater.app_heater_enable.bits & BIT_COOLING_EN ) != 0)
{
app_cool_timer_start();
app_heat_fan();
}
else
{
app_heat_off(); //выключаем обогрев и вентилятор
}
app_sw_off_timer_stop(); //останавливаем таймер отключения если запущен
app_heater.app_heater_enable.flags.osc_en = 0;
app_osc_stop();
}
static void stateHeat(app_prog_t app_prog)
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_HEAT\r\n"RTT_CTRL_RESET);
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
app_state_change(APP_HEAT);
switch(app_prog)
{
case PROG_HEAT_TURBO:
{
app_heater.app_prog = PROG_HEAT_TURBO;
app_cool_timer_stop();
app_heater.app_heater_enable.flags.cooling_en = 1;
app_heat_turbo_enable();
app_heat_turbo();
break;
}
case PROG_HEAT_FAN:
{
app_heater.app_prog = PROG_HEAT_FAN;
app_cool_timer_start();
app_heat_disable();
app_heat_fan();
break;
}
case PROG_HEAT_LOW:
default:
{
app_heater.app_prog = PROG_HEAT_LOW;
app_cool_timer_stop();
app_heater.app_heater_enable.flags.cooling_en = 1;
app_heat_low_enable();
app_heat_low();
break;
}
}
if((app_heater.app_heater_enable.bits & BIT_OSC_EN) != 0)
{
app_osc_start(); //запускаем вращение если оно было активировано
}
}
static void stateStandByAuto(void)
{
if(app_heater.app_state == APP_STAND_BY_AUTO) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_STAND_BY_AUTO\r\n"RTT_CTRL_RESET);
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
app_state_change(APP_STAND_BY_AUTO);
app_heat_low_enable();
if((app_heater.app_heater_enable.bits & BIT_COOLING_EN ) != 0)
{
app_cool_timer_start();
app_heat_fan();
}
else
{
app_heat_off(); //выключаем обогрев и вентилятор
}
app_osc_stop();
}
static void stateHeatAuto(void)
{
if(app_heater.app_state == APP_HEAT_AUTO) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_HEAT_AUTO\r\n"RTT_CTRL_RESET);
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
app_state_change(APP_HEAT_AUTO);
app_cool_timer_stop();
app_heater.app_heater_enable.flags.cooling_en = 1;
app_heat_low_enable();
app_heat_low();
if((app_heater.app_heater_enable.bits & BIT_OSC_EN) != 0)
{
app_osc_start(); //запускаем вращение если оно было активировано
}
}
static void stateStandByAf(void)
{
if(app_heater.app_state == APP_STAND_BY_AF) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_STAND_BY_AF\r\n"RTT_CTRL_RESET);
app_state_change(APP_STAND_BY_AF);
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
app_heat_low_enable();
if((app_heater.app_heater_enable.bits & BIT_COOLING_EN ) != 0)
{
app_cool_timer_start();
app_heat_fan();
}
else
{
app_heat_off(); //выключаем обогрев и вентилятор
}
app_osc_stop();
}
static void stateHeatAf(void)
{
if(app_heater.app_state == APP_HEAT_AF) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_HEAT_AF\r\n"RTT_CTRL_RESET);
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
app_state_change(APP_HEAT_AF);
app_cool_timer_stop();
app_heater.app_heater_enable.flags.cooling_en = 1;
app_heat_low_enable();
app_heat_low();
if((app_heater.app_heater_enable.bits & BIT_OSC_EN) != 0)
{
app_osc_start();// запускаем вращение если оно было активировано(в случае авто режима)
}
}
static void stateParing(void)
{
if(app_heater.app_state == APP_PAIRING) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_PAIRING\r\n"RTT_CTRL_RESET);
app_state_change(APP_PAIRING);
adv_data_set_paring();
app_ind_set_pairing();
app_timeouts_timer_start(APP_PAIRING_TIMEOUT_MS); //запускаем таймер апдейта
}
static void stateUpdate(void)
{
if(app_heater.app_state == APP_FW_UPDATE) return;
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_FW_UPDATE\r\n"RTT_CTRL_RESET);
app_state_change(APP_FW_UPDATE);
app_ind_set_update();
app_timeouts_timer_start(APP_FW_UPDATE_TIMEOUT_MS); //запускаем таймер апдейта
}
static void stateOverHeat(void)
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_OVER_HEAT\r\n"RTT_CTRL_RESET);
app_state_change(APP_OVER_HEAT);
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
app_heat_disable();
if((app_heater.app_heater_enable.bits & BIT_COOLING_EN ) != 0)
{
app_cool_timer_start();
app_heat_fan();
}
else
{
app_heat_off(); //выключаем обогрев и вентилятор
}
app_sw_off_timer_stop(); //останавливаем таймер отключения если запущен
app_heater.app_heater_enable.flags.osc_en = 0;
app_osc_stop();
}
/**@brief Функция выполняет работу при выходе из соответствующего состояния
*
* @param none
*
* @return none
*/
static void app_exit_state( app_state_t app_state )
{
switch( app_state )
{
case APP_PAIRING:
{
adv_data_unset_paring();
app_timeouts_timer_stop(); //останавливаем таймер перинга если вышли из режима
break;
}
case APP_FW_UPDATE:
{
app_timeouts_timer_stop(); //останавливаем таймер апдейта если вышли из режима
break;
}
default:
{
break;
}
}
return;
}
static void app_state_change(app_state_t new_state)
{
app_exit_state( app_heater.app_state );
app_heater.app_state = new_state;
}
static void app_keyb_proccess(void)
{
if(app_get_state() == APP_API_ERROR_STATE) return;
for(uint8_t i=0; i<KEYB_BUTTON_COUNT; ++i) //чтение состояния кнопок
{
keyb_read_data(i, &app_keyboard_data[i]);
}
for(uint8_t i=0;i<KEYB_BUTTON_COUNT;i++)
{
if(app_keyboard_data[i].event_press == KEYB_EVENT_CAPTURED)
{
if((app_heater.app_heater_state.bits & BIT_APP_LOCK ) != 0) //запрещаем обработку кнопок если включена блокировка
{
app_ind_set_lock();
return;
}
}
}
if(app_get_state() == APP_API_FW_UPDATE_STATE
|| app_get_state() == APP_API_PAIRING_STATE
|| app_get_state() == APP_API_ERROR_STATE)
{
return;
}
if(app_keyboard_data[LOCK_KEY].pressed_time_ms >= APP_KEY_LOCK_TIME_MS) //проверяем время нажатия кнопки для преключения в состояния блокировки
{
switch(app_heater.app_state)
{
case APP_STAND_BY:
case APP_HEAT:
case APP_STAND_BY_AUTO:
case APP_HEAT_AUTO:
case APP_STAND_BY_AF:
case APP_HEAT_AF:
{
if(app_flags.b_release_wait == 0)
{
app_flags.b_release_wait = 1;//выставляем флаг ожидания релиза кнопки
app_set_lock(app_heater.app_heater_state.flags.APP_LOCK ? 0:1);
}
return;
}
default:
break;
}
}
if(app_keyboard_data[LOCK_KEY].event_release == KEYB_EVENT_CAPTURED)
{
switch(app_heater.app_state)
{
case APP_STAND_BY:
case APP_HEAT:
case APP_STAND_BY_AUTO:
case APP_HEAT_AUTO:
case APP_STAND_BY_AF:
case APP_HEAT_AF:
{
if(app_flags.b_release_wait == 1)
{
app_flags.b_release_wait = 0;
return;
}
break;
}
default:
break;
}
}
if((app_heater.app_heater_state.bits & BIT_APP_LOCK ) == 0) //запрещаем обработку кнопок если включена блокировка
{
if(app_keyboard_data[PAIRING_KEY].pressed_time_ms >= APP_KEY_PARING_TIME ) //ожидаем время нажатия для пейринга
{
switch(app_heater.app_state)
{
case APP_STAND_BY:
{
if(app_flags.b_release_wait == 0)
{
app_flags.b_release_wait = 1;//выставляем флаг ожидания релиза кнопки
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_MULTI));
}
return;
}
default:
break;
}
}
if(app_keyboard_data[PAIRING_KEY].event_release == KEYB_EVENT_CAPTURED) //если кнопка перинга отпущена переходим в режим перига
{
switch(app_heater.app_state)
{
case APP_STAND_BY:
{
if(app_flags.b_release_wait == 1)
{
app_flags.b_release_wait = 0;
stateParing();
return;
}
break;
}
default:
break;
}
}
if(app_keyboard_data[UNPAIRING_KEY].pressed_time_ms >= APP_KEY_UNPARING_TIME ) //ожидаем время нажатия для анпейринга
{
switch(app_heater.app_state)
{
case APP_STAND_BY:
{
if(app_flags.b_release_wait == 0)
{
app_flags.b_release_wait = 1;//выставляем флаг ожидания релиза кнопки
APP_ERROR_CHECK(buz_add_beep(300,150,BUZ_BEEP_MULTI));
}
return;
}
default:
break;
}
return;
}
if(app_keyboard_data[UNPAIRING_KEY].event_release == KEYB_EVENT_CAPTURED)
{
switch(app_heater.app_state)
{
case APP_STAND_BY:
{
if(app_flags.b_release_wait == 1)
{
app_flags.b_release_wait = 0;
com_slave_unpair_proccess(); //Делаем анперинг
return;
}
break;
}
default:
break;
}
}
if(app_keyboard_data[OSC_KEY].event_release == KEYB_EVENT_CAPTURED) //переключаем состояние осцилятора
{
switch (app_heater.app_state)
{
case APP_HEAT:
case APP_STAND_BY_AUTO:
case APP_HEAT_AUTO:
case APP_STAND_BY_AF:
case APP_HEAT_AF:
{
app_osc_enable(!app_heater.app_heater_enable.flags.osc_en);
break;
}
default:
break;
}
}
//активируем таймер отключения и инкриментируем время
if(app_keyboard_data[TIMER_KEY].event_release == KEYB_EVENT_CAPTURED)
{
switch (app_heater.app_state)
{
case APP_HEAT:
case APP_STAND_BY_AUTO:
case APP_HEAT_AUTO:
case APP_STAND_BY_AF:
case APP_HEAT_AF:
{
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
uint16_t time = HOUR_TO_MINUTES(app_get_sw_off_time_left_h() + 1);
app_set_sw_off_time(time);
break;
}
default:
break;
}
}
if(app_keyboard_data[LEVEL_KEY].event_release == KEYB_EVENT_CAPTURED)//переключение между режимами нагревателя
{
app_power_iterate(0);
}
if(app_keyboard_data[SWITCHER_KEY].event_release == KEYB_EVENT_CAPTURED) //выставляем флаг активной/пассивной работы
{
app_switch();
}
}
}
/********************************************************************************
*
********************************************************************************/
static void app_temp_serv_proccess(void)
{
temp_serv_read(&app_temp_serv_data);
if(app_get_state() == APP_API_FW_UPDATE_STATE
|| app_get_state() == APP_API_PAIRING_STATE
|| app_get_state() == APP_API_ERROR_STATE)
{
return;
}
if(app_get_curent_temp() >= APP_OVERHEAT_TEMP)
{
stateOverHeat();
app_ind_set_overheat();
}
switch (app_heater.app_state)
{
case APP_HEAT:
case APP_HEAT_AUTO:
case APP_STAND_BY_AUTO:
case APP_HEAT_AF:
case APP_STAND_BY_AF:
{
if(app_heater.app_prog == PROG_AUTO)
{
if(app_temp_serv_data.event_lower == TEMP_EVENT_CAPTURED)
{
stateHeatAuto();
}
else if(app_temp_serv_data.event_higher == TEMP_EVENT_CAPTURED)
{
stateStandByAuto();
}
}
else if(app_heater.app_prog == PROG_AF)
{
if(app_temp_serv_data.event_lower == TEMP_EVENT_CAPTURED)
{
stateHeatAf();
}
else if(app_temp_serv_data.event_higher == TEMP_EVENT_CAPTURED)
{
stateStandByAf();
}
}
break;
}
default:
break;
}
}
/********************************************************************************
*
********************************************************************************/
void application_process(void)
{
app_keyb_proccess();
app_temp_serv_proccess();
app_ind_proccess();
return;
}
/********************************************************************************
*
********************************************************************************/
/********************************************************************************
*
********************************************************************************/
/**
* описание в application_api.h
*/
uint16_t app_get_version(void)
{
return FIRMWARE_VER;
}
bool app_state_check(app_state_t state)
{
if(app_heater.app_state == state)
{
return true;
}
else
{
return false;
}
}
uint8_t app_get_state(void)
{
switch(app_heater.app_state)
{
case APP_FW_UPDATE:
{
return APP_API_FW_UPDATE_STATE;
}
case APP_PAIRING:
{
return APP_API_PAIRING_STATE;
}
case APP_STAND_BY:
{
return APP_API_OFF_STATE;
}
case APP_OVER_HEAT:
{
return APP_API_ERROR_STATE;
}
default:
{
return APP_API_ON_STATE;
}
}
}
uint8_t app_get_error(void)
{
switch(app_heater.app_state)
{
case APP_OVER_HEAT:
{
return APP_API_CRITICAL_ERROR;
}
default:
return APP_API_NO_ERROR;
}
}
uint8_t app_set_sw_off_time(uint16_t time)
{
if( app_get_state() != APP_API_ON_STATE) return 0;
if((time > 480) || (time == 0)) //задать интервал можно неболее 8 часов
{
app_sw_off_timer_stop(); // если время = 0, отключаем таймер
}
else
{
app_sw_off_time_left_m = time;
app_sw_off_timer_start();
}
app_ind_set_time_set();
return 1;
}
uint8_t app_get_sw_off_time_left_h(void)
{
if((app_sw_off_time_left_m % 60) == 0)
{
return MINUTES_TO_HOUR(app_sw_off_time_left_m);
}
else
{
return MINUTES_TO_HOUR(app_sw_off_time_left_m) + 1;
}
}
uint16_t app_get_sw_off_time_left(void)
{
return app_sw_off_time_left_m;
}
uint8_t app_get_sw_off_timer_flag(void)
{
return app_heater.app_heater_state.flags.APP_TIMER;
}
uint8_t app_set_sw_on(void)
{
if( app_get_state() == APP_API_FW_UPDATE_STATE
|| app_get_state() == APP_API_PAIRING_STATE
|| app_get_state() == APP_API_ERROR_STATE )
{
return 0;
}
stateHeat(app_heater.app_prog);
return 1;
}
uint8_t app_set_sw_off(void)
{
if( app_get_state() == APP_API_FW_UPDATE_STATE
|| app_get_state() == APP_API_PAIRING_STATE
|| app_get_state() == APP_API_ERROR_STATE )
{
return 0;
}
stateStandBy();
return 1;
}
uint8_t app_switch(void)
{
switch (app_heater.app_state)
{
case APP_STAND_BY:
{
stateHeat(PROG_HEAT_LOW);
return 1;
}
case APP_HEAT:
case APP_HEAT_AUTO:
case APP_HEAT_AF:
case APP_STAND_BY_AUTO:
case APP_STAND_BY_AF:
{
stateStandBy();
return 1;
}
default:
return 0;
}
}
uint8_t app_power_iterate(int8_t vector)
{
if(appIterStepAllowFl == false) return 0;
APP_ERROR_CHECK(app_timer_start(app_iteration_timer_id, APP_TIMER_TICKS(500, APP_TIMER_PRESCALER), NULL ));
appIterStepAllowFl = false;
switch(vector){
case 0:{
switch (app_heater.app_state){
case APP_HEAT:{
switch(app_heater.app_prog){
case PROG_HEAT_LOW:{
stateHeat(PROG_HEAT_TURBO);
return 1;
}
case PROG_HEAT_TURBO:{
stateHeat(PROG_HEAT_FAN);
return 1;
}
case PROG_HEAT_FAN:{
stateHeat(PROG_HEAT_LOW);
return 1;
}
default:
return 0;
}
}
default:
return 0;
}
}
default:
return 0;
}
}
uint8_t app_set_lock(uint8_t lock)
{
if( app_get_state() == APP_API_FW_UPDATE_STATE
|| app_get_state() == APP_API_PAIRING_STATE
|| app_get_state() == APP_API_ERROR_STATE )
{
return 0;
}
if (lock > 1) return 0;
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
if(lock)
{
app_heater.app_heater_state.flags.APP_LOCK = 1; //выставляем флаг блокировки
app_ind_set_lock(); //выводим индикацию
}
else
{
app_heater.app_heater_state.flags.APP_LOCK = 0;//выставляем флаг разблокировки
app_ind_set_unlock(); //выводим индикацию
}
return 1;
}
uint8_t app_get_lock(void)
{
return app_heater.app_heater_state.flags.APP_LOCK;
}
uint8_t app_set_heat_program(uint8_t prog)
{
if( app_get_state() == APP_API_FW_UPDATE_STATE
|| app_get_state() == APP_API_PAIRING_STATE
|| app_get_state() == APP_API_ERROR_STATE)
{
return 0;
}
switch(prog)
{
case PROG_HEAT_LOW:
{
if(app_heater.app_prog == PROG_HEAT_LOW) break;
stateHeat(PROG_HEAT_LOW);
break;
}
case PROG_HEAT_TURBO:
{
if(app_heater.app_prog == PROG_HEAT_TURBO) break;
stateHeat(PROG_HEAT_TURBO);
break;
}
case PROG_HEAT_FAN:
{
if(app_heater.app_prog == PROG_HEAT_FAN) break;
stateHeat(PROG_HEAT_FAN);
break;
}
case PROG_AUTO:
{
if(app_heater.app_prog == PROG_AUTO) break;
app_heater.app_prog = PROG_AUTO;
temp_serv_set_target(app_target_temp);
app_ind_set_auto();
break;
}
case PROG_AF:
{
if(app_heater.app_prog == PROG_AF) break;
app_heater.app_prog = PROG_AF;
temp_serv_set_target(APP_ANTI_FROST_TEMP);
app_ind_set_af();
break;
}
default:
return 0;
}
return 1;
}
uint8_t app_get_heat_program(void)
{
return app_heater.app_prog;
}
uint8_t app_set_target_temp(uint8_t targetTemp)
{
if (targetTemp > 35 || targetTemp < 8) return 0;
app_target_temp = targetTemp;
if(app_heater.app_prog != PROG_AF)
{
temp_serv_set_target(app_target_temp);
}
return 1;
}
uint8_t app_get_target_temp(void)
{
return app_target_temp;
}
uint8_t app_get_curent_temp(void)
{
return (uint8_t)temp_serv_get_current_temp();
}
uint8_t app_osc_get_enable(void)
{
return app_heater.app_heater_enable.flags.osc_en;
}
uint8_t app_osc_enable( uint8_t enable)
{
if( app_get_state() == APP_API_FW_UPDATE_STATE
|| app_get_state() == APP_API_PAIRING_STATE
|| app_get_state() == APP_API_ERROR_STATE)
{
return 0;
}
if(enable > 1) return 0;
if(app_heater.app_heater_enable.flags.sound_en)
{
APP_ERROR_CHECK(buz_add_beep(150,150,BUZ_BEEP_SINGLE));
}
if(enable)
{
switch(app_heater.app_state)
{
case APP_HEAT:
case APP_HEAT_AUTO:
case APP_HEAT_AF:
{
app_heater.app_heater_enable.flags.osc_en = 1;
app_osc_start();
break;
}
case APP_STAND_BY_AUTO:
case APP_STAND_BY_AF:
{
app_heater.app_heater_enable.flags.osc_en = 1;
break;
}
default:
break;
}
}
else
{
app_heater.app_heater_enable.flags.osc_en = 0;
app_osc_stop();
}
return 1;
}
void app_osc_start(void)
{
app_heater.app_heater_state.flags.APP_OSC = 1;
NRF_GPIO->OUTSET = (1UL << MOTO);
}
void app_osc_stop(void)
{
app_heater.app_heater_state.flags.APP_OSC = 0;
NRF_GPIO->OUTCLR = (1UL << MOTO);
}
uint8_t app_get_heat_low_enable(void)
{
return app_heater.app_heater_enable.flags.heat_low_en;
}
uint8_t app_get_heat_turbo_enable(void)
{
return app_heater.app_heater_enable.flags.heat_turbo_en;
}
static void app_heat_off(void)
{
NRF_GPIO->OUTCLR = (1UL << MAIN_HEAT_L);
NRF_GPIO->OUTCLR = (1UL << MAIN_HEAT_H);
NRF_GPIO->OUTCLR = (1UL << FAN);
app_heater.app_heater_state.flags.APP_HEAT_LOW = 0;
app_heater.app_heater_state.flags.APP_HEAT_TURBO = 0;
app_heater.app_heater_state.flags.APP_HEAT_FAN = 0;
}
static void app_heat_fan(void)
{
NRF_GPIO->OUTCLR = (1UL << MAIN_HEAT_L);
NRF_GPIO->OUTCLR = (1UL << MAIN_HEAT_H);
NRF_GPIO->OUTSET = (1UL << FAN);
app_heater.app_heater_state.flags.APP_HEAT_LOW = 0;
app_heater.app_heater_state.flags.APP_HEAT_TURBO = 0;
app_heater.app_heater_state.flags.APP_HEAT_FAN = 1;
}
static void app_heat_low(void)
{
NRF_GPIO->OUTSET = (1UL << MAIN_HEAT_L);
NRF_GPIO->OUTCLR = (1UL << MAIN_HEAT_H);
NRF_GPIO->OUTSET = (1UL << FAN);
app_heater.app_heater_state.flags.APP_HEAT_LOW = 1;
app_heater.app_heater_state.flags.APP_HEAT_TURBO = 0;
app_heater.app_heater_state.flags.APP_HEAT_FAN = 1;
}
static void app_heat_turbo(void)
{
NRF_GPIO->OUTSET = (1UL << MAIN_HEAT_L);
NRF_GPIO->OUTSET = (1UL << MAIN_HEAT_H);
NRF_GPIO->OUTSET = (1UL << FAN);
app_heater.app_heater_state.flags.APP_HEAT_LOW = 1;
app_heater.app_heater_state.flags.APP_HEAT_TURBO = 1;
app_heater.app_heater_state.flags.APP_HEAT_FAN = 1;
}
static void app_heat_low_enable(void)
{
app_heater.app_heater_enable.flags.heat_low_en = 1;
app_heater.app_heater_enable.flags.heat_turbo_en = 0;
}
static void app_heat_turbo_enable(void)
{
app_heater.app_heater_enable.flags.heat_low_en = 1;
app_heater.app_heater_enable.flags.heat_turbo_en = 1;
}
static void app_heat_disable(void)
{
app_heater.app_heater_enable.flags.heat_low_en = 0;
app_heater.app_heater_enable.flags.heat_turbo_en = 0;
}
uint8_t app_set_sound(uint8_t sound_en)
{
if (sound_en >1) return 0;
app_heater.app_heater_enable.flags.sound_en = sound_en;
return 1;
}
uint8_t app_get_sound (void)
{
return app_heater.app_heater_enable.flags.sound_en;
}
uint8_t app_set_calendar_data(void *timestamp, void *shift)
{
calendar_utc_t m_time_stamp = 0;
calendar_shift_utc_t m_shift = 0;
m_time_stamp = uint32_decode(timestamp); //преобразуем данные массива в uint32_t
m_shift = uint32_decode(shift); //преобразуем данные массива в uint32_t
uint32_t err_code = calendar_set_time(m_time_stamp, m_shift);
switch (err_code)
{
case NRF_SUCCESS:
return ERSP_SUCCESS;
case NRF_ERROR_INVALID_DATA:
return ERSP_ERROR_INVALID_DATA;
case DRIVER_MODULE_NOT_INITIALZED:
return ERSP_ERROR_INTERNAL;
}
return ERSP_ERROR_UNKNOWN;
}
void app_get_calendar_data(void *timestamp, void *shift)
{
calendar_utc_t m_time_stamp = 0;
calendar_shift_utc_t m_shift = 0;
//получаем данные о текущем UTC и времени сдвига
uint32_t err_code = calendar_get_utc_time(&m_time_stamp, &m_shift);
APP_ERROR_CHECK(err_code);
memcpy(timestamp, &m_time_stamp, sizeof(calendar_utc_t));
memcpy(shift, &m_shift, sizeof(calendar_shift_utc_t));
}
void app_get_evcal_task(uint8_t task_num, void *p_buf)
{
uint32_t err_code = evcal_get_task_data(task_num, p_buf);
if(err_code != NRF_SUCCESS){
memset(p_buf, 0, sizeof(evcal_task_t));
}
}
uint8_t app_add_evcal_task(void *p_input, uint8_t *uid)
{
//записываем новую задачу в календарь
uint32_t err_code = evcal_save_task(p_input);
*uid = ((evcal_task_t *)p_input)->uid; //записываем UID присвоенной задачи
switch (err_code)
{
case NRF_SUCCESS:
{
return ERSP_SUCCESS;
}
case NRF_ERROR_NO_MEM:
{
return ERSP_ERROR_NO_MEM;
}
case DRIVER_MODULE_NOT_INITIALZED:
case NRF_ERROR_NULL:
{
return ERSP_ERROR_INTERNAL;
}
}
return ERSP_ERROR_UNKNOWN;
}
uint8_t app_del_evcal_task(uint8_t uid_task)
{
//записываем новую задачу в календарь
uint32_t err_code = evcal_delete_task(uid_task);
switch (err_code)
{
case NRF_SUCCESS:
{
return ERSP_SUCCESS;
}
case NRF_ERROR_NOT_FOUND:
{
return ERSP_ERROR_NOT_FOUND;
}
case NRF_ERROR_INVALID_PARAM:
{
return ERSP_ERROR_INVALID_PARAM;
}
case DRIVER_MODULE_NOT_INITIALZED:
{
return ERSP_ERROR_INTERNAL;
}
}
return ERSP_ERROR_UNKNOWN;
}
uint8_t app_erase_evcal(void)
{
if(evcal_erase_all_tasks() == NRF_SUCCESS){
return ERSP_SUCCESS;
} else {
return ERSP_ERROR_INTERNAL;
}
}
uint8_t app_get_ver_evcal(void)
{
return EVCAL_DRIVER_VERSION;
}
uint8_t app_get_max_task_evcal(void)
{
return EVCAL_MAX_TASKS;
}
uint8_t app_get_cur_task_num_evcal(void)
{
uint8_t m_num_task = 0;
APP_ERROR_CHECK(evcal_get_task_number(&m_num_task));
return m_num_task;
}
uint8_t app_enter_fw_update_state(void)
{
if(app_get_state() == APP_API_OFF_STATE)
{
stateUpdate();
return 1;
}
return 0;
}
void app_exit_fw_update_state(void)
{
stateStandBy();
}
void app_fw_update_proc(void)
{
if( app_heater.app_state == APP_FW_UPDATE )
{
APP_ERROR_CHECK(timer_reset(TIMERS_APP_TIMEOUTS));
}
}
void app_set_open_session_flag(void)
{
app_flags.b_session_is_opened = 1;
return;
}
void app_set_connection_flag(void)
{
app_flags.b_connection_is_established = 1;
return;
}
void app_clear_connection_flag(void)
{
app_flags.b_session_is_opened = 0;
app_flags.b_connection_is_established = 0;
return;
}
void app_slave_pairing_complite( void )
{
stateStandBy();
}
void app_slave_pairing_error(void)
{
stateStandBy();
}
/*****************************************************************************************************/