source: svn/newcon3bcm2_21bu/nexus/app/dta/bapp.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 57.9 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2006, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile:  $
11 * $brcm_Revision:  $
12 * $brcm_Date: $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log:  $
19 *
20 ***************************************************************************/
21
22#include "bapp.h"
23#include "bgfx.h"
24#include "bstd.h"
25#include "led.h"
26#include "bapp_palette.h"
27
28BDBG_MODULE(bapp);              /* Register software module with debug interface */
29
30static const unsigned short s_volume[] =
31{
32        4096, 3254, 2584, 2053,
33        1631, 1295, 1029, 817,
34        649, 516, 410, 325,
35        258, 205, 163, 130,
36        103, 82, 65, 52, 
37        41, 33, 26, 21, 
38        16, 13, 10, 8, 
39        6, 5, 4, 3
40};
41const int s_volume_num = sizeof(s_volume)/sizeof(unsigned short);
42
43/**
44Summary:
45        IO structure passed to bgfx when initialized
46**/
47
48static bgfx_io_t s_io =
49{
50        bin_read,
51        bin_tell,
52        bin_set
53};
54#define BAPP_VCHIP_TIMEOUT            (7000)      /* Milliseconds */
55#define BAPP_RATINGS_EVAL_DELAY       (500)       /* Milliseconds */
56#define DEFAULT_VOLUME                                  0
57#define DEFAULT_RFM_VOLUME                              78
58#define BAPP_DIAG_TIMEOUT                               3               /* Seconds */
59
60#define BAPP_VCHIP_MSG                                  BDBG_WRN
61#define TIME_APP_DRAWING
62static bgfx_font_t  s_font[eFONT_SIZE_MAX];
63
64static void bapp_eval_state(bapp_t *p_app,bapp_state_t new_state);
65#if !defined(RAM_BUILD)
66static int bapp_stop_decode(bapp_t *p_app);
67#endif
68static int bapp_channel_hunt(bapp_t *p_app);
69static void bapp_standby(bapp_t *p_app, bool power);
70static void bapp_new_screen(bapp_t *p_app);
71
72extern unsigned int g_FrancophilB_22_mono_size;
73extern const unsigned char g_FrancophilB_22_mono[];
74extern unsigned int g_FrancophilB_28_mono_size;
75extern const unsigned char g_FrancophilB_28_mono[];
76
77/*
78 * Global app reference used by a couple callbacks to reference the application.
79 */
80
81bapp_t *s_p_app = NULL;
82
83static bscreen_t g_screens[] =
84{  /* title_text_id                    desc_text_id                          help_text_id      top_banner_height      num_buttons   idle_timeout                          p_button_array                  (* draw)()                     (* handle_event)()             local_state */
85        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      BANNER_SMALL_TIMEOUT,   eSCREEN_MAX, 0,                          bscreen_banner_draw,           screen_banner_event,           (uint32_t)&g_banner_state},
86        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      0,                      eSCREEN_MAX, 0,                          bscreen_screensaver_draw,      screen_screensaver_event,      (uint32_t)&g_screensaver_state},
87        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      0,                      eSCREEN_MAX, 0,                          bscreen_power_off_draw,        screen_power_off_event,        0},
88        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_diag_menu_draw,        bscreen_diag_menu_event,       0},
89        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_sys_info_draw,         bscreen_sys_info_event,        0},
90        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_dta_status_draw,       bscreen_dta_status_event,      0},
91        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_mso_info_draw,         bscreen_mso_info_event,        0},
92        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_tuner_status_draw,     bscreen_tuner_status_event,    0},
93        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_ch_status_draw,        bscreen_ch_status_event,       0},
94        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_ch_map_status_draw,    bscreen_ch_map_status_event,   0},
95        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_msg_status_draw,       bscreen_msg_status_event,      0},
96        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_code_objects_draw,     bscreen_code_objects_event,    0},
97        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_code_download_draw,    bscreen_code_download_event,   0},
98        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_decoder_status_draw,   bscreen_decoder_status_event,  0},
99/*      { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_hh_draw,               bscreen_hh_event,              0},*/
100        { eTEXT_MAX,                       eTEXT_MAX,                        eTEXT_MAX,            0,                     0, 0, 0,      SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0,                          bscreen_status_draw,           bscreen_status_event,          0},
101};                                                                                                                                                                 
102
103const unsigned char g_screens_num = sizeof(g_screens)/sizeof(g_screens[0]);
104
105void bl_write(void)
106{
107}
108#ifdef BDBG_DEBUG_BUILD
109static const char *s_chm_evt_str[] =
110{
111        "CHM_EVT_CANCEL",
112        "CHM_EVT_DONE",
113        "CHM_EVT_REDRAW",
114        "CHM_EVT_PROGRESS",
115        "CHM_EVT_SIGNAL",
116        "CHM_EVT_DOWNLOAD",
117        "CHM_EVT_EAS",
118        "CHM_EVT_CA",
119        "CHM_EVT_NETWORK",
120        "CHM_EVT_STATUS",
121        "CHM_EVT_AV_MUTE",     
122        "CHM_EVT_ACTIVATION",   
123        "CHM_EVT_CONFIGURATION",   
124        "CHM_EVT_VCT_ID",   
125        "CHM_EVT_LOCATION",     
126        "CHM_EVT_TIMEZONE",     
127        "CHM_EVT_PHONENUMBER",
128        "CHM_EVT_RESET",
129        "CHM_EVT_SAVE",
130        "CHM_EVT_TIME",
131};
132#endif
133
134/*
135Summary:
136        Set the LED mode based on the state and settings.
137*/
138void bapp_led_set_mode(bapp_t *p_app)
139{
140        enum led_mode_t mode = led_off_mode;
141
142        if (!p_app->power)
143        {
144                mode = led_off_mode;
145        } else
146        {
147                switch (p_app->state)
148                {
149                case eAPP_STATE_HUNT:  mode = led_hunt_mode; break;
150                case eAPP_STATE_PENDING: mode = led_pending_init_mode; break;
151                case eAPP_STATE_NORMAL:  mode = led_on_mode;  break;
152                case eAPP_STATE_DOWNLOAD:  mode = led_download_mode;  break;
153                case eAPP_STATE_FACTORY:
154                case eAPP_STATE_DEFAULT:
155                case eAPP_STATE_DONE:
156                        break;
157                }
158        }
159
160        if (mode == p_app->led_mode)
161        {
162                return;
163        }
164
165        p_app->led_mode = mode;
166        led_set_mode(mode);
167}
168
169/*
170 * Flush cache
171 */
172
173void bapp_flush_screen(bapp_t *p_app)
174{
175        BDBG_WRN(("%s:%d-%d\n",__FUNCTION__,__LINE__,p_app->nexus.surface_idx));
176        NEXUS_Surface_Flush(p_app->nexus.surface[p_app->nexus.surface_idx]);
177        NEXUS_Display_SetGraphicsFramebuffer(p_app->nexus.display, p_app->nexus.surface[p_app->nexus.surface_idx]);
178
179        p_app->nexus.surface_idx++;
180        if (p_app->nexus.surface_idx >= BAPP_NUM_SURFACES)
181        {
182                p_app->nexus.surface_idx = 0;
183        }
184
185        p_app->surf.surface.buf = p_app->nexus.mem[p_app->nexus.surface_idx].buffer;
186}
187
188/*
189Summary:
190Set volume level
191Description:
192        Set Volume level (range 0(full) - s_volume_num)
193 */
194void bapp_set_audio_volume(bapp_t *p_app, uint8_t level)
195{
196        uint32_t new_vol = level;
197        uint32_t cur_vol = p_app->audio_vol;
198        uint32_t vol;
199
200        /* possibly cancel mute */
201        if (level < (s_volume_num - 1))
202        {
203                bapp_audio_mute(p_app, 0);
204        }
205
206        BDBG_WRN(("%s audio_vol = %d, new_vol = %d, is_muted = %d...\n",__FUNCTION__,p_app->audio_vol,new_vol,p_app->is_muted));
207
208        if ((level >= s_volume_num) || (new_vol == cur_vol))
209                return;
210
211        if (new_vol > cur_vol)
212        {
213                for (p_app->audio_vol = cur_vol; p_app->audio_vol < new_vol; ++p_app->audio_vol)
214                {
215                        vol = s_volume[p_app->audio_vol];
216                        /* JPF TODO Set the volume here */
217                        bapp_task_sleep(1);
218                }
219        } else
220        {
221                for (p_app->audio_vol = cur_vol; p_app->audio_vol > new_vol; --p_app->audio_vol)
222                {
223                        vol = s_volume[p_app->audio_vol];
224                        /* JPF TODO Set the volume here */
225                        bapp_task_sleep(1);
226                }
227        }
228        p_app->audio_vol = level;
229        vol = s_volume[p_app->audio_vol];
230        /* JPF TODO Set the volume here */
231}
232/*
233Summary:
234Mute audio
235Description:
236Mute audio when enable is non-zero.
237 */
238void bapp_audio_mute(bapp_t *p_app, int mute)
239{
240        int vol,idx;
241
242        if ((mute && p_app->is_muted) || (!mute && !p_app->is_muted) || p_app->settings.av_mute)
243                return;
244
245        BDBG_WRN(("%s mute = %d, audo_vol = %d, is_muted = %d...\n",__FUNCTION__,mute,p_app->audio_vol,p_app->is_muted));
246        if (mute)
247        {
248                for (idx = p_app->audio_vol; idx < s_volume_num; ++idx)
249                {
250                        vol = s_volume[idx];
251                        /* JPF TODO Set the volume here */
252                        bapp_task_sleep(1);
253                }
254                p_app->is_muted = true;
255        } else
256        {
257                for (idx = (s_volume_num-1); idx >= p_app->audio_vol; --idx)
258                {
259                        vol = s_volume[idx];
260                        /* JPF TODO Set the volume here */
261                        bapp_task_sleep(1);
262                }
263                p_app->is_muted = false;
264        }
265}
266/*
267Summary:
268Mute both audio and video.
269Description:
270Mute both audio and video when enable is non-zero.
271 */
272void bapp_av_mute(bapp_t *p_app, int mute)
273{
274#if 0 /* JPF TODO MUTE DISPLAY AND AUDIO */
275        bdecode_config cfg;
276
277        bapp_audio_mute(p_app,mute);
278        bdecode_get_config(p_app->decode,&cfg);
279        if (mute)
280                cfg.mute = 1;
281        else
282                cfg.mute = 0;
283
284        bdecode_set_config(p_app->decode,&cfg);
285
286        if (mute)
287        {
288                bapp_sync(p_app);
289                bgfx_fill_rect(&p_app->surf,0,0,eWIDTH,eHEIGHT,eCOLOR_CLEAR);
290                bapp_flush_screen(p_app);
291        }
292
293        p_app->settings.av_mute = mute;
294        p_app->settings_dirty = true;
295#endif
296}
297/*
298Summary:
299Configure the video output mode.
300Description:
301Configure the video output mode.
302 */
303void bapp_output_mode(bapp_t *p_app, int widescreen)
304{
305#if 0 /* JPF TODO SET OUTPUT MODE- extend to HD */
306        bdecode_config cfg;
307        bdecode_get_config(p_app->decode,&cfg);
308        if (widescreen)
309        {
310                BDBG_WRN(("Widescreen (%d)\n", widescreen));
311                cfg.widescreen = widescreen;
312        } else
313        {
314                BDBG_WRN(("Full Screen...\n"));
315                cfg.widescreen = 0;
316        }
317        bdecode_set_config(p_app->decode,&cfg);
318#endif
319}
320
321/*
322Summary:
323Apply the current settings.
324Description:
325Apply the current settings. Restart decode.
326 */
327static void bapp_apply_settings(bapp_t *p_app)
328{
329        p_app->audio_vol  = p_app->settings.audio_vol;
330
331        bapp_output_mode(p_app, 0);
332        bapp_set_audio_volume(p_app, p_app->audio_vol);
333}
334
335/*
336Summary:
337Reset the current user settings
338Description:
339Reset the current user settings.  Note this does not change them in flash.
340 */
341void bapp_reset_settings(bapp_t *p_app)
342{
343        memset(&p_app->settings, 0, sizeof(p_app->settings));
344
345        ch_map_init(&(p_app->settings.ch_map),p_app->ch_map_mutex);
346        p_app->settings.network_PID = CONFIG_NETWORK_PID;
347        p_app->settings.VCT_ID = CONFIG_DEF_VCT_ID;
348        p_app->settings.EMM_PID = CONFIG_DEF_EMM_PID;
349        /* this will make sure volume is reset to default from UI */
350        p_app->audio_vol = p_app->settings.audio_vol;
351}
352
353/*
354Summary:
355        Calculate the ch_map storage size in bytes
356 */
357typedef struct settings_hdr_t
358{
359        uint32_t settings_size;
360        uint32_t st_cnt;
361        uint32_t vch_cnt;
362        uint32_t mms_cnt;
363        uint32_t freq_cnt;
364        uint32_t cur_ch;
365}settings_hdr_t;
366
367static void bapp_calc_settings_hdr(bapp_t *p_app, settings_hdr_t *p_hdr)
368{
369        p_hdr->freq_cnt = p_app->settings.ch_map.freq_map.num_freq;
370        p_hdr->mms_cnt = p_app->settings.ch_map.mms_map.num_mms;
371        p_hdr->st_cnt = p_app->settings.ch_map.st_map.num_st;
372        p_hdr->vch_cnt = p_app->settings.ch_map.vch_map.num_vch;
373        p_hdr->cur_ch = p_app->settings.ch_map.cur_ch; /* also store cur_ch in the header */
374        p_hdr->settings_size = sizeof(settings_hdr_t); /* Size header */
375        p_hdr->settings_size += ((uint32_t)&(p_app->settings.ch_map) - (uint32_t)&(p_app->settings)); /* Settings minus ch_map */
376        p_hdr->settings_size += (p_hdr->mms_cnt * sizeof(mms_t)); /* mms records */
377        p_hdr->settings_size += (p_hdr->freq_cnt * sizeof(freq_t)); /* freq records */
378        p_hdr->settings_size += (p_hdr->st_cnt * sizeof(st_t)); /* st records */
379        p_hdr->settings_size += (p_hdr->vch_cnt * sizeof(vch_t)); /* vch records */
380}
381/*
382Summary:
383Load current settings from NVM
384 */
385static void bapp_load_settings(bapp_t *p_app)
386{
387        settings_hdr_t settings_hdr;
388        uint8_t *p_flash_data = NULL;
389        uint32_t flash_data_length;
390        uint32_t offset = 0;
391        uint32_t size = 0;
392        if (fstore_get(&p_app->flash_storage, eFS_APP_DATA, (void **)&(p_flash_data), &flash_data_length) == b_ok)
393        {
394                memcpy(&settings_hdr,p_flash_data,sizeof(settings_hdr_t));
395                if (flash_data_length == settings_hdr.settings_size)
396                {
397                        /* flash data valid - use it! */
398                        BDBG_WRN(("Flash valid app data length %d bytes restore settings\n", flash_data_length));
399
400                        ch_map_init(&(p_app->settings.ch_map),p_app->ch_map_mutex);
401                        ch_map_reset(&(p_app->settings.ch_map));
402                        if (bapp_task_acquire_mutex(p_app->settings.ch_map.p_mutex,45) == b_ok)
403                        {
404                                p_app->settings.ch_map.freq_map.num_freq = (uint8_t)settings_hdr.freq_cnt;
405                                p_app->settings.ch_map.mms_map.num_mms = (uint8_t)settings_hdr.mms_cnt;
406                                p_app->settings.ch_map.st_map.num_st = (uint16_t)settings_hdr.st_cnt;
407                                p_app->settings.ch_map.vch_map.num_vch = (uint16_t)settings_hdr.vch_cnt;
408                                p_app->settings.ch_map.cur_ch = (uint16_t)settings_hdr.cur_ch;
409                                offset = sizeof(settings_hdr_t);
410                                size = ((uint32_t)&(p_app->settings.ch_map) - (uint32_t)&(p_app->settings));
411                                memcpy(&p_app->settings,&p_flash_data[offset],size); /* Copy settings minus the ch_map */
412                                offset += size;
413                                size = sizeof(mms_t) * p_app->settings.ch_map.mms_map.num_mms;
414                                memcpy(p_app->settings.ch_map.mms_map.mms,&p_flash_data[offset],size); /* Copy settings mms portion of the ch_map */
415                                offset += size;
416                                size = sizeof(freq_t) * p_app->settings.ch_map.freq_map.num_freq;
417                                memcpy(p_app->settings.ch_map.freq_map.freq,&p_flash_data[offset],size); /* Copy settings freq portion of the ch_map */
418                                offset += size;
419                                size = sizeof(st_t) * p_app->settings.ch_map.st_map.num_st;
420                                memcpy(p_app->settings.ch_map.st_map.st,&p_flash_data[offset],size); /* Copy settings st portion of the ch_map */
421                                offset += size;
422                                size = sizeof(vch_t) * p_app->settings.ch_map.vch_map.num_vch;
423                                memcpy(p_app->settings.ch_map.vch_map.vch,&p_flash_data[offset],size); /* Copy settings vch portion of the ch_map */
424                                bapp_task_release_mutex(p_app->settings.ch_map.p_mutex);
425                                p_app->settings_dirty = false;
426                                ch_output(bapp_cur_ch_map(p_app));
427                        } 
428                        else
429                        {
430                                BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__));
431                        }
432                        return;
433                }
434        }
435
436        /* flash contains invalid saved data */
437        BDBG_WRN(("Flash app data length %d not equal to header length %d, reset.\n", flash_data_length, settings_hdr.settings_size));
438
439        bapp_reset_settings(p_app);
440        p_app->audio_vol    =    p_app->settings.audio_vol;
441
442        /* update flash with new settings */
443        bapp_save_settings(p_app);
444}
445
446/*
447Summary:
448Save current settings to NVM
449Description:
450Save current settings to NVM
451 */
452void bapp_save_settings(bapp_t *p_app)
453{
454        settings_hdr_t settings_hdr;
455
456        uint8_t *p_flash_data = NULL;
457        uint32_t offset = 0;
458        uint32_t size = 0;
459       
460        /* update unsaved settings */
461        p_app->settings.audio_vol  = p_app->audio_vol;
462
463        bapp_calc_settings_hdr(p_app,&settings_hdr);
464
465        p_flash_data = bapp_util_malloc(settings_hdr.settings_size);
466        if (!p_flash_data)
467        {
468                BDBG_WRN(("Could not find temporary memory to save settings to flash\n", settings_hdr.settings_size));
469                return;
470        }
471        BDBG_WRN(("Flash data length %d bytes, save settings\n", settings_hdr.settings_size));
472        memcpy(p_flash_data,&settings_hdr,sizeof(settings_hdr_t));
473
474        if (bapp_task_acquire_mutex(p_app->settings.ch_map.p_mutex,45) == b_ok)
475        {
476                offset = sizeof(settings_hdr_t);
477                size = ((uint32_t)&(p_app->settings.ch_map) - (uint32_t)&(p_app->settings));
478                memcpy(&p_flash_data[offset],&p_app->settings,size); /* Copy settings minus the ch_map */
479                offset += size;
480                size = sizeof(mms_t) * p_app->settings.ch_map.mms_map.num_mms;
481                memcpy(&p_flash_data[offset],p_app->settings.ch_map.mms_map.mms,size); /* Copy settings mms portion of the ch_map */
482                offset += size;
483                size = sizeof(freq_t) * p_app->settings.ch_map.freq_map.num_freq;
484                memcpy(&p_flash_data[offset],p_app->settings.ch_map.freq_map.freq,size); /* Copy settings freq portion of the ch_map */
485                offset += size;
486                size = sizeof(st_t) * p_app->settings.ch_map.st_map.num_st;
487                memcpy(&p_flash_data[offset],p_app->settings.ch_map.st_map.st,size); /* Copy settings st portion of the ch_map */
488                offset += size;
489                size = sizeof(vch_t) * p_app->settings.ch_map.vch_map.num_vch;
490                memcpy(&p_flash_data[offset],p_app->settings.ch_map.vch_map.vch,size); /* Copy settings vch portion of the ch_map */
491                bapp_task_release_mutex(p_app->settings.ch_map.p_mutex);
492        } 
493        else
494        {
495                BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__));
496                return;
497        }
498
499        p_app->settings_dirty = false;
500        if (fstore_update(&p_app->flash_storage, eFS_APP_DATA, p_flash_data, settings_hdr.settings_size) != b_ok)
501        {
502                BDBG_WRN(("fstore_update failed\n"));
503        } else
504        {
505                BDBG_WRN(("fstore_update success\n"));
506        }
507}
508/*
509Summary:
510Power down audio DAC and power off
511 */
512void bapp_do_poweroff(bapp_t *p_app)
513{
514        /* JPF TODO Power OFF */
515}
516
517/*
518Summary:
519Initialize the main app structure.
520Description:
521Do necessary configuration of main app structure.  Assumes
522p_app is allocated and p_surf and palette are initialized.
523 */
524void bapp_init(bapp_t *p_app)
525{
526
527        bapp_lang_t e_lang;
528        bresult rc;
529        unsigned int *palette;  /* [out] address of palette */
530        int width;                              /* [out] width of the OSD surface  */
531        int height;                             /* [out] height of the OSD surface  */
532        int pitch;                              /* [out] pitch of the OSD surface  */
533
534        BDBG_MSG(("%s:%d\n",__FUNCTION__,__LINE__));
535        memset(p_app,0,sizeof(bapp_t));
536
537        s_p_app = p_app;
538        p_app->last_key_down = (bIR_codes_t)0xFFF;
539
540        p_app->last_screen_id = eSCREEN_MAX;
541
542        /* Initialize Nexus */
543        bapp_nexus_open(&(p_app->nexus), eTUNE_TYPE_QAM);
544
545        /* initialize bgfx */
546        bgfx_init(&s_io,NULL);
547
548        rc = bgfx_create(&(p_app->surf),
549                                                                p_app->nexus.createSettings[p_app->nexus.surface_idx].width,
550                                                                p_app->nexus.createSettings[p_app->nexus.surface_idx].height,
551                                                                (uint8_t*)p_app->nexus.mem[p_app->nexus.surface_idx].buffer,
552                                                                p_app->nexus.mem[p_app->nexus.surface_idx].pitch,
553                                                                (bgfx_palette_t*)p_app->nexus.mem[p_app->nexus.surface_idx].palette, 
554                                                                BGFX_SURF_PRIMARY | BGFX_SURF_BPP(bapp_get_bpp()));
555
556        BDBG_ASSERT(rc == 0);
557
558        /* Open IR */
559        bapp_remote_open(&(p_app->remote));
560        BDBG_ASSERT(p_app->remote);
561
562        GETTIMEOFDAY(&p_app->timeout_tv);
563
564        smessage_init(NULL);
565
566        bapp_task_create_queue(&p_app->msg_queue, p_app->msg_event, MAX_MSG_EVENT);
567        BDBG_ASSERT(p_app->msg_queue);
568
569        rc = bapp_task_create_mutex(&p_app->ch_map_mutex);
570        BDBG_ASSERT(rc == b_ok);
571
572        ch_map_init(&(p_app->settings.ch_map),p_app->ch_map_mutex);
573       
574        /* should after bgraphics_open, since bgraphics_open will overwrite some BVN TOP registers, e.g. AMOL */
575        chm_init(&p_app->chm,p_app);
576
577        p_app->yield_ms = APP_DEFAULT_YIELD;
578        p_app->lang = eLANG_ENGLISH;
579
580        p_app->width = p_app->nexus.createSettings[p_app->nexus.surface_idx].width;
581        p_app->height = p_app->nexus.createSettings[p_app->nexus.surface_idx].height;
582        BDBG_MSG(("%s:%d - Width = %d, Height = %d, Pitch = %d.\n",__FUNCTION__,__LINE__,width,height,pitch));
583
584        BDBG_MSG(("%s:%d - Initialize screens.\n",__FUNCTION__,__LINE__));
585
586        /* Default to NULL (empty) screen (TODO:  goto factory test then setup wizard.) */
587        p_app->screen_id = eSCREEN_BANNER;
588
589        p_app->p_screens = g_screens;
590        p_app->num_screens = g_screens_num;
591
592        BDBG_MSG(("%s:%d - Load fonts.\n",__FUNCTION__,__LINE__));
593
594        memset(&s_font[eFONT_SIZE_SMALL],0,sizeof(bgfx_font_t) * 3);
595        p_app->br.cnt = 0;
596        p_app->br.data = (unsigned char*)g_FrancophilB_22_mono;
597        p_app->br.size = g_FrancophilB_22_mono_size;
598
599        BDBG_ASSERT(bgfx_load_font(&(s_font[eFONT_SIZE_SMALL]),&p_app->br) == 0);
600
601        p_app->br.cnt = 0;
602        p_app->br.data = (unsigned char*)g_FrancophilB_28_mono;
603        p_app->br.size = g_FrancophilB_28_mono_size;
604
605        BDBG_ASSERT(bgfx_load_font(&(s_font[eFONT_SIZE_MED]),&p_app->br) == 0);
606
607        for (e_lang = eLANG_ENGLISH; e_lang < eLANG_MAX; ++e_lang)
608        {
609                p_app->p_font[e_lang][eFONT_SIZE_SMALL] = &s_font[eFONT_SIZE_SMALL];
610                p_app->p_font[e_lang][eFONT_SIZE_MED] = &s_font[eFONT_SIZE_MED];
611        }
612
613        BDBG_ASSERT(fstore_init(&(p_app->flash_storage)) == b_ok);
614
615        bapp_load_settings(p_app);
616
617        if (p_app->settings.activated)
618        {
619                if (((int)p_app->settings.timeout_cnt) >= 2)
620                {
621                        p_app->settings.timeout_cnt -= 2;
622                } else
623                {
624                        p_app->settings.activated = false;
625                        p_app->settings_dirty = true;
626                }
627        }
628
629#ifdef CONFIG_DTA_CABLE_TESTING
630        {
631                bapp_task_mutex_t       *p_mutex = p_app->settings.ch_map.p_mutex;
632                extern const ch_map_t s_ch_map;
633                memcpy(&p_app->settings.ch_map,&s_ch_map, sizeof(s_ch_map));
634                p_app->settings.ch_map.p_mutex = p_mutex;
635                p_app->settings.activated = true;
636        }
637#endif
638
639        bapp_apply_settings(p_app);
640
641        BDBG_WRN(("%s:%d - av_mute = %d\n",__FUNCTION__,__LINE__,p_app->settings.av_mute));
642        BDBG_WRN(("%s:%d - prev_state = %d\n",__FUNCTION__,__LINE__,p_app->settings.state));
643
644        bapp_av_mute(p_app,0);
645
646        bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
647        bapp_new_screen(p_app);
648        p_app->power = 1;
649
650        /* Always enter pending state on hard power up. */
651#ifdef CONFIG_DTA_CABLE_TESTING
652        bapp_eval_state(p_app,eAPP_STATE_NORMAL);
653#else
654        if (p_app->settings.psi_scan)
655                bapp_eval_state(p_app,eAPP_STATE_NORMAL);
656        else
657                bapp_eval_state(p_app,eAPP_STATE_HUNT);
658#endif
659
660#if 0
661#ifdef BDBG_DEBUG_BUILD
662        BDBG_SetModuleLevel("bscreen",BDBG_eMsg);
663#endif
664        BDBG_SetModuleLevel("xpt_mesg",BDBG_eMsg);
665        BDBG_SetModuleLevel("nexus_message",BDBG_eMsg);
666        BDBG_SetModuleLevel("BXVD",BDBG_eMsg);
667        BDBG_SetModuleLevel("nexus_video_decoder",BDBG_eMsg);
668        BDBG_SetModuleLevel("nexus_audio_decoder",BDBG_eTrace);
669        BDBG_SetModuleLevel("nexus_demux",BDBG_eMsg);
670        BDBG_SetModuleLevel("nexus_audio_dac",BDBG_eTrace);
671        BDBG_SetModuleLevel("rap_output",BDBG_eTrace);
672#endif
673}
674/*
675Summary:
676Main app event handler.
677Description:
678Main application event handler.
679 */
680void bapp_handle_event(bapp_t *p_app, bscreen_event_t *p_event)
681{
682        if (p_event && (p_event->type == eS_EVENT_IR) && (p_event->id >= eIR_CHMAP))
683        {
684                BDBG_WRN(("%s:%d - event_id = 0x%08x\n",__FUNCTION__,__LINE__,p_event->id));
685                switch (p_event->id)
686                {
687                case eIR_CHMAP: /* Output channel map on UART */
688                        ch_output(bapp_cur_ch_map(p_app));
689                        break;
690
691                case eIR_SCAN: /* Perform channel scan */
692                        p_app->state = eAPP_STATE_NORMAL;
693                        if (p_app->settings.psi_scan)
694                        {
695                                p_app->settings.activated = 1;
696                                p_app->settings_dirty = true;
697                        }
698                        bapp_eval_state(p_app,eAPP_STATE_HUNT);
699                        if (p_app->settings.psi_scan)
700                        {
701                                bapp_eval_state(p_app,eAPP_STATE_NORMAL);
702                        }
703                        break;
704
705                case eIR_SETUP: /* Perform default setup */
706                        p_app->state = eAPP_STATE_NORMAL;
707                        bapp_eval_state(p_app,eAPP_STATE_DOWNLOAD);
708                        break;
709
710                case eIR_EXIT: /* Exit to banner menu */
711                        bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
712                        break;
713
714                default:
715                        if ((p_event->id & eIR_SETCH) == eIR_SETCH)
716                        {
717                                /* TODO Tune to channel number */
718                                bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
719                        }
720                        break;
721                }
722        }
723}
724
725/*
726Summary:
727Main app idle time handler.
728Description:
729Main application idle time handler.
730 */
731void bapp_idle(bapp_t *p_app)
732{
733        struct timeval end_tv;
734        unsigned int delta_hrs;
735        static chm_event_t evt;
736
737        GETTIMEOFDAY(&end_tv);
738
739        delta_hrs = (end_tv.tv_sec - p_app->timeout_tv.tv_sec)/(60 * 60);
740        if ((delta_hrs > 0) && (((int)p_app->settings.timeout_cnt) > 0))
741        {
742                p_app->settings.timeout_cnt--;
743                BDBG_WRN(("%s decriment timeout counter %d\n",__FUNCTION__,p_app->settings.timeout_cnt));
744                p_app->timeout_tv = end_tv;
745        }
746
747        if ((p_app->state == eAPP_STATE_NORMAL) && p_app->settings.activated && !p_app->settings.psi_scan)
748        {
749                if (((int)p_app->settings.timeout_cnt) <= 0)
750                {
751                        evt.id = 0;
752                        evt.type = eCHM_EVT_ACTIVATION;
753                        bapp_task_post_event(p_app->msg_queue,(bapp_task_event_t)&evt);
754                }
755        }
756
757        if (p_app->check_poweron)
758        {
759                if (p_app->poweron_ms < bapp_task_getticks())
760                {
761                        p_app->check_poweron = false;
762                }
763        }
764
765        if ((p_app->state == eAPP_STATE_NORMAL) &&
766                p_app->eas_timeout && (p_app->eas_timeout < (unsigned int)end_tv.tv_sec))
767        {
768                p_app->eas_timeout = 0;
769                if (p_app->eas_text)
770                {
771                        p_app->eas_text = false;
772                        /* clear eas text scrolling screen */
773                        bapp_sync(p_app);
774                        screen_null_draw(p_app, NULL);
775                        bapp_flush_screen(p_app);
776                }
777                bapp_tune_prev(p_app);
778                bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
779        }
780#ifndef OLD_INFO_KEY_PROCESSING
781        if (p_app->last_key_down == eIR_INFO)
782        {
783                struct timeval cur_tv;
784                BDBG_WRN(("%s: p_app->last_key_down == eIR_INFO \n",__FUNCTION__));
785                GETTIMEOFDAY(&cur_tv);
786                if ((p_app->last_key_tv.tv_sec + BAPP_DIAG_TIMEOUT) <= cur_tv.tv_sec)
787                {
788                        BDBG_WRN(("%s: DIAG_TIMEOUT \n",__FUNCTION__));
789                        bapp_set_current_screen(p_app, eSCREEN_DIAG_MENU, eSCREEN_MAX);
790                        bapp_new_screen(p_app);
791                }
792        }
793#endif
794}
795/*
796Summary:
797Wait for vsync.
798Description:
799Block waiting for vsync so drawing can by syncronized with screen refresh.
800 */
801void bapp_sync(bapp_t *p_app)
802{
803        /* do nothing */
804}
805
806/*
807Summary:
808Enable closed captioning.
809Description:
810Enable closed captioning and send clear characters.
811 */
812void bapp_enable_cc(bapp_t *p_app, int enable)
813{
814#if 0 /* JPF TODO */
815        bdecode_config cfg;
816        bdecode_get_config(p_app->decode,&cfg);
817        if (cfg.cc_enabled != enable)
818        {
819                cfg.cc_enabled = (enable == 0) ? 0 : 1;
820                bdecode_set_config(p_app->decode,&cfg);
821        }
822#endif
823}
824/*
825Summary:
826Handle new screen.
827Description:
828Block waiting for vsync so drawing can by syncronized with screen refresh.
829 */
830static void bapp_screen_redraw(bapp_t *p_app)
831{
832        bscreen_event_t screen_event;
833        screen_event.type = eS_EVENT_REDRAW;
834        screen_event.id = 0;
835        BDBG_MSG(("%s:%d - sending setup event to %d.\n",__FUNCTION__,__LINE__,p_app->screen_id));
836        if (p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event))
837        {
838                p_app->last_screen_id = -1;
839                bapp_new_screen(p_app);
840        }
841}
842
843/*
844Summary:
845Handle new screen.
846Description:
847Block waiting for vsync so drawing can by syncronized with screen refresh.
848 */
849static void bapp_new_screen(bapp_t *p_app)
850{
851        bscreen_event_t screen_event;
852#ifdef TIME_APP_DRAWING
853        struct timeval start_tv,end_tv,result_tv;
854        unsigned int dt;
855#endif
856        screen_event.type = 0;
857        if (p_app->last_screen_id != p_app->screen_id)
858        {
859                BDBG_WRN(("%s:%d - sending setup event to %d.\n",__FUNCTION__,__LINE__,p_app->screen_id));
860                screen_event.type = eS_EVENT_SETUP;
861                screen_event.id = 0;
862                p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event);
863        }
864
865        p_app->last_screen_id = p_app->screen_id;
866#ifdef TIME_APP_DRAWING
867        GETTIMEOFDAY(&start_tv);
868#endif
869
870        bapp_sync(p_app);
871        p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id]));
872        bapp_flush_screen(p_app);
873
874#ifdef TIME_APP_DRAWING
875        GETTIMEOFDAY(&end_tv);
876        timeval_subtract(&result_tv,&end_tv,&start_tv);
877        dt = result_tv.tv_sec * 1000 + result_tv.tv_usec/1000;
878        BDBG_WRN(("Drawing screen %d took %d ms\n",p_app->screen_id,dt));
879#endif
880
881        /* send a setup done event to start any post drawing setup */
882        if (screen_event.type == eS_EVENT_SETUP)
883        {
884                screen_event.type = eS_EVENT_SETUP_DONE;
885                screen_event.id = 0;
886                if (p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event))
887                {
888                        p_app->last_screen_id = p_app->screen_id;
889                        screen_event.type = eS_EVENT_SETUP;
890                        screen_event.id = 0;
891                        p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event);
892#ifdef TIME_APP_DRAWING
893                        GETTIMEOFDAY(&start_tv);
894#endif
895                        bapp_sync(p_app);
896                        p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id]));
897                        bapp_flush_screen(p_app);
898
899#ifdef TIME_APP_DRAWING
900                        GETTIMEOFDAY(&end_tv);
901                        timeval_subtract(&result_tv,&end_tv,&start_tv);
902                        dt = result_tv.tv_sec * 1000 + result_tv.tv_usec/1000;
903                        BDBG_WRN(("Drawing took %d milliseconds\n",dt));
904#endif
905                }
906        }
907}
908
909/*
910Summary:
911sets the current screen for display
912Description:
913sets the current screen for display. 
914if id == eSCREEN_MAX then simply backup a screen
915if save_last == eSCREEN_MAX, also saves last screen id.
916 */
917void bapp_set_current_screen(bapp_t *p_app, bapp_screen_id_t id, bapp_screen_id_t save_last)
918{
919        bscreen_t *p_screen     = &(p_app->p_screens[p_app->screen_id]);
920        bscreen_t *p_screen_new = &(p_app->p_screens[id]);
921#ifdef BDBG_DEBUG_BUILD
922        unsigned int cur_screen = p_app->screen_id;
923#endif
924        BDBG_WRN(("Attempt to change screen from %d to %d\n",cur_screen, id));
925
926        if (id == p_app->screen_id)
927                return;
928
929        if (id == eSCREEN_MAX)
930        {
931                bapp_goto_last_screen(p_app);
932        } else
933        {
934                if (save_last == eSCREEN_MAX)
935                        p_screen_new->last_screen_id = p_app->screen_id;
936                else
937                {
938                        p_screen_new->last_screen_id = save_last;
939                        p_screen->button_selection = 0; /* if we do not save the last screen, clear out focus history */
940                }
941
942                if (id < eSCREEN_MAX)
943                        p_app->screen_id = id;
944        }
945
946        if (p_app->screen_id == eSCREEN_MAX)
947        {
948                p_app->screen_id = eSCREEN_BANNER; /* Default to channel change screen */
949        }
950        BDBG_WRN(("Changing screen from %d to %d\n",cur_screen, p_app->screen_id));
951
952}
953
954/*
955Summary:
956sets the current screen for display to be the last screen
957Description:
958sets the current screen for display to be the last screen
959 */
960void bapp_goto_last_screen(bapp_t *p_app)
961{
962        bscreen_t *p_screen     = &(p_app->p_screens[p_app->screen_id]);
963        p_app->screen_id = p_screen->last_screen_id;
964        if (p_app->screen_id == eSCREEN_MAX)
965        {
966                p_app->screen_id = eSCREEN_BANNER; /* Default to channel change screen */
967        }
968}
969
970/*
971Summary:
972Enter/exit standby
973 */
974static void bapp_standby(bapp_t *p_app, bool power)
975{
976        if (!power && p_app->check_poweron)
977        {
978                return;
979        }
980
981        if (power)
982        {
983                /* turning power on */
984                BDBG_ERR(("######## Turn ON ########\n"));
985
986                bapp_set_palette(p_app, ePALETTE_DEFAULT);
987
988                /* restore settings */
989                p_app->audio_vol  = p_app->settings.audio_vol; /* restore last volume level */
990                p_app->audio_mute = false; /* ensure audio mute user setting is off */
991
992                bapp_av_mute(p_app,0);
993                bapp_audio_mute(p_app,0);
994
995                bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
996                bapp_new_screen(p_app);
997                if (p_app->state == eAPP_STATE_NORMAL)
998                {
999                        bapp_tune(p_app);
1000                }
1001        } else
1002        {
1003
1004                /* turning power off */
1005#ifdef BDBG_DEBUG_BUILD
1006                uint32_t current_tick = bapp_task_getticks();
1007#endif
1008
1009                bapp_av_mute(p_app,1);
1010                BDBG_ERR(("######## Turn OFF @ 0x%08x ########\n",TICKS_TO_MS(current_tick)));
1011
1012                bapp_set_current_screen(p_app, eSCREEN_POWER_OFF, eSCREEN_MAX);
1013                bapp_new_screen(p_app);
1014
1015                p_app->settings.state = p_app->state;
1016                p_app->settings_dirty = true;
1017
1018                /* save settings if saved channel number or saved volume level is incorrect
1019                   note that these settings are saved here because the change often during
1020                   normal stb operation and there is no need to maintain this information
1021                   except between power cycles.  these settings are also duplicated in both
1022                   the settings struct and the p_app struct.*/
1023                if ((p_app->settings.audio_vol != p_app->audio_vol) || p_app->settings_dirty)
1024                {
1025                        p_app->settings.audio_vol  = p_app->audio_vol;
1026                        bapp_save_settings(p_app);
1027                }
1028                BDBG_WRN(("######## NOTIFY POWERCTRL ########"));
1029        }
1030
1031        p_app->power = power;
1032}
1033/*
1034Summary:
1035Handle diag events.
1036 */
1037#ifdef OLD_INFO_KEY_PROCESSING
1038static bool bapp_enter_diag(bapp_t *p_app,bIR_codes_t code)
1039{
1040        bool result = false;
1041        switch (code)
1042        {
1043        case eIR_INFO:
1044                bapp_set_current_screen(p_app, eSCREEN_DIAG_MENU, eSCREEN_MAX);
1045                bapp_new_screen(p_app);
1046                result = true;
1047                break;
1048        default:
1049                break;
1050        }
1051        return result;
1052}
1053#endif
1054/*
1055Summary:
1056Handle user events.
1057 */
1058static void bapp_handle_user_event(bapp_t *p_app,
1059                                                                   bapp_event_t *p_event
1060                                                                  )
1061{
1062        bscreen_event_t screen_event;
1063        bool key_up = (p_event->id & 0x40000000) ? true : false;
1064        bIR_codes_t code = (bIR_codes_t)(p_event->id & ~0x40000000);
1065
1066#ifdef OLD_INFO_KEY_PROCESSING
1067        struct timeval cur_tv;
1068#endif
1069
1070        BDBG_WRN(("%s:%d 0x%02x(%s)\n",__FUNCTION__,__LINE__,code,(key_up) ? "up" : "down"));
1071
1072        switch (code)
1073        {
1074        case eIR_POWER:
1075                if (key_up && !p_app->check_poweron)
1076                        bapp_standby(p_app, 1/*!p_app->power*/);
1077                break;
1078        case 0x71:
1079        case 0x72:
1080        case eIR_RFM:
1081                if (key_up)
1082                {
1083                        /* JPF TODO ? */
1084                }
1085                break;
1086        default:
1087
1088                /* Test to see if we should enter the diagnostic state */
1089#ifdef OLD_INFO_KEY_PROCESSING
1090                if (key_up && (p_app->last_key_down == code) && !p_app->settings.av_mute)
1091                {
1092                        GETTIMEOFDAY(&cur_tv);
1093                        if ((p_app->last_key_tv.tv_sec + BAPP_DIAG_TIMEOUT) <= cur_tv.tv_sec)
1094                        {
1095                                if (bapp_enter_diag(p_app,code))
1096                                        break;
1097                        }
1098                }
1099#endif
1100                if ((p_app->state != eAPP_STATE_NORMAL) && (p_app->screen_id == eSCREEN_BANNER))
1101                        break;
1102
1103                screen_event.type = eS_EVENT_IR;
1104                screen_event.id = p_event->id;
1105                if (p_app->p_screens[p_app->screen_id].handle_event(p_app,
1106                                                                                                                        (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event))
1107                {
1108                        BDBG_MSG(("%s:%d screen_id %d\n",__FUNCTION__,__LINE__,p_app->screen_id));
1109                        /* Wait for vsync then do screen drawing */
1110                        bapp_new_screen(p_app);
1111                } else
1112                {
1113                        bapp_handle_event(p_app,&screen_event);
1114                }
1115        }
1116
1117        if (p_app->state != eAPP_STATE_FACTORY)
1118        {
1119                /* JPF TODO ? */
1120        }
1121
1122        if (!key_up)
1123        {
1124                BDBG_WRN(("%s: !key_up \n",__FUNCTION__));
1125                p_app->last_key_down = code;
1126                GETTIMEOFDAY(&p_app->last_key_tv);
1127        }
1128#ifndef OLD_INFO_KEY_PROCESSING
1129        else
1130        {
1131                BDBG_WRN(("%s: key_up \n",__FUNCTION__));
1132                p_app->last_key_down = (bIR_codes_t)0xFFF; /* key up */
1133        }
1134#endif
1135}
1136
1137/*
1138Summary:
1139Handle channel manager events.
1140 */
1141static bapp_state_t bapp_handle_chm_event(bapp_t *p_app)
1142{
1143        bscreen_event_t screen_event;
1144        chm_event_t *p_event;
1145        struct timeval start_tv;
1146        unsigned short cur_ch;
1147
1148        bapp_state_t new_state = p_app->state;
1149
1150        /* Check for notification events */
1151        if ((p_event = (chm_event_t*)bapp_task_pend_event(p_app->msg_queue,0)) != NULL)
1152        {
1153                screen_event.type = eS_EVENT_MAX;
1154                screen_event.id = p_event->id;
1155           /* if (p_event->type != eCHM_EVT_SIGNAL) */
1156                {
1157                        BDBG_WRN(("%s (%s)\n",__FUNCTION__,s_chm_evt_str[p_event->type]));
1158                }
1159                switch (p_event->type)
1160                {
1161                case eCHM_EVT_CANCEL: screen_event.type = eS_EVENT_CANCEL; break;
1162                case eCHM_EVT_DONE: screen_event.type = eS_EVENT_DONE; break;
1163                case eCHM_EVT_REDRAW: screen_event.type = eS_EVENT_REDRAW; break;
1164                case eCHM_EVT_PROGRESS: screen_event.type = eS_EVENT_PROGRESS; break;
1165                case eCHM_EVT_SIGNAL:
1166                        {
1167                                chm_signal_event_t *p_sig = (chm_signal_event_t*)p_event;
1168                                p_app->lock = (p_sig->lock) ? true : false;
1169                                p_app->signal_level = p_sig->power;
1170                                p_app->tuned_freq = p_sig->freq_hz;
1171                                p_app->snr = p_sig->SNR;
1172                                p_app->mode = p_sig->mode;
1173                        }
1174                        break;
1175                case eCHM_EVT_DOWNLOAD:
1176                        new_state = eAPP_STATE_DOWNLOAD;
1177                        break;
1178                case eCHM_EVT_EAS:
1179                        BDBG_MSG(("%s:%d EAS TIMER STARTED)\n",__FUNCTION__,__LINE__));
1180                        if (p_app->state == eAPP_STATE_NORMAL)
1181                        {
1182                                GETTIMEOFDAY(&start_tv);
1183                                if (ch_map_set(bapp_cur_ch_map(p_app),p_event->id && 0xFFFF))
1184                                {
1185                                        static unsigned char *eas_buf = NULL;
1186
1187#ifndef EAS_BUF_LEN     /* defined in chan_mgr_cable.c. Make sure they are match */
1188#define EAS_BUF_LEN     (1024 + 188)
1189#endif
1190                                        /* if 0, don't timeout */
1191                                        if (p_event->id >> 16)
1192                                                p_app->eas_timeout = start_tv.tv_sec + (p_event->id >> 16);
1193                                        else
1194                                                p_app->eas_timeout = 0;
1195                                        bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
1196                                        bapp_tune(p_app);
1197                                        if (!eas_buf)
1198                                        {
1199                                                eas_buf = bapp_util_malloc(EAS_BUF_LEN);
1200                                                if (!eas_buf)
1201                                                {
1202                                                        BDBG_ERR(("%s: out of memory)\n",__func__));
1203                                                        break;
1204                                                }
1205                                        }
1206                                        /* use a local buffer to avoid conflict when eas getting other data and while text scrolling in progress*/
1207                                        memcpy(eas_buf, p_app->chm.eas_buf, EAS_BUF_LEN);
1208                                        if (BERR_SUCCESS == bscreen_eas_text_scrolling_info(p_app, eas_buf, EAS_BUF_LEN))
1209                                        {
1210                                                p_app->eas_text = true;
1211                                        }
1212                                }
1213                        }
1214                        break;
1215                case eCHM_EVT_CA:
1216                        {
1217                                chm_ca_event_t *p_ca_evt = (chm_ca_event_t*)p_event;
1218                                if ((p_app->settings.CA_System_ID != p_ca_evt->CA_System_ID) ||
1219                                        (p_app->settings.EMM_PID != p_ca_evt->EMM_PID))
1220                                {
1221                                        p_app->settings.CA_System_ID = p_ca_evt->CA_System_ID;
1222                                        p_app->settings.EMM_Provider_ID = p_ca_evt->EMM_Provider_ID;
1223                                        p_app->settings.SCP_operating_mode = p_ca_evt->SCP_operating_mode;
1224                                        p_app->settings.EMM_PID = p_ca_evt->EMM_PID;
1225                                        p_app->settings.has_CAT = true;
1226                                        p_app->settings.turn_on_freq_khz = p_ca_evt->freq_khz;
1227                                        p_app->settings_dirty = true;
1228                                }
1229                        }
1230                        break;
1231                case eCHM_EVT_NETWORK:
1232                        p_app->settings.network_PID = p_event->id;
1233                        p_app->settings_dirty = true;
1234                        break;
1235                case eCHM_EVT_STATUS:
1236                        switch (p_event->id)
1237                        {
1238                        case eCHM_STATUS_HUNT: /* HUNT MODE */
1239                                BDBG_WRN(("eCHM_STATUS_HUNT\n"));
1240                                break;
1241                        case eCHM_STATUS_PENDING_INIT: /* Pending Init MODE */
1242                                BDBG_WRN(("eCHM_STATUS_PENDING_INIT\n"));
1243                                new_state = eAPP_STATE_PENDING;
1244                                break;
1245                        case eCHM_STATUS_CHMAP:
1246                                BDBG_WRN(("eCHM_STATUS_CHMAP flags = 0x%08x\n",p_event->ticks));
1247                                if (ch_map_cmp(&(p_app->settings.ch_map),&(p_app->chm.ch_map)) & p_event->ticks)
1248                                {
1249                                        BDBG_WRN(("Channel map changed 0x%08x\n",p_event->ticks));
1250                                        cur_ch = p_app->settings.ch_map.cur_ch;
1251                                        ch_map_copy(&(p_app->settings.ch_map),&(p_app->chm.ch_map),p_event->ticks);
1252                                        p_app->settings.ch_map.cur_ch = cur_ch;
1253        #ifdef BDBG_DEBUG_BUILD
1254                                        ch_output(bapp_cur_ch_map(p_app));
1255        #endif
1256                                        p_app->settings_dirty = true;
1257                                }
1258                                else
1259                                {
1260                                        BDBG_WRN(("Channel map NOT changed\n"));
1261                                }
1262                                if (p_app->settings.psi_scan)
1263                                {
1264                                        p_app->settings.activated = 1;
1265                                        p_app->settings.timeout_cnt = 0xFFFF;
1266                                }
1267                                if (p_app->settings.activated)
1268                                {
1269                                        if ((p_app->state == eAPP_STATE_NORMAL) && p_app->settings_dirty)
1270                                        {
1271                                                bapp_save_settings(p_app);
1272                                                /* if just scanned and have channnels, force to tune first channel  */
1273                                                if (p_app->settings.ch_map.vch_map.num_vch)
1274                                                {
1275                                                        p_app->chm.force_tune = true;
1276                                                        bapp_tune(p_app);
1277                                                }
1278                                        } 
1279                                        else
1280                                        {
1281                                                new_state = eAPP_STATE_NORMAL;
1282                                        }
1283                                } 
1284                                else
1285                                {
1286                                        BDBG_WRN(("### ERROR recieve new channel map while still not activated - return to Hunt Mode\n"));
1287                                        new_state = eAPP_STATE_HUNT;
1288                                }
1289                                break;
1290
1291                        case eCHM_STATUS_PAT:
1292                        p_app->has_PAT = true; 
1293#if 0
1294                        if (ch_map_cmp(&(p_app->settings.ch_map),&(p_app->chm.ch_map)) & p_event->ticks)
1295                        {
1296                                BDBG_WRN(("Channel map changed 0x%08x\n",p_event->ticks));
1297                                cur_ch = p_app->settings.ch_map.cur_ch;
1298                                ch_map_copy(&(p_app->settings.ch_map),&(p_app->chm.ch_map),p_event->ticks);
1299                                p_app->settings.ch_map.cur_ch = cur_ch;
1300#ifdef BDBG_DEBUG_BUILD
1301                                ch_output(bapp_cur_ch_map(p_app));
1302#endif
1303                                p_app->settings_dirty = true;
1304                        }
1305                        else
1306                        {
1307                                BDBG_WRN(("Channel map NOT changed\n"));
1308                        }
1309#endif
1310                        break;
1311                        case eCHM_STATUS_NOPAT: p_app->has_PAT = false; break;
1312                        case eCHM_STATUS_TUNE_MS: p_app->tune_ms = p_event->ticks; break;
1313                        case eCHM_STATUS_SI_MS: p_app->si_ms = p_event->ticks; break;
1314                        }
1315
1316                        break;
1317                case eCHM_EVT_AV_MUTE:
1318                        bapp_standby(p_app,!p_event->id);
1319                        break;
1320                case eCHM_EVT_ACTIVATION:
1321                        {
1322                                bool current_activation = p_app->settings.activated;
1323                                p_app->settings.activated = p_event->id;
1324                                if (p_app->settings.activated != current_activation)
1325                                {
1326                                        p_app->settings_dirty = true;
1327                                        if (!p_app->settings.activated)
1328                                        {
1329                                                p_app->settings.deactivated = 1;
1330                                                new_state = eAPP_STATE_HUNT;
1331                                        }
1332                                        else
1333                                        {
1334                                                p_app->settings.deactivated = 0;
1335                                                if (p_app->settings.timeout_policy == 1)
1336                                                {
1337                                                        p_app->settings.timeout_cnt = p_app->settings.timeout;
1338                                                }
1339#ifdef BDBG_DEBUG_BUILD
1340                                                /* Some default value to prevent immediate de-activation in lab environments */
1341                                                else if (p_app->settings.timeout == 0)
1342                                                {
1343                                                        p_app->settings.timeout_cnt     += 4; 
1344                                                }
1345#endif
1346                                        }
1347                                }
1348                        }
1349                        break;
1350                case eCHM_EVT_VCT_ID:
1351                        {
1352                                unsigned short current_vct_id = p_app->settings.VCT_ID;
1353                                p_app->settings.VCT_ID = p_event->id;
1354
1355                                if ((p_app->settings.VCT_ID != current_vct_id) && (CONFIG_DEF_VCT_ID != 0xFFFF))
1356                                {
1357                                        BDBG_WRN(("%s:%d Configuration VCT_ID %d does not match current value %d\n",
1358                                                          __FUNCTION__,__LINE__,p_app->settings.VCT_ID,current_vct_id));
1359                                        p_app->settings.activated = false;
1360                                        new_state = eAPP_STATE_PENDING;
1361                                }
1362                                p_app->settings_dirty = true;
1363                        }
1364                        break;
1365                case eCHM_EVT_CONFIGURATION:
1366                        {
1367                                chm_config_event_t *p_cfg_evt = (chm_config_event_t*)p_event;
1368                                unsigned short current_vct_id = p_app->settings.VCT_ID;
1369                                p_app->settings.VCT_ID = p_cfg_evt->VCT_ID;
1370                                p_app->settings.timeout = p_cfg_evt->timeout;
1371                                p_app->settings.timeout_policy = p_cfg_evt->timeout_policy;
1372                                p_app->settings.max_location_errors = p_cfg_evt->max_location_errors;
1373
1374                                if (p_app->settings.timeout_policy == 0)
1375                                {
1376                                        p_app->settings.timeout_cnt = p_cfg_evt->timeout;
1377                                }
1378                                p_app->settings.location = p_cfg_evt->location;
1379                                if (p_app->have_time)
1380                                {
1381                                        p_app->settings.message_time = p_app->system_time;
1382                                } else
1383                                {
1384                                        BDBG_WRN(("%s:%d Need system time before configuration can be processed\n",__FUNCTION__,__LINE__));
1385                                        break;
1386                                }
1387
1388                                if ((p_app->settings.VCT_ID != current_vct_id) && (CONFIG_DEF_VCT_ID != 0xFFFF))
1389                                {
1390                                        BDBG_WRN(("%s:%d Configuration VCT_ID %d does not match current value %d\n",
1391                                                          __FUNCTION__,__LINE__,p_app->settings.VCT_ID,current_vct_id));
1392                                        p_app->settings.activated = false;
1393                                        new_state = eAPP_STATE_PENDING;
1394                                }
1395                                p_app->settings_dirty = true;
1396                        }
1397                        break;
1398                case eCHM_EVT_LOCATION:
1399                        if(p_app->settings.psi_scan)
1400                                break;
1401                        p_app->location = p_event->id;
1402                        if (p_app->settings.location != p_event->id)
1403                        {
1404                                if (p_app->settings.location_errors > p_app->settings.max_location_errors)
1405                                {
1406                                        p_app->settings.activated = false;
1407                                        new_state = eAPP_STATE_HUNT;
1408                                }
1409                                else
1410                                {
1411                                        p_app->settings.location_errors++; 
1412                                        p_app->settings_dirty = true;
1413                                }
1414                        }
1415                        else
1416                        {
1417                                if (p_app->settings.timeout_policy == 0)
1418                                {
1419                                        p_app->settings.timeout_cnt = p_app->settings.timeout;
1420                                }
1421                        }
1422                        break;
1423
1424                case eCHM_EVT_TIME:
1425                        {
1426                                chm_time_event_t *p_time_evt = (chm_time_event_t*)p_event;
1427                                p_app->system_time = p_time_evt->system_time;
1428                                p_app->system_offset = p_time_evt->system_offset;
1429                                p_app->settings.utc_offset = (int)p_time_evt->utc_offset;
1430                                p_app->have_time = true;
1431                        }
1432                        break;
1433
1434                case eCHM_EVT_TIMEZONE:
1435                        {
1436                                chm_tz_event_t *p_tz_evt = (chm_tz_event_t*)p_event;
1437                                if (p_tz_evt->utc_offset & 0x10000)
1438                                        p_app->settings.utc_offset = (int)((0xFFFF & p_tz_evt->utc_offset) | 0xFFFF0000);
1439                                else
1440                                        p_app->settings.utc_offset = (int)(0xFFFF & p_tz_evt->utc_offset);
1441                                p_app->settings.dst_delta = p_tz_evt->dst_delta;
1442                                p_app->settings.dst_entry = p_tz_evt->dst_entry;
1443                                p_app->settings.dst_exit = p_tz_evt->dst_exit;
1444                                p_app->settings_dirty = true;
1445                        }
1446                        break;
1447                case eCHM_EVT_PHONENUMBER:
1448                        if (bapp_util_strcmp((char*)&(p_app->settings.phonenumber),p_event->data) != 0) 
1449                        {
1450                                if (bapp_util_strlen(p_event->data) > MAX_PHONE_LEN) 
1451                                        p_event->data[MAX_PHONE_LEN-1] = 0;
1452                                bapp_util_strcpy((char*)&(p_app->settings.phonenumber),p_event->data);
1453                                p_app->settings_dirty = true;
1454                        }
1455                        break;
1456                case eCHM_EVT_RESET:
1457                        switch (p_event->id)
1458                        {
1459                        default:
1460                        case 0: /* nop */
1461                                break;
1462                        case 1: /* reset */
1463                                bapp_do_poweroff(p_app);
1464                                break;
1465                        case 2: /* reset some */
1466                                bapp_reset_settings(p_app);
1467                                bapp_save_settings(p_app);
1468                                bapp_do_poweroff(p_app);
1469                                break;
1470                        case 3: /* reset full */
1471                                bapp_reset_settings(p_app);
1472                                bapp_save_settings(p_app);
1473                                /* Erase downloaded firmware here */
1474                                bapp_do_poweroff(p_app);
1475
1476                                break;
1477                        }
1478                        break;
1479                case eCHM_EVT_SAVE:
1480                        /* Must be careful of when this is done if running from flash */
1481                        if ((p_app->settings.audio_vol != p_app->audio_vol) || p_app->settings_dirty)
1482                        {
1483                                p_app->settings.audio_vol  = p_app->audio_vol;
1484                                bapp_save_settings(p_app);
1485                        }
1486                        break;
1487                }
1488                BDBG_MSG(("%s:%d CHM EVENT = %d)\n",__FUNCTION__,__LINE__,p_event->type));
1489
1490                if (p_app->p_screens[p_app->screen_id].handle_event(p_app,
1491                                                                                                                        (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event))
1492                {
1493                        BDBG_WRN(("%s:%d screen_id %d\n",__FUNCTION__,__LINE__,p_app->screen_id));
1494                        /* Wait for vsync then do screen drawing */
1495                        bapp_new_screen(p_app);
1496                } else
1497                {
1498                        bapp_handle_event(p_app,&screen_event);
1499                }
1500        }
1501        return new_state;
1502}
1503
1504/*
1505Summary:
1506Main event loop when in normal operation mode.
1507 */
1508static bapp_state_t bapp_run_main(bapp_t *p_app)
1509{
1510        bapp_event_t event;
1511        bscreen_event_t screen_event;
1512
1513        /* Check for UI event */
1514        if (bapp_remote_get_event(p_app->remote,&event) == eBAPP_RESULT_OK)
1515        {
1516                p_app->last_keypress_tick = bapp_task_getticks();
1517                bapp_handle_user_event(p_app,&event);
1518        }
1519
1520        /* Yield control */
1521        bapp_util_sleep(p_app->yield_ms);
1522
1523
1524        screen_event.type = eS_EVENT_IDLE;
1525        screen_event.id = 0;
1526        /* Give screen idle time to handle menu timeouts, etc */
1527        if (p_app->p_screens[p_app->screen_id].handle_event(p_app,
1528                                                                                                                (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event))
1529        {
1530                /* Wait for vsync then do screen drawing */
1531                bapp_new_screen(p_app);
1532        }
1533
1534        /* Do application idle time processing */
1535        bapp_idle(p_app);
1536
1537        return p_app->state;
1538}
1539
1540#if 0
1541/*
1542Summary:
1543Main event loop when in normal operation mode.
1544 */
1545static bapp_state_t bapp_pending(bapp_t *p_app)
1546{
1547        bscreen_event_t screen_event;
1548        unsigned short num_vch, num_st;
1549        unsigned char num_freq ;
1550        bapp_event_t event;
1551        unsigned event_cnt;
1552
1553        /* Check for UI event */
1554        if (buser_input_get_event(p_app->user_io,&event,1,&event_cnt) == b_ok)
1555        {
1556                if (event_cnt > 0)
1557                {
1558                        p_app->last_keypress_tick = bapp_task_getticks();
1559                        bapp_handle_user_event(p_app,&event);
1560                }
1561        }
1562
1563        screen_event.type = eS_EVENT_IDLE;
1564        screen_event.id = 0;
1565        /* Give screen idle time to handle menu timeouts, etc */
1566        if (p_app->p_screens[p_app->screen_id].handle_event(p_app,
1567                                                                                                                (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event))
1568        {
1569                /* do screen drawing */
1570                bapp_new_screen(p_app);
1571        }
1572
1573        /* Yield control */
1574        bapp_util_sleep(p_app->yield_ms);
1575
1576        /* Check to see if there is a channel map */
1577        ch_map_get_counts(bapp_cur_ch_map(p_app),&num_vch,&num_st,&num_freq);
1578
1579#if 0
1580        if ((num_vch > 0) && (p_app->settings.activated || (p_app->settings.VCT_ID == 0)))
1581        {
1582                BDBG_WRN(("%s:%d Switch to NORMAL State(%d,%d,%d)\n",__FUNCTION__,__LINE__,
1583                                  num_vch,p_app->settings.activated,p_app->settings.VCT_ID));
1584                return eAPP_STATE_NORMAL;
1585        }
1586#endif
1587        return p_app->state;
1588}
1589#endif
1590
1591/*
1592Summary:
1593Main event loop when in normal operation mode.
1594 */
1595static bapp_state_t bapp_downloading(bapp_t *p_app)
1596{
1597
1598        /* Yield control */
1599        bapp_util_sleep(p_app->yield_ms);
1600        return(p_app->chm.cmd == eCHM_DOWNLOAD) ? eAPP_STATE_DOWNLOAD : eAPP_STATE_NORMAL;
1601}
1602
1603
1604/*
1605Summary:
1606Perform a channel hunt (for cable ).
1607 */
1608static int bapp_channel_hunt(bapp_t *p_app)
1609{
1610        p_app->chm_cmd.cmd_id = eCHM_HUNT;
1611        chm_cmd(&p_app->chm,&p_app->chm_cmd);
1612        return 0;
1613}
1614
1615/*
1616Summary:
1617Main app loop.
1618Description:
1619Main application event loop.
1620 */
1621#ifdef BDBG_DEBUG_BUILD
1622static const char *s_app_state_name[] = { "DEFAULT","HUNTING","PENDING","NORMAL","DOWNLOAD","FACTORY","DONE"};
1623#endif
1624
1625static void bapp_eval_state(bapp_t *p_app,bapp_state_t new_state)
1626{
1627        bapp_led_set_mode(p_app);
1628        led_update(APP_DEFAULT_YIELD); 
1629        if (p_app->state == new_state)
1630                return;
1631
1632        BDBG_WRN(("from %s to %s\n",s_app_state_name[p_app->state], s_app_state_name[new_state] ));
1633
1634        /* Handle exiting current state */
1635        switch (p_app->state)
1636        {
1637        case eAPP_STATE_PENDING:
1638                if ((new_state == eAPP_STATE_NORMAL) && p_app->settings_dirty)
1639                {
1640                        bapp_save_settings(p_app);
1641                }
1642                p_app->last_screen_id = eSCREEN_MAX;
1643                memset(&p_app->cur_vch,0,sizeof(p_app->cur_vch));
1644                break;
1645        case eAPP_STATE_HUNT:
1646                bapp_screen_redraw(p_app);
1647                bapp_task_sleep(250); /* must display full progress bar for at least 250ms before proceding */
1648        case eAPP_STATE_DOWNLOAD:
1649        case eAPP_STATE_NORMAL:
1650        case eAPP_STATE_FACTORY:
1651        case eAPP_STATE_DEFAULT:
1652        case eAPP_STATE_DONE:
1653                break;
1654        }
1655
1656        /* Handle entering new state */
1657        switch (new_state)
1658        {
1659        case eAPP_STATE_HUNT:
1660                if (p_app->screen_id < eSCREEN_DIAG_MENU)
1661                {
1662                        if (p_app->power)
1663                                bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
1664                        else
1665                                bapp_set_current_screen(p_app, eSCREEN_POWER_OFF, eSCREEN_MAX);
1666                        bapp_new_screen(p_app);
1667                }
1668                bapp_channel_hunt(p_app);
1669                break;
1670        case eAPP_STATE_NORMAL:
1671                if (p_app->screen_id < eSCREEN_DIAG_MENU)
1672                {
1673                        if (p_app->power)
1674                                bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
1675                        else
1676                                bapp_set_current_screen(p_app, eSCREEN_POWER_OFF, eSCREEN_MAX);
1677                }
1678                bapp_new_screen(p_app);
1679                bapp_tune(p_app);
1680                break;
1681        case eAPP_STATE_DOWNLOAD:
1682                if (p_app->screen_id < eSCREEN_DIAG_MENU)
1683                {
1684                        if (p_app->power)
1685                                bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX);
1686                        else
1687                                bapp_set_current_screen(p_app, eSCREEN_POWER_OFF, eSCREEN_MAX);
1688                        bapp_new_screen(p_app);
1689                }
1690                p_app->chm_cmd.cmd_id = eCHM_DOWNLOAD;
1691                chm_cmd(&p_app->chm,&p_app->chm_cmd);
1692                break;
1693        case eAPP_STATE_FACTORY:
1694                bapp_set_current_screen(p_app, eSCREEN_STATUS, eSCREEN_MAX);
1695                bapp_new_screen(p_app);
1696                break;
1697        case eAPP_STATE_PENDING:
1698        case eAPP_STATE_DEFAULT:
1699        case eAPP_STATE_DONE:
1700                break;
1701        }
1702
1703        /* Make new state the current state */
1704        p_app->state = new_state;
1705        switch (new_state)
1706        {
1707        case eAPP_STATE_PENDING:
1708        case eAPP_STATE_NORMAL:
1709                bapp_screen_redraw(p_app);
1710                break;
1711        default:
1712                break;
1713        }
1714
1715}
1716/*
1717Summary:
1718Main app loop.
1719Description:
1720Main application event loop.
1721 */
1722void bapp_run(bapp_t *p_app)
1723{
1724        bapp_state_t new_state;
1725        BDBG_WRN(("%s:%d - Start running.\n",__FUNCTION__,__LINE__));
1726        bapp_screen_redraw(p_app);
1727        while (p_app->state != eAPP_STATE_DONE)
1728        {
1729                new_state = p_app->state;
1730                switch (p_app->state)
1731                {
1732                case eAPP_STATE_HUNT:
1733                case eAPP_STATE_PENDING:
1734                case eAPP_STATE_NORMAL:
1735                case eAPP_STATE_FACTORY:
1736                        new_state = bapp_run_main(p_app);
1737                        break;
1738                case eAPP_STATE_DOWNLOAD:
1739                        new_state = bapp_downloading(p_app);
1740                        break;
1741                case eAPP_STATE_DEFAULT:
1742                case eAPP_STATE_DONE:
1743
1744                        /* Yield control */
1745                        bapp_util_sleep(p_app->yield_ms);
1746                        break;
1747                }
1748
1749                /* Check for chm event */
1750                if (new_state == p_app->state)
1751                        new_state = bapp_handle_chm_event(p_app);
1752
1753                bapp_eval_state(p_app,new_state);
1754        }
1755
1756        /* finish */
1757        bapp_nexus_close(&p_app->nexus);
1758}
1759
1760/*
1761Summary:
1762Return current application channel map.
1763 */
1764ch_map_t *bapp_cur_ch_map(bapp_t *p_app)
1765{
1766        return &(p_app->settings.ch_map);
1767}
1768
1769/*
1770Summary:
1771Tune to the current frequency and get the VCT.
1772Description:
1773Tune to the current frequency and get the VCT. Returns non-zero on failure.
1774 */
1775int bapp_change_channel(bapp_t *p_app, int ch_up, int tune)
1776{
1777        int retval = -1;
1778        bool result;
1779
1780        BDBG_MSG(("%s (%d,%d)\n",__FUNCTION__,ch_up,tune));
1781
1782        if (ch_up)
1783        {
1784                result = ch_map_set_next(bapp_cur_ch_map(p_app));
1785        } else
1786        {
1787                result = ch_map_set_prev(bapp_cur_ch_map(p_app));
1788        }
1789
1790        if (!result)
1791        {
1792                BDBG_ERR(("%s (%d,%d) failed \n",__FUNCTION__,ch_up,tune));
1793                return retval;
1794        }
1795
1796        if (tune)
1797        {
1798                retval = bapp_tune(p_app);
1799
1800                p_app->settings_dirty = true;
1801        } else
1802        {
1803                retval = 0;
1804        }
1805        return retval;
1806}
1807
1808/*
1809Summary:
1810Tune to the specified channel.
1811Description:
1812Tune to the specified channel or nearest to the channel. Returns non-zero on failure.
1813 */
1814int bapp_set_channel(bapp_t *p_app, int channel)
1815{
1816        int retval = -1; 
1817        vch_t cur_vch;
1818        st_t    cur_st;
1819        freq_t cur_freq;
1820        BDBG_WRN(("%s (%d)\n",__FUNCTION__,channel));
1821
1822        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&cur_vch,&cur_st,&cur_freq))
1823        {
1824                BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__));
1825                return 0;
1826        }
1827#if 1
1828        if (!ch_map_is_channel_visible(bapp_cur_ch_map(p_app),(unsigned short)channel))
1829        {
1830                BDBG_WRN(("%s Hidden channel %d\n",__FUNCTION__,channel));
1831                return 0;
1832        }
1833#endif
1834        if (ch_map_set_ch(bapp_cur_ch_map(p_app),(unsigned short)channel))
1835        {
1836                p_app->settings_dirty = true;
1837                retval = bapp_tune(p_app);
1838        }
1839
1840        return retval;
1841}
1842
1843/*
1844Summary:
1845Tune to the current channel.
1846 */
1847int bapp_tune(bapp_t *p_app)
1848{   
1849        vch_t new_vch;
1850        st_t    new_st;
1851        freq_t new_freq;
1852
1853        if (p_app->settings.av_mute)
1854                return 0;
1855
1856        p_app->prev_vch = p_app->cur_vch;
1857
1858        /* check to see if the current channel info has changed */
1859        if (p_app->decoding)
1860        {
1861                if (!ch_map_get_current(bapp_cur_ch_map(p_app),&new_vch,&new_st,&new_freq))
1862                {
1863                        BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__));
1864                        return 0;
1865                }
1866                if ((new_freq.freq_khz == p_app->cur_freq.freq_khz) && (new_vch.program_num == p_app->cur_vch.program_num))
1867                {
1868                        BDBG_WRN(("%s Channel info did not change skip re tune.\n",__FUNCTION__));
1869                        return 0;
1870                }
1871                BDBG_WRN(("%s Channel Navigation Changed - Retune\n",__FUNCTION__));
1872        }
1873
1874        p_app->lock = false;
1875        p_app->signal_level = 0;
1876
1877        p_app->tune_cmd.cmd_id = eCHM_TUNE;
1878        p_app->tune_cmd.type = eCHM_CURRENT;
1879        chm_cmd(&p_app->chm,(chm_cmd_event_t*)&p_app->tune_cmd);
1880        p_app->decoding         = true;
1881        p_app->last_tune_tick   = bapp_task_getticks();
1882        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&p_app->cur_vch,&p_app->cur_st,&p_app->cur_freq))
1883        {
1884                BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__));
1885                return 0;
1886        }
1887        return 0;
1888}
1889/*
1890Summary:
1891Tune to the current channel.
1892 */
1893int bapp_tune_prev(bapp_t *p_app)
1894{
1895        return bapp_set_channel(p_app,p_app->prev_vch.ch_num);
1896}
1897
1898#if !defined(RAM_BUILD)
1899/*
1900Summary:
1901Stop decoding audio and video
1902 */
1903static int bapp_stop_decode(bapp_t *p_app)
1904{
1905        p_app->chm_cmd.cmd_id = eCHM_STOP;
1906        chm_cmd(&p_app->chm,&p_app->chm_cmd);
1907        p_app->decoding = false;
1908        return 0;
1909}
1910#endif
1911
1912/*
1913Summary:
1914Restart audio decode (after SAP swap audio PID)
1915 */
1916int bapp_rotate_audio_sap(bapp_t *p_app)
1917{
1918        vch_t vch;
1919        st_t st;
1920        freq_t freq;
1921
1922        if (p_app->settings.av_mute || !p_app->decoding)
1923                return 0;
1924
1925        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq))
1926        {
1927                BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__));
1928                return 0;
1929        }
1930
1931        if (vch.num_audio <= 1)
1932                return 0;
1933
1934        vch.cur_audio++;
1935        if (   vch.cur_audio    >=    vch.num_audio)
1936        {
1937                vch.cur_audio = 0;
1938        }
1939
1940        if (!ch_map_vch_update(bapp_cur_ch_map(p_app),&vch))
1941        {
1942                BDBG_WRN(("%s Error updating channel map.\n",__FUNCTION__));
1943                return 0;
1944        }
1945
1946        p_app->chm_cmd.cmd_id = eCHM_SAP;
1947        chm_cmd(&p_app->chm,&p_app->chm_cmd);
1948        return 0;
1949}
1950/*
1951Summary:
1952set CLUT
1953 */
1954void bapp_set_palette(bapp_t *p_app, bapp_palette_t palette)
1955{
1956        unsigned int *clut;      /* [out] address of palette */
1957        unsigned int size;
1958       
1959        switch (palette)
1960        {
1961        case ePALETTE_SCREENSAVER:
1962                bapp_palette_get(ePALETTE_LOGO,&clut,&size);
1963                break;
1964        case ePALETTE_DEFAULT:
1965        default:
1966                bapp_palette_get(ePALETTE_APP,&clut,&size);
1967                break;
1968        }
1969
1970        bapp_util_memcpy(p_app->nexus.mem[p_app->nexus.surface_idx].palette,clut, size);
1971        NEXUS_Surface_Flush(p_app->nexus.surface[p_app->nexus.surface_idx]);
1972}
1973
1974/*
1975Summary:
1976returns true is sufficient signal strength, false otherwise
1977always returns true for TUNE_DURATION msecs after tuning begins.
1978 */
1979bool bapp_get_signal_status(bapp_t *p_app)
1980{
1981#if 1 /* JPF TODO */
1982        return true;
1983#else
1984        static bool     first_call           = true;
1985        static bool     good_signal          = true;
1986        static uint32_t last_video_pts       = 0;
1987        static uint32_t last_video_pts_ticks = 0;
1988        static uint32_t last_audio_pts       = 0;
1989        vch_t vch;
1990        st_t st;
1991        freq_t freq;
1992        bdecode_config cfg;
1993
1994        bdecode_status    status;
1995        uint32_t          current_ticks = bapp_task_getticks();
1996
1997        /* If the decode is stopped dont report bad signal */
1998        if (p_app->decoding == false)
1999                return true;
2000
2001        /* check for tune duration timeout - this is used to restrict display of the 'no signal'
2002           popup for a period of time (TUNE_DURATION) after tuning */
2003        if (current_ticks < (p_app->last_tune_tick + MS_TO_TICKS(TUNE_DURATION)))
2004                return true;
2005
2006        if (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq))
2007                return false;
2008
2009        /* if first time calling function get baseline video pts
2010         * then wait 500msecs and continue.  since we require 2 samples
2011         * of decoder status at least 500msecs apart to determine signal
2012         * status, we need to "prime the pump" on the very first call only
2013         */
2014        if (first_call)
2015        {
2016                first_call = false;
2017                status.audio_decode = p_app->audio;
2018                bdecode_get_status(p_app->decode,&status);
2019                last_video_pts       = status.video_pts;
2020                last_video_pts_ticks = current_ticks;
2021                bapp_task_sleep(500);
2022                current_ticks = bapp_task_getticks();
2023
2024                last_audio_pts      = status.audio_pts;
2025        }
2026
2027        /* make sure video pts is changing - indicates successful decoding.
2028         * only check every 500msecs or so
2029         */
2030        if ((current_ticks - last_video_pts_ticks) > MS_TO_TICKS(500))
2031        {
2032                status.audio_decode = p_app->audio;
2033                bdecode_get_status(p_app->decode,&status);
2034
2035                /* if pts is changing, we are decoding properly */
2036                good_signal = (last_video_pts != status.video_pts);
2037
2038                if (good_signal == false)
2039                {
2040                        good_signal = (last_audio_pts != status.audio_pts);
2041                }
2042                last_audio_pts = status.audio_pts;
2043                BDBG_MSG(("good_signal:%d vpts:0x%08x last_vpts:0x%08x ticks:%d", good_signal, status.video_pts, last_video_pts, current_ticks));
2044
2045                last_video_pts = status.video_pts;
2046                last_video_pts_ticks = current_ticks;
2047        }
2048
2049        bdecode_get_config(p_app->decode,&cfg);
2050        if (!good_signal)
2051        {
2052                if (cfg.channel_change != 0)
2053                {
2054                        cfg.mute = 1;
2055                        cfg.channel_change = 0;
2056                        bdecode_set_config(p_app->decode,&cfg);
2057                }
2058        } else
2059        {
2060                if (cfg.channel_change != 2)
2061                {
2062                        cfg.mute = 0;
2063                        cfg.channel_change = 2;
2064                        bdecode_set_config(p_app->decode,&cfg);
2065                }
2066        }
2067
2068        return good_signal;
2069#endif
2070}
2071
2072/*
2073Summary:
2074Return the current screen.
2075 */
2076
2077bscreen_t * bapp_get_current_screen(bapp_t *p_app)
2078{
2079        return &p_app->p_screens[p_app->screen_id];
2080}
2081
2082/*
2083Summary:
2084        Return the application reference.
2085 */
2086
2087bapp_t *bapp_get_app(void)
2088{
2089        return s_p_app;
2090}
2091
2092bapp_result_t bapp_post_event(bapp_task_event_t event)
2093{
2094        BDBG_WRN(("%s 0x%08x\n",__FUNCTION__,event));
2095        return bapp_task_post_event(s_p_app->msg_queue,event);
2096}
2097
2098
Note: See TracBrowser for help on using the repository browser.