void medium_priority_cb() { #ifdef TIMING_DEBUG debug_timing(3, 0); #endif MIXER_CalcChannels(); #ifdef TIMING_DEBUG debug_timing(3, 1); #endif }
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 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 }
/** * Decode panel information from the fdt, according to a standard binding * * @param blob fdt blob * @param node offset of fdt node to read from * @param config structure to store fdt config into * @return 0 if ok, -ve on error */ static int tegra_decode_panel(const void *blob, int node, struct fdt_disp_config *config) { int front, back, ref; config->width = fdtdec_get_int(blob, node, "xres", -1); config->height = fdtdec_get_int(blob, node, "yres", -1); config->pixel_clock = fdtdec_get_int(blob, node, "clock", 0); if (!config->pixel_clock || config->width == -1 || config->height == -1) { debug("%s: Pixel parameters missing\n", __func__); return -FDT_ERR_NOTFOUND; } back = fdtdec_get_int(blob, node, "left-margin", -1); front = fdtdec_get_int(blob, node, "right-margin", -1); ref = fdtdec_get_int(blob, node, "hsync-len", -1); if ((back | front | ref) == -1) { debug("%s: Horizontal parameters missing\n", __func__); return -FDT_ERR_NOTFOUND; } /* Use a ref-to-sync of 1 always, and take this from the front porch */ config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; config->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; config->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back; config->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC]; debug_timing("horiz", config->horiz_timing); back = fdtdec_get_int(blob, node, "upper-margin", -1); front = fdtdec_get_int(blob, node, "lower-margin", -1); ref = fdtdec_get_int(blob, node, "vsync-len", -1); if ((back | front | ref) == -1) { debug("%s: Vertical parameters missing\n", __func__); return -FDT_ERR_NOTFOUND; } config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; config->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; config->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back; config->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC]; debug_timing("vert", config->vert_timing); return 0; }
static int tegra_lcd_ofdata_to_platdata(struct udevice *dev) { struct tegra_lcd_priv *priv = dev_get_priv(dev); struct fdtdec_phandle_args args; const void *blob = gd->fdt_blob; int node = dev->of_offset; int front, back, ref; int panel_node; int rgb; int bpp, bit; int ret; priv->disp = (struct disp_ctlr *)dev_get_addr(dev); if (!priv->disp) { debug("%s: No display controller address\n", __func__); return -EINVAL; } rgb = fdt_subnode_offset(blob, node, "rgb"); panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); if (panel_node < 0) { debug("%s: Cannot find panel information\n", __func__); return -EINVAL; } priv->width = fdtdec_get_int(blob, panel_node, "xres", -1); priv->height = fdtdec_get_int(blob, panel_node, "yres", -1); priv->pixel_clock = fdtdec_get_int(blob, panel_node, "clock", 0); if (!priv->pixel_clock || priv->width == -1 || priv->height == -1) { debug("%s: Pixel parameters missing\n", __func__); return -EINVAL; } back = fdtdec_get_int(blob, panel_node, "left-margin", -1); front = fdtdec_get_int(blob, panel_node, "right-margin", -1); ref = fdtdec_get_int(blob, panel_node, "hsync-len", -1); if ((back | front | ref) == -1) { debug("%s: Horizontal parameters missing\n", __func__); return -EINVAL; } /* Use a ref-to-sync of 1 always, and take this from the front porch */ priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; priv->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; priv->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back; priv->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC]; debug_timing("horiz", priv->horiz_timing); back = fdtdec_get_int(blob, panel_node, "upper-margin", -1); front = fdtdec_get_int(blob, panel_node, "lower-margin", -1); ref = fdtdec_get_int(blob, panel_node, "vsync-len", -1); if ((back | front | ref) == -1) { debug("%s: Vertical parameters missing\n", __func__); return -EINVAL; } priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; priv->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; priv->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back; priv->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC]; debug_timing("vert", priv->vert_timing); bpp = fdtdec_get_int(blob, panel_node, "nvidia,bits-per-pixel", -1); bit = ffs(bpp) - 1; if (bpp == (1 << bit)) priv->log2_bpp = bit; else priv->log2_bpp = bpp; if (bpp == -1) { debug("%s: Pixel bpp parameters missing\n", __func__); return -EINVAL; } if (fdtdec_parse_phandle_with_args(blob, panel_node, "nvidia,pwm", "#pwm-cells", 0, 0, &args)) { debug("%s: Unable to decode PWM\n", __func__); return -EINVAL; } ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm); if (ret) { debug("%s: Unable to find PWM\n", __func__); return -EINVAL; } priv->pwm_channel = args.args[0]; priv->cache_type = fdtdec_get_int(blob, panel_node, "nvidia,cache-type", FDT_LCD_CACHE_WRITE_BACK_FLUSH); /* These GPIOs are all optional */ gpio_request_by_name_nodev(blob, panel_node, "nvidia,backlight-enable-gpios", 0, &priv->backlight_en, GPIOD_IS_OUT); gpio_request_by_name_nodev(blob, panel_node, "nvidia,lvds-shutdown-gpios", 0, &priv->lvds_shutdown, GPIOD_IS_OUT); gpio_request_by_name_nodev(blob, panel_node, "nvidia,backlight-vdd-gpios", 0, &priv->backlight_vdd, GPIOD_IS_OUT); gpio_request_by_name_nodev(blob, panel_node, "nvidia,panel-vdd-gpios", 0, &priv->panel_vdd, GPIOD_IS_OUT); if (fdtdec_get_int_array(blob, panel_node, "nvidia,panel-timings", priv->panel_timings, FDT_LCD_TIMINGS)) return -EINVAL; return 0; }
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(); } }