From b5ecce21b0f3467bf5ef35b84a921bb081417764 Mon Sep 17 00:00:00 2001 From: Thomas Eichinger Date: Tue, 25 Nov 2014 15:46:26 +0100 Subject: [PATCH 2/5] Add RIOT adaption --- bsp/boards/board_ow.h | 40 +++ bsp/boards/riot-adaption/Makefile | 3 + bsp/boards/riot-adaption/board_info.h | 90 ++++++ bsp/boards/riot-adaption/board_ow.c | 28 ++ bsp/boards/riot-adaption/debugpins.c | 27 ++ bsp/boards/riot-adaption/eui64.c | 25 ++ bsp/boards/riot-adaption/leds_ow.c | 137 ++++++++++ bsp/boards/riot-adaption/radio.c | 496 ++++++++++++++++++++++++++++++++++ bsp/boards/riot-adaption/radiotimer.c | 155 +++++++++++ bsp/boards/riot-adaption/spi_ow.c | 321 ++++++++++++++++++++++ bsp/boards/riot-adaption/uart_ow.c | 96 +++++++ 11 files changed, 1418 insertions(+) create mode 100644 bsp/boards/board_ow.h create mode 100644 bsp/boards/riot-adaption/Makefile create mode 100644 bsp/boards/riot-adaption/board_info.h create mode 100644 bsp/boards/riot-adaption/board_ow.c create mode 100644 bsp/boards/riot-adaption/debugpins.c create mode 100644 bsp/boards/riot-adaption/eui64.c create mode 100644 bsp/boards/riot-adaption/leds_ow.c create mode 100644 bsp/boards/riot-adaption/radio.c create mode 100644 bsp/boards/riot-adaption/radiotimer.c create mode 100644 bsp/boards/riot-adaption/spi_ow.c create mode 100644 bsp/boards/riot-adaption/uart_ow.c diff --git a/bsp/boards/board_ow.h b/bsp/boards/board_ow.h new file mode 100644 index 0000000..adc373c --- /dev/null +++ b/bsp/boards/board_ow.h @@ -0,0 +1,40 @@ +#ifndef __BOARD_H +#define __BOARD_H + +/** +\addtogroup BSP +\{ +\addtogroup board +\{ + +\brief Cross-platform declaration "board" bsp module. + +\author Thomas Watteyne , February 2012. +*/ + +#include "board_info.h" +#include "toolchain_defs.h" + +//=========================== define ========================================== + +typedef enum { + DO_NOT_KICK_SCHEDULER, + KICK_SCHEDULER, +} kick_scheduler_t; + +//=========================== typedef ========================================= + +//=========================== variables ======================================= + +//=========================== prototypes ====================================== + +void board_init(void); +void board_sleep(void); +void board_reset(void); + +/** +\} +\} +*/ + +#endif diff --git a/bsp/boards/riot-adaption/Makefile b/bsp/boards/riot-adaption/Makefile new file mode 100644 index 0000000..fad1c2e --- /dev/null +++ b/bsp/boards/riot-adaption/Makefile @@ -0,0 +1,3 @@ +MODULE = openwsn + +include $(RIOTBASE)/Makefile.base \ No newline at end of file diff --git a/bsp/boards/riot-adaption/board_info.h b/bsp/boards/riot-adaption/board_info.h new file mode 100644 index 0000000..85f2eb1 --- /dev/null +++ b/bsp/boards/riot-adaption/board_info.h @@ -0,0 +1,90 @@ +/** +\brief agilefox board information bsp module (based on openmoteSTM32 code). + +This module simply defines some strings describing the board, which CoAP uses +to return the board's description. + +\author Thomas Watteyne , February 2012. +\author Tengfei Chang , July 2012. +\author Alaeddine Weslati , August 2013. +*/ + +#ifndef __BOARD_INFO_H +#define __BOARD_INFO_H + +#include "stdint.h" +#include "string.h" +#include "cpu.h" + +//=========================== defines ========================================= + +#define INTERRUPT_DECLARATION(); //no declaration + +#define DISABLE_INTERRUPTS() irq_disable(); +#define ENABLE_INTERRUPTS() irq_enable(); + +//===== timer + +#define PORT_TIMER_WIDTH uint32_t +#define PORT_RADIOTIMER_WIDTH uint32_t + +#define PORT_SIGNED_INT_WIDTH int32_t +#define PORT_TICS_PER_MS 32 +#define SCHEDULER_WAKEUP() //EXTI->SWIER |= EXTI_Line1; +#define SCHEDULER_ENABLE_INTERRUPT() //enable in board use EXTI_Line1 + +//===== pinout + +// [P4.7] radio SLP_TR_CNTL +#define PORT_PIN_RADIO_SLP_TR_CNTL_HIGH() //GPIOA->ODR |= (1<<0); +#define PORT_PIN_RADIO_SLP_TR_CNTL_LOW() //GPIOA->ODR &= ~(1<<0); +// radio reset line +// radio /RST +#define PORT_PIN_RADIO_RESET_HIGH() //GPIOC->ODR |= 0X0040;// nothing +#define PORT_PIN_RADIO_RESET_LOW() //GPIOC->ODR &= ~0X0040;// nothing + +//===== IEEE802154E timing + +//// time-slot related +//#define PORT_TsSlotDuration 491 // counter counts one extra count, see datasheet +//// execution speed related +//#define PORT_maxTxDataPrepare 66 // 2014us (measured 746us) +//#define PORT_maxRxAckPrepare 10 // 305us (measured 83us) +//#define PORT_maxRxDataPrepare 33 // 1007us (measured 84us) +//#define PORT_maxTxAckPrepare 10 // 305us (measured 219us) +//// radio speed related +//#define PORT_delayTx 9 // 214us (measured 219us) +//#define PORT_delayRx 0 // 0us (can not measure) +//// radio watchdog + +// time-slot related +#define PORT_TsSlotDuration 245 // counter counts one extra count, see datasheet +// execution speed related (rcc configure need 235us) +#define PORT_maxTxDataPrepare 33 // 2014us (measured 812us+235) stm32 +#define PORT_maxRxAckPrepare 10 // 900us (measured 171us+235) stm32 +#define PORT_maxRxDataPrepare 16 // 976us (measured 170us+235) stm32 +#define PORT_maxTxAckPrepare 10 // 900us (measured 323us+235) stm32 +// radio speed related +#define PORT_delayTx 10 // 549us (measured 315us+235) ..... +#define PORT_delayRx 0 // 0us (can not measure) + +//===== adaptive_sync accuracy + +#define SYNC_ACCURACY 2 // ticks + +//=========================== typedef ======================================== + +//=========================== variables ======================================= + +static const uint8_t rreg_uriquery[] = "h=ucb"; +static const uint8_t infoBoardname[] = "riot-os"; +static const uint8_t infouCName[] = "various"; +static const uint8_t infoRadioName[] = "various"; + +//=========================== prototypes ====================================== + +//=========================== public ========================================== + +//=========================== private ========================================= + +#endif diff --git a/bsp/boards/riot-adaption/board_ow.c b/bsp/boards/riot-adaption/board_ow.c new file mode 100644 index 0000000..95f29b1 --- /dev/null +++ b/bsp/boards/riot-adaption/board_ow.c @@ -0,0 +1,28 @@ +#include "board_ow.h" +#include "radiotimer.h" +#include "radio.h" +#include "debugpins.h" +#include "spi_ow.h" + +#define ENABLE_DEBUG (1) +#include "debug.h" + +void board_init_ow(void) +{ + DEBUG("%s\n",__PRETTY_FUNCTION__); + spi_init_ow(); + radio_init(); + DEBUG("%s\n",__PRETTY_FUNCTION__); + radiotimer_init(); + DEBUG("%s\n",__PRETTY_FUNCTION__); + debugpins_init(); + DEBUG("%s\n",__PRETTY_FUNCTION__); +} + +void board_sleep(void) +{ +} + +void board_reset(void) +{ +} \ No newline at end of file diff --git a/bsp/boards/riot-adaption/debugpins.c b/bsp/boards/riot-adaption/debugpins.c new file mode 100644 index 0000000..06c7c2e --- /dev/null +++ b/bsp/boards/riot-adaption/debugpins.c @@ -0,0 +1,27 @@ +#include "debugpins.h" + +void debugpins_init(void) {} + +void debugpins_frame_toggle(void) {} +void debugpins_frame_clr(void) {} +void debugpins_frame_set(void) {} + +void debugpins_slot_toggle(void) {} +void debugpins_slot_clr(void) {} +void debugpins_slot_set(void) {} + +void debugpins_fsm_toggle(void) {} +void debugpins_fsm_clr(void) {} +void debugpins_fsm_set(void) {} + +void debugpins_task_toggle(void) {} +void debugpins_task_clr(void) {} +void debugpins_task_set(void) {} + +void debugpins_isr_toggle(void) {} +void debugpins_isr_clr(void) {} +void debugpins_isr_set(void) {} + +void debugpins_radio_toggle(void) {} +void debugpins_radio_clr(void) {} +void debugpins_radio_set(void) {} \ No newline at end of file diff --git a/bsp/boards/riot-adaption/eui64.c b/bsp/boards/riot-adaption/eui64.c new file mode 100644 index 0000000..da9da6d --- /dev/null +++ b/bsp/boards/riot-adaption/eui64.c @@ -0,0 +1,25 @@ +#include "eui64.h" + +//=========================== defines ========================================= +// stm32f103rey, 96-bit unique ID address +#define UNIQUE_ID_BASE_ADDRESS 0x1FFFF7E8 + +//=========================== variables ======================================= + +const uint8_t const *uid = (const uint8_t *const) UNIQUE_ID_BASE_ADDRESS; + +//=========================== prototypes ====================================== + +//=========================== public ========================================== + +void eui64_get(uint8_t* addressToWrite) +{ + addressToWrite[0] = uid[0]; + addressToWrite[1] = uid[1]; + addressToWrite[2] = uid[2]; + addressToWrite[3] = uid[3]; + addressToWrite[4] = uid[4]; + addressToWrite[5] = uid[5]; + addressToWrite[6] = uid[6]; + addressToWrite[7] = uid[7]; +} \ No newline at end of file diff --git a/bsp/boards/riot-adaption/leds_ow.c b/bsp/boards/riot-adaption/leds_ow.c new file mode 100644 index 0000000..cd892e1 --- /dev/null +++ b/bsp/boards/riot-adaption/leds_ow.c @@ -0,0 +1,137 @@ +#include "board.h" +#include "leds.h" + +void Delay(void); + + +void leds_init_ow(void) +{ +} + +/* red */ +void leds_error_on(void) +{ + LED_RED_ON; +} + +void leds_error_off(void) +{ + LED_RED_OFF; +} +void leds_error_toggle(void) +{ + LED_RED_TOGGLE; +} +uint8_t leds_error_isOn(void) +{ + uint8_t bitstatus = 0x00; + if ((LED_RED_PORT->ODR & LED_RED_PIN) != (uint32_t)0) + { + bitstatus = 0x00; + } + else + { + bitstatus = 0x01; + } + return bitstatus; +} +void leds_error_blink(void) {} + +/* green */ +void leds_sync_on(void) +{ + LED_GREEN_ON; +} +void leds_sync_off(void) +{ + LED_GREEN_OFF; +} +void leds_sync_toggle(void) +{ + LED_GREEN_TOGGLE; +} +uint8_t leds_sync_isOn(void) +{ + uint8_t bitstatus = 0x00; + if ((LED_GREEN_PORT->ODR & LED_GREEN_PIN) != (uint32_t)0) + { + bitstatus = 0x00; + } + else + { + bitstatus = 0x01; + } + return bitstatus; +} + +/* orange */ +void leds_radio_on(void) +{ + LED_ORANGE_ON; +} +void leds_radio_off(void) +{ + LED_ORANGE_OFF; +} +void leds_radio_toggle(void) +{ + LED_ORANGE_TOGGLE; +} +uint8_t leds_radio_isOn(void) +{ + uint8_t bitstatus = 0x00; + if ((LED_ORANGE_PORT->ODR & LED_ORANGE_PIN) != (uint32_t)0) + { + bitstatus = 0x00; + } + else + { + bitstatus = 0x01; + } + return bitstatus; +} + +/* yellow */ +void leds_debug_on(void) {} +void leds_debug_off(void) {} +void leds_debug_toggle(void) {} +uint8_t leds_debug_isOn(void) { return 0;} + +void leds_all_on(void) +{ + leds_error_on(); + leds_sync_on(); + leds_radio_on(); +} +void leds_all_off(void) +{ + leds_error_off(); + leds_sync_off(); + leds_radio_off(); +} +void leds_all_toggle(void) +{ + leds_error_toggle(); + leds_sync_toggle(); + leds_radio_toggle(); +} + +void leds_circular_shift(void) +{ + leds_error_toggle(); + Delay(); + leds_sync_toggle(); + Delay(); + leds_radio_toggle(); + Delay(); +} + +void leds_increment(void) {} + +//=========================== private ========================================= + +void Delay(void) +{ + uint32_t i; + for(i=0; i<0xfffff; i++); +} \ No newline at end of file diff --git a/bsp/boards/riot-adaption/radio.c b/bsp/boards/riot-adaption/radio.c new file mode 100644 index 0000000..203550c --- /dev/null +++ b/bsp/boards/riot-adaption/radio.c @@ -0,0 +1,496 @@ +#include "board_ow.h" +#include "radio.h" +#include "at86rf231_ow.h" +#include "spi_ow.h" +#include "radiotimer.h" +#include "debugpins.h" +#include "leds.h" +#include "board.h" +#include "spi.h" +#include "periph_conf.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + + +//=========================== defines ========================================= + +//=========================== variables ======================================= + +typedef struct { + radiotimer_capture_cbt startFrame_cb; + radiotimer_capture_cbt endFrame_cb; + radio_state_t state; +} radio_vars_t; + +radio_vars_t radio_vars; + +//=========================== prototypes ====================================== + +void radio_spiWriteReg(uint8_t reg_addr, uint8_t reg_setting); +uint8_t radio_spiReadReg(uint8_t reg_addr); +void radio_spiWriteTxFifo(uint8_t* bufToWrite, uint8_t lenToWrite); +void radio_spiReadRxFifo(uint8_t* pBufRead, + uint8_t* pLenRead, + uint8_t maxBufLen, + uint8_t* pLqi); +uint8_t radio_spiReadRadioInfo(void); + +//=========================== public ========================================== + +//===== admin + +void radio_init(void) { + + // clear variables + memset(&radio_vars,0,sizeof(radio_vars_t)); + + // change state + radio_vars.state = RADIOSTATE_STOPPED; + DEBUG("%s\n",__PRETTY_FUNCTION__); + // configure the radio + radio_spiWriteReg(RG_TRX_STATE, CMD_FORCE_TRX_OFF); // turn radio off + + radio_spiWriteReg(RG_IRQ_MASK, + (AT_IRQ_RX_START| AT_IRQ_TRX_END)); // tell radio to fire interrupt on TRX_END and RX_START + radio_spiReadReg(RG_IRQ_STATUS); // deassert the interrupt pin in case is high + radio_spiWriteReg(RG_ANT_DIV, RADIO_CHIP_ANTENNA); // use chip antenna +#define RG_TRX_CTRL_1 0x04 + radio_spiWriteReg(RG_TRX_CTRL_1, 0x20); // have the radio calculate CRC + //busy wait until radio status is TRX_OFF + uint16_t c = 0; + while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != TRX_OFF) + if (c++ == 10000) { + DEBUG("radio_spiReadReg timeout\n"); + break; + } + DEBUG("%s\n",__PRETTY_FUNCTION__); + // change state + radio_vars.state = RADIOSTATE_RFOFF; +} + +void radio_setOverflowCb(radiotimer_compare_cbt cb) { + radiotimer_setOverflowCb(cb); +} + +void radio_setCompareCb(radiotimer_compare_cbt cb) { + radiotimer_setCompareCb(cb); +} + +void radio_setStartFrameCb(radiotimer_capture_cbt cb) { + radio_vars.startFrame_cb = cb; +} + +void radio_setEndFrameCb(radiotimer_capture_cbt cb) { + radio_vars.endFrame_cb = cb; +} + +//===== reset + +void radio_reset(void) { + PORT_PIN_RADIO_RESET_LOW(); +} + +//===== timer + +void radio_startTimer(PORT_TIMER_WIDTH period) { + radiotimer_start(period); +} + +PORT_TIMER_WIDTH radio_getTimerValue(void) { + return radiotimer_getValue(); +} + +void radio_setTimerPeriod(PORT_TIMER_WIDTH period) { + radiotimer_setPeriod(period); +} + +PORT_TIMER_WIDTH radio_getTimerPeriod(void) { + return radiotimer_getPeriod(); +} + +//===== RF admin + +void radio_setFrequency(uint8_t frequency) { + // change state + radio_vars.state = RADIOSTATE_SETTING_FREQUENCY; + + // configure the radio to the right frequecy + radio_spiWriteReg(RG_PHY_CC_CCA,0x20+frequency); + + // change state + radio_vars.state = RADIOSTATE_FREQUENCY_SET; +} + +void radio_rfOn(void) { + PORT_PIN_RADIO_RESET_LOW(); +} + +void radio_rfOff(void) { + DEBUG("%s\n",__PRETTY_FUNCTION__); + // change state + radio_vars.state = RADIOSTATE_TURNING_OFF; + radio_spiReadReg(RG_TRX_STATUS); + DEBUG("step 1\n"); + // turn radio off + radio_spiWriteReg(RG_TRX_STATE, CMD_FORCE_TRX_OFF); + DEBUG("step 2\n"); + radio_spiWriteReg(RG_TRX_STATE, CMD_TRX_OFF); + + // busy wait until done + uint16_t c = 0; + while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != TRX_OFF) + ;// if (c++ == 100000) { +// DEBUG("%s: radio_spiReadReg timeout\n", __PRETTY_FUNCTION__); +// break; +// } + + DEBUG("step 3\n"); + // wiggle debug pin + debugpins_radio_clr(); + leds_radio_off(); + DEBUG("step 4\n"); + // change state + radio_vars.state = RADIOSTATE_RFOFF; + DEBUG("step 5\n"); +} + +//===== TX + +void radio_loadPacket(uint8_t* packet, uint8_t len) { + // change state + radio_vars.state = RADIOSTATE_LOADING_PACKET; + + // load packet in TXFIFO + radio_spiWriteTxFifo(packet,len); + + // change state + radio_vars.state = RADIOSTATE_PACKET_LOADED; +} + +void radio_txEnable(void) { + // change state + radio_vars.state = RADIOSTATE_ENABLING_TX; + + // wiggle debug pin + debugpins_radio_set(); + leds_radio_on(); + + // turn on radio's PLL + radio_spiWriteReg(RG_TRX_STATE, CMD_PLL_ON); + uint16_t c = 0; + while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != PLL_ON) // busy wait until done + ;// if (c++ == 100000) { +// DEBUG("%s: radio_spiReadReg timeout\n", __PRETTY_FUNCTION__); +// break; +// } + + // change state + radio_vars.state = RADIOSTATE_TX_ENABLED; +} + +void radio_txNow(void) { + PORT_TIMER_WIDTH val; + // change state + radio_vars.state = RADIOSTATE_TRANSMITTING; + leds_radio_toggle(); + // send packet by pulsing the SLP_TR_CNTL pin + PORT_PIN_RADIO_SLP_TR_CNTL_HIGH(); + PORT_PIN_RADIO_SLP_TR_CNTL_LOW(); + leds_radio_toggle(); + // The AT86RF231 does not generate an interrupt when the radio transmits the + // SFD, which messes up the MAC state machine. The danger is that, if we leave + // this funtion like this, any radio watchdog timer will expire. + // Instead, we cheat an mimick a start of frame event by calling + // ieee154e_startOfFrame from here. This also means that software can never catch + // a radio glitch by which #radio_txEnable would not be followed by a packet being + // transmitted (I've never seen that). + if (radio_vars.startFrame_cb!=NULL) { + // call the callback + val=radiotimer_getCapturedTime(); + radio_vars.startFrame_cb(val); + } + DEBUG("SENT\n"); +} + +//===== RX + +void radio_rxEnable(void) { + // change state + radio_vars.state = RADIOSTATE_ENABLING_RX; + + // put radio in reception mode + radio_spiWriteReg(RG_TRX_STATE, CMD_RX_ON); + + // wiggle debug pin + debugpins_radio_set(); + leds_radio_on(); + + // busy wait until radio really listening + uint16_t c = 0; + while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != RX_ON) + ;// if (c++ == 100000) { +// DEBUG("%s: radio_spiReadReg timeout\n",__PRETTY_FUNCTION__); +// break; +// } + + // change state + radio_vars.state = RADIOSTATE_LISTENING; +} + +void radio_rxNow(void) { + // nothing to do + +} + +void radio_getReceivedFrame(uint8_t* pBufRead, + uint8_t* pLenRead, + uint8_t maxBufLen, + int8_t* pRssi, + uint8_t* pLqi, + uint8_t* pCrc) { + uint8_t temp_reg_value; + + //===== crc + temp_reg_value = radio_spiReadReg(RG_PHY_RSSI); + *pCrc = (temp_reg_value & 0x80)>>7; // msb is whether packet passed CRC + + //===== rssi + // as per section 8.4.3 of the AT86RF231, the RSSI is calculate as: + // -91 + ED [dBm] + temp_reg_value = radio_spiReadReg(RG_PHY_ED_LEVEL); + *pRssi = -91 + temp_reg_value; + + //===== packet + radio_spiReadRxFifo(pBufRead, + pLenRead, + maxBufLen, + pLqi); +} + +//=========================== private ========================================= + +static inline void CSn_SET(void) +{ + SPI_0_CS_PORT->BSRR = (1 << SPI_0_CS_PIN); +} +static inline void CSn_CLR(void) +{ + SPI_0_CS_PORT->BRR = (1 << SPI_0_CS_PIN); +} + +uint8_t radio_spiReadRadioInfo(void){ + uint8_t spi_tx_buffer[3]; + uint8_t spi_rx_buffer[3]; + DEBUG("%s\n",__PRETTY_FUNCTION__); + // prepare buffer to send over SPI + spi_tx_buffer[0] = (0x80 | 0x1E); // [b7] Read/Write: 1 (read) + // [b6] RAM/Register : 1 (register) + // [b5-0] address: 0x1E (Manufacturer ID, Lower 16 Bit) + spi_tx_buffer[1] = 0x00; // send a SNOP strobe just to get the reg value + spi_tx_buffer[2] = 0x00; // send a SNOP strobe just to get the reg value + + // retrieve radio manufacturer ID over SPI + // spi_txrx(spi_tx_buffer, + // sizeof(spi_tx_buffer), + // SPI_BUFFER, + // spi_rx_buffer, + // sizeof(spi_rx_buffer), + // SPI_FIRST, + // SPI_LAST); + CSn_CLR(); + spi_transfer_bytes(SPI_0, spi_tx_buffer, spi_rx_buffer, 3); + CSn_SET(); + return spi_rx_buffer[2]; +} + +void radio_spiWriteReg(uint8_t reg_addr, uint8_t reg_setting) { + uint8_t spi_tx_buffer[2]; + uint8_t spi_rx_buffer[2]; + spi_tx_buffer[0] = (0xC0 | reg_addr); // turn addess in a 'reg write' address + spi_tx_buffer[1] = reg_setting; + + // spi_txrx(spi_tx_buffer, + // sizeof(spi_tx_buffer), + // SPI_BUFFER, + // (uint8_t*)spi_rx_buffer, + // sizeof(spi_rx_buffer), + // SPI_FIRST, + // SPI_LAST); + CSn_CLR(); + spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL); + spi_transfer_byte(SPI_0, spi_tx_buffer[1], NULL); + CSn_SET(); +} + +uint8_t radio_spiReadReg(uint8_t reg_addr) { + uint8_t spi_tx_buffer[2]; + uint8_t spi_rx_buffer[2]; + spi_tx_buffer[0] = (0x80 | reg_addr); // turn addess in a 'reg read' address + spi_tx_buffer[1] = 0x00; // send a no_operation command just to get the reg value + + // spi_txrx(spi_tx_buffer, + // sizeof(spi_tx_buffer), + // SPI_BUFFER, + // (uint8_t*)spi_rx_buffer, + // sizeof(spi_rx_buffer), + // SPI_FIRST, + // SPI_LAST); + CSn_CLR(); + spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL); + spi_transfer_byte(SPI_0, 0, spi_rx_buffer); + CSn_SET(); + + return spi_rx_buffer[0]; +} + +/** for testing purposes, remove if not needed anymore**/ + +void radio_spiWriteTxFifo(uint8_t* bufToWrite, uint8_t lenToWrite) { + uint8_t spi_tx_buffer[2]; + uint8_t spi_rx_buffer[1+1+127]; // 1B SPI address, 1B length, max. 127B data + DEBUG("%s\n",__PRETTY_FUNCTION__); + spi_tx_buffer[0] = 0x60; // SPI destination address for TXFIFO + spi_tx_buffer[1] = lenToWrite; // length byte + + CSn_CLR(); + spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL); + spi_transfer_byte(SPI_0, spi_tx_buffer[1], NULL); + spi_transfer_bytes(SPI_0, bufToWrite, NULL, lenToWrite); + CSn_SET(); + + // spi_txrx(spi_tx_buffer, + // sizeof(spi_tx_buffer), + // SPI_BUFFER, + // spi_rx_buffer, + // sizeof(spi_rx_buffer), + // SPI_FIRST, + // SPI_NOTLAST); + + // spi_txrx(bufToWrite, + // lenToWrite, + // SPI_BUFFER, + // spi_rx_buffer, + // sizeof(spi_rx_buffer), + // SPI_NOTFIRST, + // SPI_LAST); +} + + + +void radio_spiReadRxFifo(uint8_t* pBufRead, + uint8_t* pLenRead, + uint8_t maxBufLen, + uint8_t* pLqi) { + // when reading the packet over SPI from the RX buffer, you get the following: + // - *[1B] dummy byte because of SPI + // - *[1B] length byte + // - [0-125B] packet (excluding CRC) + // - *[2B] CRC + // - *[1B] LQI + uint8_t spi_tx_buffer[125]; + uint8_t spi_rx_buffer[3]; + DEBUG("%s\n",__PRETTY_FUNCTION__); + spi_tx_buffer[0] = 0x20; + + CSn_CLR(); + spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL); + spi_transfer_byte(SPI_0, 0, spi_rx_buffer); + // 2 first bytes + // spi_txrx(spi_tx_buffer, + // 2, + // SPI_BUFFER, + // spi_rx_buffer, + // sizeof(spi_rx_buffer), + // SPI_FIRST, + // SPI_NOTLAST); + + *pLenRead = spi_rx_buffer[0]; + + if (*pLenRead>2 && *pLenRead<=127) { + // valid length + spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL); + spi_transfer_bytes(SPI_0, NULL, pBufRead, *pLenRead); + + // //read packet + // spi_txrx(spi_tx_buffer, + // *pLenRead, + // SPI_BUFFER, + // pBufRead, + // 125, + // SPI_NOTFIRST, + // SPI_NOTLAST); + spi_transfer_byte(SPI_0, 0, 0); + spi_transfer_byte(SPI_0, 0, 0); + spi_transfer_byte(SPI_0, 0, pLqi); + // CRC (2B) and LQI (1B) + // spi_txrx(spi_tx_buffer, + // 2+1, + // SPI_BUFFER, + // spi_rx_buffer, + // 3, + // SPI_NOTFIRST, + // SPI_LAST); + + // *pLqi = spi_rx_buffer[2]; + + } else { + // invalid length + spi_transfer_byte(SPI_0, 0, 0); + // read a just byte to close spi + // spi_txrx(spi_tx_buffer, + // 1, + // SPI_BUFFER, + // spi_rx_buffer, + // sizeof(spi_rx_buffer), + // SPI_NOTFIRST, + // SPI_LAST); + } + CSn_SET(); +} + +//=========================== callbacks ======================================= + +//=========================== interrupt handlers ============================== + +kick_scheduler_t radio_isr(void) { + PORT_TIMER_WIDTH capturedTime; + uint8_t irq_status; + + // capture the time + capturedTime = radiotimer_getCapturedTime(); + + // reading IRQ_STATUS causes radio's IRQ pin to go low + irq_status = radio_spiReadReg(RG_IRQ_STATUS); + + // start of frame event + if (irq_status & AT_IRQ_RX_START) { + DEBUG("Start of frame.\n"); + // change state + radio_vars.state = RADIOSTATE_RECEIVING; + if (radio_vars.startFrame_cb!=NULL) { + // call the callback + radio_vars.startFrame_cb(capturedTime); + // kick the OS + return KICK_SCHEDULER; + } else { + while(1); + } + } + // end of frame event + if (irq_status & AT_IRQ_TRX_END) { + DEBUG("End of Frame.\n"); + // change state + radio_vars.state = RADIOSTATE_TXRX_DONE; + if (radio_vars.endFrame_cb!=NULL) { + // call the callback + radio_vars.endFrame_cb(capturedTime); + // kick the OS + return KICK_SCHEDULER; + } else { + while(1); + } + } + + return DO_NOT_KICK_SCHEDULER; +} \ No newline at end of file diff --git a/bsp/boards/riot-adaption/radiotimer.c b/bsp/boards/riot-adaption/radiotimer.c new file mode 100644 index 0000000..e9c0b54 --- /dev/null +++ b/bsp/boards/riot-adaption/radiotimer.c @@ -0,0 +1,155 @@ +/** +\brief openmoteSTM32 definition of the "radiotimer" bsp module. +On openmoteSTM32, we use RTC for the radiotimer module. +\author Thomas Watteyne , February 2012. +\author Chang Tengfei , July 2012. +*/ + +#include "stdint.h" + +#include "periph/timer.h" + +#include "leds.h" +#include "radiotimer.h" +#include "board_info.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + + +//=========================== variables ======================================= + +enum radiotimer_irqstatus_enum{ + RADIOTIMER_NONE = 0x00, //alarm interrupt default status + RADIOTIMER_OVERFLOW = 0x01, //alarm interrupt caused by overflow + RADIOTIMER_COMPARE = 0x02, //alarm interrupt caused by compare +}; + +typedef struct { + radiotimer_compare_cbt overflow_cb; + radiotimer_compare_cbt compare_cb; + uint8_t overflowORcompare;//indicate RTC alarm interrupt status + uint16_t currentSlotPeriod; +} radiotimer_vars_t; + +volatile radiotimer_vars_t radiotimer_vars; +uint16_t current_period; + +//=========================== prototypes ====================================== + +//=========================== public ========================================== + +//===== admin + +void radiotimer_init(void) { + // clear local variables + memset(&radiotimer_vars,0,sizeof(radiotimer_vars_t)); + current_period = 0; +} + +void radiotimer_setOverflowCb(radiotimer_compare_cbt cb) { + radiotimer_vars.overflow_cb = cb; +} + +void radiotimer_setCompareCb(radiotimer_compare_cbt cb) { + radiotimer_vars.compare_cb = cb; +} + +void radiotimer_setStartFrameCb(radiotimer_capture_cbt cb) { + while(1); +} + +void radiotimer_setEndFrameCb(radiotimer_capture_cbt cb) { + while(1); +} + +void radiotimer_start(uint16_t period) { + DEBUG("%s\n", __PRETTY_FUNCTION__); + timer_init(TIMER_1, 1, &radiotimer_isr); + timer_set(TIMER_1, 1, (0xffff)&((unsigned int)period)); + current_period = period; + radiotimer_vars.currentSlotPeriod = period; + radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW; +} + +//===== direct access + +uint16_t radiotimer_getValue(void) { + return (uint16_t)((0xffff)&timer_read(TIMER_1)); +} + +void radiotimer_setPeriod(uint16_t period) { + timer_set(TIMER_1, 1, (0xffff)&((unsigned int)period)); + current_period = period; + radiotimer_vars.currentSlotPeriod = period; + + //set radiotimer irpstatus + radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW; +} + +uint16_t radiotimer_getPeriod(void) { + return current_period; +} + +//===== compare + +void radiotimer_schedule(uint16_t offset) { + timer_irq_disable(TIMER_1); + timer_set(TIMER_1, 1, offset); + current_period = offset; + timer_irq_enable(TIMER_1); + //set radiotimer irpstatus + radiotimer_vars.overflowORcompare = RADIOTIMER_COMPARE; +} + +void radiotimer_cancel(void) { + timer_irq_disable(TIMER_1); + timer_clear(TIMER_1, 1); + current_period = 0; + timer_irq_enable(TIMER_1); + + //set radiotimer irpstatus + radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW; +} + +//===== capture + +inline uint16_t radiotimer_getCapturedTime(void) { + return (uint16_t)((0xffff)&timer_read(TIMER_1)); +} + +//=========================== private ========================================= + +//=========================== interrupt handlers ============================== + +kick_scheduler_t radiotimer_isr(void) { + uint8_t taiv_temp = radiotimer_vars.overflowORcompare; + switch (taiv_temp) { + case RADIOTIMER_COMPARE: + DEBUG("%s cmp\n", __PRETTY_FUNCTION__); + if (radiotimer_vars.compare_cb!=NULL) { + radiotimer_vars.compare_cb(); + // kick the OS + return KICK_SCHEDULER; + } + break; + case RADIOTIMER_OVERFLOW: // timer overflows + DEBUG("%s of\n", __PRETTY_FUNCTION__); + if (radiotimer_vars.overflow_cb!=NULL) { + //Wait until last write operation on RTC registers has finished + timer_reset(TIMER_1); + // call the callback + radiotimer_vars.overflow_cb(); + DEBUG("returned...\n"); + // kick the OS + return KICK_SCHEDULER; + } + break; + case RADIOTIMER_NONE: // this should not happen + DEBUG("%s none\n", __PRETTY_FUNCTION__); + default: + DEBUG("%s default\n", __PRETTY_FUNCTION__); + // while(1); // this should not happen + } + return DO_NOT_KICK_SCHEDULER; +} \ No newline at end of file diff --git a/bsp/boards/riot-adaption/spi_ow.c b/bsp/boards/riot-adaption/spi_ow.c new file mode 100644 index 0000000..56193f6 --- /dev/null +++ b/bsp/boards/riot-adaption/spi_ow.c @@ -0,0 +1,321 @@ +#include "stdio.h" +#include "stdint.h" +#include "string.h" +#include "spi_ow.h" +#include "spi.h" +#include "leds.h" +#include "board.h" +#include "radio.h" +#include "periph/gpio.h" +#include "periph_conf.h" +#include "at86rf231.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +//=========================== defines ========================================= + +//=========================== variables ======================================= + +typedef struct { + // information about the current transaction + uint8_t* pNextTxByte; + uint8_t numTxedBytes; + uint8_t txBytesLeft; + spi_return_t returnType; + uint8_t* pNextRxByte; + uint8_t maxRxBytes; + spi_first_t isFirst; + spi_last_t isLast; + // state of the module + uint8_t busy; +#ifdef SPI_IN_INTERRUPT_MODE + // callback when module done + spi_cbt callback; +#endif +} spi_vars_t; + +volatile spi_vars_t spi_vars; + +//=========================== prototypes ====================================== +// inline static void RESET_CLR(void) { GPIOC->BRR = 1<<1; } +// inline static void RESET_SET(void) { GPIOC->BSRR = 1<<1; } +// inline static void CSn_SET(void) { GPIOA->BSRR = 1<<4; } +// inline static void CSn_CLR(void) { GPIOA->BRR = 1<<4; } +// inline static void SLEEP_CLR(void) { GPIOA->BRR = 1<<2; } +static inline void RESET_CLR(void) +{ + SPI_0_RESET_PORT->BRR = (1 << SPI_0_RESET_PIN); +} +static inline void RESET_SET(void) +{ + SPI_0_RESET_PORT->BSRR = (1 << SPI_0_RESET_PIN); +} +static inline void CSn_SET(void) +{ + SPI_0_CS_PORT->BSRR = (1 << SPI_0_CS_PIN); +} +static inline void CSn_CLR(void) +{ + SPI_0_CS_PORT->BRR = (1 << SPI_0_CS_PIN); +} +static inline void SLEEP_CLR(void) +{ + SPI_0_SLEEP_PORT->BRR = (1 << SPI_0_SLEEP_PIN); +} + +//=========================== public ========================================== + +void spi_init_ow(void) { + // clear variables + memset(&spi_vars,0,sizeof(spi_vars_t)); + + /* set up GPIO pins */ + /* SCLK and MOSI*/ + GPIOA->CRL &= ~(0xf << (5 * 4)); + GPIOA->CRL |= (0xb << (5 * 4)); + GPIOA->CRL &= ~(0xf << (7 * 4)); + GPIOA->CRL |= (0xb << (7 * 4)); + /* MISO */ + gpio_init_in(SPI_0_MISO_GPIO, GPIO_NOPULL); + + /* SPI init */ + spi_init_master(SPI_0, SPI_CONF_FIRST_RISING, 4500000); + + spi_poweron(SPI_0); + + /* IRQ0 */ + gpio_init_in(SPI_0_IRQ0_GPIO, GPIO_NOPULL); + gpio_init_int(SPI_0_IRQ0_GPIO, GPIO_NOPULL, GPIO_RISING, radio_isr); + + /* Connect EXTI4 Line to PC4 pin */ + gpio_irq_enable(SPI_0_IRQ0_GPIO); + + /* CS */ + gpio_init_out(SPI_0_CS_GPIO, GPIO_NOPULL); + /* SLEEP */ + gpio_init_out(SPI_0_SLEEP_GPIO, GPIO_NOPULL); + /* RESET */ + gpio_init_out(SPI_0_RESET_GPIO, GPIO_NOPULL); + + // force reset + RESET_CLR(); + CSn_SET(); + SLEEP_CLR(); + + for (uint16_t j=0;j<0xFFFF;j++); //small wait + + RESET_SET(); + // /* set up GPIO pins */ + // /* SCLK and MOSI*/ + // GPIOA->CRL &= ~(0xf << (5 * 4)); + // GPIOA->CRL |= (0xb << (5 * 4)); + // GPIOA->CRL &= ~(0xf << (7 * 4)); + // GPIOA->CRL |= (0xb << (7 * 4)); + // /* MISO */ + // gpio_init_in(SPI_0_MISO_GPIO, GPIO_NOPULL); + + // /* SPI init */ + // spi_init_master(SPI_0, SPI_CONF_FIRST_RISING, 4500000); + + // spi_poweron(SPI_0); + + // /* IRQ0 */ + // gpio_init_in(SPI_0_IRQ0_GPIO, GPIO_NOPULL); + // gpio_init_int(SPI_0_IRQ0_GPIO, GPIO_NOPULL, GPIO_RISING, radio_isr); + + // /* Connect EXTI4 Line to PC4 pin */ + // gpio_irq_enable(SPI_0_IRQ0_GPIO); + + // /* CS */ + // gpio_init_out(SPI_0_CS_GPIO, GPIO_NOPULL); + // /* SLEEP */ + // gpio_init_out(SPI_0_SLEEP_GPIO, GPIO_NOPULL); + // /* RESET */ + // gpio_init_out(SPI_0_RESET_GPIO, GPIO_NOPULL); + + // /* force reset */ + // RESET_CLR(); + // CSn_SET(); + // SLEEP_CLR(); + + // vtimer_usleep(AT86RF231_TIMING__RESET); + + // RESET_SET(); + + // /* Wait until TRX_OFF is entered */ + // vtimer_usleep(AT86RF231_TIMING__RESET_TO_TRX_OFF); + + // /* Send a FORCE TRX OFF command */ + // at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__FORCE_TRX_OFF); + + // /* Wait until TRX_OFF state is entered from P_ON */ + // vtimer_usleep(AT86RF231_TIMING__SLEEP_TO_TRX_OFF); + + // /* busy wait for TRX_OFF state */ + // uint8_t status; + // uint8_t max_wait = 100; // TODO : move elsewhere, this is in 10us + + // do { + // status = at86rf231_get_status(); + + // vtimer_usleep(10); + + // if (!--max_wait) { + // printf("at86rf231 : ERROR : could not enter TRX_OFF mode\n"); + // break; + // } + // } while ((status & AT86RF231_TRX_STATUS_MASK__TRX_STATUS) + // != AT86RF231_TRX_STATUS__TRX_OFF); + +} + +#ifdef SPI_IN_INTERRUPT_MODE +void spi_setCallback(spi_cbt cb) { + spi_vars.callback = cb; +} +#endif + +void spi_txrx(uint8_t* bufTx, + uint8_t lenbufTx, + spi_return_t returnType, + uint8_t* bufRx, + uint8_t maxLenBufRx, + spi_first_t isFirst, + spi_last_t isLast) { + +#ifdef SPI_IN_INTERRUPT_MODE + // disable interrupts + NVIC_RESETPRIMASK(); +#endif + + // register spi frame to send + spi_vars.pNextTxByte = bufTx; + spi_vars.numTxedBytes = 0; + spi_vars.txBytesLeft = lenbufTx; + spi_vars.returnType = returnType; + spi_vars.pNextRxByte = bufRx; + spi_vars.maxRxBytes = maxLenBufRx; + spi_vars.isFirst = isFirst; + spi_vars.isLast = isLast; + + // SPI is now busy + spi_vars.busy = 1; + + + // lower CS signal to have slave listening + if (spi_vars.isFirst==SPI_FIRST) { + CSn_CLR(); + } + +#ifdef SPI_IN_INTERRUPT_MODE + // implementation 1. use a callback function when transaction finishes + + // write first byte to TX buffer + SPI_I2S_SendData(SPI1,*spi_vars.pNextTxByte); + + // re-enable interrupts + NVIC_SETPRIMASK(); +#else + // implementation 2. busy wait for each byte to be sent + // send all bytes + while (spi_vars.txBytesLeft>0) { + // write next byte to TX buffer + // SPI_I2S_SendData(SPI1,*spi_vars.pNextTxByte); + spi_transfer_byte(SPI_0, *((char*)spi_vars.pNextTxByte), NULL); + + // busy wait on the interrupt flag +// uint16_t c = 0; +// while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET) +// ;// if (c++ == 10000) { +// // //DEBUG("spi_txrx timeout\n"); +// // break; +// // } + +// // clear the interrupt flag +// SPI_I2S_ClearFlag(SPI1, SPI_I2S_FLAG_RXNE); + // save the byte just received in the RX buffer + switch (spi_vars.returnType) { + case SPI_FIRSTBYTE: + if (spi_vars.numTxedBytes==0) { + spi_transfer_byte(SPI_0, 0, (char*)spi_vars.pNextRxByte); + // *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1); + } + break; + case SPI_BUFFER: + spi_transfer_byte(SPI_0, 0, (char*)spi_vars.pNextRxByte); + // *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1); + spi_vars.pNextRxByte++; + break; + case SPI_LASTBYTE: + spi_transfer_byte(SPI_0, 0, (char*)spi_vars.pNextRxByte); + // *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1); + break; + } + // one byte less to go + spi_vars.pNextTxByte++; + spi_vars.numTxedBytes++; + spi_vars.txBytesLeft--; + } + + // put CS signal high to signal end of transmission to slave + if (spi_vars.isLast==SPI_LAST) { + CSn_SET(); + } + + // SPI is not busy anymore + spi_vars.busy = 0; +#endif +} + +//=========================== private ========================================= + +//=========================== interrupt handlers ============================== + +kick_scheduler_t spi_isr(void) { +#ifdef SPI_IN_INTERRUPT_MODE + // save the byte just received in the RX buffer + switch (spi_vars.returnType) { + case SPI_FIRSTBYTE: + if (spi_vars.numTxedBytes==0) { + *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1); + } + break; + case SPI_BUFFER: + *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1); + spi_vars.pNextRxByte++; + break; + case SPI_LASTBYTE: + *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1); + break; + } + + // one byte less to go + spi_vars.pNextTxByte++; + spi_vars.numTxedBytes++; + spi_vars.txBytesLeft--; + + if (spi_vars.txBytesLeft>0) { + // write next byte to TX buffer + SPI_SendData(SPI1,*spi_vars.pNextTxByte); + } else { + // put CS signal high to signal end of transmission to slave + if (spi_vars.isLast==SPI_LAST) { + GPIO_SetBits(GPIOA, GPIO_Pin_4); + } + // SPI is not busy anymore + spi_vars.busy = 0; + + // SPI is done! + if (spi_vars.callback!=NULL) { + // call the callback + spi_vars.callback(); + // kick the OS + return 1; + } + } +#else + while(1);// this should never happen + return 1; +#endif +} \ No newline at end of file diff --git a/bsp/boards/riot-adaption/uart_ow.c b/bsp/boards/riot-adaption/uart_ow.c new file mode 100644 index 0000000..c2bcb4f --- /dev/null +++ b/bsp/boards/riot-adaption/uart_ow.c @@ -0,0 +1,96 @@ +#include "uart_ow.h" +#include "leds.h" +#include "periph/uart.h" + +//=========================== defines ========================================= + +//=========================== variables ======================================= + +typedef struct { + uart_tx_cbt txCb; + uart_rx_cbt rxCb; + uint8_t startOrend; + uint8_t flagByte; +} uart_vars_t; + +volatile uart_vars_t uart_vars; + +//=========================== prototypes ====================================== + +//=========================== public ========================================== + +void uart_init_ow(void) +{ + // reset local variables + memset(&uart_vars,0,sizeof(uart_vars_t)); + + //when this value is 0, we are send the first data + uart_vars.startOrend = 0; + //flag byte for start byte and end byte + uart_vars.flagByte = 0x7E; +} + +void uart_setCallbacks(uart_tx_cbt txCb, uart_rx_cbt rxCb) +{ + uart_vars.txCb = txCb; + uart_vars.rxCb = rxCb; +} + +void uart_enableInterrupts(void) +{ + // USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); +} + +void uart_disableInterrupts(void) +{ + // USART_ITConfig(USART1, USART_IT_TXE, DISABLE); + // USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); +} + +void uart_clearRxInterrupts(void) +{ + // USART_ClearFlag(USART1, USART_FLAG_RXNE); +} + +void uart_clearTxInterrupts(void) +{ + // USART_ClearFlag(USART1, USART_FLAG_TXE); +} + +void uart_writeByte(uint8_t byteToWrite) +{ + // USART_SendData(USART1, byteToWrite); + // while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); + + // //start or end byte? + // if(byteToWrite == uart_vars.flagByte) { + // uart_vars.startOrend = (uart_vars.startOrend == 0)?1:0; + // //start byte + // if(uart_vars.startOrend == 1) { + // USART_ITConfig(USART1, USART_IT_TXE, ENABLE); + // } else { + // USART_ITConfig(USART1, USART_IT_TXE, DISABLE); + // } + // } +} + +uint8_t uart_readByte(void) +{ + // uint16_t temp; + // temp = USART_ReceiveData(USART1); + // return (uint8_t)temp; +} + +//=========================== interrupt handlers ============================== + +kick_scheduler_t uart_tx_isr(void) +{ + uart_vars.txCb(); + return DO_NOT_KICK_SCHEDULER; +} + +kick_scheduler_t uart_rx_isr(void) +{ + uart_vars.rxCb(); + return DO_NOT_KICK_SCHEDULER; +} \ No newline at end of file -- 2.2.0