diff --git a/app/include/app_transparent_client.hpp b/app/include/app_transparent_client.hpp index fb428a9..3d3c96b 100644 --- a/app/include/app_transparent_client.hpp +++ b/app/include/app_transparent_client.hpp @@ -36,8 +36,23 @@ private: Utility::FunctionOwned m_isr_cb_pointer; std::optional m_pending_irqs = std::nullopt; + enum class AppState + { + STARTUP, + PASSIVE, + ACTIVE_RX, + ACTIVE_TX, + RX_FRAME_READY + }; + + AppState m_state = AppState::STARTUP; + void m_cbRadioIrqHandler(radio::HwInstance*); - void m_processInterrupts(); + std::optional m_hwInterruptToNewState(); + void m_transitionToState(const AppState& new_state); + void m_processState(); + void m_initiateTx(); + bool m_txBufferIsReady(); }; } diff --git a/app/src/app_transparent_client.cpp b/app/src/app_transparent_client.cpp index 81ef9f0..599b0ae 100644 --- a/app/src/app_transparent_client.cpp +++ b/app/src/app_transparent_client.cpp @@ -5,6 +5,10 @@ #include "radio_hw_instance.hpp" #include "app_transparent_client.hpp" +#include "skullc_samd21_hal.hpp" +#include "utility_logging.hpp" + +#include namespace App { @@ -14,7 +18,7 @@ TransparentClient::TransparentClient(const RadioSettings& initial_settings) , m_isr_cb_pointer(*this, &TransparentClient::m_cbRadioIrqHandler) { apply_settings(initial_settings); - + m_radio->set_irq_handler(&m_isr_cb_pointer); m_radio->set_current_state(radio::HwInstance::States::PLL_ON); } @@ -30,8 +34,21 @@ void TransparentClient::apply_settings(const RadioSettings& settings) void TransparentClient::process() { - if (m_pending_irqs) - m_processInterrupts(); + std::optional new_state_request = std::nullopt; + + { + Utility::AtomicScopeGuard irq_guard; + if (m_pending_irqs) + new_state_request = m_hwInterruptToNewState(); + } + + if (!new_state_request && m_txBufferIsReady()) + new_state_request = AppState::ACTIVE_TX; + + if (new_state_request) + m_transitionToState(*new_state_request); + + m_processState(); } void TransparentClient::m_cbRadioIrqHandler(radio::HwInstance*) @@ -43,9 +60,86 @@ void TransparentClient::m_cbRadioIrqHandler(radio::HwInstance*) m_pending_irqs = new_irqs; } -void TransparentClient::m_processInterrupts() +std::optional TransparentClient::m_hwInterruptToNewState() { + const radio::Interrupts current_irqs = *m_pending_irqs; m_pending_irqs = std::nullopt; + + SKULLC_LOG_DEBUG("APP: Processing IRQs: %d.", current_irqs); + + const auto flag_is_set = [current_irqs](const radio::Interrupts& flag) -> bool + { + return std::underlying_type_t(current_irqs & flag); + }; + + switch (m_state) + { + case AppState::STARTUP: + if (flag_is_set(radio::Interrupts::PLL_LOCK)) + return AppState::PASSIVE; + break; + case AppState::PASSIVE: + if (flag_is_set(radio::Interrupts::RX_START)) + return AppState::ACTIVE_RX; + else if (flag_is_set(radio::Interrupts::AMI)) + return AppState::RX_FRAME_READY; + break; + case AppState::ACTIVE_RX: + [[fallthrough]]; + case AppState::ACTIVE_TX: + if (flag_is_set(radio::Interrupts::TRX_END)) + return AppState::PASSIVE; + break; + default: + break; + } + + return std::nullopt; +} + +void TransparentClient::m_transitionToState(const AppState& new_state) +{ + SKULLC_LOG_DEBUG("APP: Trans. to state. %d -> %d.", m_state, new_state); + + switch (m_state) + { + case AppState::STARTUP: + if (new_state == AppState::PASSIVE) + m_radio->set_current_state(radio::HwInstance::States::RX_ON); + break; + case AppState::PASSIVE: + // new_state == AppState::ACTIVE_RX is a HW transition. State machine simply locks itself. + // new_state == AppState::RX_FRAME_READY is handled in process state. + if (new_state == AppState::ACTIVE_TX) + m_initiateTx(); + break; + case AppState::ACTIVE_RX: + // new_state == AppState::PASSIVE is a HW transition. State machine simply unlocks itself. + break; + case AppState::ACTIVE_TX: + if (new_state == AppState::PASSIVE) + m_radio->set_current_state(radio::HwInstance::States::RX_ON); + break; + case AppState::RX_FRAME_READY: + break; + } + + m_state = new_state; +} + +void TransparentClient::m_processState() +{ + return; +} + +void TransparentClient::m_initiateTx() +{ + return; +} + +bool TransparentClient::m_txBufferIsReady() +{ + return false; } } diff --git a/main.cpp b/main.cpp index 1a0c03d..5aec3b9 100644 --- a/main.cpp +++ b/main.cpp @@ -42,21 +42,19 @@ int main() const App::RadioSettings settings; m_app.setup(settings); - radio::HwInstance* radio_hw = radio::HwInstance::instance(); + + std::uint32_t counter = 0; /* Replace with your application code */ while (true) { - gpio_toggle_pin_level(OUT_LED_RX); + if (counter++ == 1000) + { + gpio_toggle_pin_level(OUT_LED_TX); + counter = 0; + } - gpio_toggle_pin_level(OUT_LED_TX); - - int16_t radio_status = radio_hw->register_read(radio::Registers::TRX_STATUS); - radio_status &= 0x1F; - - SKULLC_LOG_INFO("Status: %d", radio_status); - SKULLC_LOG_INFO("Millis: %u", Hal::StaticHal::getMillis()); - - delay_ms(1000); + m_app->process(); + Hal::StaticHal::delay(1); } } diff --git a/radio/src/radio_hw_instance.cpp b/radio/src/radio_hw_instance.cpp index fdc749c..7593276 100644 --- a/radio/src/radio_hw_instance.cpp +++ b/radio/src/radio_hw_instance.cpp @@ -150,6 +150,7 @@ bool HwInstance::set_current_state(const States& new_state) register_write(Registers::TRX_STATE, std::uint8_t(new_state)); m_wait_can_transition(); + SKULLC_LOG_DEBUG("HW: New state. %d -> %d.", m_current_state, new_state); m_current_state = new_state; return true; }