turn ftdi driver into echo server
[goodfet] / firmware / apps / radios / cc2500.c
1 /*! \file ccspi.c
2   \author Jean-Michel Picod
3   \brief Chipcon SPI CC2500
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
17 #include "cc2500.h"
18 #include "spi.h"
19
20 #define CC2500_MEM_READ         0x80
21 #define CC2500_MEM_BURST        0x40
22 #define CC2500_MEM_WRITE        0x00
23
24 #define RADIO_TX   SETCE
25 #define RADIO_RX   CLRCE
26
27 //! Handles a Chipcon SPI command.
28 void cc2500_handle_fn( uint8_t const app,
29                       uint8_t const verb,
30                       uint32_t const len);
31
32 // define the ccspi app's app_t
33 app_t const cc2500_app = {
34
35         /* app number */
36         CC2500,
37
38         /* handle fn */
39         cc2500_handle_fn,
40
41         /* name */
42         "CC2500",
43
44         /* desc */
45         "\tThe CC2500 app adds support for the Chipcon SPI register\n"
46         "\tinterface for the CC2500 (and similar) chip.\n"
47 };
48
49 //! Set up the pins for CCSPI mode.
50 void cc2500setup(){
51   SPIDIR&=~MISO;
52   SPIDIR|=MOSI+SCK;
53   DIRSS;
54   DIRCE;
55
56   msdelay(100);
57
58   CLRCE;
59   SETCE;
60
61   //Begin a new transaction.
62   CLRSS;
63   SETSS;
64 }
65
66 //! Read and write an CCSPI byte.
67 u8 cc2500trans8(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 cc2500_regwrite(u8 reg, const u8 *buf, int len){
93   CLRSS;
94
95   if (len>1)
96     reg |= CC2500_MEM_BURST;
97   reg=cc2500trans8(reg|CC2500_MEM_READ);
98   while(len--)
99     cc2500trans8(*buf++);
100
101   SETSS;
102   return reg;//status
103 }
104 //! Reads a register
105 u8 cc2500_regread(u8 reg, u8 *buf, int len){
106   CLRSS;
107
108   if (len>1)
109     reg|=CC2500_MEM_BURST;
110   reg=cc2500trans8(reg|CC2500_MEM_WRITE);
111   while(len--)
112     *buf++=cc2500trans8(0);
113
114   SETSS;
115   return reg;//status
116 }
117
118 //! Handles a Chipcon SPI command.
119 void cc2500_handle_fn( uint8_t const app,
120                       uint8_t const verb,
121                       uint32_t const len){
122   unsigned long i, nbyte;
123
124   SETSS;
125   cc2500setup();
126
127   switch(verb){
128   case PEEK:
129   case READ:
130     cmddata[0]|=CC2500_MEM_READ; //Set the read bit.
131     //DO NOT BREAK HERE.
132   case WRITE:
133   case POKE:
134     if (len > 2)
135       cmddata[0] |= CC2500_MEM_BURST;
136     CLRSS; //Drop !SS to begin transaction.
137     for(i=0;i<len;i++)
138       cmddata[i]=cc2500trans8(cmddata[i]);
139     SETSS;  //Raise !SS to end transaction.
140     txdata(app,verb,len);
141     break;
142   case SETUP:
143     cc2500setup();
144     txdata(app,verb,0);
145     break;
146
147   case CC2500_REPEAT_RX:
148     while (1) {
149       cc2500_handle_fn(app, CC2500_RX, 0);
150     }
151     break;
152
153   case CC2500_RX:
154     debugstr("RX is not functionning right now");
155     txdata(app, verb, 0);
156     break;
157
158   case CC2500_TX:
159     RADIO_TX; // Set option power amplificator to TX
160     // FIXME: Flush FIFO first ?
161     // Fill FIFO
162     CLRSS;
163     cc2500trans8(CC2500_TXFIFO | CC2500_MEM_BURST); // TX FIFO Burst
164     for (i = 0; i < len; i++)
165       cc2500trans8(cmddata[i]);
166     SETSS; // Exit burst mode
167     CLRSS;
168     cc2500trans8(CC2500_STX); // Go to TX mode
169     SETSS;
170     txdata(app, verb, 0);
171     break;
172
173   case CC2500_RX_FLUSH:
174     //Flush the buffer.
175     CLRSS;
176     cc2500trans8(CC2500_SIDLE);
177     cc2500trans8(CC2500_SFLUSHRX);
178     SETSS;
179     txdata(app,verb,0);
180     break;
181
182   case CC2500_TX_FLUSH:
183     //Flush the buffer.
184     CLRSS;
185     cc2500trans8(CC2500_SIDLE);
186     cc2500trans8(CC2500_SFLUSHTX);
187     SETSS;
188     txdata(app,verb,0);
189     break;
190
191   default:
192     debugstr("Not yet supported in CC2500");
193     txdata(app,verb,0);
194     break;
195   }
196
197 }