transceiver.h

Go to the documentation of this file.
00001 /* Copyright (c) 2007 Axel Wachtler
00002    All rights reserved.
00003 
00004    Redistribution and use in source and binary forms, with or without
00005    modification, are permitted provided that the following conditions
00006    are met:
00007 
00008    * Redistributions of source code must retain the above copyright
00009      notice, this list of conditions and the following disclaimer.
00010    * Redistributions in binary form must reproduce the above copyright
00011      notice, this list of conditions and the following disclaimer in the
00012      documentation and/or other materials provided with the distribution.
00013    * Neither the name of the authors nor the names of its contributors
00014      may be used to endorse or promote products derived from this software
00015      without specific prior written permission.
00016 
00017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027    POSSIBILITY OF SUCH DAMAGE. */
00028 
00029 /* $Id: transceiver.h,v 1.27 2011/01/21 06:59:27 awachtler Exp $ */
00035 #ifndef TRANSCEIVER_H
00036 #define TRANSCEIVER_H
00037 
00043 /* === Includes ============================================================== */
00044 #include "board.h"
00045 
00046 #if RADIO_TYPE == RADIO_AT86RF230 || defined(DOXYGEN)
00047 # include "at86rf230a.h"
00048 #elif RADIO_TYPE == RADIO_AT86RF230B
00049 # include "at86rf230b.h"
00050 #elif RADIO_TYPE == RADIO_AT86RF231
00051 # include "at86rf231.h"
00052 #elif RADIO_TYPE == RADIO_AT86RF212
00053 # include "at86rf212.h"
00054 #elif RADIO_TYPE == RADIO_ATMEGA128RFA1_A ||\
00055       RADIO_TYPE == RADIO_ATMEGA128RFA1_B ||\
00056       RADIO_TYPE == RADIO_ATMEGA128RFA1_C ||\
00057       RADIO_TYPE == RADIO_ATMEGA128RFA1_D
00058 # include "atmega_rfa1.h"
00059 #else
00060 # error "RADIO_TYPE is not defined or wrong"
00061 #endif
00062 #include <stdbool.h>
00063 
00064 /* === Externals ============================================================= */
00065 
00066 /* === Types ================================================================= */
00067 
00068 #if defined(DOXYGEN)
00069 
00070     /* this types are defined in at86rfXXX.{h,txt} in order
00071        to provide a radio abstraction */
00072 
00075     typedef uint8_t trx_ramaddr_t;
00076 
00079     typedef uint8_t trx_regval_t;
00080 
00083     typedef uint8_t trx_regaddr_t;
00084 
00085 #endif
00086 
00089 typedef void (*trx_irq_handler_t)(uint8_t cause);
00090 
00091 typedef enum
00092 {
00093    CFG_FLASH,
00094    CFG_EEPROM,
00095    CFG_NONE
00096 } trx_cfg_t;
00097 
00098 /* === Macros ================================================================ */
00099 /* error codes */
00101 #define TRX_OK        (0)
00102 
00103 #define TRX_INIT_FAIL (1)
00104 
00105 #define TRX_PLL_FAIL  (2)
00106 
00107 #define INVALID_PART_NUM (2)  
00108 #define INVALID_REV_NUM  (1)  
00110 /* Data Rate macros, generated by python Tools/cmdhash.py  `cat rates.txt` */
00111 #define BPSK20 (0x52)
00112 #define BPSK20_STR "BPSK20"
00113 #define BPSK40 (0x92)
00114 #define BPSK40_STR "BPSK40"
00115 #define OQPSK100 (0x90)
00116 #define OQPSK100_STR "OQPSK100"
00117 #define OQPSK200 (0x93)
00118 #define OQPSK200_STR "OQPSK200"
00119 #define OQPSK250 (0x33)
00120 #define OQPSK250_STR "OQPSK250"
00121 #define OQPSK400 (0x95)
00122 #define OQPSK400_STR "OQPSK400"
00123 #define OQPSK500 (0x94)
00124 #define OQPSK500_STR "OQPSK500"
00125 #define OQPSK1000 (0x34)
00126 #define OQPSK1000_STR "OQPSK1000"
00127 #define OQPSK2000 (0x54)
00128 #define OQPSK2000_STR "OQPSK2000"
00129 
00130 #define RATE_NONE (0xFF)
00131 
00133 #ifndef MAX_FRAME_SIZE
00134 # define MAX_FRAME_SIZE (127)
00135 #endif
00136 
00137 /* channel handling */
00138 #define TRX_NEXT_CHANNEL(x) ((channel_t)(x+1) > TRX_MAX_CHANNEL ? TRX_MAX_CHANNEL : x+1)
00139 #define TRX_PREV_CHANNEL(x) ((channel_t)(x-1) < TRX_MIN_CHANNEL ? TRX_MIN_CHANNEL : x-1)
00140 #define TRX_NEXT_CHANNEL_WRAP(x) ((channel_t)(x+1) > TRX_MAX_CHANNEL ? TRX_MIN_CHANNEL : x+1 )
00141 #define TRX_PREV_CHANNEL_WRAP(x) ((channel_t)(x-1) < TRX_MIN_CHANNEL ? TRX_MAX_CHANNEL : x-1 )
00142 
00143 
00144 #if defined (SR_MASK_AMI) || defined(DOXYGEN)
00145 
00146 # define TRX_IRQ_AMI_EI() trx_bit_write(SR_MASK_AMI, 1);
00147 
00148 # define TRX_IRQ_AMI_DI() trx_bit_write(SR_MASK_AMI, 0);
00149 #endif
00150 
00151 #if defined (SR_MASK_BAT_LOW) || defined(DOXYGEN)
00152 
00153 # define TRX_IRQ_BAT_LOW_EI() trx_bit_write(SR_MASK_BAT_LOW, 1);
00154 
00155 # define TRX_IRQ_BAT_LOW_DI() trx_bit_write(SR_MASK_BAT_LOW, 0);
00156 #endif
00157 
00158 #if defined (SR_MASK_CCA_ED_READY) || defined(DOXYGEN)
00159 
00160 # define TRX_IRQ_CCA_ED_READY_EI() trx_bit_write(SR_MASK_CCA_ED_READY, 1);
00161 
00162 # define TRX_IRQ_CCA_ED_READY_DI() trx_bit_write(SR_MASK_CCA_ED_READY, 0);
00163 #endif
00164 
00165 #if defined (SR_MASK_PLL_UNLOCK) || defined(DOXYGEN)
00166 
00167 # define TRX_IRQ_PLL_UNLOCK_EI() trx_bit_write(SR_MASK_PLL_UNLOCK, 1);
00168 
00169 # define TRX_IRQ_PLL_UNLOCK_DI() trx_bit_write(SR_MASK_PLL_UNLOCK, 0);
00170 #endif
00171 
00172 #if defined (SR_MASK_RX_START) || defined(DOXYGEN)
00173 
00174 # define TRX_IRQ_RX_START_EI() trx_bit_write(SR_MASK_RX_START, 1);
00175 
00176 # define TRX_IRQ_RX_START_DI() trx_bit_write(SR_MASK_RX_START, 0);
00177 #endif
00178 
00179 #if defined (SR_MASK_TRX_IRQ_END) || defined(DOXYGEN)
00180 
00181 # define TRX_IRQ_TRX_IRQ_END_EI() trx_bit_write(SR_MASK_TRX_IRQ_END, 1);
00182 
00183 # define TRX_IRQ_TRX_IRQ_END_DI() trx_bit_write(SR_MASK_TRX_IRQ_END, 0);
00184 #endif
00185 
00186 #if defined (SR_MASK_TRX_IRQ_START) || defined(DOXYGEN)
00187 
00188 # define TRX_IRQ_TRX_IRQ_START_EI() trx_bit_write(SR_MASK_TRX_IRQ_START, 1);
00189 
00190 # define TRX_IRQ_TRX_IRQ_START_DI() trx_bit_write(SR_MASK_TRX_IRQ_START, 0);
00191 #endif
00192 
00193 #if defined (SR_MASK_UR) || defined(DOXYGEN)
00194 
00195 # define TRX_IRQ_UR_EI() trx_bit_write(SR_MASK_UR, 1);
00196 
00197 # define TRX_IRQ_UR_DI() trx_bit_write(SR_MASK_UR, 0);
00198 #endif
00199 
00200 /* === Prototypes ============================================================ */
00201 #ifdef __cplusplus
00202 extern "C" {
00203 #endif
00204 
00205 #if !defined(TRX_IF_RFA1)
00206 
00215 void trx_io_init (uint8_t spirate);
00216 #else  /* RFA1 */
00217 #define trx_io_init(dummy) do { /* dummy macro */ } while (0)
00218 #endif
00219 
00220 
00223 void trx_set_irq_handler(trx_irq_handler_t irqhandler);
00224 
00232 void trx_reg_write(trx_regaddr_t addr, trx_regval_t val);
00233 
00242 uint8_t trx_reg_read(trx_regaddr_t addr);
00243 
00244 
00245 
00261 trx_regval_t trx_bit_read(trx_regaddr_t addr, trx_regval_t mask, uint8_t pos);
00262 
00263 
00280 void trx_bit_write(trx_regaddr_t addr, trx_regval_t mask, uint8_t pos, trx_regval_t value);
00281 
00292 void trx_frame_write(uint8_t length, uint8_t *data);
00293 
00305 uint8_t trx_frame_read(uint8_t *data, uint8_t datasz, uint8_t *lqi);
00306 
00307 
00324 uint8_t trx_frame_read_crc(uint8_t *data, uint8_t datasz, bool *crc_ok);
00325 
00326 
00344 uint8_t trx_frame_read_data_crc(uint8_t *data, uint8_t datasz, uint8_t *lqi, bool *crc_ok);
00345 
00353 uint8_t trx_frame_get_length(void);
00354 
00365 void trx_sram_write(trx_ramaddr_t addr, uint8_t length, uint8_t *data);
00366 
00375 void trx_sram_read(trx_ramaddr_t addr, uint8_t length, uint8_t *data);
00376 
00386 void trx_parms_get(trx_param_t *p);
00387 
00400 uint8_t trx_parms_set(trx_param_t *p);
00401 
00413 uint8_t trx_set_datarate(uint8_t rate_type);
00414 
00419 uint8_t trx_get_datarate(void);
00420 
00425 uint8_t trx_get_number_datarates(void);
00426 
00437 void * trx_get_datarate_str_p(uint8_t idx);
00438 
00445 void * trx_decode_datarate_p(uint8_t rhash);
00446 
00456 uint8_t trx_get_datarate_str(uint8_t idx, char * rstr, uint8_t nlen);
00457 
00467 uint8_t trx_decode_datarate(uint8_t rhash, char * rstr, uint8_t nlen);
00468 
00469 /*=== Inline Functions ================================================*/
00470 /*
00471  * This are functions that are usually called once in an application,
00472  * so we decalre it inline here
00473  */
00474 
00478 static inline uint8_t trx_init(void)
00479 {
00480 uint8_t val;
00481 
00482     /* reset transceiver */
00483     TRX_RESET_LOW();
00484     TRX_SLPTR_LOW();
00485     DELAY_US(TRX_RESET_TIME_US);
00486     TRX_RESET_HIGH();
00487 
00488     /* set TRX_OFF (for the case we come from P_ON) */
00489     trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
00490     DELAY_US(TRX_INIT_TIME_US);
00491     val = trx_reg_read(RG_TRX_STATUS);
00492     return (val != TRX_OFF) ? TRX_OK : TRX_INIT_FAIL;
00493 }
00494 
00495 
00496 static inline uint8_t trx_check_pll_lock(void)
00497 {
00498 uint8_t val, cnt = 255;
00499 
00500     trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00501     trx_reg_write(RG_IRQ_MASK, TRX_IRQ_PLL_LOCK);
00502     trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
00503     cnt = 255;
00504     do
00505     {
00506         DELAY_US(TRX_PLL_LOCK_TIME_US);
00507         val = trx_reg_read(RG_IRQ_STATUS);
00508         if (val & TRX_IRQ_PLL_LOCK)
00509         {
00510             break;
00511         }
00512     }
00513     while(--cnt);
00514 
00515     /* clear pending IRQs*/
00516     trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00517     trx_reg_read(RG_IRQ_STATUS);
00518     return (cnt > 0) ? TRX_OK : TRX_PLL_FAIL;
00519 }
00520 
00521 
00531 static inline int trx_identify(void)
00532 {
00533     int ret = 0;
00534 
00535     if(RADIO_PART_NUM != trx_reg_read(RG_PART_NUM))
00536     {
00537         ret |= INVALID_PART_NUM;
00538     }
00539 
00540     if(RADIO_VERSION_NUM != trx_reg_read(RG_VERSION_NUM))
00541     {
00542         ret |= INVALID_REV_NUM;
00543     }
00544     return ret;
00545 }
00546 
00550 static inline void trx_set_panid(uint16_t panid)
00551 {
00552     trx_reg_write(RG_PAN_ID_0,(panid&0xff));
00553     trx_reg_write(RG_PAN_ID_1,(panid>>8));
00554 }
00555 
00560 static inline void trx_set_shortaddr(uint16_t shortaddr)
00561 {
00562     trx_reg_write(RG_SHORT_ADDR_0,(shortaddr&0xff));
00563     trx_reg_write(RG_SHORT_ADDR_1,(shortaddr>>8));
00564 }
00565 
00570 static inline void trx_set_longaddr(uint64_t longaddr)
00571 {
00572     trx_reg_write(RG_IEEE_ADDR_0, (uint8_t)(longaddr>>0) );
00573     trx_reg_write(RG_IEEE_ADDR_1, (uint8_t)(longaddr>>8) );
00574     trx_reg_write(RG_IEEE_ADDR_2, (uint8_t)(longaddr>>16));
00575     trx_reg_write(RG_IEEE_ADDR_3, (uint8_t)(longaddr>>24));
00576     trx_reg_write(RG_IEEE_ADDR_4, (uint8_t)(longaddr>>32));
00577     trx_reg_write(RG_IEEE_ADDR_5, (uint8_t)(longaddr>>40));
00578     trx_reg_write(RG_IEEE_ADDR_6, (uint8_t)(longaddr>>48));
00579     trx_reg_write(RG_IEEE_ADDR_7, (uint8_t)(longaddr>>56));
00580 }
00581 
00582 /* todo add and test a fucntion for setting the ext address */
00583 
00584 #ifdef __cplusplus
00585 } /* extern "C" */
00586 #endif
00587 
00591 #endif /* TRANSCEIVER_H */

This documentation for µracoli was generated on Wed Feb 2 2011 by  doxygen 1.7.1