A Atmel RF2xx Radio Library for Mbed

Dependents:   xBedRadio MxSniffer

Revision:
0:5f1d66c85ae0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MxRadio.h	Thu Apr 09 16:42:51 2015 +0800
@@ -0,0 +1,313 @@
+/* Copyright (c) 2011 Frank Zhao
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+ * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of the authors 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */
+
+#ifndef MxRadio_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "uracolib/board.h"
+#include "MxRadioCfg.h"
+#include "uracolib/radio.h"
+#include "uracolib/transceiver.h"
+#include <stdint.h>
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "mbed.h"
+#define ZR_RXFRMBUFF_SIZE MAX_FRAME_SIZE
+#define ZR_FIFO_SIZE 128 // size for the RX FIFO ring buffer
+#define ZR_TXTMPBUFF_SIZE MAX_FRAME_SIZE // size for the TX non-immediate transmit buffer
+
+#define ZR_TXWAIT_BEFORE // when you call any TX functions, it will wait until the previous transmission has finished before initiating a new transmission
+#define ZR_TXWAIT_AFTER // when you call any TX functions, it will transmit and then wait until that transmission finished
+
+// just a class definition, for usage and comments, see the cpp file
+class cMxRadio
+{
+private:
+
+	uint8_t temprssi;
+	radio_status_t radiostatus;
+	SPI m_spi;
+	DigitalOut m_cs;
+	DigitalOut reset_pin;
+	DigitalOut sleep_pin;
+
+protected:
+	InterruptIn irq_pin;
+private:
+	 uint8_t rxFrameBuffer[ZR_RXFRMBUFF_SIZE];
+	 uint8_t rxRingBuffer[ZR_FIFO_SIZE];
+	 uint8_t rxRingBufferHead;
+	 uint8_t rxRingBufferTail;
+	 uint8_t txTmpBuffer[ZR_TXTMPBUFF_SIZE];
+	 uint8_t txTmpBufferLength;
+	 uint8_t lastLqi;
+	 uint8_t lastRssi;
+	 uint8_t hasAttachedRxEvent;
+	 uint8_t hasAttachedTxEvent;
+	 uint8_t usedBeginTransmission;
+	volatile  uint8_t txIsBusy;
+
+	 uint8_t* (*zrEventReceiveFrame)(uint8_t, uint8_t*, uint8_t, int8_t,uint8_t);
+	 void (*zrEventTxDone)(radio_tx_done_t);
+
+	 uint8_t* onReceiveFrame(uint8_t, uint8_t*, uint8_t, int8_t,uint8_t);
+	 void onTxDone(radio_tx_done_t);
+	 bool setautotx,setautorx,needack;
+
+	//come from radio.h
+	void radio_init(uint8_t * rxbuf, uint8_t rxbufsz);
+	void radio_force_state(radio_state_t state);
+	void radio_set_state(radio_state_t state);
+	void radio_set_param(radio_attribute_t attr, radio_param_t parm);
+	void radio_send_frame(uint8_t len, uint8_t *frm, uint8_t compcrc);
+	radio_cca_t radio_do_cca(void);
+	int radio_putchar(int c);
+	int radio_getchar(void);
+	void usr_radio_error(radio_error_t err);
+	void usr_radio_irq(uint8_t cause);
+	uint8_t * usr_radio_receive_frame(uint8_t len, uint8_t *frm, uint8_t lqi, int8_t ed, uint8_t crc_fail);
+	void usr_radio_tx_done(radio_tx_done_t status);
+	//come from transciever
+	void trx_io_init (int spirate);
+	void trx_reg_write(trx_regaddr_t addr, trx_regval_t val);
+	uint8_t trx_reg_read(trx_regaddr_t addr);
+	trx_regval_t trx_bit_read(trx_regaddr_t addr, trx_regval_t mask, uint8_t pos);
+	void trx_bit_write(trx_regaddr_t addr, trx_regval_t mask, uint8_t pos, trx_regval_t value);
+	void trx_frame_write(uint8_t length, uint8_t *data);
+	uint8_t trx_frame_read(uint8_t *data, uint8_t datasz, uint8_t *lqi);
+	//uint8_t trx_frame_read_crc(uint8_t *data, uint8_t datasz, bool *crc_ok);
+	//uint8_t trx_frame_read_data_crc(uint8_t *data, uint8_t datasz, uint8_t *lqi, bool *crc_ok);
+	uint8_t trx_frame_get_length(void);
+	void trx_sram_write(trx_ramaddr_t addr, uint8_t length, uint8_t *data);
+	void trx_sram_read(trx_ramaddr_t addr, uint8_t length, uint8_t *data);
+	void trx_parms_get(trx_param_t *p);
+	uint8_t trx_parms_set(trx_param_t *p);
+	uint8_t trx_set_datarate(uint8_t rate_type);
+	uint8_t trx_get_datarate(void);
+	uint8_t trx_get_number_datarates(void);
+	//void * trx_get_datarate_str_p(uint8_t idx);
+	//void * trx_decode_datarate_p(uint8_t rhash);
+	//uint8_t trx_get_datarate_str(uint8_t idx, char * rstr, uint8_t nlen);
+	//uint8_t trx_decode_datarate(uint8_t rhash, char * rstr, uint8_t nlen);
+	/**
+	 * @brief Basic radio initialization function,
+	 */
+	 inline uint8_t trx_init(void)
+	{
+		uint8_t val;
+		/* reset transceiver */
+		reset_pin=0;//TRX_RESET_LOW();
+		sleep_pin=0;//TRX_SLPTR_LOW();
+		DELAY_US(TRX_RESET_TIME_US);
+		reset_pin=1;//TRX_RESET_HIGH();
+		/* set TRX_OFF (for the case we come from P_ON) */
+		trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
+
+#if RADIO_TYPE == RADIO_AT86RF212
+		trx_reg_write(RG_TRX_CTRL_0, 0x19);
+#ifdef CHINABAND
+		trx_reg_write(RG_CC_CTRL_1, CCBAND );
+		trx_reg_write(RG_CC_CTRL_0, 11);//channel 0
+		trx_reg_write(RG_TRX_CTRL_2, TRX_OQPSK250);
+		DELAY_US(510);
+#endif
+#endif
+
+		DELAY_US(TRX_INIT_TIME_US);
+		val = trx_reg_read(RG_TRX_STATUS);
+		return (val != TRX_OFF) ? TRX_OK : TRX_INIT_FAIL;
+	}
+	 inline uint8_t trx_check_pll_lock(void)
+	{
+	uint8_t val, cnt = 255;
+
+	    trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
+	    trx_reg_write(RG_IRQ_MASK, TRX_IRQ_PLL_LOCK);
+	    trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
+	    cnt = 255;
+	    do
+	    {
+	        DELAY_US(TRX_PLL_LOCK_TIME_US);
+	        val = trx_reg_read(RG_IRQ_STATUS);
+	        if (val & TRX_IRQ_PLL_LOCK)
+	        {
+	            break;
+	        }
+	    }
+	    while(--cnt);
+
+	    /* clear pending IRQs*/
+	    trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
+	    trx_reg_read(RG_IRQ_STATUS);
+	    return (cnt > 0) ? TRX_OK : TRX_PLL_FAIL;
+	}
+
+	/**
+	 * @brief Verify that correct radio type is used.
+	 *
+	 * @return status value, with the following meaning:
+	 *        - 0 if part and revision number match
+	 *        - 1 if revision number does @b not match
+	 *        - 2 if part number does @b not match
+	 *        - 3 if part and revision number does @b not match
+	 */
+	 inline int trx_identify(void)
+	{
+	    int ret = 0;
+
+	    if(RADIO_PART_NUM != trx_reg_read(RG_PART_NUM))
+	    {
+	        ret |= INVALID_PART_NUM;
+	    }
+
+	    if(RADIO_VERSION_NUM != trx_reg_read(RG_VERSION_NUM))
+	    {
+	        ret |= INVALID_REV_NUM;
+	    }
+	    return ret;
+	}
+
+	/**
+	 * @brief Write the PANID to the address filter registers
+	 */
+	 inline void trx_set_panid(uint16_t panid)
+	{
+	    trx_reg_write(RG_PAN_ID_0,(panid&0xff));
+	    trx_reg_write(RG_PAN_ID_1,(panid>>8));
+	}
+
+	/**
+	 * @brief Write the 16 bit short address to the
+	 * address filter registers
+	 */
+	 inline void trx_set_shortaddr(uint16_t shortaddr)
+	{
+	    trx_reg_write(RG_SHORT_ADDR_0,(shortaddr&0xff));
+	    trx_reg_write(RG_SHORT_ADDR_1,(shortaddr>>8));
+	}
+
+	/**
+	 * @brief Write the 64 bit long address (MAC address) to the
+	 * address filter registers
+	 */
+	 inline void trx_set_longaddr(uint64_t longaddr)
+	{
+	    trx_reg_write(RG_IEEE_ADDR_0, (uint8_t)(longaddr>>0) );
+	    trx_reg_write(RG_IEEE_ADDR_1, (uint8_t)(longaddr>>8) );
+	    trx_reg_write(RG_IEEE_ADDR_2, (uint8_t)(longaddr>>16));
+	    trx_reg_write(RG_IEEE_ADDR_3, (uint8_t)(longaddr>>24));
+	    trx_reg_write(RG_IEEE_ADDR_4, (uint8_t)(longaddr>>32));
+	    trx_reg_write(RG_IEEE_ADDR_5, (uint8_t)(longaddr>>40));
+	    trx_reg_write(RG_IEEE_ADDR_6, (uint8_t)(longaddr>>48));
+	    trx_reg_write(RG_IEEE_ADDR_7, (uint8_t)(longaddr>>56));
+	}
+
+	 inline uint16_t crc16_update(uint16_t crc, uint8_t a)
+	     {
+	         int i;
+
+	         crc ^= a;
+	         for (i = 0; i < 8; ++i)
+	         {
+	             if (crc & 1)
+	                 crc = (crc >> 1) ^ 0xA001;
+	             else
+	                 crc = (crc >> 1);
+	         }
+
+	         return crc;
+	     }
+
+	void rf_irq_callback();
+
+	//rf230.cpp
+	void radio_error(radio_error_t err);
+	void radio_receive_frame(void);
+	void radio_irq_handler(uint8_t cause);
+	//events
+	void zr_attach_error(void (*)(radio_error_t));
+	void zr_attach_irq(void (*)(uint8_t));
+	void zr_attach_receive_frame(uint8_t* (cMxRadio::*)(uint8_t, uint8_t*, uint8_t, int8_t,uint8_t));
+	void zr_attach_tx_done(void (cMxRadio::*)(radio_tx_done_t));
+
+	 void (*user_radio_error)(radio_error_t);
+	 void (*user_radio_irq)(uint8_t);
+	 uint8_t* (cMxRadio::*user_radio_receive_frame)(uint8_t, uint8_t*, uint8_t, int8_t,uint8_t);
+	 void (cMxRadio::*user_radio_tx_done)(radio_tx_done_t);
+
+
+public:
+	cMxRadio(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName slp, PinName irq);
+	~cMxRadio();
+	void begin(channel_t);
+	void begin(channel_t,uint16_t,uint16_t,bool,bool,bool,char);
+	void begin(channel_t,uint16_t,uint16_t,bool,bool,bool);
+	void begin(channel_t, uint8_t*);
+	void setFrameHeader(uint8_t*);
+	void attachError(void(*)(radio_error_t));
+	void attachIrq(void(*)(uint8_t));
+	void attachReceiveFrame(uint8_t* (*)(uint8_t, uint8_t*, uint8_t, int8_t,uint8_t));
+	void sendFrame(uint16_t ,bool ,uint8_t* , uint8_t );
+	void attachTxDone(void(*)(radio_tx_done_t));
+	int8_t available();
+	int16_t peek();
+	int16_t read();
+	void flush();
+	void write(uint8_t);
+	void write(char*);
+	void write(uint8_t*, uint8_t);
+	void send(uint8_t);
+	void txFrame(uint8_t*, uint8_t);
+	void beginTransmission();
+	void beginTransmission(uint16_t);
+	void endTransmission();
+	void cancelTransmission();
+	void setParam(radio_attribute_t, radio_param_t);
+	radio_cca_t doCca();
+	void setState(radio_state_t, uint8_t);
+	void setState(radio_state_t);
+	void setStateRx();
+	void setChannel(channel_t);
+	uint8_t getChannel();
+	void forceState(radio_state_t);
+	void waitTxDone(uint16_t);
+	int8_t getRssiNow();
+	int8_t getLastRssi();
+	uint8_t getLqi();
+	int8_t getLastEd();
+	int8_t getEdNow();
+};
+
+extern cMxRadio MxRadio; // make single instance accessible
+
+#define MxRadio_h
+#endif