2 \author Travis Goodspeed
3 \brief Chipcon SPI Register Interface
5 Unfortunately, there is very little similarity between the CC2420
6 and the CC2500, to name just two of the myriad of Chipcon SPI
7 radios. Auto-detection will be a bit difficult, but more to the
8 point, all high level functionality must be moved into the client.
11 //Higher level left to client application.
15 #include <stdlib.h> //added for itoa
20 //! Handles a Chipcon SPI command.
21 void ccspi_handle_fn( uint8_t const app,
25 // define the ccspi app's app_t
26 app_t const ccspi_app = {
38 "\tThe CCSPI app adds support for the Chipcon SPI register\n"
39 "\tinterface. Unfortunately, there is very little similarity\n"
40 "\tbetween the CC2420 and the CC2500, to name just two of the\n"
41 "\tmyriad of Chipcon SPI radios. Auto-detection will be a bit\n"
42 "\tdifficult, but more to the point, all high level functionality\n"
43 "\tmust be moved into the client.\n"
46 //! Set up the pins for CCSPI mode.
53 //P4OUT|=BIT5; //activate CC2420 voltage regulator
57 /*P4OUT&=~BIT6; FIXME Does the new code work on Z1 and Telosb?
62 //Begin a new transaction.
67 //! Read and write an CCSPI byte.
68 u8 ccspitrans8(u8 byte){
69 register unsigned int bit;
70 //This function came from the CCSPI Wikipedia article.
73 for (bit = 0; bit < 8; bit++) {
74 /* write MOSI on trailing edge of previous clock */
83 /* read MISO on trailing edge */
92 //! Reflexively jam on the present channel.
93 void ccspireflexjam(u16 delay){
95 #if defined(FIFOP) && defined(SFD) && defined(FIFO) && defined(PLED2DIR) && defined(PLED2PIN) && defined(PLED2OUT)
98 debugstr("Reflex jamming until reset.");
100 txdata(CCSPI,CCSPI_REFLEX,1); //Let the client continue its business.
102 //Wait until a packet is received
104 //Has there been an overflow in the RX buffer?
106 //debugstr("Clearing RX overflow");
108 ccspitrans8(0x08); //SFLUSHRX
112 //Turn on LED 2 (green) as signal
113 PLED2DIR |= PLED2PIN;
114 PLED2OUT &= ~PLED2PIN;
118 //Wait a few us to send it.
121 //Transmit the packet.
127 //Load the next jamming packet.
128 //Note: attempts to preload this actually slowed the jam time down from 7 to 9 bytes.
130 ccspitrans8(CCSPI_TXFIFO);
131 char pkt[5] = {0x05, 0, 0, 0, 0};
132 //char pkt[15] = {0x0f, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef, 0xba, 0xbe, 0xc0};
133 //char pkt[12] = {0x0c, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef};
134 for(i=0;i<pkt[0];i++)
138 //* I think this might be unnecessary.
139 //msdelay(100+delay); //Instead of waiting for pulse on SFD
143 ccspitrans8(0x09); //SFLUSHTX
147 //Turn off LED 2 (green) as signal
148 PLED2DIR |= PLED2PIN;
149 PLED2OUT |= PLED2PIN;
152 debugstr("Can't reflexively jam without SFD, FIFO, FIFOP, and P2LEDx definitions - try using telosb platform.");
159 //! Writes a register
160 u8 ccspi_regwrite(u8 reg, const u8 *buf, int len){
163 reg=ccspitrans8(reg);
171 u8 ccspi_regread(u8 reg, u8 *buf, int len){
174 reg=ccspitrans8(reg);
176 *buf++=ccspitrans8(0);
182 //! Handles a Chipcon SPI command.
183 void ccspi_handle_fn( uint8_t const app,
189 //debugstr("Chipcon SPI handler.");
193 cmddata[0]|=0x40; //Set the read bit.
198 CLRSS; //Drop !SS to begin transaction.
199 j=cmddata[0];//Backup address.
201 cmddata[i]=ccspitrans8(cmddata[i]);
202 SETSS; //Raise !SS to end transaction.
203 cmddata[0]=j&~0x40;//Restore address.
204 txdata(app,verb,len);
212 //Has there been an overflow?
214 debugstr("Clearing overflow");
216 ccspitrans8(0x08); //SFLUSHRX
218 txdata(app,verb,0); //no packet
224 //Wait for completion.
229 ccspitrans8(CCSPI_RXFIFO | 0x40);
230 //ccspitrans8(0x3F|0x40);
231 cmddata[0]=0x20; //to be replaced with length
234 /* This reads too far on some CC2420 revisions, but on others it
235 works fine. It probably has to do with whether FIFO drops
236 before or after the SPI clocking.
238 A software fix is to reset the CC2420 between packets. This
239 works, but a better solution is desired.
241 for(i=0;i<cmddata[0]+1;i++)
242 //for(i=0;FIFO && i<0x80;i++)
243 cmddata[i]=ccspitrans8(0x00);
246 /* We used to flush the RX buffer after receive. No longer.
248 ccspitrans8(0x08); //SFLUSHRX
252 //Only should transmit a packet if the length is legal.
253 if(cmddata[0]&0x80) i=0;
260 debugstr("Can't RX a packet with SFD and FIFOP definitions.");
266 //Has there been an overflow?
268 debugstr("Clearing overflow");
270 ccspitrans8(0x08); //SFLUSHRX
272 txdata(app,verb,0); //no packet
278 //Wait for completion.
281 //Decrypt the packet.
282 CLRSS; ccspitrans8(CCSPI_SRXDEC); SETSS;
284 //Wait for decryption to complete.
289 ccspitrans8(CCSPI_RXFIFO | 0x40);
290 //ccspitrans8(0x3F|0x40);
291 cmddata[0]=0x20; //to be replaced with length
294 /* This reads too far on some CC2420 revisions, but on others it
295 works fine. It probably has to do with whether FIFO drops
296 before or after the SPI clocking.
298 A software fix is to reset the CC2420 between packets. This
299 works, but a better solution is desired.
301 for(i=0;i<cmddata[0]+1;i++)
302 //for(i=0;FIFO && i<0x80;i++)
303 cmddata[i]=ccspitrans8(0x00);
306 //Only should transmit a packet if the length is legal.
307 if(cmddata[0]&0x80) i=0;
314 debugstr("Can't RX a packet with SFD and FIFOP definitions.");
321 ccspitrans8(CCSPI_SFLUSHRX);
328 ccspireflexjam(len?cmddataword[0]:0);
331 case CCSPI_REFLEX_AUTOACK:
332 #if defined(FIFOP) && defined(SFD) && defined(FIFO) && defined(PLED2DIR) && defined(PLED2PIN) && defined(PLED2OUT)
333 //txdata(app, verb, 1);
337 //Has there been an overflow in the RX buffer?
339 //debugstr("Clearing overflow");
341 ccspitrans8(0x08); //SFLUSHRX
345 //Wait until a packet is received
347 //Turn on LED 2 (green) as signal
348 PLED2DIR |= PLED2PIN;
349 PLED2OUT &= ~PLED2PIN;
351 //Put radio in TX mode
352 //Note: Not doing this slows down jamming, so can't jam short packets.
353 // However, if we do this, it seems to mess up our RXFIFO ability.
357 //Load the jamming packet
359 ccspitrans8(CCSPI_TXFIFO);
360 char pkt[7] = {0x07, 0x01, 0x08, 0xff, 0xff, 0xff, 0xff};
361 for(i=0;i<pkt[0];i++)
364 //Transmit the jamming packet
366 ccspitrans8(0x04); //STXON
368 msdelay(200); //Instead of examining SFD line status
371 ccspitrans8(0x09); //SFLUSHTX
374 //Get the orignally received packet, up to the seqnum field.
376 ccspitrans8(CCSPI_RXFIFO | 0x40);
378 cmddata[i]=ccspitrans8(0xde);
382 ccspitrans8(0x08); //SFLUSHRX
384 //Send the sequence number of the jammed packet back to the client
385 //itoa(cmddata[3], byte, 16);
387 //txdata(app,verb,cmddata[3]);
389 //TODO turn on AUTOCRC for it to apply to the TX???
390 // this may overcome issues of bad crc / length issues?
391 //mdmctrl0 (0x11) register set bit 5 to true.
393 //Create the forged ACK packet
394 cmddata[0] = 6; //length of ack frame plus length
395 cmddata[1] = 0x02; //first byte of FCF
396 cmddata[2] = 0x00; //second byte of FCF
397 //[3] is already filled with the sequence number
401 int q = (crc ^ c) & 15; //Do low-order 4 bits
402 crc = (crc / 16) ^ (q * 4225);
403 q = (crc ^ (c / 16)) & 15; //And high 4 bits
404 crc = (crc / 16) ^ (q * 4225);
406 cmddata[4] = crc & 0xFF;
407 cmddata[5] = (crc >> 8) & 0xFF;
409 for(i=0;i<cmddata[0];i++) {
410 itoa(cmddata[i], byte, 16);
413 //Load the forged ACK packet
415 ccspitrans8(CCSPI_TXFIFO);
416 for(i=0;i<cmddata[0];i++)
417 ccspitrans8(cmddata[i]);
419 //Transmit the forged ACK packet
422 ccspitrans8(0x04); //STXON
424 msdelay(200); //TODO try doing this based on SFD line status instead
427 ccspitrans8(0x09); //SFLUSHTX
430 //TODO disable AUTOCRC here again to go back to promiscous mode
432 //Turn off LED 2 (green) as signal
433 PLED2DIR |= PLED2PIN;
434 PLED2OUT |= PLED2PIN;
436 //TODO the firmware stops staying in this mode after a while, and stops jamming... need to find a fix.
438 debugstr("Can't reflexively jam without SFD, FIFO, FIFOP, and P2LEDx definitions - try using telosb platform.");
446 ccspitrans8(CCSPI_SFLUSHTX);
454 //Wait for last packet to TX.
455 //while(ccspi_status()&BIT3);
459 ccspitrans8(0x09); //SFLUSHTX
465 ccspitrans8(CCSPI_TXFIFO);
466 for(i=0;i<cmddata[0];i++)
467 ccspitrans8(cmddata[i]);
470 //Transmit the packet.
472 ccspitrans8(0x04); //STXON
475 //Wait for the pulse on SFD, after which the packet has been sent.
481 debugstr("Can't TX a packet with SFD and FIFOP definitions.");
486 debugstr("Not yet supported in CCSPI");