ab1051fdd34a71dca86d39e7205acccb07c2006c
[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
50 #define RADIOACTIVE SETCE
51 #define RADIOPASSIVE CLRCE
52
53 //! Set up the pins for CCSPI mode.
54 void ccspisetup(){
55   SETSS;
56   P5DIR&=~MISO;
57   P5DIR|=MOSI+SCK;
58   DIRSS;
59   DIRCE;
60   
61   //Begin a new transaction.
62   CLRSS; 
63   SETSS;
64 }
65
66 //! Read and write an CCSPI byte.
67 u8 ccspitrans8(u8 byte){
68   register unsigned int bit;
69   //This function came from the CCSPI Wikipedia article.
70   //Minor alterations.
71   
72   for (bit = 0; bit < 8; bit++) {
73     /* write MOSI on trailing edge of previous clock */
74     if (byte & 0x80)
75       SETMOSI;
76     else
77       CLRMOSI;
78     byte <<= 1;
79  
80     SETCLK;
81   
82     /* read MISO on trailing edge */
83     byte |= READMISO;
84     CLRCLK;
85   }
86   
87   return byte;
88 }
89
90
91 //! Writes a register
92 u8 ccspi_regwrite(u8 reg, const u8 *buf, int len){
93   CLRSS;
94   
95   reg=ccspitrans8(reg);
96   while(len--)
97     ccspitrans8(*buf++);
98   
99   SETSS;
100   return reg;//status
101 }
102 //! Reads a register
103 u8 ccspi_regread(u8 reg, u8 *buf, int len){
104   CLRSS;
105   
106   reg=ccspitrans8(reg);
107   while(len--)
108     *buf++=ccspitrans8(0);
109   
110   SETSS;
111   return reg;//status
112 }
113
114 //! Handles a Chipcon SPI command.
115 void ccspi_handle_fn( uint8_t const app,
116                                           uint8_t const verb,
117                                           uint32_t const len)
118 {
119   unsigned long i;
120   
121   //Drop CE to passify radio.
122   RADIOPASSIVE;
123   //Raise !SS to end transaction, just in case we forgot.
124   SETSS;
125   ccspisetup();
126   
127   switch(verb){
128     //PEEK and POKE might come later.
129   case READ:  
130   case WRITE:
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
138   case PEEK://Grab CCSPI Register
139     CLRSS; //Drop !SS to begin transaction.
140     ccspitrans8(CCSPI_R_REGISTER | cmddata[0]); //000A AAAA
141     for(i=1;i<len;i++)
142       cmddata[i]=ccspitrans8(cmddata[i]);
143     SETSS;  //Raise !SS to end transaction.
144     txdata(app,verb,len);
145     break;
146     
147   case POKE://Poke CCSPI Register
148     CLRSS; //Drop !SS to begin transaction.
149     ccspitrans8(CCSPI_W_REGISTER | cmddata[0]); //001A AAAA
150     for(i=1;i<len;i++)
151       cmddata[i]=ccspitrans8(cmddata[i]);
152     SETSS;  //Raise !SS to end transaction.
153     txdata(app,verb,len);
154     break;
155   case SETUP:
156     ccspisetup();
157     txdata(app,verb,0);
158     break;
159   case CCSPI_RX:
160     RADIOPASSIVE;
161     //Get the packet.
162     CLRSS;
163     ccspitrans8(CCSPI_RXFIFO);
164     for(i=0;i<32;i++)
165       cmddata[i]=ccspitrans8(0xde);
166     SETSS;
167     //no break
168     txdata(app,verb,32);
169     break;
170   case CCSPI_RX_FLUSH:
171     //Flush the buffer.
172     CLRSS;
173     ccspitrans8(CCSPI_SFLUSHRX);
174     SETSS;
175     
176     //Return the packet.
177     txdata(app,verb,32);
178     break;
179   case CCSPI_TX:
180   case CCSPI_TX_FLUSH:
181   default:
182     debugstr("Not yet supported.");
183     txdata(app,verb,0);
184     break;
185   }
186   
187
188   SETSS;//End session
189   RADIOACTIVE;
190 }