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
+111
View File
@@ -0,0 +1,111 @@
#!/usr/bin/perl
# 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.
# Group ELF symbols by subsystem (Network, Storage, Sparton, GPS, Iridium,
# Serial, Console, Sh3d, WII5, Other) and report sizes. Useful for understanding
# where the firmware is spending its program/data memory.
#
# Configure with env vars:
# WII5_AVR_READELF = path to avr-readelf binary
# WII5_ELF = path to wii5_buoy.ino.elf
#
# Usage: WII5_AVR_READELF=... WII5_ELF=... perl tools/memory.pl [items_max]
use strict;
use warnings;
use Data::Dumper;
my $items_max = $ARGV[0] || 0;
my $exe_read = $ENV{WII5_AVR_READELF} or die "WII5_AVR_READELF not set\n";
my $elf = $ENV{WII5_ELF} or die "WII5_ELF not set\n";
my $fh;
open ($fh, "$exe_read -a $elf |grep OBJECT |") or die "Cannot run readelf: $!\n";
my $grouped = {
Serial => {total => 0, items => {}},
Network => {total => 0, items => {}},
Console => {total => 0, items => {}},
Sh3d => {total => 0, items => {}},
Storage => {total => 0, items => {}},
Sparton => {total => 0, items => {}},
GPS => {total => 0, items => {}},
Iridium => {total => 0, items => {}},
WII5 => {total => 0, items => {}},
Other => {total => 0, items => {}},
};
while (<$fh>) {
chomp;
# Sample line layout (column-aligned):
# 1815: 00801796 1 OBJECT GLOBAL HIDDEN 3 _ZN7TwoWire12transmitting
my $size = substr($_, 16, 6);
my $name = substr($_, 51, 100);
if (
($name =~ /network/i)
|| ($name =~ /radio/i)
) {
$grouped->{Network}{total} += $size;
$grouped->{Network}{items}{$name} = $size;
}
elsif (
($name =~ /storage/i)
|| ($name =~ /Sd/)
) {
$grouped->{Storage}{total} += $size;
$grouped->{Storage}{items}{$name} = $size;
}
elsif ($name =~ /sparton/i) {
$grouped->{Sparton}{total} += $size;
$grouped->{Sparton}{items}{$name} = $size;
}
elsif ($name =~ /gps/i) {
$grouped->{GPS}{total} += $size;
$grouped->{GPS}{items}{$name} = $size;
}
elsif ($name =~ /iridium/i) {
$grouped->{Iridium}{total} += $size;
$grouped->{Iridium}{items}{$name} = $size;
}
elsif ($name =~ /serial/i) {
$grouped->{Serial}{total} += $size;
$grouped->{Serial}{items}{$name} = $size;
}
elsif ($name =~ /console/i) {
$grouped->{Console}{total} += $size;
$grouped->{Console}{items}{$name} = $size;
}
elsif ($name =~ /sh3d/i) {
$grouped->{Sh3d}{total} += $size;
$grouped->{Sh3d}{items}{$name} = $size;
}
elsif ($name =~ /wii5/i) {
$grouped->{WII5}{total} += $size;
$grouped->{WII5}{items}{$name} = $size;
}
else {
$grouped->{Other}{total} += $size;
$grouped->{Other}{items}{$name} = $size;
}
}
foreach my $group_key (sort {$grouped->{$b}{total} <=> $grouped->{$a}{total} } keys %$grouped) {
print "$group_key => " . $grouped->{$group_key}{total} . "\n";
my $item_count = 0;
foreach my $item_key (
sort {
$grouped->{$group_key}{items}{$b} <=> $grouped->{$group_key}{items}{$a}
} keys %{$grouped->{$group_key}{items}}
) {
if ($item_count < $items_max) {
print " $item_key => " . $grouped->{$group_key}{items}{$item_key} . "\n";
}
$item_count++;
}
}