source: svn/trunk/newcon3bcm2_21bu/dta/src/settop_api/bsettop_tuner_aob.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 16.2 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2012, 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#include "bsettop_tuner_aob.h"
22#include "bmem.h"
23#include "btnr.h"
24#include "btnr_priv.h"
25#include "btnr_ob_3x7x.h"
26#include "baob.h"
27#include "gist.h"
28#include "bkni_multi.h"
29#include "bos_task_priorities.h"
30#include "bapp_util.h"
31/* needed for OOB, should we have a central place to do it? */
32#include "bchp_ufe_afe.h"
33
34BDBG_MODULE(btuner_aob);                /* Register software module with debug interface */
35
36#define AOB_TASK_STACK  0x400
37#define TIMEOUT_INC_MS  50
38
39#define TURE_TIMEOUT_MS (3*500)
40
41struct btuner_aob
42{
43        b_task_params task_params;
44        b_task_t task_h;
45        unsigned int task_stack[AOB_TASK_STACK];
46        b_mutex_t               mutex;
47
48        /* module specific variables */
49        BKNI_EventHandle lockEvent;
50        BKNI_EventHandle isrEvent;
51        bool isLocked;
52        bool isPowerSaver;
53        bool no_signal;
54
55        btuner_aob_params last_params;
56        BTNR_Handle tnraobHandle;
57        BAOB_Handle aobHandle;
58        unsigned int freq_hz;
59        unsigned int timeout_ms;
60};
61
62static btuner_aob_t     p_s_tuner_aob = NULL;
63
64/*
65 * Summary:
66 *    turn on power on daisy VHF. It is a workaround since BTNR_SetPowerSaver function
67 *    can turn it off
68 **/
69static void btuner_aob_P_power_on_daisy_out(btuner_aob_t tuner_aob) 
70{
71        uint32_t reg;
72
73        BDBG_ASSERT(tuner_aob);
74
75        /* power this VHF daisy that OOB needed */
76        reg = BREG_Read32(GetREG(), BCHP_UFE_AFE_TNR0_PWRUP_01);
77        reg |= BCHP_UFE_AFE_TNR0_PWRUP_01_i_pwrup_DAISY_VHF_MASK;
78        BREG_Write32(GetREG(), BCHP_UFE_AFE_TNR0_PWRUP_01, reg);
79}
80
81/*
82 * Summary:
83 *    Callback for notifying the lock status change event
84 **/
85static BAOB_CallbackFunc btuner_aob_cbLockChangeFunc(
86        void *pParam
87        )
88{
89        bool lockStatus;
90        btuner_aob_t p_aob;
91
92        p_aob = (btuner_aob_t)pParam;
93        BDBG_ASSERT(p_aob);
94
95        BAOB_GetLockStatus(p_aob->aobHandle, &lockStatus );
96        BDBG_WRN(("%s: locked=%d",__func__, lockStatus));
97        if (p_aob) {
98                /* notify event */
99                BKNI_SetEvent(p_aob->lockEvent);
100        }
101        p_aob->no_signal = false;
102        return 0;
103}
104
105#if 0
106/*
107 * Summary:
108 *    Callback for notifying the no signal event
109 **/
110static BAOB_CallbackFunc btuner_aob_cbNoSignal(
111        void *pParam
112        )
113{
114        btuner_aob_t p_aob = (btuner_aob_t)pParam;
115
116        BDBG_ASSERT(p_aob);
117
118        /* what should we do? may be add an Application CB to notify the application immediately */
119        p_aob->no_signal = true;
120        return 0;
121}
122#endif
123
124#define OOB_ID          3
125
126/***************************************************************************
127Summary:
128Acquisition processing thread
129 ***************************************************************************/
130static void aob_task(void *arg)
131{
132        btuner_aob_t p_aob = (btuner_aob_t)arg;
133        //int id = OOB_ID;
134
135        BERR_Code rc;
136
137        BDBG_ASSERT(p_aob);
138
139        BDBG_MSG(("aob_task"));
140        while (1)
141        {
142                rc = BKNI_WaitForEvent(p_aob->isrEvent,10);
143                if (BERR_TIMEOUT != rc)
144                {
145                        //BDBG_WRN(("%s ISR Event",__FUNCTION__));
146                        if (bos_acquire_mutex(&(p_aob->mutex), BOS_PEND_FOREVER) == b_ok)
147                        {
148                                BTNR_Ob_3x7x_ProcessInterruptEvent(p_aob->tnraobHandle);
149                                bos_release_mutex(&(p_aob->mutex));
150                        }
151                }
152                rc = BKNI_WaitForEvent(p_aob->lockEvent,10);
153                if (BERR_SUCCESS == rc && !p_aob->isPowerSaver)
154                {
155                        BDBG_WRN(("%s Lock Event",__FUNCTION__));
156                        /* only return if user don't issue tune request */
157                        if (bos_acquire_mutex(&(p_aob->mutex), BOS_PEND_FOREVER) == b_ok)
158                        {
159                                bool lockStatus;
160                               
161                                if (p_aob->freq_hz) 
162                                        BAOB_GetLockStatus(p_aob->aobHandle, &lockStatus);
163                                // function is not defined, what should we do?
164                                //BAOB_ProcessNotification(p_aob->aobHandle, id);
165                                bos_release_mutex(&(p_aob->mutex));
166                                if (p_aob->freq_hz && !lockStatus) {
167                                        btuner_aob_tune(p_aob, p_aob->freq_hz, &p_aob->last_params);
168                                        /* delay more so that we don't tune too much */
169                                        bos_sleep(50);
170                                }
171                        }
172                }
173                /* increase sleep time if we are either in power saving mode or no signal detected */
174                bos_sleep(50 + (p_aob->isPowerSaver ? 500 : 0) + (p_aob->no_signal ? 500 : 0));
175        }
176}
177
178/*
179Summary:
180Open a AOB tuner.
181
182Description:
183On most platforms, the tuner_id is simply an index of the tuners.
184
185On platforms with more frontend options (e.g. 97038), please see bsettop_ids.txt
186for documentation on special numbers.
187
188*/
189btuner_aob_t btuner_aob_open(
190        bobject_t tuner_id      /* - handle used to identify a particular tuner */
191        )
192{
193        btuner_aob_t p_aob = NULL;
194        bresult rc;
195
196        p_aob = (btuner_aob_t)BKNI_Malloc(sizeof(struct btuner_aob));
197        if (!p_aob)
198                return NULL;
199
200        BKNI_Memset(p_aob,0,sizeof(*p_aob));
201
202        p_aob->task_params.name="aob_task";
203        p_aob->task_params.priority = AOB_ACQ_PRIORITY;
204        p_aob->task_params.stack_size = AOB_TASK_STACK;
205        p_aob->task_params.stack = p_aob->task_stack;
206
207#if 1
208        BDBG_SetModuleLevel("baob_acquire",BDBG_eMsg);
209        BDBG_SetModuleLevel("baob_status",BDBG_eMsg);
210        BDBG_SetModuleLevel("baob_utils",BDBG_eMsg);
211#endif
212
213        BAOB_Settings aobSettings;
214        BTNR_Ob_3x7x_Settings tnrobSettings;
215
216        BTNR_Ob_3x7x_GetDefaultSettings(&tnrobSettings);
217        tnrobSettings.i2cAddr = 0;
218        tnrobSettings.hTmr = GetTMR();
219        tnrobSettings.hHeap = GetHEAP();
220
221        rc = BTNR_Ob_3x7x_Open(&p_aob->tnraobHandle, &tnrobSettings, GetREG());
222        BDBG_ASSERT(p_aob->tnraobHandle);
223
224        /* Get events and register callbacks */
225        BTNR_Ob_3x7x_GetInterruptEventHandle(p_aob->tnraobHandle, &p_aob->isrEvent);
226        BDBG_ASSERT(p_aob->isrEvent);
227
228        // Initialize hChip7552, hReg7552, and hRpc . . .
229        //
230        // Initialize BTNR_3128Ob (for us, 7552)
231        //
232        // BAOB initialization for BCM3128
233        BAOB_GetDefaultSettings( &aobSettings, GetCHP() );
234
235        // Configure the Crystal Frequency of H/W board. Need to check for the Xtal frequency
236        //aobSettings.xtalFreq = 24000000;
237        //FEC should be enabled, however if enabled we can't get data, for now enabled first
238        //aobSettings.enableFEC = true;         // false: CableCARD will do FEC, true: legacy OOB needs FEC
239        aobSettings.hTmr = GetTMR();
240        aobSettings.hHeap = GetHEAP();
241
242        rc = BAOB_Open( &p_aob->aobHandle, GetCHP(), GetREG(), GetINT(), &aobSettings );
243        BDBG_ASSERT(p_aob->aobHandle);
244
245        BKNI_CreateEvent(&(p_aob->lockEvent));
246        BDBG_ASSERT(p_aob->lockEvent);
247
248        // Install callback for state change event, where last parameter is for general use.
249        BAOB_InstallCallback(p_aob->aobHandle, BAOB_Callback_eLockChange, (BAOB_CallbackFunc)btuner_aob_cbLockChangeFunc, (void *)p_aob);
250        //BAOB_InstallCallback(p_aob->aobHandle, BAOB_Callback_eAsyncStatusReady, (BAOB_CallbackFunc)btuner_aob_cbNoSignal, (void *)p_aob);
251
252        rc = bos_create_mutex(&p_aob->mutex);
253        BDBG_ASSERT(rc == b_ok);
254
255        /* initialize variables first */
256        btuner_aob_params_init(p_aob, &p_aob->last_params);
257        /* we have 75.25 and 103.25 MHz frequencies in our HE with OOB data */
258        p_aob->freq_hz = 0;
259
260        bos_start_task(&(p_aob->task_h),&(p_aob->task_params),aob_task,p_aob);
261
262        p_s_tuner_aob = p_aob;
263
264        return p_aob;
265}
266
267/*
268Summary:
269Close an AOB tuner.
270*/
271void btuner_aob_close(
272                btuner_aob_t tuner_aob   /* - handle returned by btuner_aob_open */
273                )
274{
275        BDBG_ASSERT(tuner_aob);
276        BDBG_ASSERT(tuner_aob->aobHandle);
277
278        /* reset callback */
279        BAOB_InstallCallback(tuner_aob->aobHandle, BAOB_Callback_eLockChange, NULL, (void *)tuner_aob);
280        //BAOB_InstallCallback(tuner_aob->aobHandle, BAOB_Callback_eAsyncStatusReady, NULL, (void *)tuner_aob);
281
282        BAOB_Close(tuner_aob->aobHandle);
283
284        bos_delete_mutex(&tuner_aob->mutex);
285        BKNI_DestroyEvent(tuner_aob->lockEvent);
286        BKNI_Free(tuner_aob);
287}
288
289/*
290 * Summary:
291 *     Tune the OOB tuner.
292 *
293 */
294static void btuner_aob_tune_tuner(btuner_aob_t tuner_aob)
295{
296        BTNR_PowerSaverSettings pwrSettings;
297        BTNR_Settings tnrSettings;
298
299        tuner_aob->isPowerSaver = false;
300
301        /* TODO: we should be able to call BTNR_SetSettings after BTNR_SetPowerSaver. verify */
302        pwrSettings.enable = false;
303        BTNR_SetPowerSaver(tuner_aob->tnraobHandle, &pwrSettings);
304
305        BTNR_GetSettings(tuner_aob->tnraobHandle, &tnrSettings);
306        tnrSettings.tnrApplication = BTNR_TunerApplication_eCable;
307        tnrSettings.rfInputMode = BTNR_RfInputMode_eInternalLna;       
308        BTNR_SetSettings(tuner_aob->tnraobHandle, &tnrSettings);
309
310        BAOB_DisablePowerSaver(tuner_aob->aobHandle);
311
312        BTNR_SetTunerRfFreq(tuner_aob->tnraobHandle, tuner_aob->freq_hz, BTNR_TunerMode_eDigital);
313}
314
315/*
316Summary:
317Tune and acquire using give parameters
318*/
319bband_t btuner_aob_tune(
320                btuner_aob_t tuner_aob,
321                unsigned int freq,                      /* - RF frequency in Hz */
322                btuner_aob_params *params       /* - parameters needed to tune and acquire */
323                )
324{
325        bool locked;
326        bband_t result = -1;
327        BAOB_AcquireParam       acqParam;
328
329        BDBG_ASSERT(tuner_aob);
330
331        BKNI_Memset(&acqParam,0,sizeof(acqParam));
332
333        if (bos_acquire_mutex(&(tuner_aob->mutex),BKNI_INFINITE) != b_ok)
334        {
335                BDBG_ERR(("%s: bos_acquire_mutex failed", __func__));
336                return result;
337        }
338
339        BKNI_ResetEvent(tuner_aob->lockEvent);
340
341        tuner_aob->freq_hz = freq;
342        btuner_aob_tune_tuner(tuner_aob);
343        btuner_aob_P_power_on_daisy_out(tuner_aob);
344
345        switch (params->spectrum) 
346        {
347                default:
348                        acqParam.spectrum = BAOB_SpectrumMode_eNoInverted;
349                        break;
350
351                        /* we have one on one match on the defines */
352                case SpectrumMode_eAuto:
353                case SpectrumMode_eNoInverted:
354                case SpectrumMode_eInverted:
355                        acqParam.spectrum = params->spectrum;
356                        break;
357        }
358        acqParam.autoAcquire = params->auto_acquire;
359        acqParam.modType = params->mode;
360        acqParam.symbolRate = params->symbol_rate;
361        acqParam.berSrc = params->ber_input_src;
362
363        BAOB_Acquire( tuner_aob->aobHandle, &acqParam);
364
365        /* looks like there is a need for the delay */
366        BKNI_Sleep(100);
367
368        /* remember last tune parameters */
369        tuner_aob->last_params = *params;
370
371        bos_release_mutex(&(tuner_aob->mutex));
372
373        if (!params->wait_for_lock)
374                result = 0;
375
376        if (params->wait_for_lock) {
377                if (BKNI_WaitForEvent(tuner_aob->lockEvent,params->timeout) != BERR_SUCCESS)
378                {
379                        BDBG_MSG(("BKNI_WaitForEvent failed in %s",__FUNCTION__));
380                }
381                else
382                        result = 0;
383        }
384        BAOB_GetLockStatus(tuner_aob->aobHandle, &locked);
385        BDBG_WRN(("%s: Lock Status: %s\n", __func__, (locked ? "locked" : "not lock")));
386        if (locked)
387                result = 0;
388       
389        return result;
390}
391
392/*
393Summary:
394Get the status of AOB receiver
395*/
396bresult btuner_aob_get_status(
397                btuner_aob_t tuner_aob,
398                btuner_aob_status *status        /* - [out] Current status of the SDS demod */
399                )
400{
401        BERR_Code err;
402        BAOB_Status aob_status;
403
404        BDBG_ASSERT(tuner_aob);
405
406        BKNI_Memset(status,0,sizeof(*status));
407
408        if (!tuner_aob->freq_hz) 
409                return BERR_INVALID_PARAMETER;
410
411        BKNI_Memset(&aob_status,0,sizeof(aob_status));
412        err = BAOB_GetStatus(tuner_aob->aobHandle,&aob_status);
413        if (err) {
414                status->lock = false;
415                return BERR_INVALID_PARAMETER;
416        }       
417        status->lock = (aob_status.isFecLock && aob_status.isQamLock);
418
419        switch (aob_status.modType)
420        {
421                case BAOB_ModulationType_eDvs167Qpsk: status->mode = eDvs167Qpsk; break;
422                case BAOB_ModulationType_eDvs178Qpsk: status->mode = eDvs178Qpsk; break;
423                case BAOB_ModulationType_ePod_Dvs167Qpsk: status->mode = ePod_Dvs167Qpsk; break;
424                case BAOB_ModulationType_ePod_Dvs178Qpsk: status->mode = ePod_Dvs178Qpsk; break;
425                default:
426                        return BERR_INVALID_PARAMETER;
427        }
428
429        status->isPowerSaverEnabled = aob_status.isPowerSaverEnabled ? 1 : 0;
430        status->sysXtalFreq = aob_status.sysXtalFreq;               /* in Hertz, Sys. Xtal freq. */
431        status->symbolRate = aob_status.symbolRate;                                     /* in Baud */
432        status->isFecLock = aob_status.isFecLock;
433        status->isQamLock = aob_status.isQamLock;
434        status->snrEstimate = aob_status.snrEstimate;                           /* in 1/256 db */
435        status->agcIntLevel = aob_status.agcIntLevel;                           /* in 1/10 percent */
436        status->agcExtLevel = aob_status.agcExtLevel;                           /* in 1/10 percent */
437        status->carrierFreqOffset = aob_status.carrierFreqOffset;       /* in 1/1000 Hz */
438        status->carrierPhaseOffset = aob_status.carrierPhaseOffset;     /* in 1/1000 Hz */
439        status->uncorrectedCount = aob_status.uncorrectedCount;         /* not self-clearing  */
440        status->correctedCount = aob_status.correctedCount;                     /* not self-clearing*/
441        status->berErrorCount = aob_status.berErrorCount;                       /* not self-clearing */
442
443        status->snr = (aob_status.snrEstimate >> 8);
444
445        BDBG_WRN(("sysXtalFreq=%d", status->sysXtalFreq));
446        BDBG_WRN(("symbolRate=%d", status->symbolRate));
447        BDBG_WRN(("isFecLock=%s", status->isFecLock ? "locked" : "Not locked"));
448        BDBG_WRN(("isQamLock=%s", status->isQamLock ? "locked" : "Not locked"));
449        BDBG_WRN(("snrEstimate=%d", status->snrEstimate));
450        BDBG_WRN(("agcIntLevel=%d", status->agcIntLevel));
451        BDBG_WRN(("agcExtLevel=%d", status->agcExtLevel));
452        BDBG_WRN(("carrierFreqOffse=%d", status->carrierFreqOffset));
453        BDBG_WRN(("carrierPhaseOffset=%d", status->carrierPhaseOffset));
454        BDBG_WRN(("uncorrectedCount=%d", status->uncorrectedCount));
455        BDBG_WRN(("correctedCount=%d", status->correctedCount));
456        BDBG_WRN(("berErrorCount=%d", status->berErrorCount));
457        BDBG_WRN(("snr=%d", status->snr));
458
459        /* remember this */
460        //tuner_aob->isPowerSaver       = aob_status.isPowerSaverEnabled;
461
462        return BERR_SUCCESS;
463}
464
465/*
466Summary:
467Required to initialize QPSK parameters to defaults
468*/
469void btuner_aob_params_init(
470                btuner_aob_t tuner_aob,                 /* - required for possible resource-dependent defaults */
471                btuner_aob_params *aob_param    /* - [out] */
472                )
473{
474        BDBG_ASSERT(tuner_aob);
475
476        BKNI_Memset(aob_param,0,sizeof(*aob_param));
477
478        aob_param->mode = eDvs178Qpsk;
479        aob_param->symbol_rate = 1024000;
480        aob_param->spectrum = SpectrumMode_eAuto;
481        aob_param->ber_input_src = BerInputSrc_eFecOutput;
482        //aob_param->wait_for_lock = true;
483        aob_param->timeout = TURE_TIMEOUT_MS;
484        //aob_param->cancel = true;
485        aob_param->auto_acquire = true;
486}
487
488/*
489 * Summary:
490 * Get an arry of soft decision for a constellation
491 * Description:
492 * I and Q range from 32767 to -32768
493 */
494#define TOTAL_AOB_SOFTDECISIONS 30
495
496bresult btuner_aob_get_softdecisions(
497                btuner_aob_t tuner_aob, 
498                btuner_aob_softdecision_t *pdec,        /* - [out] array of soft decisions */
499                size_t length                                           /* number of soft decisions to get */
500                )
501{
502        int i,j;
503        bresult rc;
504        int16_t nbr;
505        int16_t d_i[TOTAL_AOB_SOFTDECISIONS], d_q[TOTAL_AOB_SOFTDECISIONS];
506
507        BDBG_ASSERT(tuner_aob);
508
509        for (i=0; i<length; i+= TOTAL_AOB_SOFTDECISIONS)
510        {
511                rc = BAOB_GetSoftDecisionBuf(tuner_aob->aobHandle,(int16_t)TOTAL_AOB_SOFTDECISIONS, d_i, d_q, &nbr);
512                if (rc) return BERR_INVALID_PARAMETER;
513
514                for (j=0; ((j<TOTAL_AOB_SOFTDECISIONS) && ((i+j)<length)); j++)
515                {
516                        pdec[i+j].i = d_i[j];
517                        pdec[i+j].q = d_q[j];
518                }
519        }   
520        return BERR_SUCCESS;
521}
522
523/*
524 * Summary:
525 *      set power saving mode
526 * Description:
527 *      enable or disable power saver mode
528 */
529bresult btuner_aob_set_power_saving(
530                btuner_aob_t tuner_aob, 
531                bool enable
532                )
533{
534        BERR_Code err;
535        BTNR_PowerSaverSettings pwrSettings;
536
537        BDBG_ASSERT(tuner_aob);
538        if (enable) {
539                err = BAOB_EnablePowerSaver(tuner_aob->aobHandle);
540        }
541        else {
542                err = BAOB_DisablePowerSaver(tuner_aob->aobHandle);
543        }
544        if (0 == err) 
545                tuner_aob->isPowerSaver = enable ? true : false;
546
547        /* TODO: we should be able to call BTNR_SetSettings after BTNR_SetPowerSaver. verify */
548        pwrSettings.enable = enable ? 1 : 0;
549        BTNR_SetPowerSaver(tuner_aob->tnraobHandle, &pwrSettings);
550
551        return (0 == err) ? BERR_SUCCESS : -1;
552}
553
554#ifdef TUNER_AOB_TEST
555/*
556Summary:
557        help function to test OOB channel acquiring.
558*/
559void btuner_aob_tune_test(unsigned int freq, int mode)
560{
561        btuner_aob_t tuner_aob = p_s_tuner_aob;
562
563        if (tuner_aob) {
564                btuner_aob_status status;
565                tuner_aob->last_params.wait_for_lock = false;
566                tuner_aob->last_params.mode = mode;
567                if (0 == mode) {
568                        tuner_aob->last_params.symbol_rate = 772000; //1544000;
569                }
570                btuner_aob_tune(tuner_aob, freq, &tuner_aob->last_params);
571                btuner_aob_get_status(tuner_aob, &status);
572                BDBG_WRN(("tune OOB frequency %d is %s", tuner_aob->freq_hz, status.lock ? "locked" : "not locked"));
573        }
574        else {
575                BDBG_WRN(("%s: please call btuner_aob_open to open OOB module first%s\n", __func__));
576        }
577}
578#endif
579
580/*
581 * Summary:
582 *      get tuned frequency
583 * Description:
584 *      get tuned frequency
585 */
586uint32_t btuner_aob_get_frequency(btuner_aob_t tuner_aob)
587{
588        BDBG_ASSERT(tuner_aob);
589
590        return tuner_aob->freq_hz;
591}
592
593/*
594 * Summary:
595 *      reset OOB tuner status
596 * Description:
597 *      reset OOB tuner status
598 */
599bresult btuner_aob_reset_status(btuner_aob_t tuner_aob)
600{
601        if (!tuner_aob->freq_hz) 
602                return BERR_NOT_INITIALIZED;    /* not tuned yet */
603        return BAOB_ResetStatus(tuner_aob->aobHandle);
604}
605
Note: See TracBrowser for help on using the repository browser.