/*************************************************************************** * Copyright (c) 2003-2006, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: * * Revision History: * * $brcm_Log: $ * ***************************************************************************/ #include "bapp.h" #include "bgfx.h" #include "bstd.h" #ifndef LINUX #include "bos.h" #include "ministd.h" #include "cache_util.h" #define GETTIMEOFDAY(tv) gettimeofday(tv) #else #include #define GETTIMEOFDAY(tv) gettimeofday(tv,NULL) #endif #include "bchp_cce_prim.h" #include "bchp_hifidac_ctrl0.h" #if (BCHP_CHIP != 3543) #if (BCHP_CHIP == 7002) #else #include "bchp_aud_adp0.h" #endif #endif #if (BCHP_CHIP == 7002) #else #include "bchp_xpt_cfg.h" #endif #include "bchp_sun_top_ctrl.h" #include "bchp_sun_l2.h" #include "bsmart.h" #include "bchp_memc_ddr.h" #include "bchp_timer.h" #if (BCHP_CHIP == 3543) #include "bchp_memc_core.h" #include "bchp_aio_misc.h" #endif #include "bchp_pcm.h" BDBG_MODULE(bapp); /* Register software module with debug interface */ #define BAPP_VCHIP_TIMEOUT (7000) /* Milliseconds */ #define BAPP_RATINGS_EVAL_DELAY (500) /* Milliseconds */ #define DEFAULT_VOLUME 100 #define DEFAULT_RFM_VOLUME 70 #define BAPP_VCHIP_MSG BDBG_WRN #define TIME_APP_DRAWING static bgfx_font_t s_font[eFONT_SIZE_MAX]; typedef enum rsys_t { eRS_MPA, eRS_US, eRS_MPA_OLD, eRS_CANADIAN_ENGLISH, eRS_CANADIAN_FRENCH, eRS_RESERVED_0, eRS_RESERVED_1 }rsys_t; const static unsigned int s_remote_type_map[] = { 5, 4, 6, 0 }; const static char *s_rsys_name[] = { "MPA", "TV", "MPA", "CE", "CF", "R0", "R1" }; bapp_t *s_p_app = NULL; static bscreen_t g_screens[] = { /* title_text_id desc_text_id help_text_id top_banner_height num_buttons idle_timeout p_button_array (* draw)() (* handle_event)() local_state */ { eTEXT_MAX, eTEXT_MAX, eTEXT_MENU_HELP1, 0, 0, 0, 0, 0, eSCREEN_NULL, 0, bscreen_banner_draw, screen_banner_event, (uint32_t)&g_banner_state}, { eTEXT_MAIN_MENU, eTEXT_MAX, eTEXT_MENU_HELP1, eMENU_TITLE_AREA_HEIGHT_0_LINE, 0, 0, g_buttons_main_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_main, bscreen_default_draw, bscreen_default_event, 0}, { eTEXT_PICTURE_MENU, eTEXT_PICTURE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_picture_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_picture, bscreen_default_draw, screen_picture_event, 0}, { eTEXT_SOUND_MENU, eTEXT_SOUND_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_sound_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_sound, bscreen_default_draw, screen_sound_event, 0}, { eTEXT_AV_MENU, eTEXT_AV_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_av_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_av, bscreen_default_draw, bscreen_default_event, 0}, { eTEXT_ANTENNA_MENU, eTEXT_ANTENNA_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_antenna_draw, screen_antenna_event, 0}, { eTEXT_CAPTIONS_MENU, eTEXT_CAPTIONS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_captions_advanced_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_advanced, bscreen_default_draw, screen_captions_advanced_event, 0}, #if 0 { eTEXT_CAPTIONS_ON_OFF_MENU, eTEXT_CAPTIONS_ON_OFF_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_on_off_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_on_off, bscreen_default_draw, screen_captions_on_off_event, 0}, { eTEXT_CAPTIONS_BASIC_MENU, eTEXT_CAPTIONS_BASIC_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_basic_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_basic, bscreen_default_draw, screen_captions_basic_event, 0}, { eTEXT_CAPTIONS_ADVANCED_MENU, eTEXT_CAPTIONS_ADVANCED_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_advanced_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_advanced, bscreen_default_draw, screen_captions_advanced_event, 0}, #endif { eTEXT_CAPTIONS_FONT_OPTIONS_MENU,eTEXT_CAPTIONS_FONT_OPTIONS_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_options_num,SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_options,bscreen_default_draw, screen_captions_font_options_event, 0}, { eTEXT_CAPTIONS_BACK_OPTIONS_MENU,eTEXT_CAPTIONS_BACK_OPTIONS_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_back_options_num,SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_back_options,bscreen_default_draw, screen_captions_back_options_event, 0}, { eTEXT_CAPTIONS_FONT_MENU, eTEXT_CAPTIONS_FONT_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font, bscreen_default_draw, screen_captions_font_event, 0}, { eTEXT_CAPTIONS_FONT_SIZE_MENU, eTEXT_CAPTIONS_FONT_SIZE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_size_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_size, bscreen_default_draw, screen_captions_font_size_event, 0}, { eTEXT_CAPTIONS_FONT_STYLE_MENU, eTEXT_CAPTIONS_FONT_STYLE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_style_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_style, bscreen_default_draw, screen_captions_font_style_event, 0}, { eTEXT_CAPTIONS_FONT_COLOR_MENU, eTEXT_CAPTIONS_FONT_COLOR_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_color_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_color, bscreen_default_draw, screen_captions_font_color_event, 0}, { eTEXT_CAPTIONS_FONT_OPACITY_MENU,eTEXT_CAPTIONS_FONT_OPACITY_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_opacity_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_opacity,bscreen_default_draw, screen_captions_font_opacity_event, 0}, { eTEXT_CAPTIONS_BACK_COLOR_MENU, eTEXT_CAPTIONS_BACK_COLOR_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_color_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_color, bscreen_default_draw, screen_captions_back_color_event, 0}, { eTEXT_CAPTIONS_BACK_OPACITY_MENU,eTEXT_CAPTIONS_BACK_OPACITY_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_opacity_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_back_opacity,bscreen_default_draw, screen_captions_back_opacity_event, 0}, { eTEXT_CAPTIONS_EDGE_COLOR_MENU ,eTEXT_CAPTIONS_EDGE_COLOR_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_edge_color_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_edge_color, bscreen_default_draw, screen_captions_edge_color_event, 0}, { eTEXT_CAPTIONS_EDGE_TYPE_MENU ,eTEXT_CAPTIONS_EDGE_TYPE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_edge_type_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_edge_type, bscreen_default_draw, screen_captions_edge_type_event, 0}, { eTEXT_CAPTIONS_RESET_MENU, eTEXT_CAPTIONS_RESET_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_reset_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_reset, bscreen_default_draw, screen_captions_reset_event, 0}, { eTEXT_LANGUAGE_MENU, eTEXT_LANGUAGE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_language_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_language, bscreen_default_draw, screen_language_event, 0}, #ifdef CONFIG_EIA_708 { eTEXT_SETUP_MENU, eTEXT_SETUP_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE-4, 0, 0, g_buttons_setup_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_setup, bscreen_default_draw, screen_setup_event, 0}, #else { eTEXT_SETUP_MENU, eTEXT_SETUP_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_setup_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_setup, bscreen_default_draw, screen_setup_event, 0}, #endif { eTEXT_WIZ_CH_SCAN_MENU, eTEXT_WIZ_CH_SCAN_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_ch_scan_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ch_scan, bscreen_wiz_ch_scan_draw, screen_ch_scan_event, 0}, { eTEXT_WIZ_SMART_CH_SCAN_MENU, eTEXT_WIZ_SMART_CH_SCAN_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_smart_ch_scan_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_smart_ch_scan, bscreen_wiz_ch_scan_draw, screen_ch_scan_event, 0}, { eTEXT_CH_SCAN_PROGRESS_MENU, eTEXT_CH_SCAN_PROGRESS_MENU_DESC, eTEXT_MENU_HELP4, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_ch_scan_progress_draw, screen_ch_scan_progress_event, 0}, { eTEXT_RESET_MENU, eTEXT_RESET_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_reset_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_reset, bscreen_default_draw, screen_reset_event, 0}, { eTEXT_WIZ_WELCOME_MENU, eTEXT_WIZ_WELCOME_MENU_DESC, eTEXT_MENU_HELP3, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_wiz_welcome_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_welcome, bscreen_wiz_welcome_draw, screen_wiz_welcome_event, 0}, { eTEXT_WIZ_LANGUAGE_MENU, eTEXT_LANGUAGE_MENU_DESC, eTEXT_MENU_HELP8, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wiz_language_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_language, bscreen_default_draw, screen_wiz_language_event, 0}, { eTEXT_WIZ_CH_SCAN_MENU, eTEXT_WIZ_CH_SCAN_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_wiz_ch_scan_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_ch_scan, bscreen_wiz_ch_scan_draw, screen_wiz_ch_scan_event, 0}, { eTEXT_WIZ_SMART_CH_SCAN_MENU, eTEXT_WIZ_SMART_CH_SCAN_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_wiz_smart_ch_scan_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_smart_ch_scan, bscreen_wiz_ch_scan_draw, screen_wiz_ch_scan_event, 0}, { eTEXT_WIZ_PIN_NEW_MENU, eTEXT_WIZ_PIN_NEW_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_4_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_CONFIRM_MENU, eTEXT_PIN_CONFIRM_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_MISMATCHED_PINS_MENU, eTEXT_MISMATCHED_PINS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wiz_mismatched_pins_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_mismatched_pins, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_WIZ_DONE_MENU, eTEXT_WIZ_DONE_MENU_DESC, eTEXT_MENU_HELP6, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_wiz_done_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_done, bscreen_wiz_done_draw, screen_wiz_done_event, 0}, { eTEXT_AUTO_POWER_MENU, eTEXT_AUTO_POWER_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_auto_power_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_auto_power, bscreen_auto_power_draw, screen_auto_power_event, 0}, { eTEXT_RATINGS_MENU, eTEXT_RATINGS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_ratings_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings, bscreen_default_draw, screen_ratings_event, 0}, { eTEXT_RATINGS_LOCK_MENU, eTEXT_RATINGS_LOCK_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_lock_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_lock, bscreen_default_draw, screen_ratings_lock_event, 0}, { eTEXT_RATINGS_LIMITS_MENU, eTEXT_RATINGS_LIMITS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_ratings_limits_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_limits, bscreen_default_draw, screen_ratings_limits_event, 0}, { eTEXT_RATINGS_TV_MENU, eTEXT_RATINGS_TV_MENU_DESC, eTEXT_MENU_HELP10,eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_tv_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_tv, bscreen_default_draw, screen_ratings_tv_event, 0}, { eTEXT_RATINGS_MOVIES_MENU, eTEXT_RATINGS_MOVIES_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_movies_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_movies, bscreen_default_draw, screen_ratings_movies_event, 0}, { eTEXT_RATINGS_RRT_DIM_MENU, eTEXT_RATINGS_RRT_DIM_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, MAX_RRT_DIM_BUTTONS, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_rrt_dim, bscreen_rrt_dim_draw, screen_ratings_rrt_dim_event, 0}, { eTEXT_RATINGS_RRT_VAL_MENU, eTEXT_RATINGS_RRT_VAL_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, MAX_RRT_VAL_BUTTONS, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_rrt_val, bscreen_rrt_val_draw, screen_ratings_rrt_val_event, 0}, { eTEXT_RATINGS_RRT_UPDATE_MENU, eTEXT_RATINGS_RRT_UPDATE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_rrt_update_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_rrt_update, bscreen_default_draw, screen_ratings_rrt_update_event, 0}, { eTEXT_PIN_ENTER_MENU, eTEXT_PIN_ENTER_MENU_DESC, eTEXT_MENU_HELP9, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_ENTER_MENU, eTEXT_PIN_ENTER_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_ENTER_MENU, eTEXT_PIN_ENTER_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_NEW_MENU, eTEXT_PIN_NEW_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_CONFIRM_MENU, eTEXT_PIN_CONFIRM_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_WRONG_PIN_LIVE_MENU, eTEXT_WRONG_PIN_LIVE_MENU_DESC, eTEXT_MENU_HELP8, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wrong_pin_live_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wrong_pin_live, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_WRONG_PIN_MENU_MENU, eTEXT_WRONG_PIN_MENU_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wrong_pin_ratings_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wrong_pin_ratings, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_WRONG_PIN_MENU_MENU, eTEXT_WRONG_PIN_MENU_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wrong_pin_reset_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wrong_pin_reset, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_MISMATCHED_PINS_MENU, eTEXT_MISMATCHED_PINS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_mismatched_pins_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_mismatched_pins, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, BANNER_SMALL_TIMEOUT, eSCREEN_NULL, 0, bscreen_banner_draw, screen_banner_event, (uint32_t)&g_banner_state}, { eTEXT_GUIDE_TITLE, eTEXT_MAX, eTEXT_MENU_HELP11,eMENU_TITLE_AREA_HEIGHT_0_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_guide_draw, screen_guide_event, (uint32_t)&g_guide_state}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, 0, eSCREEN_NULL, 0, bscreen_screensaver_draw, screen_screensaver_event, (uint32_t)&g_screensaver_state}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, 0, eSCREEN_NULL, 0, bscreen_power_off_draw, screen_power_off_event, 0}, { eTEXT_TIMEZONE_MENU, eTEXT_TIMEZONE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_timezone_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_timezone, bscreen_default_draw, bscreen_timezone_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_status_draw, bscreen_status_event, 0}, #ifdef CONFIG_DTA_CABLE { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_debug_draw, bscreen_debug_event, 0}, #endif }; const unsigned char g_screens_num = sizeof(g_screens)/sizeof(g_screens[0]); #if (DEF_CH_MAP == 3) /* default channel production default channel map */ #warning "DEF_CH_MAP = 3" static const bapp_ch_t s_def_ch_map[] = { #if 0 {14,1,12,1,0x21,0x21,1,0,{0x24,0,0},{0x0046, 0x0065, 0x0067, 0x0084, 0x0045, 0x0049, 0x0052},0}, #else {18,1,16,1,0x21,0x21,3,0,{0x24,0x25,0},{0x004B, 0x0054, 0x004C, 0x0041, 0x002D, 0x0044, 0x0054},0}, #endif {2,1,0,1,0x21,0x21,1,0,{0x24,0,0},{0x0046, 0x0065, 0x0067, 0x0084, 0x0045, 0x0048, 0x0050},0}, {69,1,67,1,0x21,0x21,1,0,{0x24,0,0},{0x0046, 0x0065, 0x0067, 0x0084, 0x0045, 0x0054, 0x0057},0}, }; const unsigned char g_def_ch_num = sizeof(s_def_ch_map)/sizeof(s_def_ch_map[0]); #elif (DEF_CH_MAP == 2) /* default channel map in San Jose for testing purposes only */ #warning "DEF_CH_MAP = 2" static const bapp_ch_t s_def_ch_map[] = { {2,1,54,1,49,49,1,0,{52,0,0},{0x004b, 0x0054, 0x0056, 0x0055, 0x002d, 0x0044, 0x0054},0}, {4,1,55,1,49,49,1,0,{52,0,0},{0x004b, 0x0052, 0x004f, 0x004e, 0x002d, 0x0053, 0x0044},0}, {4,2,55,1,65,65,1,0,{68,0,0},{0x004b, 0x0052, 0x004f, 0x004e, 0x002d, 0x0048, 0x0044},0}, {5,1,27,0,49,49,1,0,{52,0,0},{0x004b, 0x0050, 0x0049, 0x0058, 0x002d, 0x0048, 0x0044},0}, {7,1,22,0,49,49,1,0,{52,0,0},{0x004b, 0x0047, 0x004f, 0x002d, 0x0044, 0x0054, 0x0020},0}, {7,2,22,0,65,65,1,0,{68,0,0},{0x004b, 0x0047, 0x004f, 0x002d, 0x0044, 0x0054, 0x0020},0}, {7,3,22,0,81,81,1,0,{84,0,0},{0x004b, 0x0047, 0x004f, 0x002d, 0x0044, 0x0054, 0x0020},0}, {9,1,28,0,49,49,1,0,{51,0,0},{0x004b, 0x0051, 0x0045, 0x0044, 0x002d, 0x0048, 0x0044},0}, {9,2,28,0,65,65,5,0,{67,0,68},{0x0045, 0x004e, 0x0043, 0x004f, 0x0052, 0x0045, 0x0000},0}, {9,3,28,0,81,81,5,0,{83,0,84},{0x0057, 0x004f, 0x0052, 0x004c, 0x0044, 0x0000, 0x0000},0}, {9,4,28,0,97,97,5,0,{99,0,100},{0x004c, 0x0049, 0x0046, 0x0045, 0x0000, 0x0000, 0x0000},0}, {9,5,28,0,113,113,5,0,{115,0,116},{0x004b, 0x0049, 0x0044, 0x0053, 0x0000, 0x0000, 0x0000},0}, {11,1,10,0,49,49,1,0,{52,0,0},{0x004b, 0x004e, 0x0054, 0x0056, 0x002d, 0x0048, 0x0044},0}, {11,2,10,0,65,65,1,0,{68,0,0},{0x004e, 0x0042, 0x0043, 0x0020, 0x0057, 0x0065, 0x0061},0}, {20,1,17,0,49,49,1,0,{52,0,0},{0x004b, 0x0042, 0x0057, 0x0042, 0x002d, 0x0048, 0x0044},0}, {20,2,17,0,65,65,1,0,{68,0,0},{0x004b, 0x0042, 0x0057, 0x0042, 0x002d, 0x0053, 0x0044},0}, {26,1,25,0,49,49,1,0,{52,0,0},{0x004b, 0x0054, 0x0053, 0x0046, 0x002d, 0x0044, 0x0031},0}, {26,2,25,0,49,49,1,0,{68,0,0},{0x004b, 0x0054, 0x0053, 0x0046, 0x002d, 0x0044, 0x0032},0}, {32,1,31,0,49,49,1,0,{52,0,0},{0x004b, 0x004d, 0x0054, 0x0050, 0x002d, 0x0044, 0x0031},0}, {32,2,31,0,65,65,1,0,{68,0,0},{0x004b, 0x004d, 0x0054, 0x0050, 0x002d, 0x0044, 0x0032},0}, {32,3,31,0,81,81,1,0,{84,0,0},{0x004b, 0x004d, 0x0054, 0x0050, 0x002d, 0x0044, 0x0033},0}, {32,5,31,0,97,97,1,0,{100,0,0},{0x004b, 0x004d, 0x0054, 0x0050, 0x002d, 0x0044, 0x0035},0}, {36,1,50,0,49,49,1,0,{52,0,0},{0x004b, 0x0049, 0x0043, 0x0055, 0x002d, 0x0044, 0x0054},0}, {36,2,50,0,65,65,1,0,{68,0,0},{0x004b, 0x0054, 0x0056, 0x004e, 0x002d, 0x0044, 0x0054},0}, {38,1,37,0,49,49,1,0,{52,0,0},{0x004b, 0x0043, 0x004e, 0x0053, 0x0000, 0x0000, 0x0000},0}, {43,1,41,0,33,33,1,0,{36,0,0},{0x004b, 0x0043, 0x0053, 0x004d, 0x0020, 0x0054, 0x0056},0}, {43,2,41,0,49,49,1,0,{52,0,0},{0x004b, 0x0043, 0x0053, 0x004d, 0x004d, 0x0048, 0x005a},0}, {43,3,41,0,65,65,1,0,{68,0,0},{0x004a, 0x0061, 0x007a, 0x007a, 0x0020, 0x0054, 0x0056},0}, {44,1,43,0,49,49,1,0,{52,0,0},{0x004b, 0x0042, 0x0043, 0x0057, 0x002d, 0x0048, 0x0044},0}, {48,1,47,0,49,49,1,0,{52,0,0},{0x004b, 0x0053, 0x0054, 0x0053, 0x002d, 0x0044, 0x0054},0}, {54,1,48,0,49,49,1,0,{51,0,0},{0x004b, 0x0054, 0x0045, 0x0048, 0x002d, 0x0048, 0x0044},0}, {54,2,48,0,65,65,1,0,{67,0,0},{0x0056, 0x002d, 0x006d, 0x0065, 0x0000, 0x0000, 0x0000},0}, {54,3,48,0,81,81,1,0,{83,0,0},{0x004b, 0x0054, 0x0045, 0x0048, 0x002d, 0x0053, 0x0044},0}, {65,1,39,0,49,49,1,0,{52,0,0},{0x0069, 0x006f, 0x006e, 0x0000, 0x0000, 0x0000, 0x0000},0}, {65,2,39,0,65,65,3,0,{68,69,0},{0x0071, 0x0075, 0x0062, 0x006f, 0x0000, 0x0000, 0x0000},0}, {65,3,39,0,81,81,1,0,{84,0,0},{0x0069, 0x006f, 0x006e, 0x0020, 0x0045, 0x0000, 0x0000},0}, {65,4,39,0,97,97,1,0,{100,0,0},{0x0057, 0x006f, 0x0072, 0x0073, 0x0068, 0x0069, 0x0070},0}, {66,1,32,0,49,49,2,0,{0,52,0},{0x004b, 0x0046, 0x0053, 0x0046, 0x0020, 0x0044, 0x0054},0}, {66,2,32,0,65,65,2,0,{0,68,0},{0x004b, 0x0044, 0x0054, 0x0056, 0x002d, 0x0044, 0x0054},0}, {68,1,45,0,49,49,1,0,{52,0,0},{0x004b, 0x0054, 0x004c, 0x004e, 0x002d, 0x0044, 0x0054},0}, }; const unsigned char g_def_ch_num = sizeof(s_def_ch_map)/sizeof(s_def_ch_map[0]); #elif (DEF_CH_MAP == 1) /* default channel map in San Diego for testing purposes only */ #warning "DEF_CH_MAP = 1" static const bapp_ch_t s_def_ch_map[] = { {8,1,53,0,49,49,1,0,{52,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {10,1,23,0,49,49,1,0,{52,0,0},{0x004b, 0x0047, 0x0054, 0x0056, 0x002d, 0x0044, 0x0054},0}, {15,1,28,0,49,49,1,0,{0,0,0},{0x004b, 0x0050, 0x0042, 0x0053, 0x002d, 0x0048, 0x0044},0}, {15,2,28,0,65,65,1,0,{0,0,0},{0x0056, 0x002d, 0x006d, 0x0065, 0x0000, 0x0000, 0x0000},0}, {39,1,38,0,49,49,1,0,{52,0,0},{0x004b, 0x004e, 0x0053, 0x0044, 0x0020, 0x0048, 0x0044},0}, {39,2,38,0,65,65,1,0,{68,0,0},{0x0057, 0x0058, 0x0020, 0x0050, 0x006c, 0x0075, 0x0073},0}, {51,1,16,0,49,49,1,0,{52,0,0},{0x004b, 0x0055, 0x0053, 0x0049, 0x002d, 0x0048, 0x0044},0}, {69,1,17,0,49,49,5,0,{52,53,0},{0x004b, 0x0053, 0x0057, 0x0042, 0x002d, 0x0044, 0x0054},0}, {69,3,17,0,65,65,1,0,{68,0,0},{0x0054, 0x0075, 0x0062, 0x0065, 0x0000, 0x0000, 0x0000},0}, }; const unsigned char g_def_ch_num = sizeof(s_def_ch_map)/sizeof(s_def_ch_map[0]); #elif (DEF_CH_MAP == 4) /* default channel map in San Diego for testing purposes only */ #warning "DEF_CH_MAP = 4" static const bapp_ch_t s_def_ch_map[] = { {2,1,0,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {3,1,1,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {4,1,2,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {5,1,3,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {6,1,4,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {7,1,5,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {8,1,6,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {9,1,7,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {10,1,8,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {11,1,9,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {12,1,10,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {13,1,11,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {14,1,12,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {15,1,13,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {16,1,14,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {17,1,15,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {18,1,16,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {19,1,17,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {20,1,18,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {21,1,19,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {22,1,20,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {23,1,21,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {24,1,22,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {25,1,23,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {26,1,24,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {27,1,25,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {28,1,26,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {29,1,27,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {30,1,28,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {31,1,29,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {32,1,30,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {33,1,31,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {34,1,32,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {35,1,33,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {36,1,34,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {37,1,35,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {38,1,36,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {39,1,37,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {40,1,38,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {41,1,39,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {42,1,40,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {43,1,41,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {44,1,42,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {45,1,43,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {46,1,44,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {47,1,45,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {48,1,46,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {49,1,47,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {50,1,48,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {51,1,49,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {52,1,50,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {53,1,51,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {54,1,52,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {55,1,53,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {56,1,54,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {57,1,55,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {58,1,56,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {59,1,57,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {60,1,58,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {61,1,59,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {62,1,60,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {63,1,61,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {64,1,62,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {65,1,63,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {66,1,64,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {67,1,65,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {68,1,66,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, {69,1,67,1,0,0,1,0,{0,0,0},{0x004b, 0x0046, 0x004d, 0x0042, 0x002d, 0x0044, 0x0054},0}, }; const unsigned char g_def_ch_num = sizeof(s_def_ch_map)/sizeof(s_def_ch_map[0]); #endif #define BAPP_TV_RATING_STR_NUM 8 static const char *bapp_tv_rating_str[BAPP_TV_RATING_STR_NUM] = { "", /* unrated */ "TV-Y", "TV-Y7", "TV-G", "TV-PG", "TV-14", "TV-MA", "" /* unrated */ }; /* LUT used to translate from user defined tv limit to canadian equivalent */ static unsigned char tv_to_can_eng[8] = { 0, 1, 2, 3, 4, 5, 6, 0}; static unsigned char tv_to_can_fra[8] = { 0, 2, 2, 2, 3, 4, 5, 0}; #define BAPP_MPAA_RATING_STR_NUM 8 static const char *bapp_mpa_rating_str[] = { "", /* unrated */ "G", "PG", "PG-13", "R", "NC-17", "X", "NR" /* Not Rated */ }; #define BAPP_CE_RATING_STR_NUM 8 static const char *bapp_ce_rating_str[] = { "E", "C", "C8+", "G", "PG", "14+", "18+" "", /* invalid */ }; #define BAPP_CF_RATING_STR_NUM 8 static const char *bapp_cf_rating_str[] = { "E", "G", "8ans+", "13ans+", "16ans+", "18ans+", "", /* invalid */ "", /* invalid */ }; void bl_write(void) { } /* * Flush cache */ void bapp_flush_screen(bapp_t *p_app) { unsigned int *palette; int width,height,pitch; if (bgraphics_sync(p_app->graphics) == berr_timeout) { BDBG_WRN(("bgraphics_sync timeout, try again.\n" )); if (bgraphics_sync(p_app->graphics) == berr_timeout) { BDBG_ERR(("bgraphics_sync timeouted out again.\n" )); } } bgraphics_get_framebuffer(p_app->graphics,(void**)&p_app->osd_mem,(unsigned int **)&palette,&width,&height,&pitch); p_app->osd_mem_size = pitch * height; p_app->width = width; p_app->height = height; p_app->surf.surface.buf = p_app->osd_mem; } /* * Determine ratings system */ static rsys_t bapp_get_rsys(unsigned char c1, unsigned char c2) { if ((c1 & 0x18) == 0x18) /* eRS_CANADIAN_ENGLISH - eRS_RESERVED_1 */ { if (c1 & 0x20) /* eRS_CANADIAN_FRENCH or eRS_RESERVED_1 */ { if (c2 & 0x08) return eRS_RESERVED_1; else return eRS_CANADIAN_FRENCH; } else { if (c2 & 0x08) return eRS_RESERVED_0; else return eRS_CANADIAN_ENGLISH; } } else /* eRS_MPA - eRS_MPA_OLD */ { if (c1 & 0x10) return eRS_MPA_OLD; else if (c1 & 0x08) return eRS_US; else return eRS_MPA; } return eRS_US; } /* * Return 1 if MPA rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_mpa_block(unsigned char mpa_level, /* MPA level 0 - 7 */ unsigned char c1 /* xds 1 character */ ) { c1 &= 0x7; /* update rating string */ if (c1 < BAPP_MPAA_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_mpa_rating_str[c1]); if (c1 == 0) return -1; /* level 0 rating not applicable */ return(c1 >= mpa_level) ? 1 : 0; } /* * Return 1 if Canadian English rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_CE_block(unsigned char CE_level, /* Canadian English level 0 - 7 */ unsigned char c2 /* xds 2 character */ ) { c2 &= 0x7; if (c2 == 7) return -1; /* level 7 rating is invalid */ /* update rating string */ if (c2 < BAPP_CE_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_ce_rating_str[c2]); if (c2 == 0) return -1; return(c2 >= CE_level) ? 1 : 0; } /* * Return 1 if Canadian French rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_CF_block(unsigned char CF_level, /* Canadian French level 0 - 7 */ unsigned char c2 /* xds 2 character */ ) { c2 &= 0x7; if ((c2 == 6) || (c2 == 7)) return -1; /* level 6 or 7 rating is invalid */ /* update rating string */ if (c2 < BAPP_CF_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_cf_rating_str[c2]); if (c2 == 0) return -1; return(c2 >= CF_level) ? 1 : 0; } /* * Return 1 if US rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_US_block(unsigned char US_level, /* US level 0 - 7 */ unsigned char mask, /* VSLD modifier mask */ unsigned char c1, /* xds 1 character */ unsigned char c2 /* xds 2 character */ ) { unsigned char tmp_c2 = c2 & 0x7; unsigned char c1_mask,c2_mask; int slen; c2_mask = (mask & 0xE) << 2; c1_mask = (mask & 0x1) << 5; /* update rating string */ if (tmp_c2 < BAPP_TV_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_tv_rating_str[tmp_c2]); else s_p_app->prog_rating_str[0] = 0; switch (tmp_c2) { case 2: if (c2 & 0x20) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'F'; s_p_app->prog_rating_str[slen + 1] = 'V'; s_p_app->prog_rating_str[slen + 2] = 0; } break; case 4: case 5: case 6: if (c2 & 0x20) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'V'; s_p_app->prog_rating_str[slen + 1] = 0; } if (c2 & 0x08) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'L'; s_p_app->prog_rating_str[slen + 1] = 0; } if (c2 & 0x10) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'S'; s_p_app->prog_rating_str[slen + 1] = 0; } if (tmp_c2 != 6) { if (c1 & 0x20) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'D'; s_p_app->prog_rating_str[slen + 1] = 0; } } break; default: break; } BDBG_MSG(("Level - %d, LIMIT - %d, mask = 0x%02x(c1m 0x%02x, c2m 0x%02x)\n",tmp_c2,US_level,mask,c1_mask,c2_mask )); if ((tmp_c2 == 0) || (tmp_c2 == 0x7)) return -1; /* level 0 and 7 ratings not applicable */ switch (US_level) { case 0: return 0; case 3: case 1:return(tmp_c2 > US_level) ? 1 : 0; case 2: { if (tmp_c2 > US_level) return 1; else if ((tmp_c2 == US_level) && /* handle case where xds rating has no vsld modifier */ ((s_p_app->settings.ratings_tv >> screen_ratings_tv_xds2pos(US_level)) & (0 | (0x1)))) return 1; else if ((tmp_c2 == US_level) && (c2 & (0x20 & c1_mask))) /* FV restriction */ return 1; } break; case 4: case 5: { if (tmp_c2 > US_level) return 1; else if ((tmp_c2 == US_level) && /* handle case where xds rating has no vsld modifier */ ((s_p_app->settings.ratings_tv >> screen_ratings_tv_xds2pos(US_level)) & (0 | (0x1)))) return 1; else if ((tmp_c2 == US_level) && ((c2 & (0x38 & c2_mask)) || (c1 & (0x20 & c1_mask)))) /* VSLD restriction */ return 1; } break; case 6: { if (tmp_c2 > US_level) return 1; else if ((tmp_c2 == US_level) && /* handle case where xds rating has no vsld modifier */ ((s_p_app->settings.ratings_tv >> screen_ratings_tv_xds2pos(US_level)) & (0 | (0x1)))) return 1; else if ((tmp_c2 == US_level) && (c2 & (0x38 & c2_mask))) /* VSL restriction */ return 1; } break; } return 0; } /* * Return 1 if rating is enabled and exceeded * Return 0 if rating is disabled or not exceeded * Returns -1 on invalid rating or error */ static int bapp_block(bapp_t *p_app, unsigned char c1, /* xds 1 character */ unsigned char c2 /* xds 2 character */ ) { rsys_t rsys; unsigned char mask = 0; int blocked = 0; rsys = bapp_get_rsys(c1,c2); BAPP_VCHIP_MSG(("%s-0x%02x,0x%02x\n",s_rsys_name[rsys],c1,c2)); switch (rsys) { default: case eRS_MPA_OLD: case eRS_MPA: { unsigned char rat = 0; /* determine most restrictive user selected movie rating and convert to xds equivalent. */ if ((p_app->settings.ratings_movies >> 0) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings_movies >> 1) & (0 | (0x1))) rat = 2; else if ((p_app->settings.ratings_movies >> 2) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings_movies >> 3) & (0 | (0x1))) rat = 4; else if ((p_app->settings.ratings_movies >> 4) & (0 | (0x1))) rat = 5; else if ((p_app->settings.ratings_movies >> 5) & (0 | (0x1))) rat = 6; else if ((p_app->settings.ratings_movies >> 6) & (0 | (0x1))) rat = 7; else rat = 0; BAPP_VCHIP_MSG(("@@@ settings.ratings_movie:%x rat:%d\n", p_app->settings.ratings_movies, rat)); blocked = bapp_mpa_block(rat, c1); break; } case eRS_US: { unsigned char tmp_c2 = c2 & 0x7; unsigned char d = 0; unsigned char l = 0; unsigned char s = 0; unsigned char v = 0; unsigned char fv = 0; unsigned char rat = 0; switch (tmp_c2) { case 1: mask = 0; break; case 2: /* build tv-y7 content ratings mask */ fv = ((p_app->settings.ratings_tv >> ePOS_TV_Y7_FV) & (0 | (0x1))); mask = (fv << 3); break; case 3: mask = 0; break; case 4: /* build tv-pg and tv-14 content ratings mask */ d = ((p_app->settings.ratings_tv >> ePOS_TV_PG_D) & (0 | (0x1))); l = ((p_app->settings.ratings_tv >> ePOS_TV_PG_L) & (0 | (0x1))); s = ((p_app->settings.ratings_tv >> ePOS_TV_PG_S) & (0 | (0x1))); v = ((p_app->settings.ratings_tv >> ePOS_TV_PG_V) & (0 | (0x1))); mask = ((v << 3) | (s << 2) | (l << 1) | (d << 0)); break; case 5: d = ((p_app->settings.ratings_tv >> ePOS_TV_14_D) & (0 | (0x1))); l = ((p_app->settings.ratings_tv >> ePOS_TV_14_L) & (0 | (0x1))); s = ((p_app->settings.ratings_tv >> ePOS_TV_14_S) & (0 | (0x1))); v = ((p_app->settings.ratings_tv >> ePOS_TV_14_V) & (0 | (0x1))); mask = ((v << 3) | (s << 2) | (l << 1) | (d << 0)); break; case 6: /* build tv-ma content ratings mask */ d = 0; l = ((p_app->settings.ratings_tv >> ePOS_TV_MA_L) & (0 | (0x1))); s = ((p_app->settings.ratings_tv >> ePOS_TV_MA_S) & (0 | (0x1))); v = ((p_app->settings.ratings_tv >> ePOS_TV_MA_V) & (0 | (0x1))); mask = ((v << 3) | (s << 2) | (l << 1) | (d << 0)); break; default: mask = 0; break; } /* determine most restrictive user selected tv rating and convert to xds equivalent. */ if ((p_app->settings.ratings_tv >> ePOS_TV_Y) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings_tv >> ePOS_TV_Y7) & (0 | (0x3))) rat = 2; else if ((p_app->settings.ratings_tv >> ePOS_TV_G) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings_tv >> ePOS_TV_PG) & (0 | (0x1F))) rat = 4; else if ((p_app->settings.ratings_tv >> ePOS_TV_14) & (0 | (0x1F))) rat = 5; else if ((p_app->settings.ratings_tv >> ePOS_TV_MA) & (0 | (0x1F))) rat = 6; else rat = 0; BAPP_VCHIP_MSG(("@@@ settings.ratings_tv:%x rat:%d\n", p_app->settings.ratings_tv, rat)); blocked = bapp_US_block(rat,mask,c1,c2); } break; case eRS_CANADIAN_ENGLISH: { unsigned char rat = 0; /* determine most restrictive user selected tv rating and convert to xds equivalent. */ if ((p_app->settings.ratings_tv >> ePOS_TV_Y) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings_tv >> ePOS_TV_Y7) & (0 | (0x3))) rat = 2; else if ((p_app->settings.ratings_tv >> ePOS_TV_G) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings_tv >> ePOS_TV_PG) & (0 | (0x1F))) rat = 4; else if ((p_app->settings.ratings_tv >> ePOS_TV_14) & (0 | (0x1F))) rat = 5; else if ((p_app->settings.ratings_tv >> ePOS_TV_MA) & (0 | (0x1F))) rat = 6; else rat = 0; blocked = bapp_CE_block(tv_to_can_eng[rat], c2); } break; case eRS_CANADIAN_FRENCH: { unsigned char rat = 0; /* determine most restrictive user selected tv rating and convert to xds equivalent. */ if ((p_app->settings.ratings_tv >> ePOS_TV_Y) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings_tv >> ePOS_TV_Y7) & (0 | (0x3))) rat = 2; else if ((p_app->settings.ratings_tv >> ePOS_TV_G) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings_tv >> ePOS_TV_PG) & (0 | (0x1F))) rat = 4; else if ((p_app->settings.ratings_tv >> ePOS_TV_14) & (0 | (0x1F))) rat = 5; else if ((p_app->settings.ratings_tv >> ePOS_TV_MA) & (0 | (0x1F))) rat = 6; else rat = 0; blocked = bapp_CF_block(tv_to_can_fra[rat], c2); } break; } /* we go thru ratings evaluation so we can always display current rating whether we are currently enforcing it or not */ if (p_app->settings.ratings_lock == 0) blocked = 0; BAPP_VCHIP_MSG(("%s:%d (%d %s)\n", __FUNCTION__,__LINE__,blocked,p_app->prog_rating_str)); { static chm_event_t rating_evt; rating_evt.type = eCHM_EVT_REDRAW; rating_evt.id = blocked; rating_evt.ticks = bos_getticks(); bos_post_event(p_app->msg_queue,(bapp_task_event_t*)&rating_evt); } return blocked; } /* * Callback to process XDS data (V-CHIP) */ static void bapp_xds_callback(int xds_class, /* the class (0 - current, used for vchip) */ int xds_type, /* the xds type (5 - vchip) */ unsigned char* data, /* the data buffer, containing data_len valid bytes */ int data_len /* the number of valid bytes in data */ ) { if (data_len != 2) return; if (xds_class == 0) { /* Current class */ if (xds_type == 5) { static chm_event_t chm_evt; int block = 0; struct timeval tv; unsigned int current_ticks = bos_getticks(); /* ignore rating if ratings was received while tuned to a different channel. */ if (current_ticks < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) return; gettimeofday(&tv); s_p_app->last_xds = tv.tv_sec; /* VCHIP processing */ block = bapp_block(s_p_app,data[0],data[1]); BDBG_WRN(("bapp_block(0x%02x,0x%02x) - %d, 0x%08x\n",data[0],data[1],block,current_ticks)); if (block != -1) { s_p_app->last_rating_tick = current_ticks; if (block != s_p_app->last_rating_block_status) { chm_evt.type = eCHM_EVT_BLOCK; chm_evt.id = block; chm_evt.ticks = current_ticks; bos_post_event(s_p_app->msg_queue,(bapp_task_event_t*)&chm_evt); } s_p_app->last_rating_block_status = block; } } } else if (xds_class == 3) { /* Miscellaneous class */ if (xds_type == 1) { /* time of day */ } else if (xds_type == 4) { #if 0 /* JPF XDS time is unreliable in current BA broadcasts */ /* local time zone */ BDBG_WRN(("### UTC OFFSET = %d(s) ###\n", data[0] & 0x1F,(data[0] & 0x20) ? "DST" : "STD")); g_xds_time_offset = data[0] & 0x1F; g_xds_dst = (data[0] & 0x20) ? 1 : 0; #endif } } } /**************************************************************** * INPUTS: none * OUTPUTS: none * RETURNS: number of pixels rendered * DESCRITPION: Get the default palette ****************************************************************/ static void get_def_palette (unsigned int *palette) { memcpy(palette,g_p_dsp->ui_comp.ui_palette, 16 * sizeof(unsigned int)); } /**************************************************************** * INPUTS: none * OUTPUTS: none * RETURNS: number of pixels rendered * DESCRITPION: Get the default palette ****************************************************************/ static void get_screensaver_palette (unsigned int *palette) { #ifndef CONFIG_SCREENSAVER BDBG_WRN(("No LOGO.\n")); #else //#error "No Logo" bcm_raw_8_t *p_header = (bcm_raw_8_t*)g_p_dsp->ui_comp.logo; uint8_t *p_clut = (uint8_t*)p_header; p_clut += sizeof(bcm_raw_8_t); //memcpy(palette,g_p_dsp->ui_comp.logo_palette, 16 * sizeof(unsigned int)); memcpy(palette,p_clut, p_header->clut_size * sizeof(unsigned int)); #endif } /**************************************************************** * INPUTS: none * OUTPUTS: none * RETURNS: number of pixels rendered * DESCRITPION: Get the default palette ****************************************************************/ static void get_eia_708_palette (unsigned int *palette) { #ifdef CONFIG_EIA_708 memcpy(palette,g_eia708_palette, 16 * sizeof(unsigned int)); #endif } /* Summary: Set PCM audio output mode. Description: Set PCM audio output mode, mono output when non-zero. */ void bapp_audio_out_mode(bapp_t *p_app, int mono) { baudio_decode_config config; baudio_decode_get_config(p_app->audio, &config); config.mono = (mono) ? true : false; baudio_decode_set_config(p_app->audio, &config); } /* Summary: Set PCM audio compression mode. Description: Set PCM audio compression mode. Returns: 0 if successful non zero if not */ int bapp_audio_comp_mode(bapp_t *p_app, int comp_mode) { baudio_decode_config config; /* defined in com/bsettop_decode_audio.h */ if (comp_mode < 0 || comp_mode >= AC3_NUM_COMP_MODES) return 1; baudio_decode_get_config(p_app->audio, &config); config.comp_mode = comp_mode; baudio_decode_set_config(p_app->audio, &config); return 0; } /* Summary: Set volume level Description: Set Volume level (range 0 - 100) */ void bapp_set_audio_volume(bapp_t *p_app, uint8_t level) { uint32_t new_vol = level; uint32_t cur_vol = p_app->audio_vol; uint32_t vol; /* possibly cancel mute */ if ((level > 0) && (p_app->audio_mute)) bapp_audio_mute(p_app, 0); if ((level > 100) || (new_vol == cur_vol)) return; if (new_vol > cur_vol) { for (p_app->audio_vol = cur_vol; p_app->audio_vol < new_vol; ++p_app->audio_vol) { vol = (p_app->audio_vol * 0x1000)/100; WriteReg32(BCHP_PCM_PB0_VOLUME,(vol << 16) | vol); bos_sleep(1); } } else { for (p_app->audio_vol = cur_vol; p_app->audio_vol > new_vol; --p_app->audio_vol) { vol = (p_app->audio_vol * 0x1000)/100; WriteReg32(BCHP_PCM_PB0_VOLUME,(vol << 16) | vol); bos_sleep(1); } } p_app->audio_vol = level; vol = (p_app->audio_vol * 0x1000)/100; WriteReg32(BCHP_PCM_PB0_VOLUME,(vol << 16) | vol); } /* Summary: Mute audio Description: Mute audio when enable is non-zero. */ void bapp_audio_mute(bapp_t *p_app, int mute) { int vol,idx; if ((mute && p_app->is_muted) || (!mute && !p_app->is_muted)) return; BDBG_WRN(("%s mute = %d, audo_vol = %d, is_muted = %d...\n",__FUNCTION__,mute,p_app->audio_vol,p_app->is_muted)); if (mute) { for (idx = p_app->audio_vol; idx >= 0; --idx) { vol = (idx * 0x1000)/100; WriteReg32(BCHP_PCM_PB0_VOLUME,(vol << 16) | vol); bos_sleep(1); } p_app->is_muted = true; } else { for (idx = 0; idx <= p_app->audio_vol; ++idx) { vol = (idx * 0x1000)/100; WriteReg32(BCHP_PCM_PB0_VOLUME,(vol << 16) | vol); bos_sleep(1); } p_app->is_muted = false; } } /* Summary: Mute both audio and video. Description: Mute both audio and video when enable is non-zero. */ void bapp_av_mute(bapp_t *p_app, int mute) { bdecode_config cfg; bapp_audio_mute(p_app,mute); bdecode_get_config(p_app->decode,&cfg); if (mute) cfg.mute = 1; else cfg.mute = 0; bdecode_set_config(p_app->decode,&cfg); } /* Summary: Configure the video output mode. Description: Configure the video output mode. */ void bapp_output_mode(bapp_t *p_app, int widescreen) { bdecode_config cfg; bdecode_get_config(p_app->decode,&cfg); if (widescreen) { BDBG_WRN(("Widescreen...\n")); cfg.widescreen = 1; } else { BDBG_WRN(("Full Screen...\n")); cfg.widescreen = 0; } bdecode_set_config(p_app->decode,&cfg); } /* Summary: Apply the current settings. Description: Apply the current settings. Restart decode. */ void bapp_apply_settings(bapp_t *p_app) { p_app->cur_ch_num = p_app->settings.cur_ch_num; p_app->audio_vol = p_app->settings.audio_vol; p_app->lang = p_app->settings.language; bapp_output_mode(p_app, (p_app->settings.picture == 0) ? 0 : 1); bapp_audio_out_mode(p_app,0); bapp_set_audio_volume(p_app, p_app->audio_vol); } /* Summary: Reset the current user settings Description: Reset the current user settings. Note this does not change them in flash. */ void bapp_reset_settings(bapp_t *p_app) { memset(&p_app->settings, 0, sizeof(p_app->settings)); { int i = 0; for (i = 0; i < MAX_RRT_DIM; i++) { p_app->settings.ratings_rrt[i] = 0; } } p_app->settings.rrt_status = eRRT_UNAVAILABLE; p_app->settings.last_rrt_id = 0; bapp_reset_cc_settings(p_app); p_app->settings.auto_power = 0; p_app->settings.audio_vol = 100; p_app->settings.dst = 1; /* this will make sure volume is reset to default from UI */ p_app->audio_vol = p_app->settings.audio_vol; } /* Summary: Reset the current advanced closed captioning user settings Description: Reset the current advanced closed captioning user settings. Note this does not change them in flash. */ void bapp_reset_cc_settings(bapp_t *p_app) { p_app->settings.captions_font = 0; p_app->settings.captions_font_size = 0; p_app->settings.captions_font_style = 0; p_app->settings.captions_font_color = 0; p_app->settings.captions_font_opacity = 0; p_app->settings.captions_back_color = 0; p_app->settings.captions_back_opacity = 0; p_app->settings.captions_edge_color = 0; p_app->settings.captions_edge_type = 0; } /* Summary: Load current settings from NVM Description: Load current settings from NVM */ void bapp_load_settings(bapp_t *p_app) { bapp_settings_t *p_flash_data = NULL; uint32_t flash_data_length; if (fstore_get(&p_app->flash_storage, eFS_APP_DATA, (void **)&(p_flash_data), &flash_data_length) == b_ok) { if (flash_data_length == sizeof(p_app->settings)) { /* flash data valid - use it! */ BDBG_WRN(("flash app data length CORRECT:%d (should be %d) restore settings\n", flash_data_length, sizeof(p_app->settings))); memcpy(&p_app->settings,p_flash_data,sizeof(bapp_settings_t)); return; } } /* flash contains invalid saved data */ BDBG_WRN(("flash app data length incorrect:%d (should be %d) save defaults\n", flash_data_length, sizeof(p_app->settings))); /* When the flash is empty and the settings get reset to defaults here, the current implementation of bapp_save_settings will wipe of the default values for volume, language and cur_ch_num with the current app values. To avoid this set the app values after calling bapp_reset_settings. I have fixed this several times but someone keeps removing this fix. Do not remove this change without addressing and understanding this issue. */ bapp_reset_settings(p_app); p_app->cur_ch_num = p_app->settings.cur_ch_num; p_app->audio_vol = p_app->settings.audio_vol; p_app->lang = p_app->settings.language; /* update flash with new settings */ bapp_save_settings(p_app); } /* Summary: Save current settings to NVM Description: Save current settings to NVM */ void bapp_save_settings(bapp_t *p_app) { /* update unsaved settings */ p_app->settings.cur_ch_num = p_app->cur_ch_num; p_app->settings.audio_vol = p_app->audio_vol; p_app->settings.language = p_app->lang; bapp_stop_decode(p_app); bos_sleep(200); /* need to make sure decode is stopped before saving settings */ p_app->settings_dirty = false; if (fstore_update(&p_app->flash_storage, eFS_APP_DATA, &p_app->settings, sizeof(p_app->settings)) != b_ok) { BDBG_WRN(("fstore_update failed\n")); } else { BDBG_WRN(("fstore_update success\n")); } } /* Summary: Power down audio DAC and power off */ void bapp_do_poweroff(bapp_t *p_app) { #if (BCHP_CHIP != 3543) /* Notifiy MCU of desire to power off */ #ifndef CONFIG_OLD_MCU WriteReg32(BCHP_GIO_DATA_LO, ReadReg32( BCHP_GIO_DATA_LO) & ~(1UL << 20)); #else WriteReg32(BCHP_GIO_DATA_LO, ReadReg32( BCHP_GIO_DATA_LO) | (1UL << 20)); #endif #else WriteReg32(BCHP_AIO_MISC_DAC_PWRDOWN,0x0000000F); WriteReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1, ReadReg32( BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1) & ~BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1_irw_top_sw_pwroff_MASK); bos_sleep(20); WriteReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1, ReadReg32( BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1) | BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1_irw_top_sw_pwroff_MASK); #endif } /* Summary: Initialize the main app structure. Description: Do necessary configuration of main app structure. Assumes p_app is allocated and p_surf and palette are initialized. */ static bgfx_io_t s_io = { bin_read, bin_tell, bin_set }; void bapp_init(bapp_t *p_app) { bapp_lang_t e_lang; bdecode_config cfg; #ifdef CONFIG_HAS_VIDEO bdecode_config cfgs[2]; #endif #ifdef LINUX bsurface_create_settings cfg; bdisplay_settings settings; bsurface_memory mem; bsurface_t framebuffer; bgraphics_palette settop_palette; #else unsigned int *palette; /* [out] address of palette */ int width; /* [out] width of the OSD surface */ int height; /* [out] height of the OSD surface */ int pitch; /* [out] pitch of the OSD surface */ #endif BDBG_MSG(("%s:%d\n",__FUNCTION__,__LINE__)); memset(p_app,0,sizeof(bapp_t)); s_p_app = p_app; /* Enable number UI navigation */ #if (BCHP_CHIP!=3543) p_app->button_numbers = true; #else p_app->button_numbers = ((ReadReg32(BCHP_GIO_DATA_HI) & STRP_NUM_DIS_MASK) == 0) ? true : false; #endif WriteReg32(SCRATCH_CMD_BASE,0);/* make sure there are no values in the Command scratch register on start */ /* Configure GPIO for output (LEDs) */ WriteReg32(LED_IODIR_REG, ReadReg32( LED_IODIR_REG) & ~(LED_IODIR_MASK)); #if (BCHP_CHIP!=3543) /* Configure the MCU Power_Off_Ready as output */ WriteReg32(BCHP_GIO_IODIR_LO, ReadReg32( BCHP_GIO_IODIR_LO) & ~(1UL << 20)); #else #if 0 /* Enable front pannel reset control */ WriteReg32(BCHP_SUN_TOP_CTRL_RESET_CTRL, ReadReg32( BCHP_SUN_TOP_CTRL_RESET_CTRL) | (BCHP_SUN_TOP_CTRL_RESET_CTRL_front_panel_reset_enable_MASK | BCHP_SUN_TOP_CTRL_RESET_CTRL_front_panel_reset_polarity_MASK)); #endif #endif BAPP_ASSERT(bsettop_init(BSETTOP_VERSION) == b_ok); #if (BCHP_CHIP != 3543) p_app->user_io = buser_input_open(B_ID(USERIO_ID)); #else { unsigned event_cnt; int ir_result; buser_input_event event; unsigned int type = (ReadReg32(BCHP_GIO_DATA_HI) & STRP_REMOTE_MASK) >> STRP_REMOTE_SHIFT; #ifndef CONFIG_XMP_REMOTE if (type < 4) p_app->user_io = buser_input_open(B_ID(s_remote_type_map[type])); else p_app->user_io = buser_input_open(B_ID(4)); #else /*RLQ, temp solution, will use type once it is ready */ type = type; BDBG_ERR(("%s: USERIO_ID=%d", __func__, USERIO_ID)); p_app->user_io = buser_input_open(B_ID(USERIO_ID)); #endif #ifndef CONFIG_FAST_IR #error "Use fast IR" { int start_ticks; /* See if there is an IR code pending */ WriteReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1, ReadReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1) | BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1_irw_top_sw_req_ir_code_MASK); /* Check for event */ start_ticks = bos_getticks() + MS_TO_TICKS(150); while ((ir_result = buser_input_get_event(p_app->user_io,&event,1,&event_cnt)) != b_ok) { if (bos_getticks() > start_ticks) { BDBG_ERR(("TIMEOUT: Waited > 150 ms for key: (ir_result = %d, event=0x%08x (%d events))\n",ir_result,event.code,event_cnt)); break; } } if ((ir_result != b_ok) || (event_cnt < 1) || (event.code != eIR_POWER)) { BDBG_ERR(("Wake up not caused by power button or IR key (ir_result = %d, event=0x%08x (%d events))\n",ir_result,event.code,event_cnt)); bos_sleep(100); /* Power off */ bapp_do_poweroff(p_app); } else { BDBG_ERR(("Powered on OK (ir_result = %d, event=0x%08x)\n",ir_result,event.code)); } } #else ir_result = buser_input_get_event(p_app->user_io,&event,1,&event_cnt); #endif p_app->check_poweron = true; p_app->poweron_ms = bos_getticks() + MS_TO_TICKS(3000); } #endif p_app->display = bdisplay_open(B_ID(0)); WriteReg32(SCRATCH_CMD_BASE,0);/* make sure there are no values in the Command scratch register on start */ #if (BCHP_CHIP == 7002) || (BCHP_CHIP == 3563) btransport_open(); #endif #ifdef LINUX bdisplay_get(p_app->display, &settings); settings.format = bvideo_format_ntsc; settings.content_mode = bdisplay_content_mode_panscan; BAPP_ASSERT(bdisplay_set(p_app->display, &settings) == b_ok); #endif p_app->decode = bdecode_open(0); BAPP_ASSERT(p_app->decode); #ifdef CONFIG_HAS_VIDEO /* Initialise for both record PID channels */ bdecode_get_config(p_app->decode, &cfgs[0]); bdecode_get_config(p_app->decode, &cfgs[1]); bmessage_init(cfgs); smessage_init(cfgs); #else bmessage_init(NULL); #endif p_app->window = bdecode_window_open(0, p_app->display); bdecode_get_config(p_app->decode,&cfg); cfg.xds_callback = bapp_xds_callback; bdecode_set_config(p_app->decode,&cfg); #ifdef CONFIG_HAS_AUDIO p_app->audio = baudio_decode_open(B_ID(0)); if (!p_app->audio) { BDBG_WRN(("baudio_decode_open failed\n")); } p_app->audio_mute = 0; #endif bstream_mpeg_init(&p_app->mpeg); p_app->tuner = btuner_open((0)); BAPP_ASSERT(p_app->tuner); bos_create_queue(&p_app->msg_queue, p_app->msg_event, MAX_MSG_EVENT); BAPP_ASSERT(p_app->msg_queue); p_app->smsg = smessage_open(bmessage_format_psi); p_app->msg = bmessage_open(bmessage_format_ts); BAPP_ASSERT(p_app->msg); p_app->graphics = bgraphics_open(B_ID(0),p_app->display); p_app->yield_ms = APP_DEFAULT_YIELD; p_app->lang = eLANG_ENGLISH; #ifdef LINUX p_app->width = 720; p_app->height = 480; bsurface_create_settings_init(&cfg, p_app->graphics); cfg.pixel_format = bgraphics_pixel_format_palette4; framebuffer = bgraphics_create_framebuffer(p_app->graphics, &cfg, false); bsurface_get_memory(framebuffer, &mem); get_def_palette(&(p_app->palette)); settop_palette.length = 16; settop_palette.palette = p_app->palette.clut; bsurface_load_clut(framebuffer, settop_palette); p_app->osd_mem = (unsigned char *)mem.buffer; p_app->osd_mem_size = mem.pitch * p_app->height; #else bgraphics_get_framebuffer(p_app->graphics,(void**)&p_app->osd_mem,(unsigned int **)&palette,&width,&height,&pitch); get_def_palette(palette); bgraphics_load_palette(p_app->graphics); p_app->osd_mem_size = pitch * height; p_app->width = width; p_app->height = height; BDBG_MSG(("%s:%d - Width = %d, Height = %d, Pitch = %d.\n",__FUNCTION__,__LINE__,width,height,pitch)); #endif BDBG_MSG(("%s:%d - Initialize screens.\n",__FUNCTION__,__LINE__)); /* Default to NULL (empty) screen (TODO: goto factory test then setup wizard.) */ p_app->screen_id = eSCREEN_BANNER_SMALL; p_app->p_screens = g_screens; p_app->num_screens = g_screens_num; BDBG_MSG(("%s:%d - Initialize bgfx.\n",__FUNCTION__,__LINE__)); /* initialize bgfx */ bgfx_init(&s_io,NULL); /* Create the OSD surface to use for all drawing */ BAPP_ASSERT(bgfx_create(&p_app->surf,p_app->width,p_app->height,(uint8_t*)p_app->osd_mem, pitch,&p_app->palette, BGFX_SURF_PRIMARY) == 0); bgfx_fill_rect(&p_app->surf,0,0,p_app->width,p_app->height,0x0); BDBG_MSG(("%s:%d - Load fonts.\n",__FUNCTION__,__LINE__)); memset(&s_font[eFONT_SIZE_SMALL],0,sizeof(bgfx_font_t) * 3); p_app->br.cnt = 0; p_app->br.data = g_p_dsp->ui_comp.small_font; p_app->br.size = g_p_dsp->ui_comp.small_font_size; BAPP_ASSERT(bgfx_load_font(&(s_font[eFONT_SIZE_SMALL]),&p_app->br) == 0); p_app->br.cnt = 0; p_app->br.data = g_p_dsp->ui_comp.medium_font; p_app->br.size = g_p_dsp->ui_comp.medium_font_size; BAPP_ASSERT(bgfx_load_font(&(s_font[eFONT_SIZE_MED]),&p_app->br) == 0); p_app->br.cnt = 0; p_app->br.data = g_p_dsp->ui_comp.large_font; p_app->br.size = g_p_dsp->ui_comp.large_font_size; BAPP_ASSERT(bgfx_load_font(&(s_font[eFONT_SIZE_LARGE]),&p_app->br) == 0); for (e_lang = eLANG_ENGLISH; e_lang < eLANG_MAX; ++e_lang) { p_app->p_font[e_lang][eFONT_SIZE_SMALL] = &s_font[eFONT_SIZE_SMALL]; p_app->p_font[e_lang][eFONT_SIZE_MED] = &s_font[eFONT_SIZE_MED]; p_app->p_font[e_lang][eFONT_SIZE_LARGE] = &s_font[eFONT_SIZE_LARGE]; } p_app->ratings_override = false; /* reset so ratings will be re-evaluated when returned to full tv */ p_app->last_rating_block_status = -1; /* assume psip unblock */ p_app->last_psip_rating_block_status = 0; #ifdef CONFIG_RFM { bdisplay_settings display_settings; boutput_rf_settings rf_settings; bdisplay_get(p_app->display, &display_settings); display_settings.rf = boutput_rf_open(B_ID(0)); boutput_rf_get(display_settings.rf, &rf_settings); rf_settings.channel = eRFM_CH3; if (ReadReg32(RFM_CH4_REG) & RFM_CH4_MASK) rf_settings.channel = eRFM_CH4; boutput_rf_set(display_settings.rf, &rf_settings); bdisplay_set(p_app->display, &display_settings); boutput_rf_set_audio_volume(display_settings.rf, DEFAULT_RFM_VOLUME); } #endif #if 0 { uint32_t value; value = (BCHP_HIFIDAC_CTRL0_DAC_VOLUME_DAC_VOL_MASK * (uint32_t)DEFAULT_VOLUME) / 100; WriteReg32(BCHP_HIFIDAC_CTRL0_DAC_VOLUME, (ReadReg32(BCHP_HIFIDAC_CTRL0_DAC_VOLUME) & ~BCHP_HIFIDAC_CTRL0_DAC_VOLUME_DAC_VOL_MASK) | (value << BCHP_HIFIDAC_CTRL0_DAC_VOLUME_DAC_VOL_SHIFT)); } #else WriteReg32(BCHP_HIFIDAC_CTRL0_DAC_VOLUME,0x904C); #endif #ifdef CONFIG_EIA_708 p_app->eia708 = bapp_eia708_open(p_app); BAPP_ASSERT(p_app->eia708); bdecode_get_config(p_app->decode,&cfg); cfg.cc_callback = bapp_eia708_cb; bdecode_set_config(p_app->decode,&cfg); #endif /* CONFIG_EIA_708 */ chm_init(&p_app->chm,p_app); #if (DEF_CH_MAP > 0) memcpy(p_app->settings.ch,s_def_ch_map, g_def_ch_num * sizeof(s_def_ch_map[0])); p_app->settings.num_channels = g_def_ch_num; #endif /* DEF_CH_MAP */ BAPP_ASSERT(fstore_init(&(p_app->flash_storage)) == b_ok); #if (BCHP_CHIP==3543) /* Check GPIO 33 and 34, if pressed then go into factory test mode */ if ((ReadReg32(BUTTON_DATA_REG) & CH_DOWN_BUTTON_MASK) == CH_DOWN_BUTTON_MASK) { p_app->screen_id = eSCREEN_STATUS; p_app->factory_test = true; } else #endif { bapp_load_settings(p_app); bapp_apply_settings(p_app); } } /* Summary: Main app event handler. Description: Main application event handler. */ void bapp_handle_event(bapp_t *p_app, bscreen_event_t *p_event) { int idx; if (p_event && (p_event->type == eS_EVENT_IR) && (p_event->id >= eIR_CHMAP)) { switch (p_event->id) { case eIR_CHMAP: /* Output channel map on UART */ for (idx = 0; idx < p_app->settings.num_channels; ++idx) { #ifdef DTA_TEST extern const unsigned short s_ch_to_freq[]; printf("{%d,%d,%d,%d,%d,%d,%d,%d,{%d,%d,%d},{0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x}, 0x%02x},\n", p_app->settings.ch[idx].major, p_app->settings.ch[idx].minor, p_app->settings.ch[idx].program_number, p_app->settings.ch[idx].freq_idx, s_ch_to_freq[p_app->settings.ch[idx].freq_idx], p_app->settings.ch[idx].psi, p_app->settings.ch[idx].pcr_pid, p_app->settings.ch[idx].video_pid, p_app->settings.ch[idx].audio_pid[0], p_app->settings.ch[idx].audio_pid[1], p_app->settings.ch[idx].audio_pid[2], p_app->settings.ch[idx].ch_name[0],p_app->settings.ch[idx].ch_name[1],p_app->settings.ch[idx].ch_name[2], p_app->settings.ch[idx].ch_name[3],p_app->settings.ch[idx].ch_name[4],p_app->settings.ch[idx].ch_name[5], p_app->settings.ch[idx].ch_name[6],p_app->settings.ch[idx].program_number ); #else printf("{%d,%d,%d,%d,%d,%d,{%d,%d,%d},{0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x}, 0x%02x},\n", p_app->settings.ch[idx].major, p_app->settings.ch[idx].minor, p_app->settings.ch[idx].freq_idx, p_app->settings.ch[idx].psi, p_app->settings.ch[idx].pcr_pid, p_app->settings.ch[idx].video_pid, p_app->settings.ch[idx].audio_pid[0], p_app->settings.ch[idx].audio_pid[1], p_app->settings.ch[idx].audio_pid[2], p_app->settings.ch[idx].ch_name[0],p_app->settings.ch[idx].ch_name[1],p_app->settings.ch[idx].ch_name[2], p_app->settings.ch[idx].ch_name[3],p_app->settings.ch[idx].ch_name[4],p_app->settings.ch[idx].ch_name[5], p_app->settings.ch[idx].ch_name[6],p_app->settings.ch[idx].cmd ); #endif } break; case eIR_SCAN: /* Perform channel scan */ bapp_channel_scan(p_app); break; case eIR_SETUP: /* Perform default setup */ p_app->settings.wiz_completed = 1; bapp_channel_scan(p_app); break; case eIR_EXIT: /* Exit to banner menu */ bapp_set_current_screen(p_app, eSCREEN_BANNER_SMALL, eSCREEN_NULL); break; default: if ((p_event->id & eIR_SETCH) == eIR_SETCH) { p_app->cur_ch_num = (p_event->id & ~eIR_SETCH); /* Set channel index (7 lsb are channel index) */ if (p_app->cur_ch_num >= p_app->settings.num_channels) p_app->cur_ch_num = 0; bapp_set_current_screen(p_app, eSCREEN_BANNER_SMALL, eSCREEN_NULL); } break; } } } /* Summary: Main app idle time handler. Description: Main application idle time handler. */ #define BAPP_CAD_TIMEOUT 10 /* in seconds */ void bapp_idle(bapp_t *p_app) { struct timeval tv; static chm_event_t chm_evt; bool rating_timeout = false; uint32_t current_ticks = bos_getticks(); if (p_app->check_poweron) { if (p_app->poweron_ms < bos_getticks()) { p_app->check_poweron = false; } } /* Do global idle time processing here like. */ gettimeofday(&tv); /* check if last psip rating has timed out */ if ((p_app->last_cad + BAPP_CAD_TIMEOUT) < tv.tv_sec) { if (p_app->last_psip_rating_block_status == 1) { BDBG_WRN(("clear PSIP rating to unrated - timed out! %d\n",tv.tv_sec)); p_app->last_psip_rating_block_status = 0; /* clear ratings string */ rating_timeout = true; } p_app->psip_rating_str[0] = 0; } /* check if last xds rating has timed out */ if ((p_app->last_rating_tick + MS_TO_TICKS(BAPP_VCHIP_TIMEOUT)) < current_ticks) { if (p_app->last_rating_block_status == 1) { BDBG_WRN(("clear XDS rating to unrated - timed out! (0x%08x)\n",current_ticks)); p_app->last_rating_block_status = 0; /* clear ratings string */ rating_timeout = true; } p_app->prog_rating_str[0] = 0; } /* send unblock message if both rating types have timed out */ if ((rating_timeout) && (p_app->last_rating_block_status != 1) && (p_app->last_psip_rating_block_status != 1)) { BDBG_WRN(("current rating timed out - unblocking!")); /* Unblock since a previous rating has timed out */ chm_evt.type = eCHM_EVT_BLOCK; chm_evt.id = 0; chm_evt.ticks = current_ticks; bos_post_event(s_p_app->msg_queue,(bapp_task_event_t*)&chm_evt); } } /* Summary: Wait for vsync. Description: Block waiting for vsync so drawing can by syncronized with screen refresh. */ void bapp_sync(bapp_t *p_app) { /* do nothing */ } /* Summary: Enable closed captioning. Description: Enable closed captioning and send clear characters. */ void bapp_enable_cc(bapp_t *p_app, int enable) { bdecode_config cfg; BDBG_MSG(("%s enable = %d, p_app->settings.captions_basic = %d, p_app->settings.captions_basic = %d\n", __FUNCTION__,enable,p_app->settings.captions_basic,p_app->captions_basic)); #ifdef CONFIG_EIA_708 bapp_eia708_enable(p_app->eia708,((enable == 0) ? false : ((p_app->settings.captions_basic > 0) ? true : false))); #endif bdecode_get_config(p_app->decode,&cfg); if (cfg.cc_enabled != enable) { cfg.cc_enabled = (enable == 0) ? 0 : 1; bdecode_set_config(p_app->decode,&cfg); } } /* Summary: Handle new screen. Description: Block waiting for vsync so drawing can by syncronized with screen refresh. */ void bapp_new_screen(bapp_t *p_app) { static int screen_id = -1; bscreen_event_t screen_event; #ifdef TIME_APP_DRAWING struct timeval start_tv,end_tv,result_tv; unsigned int dt; #endif screen_event.type = 0; if (screen_id != (int)p_app->screen_id) { BDBG_MSG(("%s:%d - sending setup event to %d.\n",__FUNCTION__,__LINE__,p_app->screen_id)); screen_event.type = eS_EVENT_SETUP; screen_event.id = 0; p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event); } screen_id = p_app->screen_id; #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&start_tv); #endif //BDBG_MSG(("%s:%d - drawing screen:%d.\n",__FUNCTION__,__LINE__,p_app->screen_id)); if (!bapp_eia708_enabled(p_app->eia708)) { bapp_sync(p_app); p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id])); bapp_flush_screen(p_app); } #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&end_tv); timeval_subtract(&result_tv,&end_tv,&start_tv); dt = result_tv.tv_sec * 1000 + result_tv.tv_usec/1000; BDBG_WRN(("Drawing screen %d took %d ms\n",p_app->screen_id,dt)); #endif /* send a setup done event to start any post drawing setup */ if (screen_event.type == eS_EVENT_SETUP) { screen_event.type = eS_EVENT_SETUP_DONE; screen_event.id = 0; if (p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { screen_id = p_app->screen_id; screen_event.type = eS_EVENT_SETUP; screen_event.id = 0; p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event); #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&start_tv); #endif if (!bapp_eia708_enabled(p_app->eia708)) { bapp_sync(p_app); p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id])); bapp_flush_screen(p_app); } #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&end_tv); timeval_subtract(&result_tv,&end_tv,&start_tv); dt = result_tv.tv_sec * 1000 + result_tv.tv_usec/1000; BDBG_WRN(("Drawing took %d milliseconds\n",dt)); #endif } } } /* Summary: Clear screen selection history Description: Clear screen selection history */ void bapp_clear_screen_selection_history(bapp_t *p_app) { int i; for (i = 0; i < p_app->num_screens; i++) { p_app->p_screens[i].button_selection = 0; } } /* Summary: sets the current screen for display Description: sets the current screen for display. if id == eSCREEN_MAX then simply backup a screen if save_last == eSCREEN_MAX, also saves last screen id. else save_last is used for the last screen id (use eSCREEN_NULL if you want the last screen id to refer to live tv) */ void bapp_set_current_screen(bapp_t *p_app, bapp_screen_id_t id, bapp_screen_id_t save_last) { bscreen_t *p_screen = &(p_app->p_screens[p_app->screen_id]); bscreen_t *p_screen_new = &(p_app->p_screens[id]); #ifdef BCM_DEBUG unsigned int cur_screen = p_app->screen_id; #endif BDBG_WRN(("Attempt to change screen from %d to %d\n",cur_screen, id)); if (id == p_app->screen_id) return; if (id == eSCREEN_MAX) { bapp_goto_last_screen(p_app); } else { if (save_last == eSCREEN_MAX) p_screen_new->last_screen_id = p_app->screen_id; else { p_screen_new->last_screen_id = save_last; p_screen->button_selection = 0; /* if we do not save the last screen, clear out focus history */ } if (id < eSCREEN_MAX) p_app->screen_id = id; } if (p_app->screen_id == eSCREEN_NULL) { p_app->screen_id = eSCREEN_BANNER_SMALL; /* Default to channel change screen */ } BDBG_WRN(("Changing screen from %d to %d\n",cur_screen, p_app->screen_id)); if (p_app->screen_id != eSCREEN_BANNER_SMALL) { bapp_av_mute(p_app, 1); bapp_enable_cc(p_app, 0); } else { /* recheck ratings block status which may have changed while in menu */ bapp_handle_blocking(p_app); } } /* Summary: sets the current screen for display to be the last screen Description: sets the current screen for display to be the last screen */ void bapp_goto_last_screen(bapp_t *p_app) { bscreen_t *p_screen = &(p_app->p_screens[p_app->screen_id]); p_app->screen_id = p_screen->last_screen_id; if (p_app->screen_id == eSCREEN_NULL) { p_app->screen_id = eSCREEN_BANNER_SMALL; /* Default to channel change screen */ } if (p_app->screen_id != eSCREEN_BANNER_SMALL) { bapp_av_mute(p_app, 1); bapp_enable_cc(p_app, 0); } } /* Summary: Handle content advisory blocking/unblocking. Returns 1 if blocking/unblocking results in a screen change, 0 otherwise */ int bapp_handle_blocking(bapp_t *p_app) { int screen_changed = 0; if (p_app->ratings_override) return screen_changed; BDBG_MSG(("last_psip_rating_block_status:%d last_rating_block_status:%d\n", p_app->last_psip_rating_block_status ,p_app->last_rating_block_status)); /* check both types of ratings - if either one says "block", we block */ if ((p_app->last_psip_rating_block_status == 1) || (p_app->last_rating_block_status == 1)) { /* show pin verification screen if not in menus */ if ((p_app->screen_id == eSCREEN_BANNER_SMALL) || (p_app->screen_id == eSCREEN_NULL)) { bapp_set_current_screen(p_app, eSCREEN_PIN_VERIFY_LIVE, eSCREEN_NULL); screen_changed = 1; } } else { /* no blocking, need to re-enable decode and possibly hide pin verification screen */ if ((p_app->screen_id == eSCREEN_PIN_VERIFY_LIVE) || (p_app->screen_id == eSCREEN_WRONG_PIN_LIVE)) { bapp_set_current_screen(p_app, eSCREEN_NULL, eSCREEN_NULL); screen_changed = 1; } } return screen_changed; } /* Summary: Turn power on or off Description: Turn power on if power = true, turn power off otherwise */ void bapp_power(bapp_t *p_app, bool power) { unsigned int flags; if (p_app->factory_test || (p_app->power == power)) { if (p_app->factory_test) { bapp_set_current_screen(p_app, eSCREEN_STATUS, eSCREEN_NULL); bapp_new_screen(p_app); } return; } if (!power && p_app->check_poweron) { return; } bapp_stop_decode(p_app); if (power) { /* turning power on */ BDBG_ERR(("######## Turn ON ########\n")); /* turning power leds on */ flags = bos_enter_critical(); #if (BCHP_CHIP!=3543) WriteReg32(LED_DATA_REG, ReadReg32( LED_DATA_REG) & ~LED_RED_MASK); #else WriteReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1, ReadReg32( BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1) & ~BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1_irw_top_sw_led_cntrl_MASK); #endif WriteReg32(LED_DATA_REG, ReadReg32( LED_DATA_REG) | LED_GREEN_MASK); bos_exit_critical(flags); bapp_set_palette(p_app, ePALETTE_DEFAULT); /* restore settings */ p_app->cur_ch_num = p_app->settings.cur_ch_num;/* restore last tuned channel */ p_app->audio_vol = p_app->settings.audio_vol; /* restore last volume level */ p_app->audio_mute = false; /* ensure audio mute user setting is off */ if (p_app->settings.wiz_completed) { bapp_set_current_screen(p_app, eSCREEN_BANNER_SMALL, eSCREEN_NULL); } else { bapp_set_current_screen(p_app, eSCREEN_WIZ_LANGUAGE, eSCREEN_WIZ_LANGUAGE); } bapp_new_screen(p_app); #if (BCHP_CHIP!=3543) #ifndef CONFIG_OLD_MCU WriteReg32(BCHP_GIO_DATA_LO, ReadReg32( BCHP_GIO_DATA_LO) | (1UL << 20)); #endif #endif /* UNCOMMENT lines below to test new RRT user notification */ /* BDBG_WRN(("######################### reset rrt region/version \n")); p_app->settings.last_rrt_id = 0; p_app->settings.rrt_status = eRRT_UNAVAILABLE; p_app->settings.ratings_lock = 1; */ } else { /* Put tuner in bypass mode. Only valid for DTT76809, but shouldn't affect other tuners either */ // Only for VSB p_app->ds.rfBypass = true; btuner_tune_ds(p_app->tuner, 0, &p_app->ds); /* turning power off */ uint32_t current_tick = bos_getticks(); BDBG_ERR(("######## Turn OFF @ 0x%08x ########\n",TICKS_TO_MS(current_tick))); /* check for auto power off */ if ((p_app->screen_id != eSCREEN_POWER_OFF) && (p_app->settings.auto_power != 3) && (current_tick >= (p_app->last_keypress_tick + MS_TO_TICKS(AUTO_POWER_OFF_TIMEOUT) * (1 + p_app->settings.auto_power)))) { p_app->settings.auto_power_off = 1; } flags = bos_enter_critical(); /* turning power leds off */ #if (BCHP_CHIP!=3543) WriteReg32(LED_DATA_REG, ReadReg32( LED_DATA_REG) | LED_RED_MASK); #else WriteReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1, ReadReg32( BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1) | BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1_irw_top_sw_led_cntrl_MASK); #endif WriteReg32(LED_DATA_REG, ReadReg32( LED_DATA_REG) & ~LED_GREEN_MASK); bos_exit_critical(flags); bapp_av_mute(p_app, 1); bapp_set_current_screen(p_app, eSCREEN_POWER_OFF, eSCREEN_NULL); bapp_new_screen(p_app); /* save settings if saved channel number or saved volume level is incorrect note that these settings are saved here because the change often during normal stb operation and there is no need to maintain this information except between power cycles. these settings are also duplicated in both the settings struct and the p_app struct.*/ if ((p_app->settings.cur_ch_num != p_app->cur_ch_num) || (p_app->settings.audio_vol != p_app->audio_vol) || (p_app->settings.language != p_app->lang) || p_app->settings.auto_power_off || p_app->settings_dirty) { p_app->settings.cur_ch_num = p_app->cur_ch_num; p_app->settings.audio_vol = p_app->audio_vol; p_app->settings.language = p_app->lang; bapp_save_settings(p_app); } printf("######## NOTIFY POWERCTRL ########\n"); /* Wait to avoid power button repeat keys from remote */ bos_sleep(2000); bapp_do_poweroff(p_app); } p_app->power = power; } /* Summary: Main app loop. Description: Main application event loop. */ void bapp_run(bapp_t *p_app) { buser_input_event event; unsigned event_cnt; bscreen_event_t screen_event; chm_event_t *p_event; p_app->done = 0; BDBG_MSG(("%s:%d - Start running.\n",__FUNCTION__,__LINE__)); bapp_power(p_app, true); while (!p_app->done) { /* Check for UI event */ if (buser_input_get_event(p_app->user_io,&event,1,&event_cnt) == b_ok) { #ifdef BCM_DEBUG static bool s_test_flag = false; if (!s_test_flag) #endif { if (event_cnt > 0) { p_app->last_keypress_tick = bos_getticks(); } } if (event_cnt && ((int)event.code == eIR_POWER)) { /* power key handled here since it is always available regardless of the currently shown screen. note: power key is consumed here and not passed on to any screens. */ bapp_power(p_app, !p_app->power); } else if (event_cnt && ((event.code & eIR_RFM) == eIR_RFM)) { bdisplay_settings settings; boutput_rf_settings rf_settings; if (event.code & 0x40000000) continue; bdisplay_get(p_app->display,&settings); boutput_rf_get(settings.rf, &rf_settings); rf_settings.channel = eRFM_CH3; bos_sleep(50); rf_settings.channel = (event.code == 0x71) ? eRFM_CH3 : eRFM_CH4; /* CH3/CH4 */ BDBG_ERR(("%s:%d set RFM CH%d (code = 0x%08x)\n",__FUNCTION__,__LINE__,(rf_settings.channel == eRFM_CH3) ? 3 : 4,event.code)); boutput_rf_set(settings.rf, &rf_settings); bapp_audio_mute(p_app,1); bdisplay_set(p_app->display, &settings); boutput_rf_set_audio_volume(settings.rf, DEFAULT_RFM_VOLUME); bapp_audio_mute(p_app,0); continue; } else if (event_cnt && ((int)event.code >= 0)) { BDBG_WRN(("%s:%d event_cnt = %d event 0x%08x(%s)\n",__FUNCTION__,__LINE__, event_cnt,event.code,(event.code & 0x40000000) ? "up" : "down")); screen_event.type = eS_EVENT_IR; screen_event.id = event.code; #ifdef BCM_DEBUG if (screen_event.id == 0x3A) { BDBG_WRN(("Enter status screen from screen %d\n",p_app->screen_id)); bapp_set_current_screen(p_app, eSCREEN_STATUS, eSCREEN_NULL); bapp_new_screen(p_app); } else if (screen_event.id == 0x3B) { BDBG_WRN(("Enter debug screen from screen %d\n",p_app->screen_id)); bapp_set_current_screen(p_app, eSCREEN_DEBUG, eSCREEN_NULL); bapp_new_screen(p_app); } else if (screen_event.id == 0xd7) { #if 0 p_app->ui_debug_mode = !p_app->ui_debug_mode; BDBG_WRN(("UI Debug Mode %d\n",p_app->ui_debug_mode)); bapp_flush_screen(p_app); p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id])); #else { uint32_t current_tick = bos_getticks(); p_app->last_keypress_tick = current_tick - (MS_TO_TICKS(AUTO_POWER_OFF_TIMEOUT) * (1 + p_app->settings.auto_power) - MS_TO_TICKS(1000 * 60)); BDBG_WRN(("Simulation auto power off last = %d, current = %d\n",p_app->last_keypress_tick,current_tick)); s_test_flag = true; } continue; #endif } else #endif /* BCM_DEBUG */ if (p_app->p_screens[p_app->screen_id].handle_event(p_app, (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { BDBG_MSG(("%s:%d screen_id %d\n",__FUNCTION__,__LINE__,p_app->screen_id)); /* Wait for vsync then do screen drawing */ bapp_new_screen(p_app); } else { bapp_handle_event(p_app,&screen_event); } } } if (!p_app->factory_test) { unsigned int flags = bos_enter_critical(); WriteReg32(LED_DATA_REG, ReadReg32( LED_DATA_REG) | LED_GREEN_MASK); bos_exit_critical(flags); } /* Check for notification events */ if ((p_event = (chm_event_t*)bos_pend_event(p_app->msg_queue,0)) != NULL) { screen_event.type = eS_EVENT_MAX; screen_event.id = p_event->id; switch (p_event->type) { case eCHM_EVT_SIGNAL: { chm_signal_event_t *p_sig = (chm_signal_event_t*)p_event; p_app->lock = (p_sig->lock) ? true : false; p_app->signal_level = p_sig->power; p_app->tuned_freq = p_sig->freq_hz; p_app->snr = p_sig->SNR; p_app->qam_b_mode = p_sig->qam_b_mode; } break; case eCHM_EVT_CANCEL: screen_event.type = eS_EVENT_CANCEL; break; case eCHM_EVT_DONE: screen_event.type = eS_EVENT_DONE; break; case eCHM_EVT_REDRAW: screen_event.type = eS_EVENT_REDRAW; break; case eCHM_PROGRESS: screen_event.type = eS_EVENT_PROGRESS; break; case eCHM_EVT_CAD: { unsigned char blocked; unsigned char region,dim,val; struct timeval tv; uint32_t current_ticks = bos_getticks(); /* ignore rating if ratings was received while tuned to a different channel. */ if (current_ticks < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) break; gettimeofday(&tv); BDBG_WRN(("PSIP Ratings @ %d\n",tv.tv_sec)); s_p_app->last_cad = tv.tv_sec; blocked = (uint8_t)(screen_event.id >> 24) & 0xFF; region = (uint8_t)(screen_event.id >> 16) & 0xFF; dim = (uint8_t)(screen_event.id >> 8) & 0xFF; val = (uint8_t)(screen_event.id & 0xFF); if ((s_p_app->ratings_region != region) || (s_p_app->ratings_dim != dim) || (s_p_app->ratings_val != val)) { s_p_app->ratings_region = region; s_p_app->ratings_dim = dim; s_p_app->ratings_val = val; } p_app->last_psip_rating_block_status = blocked; if (bapp_handle_blocking(p_app)) screen_event.type = eS_EVENT_SETUP; else /* Update OSD */ screen_event.type = eS_EVENT_REDRAW; } break; case eCHM_EVT_BLOCK: /* ignore rating if ratings was received while tuned to a different channel. */ if (bos_getticks() < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) break; /* p_app->last_rating_block_status = screen_event.id; - not necessary because already updated by bapp_xds_callback() */ if (bapp_handle_blocking(p_app)) screen_event.type = eS_EVENT_SETUP; break; case eCHM_EVT_RRT: { unsigned char rating_region; unsigned char version_number; uint32_t current_ticks = bos_getticks(); if (p_app->settings.ratings_lock < 2) break; /* ignore rating if ratings was received while tuned to a different channel. */ if (current_ticks < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) break; rating_region = (uint8_t)(screen_event.id >> 8) & 0xFF; version_number = (uint8_t)(screen_event.id & 0x1F); if (rating_region == 1) break; /* this will be dealt with in the default screen idle loop since we only want to alter rrt settings when the user is not in the menu system. */ if (screen_event.id != p_app->settings.last_rrt_id) { BDBG_WRN(("####### NEW RRT(0x%02x,0x%02x) ###\n",rating_region,version_number)); p_app->settings.last_rrt_id = screen_event.id; p_app->settings.rrt_status = eRRT_AVAILABLE; switch (p_app->screen_id) { case eSCREEN_RATINGS: case eSCREEN_RATINGS_LOCK: case eSCREEN_RATINGS_LIMITS: case eSCREEN_RATINGS_TV: case eSCREEN_RATINGS_MOVIES: case eSCREEN_RATINGS_RRT_DIM: case eSCREEN_RATINGS_RRT_VAL: case eSCREEN_RATINGS_RRT_UPDATE: bapp_set_current_screen(p_app, eSCREEN_RATINGS_RRT_UPDATE, eSCREEN_NULL); bapp_new_screen(p_app); break; default: bapp_set_current_screen(p_app, eSCREEN_RATINGS_RRT_UPDATE, eSCREEN_MAX); bapp_new_screen(p_app); break; } } } break; case eCHM_EVT_CSD: /* Do nothing */ break; } BDBG_MSG(("%s:%d CHM EVENT = %d)\n",__FUNCTION__,__LINE__,p_event->type)); if (p_app->p_screens[p_app->screen_id].handle_event(p_app, (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { BDBG_MSG(("%s:%d screen_id %d\n",__FUNCTION__,__LINE__,p_app->screen_id)); /* Wait for vsync then do screen drawing */ bapp_new_screen(p_app); } else { bapp_handle_event(p_app,&screen_event); } } /* Yield control */ bapp_sleep(p_app->yield_ms); screen_event.type = eS_EVENT_IDLE; screen_event.id = 0; /* Give screen idle time to handle menu timeouts, etc */ if (p_app->p_screens[p_app->screen_id].handle_event(p_app, (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { /* Wait for vsync then do screen drawing */ bapp_new_screen(p_app); } /* Do application idle time processing */ bapp_idle(p_app); } /* finish */ bmessage_uninit(); bsettop_uninit(); } /* Summary: Check current channel for SAP Description: Check current channel for SAP, and set current_sap to -1 if no, otherwise current lang as base to rotate */ void bapp_check_sap(bapp_t *p_app) { p_app->num_sap = 0; if (p_app->settings.ch[p_app->cur_ch_num].audio_pid[0]) p_app->num_sap++; if (p_app->settings.ch[p_app->cur_ch_num].audio_pid[1]) p_app->num_sap++; if (p_app->settings.ch[p_app->cur_ch_num].audio_pid[2]) p_app->num_sap++; BDBG_WRN(("%s p_app->num_sap = %d\n",__FUNCTION__,p_app->num_sap)); } /* Summary: Tune to the current frequency and get the VCT. Description: Tune to the current frequency and get the VCT. Returns non-zero on failure. */ int bapp_change_channel(bapp_t *p_app, int ch_up, int tune) { int retval = -1; if (p_app->settings.num_channels) { int i = 0; p_app->last_ch_num = p_app->cur_ch_num; /* search for the next "active" channel in ch list */ for (i = 0; (i < p_app->settings.num_channels); i++) { if (ch_up) { p_app->cur_ch_num++; if (p_app->cur_ch_num >= p_app->settings.num_channels) p_app->cur_ch_num = 0; } else { if (p_app->cur_ch_num == 0) { p_app->cur_ch_num = p_app->settings.num_channels - 1; } else p_app->cur_ch_num--; } if (!p_app->settings.ch[p_app->cur_ch_num].hidden) break; } BDBG_ERR(("bapp_change_channel %d.%d\n",p_app->settings.ch[p_app->cur_ch_num].major,p_app->settings.ch[p_app->cur_ch_num].minor)); if (tune) { retval = bapp_tune(p_app); } else { retval = 0; } } return retval; } /* Summary: Tune to the specified channel. Description: Tune to the specified channel or nearest to the channel. Returns non-zero on failure. */ int bapp_set_channel(bapp_t *p_app, int major, int minor) { int retval = -1; int i = 0; BDBG_ERR(("bapp_set_channel %d.%d\n",major,minor)); /* search channel list for channel data */ for (i = 0; i < p_app->settings.num_channels; i++) { if (major == 0) continue; if ((p_app->settings.ch[i].major == major) && (p_app->settings.ch[i].minor == minor)) { /* found matching channel */ if (p_app->cur_ch_num != i) { p_app->last_ch_num = p_app->cur_ch_num; p_app->cur_ch_num = i; retval = bapp_tune(p_app); } else { /* already tuned to correct channel so do nothing */ retval = 0; } } } return retval; } /* Summary: Perform a channel scan. Description: Perform a channel scan. Returns non-zero on failure. */ int bapp_channel_scan(bapp_t *p_app) { p_app->settings.cur_ch_num = 0; p_app->cur_ch_num = 0; chm_cmd(&p_app->chm,eCHM_SCAN); return 0; } /* Summary: Tune to the current channel. */ int bapp_tune(bapp_t *p_app) { /* only tune necessary */ if ((p_app->cur_ch_num == p_app->chm.cur_ch_num) && (p_app->chm.cur_ch_num != 0xFF) && (p_app->decoding)) return 0; p_app->current_sap = p_app->lang; p_app->captions_basic = p_app->settings.captions_basic; if (p_app->ratings_override_set) { p_app->ratings_override_set = false; } else { p_app->ratings_override = false; } /* reset so ratings will be re-evaluated when returned to full tv */ p_app->last_rating_block_status = -1; /* assume psip unblock */ p_app->last_psip_rating_block_status = 0; /* clear ratings string */ p_app->prog_rating_str[0] = 0; p_app->psip_rating_str[0] = 0; BDBG_WRN(("Reset rating string @ %d\n",__LINE__)); chm_cmd(&p_app->chm,eCHM_TUNE); p_app->decoding = true; p_app->last_tune_tick = bos_getticks(); return 0; } /* Summary: Stop decoding audio and video */ int bapp_stop_decode(bapp_t *p_app) { chm_cmd(&p_app->chm,eCHM_STOP); p_app->decoding = false; return 0; } /* Summary: Restart decoding audio and video */ int bapp_restart_decode(bapp_t *p_app) { bapp_stop_decode(p_app); bapp_tune(p_app); return 0; } /* Summary: Restart audio decode (after SAP swap audio PID) */ int bapp_rotate_audio_sap(bapp_t *p_app) { bapp_check_sap(p_app); if (p_app->num_sap <= 1) { BDBG_WRN(("p_app->num_sap = %d\n",p_app->num_sap)); return -1; } p_app->current_sap++; p_app->current_sap %= 3; /* max 3 SAP */ if (0 == p_app->settings.ch[p_app->cur_ch_num].audio_pid[p_app->current_sap]) p_app->current_sap = (p_app->current_sap + 1) % 3; /* in case only two SAPs */ BDBG_WRN(("audio[%d].pid=%d\n", p_app->current_sap, p_app->settings.ch[p_app->cur_ch_num].audio_pid[p_app->current_sap])); baudio_decode_stop(p_app->audio); // Need to update for new stream structures p_app->stream->mpeg.audio[0].pid = p_app->settings.ch[p_app->cur_ch_num].audio_pid[p_app->current_sap]; baudio_decode_start(p_app->audio, (void *)1, p_app->stream); return 0; } /* Summary: set CLUT */ void bapp_set_palette(bapp_t *p_app, bapp_palette_t palette) { unsigned int *clut; /* [out] address of palette */ int width; /* [out] width of the OSD surface */ int height; /* [out] height of the OSD surface */ int pitch; /* [out] pitch of the OSD surface */ bgraphics_get_framebuffer(p_app->graphics,(void**)&p_app->osd_mem,(unsigned int **)&clut,&width,&height,&pitch); switch (palette) { case ePALETTE_SCREENSAVER: get_screensaver_palette(clut); break; case ePALETTE_EIA_708: get_eia_708_palette(clut); break; case ePALETTE_DEFAULT: default: get_def_palette(clut); break; } bgraphics_load_palette(p_app->graphics); } /* Summary: returns true is sufficient signal strength, false otherwise always returns true for TUNE_DURATION msecs after tuning begins. */ bool bapp_get_signal_status(bapp_t *p_app) { static bool first_call = true; static bool good_signal = true; static uint32_t last_video_pts = 0; static uint32_t last_video_pts_ticks = 0; static uint32_t last_audio_pts = 0; static uint32_t last_audio_pts_ticks = 0; bdecode_status status; uint32_t current_ticks = bos_getticks(); /* check for tune duration timeout - this is used to restrict display of the 'no signal' popup for a period of time (TUNE_DURATION) after tuning */ if (current_ticks < (p_app->last_tune_tick + MS_TO_TICKS(TUNE_DURATION))) return true; /* if no channels, don't bother doing any more checking */ if (p_app->settings.num_channels == 0) return false; /* if the stream is audio only return true */ if ((p_app->settings.ch[p_app->cur_ch_num].video_pid == 0) && (p_app->settings.ch[p_app->cur_ch_num].audio_pid != 0)) return true; /* if first time calling function get baseline video pts * then wait 500msecs and continue. since we require 2 samples * of decoder status at least 500msecs apart to determine signal * status, we need to "prime the pump" on the very first call only */ if (first_call) { first_call = false; status.audio_decode = p_app->audio; bdecode_get_status(p_app->decode,&status); last_video_pts = status.video_pts; last_video_pts_ticks = current_ticks; bos_sleep(500); current_ticks = bos_getticks(); last_audio_pts = status.audio_pts; } /* make sure video pts is changing - indicates successful decoding. * only check every 500msecs or so */ if ((current_ticks - last_video_pts_ticks) > MS_TO_TICKS(500)) { status.audio_decode = p_app->audio; bdecode_get_status(p_app->decode,&status); /* if pts is changing, we are decoding properly */ good_signal = (last_video_pts != status.video_pts); if (good_signal == false) { good_signal = (last_audio_pts != status.audio_pts); } last_audio_pts = status.audio_pts; BDBG_MSG(("good_signal:%d vpts:0x%08x last_vpts:0x%08x ticks:%d", good_signal, status.video_pts, last_video_pts, current_ticks)); last_video_pts = status.video_pts; last_video_pts_ticks = current_ticks; } return good_signal; } /* Summary: Set closed captions options Description: Set closed captions options */ void bapp_set_captions_options(bapp_t *p_app) { BDBG_ERR(("%s current %d, new %d", __FUNCTION__,p_app->settings.captions_basic,p_app->captions_basic)); if (p_app->captions_basic != p_app->settings.captions_basic) { p_app->settings.captions_basic = p_app->captions_basic; p_app->settings_dirty = true; } } /* Summary: Main entry point */ #ifdef LINUX int main(void) { static bapp_t app; bapp_init(&app); bapp_run(&app); } #endif