blob: c4d775217e4e8453715137ed0440b94e60eb55d2 [file] [log] [blame]
adamdunkels573bc292003-10-01 08:04:03 +00001/**
2 * \file
3 * Device driver and packet framing for the RFM-TR1001 radio module.
4 * \author FU Berlin (original implementation)
5 * \author Adam Dunkels <adam@sics.se>
6 *
7 * This file implements a device driver for the RFM-TR1001 radio
8 * tranciever as well as a simple packet framing format, simimilar to
9 * PPP (AHDLC) framing.
10 *
adamdunkels3845cd72003-11-27 15:59:00 +000011 * \note A lot of the stuff in this file is currently a "hack" form
12 * (particularly the "MAC" stuff and the ackowledgements)!
adamdunkels573bc292003-10-01 08:04:03 +000013 */
14
15#include "tr1001.h"
16#include "uip.h"
adamdunkels3845cd72003-11-27 15:59:00 +000017#include "uip-fw.h"
adamdunkels573bc292003-10-01 08:04:03 +000018
19#include "sensors.h"
20
21#include <io.h>
22#include <signal.h>
23
24
25#define RXSTATE_READY 0 /**< \internal Receive state: ready for a
26 new packet. */
27#define RXSTATE_START1 1 /**< \internal Receive state: first start
28 byte read, waiting for second. */
29#define RXSTATE_START2 2 /**< \internal Receive state: second start
30 byte read, waiting for header. */
31#define RXSTATE_RAWHEADER 3 /**< \internal Receive state: reading raw
32 packet header, without encoding. */
33#define RXSTATE_HEADER1 4 /**< \internal Receive state: reading
34 packet header, non-negative byte. */
35#define RXSTATE_HEADER2 5 /**< \internal Receive state: reading
36 packet header, negative byte. */
37#define RXSTATE_RAWDATA 6 /**< \internal Receive state: reading raw
38 packet data, without encoding. */
39#define RXSTATE_DATA1 7 /**< \internal Receive state: reading
40 packet data, non-negative byte. */
41#define RXSTATE_DATA2 8 /**< \internal Receive state: reading
42 packet data, negative byte. */
43#define RXSTATE_ERROR 9 /**< \internal Receive state: error in
44 packet reception. */
45#define RXSTATE_FULL 10 /**< \internal Receive state: a full packet
46 has been received. */
47
48#define NEG(b) (0xff - b) /**< \internal Logical negation of an 8-bit
49 quantity. */
50
51/**
52 * \internal
53 * The buffer which holds incoming data.
54 */
55#define RXBUFSIZE UIP_BUFSIZE
56static unsigned char rxbuf[RXBUFSIZE];
57
58/**
59 * \internal
60 * A pointer into the rxbuf buffer which points to the next available byte.
61 */
62static unsigned short rxpos;
63
64/**
65 * \internal
66 * The length of the packet that currently is being received.
67 */
68static unsigned short rxlen;
69
70/**
71 * \internal
72 * The reception state.
73 */
74static unsigned char rxstate = RXSTATE_READY;
75
76
77/**
78 * \internal
79 * The structure of the packet header.
80 */
81struct tr1001_hdr {
adamdunkels573bc292003-10-01 08:04:03 +000082 u8_t type; /**< The packet type. */
adamdunkels3845cd72003-11-27 15:59:00 +000083 u8_t id; /**< A packet identifier. */
adamdunkels573bc292003-10-01 08:04:03 +000084 u8_t len[2]; /**< The 16-bit length of the packet in network byte
85 order. */
86};
87
88/**
adamdunkels3845cd72003-11-27 15:59:00 +000089 * \internal The length of the packet header.
90 */
91#define TR1001_HDRLEN 4
92
93/**
94 * \internal
95 * The "data" packet type.
96 */
97#define TR1001_TYPE_DATA 1
98
99/**
100 * \internal
101 * The "acknowledgement" packet type.
102 */
103#define TR1001_TYPE_ACK 2
104
105/**
106 * \internal
107 * Determines if the negencoding should be used or not. This
adamdunkels573bc292003-10-01 08:04:03 +0000108 * causes each byte which is sent out to be sent twice, first normally
109 * and second with all bits inverted. */
110#define TR1001_CONF_NEGENCODING 1
111
adamdunkels3845cd72003-11-27 15:59:00 +0000112/**
113 * \internal
114 * The incremental packet identifier.
115 */
116static u8_t packet_id;
117
adamdunkels573bc292003-10-01 08:04:03 +0000118/*------------------------------------------------------------------------------*/
119/**
120 * \internal
121 * Turn on data transmission in On-Off-Keyed mode.
122 */
123/*------------------------------------------------------------------------------*/
124static void
125txook(void)
126{
127 P3SEL = 0xf0;
128 P5OUT |= 0x40;
129 P5OUT &= 0x7f;
130}
131/*------------------------------------------------------------------------------*/
132/**
133 * \internal
134 * Turn on data reception for the radio tranceiver.
135 */
136/*------------------------------------------------------------------------------*/
137static void
138rxon(void)
139{
140 P3SEL = 0xe0;
141 P5OUT |= 0xc0;
142}
143/*------------------------------------------------------------------------------*/
144/**
145 * \internal
146 * Clear the recevie buffer and reset the receiver state.
147 */
148/*------------------------------------------------------------------------------*/
149static void
150rxclear(void)
151{
152 rxpos = 0;
153 rxstate = RXSTATE_READY;
154}
155/*------------------------------------------------------------------------------*/
156/**
157 * \internal
158 * Send a byte of data over the radio.
159 *
160 * \param b The byte to be sent.
161 */
162/*------------------------------------------------------------------------------*/
163static void
164send(unsigned char b)
165{
166 /* Wait until the USART0 TX buffer is ready. */
167 while((IFG1 & UTXIFG0) == 0);
168
169 /* Send the byte. */
170 TXBUF0 = b;
171}
172/*------------------------------------------------------------------------------*/
173/**
174 * \internal
175 * Send a byte of data and its logical negation (all bits inverted)
176 * over the radio.
177 *
178 * \param b The byte to be sent.
179 */
180/*------------------------------------------------------------------------------*/
181static void
182send2(unsigned char b)
183{
184 send(b);
185#if TR1001_CONF_NEGENCODING
186 send(NEG(b));
187#endif /* TR1001_CONF_NEGENCODING */
188}
189/*------------------------------------------------------------------------------*/
190/**
191 * Set the transmission power of the tranciever.
192 *
193 * The sensor board is equipped with a DS1804 100 position trimmer
194 * potentiometer which is used to set the transmission input current
195 * to the radio tranciever chip, thus setting the transmission power
196 * of the radio tranciever.
197 *
198 * This function sets the trimmer potentiometer to a value between 1
199 * and 100.
200 *
201 * \param p The power of the tranciever, between 1 (lowest) and 100
202 * (highest).
203 */
204/*------------------------------------------------------------------------------*/
205void
206tr1001_set_txpower(unsigned char p)
207{
208 int i;
209
210 /* Clamp maximum power. */
211 if(p > 100) {
212 p = 100;
213 }
214
215 /* First, run the potentiometer down to zero so that we know the
216 start value of the potentiometer. */
217 P2OUT &= 0xDF; /* P25 = 0 (down selected) */
218 P2OUT &= 0xBF; /* P26 = 0 (chipselect on) */
219 for(i = 0; i < 102; ++i) {
220 P2OUT &= 0xEF; /* P24 = 0 (inc) */
221 P2OUT |= 0x10;
222 }
223
224 /* Now, start to increase the value of the potentiometer until it
225 reaches the desired value.*/
226
227 P2OUT |= 0x20; /* P25 = 1 (up selected) */
228 for(i = 0; i < p; ++i) {
229 P2OUT &= 0xEF; /* P24 = 0 (inc) */
230 P2OUT |= 0x10;
231 }
232 P2OUT |= 0x40; /* P26 = 1 (chipselect off) */
233}
234/*------------------------------------------------------------------------------*/
235/**
236 * Initialize the radio tranciever.
237 *
238 * Turns on reception of bytes and installs the receive interrupt
239 * handler.
240 */
241/*------------------------------------------------------------------------------*/
242void
243tr1001_init(void)
244{
245 /* Turn on reception. */
246 rxon();
247
248 /* Reset reception state. */
249 rxclear();
250
251
252 UCTL0 = CHAR; /* 8-bit character */
253 UTCTL0 = SSEL1; /* UCLK = SMCLK */
254
255#define TR1001_SPEED 19200
256
257 if(TR1001_SPEED == 19200) {
258 /* Set TR1001 to 19200 */
259 UBR00 = 0x80; /* 2,457MHz/19200 = 128 -> 0x80 */
260 UBR10 = 0x00; /* */
261 UMCTL0 = 0x00; /* no modulation */
262 } else if(TR1001_SPEED == 38400) {
263 /* Set TR1001 to 38400 */
264 UBR00 = 0x40; /* 2,457MHz/38400 = 64 -> 0x40 */
265 UBR10 = 0x00; /* */
266 UMCTL0 = 0x00; /* no modulation */
267 } else if(TR1001_SPEED == 57600) {
268 UBR00 = 0x2a; /* 2,457MHz/57600 = 42.7 -> 0x2A */
269 UBR10 = 0x00; /* */
270 UMCTL0 = 0x5b; /* */
271 } else if(TR1001_SPEED == 115200) {
272 UBR00 = 0x15; /* 2,457MHz/115200 = 21.4 -> 0x15 */
273 UBR10 = 0x00; /* */
274 UMCTL0 = 0x4a; /* */
275 }
276
277#if 0
278 /* 19200 bps */
279 UBR00 = 0x80; /* 2,457MHz/19200 = 128 -> 0x80 */
280 UBR10 = 0x00; /* */
281 UMCTL0 = 0x00; /* no modulation */
282#endif /* 0 */
283
284 ME1 |= UTXE0 + URXE0; /* Enable USART0 TXD/RXD */
285
286 /* Turn on receive interrupt. */
287 IE1 |= URXIE0;
288}
289/*------------------------------------------------------------------------------*/
290/**
291 * Check if an incoming packet has been received.
292 *
293 * This function checks the receive buffer to see if an entire packet
294 * has been received. The actual reception is handled by an interrupt
295 * handler.
296 *
297 * \return The length of the received packet, or 0 if no packet has
298 * been received.
299 */
300/*------------------------------------------------------------------------------*/
301unsigned short
302tr1001_poll(void)
303{
304 unsigned short tmplen;
305
306 if(rxstate == RXSTATE_FULL) {
307 if(rxlen > UIP_BUFSIZE - UIP_LLH_LEN) {
308 rxlen = UIP_BUFSIZE - UIP_LLH_LEN;
309 }
adamdunkels3845cd72003-11-27 15:59:00 +0000310 memcpy(&uip_buf[UIP_LLH_LEN], rxbuf + TR1001_HDRLEN, rxlen);
adamdunkels573bc292003-10-01 08:04:03 +0000311 tmplen = rxlen;
312 rxclear();
313 return tmplen;
314 }
315
316 if(rxstate == RXSTATE_ERROR) {
317 blink();
318 rxclear();
319 }
320
321 return 0;
322}
323/*------------------------------------------------------------------------------*/
324/**
325 * \internal
326 * Interrupt handler for the data reception.
327 */
328/*------------------------------------------------------------------------------*/
329interrupt (UART0RX_VECTOR)
330 tr1001_rxhandler(void)
331{
332 unsigned char c;
333
334 c = RXBUF0;
335
336 switch(rxstate) {
337 case RXSTATE_ERROR:
338 /* Do nothing, wait until error has been hendled. */
339 break;
340 case RXSTATE_READY:
341 if(c == 0xff) {
342 rxstate = RXSTATE_START1;
343 }
344 break;
345 case RXSTATE_START1:
346 if(c == 0x01) {
347 rxstate = RXSTATE_START2;
348 } else {
349 rxstate = RXSTATE_READY;
350 }
351 break;
352 case RXSTATE_START2:
353 if(c == 0x7f) {
354#if TR1001_CONF_NEGENCODING
355 rxstate = RXSTATE_HEADER1;
356#else /* TR1001_CONF_NEGENCODING */
357 rxstate = RXSTATE_RAWHEADER;
358#endif /* TR1001_CONF_NEGENCODING */
359 } else {
360 rxstate = RXSTATE_READY;
361 }
362 break;
363 case RXSTATE_RAWHEADER:
364 rxbuf[rxpos] = c;
365 ++rxpos;
adamdunkels3845cd72003-11-27 15:59:00 +0000366 if(rxpos == TR1001_HDRLEN) {
adamdunkels573bc292003-10-01 08:04:03 +0000367 rxlen = ((((struct tr1001_hdr *)rxbuf)->len[0] << 8) +
368 ((struct tr1001_hdr *)rxbuf)->len[1]);
369 rxstate = RXSTATE_RAWDATA;
370 }
371 break;
372 case RXSTATE_HEADER1:
373 /* Receive a data byte of the header. */
374 rxbuf[rxpos] = c;
375 rxstate = RXSTATE_HEADER2;
376 break;
377 case RXSTATE_HEADER2:
378 /* We should have received the bit-wise negation of the previously
379 received byte, or else something has gone wrong and we set the
380 error flag. */
381 if(NEG(c) == rxbuf[rxpos]) {
382 ++rxpos;
adamdunkels3845cd72003-11-27 15:59:00 +0000383 if(rxpos == TR1001_HDRLEN) {
adamdunkels573bc292003-10-01 08:04:03 +0000384 rxlen = ((((struct tr1001_hdr *)rxbuf)->len[0] << 8) +
385 ((struct tr1001_hdr *)rxbuf)->len[1]);
386 rxstate = RXSTATE_DATA1;
387 } else {
388 rxstate = RXSTATE_HEADER1;
389 }
390 } else {
391 rxstate = RXSTATE_ERROR;
392 }
393 break;
394 case RXSTATE_DATA1:
395 /* Receive a data byte. */
396 rxbuf[rxpos] = c;
397 rxstate = RXSTATE_DATA2;
398 break;
399 case RXSTATE_DATA2:
400 /* We should have received the bit-wise negation of the previously
401 received byte, or else something has gone wrong and we set the
402 error flag. */
403 if(NEG(c) == rxbuf[rxpos]) {
404 ++rxpos;
adamdunkels3845cd72003-11-27 15:59:00 +0000405 if(rxpos == rxlen + TR1001_HDRLEN) {
adamdunkels573bc292003-10-01 08:04:03 +0000406 rxstate = RXSTATE_FULL;
407 } else if(rxpos > sizeof(rxbuf)) {
408 rxstate = RXSTATE_ERROR;
409 } else {
410 rxstate = RXSTATE_DATA1;
411 }
412 } else {
413 rxstate = RXSTATE_ERROR;
414 }
415 break;
416 case RXSTATE_RAWDATA:
417 rxbuf[rxpos] = c;
418 ++rxpos;
adamdunkels3845cd72003-11-27 15:59:00 +0000419 if(rxpos == rxlen + TR1001_HDRLEN) {
adamdunkels573bc292003-10-01 08:04:03 +0000420 rxstate = RXSTATE_FULL;
421 } else if(rxpos > sizeof(rxbuf)) {
422 rxstate = RXSTATE_ERROR;
423 }
424 break;
425 case RXSTATE_FULL:
426 /* Just drop the incoming byte. */
427 break;
428 default:
429 /* Just drop the incoming byte. */
430 rxstate = RXSTATE_READY;
431 break;
432 }
433}
434/*------------------------------------------------------------------------------*/
435/**
436 * \internal
437 *
438 * A stupid function which causes a small delay based on its argument.
439 *
440 * It is a hack, not intended for "real" use.
441 *
442 */
443/*------------------------------------------------------------------------------*/
444static void
445delay_hack(int d)
446{
447 int i, j = 2;
448
449 for(i = 0; i < d; ++i) {
450 j = j * j;
451 }
452}
453/*------------------------------------------------------------------------------*/
454/**
adamdunkels3845cd72003-11-27 15:59:00 +0000455 * \internal
adamdunkels573bc292003-10-01 08:04:03 +0000456 *
adamdunkels3845cd72003-11-27 15:59:00 +0000457 * Prepare a transmission.
458 *
459 * This function does the necessary setup before a packet can be sent
460 * out.
adamdunkels573bc292003-10-01 08:04:03 +0000461 */
462/*------------------------------------------------------------------------------*/
adamdunkels3845cd72003-11-27 15:59:00 +0000463static void
464prepare_transmission(void)
adamdunkels573bc292003-10-01 08:04:03 +0000465{
466 unsigned short i, laststate;
adamdunkels3845cd72003-11-27 15:59:00 +0000467
adamdunkels573bc292003-10-01 08:04:03 +0000468 /* Delay the transmission for a while. The length of the delay is
469 based on the lowest bits of the battery sensor, which seems to be
470 jumping up and down somewhat unpredictably (but I might very well
471 be wrong). */
adamdunkels3845cd72003-11-27 15:59:00 +0000472 /* P2OUT &= 0xFE;*/
adamdunkels573bc292003-10-01 08:04:03 +0000473 delay_hack(400 * (sensors_battery & 0x0f));
adamdunkels3845cd72003-11-27 15:59:00 +0000474 /* P2OUT |= 0x01; */
adamdunkels573bc292003-10-01 08:04:03 +0000475
476 /* First check that we don't currently are receiveing a packet, and
477 if so we wait until the reception has been completed. Reception
478 is done with interrupts so it is OK for us to wait in a while()
479 loop. */
480 i = 0;
481 laststate = rxstate;
482 while(rxstate != RXSTATE_READY &&
483 rxstate != RXSTATE_FULL &&
484 rxstate != RXSTATE_ERROR) {
485
486 /* Make sure that we don't stay too long in the same rxstate
487 (which would indicate that the receiving interrupt somehow has
488 locked up). */
489 if(laststate == rxstate) {
490 ++i;
491 if(i == 0xffff) {
492 rxstate = RXSTATE_ERROR;
493 break;
494 }
495 } else {
496 i = 0;
497 }
498 laststate = rxstate;
499 }
500
adamdunkels573bc292003-10-01 08:04:03 +0000501 /* Turn on OOK mode with transmission. */
502 txook();
503
504 /* Delay for a while to let the transmitted settle in its new
505 state. */
506 delay_hack(400);
507
adamdunkels3845cd72003-11-27 15:59:00 +0000508}
509/*------------------------------------------------------------------------------*/
510/**
511 * Send a packet and wait for an acknowledgement.
512 *
513 * This function calls tr1001_send() to send out a packet, and waits
514 * for an acknowledgement from the receiver.
515 *
516 */
517/*------------------------------------------------------------------------------*/
518u8_t
519tr1001_send_acked(void)
520{
521 unsigned short tmplen, count;
522 struct tr1001_hdr *ackhdr = (struct tr1001_hdr *)rxbuf;
523 ek_clock_t start;
524
525
526 tr1001_send();
527
528 start = ek_clock();
529 count = 0;
530 P2OUT &= 0xFB;
531 /* Block while checking if a packet has arrived. */
532 while((volatile u8_t)rxstate != RXSTATE_FULL &&
533 (volatile u8_t)rxstate != RXSTATE_ERROR) {
534 /* Wait no more than one second. */
535 if((ek_clock_t)(ek_clock() - start) > (ek_clock_t)CLK_TCK) {
536 break;
537 }
538 }
539 P2OUT |= 0x04;
540
541
542 if(rxstate == RXSTATE_FULL) {
543 if(ackhdr->type == TR1001_TYPE_ACK &&
544 ackhdr->id == packet_id) {
545 beep();
546 rxclear();
547 return UIP_FW_OK;
548 }
549 }
550
551 if(rxstate == RXSTATE_ERROR) {
552 rxclear();
553 blink();
554 }
555 return UIP_FW_DROPPED;
556}
557/*------------------------------------------------------------------------------*/
558/**
559 * Send out a packet from the uip_buf buffer.
560 *
561 * This function causes a packet to be sent out after a small random
562 * delay, but without doing any MAC layer collision detection or
563 * back-offs. The packet is sent with a 4 byte header that contains a
564 * a "type" identifier, an 8-bit packet ID field and the length of the
565 * packet in network byte order.
566 */
567/*------------------------------------------------------------------------------*/
568u8_t
569tr1001_send(void)
570{
571 u8_t *hdr;
572 u16_t hdrlen;
573 u8_t *data;
574 u16_t datalen;
575 int i;
576
577 hdr = &uip_buf[UIP_LLH_LEN];
578 hdrlen = UIP_TCPIP_HLEN;
579 data = uip_appdata;
580 if(uip_len < UIP_TCPIP_HLEN) {
581 datalen = 0;
582 } else {
583 datalen = uip_len - UIP_TCPIP_HLEN;
584 }
585
586 /* Prepare the transmission. */
587 prepare_transmission();
588
adamdunkels573bc292003-10-01 08:04:03 +0000589 /* Send first preamble byte. */
590 send(0xaa);
591
592 /* Send second preamble byte. */
593 send(0xaa);
594
595 /* Send sync byte. */
596 send(0x0ff);
597
598 /* Send first start byte. */
599 send(0x01);
600
601 /* Send second start byte. */
602 send(0x07f);
603
604 /* Send packet header. */
adamdunkels3845cd72003-11-27 15:59:00 +0000605 send2(TR1001_TYPE_DATA);
606 send2(++packet_id);
adamdunkels573bc292003-10-01 08:04:03 +0000607 send2(uip_len >> 8);
608 send2(uip_len & 0xff);
609
610 /* Send packet data. */
adamdunkels3845cd72003-11-27 15:59:00 +0000611 for(i = 0; i < hdrlen; ++i) {
612 send2(hdr[i]);
613 }
614 for(i = 0;i < datalen; ++i) {
615 send2(data[i]);
adamdunkels573bc292003-10-01 08:04:03 +0000616 }
617
618 /* Send trailing bytes. */
619 send(0xaa);
620 send(0xaa);
621
622 /* Turn on reception again. */
623 rxon();
624
adamdunkels3845cd72003-11-27 15:59:00 +0000625 return UIP_FW_OK;
626}
627/*------------------------------------------------------------------------------*/
628/**
629 * Acknowledge a received packet.
630 *
631 * This function sends out an acknowledgement packet for the
632 * previously received packet, which must be present in the uip_buf
633 * buffer.
634 *
635 * \retval UIP_FW_OK The acknowledgement was successfully.
636 * \retval UIP_FW_DROPPED The acknowledgement was dropped before transmission.
637 */
638/*------------------------------------------------------------------------------*/
639u8_t
640tr1001_ack(void)
641{
642 /* Prepare the transmission. */
643 prepare_transmission();
644
645 /* Send first preamble byte. */
646 send(0xaa);
647
648 /* Send second preamble byte. */
649 send(0xaa);
650
651 /* Send sync byte. */
652 send(0x0ff);
653
654 /* Send first start byte. */
655 send(0x01);
656
657 /* Send second start byte. */
658 send(0x07f);
659
660 /* Send packet header. */
661 send2(TR1001_TYPE_ACK);
662 send2(((struct tr1001_hdr *)uip_buf)->id);
663 send2(0);
664 send2(0);
665
666 /* Send trailing bytes. */
667 send(0xaa);
668 send(0xaa);
669
670 /* Turn on reception again. */
671 rxon();
672
673 /* beep();*/
674
675 return UIP_FW_OK;
676
adamdunkels573bc292003-10-01 08:04:03 +0000677}
678/*------------------------------------------------------------------------------*/