Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions boards/ubcrocket/polarity/ubcrocket_polarity.dts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
baro0 = &baro0;
baro1 = &baro1;
pyro0 = &pyro0;
radio0 = &radio0;
sdmmc1 = &sdmmc1;
};
};
Expand All @@ -50,14 +51,24 @@
pinctrl-0 = <&spi1_sck_pa5 &spi1_mosi_pa7 &spi1_miso_pa6>;
pinctrl-names = "default";

// Chip select pin for Pyro board on PE14 (i think)
cs-gpios = <&gpioe 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
cs-gpios = <&gpioe 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
<&gpioe 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;

// Pyro board CS on PE14
pyro0: pyro0@0 {
status = "okay";
compatible = "vnd,spi-device"; // TODO: Could write a custom binding instead of using this test one with raw spi commands
compatible = "vnd,spi-device";
reg = <0>;
spi-max-frequency = <1000000>;
};

// Radio board CS on PE8
radio0: radio0@1 {
status = "okay";
compatible = "vnd,spi-device";
reg = <1>;
spi-max-frequency = <1000000>;
};
};

// Enable and configure SPI2
Expand Down
1 change: 1 addition & 0 deletions firmware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ include(nanopb)
# Generate protobuf sources from falcon-protos
set(FALCON_PROTOS_DIR ${CMAKE_CURRENT_LIST_DIR}/../../modules/falcon-protos)
zephyr_nanopb_sources(app ${FALCON_PROTOS_DIR}/HelloWorldPacket.proto)
zephyr_nanopb_sources(app ${FALCON_PROTOS_DIR}/TelemetryPacket.proto)

target_sources(app PRIVATE
src/main.c
Expand Down
95 changes: 86 additions & 9 deletions firmware/src/radio/radio_thread.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/crc.h>
#include <zephyr/data/cobs.h>
#include <zephyr/net_buf.h>
#include <pb_encode.h>
#include <HelloWorldPacket.pb.h>
#include <TelemetryPacket.pb.h>
#include "data.h"

LOG_MODULE_REGISTER(radio_thread, LOG_LEVEL_INF);

#define RADIO_THREAD_STACK_SIZE 2048
#define RADIO_THREAD_PRIORITY 5
#define RADIO_THREAD_PERIOD_MS 1000

/* SPI protocol constants (ulysses-gnss-radio spec) */
#define SPI_CMD_RADIO_TX 0x04
#define SPI_DUMMY_SIZE 4
#define SPI_HEADER_SIZE (1 + SPI_DUMMY_SIZE) /* 5: cmd + dummy bytes */

/* COBS/framing sizing */
#define MAX_COBS_SIZE 256 /* max size of COBS encoded data, defined by GNSS/RADIO SPI spec */
#define MAX_FRAME_SIZE ((MAX_COBS_SIZE - 2) * 254 / 255) /* 253 */
#define MAX_PAYLOAD_SIZE (MAX_FRAME_SIZE - sizeof(uint16_t)) /* 251 */

/* Total SPI transaction: [CMD:1][DUMMY:4][PAYLOAD:256] = 261 bytes */
#define SPI_TX_SIZE (SPI_HEADER_SIZE + MAX_COBS_SIZE) /* 261 */

NET_BUF_POOL_DEFINE(cobs_src_pool, 1, MAX_FRAME_SIZE, 0, NULL);
NET_BUF_POOL_DEFINE(cobs_dst_pool, 1, MAX_COBS_SIZE, 0, NULL);

Expand All @@ -25,23 +38,79 @@ static struct k_thread radio_thread;
BUILD_ASSERT(MAX_FRAME_SIZE + MAX_FRAME_SIZE / 254 + 2 <= MAX_COBS_SIZE,
"MAX_FRAME_SIZE too large for MAX_COBS_SIZE");

static const struct spi_dt_spec radio_spi =
SPI_DT_SPEC_GET(DT_ALIAS(radio0),
SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8));

static int radio_spi_send(const uint8_t *cobs_data, size_t cobs_len)
{
uint8_t tx_buf[SPI_TX_SIZE] = {0};

tx_buf[0] = SPI_CMD_RADIO_TX;
/* bytes 1-4 are dummy (already zeroed) */
// memcpy(&tx_buf[SPI_HEADER_SIZE], cobs_data, cobs_len);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: delete this comment

memcpy(&tx_buf[SPI_HEADER_SIZE], cobs_data, cobs_len);
/* remaining payload bytes are zero-padded (already zeroed) */

const struct spi_buf spi_tx = {
.buf = tx_buf,
.len = sizeof(tx_buf),
};
const struct spi_buf_set tx_set = {
.buffers = &spi_tx,
.count = 1,
};

return spi_write_dt(&radio_spi, &tx_set);
}

static void radio_thread_fn(void *p1, void *p2, void *p3)
{
uint32_t counter = 0;

if (!spi_is_ready_dt(&radio_spi)) {
LOG_ERR("Radio SPI device not ready");
return;
}
LOG_INF("Radio SPI device ready");

while (1) {
HelloWorldPacket message = HelloWorldPacket_init_zero;
TelemetryPacket message = TelemetryPacket_init_zero;
uint8_t buffer[MAX_PAYLOAD_SIZE];

struct imu_data imu;
struct baro_data baro;
struct state_data state;

get_imu_data(&imu);
get_baro_data(&baro);
get_state_data(&state);

message.counter = counter;
strncpy(message.message, "hello world", sizeof(message.message) - 1);
message.timestamp_ms = (uint32_t)k_uptime_get();
message.state = (FlightState)state.state;

message.accel_x = imu.accel[0];
message.accel_y = imu.accel[1];
message.accel_z = imu.accel[2];
message.gyro_x = imu.gyro[0];
message.gyro_y = imu.gyro[1];
message.gyro_z = imu.gyro[2];

message.kf_altitude = baro.altitude;
message.kf_velocity = baro.velocity;

message.baro0_healthy = baro.baro0.healthy;
message.baro1_healthy = baro.baro1.healthy;

message.ground_altitude = state.ground_altitude;

pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
bool status = pb_encode(&stream, HelloWorldPacket_fields, &message);
bool status = pb_encode(&stream, TelemetryPacket_fields, &message);
size_t message_length = stream.bytes_written;

if (!status) {
LOG_ERR("Failed to encode HelloWorldPacket: %s",
LOG_ERR("Failed to encode TelemetryPacket: %s",
PB_GET_ERROR(&stream));
counter++;
k_sleep(K_MSEC(RADIO_THREAD_PERIOD_MS));
Expand Down Expand Up @@ -75,10 +144,18 @@ static void radio_thread_fn(void *p1, void *p2, void *p3)
int ret = cobs_encode(src_buf, dst_buf, COBS_FLAG_TRAILING_DELIMITER);

if (ret == 0) {
LOG_INF("Encoded packet: counter=%u, pb=%zu, cobs=%u bytes",
counter, message_length, dst_buf->len);
LOG_HEXDUMP_DBG(dst_buf->data, dst_buf->len,
"COBS encoded packet");
/* Send over SPI to radio board */
ret = radio_spi_send(dst_buf->data, dst_buf->len);
if (ret < 0) {
LOG_ERR("SPI write failed: %d", ret);
} else {
LOG_INF("Sent telemetry: counter=%u, alt=%.1f, vel=%.1f, "
"state=%d, pb=%zu, cobs=%u bytes",
counter, (double)message.kf_altitude,
(double)message.kf_velocity,
(int)message.state, message_length,
dst_buf->len);
}
} else {
LOG_ERR("COBS encoding failed: %d", ret);
}
Expand Down
Loading