1 #include <twr_spirit1.h>
2 #include <twr_scheduler.h>
4 #include <twr_system.h>
7 #include <SPIRIT_Config.h>
8 #include <SDK_Configuration_Common.h>
9 #include <MCU_Interface.h>
13 TWR_SPIRIT1_STATE_INIT = 0,
14 TWR_SPIRIT1_STATE_SLEEP = 1,
15 TWR_SPIRIT1_STATE_TX = 2,
16 TWR_SPIRIT1_STATE_RX = 3
18 } twr_spirit1_state_t;
22 int initialized_semaphore;
26 twr_spirit1_state_t desired_state;
27 twr_spirit1_state_t current_state;
28 uint8_t tx_buffer[TWR_SPIRIT1_MAX_PACKET_SIZE];
30 uint8_t rx_buffer[TWR_SPIRIT1_MAX_PACKET_SIZE];
40 #define XTAL_FREQUENCY 50000000
42 SRadioInit xRadioInit = {
53 PktBasicInit xBasicInit={
66 PktBasicAddressesInit xAddressInit={
69 EN_FILT_MULTICAST_ADDRESS,
71 EN_FILT_BROADCAST_ADDRESS,
77 SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
78 SPIRIT_GPIO_DIG_OUT_IRQ
81 static void _twr_spirit1_enter_state_tx(
void);
82 static void _twr_spirit1_check_state_tx(
void);
83 static void _twr_spirit1_enter_state_rx(
void);
84 static void _twr_spirit1_check_state_rx(
void);
85 static void _twr_spirit1_enter_state_sleep(
void);
87 void twr_spirit1_hal_chip_select_low(
void);
88 void twr_spirit1_hal_chip_select_high(
void);
89 uint8_t twr_spirit1_hal_transfer_byte(uint8_t value);
90 static void twr_spirit1_hal_init_gpio(
void);
91 static void twr_spirit1_hal_deinit_gpio(
void);
92 static void twr_spirit1_hal_init_spi(
void);
93 static void twr_spirit1_hal_deinit_spi(
void);
95 static void _twr_spirit1_task(
void *param);
100 if (_twr_spirit1.initialized_semaphore > 0)
102 _twr_spirit1.initialized_semaphore++;
107 memset(&_twr_spirit1, 0,
sizeof(_twr_spirit1));
109 SpiritRadioSetXtalFrequency(XTAL_FREQUENCY);
114 SpiritEnterShutdown();
116 SpiritExitShutdown();
118 SpiritManagementWaExtraCurrent();
121 SpiritGpioInit(&xGpioIRQ);
124 if (SpiritRadioInit(&xRadioInit) != 0)
127 twr_spirit1_hal_shutdown_high();
129 twr_spirit1_hal_deinit_spi();
131 twr_spirit1_hal_deinit_gpio();
137 SpiritPktBasicInit(&xBasicInit);
139 SpiritPktBasicAddressesInit(&xAddressInit);
141 _twr_spirit1.desired_state = TWR_SPIRIT1_STATE_SLEEP;
145 _twr_spirit1.initialized_semaphore++;
152 if (--_twr_spirit1.initialized_semaphore != 0)
157 twr_spirit1_hal_shutdown_high();
159 twr_spirit1_hal_deinit_spi();
161 twr_spirit1_hal_deinit_gpio();
172 _twr_spirit1.event_handler = event_handler;
173 _twr_spirit1.event_param = event_param;
178 return _twr_spirit1.tx_buffer;
183 _twr_spirit1.tx_length = length;
188 return _twr_spirit1.tx_length;
193 return _twr_spirit1.rx_buffer;
198 return _twr_spirit1.rx_length;
203 return _twr_spirit1.rx_rssi;
208 _twr_spirit1.rx_timeout = timeout;
210 if (_twr_spirit1.current_state == TWR_SPIRIT1_STATE_RX)
218 _twr_spirit1.rx_tick_timeout =
twr_tick_get() + _twr_spirit1.rx_timeout;
221 if (_twr_spirit1.initialized_semaphore > 0)
230 _twr_spirit1.desired_state = TWR_SPIRIT1_STATE_TX;
232 if (_twr_spirit1.initialized_semaphore > 0)
240 _twr_spirit1.desired_state = TWR_SPIRIT1_STATE_RX;
242 if (_twr_spirit1.initialized_semaphore > 0)
250 _twr_spirit1.desired_state = TWR_SPIRIT1_STATE_SLEEP;
252 if (_twr_spirit1.initialized_semaphore > 0)
258 static void _twr_spirit1_task(
void *param)
262 if ((_twr_spirit1.current_state == TWR_SPIRIT1_STATE_RX) && (
twr_tick_get() >= _twr_spirit1.rx_tick_timeout))
264 if (_twr_spirit1.event_handler != NULL)
270 if (_twr_spirit1.desired_state != _twr_spirit1.current_state)
272 if (_twr_spirit1.desired_state == TWR_SPIRIT1_STATE_TX)
274 _twr_spirit1_enter_state_tx();
278 else if (_twr_spirit1.desired_state == TWR_SPIRIT1_STATE_RX)
280 _twr_spirit1_enter_state_rx();
284 else if (_twr_spirit1.desired_state == TWR_SPIRIT1_STATE_SLEEP)
286 _twr_spirit1_enter_state_sleep();
294 if (_twr_spirit1.current_state == TWR_SPIRIT1_STATE_TX)
296 _twr_spirit1_check_state_tx();
300 else if (_twr_spirit1.current_state == TWR_SPIRIT1_STATE_RX)
302 _twr_spirit1_check_state_rx();
308 static void _twr_spirit1_enter_state_tx(
void)
310 GPIOA->PUPDR |= GPIO_PUPDR_PUPD7_1;
312 _twr_spirit1.current_state = TWR_SPIRIT1_STATE_TX;
314 SpiritCmdStrobeSabort();
315 SpiritCmdStrobeReady();
316 SpiritCmdStrobeFlushTxFifo();
318 SpiritIrqDeInit(NULL);
319 SpiritIrqClearStatus();
320 SpiritIrq(TX_DATA_SENT, S_ENABLE);
322 SpiritPktBasicSetPayloadLength(_twr_spirit1.tx_length);
325 SpiritPktBasicSetDestinationAddress(0x35);
327 SpiritSpiWriteLinearFifo(_twr_spirit1.tx_length, _twr_spirit1.tx_buffer);
334 static void _twr_spirit1_check_state_tx(
void)
336 SpiritIrqs xIrqStatus;
338 SpiritIrqGetStatus(&xIrqStatus);
340 if (xIrqStatus.IRQ_TX_DATA_SENT)
342 SpiritIrqClearStatus();
344 _twr_spirit1.desired_state = TWR_SPIRIT1_STATE_SLEEP;
346 if (_twr_spirit1.event_handler != NULL)
351 if (_twr_spirit1.desired_state == TWR_SPIRIT1_STATE_RX)
353 _twr_spirit1_enter_state_rx();
355 else if (_twr_spirit1.desired_state == TWR_SPIRIT1_STATE_SLEEP)
357 _twr_spirit1_enter_state_sleep();
359 else if (_twr_spirit1.desired_state == TWR_SPIRIT1_STATE_TX)
361 _twr_spirit1_enter_state_tx();
366 static void _twr_spirit1_enter_state_rx(
void)
368 GPIOA->PUPDR |= GPIO_PUPDR_PUPD7_1;
370 _twr_spirit1.current_state = TWR_SPIRIT1_STATE_RX;
378 _twr_spirit1.rx_tick_timeout =
twr_tick_get() + _twr_spirit1.rx_timeout;
383 SpiritIrqs xIrqStatus;
385 SpiritIrqDeInit(&xIrqStatus);
386 SpiritIrq(RX_DATA_DISC, S_ENABLE);
387 SpiritIrq(RX_DATA_READY, S_ENABLE);
390 SpiritPktBasicSetPayloadLength(20);
393 SpiritQiSetSqiThreshold(SQI_TH_0);
394 SpiritQiSqiCheck(S_ENABLE);
397 SpiritTimerSetRxTimeoutMs(1000.0);
398 SpiritTimerSetRxTimeoutStopCondition(SQI_ABOVE_THRESHOLD);
401 SpiritIrqClearStatus();
409 static void _twr_spirit1_check_state_rx(
void)
411 SpiritIrqs xIrqStatus;
414 SpiritIrqGetStatus(&xIrqStatus);
417 if (xIrqStatus.IRQ_RX_DATA_DISC)
424 if (xIrqStatus.IRQ_RX_DATA_READY)
427 uint8_t cRxData = SpiritLinearFifoReadNumElementsRxFifo();
429 if (cRxData <= TWR_SPIRIT1_MAX_PACKET_SIZE)
432 SpiritSpiReadLinearFifo(cRxData, _twr_spirit1.rx_buffer);
434 _twr_spirit1.rx_length = cRxData;
438 twr_spirit1_read(RSSI_LEVEL_BASE, &rssi_level, 1);
440 _twr_spirit1.rx_rssi = ((int) rssi_level) / 2 - 130;
448 _twr_spirit1.rx_tick_timeout =
twr_tick_get() + _twr_spirit1.rx_timeout;
453 if (_twr_spirit1.event_handler != NULL)
461 SpiritCmdStrobeFlushRxFifo();
467 static void _twr_spirit1_enter_state_sleep(
void)
469 _twr_spirit1.current_state = TWR_SPIRIT1_STATE_SLEEP;
471 SpiritCmdStrobeSabort();
472 SpiritCmdStrobeReady();
473 SpiritIrqDeInit(NULL);
474 SpiritIrqClearStatus();
475 SpiritCmdStrobeStandby();
477 GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD7_1;
480 twr_spirit_status_t twr_spirit1_command(uint8_t command)
483 twr_system_pll_enable();
486 twr_spirit1_hal_chip_select_low();
489 uint16_t status_value = twr_spirit1_hal_transfer_byte(0x80) << 8;
492 status_value |= twr_spirit1_hal_transfer_byte(command);
495 twr_spirit1_hal_chip_select_high();
498 twr_system_pll_disable();
500 twr_spirit_status_t *status = ((twr_spirit_status_t *) &status_value);
506 twr_spirit_status_t twr_spirit1_write(uint8_t address,
const void *buffer,
size_t length)
509 twr_system_pll_enable();
512 twr_spirit1_hal_chip_select_low();
515 uint16_t status_value = twr_spirit1_hal_transfer_byte(0) << 8;
518 status_value |= twr_spirit1_hal_transfer_byte(address);
521 for (
size_t i = 0; i < length; i++)
524 twr_spirit1_hal_transfer_byte(*((uint8_t *) buffer + i));
528 twr_spirit1_hal_chip_select_high();
531 twr_system_pll_disable();
533 twr_spirit_status_t *status = ((twr_spirit_status_t *) &status_value);
539 twr_spirit_status_t twr_spirit1_read(uint8_t address,
void *buffer,
size_t length)
542 twr_system_pll_enable();
545 twr_spirit1_hal_chip_select_low();
548 uint16_t status_value = twr_spirit1_hal_transfer_byte(1) << 8;
551 status_value |= twr_spirit1_hal_transfer_byte(address);
554 for (
size_t i = 0; i < length; i++)
557 *((uint8_t *) buffer + i) = twr_spirit1_hal_transfer_byte(0);
561 twr_spirit1_hal_chip_select_high();
564 twr_system_pll_disable();
566 twr_spirit_status_t *status = ((twr_spirit_status_t *) &status_value);
572 void twr_spirit1_hal_init(
void)
578 twr_spirit1_hal_init_gpio();
581 twr_spirit1_hal_init_spi();
584 twr_spirit1_hal_shutdown_high();
587 void twr_spirit1_hal_shutdown_low(
void)
590 GPIOB->BSRR = GPIO_BSRR_BR_7;
593 GPIOA->BSRR = GPIO_BSRR_BS_15;
604 void twr_spirit1_hal_shutdown_high(
void)
607 twr_system_pll_enable();
610 GPIOA->BSRR = GPIO_BSRR_BR_15;
613 GPIOB->BSRR = GPIO_BSRR_BS_7;
626 twr_system_pll_disable();
629 void twr_spirit1_hal_chip_select_low(
void)
632 GPIOA->BSRR = GPIO_BSRR_BR_15;
644 void twr_spirit1_hal_chip_select_high(
void)
654 GPIOA->BSRR = GPIO_BSRR_BS_15;
664 uint8_t twr_spirit1_hal_transfer_byte(uint8_t value)
667 while ((SPI1->SR & SPI_SR_TXE) == 0)
676 while ((SPI1->SR & SPI_SR_RXNE) == 0)
687 static void twr_spirit1_hal_init_gpio(
void)
690 RCC->IOPENR |= RCC_IOPENR_GPIOHEN | RCC_IOPENR_GPIOBEN | RCC_IOPENR_GPIOAEN;
696 GPIOB->BSRR = GPIO_BSRR_BS_7;
699 GPIOA->PUPDR |= GPIO_PUPDR_PUPD7_1;
702 GPIOB->PUPDR |= GPIO_PUPDR_PUPD4_1;
705 GPIOH->PUPDR |= GPIO_PUPDR_PUPD0_1;
708 GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED15_1 | GPIO_OSPEEDER_OSPEED15_0;
711 GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEED5_1 | GPIO_OSPEEDER_OSPEED5_0 | GPIO_OSPEEDER_OSPEED3_1 | GPIO_OSPEEDER_OSPEED3_0;
714 GPIOA->MODER &= ~(GPIO_MODER_MODE15_1 | GPIO_MODER_MODE7_1 | GPIO_MODER_MODE7_0);
717 GPIOB->MODER &= ~(GPIO_MODER_MODE7_1 | GPIO_MODER_MODE5_0 | GPIO_MODER_MODE4_0 | GPIO_MODER_MODE3_0);
720 GPIOH->MODER &= ~(GPIO_MODER_MODE0_1 | GPIO_MODER_MODE0_0);
723 static void twr_spirit1_hal_deinit_gpio(
void)
726 GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED15_Msk;
729 GPIOB->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEED5_Msk | GPIO_OSPEEDER_OSPEED3_Msk);
732 GPIOA->MODER |= GPIO_MODER_MODE15_Msk | GPIO_MODER_MODE7_Msk;
735 GPIOB->MODER |= GPIO_MODER_MODE7_Msk | GPIO_MODER_MODE5_Msk | GPIO_MODER_MODE4_Msk | GPIO_MODER_MODE3_Msk;
738 GPIOH->MODER |= GPIO_MODER_MODE0_Msk;
741 GPIOB->BSRR = GPIO_BSRR_BR_7;
744 GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD7_Msk;
747 GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD4_Msk;
750 GPIOH->PUPDR &= ~GPIO_PUPDR_PUPD0_Msk;
753 static void twr_spirit1_hal_init_spi(
void)
756 RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
759 SPI1->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_BR_1 | SPI_CR1_MSTR;
762 SPI1->CR1 |= SPI_CR1_SPE;
765 static void twr_spirit1_hal_deinit_spi(
void)
771 RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN;
void twr_exti_register(twr_exti_line_t line, twr_exti_edge_t edge, void(*callback)(twr_exti_line_t, void *), void *param)
Enable EXTI line interrupt and register callback function.
void twr_exti_unregister(twr_exti_line_t line)
Disable EXTI line interrupt.
twr_exti_line_t
EXTI lines.
@ TWR_EXTI_LINE_PA7
EXTI line PA7.
@ TWR_EXTI_EDGE_FALLING
EXTI line is configured to falling edge sensitivity.
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
size_t twr_scheduler_task_id_t
Task ID assigned by scheduler.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
bool twr_spirit1_deinit(void)
Deitialize.
void * twr_spirit1_get_rx_buffer(void)
Get RX buffer.
void * twr_spirit1_get_tx_buffer(void)
Get TX buffer.
void twr_spirit1_tx(void)
Enter TX state.
twr_spirit1_event_t
Callback events.
void twr_spirit1_set_rx_timeout(twr_tick_t timeout)
Set TX timeout.
size_t twr_spirit1_get_tx_length(void)
Get TX buffer length.
int twr_spirit1_get_rx_rssi(void)
Get RSSI.
void twr_spirit1_sleep(void)
Enter sleep state.
void twr_spirit1_set_tx_length(size_t length)
Set TX buffer length.
bool twr_spirit1_init(void)
Initialize.
size_t twr_spirit1_get_rx_length(void)
Get RX buffer length.
void twr_spirit1_rx(void)
Enter RX state.
void twr_spirit1_set_event_handler(void(*event_handler)(twr_spirit1_event_t, void *), void *event_param)
Set callback function.
@ TWR_SPIRIT1_EVENT_RX_TIMEOUT
Event is RX timeout.
@ TWR_SPIRIT1_EVENT_TX_DONE
Event is TX done.
@ TWR_SPIRIT1_EVENT_RX_DONE
Event is RX done.
#define TWR_TICK_INFINITY
Maximum timestamp value.
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
uint64_t twr_tick_t
Timestamp data type.
void twr_timer_clear(void)
Clear timer counter.
void twr_timer_init(void)
Initialize timer.
void twr_timer_delay(uint16_t microseconds)
Relative delay.
void twr_timer_stop(void)
Stop timer.
void twr_timer_start(void)
Start timer.
uint16_t twr_timer_get_microseconds(void)
Get actual tick of timer.