Files
WII5Firmware/WII5Setup.cpp
T
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

450 lines
10 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 WII5Setup.cpp
* @brief Boot-time hardware bring-up: pin defaults, peripherals, and serial ports.
*/
/*
Setup - Turn everything on etc
*/
#include <Arduino.h>
#include <TimeLib.h>
#include <WII5.h>
#include <WII5Setup.h>
#include <avr/wdt.h>
// Debugging etc - move to header file
#define DEBUG_SLEEP
void WII5Setup::beginSafe() {
// WDT
#ifdef WDT_RESET
pinMode(WDT_RESET, OUTPUT);
digitalWrite(WDT_RESET, LOW);
#endif
// Make buzzer OUTPUT and OFF
#ifdef POWER_BUZZER_PIN
pinMode(POWER_BUZZER_PIN, OUTPUT);
digitalWrite(POWER_BUZZER_PIN, LOW);
#endif
// 5V - FORCE On until sure Maths is off
#ifdef SHARED_5VOLT_ON
pinMode(SHARED_5VOLT_PIN, OUTPUT);
digitalWrite(SHARED_5VOLT_PIN, HIGH);
#endif
// Maths - FORCE On until sure Maths is off
#ifdef POWER_MATHS_PIN
pinMode(POWER_MATHS_PIN, OUTPUT);
digitalWrite(POWER_MATHS_PIN, HIGH);
#endif
// SD: Power
#if POWER_STORAGE_1_PIN>0
pinMode(POWER_STORAGE_1_PIN, OUTPUT);
digitalWrite(POWER_STORAGE_1_PIN, HIGH);
#endif
#if POWER_STORAGE_2_PIN>0
pinMode(POWER_STORAGE_2_PIN, OUTPUT);
digitalWrite(POWER_STORAGE_2_PIN, HIGH);
#endif
// SD: Buffers
#ifdef STORAGE_SD1_MATHS_PIN
pinMode(STORAGE_SD1_MATHS_PIN, OUTPUT);
digitalWrite(STORAGE_SD1_MATHS_PIN, HIGH);
pinMode(STORAGE_SD2_MATHS_PIN, OUTPUT);
digitalWrite(STORAGE_SD2_MATHS_PIN, LOW);
#endif
// Sub 1 and 2
#ifdef POWER_SUBBOARD_1_PIN
pinMode(POWER_SUBBOARD_1_PIN, OUTPUT);
digitalWrite(POWER_SUBBOARD_1_PIN, LOW);
#endif
#ifdef POWER_SUBBOARD_2_PIN
pinMode(POWER_SUBBOARD_2_PIN, OUTPUT);
digitalWrite(POWER_SUBBOARD_2_PIN, LOW);
#endif
// GPS
pinMode(POWER_GPS_PIN, OUTPUT);
digitalWrite(POWER_GPS_PIN, LOW);
// Iridium
pinMode(POWER_COMMS_PIN, OUTPUT);
digitalWrite(POWER_COMMS_PIN, LOW);
// Batt2
#ifdef BATTERY_2_PIN
pinMode(BATTERY_2_PIN, OUTPUT);
digitalWrite(BATTERY_2_PIN, LOW);
#endif
// Radio
#ifdef WII5_RADIO_LORA
pinMode(POWER_RADIO_PIN, OUTPUT);
digitalWrite(POWER_RADIO_PIN, LOW);
#endif
// Strobe
pinMode(POWER_STROBE1_ON, OUTPUT);
digitalWrite(POWER_STROBE1_ON, LOW);
#ifdef TIMING_SPARTON_RUN
pinMode(TIMING_SPARTON_RUN, OUTPUT);
#endif
#ifdef TIMING_SPARTON_CHAR
pinMode(TIMING_SPARTON_CHAR, OUTPUT);
#endif
#ifdef TIMING_SPARTON_RECORD
pinMode(TIMING_SPARTON_RECORD, OUTPUT);
#endif
#ifdef TIMING_SD_WRITE
pinMode(TIMING_SD_WRITE, OUTPUT);
#endif
}
void WII5Setup::bootbeep() {
#ifdef POWER_BUZZER_PIN
#ifdef SHARED_5VOLT_ON
digitalWrite(SHARED_5VOLT_PIN, HIGH);
#endif
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(250);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(250);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(250);
digitalWrite(POWER_BUZZER_PIN, LOW);
#endif
}
void WII5Setup::shutdownbeep() {
#ifdef POWER_BUZZER_PIN
#ifdef SHARED_5VOLT_ON
digitalWrite(SHARED_5VOLT_PIN, HIGH);
#endif
delay(250);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(125);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(125);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(125);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(125);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(125);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(125);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
delay(125);
digitalWrite(POWER_BUZZER_PIN, HIGH);
delay(125);
digitalWrite(POWER_BUZZER_PIN, LOW);
#endif
}
void WII5Setup::begin() {
// TODO 2024 - Check state of button 2 is on
// if so set special Maths flag - alwayson?
// If button 2 goes off at any point or button1 on, then always off is forever off?
setupConsole();
setupPower();
setupIO();
setupNetwork();
setupWII5();
#ifdef WII5_STORAGE_SDBLOCK
sdBlock.debug = false;
sdBlock.stream = &Serial;
sdBlock.begin(wii5Config.getDeviceId());
#endif
}
#ifdef WII5_DEBUG_SERIAL
void cb(uint8_t l, char *buf) {
switch(l) {
case LOG_INFO:
SerialDebug.print(F("LOG:INFO:"));
break;
case LOG_WARN:
SerialDebug.print(F("LOG:WARN:"));
break;
case LOG_ERROR:
SerialDebug.print(F("LOG:ERROR:"));
break;
case LOG_DEBUG:
SerialDebug.print(F("LOG:DEBUG:"));
break;
case LOG_FATAL:
SerialDebug.print(F("LOG:FATAL:"));
break;
default:
SerialDebug.print(F("LOG:?:"));
break;
};
SerialDebug.print(buf);
SerialDebug.println();
}
#endif
void WII5Setup::setupPower() {
if (_setupPower) return;
_setupPower = true;
}
void WII5Setup::setupConsole() {
if (_setupConsole) return;
_setupConsole = true;
SerialConsole.begin(SerialConsole_Baud);
// Hard coded BAD - Where to put this for reuse in WII5 buoys
// Maybe a macro in the Board file?
console.begin(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, wii5BufferConsoleCmd, WII5_BUFFER_CONSOLE_CMD);
// TODO ? console.enableNmea();
// Here we add the main console as an OUTPUT only
#if defined(WII5_DEBUG_SERIAL) && defined(WII5_DEBUG_SERIAL_CONSOLE)
console.add(&SerialConsole, CONSOLE_DIRECTION_OUTPUT);
#else
console.add(&SerialConsole);
#endif
// NOTE: We are using Iridium as it is currently only Binary code we need
#ifdef WII5_GPS
console.setBinaryBuffer(wii5BinaryIridium, WII5_IRIDIUM_BIN_MAX);
#endif
#ifdef WII5_DEBUG_SERIAL
SerialDebug.begin(WII5_DEBUG_SERIAL_BAUD);
#ifdef WII5_DEBUG_SERIAL_CONSOLE
console.add(&SerialDebug, CONSOLE_DIRECTION_BOTH);
#else
console.setCallbackFunction(cb);
console.setCallbackLevel(LOG_FATAL);
#endif
#endif
#ifdef WII5_STATUS_SERIAL
SerialStatus.begin(WII5_STATUS_SERIAL_BAUD);
#endif
#ifdef WII5_MATHS_SERIAL
SerialMaths.begin(WII5_MATHS_SERIAL_BAUD);
console.add(&SerialMaths, CONSOLE_DIRECTION_BOTH);
#endif
console.setLevel(LOG_INFO);
}
void WII5Setup::setupNetwork() {
if (_setupNetwork) return;
_setupNetwork = true;
#ifdef WII5_RADIO_LORA
wii5RadioLoRa.begin();
#endif
}
void WII5Setup::setupIO() {
if (_setupIO) return;
_setupIO = true;
// IO - LED, Buttons et al
sh3dNodeIO.begin(LED_1, LED_2, LED_3, LED_4, BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4);
// SET LED to Fast Flash
#if LED_1>0
sh3dNodeIO.led1Set( LED_SHORT );
sh3dNodeIO.led1SetDefault(LED_SHORT);
sh3dNodeIO.led1SetTimeout(300000);
#endif
#if LED_2>0
#ifdef POWER_BUZZER_PIN
// Off after 5 seconds
sh3dNodeIO.led2Set( LED_OFF );
sh3dNodeIO.led2SetDefault(LED_OFF);
sh3dNodeIO.led2SetTimeout(10000);
#else
sh3dNodeIO.led2Set( LED_SLOW );
sh3dNodeIO.led2SetDefault(LED_SLOW);
sh3dNodeIO.led2SetTimeout(10000);
#endif
#endif
#if LED_3>0
sh3dNodeIO.led3Set( LED_SLOW );
sh3dNodeIO.led3SetDefault(LED_SLOW);
sh3dNodeIO.led3SetTimeout(10000);
#endif
#if LED_4>0
sh3dNodeIO.led4Set( LED_SLOW );
sh3dNodeIO.led4SetDefault(LED_SLOW);
sh3dNodeIO.led4SetTimeout(10000);
#endif
}
void WII5Setup::setupWII5() {
if (_setupWII5) return;
_setupWII5 = true;
wii5Config.begin();
#ifdef WII5_RTC
wii5RTC.begin();
#endif
wii5Commands.begin();
wii5Battery.begin();
#ifdef WII5_GPS
wii5Gps.begin();
#endif
#ifdef WII5_COMMS_IRIDIUM
wii5Iridium.begin();
#endif
wii5Maths.begin();
// wii5MPU9250.begin();
wii5Weather_18B20.begin();
#ifdef WII5_IMU_SPARTON
wii5Sparton.begin();
#endif
wii5Communications.begin();
}
void WII5Setup::sleepBefore(bool MathsON) {
// Tell devices they are really off.
wii5Sparton.stop(true);
wii5Iridium.stop(true);
wii5Gps.off();
sdBlock.cardForceClose();
#ifdef WII5_WDT_INTERNAL
wdt_disable();
#endif
// Turn off Shared, and Maths CPU
pinMode(SHARED_5VOLT_PIN, OUTPUT);
pinMode(POWER_MATHS_PIN, OUTPUT);
if (MathsON) {
digitalWrite(SHARED_5VOLT_PIN, HIGH);
digitalWrite(POWER_MATHS_PIN, HIGH);
}
else {
digitalWrite(SHARED_5VOLT_PIN, LOW);
digitalWrite(POWER_MATHS_PIN, LOW);
}
// Storage SD Card
#if POWER_STORAGE_1_PIN>0
pinMode(POWER_STORAGE_1_PIN, OUTPUT);
digitalWrite(POWER_STORAGE_1_PIN, LOW);
#endif
#if POWER_STORAGE_2_PIN>0
pinMode(POWER_STORAGE_2_PIN, OUTPUT);
digitalWrite(POWER_STORAGE_2_PIN, LOW);
#endif
// GPS, Radio, MPU and Strobe
pinMode(POWER_GPS_PIN, OUTPUT);
digitalWrite(POWER_GPS_PIN, LOW);
pinMode(POWER_COMMS_PIN, OUTPUT);
digitalWrite(POWER_COMMS_PIN, LOW);
pinMode(POWER_RADIO_PIN, OUTPUT);
digitalWrite(POWER_RADIO_PIN, LOW);
pinMode(POWER_STROBE1_ON, OUTPUT);
digitalWrite(POWER_STROBE1_ON, LOW);
// Misc Controlling lines
pinMode(STORAGE_SD1_MATHS_PIN, INPUT);
pinMode(STORAGE_SD2_MATHS_PIN, INPUT);
pinMode(SPARTON_RESET, INPUT);
pinMode(RADIO_CS, INPUT);
pinMode(STORAGE_CS, INPUT);
// LEDs 2024 Updated to OUTPUT LOW
#if LED_1>0
pinMode(LED_1, OUTPUT);
digitalWrite(LED_1, LOW);
#endif
#if LED_2>0
pinMode(LED_2, OUTPUT);
digitalWrite(LED_2, LOW);
#endif
#if LED_3>0
pinMode(LED_3, OUTPUT);
#endif
// Weather
pinMode(POWER_WEATHER_18B20_PIN, INPUT);
pinMode(POWER_WEATHER_PIN, INPUT);
}
void WII5Setup::sleepAfter() {
// Really make sure still output
pinMode(SHARED_5VOLT_PIN, OUTPUT);
pinMode(POWER_MATHS_PIN, OUTPUT);
// Storage SD Card
#if POWER_STORAGE_1_PIN>0
pinMode(POWER_STORAGE_1_PIN, OUTPUT);
digitalWrite(POWER_STORAGE_1_PIN, HIGH);
#endif
#if POWER_STORAGE_2_PIN>0
pinMode(POWER_STORAGE_2_PIN, OUTPUT);
#endif
// GPS, Radio, MPU and Strobe
pinMode(POWER_GPS_PIN, OUTPUT);
pinMode(POWER_COMMS_PIN, OUTPUT);
pinMode(POWER_RADIO_PIN, OUTPUT);
pinMode(POWER_STROBE1_ON, OUTPUT);
// Misc Controlling lines
pinMode(STORAGE_SD1_MATHS_PIN, OUTPUT);
pinMode(STORAGE_SD2_MATHS_PIN, OUTPUT);
pinMode(SPARTON_RESET, OUTPUT);
pinMode(RADIO_CS, OUTPUT);
pinMode(STORAGE_CS, OUTPUT);
// LEDs
pinMode(LED_1, OUTPUT);
#if LED_2>0
pinMode(LED_2, OUTPUT);
#endif
#if LED_3>0
pinMode(LED_3, OUTPUT);
#endif
// Weather
pinMode(POWER_WEATHER_18B20_PIN, OUTPUT);
pinMode(POWER_WEATHER_PIN, OUTPUT);
#ifdef WII5_WDT_INTERNAL
wdt_enable(WDTO_8S);
#endif
}
WII5Setup wii5Setup;