Add macros by Roger Larsson to select between hardware or software SPI transactions.

Minor speed optimizations.
This commit is contained in:
dak664 2010-11-30 19:47:40 +00:00
parent b58e13f8e1
commit 0ba9846abd
2 changed files with 90 additions and 82 deletions

View File

@ -47,7 +47,7 @@
* \file * \file
* \brief This file contains low-level radio driver code. * \brief This file contains low-level radio driver code.
* *
* $Id: hal.h,v 1.3 2010/02/26 21:15:29 dak664 Exp $ * $Id: hal.h,v 1.4 2010/11/30 19:47:40 dak664 Exp $
*/ */
#ifndef HAL_AVR_H #ifndef HAL_AVR_H
@ -366,7 +366,9 @@ void hal_register_write( uint8_t address, uint8_t value );
uint8_t hal_subregister_read( uint8_t address, uint8_t mask, uint8_t position ); uint8_t hal_subregister_read( uint8_t address, uint8_t mask, uint8_t position );
void hal_subregister_write( uint8_t address, uint8_t mask, uint8_t position, void hal_subregister_write( uint8_t address, uint8_t mask, uint8_t position,
uint8_t value ); uint8_t value );
void hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback); //void hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback);
/* For speed RF230BB does not use a callback */
void hal_frame_read(hal_rx_frame_t *rx_frame);
void hal_frame_write( uint8_t *write_buffer, uint8_t length ); void hal_frame_write( uint8_t *write_buffer, uint8_t length );
void hal_sram_read( uint8_t address, uint8_t length, uint8_t *data ); void hal_sram_read( uint8_t address, uint8_t length, uint8_t *data );
void hal_sram_write( uint8_t address, uint8_t length, uint8_t *data ); void hal_sram_write( uint8_t address, uint8_t length, uint8_t *data );

View File

@ -56,6 +56,7 @@
* This file contains low-level radio driver code. * This file contains low-level radio driver code.
* This version is optimized for use with the "barebones" RF230bb driver, * This version is optimized for use with the "barebones" RF230bb driver,
* which communicates directly with the contiki core MAC layer. * which communicates directly with the contiki core MAC layer.
* It is optimized for speed at the expense of generality.
*/ */
@ -131,6 +132,42 @@ static uint16_t hal_system_time = 0;
/*============================ PROTOTYPES ====================================*/ /*============================ PROTOTYPES ====================================*/
/*============================ IMPLEMENTATION ================================*/ /*============================ IMPLEMENTATION ================================*/
#ifndef RF230BB_HARDWARE_SPI
#define RF230BB_HARDWARE_SPI 1
#endif
#if RF230BB_HARDWARE_SPI
// AVR with hardware spi tranfers
#define HAL_SPI_TRANSFER_OPEN() { \
AVR_ENTER_CRITICAL_REGION(); \
HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
#define HAL_SPI_TRANSFER_WRITE(to_write) SPDR = to_write
#define HAL_SPI_TRANSFER_WAIT() ({while ((SPSR & (1 << SPIF)) == 0) {;}}) /* gcc extension, alternative inline function */
#define HAL_SPI_TRANSFER_READ() (SPDR)
#define HAL_SPI_TRANSFER_CLOSE() \
HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
AVR_LEAVE_CRITICAL_REGION(); \
}
#define HAL_SPI_TRANSFER(to_write) ( \
HAL_SPI_TRANSFER_WRITE(to_write), \
HAL_SPI_TRANSFER_WAIT(), \
HAL_SPI_TRANSFER_READ() )
#else /* RF230BB_HARDWARE_SPI */
// Software SPI transfers (Mulle, for reference)
#define HAL_SPI_TRANSFER_OPEN() { uint8_t spiTemp; \
AVR_ENTER_CRITICAL_REGION(); \
HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
#define HAL_SPI_TRANSFER_WRITE(to_write) (spiTemp = spiWrite(to_write))
#define HAL_SPI_TRANSFER_WAIT() (0)
#define HAL_SPI_TRANSFER_READ() (spiTemp)
#define HAL_SPI_TRANSFER_CLOSE() \
HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \
AVR_LEAVE_CRITICAL_REGION(); \
}
#define HAL_SPI_TRANSFER(to_write) (spiTemp = spiWrite(to_write))
#endif /* RF230BB_HARDWARE_SPI */
/** \brief This function initializes the Hardware Abstraction Layer. /** \brief This function initializes the Hardware Abstraction Layer.
*/ */
void void
@ -313,22 +350,14 @@ hal_register_read(uint8_t address)
uint8_t register_value = 0; uint8_t register_value = 0;
AVR_ENTER_CRITICAL_REGION(); HAL_SPI_TRANSFER_OPEN();
HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
/*Send Register address and read register content.*/ /*Send Register address and read register content.*/
SPDR = address; register_value = HAL_SPI_TRANSFER(address); // dummy read
while ((SPSR & (1 << SPIF)) == 0) {;}
register_value = SPDR;
SPDR = register_value; register_value = HAL_SPI_TRANSFER(register_value); // dummy write
while ((SPSR & (1 << SPIF)) == 0) {;}
register_value = SPDR;
HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ HAL_SPI_TRANSFER_CLOSE();
AVR_LEAVE_CRITICAL_REGION();
return register_value; return register_value;
} }
@ -348,22 +377,14 @@ hal_register_write(uint8_t address, uint8_t value)
/* Add the Register Write command to the address. */ /* Add the Register Write command to the address. */
address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address); address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address);
AVR_ENTER_CRITICAL_REGION(); HAL_SPI_TRANSFER_OPEN();
HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */
/*Send Register address and write register content.*/ /*Send Register address and write register content.*/
SPDR = address; uint8_t dummy_read = HAL_SPI_TRANSFER(address);
while ((SPSR & (1 << SPIF)) == 0) {;}
uint8_t dummy_read = SPDR;
SPDR = value; dummy_read = HAL_SPI_TRANSFER(value);
while ((SPSR & (1 << SPIF)) == 0) {;}
dummy_read = SPDR;
HAL_SS_HIGH(); /* End the transaction by pulling the Slave Slect High. */ HAL_SPI_TRANSFER_CLOSE();
AVR_LEAVE_CRITICAL_REGION();
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
@ -425,33 +446,30 @@ hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position,
* If the frame currently available in the radio transceiver's frame buffer * If the frame currently available in the radio transceiver's frame buffer
* is out of the defined bounds. Then the frame length, lqi value and crc * is out of the defined bounds. Then the frame length, lqi value and crc
* be set to zero. This is done to indicate an error. * be set to zero. This is done to indicate an error.
* This version is optimized for use with contiki RF230BB driver * This version is optimized for use with contiki RF230BB driver.
* The callback routine and CRC are left out for speed in reading the rx buffrer .
* *
* \param rx_frame Pointer to the data structure where the frame is stored. * \param rx_frame Pointer to the data structure where the frame is stored.
* \param rx_callback Pointer to callback function for receiving one byte at a time. * \param rx_callback Pointer to callback function for receiving one byte at a time.
*/ */
void void
hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback) //hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback)
hal_frame_read(hal_rx_frame_t *rx_frame)
{ {
uint8_t *rx_data=0; // uint8_t *rx_data=0;
uint8_t *rx_data;
/* check that we have either valid frame pointer or callback pointer */ /* check that we have either valid frame pointer or callback pointer */
// if (!rx_frame && !rx_callback) // if (!rx_frame && !rx_callback)
// return; // return;
AVR_ENTER_CRITICAL_REGION(); HAL_SPI_TRANSFER_OPEN();
HAL_SS_LOW();
/*Send frame read command.*/ /*Send frame read command.*/
SPDR = HAL_TRX_CMD_FR; (void)HAL_SPI_TRANSFER(HAL_TRX_CMD_FR);
while ((SPSR & (1 << SPIF)) == 0) {;}
uint8_t frame_length = SPDR;
/*Read frame length.*/ /*Read frame length.*/
SPDR = frame_length; uint8_t frame_length = HAL_SPI_TRANSFER(0);
while ((SPSR & (1 << SPIF)) == 0) {;}
frame_length = SPDR;
/*Check for correct frame length.*/ /*Check for correct frame length.*/
if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){ if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){
@ -462,44 +480,43 @@ hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback)
// } else { // } else {
// rx_callback(frame_length); // rx_callback(frame_length);
// } // }
/*Upload frame buffer to data pointer. Calculate CRC.*/ /*Upload frame buffer to data pointer */
SPDR = frame_length;
while ((SPSR & (1 << SPIF)) == 0) {;} HAL_SPI_TRANSFER_WRITE(0);
HAL_SPI_TRANSFER_WAIT();
do{ do{
uint8_t tempData = SPDR; *rx_data++ = HAL_SPI_TRANSFER_READ();
SPDR = 0; /* dummy write */ HAL_SPI_TRANSFER_WRITE(0);
HAL_SPI_TRANSFER_WAIT();
// if (rx_frame){ // if (rx_frame){
*rx_data++ = tempData; // *rx_data++ = tempData;
// } else { // } else {
// rx_callback(tempData); // rx_callback(tempData);
// } // }
/* RF230 does crc in hardware, for speed we hope the buffer is not being overwritten! */ /* RF230 does crc in hardware, doing the checksum here ensures the rx buffer has not been overwritten by the next packet */
/* Since doing the checksum makes such overwrites more probable, we skip it and hope for the best. */
/* A full buffer should be read in 320us at 2x spi clocking, so with a low interrupt latency overwrites should not occur */
// crc = _crc_ccitt_update(crc, tempData); // crc = _crc_ccitt_update(crc, tempData);
while ((SPSR & (1 << SPIF)) == 0) {;}
} while (--frame_length > 0); } while (--frame_length > 0);
/*Read LQI value for this frame.*/ /*Read LQI value for this frame.*/
// if (rx_frame){ // if (rx_frame){
rx_frame->lqi = SPDR; rx_frame->lqi = HAL_SPI_TRANSFER_READ();
// } else { // } else {
// rx_callback(SPDR); // rx_callback(SPDR);
// } // }
HAL_SS_HIGH();
rx_frame->crc = 1;
/*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/ /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/
// if (rx_frame){ // if (rx_frame){
// rx_frame->crc = (crc == HAL_CALCULATED_CRC_OK); rx_frame->crc = 1;
// } else { // } else {
// rx_callback(crc != HAL_CALCULATED_CRC_OK); // rx_callback(crc != HAL_CALCULATED_CRC_OK);
// } // }
} else { } else {
HAL_SS_HIGH();
// if (rx_frame){ // if (rx_frame){
rx_frame->length = 0; rx_frame->length = 0;
rx_frame->lqi = 0; rx_frame->lqi = 0;
@ -507,7 +524,7 @@ hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback)
// } // }
} }
AVR_LEAVE_CRITICAL_REGION(); HAL_SPI_TRANSFER_CLOSE();
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
@ -522,32 +539,20 @@ hal_frame_write(uint8_t *write_buffer, uint8_t length)
{ {
length &= HAL_TRX_CMD_RADDRM; /* Truncate length to maximum frame length. */ length &= HAL_TRX_CMD_RADDRM; /* Truncate length to maximum frame length. */
AVR_ENTER_CRITICAL_REGION(); HAL_SPI_TRANSFER_OPEN();
HAL_SS_LOW(); /* Initiate the SPI transaction. */
/*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/ /*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/
SPDR = HAL_TRX_CMD_FW;
while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t dummy_read = HAL_SPI_TRANSFER(HAL_TRX_CMD_FW);
uint8_t dummy_read = SPDR;
SPDR = length; dummy_read = HAL_SPI_TRANSFER(length);
while ((SPSR & (1 << SPIF)) == 0) {;}
dummy_read = SPDR;
/* Download to the Frame Buffer. */ /* Download to the Frame Buffer. */
do{ do{
SPDR = *write_buffer++; dummy_read = HAL_SPI_TRANSFER(*write_buffer++);
--length; } while (--length > 0);
while ((SPSR & (1 << SPIF)) == 0) {;} HAL_SPI_TRANSFER_CLOSE();
dummy_read = SPDR;
} while (length > 0);
HAL_SS_HIGH(); /* Terminate SPI transaction. */
AVR_LEAVE_CRITICAL_REGION();
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
@ -653,11 +658,11 @@ ISR(RADIO_VECT)
{ {
/*The following code reads the current system time. This is done by first /*The following code reads the current system time. This is done by first
reading the hal_system_time and then adding the 16 LSB directly from the reading the hal_system_time and then adding the 16 LSB directly from the
TCNT1 register. TCNT1 register. Not implented in RF230BB for speed
*/ */
uint32_t isr_timestamp = hal_system_time; // uint32_t isr_timestamp = hal_system_time;
isr_timestamp <<= 16; // isr_timestamp <<= 16;
isr_timestamp |= TCNT1; // isr_timestamp |= TCNT1;
volatile uint8_t state; volatile uint8_t state;
INTERRUPTDEBUG(1); INTERRUPTDEBUG(1);
@ -672,8 +677,8 @@ ISR(RADIO_VECT)
base. The division is moved here so we can spend less time waiting for SPI base. The division is moved here so we can spend less time waiting for SPI
data. data.
*/ */
isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */ // isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */
isr_timestamp &= HAL_SYMBOL_MASK; // isr_timestamp &= HAL_SYMBOL_MASK;
while ((SPSR & (1 << SPIF)) == 0) {;} while ((SPSR & (1 << SPIF)) == 0) {;}
uint8_t interrupt_source = SPDR; /* The interrupt variable is used as a dummy read. */ uint8_t interrupt_source = SPDR; /* The interrupt variable is used as a dummy read. */
@ -723,14 +728,15 @@ ISR(RADIO_VECT)
#if RF230_CONF_AUTOACK #if RF230_CONF_AUTOACK
rf230_last_rssi=hal_subregister_read(SR_ED_LEVEL); rf230_last_rssi=hal_subregister_read(SR_ED_LEVEL);
if (rf230_last_rssi >= RF230_MIN_RX_POWER) { if (rf230_last_rssi >= RF230_MIN_RX_POWER) {
// if (hal_subregister_read(SR_ED_LEVEL) >= RF230_MIN_RX_POWER) { // if (hal_subregister_read(SR_ED_LEVEL) >= RF230_MIN_RX_POWER) {
#else #else
rf230_last_rssi=hal_subregister_read(SR_RSSI); rf230_last_rssi=hal_subregister_read(SR_RSSI);
// if (hal_subregister_read(SR_RSSI) >= RF230_MIN_RX_POWER/3) { // if (hal_subregister_read(SR_RSSI) >= RF230_MIN_RX_POWER/3) {
if (rf230_last_rssi >= RF230_MIN_RX_POWER/3) { if (rf230_last_rssi >= RF230_MIN_RX_POWER/3) {
#endif #endif
#endif #endif
hal_frame_read(&rxframe, NULL); // hal_frame_read(&rxframe, NULL);
hal_frame_read(&rxframe);
rf230_interrupt(); rf230_interrupt();
// trx_end_callback(isr_timestamp); // trx_end_callback(isr_timestamp);
#ifdef RF230_MIN_RX_POWER #ifdef RF230_MIN_RX_POWER