/*************************************************************************** * Copyright (C) 2008, Crawlerz * * * * Description: * * Low-level Radio "C" code snippets for: * * - Unigen's Juno M & Juno W RF Modules * * - Cypress CYWM6934 & CYWM6935 RF Modules * * - Cypress CYWUSB6932, CYWUSB6934, CYWUSB6935, and CYWUSB6953 * * Version: * * 2008.35.2 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #define SPI_WR 0x80 #define SPI_RD 0x00 #define SPI_INC 0x40 #define SPI_FRZ 0x00 // 0.65 is the implementation specific cal factor for DelayMicroSec(); #define SYNTH_SETTLE 200 * 0.65 // 200usec #define PREAMBLE_64kbps 64 * 0.65 // 64usec (2 symbols worth) #define PREAMBLE_16kbps 128 * 0.65 // 128usec (2 symbols worth) #define RECEIVER_READY 35 * 0.65 // 35usec #define CRYSTAL_STARTUP 2100 * 0.65 // 2100usec #define RSSI_ADC_CONVERSION 50 * 0.65 // 50usec #define tPD 10 * 0.65 // 10usec #define tPWR_RST 1300 * 0.65 // 1300usec #define tPDN_X13 2000 * 0.65 // 2000usec #define tSPI_RDY 1 * 0.65 // 1usec // RadioInit table - reg addr followed by init value, sequence is important const BYTE code RadioInitTable[] = { 0x20, 0x45, //REG_ANALOG_CTL 0x20, 0x44, //REG_ANALOG_CTL 0x2E, 0x80, //REG_PWR_CTL 0x26, 0xC0, //REG_VCO_CAL 0x33, 0x41, //REG_CLOCK_ENABLE 0x32, 0x41, //REG_CLOCK_MANUAL 0x24, 0x40, //REG_CRYSTAL_ADJ 0x06, 0x09, //REG_SERDES_CTL, EOF=1 (first missed correlation) 0x10, 0xFF, //REG_TX_VALID 0x23, 0x05, //REG_PA - PA=5 0x21, 0x02 //REG_CHANNEL = 2402MHz }; const BYTE code Radio64kbpsTable[] = { 0x04, 0x06, //REG_DATA_RATE - 64kbps, CODELEN=32, DATAMODE=DDR 0x19, 0x03, //REG_THRESHOLD_L - TH32=3 0x1A, 0x1D, //REG_THRESHOLD_H - TH32=3 0x11, 0xDC, //REG_PN_CODE, A overwrite default w/ PN Code Index 1 (64kbps table) 0x12, 0xC0, //REG_PN_CODE, A 0x13, 0x6B, //REG_PN_CODE, A 0x14, 0xB8, //REG_PN_CODE, A 0x15, 0x2B, //REG_PN_CODE, B 0x16, 0x09, //REG_PN_CODE, B 0x17, 0xBB, //REG_PN_CODE, B 0x18, 0xB2 //REG_PN_CODE, B }; const BYTE code Radio16kbpsTable[] = { 0x04, 0x00, //REG_DATA_RATE - 16kbps, CODELEN=64, DATAMODE=SDR 0x19, 0x08, //REG_THRESHOLD_L - TH32=8 0x1A, 0x38, //REG_THRESHOLD_H - TH32=8 0x11, 0x3F, //REG_PN_CODE, A overwrite default w/ PN Code Index 1 (16kbps table) 0x12, 0x2C, //REG_PN_CODE, A 0x13, 0x4E, //REG_PN_CODE, A 0x14, 0xAA, //REG_PN_CODE, A 0x15, 0x71, //REG_PN_CODE, A 0x16, 0x48, //REG_PN_CODE, A 0x17, 0x7A, //REG_PN_CODE, A 0x18, 0xC9 //REG_PN_CODE, A }; // RadioPnCode 64kbps table const BYTE code Radio64kbpsPnCodeTable[] = { 0x6A, 0xE7, 0x01, 0xEA, 0x03, 0xFD, 0x13, 0xD2, //PN Code 0 0xDC, 0xC0, 0x6B, 0xB8, 0x2B, 0x09, 0xBB, 0xB2, //PN Code 1 0xA3, 0x1E, 0xF2, 0xA4, 0x31, 0x32, 0x7A, 0xB3, //PN Code 2 0x44, 0x83, 0x3B, 0xDD, 0x14, 0xCF, 0x8E, 0xC9, //PN Code 3 0x35, 0x35, 0x4E, 0xC5, 0xF3, 0x52, 0x47, 0xB0, //PN Code 4 0x7C, 0x23, 0x8A, 0xCE, 0x45, 0x5C, 0x54, 0xD7, //PN Code 5 0x81, 0xAC, 0xFB, 0x83, 0x7A, 0x9A, 0x61, 0xAC, //PN Code 6 0x3C, 0x12, 0x5F, 0x9C, 0x39, 0x98, 0xF6, 0x8A //PN Code 7 }; // RadioPnCode 16kbps table const BYTE code Radio16kbpsPnCodeTable[] = { 0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3, // Index 0 0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9, // Index 1 0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82, // Index 2 0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB, // Index 3 0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7, // Index 4 0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95, // Index 5 0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4, // Index 6 0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF // Index 7 }; BYTE radio_mid[] = {0,0,0,0}; // 16-bytes - data, data, data, data... BYTE radio_txbuf[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; // 32-bytes - data, valid, data, valid... BYTE radio_rxbuf[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; BYTE radio_rssi = 0; BYTE radio_status[] = {0,0,0,0,0,0}; // 0 - REG_TX_INT_STAT // 1 - SPARE // 2 - REG_RX_INT_STAT // 3 - REG_RX_DATA_A // 4 - REG_RX_VALID_A // 5 - REG_RSSI // prototypes for radio snippets void DelayMicroSec(WORD microsec); void RadioReset(void); void RadioInit(void); void RadioSetPnCode(BYTE index); void RadioGetMid(void); BYTE RadioTransmit(BYTE len, BYTE *txbuf); BYTE RadioReceive(BYTE *rxbuf); void RadioSleep(void); void RadioWake(void); BYTE RadioGetRssi(void); void DelayMicroSec(WORD microsec) { WORD i; for(i=0;i 3) len += 2; } if(radio_status[2]&0x02 && len) break; if(len > sizeof(radio_rxbuf)) { len = sizeof(radio_rxbuf); break; } } // ~75usec of "idle" time between bytes when using 64kbps SpiWrite((SPI_FRZ | 0x03), 0x00); //REG_CONTROL - return to idle radio_status[5] = SpiRead((SPI_FRZ | 0x22)); // store REG_RSSI return(len); } void RadioSleep(void) { SpiWrite((SPI_FRZ | 0x03), 0x00); //REG_CONTROL - force idle nPD_LO; // force sleep DelayMicroSec(tPD); //10usec // typically takes ~50usec from the time nPD is asserted to low power mode } void RadioWake(void) { nPD_HI; // force idle DelayMicroSec(CRYSTAL_STARTUP); // ~Xmsec for crystal start to stable - idle } BYTE RadioGetRssi(void) { SpiWrite((SPI_FRZ | 0x2F), 0x80); //REG_CARRIER_DETECT - force radio to manually acquire rssi reading SpiWrite((SPI_FRZ | 0x03), 0x90); //REG_CONTROL - put radio in receive mode - triggers rssi adc DelayMicroSec(SYNTH_SETTLE); // wait for synth to settle DelayMicroSec(RECEIVER_READY); // wait for receiver ready DelayMicroSec(RSSI_ADC_CONVERSION); // wait for 5-bit rssi adc to complete radio_status[5] = SpiRead((SPI_FRZ | 0x22)); //REG_RSSI - flush stale rssi reading DelayMicroSec(RSSI_ADC_CONVERSION); // wait for 5-bit rssi adc to complete radio_status[5] = SpiRead((SPI_FRZ | 0x22)); //REG_RSSI - get rssi reading SpiWrite((SPI_FRZ | 0x2F), 0x00); //REG_CARRIER_DETECT - manually clear CDET SpiWrite((SPI_FRZ | 0x03), 0x00); //REG_CONTROL - put radio in idle mode return(radio_status[5]); }