83dfa37b4ca42d6e4a5b1ae16e7adc78a5228e8c
[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
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     debugstr("Beta implementation.");
192     cmddata[0] = 1;
193     txdata(app,verb,cmddata[0]+1);
194
195     while(1) {
196         //Wait until a packet is received
197         while(!SFD);
198         //Turn on LED 2 (green) as signal
199             PLED2DIR |= PLED2PIN;
200             PLED2OUT &= ~PLED2PIN;
201
202         //Switch the radio to TX mode
203         CLRSS;  //Drop !SS to begin transaction.
204         ccspitrans8(0x04);
205         SETSS;  //Raise !SS to end transaction.
206         //txdata(app,verb,len);
207
208         //Load the packet.
209         CLRSS;
210         ccspitrans8(CCSPI_TXFIFO);
211         char pkt[15] = {0x0f, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef, 0xba, 0xbe, 0xc0};
212         for(i=0;i<pkt[0];i++)
213           ccspitrans8(pkt[i]);
214         SETSS;
215         debugstr("Packet loaded for tx.");
216         //Transmit the packet.
217         CLRSS;
218         ccspitrans8(0x04); //STXON
219         SETSS;
220         //Wait for the pulse on SFD, after which the packet has been sent.
221         //while(!SFD);
222         //while(SFD);
223         msdelay(300);
224         //Flush TX buffer.
225         CLRSS;
226         ccspitrans8(0x09); //SFLUSHTX
227         SETSS;
228
229         //while(SFD);
230         //msdelay(200);
231         //Turn off LED 2 (green) as signal
232             PLED2DIR |= PLED2PIN;
233             PLED2OUT |= PLED2PIN;
234     }
235     //TODO the firmware stops staying in this mode after a while, and stops jamming... need to find a fix!
236     break;
237
238   case CCSPI_TX_FLUSH:
239     //Flush the buffer.
240     CLRSS;
241     ccspitrans8(CCSPI_SFLUSHTX);
242     SETSS;
243     
244     txdata(app,verb,0);
245     break;
246   case CCSPI_TX:
247 #ifdef FIFOP
248     
249     //Wait for last packet to TX.
250     //while(ccspi_status()&BIT3);
251     
252     //Load the packet.
253     CLRSS;
254     ccspitrans8(CCSPI_TXFIFO);
255     for(i=0;i<cmddata[0];i++)
256       ccspitrans8(cmddata[i]);
257     SETSS;
258     
259     //Transmit the packet.
260     CLRSS;
261     ccspitrans8(0x04); //STXON
262     SETSS;
263     
264     //Wait for the pulse on SFD, after which the packet has been sent.
265     while(!SFD);
266     while(SFD);
267     
268     //Flush TX buffer.
269     CLRSS;
270     ccspitrans8(0x09); //SFLUSHTX
271     SETSS;
272     
273     txdata(app,verb,0);
274 #else
275     debugstr("Can't TX a packet with SFD and FIFOP definitions.");
276     txdata(app,NOK,0);
277 #endif
278     break;
279   default:
280     debugstr("Not yet supported in CCSPI");
281     txdata(app,verb,0);
282     break;
283   }
284   
285
286 }