f47e54c9dc42a77cf5d31a8e56ad57f97c685ce3
[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       txdata(app,verb,cmddata[0]+2);
170     }else{
171       //No packet.
172       txdata(app,verb,0);
173     }
174 #else
175     debugstr("Can't RX a packet with SFD and FIFOP definitions.");
176     txdata(app,NOK,0);
177 #endif
178     break;
179   case CCSPI_RX_FLUSH:
180     //Flush the buffer.
181     CLRSS;
182     ccspitrans8(CCSPI_SFLUSHRX);
183     SETSS;
184     
185     txdata(app,verb,0);
186     break;
187   case CCSPI_REFLEX:
188     debugstr("Coming soon.");
189     txdata(app,verb,0);
190     break;
191   case CCSPI_TX_FLUSH:
192      //Flush the buffer.
193     CLRSS;
194     ccspitrans8(CCSPI_SFLUSHTX);
195     SETSS;
196     
197     txdata(app,verb,0);
198     break;
199   case CCSPI_TX:
200 #ifdef FIFOP
201     
202     /* //Has there been an overflow?
203     if(ccspi_status()&BIT5){
204       debugstr("Clearing underflow");
205       CLRSS;
206       ccspitrans8(0x09); //SFLUSHTX
207       SETSS;
208     } 
209     */
210     
211         
212     //Wait for last packet to TX.
213     //while(ccspi_status()&BIT3);
214     
215     //Load the packet.
216     CLRSS;
217     ccspitrans8(CCSPI_TXFIFO);
218     for(i=0;i<cmddata[0];i++)
219       ccspitrans8(cmddata[i]);
220     SETSS;
221     
222     //Transmit the packet.
223     CLRSS;
224     ccspitrans8(0x04); //STXON
225     SETSS;
226     
227     
228     txdata(app,verb,0);
229 #else
230     debugstr("Can't TX a packet with SFD and FIFOP definitions.");
231     txdata(app,NOK,0);
232 #endif
233     break;
234   default:
235     debugstr("Not yet supported in CCSPI");
236     txdata(app,verb,0);
237     break;
238   }
239   
240
241 }