#!/usr/bin/env python3 """Quick boot test for PLL config firmware.""" import sys sys.path.insert(0, 'tools') from skywalker_lib import SkyWalker1 CMD_RAW_DEMOD_READ = 0xB1 CMD_I2C_SCAN = 0xB4 CMD_GET_PLL_DIAG = 0xBF sw = SkyWalker1() sw.open() print('=== SkyWalker-1 Custom Firmware Boot Test ===') print() # Check firmware version ver = sw.get_fw_version() print(f'Firmware version: {ver}') # Check config status cfg = sw.get_config() print(f'Config status: 0x{cfg:02X}') bits = [] if cfg & 0x01: bits.append('Started') if cfg & 0x02: bits.append('FW_Loaded') if cfg & 0x04: bits.append('Intersil') if cfg & 0x08: bits.append('DVBmode') if cfg & 0x10: bits.append('22kHz') if cfg & 0x20: bits.append('18V') if cfg & 0x40: bits.append('DCtuned') if cfg & 0x80: bits.append('Armed') print(f' Flags: {" | ".join(bits) if bits else "(none)"}') print() # Check last error before boot err = sw.get_last_error() print(f'Last error (pre-boot): 0x{err:02X}') print() # Boot the BCM4500 print('--- Booting BCM4500 ---') boot_result = sw.boot() print(f'Boot result: {boot_result}') cfg = sw.get_config() print(f'Config after boot: 0x{cfg:02X}') bits = [] if cfg & 0x01: bits.append('Started') if cfg & 0x02: bits.append('FW_Loaded') if cfg & 0x04: bits.append('Intersil') if cfg & 0x08: bits.append('DVBmode') if cfg & 0x10: bits.append('22kHz') if cfg & 0x20: bits.append('18V') if cfg & 0x40: bits.append('DCtuned') if cfg & 0x80: bits.append('Armed') print(f' Flags: {" | ".join(bits) if bits else "(none)"}') err = sw.get_last_error() ERR_NAMES = { 0x00: 'ERR_OK', 0x01: 'ERR_I2C_TIMEOUT', 0x02: 'ERR_I2C_NAK', 0x03: 'ERR_I2C_ARB_LOST', 0x04: 'ERR_BCM_NOT_READY (PLL config failed)', 0x05: 'ERR_BCM_TIMEOUT', } print(f'Last error after boot: 0x{err:02X} = {ERR_NAMES.get(err, "unknown")}') print() # PLL config diagnostics print('--- PLL Config Diagnostics ---') try: pd = sw._vendor_in(CMD_GET_PLL_DIAG, value=0, index=0, length=10) print(f' EEPROM present: {"YES" if pd[0] else "NO"}') print(f' First block count: 0x{pd[1]:02X}' + (' (sentinel=0, no PLL data!)' if pd[1] == 0 else (' (not reached)' if pd[1] == 0xFF else f' ({pd[1]} AB bytes)'))) print(f' Blocks written: {pd[2]}') print(f' Last A9 value: 0x{pd[3]:02X}' + (' (none)' if pd[3] == 0xFF else '')) print(f' Last AA value: 0x{pd[4]:02X}' + (' (none)' if pd[4] == 0xFF else '')) print(f' Last AB count: 0x{pd[5]:02X}' + (' (none)' if pd[5] == 0xFF else '')) print(f' Config mode exit: {"OK" if pd[6] == 1 else ("FAIL" if pd[6] == 0 else "not reached")}') print(f' Overall PLL result: {"SUCCESS" if pd[7] == 1 else "FAILED"}') print(f' Boot stage: 0x{pd[8]:02X}' + (' (all complete)' if pd[8] == 0xFF else f' (stopped at stage {pd[8]})')) print(f' Last error: 0x{pd[9]:02X}') except Exception as e: print(f' PLL diag failed: {e}') print() # I2C bus scan print('--- I2C Bus Scan ---') try: bitmap = sw._vendor_in(CMD_I2C_SCAN, value=0, index=0, length=16) found = [] for byte_idx in range(16): for bit_idx in range(8): if bitmap[byte_idx] & (1 << bit_idx): addr = byte_idx * 8 + bit_idx found.append(addr) labels = {0x08: 'BCM4500', 0x10: 'BCM3440', 0x51: 'EEPROM'} for addr in found: label = labels.get(addr, '') print(f' 0x{addr:02X} {label}') if not found: print(' (no devices found!)') except Exception as e: print(f' Scan failed: {e}') print() # Try reading signal print('--- Signal Check ---') try: sig = sw.signal_monitor() print(f'Signal monitor: {sig}') except Exception as e: print(f'Signal monitor failed: {e}') # Read BCM4500 direct registers via 0xB1 vendor command # wValue=register address, wIndex=1 for direct read mode print() print('--- BCM4500 Direct Register Reads ---') key_regs = [ (0xA0, 'CFG_MODE'), (0xA2, 'STATUS'), (0xA4, 'LOCK'), (0xA9, 'PLL_A9'), (0xAA, 'PLL_AA'), (0xAB, 'PLL_AB'), ] for reg, label in key_regs: try: data = sw._vendor_in(CMD_RAW_DEMOD_READ, value=reg, index=1, length=1) val = data[0] print(f' 0x{reg:02X} ({label:8s}): 0x{val:02X}') except Exception as e: print(f' 0x{reg:02X} ({label:8s}): FAILED ({e})') # Indirect register reads via 0xB1 with wIndex=0 (indirect mode) # wValue=page, wIndex=0. Only meaningful if the DSP core is running. print() print('--- BCM4500 Indirect Register Reads (DSP core test) ---') for page in [0x06, 0x07, 0x0F]: try: data = sw._vendor_in(CMD_RAW_DEMOD_READ, value=page, index=0, length=1) val = data[0] alive = ' << DSP responding' if val != 0 else '' print(f' Page 0x{page:02X}: 0x{val:02X}{alive}') except Exception as e: print(f' Page 0x{page:02X}: FAILED ({e})') # Cross-check: read key registers via 0xB5 (raw I2C, writes into EP0BUF directly) # This bypasses the 0xB1 handler's val variable entirely CMD_I2C_RAW_READ = 0xB5 BCM4500_ADDR = 0x08 print() print('--- Cross-check via 0xB5 Raw I2C Read (BCM4500 @ 0x08) ---') for reg, label in key_regs: try: data = sw._vendor_in(CMD_I2C_RAW_READ, value=BCM4500_ADDR, index=reg, length=1) val = data[0] tag = ' ** I2C FAIL (0xFF) **' if val == 0xFF else '' print(f' 0x{reg:02X} ({label:8s}): 0x{val:02X}{tag}') except Exception as e: print(f' 0x{reg:02X} ({label:8s}): FAILED ({e})') # Full register dump 0xA0-0xBF via 0xB5 raw I2C (ground truth) print() print('--- Full Direct Register Dump 0xA0-0xBF (via 0xB5 raw I2C) ---') for reg in range(0xA0, 0xC0): try: data = sw._vendor_in(CMD_I2C_RAW_READ, value=BCM4500_ADDR, index=reg, length=1) val = data[0] print(f' 0x{reg:02X}: 0x{val:02X}') except Exception as e: print(f' 0x{reg:02X}: FAIL') sw.close() print() print('=== Test Complete ===')