CC1000ControlM.nc
上传用户:joranyuan
上传日期:2022-06-23
资源大小:3306k
文件大小:15k
源码类别:

网络

开发平台:

Others

  1. /* tab:4
  2.  *
  3.  *
  4.  * "Copyright (c) 2000-2002 The Regents of the University  of California.  
  5.  * All rights reserved.
  6.  *
  7.  * Permission to use, copy, modify, and distribute this software and its
  8.  * documentation for any purpose, without fee, and without written agreement is
  9.  * hereby granted, provided that the above copyright notice, the following
  10.  * two paragraphs and the author appear in all copies of this software.
  11.  * 
  12.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  13.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  14.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  15.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16.  * 
  17.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  18.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  19.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  20.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  21.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
  22.  *
  23.  */
  24. /* tab:4
  25.  *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By
  26.  *  downloading, copying, installing or using the software you agree to
  27.  *  this license.  If you do not agree to this license, do not download,
  28.  *  install, copy or use the software.
  29.  *
  30.  *  Intel Open Source License 
  31.  *
  32.  *  Copyright (c) 2002 Intel Corporation 
  33.  *  All rights reserved. 
  34.  *  Redistribution and use in source and binary forms, with or without
  35.  *  modification, are permitted provided that the following conditions are
  36.  *  met:
  37.  * 
  38.  * Redistributions of source code must retain the above copyright
  39.  *  notice, this list of conditions and the following disclaimer.
  40.  * Redistributions in binary form must reproduce the above copyright
  41.  *  notice, this list of conditions and the following disclaimer in the
  42.  *  documentation and/or other materials provided with the distribution.
  43.  *      Neither the name of the Intel Corporation nor the names of its
  44.  *  contributors may be used to endorse or promote products derived from
  45.  *  this software without specific prior written permission.
  46.  *  
  47.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  48.  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  49.  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  50.  *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
  51.  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  52.  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  53.  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  54.  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  55.  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  56.  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  57.  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  58.  * 
  59.  * 
  60.  */
  61. /*
  62.  *
  63.  * Authors: Jaein Jeong, Phil Buonadonna
  64.  * Date last modified:  $Revision: 1.1.1.1 $
  65.  *
  66.  * This module provides the CONTROL functionality for the Chipcon1000 series radio.
  67.  * It exports both a standard control interface and a custom interface to control
  68.  * CC1000 operation.
  69.  */
  70. module CC1000ControlM {
  71.   provides {
  72.     interface StdControl;
  73.     interface CC1000Control;
  74.   }
  75.   uses {
  76.     interface HPLCC1000 as HPLChipcon;
  77.   }
  78. }
  79. implementation
  80. {
  81.   uint32_t gCurrentChannel;
  82.   norace uint8_t gCurrentParameters[31];
  83.   enum {
  84.     IF = 150000,
  85.     FREQ_MIN = 4194304,
  86.     FREQ_MAX = 16751615
  87.   };
  88.   const uint32_t FRefTbl[9] = {2457600,
  89.        2106514,
  90.        1843200,
  91.        1638400,
  92.        1474560,
  93.        1340509,
  94.        1228800,
  95.        1134277,
  96.        1053257};
  97.   
  98.   const uint16_t CorTbl[9] = {1213,
  99.       1416,
  100.       1618,
  101.       1820,
  102.       2022,
  103.       2224,
  104.       2427,
  105.       2629,
  106.       2831};
  107.   
  108.   const uint16_t FSepTbl[9] = {0x1AA,
  109.        0x1F1,
  110.        0x238,
  111.        0x280,
  112.        0x2C7,
  113.        0x30E,
  114.        0x355,
  115.        0x39C,
  116.        0x3E3};
  117.   
  118.   //
  119.   // PRIVATE Module functions
  120.   //
  121.   ///************************************************************/
  122.   ///* Function: chipcon_cal                                    */
  123.   ///* Description: places the chipcon radio in calibrate mode  */
  124.   ///*                                                          */
  125.   ///************************************************************/
  126.   result_t chipcon_cal()
  127.   {
  128.     //int i;
  129.     //int freq = tunefreq;
  130.     call HPLChipcon.write(CC1K_PA_POW,0x00);  // turn off rf amp
  131.     call HPLChipcon.write(CC1K_TEST4,0x3f);   // chip rate >= 38.4kb
  132.     // RX - configure main freq A
  133.     call HPLChipcon.write(CC1K_MAIN,
  134.   ((1<<CC1K_TX_PD) | (1<<CC1K_RESET_N)));
  135.     //TOSH_uwait(2000);
  136.     // start cal
  137.     call HPLChipcon.write(CC1K_CAL,
  138.   ((1<<CC1K_CAL_START) | 
  139.    (1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));
  140. #if 0
  141.     for (i=0;i<34;i++)  // need 34 ms delay
  142.       TOSH_uwait(1000);
  143. #endif
  144.     while (((call HPLChipcon.read(CC1K_CAL)) & (1<<CC1K_CAL_COMPLETE)) == 0);
  145.     //exit cal mode
  146.     call HPLChipcon.write(CC1K_CAL,
  147.   ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));
  148.     // TX - configure main freq B
  149.     call HPLChipcon.write(CC1K_MAIN,
  150.   ((1<<CC1K_RXTX) | (1<<CC1K_F_REG) | (1<<CC1K_RX_PD) | 
  151.    (1<<CC1K_RESET_N)));
  152.     // Set TX current
  153.     call HPLChipcon.write(CC1K_CURRENT,gCurrentParameters[29]);
  154.     call HPLChipcon.write(CC1K_PA_POW,0x00);
  155.     //TOSH_uwait(2000);
  156.     // start cal
  157.     call HPLChipcon.write(CC1K_CAL,
  158.   ((1<<CC1K_CAL_START) | 
  159.    (1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));
  160. #if 0
  161.     for (i=0;i<28;i++)  // need 28 ms delay
  162.       TOSH_uwait(1000);
  163. #endif
  164.     while (((call HPLChipcon.read(CC1K_CAL)) & (1<<CC1K_CAL_COMPLETE)) == 0);
  165.     //exit cal mode
  166.     call HPLChipcon.write(CC1K_CAL,
  167.   ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));
  168.     
  169.     //TOSH_uwait(200);
  170.     return SUCCESS;
  171.   }
  172.   void cc1000SetFreq() {
  173.     uint8_t i;
  174.     // FREQA, FREQB, FSEP, CURRENT(RX), FRONT_END, POWER, PLL
  175.     for (i = 1;i < 0x0d;i++) {
  176.       call HPLChipcon.write(i,gCurrentParameters[i]);
  177.     }
  178.     // MATCH
  179.     call HPLChipcon.write(CC1K_MATCH,gCurrentParameters[0x12]);
  180.     chipcon_cal();
  181.     return;
  182.   }
  183.   void cc1000SetModem() {
  184.     call HPLChipcon.write(CC1K_MODEM2,gCurrentParameters[0x0f]);
  185.     call HPLChipcon.write(CC1K_MODEM1,gCurrentParameters[0x10]);
  186.     call HPLChipcon.write(CC1K_MODEM0,gCurrentParameters[0x11]);
  187.     return;
  188.   }
  189.   /*
  190.    * cc1000ComputeFreq(uint32_t desiredFreq);
  191.    *
  192.    * Compute an achievable frequency and the necessary CC1K parameters from
  193.    * a given desired frequency (Hz). The function returns the actual achieved
  194.    * channel frequency in Hz.
  195.    *
  196.    * This routine assumes the following:
  197.    *  - Crystal Freq: 14.7456 MHz
  198.    *  - LO Injection: High
  199.    *  - Separation: 64 KHz
  200.    *  - IF: 150 KHz
  201.    * 
  202.    * Approximate costs for this function:
  203.    *  - ~870 bytes FLASH
  204.    *  - ~32 bytes RAM
  205.    *  - 9400 cycles
  206.    */
  207.   uint32_t cc1000ComputeFreq(uint32_t desiredFreq) {
  208.     uint32_t ActualChannel = 0;
  209.     uint32_t RXFreq = 0, TXFreq = 0;
  210.     int32_t Offset = 0x7fffffff;
  211.     uint16_t FSep = 0;
  212.     uint8_t RefDiv = 0;
  213.     uint8_t i;
  214.     for (i = 0; i < 9; i++) {
  215.       uint32_t NRef = ((desiredFreq + IF));
  216.       uint32_t FRef = FRefTbl[i];
  217.       uint32_t Channel = 0;
  218.       uint32_t RXCalc = 0, TXCalc = 0;
  219.       int32_t  diff;
  220.       NRef = ((desiredFreq + IF) << 2) / FRef;
  221.       if (NRef & 0x1) {
  222.   NRef++;
  223.       }
  224.       if (NRef & 0x2) {
  225. RXCalc = 16384 >> 1;
  226. Channel = FRef >> 1;
  227.       }
  228.       NRef >>= 2;
  229.       RXCalc += (NRef * 16384) - 8192;
  230.       if ((RXCalc < FREQ_MIN) || (RXCalc > FREQ_MAX)) 
  231. continue;
  232.     
  233.       TXCalc = RXCalc - CorTbl[i];
  234.       if ((TXCalc < FREQ_MIN) || (TXCalc > FREQ_MAX)) 
  235. continue;
  236.       Channel += (NRef * FRef);
  237.       Channel -= IF;
  238.       diff = Channel - desiredFreq;
  239.       if (diff < 0)
  240. diff = 0 - diff;
  241.       if (diff < Offset) {
  242. RXFreq = RXCalc;
  243. TXFreq = TXCalc;
  244. ActualChannel = Channel;
  245. FSep = FSepTbl[i];
  246. RefDiv = i + 6;
  247. Offset = diff;
  248.       }
  249.     }
  250.     if (RefDiv != 0) {
  251.       // FREQA
  252.       gCurrentParameters[0x3] = (uint8_t)((RXFreq) & 0xFF);  // LSB
  253.       gCurrentParameters[0x2] = (uint8_t)((RXFreq >> 8) & 0xFF);
  254.       gCurrentParameters[0x1] = (uint8_t)((RXFreq >> 16) & 0xFF);  // MSB
  255.       // FREQB
  256.       gCurrentParameters[0x6] = (uint8_t)((TXFreq) & 0xFF); // LSB
  257.       gCurrentParameters[0x5] = (uint8_t)((TXFreq >> 8) & 0xFF);
  258.       gCurrentParameters[0x4] = (uint8_t)((TXFreq >> 16) & 0xFF);  // MSB
  259.       // FSEP
  260.       gCurrentParameters[0x8] = (uint8_t)((FSep) & 0xFF);  // LSB
  261.       gCurrentParameters[0x7] = (uint8_t)((FSep >> 8) & 0xFF); //MSB
  262.       if (ActualChannel < 500000000) {
  263. if (ActualChannel < 400000000) {
  264. // CURRENT (RX)
  265.   gCurrentParameters[0x9] = ((8 << CC1K_VCO_CURRENT) | (1 << CC1K_LO_DRIVE));
  266. // CURRENT (TX)
  267.   gCurrentParameters[0x1d] = ((9 << CC1K_VCO_CURRENT) | (1 << CC1K_PA_DRIVE));
  268. }
  269. else {
  270. // CURRENT (RX)
  271.   gCurrentParameters[0x9] = ((4 << CC1K_VCO_CURRENT) | (1 << CC1K_LO_DRIVE));
  272. // CURRENT (TX)
  273.   gCurrentParameters[0x1d] = ((8 << CC1K_VCO_CURRENT) | (1 << CC1K_PA_DRIVE));
  274. }
  275. // FRONT_END
  276. gCurrentParameters[0xa] = (1 << CC1K_IF_RSSI); 
  277. // MATCH
  278. gCurrentParameters[0x12] = (7 << CC1K_RX_MATCH);
  279.       }
  280.       else {
  281. // CURRENT (RX)
  282.   gCurrentParameters[0x9] = ((8 << CC1K_VCO_CURRENT) | (3 << CC1K_LO_DRIVE));
  283. // CURRENT (TX)
  284.   gCurrentParameters[0x1d] = ((15 << CC1K_VCO_CURRENT) | (3 << CC1K_PA_DRIVE));
  285. // FRONT_END
  286. gCurrentParameters[0xa] = ((1<<CC1K_BUF_CURRENT) | (2<<CC1K_LNA_CURRENT) | 
  287.  (1<<CC1K_IF_RSSI));
  288. // MATCH
  289. gCurrentParameters[0x12] = (2 << CC1K_RX_MATCH);
  290.       }
  291.       // PLL
  292.       gCurrentParameters[0xc] = (RefDiv << CC1K_REFDIV);
  293.     }
  294.     gCurrentChannel = ActualChannel;
  295.     return ActualChannel;
  296.   }
  297.   //
  298.   // PUBLIC Module Functions
  299.   //
  300.   command result_t StdControl.init() {
  301.     outp (0x41,TCCR3B);
  302.     call HPLChipcon.init();
  303.     // wake up xtal and reset unit
  304.     call HPLChipcon.write(CC1K_MAIN,
  305.   ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
  306.    (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD))); 
  307.     // clear reset.
  308.     call HPLChipcon.write(CC1K_MAIN,
  309.   ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
  310.    (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD) |
  311.    (1<<CC1K_RESET_N))); 
  312.     // reset wait time
  313.     TOSH_uwait(2000);        
  314.     // Set default parameter values
  315.     // POWER 0dbm
  316.     gCurrentParameters[0xb] = ((8 << CC1K_PA_HIGHPOWER) | (0 << CC1K_PA_LOWPOWER)); 
  317.     call HPLChipcon.write(CC1K_PA_POW, gCurrentParameters[0xb]);
  318.     // LOCK Manchester Violation default
  319.     gCurrentParameters[0xd] = (9 << CC1K_LOCK_SELECT);
  320.     call HPLChipcon.write(CC1K_LOCK_SELECT, gCurrentParameters[0xd]);
  321.     // Default modem values = 19.2 Kbps (38.4 kBaud), Manchester encoded
  322.     // MODEM2
  323.     gCurrentParameters[0xf] = 0;
  324.     //call HPLChipcon.write(CC1K_MODEM2,gCurrentParameters[0xf]);
  325.     // MODEM1
  326.     gCurrentParameters[0x10] = ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | 
  327. (3<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N));
  328.     //call HPLChipcon.write(CC1K_MODEM1,gCurrentParameters[0x10]);
  329.     // MODEM0
  330.     gCurrentParameters[0x11] = ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | 
  331. (1<<CC1K_XOSC_FREQ));
  332.     //call HPLChipcon.write(CC1K_MODEM0,gCurrentParameters[0x11]);
  333.     cc1000SetModem();
  334.     // FSCTRL
  335.     gCurrentParameters[0x13] = (1 << CC1K_FS_RESET_N);
  336.     call HPLChipcon.write(CC1K_FSCTRL,gCurrentParameters[0x13]);
  337.     // HIGH Side LO
  338.     gCurrentParameters[0x1e] = TRUE;
  339.     // Program registers w/ default freq and calibrate
  340. #ifdef CC1K_DEF_FREQ
  341.     call CC1000Control.TuneManual(CC1K_DEF_FREQ);
  342. #else
  343.     call CC1000Control.TunePreset(CC1K_DEF_PRESET);     // go to default tune frequency
  344. #endif
  345.     return SUCCESS;
  346.   }
  347.   command result_t CC1000Control.TunePreset(uint8_t freq) {
  348.     int i;
  349.     for (i=1;i < 31 /*0x14*/;i++) {
  350.       //call HPLChipcon.write(i,PRG_RDB(&CC1K_Params[freq][i]));
  351.       gCurrentParameters[i] = PRG_RDB(&CC1K_Params[freq][i]);
  352.     }
  353.     cc1000SetFreq();
  354.     return SUCCESS;
  355.   }
  356.   command uint32_t CC1000Control.TuneManual(uint32_t DesiredFreq) {
  357.     uint32_t actualFreq;
  358.     actualFreq = cc1000ComputeFreq(DesiredFreq);
  359.     cc1000SetFreq();
  360.     return actualFreq;
  361.   }
  362.   async command result_t CC1000Control.TxMode() {
  363.     // MAIN register to TX mode
  364.     call HPLChipcon.write(CC1K_MAIN,
  365.   ((1<<CC1K_RXTX) | (1<<CC1K_F_REG) | (1<<CC1K_RX_PD) | 
  366.    (1<<CC1K_RESET_N)));
  367.     // Set the TX mode VCO Current
  368.     call HPLChipcon.write(CC1K_CURRENT,gCurrentParameters[29]);
  369.     TOSH_uwait(250);
  370.     call HPLChipcon.write(CC1K_PA_POW,gCurrentParameters[0xb] /*rfpower*/);
  371.     TOSH_uwait(20);
  372.     return SUCCESS;
  373.   }
  374.   async command result_t CC1000Control.RxMode() {
  375.     // MAIN register to RX mode
  376.     // Powerup Freqency Synthesizer and Receiver
  377.     call HPLChipcon.write(CC1K_CURRENT,gCurrentParameters[0x09]);
  378.     call HPLChipcon.write(CC1K_PA_POW,0x00); // turn off power amp
  379.     call HPLChipcon.write(CC1K_MAIN,
  380.   ((1<<CC1K_TX_PD) | (1<<CC1K_RESET_N)));
  381.     // Sex the RX mode VCO Current
  382.     TOSH_uwait(125);
  383.     return SUCCESS;
  384.   }
  385.   command result_t CC1000Control.BIASOff() {
  386.     // MAIN register to SLEEP mode
  387.     call HPLChipcon.write(CC1K_MAIN,
  388.   ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
  389.    (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD) |
  390.    (1<<CC1K_RESET_N)));
  391.  
  392.     return SUCCESS;
  393.   }
  394.   command result_t CC1000Control.BIASOn() {
  395.     //call CC1000Control.RxMode();
  396.     call HPLChipcon.write(CC1K_MAIN,
  397.   ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
  398.    (1<<CC1K_FS_PD) | 
  399.    (1<<CC1K_RESET_N)));
  400.     
  401.     TOSH_uwait(200 /*500*/);
  402.     return SUCCESS;
  403.   }
  404.   command result_t StdControl.stop() {
  405.     // MAIN register to power down mode. Shut everything off
  406.     call HPLChipcon.write(CC1K_MAIN,
  407.   ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
  408.    (1<<CC1K_FS_PD) | (1<<CC1K_CORE_PD) | (1<<CC1K_BIAS_PD) |
  409.    (1<<CC1K_RESET_N)));
  410.     call HPLChipcon.write(CC1K_PA_POW,0x00);  // turn off rf amp
  411.     return SUCCESS;
  412.   }
  413.   command result_t StdControl.start() {
  414.     // wake up xtal osc
  415.     call HPLChipcon.write(CC1K_MAIN,
  416.   ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
  417.    (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD) |
  418.    (1<<CC1K_RESET_N)));
  419.     //TOSH_uwait(2000);
  420. //    call CC1000Control.RxMode();
  421.     return SUCCESS;
  422.   }
  423.   command result_t CC1000Control.SetRFPower(uint8_t power) {
  424.     gCurrentParameters[0xb] = power;
  425.     //rfpower = power;
  426.     //call HPLChipcon.write(CC1K_PA_POW,rfpower); // Set power amp value
  427.     return SUCCESS;
  428.   }
  429.   command uint8_t CC1000Control.GetRFPower() {
  430.     return gCurrentParameters[0xb]; //rfpower;
  431.   }
  432.   command result_t CC1000Control.SelectLock(uint8_t Value) {
  433.     //LockVal = Value;
  434.     gCurrentParameters[0xd] = (Value << CC1K_LOCK_SELECT);
  435.     return call HPLChipcon.write(CC1K_LOCK,(Value << CC1K_LOCK_SELECT));
  436.   }
  437.   command uint8_t CC1000Control.GetLock() {
  438.     uint8_t retVal;
  439.     retVal = (uint8_t)call HPLChipcon.GetLOCK(); 
  440.     return retVal;
  441.   }
  442.   command bool CC1000Control.GetLOStatus() {
  443.     return gCurrentParameters[0x1e];
  444.   }
  445. }