Contiki 2.5
tr1001.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * @(#)$Id: tr1001.c,v 1.13 2010/03/02 22:40:39 nifi Exp $
32  */
33 /**
34  * \addtogroup esb
35  * @{
36  */
37 
38 /**
39  * \defgroup tr1001 TR1001 radio tranciever device driver
40  * @{
41  */
42 
43 /**
44  * \file
45  * Device driver and packet framing for the RFM-TR1001 radio module.
46  * \author Adam Dunkels <adam@sics.se>
47  *
48  * This file implements a device driver for the RFM-TR1001 radio
49  * tranciever.
50  *
51  */
52 
53 #include "contiki.h"
54 #include "contiki-esb.h"
55 
56 #include "dev/tr1001.h"
57 #include "dev/radio-sensor.h"
58 #include "lib/me.h"
59 #include "lib/crc16.h"
60 #include "net/netstack.h"
61 #include "net/rime/rimestats.h"
62 
63 #include <string.h>
64 
65 #ifdef TR1001_CONF_BEEP_ON_BAD_CRC
66 #define BEEP_ON_BAD_CRC TR1001_CONF_BEEP_ON_BAD_CRC
67 #else
68 #define BEEP_ON_BAD_CRC 1
69 #endif /* TR1001_CONF_BEEP_ON_BAD_CRC */
70 
71 #if BEEP_ON_BAD_CRC
72 #include "dev/beep.h"
73 #define BEEP_BEEP(t) beep_beep(t)
74 #else
75 #define BEEP_BEEP(t)
76 #endif /* BEEP_ON_BAD_CRC */
77 
78 #define RXSTATE_READY 0
79 #define RXSTATE_RECEIVING 1
80 #define RXSTATE_FULL 2
81 
82 #define SYNCH1 0x3c
83 #define SYNCH2 0x03
84 
85 #ifdef TR1001_CONF_BUFFER_SIZE
86 #define RXBUFSIZE TR1001_CONF_BUFFER_SIZE
87 #else
88 #define RXBUFSIZE PACKETBUF_SIZE
89 #endif /* TR1001_CONF_BUFFER_SIZE */
90 
91 /*
92  * Pending data to send when using prepare/transmit functions.
93  */
94 static const void *pending_data;
95 
96 /*
97  * The buffer which holds incoming data.
98  */
99 unsigned char tr1001_rxbuf[RXBUFSIZE];
100 
101 /*
102  * The length of the packet that currently is being received.
103  */
104 static unsigned short tr1001_rxlen = 0;
105 
106 /*
107  * The reception state.
108  */
109 volatile unsigned char tr1001_rxstate = RXSTATE_READY;
110 
111 static uint16_t rxcrc, rxcrctmp;
112 
113 /*
114  * The structure of the packet header.
115  */
116 struct tr1001_hdr {
117  uint8_t len[2]; /**< The 16-bit length of the packet in network byte
118  order. */
119 };
120 
121 /*
122  * The length of the packet header.
123  */
124 #define TR1001_HDRLEN sizeof(struct tr1001_hdr)
125 
126 #define OFF 0
127 #define ON 1
128 static uint8_t onoroff = OFF;
129 
130 #define NUM_SYNCHBYTES 4
131 
132 void tr1001_default_rxhandler(unsigned char c);
133 PT_THREAD(tr1001_default_rxhandler_pt(unsigned char c));
134 static struct pt rxhandler_pt;
135 
136 /*
137  * This timer is used to keep track of when the last byte was received
138  * over the radio. If the inter-byte time is too large, the packet
139  * currently being received is discarded and a new packet reception is
140  * initiated.
141  */
142 static struct timer rxtimer;
143 
144 static unsigned short tmp_sstrength, sstrength;
145 static unsigned short tmp_count;
146 
147 #define DEBUG 0
148 #if DEBUG
149 #include <stdio.h>
150 #define LOG(...) printf(__VA_ARGS__)
151 #else
152 #define LOG(...)
153 #endif
154 
155 /*---------------------------------------------------------------------------*/
156 PROCESS(tr1001_process, "TR1001 driver");
157 /*---------------------------------------------------------------------------*/
158 
159 static int prepare_packet(const void *data, unsigned short len);
160 static int transmit_packet(unsigned short len);
161 static int receiving_packet(void);
162 static int pending_packet(void);
163 static int channel_clear(void);
164 static int tr1001_on(void);
165 static int tr1001_off(void);
166 
167 const struct radio_driver tr1001_driver = {
168  tr1001_init,
169  prepare_packet,
170  transmit_packet,
171  tr1001_send,
172  tr1001_read,
176  tr1001_on,
177  tr1001_off
178 };
179 
180 /*---------------------------------------------------------------------------*/
181 /*
182  * Turn on data transmission in On-Off-Keyed mode.
183  */
184 static void
185 txook(void)
186 {
187  P3SEL = 0xf0;
188  P5OUT |= 0x40;
189  P5OUT &= 0x7f;
190 }
191 /*---------------------------------------------------------------------------*/
192 /*
193  * Turn on data reception for the radio tranceiver.
194  */
195 static void
196 rxon(void)
197 {
198  P3SEL = 0xe0;
199  P5OUT |= 0xc0;
200 
201  /* Enable the receiver. */
202  ME1 |= URXE0;
203 
204  /* Turn on receive interrupt. */
205  IE1 |= URXIE0;
206 
207 }
208 /*---------------------------------------------------------------------------*/
209 /*
210  * Turn off data reception for the radio tranceiver.
211  */
212 static void
213 rxoff(void)
214 {
215  P5OUT &= 0x3f;
216 
217  /* Disable the receiver. */
218  ME1 &= ~URXE0;
219 
220  /* Turn off receive interrupt. */
221  IE1 &= ~URXIE0;
222 }
223 /*---------------------------------------------------------------------------*/
224 /*
225  * Clear the recevie buffer and reset the receiver state.
226  */
227 static void
228 rxclear(void)
229 {
230  tr1001_rxstate = RXSTATE_READY;
231 }
232 /*---------------------------------------------------------------------------*/
233 /*
234  * Turn TR1001 radio transceiver off.
235  */
236 /*---------------------------------------------------------------------------*/
237 static int
238 tr1001_off(void)
239 {
240  if(onoroff == OFF) {
241  return 1;
242  }
243  onoroff = OFF;
244  rxoff();
245  rxclear();
246 
247  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
248  return 1;
249 }
250 /*---------------------------------------------------------------------------*/
251 /*
252  * Turn TR1001 radio transceiver on.
253  */
254 /*---------------------------------------------------------------------------*/
255 static int
256 tr1001_on(void)
257 {
258  if(onoroff == ON) {
259  return 1;
260  }
261 
262  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
263 
264  onoroff = ON;
265  rxon();
266  rxclear();
267  return 1;
268 }
269 /*---------------------------------------------------------------------------*/
270 /*
271  * Send a byte of data over the radio.
272  *
273  * \param b The byte to be sent.
274  */
275 static void
276 send(unsigned char b)
277 {
278  clock_time_t start;
279 
280  start = clock_time();
281 
282  /* Wait until the USART0 TX buffer is ready. */
283  while((IFG1 & UTXIFG0) == 0) {
284  /* Wait no more than one second. */
285  if((clock_time_t)(clock_time() - start) > (clock_time_t)CLOCK_SECOND) {
286  break;
287  }
288  }
289 
290  /* Send the byte. */
291  TXBUF0 = b;
292 }
293 /*---------------------------------------------------------------------------*/
294 /*
295  * Send a byte of data and its logical negation (all bits inverted)
296  * over the radio.
297  *
298  * \param b The byte to be sent.
299  */
300 static void
301 send2(unsigned char b)
302 {
303  uint16_t m;
304  m = me_encode(b);
305  send(m >> 8);
306  send(m & 0xff);
307 }
308 static uint16_t
309 send2_crc16(unsigned char b, uint16_t crcacc)
310 {
311  uint16_t m;
312  m = me_encode(b);
313  send(m >> 8);
314  send(m & 0xff);
315  return crc16_add(b, crcacc);
316 }
317 /*---------------------------------------------------------------------------*/
318 void
319 tr1001_set_txpower(unsigned char p)
320 {
321  int i;
322 
323  /* Clamp maximum power. */
324  if(p > 100) {
325  p = 100;
326  }
327 
328  /* First, run the potentiometer down to zero so that we know the
329  start value of the potentiometer. */
330  P2OUT &= 0xDF; /* P25 = 0 (down selected) */
331  P2OUT &= 0xBF; /* P26 = 0 (chipselect on) */
332  for(i = 0; i < 102; ++i) {
333  P2OUT &= 0xEF; /* P24 = 0 (inc) */
334  P2OUT |= 0x10;
335  }
336 
337  /* Now, start to increase the value of the potentiometer until it
338  reaches the desired value.*/
339 
340  P2OUT |= 0x20; /* P25 = 1 (up selected) */
341  for(i = 0; i < p; ++i) {
342  P2OUT &= 0xEF; /* P24 = 0 (inc) */
343  P2OUT |= 0x10;
344  }
345  P2OUT |= 0x40; /* P26 = 1 (chipselect off) */
346 }
347 /*---------------------------------------------------------------------------*/
348 int
349 tr1001_init(void)
350 {
351  PT_INIT(&rxhandler_pt);
352 
353  onoroff = OFF;
354 
355  UCTL0 = CHAR; /* 8-bit character */
356  UTCTL0 = SSEL1; /* UCLK = SMCLK */
357 
358  tr1001_set_speed(TR1001_19200);
359 
360  ME1 |= UTXE0 + URXE0; /* Enable USART0 TXD/RXD */
361 
362  /* Turn on receive interrupt. */
363  IE1 |= URXIE0;
364 
365  timer_set(&rxtimer, CLOCK_SECOND / 4);
366 
367 
368  tr1001_on();
369  tr1001_set_txpower(100);
370 
371  /* Reset reception state. */
372  rxclear();
373 
374  process_start(&tr1001_process, NULL);
375 
376  return 1;
377 }
378 /*---------------------------------------------------------------------------*/
379 interrupt (UART0RX_VECTOR)
380  tr1001_rxhandler(void)
381 {
382  ENERGEST_ON(ENERGEST_TYPE_IRQ);
383  tr1001_default_rxhandler_pt(RXBUF0);
384  if(tr1001_rxstate == RXSTATE_FULL) {
385  LPM4_EXIT;
386  }
387  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
388 }
389 /*---------------------------------------------------------------------------*/
390 #if DEBUG
391 static void
392 dump_packet(int len)
393 {
394  int i;
395  for(i = 0; i < len; ++i) {
396  LOG("%d: 0x%02x\n", i, tr1001_rxbuf[i]);
397  }
398 }
399 #endif /* DEBUG */
400 /*---------------------------------------------------------------------------*/
401 PT_THREAD(tr1001_default_rxhandler_pt(unsigned char incoming_byte))
402 {
403  static unsigned char rxtmp, tmppos;
404 
405  if(timer_expired(&rxtimer) && tr1001_rxstate != RXSTATE_FULL) {
406  PT_INIT(&rxhandler_pt);
407  }
408 
409  timer_restart(&rxtimer);
410 
411  if(tr1001_rxstate == RXSTATE_RECEIVING) {
412  unsigned short signal = radio_sensor.value(0);
413  tmp_sstrength += (signal >> 2);
414  tmp_count++;
415  }
416 
417  PT_BEGIN(&rxhandler_pt);
418 
419  while(1) {
420 
421  /* Reset reception state. */
422  rxclear();
423 
424  /* Wait until we receive the first syncronization byte. */
425  PT_WAIT_UNTIL(&rxhandler_pt, incoming_byte == SYNCH1);
426 
427  tr1001_rxstate = RXSTATE_RECEIVING;
428 
429  /* Read all incoming syncronization bytes. */
430  PT_WAIT_WHILE(&rxhandler_pt, incoming_byte == SYNCH1);
431 
432  /* We should receive the second synch byte by now, otherwise we'll
433  restart the protothread. */
434  if(incoming_byte != SYNCH2) {
435  PT_RESTART(&rxhandler_pt);
436  }
437 
438  /* Start signal strength measurement */
439  tmp_sstrength = 0;
440  tmp_count = 0;
441 
442  /* Reset the CRC. */
443  rxcrc = 0xffff;
444 
445  /* Read packet header. */
446  for(tmppos = 0; tmppos < TR1001_HDRLEN; ++tmppos) {
447 
448  /* Wait for the first byte of the packet to arrive. */
449  PT_YIELD(&rxhandler_pt);
450 
451  /* If the incoming byte isn't a valid Manchester encoded byte,
452  we start again from the beginning. */
453  if(!me_valid(incoming_byte)) {
454  BEEP_BEEP(1000);
455  LOG("Incorrect manchester in header at byte %d/1\n", tmppos);
456  RIMESTATS_ADD(badsynch);
457  PT_RESTART(&rxhandler_pt);
458  }
459 
460  rxtmp = me_decode8(incoming_byte);
461 
462  /* Wait for the next byte to arrive. */
463  PT_YIELD(&rxhandler_pt);
464 
465  if(!me_valid(incoming_byte)) {
466  BEEP_BEEP(1000);
467  LOG("Incorrect manchester in header at byte %d/2\n", tmppos);
468  RIMESTATS_ADD(badsynch);
469  PT_RESTART(&rxhandler_pt);
470  }
471 
472  /* Put together the two bytes into a single Manchester decoded
473  byte. */
474 
475  tr1001_rxbuf[tmppos] = (rxtmp << 4) | me_decode8(incoming_byte);
476 
477  /* Calculate the CRC. */
478  rxcrc = crc16_add(tr1001_rxbuf[tmppos], rxcrc);
479 
480 
481  }
482 
483  /* Since we've got the header, we can grab the length from it. */
484  tr1001_rxlen = ((((struct tr1001_hdr *)tr1001_rxbuf)->len[0] << 8) +
485  ((struct tr1001_hdr *)tr1001_rxbuf)->len[1]);
486 
487  /* If the length is longer than we can handle, we'll start from
488  the beginning. */
489  if(tmppos + tr1001_rxlen > sizeof(tr1001_rxbuf)) {
490  RIMESTATS_ADD(toolong);
491  PT_RESTART(&rxhandler_pt);
492  }
493 
494  /* Read packet data. */
495  for(; tmppos < tr1001_rxlen + TR1001_HDRLEN; ++tmppos) {
496  PT_YIELD(&rxhandler_pt);
497 
498  if(!me_valid(incoming_byte)) {
499  LOG("Incorrect manchester 0x%02x at byte %d/1\n", incoming_byte,
500  tmppos - TR1001_HDRLEN);
501  BEEP_BEEP(1000);
502  RIMESTATS_ADD(badsynch);
503  PT_RESTART(&rxhandler_pt);
504  }
505 
506  rxtmp = me_decode8(incoming_byte);
507 
508  PT_YIELD(&rxhandler_pt);
509 
510  if(!me_valid(incoming_byte)) {
511  LOG("Incorrect manchester at byte %d/2\n", tmppos - TR1001_HDRLEN);
512  BEEP_BEEP(1000);
513  RIMESTATS_ADD(badsynch);
514  PT_RESTART(&rxhandler_pt);
515  }
516 
517  tr1001_rxbuf[tmppos] = (rxtmp << 4) | me_decode8(incoming_byte);
518  rxcrc = crc16_add(tr1001_rxbuf[tmppos], rxcrc);
519 
520  }
521 
522  /* Read the frame CRC. */
523  for(tmppos = 0; tmppos < 4; ++tmppos) {
524 
525  PT_YIELD(&rxhandler_pt);
526 
527  if(!me_valid(incoming_byte)) {
528  BEEP_BEEP(1000);
529  RIMESTATS_ADD(badsynch);
530  PT_RESTART(&rxhandler_pt);
531  }
532 
533  rxcrctmp = (rxcrctmp << 4) | me_decode8(incoming_byte);
534  }
535 
536  if(rxcrctmp == rxcrc) {
537  /* A full packet has been received and the CRC checks out. We'll
538  request the driver to take care of the incoming data. */
539 
540  RIMESTATS_ADD(llrx);
541  process_poll(&tr1001_process);
542 
543  /* We'll set the receive state flag to signal that a full frame
544  is present in the buffer, and we'll wait until the buffer has
545  been taken care of. */
546  tr1001_rxstate = RXSTATE_FULL;
547  PT_WAIT_UNTIL(&rxhandler_pt, tr1001_rxstate != RXSTATE_FULL);
548 
549  } else {
550  LOG("Incorrect CRC\n");
551  BEEP_BEEP(1000);
552  RIMESTATS_ADD(badcrc);
553  }
554  }
555  PT_END(&rxhandler_pt);
556 }
557 /*---------------------------------------------------------------------------*/
558 static int
559 prepare_packet(const void *data, unsigned short len)
560 {
561  pending_data = data;
562  return 0;
563 }
564 /*---------------------------------------------------------------------------*/
565 static int
566 transmit_packet(unsigned short len)
567 {
568  int ret = RADIO_TX_ERR;
569  if(pending_data != NULL) {
570  ret = tr1001_send(pending_data, len);
571  pending_data = NULL;
572  }
573  return ret;
574 }
575 /*---------------------------------------------------------------------------*/
576 int
577 tr1001_send(const void *packet, unsigned short len)
578 {
579  int i;
580  uint16_t crc16;
581 
582  LOG("tr1001_send: sending %d bytes\n", len);
583 
584  if(onoroff == ON) {
585  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
586  }
587  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
588 
589  /* Prepare the transmission. */
590 
591  /* Delay the transmission for a short random duration. */
592  clock_delay(random_rand() & 0x3ff);
593 
594 
595  /* Check that we don't currently are receiving a packet, and if so
596  we wait until the reception has been completed. Reception is done
597  with interrupts so it is OK for us to wait in a while() loop. */
598 
599  while(tr1001_rxstate == RXSTATE_RECEIVING &&
600  !timer_expired(&rxtimer)) {
601  /* Delay the transmission for a short random duration. */
602  clock_delay(random_rand() & 0x7ff);
603  }
604 
605 
606  /* Turn on OOK mode with transmission. */
607  txook();
608 
609  /* According to the datasheet, the transmitter must wait for 12 us
610  in order to settle. Empirical tests show that is it better to
611  wait for something like 283 us... */
612  clock_delay(200);
613 
614 
615  /* Transmit preamble and synch bytes. */
616  for(i = 0; i < 20; ++i) {
617  send(0xaa);
618  }
619  /* send(0xaa);
620  send(0xaa);*/
621  send(0xff);
622 
623  for(i = 0; i < NUM_SYNCHBYTES; ++i) {
624  send(SYNCH1);
625  }
626  send(SYNCH2);
627 
628  crc16 = 0xffff;
629 
630  /* Send packet header. */
631  crc16 = send2_crc16(len >> 8, crc16);
632  crc16 = send2_crc16(len & 0xff, crc16);
633 
634  /* Send packet data. */
635  for(i = 0; i < len; ++i) {
636  crc16 = send2_crc16(((uint8_t *)packet)[i], crc16);
637  }
638 
639  /* Send CRC */
640  send2(crc16 >> 8);
641  send2(crc16 & 0xff);
642 
643  /* Send trailing bytes. */
644  send(0x33);
645  send(0xcc);
646  send(0x33);
647  send(0xcc);
648 
649  /* Turn on (or off) reception again. */
650  if(onoroff == ON) {
651  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
652  rxon();
653  rxclear();
654  } else {
655  rxoff();
656  rxclear();
657  }
658 
659  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
660  RIMESTATS_ADD(lltx);
661 
662  return RADIO_TX_OK;
663 }
664 /*---------------------------------------------------------------------------*/
665 int
666 tr1001_read(void *buf, unsigned short bufsize)
667 {
668  unsigned short tmplen;
669 
670  if(tr1001_rxstate == RXSTATE_FULL) {
671 
672 #if DEBUG
673  dump_packet(tr1001_rxlen + 2);
674 #endif /* DEBUG */
675 
676  tmplen = tr1001_rxlen;
677 
678  if(tmplen > bufsize) {
679  LOG("tr1001_read: too large packet: %d/%d bytes\n", tmplen, bufsize);
680  rxclear();
681  RIMESTATS_ADD(toolong);
682  return -1;
683  }
684 
685  memcpy(buf, &tr1001_rxbuf[TR1001_HDRLEN], tmplen);
686 
687  /* header + content + CRC */
688  sstrength = (tmp_count ? ((tmp_sstrength / tmp_count) << 2) : 0);
689 
690  rxclear();
691 
692  LOG("tr1001_read: got %d bytes\n", tmplen);
693 
694  return tmplen;
695  }
696  return 0;
697 }
698 /*---------------------------------------------------------------------------*/
699 static int
700 receiving_packet(void)
701 {
702  return tr1001_rxstate == RXSTATE_RECEIVING &&
703  !timer_expired(&rxtimer);
704 }
705 /*---------------------------------------------------------------------------*/
706 static int
707 pending_packet(void)
708 {
709  return tr1001_rxstate == RXSTATE_FULL;
710 }
711 /*---------------------------------------------------------------------------*/
712 static int
713 channel_clear(void)
714 {
715  /* TODO add CCA functionality */
716  return 0;
717 }
718 /*---------------------------------------------------------------------------*/
719 PROCESS_THREAD(tr1001_process, ev, data)
720 {
721  int len;
722  PROCESS_BEGIN();
723 
724  /* Reset reception state now that the process is ready to receive data. */
725  rxclear();
726 
727  while(1) {
728  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
729  packetbuf_clear();
731  if(len > 0) {
733  NETSTACK_RDC.input();
734  }
735  }
736 
737  PROCESS_END();
738 }
739 /*---------------------------------------------------------------------------*/
740 void
741 tr1001_set_speed(unsigned char speed)
742 {
743 
744  if(speed == TR1001_19200) {
745  /* Set TR1001 to 19200 */
746  UBR00 = 0x80; /* 2,457MHz/19200 = 128 -> 0x80 */
747  UBR10 = 0x00; /* */
748  UMCTL0 = 0x00; /* no modulation */
749  } else if(speed == TR1001_38400) {
750  /* Set TR1001 to 38400 */
751  UBR00 = 0x40; /* 2,457MHz/38400 = 64 -> 0x40 */
752  UBR10 = 0x00; /* */
753  UMCTL0 = 0x00; /* no modulation */
754  } else if(speed == TR1001_57600) {
755  UBR00 = 0x2a; /* 2,457MHz/57600 = 42.7 -> 0x2A */
756  UBR10 = 0x00; /* */
757  UMCTL0 = 0x5b; /* */
758  } else if(speed == TR1001_115200) {
759  UBR00 = 0x15; /* 2,457MHz/115200 = 21.4 -> 0x15 */
760  UBR10 = 0x00; /* */
761  UMCTL0 = 0x4a; /* */
762  } else {
763  tr1001_set_speed(TR1001_19200);
764  }
765 }
766 /*---------------------------------------------------------------------------*/
767 unsigned short
768 tr1001_sstrength(void)
769 {
770  return sstrength;
771 }
772 /*---------------------------------------------------------------------------*/
773 /** @} */
774 /** @} */