295abb37ee
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.
266 lines
7.6 KiB
C++
266 lines
7.6 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 WII5Iridium.h
|
|
* @brief Iridium 9602/9603 SBD modem driver: AT-command state machine.
|
|
*/
|
|
|
|
#ifndef WII5Iridium_h
|
|
#define WII5Iridium_h
|
|
|
|
|
|
#include <Arduino.h>
|
|
#include <WII5.h>
|
|
#include <elapsedMillis.h>
|
|
#ifdef WII5_COMMS_IRIDIUM
|
|
|
|
/*
|
|
How to make request ?
|
|
|
|
How to know when complete?
|
|
|
|
|
|
void loop() {
|
|
wii5Iridium.loop();
|
|
|
|
if (wii5Iridium.lastStatus) {
|
|
// Check the Status of the last thing we sent
|
|
}
|
|
|
|
if (wii5Iridium.lastReceive) {
|
|
// TODO
|
|
}
|
|
|
|
}
|
|
|
|
|
|
DATA STRUCTURE TO Send
|
|
|
|
* Wrap WII5 Binary Packet in Iridium specific data
|
|
* Time it took to send (updated just before send each time)
|
|
* Number of retries
|
|
* Last Signal quality
|
|
|
|
|
|
Useful References:
|
|
|
|
https://docs.rockblock.rock7.com/reference#sbdix
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
enum WII5IRIDIUM_REQUEST {
|
|
WII5IRIDIUM_REQUEST_NONE,
|
|
WII5IRIDIUM_REQUEST_FIRMWARE,
|
|
WII5IRIDIUM_REQUEST_TIME,
|
|
WII5IRIDIUM_REQUEST_SIGNALQUALITY,
|
|
WII5IRIDIUM_REQUEST_SENDTEXT,
|
|
WII5IRIDIUM_REQUEST_SENDBIN,
|
|
};
|
|
|
|
enum WII5IRIDIUM_STATUS {
|
|
WII5IRIDIUM_STATUS_READY, // Ready to send, no errors
|
|
WII5IRIDIUM_STATUS_BUSY, // Busy, still sending, need to wait
|
|
WII5IRIDIUM_STATUS_FAILED // Reason for failure?
|
|
};
|
|
|
|
// TODO request - need to know what the input is and how to stop...
|
|
|
|
enum WII5IRIDIUM_STEPS {
|
|
// Just off.
|
|
WII5IRIDIUM_OFF, // Turn it off - power and all
|
|
WII5IRIDIUM_POWER, // Turn on power and wait 500ms
|
|
WII5IRIDIUM_ALIVE, // Send "AT" until get OK or timeout
|
|
WII5IRIDIUM_BOOT, // ATE1, AT&D0, AT&K0, AT+SBDMTA=0
|
|
|
|
// Firmware
|
|
WII5IRIDIUM_FIRMWARE,// AT+CGMR
|
|
|
|
// IMEI
|
|
WII5IRIDIUM_IMEI, // AT-MSSTM
|
|
|
|
// System Time
|
|
WII5IRIDIUM_SYSTERMTIME, // AT-MSSTM
|
|
|
|
// Signal Quality
|
|
WII5IRIDIUM_SIGNALQUALITY_WAIT,
|
|
WII5IRIDIUM_SIGNALQUALITY, // AT+CSQ
|
|
|
|
// Choose - send Text or Binary - always returns data
|
|
WII5IRIDIUM_RETRY, // Wait here a bit before rety
|
|
WII5IRIDIUM_SEND_JUMP, // Are we TEXT or BINARY
|
|
|
|
// Send Text
|
|
WII5IRIDIUM_PREPARE_TEXT, // AT+SBDWT=RockBlocks1
|
|
WII5IRIDIUM_SEND, // AT+SBDI ... +SBDI: 1, 3, 0, 0, 0, 0
|
|
|
|
// Send Binary
|
|
WII5IRIDIUM_PREPARE_BIN1, // AT+SBDWB={n} (size of data)
|
|
WII5IRIDIUM_PREPARE_BIN2, // AT+SBDWB={n} (size of data)
|
|
|
|
// Receive Message
|
|
WII5IRIDIUM_RECEIVE, // AT+SBDRB ... AT+SBDRB (echo back)
|
|
WII5IRIDIUM_RECEIVE_BIN, // first 2 bytes = size, then binary, then checksum
|
|
|
|
WII5IRIDIUM_WAITING, // Waiting - hurry up and absorb
|
|
|
|
// Complete
|
|
WII5IRIDIUM_STOP_PREPARE, // END ! Jump to STOP_PREPARE,
|
|
WII5IRIDIUM_END // Very end
|
|
};
|
|
#define DEFAULT_MINUTES 5
|
|
|
|
#define IRIDIUM_RETRY_MIN 2 // Used for low power mode, how many times to rety minimum
|
|
#define IRIDIUM_RETRY_MAX 20 // Maximum number of retries for normal modes
|
|
|
|
// FROM IridiumSBD by Rock Blocks
|
|
#define ISBD_LIBRARY_REVISION 2
|
|
#define ISBD_DEFAULT_AT_TIMEOUT 30
|
|
#define ISBD_MSSTM_RETRY_INTERVAL 10
|
|
#define ISBD_DEFAULT_SBDIX_INTERVAL 10
|
|
#define ISBD_USB_SBDIX_INTERVAL 30
|
|
#define ISBD_DEFAULT_SENDRECEIVE_TIME 300
|
|
#define ISBD_STARTUP_MAX_TIME 240
|
|
#define ISBD_MAX_MESSAGE_LENGTH 340
|
|
#define ISBD_MSSTM_WORKAROUND_FW_VER 13001
|
|
|
|
#define ISBD_SUCCESS 0
|
|
#define ISBD_ALREADY_AWAKE 1
|
|
#define ISBD_SERIAL_FAILURE 2
|
|
#define ISBD_PROTOCOL_ERROR 3
|
|
#define ISBD_CANCELLED 4
|
|
#define ISBD_NO_MODEM_DETECTED 5
|
|
#define ISBD_SBDIX_FATAL_ERROR 6
|
|
#define ISBD_SENDRECEIVE_TIMEOUT 7
|
|
#define ISBD_RX_OVERFLOW 8
|
|
#define ISBD_REENTRANT 9
|
|
#define ISBD_IS_ASLEEP 10
|
|
#define ISBD_NO_SLEEP_PIN 11
|
|
#define ISBD_NO_NETWORK 12
|
|
#define ISBD_MSG_TOO_LONG 13
|
|
|
|
enum WII5IRIDIUM_RETURNS {
|
|
WII5IRIDIUM_RETURN_AT,
|
|
WII5IRIDIUM_RETURN_OK,
|
|
WII5IRIDIUM_RETURN_READY,
|
|
WII5IRIDIUM_RETURN_ERROR,
|
|
WII5IRIDIUM_RETURN_SBDI, // +SBDI, +SBDIX, +SBDIXA (moCode, &moMSN, &mtCode, &mtMSN, &mtLen, &mtRemaining)
|
|
WII5IRIDIUM_RETURN_CSQ, // +CSQ:{n}
|
|
WII5IRIDIUM_RETURN_MSSTM, // -MSSTM
|
|
WII5IRIDIUM_RETURN_BINARY // Hard coded the binary
|
|
};
|
|
|
|
/**
|
|
* @brief Driver for the Iridium 9602/9603 SBD modem.
|
|
*
|
|
* AT-command state machine: power on, wait for the modem to come alive,
|
|
* boot up (ATE1, AT&D0, AT&K0, AT+SBDMTA=0), then drive a sequence of
|
|
* +CSQ / +SBDWB / +SBDIX / +SBDRB cycles to send and receive 340-byte
|
|
* SBD messages. State is in WII5IRIDIUM_STEPS; see step transitions in
|
|
* WII5Iridium.cpp::loop().
|
|
*/
|
|
class WII5Iridium : public WII5Power, public WII5SerialManager{
|
|
public:
|
|
WII5Iridium() {}
|
|
virtual WII5_CONTROLLERS controllerId() {return WII5CONTROLLER_DRIVER;}
|
|
virtual WII5_DRIVERS driverId() {return WII5DRIVER_COMMS_IRIDIUM;}
|
|
|
|
/** @brief One-time bring-up. */
|
|
void begin();
|
|
/** @brief State-machine tick: parses serial, advances steps. */
|
|
void loop();
|
|
|
|
/** @brief Queue a firmware-version query (AT+CGMR). */
|
|
bool requestFirmware();
|
|
/** @brief Queue a binary send (uses buffer set by setBinary/setBinSize). */
|
|
bool requestSendBinary();
|
|
/** @brief Queue a text send (uses buffer set by setText). */
|
|
bool requestSendText();
|
|
/** @brief Currently-queued request type. */
|
|
WII5IRIDIUM_REQUEST currentRequest();
|
|
/** @brief Set the binary buffer + length for the next send. */
|
|
void setBinary(uint8_t* buf, uint16_t size);
|
|
/** @brief Set just the size of the binary buffer (caller writes the bytes). */
|
|
void setBinSize(uint16_t size);
|
|
/** @brief Set the text payload for the next send (RAM string). */
|
|
void setText(char* str);
|
|
/** @brief Set the text payload for the next send (PROGMEM string). */
|
|
void setText(const __FlashStringHelper *str);
|
|
|
|
/** @brief Begin a comms cycle (`force` skips initialized check). */
|
|
virtual void start(bool force = false);
|
|
/** @brief Abort the current cycle. */
|
|
void stop(bool force = false);
|
|
/** @brief Apply power to the Iridium modem. */
|
|
void powerOn(bool force = false);
|
|
/** @brief Cut power to the Iridium modem. */
|
|
void powerOff(bool force = false);
|
|
/** @brief Are we waiting on the modem to finish a step? */
|
|
bool waiting();
|
|
|
|
/** @brief Is the state machine currently in a non-idle step? */
|
|
bool isRunning();
|
|
|
|
// TODO Storage? why can't we use a 64 bit (8 byte) number?
|
|
char imei[18]; // 14 or up to 16 digits?
|
|
// uint32_t ; // 14 or up to 16 digits?
|
|
|
|
elapsedMillis lastSince;
|
|
uint8_t lastSignalQuality;
|
|
uint16_t lastMOMSN;
|
|
WII5IRIDIUM_SEND_RESULT lastSend;
|
|
WII5IRIDIUM_RECEIVE_RESULT lastReceive;
|
|
uint16_t lastReceiveLen;
|
|
uint8_t* lastReceiveBuff;
|
|
|
|
|
|
virtual void sendNewLine();
|
|
|
|
protected:
|
|
bool running;
|
|
WII5IRIDIUM_STEPS step;
|
|
WII5IRIDIUM_STEPS stepLast;
|
|
elapsedMillis stepWait;
|
|
|
|
void programLine(uint16_t l);
|
|
|
|
bool initialized;
|
|
WII5IRIDIUM_REQUEST currentType;
|
|
uint8_t retry; // How many times did we retry ?
|
|
uint8_t sigQualRetry; // How many times did we retry ?
|
|
uint8_t sigQualMin; // How many times did we retry ?
|
|
uint32_t binSize; // Size of binary data to send
|
|
|
|
uint16_t checksum;
|
|
uint16_t loopcount;
|
|
uint8_t *txData;
|
|
|
|
// Firmware (and age)
|
|
// Signal Quality (and age)
|
|
// DateTime (and age)
|
|
// Send Status (and age) (WAITING, COMPLETE, ERROR)
|
|
// Send Queue ? (or external)
|
|
// Receive Queue (or external)
|
|
|
|
|
|
// lastCSQ
|
|
// lastIMEI
|
|
// lastSystemTime
|
|
// lastID???
|
|
// lastStatus??
|
|
|
|
// Last Status =
|
|
|
|
};
|
|
|
|
extern WII5Iridium wii5Iridium;
|
|
|
|
#endif
|
|
#endif
|