Verified Whole-Orbit telemetry format for Nayif-1 (FUNCube) — 25-byte records, decoded from official Dashboard + 70k real records

Hi @bali & everyone in the community,

I’ve been working through a large archive of SatNOGS frames for Nayif-1 (EO-88) and managed to fully reverse-engineer and verify the FUNcube Whole-Orbit (WO) telemetry format. Since gr-satellites currently treats Nayif-1 WO as 23-byte raw blobs and the High-Resolution parser does not match the satellite’s own decoder, I thought this would be useful to share.

Method. The reference is the official FUNcube Nayif-1 Dashboard for Windows (http://download.funcube.org.uk/Nayif-1_Dashboard_1040_Installer.msi). I decompiled it (WholeOrbitSample.cs, WholeOrbitDataStore.cs, HighResolutionSample.cs, HighResolutionDataStore.cs, Telemetry.cs, BKSystem.IO/BitStream.cs) and extracted the exact bit layout. I then wrote a pure-Python + Kaitai (.ksy) decoder and verified it against real frames (733 complete orbits = 70,368 WO records), including a 100% match of the freshest WO record against the realtime block of the same cycle (see below).

Whole-Orbit record = 25 bytes (200 bits), read MSB-first sequentially:

bits width field conversion
0-11 12 WOTempMcu v=raw*0.00078753; v>=0.7012 ? 25-(v-0.7012)/0.001646 : 25-(v-0.7012)/0.001749
12-23 12 WOTempRf °C = -0.3465*(raw&0x3FF)+266.70646 (top 2 bits const “11”)
24-35 12 WOTempPa piecewise-linear 31-anchor table on (raw&0x3FF) (see ksy)
36-45 10 WOPanelTempXp °C = -0.208*raw+158.792
46-55 10 WOPanelTempXm °C = -0.208*raw+158.792
56-65 10 WOPanelTempYp °C = -0.208*raw+158.792
66-75 10 WOPanelTempYm °C = -0.208*raw+158.792
76-85 10 WOPanelTempZp °C = -0.208*raw+158.792
86-95 10 WOPanelTempZm °C = -0.208*raw+158.792
96-155 10x6 WOSunSensorXp/Xm/Yp/Ym/Zp/Zm raw
156-163 8 WOBatteryTemp raw
164-173 10 WOPanelCurrent raw (= RT totalphotocurrent)
174-187 14 WOBatteryVoltage raw (mV)
188-199 12 WOSystemCurrent raw (= RT systemcurrent)

Reassembly. Each WO frame (ft 0-11) carries 8 x 25-byte records in its 200-byte payload; a cycle is the 12 WO frames sharing the same 24-bit in-frame sequence number (bytes 50-52). Record sampleNumber = 96 - frame_id*8 - sample_in_frame; WO1 holds the oldest samples (96..89), WO12 the freshest (8..1). Time anchor from the Dashboard: sample_time = receive_time - sampleNumber minutes - frame_id*5 s.

Cross-check with the realtime block (341 cycles where all 24 frame types present; realtime block lives in bytes 2-56 of every frame):

  • battery voltage, battery temp, panel current, all 6 sun sensors: WO freshest record == RT, 100%

  • (WO temp_rf & 0x3FF)>>2 == RT rftemp, 100% (top 2 bits of the 12-bit fields are a constant 0xC00)

  • (WO temp_pa & 0x3FF)>>2 == RT paboardtemp, 100%

  • WO system_current == RT systemcurrent, 100%

High-Resolution frames (ft 12-16) are not what gr-satellites parses. The Dashboard decodes 132-bit samples: 6x10-bit sun sensors, then per axis a 22-bit signed magnetometer (x4), plus iMTQ IVA / coil-active / error flags — packed continuously across the five 200-byte HR frames (samples wrap across frame boundaries via the offset lookup in HighResolutionDataStore.cs; 60 samples per cycle).

About JY1SAT (JO-97). JY1SAT is a different satellite (NORAD 43803, launched on the same PSLV-C43 mission as Nayif-1) but carries the same FUNcube payload, so it uses the same protocol and the same extended frame path in gr-satellites (its header ext-ID byte is 0x10 vs Nayif-1’s 0x08). That means JY1SAT is affected by the same 23-byte WO bug and the same HR parser issue — and it also has the ft 32/33 SSDV frames that gr-satellites still reports as unknown. I’ve only validated the layout against Nayif-1 data, so if anyone has JY1SAT (or FUNcube-1) WO/HR archives I’d love to confirm the 25-byte format carries over. Note FUNcube-1 (AO-73) uses the same protocol but a different WO layout (WholeOrbitFC1), so it is not affected.

Artifacts: nayif1.ksy (Kaitai Struct, compiles with kaitai-struct-compiler 0.11, verified 0 mismatches on 32,736 records) and a pure-Python decoder. Happy to share anything or submit the corrected decoder as a PR to gr-satellites.

Thank you!
73!

1 Like