#!/usr/bin/env python3 """Deep verification: full register dump + indirect register test. Checks whether: 1. Direct registers (0xA0-0xBF) are truly all 0x02 or vary 2. Indirect registers respond (proves DSP core is running) 3. Signal monitoring works after boot 4. Boot with vs without FW download produces different indirect reg values """ import sys import time sys.path.insert(0, 'tools') from skywalker_lib import SkyWalker1 CMD_RAW_DEMOD_READ = 0xB1 CMD_I2C_RAW_READ = 0xB5 BCM4500_ADDR = 0x08 def full_direct_dump(sw, label): """Read all direct registers 0xA0-0xBF via raw I2C.""" print(f'\n --- {label}: Direct Register Dump 0xA0-0xBF ---') values = {} for reg in range(0xA0, 0xC0): try: data = sw._vendor_in(CMD_I2C_RAW_READ, value=BCM4500_ADDR, index=reg, length=1) values[reg] = data[0] except Exception: values[reg] = None # Print in 2 rows of 16 for base in [0xA0, 0xB0]: row = [] for reg in range(base, base + 16): v = values.get(reg) row.append(f'{v:02X}' if v is not None else '??') print(f' {base:02X}: {" ".join(row)}') unique = set(v for v in values.values() if v is not None) print(f' Unique values: {sorted(f"0x{v:02X}" for v in unique)}') return values def indirect_reg_test(sw, label): """Read indirect registers to test DSP core responsiveness. Uses 0xB1 with wIndex=0 (indirect mode): wValue=page.""" print(f'\n --- {label}: Indirect Register Test ---') # Key DSP pages: 0x00 (config), 0x06 (acq), 0x07 (AGC), # 0x0A (Viterbi), 0x0F (transport) pages = [0x00, 0x01, 0x06, 0x07, 0x0A, 0x0F, 0x10, 0x20] results = {} for page in pages: try: data = sw._vendor_in(CMD_RAW_DEMOD_READ, value=page, index=0, length=1) val = data[0] results[page] = val marker = ' << DSP alive!' if val != 0 else '' print(f' Page 0x{page:02X}: 0x{val:02X}{marker}') except Exception as e: results[page] = None print(f' Page 0x{page:02X}: FAILED ({e})') nonzero = sum(1 for v in results.values() if v and v != 0) print(f' Non-zero pages: {nonzero}/{len(pages)}') return results def boot_and_test(sw, flags, label): """Boot with given flags and run full diagnostics.""" print(f'\n{"="*60}') print(f'TEST: {label} (wIndex=0x{flags:02X})') print(f'{"="*60}') # Shutdown + wait sw._vendor_in(0x89, value=0, index=0, length=3) time.sleep(0.5) # Boot result = sw._vendor_in(0x89, value=1, index=flags, length=3) cfg, stage = result[0], result[1] bits = [] if cfg & 0x01: bits.append('Started') if cfg & 0x02: bits.append('FW_Loaded') print(f' Config: 0x{cfg:02X} ({" | ".join(bits) if bits else "none"})') print(f' Stage: 0x{stage:02X}' + (' (COMPLETE)' if stage == 0xFF else f' (at {stage})')) # Full register dumps direct = full_direct_dump(sw, label) indirect = indirect_reg_test(sw, label) # Wait and re-test indirect (DSP may need startup time) time.sleep(0.5) indirect2 = indirect_reg_test(sw, f'{label} +500ms') # Signal monitor print(f'\n --- Signal Monitor ---') try: sig = sw.signal_monitor() print(f' {sig}') except Exception as e: print(f' Failed: {e}') return direct, indirect, indirect2 def main(): sw = SkyWalker1() sw.open() print('=== BCM4500 Deep Boot Verification ===') print(f'Firmware: {sw.get_fw_version()}') # Test 1: Init blocks only (no FW download) d1, i1, i1b = boot_and_test(sw, 0x01, 'Init blocks only (skip FW download)') # Test 2: Full boot (FW download + init blocks) d2, i2, i2b = boot_and_test(sw, 0x00, 'Full boot (FW download + init blocks)') # Compare indirect registers between the two modes print(f'\n{"="*60}') print('COMPARISON: Indirect Registers (init-only vs full boot)') print('='*60) pages = [0x00, 0x01, 0x06, 0x07, 0x0A, 0x0F, 0x10, 0x20] for page in pages: v1 = i1b.get(page) v2 = i2b.get(page) v1s = f'0x{v1:02X}' if v1 is not None else '??' v2s = f'0x{v2:02X}' if v2 is not None else '??' diff = ' << DIFFERENT!' if v1 != v2 else '' print(f' Page 0x{page:02X}: init-only={v1s} full={v2s}{diff}') # Compare direct registers print(f'\nDirect register comparison (0xA0-0xBF):') diffs = [] for reg in range(0xA0, 0xC0): v1 = d1.get(reg) v2 = d2.get(reg) if v1 != v2: diffs.append(f' 0x{reg:02X}: init-only=0x{v1:02X} full=0x{v2:02X}') if diffs: print('\n'.join(diffs)) else: print(' No differences (all registers identical)') sw.close() print('\n=== Done ===') if __name__ == '__main__': main()