Initial implementation of app state machine
This commit is contained in:
parent
1c695fbaa8
commit
c994e63478
@ -36,8 +36,23 @@ private:
|
|||||||
Utility::FunctionOwned<TransparentClient, void (radio::HwInstance*)> m_isr_cb_pointer;
|
Utility::FunctionOwned<TransparentClient, void (radio::HwInstance*)> m_isr_cb_pointer;
|
||||||
std::optional<radio::Interrupts> m_pending_irqs = std::nullopt;
|
std::optional<radio::Interrupts> 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_cbRadioIrqHandler(radio::HwInstance*);
|
||||||
void m_processInterrupts();
|
std::optional<AppState> m_hwInterruptToNewState();
|
||||||
|
void m_transitionToState(const AppState& new_state);
|
||||||
|
void m_processState();
|
||||||
|
void m_initiateTx();
|
||||||
|
bool m_txBufferIsReady();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,10 @@
|
|||||||
#include "radio_hw_instance.hpp"
|
#include "radio_hw_instance.hpp"
|
||||||
|
|
||||||
#include "app_transparent_client.hpp"
|
#include "app_transparent_client.hpp"
|
||||||
|
#include "skullc_samd21_hal.hpp"
|
||||||
|
#include "utility_logging.hpp"
|
||||||
|
|
||||||
|
#include <utility_atomicscopeguard.hpp>
|
||||||
|
|
||||||
namespace App
|
namespace App
|
||||||
{
|
{
|
||||||
@ -14,7 +18,7 @@ TransparentClient::TransparentClient(const RadioSettings& initial_settings)
|
|||||||
, m_isr_cb_pointer(*this, &TransparentClient::m_cbRadioIrqHandler)
|
, m_isr_cb_pointer(*this, &TransparentClient::m_cbRadioIrqHandler)
|
||||||
{
|
{
|
||||||
apply_settings(initial_settings);
|
apply_settings(initial_settings);
|
||||||
|
m_radio->set_irq_handler(&m_isr_cb_pointer);
|
||||||
m_radio->set_current_state(radio::HwInstance::States::PLL_ON);
|
m_radio->set_current_state(radio::HwInstance::States::PLL_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,8 +34,21 @@ void TransparentClient::apply_settings(const RadioSettings& settings)
|
|||||||
|
|
||||||
void TransparentClient::process()
|
void TransparentClient::process()
|
||||||
{
|
{
|
||||||
if (m_pending_irqs)
|
std::optional<AppState> new_state_request = std::nullopt;
|
||||||
m_processInterrupts();
|
|
||||||
|
{
|
||||||
|
Utility::AtomicScopeGuard<Peripherals::Hal::Samd::StaticHal> 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*)
|
void TransparentClient::m_cbRadioIrqHandler(radio::HwInstance*)
|
||||||
@ -43,9 +60,86 @@ void TransparentClient::m_cbRadioIrqHandler(radio::HwInstance*)
|
|||||||
m_pending_irqs = new_irqs;
|
m_pending_irqs = new_irqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransparentClient::m_processInterrupts()
|
std::optional<TransparentClient::AppState> TransparentClient::m_hwInterruptToNewState()
|
||||||
{
|
{
|
||||||
|
const radio::Interrupts current_irqs = *m_pending_irqs;
|
||||||
m_pending_irqs = std::nullopt;
|
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<radio::Interrupts>(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
20
main.cpp
20
main.cpp
@ -42,21 +42,19 @@ int main()
|
|||||||
const App::RadioSettings settings;
|
const App::RadioSettings settings;
|
||||||
|
|
||||||
m_app.setup(settings);
|
m_app.setup(settings);
|
||||||
radio::HwInstance* radio_hw = radio::HwInstance::instance();
|
|
||||||
|
std::uint32_t counter = 0;
|
||||||
|
|
||||||
/* Replace with your application code */
|
/* Replace with your application code */
|
||||||
while (true)
|
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);
|
m_app->process();
|
||||||
|
Hal::StaticHal::delay(1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,6 +150,7 @@ bool HwInstance::set_current_state(const States& new_state)
|
|||||||
|
|
||||||
register_write(Registers::TRX_STATE, std::uint8_t(new_state));
|
register_write(Registers::TRX_STATE, std::uint8_t(new_state));
|
||||||
m_wait_can_transition();
|
m_wait_can_transition();
|
||||||
|
SKULLC_LOG_DEBUG("HW: New state. %d -> %d.", m_current_state, new_state);
|
||||||
m_current_state = new_state;
|
m_current_state = new_state;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user