adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 1 | /** |
| 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 | * |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 11 | * \note A lot of the stuff in this file is currently a "hack" form |
| 12 | * (particularly the "MAC" stuff and the ackowledgements)! |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 13 | */ |
| 14 | |
| 15 | #include "tr1001.h" |
| 16 | #include "uip.h" |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 17 | #include "uip-fw.h" |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 18 | |
| 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 |
| 56 | static unsigned char rxbuf[RXBUFSIZE]; |
| 57 | |
| 58 | /** |
| 59 | * \internal |
| 60 | * A pointer into the rxbuf buffer which points to the next available byte. |
| 61 | */ |
| 62 | static unsigned short rxpos; |
| 63 | |
| 64 | /** |
| 65 | * \internal |
| 66 | * The length of the packet that currently is being received. |
| 67 | */ |
| 68 | static unsigned short rxlen; |
| 69 | |
| 70 | /** |
| 71 | * \internal |
| 72 | * The reception state. |
| 73 | */ |
| 74 | static unsigned char rxstate = RXSTATE_READY; |
| 75 | |
| 76 | |
| 77 | /** |
| 78 | * \internal |
| 79 | * The structure of the packet header. |
| 80 | */ |
| 81 | struct tr1001_hdr { |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 82 | u8_t type; /**< The packet type. */ |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 83 | u8_t id; /**< A packet identifier. */ |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 84 | u8_t len[2]; /**< The 16-bit length of the packet in network byte |
| 85 | order. */ |
| 86 | }; |
| 87 | |
| 88 | /** |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 89 | * \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 |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 108 | * 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 | |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 112 | /** |
| 113 | * \internal |
| 114 | * The incremental packet identifier. |
| 115 | */ |
| 116 | static u8_t packet_id; |
| 117 | |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 118 | /*------------------------------------------------------------------------------*/ |
| 119 | /** |
| 120 | * \internal |
| 121 | * Turn on data transmission in On-Off-Keyed mode. |
| 122 | */ |
| 123 | /*------------------------------------------------------------------------------*/ |
| 124 | static void |
| 125 | txook(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 | /*------------------------------------------------------------------------------*/ |
| 137 | static void |
| 138 | rxon(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 | /*------------------------------------------------------------------------------*/ |
| 149 | static void |
| 150 | rxclear(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 | /*------------------------------------------------------------------------------*/ |
| 163 | static void |
| 164 | send(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 | /*------------------------------------------------------------------------------*/ |
| 181 | static void |
| 182 | send2(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 | /*------------------------------------------------------------------------------*/ |
| 205 | void |
| 206 | tr1001_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 | /*------------------------------------------------------------------------------*/ |
| 242 | void |
| 243 | tr1001_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 | /*------------------------------------------------------------------------------*/ |
| 301 | unsigned short |
| 302 | tr1001_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 | } |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 310 | memcpy(&uip_buf[UIP_LLH_LEN], rxbuf + TR1001_HDRLEN, rxlen); |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 311 | 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 | /*------------------------------------------------------------------------------*/ |
| 329 | interrupt (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; |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 366 | if(rxpos == TR1001_HDRLEN) { |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 367 | 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; |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 383 | if(rxpos == TR1001_HDRLEN) { |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 384 | 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; |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 405 | if(rxpos == rxlen + TR1001_HDRLEN) { |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 406 | 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; |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 419 | if(rxpos == rxlen + TR1001_HDRLEN) { |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 420 | 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 | /*------------------------------------------------------------------------------*/ |
| 444 | static void |
| 445 | delay_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 | /** |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 455 | * \internal |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 456 | * |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 457 | * Prepare a transmission. |
| 458 | * |
| 459 | * This function does the necessary setup before a packet can be sent |
| 460 | * out. |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 461 | */ |
| 462 | /*------------------------------------------------------------------------------*/ |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 463 | static void |
| 464 | prepare_transmission(void) |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 465 | { |
| 466 | unsigned short i, laststate; |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 467 | |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 468 | /* 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). */ |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 472 | /* P2OUT &= 0xFE;*/ |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 473 | delay_hack(400 * (sensors_battery & 0x0f)); |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 474 | /* P2OUT |= 0x01; */ |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 475 | |
| 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 | |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 501 | /* 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 | |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 508 | } |
| 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 | /*------------------------------------------------------------------------------*/ |
| 518 | u8_t |
| 519 | tr1001_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 | /*------------------------------------------------------------------------------*/ |
| 568 | u8_t |
| 569 | tr1001_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 | |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 589 | /* 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. */ |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 605 | send2(TR1001_TYPE_DATA); |
| 606 | send2(++packet_id); |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 607 | send2(uip_len >> 8); |
| 608 | send2(uip_len & 0xff); |
| 609 | |
| 610 | /* Send packet data. */ |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 611 | for(i = 0; i < hdrlen; ++i) { |
| 612 | send2(hdr[i]); |
| 613 | } |
| 614 | for(i = 0;i < datalen; ++i) { |
| 615 | send2(data[i]); |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 616 | } |
| 617 | |
| 618 | /* Send trailing bytes. */ |
| 619 | send(0xaa); |
| 620 | send(0xaa); |
| 621 | |
| 622 | /* Turn on reception again. */ |
| 623 | rxon(); |
| 624 | |
adamdunkels | 3845cd7 | 2003-11-27 15:59:00 +0000 | [diff] [blame] | 625 | 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 | /*------------------------------------------------------------------------------*/ |
| 639 | u8_t |
| 640 | tr1001_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 | |
adamdunkels | 573bc29 | 2003-10-01 08:04:03 +0000 | [diff] [blame] | 677 | } |
| 678 | /*------------------------------------------------------------------------------*/ |