#!/usr/bin/env python3 """Clock EXACTLY the requested byte count, the way the GC driver does.""" import time, collections import RPi.GPIO as GPIO CLK, MOSI, MISO, CS = 11, 10, 9, 8 GPIO.setmode(GPIO.BCM); GPIO.setwarnings(False) GPIO.setup(CLK, GPIO.OUT, initial=1); GPIO.setup(MOSI, GPIO.OUT, initial=0) GPIO.setup(CS, GPIO.OUT, initial=1); GPIO.setup(MISO, GPIO.IN) def xfer(b): r = 0 for i in range(7, -1, -1): GPIO.output(MOSI, (b >> i) & 1) GPIO.output(CLK, 0) r = (r << 1) | GPIO.input(MISO) GPIO.output(CLK, 1) return r def read(addr, n, gap=0.005, idle=0.010): GPIO.output(CS, 0); GPIO.output(CLK, 1); time.sleep(0.0005) xfer((addr >> 6) & 0x7F); xfer(((addr & 0x3F) << 2) | ((n - 1) & 3)) time.sleep(gap) out = [xfer(0x00) for _ in range(n)] # EXACTLY n bytes, no more GPIO.output(CS, 1); time.sleep(idle) return out def trial(tag, addr, n, want, reps=21, idle=0.010): hits = collections.Counter(); ok = 0 seq = [] for _ in range(reps): r = read(addr, n, idle=idle) hits[" ".join("%02x" % x for x in r)] += 1 good = r == want ok += good seq.append("." if good else "x") print(f" {tag:<34} {ok:>2}/{reps} {''.join(seq)}") for pat, cnt in hits.most_common(3): print(f" {cnt:>3}x {pat}") print("=== exact-length reads, 10ms idle between transactions ===") trial("device ID @0x0000 (4B)", 0x0000, 4, [0x04, 0x02, 0x02, 0x00]) trial("NWAYS @0x31 (1B)", 0x31, 1, [0x17]) trial("HIPR @0x3A (1B)", 0x3A, 1, [0x01]) print() print("=== same, but 200ms idle (does state decay?) ===") trial("device ID @0x0000 (4B)", 0x0000, 4, [0x04, 0x02, 0x02, 0x00], reps=9, idle=0.200) GPIO.cleanup()