524052f0fa33450390cdb561b22a12242dffc693
[goodfet] / firmware / apps / radios / ccspi.c
1 /*! \file ccspi.c
2   \author Travis Goodspeed
3   \brief Chipcon SPI Register Interface
4   
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.
9 */
10
11 //Higher level left to client application.
12
13 #include "platform.h"
14 #include "command.h"
15 #include <stdlib.h> //added for itoa
16 #include <signal.h>
17 #include <io.h>
18 #include <iomacros.h>
19
20 #include "ccspi.h"
21 #include "spi.h"
22
23 //! Handles a Chipcon SPI command.
24 void ccspi_handle_fn( uint8_t const app,
25                                           uint8_t const verb,
26                                           uint32_t const len);
27
28 // define the ccspi app's app_t
29 app_t const ccspi_app = {
30
31         /* app number */
32         CCSPI,
33
34         /* handle fn */
35         ccspi_handle_fn,
36
37         /* name */
38         "CCSPI",
39
40         /* desc */
41         "\tThe CCSPI app adds support for the Chipcon SPI register\n"
42         "\tinterface. Unfortunately, there is very little similarity\n"
43         "\tbetween the CC2420 and the CC2500, to name just two of the\n"
44         "\tmyriad of Chipcon SPI radios.  Auto-detection will be a bit\n"
45         "\tdifficult, but more to the point, all high level functionality\n"
46         "\tmust be moved into the client.\n"
47 };
48
49 //! Set up the pins for CCSPI mode.
50 void ccspisetup(){
51   SPIDIR&=~MISO;
52   SPIDIR|=MOSI+SCK;
53   DIRSS;
54   DIRCE;
55   
56   P4OUT|=BIT5; //activate CC2420 voltage regulator
57   msdelay(100);
58   
59   //Reset the CC2420.
60   P4OUT&=~BIT6;
61   P4OUT|=BIT6;
62   
63   //Begin a new transaction.
64   CLRSS;
65   SETSS;
66 }
67
68 //! Read and write an CCSPI byte.
69 u8 ccspitrans8(u8 byte){
70   register unsigned int bit;
71   //This function came from the CCSPI Wikipedia article.
72   //Minor alterations.
73   
74   for (bit = 0; bit < 8; bit++) {
75     /* write MOSI on trailing edge of previous clock */
76     if (byte & 0x80)
77       SETMOSI;
78     else
79       CLRMOSI;
80     byte <<= 1;
81  
82     SETCLK;
83   
84     /* read MISO on trailing edge */
85     byte |= READMISO;
86     CLRCLK;
87   }
88   
89   return byte;
90 }
91
92
93 //! Writes a register
94 u8 ccspi_regwrite(u8 reg, const u8 *buf, int len){
95   CLRSS;
96   
97   reg=ccspitrans8(reg);
98   while(len--)
99     ccspitrans8(*buf++);
100   
101   SETSS;
102   return reg;//status
103 }
104 //! Reads a register
105 u8 ccspi_regread(u8 reg, u8 *buf, int len){
106   CLRSS;
107   
108   reg=ccspitrans8(reg);
109   while(len--)
110     *buf++=ccspitrans8(0);
111   
112   SETSS;
113   return reg;//status
114 }
115
116 //! Handles a Chipcon SPI command.
117 void ccspi_handle_fn( uint8_t const app,
118                       uint8_t const verb,
119                       uint32_t const len){
120   unsigned long i;
121   
122   //debugstr("Chipcon SPI handler.");
123   
124   switch(verb){
125   case PEEK:
126     cmddata[0]|=0x40; //Set the read bit.
127     //DO NOT BREAK HERE.
128   case READ:
129   case WRITE:
130   case POKE:
131     CLRSS; //Drop !SS to begin transaction.
132     for(i=0;i<len;i++)
133       cmddata[i]=ccspitrans8(cmddata[i]);
134     SETSS;  //Raise !SS to end transaction.
135     txdata(app,verb,len);
136     break;
137   case SETUP:
138     ccspisetup();
139     txdata(app,verb,0);
140     break;
141   case CCSPI_RX:
142 #ifdef FIFOP
143     //Has there been an overflow?
144     if((!FIFO)&&FIFOP){
145       debugstr("Clearing overflow");
146       CLRSS;
147       ccspitrans8(0x08); //SFLUSHRX
148       SETSS;
149     }
150     
151     //Is there a packet?
152     if(FIFOP&&FIFO){
153       //Wait for completion.
154       while(SFD);
155       
156       //Get the packet.
157       CLRSS;
158       ccspitrans8(CCSPI_RXFIFO | 0x40);
159       //ccspitrans8(0x3F|0x40);
160       cmddata[0]=0xff; //to be replaced with length
161       for(i=0;i<cmddata[0]+2;i++)
162         cmddata[i]=ccspitrans8(0xde);
163       SETSS;
164       
165       //Flush buffer.
166       CLRSS;
167       ccspitrans8(0x08); //SFLUSHRX
168       SETSS;
169       //Only should transmit length of one more than the reported
170       // length of the frame, which holds the length byte:
171       txdata(app,verb,cmddata[0]+1);
172     }else{
173       //No packet.
174       txdata(app,verb,0);
175     }
176 #else
177     debugstr("Can't RX a packet with SFD and FIFOP definitions.");
178     txdata(app,NOK,0);
179 #endif
180     break;
181   case CCSPI_RX_FLUSH:
182     //Flush the buffer.
183     CLRSS;
184     ccspitrans8(CCSPI_SFLUSHRX);
185     SETSS;
186     
187     txdata(app,verb,0);
188     break;
189
190   case CCSPI_REFLEX:
191 #if defined(FIFOP) && defined(SFD) && defined(FIFO) && defined(PLED2DIR) && defined(PLED2PIN) && defined(PLED2OUT)
192     txdata(app,verb,1);  //Just sending some response back to client
193     while(1) {
194         //Wait until a packet is received
195         while(!SFD);
196         //Turn on LED 2 (green) as signal
197             PLED2DIR |= PLED2PIN;
198             PLED2OUT &= ~PLED2PIN;
199
200         //Put radio in TX mode
201         CLRSS;
202         ccspitrans8(0x04);
203         SETSS;
204
205         //Load the jamming packet.
206         //TODO try to preload this to get faster effects
207         CLRSS;
208         ccspitrans8(CCSPI_TXFIFO);
209         char pkt[15] = {0x0f, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef, 0xba, 0xbe, 0xc0};
210         //char pkt[12] = {0x0c, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef};
211         for(i=0;i<pkt[0];i++)
212           ccspitrans8(pkt[i]);
213         SETSS;
214
215         //Transmit the packet.
216         CLRSS;
217         ccspitrans8(0x04); //STXON
218         SETSS;
219         msdelay(100);      //Instead of waiting for pulse on SFD
220         //Flush TX buffer.
221         CLRSS;
222         ccspitrans8(0x09); //SFLUSHTX
223         SETSS;
224
225         //Turn off LED 2 (green) as signal
226             PLED2DIR |= PLED2PIN;
227             PLED2OUT |= PLED2PIN;
228     }
229     //TODO the firmware stops staying in this mode after a while, and stops jamming... need to find a fix.
230     break;
231 #else
232     debugstr("Can't reflexively jam without SFD, FIFO, FIFOP, and P2LEDx definitions - try using telosb platform.");
233     txdata(app,NOK,0);
234 #endif
235
236   case CCSPI_REFLEX_SEQNUM:
237 #if defined(FIFOP) && defined(SFD) && defined(FIFO) && defined(PLED2DIR) && defined(PLED2PIN) && defined(PLED2OUT)
238     //char byte[4];
239     while(1) {
240         //Has there been an overflow in the RX buffer?
241         //TODO do we really need to check this??
242         if((!FIFO)&&FIFOP){
243           //debugstr("Clearing overflow");
244           CLRSS;
245           ccspitrans8(0x08); //SFLUSHRX
246           SETSS;
247         }
248
249         //Wait until a packet is received
250         while(!SFD);
251         //Turn on LED 2 (green) as signal
252             PLED2DIR |= PLED2PIN;
253             PLED2OUT &= ~PLED2PIN;
254
255         //Get the orignally received packet, up to the seqnum field.
256         CLRSS;
257         ccspitrans8(CCSPI_RXFIFO | 0x40);
258         for(i=0;i<4;i++)
259             cmddata[i]=ccspitrans8(0xde);
260         SETSS;
261         //Flush RX buffer.
262         CLRSS;
263         ccspitrans8(0x08); //SFLUSHRX
264         SETSS;
265         //Send the sequence number of the jammed packet back to the client
266         //itoa(cmddata[3], byte, 16);
267         //debugstr(byte);
268         txdata(app,verb,cmddata[3]);
269
270         //Put radio in TX mode
271         CLRSS;
272         ccspitrans8(0x04);
273         SETSS;
274
275         //Load the packet.
276         CLRSS;
277         ccspitrans8(CCSPI_TXFIFO);
278         char pkt[12] = {0x0c, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef};
279         for(i=0;i<pkt[0];i++)
280           ccspitrans8(pkt[i]);
281         SETSS;
282
283         //Transmit the packet.
284         CLRSS;
285         ccspitrans8(0x04);  //STXON
286         SETSS;
287         msdelay(200);       //Instead of examining SFD line status
288         //Flush TX buffer.
289         CLRSS;
290         ccspitrans8(0x09);  //SFLUSHTX
291         SETSS;
292
293         //Turn off LED 2 (green) as signal
294             PLED2DIR |= PLED2PIN;
295             PLED2OUT |= PLED2PIN;
296     }
297     //TODO the firmware stops staying in this mode after a while, and stops jamming... need to find a fix.
298 #else
299     debugstr("Can't reflexively jam without SFD, FIFO, FIFOP, and P2LEDx definitions - try using telosb platform.");
300     txdata(app,NOK,0);
301 #endif
302     break;
303
304   case CCSPI_TX_FLUSH:
305     //Flush the buffer.
306     CLRSS;
307     ccspitrans8(CCSPI_SFLUSHTX);
308     SETSS;
309     
310     txdata(app,verb,0);
311     break;
312   case CCSPI_TX:
313 #ifdef FIFOP
314     
315     //Wait for last packet to TX.
316     //while(ccspi_status()&BIT3);
317     
318     //Load the packet.
319     CLRSS;
320     ccspitrans8(CCSPI_TXFIFO);
321     for(i=0;i<cmddata[0];i++)
322       ccspitrans8(cmddata[i]);
323     SETSS;
324     
325     //Transmit the packet.
326     CLRSS;
327     ccspitrans8(0x04); //STXON
328     SETSS;
329     
330     //Wait for the pulse on SFD, after which the packet has been sent.
331     while(!SFD);
332     while(SFD);
333     
334     //Flush TX buffer.
335     CLRSS;
336     ccspitrans8(0x09); //SFLUSHTX
337     SETSS;
338     
339     txdata(app,verb,0);
340 #else
341     debugstr("Can't TX a packet with SFD and FIFOP definitions.");
342     txdata(app,NOK,0);
343 #endif
344     break;
345   default:
346     debugstr("Not yet supported in CCSPI");
347     txdata(app,verb,0);
348     break;
349   }
350
351 }