Initial public release of WII5 Buoy firmware

Firmware for an autonomous wave-measurement buoy (ATmega2560-based
WII5 v2 board). Reads wave motion from a Sparton AHRS-M1/M2 IMU,
samples GPS and battery state, and reports back over Iridium SBD
satellite telemetry. Originally developed 2012-2024.

This is the first public release. Code, documentation, and field-tested
operating modes (Capture, Sleep, Position, ManualTest, SelfTest,
LowBattery) are licensed under Apache 2.0 — see LICENSE and NOTICE.

See README.md for an overview and build instructions, CONTRIBUTING.md
for how to contribute, and DEPLOYMENTS.md for the field-deployment log.
This commit is contained in:
2026-05-07 16:00:21 +10:00
commit 295abb37ee
122 changed files with 38142 additions and 0 deletions
+239
View File
@@ -0,0 +1,239 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2012-2024 Scott Penrose <scottp@dd.com.au> and WII5 Buoy contributors
//
// This file is part of WII5 Buoy firmware.
// See LICENSE for full terms.
/**
* @file WII5BinData.h
* @brief Binary message format for Iridium SBD: layout, packing, and split logic.
*/
#ifndef WII5BinData_h
#define WII5BinData_h
#include <WII5.h>
// Header Size = 15
typedef struct {
// 0
uint16_t wii_binary_id; // Fixed ID for the old system - 60001
// 2
uint32_t bindata_type; // Which packet type is this.
// 6
uint8_t bindata_packet; // Which part of the packet is this - note we don't need total, can claculate from type
// Essential data to allow packets to be put back together
// 7
uint32_t deviceId; // Ideally move back to uint32_t
// 11
uint32_t recordCount;
} WII5_BINDATA_HEADER;
#define WII5_BINDATA_0_TEXT "Status,Temp,Volts,GPS"
typedef struct {
// uint8_t deviceId_SHORT; // Ideally move back to uint32_t
uint32_t status; // Special status bit fields to tell us what is going on
time_t last;
int16_t voltage; // 0..16 with 2 decimal places -10000 .. + 10000
int16_t temperature; // -100 .. +100 with two decimal places 2452
uint8_t mode;
float gps_lat;
float gps_lon;
// Ideally status - number or reboots/resets and other errors
// How many messages sent, disk space and lots more.
} WII5_BINDATA_0;
#define WII5_BINDATA_1_TEXT "GPS Extended"
// Detailed GPS data
typedef struct {
uint16_t lastRunTime; // Number of seconds to lock last time
time_t when; // When we last got a time lock
int16_t altitude; // Altitutde in meters
uint8_t satellites;
float hdop;
} WII5_BINDATA_1;
#define WII5_BINDATA_2_TEXT "Iridium Extended"
// Detailed Iridium data
typedef struct {
uint16_t lastRunTime; // How long did the last one take
uint8_t signalQuality;
// uint32_t lastId; (the last id sent etc)
// total_sent
// total_received (I think the Iridium knows)
// imei - very large
} WII5_BINDATA_2;
#define WII5_BINDATA_3_TEXT "Message - Small (<50 bytes)"
// Commands - Tiny version
typedef struct {
uint32_t status; // Special status bit fields to tell us what is going on
uint32_t command; // Commands as usual, top bit (32) is on for ACK
uint8_t id; // Resposne must contain request id in case we have many
uint8_t response;
// TODO 2024 - This is a BREAKING CHANGE for any old buoys - could be fixed on WII3_Server BinData by supporting 30 or 25 text chars
char message[25]; // On ACK/NACK it can contain error data... TODO 2024 Changed from 30 to 25 - where else / what else
} WII5_BINDATA_3;
#define WII5_BINDATA_4_TEXT "Message - large (< 300 bytes)"
// Commands - full size version
typedef struct {
// uint32_t status; // Special status bit fields to tell us what is going on
// uint32_t command; // Commands as usual, top bit (32) is on for ACK
// uint8_t id;
// uint8_t response;
char message[235]; // On ACK/NACK it can contain error data
// Here we may use this to send a script, by including in this
// message tag - sh/1/3: - ie. write to shell script, Part 1 of 3
// Rest is concat to the end of the scipt
} WII5_BINDATA_4;
// TODO Idea - Results/Processed/Run sumary - HMO etc?
#define WII5_BINDATA_5_TEXT "Extra Buoy Information"
typedef struct {
uint32_t runCount;
uint32_t integerVersion; // 16
// char version[20];
} WII5_BINDATA_5;
#define WII5_BINDATA_6_TEXT "Processed - QF"
typedef struct {
float qf_mvar;
float qf_p_accel;
// (gyro not being used) float qf_p_gyro;
// (mag not being used) float qf_p_mag;
// (kistler not being used) float qf_kist",
// (kistler not being used) qf_p_kist",
float qf_imu;
float qf_head;
float a;
float b;
} WII5_BINDATA_6;
#define WII5_BINDATA_7_TEXT "Processed - _max"
typedef struct {
float tz_max[4];
float htm_max[4];
float hcm_max[4];
float hz_max[4];
} WII5_BINDATA_7;
#define WII5_BINDATA_8_TEXT "WII5Processed1"
typedef struct {
WII5Processed1 processed1;
} WII5_BINDATA_8;
#define WII5_BINDATA_9_TEXT "WII5Processed2"
typedef struct {
WII5Processed2 processed2;
} WII5_BINDATA_9;
#define WII5_BINDATA_10_TEXT "WII5MetaDataObject"
typedef struct {
WII5MetaDataObject metadata;
} WII5_BINDATA_10;
// Processed - Direction
#define WII5_BINDATA_11_TEXT "Processed - Direction array"
typedef struct {
int direction[54];
} WII5_BINDATA_11;
#define WII5_BINDATA_12_TEXT "Processed - Misc and Quality"
// Processed - Metadatas full (excluding kistler, mag, gyro)
// TODO: trim BinData record set to active fields
typedef struct {
float hmo;
float theta;
float dp;
float s;
float r;
float nstd;
float f2;
float yaw_std;
float open_water;
float power_diff;
float tp;
} WII5_BINDATA_12;
// Moments
#define WII5_BINDATA_13_TEXT "Processed - Moment array"
typedef struct {
float moments[7];
} WII5_BINDATA_13;
// PSD
#define WII5_BINDATA_14_TEXT "Processed - PSD array"
typedef struct {
float psd[55];
} WII5_BINDATA_14;
typedef struct {
} WII5_BINDATA_15;
/**
* @brief Binary message format for Iridium SBD.
*
* Each SBD message starts with a WII5_BINDATA_HEADER (binary id 60001,
* record metadata, a 32-bit `bindata_type` bitmap), then a sequence of
* fixed-size payload structs (WII5_BINDATA_0 .. _15) selected by which
* bits are set in `bindata_type`. The `getSplit()` helper splits an
* over-sized type bitmap across multiple 340-byte SBD frames.
*/
class WII5BinData {
public:
WII5BinData() {}
/** @brief One-time bring-up. */
void begin();
/** @brief Pop the next chunk that fits in `max_size` bytes; advances start_bit. */
bool getSplit(uint32_t in_t, uint16_t max_size, uint8_t* start_bit, uint32_t* out_t);
/** @brief Size of a single payload struct selected by bit `b`. */
uint16_t getSizeOne(uint8_t b);
/** @brief Set bit `b` in `t` and return the modified value. */
uint16_t setBit(uint32_t t, uint8_t b);
/** @brief Total wire size for a type bitmap, including the header. */
uint16_t getSize(uint32_t t);
/** @brief Total payload size for a type bitmap, excluding the header. */
uint16_t getSizeObj(uint32_t t);
/** @brief Initialize a binary buffer with header for type `t`. */
bool createData(uint32_t t, void* buf, uint16_t maxSize, uint32_t recordCount = 0);
/** @brief Fill the payload structs in `buf` from live device state. */
bool setData(uint32_t t, void* buf, uint16_t maxSize);
/** @brief Fill the payload structs from a pre-loaded SD metadata block. */
bool setBlockMetadata(uint32_t t, void* buf, uint16_t maxSize, WII5MetaDataObject* metadata);
/** @brief Fill the payload structs from a pre-loaded SD results (processed) block. */
bool setBlockResults(uint32_t t, void* buf, uint16_t maxSize, WII5Processed* processed);
/** @brief Print a human-readable dump of the buffer to the console. */
void dumpData(void* buf, uint16_t maxSize, bool values);
/** @brief Print the size of every BinData payload type. */
void showSizes(char* bufout = NULL, uint16_t bufsize = 0);
/** @brief Print the split sequence for a given type bitmap. */
void showSplit(uint32_t in_t, uint16_t max_size, char* bufout = NULL, uint16_t bufsize = 0);
/** @brief Human-readable title for payload bit `bit`. */
char* strTitle(uint8_t bit, bool ext);
/** @brief Does this buffer's header type-bitmap include bit `bit`? */
bool hasType(uint8_t bit, void* buf, uint16_t maxSize);
/** @brief Pointer to the payload struct for bit `bit` inside `buf`. */
void* getData(uint8_t bit, void* buf, uint16_t maxSize);
/** @brief Validate header and return pointer to the embedded command struct. */
WII5_BINDATA_3* getCommand(void* buf, uint16_t maxSize);
/** @brief Print the list of bits set in a type bitmap. */
void showBlocks(uint32_t t);
protected:
bool testDone;
};
extern WII5BinData wii5BinData;
#endif