/**
flat_air_control_ep
*/
#define MY_ENV_MYHW 1
// run on my My Hardware Project
#define MY_ENV_WOKWI 2
// for running in simulation env at https://wokwi.com/projects/382904758010920961
// there only pico NOT pico w is supported
#define MY_ENV_MYHW_DEV 3
// run on bare hardware /w buttons and led only
//#define MY_ENV MY_ENV_MYHW
//OR
#define MY_ENV MY_ENV_WOKWI
//OR
//#define MY_ENV MY_ENV_MYHW_DEV
#define MY_LED_DBG_ON 1
#define MY_LED_DBG_OFF 0
//#define MY_LED_DBG MY_LED_DBG_ON
#define MY_LED_DBG MY_LED_DBG_OFF
//for DBG messages, PICO onboard led blinking etc.
#include <stdio.h>
#include <limits.h>
#include "string.h"
#include "pico.h"
#include "pico/stdlib.h"
#include "hardware/timer.h"
#include "hardware/gpio.h"
#if MY_ENV == MY_ENV_MYHW
#include "pico/cyw43_arch.h"
#include "LCD_2in.h"
#include "DEV_Config.h"
#include "GUI_Paint.h"
#endif
#if MY_ENV == MY_ENV_MYHW_DEV
#include "pico/cyw43_arch.h"
#endif
//debounce button events:
// for falling ctrl button
absolute_time_t timeout_time_ctrl_btn=0;
absolute_time_t current_time_ctrl_btn=0;
// for falling bathroom button
absolute_time_t timeout_time_bathroom_btn=0;
absolute_time_t current_time_bathroom_btn=0;
// for falling reset button:
absolute_time_t timeout_time_rst_btn=0;
absolute_time_t current_time_rst_btn=0;
// for falling shift function button:
absolute_time_t timeout_time_shift_btn=0;
absolute_time_t current_time_shift_btn=0;
volatile alarm_id_t alarm_verify_state_ctrl_btn=0;
volatile alarm_id_t alarm_verify_state_bathroom_btn=0;
volatile alarm_id_t alarm_verify_state_rst_btn=0;
volatile alarm_id_t alarm_verify_state_shift_btn=0;
// time measuring for ongoing alarm:
absolute_time_t active_alarm_termination_time=0;
absolute_time_t current_time=0;
// prod.:
// interval time is 5 min = 15 x 60 * 1000 *1000 us = 300000000
// interval time is 15 min = 15 x 60 * 1000 *1000 us = 900000000
const absolute_time_t on_time_btn_actuation=900000000;
//debugging: 5s
//const uint32_t on_time_btn_actuation=5000;
uint8_t fwd_time_mp=180;
// ex. below w/ interval time of 15 min ( on_time_btn_actuation = 900000000)
// 90 means 10 seconds on_time_btn_actuation
// 40 means 20 seconds on_time_btn_actuation
//uint8_t fwd_time_mp=45;
// 180 means 5 seconds on_time_btn_actuation
//uint8_t fwd_time_mp=180;
//final extra time is 1 min = 1 x 60 * 1000 *1000 us = 60000000
const absolute_time_t final_extratime=60000000;
volatile uint8_t current_open_count_btn_actuations=0; //Note: current_open_count_btn_actuations=0 means in additional:
//Final overlaping time aka "final_extratime" is probably going on.
volatile alarm_id_t active_alarm = 0;
bool volatile is_before_first_alarm_of_ctrl_btn_actuation_cascade=false;
// - needed for doing initial half interval time waiting on endpoint_state 1
bool volatile is_before_last_alarm_of_ctrl_btn_actuation_cascade=false;
bool volatile ist_final_extratime=false;
bool volatile append_rst_final_extratime=false;
bool volatile ext_bathroom_rst=false;
bool volatile is_self_btn_actuation=false;
bool volatile shift_enabled=false;
#if MY_LED_DBG == MY_LED_DBG_ON
#if MY_ENV == MY_ENV_WOKWI
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
#endif
#if MY_ENV == MY_ENV_MYHW || MY_ENV == MY_ENV_MYHW_DEV
const uint LED_PIN = CYW43_WL_GPIO_LED_PIN;
#endif
#endif
bool volatile led_state=false;
/*This gadgets states:
endpoint_state=0 ...remote control ready
endpoint_state=1 ...local control activated ( - the gadget itself rules now)
endpoint_state=2 ...external control goes on ( flat's bathroom btn was touched) -> must wait till it is over
endpoint_state=3 ...permanent off-mode
endpoint_state=4 ...temporary off-mode
*/
uint8_t endpoint_state=0;
void alter_DBG_LED() {
#if MY_LED_DBG == MY_LED_DBG_ON
led_state = !led_state;
#if MY_ENV == MY_ENV_WOKWI
gpio_put(LED_PIN, led_state);
#endif
#if MY_ENV == MY_ENV_MYHW || MY_ENV == MY_ENV_MYHW_DEV
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_state);
#endif
#endif
}
void actuate_bathroom_button_twin() {
is_self_btn_actuation = true; //mask self actuation
gpio_put(20,true);
// Just to be sure xD
sleep_ms(1000);
gpio_put(20,false);
is_self_btn_actuation = false; //demask
}
int64_t alarm_callback_verify_state_ctrl_btn(alarm_id_t id, void *user_data) {
alarm_verify_state_ctrl_btn = 0;
if (gpio_get(14)==false){
if (!(ist_final_extratime==true)){
if (!(append_rst_final_extratime==true)){
switch (endpoint_state){
case 0:
if (shift_enabled){
current_open_count_btn_actuations=1;
endpoint_state=4;
alter_DBG_LED();
}else{
//mark for inital half time
is_before_first_alarm_of_ctrl_btn_actuation_cascade=true;
endpoint_state=1;
alter_DBG_LED();
#if MY_ENV == MY_ENV_WOKWI
printf("current_open_count_btn_actuations is %d\n", current_open_count_btn_actuations);
#endif
current_open_count_btn_actuations=current_open_count_btn_actuations+1;
}
break;
case 1:
if (shift_enabled){
current_open_count_btn_actuations=1;
endpoint_state=4;
alter_DBG_LED();
}else{
current_open_count_btn_actuations=current_open_count_btn_actuations+1;
}
break;
case 3:
if (shift_enabled){
current_open_count_btn_actuations=1;
endpoint_state=4;
alter_DBG_LED();
}
break;
case 4:
if (shift_enabled){
current_open_count_btn_actuations=current_open_count_btn_actuations+1;
}
break;
}
}
}
#if MY_LED_DBG == MY_LED_DBG_ON
printf("interrupt worked\n");
#endif
}
return 0;
}
void inter_ctrl_btn(uint32_t events) {
current_time_ctrl_btn = get_absolute_time();
if (absolute_time_diff_us(current_time_ctrl_btn,timeout_time_ctrl_btn) < 0) {
timeout_time_ctrl_btn = make_timeout_time_ms(300);
alarm_verify_state_ctrl_btn=add_alarm_in_ms(50, alarm_callback_verify_state_ctrl_btn, NULL, false);
}
}
int64_t alarm_callback_verify_state_bathroom_btn(alarm_id_t id, void *user_data) {
alarm_verify_state_bathroom_btn = 0;
if (gpio_get(22)==true){
if (endpoint_state==1){
is_before_first_alarm_of_ctrl_btn_actuation_cascade=false; //reset for next EP State 1
is_before_last_alarm_of_ctrl_btn_actuation_cascade=false; //reset for next EP State 1
}
ext_bathroom_rst=true;
current_open_count_btn_actuations=1;
if (endpoint_state!=2) {
alter_DBG_LED();
}
endpoint_state=2;
// !!! NOT in prod:
//actuate_bathroom_button_twin();
// !!!
#if MY_LED_DBG == MY_LED_DBG_ON
printf("inter-br: open-cnt left with value of %d\n", current_open_count_btn_actuations);
#endif
}
return 0;
}
void inter_bathroom_btn(uint32_t events) {
current_time_bathroom_btn = get_absolute_time();
if (!(is_self_btn_actuation == true)){
if (absolute_time_diff_us(current_time_bathroom_btn,timeout_time_bathroom_btn) < 0) {
timeout_time_bathroom_btn = make_timeout_time_ms(300);
alarm_verify_state_bathroom_btn=add_alarm_in_ms(50, alarm_callback_verify_state_bathroom_btn, NULL, false);
}
}
}
int64_t alarm_callback_verify_state_rst_btn(alarm_id_t id, void *user_data) {
alarm_verify_state_rst_btn = 0;
if (gpio_get(16)==false){
switch (endpoint_state){
case 0:
if (shift_enabled){
shift_enabled=false;
endpoint_state=3;
alter_DBG_LED();
}
break;
case 1:
if (is_before_last_alarm_of_ctrl_btn_actuation_cascade==true) {
append_rst_final_extratime=true;
current_open_count_btn_actuations=1;
}else{
current_open_count_btn_actuations=0; //reset
}
is_before_last_alarm_of_ctrl_btn_actuation_cascade=false; //reset for next EP State 1
is_before_first_alarm_of_ctrl_btn_actuation_cascade=false; //reset for next EP State 1
if (shift_enabled){
shift_enabled=false;
endpoint_state=3;
alter_DBG_LED();
}else{
endpoint_state=0;
alter_DBG_LED();
}
#if MY_LED_DBG == MY_LED_DBG_ON
printf("inter-rst: open-cnt left with value of %d\n", current_open_count_btn_actuations);
#endif
break;
case 2:
break;
case 3:
shift_enabled=false;
endpoint_state=0;
alter_DBG_LED();
break;
case 4:
if (shift_enabled){
shift_enabled=false;
endpoint_state=3;
alter_DBG_LED();
}else{
endpoint_state=0;
alter_DBG_LED();
}
current_open_count_btn_actuations=1; //reset
break;
}
}
return 0;
}
void inter_rst_btn(uint32_t events) {
current_time_rst_btn = get_absolute_time();
if (absolute_time_diff_us(current_time_rst_btn,timeout_time_rst_btn) < 0) {
timeout_time_rst_btn = make_timeout_time_ms(300);
alarm_verify_state_rst_btn=add_alarm_in_ms(50, alarm_callback_verify_state_rst_btn, NULL, false);
}
}
int64_t alarm_callback_verify_state_shift_btn(alarm_id_t id, void *user_data) {
alarm_verify_state_shift_btn = 0;
if (gpio_get(5)==false){
if (shift_enabled==true) {
shift_enabled=false;
}else{
shift_enabled=true;
}
#if MY_LED_DBG == MY_LED_DBG_ON
printf("inter-shift is enabled");
#endif
}
return 0;
}
void inter_shift_btn(uint32_t events) {
current_time_shift_btn = get_absolute_time();
if (absolute_time_diff_us(current_time_shift_btn,timeout_time_shift_btn) < 0) {
timeout_time_shift_btn = make_timeout_time_ms(300);
alarm_verify_state_shift_btn=add_alarm_in_ms(50, alarm_callback_verify_state_shift_btn, NULL, false);
}
}
void interrupt_routine(uint gpio, uint32_t events) {
/*
"LEVEL LOW", // 0x1
"LEVEL HIGH", // 0x2
"EDGE FALL", // 0x4
"EDGE RISE" // 0x8
*/
if((gpio==14) && ((events & GPIO_IRQ_EDGE_FALL)==GPIO_IRQ_EDGE_FALL)) inter_ctrl_btn(events);
if((gpio==5) && ((events & GPIO_IRQ_EDGE_FALL)==GPIO_IRQ_EDGE_FALL)) inter_shift_btn(events);
if((gpio==16) && ((events & GPIO_IRQ_EDGE_FALL)==GPIO_IRQ_EDGE_FALL)) inter_rst_btn(events);
if((gpio==22) && ((events & GPIO_IRQ_EDGE_RISE)==GPIO_IRQ_EDGE_RISE)) inter_bathroom_btn(events);
}
int64_t alarm_callback(alarm_id_t id, void *user_data) {
#if MY_LED_DBG == MY_LED_DBG_ON
printf("Timer %d has fired!\n", (int) id);
#endif
active_alarm = 0;
if (ist_final_extratime==true){
ist_final_extratime=false; //reset
}else{
current_open_count_btn_actuations--;
}
#if MY_LED_DBG == MY_LED_DBG_ON
printf("alarm-cb: open-cnt left with value of %d\n", current_open_count_btn_actuations);
#endif
return 0;
}
void display_status() {
#if MY_ENV != MY_ENV_MYHW_DEV
char TimeToGo_s_str[100];
char timeToGo_suffix_str[80] = " mins to go";
double TimeToGo = 0.0;
double current_time_to_go_active_alarm = 0.0;
char Endpoint_State_str[50];
switch (endpoint_state){
case 0:
strcpy(Endpoint_State_str, "Remote control");
#if MY_ENV == MY_ENV_WOKWI
printf("%s\n",Endpoint_State_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(5, 50, Endpoint_State_str, &Font20, RED, WHITE );
#endif
if (active_alarm > 0){
current_time = get_absolute_time();
current_time_to_go_active_alarm = ((double) absolute_time_diff_us(current_time,active_alarm_termination_time))/1000000/60;
if (append_rst_final_extratime==true){
//treat already "touched button" from EP state 1 before - forced via reset button:
current_time_to_go_active_alarm=current_time_to_go_active_alarm + ((double) final_extratime)/fwd_time_mp/1000000/60;
}
TimeToGo = current_time_to_go_active_alarm;
sprintf(TimeToGo_s_str, "%.2f", TimeToGo);
strcat(TimeToGo_s_str, timeToGo_suffix_str);
#if MY_ENV == MY_ENV_WOKWI
printf("\n");
printf("%s\n",TimeToGo_s_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(20, 100, TimeToGo_s_str , &Font20, RED, WHITE );
#endif
}
break;
case 1:
strcpy(Endpoint_State_str, "Local control");
#if MY_ENV == MY_ENV_WOKWI
printf("%s\n",Endpoint_State_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(5, 50, Endpoint_State_str, &Font20, MAGENTA, WHITE );
#endif
if (active_alarm > 0){
//assert : (active_alarm_termination_time - current_time) >0)
current_time = get_absolute_time();
TimeToGo = ((double) absolute_time_diff_us(current_time,active_alarm_termination_time))/1000000/60;
switch (current_open_count_btn_actuations){
case 0:
// remaining time of current amount of final extra time
break;
case 1:
//prev. + additional full amount of final extra time
TimeToGo = TimeToGo + ((double) final_extratime)/((double) fwd_time_mp)/1000000/60;
break;
case 2 ... INT_MAX:
//prev. + additional regular intervals
TimeToGo = TimeToGo + ((double) current_open_count_btn_actuations-1)*on_time_btn_actuation/fwd_time_mp/1000000/60 + ((double) final_extratime)/fwd_time_mp/1000000/60;
break;
}
sprintf(TimeToGo_s_str, "%.2f", TimeToGo);
strcat(TimeToGo_s_str, timeToGo_suffix_str);
#if MY_ENV == MY_ENV_WOKWI
printf("\n");
printf("%s\n",TimeToGo_s_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(20, 100, TimeToGo_s_str, &Font20, MAGENTA, WHITE );
#endif
}
break;
case 2:
strcpy(Endpoint_State_str, "Ext. Bath BTN ctrl");
#if MY_ENV == MY_ENV_WOKWI
printf("%s\n",Endpoint_State_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(5, 50, Endpoint_State_str, &Font20, BLUE, WHITE );
#endif
if (active_alarm > 0){
current_time = get_absolute_time();
TimeToGo = ((double)absolute_time_diff_us(current_time,active_alarm_termination_time))/1000000/60;
sprintf(TimeToGo_s_str, "%.2f", TimeToGo);
strcat(TimeToGo_s_str, timeToGo_suffix_str);
#if MY_ENV == MY_ENV_WOKWI
printf("\n");
printf("%s\n",TimeToGo_s_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(20, 100, TimeToGo_s_str, &Font20, BLUE, WHITE );
#endif
}
break;
case 3:
strcpy(Endpoint_State_str, "Always Off-Mode");
#if MY_ENV == MY_ENV_WOKWI
printf("%s\n",Endpoint_State_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(5, 50, Endpoint_State_str, &Font20, BLACK, WHITE );
#endif
if (active_alarm > 0){
current_time = get_absolute_time();
current_time_to_go_active_alarm = ((double) absolute_time_diff_us(current_time,active_alarm_termination_time))/1000000/60;
if (append_rst_final_extratime==true){
//treat already "touched button" from EP state 1 before - forced via reset button:
current_time_to_go_active_alarm=current_time_to_go_active_alarm + ((double) final_extratime)/fwd_time_mp/1000000/60;
}
current_time_to_go_active_alarm = ((double) absolute_time_diff_us(current_time,active_alarm_termination_time))/1000000/60;
TimeToGo = current_time_to_go_active_alarm;
sprintf(TimeToGo_s_str, "%.2f", TimeToGo);
strcat(TimeToGo_s_str, timeToGo_suffix_str);
#if MY_ENV == MY_ENV_WOKWI
printf("\n");
printf("%s\n",TimeToGo_s_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(20, 100, TimeToGo_s_str , &Font20, BLACK, WHITE );
#endif
}
break;
case 4:
strcpy(Endpoint_State_str, "Temporary Off-Mode");
#if MY_ENV == MY_ENV_WOKWI
printf("%s\n",Endpoint_State_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(5, 50, Endpoint_State_str, &Font20, CYAN, WHITE );
#endif
if (active_alarm > 0){
current_time = get_absolute_time();
TimeToGo = ((double) absolute_time_diff_us(current_time,active_alarm_termination_time))/1000000/60;
switch (current_open_count_btn_actuations){
case 0:
// remaining time of current regular interval
TimeToGo = TimeToGo;
break;
case 1 ... INT_MAX:
//prev. + additional regular intervals
TimeToGo = TimeToGo + ((double) current_open_count_btn_actuations-1)*on_time_btn_actuation/fwd_time_mp/1000000/60;
break;
}
sprintf(TimeToGo_s_str, "%.2f", TimeToGo);
strcat(TimeToGo_s_str, timeToGo_suffix_str);
#if MY_ENV == MY_ENV_WOKWI
printf("\n");
printf("%s\n",TimeToGo_s_str);
#endif
#if MY_ENV == MY_ENV_MYHW
Paint_DrawString_EN(20, 100, TimeToGo_s_str , &Font20, CYAN, WHITE );
#endif
}
break;
}
#if MY_ENV == MY_ENV_WOKWI
printf("shift = %d\n", (int) shift_enabled);
printf("\n");
#endif
#endif
}
int main() {
stdio_init_all();
#if MY_ENV == MY_ENV_MYHW || MY_ENV == MY_ENV_MYHW_DEV
if (cyw43_arch_init()) {
printf("WiFi init failed");
return -1;
}
#endif
led_state = true;
#if MY_LED_DBG == MY_LED_DBG_ON
#if MY_ENV == MY_ENV_WOKWI
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
gpio_put(LED_PIN, led_state);
#endif
#if MY_ENV == MY_ENV_MYHW || MY_ENV == MY_ENV_MYHW_DEV
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_state);
#endif
#endif
// <- erst ab dem Absatz funkt es auch per alter_DBG_LED() !!
// interrupts
//local ctrl button:
gpio_init(14);
gpio_set_dir(14,GPIO_IN);
gpio_pull_up(14);
gpio_set_irq_enabled_with_callback(14, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE , true, &interrupt_routine);
//shift function button:
gpio_init(5); // is PIN 7 (and PIN8 is a GND)
gpio_set_dir(5,GPIO_IN);
gpio_pull_up(5);
gpio_set_irq_enabled(5, GPIO_IRQ_EDGE_FALL, true);
//local reset button:
gpio_init(16);
gpio_set_dir(16,GPIO_IN);
gpio_pull_up(16);
gpio_set_irq_enabled(16, GPIO_IRQ_EDGE_FALL, true);
//external bathroom button:
gpio_init(22);
gpio_set_dir(22,GPIO_IN);
gpio_pull_down(22);
gpio_set_irq_enabled(22, GPIO_IRQ_EDGE_RISE, true);
//prepare bathroom button twin:
gpio_init(20);
gpio_set_dir(20,GPIO_OUT);
gpio_put(20,false);
#if MY_ENV == MY_ENV_MYHW
DEV_Delay_ms(100);
if(DEV_Module_Init()!=0){
return -1;
}
DEV_SET_PWM(50);
/* LCD Init */
printf("Flat Air Control Endpoint\r\n");
LCD_2IN_Init(HORIZONTAL);
LCD_2IN_Clear(WHITE);
//LCD_SetBacklight(1023);
UDOUBLE Imagesize = LCD_2IN_HEIGHT*LCD_2IN_WIDTH*2;
UWORD *BlackImage;
if((BlackImage = (UWORD *)malloc(Imagesize)) == NULL) {
printf("Failed to apply for black memory...\r\n");
exit(0);
}
// /*1.Create a new image cache named IMAGE_RGB and fill it with white*/
Paint_NewImage((UBYTE *)BlackImage,LCD_2IN.WIDTH,LCD_2IN.HEIGHT, 90, WHITE);
Paint_SetScale(65);
Paint_Clear(WHITE);
Paint_SetRotate(ROTATE_270);
// /* GUI */
printf("drawing...\r\n");
// /*2.Drawing on the image*/
// Just to be sure xD
sleep_ms(100);
#endif
while(1) {
sleep_ms(1000);
// (de)activate mqtt ability (but always offer info for remote control computer)
// act
if (!(active_alarm > 0)){
//no active alarm
if (append_rst_final_extratime==true){
//wait for remainder of ep state 1:
append_rst_final_extratime=false;
ist_final_extratime=true;
active_alarm = add_alarm_in_us(final_extratime/fwd_time_mp, alarm_callback, NULL, false);
active_alarm_termination_time = delayed_by_us(get_absolute_time(),final_extratime/fwd_time_mp);
}else {
// fall back to endpoint state 0 :
if ((current_open_count_btn_actuations == 0) && (is_before_last_alarm_of_ctrl_btn_actuation_cascade==false) && (endpoint_state==1)) {
endpoint_state=0;
alter_DBG_LED();
shift_enabled=false;
}
if ((current_open_count_btn_actuations == 0) && (endpoint_state==2)){
endpoint_state=0;
alter_DBG_LED();
shift_enabled=false;
}
if ((current_open_count_btn_actuations == 0) && (endpoint_state==4)){
endpoint_state=0;
alter_DBG_LED();
shift_enabled=false;
}
switch (endpoint_state){
case 0:
// statements
//actuate_bathroom_button_twin();
//printf("endpoint_state is %d\n", endpoint_state);
break;
case 1:
// statements
// assert: current_open_count_btn_actuations > 0
if (is_before_first_alarm_of_ctrl_btn_actuation_cascade==true) {
is_before_first_alarm_of_ctrl_btn_actuation_cascade=false; //reset
is_before_last_alarm_of_ctrl_btn_actuation_cascade=true;
// doing first time on open count
active_alarm = add_alarm_in_us(on_time_btn_actuation/fwd_time_mp, alarm_callback, NULL, false);
active_alarm_termination_time = delayed_by_us(get_absolute_time(),on_time_btn_actuation/fwd_time_mp);
actuate_bathroom_button_twin();
} else {
switch (current_open_count_btn_actuations){
case 0:
if (is_before_last_alarm_of_ctrl_btn_actuation_cascade == true) {
is_before_last_alarm_of_ctrl_btn_actuation_cascade=false;//reset
// doing final extra time on an ongoing open count
ist_final_extratime=true;
active_alarm = add_alarm_in_us(final_extratime/fwd_time_mp, alarm_callback, NULL, false);
active_alarm_termination_time = delayed_by_us(get_absolute_time(),final_extratime/fwd_time_mp);
}
break;
case 1 ... INT_MAX:
//intermediate (regular) intervals
active_alarm = add_alarm_in_us(on_time_btn_actuation/fwd_time_mp, alarm_callback, NULL, false);
active_alarm_termination_time = delayed_by_us(get_absolute_time(),on_time_btn_actuation/fwd_time_mp);
//printf("endpoint_state is %d\n", endpoint_state);
actuate_bathroom_button_twin();
break;
}
}
break;
case 2:
// statements
active_alarm = add_alarm_in_us((on_time_btn_actuation+final_extratime)/fwd_time_mp, alarm_callback, NULL, false);
active_alarm_termination_time = delayed_by_us(get_absolute_time(),(on_time_btn_actuation+final_extratime)/fwd_time_mp);
break;
case 3:
// permanent off-mode
break;
case 4:
// temporary off-mode
if (current_open_count_btn_actuations >= 1) {
active_alarm = add_alarm_in_us((on_time_btn_actuation+final_extratime)/fwd_time_mp, alarm_callback, NULL, false);
active_alarm_termination_time = delayed_by_us(get_absolute_time(),(on_time_btn_actuation+final_extratime)/fwd_time_mp);
}
break;
}
}
}else{
//active alarm exists
if ((endpoint_state==2)&& (ext_bathroom_rst==true)){
ext_bathroom_rst=false;
append_rst_final_extratime=false;
ist_final_extratime=false;
cancel_alarm(active_alarm);
active_alarm = 0;
active_alarm = add_alarm_in_us((on_time_btn_actuation+final_extratime)/fwd_time_mp, alarm_callback, NULL, false);
active_alarm_termination_time = delayed_by_us(get_absolute_time(),(on_time_btn_actuation+final_extratime)/fwd_time_mp);
}
}
#if MY_ENV == MY_ENV_MYHW
Paint_Clear(WHITE);
#endif
// display status on lcd panel
#if MY_ENV != MY_ENV_MYHW_DEV
display_status();
#endif
#if MY_ENV == MY_ENV_MYHW
// /*3.Refresh the picture in RAM to LCD*/
LCD_2IN_Display((UBYTE *)BlackImage);
#endif
}
#if MY_ENV == MY_ENV_MYHW
/* Module Exit */
free(BlackImage);
BlackImage = NULL;
DEV_Module_Exit();
#endif
}