Compare commits
No commits in common. "0f8b5bb0b1856c42c2bd26ab4ffd998ebb0bf812" and "master" have entirely different histories.
0f8b5bb0b1
...
master
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include "app_settings.hpp"
|
#include "app_settings.hpp"
|
||||||
#include "radio_interrupts.hpp"
|
#include "radio_interrupts.hpp"
|
||||||
#include "radio_protocol_frame.hpp"
|
|
||||||
|
|
||||||
namespace radio
|
namespace radio
|
||||||
{
|
{
|
||||||
@ -35,10 +34,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
radio::HwInstance* m_radio;
|
radio::HwInstance* m_radio;
|
||||||
Utility::FunctionOwned<TransparentClient, void (radio::HwInstance*)> m_isr_cb_pointer;
|
Utility::FunctionOwned<TransparentClient, void (radio::HwInstance*)> m_isr_cb_pointer;
|
||||||
RadioSettings m_active_settings;
|
|
||||||
std::optional<radio::Interrupts> m_pending_irqs = std::nullopt;
|
std::optional<radio::Interrupts> m_pending_irqs = std::nullopt;
|
||||||
std::optional<radio::protocol::FrameStructure> m_tx_buffer_frame = std::nullopt;
|
|
||||||
std::array<std::uint8_t, 128> m_tx_buffer_raw;
|
|
||||||
|
|
||||||
enum class AppState
|
enum class AppState
|
||||||
{
|
{
|
||||||
@ -57,8 +53,6 @@ private:
|
|||||||
void m_processState();
|
void m_processState();
|
||||||
void m_initiateTx();
|
void m_initiateTx();
|
||||||
bool m_txBufferIsReady();
|
bool m_txBufferIsReady();
|
||||||
|
|
||||||
void m_prepareTransmission(const std::uint16_t dst_mac, const std::array<std::uint8_t, 22>& buffer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
namespace Hal = Peripherals::Hal::Samd;
|
namespace Hal = Peripherals::Hal::Samd;
|
||||||
|
|
||||||
using Logger = Utility::AsyncLogger<Hal::SerialInterfaceAsync<usart_async_descriptor>, Hal::StaticHal, 10, 255>;
|
using Logger = Utility::AsyncLogger<Hal::SerialInterfaceAsync<usart_async_descriptor>, Hal::StaticHal, 5, 255>;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|||||||
@ -6,11 +6,8 @@
|
|||||||
|
|
||||||
#include "app_transparent_client.hpp"
|
#include "app_transparent_client.hpp"
|
||||||
#include "skullc_samd21_hal.hpp"
|
#include "skullc_samd21_hal.hpp"
|
||||||
#include "radio_protocol.hpp"
|
#include "utility_logging.hpp"
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include <utility_logging.hpp>
|
|
||||||
#include <utility_atomicscopeguard.hpp>
|
#include <utility_atomicscopeguard.hpp>
|
||||||
|
|
||||||
namespace App
|
namespace App
|
||||||
@ -33,8 +30,6 @@ void TransparentClient::apply_settings(const RadioSettings& settings)
|
|||||||
m_radio->set_pan_id(settings.pan_id);
|
m_radio->set_pan_id(settings.pan_id);
|
||||||
m_radio->set_tx_power(settings.tx_power_dbm);
|
m_radio->set_tx_power(settings.tx_power_dbm);
|
||||||
m_radio->set_max_retries(settings.retries);
|
m_radio->set_max_retries(settings.retries);
|
||||||
|
|
||||||
m_active_settings = settings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransparentClient::process()
|
void TransparentClient::process()
|
||||||
@ -53,20 +48,6 @@ void TransparentClient::process()
|
|||||||
if (new_state_request)
|
if (new_state_request)
|
||||||
m_transitionToState(*new_state_request);
|
m_transitionToState(*new_state_request);
|
||||||
|
|
||||||
static int count = 0;
|
|
||||||
static bool sent = false;
|
|
||||||
if (count++ == 5000 && !sent)
|
|
||||||
{
|
|
||||||
sent = true;
|
|
||||||
|
|
||||||
if (m_active_settings.short_address == 11)
|
|
||||||
{
|
|
||||||
SKULLC_LOG_DEBUG("Attempting send.");
|
|
||||||
const std::array<std::uint8_t, 22> buff = {"Lol this is a message"};
|
|
||||||
m_prepareTransmission(18, buff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_processState();
|
m_processState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,47 +134,12 @@ void TransparentClient::m_processState()
|
|||||||
|
|
||||||
void TransparentClient::m_initiateTx()
|
void TransparentClient::m_initiateTx()
|
||||||
{
|
{
|
||||||
m_radio->set_current_state(radio::HwInstance::States::PLL_ON);
|
return;
|
||||||
const std::size_t buffer_size = radio::protocol::composeFrameBuffer(m_tx_buffer_raw.data(), *m_tx_buffer_frame);
|
|
||||||
|
|
||||||
SKULLC_LOG_DEBUG("APP: Initiating TX of %u bytes.", buffer_size);
|
|
||||||
|
|
||||||
char raw_data[255] = { 0 };
|
|
||||||
for (std::size_t i = 0, data_offset = 0; i < buffer_size; i++)
|
|
||||||
{
|
|
||||||
data_offset += std::sprintf(&raw_data[data_offset], "%02X", m_tx_buffer_raw[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Utility::skullc_logger->log("\n\rDATA\n\r%s\n\r", raw_data);
|
|
||||||
|
|
||||||
m_radio->sram_write(m_tx_buffer_raw.data(), buffer_size + 1);
|
|
||||||
m_radio->set_current_state(radio::HwInstance::States::BUSY_TX);
|
|
||||||
|
|
||||||
m_tx_buffer_frame = std::nullopt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TransparentClient::m_txBufferIsReady()
|
bool TransparentClient::m_txBufferIsReady()
|
||||||
{
|
{
|
||||||
return m_tx_buffer_frame.has_value();
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
void TransparentClient::m_prepareTransmission(const std::uint16_t dst_mac, const std::array<std::uint8_t, 22>& buffer)
|
|
||||||
{
|
|
||||||
using namespace radio::protocol;
|
|
||||||
Address src_address;
|
|
||||||
src_address.setShortAddress(m_active_settings.short_address);
|
|
||||||
src_address.pan_id = m_active_settings.pan_id;
|
|
||||||
|
|
||||||
Address dst_address;
|
|
||||||
dst_address.setShortAddress(dst_mac);
|
|
||||||
dst_address.pan_id = m_active_settings.pan_id;
|
|
||||||
|
|
||||||
FrameStructure frame = FrameStructure::createDataFrame()
|
|
||||||
.setSourceAddress(src_address)
|
|
||||||
.setDestinationAddress(dst_address)
|
|
||||||
.setPayload(buffer);
|
|
||||||
|
|
||||||
m_tx_buffer_frame = frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
6
main.cpp
6
main.cpp
@ -11,9 +11,6 @@
|
|||||||
|
|
||||||
namespace Hal = Peripherals::Hal::Samd;
|
namespace Hal = Peripherals::Hal::Samd;
|
||||||
|
|
||||||
#define APP_NODE_ID 11
|
|
||||||
//#define APP_NODE_ID 18
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -42,8 +39,7 @@ int main()
|
|||||||
|
|
||||||
SKULLC_LOG_DEBUG("Begin.");
|
SKULLC_LOG_DEBUG("Begin.");
|
||||||
|
|
||||||
App::RadioSettings settings;
|
const App::RadioSettings settings;
|
||||||
settings.short_address = APP_NODE_ID;
|
|
||||||
|
|
||||||
m_app.setup(settings);
|
m_app.setup(settings);
|
||||||
|
|
||||||
|
|||||||
@ -66,8 +66,6 @@ struct HwInstance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sram_write(const std::uint8_t* data, const std::size_t length, const std::uint8_t offset = 0);
|
|
||||||
|
|
||||||
States current_state() const;
|
States current_state() const;
|
||||||
bool set_current_state(const States& new_state);
|
bool set_current_state(const States& new_state);
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
namespace radio::protocol
|
namespace radio::protocol
|
||||||
{
|
{
|
||||||
|
|
||||||
std::size_t composeFrameBuffer(std::uint8_t* data, const FrameStructure& frame);
|
std::size_t composeFrameBuffer(const FrameStructure& frame);
|
||||||
FrameStructure decomposeFrameBuffer(const std::uint8_t* data);
|
FrameStructure decomposeFrameBuffer(const std::uint8_t* data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -120,21 +120,6 @@ void HwInstance::register_write(const Registers& address, const uint8_t value)
|
|||||||
gpio_set_pin_level(OUT_RADIO_CS, true);
|
gpio_set_pin_level(OUT_RADIO_CS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HwInstance::sram_write(const std::uint8_t* data, const std::size_t length, const std::uint8_t offset)
|
|
||||||
{
|
|
||||||
std::uint8_t header_data[2] = {
|
|
||||||
std::uint8_t(0x40),
|
|
||||||
offset
|
|
||||||
};
|
|
||||||
|
|
||||||
gpio_set_pin_level(OUT_RADIO_CS, false);
|
|
||||||
|
|
||||||
io_write(m_spi_io, header_data, 2);
|
|
||||||
io_write(m_spi_io, data, length);
|
|
||||||
|
|
||||||
gpio_set_pin_level(OUT_RADIO_CS, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
HwInstance::States HwInstance::current_state() const
|
HwInstance::States HwInstance::current_state() const
|
||||||
{
|
{
|
||||||
return m_current_state;
|
return m_current_state;
|
||||||
|
|||||||
@ -57,7 +57,6 @@ FrameStructure FrameStructure::createDataFrame()
|
|||||||
FrameStructure& FrameStructure::setPayload(const std::uint8_t* data, const std::uint8_t length)
|
FrameStructure& FrameStructure::setPayload(const std::uint8_t* data, const std::uint8_t length)
|
||||||
{
|
{
|
||||||
std::memmove(payload.data(), data, length);
|
std::memmove(payload.data(), data, length);
|
||||||
payload_length = length;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,142 +0,0 @@
|
|||||||
from dataclasses import dataclass
|
|
||||||
from enum import Enum
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
MAX_PAYLOAD_LENGTH = 127
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class PhyHeader:
|
|
||||||
frame_length: int
|
|
||||||
|
|
||||||
@property
|
|
||||||
def size(self) -> int:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_bytes(data: bytes) -> "PhyHeader":
|
|
||||||
return PhyHeader(data[0] & 0x7F)
|
|
||||||
|
|
||||||
|
|
||||||
class FrameType(Enum):
|
|
||||||
BEACON = 0b000
|
|
||||||
DATA = 0b001
|
|
||||||
ACKNOWLEDGE = 0b010
|
|
||||||
MAC_COMMAND = 0b011
|
|
||||||
|
|
||||||
|
|
||||||
class AddressingMode(Enum):
|
|
||||||
NOT_SPECIFIED = 0b00
|
|
||||||
RESERVED = 0b01
|
|
||||||
SHORT = 0b10
|
|
||||||
LONG = 0b11
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class FrameControlField:
|
|
||||||
type: FrameType
|
|
||||||
security_enabled: bool
|
|
||||||
frame_pending: bool
|
|
||||||
ack_requested: bool
|
|
||||||
pan_id_compression: bool
|
|
||||||
destination_addressing_mode: AddressingMode
|
|
||||||
frame_version: int
|
|
||||||
source_addressing_mode: AddressingMode
|
|
||||||
|
|
||||||
@property
|
|
||||||
def size(self) -> int:
|
|
||||||
return 2
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_bytes(data: bytes) -> "FrameControlField":
|
|
||||||
frame_type = FrameType((data[0] & 0b1110_0000) >> 5)
|
|
||||||
security_enabled = bool(data[0] & 0b0001_0000 >> 4)
|
|
||||||
frame_pending = bool((data[0] & 0b0000_1000) >> 3)
|
|
||||||
ack_requested = bool((data[0] & 0b0000_0100) >> 2)
|
|
||||||
pan_id_compression = bool((data[0] & 0b0000_0010) >> 1)
|
|
||||||
|
|
||||||
dst_addressing = AddressingMode((data[1] & 0b0011_0000) >> 4)
|
|
||||||
frame_version = (data[1] & 0b0000_1100) >> 2
|
|
||||||
src_addressing = AddressingMode((data[1] & 0b0000_0011))
|
|
||||||
|
|
||||||
return FrameControlField(
|
|
||||||
frame_type,
|
|
||||||
security_enabled,
|
|
||||||
frame_pending,
|
|
||||||
ack_requested,
|
|
||||||
pan_id_compression,
|
|
||||||
dst_addressing,
|
|
||||||
frame_version,
|
|
||||||
src_addressing
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Address:
|
|
||||||
mac: int
|
|
||||||
pan_id: int
|
|
||||||
is_short_mode: bool = False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def size(self) -> int:
|
|
||||||
if self.is_short_mode:
|
|
||||||
return 2 + 2
|
|
||||||
else:
|
|
||||||
return 2 + 8
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_bytes(data: bytes, addressing_mode: AddressingMode) -> Optional["Address"]:
|
|
||||||
if addressing_mode == AddressingMode.NOT_SPECIFIED:
|
|
||||||
return None
|
|
||||||
|
|
||||||
pan = int.from_bytes(data[0:2], byteorder="little")
|
|
||||||
|
|
||||||
if addressing_mode == AddressingMode.SHORT:
|
|
||||||
is_short = True
|
|
||||||
address = int.from_bytes(data[2:4], byteorder="little")
|
|
||||||
else:
|
|
||||||
is_short = False
|
|
||||||
address = int.from_bytes(data[2:10], byteorder="little")
|
|
||||||
|
|
||||||
return Address(
|
|
||||||
address,
|
|
||||||
pan,
|
|
||||||
is_short
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class MacProtocolDataUnit:
|
|
||||||
frame_control_field: FrameControlField
|
|
||||||
sequence_number: int
|
|
||||||
destination_address: Optional[Address]
|
|
||||||
source_address: Optional[Address]
|
|
||||||
payload: bytes
|
|
||||||
frame_checksum: int
|
|
||||||
|
|
||||||
def payload_length(self, header: PhyHeader) -> int:
|
|
||||||
# Payload length = length - FCF size - sequence nr (2 bytes) - src address size - dst address size
|
|
||||||
# - checksum size (2 bytes)
|
|
||||||
return header.frame_length - self.frame_control_field.size \
|
|
||||||
- 2 \
|
|
||||||
- self.source_address.size \
|
|
||||||
- self.destination_address.size \
|
|
||||||
- 2
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_bytes(data: bytes, header: PhyHeader) -> "MacProtocolDataUnit":
|
|
||||||
offset = 0
|
|
||||||
|
|
||||||
fcf = FrameControlField.from_bytes(data)
|
|
||||||
offset += fcf.size
|
|
||||||
|
|
||||||
sequence_nr = int.from_bytes(data[offset:], byteorder="little")
|
|
||||||
offset += 2
|
|
||||||
|
|
||||||
dst_address = Address.from_bytes(data[offset:], fcf.destination_addressing_mode)
|
|
||||||
offset += dst_address.size if dst_address else 0
|
|
||||||
src_address = Address.from_bytes(data[offset:], fcf.source_addressing_mode)
|
|
||||||
offset += src_address.size if src_address else 0
|
|
||||||
|
|
||||||
# @todo: payload and CRC parsing.
|
|
||||||
return MacProtocolDataUnit(fcf, sequence_nr, dst_address, src_address, bytes(), 0)
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
from packet_structs import *
|
|
||||||
|
|
||||||
|
|
||||||
def decode_sram(data: bytes) -> (PhyHeader, MacProtocolDataUnit):
|
|
||||||
header = PhyHeader.from_bytes(data)
|
|
||||||
mpdu = MacProtocolDataUnit.from_bytes(data[1:], header)
|
|
||||||
|
|
||||||
return header, mpdu
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raw_data_str = "230198002300120023000B004C6F6C20746869732069732061206D65737361676500"
|
|
||||||
raw_data = bytes.fromhex(raw_data_str)
|
|
||||||
|
|
||||||
print(f"Raw:\n\r{raw_data}\n\r")
|
|
||||||
header, mpdu = decode_sram(raw_data)
|
|
||||||
|
|
||||||
print(f"Header: {header}")
|
|
||||||
print(f"MPDU: {mpdu}")
|
|
||||||
Loading…
x
Reference in New Issue
Block a user