birdcage/docs/g2-nvs-dump.md
Ryan Malloy 7ff91b08ea Refactor probe tool to generic embedded console scanner, document full G2 command inventory
Rewrote hidden_menu_probe.py from Winegard-hardcoded to auto-discovering:
detects prompt, error string, and submenu structure from any firmware console.
Extracted Winegard-specific candidate words to scripts/wordlists/winegard.txt.

Deep probe of all 12 G2 submenus discovered commands across A3981 (driver
diagnostics), ADC (RSSI monitoring + position sweep), DVB (extended help via
man, transponder selection), EEPROM (read/write), GPIO (pin R/W), LATLON
(calculator), MOT (azscan, sw), PEAK (EchoStar switch), and STEP (raw
stepper control). NVS submenu generates false positives — treats any input
as sequential index reads.

Safety: added q/Q to default blocklist, bare-CR check before navigate_to_root
to prevent accidental shell termination between submenus.
2026-02-12 21:05:33 -07:00

67 KiB
Raw Blame History

Carryout G2 Firmware Exploration

Firmware: Version 02.02.48 (Copyright 2013 - Winegard Company) Date: 2026-02-12 Connection: DSD TECH SH-U11 USB RS-422 @ 115200 8N1

Hardware Platform

Discovered via osid command:

NXP Kinetis K60 ARM Cortex-M4
  Package:       144-pin
  Silicon Rev:   2.4
  Mask Set:      4N22D
  P-Flash:       512 KB
  RAM:           128 KB
  Core Clock:    96 MHz (CCLK)
  Bus Clock:     48 MHz (BCLK)
  System ID:     TWELINCH
  Antenna ID:    12-IN G2
  Software:      02.02.48
  Flash Base:    0x00010000 (65536)
  Flash Size:    458752 bytes (448 KB)

The "TWELINCH" system ID = "Twelve Inch", matching the Carryout G2's ~12" dish diameter. Flash starts at 64 KB offset (first 64 KB is bootloader/vector table), leaving 448 KB for application firmware.

Exact part number: MK60DN512VLQ10

  • MK60 = Kinetis K60 family (Cortex-M4 + DSP)
  • DN512 = 512 KB program flash (no FlexNVM)
  • VLQ = LQFP 144-pin package (20x20mm)
  • 10 = 100 MHz max frequency

Datasheets: docs/K60-datasheet.pdf (K60P144M100SF2V2, Rev 3, 6/2013), docs/K60-reference-manual.pdf (K60P144M100SF2V2RM, ~1800 pages)

Key Peripherals (from datasheet)

Peripheral Count Notes
UART 5 UART0 = RS-422 console (confirmed)
DSPI 3 SPI with DMA; DSPI0/1 likely → A3981 motor drivers
I2C 2
ADC 2× 16-bit 863ns conversion; ADC0 likely → RSSI measurement
DAC 2× 12-bit
USB 1× OTG On-chip transceiver, no external PHY needed
CAN 2 Likely unused
Ethernet 1× IEEE 1588 Likely unused
FlexTimer 3 (12 ch) Motor PWM / step timing
DMA 16 channel

USB Port (Potentially Accessible)

The K60 has dedicated USB pins (not muxable with GPIO):

LQFP Pin Signal Function
19 USB0_DP USB Data+
20 USB0_DM USB Data-
21 VOUT33 USB VREG 3.3V output
22 VREGIN USB VREG 5V input (self-power from USB)

The Trav'ler Pro uses USB A-to-A (ttyACM0) for its serial console — this proves Winegard has USB CDC/ACM firmware for the Kinetis platform. The G2 may also have a USB connector on the PCB (possibly internal, for field service).

NVS indices 2 ("Debug 2nd Console Port") and 4 ("Debug Port Connection") hint at multiple console port support — USB could be the second port.

Root Menu Structure

At the TRK> prompt, ? lists all available submenus:

Submenu Command Description
A3981 a3981 Allegro A3981 stepper motor driver IC control
ADC adc Analog-to-digital converter / RSSI / board ID
Dipswitch dipswitch DIP switch configuration readout
DVB dvb BCM4515 DVB receiver / signal analysis
EEPROM eeprom Non-volatile EEPROM storage (separate from NVS)
GPIO gpio MCU pin register dump (5 ports, 98 pins)
LATLON latlon Satellite longitude/elevation parameters
MOT mot Degree-based motor positioning (high-level)
NVS nvs Non-volatile settings (operational parameters)
OS os Operating system / task manager / MCU identification
PEAK peak Signal peaking / DiSEqC switch testing
STEP step Raw microstep motor control (low-level)

Three-layer motor control architecture:

  1. step — raw microstep commands (ustep/sec, engage/release motors)
  2. mot — degree-based positioning (a <id> <deg>, h <id>)
  3. Application — satellite tracking (NVS config, peak, DVB)

NVS Values

Num  Name                         Current      Saved      Default
---- --------------------------  ----------  ----------  ----------
  0) Log ID's                    0x00000007  0x00000007  0x00000007
  1) Log Device                  0x00000001  0x00000001  0x00000001
  2) Debug 2nd Console Port               0           0           0
  3) Debug 2nd Packet Port                0           0           0
  4) Debug Port Connection                0           0           0
 16) Pitch Deadband                    0.00        0.00        0.00
 17) Roll Deadband                     0.00        0.00        0.00
 18) Yaw Deadband                      0.00        0.00        0.00
 20) Disable Tracker Proc?             TRUE        TRUE       FALSE  ← MODIFIED
 21) Tracker Proc Run Mode                0           0           0
 22) Conical Alpha Az                   200         200         200
 23) Conical Alpha El                   200         200         200
 24) Conical Radius                    1.00        1.00        1.00
 25) Conical Count Max                   20          20          20
 26) Conical Test Drift                  +0          +0          +0
 27) Circle RPM                         120         120         120
 28) Circle Pts/Rev                       6           6           6
 32) Conical Az Clamp                  8.00        8.00        8.00
 33) Conical El Clamp                  8.00        8.00        8.00
 35) Motor Pts/Rev                       72          72          72
 36) Circle Az Radius                  1.00        1.00        1.00
 37) Circle El Radius                  1.00        1.00        1.00
 38) Sleep Mode Timer Secs              420         420         420
 40) Motor Type                           0           0           0
 41) Satellite Scan Velocity          55.00       55.00       55.00
 48) Motor Spiral Velocity            55.00       55.00       55.00
 49) Motor Gear Ratio            0x00000000  0x00000000  0x00000000
 63) GPS Heading Threshold             1.00        1.00        1.00
 64) GPS Moving Threshold          5.00 MPH    5.00 MPH    5.00 MPH
 66) Spiral Signal In A Row Min          +3          +3          +3
 67) Spiral Signal In A Row Max         +20         +20         +20
 68) Signal Odd to Even Offset           +0          +0          +0
 69) Signal Offset                       80          80          80
 70) Signal Baseline Angle            65.00       65.00       65.00
 71) Signal Re-Peak Degrade Percent      25          25          25
 72) Gyro Sensitivity                 +1110       +1110       +1110
 73) Gyro Filter Size                    +1          +1          +1
 74) Gyro Calib Readings                100         100         100
 75) Gyro Mount Type                      1           1           1
 76) Gyro Velocity Offset                 4           4           4
 77) Gyro Max Accel                     600         600         600
 80) AZ Max Vel                       65.00       65.00       65.00
 81) AZ Max Accel                    400.00      400.00      400.00
 82) AZ Home Velocity                 55.00       55.00       55.00
 83) AZ Steps/Rev                     40000       40000       40000
 84) AZ Direction                        +1          +1          +1
 85) EL Max Vel                       45.00       45.00       45.00
 86) EL Max Accel                    400.00      400.00      400.00
 87) EL Home Velocity                 45.00       45.00       45.00
 88) EL Steps/Rev                     24960       24960       24960
 89) EL Direction                        +1          +1          +1
 95) AZ Low current limit        0x0000ff0c  0x0000ff0c  0x0000ff0c
 96) AZ High current limit       0x0000ff30  0x0000ff30  0x0000ff30
 97) EL Low current limit        0x0000ff0c  0x0000ff0c  0x0000ff0c
 98) EL High current limit       0x0000ff40  0x0000ff40  0x0000ff40
101) Minimum Elevation Angle          18.00       18.00       18.00
102) Maximum Elevation Angle          65.00       65.00       65.00
103) Elevation Home Angle             65.00       65.00       65.00
106) Az Stall Detect                     78          78          78
107) El Stall Detect                     75          75          75
108) Az Stall Samples                   100         100         100
109) El Stall Samples                   100         100         100
110) EL Home Current Limit       0x0000ff28  0x0000ff28  0x0000ff28
111) AZ Home Current Limit       0x0000ff40  0x0000ff40  0x0000ff40
112) Disable Dipswitch?               FALSE       FALSE       FALSE
113) Dipswitch Value                    101         101         101
114) Dipswitch Front/Rear Mount           0           0           0
115) Mount Offset Angle                  +0          +0          +0
118) Signal Use LNB Clamp             FALSE       FALSE       FALSE
128) AZ PID Kp                         +600        +600        +600
129) AZ PID Kv                          +60         +60         +60
130) AZ PID Ki                           +1          +1          +1
131) EL PID Kp                         +250        +250        +250
132) EL PID Kv                          +50         +50         +50
133) EL PID Ki                           +1          +1          +1
136) AZ PWM Stall Cnt                     6           6           6
137) EL PWM Stall Cnt                     5           5           5
143) Tracking Number                      0           0           0

Key Parameters for Satellite Tracking

NVS Name Value Notes
20 Disable Tracker Proc? TRUE Prevents TV satellite search on boot
83 AZ Steps/Rev 40000 Centidegrees per revolution (400.00°)
88 EL Steps/Rev 24960 ~249.60° per revolution
80 AZ Max Vel 65.00 °/s azimuth max velocity
85 EL Max Vel 45.00 °/s elevation max velocity
101 Min Elevation 18.00 Firmware floor (degrees)
102 Max Elevation 65.00 Firmware ceiling (degrees)
103 EL Home Angle 65.00 Where EL homes to on startup
128-133 PID Gains varies AZ/EL motor PID tuning parameters

Boot Sequence Observed

Bootloader Phase (<50ms, non-interactive)

Captured via scripts/boot_capture.py with high-resolution timestamps:

[0.050s] 01 00                    ← binary status bytes (bootloader→app handshake?)
[0.050s] Bootloader version: 1.01
[0.050s] Application is running...
[0.050s] 98 80 96                 ← binary bytes (integrity check? jump address?)
[0.100s] Application Starting Kinetis PCB... power up/reset

The bootloader runs at 115200 baud (same as application — confirmed by multi-baud capture at 9600/19200/38400/57600/230400/460800). There is no interactive window — ESC, CR, BREAK, 0x55 autobaud, and other interrupt sequences at 5-30ms delays all failed to stop the boot. The bootloader checks a flag (likely in EEPROM or a reserved flash sector) and immediately jumps to the application at 0x10000 if no firmware update is pending.

Application Phase (~10s to prompt)

Version 02.02.48
Copyright 2013 - Winegard Company
Boot Complete

Loc Startup: IDU NOT Present
app_dipswitch:101
Primary Update:  10100
Alternate Update:  11900
Toggle Ability Update: 0
Alternate2 Update:      0
Sat Provider Update: 1
DVB:  id:0000, lon:101.00E
Tuner = WIDE
Signal offset = 80
Signal baseline angle = 6500
Signal Re-Peak Pct = 25
NVS Status: 0  Sleep: 420  Dipswitch: 101
Sleep: 420  NVS: 420
NoGpsStartUp: 721
STATIONARY MODE
Enabled LNB ODU 18V
GPS Not Found

Homing Sequence

After boot, the dish homes both motors (EL first, then AZ) using stall detection:

MotorHome:1 timeout:2000          ← EL motor homing
Home TwelInch El   Velocity: 4500
EL Stall Timeout
El Home Angle: 6500

MotorHome:0 timeout:8000          ← AZ motor homing
Home TwelInch Az
End MotorAzStall:part1
Antenna Facing Front
home:0  wrap_pos:0  wrap_min:-42333  wrap_max:2333

Cable Wrap Limits

From homing output: wrap_min:-42333 wrap_max:2333

  • In centidegrees: -423.33° to +23.33° from home position
  • Total range: 446.66° (~1.24 full rotations)

Motor Control

Position Query

In the MOT> submenu, a returns position with 4-space indentation:

a
    Angle[0] = 180.00       ← AZ (degrees)
    Angle[1] = 45.00        ← EL (degrees)
MOT>

Move Command

a <id> <deg> returns a confirmation (no array index) and the prompt immediately while the motor moves in the background:

a 1 46
    Angle = 46.00
MOT>

Observed Motor Behavior

Test Command Target Actual Overshoot
EL move out a 1 46 46.00 46.05 +0.05°
AZ move out a 0 181 181.00 181.01 +0.01°
EL return a 1 45 45.00 44.94 -0.06°
AZ return a 0 180 180.00 179.98 -0.02°

Direction-dependent overshoot: the motor consistently overshoots in the direction of travel, undershooting on return. This is classic stepper backlash + PID settling behavior and is what the leapfrog algorithm compensates for.

MOT Submenu — Full Command Reference

Available commands:
   a             Go to angle [[[motor] [[+|-]angle]]]
   azscan        Scan AZ from EL Min-Max Angle [az_rel_angle] [el_rel_angle] [delay]
   azscanwxp     Scan AZ from EL Min-Max with all transponders [motor] [span] [resolution] [num_xp]
   e             Engage motors
   ela2s         Elevation Law Test - Angle to Steps [angle]
   elminmaxhome  Display Min, Max & Home Elevation Angles
   els2a         Elevation Law Test - Steps to Angle [steps]
   h             Home Motors [motor num or * (both)]
   l             List Motors in System
   life          Az/El Life test [az_rel_angle] [el_rel_angle]
   ma            Set Max Acceleration [[motor] [deg/sec/sec]]
   motorboth     Both Motor Life test [AZ delta(0-25)] [EL delta(0-25)]
   motorlife     Motor Life Test [motor_id] [min_angle] [max_angle]
   mv            Set Max Velocity [motor] [deg/sec]
   p             Go To Position [motor] [pos]
   pid           Set PID Parameters [motor] [Kp] [Kv] [Ki]
   r             Release Motors
   sd            Stall Detect [motor] [dir] [timeout_ms] [iterations (0=forever)]
   sp            Set Position [motor] [pos]
   sw            Set Wrap Position [motor] [pos]
   v             Goto Velocity [motor] [deg/rev]
   vms           Goto Velocity For Milliseconds [motor] [deg/rev] [ms]
   w             Wrap Manager [motor] [ON/OFF]

Relative Moves

a supports +/- prefix for relative moves:

a 0 +5      ← move AZ 5° CW from current
a 1 -2      ← move EL 2° down from current

This is undocumented in the upstream repos and very useful for incremental positioning during tracking.

Motor List

l
Motors:
    0 - AZIMUTH: local
    1 - ELEVATION: local

"local" means direct A3981 driver control (vs. a networked motor controller).

Motor Dynamics

ma → Accel[0] = 400.0  Accel[1] = 400.0   (deg/sec²)
mv → Max Vel[0] = 65.0  Max Vel[1] = 45.0  (deg/sec)

Both axes have identical acceleration (400 deg/sec²). AZ max velocity is faster (65 deg/sec) than EL (45 deg/sec) — different gear ratios and mechanical loads.

Step Position

p shows position in microsteps:

p → Position[0] = 19998  Position[1] = 3116

Cross-check with angle: AZ 179.98° × (40000/360) = 19998 steps. Linear mapping for both axes (angle = steps × 360 / steps_per_rev).

Elevation Limits

elminmaxhome → Min: 1800  Max: 6500  Home: 6500

All values in centidegrees: Min=18.00°, Max=65.00°, Home=65.00°. The home position is at maximum elevation (stow position).

Elevation Law Conversion

ela2s converts angle → steps, els2a converts steps → angle:

Angle Steps Notes
1248 Below min (warning: "Min: 1800")
18° 1248 Minimum EL (same steps as 0°)
45° 3120
65° 4506 Maximum EL
90° 4506 Above max (warning: "Max: 6500")

The mapping is linear: steps ≈ angle × (24960/360). The "law" is a simple linear function for this dish — no non-linear linkage compensation.

Engage / Release

  • e — Engage motors (enable A3981 drivers, PID loop holds position)
  • r — Release motors (disable drivers, dish can move freely by hand)

Sky Scan Commands

azscan <az_rel> <el_rel> <delay> — Scan AZ while stepping EL from min to max angle. Parameters are relative angles and dwell delay. Used for basic signal surveys.

azscanwxp <motor> <span> <resolution> <num_xp> — Advanced sky scan that steps in hundredths of a degree and checks all transponders at each position. This is the core of Davidson's winegard-sky-scan project. The resolution parameter in hundredths of a degree enables 0.01° precision scanning — far finer than the standard a command.

Stall Detection

sd <motor> <dir> <timeout> [iterations] — Run stall detection on a motor. Default timeouts: AZ=10000ms, EL=2000ms. The firmware drives the motor in the specified direction until it stalls (current spike from A3981). Set iterations to 0 for continuous mode. Used during homing and calibration.

Life / Durability Tests

Factory test commands that continuously exercise the motors:

  • life <az_rel> <el_rel> — Oscillate both axes by relative angles
  • motorlife <id> <min> <max> — Sweep a single motor between min/max angles
  • motorboth <az_delta> <el_delta> — Exercise both motors, max 25° delta each

Write-Only Commands

These commands require parameters — no read-only mode:

  • pid <motor> <Kp> <Kv> <Ki> — Set PID gains (no read command)
  • sp <motor> <pos> — Set step position counter (doesn't move motor)
  • sw <motor> <pos> — Set wrap position
  • w <motor> ON/OFF — Enable/disable wrap manager

DVB Subsystem (BCM4515)

Hardware

BCM Hardware=  ID: 0x4515  VER: 0xB0
BCM Firmware=  MAJOR VER: 0x71 (113)  MINOR VER: 0x25 (37)
BCM Strap Config: 0x25018

Channel Parameters (dis)

Power Mode:           ON
Search Transponders:  ON
Auto Search Mode:     1
Shuffle Mode:         ON
Frequency List:       Non-Stacked

Num  Parameter            Current                  Default
1    Frequency            1090640 (kHz)            974000 (kHz)
2    Symbol Rate          0 (PeakScanEnabled)      20000 (ksps)
3    Trans_Mod_CRate      blind_scan               blind_scan
4    Blind Scan Mode      ___trb_dvb_dss_____      ___trb_dvb_dss_____
5    LNB Polarity         ODU:13V                  ---
6    LNB Tone (ODU)       off                      off
7    Roll-off             0.35                     0.35
8    LPF Cutoff           0 (auto)                 0 (MHz)
9    Carrier Offset       0 (kHz)                  0 (kHz)
10   FreqSearchRange      5000 (kHz)               5000 (kHz)
11   DCII Mode            dcii_qpsk_comb           dcii_qpsk_comb
12   Spectral Inv         scan                     scan
13   PScnSymRtRngMin      18000 (ksps)             18000 (ksps)
14   PScnSymRtRngMax      24000 (ksps)             24000 (ksps)
15   SignalDetectMode      off                     off

RSSI Response Format

rssi 5
iterations:5  interval(msec):20
 Reads:5  RSSI[avg: 500  cur: 500]
DVB>

500 is the noise floor (no signal lock, dish pointed at arbitrary sky).

LNB Voltage

lnbdc odu enables LNA at 13V. lnbv streams continuous voltage readings:

Reads:1  LNB Voltage (mV): 13239  ( ADC value: 119 )
Reads:2  LNB Voltage (mV): 13182  ( ADC value: 118 )
...

Stable at ~13.11V (ADC 117). Boot default is 18V; lnbdc odu switches to 13V. 13V = vertical polarization, 18V = horizontal polarization on a standard LNB.

AGC (Streaming)

agc streams RF and IF automatic gain control plus SNR/NID:

Reads:1  RF_AGC[avg: 1327353088  cur: 1327353088] IF_AGC[avg: 2684354560  cur: 2684354560]  SNR: 0.0  NID: FFFF/none
  • RF_AGC values are raw BCM4515 32-bit register values
  • IF_AGC constant at 0xA0000000 (fixed IF gain)
  • SNR: 0.0 when no signal lock
  • NID: FFFF/none = no DVB network ID detected

SNR (Streaming)

snr streams signal-to-noise ratio readings:

Reads:1  SNR[avg: 0.0  cur: 0.0]
Reads:2  SNR[avg: 0.0  cur: 0.0]
...
Reads:223  SNR[avg: 0.0  cur: 3.1]   ← transient RF spike
Reads:250  SNR[avg: 0.0  cur: 2.6]   ← another transient

At noise floor, average stays 0.0 but occasional transient spikes appear in the cur field — fleeting RF energy. Stays in DVB submenu when interrupted.

Lock Status (ls) — Streaming

ls is a STREAMING command that continuously scans all 32 transponders, trying multiple modulations per frequency. Output is a continuous scan log:

Xp:1  Freq:974000 SymRate:20000 Mode:blind_scan ... no_lock
Xp:1  Freq:974000 SymRate:20000 Mode:turbo_qpsk_... ... no_lock
...

When interrupted with CR, ls prints "Terminating shell." and drops to TRK> (exits DVB submenu entirely). This is unique among DVB streaming commands — all others stay in DVB submenu when interrupted.

Quick Lock Status (qls) — Streaming

qls streams compact lock status at ~100ms intervals:

Lock:0  rssi:500  cnt:0
Lock:0  rssi:500  cnt:0
...

Stays in DVB submenu when interrupted. Ideal for real-time signal monitoring during dish movement (low bandwidth, high update rate).

Network ID (nid) — Streaming

nid streams network identification:

nid: FFFF/none
nid: FFFF/none

Uses CR-overwrite (carriage return without newline) for in-place updates. FFFF = no DVB network detected. Can be difficult to interrupt cleanly — may need multiple CR + flush cycles.

Signal Statistics (stats) — Streaming

stats streams signal statistics. Produces no output when there is no signal lock. Stays in DVB submenu when interrupted.

Diagnostics (diag) — One-Shot

diag is a multi-block ONE-SHOT command that outputs detailed per-transponder diagnostics for each transponder currently being tried:

  SymRate: 18514984    Freq: 974000
  Bit Rate: 29893160
  SNR: 0.0   SymRateErr: -1258   CarrierOffset: 0   CarrierErr: 3295097
  Tuner LPF: 12   RF_AGC: 2214707264
  BER Errors: 0   MPEG Frm Errors: 0   MPEG Frm Count: 0
  Reacquisitions: 7
  RS Corr/Uncorr: 0 / 0   Pre-Vit: 0
  sp inv: scan   phase rotation: 0
  Acq Time: 4259 msec
  trans_mod_coderate: no_lock
  Tuner PLL: LOCKED   Internal BERT: not locked
  Demod: not locked   Timing Loop Lock: disabled

Transponder Table (table) — One-Shot (Long)

table generates a full scan across all 32 transponders. Takes ~136 seconds (~4.25s per transponder, matching tabto acquisition timeout of 4000ms).

The output starts with a configuration summary showing all modifiable parameters with their current values and the commands to change them, then a detailed per-transponder table with columns:

Xp  Freq  SigDet  SymRate  PeakPower  SNR  LPF  RF_AGC  AcqTime  Mode
NID/SAT  XpTime  LNBVsens  RSSI  BitrateOut  SymRateError  CarrierOffset
CarrierError  BER_Errors  MPEG_Errors  MPEG_Count  Reacq

With shuffle mode ON, transponders scan in interleaved groups of 4: 1,2,3,4 → 17,18,19,20 → 5,6,7,8 → 21,22,23,24 → 9,10,11,12 → 25,26,27,28 → 13,14,15,16 → 29,30,31,32.

LNB voltage alternates between ~13V (vertical polarization) and ~20V (horizontal polarization) across transponder groups.

After scan completes: Table Completion Time (seconds): 136 Transponders Locked: 0 then auto-restores LNB to STB mode: Enabled LNB STB.

Frequency List (freqs)

Returns the active frequency list name:

freqs → Non-Stacked

"Non-Stacked" means standard Ku-band IF frequencies without stacking (stacked LNBs combine multiple bands into one cable).

Transponder Range (range)

range → Transponder Range: [ 1 - 32 ]

Power State (pwr)

pwr → SDS and DiSEqC core power enabled

Shows power state of the Satellite Detection System and DiSEqC subsystems.

Search Mode (srch_mode)

srch_mode → Auto Search Mode: 1

Mode 1 = automatic transponder search with blind scan.

Timeout Settings

Two separate timeout configurations:

Table scan timeouts (tabto):

Timeout (msec):  Acq:4000  NID:20000  Signal Detect:0

Single transponder tune timeouts (to):

Timeout (msec):  Acq:500  NID:12000

tabto takes arguments: tabto <acq> <nid> <sd> (set 0 to disable NID/SD). to takes arguments: to <acq> <nid>.

Toggle Commands

These commands toggle a mode and print the new state:

Command What it toggles
srch Search Transponders mode (on/off)
shuf Transponder shuffle order (on/off)
tablex Extended table mode (on/off)

Defaults Reset (def)

def silently resets all channel parameters to defaults. No output, no confirmation. Use with caution — there is no undo.

Modulation Switch (msw)

msw requires arguments but rejects all tested inputs (msw 0, msw 1, msw on). Format unknown — possibly vestigial or requires a specific modulation string.

Channel Parameter Help (h <n>)

h <n> shows valid values for each of the 13+2 channel parameters:

Param Name Range / Values
1 Frequency 2500002150000 kHz (L-band IF)
2 Symbol Rate 0 (Peak Scan) or 200045000 ksps
3 Trans_Mod_CRate 30+ modes (see table below)
4 Blind Scan Mode Bitmask: s2, trb, dvb, dss, dcii (see below)
5 LNB Polarity 13V (vertical) / 18V (horizontal)
6 LNB Tone off / on (22kHz for high-band switching)
7 Roll-off 0.20 / 0.35
8 LPF Cutoff 0 (auto) or 140 MHz
9 Carrier Offset -5000 to +5000 Hz
10 FreqSearchRange 010000 kHz
11 DCII Mode comb, i, q (QPSK) / ocomb, oi, oq (OQPSK)
12 Spectral Inversion 0=normal, 1=q inv, 2=i inv, 3=scan
13 PScnSymRtRngMin 200045000 ksps
14 PScnSymRtRngMax (shown in dis, no h 14 help)
15 SignalDetectMode (shown in dis, no h 15 help)

Supported Modulations (Param 3)

DVB-S:   dvbs_qpsk_1_2, dvbs_qpsk_2_3, dvbs_qpsk_3_4,
         dvbs_qpsk_5_6, dvbs_qpsk_7_8
DSS:     dss_qpsk_1_2, dss_qpsk_2_3, dss_qpsk_6_7
DCII:    dcii_qpsk_1_2, dcii_qpsk_2_3, dcii_qpsk_3_4,
         dcii_qpsk_5_11, dcii_qpsk_4_5
DVB-S2:  s2_qpsk_1_2, s2_qpsk_3_5, s2_qpsk_2_3, s2_qpsk_3_4,
         s2_qpsk_4_5, s2_qpsk_5_6, s2_qpsk_8_9, s2_qpsk_9_10,
         s2_8psk_3_5, s2_8psk_2_3, s2_8psk_3_4
Turbo:   turbo_qpsk_1_2, turbo_qpsk_2_3, turbo_qpsk_3_4,
         turbo_qpsk_5_6, turbo_qpsk_7_8,
         turbo_8psk_2_3, turbo_8psk_3_4, turbo_8psk_4_5,
         turbo_8psk_5_6, turbo_8psk_8_9
Special: blind_scan

Blind Scan Mode Bitmask (Param 4)

Visual bitmask format: s2_trb_dvb_dss_dcii

Value Pattern Standards enabled
s2 s2_______________ DVB-S2 only
trb ___trb___________ Turbo FEC only
dvb _______dvb_______ DVB-S only
dss ___________dss___ DSS (DirecTV) only
dcii _______________dcii DCII (DigiCipher) only
all s2_trb_dvb_dss_dcii All standards
dish ___trb_dvb________ DISH Network (turbo + DVB-S)
3 ___trb_dvb_dss___ DirecTV 3-standard
shaw ___trb_________dcii Shaw (turbo + DCII)
nodcii s2_trb_dvb_dss___ All except DCII
nos2 ___trb_dvb_dss_dcii All except DVB-S2

DiSEqC Commands

All DiSEqC 2.x read commands fail with RxReplyTimeout when no switch is connected (expected — the G2 has a direct LNB without a multi-switch):

Command Function Result (no switch)
di2id Read LNB hardware ID LNB Read HW ID FAIL
di2stat Read LNB status LNB Read Status FAIL
di2conf Read LNB config LNB Read Config FAIL
di2sc Short circuit test LNB Short Circuit FAIL
di2rcs Read switch state LNB Switch State FAIL
di2cs Configure switch No Parameters Specified (needs args)
send <3-6 bytes> Raw DiSEqC packet (not tested — no switch)

DiSEqC Timing Parameters

Command Parameter Default
ovraddr LNB address 0x11 (standard first LNB)
rrto Receive reply timeout 210 ms
tdthresh Tone detect threshold 110 (units: 0.16 counts/mV)
pretx Pre-command TX delay 15 ms

DVB Command Reference

Command Type Description
rssi <n> One-shot Average signal strength over n samples
snr Streaming SNR readings (avg + current)
agc Streaming RF/IF AGC + SNR + NID
lnbdc odu One-shot Enable LNB in ODU mode (13V)
lnbv Streaming Continuous LNB voltage monitoring
ls Streaming Full transponder lock scan (exits DVB on interrupt!)
qls Streaming Quick lock status (~100ms updates)
nid Streaming Network ID (CR-overwrite display)
stats Streaming Signal statistics (silent when no lock)
config One-shot BCM hardware/firmware version
dis One-shot Display all channel parameters
diag One-shot Multi-block per-transponder diagnostics
table One-shot Full 32-transponder scan (~136s)
freqs One-shot Frequency list name
range One-shot Transponder scan range
pwr One-shot SDS/DiSEqC power state
srch_mode One-shot Auto search mode value
tabto Read/Write Table scan timeouts (acq/nid/sd)
to Read/Write Single tune timeouts (acq/nid)
t <n> Write Select transponder
e <n> <v> Write Edit channel parameter
h <n> Read Parameter help (valid values for param n, 1-13)
srch Toggle Search transponders mode
shuf Toggle Transponder shuffle order
tablex Toggle Extended table mode
def Write Reset all params to defaults (silent, no undo!)
msw <?> Write Modulation switch (format unknown)
ovraddr [addr] Read/Write DiSEqC LNB address
rrto [ms] Read/Write DiSEqC receive reply timeout
tdthresh [val] Read/Write DiSEqC tone detect threshold
pretx [ms] Read/Write DiSEqC pre-TX delay
di2id Read DiSEqC 2.x: read LNB hardware ID
di2stat Read DiSEqC 2.x: read LNB status
di2conf Read DiSEqC 2.x: read LNB config
di2sc Read DiSEqC 2.x: short circuit test
di2rcs Read DiSEqC 2.x: read switch state
di2cs <args> Write DiSEqC 2.x: configure switch
send <3-6 hex> Write Raw DiSEqC packet

Streaming commands: snr, agc, lnbv, qls, nid, stats run until CR interrupts. All stay in DVB submenu except ls which drops to TRK>.

Toggle commands: srch, shuf, tablex alternate on/off and print new state.

Satellite Configuration

DVB:  id:0000, lon:101.00E       ← DirecTV 101°W (stored as East longitude)
Primary Update:  10100            ← 101.00° in centidegrees
Alternate Update:  11900          ← 119.00°
Sat Provider Update: 1           ← Provider ID
Dipswitch Value: 101             ← DirecTV configuration

A3981 Motor Driver IC

The Allegro A3981 is an automotive-grade programmable stepper motor driver controlled by the K60 MCU via SPI. Two A3981 chips — one per axis (AZ, EL).

Datasheet: docs/A3981-datasheet.pdf (Allegro Microsystems) ECAD files: docs/A3981-ecad.kicad_sym, docs/A3981-ecad.pretty/

A3981 Commands (A3981>)

Command Type Description
diag Read Fault diagnostics for both axes
sm Read Step size mode (AUTO/MANUAL)
ss Read Current step size (microstepping level)
cm Read Current control mode (AUTO/MANUAL)
st <params> Write Set torque/current parameters
reset Write Clear latched A3981 faults on both axes

Diagnostics

diag
AZ DIAG: OK
EL DIAG: OK

Microstepping Configuration

ss
KEY: FULL-16, HALF-8, QTR-4, EIGHTH-2, SIXTEENTH-1
AZ Step Size:1
EL Step Size:1

Both axes at step size 1 = 1/16 microstepping (finest available). The A3981 supports full, half, quarter, eighth, and sixteenth steps. The inverted key (FULL=16, SIXTEENTH=1) is the firmware's internal representation — likely a divisor applied to the full-step pulse count.

Step Size and Current Modes

sm                          cm
AZ Step Size Mode = AUTO    AZ: Mode = AUTO
EL Step Size Mode = AUTO    EL: Mode = AUTO

AUTO mode means the driver dynamically adjusts microstepping resolution and current level based on motor speed. At low speeds, fine microstepping (1/16) provides smooth motion and precise positioning. At higher speeds, the driver may switch to coarser steps to maintain torque.

Fault Reset

reset
Az/El A3981 Faults Reset.

Clears latched fault conditions (overcurrent, open load, thermal). This is a write operation — it actively clears the fault registers, not a read-only status check. Use diag for non-destructive fault checking.

ADC Subsystem (ADC>)

Command Type Description
m Streaming Monitor RSSI continuously
rssi One-shot Read RSSI (same noise-floor value as DVB)
scan Unknown Scan ADC on azimuth axis
bdid One-shot Board identification string
bdrevid One-shot Board revision ID

Board Identification

bdid     → STATIONARY
bdrevid  → A

"STATIONARY" confirms this is the non-mobile (non-in-motion) variant. Board revision "A" is the first production revision.

RSSI via ADC

rssi → 500

Same noise floor value (500) as the DVB rssi command. The ADC subsystem reads the same analog signal path — likely a baseband power detector output from the BCM4515 routed to a K60 ADC input.

Dipswitch (DIPSWITCH>)

dipswitch
val:ffffff01
app_dipswitch:101

The raw value 0xFFFFFF01 has the low byte = 0x01. The app_dipswitch value 101 corresponds to the DirecTV satellite configuration. Dipswitch values select the satellite provider (DirecTV, DISH, Bell) and determine which transponder frequencies the search algorithm tries.

EEPROM (EE>)

Command Type Description
ee <idx> Read Read EEPROM value at index
ee <idx> <val> Write Write EEPROM value at index
inv [<idx>] Write Invalidate EEPROM index (destructive!)
def Write Restore all EEPROM values to factory defaults

EEPROM is a separate storage area from NVS. NVS holds operational parameters (motor tuning, PID gains, satellite config). EEPROM appears to hold calibration or factory data — likely stored in an external I2C EEPROM (AT24Cxx or similar) rather than the K60's internal flash.

EEPROM Structure

The EEPROM has exactly 17 indices (0-16). The firmware enforces bounds:

ee 17
Index out of bounds:17 Min:0 Max:16

Each index stores a 32-bit unsigned integer. Invalid entries return a sentinel value of 65793 (0x00010101) — three bytes of 0x01 in the low 24 bits. The firmware distinguishes between valid and invalid reads:

  • Valid: Read value = <decimal> — data is trusted
  • Invalid: Failed to read. val:<decimal> — data exists but flagged invalid

Complete EEPROM Dump

Dumped via scripts/ee_dump.py (pyserial script scanning all indices):

Index Decimal Hex Status Notes
0 65793 0x00010101 INVALID Accidentally invalidated (inv 0)
1 0 0x00000000 OK
2 22897 0x00005971 OK
3 3748 0x00000EA4 OK
4 4346 0x000010FA OK
5 11637 0x00002D75 OK
6 65793 0x00010101 INVALID Factory default (never written)
7 65793 0x00010101 INVALID Factory default
8 65793 0x00010101 INVALID Factory default
9 65793 0x00010101 INVALID Factory default
10 65793 0x00010101 INVALID Factory default
11 65793 0x00010101 INVALID Factory default
12 65793 0x00010101 INVALID Factory default
13 65793 0x00010101 INVALID Factory default
14 65793 0x00010101 INVALID Factory default
15 65793 0x00010101 INVALID Factory default
16 65793 0x00010101 INVALID Factory default

Only 6 indices (0-5) were ever written with valid data. Indices 6-16 have never been programmed — all contain the 0x00010101 sentinel. The EEPROM has capacity for 17 values but only the first 6 are used by this firmware version.

Value Analysis

The valid EEPROM values (indices 1-5) don't correspond to any obvious motor positions, NVS indices, or physical constants. They may represent:

  • Factory calibration offsets — motor encoder corrections, sensor trim
  • Manufacturing data — serial number components, PCB revision, test results
  • Checksum/signature — authentication for firmware/hardware pairing

Index 0 (originally valid, now invalidated) was likely a calibration value or header byte. Its original value is unknown — def might restore it.

Command Notes

inv [<idx>] — "Invalidate", not "inventory". Marks an index as invalid by writing the 0x00010101 sentinel. The firmware still returns the raw value on read but flags it as Failed to read. Destructive and immediate — no confirmation prompt.

def — Restores all EEPROM indices to factory defaults. Not tested on this unit (would overwrite the accidentally-invalidated index 0 but also reset any user-modified values). Worth trying if index 0's missing value causes issues.

ee <idx> <val> — Write a value to an index. Accepts decimal integers. Can be used to restore invalidated indices if the original value is known.

GPIO Registers (GPIO>)

Command Type Description
regs Read Dump all GPIO pin states (0/1)
r <port> <pin> Read Read single GPIO pin (e.g., r A 5)
w <port> <pin> Write Write to GPIO pin (toggle)
dir <bit> <val> Write Set pin direction (input/output)

The regs command dumps all MCU GPIO pins across 5 ports (K60 144-pin). Note: pins A20-A23 and B12-B15 are not enumerated (reserved or unbonded):

Port Pins Enumerated High Pins (=1)
A A0A19, A24A29 (26 pins) A1, A3, A4, A5, A15, A16, A25A29
B B0B11, B16B23 (20 pins) B0, B1, B2, B3, B11
C C0C19 (20 pins) C10, C11, C12, C13, C18
D D0D15 (16 pins) D11, D12, D13
E E0E12, E24E29 (19 pins) E0, E1, E2, E4, E5, E7, E9E12, E24E28

Total: 101 pins enumerated. "Unknown bit E29" logged by firmware — pin E29 is defined in hardware but not assigned a function (test point or reserved).

LATLON (LATLON>)

Command Type Description
l <satlon1> <satlon2> <satel1> <satel2> Read Calculate dish lat/lon from two satellite observations

This is the dish's self-localization algorithm — it triangulates its own geographic position by observing two known geostationary satellites. The four parameters are longitude and elevation pairs for two satellites.

l -110 -119 40 38
 anglesentered = -11000 -11900 4000 3800
    Lat = 4295  Lon = 25655

Output is in centidegrees: Lat 4295 = 42.95°N, Lon 25655 = 256.55°E (= 103.45°W). This is a reasonable US mid-latitude position given DISH Network satellites at 110°W and 119°W with elevation angles of 40° and 38°.

The firmware uses this for automatic satellite look-angle computation when no GPS is available (the G2 has no GPS module — "GPS Not Found" at boot).

PEAK Subsystem (PEAK>)

Command Type Description
ts Streaming (DANGEROUS) EchoStar/DiSEqC switch toggle — runs forever, can't be interrupted
pw <az> <el> Motor+Signal Peak wide — sweep around AZ/EL to find signal peak
psnr <az> <el> Motor+Signal Peak SNR — sweep around AZ/EL optimizing for SNR
pxy1 [<n>] Motor+Signal Peak XY1 — 2D cross-pattern peak search, repeat n times (default 1)
stb One-shot STB control test — toggles LNB polarity and compares RSSI
rssits Streaming RSSI test — prints every 1 minute (exits submenu on interrupt!)

EchoStar Switch Toggle (ts) — DANGEROUS!

The ts command runs indefinitely, probing for a DiSEqC/EchoStar switch by toggling LNB voltage and reading the switch response. It cannot be stopped by sending q — the running command consumes all input. The only escape is to close and reopen the serial port.

ts
(14000+ reads, all showing: 0b0000 0)

All reads returned 0b0000 0 — no switch connected (expected, since the G2's LNB is directly connected without a multi-switch).

STB Control Test (stb)

Toggles LNB polarization and compares RSSI at each polarity:

stb
Enabled LNB ODU 18V
Even_sig = 504
Enabled LNB STB
Odd_sig = 232
Enabled LNB STB
Odd_sig = 233 Ctr = 0
  • Enabled LNB ODU 18V → horizontal polarization (18V), Even_sig = 504
  • Enabled LNB STB → vertical polarization (13V), Odd_sig = 232
  • Ctr = 0 → no DiSEqC switch response detected
  • The 504 vs 232 difference (~2x) reflects the polarization-dependent noise floor. "Even" = H-pol transponders (18V), "Odd" = V-pol (13V) — DBS convention.

RSSI Test (rssits)

Starts a background RSSI monitoring task that prints every 1 minute. When interrupted, exits the PEAK submenu entirely (drops to TRK> root), similar to DVB ls behavior.

STEP Subsystem (STEP>) — Low-Level Motor Control

Command Type Description
e Write Engage motor (enable driver)
r Write Release motors (disable driver, coast to stop)
p Read/Write Go to position (absolute, in microsteps), or read current position
v Write Go to velocity (continuous rotation)
ma Read/Write Set/get max acceleration (ustep/sec/msec)
mv Read/Write Set/get max velocity (ustep/sec)
pid Read/Write Set/get PID tuning values

This is the raw stepper motor interface — below the mot menu's degree-based abstraction. Commands operate in microsteps rather than degrees. The relationship between microsteps and degrees depends on:

  • Gear ratio (NVS 49, currently 0x00000000)
  • Steps per revolution (NVS 83: AZ=40000, NVS 88: EL=24960)
  • Microstepping level (A3981: both at 1/16)

Current Values (read mode)

p       →  Step Pos[0] = 19998    Step Pos[1] = 3116
ma      →  Accel[0] = 44         Accel[1] = 28
mv      →  Max Vel [0] = 7222    Max Vel [1] = 3120
pid     →  Kp=250  Kv=50

MOT↔STEP Conversion Table

Parameter STEP (microsteps) MOT (degrees) Factor
AZ position 19998 179.98° 111.11 steps/°
EL position 3116 44.94° 69.33 steps/°
AZ max vel 7222 ustep/s 65.0°/s ÷111.11
EL max vel 3120 ustep/s 45.0°/s ÷69.33
AZ accel 44 ustep/s/ms ~396°/s² ×1000÷111.11
EL accel 28 ustep/s/ms ~404°/s² ×1000÷69.33

PID Tuning

pid returns Kp=250 Kv=50 — proportional and velocity gains. No Ki term, indicating a PD (proportional-derivative) position loop. This is typical for stepper motors which don't drift under holding torque. Matches NVS indices 128-129. Note: pid is write-only in MOT> but readable in STEP>.

The e/r commands engage and release the A3981 motor drivers. When released, the motors are unpowered and the dish can be moved by hand (useful for manual positioning or emergency stow). When engaged, the PID loop holds position.

ADC Subsystem (ADC>)

Command Type Description
bdid Read Board ID — returns STATIONARY
bdrevid Read Board revision ID — returns A
rssi Read Single RSSI reading (ADC value, not DVB RSSI)
m Toggle? Monitor RSSI — returns immediately, may enable background monitoring
scan Streaming Continuous ADC scan with position, RSSI, Lock, SNR, and delta

Board Identity

  • Board ID: STATIONARY — distinguishes from mobile/in-motion antenna variants
  • Board Rev ID: A — PCB revision

RSSI (ADC)

rssi returns a single ADC reading: 232 at noise floor. This is the raw ADC value from an analog RSSI detector (separate from the DVB tuner's digital RSSI). The ADC RSSI baseline (~232) corresponds to the DVB Odd_sig in the PEAK stb test, suggesting both measure the same RF path at V-pol.

Scan (Streaming)

scan performs a continuous RF scan at the current position:

Starting position AZ:17998 EL:4494 Stop at:0
Motor:0 Angle:17998 RSSI:232 Lock:0 SNR:  0.0 Scan Delta:0
Motor:0 Angle:17998 RSSI:238 Lock:0 SNR:  0.0 Scan Delta:0
Motor:0 Angle:17998 RSSI:233 Lock:0 SNR:  0.4 Scan Delta:0
...

Positions are in centidegrees (17998 = 179.98°). Scan Delta:0 indicates no motor movement — the scan reads RSSI at the fixed position. Stop at:0 suggests it scans until manually interrupted. Occasional SNR transients (0.10.4 dB) appear from fleeting RF energy. The scan likely moves the motor when used with the azscanwxp sky-scan command from the MOT menu.

Dipswitch Subsystem (DIPSWITCH>)

Command Type Description
dipswitch Read Read physical DIP switch state and interpreted value
dipswitch
val:ffffff01
app_dipswitch:101
  • val: ffffff01 — raw GPIO register reading. The 0x01 LSB indicates one switch position is active; 0xFF bytes are pulled-up (inactive) switches.
  • app_dipswitch: 101 — firmware-interpreted value. Matches NVS index 113 ("Dipswitch Value: 101"), which encodes a DirecTV satellite configuration.

The physical DIP switch on the PCB selects the satellite provider's transponder list for TV search mode. NVS index 112 ("Disable Dipswitch?") controls whether the firmware reads the physical switch or uses the NVS-stored value. Since we've disabled the tracker (NVS 20 = TRUE), the DIP switch setting is ignored.

A3981 Motor Driver (A3981>)

Command Type Description
diag Read Read AZ/EL diagnostic pins (fault status)
sm Read/Write Get/set step size mode (AUTO, manual)
ss Read/Write Get/set step size (microstepping divisor)
st Read/Write Get/set torque level (HIGH/LOW current)
cm Read/Write Get/set current control mode (AUTO, manual)
reset Write Reset AZ/EL A3981 diagnostic/fault registers

Current State

diag   →  AZ DIAG: OK          EL DIAG: OK
sm     →  AZ: Step Size Mode = AUTO    EL: Step Size Mode = AUTO
ss     →  AZ: Step Size:1      EL: Step Size:1
st     →  AZ Torq:LOW          EL Torq:LOW
cm     →  AZ: Mode = AUTO      EL: Mode = AUTO

Step Size Key

The ss value is a microstepping divisor, not multiplier:

Value Mode Microsteps per full step
16 FULL 1 (full step)
8 HALF 2
4 QTR 4
2 EIGHTH 8
1 SIXTEENTH 16 (finest)

Both motors are at 1 (1/16 microstepping — finest resolution). In AUTO mode, the A3981 IC automatically selects the step size based on speed: finer steps at low speed for smooth positioning, coarser steps at high speed for torque.

Torque and Current Control

st shows torque is LOW (motors idle/holding). cm shows current control is AUTO — the firmware switches between high current (moving) and low current (holding) automatically. This reduces power consumption and heat when the dish is stationary.

The diag pins expose A3981 fault conditions: overcurrent, overtemperature, open-load (disconnected motor winding), or short-to-ground. OK means no faults detected. Use reset to clear latched fault flags.

OS Subsystem (OS>)

Command Type Description
id Read Full MCU and firmware identification
reboot Write Reboot microcontroller (confirmed — full boot cycle ~10s)

System Identification (id)

NVS Version:    1.02.13
System ID:  TWELINCH
 K60-144pin
 Silicon Rev 2.4
 Mask Set 4N22D
 512 kBytes of P-flash
 P-flash only
 128 kBytes of RAM
 Board Rev ID:         A
 Board ID:             STATIONARY
 Ant ID:               12-IN G2
 Software version:     02.02.48
 CCLK:                 96000000
 BCLK:                 48000000
 Flash Base Address:   65536
 Flash Size:           458752

Key details:

  • System ID: TWELINCH — "Twelve Inch" (12" dish diameter)
  • Ant ID: 12-IN G2 — Carryout G2 model identifier
  • Silicon: K60-144pin, Rev 2.4, Mask 4N22D — NXP MK60DN512VLQ10
  • Clocks: CCLK=96 MHz (core), BCLK=48 MHz (bus)
  • Flash: Base at 0x10000 (64KB), size 458752 bytes (448KB usable firmware space)
  • NVS Version: 1.02.13 — the non-volatile storage schema version

Note: tasks and kill commands (available on other variants like HAL 0.0.00) are not present in the G2's OS submenu. On the G2, the satellite search is disabled permanently via NVS index 20 instead of killing a running task.

Firmware Command Behavior Notes

Command Types

  • One-shot: Executes once, returns result, shows prompt (>). Safe.
  • Streaming: Runs indefinitely until interrupted. Some accept q to stop, others require closing the serial port. The ts, agc, and lnbv commands are known streamers.
  • Write: Modifies state (motor position, NVS values, fault registers). Use with caution.

Serial Protocol Notes

  • Firmware expects ASCII CR (0x0D) as line terminator
  • Response terminates with > prompt character (ASCII 62)
  • Console does not support backspace — press Enter to clear on typo
  • Streaming commands consume all serial input while running
  • Some commands (e.g., st) are setters that return "Invalid params" when called without arguments — they are not read-only despite appearing in help listings without obvious setter syntax

TODO: Physical Board Inspection

Tasks for when the dome housing is opened and the control PCB is accessible.

USB Port Investigation

  • Inspect LQFP-144 package pins 19-22 (USB0_DP, USB0_DM, VOUT33, VREGIN) — these are on the corner near pin 1. Look for traces routing to a connector, test pads, or unpopulated header
  • Look for a USB mini/micro/Type-A connector anywhere on the PCB (may be behind a panel, under a shield can, or on the back side)
  • Check for a VBUS sense GPIO trace — the K60 needs a GPIO pin to detect USB cable insertion (ref manual Section 3.9.2)
  • If USB pads found: probe with multimeter for continuity to K60 pins 19-22

Debug / Programming Interface

  • Look for SWD/JTAG debug header (K60 has dedicated SWD pins: SWDIO on PTA3/pin 50, SWDCLK on PTA0/pin 46, SWO on PTA2/pin 49, RESET on pin 74). Could be a 10-pin Cortex Debug connector, 2x5 shrouded header, or unpopulated pads
  • Check for a UART boot mode pin — K60 supports serial bootloader via UART if NMI/FOPT bits are configured. Look for jumpers or DIP switches near the MCU
  • Identify the boot flash at 0x00000-0x0FFFF — is it internal to the K60 or an external SPI flash? Check for small SOIC-8 flash chips near MCU

Firmware Extraction via SWD

Serial bootloader has no interactive mode (confirmed: no interrupt window, no baud rate trick, binary-only status bytes 01 00 and 98 80 96). SWD is the primary extraction path.

Equipment: SWD probe (ST-Link V2, J-Link, or similar) + 4 jumper wires.

Connections (minimum 3 wires + GND):

Signal K60 Pin LQFP-144 Notes
SWDIO PTA3 Pin 50 Bidirectional data
SWDCLK PTA0 Pin 46 Clock (probe drives)
GND Multiple Common ground with probe
RESET Pin 74 Optional but recommended
SWO PTA2 Pin 49 Optional trace output

Step 1: Check flash security (CRITICAL — do this first)

# pyocd (recommended)
pyocd cmd -t mk60dn512xxx10 -c "read32 0x40C"

# or openocd
openocd -f interface/stlink.cfg -f target/k60.cfg \
  -c "init; halt; mdw 0x40C; exit"

The Flash Security register (FTFL_FSEC) at 0x40C:

  • Bits [1:0] = 10SECURED — SWD reads blocked, need EzPort fallback
  • Bits [1:0] = 00 or 11UNSECURED — full flash dump possible

Also check 0x400 (FTFL_FOPT / Flash Configuration Field at 0x400-0x40F):

pyocd cmd -t mk60dn512xxx10 -c "read8 0x400 16"

This 16-byte field (programmed into flash at 0x400) controls boot security, backdoor key, mass erase enable, and other flash protection settings.

Step 2: Dump firmware (if unsecured)

# Full 512KB flash dump (bootloader + application)
pyocd flash -t mk60dn512xxx10 -r firmware_full.bin \
  --address 0x00000 --size 0x80000

# Or just the application (448KB)
pyocd flash -t mk60dn512xxx10 -r firmware_app.bin \
  --address 0x10000 --size 0x70000

# Also dump the 128KB RAM (may contain runtime state)
pyocd cmd -t mk60dn512xxx10 \
  -c "savemem 0x1FFF0000 0x20020000 sram_dump.bin"

Step 3: If flash is secured — EzPort fallback

EzPort is an SPI-based flash interface activated by holding PTA4 (pin 51) low during reset. It may bypass flash security for reads on some K60 silicon revisions (Rev 2.4 / mask 4N22D — check errata).

EzPort SPI wiring:
  EZP_CS   = PTA4 (pin 51) — hold LOW during reset to enter EzPort
  EZP_CLK  = PTA0 (pin 46) — same pin as SWDCLK!
  EZP_DOUT = PTA2 (pin 49) — same pin as SWO
  EZP_DIN  = PTA1 (pin 47)

EzPort commands: 0x03 = Read, 0x05 = Read Status, 0x0B = Fast Read. Use an SPI master (ESP32, RPi, FTDI MPSSE) at ≤ 4 MHz.

Flash layout (from os id):

0x00000 - 0x0FFFF  Bootloader v1.01 (64KB)
0x10000 - 0x7FFFF  Application v02.02.48 (448KB)
                   Total: 512KB (0x80000)

Boot sequence bytes (from serial capture):

reboot echo → 0x01 0x00 (binary status) → "Bootloader version: 1.01"
→ "Application is running..." → 0x98 0x80 0x96 (binary, meaning unknown)
→ "Application Starting Kinetis PCB..."

The 0x01 0x00 and 0x98 0x80 0x96 are binary protocol bytes between bootloader and application — possibly a handshake or integrity check. Understanding these requires disassembling the bootloader.

Component Identification

  • Photograph both sides of the PCB (high-res, good lighting)
  • Read markings on the BCM4515 DVB tuner IC — confirm package, check for additional Broadcom support ICs nearby
  • Identify the two A3981 stepper driver ICs (TSSOP-28 with exposed pad, should be near motor connectors). Note their orientation and surrounding passives (sense resistors for current measurement)
  • Read crystal oscillator marking — frequency determines PLL configuration (K60 accepts 3-32 MHz, likely 8 MHz or 16 MHz for clean 96 MHz PLL)
  • Check for external EEPROM (separate from K60 internal flash) — likely I2C EEPROM near MCU, possibly AT24Cxx or M24Cxx series
  • Look for LNB voltage regulator circuit (13V/18V switching) — probably near the coax F-connector

Gyro / IMU Investigation

  • NVS indices 72-77 configure gyro parameters (sensitivity, filter, mount type) but boot log says nothing about a gyro. Check if there's an onboard MEMS gyro or an unpopulated footprint for one
  • If present, identify the gyro IC (likely single-axis rate gyro given the NVS parameters — "Gyro Mount Type: 1" suggests a specific axis)
  • If unpopulated: the G2 may share a PCB design with a larger model (Trav'ler SK-1000?) that includes a gyro for in-motion tracking

GPS Investigation

  • Boot log says "GPS Not Found" — look for a GPS module footprint (populated or empty). NVS 63-64 configure GPS heading/moving thresholds
  • Check for a GPS antenna connector (SMA or U.FL) or ceramic patch antenna on the PCB
  • If unpopulated: same shared-PCB theory as the gyro — the G2 firmware has GPS support but the hardware may be DNP (Do Not Populate)

Motor / Drive Train

  • Trace SPI bus from K60 to A3981 drivers — identify which DSPI peripheral (DSPI0, DSPI1, or DSPI2) connects to which axis (AZ vs EL)
  • Identify motor sense resistors near A3981 chips — value determines current limit calibration. Compare with NVS current limit hex values (indices 95-98, 110-111)
  • Check motor connectors — are they direct stepper connections (4-wire) or do they go through additional driver stages?
  • Look for limit switches or optical encoders (the G2 uses stall detection for homing, but there may be unused provisions for position feedback)

RF Signal Path

  • Trace signal path: F-connector → LNB bias tee → BCM4515 RF input
  • Identify any bandpass filters, LNAs, or frequency conversion stages between the coax and the BCM4515
  • Check if the ADC RSSI signal is a dedicated analog output from BCM4515 or if it's derived from an AGC control voltage

Power Supply

  • Identify main voltage rails — the board likely has 12V input (from RP-SK87 PSU), 5V (for logic), 3.3V (K60 core), and motor supply
  • Check if the USB VREG (K60 pins 21-22) is connected to anything or if VOUT33 is tied to the board's 3.3V rail directly
  • Identify motor power supply — A3981 supports up to 28V, the board likely runs motors at 12V from the main supply

TODO: Firmware Exploration (Serial Console)

Remaining commands to test via the RS-422 console.

DVB Submenu (Task #13) — COMPLETE

  • ls — streaming transponder scan (exits DVB submenu on interrupt!)
  • qls — streaming quick lock status (~100ms: Lock:0 rssi:500 cnt:0)
  • snr — streaming SNR readings (transient spikes in noise floor)
  • diag — multi-block one-shot per-transponder diagnostics
  • table — full 32-transponder scan (~136s), detailed per-xp data
  • freqs — frequency list name ("Non-Stacked")
  • stats — streaming, silent when no lock
  • nid — streaming network ID (FFFF/none), CR-overwrite display
  • di2id / di2stat / di2conf / di2sc / di2rcs — all fail (no switch)
  • di2cs — needs parameters (switch config)
  • send — needs 3-6 hex bytes (raw DiSEqC packet)
  • h 1-13 — full parameter help documented
  • tabto / to — timeout configs (table vs single tune)
  • ovraddr / rrto / tdthresh / pretx — DiSEqC timing params
  • srch / shuf / tablex — toggle commands
  • pwr — power state, srch_mode — search mode, range — scan range
  • def — silent defaults reset (dangerous!), msw — format unknown
  • e <n> <v> — edit channel params (not tested — would modify state)
  • send <hex> — raw DiSEqC (not tested — no switch connected)

MOT Submenu (Task #14) — COMPLETE

  • Full ? help listing — 25 commands discovered (see Motor Control section)
  • a supports relative moves with +/- prefix (undocumented upstream!)
  • h * homes both motors simultaneously
  • l — lists 2 motors: 0=AZIMUTH (local), 1=ELEVATION (local)
  • ma / mv — read motor dynamics (400 deg/s², 65/45 deg/s AZ/EL)
  • p — read step positions (19998 AZ, 3116 EL)
  • elminmaxhome — EL min=18°, max=65°, home=65°
  • ela2s / els2a — angle↔step conversion (linear mapping confirmed)
  • e / r — engage/release motors
  • azscan / azscanwxp — sky scan commands documented
  • sd — stall detection documented
  • life / motorlife / motorboth — factory life test commands
  • pid, sp, sw, w, v, vms — write-only commands documented
  • g <az> <el> — NOT available on G2 (not in help listing)
  • Test h 0 and h 1 homing (requires clear space around dish)
  • Test azscanwxp with real scan parameters (RF imaging)

NVS Experiments (Caution)

  • NVS 2 ("Debug 2nd Console Port") — try setting to 1, check if USB console activates. Save original value first, restore after test
  • NVS 4 ("Debug Port Connection") — similar test
  • NVS 112 ("Disable Dipswitch?") — what happens if dipswitch is disabled?
  • NVS 38 ("Sleep Mode Timer") — currently 420s (7 min). Set higher to prevent sleep during long tracking sessions

A3981 Submenu (Task #16) — COMPLETE

  • Full ? help listing — 6 commands: diag, sm, ss, st, cm, reset
  • diag — AZ/EL both OK (no faults)
  • sm — step size mode: both AUTO
  • ss — step size: both 1 (1/16 microstepping, finest)
  • st — torque: both LOW (idle)
  • cm — current control mode: both AUTO
  • Test diag output under motor load (move motor, read diag simultaneously)
  • Test changing step mode from AUTO to manual
  • reset — clear fault flags (no faults to clear currently)

ADC Submenu (Task #16) — COMPLETE

  • Full ? help listing — 5 commands: bdid, bdrevid, rssi, m, scan
  • bdid → STATIONARY, bdrevid → A
  • rssi → 232 (noise floor baseline)
  • scan — streaming: position + RSSI + Lock + SNR + delta per sample
  • m — returns immediately (toggle for background monitoring?)

Dipswitch Submenu (Task #16) — COMPLETE

  • Full ? help listing — 1 command: dipswitch
  • dipswitch → val:ffffff01, app_dipswitch:101

GPIO Submenu (Task #16) — COMPLETE

  • Full ? help listing — 4 commands: regs, r, w, dir
  • regs — full 101-pin dump (5 ports, all pin states)
  • r <port> <pin> / w <port> <pin> / dir <bit> <val> — help documented
  • Map specific GPIO pins to hardware functions (SPI→A3981, UART, I2C, etc.)

LATLON Submenu (Task #16) — COMPLETE

  • Full ? help listing — 1 command: l <satlon1> <satlon2> <satel1> <satel2>
  • Tested with satellite positions — self-localization algorithm confirmed

OS Submenu (Task #16) — COMPLETE

  • Full ? help listing — 2 commands: id, reboot (no tasks/kill on G2!)
  • id — full system identification including NVS version, MCU details, clock speeds
  • Deep probe: go/date/time initially appeared as hidden commands but were confirmed as false positives — boot sequence output captured after reboot caused a system restart mid-probe. All three return "Invalid command" post-boot.

PEAK Submenu (Task #16) — COMPLETE

  • Full ? help listing — 6 commands: ts, pw, psnr, pxy1, stb, rssits
  • stb — LNB polarity switching test (18V=504 RSSI, 13V=232 RSSI)
  • rssits — streaming every 1 min, exits submenu on interrupt
  • pw / psnr help — both take <az_deg> <el_deg> (signal peaking algorithms)
  • pxy1 help — takes <n> repeat count (2D cross-pattern peak search)
  • Test pw / psnr / pxy1 with a real satellite signal

EEPROM Submenu (Task #15) — COMPLETE

  • Full ? help listing — 3 commands: ee, inv, def
  • Complete EEPROM dump (all 17 indices, 0-16) via scripts/ee_dump.py
  • Bounds discovery: firmware enforces Min:0 Max:16
  • Sentinel value: 0x00010101 for invalid/uninitialized entries
  • Only 6 indices (0-5) ever written; 6-16 factory default (invalid)
  • def — restore factory defaults (not tested — would reset all values)
  • Determine meaning of valid EEPROM values (indices 1-5)
  • Restore index 0 via def or ee 0 <value> if original value is discovered

STEP Submenu (Task #16) — COMPLETE

  • e — engage motors ("Motors engaged"), verified via MOT
  • r — release motors (documented via MOT, not tested to avoid losing position)
  • p — read step positions (AZ=19998, EL=3116)
  • ma / mv — read accel and velocity in raw microstep units
  • pidreadable in STEP (write-only in MOT): Kp=250, Kv=50
  • MOT↔STEP conversion table verified (linear mapping)
  • p <motor> <pos> — test absolute microstep move (40000 steps/rev AZ, 24960 EL)
  • v <motor> <vel> — test continuous velocity mode

Hidden Command Deep Probe — COMPLETE

Systematic brute-force probe of 415 candidate commands across all 13 menu levels (root + 12 submenus). Script: scripts/hidden_menu_probe.py --deep

Results by submenu:

Submenu Probed Hits Known New Notes
TRK> 415 3 3 0 Only q, Q, help
OS> 415 7 4 0 go/date/time were false positives (see below)
MOT> 415 22 22 0 All in help listing already
DVB> 415 12 12 0 All previously discovered
STEP> 415 12 12 0 Mirrors MOT (engage/release/pos/vel)
A3981> 415 5 5 0 All in help listing already
ADC> 415 7 7 0
GPIO> 415 7 7 0
PEAK> 415 3 3 0
NVS> 415 412 n/a 0 False positives: auto-advance cursor
EE> 415 3 3 0
LATLON> 415 5 5 0
DIPSWITCH> 415 3 3 0

OS false positives explained: The probe hit reboot early in the OS sequence, causing a full system restart (~10s). The probe script continued sending commands into the boot stream. go, date, and time appeared as "hits" because their responses contained non-error text — but this text was unsolicited boot output, not command responses:

  • go "response" = SPI2 initialization output (BCM4515 firmware transfer at boot)
  • date "response" = BCM4515 hardware init (AP RAM FW VERIFIED, chip IDs)
  • time "response" = DVB channel init (dvbPrvChangeChannelInit Complete)

All three return "Invalid command" when tested manually in the OS submenu after boot completes. The boot output is still valuable — it reveals the SPI2 clock (6,857,142 Hz = 48 MHz / 7), SPI mode 3 (CPOL=1, CPHA=1), and the full BCM4515 bring-up sequence.

NVS false positives: The NVS submenu returned 412 hits because its parser treats any unrecognized input as "read next entry" — an internal cursor auto-advances through the NVS table. These are NOT hidden commands, just the fallthrough behavior of the NVS e (edit/read) command parser.

Conclusion: Zero genuinely hidden commands found across all 13 menu levels. The G2 firmware shell is well-scoped — no memory access, no flash read/dump, no hidden debug backdoors. Firmware extraction requires physical access (SWD or EzPort).