/** * \brief This will display the temperature in degrees F or C. */ void menu_display_temp(void) { int16_t result = temp_get(temp_mode); /* Display the temp result on the lower 4 digit display with the proper symbol. */ if(temp_mode == TEMP_UNIT_CELCIUS){ lcd_symbol_clr(LCD_SYMBOL_F); lcd_symbol_set(LCD_SYMBOL_C); } else{ lcd_symbol_clr(LCD_SYMBOL_C); lcd_symbol_set(LCD_SYMBOL_F); } /* Check for the DEBUG JTAG enable bit and display a CAUTION symbol to the user. */ /* CAUTION represents false value. */ if(MCUCR & 0x80){ lcd_symbol_clr(LCD_SYMBOL_ATT); } else{ lcd_symbol_set(LCD_SYMBOL_ATT); } lcd_num_putdec(result, LCD_NUM_PADDING_SPACE); }
/** * \brief This will clear the temperature displayed in the 4 digit LCD segments. */ void menu_clear_temp(void) { temp_flag = false; lcd_symbol_clr(LCD_SYMBOL_F); lcd_symbol_clr(LCD_SYMBOL_C); lcd_symbol_clr(LCD_SYMBOL_ATT); lcd_num_clr(); }
void mbox_deinit(void) { // Remove any envelope symbols lcd_symbol_clr(LCD_SYMBOL_ENV_MAIN); lcd_symbol_clr(LCD_SYMBOL_ENV_CL); lcd_symbol_clr(LCD_SYMBOL_ENV_OP); // Close mailbox and indicate no longer initialized mbox_close(); mbox_initalized = false; }
void loc_evt_bl_entered(void *evt) { rvn_loc_cmd_std_t cmd; SIPC_ACK_PACKET(); switch (avrraven.status.state) { case STATE_M1284P_RESTART_WAIT_BOOT_EVENT: cmd.id = RVN_LOC_CMD_APP_START; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); lcd_puts_P("WAIT FOR M1284 APP PROG"); avrraven.status.state = STATE_M1284P_RESTART_WAIT_APP_EVENT; break; case STATE_M1284P_ENTER_BOOT_WAIT_BOOT_EVENT: // ATmega1284 is in boot loader led_status_set(LED_FAST_BLINK); lcd_puts_P("WRITING M1284 FACTORY DEFAULT FW"); cmd.id = RVN_LOC_CMD_ENTER_BOOT; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); // Set FW image offset to read from factory default location on data flash avrraven.status.m1284p_img_offset = M1284P_FLASH_FD_IMG_ADR; // Set new avrraven.status.state avrraven.status.state = STATE_M1284P_UPGRADE_INIT_WAIT_RESPOND; break; case STATE_M1284P_UPGRADE_INIT_WAIT_RESPOND: // ATmega1284 has entered booloader mode lcd_symbol_clr(LCD_SYMBOL_ZLINK); lcd_symbol_clr(LCD_SYMBOL_ZIGBEE); lcd_symbol_clr(LCD_SYMBOL_RX); lcd_symbol_clr(LCD_SYMBOL_TX); lcd_symbol_antenna_signal(LCD_SYMBOL_ANTENNA_DIS); // Allocate memory for FW packets if ((m1284p_fw_packet = (rvn_loc_cmd_fw_packet_t*)vrt_mem_alloc(sizeof(rvn_loc_cmd_fw_packet_t)+RVN_FW_PACKET_SIZE)) == NULL){ break; } // Initiate transfer avrraven.status.m1284p_address_offset = 0; send_m1284p_fw_packet(avrraven.status.m1284p_img_offset, avrraven.status.m1284p_address_offset, m1284p_fw_packet); lcd_num_putdec((int)(avrraven.status.m1284p_address_offset/1024), LCD_NUM_PADDING_SPACE); avrraven.status.state = STATE_M1284P_UPGRADE_PACKET_WAIT_RESPOND; break; default: // This event is ignored in any other state break; } }
/*========================= IMPLEMENTATION =========================*/ void int_evt_startup(void* evt) { rvn_loc_cmd_std_t cmd; uint32_t blcc; switch (avrraven.status.state) { case STATE_STARTUP: /* Restart ATmega1284 application program. If in bootloader mode, start * Application program. If command disappears (during ATmega1284 startup etc.) * this application will react on the application startup event sent by * ATmega1284. */ cmd.id = RVN_LOC_CMD_ENTER_BOOT; sipc_send_frame(sizeof(rvn_loc_cmd_std_t), (uint8_t *)&cmd); // Put init symbols lcd_symbol_set(LCD_SYMBOL_RAVEN); lcd_symbol_clr(LCD_SYMBOL_RX); lcd_symbol_clr(LCD_SYMBOL_TX); lcd_symbol_antenna_signal(LCD_SYMBOL_ANTENNA_DIS); avrraven.status.ntwk_address = NTWK_ADDRESS_INVALID; // led_status_set(LED_OFF); // lcd_puts_P("WAIT FOR M1284 BOOT LOADER"); // If m1284 factory default fw should be loaded: BLCC_READ(blcc); if (blcc == BLCC_LOAD_FACTORY_DEFAULT) { avrraven.status.state = STATE_M1284P_ENTER_BOOT_WAIT_BOOT_EVENT; } else { avrraven.status.state = STATE_M1284P_RESTART_WAIT_BOOT_EVENT; } break; default: // Startupevent in any other state is ignored break; } }
void loc_rsp_fail(void* rsp) { rvn_loc_cmd_std_t cmd; SIPC_ACK_PACKET(); switch (avrraven.status.state) { case STATE_OTA_TRANS_WAITING_FOR_RX_ENABLE_RESPONSE: lcd_symbol_clr(LCD_SYMBOL_RX); // TIMED_FUNCTION lcd_symbol_clr(LCD_SYMBOL_TX); // TIMED_FUNCTION avrraven.status.state = STATE_IDLE; break; case STATE_RADIO_WAIT_FOR_RX_REENABLE_RESPONSE: lcd_puts_P("RX ENABLE FAILED"); led_status_set(LED_FAST_BLINK); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; case STATE_RADIO_WAIT_FOR_RX_ENABLE_RESPONSE: cmd.id = RVN_LOC_CMD_RX_ON; // re-try enabling rx sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); avrraven.status.state = STATE_RADIO_WAIT_FOR_RX_REENABLE_RESPONSE; break; case STATE_FW_WRITE: lcd_puts_P("PACKET ERROR"); led_status_set(LED_FAST_BLINK); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; case STATE_RADIO_CONNECTING: lcd_puts_P("NO NET"); led_status_set(LED_FAST_BLINK); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; default: lcd_puts_P("ERROR"); led_status_set(LED_FAST_BLINK); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; } }
/*========================= IMPLEMENTATION =========================*/ void loc_rsp_ok(void* rsp) { rvn_loc_cmd_get_param_t cmd_get_param; rvn_loc_cmd_std_t cmd; uint32_t blcc; FMENU_item_flash_t* current_menu_entry = FMENU_GetCurrentItem(&MENU_menuHandle); SIPC_ACK_PACKET(); switch (avrraven.status.state) { /*======================== FW write ========================*/ case STATE_FW_WRITE_INIT: lcd_puts_P("RECEIVING FW IMAGE"); avrraven.status.state = STATE_FW_WRITE; break; case STATE_FW_WRITE_INIT_WAIT_RX_ENABLE_RESPONSE: avrraven.status.state = STATE_FW_WRITE; break; case STATE_FW_WRITE_COMPLETE_WAIT_RX_ENABLE_RESPONSE: lcd_puts_P("DONE"); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; case STATE_OTA_TRANS_WAITING_FOR_RX_ENABLE_RESPONSE: avrraven.status.state = STATE_IDLE; break; case STATE_FW_WRITE_WAIT_RX_ENABLE_RESPONSE: avrraven.status.state = STATE_FW_WRITE; break; case STATE_FW_WRITE_WAIT_TX_DONE: avrraven.status.state = STATE_FW_WRITE; break; case STATE_FW_WRITE_COMPLETE_WAIT_TX_DONE: lcd_puts_P("DONE"); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; case STATE_FW_WRITE_IMAGE: // Set ATmega1284p in boot loader mode led_status_set(LED_FAST_BLINK); lcd_puts_P("WRITING M1284 IMAGE"); cmd.id = RVN_LOC_CMD_ENTER_BOOT; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); avrraven.status.state = STATE_M1284P_UPGRADE_INIT_WAIT_RESPOND; break; case STATE_FW_WRITE_COMPLETE_WAIT_RADIO: lcd_symbol_set(LCD_SYMBOL_ZLINK); lcd_symbol_set(LCD_SYMBOL_ZIGBEE); lcd_symbol_antenna_signal(LCD_SYMBOL_ANTENNA_SIG_3); cmd.id = RVN_LOC_CMD_RX_ON; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); avrraven.status.state = STATE_FW_WRITTEN_WAIT_RX_ENABLE_RESPONSE; break; case STATE_FW_WRITTEN_WAIT_RX_ENABLE_RESPONSE: lcd_puts_P("FW WRITTEN SUCCESSFULLY"); ota_event(RVN_OTA_EVT_FW_WRITE_DONE, 0x0000); BLCC_WRITE(BLCC_NORMAL_APP_START); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; case STATE_FW_WRITE: break; /*======================== Radio ========================*/ case STATE_RADIO_CONNECTING: lcd_symbol_set(LCD_SYMBOL_ZLINK); lcd_symbol_set(LCD_SYMBOL_ZIGBEE); lcd_symbol_antenna_signal(LCD_SYMBOL_ANTENNA_SIG_3); cmd.id = RVN_LOC_CMD_RX_ON; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); avrraven.status.state = STATE_RADIO_WAIT_FOR_RX_ENABLE_RESPONSE; break; case STATE_RADIO_DISCONNECTING: lcd_symbol_clr(LCD_SYMBOL_ZLINK); lcd_symbol_clr(LCD_SYMBOL_ZIGBEE); lcd_symbol_clr(LCD_SYMBOL_RX); lcd_symbol_clr(LCD_SYMBOL_TX); lcd_symbol_antenna_signal(LCD_SYMBOL_ANTENNA_DIS); lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); lcd_num_clr_all(); avrraven.status.ntwk_address = NTWK_ADDRESS_INVALID; avrraven.status.state = STATE_IDLE; break; case STATE_RADIO_WAIT_FOR_RX_ENABLE_RESPONSE: case STATE_RADIO_WAIT_FOR_RX_REENABLE_RESPONSE: // Get short address cmd_get_param.id = RVN_LOC_CMD_GET_PARAM; cmd_get_param.param = NWK_ADDRESS; sipc_send_frame(sizeof(rvn_loc_cmd_get_param_t), (uint8_t *)&cmd_get_param); avrraven.status.state = STATE_RADIO_GET_ADDRESS_WAIT_RESPONSE; break; /*======================== ATmega1284p ========================*/ case STATE_M1284P_UPGRADE_INIT_WAIT_RESPOND: /*Does nothing. Waiting for enter bootloader event*/ break; case STATE_M1284P_UPGRADE_PACKET_WAIT_RESPOND: send_m1284p_fw_packet(avrraven.status.m1284p_img_offset, avrraven.status.m1284p_address_offset, m1284p_fw_packet); lcd_num_putdec((int)(avrraven.status.m1284p_address_offset/1024), LCD_NUM_PADDING_SPACE); if ((avrraven.status.m1284p_address_offset += RVN_FW_PACKET_SIZE) == M1284P_APP_FLASH_SIZE) { vrt_mem_free((void *)(m1284p_fw_packet)); lcd_puts_P("DONE"); avrraven.status.state = STATE_M1284P_UPGRADE_DONE_WAIT_RESPOND; } else { /* stay in same avrraven.status.state and wait for response on the FW packet*/ } break; case STATE_M1284P_UPGRADE_DONE_WAIT_RESPOND: // Start ATmega1284's new FW cmd.id = RVN_LOC_CMD_APP_START; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); // If m1284 factory default fw loaded, m3290 fw allready upgraded, and BLCC_READ(blcc); if (blcc == BLCC_LOAD_FACTORY_DEFAULT) { BLCC_WRITE(BLCC_FW_UPGRADE_COMPLETE); reboot(); } else { // Start own bootloader without waitig for 1284 to reboot BLCC_WRITE(BLCC_FW_UPGRADE_START_REQUEST_FROM_APP); reboot(); } break; case STATE_M1284P_NEW_FW_WAIT_EVENT: /*Does nothing. Waiting for app prog start event*/ break; case STATE_M1284P_RESTART_WAIT_BOOT_EVENT: case STATE_M1284P_ENTER_BOOT_WAIT_BOOT_EVENT: /*Does nothing. Waiting for boot loader start event*/ break; case STATE_M1284P_RESTART_WAIT_APP_EVENT: /*Does nothing. Waiting for app prog start event*/ break; case STATE_M1284P_DISCONNECT_WAIT_RESPOND: // Set ATmega1284p in boot loader mode led_status_set(LED_FAST_BLINK); lcd_puts_P("WRITING 1284P FW"); cmd.id = RVN_LOC_CMD_ENTER_BOOT; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); avrraven.status.state = STATE_M1284P_UPGRADE_INIT_WAIT_RESPOND; break; /*======================== Misc ========================*/ case STATE_OTA_TRANSACTION_WAITING_FOR_RESPONSE: lcd_symbol_clr(LCD_SYMBOL_RX); // TIMED_FUNCTION lcd_symbol_set(LCD_SYMBOL_TX); // TIMED_FUNCTION cmd.id = RVN_LOC_CMD_RX_ON; sipc_send_frame(sizeof(cmd), (uint8_t *)&cmd); avrraven.status.state = STATE_OTA_TRANS_WAITING_FOR_RX_ENABLE_RESPONSE; break; case STATE_MAIL_SEND_INIT: lcd_puts_P("SENDING"); led_status_set(LED_SOFT_BLINK); avrraven.status.state = STATE_MAIL_SENDING; break; default: // OK responses in unknown state is ignored break; } }
void loc_evt_ota_packet(void *evt) { rvn_loc_evt_ota_packet_t* ota_packet = evt; // Get OTA packet header (Network layer) rvn_ota_transport_t* ota_transport = (rvn_ota_transport_t*)&ota_packet->data; // Get transport header uint8_t* app_data = (uint8_t*)&ota_transport->data; // Get application data packet uint8_t id = app_data[0]; // Get application packet id // Update radio symbols lcd_symbol_clr(LCD_SYMBOL_TX); // TIMED_FUNCTION lcd_symbol_set(LCD_SYMBOL_RX); // TIMED_FUNCTION lcd_symbol_antenna_signal(3); if (ota_packet->lqi<220) { lcd_symbol_clr(LCD_SYMBOL_ANT_SIG3); } if (ota_packet->lqi<200) { lcd_symbol_clr(LCD_SYMBOL_ANT_SIG2); } if (ota_packet->lqi<150) { lcd_symbol_clr(LCD_SYMBOL_ANT_SIG1); } // Execute OTA command handler switch (id) { case RVN_OTA_CMD_FW_WRITE_INIT: ota_cmd_fw_write_initiated(ota_packet); break; case RVN_OTA_CMD_FW_WRITE_PACKET: ota_cmd_fw_write_packet(ota_packet); break; case RVN_OTA_CMD_FW_WRITE_COMPLETED: ota_cmd_fw_write_completed(ota_packet); break; case RVN_OTA_CMD_FW_WRITE_IMAGE: ota_cmd_fw_write_image(ota_packet); break; case RVN_OTA_CMD_TXTMSG: ota_cmd_txtmsg(ota_packet); break; case RVN_OTA_CMD_SHARED_RD: ota_cmd_shared_rd(ota_packet); break; case RVN_OTA_CMD_GETNAME: ota_cmd_getname(ota_packet); break; case RVN_OTA_CMD_FOPEN: ota_cmd_fopen(ota_packet); break; case RVN_OTA_CMD_FCLOSE: ota_cmd_fclose(ota_packet); break; case RVN_OTA_CMD_FREAD: ota_cmd_fread(ota_packet); break; case RVN_OTA_CMD_FWRITE: ota_cmd_fwrite(ota_packet); break; case RVN_OTA_CMD_SIGN_ON: ota_cmd_sign_on(ota_packet); break; case RVN_OTA_RSP_OK: ota_rsp_ok(ota_packet); break; case RVN_OTA_RSP_ERROR: case RVN_OTA_RSP_BUSY: case RVN_OTA_RSP_NOT_SUPPORTED: ota_rsp_error(ota_packet); break; default:{ // ACK unknown sipc packet SIPC_ACK_PACKET(); // Respond not supported ota_simple_response(RVN_OTA_RSP_NOT_SUPPORTED, ota_packet->adr, ota_transport->seq_nmbr);} break; } }
void int_evt_key(void* evt) { key_state_t key_state = *(key_state_t*)evt; FMENU_item_flash_t* current_menu_entry = FMENU_GetCurrentItem(&MENU_menuHandle); FMENU_item_flash_t* new_menu_entry = current_menu_entry; menu_action_t menu_action = MENU_ACTION_ENTER; int int_temp; static uint8_t file_name[SFS_MAX_FILENAME_BUFFER_SIZE]; unsigned char search_string[SFS_MAX_FILENAME_BUFFER_SIZE]; lcd_config_t config; static key_state_t auto_key_state; static bool auto_key_wait = true; static bool auto_key_registered = false; static asy_tmr_t auto_key_timer = ASY_TMR_NO_TIMER; // Navigate to next avrraven.status.state switch (key_state){ case KEY_UP: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateUp(&MENU_menuHandle); break; case STATE_CONFIG_DEBUG_ENABLE: lcd_puts_P("ENABLE"); avrraven.user_config.debug_enable = true; break; case STATE_CONFIG_TXTPREV_ENABLE: lcd_puts_P("ENABLE"); avrraven.user_config.txtmsg_preview = true; break; case STATE_CONFIG_FW_UPGRADE: lcd_puts_P("AUTO"); avrraven.user_config.fw_upgr_auto = true; break; case STATE_CONFIG_CONNECT: lcd_puts_P("AUTO"); avrraven.user_config.join_auto = true; break; case STATE_CONFIG_IMG_RCV: lcd_puts_P("AUTO"); avrraven.user_config.fw_rcv_auto = true; break; case STATE_CONFIG_NAME: case STATE_MAIL_COMPOSE: txtedit_event(TXTEDIT_KEY_UP); break; case STATE_CONFIG_LCD_CONTRAST: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE); config = lcd_config_get(); config.contrast = numedit_buffer; lcd_config_set(config); break; case STATE_CONFIG_CLOCK_MIN: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // hours from current clock int clk = set_time.hour*100 + numedit_event(NUMEDIT_KEY_UP); // minutes from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_CLOCK_HOUR: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // minutes from current clock int clk = numedit_event(NUMEDIT_KEY_UP)*100 + set_time.min; // hours from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_LCD_SCROLLING: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE); // Update LCD scrolling settings config = lcd_config_get(); config.scrolling = (lcd_scrolling_t)numedit_value_get(); lcd_config_set(config); break; case STATE_CONFIG_RADIO_CHANNEL: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: avrraven.user_config.unit.temp = TEMP_UNIT_CELCIUS; lcd_symbol_clr(LCD_SYMBOL_F); lcd_symbol_set(LCD_SYMBOL_C); break; case STATE_CONFIG_UNIT_CLOCK: avrraven.user_config.unit.clock = TIME_CLOCK_UNIT_24; if (avrraven.user_config.unit.clock == TIME_CLOCK_UNIT_24) { lcd_symbol_clr(LCD_SYMBOL_AM); lcd_symbol_clr(LCD_SYMBOL_PM); lcd_num_puthex(0x2400, LCD_NUM_PADDING_ZERO); } else { lcd_symbol_set(LCD_SYMBOL_AM); lcd_symbol_set(LCD_SYMBOL_PM); lcd_num_puthex(0x1200, LCD_NUM_PADDING_ZERO); } break; case STATE_MAIL_READ: mbox_mail_get(¤t_mail, MBOX_GET_NEXT); if (current_mail != NULL) { int_temp = current_mail->size; lcd_puta(current_mail->data, int_temp); lcd_num_puthex(current_mail->address, LCD_NUM_PADDING_ZERO); } break; case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_AUDIO_FILE_SELECT: strncpy_P((char*)search_string, AUDIO_FILE_TYPE, AUDIO_FILE_TYPE_SIZE); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_REV); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; case STATE_STORAGE_FILE_LIST: strncpy_P((char*)search_string, "*.*", 4); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_REV); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; default: // Key events in unknown state is ignored break; } break; case KEY_DOWN: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateDown(&MENU_menuHandle); break; case STATE_CONFIG_DEBUG_ENABLE: lcd_puts_P("DISABLE"); avrraven.user_config.debug_enable = false; break; case STATE_CONFIG_TXTPREV_ENABLE: lcd_puts_P("DISABLE"); avrraven.user_config.txtmsg_preview = false; break; case STATE_CONFIG_FW_UPGRADE: lcd_puts_P("USR ACK"); avrraven.user_config.fw_rcv_auto = false; break; case STATE_CONFIG_CONNECT: lcd_puts_P("MANUAL"); avrraven.user_config.join_auto = false; break; case STATE_CONFIG_IMG_RCV: lcd_puts_P("USR ACK"); avrraven.user_config.fw_rcv_auto = false; break; case STATE_MAIL_COMPOSE: case STATE_CONFIG_NAME: txtedit_event(TXTEDIT_KEY_DOWN); break; case STATE_CONFIG_LCD_CONTRAST: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE); config = lcd_config_get(); config.contrast = numedit_buffer; lcd_config_set(config); break; case STATE_CONFIG_CLOCK_MIN: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // hours from current clock int clk = set_time.hour*100 + numedit_event(NUMEDIT_KEY_DOWN); // minutes from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_CLOCK_HOUR: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // minutes from current clock int clk = numedit_event(NUMEDIT_KEY_DOWN)*100 + set_time.min; // hours from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_LCD_SCROLLING: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE); // Update LCD scrolling settings config = lcd_config_get(); config.scrolling = (lcd_scrolling_t)numedit_value_get(); lcd_config_set(config); break; case STATE_CONFIG_RADIO_CHANNEL: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: avrraven.user_config.unit.temp = TEMP_UNIT_FAHRENHEIT; lcd_symbol_clr(LCD_SYMBOL_C); lcd_symbol_set(LCD_SYMBOL_F); break; case STATE_CONFIG_UNIT_CLOCK: avrraven.user_config.unit.clock = TIME_CLOCK_UNIT_12; if (avrraven.user_config.unit.clock == TIME_CLOCK_UNIT_24) { lcd_symbol_clr(LCD_SYMBOL_AM); lcd_symbol_clr(LCD_SYMBOL_PM); lcd_num_puthex(0x2400, LCD_NUM_PADDING_ZERO); } else { lcd_symbol_set(LCD_SYMBOL_AM); lcd_symbol_set(LCD_SYMBOL_PM); lcd_num_puthex(0x1200, LCD_NUM_PADDING_ZERO); } break; case STATE_MAIL_READ: mbox_mail_get(¤t_mail, MBOX_GET_PREV); if (current_mail != NULL) { int_temp = current_mail->size; lcd_puta(current_mail->data, int_temp); lcd_num_puthex(current_mail->address, LCD_NUM_PADDING_ZERO); } break; case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_AUDIO_FILE_SELECT: strncpy_P((char*)search_string, AUDIO_FILE_TYPE, AUDIO_FILE_TYPE_SIZE); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_FWD); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; case STATE_STORAGE_FILE_LIST: strncpy_P((char*)search_string, "*.*", 4); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_FWD); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; default: // Key events in unknown state is ignored break; } break; case KEY_LEFT: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateLeft(&MENU_menuHandle); break; case STATE_CONFIG_CLOCK_MIN: { // Set min timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.min = numedit_buffer; new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on hours numedit_done(); // Start numeric editor on hours { timendate_clk_t current_time; timndate_clock_get(¤t_time, avrraven.user_config.unit.clock); numedit_buffer = current_time.hour; numedit_config_t conf = { .number = &numedit_buffer, .min_value = 0, .max_value = 23, .radix = NUMEDIT_RADIX_DEC, .size = 2, .offset = 2 }; numedit_init(conf); } avrraven.status.state = STATE_CONFIG_CLOCK_HOUR; break; case STATE_AUDIO_FILE_SELECT: if (audio_playback_active() == true) { audio_playback_stop(); } lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_NAME: case STATE_MAIL_COMPOSE: txtedit_event(TXTEDIT_KEY_LEFT); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_LEFT), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: break; case STATE_CONFIG_UNIT_CLOCK: break; /* case STATE_MAIL_READ: mbox_mail_getnext(&txtmsg); if (txtmsg != NULL) { int_temp = ((txtmsg->size) < LCD_SEGMENT_COUNT) ? txtmsg->size : LCD_SEGMENT_COUNT; mail_read_offset = ((mail_read_offset + LCD_SEGMENT_COUNT) >= txtmsg->size) ? mail_read_offset : (mail_read_offset + LCD_SEGMENT_COUNT); lcd_puta(&txtmsg->data[mail_read_offset], int_temp); } break;*/ case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; default: // Key events in unknown state is ignored break; } break; case KEY_RIGHT: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateRight(&MENU_menuHandle); break; case STATE_CONFIG_CLOCK_HOUR: { // Set hour timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.hour = numedit_buffer; new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on hours numedit_done(); // Start numeric editor on minutes { timendate_clk_t current_time; timndate_clock_get(¤t_time, avrraven.user_config.unit.clock); numedit_buffer = current_time.min; numedit_config_t conf = { .number = &numedit_buffer, .min_value = 0, .max_value = 59, .radix = NUMEDIT_RADIX_DEC, .size = 2, .offset = 0 }; numedit_init(conf); } avrraven.status.state = STATE_CONFIG_CLOCK_MIN; break; case STATE_MAIL_COMPOSE: case STATE_CONFIG_NAME: txtedit_event(TXTEDIT_KEY_RIGHT); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_RIGHT), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: break; case STATE_CONFIG_UNIT_CLOCK: break; case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; default: // Key events in unknown state is ignored break; } break; case KEY_ENTER: switch (avrraven.status.state) { case STATE_DISPLAY_MESSAGE: // Default display avrraven.status.state lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); led_status_set(LED_OFF); lcd_num_clr_all(); // Refresh menu function (in case it affects the display) menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_LCD_CONTRAST: // Done numeric editing, write value to user configuration numedit_done(); avrraven.user_config.lcd.contrast = (lcd_contrast_t)numedit_buffer; // Update LCD HW config = lcd_config_get(); config.contrast = avrraven.user_config.lcd.contrast; lcd_config_set(config); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_LCD_SCROLLING: // Done numeric editing, write value to user configuration avrraven.user_config.lcd.scrolling = (lcd_scrolling_t)numedit_value_get(); numedit_done(); // Update LCD scrolling settings config = lcd_config_get(); config.scrolling = avrraven.user_config.lcd.scrolling; lcd_config_set(config); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_RADIO_CHANNEL: // Done numeric editing, write value to user configuration avrraven.user_config.channel = numedit_value_get(); numedit_done(); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_CLOCK_HOUR: { // Set hour timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.hour = numedit_value_get(); new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on hours numedit_done(); // Start show clock event menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_CLOCK_MIN: { // Set min timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.min = numedit_value_get(); new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on minutes numedit_done(); // Start show clock event menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_DEBUG_ENABLE: // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_RADIO_PANID: // Done numeric editing on hours numedit_done(); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_UNIT_TEMP: case STATE_CONFIG_UNIT_CLOCK: case STATE_CONFIG_TXTPREV_ENABLE: case STATE_CONFIG_FW_UPGRADE: case STATE_CONFIG_CONNECT: case STATE_CONFIG_IMG_RCV: // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_MAIL_PREVIEW: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } led_status_set(LED_OFF); avrraven.status.state = STATE_IDLE; break; case STATE_AUDIO_FILE_SELECT: if (audio_playback_active() == false) { audio_playback_start(file_name, false); } else { audio_playback_stop(); } break; case STATE_STORAGE_FILE_LIST: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_FW_WAIT_USER_CONFIRMATION: avrraven.status.state = STATE_FW_WRITE_INIT; break; case STATE_IDLE: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } break; case STATE_AUDIO_RECORD: audio_record_stop(); lcd_symbol_clr(LCD_SYMBOL_MIC); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_NAME: txtedit_event(TXTEDIT_KEY_ENTER); txtedit_done(); USER_CONFIG_STORE(); // Print the menu title to the display lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_MAIL_READ: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); // If any unread mail, show closed envelope if (mbox_unread() == true) { lcd_symbol_set(LCD_SYMBOL_ENV_MAIN); lcd_symbol_set(LCD_SYMBOL_ENV_CL); lcd_symbol_clr(LCD_SYMBOL_ENV_OP); // If all mail read, show open envelope } else { lcd_symbol_set(LCD_SYMBOL_ENV_MAIN); lcd_symbol_set(LCD_SYMBOL_ENV_CL); lcd_symbol_set(LCD_SYMBOL_ENV_OP); } // show number of mails on display int_temp = mbox_mail_count_get(); lcd_num_putdec(int_temp, LCD_NUM_PADDING_SPACE); mbox_close(); avrraven.status.state = STATE_IDLE; break; case STATE_MAIL_COMPOSE: txtedit_event(TXTEDIT_KEY_ENTER); txtedit_done(); mbox_mail_buffer_put(new_mail_buffer); { lcd_puts_P("ADDRESS"); numedit_config_t conf = { .number = &numedit_buffer, .min_value = 0, .max_value = UINT16_MAX, .radix = NUMEDIT_RADIX_DEC, .size = 1, .offset = 0 }; numedit_init(conf); } numedit_buffer = 0x0000; // default address lcd_num_puthex(numedit_buffer, LCD_NUM_PADDING_ZERO); avrraven.status.state = STATE_MAIL_COMPOSE_ADDRESS_SET; break; case STATE_MAIL_COMPOSE_ADDRESS_SET: avrraven.status.trans_seq_nmbr = mbox_mail_send(numedit_value_get(), txtedit_size_get()); avrraven.status.state = STATE_MAIL_SEND_INIT; numedit_done(); mbox_close(); break; default: lcd_puts_P("CANCELED"); led_status_set(LED_FAST_BLINK); lcd_num_clr_all(); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; } break; case KEY_NO_KEY: // Do nothing? break; default: // Key events in unknown state is ignored break; } // Navigate menu if new menu entry is different from last if (new_menu_entry != current_menu_entry) { navigate_menu(current_menu_entry, new_menu_entry, menu_action); } // After processing the key event it is safe to enable auto key auto_key_state = key_state; if (key_state != KEY_NO_KEY) { if (auto_key_registered == false) { long delay; if (auto_key_wait == true) { delay = 300; auto_key_wait = false; } else { asy_tmr_put(auto_key_timer); delay = 80; auto_key_registered = true; } auto_key_timer = asy_tmr_get(int_evt_key, (void*)&auto_key_state, delay); } } else { asy_tmr_put(auto_key_timer); auto_key_wait = true; auto_key_registered = false; } } void int_evt_check_key(void* evt) { static bool first_time = true; // Static variable used as flag to indicate first execution of function static key_state_t last_key_state; // Variable hodling last value of the joystick. Used to detect changes in joystick state /* Check joystick state. Post event if any change since last * First time function is executed no event is posted. This is * done to not respond if joystick activated while booting */ key_state_t new_key_state; if (first_time) { last_key_state = key_state_get(); new_key_state = last_key_state; first_time = false; } else if((new_key_state = key_state_get()) != last_key_state){ last_key_state = new_key_state; vrt_post_event(int_evt_key, (void*)&last_key_state); } } void int_evt_lcd_shift_left(void* evt) { lcd_text_shift_left(); } void int_evt_lcd_cursor_toggle(void* evt) { lcd_cursor_toggle(); } void int_evt_lcd_num_refresh(void* evt) { lcd_num_refresh(); } void int_evt_update_batt(void* evt) { int16_t vcc_batt = battery_voltage_read(); lcd_symbol_battery_empty(); if (vcc_batt>2000) { lcd_symbol_set(LCD_SYMBOL_BAT_CAP1); } if (vcc_batt>2500) { lcd_symbol_set(LCD_SYMBOL_BAT_CAP2); } if (vcc_batt>2800) { lcd_symbol_set(LCD_SYMBOL_BAT_CAP3); } // Indicate low battery if voltage less than 2.6 V if (avrraven.status.batt_low == false) { if (vcc_batt<2600) { avrraven.status.batt_low = true; lcd_symbol_set(LCD_SYMBOL_ATT); mbox_deinit(); sfs_deinit(); } } } void int_evt_show_clock(void* evt) { static bool col = false; timendate_clk_t clk; timndate_clock_get(&clk, avrraven.user_config.unit.clock); int16_t display_clock = clk.hour*100 + clk.min; lcd_num_putdec(display_clock, LCD_NUM_PADDING_ZERO); if ((col = !col) == true){ lcd_symbol_set(LCD_SYMBOL_COL); } else { lcd_symbol_clr(LCD_SYMBOL_COL); } } void int_evt_toggle_num_digit(void* evt) { int8_t digit_mask = *(int8_t*)evt; lcd_num_enable(digit_mask); } void int_evt_audio(void* evt) { audio_event_handler(); }