From 8cddb07ee43a12f7e8931479f4b6b605aab08761 Mon Sep 17 00:00:00 2001 From: Erki Date: Wed, 13 Jul 2022 22:41:57 +0300 Subject: [PATCH] Configuration tooling added --- main.cpp | 12 +-- radio/include/radio_hw_instance.hpp | 29 ++++++++ radio/src/radio_hw_instance.cpp | 111 ++++++++++++++++++++++++++-- 3 files changed, 138 insertions(+), 14 deletions(-) diff --git a/main.cpp b/main.cpp index e5cdfe2..1762ff0 100644 --- a/main.cpp +++ b/main.cpp @@ -34,7 +34,7 @@ int main() App::Logging::setup(); - radio::HwInstance radio_hw; + radio::HwInstance* radio_hw = radio::HwInstance::instance(); SKULLC_LOG_DEBUG("Begin."); /* Replace with your application code */ @@ -42,12 +42,12 @@ int main() { gpio_toggle_pin_level(OUT_LED_RX); - const int16_t radio_num = radio_hw.register_read(radio::Registers::PART_NUM); + const int16_t radio_num = radio_hw->register_read(radio::Registers::PART_NUM); SKULLC_LOG_INFO("Reg 0x1C: %d", radio_num); gpio_toggle_pin_level(OUT_LED_TX); - int16_t radio_status = radio_hw.register_read(radio::Registers::TRX_STATUS); + int16_t radio_status = radio_hw->register_read(radio::Registers::TRX_STATUS); radio_status &= 0x1F; SKULLC_LOG_INFO("Status: %d", radio_status); @@ -56,19 +56,19 @@ int main() if (radio_status == 0x08 && transitioned == 0) { SKULLC_LOG_DEBUG("Transitioning..."); - radio_hw.set_current_state(radio::HwInstance::States::PLL_ON); + radio_hw->set_current_state(radio::HwInstance::States::PLL_ON); transitioned = 1; } else if (radio_status == 0x09 && transitioned == 1) { SKULLC_LOG_DEBUG("Transitioning 2..."); - radio_hw.set_current_state(radio::HwInstance::States::RX_ON); + radio_hw->set_current_state(radio::HwInstance::States::RX_ON); transitioned = 2; } else if (radio_status == 0x09 && transitioned == 1) { SKULLC_LOG_DEBUG("Transitioning 2..."); - radio_hw.set_current_state(radio::HwInstance::States::RX_ON); + radio_hw->set_current_state(radio::HwInstance::States::RX_ON); transitioned = 2; } diff --git a/radio/include/radio_hw_instance.hpp b/radio/include/radio_hw_instance.hpp index b19b70a..f6e7b0e 100644 --- a/radio/include/radio_hw_instance.hpp +++ b/radio/include/radio_hw_instance.hpp @@ -6,6 +6,10 @@ #define SKL_TUNNEL_RADIO_HW_INSTANCE_HPP #include +#include +#include +#include +#include #include "radio_hw_registers.hpp" @@ -43,8 +47,33 @@ struct HwInstance uint8_t register_read(const Registers& address); void register_write(const Registers& address, const uint8_t value); + template + void register_write(const Registers& initial_address, const T value) + { + static_assert(std::is_integral_v, "T must be an integral type."); + std::array data_array; + std::memcpy(data_array.data(), &value, sizeof(T)); + + for (std::uint8_t i = 0; i < sizeof(T); i++) + { + const std::uint8_t address = std::uint8_t(initial_address) + i; + register_write(Registers(address), std::uint8_t(data_array[i])); + } + } + States current_state() const; bool set_current_state(const States& new_state); + + void set_address_short(const std::uint16_t address); + void set_address_long(const std::uint64_t address); + void set_channel(const std::uint8_t channel); + void set_pan_id(const std::uint16_t pan_id); + void set_tx_power(std::int16_t power); + void set_max_retries(std::uint8_t retries); + void set_csma_max_retries(const std::optional& retries); + void set_csma_backoff_exponential(std::uint8_t max, std::uint8_t min); + void set_csma_seed(const std::uint16_t entropy); + private: spi_m_sync_descriptor* m_spi = nullptr; io_descriptor* m_spi_io = nullptr; diff --git a/radio/src/radio_hw_instance.cpp b/radio/src/radio_hw_instance.cpp index f47a32f..cc1a43d 100644 --- a/radio/src/radio_hw_instance.cpp +++ b/radio/src/radio_hw_instance.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace { @@ -113,6 +114,11 @@ void HwInstance::register_write(const Registers& address, const uint8_t value) gpio_set_pin_level(OUT_RADIO_CS, true); } +HwInstance::States HwInstance::current_state() const +{ + return m_current_state; +} + bool HwInstance::set_current_state(const States& new_state) { if (new_state == m_current_state) @@ -127,43 +133,36 @@ bool HwInstance::set_current_state(const States& new_state) case States::P_ON: if (new_state == States::TRX_OFF) { - can_transition = true; trx_state_value = 0x08; } break; case States::TRX_OFF: if (new_state == States::RX_ON) { - can_transition = true; trx_state_value = 0x06; } else if (new_state == States::PLL_ON) { - can_transition = true; trx_state_value = 0x09; } break; case States::RX_ON: if (new_state == States::PLL_ON) { - can_transition = true; trx_state_value = 0x09; } else if (new_state == States::TRX_OFF) { - can_transition = true; trx_state_value = 0x08; } break; case States::PLL_ON: if (new_state == States::RX_ON) { - can_transition = true; trx_state_value = 0x06; } else if (new_state == States::TRX_OFF) { - can_transition = true; trx_state_value = 0x08; } break; @@ -172,7 +171,7 @@ bool HwInstance::set_current_state(const States& new_state) return false; } - if (can_transition) + if (trx_state_value) { register_write(Registers::TRX_STATE, *trx_state_value); m_wait_transition_complete(); @@ -185,6 +184,102 @@ bool HwInstance::set_current_state(const States& new_state) } } +void HwInstance::set_address_short(const std::uint16_t address) +{ + register_write(Registers::SHORT_ADDR_0, address); +} + +void HwInstance::set_address_long(const std::uint64_t address) +{ + register_write(Registers::IEEE_ADDR_0, address); +} + +void HwInstance::set_channel(const std::uint8_t channel) +{ + static constexpr std::uint8_t channel_min = 11; + static constexpr std::uint8_t channel_max = 26; + + SKULLC_ASSERT_DEBUG(channel >= channel_min && channel <= channel_max); + if (channel > channel_max || channel < channel_min) + { + return; + } + + std::uint8_t reg_value = register_read(Registers::PHY_CC_CCA); + reg_value &= ~0x1F; + reg_value |= channel & 0x1F; + register_write(Registers::PHY_CC_CCA, reg_value); +} + +void HwInstance::set_pan_id(const std::uint16_t pan_id) +{ + register_write(Registers::PAN_ID_0, pan_id); +} + +void HwInstance::set_tx_power(std::int16_t power) +{ + static constexpr std::array dbm_to_tx_power{ + 0x0F, 0x0F, 0x0F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0C, + 0x0B, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x03, 0x00 + }; + + power += 17; + power = std::clamp(power, std::int16_t(0), std::int16_t(21)); + register_write(Registers::PHY_TX_PWR, dbm_to_tx_power[power]); +} + +void HwInstance::set_max_retries(std::uint8_t retries) +{ + retries = std::clamp(retries, 0, 7); + + constexpr std::uint8_t mask = 0xF0; + + std::uint8_t reg_value = register_read(Registers::XAH_CTRL_0); + reg_value &= ~mask; + reg_value |= (retries << 4) & mask; + register_write(Registers::XAH_CTRL_0, reg_value); +} + +void HwInstance::set_csma_max_retries(const std::optional& retries) +{ + std::uint8_t value_to_write = 0; + if (!retries) + value_to_write = 7; + else + value_to_write = std::clamp(*retries, 0, 5); + + constexpr std::uint8_t mask = 0x0E; + + std::uint8_t reg_value = register_read(Registers::XAH_CTRL_0); + reg_value &= ~mask; + reg_value |= (value_to_write << 1) & mask; + register_write(Registers::XAH_CTRL_0, reg_value); +} + +void HwInstance::set_csma_backoff_exponential(std::uint8_t max, std::uint8_t min) +{ + max = std::clamp(max, 0, 8); + min = std::clamp(min, 0, max); + + const std::uint8_t reg_value = (max << 4) | min; + register_write(Registers::CSMA_BE, reg_value); +} + +void HwInstance::set_csma_seed(const std::uint16_t entropy) +{ + std::array entropy_data{ 0 }; + std::memcpy(entropy_data.data(), &entropy, 2); + + register_write(Registers::CSMA_SEED_0, entropy_data[0]); + + constexpr std::uint8_t mask = 0x07; + + std::uint8_t reg_value = register_read(Registers::CSMA_SEED_1); + reg_value &= ~mask; + reg_value |= entropy_data[1] & mask; + register_write(Registers::CSMA_SEED_1, reg_value); +} + void HwInstance::m_wait_transition_complete() { while (true)