Files
scottp 295abb37ee 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.
2026-05-07 16:27:18 +10:00

359 lines
9.2 KiB
C++

// 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 WII5Config.cpp
* @brief Persistent configuration in EEPROM: device ID, mode defaults, calibrations.
*/
/*
WII5Config
*/
#include <Arduino.h>
#include <WII5Config.h>
#include <WII5Sh3dConsole.h>
void WII5Config::begin() {
sh3dNodeConfig.begin();
_deviceId = (uint32_t)(sh3dNodeConfig.getNodeId());
readConfigData();
readStatusData();
#ifdef WII5_DEBUG_SERIAL
SerialDebug.print(F("CONFIG:ID:"));
SerialDebug.print(getDeviceId());
SerialDebug.println();
#endif
console.log(LOG_DEBUG, F("Config: id=%lu"), getDeviceId());
}
void WII5Config::resetStatusData() {
// Tag it
statusData.type = WII5_DATA_STATUS_TYPE;
statusData.version = WII5_DATA_STATUS_VERSION;
// statusData.xxxCount = 0;
}
void WII5Config::resetConfigData() {
// Tag it
configData.type = WII5_DATA_CONFIG_TYPE;
configData.version = WII5_DATA_CONFIG_VERSION;
// Sensible defaults
configData.gpsTimeout = 300;
configData.flags = 0x0;
configData.disableLowBattery = 0;
// MODE: Capture
configData.capturePeriod = 20;
configData.captureBinaryType = 769;
configData.captureRecords = 5120;
//
// 1 = Packet 0 - dates, times, lat, lon, etc.
// 769 = 0,8,9
//
// MODE: Position
configData.positionPeriod = 5;
configData.positionBinaryType = 1; // TODO Bogus
// MODE: Sleep
configData.sleepPeriod = 12 * 60; // 12 hours
configData.sleepBinaryType = 1; // TODO Bogus
configData.sleepUntil = 0; //
// MODE: Default and Temporary
configData.defaultMode = WII5MODE_CAPTURE;
configData.temporaryMode = WII5MODE_NONE;
configData.temporaryModeExpires = 0;
// Battery
configData.batteryLow = 900;
configData.batteryMid = 1050;
// Save it
updateConfigData();
}
// WARNING: Don't want to do this without clearning SD Card !
void WII5Config::resetCounters() {
sh3dNodeConfig.clearRecordCount();
sh3dNodeConfig.clearRunCount();
}
void WII5Config::readStatusData() {
if (sizeof(statusData) > WII5CONFIG_MAXBLOCK) {
console.log(LOG_ERROR, F("Config: Size of Status too big. Size=%d, Maxiumum=%d"), sizeof(statusData), WII5CONFIG_MAXBLOCK);
}
EEPROM.readBlock(WII5CONFIG_OFFSET + WII5CONFIG_STATUSDATA, statusData);
// TODO checking data etc.
}
void WII5Config::updateStatusData() {
EEPROM.updateBlock(WII5CONFIG_OFFSET + WII5CONFIG_STATUSDATA, statusData);
}
void WII5Config::readConfigData() {
if (sizeof(configData) > WII5CONFIG_MAXBLOCK) {
console.log(LOG_ERROR, F("Config: Size of Config too big. Size=%d, Maxiumum=%d"), sizeof(configData), WII5CONFIG_MAXBLOCK);
}
EEPROM.readBlock(WII5CONFIG_OFFSET + WII5CONFIG_CONFIGDATA, configData);
// TODO checking data etc.
}
void WII5Config::updateConfigData() {
EEPROM.updateBlock(WII5CONFIG_OFFSET + WII5CONFIG_CONFIGDATA, configData);
}
uint32_t WII5Config::getDeviceId() {
return _deviceId;
}
void WII5Config::setDeviceId(uint32_t newId) {
sh3dNodeConfig.setNodeId(newId);
_deviceId = newId;
}
void WII5Config::setDisableLowBattery(time_t exp) {
// TODO Check values
// lowBatteryDisable = exp;
}
time_t WII5Config::getDisableLowBattery() {
return 0; // lowBatteryDisable;
}
bool WII5Config::_checkMode(WII5_MODES newMode, uint32_t v1, uint32_t v2, uint32_t v3, uint32_t v4) {
// TODO check mode, and v1,2,3 dependeing on mode
// TODO check expiry ?
return true;
}
void WII5Config::setDefaultMode(WII5_MODES newMode) {
configData.defaultMode = newMode;
updateConfigData();
}
WII5_MODES WII5Config::getDefaultMode() {
return configData.defaultMode;
}
void WII5Config::setTemporaryMode(time_t exp, WII5_MODES newMode) {
configData.temporaryMode = newMode;
configData.temporaryModeExpires = exp;
updateConfigData();
}
WII5_MODES WII5Config::getTemporaryMode() {
return configData.temporaryMode;
}
uint32_t WII5Config::updateRecordCount() {
return (uint32_t)sh3dNodeConfig.updateRecordCount();
}
uint32_t WII5Config::getRecordCount() {
return (uint32_t)sh3dNodeConfig.getRecordCount();
}
bool WII5Config::getFlag(WII5_FLAGS f) {
return (BitVal(configData.flags, f) == 1);
}
void WII5Config::setFlag(WII5_FLAGS f, bool state) {
if (state)
SetBit(configData.flags, f);
else
ClearBit(configData.flags, f);
updateConfigData();
}
uint32_t WII5Config::getGpsTimeout() {
// Minimum 1 minute
if (configData.gpsTimeout < 60)
return 60;
// Maximum 10 minutes
else if (configData.gpsTimeout > 600)
return 600;
else
return configData.gpsTimeout;
}
void WII5Config::setGpsTimeout(uint32_t t) {
configData.gpsTimeout = t;
updateConfigData();
}
void WII5Config::setCaptureRecords(uint32_t in) {
configData.captureRecords = in;
updateConfigData();
}
uint32_t WII5Config::getCaptureRecords() {
if (configData.captureRecords < 100)
return 5120;
else if (configData.captureRecords > 57600)
return 57600;
else
return configData.captureRecords;
}
void WII5Config::setCapturePeriod(uint32_t in) {
configData.capturePeriod = in;
updateConfigData();
}
uint32_t WII5Config::getCapturePeriod() {
// Envorce limits 5 - 720 (12 hours)
// 12 Hours
if (configData.capturePeriod > 720)
return 720;
// 5 Minutes
else if (configData.capturePeriod < 5)
return 5;
else
return configData.capturePeriod;
}
void WII5Config::setCaptureBinaryType(uint32_t in) {
configData.captureBinaryType = in;
updateConfigData();
}
uint32_t WII5Config::getCaptureBinaryType() {
return configData.captureBinaryType;
}
void WII5Config::setPositionPeriod(uint32_t in) {
configData.positionPeriod = in;
updateConfigData();
}
uint32_t WII5Config::getPositionPeriod() {
return configData.positionPeriod;
}
void WII5Config::setPositionBinaryType(uint32_t in) {
configData.positionBinaryType = in;
updateConfigData();
}
uint32_t WII5Config::getPositionBinaryType() {
return configData.positionBinaryType;
}
void WII5Config::setSleepUntil(uint32_t in) {
configData.sleepUntil = in;
updateConfigData();
}
uint32_t WII5Config::getSleepUntil() {
return configData.sleepBinaryType;
}
void WII5Config::setSleepBinaryType(uint32_t in) {
configData.sleepBinaryType = in;
updateConfigData();
}
uint32_t WII5Config::getSleepBinaryType() {
return configData.sleepBinaryType;
}
void WII5Config::setSleepPeriod(uint32_t in) {
configData.sleepPeriod = in;
updateConfigData();
}
uint32_t WII5Config::getSleepPeriod() {
// Envorce limits 5 - 720 (12 hours)
// 6 Hours
if (configData.sleepPeriod > 360)
return 360;
// 1 minute minimum, becomes 1 hour if nothing
else if (configData.sleepPeriod < 1)
return 1;
else
return configData.sleepPeriod;
}
void WII5Config::dump(bool toConsole, Print* toOther) {
snprintf_P(
wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT,
PSTR("@Data,config,deviceid=%lu,recordid=%lu\r\n"),
getDeviceId(), getRecordCount()
);
if (toOther) toOther->print(wii5BufferConsolePrint);
if (toConsole) console.print(wii5BufferConsolePrint);
snprintf_P(
wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT,
PSTR("@Data,config,defaultMode=%d/%s\r\n"),
int(getDefaultMode()), wii5Strings.strMode(getDefaultMode())
);
if (toOther) toOther->print(wii5BufferConsolePrint);
if (toConsole) console.print(wii5BufferConsolePrint);
// TODO Temporary mode
snprintf_P(
wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT,
PSTR("@Data,config,capturePeriod=%lu,captureBinaryType=%lu,captureRecords=%lu\r\n"),
getCapturePeriod(), getCaptureBinaryType(), getCaptureRecords()
);
if (toOther) toOther->print(wii5BufferConsolePrint);
if (toConsole) console.print(wii5BufferConsolePrint);
snprintf_P(
wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT,
PSTR("@Data,config,positionPeriod=%lu,positionBinaryType=%lu\r\n"),
getPositionPeriod(), getPositionBinaryType()
);
if (toOther) toOther->print(wii5BufferConsolePrint);
if (toConsole) console.print(wii5BufferConsolePrint);
snprintf_P(
wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT,
PSTR("@Data,config,sleepPeriod=%lu,sleepBinaryType=%lu,sleepUntil=%lu\r\n"),
getSleepPeriod(), getSleepBinaryType(), getSleepUntil()
);
if (toOther) toOther->print(wii5BufferConsolePrint);
if (toConsole) console.print(wii5BufferConsolePrint);
snprintf_P(
wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT,
PSTR("@Data,config,batteryLow=%d,batteryMid=%d\r\n"),
getBatteryLow(), getBatteryMid()
);
if (toOther) toOther->print(wii5BufferConsolePrint);
if (toConsole) console.print(wii5BufferConsolePrint);
// time_t getDisableLowBattery();
// uint32_t getRecordCount();
// bool getFlag(WII5_FLAGS f);
// uint32_t getGpsTimeout();
}
uint16_t WII5Config::getBatteryLow() {
if (configData.batteryLow > 1500)
return 1100;
return configData.batteryLow;
}
void WII5Config::setBatteryLow(uint16_t in) {
configData.batteryLow = in;
updateConfigData();
}
uint16_t WII5Config::getBatteryMid() {
if (configData.batteryMid < getBatteryLow())
return getBatteryLow() + 100;
if (configData.batteryMid > 1500)
return getBatteryLow() + 100;
return configData.batteryMid;
}
void WII5Config::setBatteryMid(uint16_t in) {
configData.batteryMid = in;
updateConfigData();
}
WII5Config wii5Config;