📄 tr1001.c
字号:
/* * Copyright (c) 2005, Swedish Institute of Computer Science * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This file is part of the Contiki operating system. * * @(#)$Id: tr1001.c,v 1.8 2007/10/25 09:30:39 adamdunkels Exp $ *//** * \addtogroup esb * @{ *//** * \defgroup tr1001 TR1001 radio tranciever device driver * @{ *//** * \file * Device driver and packet framing for the RFM-TR1001 radio module. * \author Adam Dunkels <adam@sics.se> * * This file implements a device driver for the RFM-TR1001 radio * tranciever. * */#include "contiki-esb.h"#include "dev/tr1001.h"#include "lib/me.h"#include "lib/crc16.h"#include <io.h>#include <signal.h>#include <string.h>#define RXSTATE_READY 0#define RXSTATE_RECEVING 1#define RXSTATE_FULL 2#define SYNCH1 0x3c#define SYNCH2 0x03#if TR1001_STATISTICSstatic unsigned short sstrength_dropped, sstrength_max, sstrength_min, tmp_sstrength_max, tmp_sstrength_min;/* The number of dropped packets */static unsigned short packets_err;/* The number of accepted packets */static unsigned short packets_ok;#endif /* TR1001_STATISTICS *//* * The buffer which holds incoming data. */#define RXBUFSIZE UIP_BUFSIZEunsigned char tr1001_rxbuf[RXBUFSIZE];/* * The length of the packet that currently is being received. */static unsigned short tr1001_rxlen = 0;/* * The reception state. */volatile unsigned char tr1001_rxstate = RXSTATE_READY;static u8_t radio_active;static u16_t rxcrc, rxcrctmp;/* * The structure of the packet header. */struct tr1001_hdr { u8_t len[2]; /**< The 16-bit length of the packet in network byte order. */};/* * The length of the packet header. */#define TR1001_HDRLEN sizeof(struct tr1001_hdr)#define OFF 0#define ON 1static u8_t onoroff = OFF;#define NUM_SYNCHBYTES 4void tr1001_default_rxhandler(unsigned char c);PT_THREAD(tr1001_default_rxhandler_pt(unsigned char c));static struct pt rxhandler_pt;/* * This timer is used to keep track of when the last byte was received * over the radio. If the inter-byte time is too large, the packet * currently being received is discarded and a new packet reception is * initiated. */static struct timer rxtimer;static unsigned short tmp_sstrength, sstrength;static unsigned short tmp_count;#define DEBUG 0#if DEBUG#include <stdio.h>#define LOG(...) printf(__VA_ARGS__)#else#define LOG(...)#endif/*---------------------------------------------------------------------------*/PROCESS(tr1001_process, "TR1001 driver");/*---------------------------------------------------------------------------*/static void (* receiver_callback)(const struct radio_driver *);static void tr1001_set_receiver(void (* recv)(const struct radio_driver *));static int tr1001_on(void);static int tr1001_off(void);const struct radio_driver tr1001_driver = { tr1001_send, tr1001_read, tr1001_set_receiver, tr1001_on, tr1001_off};/*---------------------------------------------------------------------------*/#if TR1001_STATISTICS#define PACKET_DROPPED() do { \ if(packets_err < ~0) {\ packets_err++;\ }\ sstrength_dropped = (tmp_count ? ((tmp_sstrength / tmp_count) << 2) : 0);\} while(0)#define PACKET_ACCEPTED() do {\ if(packets_ok < ~0) {\ packets_ok++;\ }\} while(0);#else#define PACKET_DROPPED()#define PACKET_ACCEPTED()#endif /* TR1001_STATISTICS *//*---------------------------------------------------------------------------*//* * Turn on data transmission in On-Off-Keyed mode. */static voidtxook(void){ P3SEL = 0xf0; P5OUT |= 0x40; P5OUT &= 0x7f;}/*---------------------------------------------------------------------------*//* * Turn on data reception for the radio tranceiver. */static voidrxon(void){ P3SEL = 0xe0; P5OUT |= 0xc0; /* Enable the receiver. */ ME1 |= URXE0; /* Turn on receive interrupt. */ IE1 |= URXIE0;}/*---------------------------------------------------------------------------*//* * Turn off data reception for the radio tranceiver. */static voidrxoff(void){ P5OUT &= 0x3f; /* Disable the receiver. */ ME1 &= ~URXE0; /* Turn off receive interrupt. */ IE1 &= ~URXIE0;}/*---------------------------------------------------------------------------*//* * Clear the recevie buffer and reset the receiver state. */static voidrxclear(void){ tr1001_rxstate = RXSTATE_READY;}/*---------------------------------------------------------------------------*//* * Turn TR1001 radio transceiver off. *//*---------------------------------------------------------------------------*/static inttr1001_off(void){ if(onoroff == OFF) { return 1; } onoroff = OFF; rxoff(); rxclear(); ENERGEST_OFF(ENERGEST_TYPE_LISTEN); return 1;}/*---------------------------------------------------------------------------*//* * Turn TR1001 radio transceiver on. *//*---------------------------------------------------------------------------*/static inttr1001_on(void){ if(onoroff == ON) { return 1; } ENERGEST_ON(ENERGEST_TYPE_LISTEN); onoroff = ON; rxon(); rxclear(); return 1;}/*---------------------------------------------------------------------------*//* * Send a byte of data over the radio. * * \param b The byte to be sent. */static voidsend(unsigned char b){ clock_time_t start; start = clock_time(); /* Wait until the USART0 TX buffer is ready. */ while((IFG1 & UTXIFG0) == 0) { /* Wait no more than one second. */ if((clock_time_t)(clock_time() - start) > (clock_time_t)CLOCK_SECOND) { break; } } /* Send the byte. */ TXBUF0 = b;}/*---------------------------------------------------------------------------*//* * Send a byte of data and its logical negation (all bits inverted) * over the radio. * * \param b The byte to be sent. */static voidsend2(unsigned char b){ u16_t m; m = me_encode(b); send(m >> 8); send(m & 0xff);}static u16_tsend2_crc16(unsigned char b, u16_t crcacc){ u16_t m; m = me_encode(b); send(m >> 8); send(m & 0xff); return crc16_add(b, crcacc);}/*---------------------------------------------------------------------------*/voidtr1001_set_txpower(unsigned char p){ int i; /* Clamp maximum power. */ if(p > 100) { p = 100; } /* First, run the potentiometer down to zero so that we know the start value of the potentiometer. */ P2OUT &= 0xDF; /* P25 = 0 (down selected) */ P2OUT &= 0xBF; /* P26 = 0 (chipselect on) */ for(i = 0; i < 102; ++i) { P2OUT &= 0xEF; /* P24 = 0 (inc) */ P2OUT |= 0x10; } /* Now, start to increase the value of the potentiometer until it reaches the desired value.*/ P2OUT |= 0x20; /* P25 = 1 (up selected) */ for(i = 0; i < p; ++i) { P2OUT &= 0xEF; /* P24 = 0 (inc) */ P2OUT |= 0x10; } P2OUT |= 0x40; /* P26 = 1 (chipselect off) */}/*---------------------------------------------------------------------------*/static voidtr1001_set_receiver(void (* recv)(const struct radio_driver *)){ receiver_callback = recv;}/*---------------------------------------------------------------------------*/voidtr1001_init(void){ PT_INIT(&rxhandler_pt);#if TR1001_STATISTICS packets_ok = packets_err = 0; sstrength_dropped = 0; sstrength_min = 0xFFFF; sstrength_max = 0;#endif /* TR1001_STATISTICS */ onoroff = OFF; UCTL0 = CHAR; /* 8-bit character */ UTCTL0 = SSEL1; /* UCLK = SMCLK */ tr1001_set_speed(TR1001_19200); ME1 |= UTXE0 + URXE0; /* Enable USART0 TXD/RXD */ /* Turn on receive interrupt. */ IE1 |= URXIE0; timer_set(&rxtimer, CLOCK_SECOND / 4); tr1001_on(); tr1001_set_txpower(100); /* Reset reception state. */ rxclear(); process_start(&tr1001_process, NULL);}/*---------------------------------------------------------------------------*/interrupt (UART0RX_VECTOR) tr1001_rxhandler(void){ ENERGEST_ON(ENERGEST_TYPE_IRQ); tr1001_default_rxhandler_pt(RXBUF0); if(tr1001_rxstate == RXSTATE_FULL) { LPM4_EXIT; } ENERGEST_OFF(ENERGEST_TYPE_IRQ);}/*---------------------------------------------------------------------------*/static voiddump_packet(int len){ int i; for(i = 0; i < len; ++i) { LOG("%d: 0x%02x\n", i, tr1001_rxbuf[i]); }}/*---------------------------------------------------------------------------*/PT_THREAD(tr1001_default_rxhandler_pt(unsigned char incoming_byte)){ static unsigned char rxtmp, tmppos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -