Iridium Communications¶
The CPF uses a NAL A3LA-R Iridium modem on COM3 (19200 baud, 8N1, power channel 4). The firmware interacts with it in two modes depending on the situation:
- SBD (Short Burst Data) — the primary link, used every surface ops and recovery cycle to exchange a status message and receive commands
- RUDICS — a dial-up TCP/IP-over-Iridium connection used to transfer full science and engineering data files to the shore server
Both modes are implemented in NAL_A3LAR (libSensorModules/IModem.cs) with supporting session logic in IridiumPosixSession and PosixSession.
Modem Initialization¶
On power-up, NAL_A3LAR.init() runs the following AT command sequence:
| Step | Command | Description |
|---|---|---|
| 1 | AT&D0 |
Ignore DTR line changes |
| 2 | AT&K0 |
Disable flow control |
| 3 | AT+SBDD2 |
Clear both MO and MT SBD message buffers |
| 4 | AT+GSN |
Read IMEI number (logged) |
| 5 | AT+SBDC |
Reset the mobile-originated message sequence number (MOMSN) |
| 6 | ATEn=0 |
Disable echo |
| 7 | AT+CICCID |
Read SIM card ICCID (logged) |
A simpler simpleInit() path only opens the port and discards buffers, used when full initialization is not required.
SBD Communications¶
SBD (Short Burst Data) is used every surface cycle (both SurfaceOps and Recovery states) to send a status message uplink (MO) and optionally receive a command message downlink (MT). The exchange is driven as a sequential action state machine within the surface state.
SBD Action Sequence¶
| Action | AT Command | Expected Response | Description |
|---|---|---|---|
sendSBDD2 |
AT+SBDD2 |
OK |
Clear MO and MT buffers |
sendCREG |
AT+CREG? |
+CREG: |
Check network registration |
sendCSQ |
AT+CSQ |
+CSQ: |
Read signal quality (0–5 scale, stored in SignalQuality) |
buildSBDWTMsg |
— | — | Build the outgoing MO message in memory |
sendSBDWTCommand |
AT+SBDWT |
READY |
Tell modem to prepare to receive message text |
loadSBDWTBuffer |
message text + CR | OK |
Load the MO message into the modem buffer (up to 1910 bytes) |
sendSBDIX |
AT+SBDIX |
+SBDIX: |
Initiate SBD session — transfers MO message and receives any queued MT message |
sendSBDRT |
AT+SBDRT |
+SBDRT: |
Read the MT message from the modem buffer (only if MT status = 1) |
The waitForResponse() method sends each command and polls for the expected response with a 40-second timeout and up to 3 retries per command. The whole SBD exchange is retried up to MAX_SBDIX_ATTEMPTS (5) times before giving up.
SBDIX Response Parsing¶
The +SBDIX response has the format:
+SBDIX: <MO status>, <MOMSN>, <MT status>, <MTMSN>, <MT length>, <MT queued>
The firmware extracts three fields:
| Field | Variable | Meaning |
|---|---|---|
| MO status | sbdixMOStatus |
0–4 = success; 5+ = failure (see below) |
| MT status | sbdixMTStatus |
0 = no message; 1 = message received; 2 = error |
| MT queued | sbdixMTQueued |
Number of additional MT messages waiting at the gateway |
MO status codes:
| Code | Meaning |
|---|---|
| 0 | MO message transferred successfully |
| 1 | MO transferred, but MT message was too large |
| 2 | MO transferred, but location update not accepted |
| 10 | Call did not complete in time |
| 11 | MO queue at GSS is full |
| 12 | MO message has too many segments |
| 13 | Session did not complete |
| 14 | Invalid segment size |
| 15 | Access denied |
| 16 | Modem is locked |
| 17 | Gateway not responding (local timeout) |
| 18 | Connection lost (RF drop) |
| 32 | No network service |
After a successful SBDIX, if sbdixMTStatus == 1 (MT message received), the firmware reads it with AT+SBDRT. If the read succeeds, the next MO message includes ACK SBD; if it fails, it includes NAK SBD.
MT messages received via SBD are delivered to BTConsole.processConsoleCommand(), which interprets them as console commands (same format as Bluetooth console commands, prefixed with $). See the Runtime Console Commands reference for the full command set.
MO Status Message Format¶
The outgoing SBD message is a comma-separated ASCII string built by StateBase.buildSBDMsg(). Maximum length is 1910 bytes. Fields:
<ISO8601 timestamp>,
,Lat,<latitude>,
,Lon,<longitude>,
,GPS TOF,<GPS time of fix>,
,Num Sats,<satellite count>,
<current state name>,
<recovery reason (if any)>,
,ProfileNum,<profile number>,
<ACK/NAK/OK SBD>,
,SQ,<signal quality>,
,MO Stat,-,
,Mission TO,<mission timeout>,
,Park Time,<park time>,
,Park P,<park depth dbar>,
,Prof Num,<profile number> of <max profiles>,
,BBVolts,<battery voltage V>,
,Can P,<canister pressure mBar>,
,Can Hum,<canister humidity %RH>,
,BBHealth,<battery health hex>
Example:
2024-03-15T10:30:00Z,,Lat,36.7950,,Lon,-121.8471,,GPS TOF,103000.00,,Num Sats,7,surfaceOps,,ProfileNum,3,OK SBD,,SQ,4,,MO Stat,-,,Mission TO,02:00:00,,Park Time,02:00:00,,Park P,150,,Prof Num,3 of 100,,BBVolts,14.823,,Can P,1013.2,,Can Hum,32.1,,BBHealth,0000
RUDICS Communications¶
RUDICS (Router-based Unrestricted Digital Internetworking Connectivity Solution) is an Iridium service that establishes a circuit-switched data call to a shore-side server, enabling full file transfer. The CPF uses RUDICS to upload science and engineering log files.
RUDICS is implemented in SurfaceOps.RudicsThreadMethod(), which runs in a dedicated thread. The IridiumPosixSession class manages the connection, and PosixSession handles login and ZMODEM file transfer.
RUDICS Sequence¶
| Step | Method | Description |
|---|---|---|
| 1 | AT+CBST=71,0,1 |
Set bearer service to 9600 bps V.110 |
| 2 | dialNumber() / dialDefaultRudics() |
Dial the RUDICS number (atd00881600005391) |
| 3 | Wait for CONNECT or NO CARRIER |
120-second dial timeout; up to 10 dial attempts |
| 4 | session.Login() |
Send username/password to the remote shell |
| 5 | session.ZModemSendTransaction(filename) |
Transfer file(s) using ZMODEM |
| 6 | session.Logout() |
Log out of the remote shell |
| 7 | session.Disconnect() |
Release serial port back to modem handler |
The session credentials and command prompt are configured in RudicsThreadMethod():
| Parameter | Value |
|---|---|
| Username | `` |
| Password | `` |
| Command prompt | $ |
| RUDICS number | 00881600005391 |
Files are dequeued from SciLogger.DequeueFileName and sent one at a time. Each file gets up to MaxFileAttempts (3) tries. If a file send fails, the thread exits and the connection is torn down.
RUDICS Status¶
The RUDICS transfer runs as a background thread. On completion (success or failure), the main surface ops sequence sends an escape sequence (+++) followed by ATH0 to hang up cleanly, then returns the serial port to the normal modem message handler.
Note: As of the current firmware, the RUDICS transfer step in
SurfaceOpsis bypassed (EngrLogger.writeToColumns("Skipping over SendFilesViaRudics")). TheactionSendFilesViaRUDICS()method andRudicsThreadMethod()are implemented but not currently called in the normal surface ops flow. SBD is the active telemetry path.
AT Command Reference¶
| Command | Method | Description |
|---|---|---|
AT |
sendAT() |
Modem attention / alive check |
AT&D0 |
sendD0() |
Ignore DTR |
AT&K0 |
sendK0() |
Disable flow control |
AT&F0 |
sendFactoryDefault() |
Restore factory defaults |
ATEn=0 |
sendNoEcho() |
Disable echo |
AT+GSN |
sendGSN() |
Read IMEI |
AT+CICCID |
sendCICCID() |
Read SIM ICCID |
AT+CSQ |
sendCSQ() |
Signal quality (0–5) |
AT+CREG? |
sendCREG() |
Network registration status |
AT+CIER=1,1 |
sendCIER11() |
Enable indicator event reporting |
AT+SBDC |
sendSBDC() |
Reset MOMSN counter |
AT+SBDD2 |
sendSBDD2() |
Clear MO and MT buffers |
AT+SBDWT |
sendSBDWTCommand() |
Prepare modem to receive MO text |
| (message) + CR | loadSBDWTBuffer() |
Load MO message into modem buffer |
AT+SBDIX |
sendSBDIX() |
Initiate SBD session (MO + MT exchange) |
AT+SBDI |
sendSBDI() |
Initiate SBD session (no MT retrieval) |
AT+SBDRT |
sendSBDRT() |
Read MT message from modem buffer |
AT+CBST=<n>,0,1 |
SelectBearerServiceType() |
Set bearer service type for RUDICS call |
ATD<number> |
dialNumber() |
Dial a number |
+++ |
sendEscapeSequence() |
Escape from data mode |
ATH0 |
sendATH0() |
Hang up |
AT+CHUP |
sendCHUP() |
Hang up (alternate) |
AT+CMEE=2 |
sendCMEE() |
Enable verbose error reporting |