1 /*! \file atmel_radio.c
2 \author bx forked from neighbor Travis Goodspeed
3 \brief Atmel Radio Register Interface
7 //Higher level left to client application.
12 #include "atmel_radio.h"
17 //! Handles a Chipcon SPI command.
18 void atmel_radio_handle_fn( uint8_t const app,
20 uint32_t const datalen32);
22 // define the atmel_radio app's app_t
23 app_t const atmel_radio_app = {
29 atmel_radio_handle_fn,
35 "\tThe ATMEL_RADIO app adds support for the atmel radio.\n"
38 #define TRX_REGISTER_BASEADDR 0x140
39 inline void reg_write(u16 addr, u8 val)
41 *(u8*)(TRX_REGISTER_BASEADDR + addr) = val;
44 inline u8 reg_read(u16 addr)
46 return *(u8*)(TRX_REGISTER_BASEADDR + addr);
49 inline void reg_bit_write(u16 addr, u8 pos, u8 value)
53 old = reg_read(addr) & ~mask; //bits to keep
54 old = old | (value << pos); //bit to add
55 reg_write(addr, old); //write byte
58 void atmel_radio_clear_frame_buffer() {
59 TRXFBST = 0; //reset the frame buffer pointer to signal it was read (resets the PHR - length value)
63 u16 atmel_radio_set_state(u8 state) //based on zigduino-radio, radio_rfa.c
66 /* ensure not in state transition */
67 while (STATE_TRANSITION_IN_PROGRESS == (STATE_TRANSITION_IN_PROGRESS &TRX_STATE)) {}
90 retries = 180; // enough to receive ongoing frame
92 if (state == (state & TRX_STATUS)) {
98 if (state != (state & TRX_STATUS)) {
99 return (state & TRX_STATUS);
105 u16 atmel_radiosetup(){
107 /* initialize transceiver
108 code based on zigduino-radio
111 TRXPR &= ~(1 << TRXRST);
113 //TRX_SLPTR_LOW. Make sure radio isn't sleeping
114 TRXPR &= ~(1 << SLPTR);
118 TRXPR |= (1 << TRXRST);
120 /* disable IRQ and clear any pending IRQs */
123 /* clear IRQ history by reading status*/
126 atmel_radio_set_state(TRX_OFF);
128 /* setup options for extended operating sniffing mode */
131 CSMA_SEED_1 &= 0xEF & ~(1 << AACK_DIS_ACK);
133 // disable filtering of reserved frame types and reserve frame type processing
134 XAH_CTRL_1 &= 0xDF & ~(1 << AACK_FLTR_RES_FT);
135 XAH_CTRL_1 &= 0xEF & ~(1 << AACK_UPLD_RES_FT);
137 // enable promiscuous mode
138 XAH_CTRL_1 |= 1 << AACK_PROM_MODE;
141 // disable frame protection
142 TRX_CTRL_2 &= 0x7F & ~(1 << RX_SAFE_MODE);
145 TRX_CTRL_1 &= 0xDF & ~(1 << TX_AUTO_CRC_ON);
148 atmel_radio_clear_frame_buffer();
150 // extended operation mode disabled by default
154 /* enter RX_ON state */
155 return atmel_radio_set_state(RX_ON);
160 void atmel_radio_pokebyte(u16 addr, u8 data) {
161 reg_write(addr, data);
164 u8 atmel_radio_peekbyte(u16 addr) {
165 return reg_read(addr);
168 //! Writes bytes into the Atmel's ram
169 void atmel_radio_pokeram(u16 addr, u8 *data, u16 len){
171 for (i = 0; i < len; i++ ) {
172 atmel_radio_pokebyte(addr+i, data[i]);
176 //! Read bytes from the Atmel's RAM.
177 void atmel_radio_peekram(u16 addr, u8 *data, u16 len){
180 for (i = 0; i < len; i++){
181 *data++=atmel_radio_peekbyte(addr+i);
185 int atmel_radio_is_frame_buffer_empty() {
190 void atmel_radio_handle_fn( uint8_t const app,
192 uint32_t const datalen32){
195 // cmddataword -> int
196 // cmddatalong -> long
204 readlen16 = cmddataword[1]; // Backup length. Second byte
205 atmel_radio_peekram(cmddataword[0], // First word is address
206 cmddata, // Return in same buffer
207 readlen16); // length
208 txdata(app,verb,readlen16);
212 atmel_radio_pokeram(cmddataword[0], // First word is address
213 cmddata+2, // Remainder of buffer is data
214 (u16) datalen32-2); //Length implied by packet length
215 txdata(app,verb, datalen32-2); //return number of poked bytes
218 ret = atmel_radiosetup();
219 txdata(app, verb, ret);
223 // ensure radio is not in the middle or receiving a packet
224 atmel_radio_set_state(RX_ON);
225 // set state to PLL_ON so frame buffer isn't clobbered
226 atmel_radio_set_state(PLL_ON);
228 if (!atmel_radio_is_frame_buffer_empty()) { //only if we recieved something new
229 framelen8 = TST_RX_LENGTH; //register contains frame length
230 if ((framelen8 > 127) ) { //frame too big
233 memcpy(cmddata, (void *) &TRXFBST, framelen8); //return in same buffer
234 atmel_radio_clear_frame_buffer();
236 framelen8 = 0; //didn't receive anything new
238 // receive packets again
239 atmel_radio_set_state(RX_ON);
241 txdata(app, verb, framelen8);
244 //prevent radio from recieving new packets
245 atmel_radio_set_state(PLL_ON);
246 uint8_t maxlen = 127;
247 if (cmddata[0] > maxlen) { //truncate too long packets
251 memcpy((void *) &TRXFBST, cmddata, datalen32); //copy length + packet
252 atmel_radio_set_state(BUSY_TX); //send packet
255 while (PLL_ON != (PLL_ON & TRX_STATUS)) {} //wait for TX done
256 //reset the frame buffer pointer to signal it was read
257 atmel_radio_clear_frame_buffer();
258 atmel_radio_set_state(RX_ON);
259 txdata(app, verb, 0);
262 case ATMEL_RADIO_AACK_ON:
265 /* enter PLL_ON state */
266 atmel_radio_set_state(PLL_ON);
267 /* enter RX_ON state */
268 atmel_radio_set_state(RX_ON);
270 txdata(app, verb, 0);
272 case ATMEL_RADIO_AACK_OFF:
275 /* enter PLL_ON state */
276 atmel_radio_set_state(PLL_ON);
277 /* enter RX_ON state */
278 atmel_radio_set_state(RX_ON);
280 txdata(app, verb, 0);
282 case ATMEL_RADIO_AUTOCRC_ON:
283 if (0 == (TRX_CTRL_1 & (1 << TX_AUTO_CRC_ON))) { //not enabled
284 atmel_radio_set_state(TRX_OFF);
285 // can only be safely set in TRX_OFF mode
286 TRX_CTRL_1 |= 1 << TX_AUTO_CRC_ON;
287 atmel_radio_set_state(RX_ON);
290 txdata(app, verb, 0);
292 case ATMEL_RADIO_AUTOCRC_OFF:
293 if (TRX_CTRL_1 & (1 << TX_AUTO_CRC_ON)) { //enabled
294 atmel_radio_set_state(TRX_OFF);
295 // can only be safely set in TRX_OFF mode
296 TRX_CTRL_1 &= 0xDF & ~(1 << TX_AUTO_CRC_ON);
297 atmel_radio_set_state(RX_ON);
299 txdata(app, verb, 0);
302 debugstr("Not yet supported in ATMEL_RADIO");