void PAGE_SplashEvent() { static unsigned int time=0; #if HAS_EXTENDED_AUDIO static unsigned int time_startup_msg; #endif if(GUI_IsModal()) return; // u8 step = 5; if ( 0 == time ) { time = CLOCK_getms() + Transmitter.splash_delay * 100; #if HAS_EXTENDED_AUDIO time_startup_msg = CLOCK_getms() + 5 * 100; // Dealy 0.5 second to play startup audio #endif } #if HAS_EXTENDED_AUDIO if (time_startup_msg && (CLOCK_getms() > time_startup_msg) ) { AUDIO_SetVolume(); MUSIC_Play(MUSIC_STARTUP); time_startup_msg = 0; } #endif if ( CLOCK_getms() > time ) PAGE_ChangeByID(PAGEID_MAIN,0); /* if ( offset > 0 ) { offset -= step; GUI_ChangeImage(&gui->splash_image,SPLASH_FILE,offset,0); GUI_Redraw(&gui->splash_image); }*/ }
void TIMER_Power(){ static u32 timer = 0; u32 alert = Transmitter.power_alarm * 60 * 1000; static u16 throttle; u16 new_throttle; u16 elevator; unsigned mode = MODE_2 == Transmitter.mode || MODE_4 == Transmitter.mode ? 2 : 1; if( 0 == timer) timer = CLOCK_getms() + alert; elevator = 2 == mode ? abs(CHAN_ReadInput(INP_THROTTLE)) : abs(CHAN_ReadInput(INP_ELEVATOR)); new_throttle = 2 == mode ? abs(CHAN_ReadInput(INP_ELEVATOR)) : abs(CHAN_ReadInput(INP_THROTTLE)); new_throttle = abs(new_throttle - throttle); if( elevator < 1000 && abs(CHAN_ReadInput(INP_AILERON)) < 1000 && new_throttle < 1000 && abs(CHAN_ReadInput(INP_RUDDER)) < 1000 && !ScanButtons() && (!HAS_TOUCH || !SPITouch_IRQ()) ) { if ( CLOCK_getms() > timer ) { timer = CLOCK_getms() + 2000; MUSIC_Play(MUSIC_SHUTDOWN); } } else timer = CLOCK_getms() + alert; throttle = 2 == mode ? abs(CHAN_ReadInput(INP_ELEVATOR)) : abs(CHAN_ReadInput(INP_THROTTLE)); }
void debug_timing(u32 type, int startend) { static u32 last_time[2][100]; static u32 loop_time[4][101]; static u32 loop_pos[4] = {-1, -1, -1, -1}; static u32 max_last[2]; static u32 max_loop[4]; static int save_priority; if (type == 0) { if (! startend) save_priority = priority_ready; if (save_priority & (1 << MEDIUM_PRIORITY)) debug_timing(2, startend); if (save_priority & (1 << LOW_PRIORITY)) debug_timing(1, startend); return; } type--; if (! startend) { u32 t = CLOCK_getms(); loop_pos[type] = (loop_pos[type] + 1) % 100; if (type < 2) { last_time[type][loop_pos[type]] = t; if (t - last_time[type][(loop_pos[type] + 99) % 100] > max_last[type]) max_last[type] = t - last_time[type][(loop_pos[type] + 99) % 100]; } loop_time[type][100] = t; } else { loop_time[type][loop_pos[type]] = CLOCK_getms() - loop_time[type][100]; if (loop_time[type][loop_pos[type]] > max_loop[type]) max_loop[type] = loop_time[type][loop_pos[type]]; if (type == 0 && loop_pos[0] == 99) { unsigned avg_loop[4] = {0, 0, 0, 0}; unsigned avg_last[2] = {0, 0}; for(int i = 0; i < 99; i++) { for(int t = 0; t < 2; t++) { u32 delay = last_time[t][(i + loop_pos[t] + 2) % 100] - last_time[t][(i + loop_pos[t] + 1) % 100]; avg_last[t] += delay; } for(int t = 0; t < 4; t++) avg_loop[t] += loop_time[t][i]; } for(int t = 0; t < 4; t++) avg_loop[t] /= 99; avg_last[0] /= 99; avg_last[1] /= 99; printf("Avg: radio: %d mix: %d med: %d/%d low: %d/%d\n", avg_loop[3], avg_loop[2], avg_loop[1], avg_last[1], avg_loop[0], avg_last[0]); printf("Max: radio: %d mix: %d med: %d/%d low: %d/%d\n", max_loop[3], max_loop[2], max_loop[1], max_last[1], max_loop[0], max_last[0]); memset(max_loop, 0, sizeof(max_loop)); max_last[0] = 0; max_last[1] = 0; } } }
void PAGE_DatalogEvent() { if((u16)(CLOCK_getms() / 1000) > next_update) { u32 left = DATALOG_Remaining(); if(remaining != left) { remaining = left; next_update = (u16)(CLOCK_getms() / 1000) + 5; GUI_Redraw(&gui->remaining); } } }
void EventLoop() { CLOCK_ResetWatchdog(); unsigned int time; #ifdef HEAP_DEBUG static int heap = 0; int h = _sbrk_r(NULL, 0); if(h > heap) { printf("heap: %x\n", h); heap = h; } #endif #ifdef TIMING_DEBUG debug_timing(0, 0); #endif priority_ready &= ~(1 << MEDIUM_PRIORITY); if(PWR_CheckPowerSwitch()) { if(! (BATTERY_Check() & BATTERY_CRITICAL)) { CONFIG_SaveModelIfNeeded(); CONFIG_SaveTxIfNeeded(); } if(Transmitter.music_shutdown) { MUSIC_Play(MUSIC_SHUTDOWN); // We wait ~1sec for shutdown music finished time = CLOCK_getms()+700; while(CLOCK_getms()<time); } PWR_Shutdown(); } BUTTON_Handler(); TOUCH_Handler(); if (priority_ready & (1 << LOW_PRIORITY)) { priority_ready &= ~(1 << LOW_PRIORITY); PAGE_Event(); PROTOCOL_CheckDialogs(); TIMER_Update(); TELEMETRY_Alarm(); BATTERY_Check(); AUTODIMMER_Update(); #if DATALOG_ENABLED DATALOG_Update(); #endif GUI_RefreshScreen(); } #ifdef TIMING_DEBUG debug_timing(0, 1); #endif }
static void _check_voltage(guiLabel_t *obj) { if (CLOCK_getms() > next_scan) { // don't need to check battery too frequently, to avoid blink of the battery label next_scan = CLOCK_getms() + BATTERY_SCAN_MSEC; s16 batt = PWR_ReadVoltage(); if (batt < Transmitter.batt_alarm) { obj->desc.style = LABEL_INVERTED; GUI_Redraw(obj); } if (batt / 10 != mp->battery / 10 && batt / 10 != mp->battery / 10 + 1) { mp->battery = batt; GUI_Redraw(obj); } } }
void PAGE_SplashEvent() { static unsigned int time=0; if(GUI_IsModal()) return; // u8 step = 5; if ( 0 == time ) time = CLOCK_getms() + Transmitter.splash_delay * 100; if ( CLOCK_getms() > time ) PAGE_ChangeByID(PAGEID_MAIN,0); /* if ( offset > 0 ) { offset -= step; GUI_ChangeImage(&gui->splash_image,SPLASH_FILE,offset,0); GUI_Redraw(&gui->splash_image); }*/ }
u32 PROTOCOL_Binding() { if (proto_state & PROTO_BINDING) { if (bind_time == 0xFFFFFFFF) return bind_time; s32 tmp = bind_time - CLOCK_getms(); return tmp > 0 ? tmp : 1; } return 0; }
void BUTTON_Handler() { static u32 last_buttons = 0; static u32 last_buttons_pressed = 0; static u32 long_press_at = 0; static u8 longpress_release = 0; static u32 last_button_time = 0; u32 ms = CLOCK_getms(); //debounce if (ms < last_button_time) return; u32 buttons = ScanButtons(); u32 buttons_pressed= buttons & (~last_buttons); u32 buttons_released=(~buttons) & last_buttons; if (buttons != last_buttons) last_button_time = ms; if(buttons_pressed && !longpress_release) { //printf("pressed: %08d\n", buttons_pressed); AUTODIMMER_Check(); exec_callbacks(buttons_pressed, BUTTON_PRESS); last_buttons_pressed = buttons_pressed; long_press_at = ms+500; longpress_release = 0; interrupt_longpress = 0; } if(buttons_released) { //printf("release: %08d\n", buttons_released); interrupt_longpress = 0; longpress_release = 0; if(!longpress_release) { exec_callbacks(buttons_released, BUTTON_RELEASE); } else { exec_callbacks(buttons_released, BUTTON_RELEASE | BUTTON_HAD_LONGPRESS); } } if(buttons && (buttons == last_buttons) && !interrupt_longpress) { if(ms > long_press_at) { //printf("long_press: %08d\n", buttons_released); exec_callbacks(last_buttons_pressed, BUTTON_LONGPRESS); longpress_release=1; long_press_at += 100; } } last_buttons=buttons; }
void TIMER_StartStop(unsigned timer) { if (Model.timer[timer].type == TIMER_STOPWATCH_PROP || Model.timer[timer].type == TIMER_COUNTDOWN_PROP) { return; } timer_state[timer] ^= 1; if(timer_state[timer]) { last_time[timer] = CLOCK_getms(); } }
void PROTOCOL_SetBindState(u32 msec) { if (msec) { if (msec == 0xFFFFFFFF) bind_time = msec; else bind_time = CLOCK_getms() + msec; proto_state |= PROTO_BINDING; PROTOCOL_SticksMoved(1); //Initialize Stick position } else { proto_state &= ~PROTO_BINDING; } }
void TOUCH_Handler() { if(! HAS_TOUCH) return; u32 pen_down=0; static u32 pen_down_last=0; static u32 pen_down_long_at=0; struct touch t; if(SPITouch_IRQ()) { pen_down=1; t=SPITouch_GetCoords(); if (! pen_down_last) pen_down_long_at=CLOCK_getms()+500; } else { pen_down=0; } if(pen_down && (!pen_down_last)) { AUTODIMMER_Check(); GUI_CheckTouch(&t, 0); } if(!pen_down && pen_down_last) { GUI_TouchRelease(); } if(pen_down && pen_down_last) { if(CLOCK_getms()>pen_down_long_at) { GUI_CheckTouch(&t, 1); pen_down_long_at += 100; } } pen_down_last=pen_down; }
/* * Main page * KEY_UP: Press once to start timers, press again to stop timers * KEY_DOWN: Press to rest timers * KEY_ENT: enter the main menu page */ void PAGE_MainInit(int page) { (void)page; (void)bar_cb; TGLICO_LoadFonts(); memset(mp, 0, sizeof(struct main_page));// Bug fix: must initialize this structure to avoid unpredictable issues in the PAGE_MainEvent memset(gui, 0, sizeof(struct mainpage_obj)); PAGE_SetModal(0); PAGE_SetActionCB(_action_cb); next_scan = CLOCK_getms()+BATTERY_SCAN_MSEC; GUI_CreateLabelBox(&gui->name, MODEL_NAME_X, MODEL_NAME_Y, //64, 12, LCD_WIDTH, LINE_HEIGHT, &MODELNAME_FONT, NULL, NULL, Model.name); show_elements(); //Battery mp->battery = PWR_ReadVoltage(); }
/* * Main page * KEY_UP: Press once to start timers, press again to stop timers * KEY_DOWN: Press to rest timers * KEY_ENT: enter the main menu page */ void PAGE_MainInit(int page) { (void)page; (void)bar_cb; memset(mp, 0, sizeof(struct main_page));// Bug fix: must initialize this structure to avoid unpredictable issues in the PAGE_MainEvent memset(gui, 0, sizeof(struct mainpage_obj)); PAGE_SetModal(0); PAGE_SetActionCB(_action_cb); PAGE_RemoveAllObjects(); next_scan = CLOCK_getms()+BATTERY_SCAN_MSEC; GUI_CreateLabelBox(&gui->name, 0, 1, //64, 12, 0, 0, &SMALL_FONT, NULL, NULL, Model.name); show_elements(); //Battery mp->battery = PWR_ReadVoltage(); }
void TIMER_Reset(unsigned timer) { if (Model.timer[timer].type == TIMER_STOPWATCH_PROP || Model.timer[timer].type == TIMER_COUNTDOWN_PROP) { timer_state[timer] = 1; last_time[timer] = CLOCK_getms(); } else { timer_state[timer] = 0; } if (Model.timer[timer].type == TIMER_STOPWATCH || Model.timer[timer].type == TIMER_STOPWATCH_PROP) { timer_val[timer] = 0; } else if(Model.timer[timer].type == TIMER_COUNTDOWN || Model.timer[timer].type == TIMER_COUNTDOWN_PROP) { timer_val[timer] = Model.timer[timer].timer * 1000; } else if(Model.timer[timer].type == TIMER_PERMANENT ) { timer_val[timer] = Model.timer[timer].val; } }
u32 ROTARY_Scan() { int last_rotary; u32 result = 0; result |= !GPIO_pin_get(ROTARY_PRESS_PIN) ? CHAN_ButtonMask(BUT_ENTER) : 0; last_rotary = rotary; if (last_rotary) { u32 rotary_clock = CLOCK_getms(); // To prevent rotary to generate button clicks too frequently we register // an event in 'result' not more often than every ROTARY_TIMEOUT msec if (rotary_clock > last_rotary_clock) { result |= last_rotary > 0 ? CHAN_ButtonMask(BUT_DOWN) : CHAN_ButtonMask(BUT_UP); last_rotary_clock = rotary_clock + ROTARY_TIMEOUT; } rotary = 0; } return result; }
void EventLoop() { CLOCK_ResetWatchdog(); #ifdef HEAP_DEBUG static int heap = 0; int h = _sbrk_r(NULL, 0); if(h > heap) { printf("heap: %x\n", h); heap = h; } #endif #ifdef TIMING_DEBUG debug_timing(0, 0); #endif priority_ready &= ~(1 << MEDIUM_PRIORITY); #if !HAS_HARD_POWER_OFF if(PWR_CheckPowerSwitch()) { if(! (BATTERY_Check() & BATTERY_CRITICAL)) { PAGE_Test(); CONFIG_SaveModelIfNeeded(); CONFIG_SaveTxIfNeeded(); } if(Transmitter.music_shutdown) { #if HAS_EXTENDED_AUDIO if(AUDIO_VoiceAvailable()) { MUSIC_Play(MUSIC_SHUTDOWN); while (CLOCK_getms() < audio_queue_time) { // Wait for voice to finished CLOCK_ResetWatchdog(); } } else { #else { // We wait ~1sec for shutdown buzzer music finished unsigned int time; MUSIC_Play(MUSIC_SHUTDOWN); time = CLOCK_getms()+700; while (CLOCK_getms() < time) { CLOCK_ResetWatchdog(); } #endif } } PWR_Shutdown(); } #endif BUTTON_Handler(); TOUCH_Handler(); INPUT_CheckChanges(); if (priority_ready & (1 << LOW_PRIORITY)) { priority_ready &= ~(1 << LOW_PRIORITY); PAGE_Event(); PROTOCOL_CheckDialogs(); TIMER_Update(); TELEMETRY_Alarm(); BATTERY_Check(); AUTODIMMER_Update(); #if HAS_DATALOG DATALOG_Update(); #endif #if HAS_VIDEO VIDEO_Update(); #endif #if HAS_EXTENDED_AUDIO AUDIO_CheckQueue(); #endif GUI_RefreshScreen(); #if HAS_HARD_POWER_OFF if (PAGE_ModelDoneEditing()) CONFIG_SaveModelIfNeeded(); CONFIG_SaveTxIfNeeded(); #endif } #ifdef TIMING_DEBUG debug_timing(0, 1); #endif } void TOUCH_Handler() { if(! HAS_TOUCH) return; u32 pen_down=0; static u32 pen_down_last=0; static u32 pen_down_long_at=0; struct touch t; if(SPITouch_IRQ()) { pen_down=1; t=SPITouch_GetCoords(); if (! pen_down_last) pen_down_long_at=CLOCK_getms()+500; } else { pen_down=0; } if(pen_down && (!pen_down_last)) { AUTODIMMER_Check(); GUI_CheckTouch(&t, 0); } if(!pen_down && pen_down_last) { GUI_TouchRelease(); } if(pen_down && pen_down_last) { if(CLOCK_getms()>pen_down_long_at) { GUI_CheckTouch(&t, 1); pen_down_long_at += 100; } } pen_down_last=pen_down; } #if HAS_VIDEO void VIDEO_Update() { static u8 video_enable = 0; static u32 check_standard_ms = 0; // Check if Video is turn on int enabled = MIXER_SourceAsBoolean(Model.videosrc); if (enabled != video_enable) { VIDEO_Enable(enabled); video_enable = enabled; if (enabled) { VIDEO_SetChannel(Model.videoch); VIDEO_Contrast(Model.video_contrast); VIDEO_Brightness(Model.video_brightness); check_standard_ms = CLOCK_getms() + 3000; } else check_standard_ms = 0; } if(video_enable && check_standard_ms > 0 && check_standard_ms < CLOCK_getms()) { u8 video_standard_current = VIDEO_GetStandard(); if((video_standard_current > 0) && (video_standard_current < 8)) { VIDEO_SetStandard(video_standard_current); check_standard_ms = 0; } else { check_standard_ms = CLOCK_getms() + 3000; } } if(video_enable) AUTODIMMER_Check(); } #endif //HAS_VIDEO #ifdef TIMING_DEBUG void debug_timing(u32 type, int startend) { static u32 last_time[2][100]; static u32 loop_time[4][101]; static u32 loop_pos[4] = {-1, -1, -1, -1}; static u32 max_last[2]; static u32 max_loop[4]; static int save_priority; if (type == 0) { if (! startend) save_priority = priority_ready; if (save_priority & (1 << MEDIUM_PRIORITY)) debug_timing(2, startend); if (save_priority & (1 << LOW_PRIORITY)) debug_timing(1, startend); return; } type--; if (! startend) { u32 t = CLOCK_getms(); loop_pos[type] = (loop_pos[type] + 1) % 100; if (type < 2) { last_time[type][loop_pos[type]] = t; if (t - last_time[type][(loop_pos[type] + 99) % 100] > max_last[type]) max_last[type] = t - last_time[type][(loop_pos[type] + 99) % 100]; } loop_time[type][100] = t; } else { loop_time[type][loop_pos[type]] = CLOCK_getms() - loop_time[type][100]; if (loop_time[type][loop_pos[type]] > max_loop[type]) max_loop[type] = loop_time[type][loop_pos[type]]; if (type == 0 && loop_pos[0] == 99) { unsigned avg_loop[4] = {0, 0, 0, 0}; unsigned avg_last[2] = {0, 0}; for(int i = 0; i < 99; i++) { for(int t = 0; t < 2; t++) { u32 delay = last_time[t][(i + loop_pos[t] + 2) % 100] - last_time[t][(i + loop_pos[t] + 1) % 100]; avg_last[t] += delay; } for(int t = 0; t < 4; t++) avg_loop[t] += loop_time[t][i]; } for(int t = 0; t < 4; t++) avg_loop[t] /= 99; avg_last[0] /= 99; avg_last[1] /= 99; printf("Avg: radio: %d mix: %d med: %d/%d low: %d/%d\n", avg_loop[3], avg_loop[2], avg_loop[1], avg_last[1], avg_loop[0], avg_last[0]); printf("Max: radio: %d mix: %d med: %d/%d low: %d/%d\n", max_loop[3], max_loop[2], max_loop[1], max_last[1], max_loop[0], max_last[0]); memset(max_loop, 0, sizeof(max_loop)); max_last[0] = 0; max_last[1] = 0; } } } #endif void debug_switches() { s32 data[INP_LAST]; for(int i = INP_HAS_CALIBRATION+1; i < INP_LAST; i++) { data[i] = CHAN_ReadRawInput(i); } while(1) { u32 changed = 0; for(int i = INP_HAS_CALIBRATION+1; i < INP_LAST; i++) { s32 val = CHAN_ReadRawInput(i); if (val != data[i]) { printf("%s=%d ", INPUT_SourceName(tempstring, i), val); data[i] = val; changed = 1; } } if (changed) { printf("\n"); } if(PWR_CheckPowerSwitch()) PWR_Shutdown(); } }
int main() { Init(); #ifndef ENABLE_MODULAR //Banner(); #endif if(PWR_CheckPowerSwitch()) PWR_Shutdown(); LCD_Clear(0x0000); #ifdef TEST_ADC ADC_ScanChannels(); while(1); #endif u32 buttons = ScanButtons(); if (CHAN_ButtonIsPressed(buttons, BUT_ENTER) || !FS_Init()) { LCD_DrawUSBLogo(LCD_WIDTH, LCD_HEIGHT); USB_Connect(); LCD_Clear(0x0000); FS_Init(); } CONFIG_LoadTx(); SPI_ProtoInit(); CONFIG_ReadDisplay(); CONFIG_ReadModel(CONFIG_GetCurrentModel()); CONFIG_ReadLang(Transmitter.language); BACKLIGHT_Brightness(Transmitter.backlight); LCD_Contrast(Transmitter.contrast); LCD_SetFont(DEFAULT_FONT.font); LCD_SetFontColor(DEFAULT_FONT.font_color); GUI_HandleButtons(1); MIXER_Init(); PAGE_Init(); CLOCK_StartWatchdog(); #if HAS_DATALOG DATALOG_Init(); #endif priority_ready = 0; CLOCK_SetMsecCallback(LOW_PRIORITY, LOW_PRIORITY_MSEC); CLOCK_SetMsecCallback(MEDIUM_PRIORITY, MEDIUM_PRIORITY_MSEC); // We need to wait until we've actually measured the ADC before proceeding while(! (priority_ready & (1 << LOW_PRIORITY))) PWR_Sleep(); //Only do this after we've initialized all channel data so the saftey works PROTOCOL_InitModules(); GUI_DrawScreen(); // Add startup delay to make sure audio player is initialized // AUDIO_Init() has already been called by CONFIG_ReadModel() #if HAS_EXTENDED_AUDIO audio_queue_time = CLOCK_getms() + 1500; num_audio=1; next_audio=1; #if (LCD_WIDTH == 480) || (LCD_WIDTH == 320) if(Display.background.drawn_background) while(CLOCK_getms() < audio_queue_time - 1200); #endif AUDIO_SetVolume(); // Initial setting of voice volume #endif MUSIC_Play(MUSIC_STARTUP); #ifdef HAS_EVENT_LOOP start_event_loop(); #else while(1) { if(priority_ready) { EventLoop(); } //This does not appear to have any impact on power //and has been disabled in common/devo/power.c //but it helps a huge amount for the emulator PWR_Sleep(); } #endif }
static int hubsan_init() { u8 if_calibration1; u8 vco_calibration0; u8 vco_calibration1; //u8 vco_current; A7105_WriteID(0x55201041); A7105_WriteReg(A7105_01_MODE_CONTROL, 0x63); A7105_WriteReg(A7105_03_FIFOI, 0x0f); A7105_WriteReg(A7105_0D_CLOCK, 0x05); A7105_WriteReg(A7105_0E_DATA_RATE, 0x04); A7105_WriteReg(A7105_15_TX_II, 0x2b); A7105_WriteReg(A7105_18_RX, 0x62); A7105_WriteReg(A7105_19_RX_GAIN_I, 0x80); A7105_WriteReg(A7105_1C_RX_GAIN_IV, 0x0A); A7105_WriteReg(A7105_1F_CODE_I, 0x07); A7105_WriteReg(A7105_20_CODE_II, 0x17); A7105_WriteReg(A7105_29_RX_DEM_TEST_I, 0x47); A7105_Strobe(A7105_STANDBY); //IF Filter Bank Calibration A7105_WriteReg(0x02, 1); //vco_current = A7105_ReadReg(0x02); u32 ms = CLOCK_getms(); CLOCK_ResetWatchdog(); while(CLOCK_getms() - ms < 500) { if(! A7105_ReadReg(0x02)) break; } if (CLOCK_getms() - ms >= 500) { DEBUG_MSG("calibration failed"); return 0; } if_calibration1 = A7105_ReadReg(A7105_22_IF_CALIB_I); A7105_ReadReg(A7105_24_VCO_CURCAL); if(if_calibration1 & A7105_MASK_FBCF) { //Calibration failed...what do we do? return 0; } //VCO Current Calibration //A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet //VCO Bank Calibration //A7105_WriteReg(0x26, 0x3b); //Recomended limits from A7105 Datasheet //VCO Bank Calibrate channel 0? //Set Channel A7105_WriteReg(A7105_0F_CHANNEL, 0); //VCO Calibration A7105_WriteReg(0x02, 2); ms = CLOCK_getms(); CLOCK_ResetWatchdog(); while(CLOCK_getms() - ms < 500) { if(! A7105_ReadReg(0x02)) break; } if (CLOCK_getms() - ms >= 500) { return 0; } vco_calibration0 = A7105_ReadReg(A7105_25_VCO_SBCAL_I); if (vco_calibration0 & A7105_MASK_VBCF) { //Calibration failed...what do we do? return 0; } //Calibrate channel 0xa0? //Set Channel A7105_WriteReg(A7105_0F_CHANNEL, 0xa0); //VCO Calibration A7105_WriteReg(A7105_02_CALC, 2); ms = CLOCK_getms(); CLOCK_ResetWatchdog(); while(CLOCK_getms() - ms < 500) { if(! A7105_ReadReg(A7105_02_CALC)) break; } if (CLOCK_getms() - ms >= 500) return 0; vco_calibration1 = A7105_ReadReg(A7105_25_VCO_SBCAL_I); if (vco_calibration1 & A7105_MASK_VBCF) { //Calibration failed...what do we do? } //Reset VCO Band calibration //A7105_WriteReg(0x25, 0x08); A7105_SetTxRxMode(TX_EN); A7105_SetPower(Model.tx_power); A7105_Strobe(A7105_STANDBY); return 1; }
//#define DEBUG_TELEMALARM void TELEMETRY_Alarm() { //Update 'updated' state every time we get here u32 current_time = CLOCK_getms(); if (current_time - last_time > TELEM_ERROR_TIME) { last_time = current_time; for(int i = 0; i < TELEM_UPDATE_SIZE; i++) { last_updated[i] = Telemetry.updated[i]; Telemetry.updated[i] = 0; } } // don't need to check all the 6 telem-configs at one time, this is not a critical and urgent task // instead, check 1 of them at a time telem_idx = (telem_idx + 1) % TELEM_NUM_ALARMS; if(! Model.telem_alarm[telem_idx]) { alarm &= ~(1 << telem_idx); // clear this set return; } u8 idx = Model.telem_alarm[telem_idx]; s32 value = TELEMETRY_GetValue(idx); if (value == 0) { alarm &= ~(1 << telem_idx); // clear this set return; } if (! TELEMETRY_IsUpdated(0xff)) { // bug fix: do not alarm when no telem packet is received, it might caused by RX is powered off alarm &= ~(1 << telem_idx); // clear this set return; } if (Model.telem_flags & (1 << telem_idx)) { if (! (alarm & (1 << telem_idx)) && (value <= Model.telem_alarm_val[telem_idx])) { if (alarm_duration[telem_idx] == 0) { alarm_duration[telem_idx] = current_time; } else if (current_time - alarm_duration[telem_idx] > CHECK_DURATION) { alarm_duration[telem_idx] = 0; alarm |= 1 << telem_idx; #ifdef DEBUG_TELEMALARM printf("set: 0x%x\n\n", alarm); #endif } } else if ((alarm & (1 << telem_idx)) && (value > (s32)Model.telem_alarm_val[telem_idx])) { if (alarm_duration[telem_idx] == 0) { alarm_duration[telem_idx] = current_time; } else if (current_time - alarm_duration[telem_idx] > CHECK_DURATION) { alarm_duration[telem_idx] = 0; alarm &= ~(1 << telem_idx); #ifdef DEBUG_TELEMALARM printf("clear: 0x%x\n\n", alarm); #endif } } else alarm_duration[telem_idx] = 0; } else { if (! (alarm & (1 << telem_idx)) && (value >= Model.telem_alarm_val[telem_idx])) { if (alarm_duration[telem_idx] == 0) { alarm_duration[telem_idx] = current_time; } else if (current_time - alarm_duration[telem_idx] > CHECK_DURATION) { alarm_duration[telem_idx] = 0; alarm |= 1 << telem_idx; #ifdef DEBUG_TELEMALARM printf("set: 0x%x\n\n", alarm); #endif } } else if ((alarm & (1 << telem_idx)) && (value < (s32)Model.telem_alarm_val[telem_idx])) { if (alarm_duration[telem_idx] == 0) { alarm_duration[telem_idx] = current_time; } else if (current_time - alarm_duration[telem_idx] > CHECK_DURATION) { alarm_duration[telem_idx] = 0; alarm &= ~(1 << telem_idx); #ifdef DEBUG_TELEMALARM printf("clear: 0x%x\n\n", alarm); #endif } } else alarm_duration[telem_idx] = 0; } if ((alarm & (1 << telem_idx))) { if (current_time >= alarm_time + MUSIC_INTERVAL) { alarm_time = current_time; #ifdef DEBUG_TELEMALARM printf("beep: %d\n\n", telem_idx); #endif MUSIC_Play(MUSIC_TELEMALARM1 + telem_idx); } } }
unsigned MIXER_UpdateTrim(u32 buttons, unsigned flags, void *data) { #define TRIM_MUSIC_DURATION 100 #define START_TONE 1000 (void)data; int i; int orig_step_size = 1; int tmp; unsigned reach_end = 0; // reach either 100 , 0, or -100 if (flags & BUTTON_LONGPRESS) { if (orig_step_size == 1) orig_step_size = 9; else if (orig_step_size == 9) orig_step_size = 10; } if (! orig_step_size) return 1; unsigned volume = 10 * Transmitter.volume; for (i = 0; i < NUM_TRIMS; i++) { int step_size = orig_step_size; reach_end = 0; int neg_button = CHAN_ButtonIsPressed(buttons, Model.trims[i].neg); if (neg_button || CHAN_ButtonIsPressed(buttons, Model.trims[i].pos)) { if (Model.trims[i].step > 190) { _trim_as_switch(flags, i, neg_button); continue; } if (flags & BUTTON_RELEASE) continue; int max = 100; if (Model.trims[i].step >= 100) { step_size = Model.trims[i].step - 90; } else if (Model.trims[i].step > 10) { step_size = step_size * Model.trims[i].step / 10; } if (neg_button) step_size = -step_size; s8 *value = MIXER_GetTrim(i); tmp = (int)(*value) + step_size; //print_buttons(buttons); if ((int)*value > 0 && tmp <= 0) { *value = 0; reach_end = 1; } else if ((int)*value < 0 && tmp >= 0) { *value = 0; reach_end = 1; } else if (tmp > max) { *value = 100; reach_end = 1; } else if (tmp < -max) { *value = -100; reach_end = 1; } else { *value = tmp; } if (reach_end && (flags & BUTTON_LONGPRESS)) BUTTON_InterruptLongPress(); if (Model.trims[i].value[0] == 0) { SOUND_SetFrequency(3951, volume); SOUND_StartWithoutVibrating(TRIM_MUSIC_DURATION, NULL); } else if (CLOCK_getms()- last_trim_music_time > TRIM_MUSIC_DURATION + 50) { // Do not beep too frequently last_trim_music_time = CLOCK_getms(); tmp = (*value >= 0) ? *value : -*value; if (step_size >=9 || step_size <= -9) SOUND_SetFrequency(START_TONE + tmp * 10, volume); // start from "c2" tone, frequence = 1000 else { // for small step change: generate 2 different tone for closing to/away from mid-point if (*value < 0) step_size = -step_size; u16 tone = START_TONE + 300; if (step_size < 0) tone = START_TONE; SOUND_SetFrequency(tone, volume); //printf("tone: %d\n\n", tone); } SOUND_StartWithoutVibrating(TRIM_MUSIC_DURATION, NULL); } } } return 1; }
void TIMER_Update() { unsigned i; unsigned chan_val = 0; u32 t = CLOCK_getms(); if (PROTOCOL_WaitingForSafe()) return; if( Transmitter.power_alarm > 0 ) TIMER_Power(); for (i = 0; i < NUM_TIMERS; i++) { if (Model.timer[i].src) { s16 val; if (MIXER_SRC(Model.timer[i].src) <= NUM_INPUTS) { volatile s16 *raw = MIXER_GetInputs(); val = raw[MIXER_SRC(Model.timer[i].src)]; } else { val = MIXER_GetChannel(Model.timer[i].src - NUM_INPUTS - 1, APPLY_SAFETY); } if (MIXER_SRC_IS_INV(Model.timer[i].src)) val = -val; if (Model.timer[i].type == TIMER_STOPWATCH_PROP || Model.timer[i].type == TIMER_COUNTDOWN_PROP) { chan_val = RANGE_TO_PCT(abs(val)); if (chan_val > 100) chan_val = 100; } else { unsigned new_state = (val - CHAN_MIN_VALUE > (CHAN_MAX_VALUE - CHAN_MIN_VALUE) / 20) ? 1 : 0; if (new_state != timer_state[i]) { if (new_state) last_time[i] = t; timer_state[i] = new_state; } } } if (timer_state[i]) { s32 delta = t - last_time[i]; if (Model.timer[i].type == TIMER_STOPWATCH_PROP || Model.timer[i].type == TIMER_COUNTDOWN_PROP) { delta = delta * chan_val / 100; } if (Model.timer[i].type == TIMER_PERMANENT) { timer_val[i] += delta; if( timer_val[i] >= 359999900) // Reset when 99h59mn59sec timer_val[i] = 0 ; Model.timer[i].val = timer_val[i]; } else if (Model.timer[i].type == TIMER_STOPWATCH || Model.timer[i].type == TIMER_STOPWATCH_PROP) { timer_val[i] += delta; } else { s32 warn_time; // start to beep for each prealert_interval at the last prealert_time(seconds) if (Transmitter.countdown_timer_settings.prealert_time != 0 && Transmitter.countdown_timer_settings.prealert_interval != 0 && timer_val[i] > Transmitter.countdown_timer_settings.prealert_interval && timer_val[i] < (s32)Transmitter.countdown_timer_settings.prealert_time + 1000) { // give extra 1seconds warn_time = ((timer_val[i] / Transmitter.countdown_timer_settings.prealert_interval) * Transmitter.countdown_timer_settings.prealert_interval); if (timer_val[i] > warn_time && (timer_val[i] - delta) <= warn_time) { MUSIC_Play(MUSIC_TIMER_WARNING); } } // Beep once for each timeup_interval past 0 if (timer_val[i] < 0 && Transmitter.countdown_timer_settings.timeup_interval != 0) { warn_time = ((timer_val[i] - Transmitter.countdown_timer_settings.timeup_interval) / Transmitter.countdown_timer_settings.timeup_interval) * Transmitter.countdown_timer_settings.timeup_interval; if (timer_val[i] > warn_time && (timer_val[i] - delta) <= warn_time) { MUSIC_Play(MUSIC_ALARM1 + i); } } if (timer_val[i] >= 0 && timer_val[i] < delta) { MUSIC_Play(MUSIC_ALARM1 + i); } timer_val[i] -= delta; } last_time[i] = t; } if (Model.timer[i].resetsrc) { s16 val; if (MIXER_SRC(Model.timer[i].resetsrc) <= NUM_INPUTS) { volatile s16 *raw = MIXER_GetInputs(); val = raw[MIXER_SRC(Model.timer[i].resetsrc)]; } else { val = MIXER_GetChannel(Model.timer[i].resetsrc - NUM_INPUTS - 1, APPLY_SAFETY); } if (MIXER_SRC_IS_INV(Model.timer[i].resetsrc)) val = -val; if (val - CHAN_MIN_VALUE > (CHAN_MAX_VALUE - CHAN_MIN_VALUE) / 20) { TIMER_Reset(i); } } } }