Prototype RF driver for STM Sub-1 GHz RF expansion board based on the SPSGRF-868 module for STM32 Nucleo.

Prototype RF Driver for STM Sub-1 GHz RF Expansion Boards based on the SPSGRF-868 and SPSGRF-915 Modules for STM32 Nucleo

Currently supported boards:

Note, in order to use expansion board X-NUCLEO-IDS01A4 in mbed you need to perform the following HW modifications on the board:

  • Unmount resistor R4
  • Mount resistor R7

Furthermore, on some Nucleo development boards (e.g. the NUCLEO_F429ZI), in order to be able to use Ethernet together with these Sub-1 GHz RF expansion boards, you need to compile this driver with macro SPIRIT1_SPI_MOSI=PB_5 defined, while the development board typically requires some HW modification as e.g. described here!

This driver can be used together with the 6LoWPAN stack (a.k.a. Nanostack).

Committer:
Wolfgang Betz
Date:
Fri Oct 14 10:42:56 2016 +0200
Revision:
2:45642c5198a2
Parent:
0:4fb29d9ee571
Child:
3:0df38cfb1e53
Run thru initialization

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 0:4fb29d9ee571 1 /*** Mbed Includes ***/
Wolfgang Betz 0:4fb29d9ee571 2 #include "mbed.h"
Wolfgang Betz 0:4fb29d9ee571 3
Wolfgang Betz 0:4fb29d9ee571 4
Wolfgang Betz 0:4fb29d9ee571 5 /*** Cube Includes ***/
Wolfgang Betz 0:4fb29d9ee571 6 #include "SPIRIT_Radio.h"
Wolfgang Betz 0:4fb29d9ee571 7 #include "SPIRIT_Management.h"
Wolfgang Betz 0:4fb29d9ee571 8 #include "SPIRIT_Commands.h"
Wolfgang Betz 0:4fb29d9ee571 9 #include "MCU_Interface.h"
Wolfgang Betz 0:4fb29d9ee571 10
Wolfgang Betz 0:4fb29d9ee571 11
Wolfgang Betz 0:4fb29d9ee571 12 /*** Contiki Lib Includes ***/
Wolfgang Betz 0:4fb29d9ee571 13 #include "spirit1.h"
Wolfgang Betz 0:4fb29d9ee571 14 #include "st-lib.h"
Wolfgang Betz 0:4fb29d9ee571 15 #include "spirit1-config.h"
Wolfgang Betz 0:4fb29d9ee571 16 #include "spirit1-const.h"
Wolfgang Betz 0:4fb29d9ee571 17
Wolfgang Betz 0:4fb29d9ee571 18
Wolfgang Betz 0:4fb29d9ee571 19 /*** Missing Cube External Declarations ***/
Wolfgang Betz 0:4fb29d9ee571 20 extern "C" void SpiritManagementSetFrequencyBase(uint32_t);
Wolfgang Betz 0:4fb29d9ee571 21
Wolfgang Betz 0:4fb29d9ee571 22
Wolfgang Betz 0:4fb29d9ee571 23 /*** A Simple Spirit1 Class ***/
Wolfgang Betz 0:4fb29d9ee571 24 class SimpleSpirit1 { // NOTE: must be a singleton (due to mix of MBED/CUBE code)!!!
Wolfgang Betz 0:4fb29d9ee571 25 protected:
Wolfgang Betz 0:4fb29d9ee571 26 static SimpleSpirit1 *_singleton;
Wolfgang Betz 0:4fb29d9ee571 27
Wolfgang Betz 0:4fb29d9ee571 28 /** Communication Interface Instance Variables **/
Wolfgang Betz 2:45642c5198a2 29 SPI _spi; // betzw - NOTE: Arduino pins are valid only for NUCLEO-F401RE
Wolfgang Betz 0:4fb29d9ee571 30 // mosi: PA_7 (D11)
Wolfgang Betz 0:4fb29d9ee571 31 // miso: PA_6 (D12)
Wolfgang Betz 0:4fb29d9ee571 32 // sclk: PB_3 (D3) or
Wolfgang Betz 0:4fb29d9ee571 33 // PA_5 (D13) (only in case you unmount R4 & mount R7,
Wolfgang Betz 0:4fb29d9ee571 34 // (note: in this case you may not use LED1 on some platforms)
Wolfgang Betz 0:4fb29d9ee571 35 // bits: 8-bit
Wolfgang Betz 0:4fb29d9ee571 36 // mode: 0
Wolfgang Betz 0:4fb29d9ee571 37 // ordr: MSB
Wolfgang Betz 0:4fb29d9ee571 38 // freq: max 10MHz
Wolfgang Betz 2:45642c5198a2 39 InterruptIn _irq; // PC_7 (D9) (falling)
Wolfgang Betz 2:45642c5198a2 40 DigitalOut _chip_select; // PB_6 (D10) ('1' == chip unselected)
Wolfgang Betz 2:45642c5198a2 41 DigitalOut _shut_down; // PA_10 (D2) ('1' == shut_down)
Wolfgang Betz 2:45642c5198a2 42 DigitalOut _led; // PB_4 (D5) (optional)
Wolfgang Betz 0:4fb29d9ee571 43
Wolfgang Betz 0:4fb29d9ee571 44 /** Static Variables from Cube Implementation **/
Wolfgang Betz 0:4fb29d9ee571 45 /*
Wolfgang Betz 0:4fb29d9ee571 46 * The buffers which hold incoming data.
Wolfgang Betz 0:4fb29d9ee571 47 * The +1 because of the first byte,
Wolfgang Betz 0:4fb29d9ee571 48 * which will contain the length of the packet.
Wolfgang Betz 0:4fb29d9ee571 49 */
Wolfgang Betz 0:4fb29d9ee571 50 uint8_t spirit_rxbuf[MAX_PACKET_LEN+1];
Wolfgang Betz 0:4fb29d9ee571 51 uint8_t spirit_txbuf[MAX_PACKET_LEN+1-SPIRIT_MAX_FIFO_LEN];
Wolfgang Betz 0:4fb29d9ee571 52 volatile unsigned int spirit_on;
Wolfgang Betz 0:4fb29d9ee571 53
Wolfgang Betz 0:4fb29d9ee571 54
Wolfgang Betz 0:4fb29d9ee571 55 /** Low Level Instance Variables **/
Wolfgang Betz 0:4fb29d9ee571 56 unsigned int _nr_of_irq_disables;
Wolfgang Betz 0:4fb29d9ee571 57
Wolfgang Betz 0:4fb29d9ee571 58 /** Low Level Ins
Wolfgang Betz 0:4fb29d9ee571 59 return *_singleton;
Wolfgang Betz 0:4fb29d9ee571 60 * tance Methods **/
Wolfgang Betz 0:4fb29d9ee571 61 void disable_irq(void) {
Wolfgang Betz 0:4fb29d9ee571 62 _irq.disable_irq();
Wolfgang Betz 0:4fb29d9ee571 63 _nr_of_irq_disables++;
Wolfgang Betz 0:4fb29d9ee571 64 MBED_ASSERT(_nr_of_irq_disables != 0);
Wolfgang Betz 0:4fb29d9ee571 65 }
Wolfgang Betz 0:4fb29d9ee571 66
Wolfgang Betz 0:4fb29d9ee571 67 void enable_irq(void) {
Wolfgang Betz 0:4fb29d9ee571 68 MBED_ASSERT(_nr_of_irq_disables > 0);
Wolfgang Betz 0:4fb29d9ee571 69 if(--_nr_of_irq_disables == 0)
Wolfgang Betz 0:4fb29d9ee571 70 _irq.enable_irq();
Wolfgang Betz 0:4fb29d9ee571 71 }
Wolfgang Betz 0:4fb29d9ee571 72
Wolfgang Betz 0:4fb29d9ee571 73 void chip_select() { _chip_select = 0; }
Wolfgang Betz 0:4fb29d9ee571 74 void chip_unselect() { _chip_select = 1; }
Wolfgang Betz 0:4fb29d9ee571 75
Wolfgang Betz 0:4fb29d9ee571 76 void enter_shutdown() { _shut_down = 1; }
Wolfgang Betz 0:4fb29d9ee571 77 void exit_shutdown() {
Wolfgang Betz 0:4fb29d9ee571 78 _shut_down = 0;
Wolfgang Betz 0:4fb29d9ee571 79 wait_ms(2); // wait two milliseconds (to allow Spirit1 a proper boot-up sequence)
Wolfgang Betz 0:4fb29d9ee571 80 }
Wolfgang Betz 0:4fb29d9ee571 81
Wolfgang Betz 0:4fb29d9ee571 82 void cs_to_sclk_delay(void) {
Wolfgang Betz 0:4fb29d9ee571 83 wait_us(1); // heuristic value
Wolfgang Betz 0:4fb29d9ee571 84 }
Wolfgang Betz 0:4fb29d9ee571 85
Wolfgang Betz 0:4fb29d9ee571 86 /** Radio Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 87 void radio_set_xtal_freq(uint32_t freq) {
Wolfgang Betz 0:4fb29d9ee571 88 SpiritRadioSetXtalFrequency(freq);
Wolfgang Betz 0:4fb29d9ee571 89 }
Wolfgang Betz 0:4fb29d9ee571 90
Wolfgang Betz 0:4fb29d9ee571 91 void radio_set_pa_level_dbm(uint8_t cIndex, float fPowerdBm) {
Wolfgang Betz 0:4fb29d9ee571 92 SpiritRadioSetPALeveldBm(cIndex, fPowerdBm);
Wolfgang Betz 0:4fb29d9ee571 93 }
Wolfgang Betz 0:4fb29d9ee571 94
Wolfgang Betz 0:4fb29d9ee571 95 void radio_set_pa_level_max_index(uint8_t cIndex) {
Wolfgang Betz 0:4fb29d9ee571 96 SpiritRadioSetPALevelMaxIndex(cIndex);
Wolfgang Betz 0:4fb29d9ee571 97 }
Wolfgang Betz 0:4fb29d9ee571 98
Wolfgang Betz 0:4fb29d9ee571 99 uint8_t radio_init(SRadioInit *init_struct) {
Wolfgang Betz 0:4fb29d9ee571 100 return SpiritRadioInit(init_struct);
Wolfgang Betz 0:4fb29d9ee571 101 }
Wolfgang Betz 0:4fb29d9ee571 102
Wolfgang Betz 0:4fb29d9ee571 103 void radio_persisten_rx(SpiritFunctionalState xNewState) {
Wolfgang Betz 0:4fb29d9ee571 104 SpiritRadioPersistenRx(xNewState);
Wolfgang Betz 0:4fb29d9ee571 105 }
Wolfgang Betz 0:4fb29d9ee571 106
Wolfgang Betz 0:4fb29d9ee571 107 void radio_afc_freeze_on_sync(SpiritFunctionalState xNewState) {
Wolfgang Betz 0:4fb29d9ee571 108 SpiritRadioAFCFreezeOnSync(xNewState);
Wolfgang Betz 0:4fb29d9ee571 109 }
Wolfgang Betz 0:4fb29d9ee571 110
Wolfgang Betz 0:4fb29d9ee571 111 /** Packet System Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 112 void pkt_basic_init(PktBasicInit* pxPktBasicInit) {
Wolfgang Betz 0:4fb29d9ee571 113 SpiritPktBasicInit(pxPktBasicInit);
Wolfgang Betz 0:4fb29d9ee571 114 }
Wolfgang Betz 0:4fb29d9ee571 115
Wolfgang Betz 0:4fb29d9ee571 116 /** IRQ Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 117 void irq_de_init(SpiritIrqs* pxIrqInit) {
Wolfgang Betz 0:4fb29d9ee571 118 SpiritIrqDeInit(pxIrqInit);
Wolfgang Betz 0:4fb29d9ee571 119 }
Wolfgang Betz 0:4fb29d9ee571 120
Wolfgang Betz 0:4fb29d9ee571 121 void irq_clear_status(void) {
Wolfgang Betz 0:4fb29d9ee571 122 SpiritIrqClearStatus();
Wolfgang Betz 0:4fb29d9ee571 123 }
Wolfgang Betz 0:4fb29d9ee571 124
Wolfgang Betz 0:4fb29d9ee571 125 void irq_set_status(IrqList xIrq, SpiritFunctionalState xNewState) {
Wolfgang Betz 0:4fb29d9ee571 126 SpiritIrq(xIrq, xNewState);
Wolfgang Betz 0:4fb29d9ee571 127 }
Wolfgang Betz 0:4fb29d9ee571 128
Wolfgang Betz 0:4fb29d9ee571 129 /** Management Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 130 void mgmt_set_freq_base(uint32_t freq) {
Wolfgang Betz 0:4fb29d9ee571 131 SpiritManagementSetFrequencyBase(freq);
Wolfgang Betz 0:4fb29d9ee571 132 }
Wolfgang Betz 0:4fb29d9ee571 133
Wolfgang Betz 0:4fb29d9ee571 134 /** Spirit GPIO Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 135 void spirit_gpio_init(SGpioInit* pxGpioInitStruct) {
Wolfgang Betz 0:4fb29d9ee571 136 SpiritGpioInit(pxGpioInitStruct);
Wolfgang Betz 0:4fb29d9ee571 137 }
Wolfgang Betz 0:4fb29d9ee571 138
Wolfgang Betz 0:4fb29d9ee571 139 /** Qi Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 140 void qi_set_sqi_threshold(SqiThreshold xSqiThr) {
Wolfgang Betz 0:4fb29d9ee571 141 SpiritQiSetSqiThreshold(xSqiThr);
Wolfgang Betz 0:4fb29d9ee571 142 }
Wolfgang Betz 0:4fb29d9ee571 143
Wolfgang Betz 0:4fb29d9ee571 144 void qi_sqi_check(SpiritFunctionalState xNewState) {
Wolfgang Betz 0:4fb29d9ee571 145 SpiritQiSqiCheck(xNewState);
Wolfgang Betz 0:4fb29d9ee571 146 }
Wolfgang Betz 0:4fb29d9ee571 147
Wolfgang Betz 0:4fb29d9ee571 148 void qi_set_rssi_threshold_dbm(int nDbmValue) {
Wolfgang Betz 0:4fb29d9ee571 149 SpiritQiSetRssiThresholddBm(nDbmValue);
Wolfgang Betz 0:4fb29d9ee571 150 }
Wolfgang Betz 0:4fb29d9ee571 151
Wolfgang Betz 0:4fb29d9ee571 152 /** Timer Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 153 void timer_set_rx_timeout_stop_condition(RxTimeoutStopCondition xStopCondition) {
Wolfgang Betz 0:4fb29d9ee571 154 SpiritTimerSetRxTimeoutStopCondition(xStopCondition);
Wolfgang Betz 0:4fb29d9ee571 155 }
Wolfgang Betz 0:4fb29d9ee571 156
Wolfgang Betz 0:4fb29d9ee571 157 void timer_set_rx_timeout_counter(uint8_t cCounter) {
Wolfgang Betz 0:4fb29d9ee571 158 SpiritTimerSetRxTimeoutCounter(cCounter);
Wolfgang Betz 0:4fb29d9ee571 159 }
Wolfgang Betz 0:4fb29d9ee571 160
Wolfgang Betz 0:4fb29d9ee571 161 void timer_set_infinite_rx_timeout(void) {
Wolfgang Betz 0:4fb29d9ee571 162 timer_set_rx_timeout_counter(0);
Wolfgang Betz 0:4fb29d9ee571 163 }
Wolfgang Betz 0:4fb29d9ee571 164
Wolfgang Betz 0:4fb29d9ee571 165 /** Command Instance Methods**/
Wolfgang Betz 0:4fb29d9ee571 166 void cmd_strobe_command(uint8_t cmd) {
Wolfgang Betz 0:4fb29d9ee571 167 SpiritCmdStrobeCommand((SpiritCmd)cmd);
Wolfgang Betz 0:4fb29d9ee571 168 }
Wolfgang Betz 0:4fb29d9ee571 169
Wolfgang Betz 0:4fb29d9ee571 170 /** Friend Functions **/
Wolfgang Betz 0:4fb29d9ee571 171 friend StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 172 friend StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 173 friend StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
Wolfgang Betz 0:4fb29d9ee571 174 friend StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 175 friend StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 176
Wolfgang Betz 0:4fb29d9ee571 177 /** Sdk Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 178 StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 179 StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 180 StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
Wolfgang Betz 0:4fb29d9ee571 181 StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 182 StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 0:4fb29d9ee571 183
Wolfgang Betz 0:4fb29d9ee571 184 /** Helper Instance Methods **/
Wolfgang Betz 0:4fb29d9ee571 185 void chip_sync_select() {
Wolfgang Betz 0:4fb29d9ee571 186 disable_irq();
Wolfgang Betz 0:4fb29d9ee571 187 chip_select();
Wolfgang Betz 0:4fb29d9ee571 188 cs_to_sclk_delay();
Wolfgang Betz 0:4fb29d9ee571 189 }
Wolfgang Betz 0:4fb29d9ee571 190
Wolfgang Betz 0:4fb29d9ee571 191 void chip_sync_unselect() {
Wolfgang Betz 0:4fb29d9ee571 192 chip_unselect();
Wolfgang Betz 0:4fb29d9ee571 193 enable_irq();
Wolfgang Betz 0:4fb29d9ee571 194 }
Wolfgang Betz 0:4fb29d9ee571 195
Wolfgang Betz 2:45642c5198a2 196 /** Init Instance Method **/
Wolfgang Betz 2:45642c5198a2 197 void init(void);
Wolfgang Betz 2:45642c5198a2 198
Wolfgang Betz 0:4fb29d9ee571 199 /** Constructor **/
Wolfgang Betz 0:4fb29d9ee571 200 SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
Wolfgang Betz 0:4fb29d9ee571 201 PinName irq, PinName cs, PinName sdn,
Wolfgang Betz 0:4fb29d9ee571 202 PinName led);
Wolfgang Betz 0:4fb29d9ee571 203
Wolfgang Betz 0:4fb29d9ee571 204 /** Destructor **/
Wolfgang Betz 0:4fb29d9ee571 205 ~SimpleSpirit1(void); // should never be called!
Wolfgang Betz 0:4fb29d9ee571 206
Wolfgang Betz 0:4fb29d9ee571 207 public:
Wolfgang Betz 0:4fb29d9ee571 208 static SimpleSpirit1& CreateInstance(PinName mosi, PinName miso, PinName sclk,
Wolfgang Betz 0:4fb29d9ee571 209 PinName irq, PinName cs, PinName sdn,
Wolfgang Betz 0:4fb29d9ee571 210 PinName led = NC) {
Wolfgang Betz 0:4fb29d9ee571 211
Wolfgang Betz 0:4fb29d9ee571 212 if(_singleton == NULL) {
Wolfgang Betz 0:4fb29d9ee571 213 _singleton = new SimpleSpirit1(mosi, miso, sclk,
Wolfgang Betz 0:4fb29d9ee571 214 irq, cs, sdn, led);
Wolfgang Betz 2:45642c5198a2 215 _singleton->init();
Wolfgang Betz 0:4fb29d9ee571 216 } else {
Wolfgang Betz 2:45642c5198a2 217 error("SimpleSpirit1 singleton already created!\n");
Wolfgang Betz 0:4fb29d9ee571 218 }
Wolfgang Betz 0:4fb29d9ee571 219
Wolfgang Betz 0:4fb29d9ee571 220 return *_singleton;
Wolfgang Betz 0:4fb29d9ee571 221 }
Wolfgang Betz 0:4fb29d9ee571 222
Wolfgang Betz 0:4fb29d9ee571 223 static SimpleSpirit1& Instance() {
Wolfgang Betz 0:4fb29d9ee571 224 if(_singleton == NULL) {
Wolfgang Betz 2:45642c5198a2 225 error("SimpleSpirit1 must be created before used!\n");
Wolfgang Betz 0:4fb29d9ee571 226 }
Wolfgang Betz 0:4fb29d9ee571 227
Wolfgang Betz 0:4fb29d9ee571 228 return *_singleton;
Wolfgang Betz 0:4fb29d9ee571 229 }
Wolfgang Betz 0:4fb29d9ee571 230
Wolfgang Betz 0:4fb29d9ee571 231 /** Attach a function to be called when a SPI interrupt occurs
Wolfgang Betz 0:4fb29d9ee571 232 *
Wolfgang Betz 0:4fb29d9ee571 233 * @param func A pointer to a void function, or 0 to set as none
Wolfgang Betz 0:4fb29d9ee571 234 *
Wolfgang Betz 0:4fb29d9ee571 235 * @note Function 'func' will be executed in interrupt context!
Wolfgang Betz 0:4fb29d9ee571 236 * @note This function enables the SPI interrupt!
Wolfgang Betz 0:4fb29d9ee571 237 */
Wolfgang Betz 0:4fb29d9ee571 238 void attach_irq(Callback<void()> &func) {
Wolfgang Betz 0:4fb29d9ee571 239 _irq.fall(func);
Wolfgang Betz 0:4fb29d9ee571 240 enable_irq();
Wolfgang Betz 0:4fb29d9ee571 241 }
Wolfgang Betz 0:4fb29d9ee571 242 };