skywalker-1/firmware-dump/fw_v213_comparison_report.md
Ryan Malloy bbdcb243dc Normalize line endings to LF across entire repository
Apply .gitattributes normalization to convert all CRLF line
endings inherited from Windows-origin source files to Unix LF.
175 files, zero content changes.
2026-02-20 10:55:50 -07:00

18 KiB

Genpix SkyWalker-1 Firmware v2.13.x Sub-Variant Comparison Report

Executive Summary

Three firmware sub-variants were extracted from SW1_update_2_13_x.exe and analyzed as 8051 (Cypress FX2) binaries via Ghidra. The analysis reveals that FW1 (v2.13.1) targets fundamentally different hardware than FW2/FW3, while FW2 (v2.13.2) and FW3 (v2.13.3) target different revisions of a newer hardware platform with an external demodulator connected via a parallel data bus.


1. Function List Comparison

Function Counts

Variant Port Functions Extra Function
FW1 (v2.13.1) 8194 82 FUN_CODE_0fc7, FUN_CODE_1405, FUN_CODE_14b9 (unique)
FW2 (v2.13.2) 8195 83 FUN_CODE_1288 (unique), FUN_CODE_0ffc
FW3 (v2.13.3) 8196 83 FUN_CODE_1288, FUN_CODE_0706 (unique)

Shared Core Functions (Same Address Across All Three)

The following functions exist at identical addresses in all variants:

CODE:0000  RESET_vector          CODE:0003  INT0_vector
CODE:0033  INT2_USB_GPIF_vector  CODE:0036  FUN_CODE_0036
CODE:0043  INT4_FX2_vector       CODE:004b  INT5_FX2_vector
CODE:0050  FUN_CODE_0050         CODE:0053  INT6_FX2_vector
CODE:0056  FUN_CODE_0056         CODE:034e  FUN_CODE_034e (vendor cmd handler)
CODE:06d9  FUN_CODE_06d9         CODE:0718  FUN_CODE_0718
CODE:072a  FUN_CODE_072a         CODE:0779  FUN_CODE_0779
CODE:079d  FUN_CODE_079d         CODE:0800  FUN_CODE_0800 (main loop)
CODE:0ca4  FUN_CODE_0ca4         CODE:0eea  FUN_CODE_0eea
CODE:1000  FUN_CODE_1000         CODE:1500  thunk (target differs!)
CODE:15b8  FUN_CODE_15b8         CODE:170d  main_entry
CODE:1799  FUN_CODE_1799         CODE:1800  FUN_CODE_1800
CODE:19ed  FUN_CODE_19ed         CODE:1a5d  FUN_CODE_1a5d
CODE:1ac6  FUN_CODE_1ac6         CODE:1b2a  FUN_CODE_1b2a

Functions That Shift Addresses (Same Logic, Different Location)

Many functions exist in all three variants but at shifted addresses:

Purpose FW1 Address FW2 Address FW3 Address
Hardware init 0x11ab 0x1288 0x1288
Demod setup 0x10d9 0x10dd 0x10dd
I2C/parallel data transfer 0x0eea (I2C) 0x0eea (parallel) 0x0eea (parallel)
Tuner detect 0x1405 0x0eea 0x0eea
Delay loop 0x14b9 0x1e92 (FW2) 0x1e88 (FW3)
EEPROM checksum 0x1ca0 0x1cff 0x1ca1
USB descriptor setup 0x2031 0x206c 0x206c
Thunk target 0x2252 0x228d 0x228d
2nd init call 0x1be6 0x1c45 0x1cf7

Functions Unique to Each Variant

FW1 only:

  • FUN_CODE_0fc7 -- An I2C write-with-retry function (tries 0x14 = 20 times via I2C bus using FUN_CODE_23ae/23ee)
  • FUN_CODE_1405 -- Tuner/demodulator identification via I2C bus + P1 port reads with signature matching
  • FUN_CODE_14b9 -- Calibrated delay function using CPUCS clock divider awareness

FW2 only:

  • FUN_CODE_0ffc -- Stores a parameter into BANK3_R1 (register save)
  • FUN_CODE_1288 -- New hardware initialization (loads from external memory at e080-e08e)

FW3 only:

  • FUN_CODE_0706 -- Memory write dispatcher that handles 3 addressing modes (XDATA, IDATA, direct)
  • FUN_CODE_1288 -- Same as FW2
  • Uses FUN_CODE_1ffc (at a different address from FW2's 0x1ffd)

2. Main Entry Comparison (CODE:170D)

Identical Across All Three:

  • IRAM clear loop (0x7F down to 0x00)
  • Init table parsing from CODE:0B88
  • Bit config table reference at CODE:1740
  • Final call to FUN_CODE_0800

One Key Difference -- Stack Pointer:

Variant SP Value
FW1 SP = 0x50
FW2 SP = 0x50
FW3 SP = 0x52

FW3 sets SP = 0x52, requiring 2 more bytes of IRAM for stack usage. This indicates FW3 uses additional internal RAM locations (0x51-0x52) for state variables that FW1/FW2 don't need, pushing the stack higher.

Confirmed: FW3 uses DAT_INTMEM_51 as a hardware status register throughout its code, while FW1/FW2 use DAT_INTMEM_4f for the same purpose. The 2-byte difference in SP exactly accounts for this.

Memory at CODE:170D:

FW1: 787f e4f6 d8fd 7581 50 02 1754 020800 e4
FW2: 787f e4f6 d8fd 7581 50 02 1754 020800 e4  (identical to FW1)
FW3: 787f e4f6 d8fd 7581 52 02 1754 020800 e4  (byte at 0x1714 = 0x52 vs 0x50)

3. Key Function Decompilation Comparison

3.1 FUN_CODE_0800 (Main Loop) -- All at Same Address

Structure identical across all three:

  1. Clear INTMEM locations 0x22-0x2D, 0x32-0x35
  2. Clear bit flags _1_0 and _0_6
  3. Call hardware init (address differs)
  4. Set up BANK register pairs (XDATA pointers): all use the same values (0x0E00, 0x0E12, 0x0E1C, 0x0E54, 0x0E8C, 0x0EE8)
  5. Call FUN_CODE_072a with init params
  6. Memory copy loop (0x80 bytes at offset 0x0E00)
  7. Retry loop with FUN_CODE_1799 (20 attempts)
  8. Retry loop with EEPROM checksum function (20 attempts)
  9. Check demod type byte at offset +10 from BANK1_R4/R5 (== 0x03 -> set flag)
  10. Enable interrupts, enter main event loop

Differences in called function addresses (relocated, not functionally different):

Call Purpose FW1 FW2 FW3
Hardware init FUN_CODE_11ab FUN_CODE_1288 FUN_CODE_1288
EEPROM checksum FUN_CODE_1ca0 FUN_CODE_1cff FUN_CODE_1ca1
USB setup FUN_CODE_2031 FUN_CODE_206c FUN_CODE_206c
Main loop poll FUN_CODE_21ec FUN_CODE_2227 FUN_CODE_2227
Interrupt check FUN_CODE_2445 FUN_CODE_247c FUN_CODE_2473
Status check FUN_CODE_2189 FUN_CODE_21c4 FUN_CODE_21c4
Buffer flush FUN_CODE_20b9 FUN_CODE_20f4 FUN_CODE_20f4
EP complete FUN_CODE_2447 FUN_CODE_247e FUN_CODE_2475

3.2 Hardware Init Function (FW1: 0x11ab, FW2/FW3: 0x1288)

Functionally identical across all three except:

Parameter FW1 FW2 FW3
P0 init value 0xa4 0xa4 0xa0
Status register DAT_INTMEM_4f DAT_INTMEM_4f DAT_INTMEM_51
Sub-init call 1 FUN_CODE_1c44 FUN_CODE_1ca3 FUN_CODE_1c45
Sub-init call 2 FUN_CODE_1000 FUN_CODE_10dd FUN_CODE_10dd
I2C/bus init FUN_CODE_213b FUN_CODE_2176 FUN_CODE_2176
Tuner init FUN_CODE_1be6 FUN_CODE_1c45 FUN_CODE_1cf7

P0 = 0xa4 vs 0xa0: P0 on the FX2 controls GPIO port 0. The difference is bit 2:

  • FW1/FW2: P0 bit 2 = 1 (0xa4 = 1010 0100)
  • FW3: P0 bit 2 = 0 (0xa0 = 1010 0000)

This suggests different default GPIO state for a control signal, likely related to the demodulator interface mode or reset polarity.

3.3 FUN_CODE_0eea -- The Most Revealing Difference

FW1: This is a standard I2C master transfer function:

  • Uses FUN_CODE_23ae (I2C START), FUN_CODE_23ee (I2C byte write), FUN_CODE_23d0 (I2C address)
  • Reads back via FUN_CODE_2164
  • Standard I2C retry with NACK detection

FW2: This is a parallel bus read with demodulator handshake:

  • Reads demod type from address table (BANK1_R4/R5 + offset)
  • Uses FUN_CODE_11b6 for demod selection
  • Toggles P0 bits 6/7 for bus control (P0.6 = chip select, P0.7 = read strobe)
  • Reads data from P1 port (parallel data bus)
  • Checks P1 ^ 0x1D (signature) then reads P1 for device ID
  • Matches device IDs: 0xC5/0xD5 (for type 3), 0x5A (type 4), 0x5B (type 5), 0x5C (type 6)
  • Controls P3 bits for demod power/reset

FW3: Similar parallel bus read as FW2 but with different timing and bus protocol:

  • Sets P0 | 0x80 once at start (not per-iteration like FW2)
  • Uses DAT_INTMEM_3f and DAT_INTMEM_40 as OR-accumulators for P1 reads
  • Two separate P1 reads per cycle: one with P0.6 high, one with P0.6 low
  • Calls FUN_CODE_1b2a with 3 parameters (accumulated OR values) vs FW2's 2 parameters
  • Uses P0 | 0x44 and P0 & 0xBF toggle pattern (vs FW2's different bit dance)

3.4 Vendor Command Handler (FUN_CODE_034e)

Structurally identical across all three -- same switch/case table structure at CODE:035e.

Key differences:

Feature FW1 FW2 FW3
Case 0x35f/0x427 call FUN_CODE_0ffe (nop) FUN_CODE_1ffd FUN_CODE_0ffe (nop)
Case 0x361 call FUN_CODE_2441 FUN_CODE_2478 FUN_CODE_246f
Case 0x365 call FUN_CODE_2443 FUN_CODE_247a FUN_CODE_2471
Case 0x36f call FUN_CODE_2357 FUN_CODE_2392 FUN_CODE_2392
Case 0x371 call FUN_CODE_243d FUN_CODE_0ffc FUN_CODE_1ffc
Case 0x373/0x3ff call FUN_CODE_2309 FUN_CODE_2344 FUN_CODE_2344
Case 0xf0 indirect call func_0x231e func_0x2359 func_0x2359
Case 0x39d return func_0x06e4 DAT=0x0 DAT=0x0
Case 0x3d1 call FUN_CODE_2110 FUN_CODE_214b FUN_CODE_214b
Case 0x3d3 behavior TR2 timer check OR operation OR operation
Case 0x405 behavior Goto LAB_05db Conditional branch Conditional branch
Case 0x421 behavior Simple check Extra P2_1, RL A logic Extra P2_1, RL A logic

FW1's unique case 0x3d3: Checks Timer 2 Run flag (TR2) -- this is used for I2C bus timeout recovery, consistent with FW1 being I2C-based.

FW2/FW3's unique case 0x421-0x423: Includes a rotate-left and P2.1 write -- this is a parallel bus data direction control, consistent with the external demodulator interface.


4. Memory Comparison at Key Offsets

CODE:0000-0x000F (Reset Vector)

FW1: 02170d 753728 e53760 1b7ffc 7e7f12 22
FW2: 02170d 753728 e53760 1b7ffc 7e7f12 22
FW3: 02170d 753728 e53760 1b7ffc 7e7f12 22
ALL IDENTICAL -- LJMP 0x170D, then INT0 vector handler

CODE:0B88-0x0B9F (Init Table Start)

FW1: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000
FW2: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000
FW3: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000
ALL IDENTICAL -- Same register/SFR initialization table

CODE:1500 (Thunk/INT Vector Target)

FW1: 02 2252 00 02 22dd 00 02 22c7 00 02 226a 00
FW2: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00
FW3: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00

FW1 jumps to different addresses than FW2/FW3. FW2 and FW3 are IDENTICAL here -- their interrupt handlers are at the same addresses.

CODE:1740-0x174F (Bit Config Table)

FW1: 4004 f456 8001 46f6 dfe4 800b 0102 0408
FW2: 4004 f456 8001 46f6 dfe4 800b 0102 0408
FW3: 4004 f456 8001 46f6 dfe4 800b 0102 0408
ALL IDENTICAL -- Same bit manipulation lookup table

CODE:0800 (Main Loop Start)

FW1: e4f52d...c208c206 12 11ab 750c0e...
FW2: e4f52d...c208c206 12 1288 750c0e...
FW3: e4f52d...c208c206 12 1288 750c0e...

Only difference: the LCALL target (FW1: 0x11ab, FW2/FW3: 0x1288).

CODE:06D9 (Utility Functions)

FW1: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622
FW2: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622
FW3: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622
ALL IDENTICAL -- Generic memory access utilities shared by all

CODE:0EEA (Critical Divergence Point)

FW1: 8f44 8c45 8d46 8b47 754a14 e544 b451...  (I2C transfer params in registers)
FW2: 753e14 e50d 240a f582 e435 0cf5 83e0...  (reads from DPTR+offset table)
FW3: 753e14 e4f5 3ff5 40 e50d 240a f582...    (similar to FW2 + accumulator init)

This confirms: FW1's FUN_CODE_0eea is a completely different function (I2C master) than FW2/FW3's (parallel bus demod interface).


5. FW2 vs FW3 Specific Differences

FW2 and FW3 are the most similar pair (1,525 bytes different). Key differences:

Feature FW2 FW3
Stack Pointer SP = 0x50 SP = 0x52
Status register DAT_INTMEM_4f DAT_INTMEM_51
P0 init 0xa4 0xa0 (bit 2 different)
FUN_CODE_0eea bus protocol Single-phase P1 read Dual-phase P1 read with OR accumulation
I2C buffer addresses DAT_INTMEM_48/49 DAT_INTMEM_4a/4b
Unique function FUN_CODE_0ffc (register store) FUN_CODE_0706 (multi-mode write)
P0 bus timing P0 &= ~0x40; P0 = 0x80 per iteration
Delay function address FUN_CODE_1e92 FUN_CODE_1e88

The P1 Read Difference is Critical

FW2 reads P1 once per bus cycle:

uVar1 = P1;  // Read with one bus state
P0 |= 0x40;  // Then change control line
uVar2 = P1;  // Read again
FUN_CODE_1b2a(uVar2, uVar1);  // Process both samples

FW3 reads P1 in two phases and OR-accumulates:

DAT_INTMEM_3f = 0; DAT_INTMEM_40 = 0;  // Clear accumulators
// Phase 1: P0.6 high
P0 |= 0x44;
bVar2 = P1;
DAT_INTMEM_3f |= bVar2;  // OR-accumulate
// Phase 2: P0.6 low
P0 &= ~0x40;
bVar2 = P1;
DAT_INTMEM_40 |= bVar2;  // OR-accumulate
FUN_CODE_1b2a(0, DAT_INTMEM_3f, DAT_INTMEM_40);  // Process accumulated

This OR-accumulation pattern in FW3 suggests dealing with a bus that may have metastable signals or requires multiple samples, characteristic of a different demodulator chip with different bus timing.


6. Hypothesis: What Distinguishes Each Variant

FW1 (v2.13.1) -- Original I2C-Connected Demodulator Hardware

Target: First-generation SkyWalker-1 PCB with an I2C-connected demodulator (likely a Conexant/Zarlink integrated tuner+demod).

Evidence:

  • Uses standard I2C protocol functions (START, STOP, ACK/NACK, byte read/write)
  • FUN_CODE_0fc7: I2C write retry loop
  • FUN_CODE_1405: Reads demodulator identification via I2C + P1 GPIO, checks device signatures:
    • Type 3: P1 == 0xA5 or 0xB5
    • Type 4: P1 == 0x5A
    • Type 5: P1 == 0x5B
    • Type 6: P1 == 0x5C
  • Has timer-based I2C timeout (TR2 check in vendor handler)
  • SP=0x50, fewer IRAM state variables needed
  • func_0x06e4 called for unknown vendor commands (older error path)

Likely demodulator: An I2C-bus demodulator supporting DVB-S/DCII/DSS, with the FX2 as USB bridge. The type codes 3-6 likely correspond to different supported modulation modes or demod silicon revisions.

FW2 (v2.13.2) -- Second-Generation Parallel-Bus Demodulator

Target: Revised SkyWalker-1 PCB with a parallel-bus connected demodulator (likely a different demod chip or a custom FPGA/ASIC).

Evidence:

  • FUN_CODE_0eea: Parallel bus read using P0 GPIO for control (CS, RD strobe) and P1 for data
  • FUN_CODE_10dd: Copies configuration from external memory (e080-e08e) into demod registers (e6c0-e6cd) -- reads 15 configuration bytes from what appears to be EEPROM/flash config area
  • Reads same device signatures but via parallel bus (P1 ^ 0x1D check, then P1 reads for 0xC5/0xD5/0x5A/0x5B/0x5C)
  • P0 = 0xa4 (bit 2 set = specific bus mode select)
  • SP = 0x50
  • Extra vendor command paths for parallel data direction (P2.1 control in case 0x421/0x423)
  • Uses FUN_CODE_14e2: Busy-wait on e678 bit 6 (demod ready flag) with 0xFFFF timeout counter

Likely demodulator: A parallel-bus demodulator with 8-bit data port on P1, active-low chip select and read strobe on P0. The external config block (e080-e08e) stores per-unit calibration/tuning data.

FW3 (v2.13.3) -- Third-Generation with Enhanced Bus Protocol

Target: Further revised PCB with the same parallel-bus demodulator as FW2 but with a different bus interface revision or a variant chip that requires modified timing.

Evidence:

  • Same demod configuration loading as FW2 (FUN_CODE_10dd identical)
  • Same parallel bus architecture but with dual-phase reading and OR-accumulation
  • P0 = 0xa0 (bit 2 clear = different bus mode or reset polarity)
  • SP = 0x52 (2 more IRAM bytes: status register moved from 0x4F to 0x51)
  • FUN_CODE_0706 (unique): Multi-mode memory write supporting XDATA, IDATA, and direct addressing -- suggests the demod communicates through multiple address spaces
  • The OR-accumulation of P1 reads suggests either:
    • A demodulator with open-drain outputs requiring multiple read cycles
    • Bus settling time issues on the newer PCB layout
    • A chip variant that serializes data across multiple bus phases

7. Summary Table

Aspect FW1 (v2.13.1) FW2 (v2.13.2) FW3 (v2.13.3)
Demod interface I2C bus Parallel bus (P0/P1) Parallel bus (enhanced)
Bus protocol I2C START/STOP/ACK Single-phase P1 read Dual-phase P1 read + OR accumulate
Stack pointer 0x50 0x50 0x52
P0 init 0xa4 0xa4 0xa0
Status register INTMEM 0x4F INTMEM 0x4F INTMEM 0x51
Config source Hardcoded External (e080-e08e) External (e080-e08e)
Demod types supported 3-6 (via I2C) 3-6 (via parallel) 3-6 (via parallel)
Binary distance from FW1 -- 3,993 bytes 3,789 bytes
Binary distance from FW2 3,993 bytes -- 1,525 bytes

8. Conclusion

The three v2.13 firmware sub-variants represent an evolutionary progression of the SkyWalker-1 hardware:

  1. v2.13.1 (FW1): Original design with I2C-connected demodulator. The FX2 communicates with the demod entirely through I2C, using standard master-mode transactions. This is the simplest interface but limited in bandwidth.

  2. v2.13.2 (FW2): Redesigned with a parallel-bus demodulator. The demod data port is connected directly to FX2's P1, with P0 bits used for bus control signals (chip select, read/write strobes). Configuration data is loaded from an external EEPROM area. This provides higher throughput for TS data transfer.

  3. v2.13.3 (FW3): Refinement of the FW2 design, likely for a newer demod silicon revision or PCB layout. Uses dual-phase bus reads with signal accumulation, different GPIO defaults, and additional IRAM for state tracking. The OR-accumulation pattern suggests dealing with bus signal integrity improvements.

The updater program's format string "FW 2.13.%i" and its selection logic presumably check the hardware revision (likely via a GPIO strap or I2C ID read) to determine which of the three firmware images to flash.

All three variants support the same modulation types (DVB-S/QPSK, Turbo QPSK/8PSK, DCII, DSS) -- the demod type codes 3-6 appear in all variants. The differences are purely about the hardware interface, not the feature set.