diff --git a/include/peripherals/nrf52832/ppi.h b/include/peripherals/nrf52832/ppi.h index 0f6e837..87bbea6 100644 --- a/include/peripherals/nrf52832/ppi.h +++ b/include/peripherals/nrf52832/ppi.h @@ -4,6 +4,18 @@ typedef struct PPI_t PPI_t; +typedef enum +{ + SHORT_RADIO_READY_START = 0, + SHORT_RADIO_END_DISABLE, + SHORT_RADIO_DISABLED_TXEN, + SHORT_RADIO_DISABLED_RXEN, + SHORT_RADIO_ADDRESS_RSSISTART, + SHORT_RADIO_END_START, + SHORT_RADIO_ADDRESS_BCSTART, + SHORT_RADIO_DISABLED_RSSISTOP, +} ppi_short_t; + // OPERATION(ppi); memreg_op_result_t ppi_operation(uint32_t base, uint32_t offset, uint32_t *value, memreg_op_t op, void *userdata); @@ -25,3 +37,6 @@ void ppi_fire_task(PPI_t *, uint8_t peripheral_id, uint8_t task_id); void ppi_fire_event(PPI_t *, uint8_t peripheral_id, uint8_t event_id, bool pend_exception); void ppi_clear_event(PPI_t *, uint8_t peripheral_id, uint8_t event_id); bool ppi_event_is_set(PPI_t *, uint8_t peripheral_id, uint8_t event_id); + +void ppi_shorts_set_enabled(PPI_t *, ppi_short_t short_id, bool enabled); +bool ppi_shorts_is_enabled(PPI_t *, ppi_short_t short_id); diff --git a/src/peripherals/nrf52832/ppi.c b/src/peripherals/nrf52832/ppi.c index e3c8765..6fc1d98 100644 --- a/src/peripherals/nrf52832/ppi.c +++ b/src/peripherals/nrf52832/ppi.c @@ -14,11 +14,20 @@ #include "peripherals/peripheral.h" #define CHANNELS_COUNT 32 +#define SHORTS_COUNT 32 #define PROGRAMMABLE_CHANNELS_COUNT (CHANNELS_COUNT - 12) #define PERIPHERALS_COUNT 0x26 #define EVENTS_COUNT 64 +#define SHORT_CHANNEL_INDEX(n) ((n) + CHANNELS_COUNT) + +#define SET_CHANNEL(n, eep_p, eep_e, tep_p, tep_t) \ + ppi->channels[n].eep_peripheral = eep_p; \ + ppi->channels[n].eep_event = EVENT_ID(eep_e); \ + ppi->channels[n].tep_peripheral = tep_p; \ + ppi->channels[n].tep_task = TASK_ID(tep_t); + _Thread_local PPI_t *current_ppi; typedef struct @@ -40,7 +49,7 @@ struct PPI_t { cpu_t **cpu; - channel_t channels[CHANNELS_COUNT]; + channel_t channels[CHANNELS_COUNT + SHORTS_COUNT]; peripheral_t *peripherals[PERIPHERALS_COUNT]; }; @@ -172,69 +181,32 @@ PPI_t *ppi_new(cpu_t **cpu) { ppi->channels[i].fixed = true; } + for (size_t i = CHANNELS_COUNT; i < CHANNELS_COUNT + SHORTS_COUNT; i++) + { + ppi->channels[i].fixed = true; + } - // TIMER0 COMPARE[0] -> RADIO TXEN - ppi->channels[20].eep_peripheral = INSTANCE_TIMER0; - ppi->channels[20].eep_event = EVENT_ID(TIMER_EVENTS_COMPARE0); - ppi->channels[20].tep_peripheral = INSTANCE_RADIO; - ppi->channels[20].tep_task = TASK_ID(RADIO_TASKS_TXEN); - - // TIMER0 COMPARE[0] -> RADIO RXEN - ppi->channels[21].eep_peripheral = INSTANCE_TIMER0; - ppi->channels[21].eep_event = EVENT_ID(TIMER_EVENTS_COMPARE0); - ppi->channels[21].tep_peripheral = INSTANCE_RADIO; - ppi->channels[21].tep_task = TASK_ID(RADIO_TASKS_RXEN); - - // TIMER0 COMPARE[1] -> RADIO DISABLE - ppi->channels[22].eep_peripheral = INSTANCE_TIMER0; - ppi->channels[22].eep_event = EVENT_ID(TIMER_EVENTS_COMPARE1); - ppi->channels[22].tep_peripheral = INSTANCE_RADIO; - ppi->channels[22].tep_task = TASK_ID(RADIO_TASKS_DISABLE); - - // RADIO BCMATCH -> AAR START - // TODO: Implement - - // RADIO READY -> CCM KSGEN - // TODO: Implement - - // RADIO ADDRESS -> CCM CRYPT - // TODO: Implement - - // RADIO ADDRESS -> TIMER0 CAPTURE[1] - ppi->channels[26].eep_peripheral = INSTANCE_RADIO; - ppi->channels[26].eep_event = EVENT_ID(RADIO_EVENTS_ADDRESS); - ppi->channels[26].tep_peripheral = INSTANCE_TIMER0; - ppi->channels[26].tep_task = TASK_ID(TIMER_TASKS_CAPTURE1); - - // RADIO END -> TIMER0 CAPTURE[1] - ppi->channels[27].eep_peripheral = INSTANCE_RADIO; - ppi->channels[27].eep_event = EVENT_ID(RADIO_EVENTS_END); - ppi->channels[27].tep_peripheral = INSTANCE_TIMER0; - ppi->channels[27].tep_task = TASK_ID(TIMER_TASKS_CAPTURE2); - - // RTC0 COMPARE[0] -> RADIO TXEN - ppi->channels[28].eep_peripheral = INSTANCE_RTC0; - ppi->channels[28].eep_event = EVENT_ID(RTC_EVENTS_COMPARE0); - ppi->channels[28].tep_peripheral = INSTANCE_RADIO; - ppi->channels[28].tep_task = TASK_ID(RADIO_TASKS_TXEN); - - // RTC0 COMPARE[0] -> RADIO RXEN - ppi->channels[29].eep_peripheral = INSTANCE_RTC0; - ppi->channels[29].eep_event = EVENT_ID(RTC_EVENTS_COMPARE0); - ppi->channels[29].tep_peripheral = INSTANCE_RADIO; - ppi->channels[29].tep_task = TASK_ID(RADIO_TASKS_RXEN); - - // RTC0 COMPARE[0] -> TIMER0 CLEAR - ppi->channels[30].eep_peripheral = INSTANCE_RTC0; - ppi->channels[30].eep_event = EVENT_ID(RTC_EVENTS_COMPARE0); - ppi->channels[30].tep_peripheral = INSTANCE_TIMER0; - ppi->channels[30].tep_task = TASK_ID(TIMER_TASKS_CLEAR); - - // RTC0 COMPARE[0] -> TIMER0 START - ppi->channels[31].eep_peripheral = INSTANCE_RTC0; - ppi->channels[31].eep_event = EVENT_ID(RTC_EVENTS_COMPARE0); - ppi->channels[31].tep_peripheral = INSTANCE_TIMER0; - ppi->channels[31].tep_task = TASK_ID(TIMER_TASKS_START); + SET_CHANNEL(20, INSTANCE_TIMER0, TIMER_EVENTS_COMPARE0, INSTANCE_RADIO, RADIO_TASKS_TXEN) + SET_CHANNEL(21, INSTANCE_TIMER0, TIMER_EVENTS_COMPARE0, INSTANCE_RADIO, RADIO_TASKS_RXEN) + SET_CHANNEL(22, INSTANCE_TIMER0, TIMER_EVENTS_COMPARE1, INSTANCE_RADIO, RADIO_TASKS_DISABLE) + // TODO: Implement RADIO BCMATCH -> AAR START + // TODO: Implement RADIO READY -> CCM KSGEN + // TODO: Implement RADIO ADDRESS -> CCM CRYPT + SET_CHANNEL(26, INSTANCE_RADIO, RADIO_EVENTS_ADDRESS, INSTANCE_TIMER0, TIMER_TASKS_CAPTURE1) + SET_CHANNEL(27, INSTANCE_RADIO, RADIO_EVENTS_END, INSTANCE_TIMER0, TIMER_TASKS_CAPTURE1) + SET_CHANNEL(28, INSTANCE_RTC0, RTC_EVENTS_COMPARE0, INSTANCE_RADIO, RADIO_TASKS_TXEN) + SET_CHANNEL(29, INSTANCE_RTC0, RTC_EVENTS_COMPARE0, INSTANCE_RADIO, RADIO_TASKS_RXEN) + SET_CHANNEL(30, INSTANCE_RTC0, RTC_EVENTS_COMPARE0, INSTANCE_TIMER0, TIMER_TASKS_CLEAR) + SET_CHANNEL(31, INSTANCE_RTC0, RTC_EVENTS_COMPARE0, INSTANCE_TIMER0, TIMER_TASKS_START) + + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_READY_START), INSTANCE_RADIO, RADIO_EVENTS_READY, INSTANCE_RADIO, RADIO_TASKS_START) + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_END_DISABLE), INSTANCE_RADIO, RADIO_EVENTS_END, INSTANCE_RADIO, RADIO_TASKS_DISABLE) + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_DISABLED_TXEN), INSTANCE_RADIO, RADIO_EVENTS_DISABLED, INSTANCE_RADIO, RADIO_TASKS_TXEN) + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_DISABLED_RXEN), INSTANCE_RADIO, RADIO_EVENTS_DISABLED, INSTANCE_RADIO, RADIO_TASKS_RXEN) + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_ADDRESS_RSSISTART), INSTANCE_RADIO, RADIO_EVENTS_ADDRESS, INSTANCE_RADIO, RADIO_TASKS_RSSISTART) + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_END_START), INSTANCE_RADIO, RADIO_EVENTS_END, INSTANCE_RADIO, RADIO_TASKS_START) + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_ADDRESS_BCSTART), INSTANCE_RADIO, RADIO_EVENTS_ADDRESS, INSTANCE_RADIO, RADIO_TASKS_BCSTART) + SET_CHANNEL(SHORT_CHANNEL_INDEX(SHORT_RADIO_DISABLED_RSSISTOP), INSTANCE_RADIO, RADIO_EVENTS_DISABLED, INSTANCE_RADIO, RADIO_TASKS_RSSISTOP) return ppi; } @@ -293,7 +265,7 @@ void ppi_fire_event(PPI_t *ppi, uint8_t peripheral_id, uint8_t event_id, bool pe if (pend_exception) cpu_exception_set_pending(*ppi->cpu, ARM_EXTERNAL_INTERRUPT_NUMBER(peripheral_id)); - for (size_t i = 0; i < CHANNELS_COUNT; i++) + for (size_t i = 0; i < CHANNELS_COUNT + SHORTS_COUNT; i++) { channel_t *channel = &ppi->channels[i]; @@ -329,3 +301,21 @@ bool ppi_event_is_set(PPI_t *ppi, uint8_t peripheral_id, uint8_t event_id) return (periph->events & (1 << event_id)) != 0; } + +void ppi_shorts_set_enabled(PPI_t *ppi, ppi_short_t short_id, bool enabled) +{ + assert(short_id < SHORTS_COUNT); + + channel_t *channel = &ppi->channels[SHORT_CHANNEL_INDEX(short_id)]; + + channel->enabled = enabled; +} + +bool ppi_shorts_is_enabled(PPI_t *ppi, ppi_short_t short_id) +{ + assert(short_id < SHORTS_COUNT); + + channel_t *channel = &ppi->channels[SHORT_CHANNEL_INDEX(short_id)]; + + return channel->enabled; +} diff --git a/src/peripherals/nrf52832/radio.c b/src/peripherals/nrf52832/radio.c index d8bc308..798e947 100644 --- a/src/peripherals/nrf52832/radio.c +++ b/src/peripherals/nrf52832/radio.c @@ -4,6 +4,7 @@ #include #include "fault.h" +#include "nrf52832.h" #include "peripherals/nrf52832/ppi.h" #define STATE_CHANGE_DELAY_INST 10000 @@ -141,6 +142,9 @@ struct RADIO_inst_t radio_state_t state, next_state; inten_t inten; + bool tx_sent_address, tx_sent_payload; + bool rx_received_address, rx_received_payload; + uint32_t mode; uint32_t txpower; uint32_t packetptr; @@ -173,29 +177,99 @@ void radio_reset(RADIO_t *radio) void radio_do_state_change(void *userdata) { RADIO_t *radio = userdata; + radio_state_t old_state = radio->state; radio->state = radio->next_state; + bool request_update = false; + switch (radio->state) { case STATE_RXDISABLE: case STATE_TXDISABLE: radio->next_state = STATE_DISABLED; + request_update = true; break; case STATE_TXRU: radio->next_state = STATE_TXIDLE; + request_update = true; break; case STATE_RXRU: radio->next_state = STATE_RXIDLE; + request_update = true; + break; + + case STATE_TX: + if (radio->tx_sent_address && radio->tx_sent_payload) + { + radio->tx_sent_address = false; + radio->tx_sent_payload = false; + radio->next_state = STATE_TXIDLE; + } + else if (radio->tx_sent_address) + { + radio->tx_sent_payload = true; + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_PAYLOAD), radio->inten.PAYLOAD); + } + else + { + radio->tx_sent_address = true; + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_ADDRESS), radio->inten.ADDRESS); + } + request_update = true; + break; + + case STATE_RX: + if (radio->rx_received_address && radio->rx_received_payload) + { + radio->rx_received_address = false; + radio->rx_received_payload = false; + radio->next_state = STATE_RXIDLE; + } + else if (radio->rx_received_address) + { + radio->rx_received_payload = true; + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_PAYLOAD), radio->inten.PAYLOAD); + } + else + { + radio->rx_received_address = true; + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_ADDRESS), radio->inten.ADDRESS); + } + request_update = true; break; default: + switch (radio->next_state) + { + case STATE_DISABLED: + if (old_state == STATE_TXDISABLE || old_state == STATE_RXDISABLE) + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_DISABLED), radio->inten.DISABLED); + break; + + case STATE_TXIDLE: + if (old_state == STATE_TXRU) + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_READY), radio->inten.READY); + else if (old_state == STATE_TX) + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_END), radio->inten.END); + break; + + case STATE_RXIDLE: + if (old_state == STATE_RXRU) + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_READY), radio->inten.READY); + else if (old_state == STATE_RX) + ppi_fire_event(current_ppi, INSTANCE_RADIO, EVENT_ID(RADIO_EVENTS_END), radio->inten.END); + break; + + default: + break; + } break; } - if (radio->next_state != radio->state) + if (request_update) ticker_add(radio->ticker, radio_do_state_change, radio, STATE_CHANGE_DELAY_INST, false); } @@ -320,7 +394,27 @@ OPERATION(radio) OP_EVENT(RADIO_EVENTS_CRCERROR) case 0x200: // SHORTS - OP_RETURN_REG(radio->shorts.value, WORD); + OP_ASSERT_SIZE(op, WORD); + + if (op == OP_READ_WORD) + { + *value = radio->shorts.value; + } + else if (op == OP_WRITE_WORD) + { + radio->shorts.value = *value; + + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_READY_START, radio->shorts.READY_START); + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_END_DISABLE, radio->shorts.END_DISABLE); + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_DISABLED_TXEN, radio->shorts.DISABLED_TXEN); + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_DISABLED_RXEN, radio->shorts.DISABLED_RXEN); + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_ADDRESS_RSSISTART, radio->shorts.ADDRESS_RSSISTART); + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_END_START, radio->shorts.END_START); + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_ADDRESS_BCSTART, radio->shorts.ADDRESS_BCSTART); + ppi_shorts_set_enabled(current_ppi, SHORT_RADIO_DISABLED_RSSISTOP, radio->shorts.DISABLED_RSSISTOP); + } + + return (MEMREG_RESULT_OK); case 0x304: // INTENSET if (OP_IS_READ(op)) @@ -423,7 +517,7 @@ OPERATION(radio) NRF52_PERIPHERAL_CONSTRUCTOR(RADIO, radio) { - RADIO_t *radio = malloc(sizeof(RADIO_t)); + RADIO_t *radio = calloc(1, sizeof(RADIO_t)); radio->ticker = ctx.ticker; ppi_add_peripheral(ctx.ppi, ctx.id, radio_task_handler, radio);