Compare commits

...

2 Commits

Author SHA1 Message Date
Erki
bb1a446f77 Basic radio boot-up code + initial state transition 2022-06-30 19:35:05 +03:00
Erki
94368b458a Remove new-ing from radio instance handling 2022-06-29 16:22:02 +03:00
4 changed files with 181 additions and 59 deletions

View File

@ -1,6 +1,7 @@
#include <atmel_start.h>
#include <utility_logging.hpp>
#include <utility_assert.hpp>
#include "radio_hw_instance.hpp"
#include "app_logging.hpp"
@ -11,30 +12,45 @@ namespace Hal = Peripherals::Hal::Samd;
namespace
{
[[noreturn]] void m_faultHandler(const char* file, const int line)
{
SKULLC_LOG_FATAL("Fault: %s:%d", file, line);
__asm__("BKPT");
while (true);
}
int main(void)
}
int main()
{
/* Initializes MCU, drivers and middleware */
atmel_start_init();
Utility::Assert::setHandler(m_faultHandler);
gpio_set_pin_level(OUT_LED_TX, false);
App::Logging::setup();
radio::HwInstance* radio_hw = radio::HwInstance::create_instance();
radio::HwInstance radio_hw;
/* Replace with your application code */
while (1)
while (true)
{
gpio_toggle_pin_level(OUT_LED_RX);
const int16_t radio_num = radio_hw->register_read(0x1C);
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);
radio_status &= 0x1F;
SKULLC_LOG_INFO("Status: %d", radio_status);
delay_ms(1000);
}
}

View File

@ -7,22 +7,30 @@
#include <hal_spi_m_sync.h>
#include "radio_hw_registers.hpp"
namespace radio
{
struct HwInstance
{
static HwInstance* create_instance();
static HwInstance* instance();
HwInstance();
HwInstance(const HwInstance&) = delete;
HwInstance(HwInstance&&) = delete;
HwInstance& operator=(const HwInstance&) = delete;
HwInstance& operator=(HwInstance&&) = delete;
void irq_handler();
uint8_t register_read(uint8_t address);
void register_write(uint8_t address, const uint8_t value);
uint8_t register_read(const Registers& address);
void register_write(const Registers& address, const uint8_t value);
private:
spi_m_sync_descriptor* m_spi = nullptr;
io_descriptor* m_spi_io = nullptr;
HwInstance();
void m_wait_transition_complete();
};
}

View File

@ -0,0 +1,64 @@
//
// Created by erki on 30.06.22.
//
#ifndef SKL_TUNNEL_RADIO_HW_REGISTERS_HPP
#define SKL_TUNNEL_RADIO_HW_REGISTERS_HPP
#include <cstdint>
namespace radio
{
enum class Registers : std::uint8_t
{
TRX_STATUS = (0x01),
TRX_STATE = (0x02),
TRX_CTRL_0 = (0x03),
TRX_CTRL_1 = (0x04),
PHY_TX_PWR = (0x05),
PHY_RSSI = (0x06),
PHY_ED_LEVEL = (0x07),
PHY_CC_CCA = (0x08),
CCA_THRES = (0x09),
RX_CTRL = (0x0A),
SFD_VALUE = (0x0B),
TRX_CTRL_2 = (0x0C),
ANT_DIV = (0x0D),
IRQ_MASK = (0x0E),
IRQ_STATUS = (0x0F),
VREG_CTRL = (0x10),
BATMON = (0x11),
XOSC_CTRL = (0x12),
CC_CTRL_1 = (0x14),
RX_SYN = (0x15),
XAH_CTRL_1 = (0x17),
FTN_CTRL = (0x18),
PLL_CF = (0x1A),
PLL_DCU = (0x1B),
PART_NUM = (0x1C),
VERSION_NUM = (0x1D),
MAN_ID_0 = (0x1E),
MAN_ID_1 = (0x1F),
SHORT_ADDR_0 = (0x20),
SHORT_ADDR_1 = (0x21),
PAN_ID_0 = (0x22),
PAN_ID_1 = (0x23),
IEEE_ADDR_0 = (0x24),
IEEE_ADDR_1 = (0x25),
IEEE_ADDR_2 = (0x26),
IEEE_ADDR_3 = (0x27),
IEEE_ADDR_4 = (0x28),
IEEE_ADDR_5 = (0x29),
IEEE_ADDR_6 = (0x2A),
IEEE_ADDR_7 = (0x2B),
XAH_CTRL_0 = (0x2C),
CSMA_SEED_0 = (0x2D),
CSMA_SEED_1 = (0x2E),
CSMA_BE = (0x2F),
TST_CTRL_DIGI = (0x36)
};
}
#endif //SKL_TUNNEL_RADIO_HW_REGISTERS_HPP

View File

@ -10,72 +10,33 @@
#include <hal_delay.h>
#include <hal_ext_irq.h>
#include <utility_assert.hpp>
#include <utility_staticpointer.hpp>
namespace
{
radio::HwInstance* _INSTANCE = nullptr;
Utility::StaticPointer<radio::HwInstance> _INSTANCE;
void _irq_handler()
{
SKULLC_ASSERT_DEBUG(_INSTANCE.isInitialized());
_INSTANCE->irq_handler();
}
void _startup()
{
gpio_set_pin_level(OUT_RADIO_RST, false);
gpio_set_pin_level(OUT_RADIO_SLP_TR, false);
delay_ms(10);
ext_irq_enable(IN_RADIO_IRQ);
ext_irq_register(IN_RADIO_IRQ, _irq_handler);
gpio_set_pin_level(OUT_RADIO_RST, true);
delay_ms(10);
}
}
namespace radio
{
HwInstance* HwInstance::create_instance()
HwInstance* HwInstance::instance()
{
return new HwInstance{};
}
if (!_INSTANCE.isInitialized())
{
_INSTANCE.setup();
}
void HwInstance::irq_handler()
{
}
uint8_t HwInstance::register_read(uint8_t address)
{
address = (address & 0x3F) | (1 << 7);
gpio_set_pin_level(OUT_RADIO_CS, false);
delay_us(1);
io_write(m_spi_io, &address, 1);
delay_us(1);
uint8_t data = 0xFF;
io_read(m_spi_io, &data, 1);
gpio_set_pin_level(OUT_RADIO_CS, true);
return data;
}
void HwInstance::register_write(const uint8_t address, const uint8_t value)
{
uint8_t data[2] = {
uint8_t((address & 0x3F) | (1 << 7) | (1 << 6)),
uint8_t(value & 0xEF)
};
gpio_set_pin_level(OUT_RADIO_CS, false);
io_write(m_spi_io, data, 2);
gpio_set_pin_level(OUT_RADIO_CS, true);
return &(*_INSTANCE);
}
HwInstance::HwInstance()
@ -86,7 +47,80 @@ HwInstance::HwInstance()
spi_m_sync_get_io_descriptor(m_spi, &m_spi_io);
spi_m_sync_enable(m_spi);
_startup();
gpio_set_pin_level(OUT_RADIO_RST, false);
gpio_set_pin_level(OUT_RADIO_SLP_TR, false);
delay_ms(10);
ext_irq_enable(IN_RADIO_IRQ);
ext_irq_register(IN_RADIO_IRQ, _irq_handler);
gpio_set_pin_level(OUT_RADIO_RST, true);
delay_ms(10);
// Enable safe mode for TX.
register_write(Registers::TRX_CTRL_2, 0x80);
// Disable external clock output.
std::uint8_t trx_ctrl = register_read(Registers::TRX_CTRL_0);
trx_ctrl &= ~(0x07);
trx_ctrl &= ~(0x08);
register_write(Registers::TRX_CTRL_0, trx_ctrl);
// Enable interrupts.
register_write(Registers::IRQ_MASK, 0x08);
// clear interrupts.
register_read(Registers::IRQ_STATUS);
m_wait_transition_complete();
register_write(Registers::TRX_STATE, 0x08);
}
void HwInstance::irq_handler()
{
}
uint8_t HwInstance::register_read(const Registers& address)
{
const uint8_t address_to_write = (uint8_t(address) & 0x3F) | (1 << 7);
gpio_set_pin_level(OUT_RADIO_CS, false);
delay_us(1);
io_write(m_spi_io, &address_to_write, 1);
delay_us(1);
uint8_t data = 0xFF;
io_read(m_spi_io, &data, 1);
gpio_set_pin_level(OUT_RADIO_CS, true);
return data;
}
void HwInstance::register_write(const Registers& address, const uint8_t value)
{
uint8_t data[2] = {
uint8_t((uint8_t(address) & 0x3F) | (1 << 7) | (1 << 6)),
uint8_t(value & 0xEF)
};
gpio_set_pin_level(OUT_RADIO_CS, false);
io_write(m_spi_io, data, 2);
gpio_set_pin_level(OUT_RADIO_CS, true);
}
void HwInstance::m_wait_transition_complete()
{
while (true)
{
int16_t radio_status = register_read(radio::Registers::TRX_STATUS);
radio_status &= 0x1F;
if (radio_status != 0x1F)
return;
}
}
}