📄 cc1020pic.lst
字号:
334: /* This routine resets the CC1020, clearing all registers. */
335: /****************************************************************************/
336:
337: void ResetCC1020(void)
338: {
339: // Reset CC1020
340: WriteToCC1020Register(CC1020_MAIN, 0x0F&~0x01);
341:
342: // Bring CC1020 out of reset
343: WriteToCC1020Register(CC1020_MAIN, 0x1F);
344: }
345:
346:
347: /****************************************************************************/
348: /* This routine calibrates the CC1020 */
349: /* Returns 0 if calibration fails, non-zero otherwise. Checks the LOCK */
350: /* to check for success. */
351: /****************************************************************************/
352:
353: char CalibrateCC1020(char PA_POWER)
354: {
355: volatile int TimeOutCounter;
356: volatile int nCalAttempt;
357:
358: // Turn off PA to avoid spurs during calibration in TX mode
359: WriteToCC1020Register(CC1020_PA_POWER,0x00);
360:
361: // Calibrate, and re-calibrate if necessary:
362: for (nCalAttempt = CAL_ATTEMPT_MAX; (nCalAttempt>0); nCalAttempt--) {
363:
364: // Start calibration
365: WriteToCC1020Register(CC1020_CALIBRATE,0xB4);
366:
367: // Monitor actual calibration start (ref. Errata Note 04 - CC1020)
368: for(TimeOutCounter=CAL_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x80)==0x80)&&(TimeOutCounter>0); TimeOutCounter--);
369: // Important note:
370: // In active mode the CC1020 should theoretically initiate an internal action/process more or less
371: // instantly upon receiving any command from e.g. an MCU. However, upon sending a [calibration start]
372: // command to CC1020, tests shows that the [STATUS.CAL_COMPLETE]-signal sometimes remains asserted
373: // (or idle) close to 100 usec after the command has been originally issued. Consequently this process
374: // must be carefully monitored to avoid premature PLL LOCK monitoring; do not proceed with subsequent
375: // PLL LOCK monitoring before the calibration has actually completed inside the CC1020! Errata Note 04
376: // suggests that [calibration start] should be monitored by a fixed timeout > 100 usec. However, the
377: // above method implements an adaptive monitoring of [calibration start], which basically waits for the
378: // [STATUS.CAL_COMPLETE]-signal to initialise/deassert (indicating calibration has actually started)
379: // before proceeding with monitoring calibration complete and PLL LOCK. Chipcon considers both methods
380: // safe, and thus leaves it up to the user, which one to use.
381:
382: // Monitor calibration complete
383: for(TimeOutCounter=CAL_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x80)==0x00)&&(TimeOutCounter>0); TimeOutCounter--);
384:
385: // Monitor lock
386: for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x00)&&(TimeOutCounter>0); TimeOutCounter--);
387:
388: // Abort further recalibration attempts if successful LOCK
389: if((ReadFromCC1020Register(CC1020_STATUS)&0x10) == 0x10) {
390: break;
391: }
392: }
393:
394: // Restore PA setting
395: WriteToCC1020Register(CC1020_PA_POWER, PA_POWER);
396:
397: // Return state of LOCK_CONTINUOUS bit
398: return ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10);
399: }
400:
401: /****************************************************************************/
402: /* This routine puts the CC1020 into RX mode (from TX). When switching to */
403: /* RX from PD, use WakeupC1020ToRX first */
404: /****************************************************************************/
405:
406: char SetupCC1020RX(char RXANALOG, char PA_POWER)
407: {
408: volatile int TimeOutCounter;
409: char lock_status;
410:
411: // Switch into RX, switch to freq. reg A
412: WriteToCC1020Register(CC1020_MAIN,0x11);
413:
414: // Setup bias current adjustment
415: WriteToCC1020Register(CC1020_ANALOG,RXANALOG);
416:
417: // Monitor LOCK
418: for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0)&&(TimeOutCounter>0); TimeOutCounter--);
419:
420: // If PLL in lock
421: if((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10){
422: // Indicate PLL in LOCK
423: lock_status = LOCK_OK;
424: // Else (PLL out of LOCK)
425: }else{
426: // If recalibration ok
427: if(CalibrateCC1020(PA_POWER)){
428: // Indicate PLL in LOCK
429: lock_status = LOCK_RECAL_OK;
430: // Else (recalibration failed)
431: }else{
432: // Indicate PLL out of LOCK
433: lock_status = LOCK_NOK;
434: }
435: }
436:
437: // Switch RX part of CC1020 on
438: WriteToCC1020Register(CC1020_MAIN,0x01);
439:
440: // Return LOCK status to application
441: return (lock_status);
442: }
443:
444: /****************************************************************************/
445: /* This routine puts the CC1020 into TX mode (from RX). When switching to */
446: /* TX from PD, use WakeupCC1020ToTX first */
447: /****************************************************************************/
448:
449: char SetupCC1020TX(char TXANALOG, char PA_POWER)
450: {
451: volatile int TimeOutCounter;
452: char lock_status;
453:
454: // Turn off PA to avoid frequency splatter
455: WriteToCC1020Register(CC1020_PA_POWER,0x00);
456:
457: // Setup bias current adjustment
458: WriteToCC1020Register(CC1020_ANALOG,TXANALOG);
459:
460: // Switch into TX, switch to freq. reg B
461: WriteToCC1020Register(CC1020_MAIN,0xC1);
462:
463: // Monitor LOCK
464: for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0)&&(TimeOutCounter>0); TimeOutCounter--);
465:
466: // If PLL in lock
467: if((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10){
468: // Indicate PLL in LOCK
469: lock_status = LOCK_OK;
470: // Else (PLL out of LOCK)
471: }else{
472: // If recalibration ok
473: if(CalibrateCC1020(PA_POWER)){
474: // Indicate PLL in LOCK
475: lock_status = LOCK_RECAL_OK;
476: // Else (recalibration failed)
477: }else{
478: // Indicate PLL out of LOCK
479: lock_status = LOCK_NOK;
480: }
481: }
482:
483: // Restore PA setting
484: WriteToCC1020Register(CC1020_PA_POWER,PA_POWER);
485:
486: // Turn OFF DCLK squelch in TX
487: WriteToCC1020Register(CC1020_INTERFACE,ReadFromCC1020Register(CC1020_INTERFACE)&~0x10);
488:
489: // Return LOCK status to application
490: return (lock_status);
491: }
492:
493: /****************************************************************************/
494: /* This routine puts the CC1020 into power down mode. Use WakeUpCC1020ToRX */
495: /* followed by SetupCC1020RX or WakeupCC1020ToTX followed by SetupCC1020TX */
496: /* to wake up from power down */
497: /****************************************************************************/
498:
499: void SetupCC1020PD(void)
500: {
501: // Put CC1020 into power-down
502: WriteToCC1020Register(CC1020_MAIN,0x1F);
503:
504: // Turn off PA to minimise current draw
505: WriteToCC1020Register(CC1020_PA_POWER,0x00);
506: }
507:
508: /****************************************************************************/
509: /* This routine wakes the CC1020 up from PD mode to RX mode */
510: /****************************************************************************/
511:
512: void WakeUpCC1020ToRX(char RXANALOG)
513: {
514: volatile int i;
515:
516: // Turn on xtal oscillator core
517: WriteToCC1020Register(CC1020_MAIN,0x1B);
518:
519: // Setup bias current adjustment
520: WriteToCC1020Register(CC1020_ANALOG,RXANALOG);
521:
522: // Insert wait routine here, must wait for xtal oscillator to stabilise,
523: // typically takes 2-5ms.
524: for (i=0x0260; i > 0; i--);
525:
526: // Turn on bias generator
527: WriteToCC1020Register(CC1020_MAIN,0x19);
528:
529: // Wait for 150 usec
530: for (i=0x0010; i > 0; i--);
531:
532: // Turn on frequency synthesiser
533: WriteToCC1020Register(CC1020_MAIN,0x11);
534: }
535:
536: /****************************************************************************/
537: /* This routine wakes the CC1020 up from PD mode to TX mode */
538: /****************************************************************************/
539:
540: void WakeUpCC1020ToTX(char TXANALOG)
541: {
542: volatile int i;
543:
544: // Turn on xtal oscillator core
545: WriteToCC1020Register(CC1020_MAIN,0xDB);
546:
547: // Setup bias current adjustment
548: WriteToCC1020Register(CC1020_ANALOG,TXANALOG);
549:
550: // Insert wait routine here, must wait for xtal oscillator to stabilise,
551: // typically takes 2-5ms.
552: for (i=0x0260; i > 0; i--);
553:
554: // Turn on bias generator
555: WriteToCC1020Register(CC1020_MAIN,0xD9);
556:
557: // Wait for 150 usec
558: for (i=0x0010; i > 0; i--);
559:
560: // Turn on frequency synthesiser
561: WriteToCC1020Register(CC1020_MAIN,0xD1);
562: }
563:
564: /****************************************************************************/
565: /* This routine acquires the average RSSI level in dBm */
566: /****************************************************************************/
567: int ReadRSSIlevelCC1020(void){
568: char i;
569: unsigned char RSSI[5];
570: unsigned char FILTER;
571: int RSSI_dBm;
572:
573: // RSSI formula based on CC1020 datahseet and application note 30:
574: // P = 1.5 x RSSI - 3 x VGA_SETTING - RSSI_Offset [dBm]
575:
576: /*
577: VGA_SETTING based on SmartRF Studio - CC1020, v5.3.0.0
578: Note: these settings could be subject to optimisation.
579:
580: 434MHz range:
581: -------------------------------------------------
582: 12.5 => VGA3 = 0x31 => VGA_SETTING = 0x11 = 17dec
583: 25 => VGA3 = 0x2F => VGA_SETTING = 0x0F = 15dec
584: 50 => VGA3 = 0x2E => VGA_SETTING = 0x0E = 14dec
585: 100 => VGA3 = 0x2D => VGA_SETTING = 0x0D = 13dec
586: 150 => VGA3 = 0x2F => VGA_SETTING = 0x0F = 15dec
587: 200 => VGA3 = 0x32 => VGA_SETTING = 0x12 = 18dec
588: 500 => VGA3 = 0x33 => VGA_SETTING = 0x13 = 19dec
589:
590: 868MHz range:
591: -------------------------------------------------
592: 12.5 => VGA3 = 0x2F => VGA_SETTING = 0x0F = 15dec
593: 25 => VGA3 = 0x2E => VGA_SETTING = 0x0E = 14dec
594: 50 => VGA3 = 0x2D => VGA_SETTING = 0x0D = 13dec
595: 100 => VGA3 = 0x2D => VGA_SETTING = 0x0D = 13dec
596: 150 => VGA3 = 0x2E => VGA_SETTING = 0x0E = 14dec
597: 200 => VGA3 = 0x30 => VGA_SETTING = 0x10 = 16dec
598: 500 => VGA3 = 0x34 => VGA_SETTING = 0x14 = 20dec
599: */
600:
601: // Get current channel spacing
602: FILTER = ReadFromCC1020Register(CC1020_FILTER)&0x7F;
603:
604: // Calculate average RSSI in dBm (initially without offset):
605: for(i = 0; i < 5; i++) {
606: RSSI[i] = ReadFromCC1020Register(CC1020_RSSI);
607: }
608: RSSI_dBm = (int)((((unsigned int)RSSI[0]+(unsigned int)RSSI[1]+(unsigned int)RSSI[2]+(unsigned int)RSSI[3]+(unsigned int)RSSI[4])*3)/(2*5));
609: RSSI_dBm = ((RSSI_dBm*3) - (3*(int)(ReadFromCC1020Register(CC1020_VGA3)&0x1F)*2)) / 2;
610:
611: // Calculate average RSSI in dBm with offset, according to frequency band:
612: // Active frequency is in 800 MHz band
613: if( (ReadFromCC1020Register(CC1020_ANALOG)&0x80) == 0x80 ) {
614: switch ( FILTER ) {
615: case 0x58://12.5 kHz spacing
616: case 0x3F://12.5 kHz spacing, optimal sensitivity
617: RSSI_dBm = RSSI_dBm - 95;
618: break;
619: case 0x2F://25 kHz spacing
620: RSSI_dBm = RSSI_dBm - 96;
621: break;
622: case 0x2B://50 kHz spacing
623: RSSI_dBm = RSSI_dBm - 95;
624: break;
625: case 0x25://100 kHz spacing
626: RSSI_dBm = RSSI_dBm - 96;
627: break;
628: case 0x22://150 kHz spacing
629: RSSI_dBm = RSSI_dBm - 99;
630: break;
631: case 0x01://200 kHz spacing
632: RSSI_dBm = RSSI_dBm - 99;
633: break;
634: case 0x00://500 kHz spacing
635: RSSI_dBm = RSSI_dBm - 101;
636: break;
637: }
638: // Active frequency is in 434 MHz band
639: } else {
640: switch ( FILTER ) {
641: case 0x38://12.5 kHz spacing
642: case 0x2F://25 kHz spacing
643: RSSI_dBm = RSSI_dBm - 102;
644: break;
645: case 0x2B://50 kHz spacing
646: RSSI_dBm = RSSI_dBm - 100;
647: break;
648: case 0x25://100 kHz spacing
649: RSSI_dBm = RSSI_dBm - 99;
650: break;
651: case 0x22://150 kHz spacing
652: RSSI_dBm = RSSI_dBm - 101;
653: break;
654: case 0x01://200 kHz spacing
655: RSSI_dBm = RSSI_dBm - 102;
656: break;
657: case 0x00://500 kHz spacing
658: RSSI_dBm = RSSI_dBm - 103;
659: break;
660: }
661: }
662:
663: return(RSSI_dBm);
664: }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -