JunMo Hong / stm-spirit1-rf-driver_for_cubebite

Fork of EV-COG-AD3029LZ by JunMo Hong

Committer:
Wolfgang Betz
Date:
Tue Oct 18 07:06:12 2016 +0200
Revision:
4:07537ca85c66
Parent:
3:0df38cfb1e53
Child:
5:c9c5bc673c64
Backup commit (with spirit lib as it was)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 0:4fb29d9ee571 1 /*** Mbed Includes ***/
Wolfgang Betz 0:4fb29d9ee571 2 #include "SimpleSpirit1.h"
Wolfgang Betz 3:0df38cfb1e53 3 #include "radio_spi.h"
Wolfgang Betz 0:4fb29d9ee571 4
Wolfgang Betz 0:4fb29d9ee571 5
Wolfgang Betz 0:4fb29d9ee571 6 /*** Macros from Cube Implementation ***/
Wolfgang Betz 4:07537ca85c66 7 #define CLEAR_TXBUF() (spirit_tx_len = 0)
Wolfgang Betz 4:07537ca85c66 8 #define CLEAR_RXBUF() (spirit_rx_len = 0)
Wolfgang Betz 4:07537ca85c66 9 #define IS_RXBUF_EMPTY() (spirit_rx_len == 0)
Wolfgang Betz 0:4fb29d9ee571 10
Wolfgang Betz 3:0df38cfb1e53 11 #ifndef NDEBUG
Wolfgang Betz 3:0df38cfb1e53 12 #include <stdio.h>
Wolfgang Betz 3:0df38cfb1e53 13 #define PRINTF(...) printf(__VA_ARGS__)
Wolfgang Betz 3:0df38cfb1e53 14 #else
Wolfgang Betz 3:0df38cfb1e53 15 #define PRINTF(...)
Wolfgang Betz 3:0df38cfb1e53 16 #endif
Wolfgang Betz 0:4fb29d9ee571 17
Wolfgang Betz 3:0df38cfb1e53 18 #if NULLRDC_CONF_802154_AUTOACK
Wolfgang Betz 3:0df38cfb1e53 19 #define ACK_LEN 3
Wolfgang Betz 3:0df38cfb1e53 20 static int wants_an_ack = 0; /* The packet sent expects an ack */
Wolfgang Betz 3:0df38cfb1e53 21 //#define ACKPRINTF printf
Wolfgang Betz 3:0df38cfb1e53 22 #define ACKPRINTF(...)
Wolfgang Betz 3:0df38cfb1e53 23 #endif /* NULLRDC_CONF_802154_AUTOACK */
Wolfgang Betz 3:0df38cfb1e53 24
Wolfgang Betz 4:07537ca85c66 25 #define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_3)
Wolfgang Betz 3:0df38cfb1e53 26
Wolfgang Betz 4:07537ca85c66 27 #define SPIRIT1_STATUS() (arch_refresh_status() & SPIRIT1_STATE_STATEBITS)
Wolfgang Betz 3:0df38cfb1e53 28
Wolfgang Betz 4:07537ca85c66 29 #define SABORT_WAIT_US (400)
Wolfgang Betz 3:0df38cfb1e53 30
Wolfgang Betz 3:0df38cfb1e53 31 #define BUSYWAIT_UNTIL(cond, millisecs) \
Wolfgang Betz 3:0df38cfb1e53 32 do { \
Wolfgang Betz 4:07537ca85c66 33 uint32_t start = _busywait_timer.read_us(); \
Wolfgang Betz 4:07537ca85c66 34 while (!(cond) && ((((uint32_t)(_busywait_timer.read_us())) - start) < ((uint32_t)millisecs)*1000U)); \
Wolfgang Betz 3:0df38cfb1e53 35 } while(0)
Wolfgang Betz 3:0df38cfb1e53 36
Wolfgang Betz 4:07537ca85c66 37 extern volatile SpiritStatus g_xStatus;
Wolfgang Betz 4:07537ca85c66 38 #define st_lib_g_x_status (g_xStatus)
Wolfgang Betz 4:07537ca85c66 39
Wolfgang Betz 4:07537ca85c66 40 #define st_lib_spirit_irqs SpiritIrqs
Wolfgang Betz 4:07537ca85c66 41
Wolfgang Betz 0:4fb29d9ee571 42
Wolfgang Betz 0:4fb29d9ee571 43 /*** Class Implementation ***/
Wolfgang Betz 3:0df38cfb1e53 44 /** Static Class Variables **/
Wolfgang Betz 3:0df38cfb1e53 45 SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
Wolfgang Betz 3:0df38cfb1e53 46 Timer SimpleSpirit1::_busywait_timer;
Wolfgang Betz 3:0df38cfb1e53 47
Wolfgang Betz 3:0df38cfb1e53 48 /** Constructor **/
Wolfgang Betz 0:4fb29d9ee571 49 SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
Wolfgang Betz 0:4fb29d9ee571 50 PinName irq, PinName cs, PinName sdn,
Wolfgang Betz 0:4fb29d9ee571 51 PinName led) :
Wolfgang Betz 0:4fb29d9ee571 52 _spi(mosi, miso, sclk),
Wolfgang Betz 0:4fb29d9ee571 53 _irq(irq),
Wolfgang Betz 0:4fb29d9ee571 54 _chip_select(cs),
Wolfgang Betz 0:4fb29d9ee571 55 _shut_down(sdn),
Wolfgang Betz 4:07537ca85c66 56 _led(led),
Wolfgang Betz 4:07537ca85c66 57 _current_irq_callback()
Wolfgang Betz 0:4fb29d9ee571 58 {
Wolfgang Betz 3:0df38cfb1e53 59 /* reset irq disable counter and irq callback & disable irq */
Wolfgang Betz 3:0df38cfb1e53 60 _nr_of_irq_disables = 0;
Wolfgang Betz 4:07537ca85c66 61 disable_spirit_irq();
Wolfgang Betz 0:4fb29d9ee571 62
Wolfgang Betz 0:4fb29d9ee571 63 /* unselect chip */
Wolfgang Betz 0:4fb29d9ee571 64 chip_unselect();
Wolfgang Betz 0:4fb29d9ee571 65
Wolfgang Betz 0:4fb29d9ee571 66 /* configure spi */
Wolfgang Betz 0:4fb29d9ee571 67 _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
Wolfgang Betz 0:4fb29d9ee571 68 _spi.frequency(5000000); // 5MHz
Wolfgang Betz 3:0df38cfb1e53 69
Wolfgang Betz 3:0df38cfb1e53 70 /* start timer */
Wolfgang Betz 3:0df38cfb1e53 71 _busywait_timer.start();
Wolfgang Betz 3:0df38cfb1e53 72
Wolfgang Betz 3:0df38cfb1e53 73 /* init cube vars */
Wolfgang Betz 3:0df38cfb1e53 74 spirit_on = OFF;
Wolfgang Betz 3:0df38cfb1e53 75 packet_is_prepared = 0;
Wolfgang Betz 3:0df38cfb1e53 76 receiving_packet = 0;
Wolfgang Betz 3:0df38cfb1e53 77 just_got_an_ack = 0;
Wolfgang Betz 4:07537ca85c66 78 last_rssi = 0 ; //MGR
Wolfgang Betz 4:07537ca85c66 79 last_lqi = 0 ; //MGR
Wolfgang Betz 2:45642c5198a2 80 }
Wolfgang Betz 0:4fb29d9ee571 81
Wolfgang Betz 3:0df38cfb1e53 82 /** Init Function **/
Wolfgang Betz 2:45642c5198a2 83 void SimpleSpirit1::init() {
Wolfgang Betz 0:4fb29d9ee571 84 /* set frequencies */
Wolfgang Betz 0:4fb29d9ee571 85 radio_set_xtal_freq(XTAL_FREQUENCY);
Wolfgang Betz 2:45642c5198a2 86 mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
Wolfgang Betz 0:4fb29d9ee571 87
Wolfgang Betz 0:4fb29d9ee571 88 /* restart board */
Wolfgang Betz 0:4fb29d9ee571 89 enter_shutdown();
Wolfgang Betz 0:4fb29d9ee571 90 exit_shutdown();
Wolfgang Betz 0:4fb29d9ee571 91
Wolfgang Betz 0:4fb29d9ee571 92 /* soft core reset */
Wolfgang Betz 4:07537ca85c66 93 cmd_strobe(SPIRIT1_STROBE_SRES);
Wolfgang Betz 0:4fb29d9ee571 94
Wolfgang Betz 0:4fb29d9ee571 95 /* Configures the SPIRIT1 radio part */
Wolfgang Betz 0:4fb29d9ee571 96 SRadioInit x_radio_init = {
Wolfgang Betz 0:4fb29d9ee571 97 XTAL_OFFSET_PPM,
Wolfgang Betz 0:4fb29d9ee571 98 (uint32_t)BASE_FREQUENCY,
Wolfgang Betz 0:4fb29d9ee571 99 (uint32_t)CHANNEL_SPACE,
Wolfgang Betz 0:4fb29d9ee571 100 CHANNEL_NUMBER,
Wolfgang Betz 0:4fb29d9ee571 101 MODULATION_SELECT,
Wolfgang Betz 0:4fb29d9ee571 102 DATARATE,
Wolfgang Betz 0:4fb29d9ee571 103 (uint32_t)FREQ_DEVIATION,
Wolfgang Betz 0:4fb29d9ee571 104 (uint32_t)BANDWIDTH
Wolfgang Betz 0:4fb29d9ee571 105 };
Wolfgang Betz 0:4fb29d9ee571 106 radio_init(&x_radio_init);
Wolfgang Betz 0:4fb29d9ee571 107 radio_set_pa_level_dbm(0,POWER_DBM);
Wolfgang Betz 0:4fb29d9ee571 108 radio_set_pa_level_max_index(0);
Wolfgang Betz 0:4fb29d9ee571 109
Wolfgang Betz 0:4fb29d9ee571 110 /* Configures the SPIRIT1 packet handler part*/
Wolfgang Betz 0:4fb29d9ee571 111 PktBasicInit x_basic_init = {
Wolfgang Betz 0:4fb29d9ee571 112 PREAMBLE_LENGTH,
Wolfgang Betz 0:4fb29d9ee571 113 SYNC_LENGTH,
Wolfgang Betz 0:4fb29d9ee571 114 SYNC_WORD,
Wolfgang Betz 0:4fb29d9ee571 115 LENGTH_TYPE,
Wolfgang Betz 0:4fb29d9ee571 116 LENGTH_WIDTH,
Wolfgang Betz 0:4fb29d9ee571 117 CRC_MODE,
Wolfgang Betz 0:4fb29d9ee571 118 CONTROL_LENGTH,
Wolfgang Betz 0:4fb29d9ee571 119 EN_ADDRESS,
Wolfgang Betz 0:4fb29d9ee571 120 EN_FEC,
Wolfgang Betz 0:4fb29d9ee571 121 EN_WHITENING
Wolfgang Betz 0:4fb29d9ee571 122 };
Wolfgang Betz 0:4fb29d9ee571 123 pkt_basic_init(&x_basic_init);
Wolfgang Betz 0:4fb29d9ee571 124
Wolfgang Betz 0:4fb29d9ee571 125 /* Enable the following interrupt sources, routed to GPIO */
Wolfgang Betz 0:4fb29d9ee571 126 irq_de_init(NULL);
Wolfgang Betz 0:4fb29d9ee571 127 irq_clear_status();
Wolfgang Betz 0:4fb29d9ee571 128 irq_set_status(TX_DATA_SENT, S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 129 irq_set_status(RX_DATA_READY,S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 130 irq_set_status(VALID_SYNC,S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 131 irq_set_status(RX_DATA_DISC, S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 132 irq_set_status(TX_FIFO_ERROR, S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 133 irq_set_status(RX_FIFO_ERROR, S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 134
Wolfgang Betz 0:4fb29d9ee571 135 /* Configure Spirit1 */
Wolfgang Betz 0:4fb29d9ee571 136 radio_persisten_rx(S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 137 qi_set_sqi_threshold(SQI_TH_0);
Wolfgang Betz 0:4fb29d9ee571 138 qi_sqi_check(S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 139 qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
Wolfgang Betz 0:4fb29d9ee571 140 timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
Wolfgang Betz 0:4fb29d9ee571 141 timer_set_infinite_rx_timeout();
Wolfgang Betz 0:4fb29d9ee571 142 radio_afc_freeze_on_sync(S_ENABLE);
Wolfgang Betz 0:4fb29d9ee571 143
Wolfgang Betz 0:4fb29d9ee571 144 /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
Wolfgang Betz 4:07537ca85c66 145 cmd_strobe(SPIRIT1_STROBE_STANDBY);
Wolfgang Betz 0:4fb29d9ee571 146 spirit_on = OFF;
Wolfgang Betz 0:4fb29d9ee571 147 CLEAR_RXBUF();
Wolfgang Betz 0:4fb29d9ee571 148 CLEAR_TXBUF();
Wolfgang Betz 0:4fb29d9ee571 149
Wolfgang Betz 0:4fb29d9ee571 150 /* Configure the radio to route the IRQ signal to its GPIO 3 */
Wolfgang Betz 0:4fb29d9ee571 151 SGpioInit x_gpio_init = {
Wolfgang Betz 0:4fb29d9ee571 152 SPIRIT_GPIO_IRQ,
Wolfgang Betz 0:4fb29d9ee571 153 SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
Wolfgang Betz 0:4fb29d9ee571 154 SPIRIT_GPIO_DIG_OUT_IRQ
Wolfgang Betz 0:4fb29d9ee571 155 };
Wolfgang Betz 0:4fb29d9ee571 156 spirit_gpio_init(&x_gpio_init);
Wolfgang Betz 0:4fb29d9ee571 157 }
Wolfgang Betz 3:0df38cfb1e53 158
Wolfgang Betz 3:0df38cfb1e53 159 /** Prepare the radio with a packet to be sent. **/
Wolfgang Betz 3:0df38cfb1e53 160 int SimpleSpirit1::prepare(const void *payload, unsigned short payload_len) {
Wolfgang Betz 3:0df38cfb1e53 161 PRINTF("Spirit1: prep %u\n", payload_len);
Wolfgang Betz 3:0df38cfb1e53 162 packet_is_prepared = 0;
Wolfgang Betz 3:0df38cfb1e53 163
Wolfgang Betz 3:0df38cfb1e53 164 /* Checks if the payload length is supported */
Wolfgang Betz 3:0df38cfb1e53 165 if(payload_len > MAX_PACKET_LEN) {
Wolfgang Betz 3:0df38cfb1e53 166 return RADIO_TX_ERR;
Wolfgang Betz 3:0df38cfb1e53 167 }
Wolfgang Betz 3:0df38cfb1e53 168
Wolfgang Betz 3:0df38cfb1e53 169 /* Should we delay for an ack? */
Wolfgang Betz 3:0df38cfb1e53 170 #if NULLRDC_CONF_802154_AUTOACK
Wolfgang Betz 3:0df38cfb1e53 171 frame802154_t info154;
Wolfgang Betz 3:0df38cfb1e53 172 wants_an_ack = 0;
Wolfgang Betz 3:0df38cfb1e53 173 if(payload_len > ACK_LEN
Wolfgang Betz 3:0df38cfb1e53 174 && frame802154_parse((char*)payload, payload_len, &info154) != 0) {
Wolfgang Betz 3:0df38cfb1e53 175 if(info154.fcf.frame_type == FRAME802154_DATAFRAME
Wolfgang Betz 3:0df38cfb1e53 176 && info154.fcf.ack_required != 0) {
Wolfgang Betz 3:0df38cfb1e53 177 wants_an_ack = 1;
Wolfgang Betz 3:0df38cfb1e53 178 }
Wolfgang Betz 3:0df38cfb1e53 179 }
Wolfgang Betz 3:0df38cfb1e53 180 #endif /* NULLRDC_CONF_802154_AUTOACK */
Wolfgang Betz 3:0df38cfb1e53 181
Wolfgang Betz 3:0df38cfb1e53 182 /* Sets the length of the packet to send */
Wolfgang Betz 4:07537ca85c66 183 disable_spirit_irq();
Wolfgang Betz 4:07537ca85c66 184 cmd_strobe(SPIRIT1_STROBE_FTX);
Wolfgang Betz 3:0df38cfb1e53 185 pkt_basic_set_payload_length(payload_len);
Wolfgang Betz 3:0df38cfb1e53 186 spi_write_linear_fifo(payload_len, (uint8_t *)payload);
Wolfgang Betz 4:07537ca85c66 187 enable_spirit_irq();
Wolfgang Betz 3:0df38cfb1e53 188
Wolfgang Betz 3:0df38cfb1e53 189 PRINTF("PREPARE OUT\n");
Wolfgang Betz 3:0df38cfb1e53 190
Wolfgang Betz 3:0df38cfb1e53 191 packet_is_prepared = 1;
Wolfgang Betz 3:0df38cfb1e53 192 return RADIO_TX_OK;
Wolfgang Betz 3:0df38cfb1e53 193 }
Wolfgang Betz 3:0df38cfb1e53 194
Wolfgang Betz 3:0df38cfb1e53 195 /** Send the packet that has previously been prepared. **/
Wolfgang Betz 3:0df38cfb1e53 196 int SimpleSpirit1::transmit(unsigned short payload_len) {
Wolfgang Betz 3:0df38cfb1e53 197 /* This function blocks until the packet has been transmitted */
Wolfgang Betz 3:0df38cfb1e53 198 //rtimer_clock_t rtimer_txdone, rtimer_rxack;
Wolfgang Betz 3:0df38cfb1e53 199
Wolfgang Betz 3:0df38cfb1e53 200 PRINTF("TRANSMIT IN\n");
Wolfgang Betz 3:0df38cfb1e53 201 if(!packet_is_prepared) {
Wolfgang Betz 3:0df38cfb1e53 202 return RADIO_TX_ERR;
Wolfgang Betz 3:0df38cfb1e53 203 }
Wolfgang Betz 3:0df38cfb1e53 204
Wolfgang Betz 3:0df38cfb1e53 205 /* Stores the length of the packet to send */
Wolfgang Betz 3:0df38cfb1e53 206 /* Others spirit_radio_prepare will be in hold */
Wolfgang Betz 4:07537ca85c66 207 spirit_tx_len = payload_len;
Wolfgang Betz 3:0df38cfb1e53 208
Wolfgang Betz 3:0df38cfb1e53 209 /* Puts the SPIRIT1 in TX state */
Wolfgang Betz 3:0df38cfb1e53 210 receiving_packet = 0;
Wolfgang Betz 3:0df38cfb1e53 211 set_ready_state();
Wolfgang Betz 4:07537ca85c66 212 cmd_strobe(SPIRIT1_STROBE_TX);
Wolfgang Betz 3:0df38cfb1e53 213 just_got_an_ack = 0;
Wolfgang Betz 3:0df38cfb1e53 214 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_TX, 1);
Wolfgang Betz 3:0df38cfb1e53 215 //BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 4); //For GFSK with high data rate
Wolfgang Betz 3:0df38cfb1e53 216 BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 50); //For FSK with low data rate
Wolfgang Betz 3:0df38cfb1e53 217
Wolfgang Betz 3:0df38cfb1e53 218 /* Reset radio - needed for immediate RX of ack */
Wolfgang Betz 3:0df38cfb1e53 219 CLEAR_TXBUF();
Wolfgang Betz 3:0df38cfb1e53 220 CLEAR_RXBUF();
Wolfgang Betz 4:07537ca85c66 221 disable_spirit_irq();
Wolfgang Betz 3:0df38cfb1e53 222 irq_clear_status();
Wolfgang Betz 4:07537ca85c66 223 cmd_strobe(SPIRIT1_STROBE_SABORT);
Wolfgang Betz 3:0df38cfb1e53 224 wait_us(SABORT_WAIT_US);
Wolfgang Betz 4:07537ca85c66 225 cmd_strobe(SPIRIT1_STROBE_READY);
Wolfgang Betz 3:0df38cfb1e53 226 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 1);
Wolfgang Betz 4:07537ca85c66 227 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 3:0df38cfb1e53 228 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 1);
Wolfgang Betz 4:07537ca85c66 229 enable_spirit_irq();
Wolfgang Betz 3:0df38cfb1e53 230
Wolfgang Betz 3:0df38cfb1e53 231 #if XXX_ACK_WORKAROUND
Wolfgang Betz 3:0df38cfb1e53 232 just_got_an_ack = 1;
Wolfgang Betz 3:0df38cfb1e53 233 #endif /* XXX_ACK_WORKAROUND */
Wolfgang Betz 3:0df38cfb1e53 234
Wolfgang Betz 3:0df38cfb1e53 235 #if NULLRDC_CONF_802154_AUTOACK
Wolfgang Betz 3:0df38cfb1e53 236 if (wants_an_ack) {
Wolfgang Betz 4:07537ca85c66 237 rtimer_txdone = _busywait_timer.read_us();
Wolfgang Betz 3:0df38cfb1e53 238 BUSYWAIT_UNTIL(just_got_an_ack, 2);
Wolfgang Betz 4:07537ca85c66 239 rtimer_rxack = _busywait_timer.read_us();
Wolfgang Betz 3:0df38cfb1e53 240
Wolfgang Betz 3:0df38cfb1e53 241 if(just_got_an_ack) {
Wolfgang Betz 4:07537ca85c66 242 ACKPRINTF("debug_ack: ack received after %u us\n",
Wolfgang Betz 3:0df38cfb1e53 243 (uint32_t)(rtimer_rxack - rtimer_txdone));
Wolfgang Betz 3:0df38cfb1e53 244 } else {
Wolfgang Betz 3:0df38cfb1e53 245 ACKPRINTF("debug_ack: no ack received\n");
Wolfgang Betz 3:0df38cfb1e53 246 }
Wolfgang Betz 3:0df38cfb1e53 247 }
Wolfgang Betz 3:0df38cfb1e53 248 #endif /* NULLRDC_CONF_802154_AUTOACK */
Wolfgang Betz 3:0df38cfb1e53 249
Wolfgang Betz 3:0df38cfb1e53 250 PRINTF("TRANSMIT OUT\n");
Wolfgang Betz 3:0df38cfb1e53 251
Wolfgang Betz 3:0df38cfb1e53 252 CLEAR_TXBUF();
Wolfgang Betz 3:0df38cfb1e53 253
Wolfgang Betz 3:0df38cfb1e53 254 packet_is_prepared = 0;
Wolfgang Betz 3:0df38cfb1e53 255
Wolfgang Betz 3:0df38cfb1e53 256 wait_us(1);
Wolfgang Betz 3:0df38cfb1e53 257
Wolfgang Betz 3:0df38cfb1e53 258 return RADIO_TX_OK;
Wolfgang Betz 3:0df38cfb1e53 259 }
Wolfgang Betz 3:0df38cfb1e53 260
Wolfgang Betz 3:0df38cfb1e53 261 /** Set Ready State **/
Wolfgang Betz 3:0df38cfb1e53 262 void SimpleSpirit1::set_ready_state(void) {
Wolfgang Betz 3:0df38cfb1e53 263 PRINTF("READY IN\n");
Wolfgang Betz 3:0df38cfb1e53 264
Wolfgang Betz 3:0df38cfb1e53 265 irq_clear_status();
Wolfgang Betz 4:07537ca85c66 266 disable_spirit_irq();
Wolfgang Betz 3:0df38cfb1e53 267
Wolfgang Betz 3:0df38cfb1e53 268 if(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY) {
Wolfgang Betz 4:07537ca85c66 269 cmd_strobe(SPIRIT1_STROBE_READY);
Wolfgang Betz 3:0df38cfb1e53 270 } else if(SPIRIT1_STATUS() == SPIRIT1_STATE_RX) {
Wolfgang Betz 4:07537ca85c66 271 cmd_strobe(SPIRIT1_STROBE_SABORT);
Wolfgang Betz 3:0df38cfb1e53 272 irq_clear_status();
Wolfgang Betz 3:0df38cfb1e53 273 }
Wolfgang Betz 3:0df38cfb1e53 274
Wolfgang Betz 4:07537ca85c66 275 enable_spirit_irq();
Wolfgang Betz 3:0df38cfb1e53 276
Wolfgang Betz 3:0df38cfb1e53 277 PRINTF("READY OUT\n");
Wolfgang Betz 3:0df38cfb1e53 278 }
Wolfgang Betz 3:0df38cfb1e53 279
Wolfgang Betz 4:07537ca85c66 280 int SimpleSpirit1::off(void) {
Wolfgang Betz 3:0df38cfb1e53 281 PRINTF("Spirit1: ->off\n");
Wolfgang Betz 3:0df38cfb1e53 282 if(spirit_on == ON) {
Wolfgang Betz 3:0df38cfb1e53 283 /* Disables the mcu to get IRQ from the SPIRIT1 */
Wolfgang Betz 4:07537ca85c66 284 disable_spirit_irq();
Wolfgang Betz 3:0df38cfb1e53 285
Wolfgang Betz 3:0df38cfb1e53 286 /* first stop rx/tx */
Wolfgang Betz 4:07537ca85c66 287 cmd_strobe(SPIRIT1_STROBE_SABORT);
Wolfgang Betz 3:0df38cfb1e53 288
Wolfgang Betz 3:0df38cfb1e53 289 /* Clear any pending irqs */
Wolfgang Betz 3:0df38cfb1e53 290 irq_clear_status();
Wolfgang Betz 3:0df38cfb1e53 291
Wolfgang Betz 3:0df38cfb1e53 292 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 5);
Wolfgang Betz 3:0df38cfb1e53 293 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
Wolfgang Betz 3:0df38cfb1e53 294 PRINTF("Spirit1: failed off->ready\n");
Wolfgang Betz 3:0df38cfb1e53 295 return 1;
Wolfgang Betz 3:0df38cfb1e53 296 }
Wolfgang Betz 3:0df38cfb1e53 297
Wolfgang Betz 3:0df38cfb1e53 298 /* Puts the SPIRIT1 in STANDBY */
Wolfgang Betz 4:07537ca85c66 299 cmd_strobe(SPIRIT1_STROBE_STANDBY);
Wolfgang Betz 3:0df38cfb1e53 300 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, 5);
Wolfgang Betz 3:0df38cfb1e53 301 if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
Wolfgang Betz 3:0df38cfb1e53 302 PRINTF("Spirit1: failed off->standby\n");
Wolfgang Betz 3:0df38cfb1e53 303 return 1;
Wolfgang Betz 3:0df38cfb1e53 304 }
Wolfgang Betz 3:0df38cfb1e53 305
Wolfgang Betz 3:0df38cfb1e53 306 spirit_on = OFF;
Wolfgang Betz 4:07537ca85c66 307 _nr_of_irq_disables = 1;
Wolfgang Betz 3:0df38cfb1e53 308 CLEAR_TXBUF();
Wolfgang Betz 3:0df38cfb1e53 309 CLEAR_RXBUF();
Wolfgang Betz 3:0df38cfb1e53 310 }
Wolfgang Betz 3:0df38cfb1e53 311 PRINTF("Spirit1: off.\n");
Wolfgang Betz 3:0df38cfb1e53 312 return 0;
Wolfgang Betz 3:0df38cfb1e53 313 }
Wolfgang Betz 3:0df38cfb1e53 314
Wolfgang Betz 4:07537ca85c66 315 int SimpleSpirit1::on(void) {
Wolfgang Betz 3:0df38cfb1e53 316 PRINTF("Spirit1: on\n");
Wolfgang Betz 4:07537ca85c66 317 cmd_strobe(SPIRIT1_STROBE_SABORT);
Wolfgang Betz 3:0df38cfb1e53 318 wait_us(SABORT_WAIT_US);
Wolfgang Betz 3:0df38cfb1e53 319 if(spirit_on == OFF) {
Wolfgang Betz 3:0df38cfb1e53 320 /* ensure we are in READY state as we go from there to Rx */
Wolfgang Betz 4:07537ca85c66 321 cmd_strobe(SPIRIT1_STROBE_READY);
Wolfgang Betz 3:0df38cfb1e53 322 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 5);
Wolfgang Betz 3:0df38cfb1e53 323 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
Wolfgang Betz 3:0df38cfb1e53 324 PRINTF("Spirit1: failed to turn on\n");
Wolfgang Betz 3:0df38cfb1e53 325 while(1);
Wolfgang Betz 3:0df38cfb1e53 326 //return 1;
Wolfgang Betz 3:0df38cfb1e53 327 }
Wolfgang Betz 3:0df38cfb1e53 328
Wolfgang Betz 3:0df38cfb1e53 329 /* now we go to Rx */
Wolfgang Betz 4:07537ca85c66 330 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 3:0df38cfb1e53 331 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 5);
Wolfgang Betz 3:0df38cfb1e53 332 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
Wolfgang Betz 3:0df38cfb1e53 333 PRINTF("Spirit1: failed to enter rx\n");
Wolfgang Betz 3:0df38cfb1e53 334 while(1);
Wolfgang Betz 3:0df38cfb1e53 335 //return 1;
Wolfgang Betz 3:0df38cfb1e53 336 }
Wolfgang Betz 3:0df38cfb1e53 337
Wolfgang Betz 3:0df38cfb1e53 338 /* Enables the mcu to get IRQ from the SPIRIT1 */
Wolfgang Betz 3:0df38cfb1e53 339 spirit_on = ON;
Wolfgang Betz 4:07537ca85c66 340 if(_current_irq_callback) {
Wolfgang Betz 4:07537ca85c66 341 MBED_ASSERT(_nr_of_irq_disables == 1);
Wolfgang Betz 4:07537ca85c66 342 enable_spirit_irq();
Wolfgang Betz 3:0df38cfb1e53 343 }
Wolfgang Betz 3:0df38cfb1e53 344 }
Wolfgang Betz 3:0df38cfb1e53 345
Wolfgang Betz 3:0df38cfb1e53 346 return 0;
Wolfgang Betz 3:0df38cfb1e53 347 }
Wolfgang Betz 3:0df38cfb1e53 348
Wolfgang Betz 3:0df38cfb1e53 349 uint16_t SimpleSpirit1::arch_refresh_status(void) {
Wolfgang Betz 3:0df38cfb1e53 350 uint16_t mcstate;
Wolfgang Betz 3:0df38cfb1e53 351 uint8_t header[2];
Wolfgang Betz 3:0df38cfb1e53 352 header[0]=READ_HEADER;
Wolfgang Betz 3:0df38cfb1e53 353 header[1]=MC_STATE1_BASE;
Wolfgang Betz 3:0df38cfb1e53 354
Wolfgang Betz 3:0df38cfb1e53 355 /* Puts the SPI chip select low to start the transaction */
Wolfgang Betz 3:0df38cfb1e53 356 chip_sync_select();
Wolfgang Betz 3:0df38cfb1e53 357
Wolfgang Betz 3:0df38cfb1e53 358 /* Write the aHeader bytes and read the SPIRIT1 status bytes */
Wolfgang Betz 3:0df38cfb1e53 359 mcstate = _spi.write(header[0]);
Wolfgang Betz 3:0df38cfb1e53 360 mcstate = mcstate<<8;
Wolfgang Betz 3:0df38cfb1e53 361
Wolfgang Betz 3:0df38cfb1e53 362 /* Write the aHeader bytes and read the SPIRIT1 status bytes */
Wolfgang Betz 3:0df38cfb1e53 363 mcstate |= _spi.write(header[1]);
Wolfgang Betz 3:0df38cfb1e53 364
Wolfgang Betz 3:0df38cfb1e53 365 /* Puts the SPI chip select high to end the transaction */
Wolfgang Betz 3:0df38cfb1e53 366 chip_sync_unselect();
Wolfgang Betz 3:0df38cfb1e53 367
Wolfgang Betz 3:0df38cfb1e53 368 return mcstate;
Wolfgang Betz 3:0df38cfb1e53 369 }
Wolfgang Betz 3:0df38cfb1e53 370
Wolfgang Betz 4:07537ca85c66 371 int SimpleSpirit1::read(void *buf, unsigned short bufsize)
Wolfgang Betz 4:07537ca85c66 372 {
Wolfgang Betz 4:07537ca85c66 373 PRINTF("READ IN\n");
Wolfgang Betz 4:07537ca85c66 374
Wolfgang Betz 4:07537ca85c66 375 /* Checks if the RX buffer is empty */
Wolfgang Betz 4:07537ca85c66 376 if(IS_RXBUF_EMPTY()) {
Wolfgang Betz 4:07537ca85c66 377 disable_spirit_irq();
Wolfgang Betz 4:07537ca85c66 378 CLEAR_RXBUF();
Wolfgang Betz 4:07537ca85c66 379 cmd_strobe(SPIRIT1_STROBE_SABORT);
Wolfgang Betz 4:07537ca85c66 380 wait_us(SABORT_WAIT_US);
Wolfgang Betz 4:07537ca85c66 381 cmd_strobe(SPIRIT1_STROBE_READY);
Wolfgang Betz 4:07537ca85c66 382 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 1);
Wolfgang Betz 4:07537ca85c66 383 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 4:07537ca85c66 384 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 1);
Wolfgang Betz 4:07537ca85c66 385 PRINTF("READ OUT RX BUF EMPTY\n");
Wolfgang Betz 4:07537ca85c66 386 enable_spirit_irq();
Wolfgang Betz 4:07537ca85c66 387 return 0;
Wolfgang Betz 4:07537ca85c66 388 }
Wolfgang Betz 4:07537ca85c66 389
Wolfgang Betz 4:07537ca85c66 390 if(bufsize < spirit_rx_len) {
Wolfgang Betz 4:07537ca85c66 391 /* If buf has the correct size */
Wolfgang Betz 4:07537ca85c66 392 PRINTF("TOO SMALL BUF\n");
Wolfgang Betz 4:07537ca85c66 393 return 0;
Wolfgang Betz 4:07537ca85c66 394 } else {
Wolfgang Betz 4:07537ca85c66 395 /* Copies the packet received */
Wolfgang Betz 4:07537ca85c66 396 memcpy(buf, spirit_rx_buf, spirit_rx_len);
Wolfgang Betz 4:07537ca85c66 397
Wolfgang Betz 4:07537ca85c66 398 #ifdef CONTIKI // betzw - TODO
Wolfgang Betz 4:07537ca85c66 399 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi); //MGR
Wolfgang Betz 4:07537ca85c66 400 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, last_lqi); //MGR
Wolfgang Betz 4:07537ca85c66 401 #endif
Wolfgang Betz 4:07537ca85c66 402
Wolfgang Betz 4:07537ca85c66 403 bufsize = spirit_rx_len;
Wolfgang Betz 4:07537ca85c66 404 CLEAR_RXBUF();
Wolfgang Betz 4:07537ca85c66 405
Wolfgang Betz 4:07537ca85c66 406 PRINTF("READ OUT\n");
Wolfgang Betz 4:07537ca85c66 407
Wolfgang Betz 4:07537ca85c66 408 return bufsize;
Wolfgang Betz 4:07537ca85c66 409 }
Wolfgang Betz 4:07537ca85c66 410
Wolfgang Betz 4:07537ca85c66 411 }
Wolfgang Betz 4:07537ca85c66 412
Wolfgang Betz 4:07537ca85c66 413 /*---------------------------------------------------------------------------*/
Wolfgang Betz 4:07537ca85c66 414 int SimpleSpirit1::channel_clear(void)
Wolfgang Betz 4:07537ca85c66 415 {
Wolfgang Betz 4:07537ca85c66 416 float rssi_value;
Wolfgang Betz 4:07537ca85c66 417 /* Local variable used to memorize the SPIRIT1 state */
Wolfgang Betz 4:07537ca85c66 418 uint8_t spirit_state = ON;
Wolfgang Betz 4:07537ca85c66 419
Wolfgang Betz 4:07537ca85c66 420 PRINTF("CHANNEL CLEAR IN\n");
Wolfgang Betz 4:07537ca85c66 421
Wolfgang Betz 4:07537ca85c66 422 if(spirit_on == OFF) {
Wolfgang Betz 4:07537ca85c66 423 /* Wakes up the SPIRIT1 */
Wolfgang Betz 4:07537ca85c66 424 on();
Wolfgang Betz 4:07537ca85c66 425 spirit_state = OFF;
Wolfgang Betz 4:07537ca85c66 426 }
Wolfgang Betz 4:07537ca85c66 427
Wolfgang Betz 4:07537ca85c66 428 /* */
Wolfgang Betz 4:07537ca85c66 429 disable_spirit_irq();
Wolfgang Betz 4:07537ca85c66 430 cmd_strobe(SPIRIT1_STROBE_SABORT);
Wolfgang Betz 4:07537ca85c66 431 /* SpiritCmdStrobeSabort();*/
Wolfgang Betz 4:07537ca85c66 432 irq_clear_status();
Wolfgang Betz 4:07537ca85c66 433 enable_spirit_irq();
Wolfgang Betz 4:07537ca85c66 434 {
Wolfgang Betz 4:07537ca85c66 435 uint32_t timeout = _busywait_timer.read_us() + 5000;
Wolfgang Betz 4:07537ca85c66 436 do {
Wolfgang Betz 4:07537ca85c66 437 mgmt_refresh_status();
Wolfgang Betz 4:07537ca85c66 438 } while((st_lib_g_x_status.MC_STATE != MC_STATE_READY) && (((uint32_t)_busywait_timer.read_us()) < timeout));
Wolfgang Betz 4:07537ca85c66 439 if(st_lib_g_x_status.MC_STATE != MC_STATE_READY) {
Wolfgang Betz 4:07537ca85c66 440 return 1;
Wolfgang Betz 4:07537ca85c66 441 }
Wolfgang Betz 4:07537ca85c66 442 }
Wolfgang Betz 4:07537ca85c66 443
Wolfgang Betz 4:07537ca85c66 444 /* Stores the RSSI value */
Wolfgang Betz 4:07537ca85c66 445 rssi_value = qi_get_rssi_dbm();
Wolfgang Betz 4:07537ca85c66 446
Wolfgang Betz 4:07537ca85c66 447 /* Puts the SPIRIT1 in its previous state */
Wolfgang Betz 4:07537ca85c66 448 if(spirit_state==OFF) {
Wolfgang Betz 4:07537ca85c66 449 off();
Wolfgang Betz 4:07537ca85c66 450 } else {
Wolfgang Betz 4:07537ca85c66 451 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 4:07537ca85c66 452 /* SpiritCmdStrobeRx();*/
Wolfgang Betz 4:07537ca85c66 453 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 5);
Wolfgang Betz 4:07537ca85c66 454 }
Wolfgang Betz 4:07537ca85c66 455
Wolfgang Betz 4:07537ca85c66 456 PRINTF("CHANNEL CLEAR OUT\n");
Wolfgang Betz 4:07537ca85c66 457
Wolfgang Betz 4:07537ca85c66 458 /* Checks the RSSI value with the threshold */
Wolfgang Betz 4:07537ca85c66 459 if(rssi_value<CCA_THRESHOLD) {
Wolfgang Betz 4:07537ca85c66 460 return 0;
Wolfgang Betz 4:07537ca85c66 461 } else {
Wolfgang Betz 4:07537ca85c66 462 return 1;
Wolfgang Betz 4:07537ca85c66 463 }
Wolfgang Betz 4:07537ca85c66 464 }
Wolfgang Betz 4:07537ca85c66 465
Wolfgang Betz 4:07537ca85c66 466 int SimpleSpirit1::incoming_packet(void)
Wolfgang Betz 4:07537ca85c66 467 {
Wolfgang Betz 4:07537ca85c66 468 return receiving_packet;
Wolfgang Betz 4:07537ca85c66 469 }
Wolfgang Betz 4:07537ca85c66 470
Wolfgang Betz 4:07537ca85c66 471 int SimpleSpirit1::pending_packet(void)
Wolfgang Betz 4:07537ca85c66 472 {
Wolfgang Betz 4:07537ca85c66 473 PRINTF("PENDING PACKET\n");
Wolfgang Betz 4:07537ca85c66 474 return !IS_RXBUF_EMPTY();
Wolfgang Betz 4:07537ca85c66 475 }
Wolfgang Betz 4:07537ca85c66 476
Wolfgang Betz 4:07537ca85c66 477 /** Contiki Irq Callback **/
Wolfgang Betz 4:07537ca85c66 478 void SimpleSpirit1::ContikiIrqHandler() {
Wolfgang Betz 4:07537ca85c66 479 st_lib_spirit_irqs x_irq_status;
Wolfgang Betz 4:07537ca85c66 480
Wolfgang Betz 4:07537ca85c66 481 /* get interrupt source from radio */
Wolfgang Betz 4:07537ca85c66 482 irq_get_status(&x_irq_status);
Wolfgang Betz 4:07537ca85c66 483 irq_clear_status();
Wolfgang Betz 4:07537ca85c66 484
Wolfgang Betz 4:07537ca85c66 485 if(x_irq_status.IRQ_RX_FIFO_ERROR) {
Wolfgang Betz 4:07537ca85c66 486 receiving_packet = 0;
Wolfgang Betz 4:07537ca85c66 487 cmd_strobe(SPIRIT1_STROBE_FRX);
Wolfgang Betz 4:07537ca85c66 488 return;
Wolfgang Betz 4:07537ca85c66 489 }
Wolfgang Betz 4:07537ca85c66 490
Wolfgang Betz 4:07537ca85c66 491 if(x_irq_status.IRQ_TX_FIFO_ERROR) {
Wolfgang Betz 4:07537ca85c66 492 receiving_packet = 0;
Wolfgang Betz 4:07537ca85c66 493 cmd_strobe(SPIRIT1_STROBE_FTX);
Wolfgang Betz 4:07537ca85c66 494 return;
Wolfgang Betz 4:07537ca85c66 495 }
Wolfgang Betz 4:07537ca85c66 496
Wolfgang Betz 4:07537ca85c66 497 /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
Wolfgang Betz 4:07537ca85c66 498 if(x_irq_status.IRQ_VALID_SYNC) {
Wolfgang Betz 4:07537ca85c66 499 receiving_packet = 1;
Wolfgang Betz 4:07537ca85c66 500 }
Wolfgang Betz 4:07537ca85c66 501
Wolfgang Betz 4:07537ca85c66 502 /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
Wolfgang Betz 4:07537ca85c66 503 if(x_irq_status.IRQ_TX_DATA_SENT) {
Wolfgang Betz 4:07537ca85c66 504 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 4:07537ca85c66 505 /* SpiritCmdStrobeRx();*/
Wolfgang Betz 4:07537ca85c66 506 CLEAR_TXBUF();
Wolfgang Betz 4:07537ca85c66 507 return;
Wolfgang Betz 4:07537ca85c66 508 }
Wolfgang Betz 4:07537ca85c66 509
Wolfgang Betz 4:07537ca85c66 510 /* The IRQ_RX_DATA_READY notifies a new packet arrived */
Wolfgang Betz 4:07537ca85c66 511 if(x_irq_status.IRQ_RX_DATA_READY) {
Wolfgang Betz 4:07537ca85c66 512 spi_read_linear_fifo(linear_fifo_read_num_elements_rx_fifo(), spirit_rx_buf);
Wolfgang Betz 4:07537ca85c66 513 spirit_rx_len = pkt_basic_get_received_pkt_length();
Wolfgang Betz 4:07537ca85c66 514 cmd_strobe(SPIRIT1_STROBE_FRX);
Wolfgang Betz 4:07537ca85c66 515
Wolfgang Betz 4:07537ca85c66 516 last_rssi = qi_get_rssi(); //MGR
Wolfgang Betz 4:07537ca85c66 517 last_lqi = qi_get_lqi(); //MGR
Wolfgang Betz 4:07537ca85c66 518
Wolfgang Betz 4:07537ca85c66 519 receiving_packet = 0;
Wolfgang Betz 4:07537ca85c66 520
Wolfgang Betz 4:07537ca85c66 521 #if NULLRDC_CONF_802154_AUTOACK
Wolfgang Betz 4:07537ca85c66 522 if (spirit_rxbuf[0] == ACK_LEN) {
Wolfgang Betz 4:07537ca85c66 523 /* For debugging purposes we assume this is an ack for us */
Wolfgang Betz 4:07537ca85c66 524 just_got_an_ack = 1;
Wolfgang Betz 4:07537ca85c66 525 }
Wolfgang Betz 4:07537ca85c66 526 #endif /* NULLRDC_CONF_802154_AUTOACK */
Wolfgang Betz 4:07537ca85c66 527
Wolfgang Betz 4:07537ca85c66 528 /* betzw - TODO: call user callback */
Wolfgang Betz 4:07537ca85c66 529 return;
Wolfgang Betz 4:07537ca85c66 530 }
Wolfgang Betz 4:07537ca85c66 531
Wolfgang Betz 4:07537ca85c66 532 if(x_irq_status.IRQ_RX_DATA_DISC)
Wolfgang Betz 4:07537ca85c66 533 {
Wolfgang Betz 4:07537ca85c66 534 /* RX command - to ensure the device will be ready for the next reception */
Wolfgang Betz 4:07537ca85c66 535 if(x_irq_status.IRQ_RX_TIMEOUT) {
Wolfgang Betz 4:07537ca85c66 536 cmd_strobe_flush_rx_fifo();
Wolfgang Betz 4:07537ca85c66 537 }
Wolfgang Betz 4:07537ca85c66 538 }
Wolfgang Betz 4:07537ca85c66 539 }