Программный модуль для чайника RK-M170S v.3.4


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

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

//RK-M170S

//v3.4

//application.c

////////////////////////////////////////////////////////////////
/********* HEADER FILE INCLUDES *************************************************/
#include <stdint.h>
#include <stdlib.h>
#include "math.h"
#include "nrf.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf_soc.h"
#include "app_error.h"
#include "app_util_platform.h"

#include "timers.h"
#include "timers_config.h"
#include "buz.h"
#include "buz_config.h"
#include "keyb.h"
#include "keyb_config.h"
#include "led.h"
#include "led_config.h"


#include "config.h"
#include "application.h"
#include "application_api.h"

#include "temp.h"
#include "boost_ctrl.h"



static void app_simple_timeout_timer_handler(void){
	app_flags.b_simple_timeout = 1;
	return;
}

static void app_clear_all_led(void){
	app_leds.led_40 = 0;
	app_leds.led_55 = 0;
	app_leds.led_70 = 0;
	app_leds.led_85 = 0;
	app_leds.led_95 = 0;
	app_leds.led_boiling = 0;
	app_leds.led_start_stop = 0;
	app_leds.led_warm = 0;
}

static void app_update_leds(void){
	uint32_t err_code = NRF_SUCCESS;

	err_code = led_write_data(LED_40_TMP, app_leds.led_40);
	APP_ERROR_CHECK(err_code);
	err_code = led_write_data(LED_55_TMP, app_leds.led_55);
	APP_ERROR_CHECK(err_code);
	err_code = led_write_data(LED_70_TMP, app_leds.led_70);
	APP_ERROR_CHECK(err_code);
	err_code = led_write_data(LED_85_TMP, app_leds.led_85);
	APP_ERROR_CHECK(err_code);
	err_code = led_write_data(LED_95_TMP, app_leds.led_95);
	APP_ERROR_CHECK(err_code);
	err_code = led_write_data(LED_WARM, app_leds.led_warm);
	APP_ERROR_CHECK(err_code);
	err_code = led_write_data(LED_ON_OFF, app_leds.led_start_stop);
	APP_ERROR_CHECK(err_code);
	err_code = led_write_data(LED_BOILING, app_leds.led_boiling);
	APP_ERROR_CHECK(err_code);
}

static void app_cnfg_heat_temp(uint8_t temp){
	if(boiling_set_temp != temp){ //если температура еще не была задана
		boiling_set_temp = temp;
		//сообщаем, что нужно поддержать температуру
		app_flags.b_keep_warm_en = 1;
	}else{
		boiling_set_temp = APP_HEATING_TEMP_C;
		//сообщаем, что не нужно поддержать температуру
		app_flags.b_keep_warm_en = 0;
	}
}

static void app_timeout_timers_restart(uint8_t timeout_s){
	uint32_t err_code;

	app_flags.b_simple_timeout = 0;
	err_code = timer_write_period(TIMER_APP_SIMPLE_TIMEOUT, TIMERS_SECOND(timeout_s));
	APP_ERROR_CHECK(err_code);
	err_code = timer_reset(TIMER_APP_SIMPLE_TIMEOUT);
	APP_ERROR_CHECK(err_code);
}

static void app_sec_timer_handler(void){
	if( 1 == app_flags.b_keep_wrm_boost_cmplt ){
		if( 0 != keep_warm_time_downcounter_s )keep_warm_time_downcounter_s--;
	}
	if( 1 == app_flags.b_boiling_complete ){
		if( 0 != boilig_complete_ind_time_downcounter_s )boilig_complete_ind_time_downcounter_s--;
	}
	if( 0 != boiling_min_time_downcounter_s )boiling_min_time_downcounter_s--;
	if( 0 != block_ind_time_downcounter_s )block_ind_time_downcounter_s--;
	if( ++boilig_temp_update_upcounter_s >= APP_BOILING_TEMP_UPDATE_TIME_S )
	{
		boilig_temp_update_upcounter_s = 0;
		boiling_temp_update_flag = true;
	}
	if(++pairing_ind_time_s >= APP_PAIRING_IND_TIME_S)
	{
		pairing_ind_time_s = 0;
	}
	if( 0 != test_time_fast_click_ms ){
		if(test_time_fast_click_ms-- == 1) app_flags.b_clear_last_btn = 1;
	}
	return;
}

static void app_msec_timer_handler(void){
	if( 0 != boiling_complete_leds_time_ms )boiling_complete_leds_time_ms--;
	if( 0 != sound_ctrl_leds_time_ms) sound_ctrl_leds_time_ms--;
	if( APP_KEEPWARM_BLINK_TIME_S == ++keep_warm_leds_time_ms ) keep_warm_leds_time_ms = 0;
	return;
}

static void app_boiling_temp_update( void ){
	static const uint8_t step = 1;				/* шаг приращения температуры индикации */

	if( app_show_boiling_temp == false )
	{
		//если не установлен флаг возвращаем реальную температуру
		boiling_ind_temp = ( temp_get_val() > APP_HEATING_TEMP_C ) ? APP_HEATING_TEMP_C : temp_get_val();
	}else{
		if( temp_get_val() > boiling_ind_temp + step )
		{
			//отменим "замазку", т.к. реальная температура больше "замазки"
			app_show_boiling_temp = false;
			boiling_ind_temp = ( temp_get_val() > APP_HEATING_TEMP_C ) ? APP_HEATING_TEMP_C : temp_get_val();
		}else{
			if( boiling_temp_update_flag == false )return;		//если не сработал таймер обновления информации
			boiling_temp_update_flag = false;

			if( boiling_temp_upcount_flag == true )
			{
				//идем вверх
				if( ( boiling_ind_temp + step ) >=  APP_HEATING_TEMP_C )
				{
					boiling_ind_temp = APP_HEATING_TEMP_C;
					boiling_temp_upcount_flag = false;	//начинаем идти вниз
				}else{
					boiling_ind_temp += step;
				}
			}else{
				if( app_state ==  APP_BOILING_PROC  )return;	//не снижаем температуру пока в режиме кипения
				//идем вниз
				if( boiling_ind_temp  >  temp_get_val() + step )
				{
					boiling_ind_temp -= step;
					boiling_ind_temp = ( boiling_ind_temp > APP_HEATING_TEMP_C ) ? APP_HEATING_TEMP_C : boiling_ind_temp;
				}else{
					boiling_ind_temp = ( temp_get_val() > APP_HEATING_TEMP_C ) ? APP_HEATING_TEMP_C : temp_get_val();
					app_show_boiling_temp = false;
				}
			}
		}
	}
	return;
}


static void appl_show_start(void){
	app_clear_all_led();
	app_leds.led_40 = app_leds.led_55 = app_leds.led_70 = app_leds.led_85 = \
	app_leds.led_95 = app_leds.led_boiling = app_leds.led_start_stop = app_leds.led_warm = 1;

	return;
}

static void appl_show_standby(void){
	app_clear_all_led();
	if(app_push_btn_time != 0){
		if(((app_push_btn_time/100)%4) == 3){
			app_leds.led_warm = 1;
		} else if(((app_push_btn_time/100)%4) == 2){
			app_leds.led_85 = 1;
		} else if(((app_push_btn_time/100)%4) == 1){
			app_leds.led_55 = 1;
		} else {
			app_leds.led_boiling = 1;
		}
	}
	return;
}

static void appl_show_pairing(void){
	app_clear_all_led();
	if((pairing_ind_time_s % 2) == 0){
		app_leds.led_boiling = app_leds.led_85 = 1;
	} else {
		app_leds.led_warm = app_leds.led_55 = 1;
	}
	return;
}

static void appl_show_config(void){
	app_clear_all_led();

	if(boiling_set_temp == 40){
		app_leds.led_40 = 1;
	}
	else if(boiling_set_temp == 55){
		app_leds.led_55 = 1;
	}
	else if(boiling_set_temp == 70){
		app_leds.led_70 = 1;
	}
	else if(boiling_set_temp == 85){
		app_leds.led_85 = 1;
	}
	else if(boiling_set_temp == 95){
		app_leds.led_95 = 1;
	}

	if(app_flags.b_boiling_en == 1){
		app_leds.led_boiling = 1;
	}
	if(app_flags.b_warm_en == 1){
		app_leds.led_warm = 1;
	}
	return;
}

static void appl_show_boiling(void){
	app_clear_all_led();

	app_leds.led_start_stop = 1;

	if(boiling_set_temp == 40){
		app_leds.led_40 = 1;
	}
	else if(boiling_set_temp == 55){
		app_leds.led_55 = 1;
	}
	else if(boiling_set_temp == 70){
		app_leds.led_70 = 1;
	}
	else if(boiling_set_temp == 85){
		app_leds.led_85 = 1;
	}
	else if(boiling_set_temp == 95){
		app_leds.led_95 = 1;
	}

	if(app_flags.b_boiling_en == 1){
		app_leds.led_boiling = 1;
	}
	if(app_flags.b_warm_en == 1){
		app_leds.led_warm = 1;
	}
	return;
}

static void appl_show_final_booling(void){
	app_clear_all_led();
	if((boiling_complete_leds_time_ms>10) || (boiling_complete_leds_time_ms%2)) {
		app_leds.led_40 = 1;
		app_leds.led_55 = 1;
		app_leds.led_70 = 1;
		app_leds.led_85 = 1;
		app_leds.led_95 = 1;
	} else {
		app_leds.led_40 = 0;
		app_leds.led_55 = 0;
		app_leds.led_70 = 0;
		app_leds.led_85 = 0;
		app_leds.led_95 = 0;
	}
}

static void appl_show_keepwarm(void){
	app_clear_all_led();

	app_leds.led_start_stop = 1;

	if(boiling_set_temp == 40){
		app_leds.led_40 = ((keep_warm_leds_time_ms/4)%2)? 1: 0;
	}
	else if(boiling_set_temp == 55){
		app_leds.led_55 = ((keep_warm_leds_time_ms/4)%2)? 1: 0;
	}
	else if(boiling_set_temp == 70){
		app_leds.led_70 = ((keep_warm_leds_time_ms/4)%2)? 1: 0;
	}
	else if(boiling_set_temp == 85){
		app_leds.led_85 = ((keep_warm_leds_time_ms/4)%2)? 1: 0;
	}
	else if(boiling_set_temp == 95){
		app_leds.led_95 = ((keep_warm_leds_time_ms/4)%2)? 1: 0;
	}

	if(app_flags.b_boiling_en == 1){
		app_leds.led_boiling = 1;
	}
	if(app_flags.b_warm_en == 1){
		app_leds.led_warm = 1;
	}
	return;
}

static void appl_show_sound_ctrl(uint8_t led_index){
	app_clear_all_led();

	switch(led_index)
	{
		case 0:
		{
			if(app_flags.b_sound_en == 1){ //если звук включен
				app_leds.led_95 = 1;
			}
			else{
				app_leds.led_40 = 1;
			}
			break;
		}
		case 1:
		{
			if(app_flags.b_sound_en == 1){ //если звук включен
				app_leds.led_85 = 1;
				app_leds.led_95 = 1;
			}
			else{
				app_leds.led_40 = 1;
				app_leds.led_55 = 1;
			}
			break;
		}
		case 2:
		{
			if(app_flags.b_sound_en == 1){ //если звук включен
				app_leds.led_70 = 1;
				app_leds.led_85 = 1;
				app_leds.led_95 = 1;
			}
			else{
				app_leds.led_40 = 1;
				app_leds.led_55 = 1;
				app_leds.led_70 = 1;
			}
			break;
		}
		case 3:
		{
			if(app_flags.b_sound_en == 1){ //если звук включен
				app_leds.led_55 = 1;
				app_leds.led_70 = 1;
				app_leds.led_85 = 1;
				app_leds.led_95 = 1;
			}
			else{
				app_leds.led_40 = 1;
				app_leds.led_55 = 1;
				app_leds.led_70 = 1;
				app_leds.led_85 = 1;
			}
			break;
		}
		//центр
		case 4:
		{
			app_leds.led_40 = 1;
			app_leds.led_55 = 1;
			app_leds.led_70 = 1;
			app_leds.led_85 = 1;
			app_leds.led_95 = 1;
			break;
		}
		//обратный ход
		case 5:
		{
			app_leds.led_40 = 1;
			app_leds.led_55 = 1;
			app_leds.led_70 = 1;
			app_leds.led_85 = 1;
			break;
		}
		case 6:
		{
			app_leds.led_40 = 1;
			app_leds.led_55 = 1;
			app_leds.led_70 = 1;
			break;
		}
		case 7:
		{
			app_leds.led_40 = 1;
			app_leds.led_55 = 1;
			break;
		}
		case 8:
		{
			app_leds.led_40 = 1;
			break;
		}
	}
	
	return;
}

static void appl_show_no_kettle(bool ind_enable){
	if(ind_enable){
		app_clear_all_led();
		app_leds.led_40 = app_leds.led_55 = app_leds.led_70 = \
		app_leds.led_85 = app_leds.led_95 = 1;
	}
	else{
		app_clear_all_led();
		if(app_push_btn_time != 0){
			if(((app_push_btn_time/100)%4) == 3){
				app_leds.led_warm = 1;
			} else if(((app_push_btn_time/100)%4) == 2){
				app_leds.led_85 = 1;
			} else if(((app_push_btn_time/100)%4) == 1){
				app_leds.led_55 = 1;
			} else {
				app_leds.led_boiling = 1;
			}
		}
	}
	return;
}

static void app_show_warm(void){
	app_clear_all_led();

	app_leds.led_start_stop = 1;

	if(boiling_set_temp == 40){
		app_leds.led_40 = 1;
	}
	else if(boiling_set_temp == 55){
		app_leds.led_55 = 1;
	}
	else if(boiling_set_temp == 70){
		app_leds.led_70 = 1;
	}
	else if(boiling_set_temp == 85){
		app_leds.led_85 = 1;
	}
	else if(boiling_set_temp == 95){
		app_leds.led_95 = 1;
	}

	if(app_flags.b_warm_en == 1){
		app_leds.led_warm = 1;
	}
	return;
}

static void app_show_test_led(void){
	app_clear_all_led();
	
	switch(app_last_btn_push)
	{
//		case KEY_ON_OFF:
//		{
//			app_leds.led_start_stop = 1;
//			break;
//		}
		case KEY_BOILING:
		{
			app_leds.led_boiling = 1;
			break;
		}
		case KEY_HEAT:
		{
			app_leds.led_warm = 1;
			break;
		}
		case KEY_40_TEMP:
		{
			app_leds.led_40 = 1;
			break;
		}
		case KEY_55_TEMP:
		{
			app_leds.led_55 = 1;
			break;
		}
		case KEY_70_TEMP:
		{
			app_leds.led_70 = 1;
			break;
		}
		case KEY_85_TEMP:
		{
			app_leds.led_85 = 1;
			break;
		}
		case KEY_95_TEMP:
		{
			app_leds.led_95 = 1;
			break;
		}
	}
	return;
}

static void app_show_test_rel(void){
	app_clear_all_led();
	
	app_leds.led_start_stop = 1;

	return;
}

static void app_show_test_temp(void){
	app_clear_all_led();
	
	uint8_t m_temp = temp_get_val();
	
	app_leds.led_warm = (m_temp & 0x01)? 1: 0;
	app_leds.led_boiling = (m_temp & 0x02)? 1: 0;
	app_leds.led_95 = (m_temp & 0x04)? 1: 0;
	app_leds.led_85= (m_temp & 0x08)? 1: 0;
	app_leds.led_70 = (m_temp & 0x10)? 1: 0;
	app_leds.led_55 = (m_temp & 0x20)? 1: 0;
	app_leds.led_40 = (m_temp & 0x40)? 1: 0;;

	return;
}


 *  @brief  Простой П-регулятор
 *
 *  @param[in]  Y - значение регулируемой величины
 *	@param[in]	U - уставка
 *	@param[in]	KV - коэффициент усиления 
 *  @return -	выход регулятора
 *			
 */
static uint16_t simple_reg( uint8_t Y, uint8_t U, uint8_t KV ){
	unsigned long int X;		//reg out
	if( Y > U ){ return 0; }
	X = ( U - Y )*KV;
	
	if( X > REG_MAX_PWM	 ){
		return REG_MAX_PWM	;
	}else{
		return X;
	}
}

/********************************************************************************
 *
 ********************************************************************************/
void application_init( void )
{
    uint32_t err_code = NRF_SUCCESS;

	app_flags.b_sound_en = 1; //разрешаем звуковые сигналы
	
	err_code = timer_create(TIMER_APP_SIMPLE_TIMEOUT, 0, (callback_t)app_simple_timeout_timer_handler );
	APP_ERROR_CHECK(err_code);
	app_timeout_timers_restart(APP_START_TIMEOUT_S);
	err_code = timer_start(TIMER_APP_SIMPLE_TIMEOUT);
	APP_ERROR_CHECK(err_code);

	err_code = timer_create(TIMER_APP_SEC_TIMER, TIMERS_SECOND(1), (callback_t)app_sec_timer_handler );
	APP_ERROR_CHECK(err_code);
	err_code = timer_start(TIMER_APP_SEC_TIMER);
	APP_ERROR_CHECK(err_code);
	err_code = timer_create(TIMER_APP_MSEC_TIMER, TIMERS_MILLISECOND(100), (callback_t)app_msec_timer_handler );
	APP_ERROR_CHECK(err_code);
	err_code = timer_start(TIMER_APP_MSEC_TIMER);
	APP_ERROR_CHECK(err_code);

	APP_BEEP_SINGLE;

	return;
}

/********************************************************************************
 *
 ********************************************************************************/

void application_init_prew_state( app_state_t app_new_state )
{
	if( app_prew_state == app_new_state )return;

	switch( app_prew_state )
	{
		case APP_START:
		{
			break;
		}
		case APP_STAND_BY:
		{
			break;
		}
		default:
		{
			break;
		}
	}

	return;
}


void application_init_new_state( app_state_t app_new_state )
{
	if( app_prew_state == app_new_state )return;

	app_push_btn_time = 0; //всегда очищаем время нажатия, при переходе между режимами
	app_last_btn_push = NO_ONE_BUTTON;
	
	switch( app_new_state )
	{
		case APP_START:
		{
			break;
		}
		case APP_STAND_BY:
		{
			//очищаем все режимы
			app_flags.b_keep_warm_en = 0;
			app_flags.b_boiling_en = 0;
			app_flags.b_warm_en = 0;
			boiling_set_temp = 0;
			break;
		}
		case APP_CONFIG_BOOLING:
		{
			app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			break;
		}
		case APP_CONFIG_WARM:
		{
			app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			break;
		}
		case APP_PAIRING:
		{
			app_timeout_timers_restart(APP_PAIRING_TIMEOUT_S);
			break;
		}
		case APP_BOILING_PROC:
		{
			app_show_boiling_temp = false;
			app_flags.b_boiling_complete = 0;
			app_flags.b_boiling_prev = 0;
			boiling_temp_upcount_flag = true;
			boiling_ind_temp = temp_get_val();
			boiling_min_time_downcounter_s = APP_BOILING_MIN_TIME_S;
			boilig_complete_ind_time_downcounter_s = APP_BOILING_COMPLETE_IND_TIME_S;
			break;
		}
		case APP_WARM_PROC:
		{
//			app_sec_timer_reset();										//сброс таймера для отсчета времени подогрева
//			keep_warm_enable = true;									//флаг разрешения подогрева
			app_flags.b_keep_wrm_boost_cmplt = 0;						//флаг зашершения выхода на заданную температуру
			app_flags.b_keep_wrm_boost_cmplt_prew = 0;					//предъидущее значение флага зашершения выхода на заданную температуру(используется для подачи звукового сигнала)
			keep_warm_time_downcounter_s = APP_KEEPWARM_MAX_TIME_S;		//время до окончания режима поддеражания
//			keep_warm_temp_set_time_downcounter_s = 0;					//время индикации изменения уставки
			keep_warm_ctrl_type = keep_warm_get_ctrl_type(  temp_get_val(), boiling_set_temp );
			keep_warm_ctrl_type_prew = keep_warm_ctrl_type;
			boost_proc_init();
			heating_force_off();
			break;
		}
		case APP_KEEPWARM_PROC:
		{
//			app_sec_timer_reset();										//сброс таймера для отсчета времени подогрева
//			keep_warm_enable = true;									//флаг разрешения подогрева
			app_flags.b_keep_wrm_boost_cmplt = 0;						//флаг зашершения выхода на заданную температуру
			app_flags.b_keep_wrm_boost_cmplt_prew = 0;					//предъидущее значение флага зашершения выхода на заданную температуру(используется для подачи звукового сигнала)
			keep_warm_time_downcounter_s = APP_KEEPWARM_MAX_TIME_S;		//время до окончания режима поддеражания
//			keep_warm_temp_set_time_downcounter_s = 0;					//время индикации изменения уставки
			keep_warm_ctrl_type = keep_warm_get_ctrl_type(  temp_get_val(), boiling_set_temp );
			keep_warm_ctrl_type_prew = keep_warm_ctrl_type;
			boost_proc_init();
			heating_force_off();
			break;
		}
		case APP_NO_KETTLE:
		{
			//очищаем все режимы
			app_flags.b_keep_warm_en = 0;
			app_flags.b_boiling_en = 0;
			app_flags.b_warm_en = 0;
			boiling_set_temp = 0;

			app_show_boiling_temp = false;
			app_timeout_timers_restart(APP_NO_KETTLE_IND_TIMEOUT_S);
			break;
		}
		case APP_SOUND_CTRL:
		{
			sound_ctrl_leds_time_ms = APP_SOUND_BLINK_TIME_S;
			break;
		}
		case APP_TEST_LED:
		{
			app_last_btn_push = NO_ONE_BUTTON;
			break;
		}
		case APP_TEST_REL:
		{
			app_timeout_timers_restart(APP_TEST_REL_POWER_ON_TIME_S);
			app_last_btn_push = NO_ONE_BUTTON;
			break;
		}
		case APP_TEST_TEMP:
		{
			app_last_btn_push = NO_ONE_BUTTON;
			break;
		}
		default:
		{
			break;
		}
	}

	app_prew_state = app_new_state;

	return;
}

/********************************************************************************
 *
 ********************************************************************************/
void application_process( void )
{
	uint32_t err_code;
	
	//считываем данные с клавиатуры
	for(uint8_t i=0; i<KEYB_BUTTON_COUNT;++i)
	{
		err_code = keyb_read_data(i, &app_keyb_data[i]);
		APP_ERROR_CHECK(err_code);
	}
	app_boiling_temp_update();
	app_update_leds();

	application_init_new_state( app_state );	//выполняет работу при изменении состояния state mashine

	switch(app_state)
	{
		case APP_START:
		{
			appl_show_start();
			//work
			heating_force_off();
			//transition
			if( app_flags.b_simple_timeout ){
				app_state = APP_STAND_BY;
			}
			break;
		}
		case APP_STAND_BY:
		{
			//indication
			appl_show_standby();
			//work
			heating_force_off();
			//проверяем отпускание всех кнопок
			APP_UNPRESS_ALL_BTN;
			if(app_flags.b_block_panel == 1) break;
			//анализ клавиатуры
			if(app_flags.b_waiting_unpress_btn == 0) //проверка на блокировку клавиатуры
			{
				if(app_keyb_data[KEY_70_TEMP].pressed_time_ms >= APP_ENTER_PAIRING_STATE_TIME_MS)
				{ //предварительно не анализировали это состояние
					if( app_push_btn_time == 0 && app_flags.b_sound_en == 1 ){
						err_code = buz_reset_beeps();
						APP_ERROR_CHECK(err_code);
						err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
						APP_ERROR_CHECK(err_code);
						err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
						APP_ERROR_CHECK(err_code);
						err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
						APP_ERROR_CHECK(err_code);
					}
					//записываем сколько времении нажимали на клавиатуру
					app_state = APP_PAIRING;
				}
				if(app_keyb_data[KEY_95_TEMP].pressed_time_ms >= APP_ENTER_UNPAIRING_STATE_TIME_MS)
				{
					APP_BEEP_L_SINGLE; //подаем длинный сигнал на анпэйринг
					app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
					app_flags.b_unpairing = 1; //выставляем флаг unparing
				}
				if( app_keyb_data[KEY_BOILING].event_press == KEYB_EVENT_CAPTURED )
				{ //переход в режим настроек кипячения
					APP_BEEP_SINGLE;
					app_flags.b_boiling_en = 1;
					app_state = APP_CONFIG_BOOLING;
				}
				if( app_keyb_data[KEY_HEAT].pressed_time_ms >= APP_ENTER_TEST_STATE_TIME_MS )
				{ //переход в режим настроек кипячения
					APP_BEEP_SINGLE;
					app_state = APP_TEST_LED;
				}
				if( app_keyb_data[KEY_HEAT].event_press == KEYB_EVENT_CAPTURED )
				{
					APP_BEEP_SINGLE;
					app_last_btn_push = KEY_HEAT;
				}
				if( app_keyb_data[KEY_HEAT].event_release == KEYB_EVENT_CAPTURED )
				{
					if(app_last_btn_push == KEY_HEAT){
						//если была нажата кнопка KEY_HEAT
						app_flags.b_warm_en = 1;
						boiling_set_temp = APP_HEATING_TEMP_C;
						app_state = APP_CONFIG_WARM;
					} else {
						
					}
				}
			}
			if( temp_get_val() < APP_TEMP_NO_KETTLE_C ){
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}

				app_state = APP_NO_KETTLE;
				break;
			}
			break;
		}
		case APP_CONFIG_BOOLING:
		{
			//indication
			appl_show_config();
			//work
			heating_force_off();
			//transition
			if( app_flags.b_simple_timeout ){
				APP_BEEP_SINGLE;
				app_state = APP_BOILING_PROC;
			}
			if(app_keyb_data[KEY_BOILING].event_press == KEYB_EVENT_CAPTURED)
			{ //нажата кнопка "кипячение"
				APP_BEEP_SINGLE; //подаем звуковой сигнал
				app_state = APP_STAND_BY; //переходим в режим ожидания
			}
			if(app_keyb_data[KEY_HEAT].event_press == KEYB_EVENT_CAPTURED)
			{ //нажата кнопка "нагрева
				APP_BEEP_SINGLE; //подаем одиночный звуковой сигнал
				app_flags.b_warm_en = 1; //включаем режим "подогрева"
				app_flags.b_boiling_en = 0; //выключаем режим "кипячение"
				app_state = APP_CONFIG_WARM; //переходим в режим настройки "кипячения"
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S); //сбрасываем таймер автоперехода
			}
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_state = APP_BOILING_PROC;
			}
			if( app_keyb_data[KEY_40_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE; //подаем одиночный звуковой сигнал
				app_cnfg_heat_temp(40);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_55_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(55);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_70_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(70);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_85_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(85);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_95_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(95);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( temp_get_val() < APP_TEMP_NO_KETTLE_C ){
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}
				app_state = APP_NO_KETTLE;
				break;
			}
			break;
		}
		case APP_CONFIG_WARM:
		{
			//indication
			appl_show_config();
			//work
			heating_force_off();
			//transition
			if( app_flags.b_simple_timeout ){
				APP_BEEP_SINGLE;
				if(boiling_set_temp == APP_HEATING_TEMP_C){
					app_state = APP_STAND_BY;
				} else{
					app_state = APP_WARM_PROC;
				}
			}
			if(app_keyb_data[KEY_BOILING].event_press == KEYB_EVENT_CAPTURED)
			{ //нажата кнопка "кипячение"
				APP_BEEP_SINGLE; //подаем одиночный звуковой сигнал
				app_flags.b_warm_en = 0; //выключаем режим "подогрева"
				app_flags.b_boiling_en = 1; //включаем режим "кипячение"
				app_state = APP_CONFIG_BOOLING; //переходим в режим настройки "кипячения"
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S); //сбрасываем таймер автоперехода
			}
			if(app_keyb_data[KEY_HEAT].event_press == KEYB_EVENT_CAPTURED)
			{
				APP_BEEP_SINGLE; //подаем звуковой сигнал
				app_state = APP_STAND_BY; //переходим в режим ожидания
			}
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				//если выбрали температуру, какую необходимо будет поддерживать
				if(boiling_set_temp != APP_HEATING_TEMP_C){
					APP_BEEP_SINGLE; //подаем одиночный звуковой сигнал
					app_state = APP_WARM_PROC; //переходим в режим подогрева
				}
			}
			if( app_keyb_data[KEY_40_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE; //подаем одиночный звуковой сигнал
				app_cnfg_heat_temp(40);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_55_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(55);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_70_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(70);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_85_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(85);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( app_keyb_data[KEY_95_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(95);
				//сбрасываем таймер автоперехода
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			if( temp_get_val() < APP_TEMP_NO_KETTLE_C ){
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}
				app_state = APP_NO_KETTLE;
				break;
			}
			break;
		}
		case APP_BOILING_PROC:
		{
			//indication
			appl_show_boiling();
			//work
			if(	( temp_is_water_boil() ) //если температура медленно ростет
				&&( 0 == boiling_min_time_downcounter_s )) //и кончилось время кипения
			{
				app_flags.b_boiling_complete = 1;
			}
			if( ( app_flags.b_boiling_complete == 1 )
				&& ( app_flags.b_boiling_prev == 0 ) )
			{
				app_show_boiling_temp = true;			//установим флаг показывать температуру кипения вместо реальной
				boilig_temp_update_upcounter_s = 0;		//установим счетчик обновления температуры в 0
				boiling_temp_update_flag = false;		//скинем флаг обновления температуры
				boiling_complete_leds_time_ms = APP_BOILING_BLINK_TIME_S; //загружаем время для мигания свеотдиодами

				//звуковая индикация завершения кипечения
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}
			}
			app_flags.b_boiling_prev = app_flags.b_boiling_complete;
			
			if( app_flags.b_boiling_complete == 1 ){
				heating_force_off();
				appl_show_final_booling();
			}else{
				heating_force_on(HEATER_MAX_PWM_DUTY_CICLE);
			}
			if( app_keyb_data[KEY_40_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE; //подаем одиночный звуковой сигнал
				app_cnfg_heat_temp(40);
			}
			if( app_keyb_data[KEY_55_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(55);
			}
			if( app_keyb_data[KEY_70_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(70);
			}
			if( app_keyb_data[KEY_85_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(85);
			}
			if( app_keyb_data[KEY_95_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_cnfg_heat_temp(95);
			}

			//transition
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_state = APP_STAND_BY;
			}
			if( temp_get_val() < APP_TEMP_NO_KETTLE_C ){
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}
				app_state = APP_NO_KETTLE;
				break;
			}
			if( temp_is_empty_kettle() ){
				heating_force_off();
				app_state	= APP_EMPTY_KETTLE;
			}
			if( ( 1 == app_flags.b_boiling_complete )
				&& ( 0 == boilig_complete_ind_time_downcounter_s ) )
			{
				if( 1 == app_flags.b_keep_warm_en ){
					app_state	= APP_KEEPWARM_PROC;
				}else{
					app_state = APP_STAND_BY;
				}
			}
			//TODO::
			//сделать проверку на долгое время включенного нагревателя
			break;
		}
		case APP_WARM_PROC:
		{
			//indication
			app_show_warm();
			//work
			if( keep_warm_ctrl_type_prew != keep_warm_ctrl_type )
			{
				//если изменился алгоритм поддержания разгон/регулятор
				//инициализируем новый алгоритм
				if( keep_warm_ctrl_type == KEEP_WARM_CTRL_BOOST )
				{
					boost_proc_init();
				}else{
					heating_force_off();
				}
				keep_warm_ctrl_type_prew = keep_warm_ctrl_type;
			}
				if(boiling_set_temp < 80) { //если заданная температура меньше чем 80 градусов
					heating_process_on( simple_reg( temp_get_val() , boiling_set_temp, 3 ) );
				} else {
					heating_process_on( simple_reg( temp_get_val() , boiling_set_temp, 5 ) );
				}
			}
			if( fabs( boiling_set_temp - temp_get_val() ) < APP_KEEPWARM_TEMP_DIFFERENCE_BOOST_IS_OVER_C )
			{
				//установим флаг выхода на заданную температуру
				app_flags.b_keep_wrm_boost_cmplt = 1;
			}
			if(	( 0 == app_flags.b_keep_wrm_boost_cmplt_prew )
				&&( 1 == app_flags.b_keep_wrm_boost_cmplt ) )
			{
				app_flags.b_keep_wrm_boost_cmplt_prew = app_flags.b_keep_wrm_boost_cmplt;
			}

			//controll

			//transition
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				heating_force_off();	//если выходим из режима обязательно выключить нагреватель
				APP_BEEP_SINGLE;
				app_state = APP_STAND_BY;
			}
			if( temp_get_val() < APP_TEMP_NO_KETTLE_C )
			{
				//чайник снят с подставки
				heating_force_off();	//если выходим из режима обязательно выключить нагреватель
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}
				app_state = APP_NO_KETTLE;
				break;
			}
			if( ( temp_is_empty_kettle() == true )
				|| ( ( app_flags.b_keep_wrm_boost_cmplt == 1 ) && ( temp_get_val() > ( boiling_set_temp + APP_OVERHEAT_NO_KETTLE_C ) ) ) )
			{
				//чайник без воды
				heating_force_off();	//если выходим из режима обязательно выключить нагреватель
				app_state	= APP_EMPTY_KETTLE;
			}
			if( temp_get_val() >= boiling_set_temp )
			{
				//звуковая индикация завершения подогрева
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}						
				app_state = APP_KEEPWARM_PROC;
			}
			break;
		}
		case APP_KEEPWARM_PROC:
		{
			//indication
			appl_show_keepwarm();
			//work
			if( keep_warm_ctrl_type_prew != keep_warm_ctrl_type )
			{
				//если изменился алгоритм поддержания разгон/регулятор
				//инициализируем новый алгоритм
				if( keep_warm_ctrl_type == KEEP_WARM_CTRL_BOOST )
				{
					boost_proc_init();
				}else{
					heating_force_off();
				}
				keep_warm_ctrl_type_prew = keep_warm_ctrl_type;
			}
			if( keep_warm_ctrl_type == KEEP_WARM_CTRL_BOOST ){
				//работа алгоритм разгона
				boost_state = boost_proc( temp_get_float_val(), (float)boiling_set_temp );
				if( boost_state == BOOST_FINISHED ){
					keep_warm_ctrl_type = KEEP_WARM_CTRL_REG;
				}
			}else{
				//работа алгоритм регулятор
				keep_warm_ctrl_type = keep_warm_get_ctrl_type(  temp_get_val(), boiling_set_temp );
				if(boiling_set_temp < 80) { //если заданная температура меньше чем 80 градусов
					heating_process_on( simple_reg( temp_get_val() , boiling_set_temp, 3 ) );
				}
				else if(boiling_set_temp < 90){
					heating_process_on( simple_reg( temp_get_val() , boiling_set_temp, 4 ) );
				}
				else{
					heating_process_on( simple_reg( temp_get_val() , boiling_set_temp, 5 ) );
				}
			}
			if( fabs( boiling_set_temp - temp_get_val() ) < APP_KEEPWARM_TEMP_DIFFERENCE_BOOST_IS_OVER_C )
			{
				//установим флаг выхода на заданную температуру
				app_flags.b_keep_wrm_boost_cmplt = 1;
			}
			if(	( 0 == app_flags.b_keep_wrm_boost_cmplt_prew )
				&&( 1 == app_flags.b_keep_wrm_boost_cmplt ) )
			{
				app_flags.b_keep_wrm_boost_cmplt_prew = app_flags.b_keep_wrm_boost_cmplt;
			}

			//controll

			//transition
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				heating_force_off();	//если выходим из режима обязательно выключить нагреватель
				APP_BEEP_SINGLE;
				app_state = APP_STAND_BY;
			}
			if( temp_get_val() < APP_TEMP_NO_KETTLE_C )
			{
				//чайник снят с подставки
				heating_force_off();	//если выходим из режима обязательно выключить нагреватель
				if( app_flags.b_sound_en == 1 ){
					err_code = buz_reset_beeps();
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
					err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
					APP_ERROR_CHECK(err_code);
				}
				app_state = APP_NO_KETTLE;
				break;
			}
			if( ( temp_is_empty_kettle() == true )
				|| ( ( app_flags.b_keep_wrm_boost_cmplt == 1 ) && ( temp_get_val() > ( boiling_set_temp + APP_OVERHEAT_NO_KETTLE_C ) ) ) )
			{
				//чайник без воды
				heating_force_off();	//если выходим из режима обязательно выключить нагреватель
				app_state	= APP_EMPTY_KETTLE;
			}
			if( 0 == keep_warm_time_downcounter_s ){
				//закончено время подогрева
				app_state	= APP_STAND_BY;
				APP_BEEP_SINGLE;
			}
			break;
		}
		case APP_NO_KETTLE:
		{
			//indication
			if( app_flags.b_simple_timeout ){
				appl_show_no_kettle(false);
			}else{
				appl_show_no_kettle(true);
			}
			//work
			heating_force_off();
			//transition
			if( temp_get_val() > APP_TEMP_NO_KETTLE_C ){
				app_state = APP_STAND_BY;
			}
			//проверяем отпускание всех кнопок
			APP_UNPRESS_ALL_BTN;
			//анализ клавиатуры
			if(app_flags.b_waiting_unpress_btn == 0) //проверка на блокировку клавиатуры
			{
				if(app_keyb_data[KEY_70_TEMP].pressed_time_ms >= APP_ENTER_PAIRING_STATE_TIME_MS)
				{ //предварительно не анализировали это состояние
					if( app_push_btn_time == 0 && app_flags.b_sound_en == 1 ){
						err_code = buz_reset_beeps();
						APP_ERROR_CHECK(err_code);
						err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
						APP_ERROR_CHECK(err_code);
						err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
						APP_ERROR_CHECK(err_code);
						err_code = buz_add_beep(APP_SHORT_BEEP_MS, APP_BEEP_PAUSE_MS, BUZ_BEEP_MULTI);
						APP_ERROR_CHECK(err_code);
					}
					//записываем сколько времении нажимали на клавиатуру
//					app_push_btn_time = app_keyb_data[KEY_70_TEMP].pressed_time_ms;
					app_state = APP_PAIRING;
				}
				if(app_keyb_data[KEY_95_TEMP].pressed_time_ms >= APP_ENTER_UNPAIRING_STATE_TIME_MS)
				{
					APP_BEEP_L_SINGLE; //подаем длинный сигнал на анпэйринг
					app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
//					app_push_btn_time = 0; //очищаем время зажатия клавиши
					app_flags.b_unpairing = 1; //выставляем флаг unparing
				}
//				if(app_keyb_data[KEY_70_TEMP].event_release == KEYB_EVENT_CAPTURED)
//				{//отжали кнопку пэйринга/анпэйринга
//					//анализируем время нажатия на клавиатуру
//					if(app_push_btn_time >= APP_ENTER_PAIRING_STATE_TIME_MS){
//						app_push_btn_time = 0;
//						app_state = APP_PAIRING;
//					}
//				}
//				if(app_keyb_data[KEY_ON_OFF].pressed_time_ms >= APP_ENTER_SOUND_STATE_TIME_MS)
//				{ //переход в режим настройки звука
//					app_flags.b_sound_en = (app_flags.b_sound_en == 1)? 0: 1;
//					APP_BEEP_SINGLE;
//					app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
//					app_state = APP_SOUND_CTRL;
//				}
			}
			break;
		}
		case APP_EMPTY_KETTLE:
		{
			//indication
			appl_show_empty_kettle();
			//work
			heating_force_off();
			//transition
			if( temp_get_val() < TEMP_KETTLE_NOT_EMPTY_C ){
				app_state	= APP_STAND_BY;
			}
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED ){
				APP_BEEP_SINGLE;
				app_state	= APP_STAND_BY;
			}
			if( temp_get_val() < APP_TEMP_NO_KETTLE_C ){
				app_state	= APP_NO_KETTLE;
			}
			break;
		}
		case APP_PAIRING:
		{
			//indication
			appl_show_pairing();
			//work
			heating_force_off();
			//waiting for R4S reset pairing_flag
			if( ( app_flags.b_simple_timeout == 1 ) ||
				( app_flags.b_pairing == 1 ) )
			{
				app_flags.b_pairing = 0;
				app_flags.b_waiting_unpress_btn = 1;
				app_state = APP_STAND_BY;
				break;
			}
			break;
		}
		case APP_SOUND_CTRL:
		{
			//indication
			appl_show_sound_ctrl((sound_ctrl_leds_time_ms/3)%9);
			//work
			heating_force_off();
			
			if(sound_ctrl_leds_time_ms == 0) app_state = APP_STAND_BY;
			break;
		}
		case APP_TEST_LED:
		{
			//indication
			app_show_test_led();
			//work
			heating_force_off(); //отключаем нагреватель
			APP_UNPRESS_ALL_BTN; //проверяем отпускание всех кнопок
			if(app_flags.b_waiting_unpress_btn == 1) break; //выходим, если блокировка клавиатуры
			//transition
			if( app_keyb_data[KEY_ON_OFF].pressed_time_ms >= APP_ENTER_TEST_STATE_TIME_MS )
			{
				APP_BEEP_SINGLE;
				app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
				app_state = APP_STAND_BY;
			}
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				if(app_last_btn_push == KEY_ON_OFF){
					app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
					app_state = APP_TEST_REL;
				} else {
					app_flags.b_clear_last_btn = 0; //очистка флага быстрого нажатия
					test_time_fast_click_ms = APP_BOILING_COMPLETE_IND_TIME_S;//запускаем таймер автообнуления клавиши
				}
				app_last_btn_push = KEY_ON_OFF;
			}
			if( app_keyb_data[KEY_HEAT].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				if(app_last_btn_push == KEY_ON_OFF){
					app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
					app_state = APP_TEST_TEMP;
				}
				app_last_btn_push = KEY_HEAT;
			}
			if( app_keyb_data[KEY_BOILING].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_last_btn_push = KEY_BOILING;
			}
			if( app_keyb_data[KEY_40_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_last_btn_push = KEY_40_TEMP;
			}
			if( app_keyb_data[KEY_55_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_last_btn_push = KEY_55_TEMP;
			}
			if( app_keyb_data[KEY_70_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_last_btn_push = KEY_70_TEMP;
			}
			if( app_keyb_data[KEY_85_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_last_btn_push = KEY_85_TEMP;
			}
			if( app_keyb_data[KEY_95_TEMP].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				app_last_btn_push = KEY_95_TEMP;
			}
			if((app_flags.b_clear_last_btn == 1) && (app_last_btn_push == KEY_ON_OFF)){
				app_flags.b_clear_last_btn = 0;
				app_last_btn_push = NO_ONE_BUTTON; //очищаем прошлую нажатую клавишу
			}

			break;
		}
		case APP_TEST_REL:
		{
			//indication
			app_show_test_rel();
			//work
			heating_force_on(HEATER_MAX_PWM_DUTY_CICLE);
			APP_UNPRESS_ALL_BTN; //проверяем отпускание всех кнопок
			if(app_flags.b_waiting_unpress_btn == 1) break; //выходим, если блокировка клавиатуры
			//transition
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				if(app_last_btn_push == KEY_ON_OFF){
					app_state = APP_TEST_LED;
				} else {
					app_flags.b_clear_last_btn = 0; //очистка флага быстрого нажатия
					test_time_fast_click_ms = APP_BOILING_COMPLETE_IND_TIME_S;//запускаем таймер автообнуления клавиши
				}
				app_last_btn_push = KEY_ON_OFF;
			}
			if((app_flags.b_clear_last_btn == 1) && (app_last_btn_push == KEY_ON_OFF)){
				app_flags.b_clear_last_btn = 0;
				app_last_btn_push = NO_ONE_BUTTON; //очищаем прошлую нажатую клавишу
			}
			if( app_flags.b_simple_timeout ){
				app_state = APP_STAND_BY;
			}
			break;
		}
		case APP_TEST_TEMP:
		{
			//indication
			app_show_test_temp();
			//work
			heating_force_off();
			APP_UNPRESS_ALL_BTN; //проверяем отпускание всех кнопок
			if(app_flags.b_waiting_unpress_btn == 1) break; //выходим, если блокировка клавиатуры
			//transition
			if( app_keyb_data[KEY_ON_OFF].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				if(app_last_btn_push == KEY_ON_OFF){
					app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
					app_state = APP_TEST_TEMP;
				} else {
					app_flags.b_clear_last_btn = 0; //очистка флага быстрого нажатия
					test_time_fast_click_ms = APP_BOILING_COMPLETE_IND_TIME_S;//запускаем таймер автообнуления клавиши
				}
				app_last_btn_push = KEY_ON_OFF;
			}
			if( app_keyb_data[KEY_HEAT].event_press == KEYB_EVENT_CAPTURED )
			{
				APP_BEEP_SINGLE;
				if(app_last_btn_push == KEY_ON_OFF){
					app_flags.b_waiting_unpress_btn = 1; //ожидаем отпускания всех кнопок
					app_state = APP_TEST_LED;
				}
				app_last_btn_push = KEY_HEAT;
			}
			if((app_flags.b_clear_last_btn == 1) && (app_last_btn_push == KEY_ON_OFF)){
				app_flags.b_clear_last_btn = 0;
				app_last_btn_push = NO_ONE_BUTTON; //очищаем прошлую нажатую клавишу
			}
			break;
		}
		default:
		{
			app_state = APP_STAND_BY;
			break;
		}
	}

	application_init_prew_state( app_state );	//выполняет работу при изменении состояния state mashine
	return;
}
/********************************************************************************
 *
 ********************************************************************************/

/********************************************************************************
 *
 ********************************************************************************/
/**
 * 	описание в application_api.h
 */
uint16_t API_GetVersion(void)
{
	return FIRMWARE_VER;
}
/**
 * 	описание в application_api.h
*/
uint8_t API_GetState(void)
{
	switch(app_state)
	{
		case APP_START:
		case APP_TEST_LED:
		case APP_TEST_REL:
		case APP_TEST_TEMP:
		case APP_SOUND_CTRL: 
		{
			return APP_API_NOT_SUPPORT_STATE;
		}
		case APP_BOILING_PROC:
		case APP_WARM_PROC:
		case APP_KEEPWARM_PROC:
		{
			return APP_API_WORK_STATE;
		}
		case APP_STAND_BY: 
		case APP_NO_KETTLE:
		case APP_EMPTY_KETTLE:
		case APP_ERROR:
		case APP_CONFIG_BOOLING:
		case APP_CONFIG_WARM:
		{
			return APP_API_STAND_BY_STATE;
		}
		case APP_PAIRING: 
		{
			return APP_API_PAIRING_STATE;
		}
	}
	return APP_API_NOT_SUPPORT_STATE;
}
/**
 * 	описание в application_api.h
*/
bool API_IsUnpairing(void)
{
	return (app_flags.b_unpairing == 1)? true: false;
}
/**
 * 	описание в application_api.h
*/
void API_ClrUnpairing(void)
{
	app_flags.b_unpairing = 0;
	return;
}
bool api_go_to_stand_by(void)
{
	if(	(app_state != APP_TEST_LED) &&
		(app_state != APP_TEST_REL) &&
		(app_state != APP_TEST_TEMP) &&
		(app_state != APP_NO_KETTLE) &&
		(app_state != APP_ERROR))
	{
		app_state = APP_STAND_BY;
		return true;
	}
	return false;
}
void api_set_connection_flag(void)
{
	app_flags.b_pairing = 1;
	return;
}
bool api_set_program(uint8_t num_prog)
{
	if(num_prog > 1) return false;
	switch(app_state)
	{
		case APP_START:
		case APP_TEST_LED:
		case APP_TEST_REL:
		case APP_TEST_TEMP:
		case APP_EMPTY_KETTLE:
		case APP_NO_KETTLE:
		case APP_SOUND_CTRL: 
		case APP_BOILING_PROC:
		case APP_WARM_PROC:
		case APP_KEEPWARM_PROC:
		case APP_ERROR:
		case APP_PAIRING: 
		{
			return false;
		}
		case APP_STAND_BY: 
		case APP_CONFIG_BOOLING:
		case APP_CONFIG_WARM:
		{
			app_flags.b_keep_warm_en = 0;
			app_flags.b_boiling_en = 0;
			app_flags.b_warm_en = 0;
			boiling_set_temp = 0;
			if(num_prog == 0){ //запрос входа у режим "кипячение"
				app_flags.b_boiling_en = 1; //выставляем бит входа в режим кипячения
				app_state = APP_CONFIG_BOOLING;
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			} else{
				app_flags.b_warm_en = 1; //выставляем бит входа в режим нагрева
				app_state = APP_CONFIG_WARM;
				app_timeout_timers_restart(APP_AUTOSTART_TIMEOUT_S);
			}
			return true;
		}
	}
	return false;
}
bool api_set_temp(uint8_t temp)
{
	uint8_t api_temp = 0;
	switch(temp)
	{
		case 0: api_temp = 0; break;
		case 1: api_temp = 40; break;
		case 2: api_temp = 55; break;
		case 3: api_temp = 70; break;
		case 4: api_temp = 85; break;
		case 5: api_temp = 95; break;
		default : return false;
	}
	switch(app_state)
	{
		case APP_START:
		case APP_TEST_LED:
		case APP_TEST_REL:
		case APP_TEST_TEMP:
		case APP_EMPTY_KETTLE:
		case APP_NO_KETTLE:
		case APP_SOUND_CTRL: 
		case APP_BOILING_PROC:
		case APP_WARM_PROC:
		case APP_KEEPWARM_PROC:
		case APP_ERROR:
		case APP_PAIRING: 
		case APP_STAND_BY: 
		{
			return false;
		}
		case APP_CONFIG_BOOLING:
		case APP_CONFIG_WARM:
		{
			boiling_set_temp = api_temp;
			if(boiling_set_temp>0) app_flags.b_keep_warm_en = 1; //нужно поддержать температуру
			return true;
		}
	}
	//неверный стэйт
	return false;
}
bool api_go_work(void)
{
	switch(app_state)
	{
		case APP_START:
		case APP_TEST_LED:
		case APP_TEST_REL:
		case APP_TEST_TEMP:
		case APP_EMPTY_KETTLE:
		case APP_NO_KETTLE:
		case APP_SOUND_CTRL: 
		case APP_BOILING_PROC:
		case APP_WARM_PROC:
		case APP_KEEPWARM_PROC:
		case APP_ERROR:
		case APP_PAIRING: 
		case APP_STAND_BY: 
		{
			return false;
		}
		case APP_CONFIG_BOOLING:
		{
			app_state = APP_BOILING_PROC;
			return true;
		}
		case APP_CONFIG_WARM:
		{
			if( (boiling_set_temp != 40) &&
				(boiling_set_temp != 55) &&
				(boiling_set_temp != 70) &&
				(boiling_set_temp != 85) &&
				(boiling_set_temp != 95) )
			{
				return false;
			}
			app_state = APP_WARM_PROC; //переходим в режим подогрева
			return true;
		}
	}
	//неверный стэйт
	return false;	
}
Made on
Tilda