Diagnosed from the user's console output - 25 chunks pushed cleanly at ~124ms each, then stalled. Two coupled causes: 1) Bus contention. tick() and Live sync share self.midi with the chunk ACKs. While the device was processing a chunk, a Note On / Clock Out / Live-sync FULL heartbeat could land on the same MIDI OUT stream and the host's parser dropped the interleaved ACK SysEx. Fix: self._fw_pushing flag set on 0x21 BEGIN, cleared on 0x23 COMMIT or any error. midi_send / Clock Out / _sync_broadcast / _sync_broadcast_full all early-out when _fw_pushing is True. Only ACKs go out during a push. 2) SysEx assembler garbage. self._sx = bytearray() per chunk leaks ~70 bytes / chunk that only GC'd every 50 chunks. 25 chunks of trash plus a slow heap walked the wrong way explains the ramp-up to 174 -> 119 -> 124 ms ACK times. GC every chunk now (~30ms cost on RP2040/RP2350 with small heap) so the assembler buffer is always fresh. Same patch on both pico-cp/ and pico-explorer/ since the bug is identical. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
66 lines
3.1 KiB
Python
66 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""PM_K-1 RTC (SKiDL): RV-8803-C7 I2C real-time clock for the practice-log timestamps.
|
|
|
|
Run INSIDE the EDA container:
|
|
cd hardware/eda && ./run.sh python3 ../eda/circuits/rtc.py
|
|
Outputs ERC + hardware/kicad/rtc.net.
|
|
|
|
VERIFIED pinout (Micro Crystal RV-8803-C7, 8-WCDFN 3.2x1.5mm):
|
|
1=SDA 2=CLKOUT 3=VDD 4=CLKOE 5=VSS 6=/INT 7=EVI 8=SCL. Single VDD (no separate VBACKUP
|
|
pin); ~240nA typ. Shares the touch I2C bus (SDA=GPIO8, SCL=GPIO9).
|
|
|
|
BACKUP: diode-OR -- system +3V3 OR the CR2032 feed VDD_RTC through Schottkys, so the
|
|
board runs the RTC off 3V3 when on, the coin cell only when off, and (importantly for an
|
|
heirloom) the cell can be replaced WITHOUT the RTC losing time. Schottkys block charging
|
|
the (non-rechargeable) cell.
|
|
|
|
Unused pins: CLKOE->GND (CLKOUT disabled), CLKOUT->NC, EVI->GND (no event input),
|
|
/INT pulled up + routed to RTC_INT (optional alarm IRQ to a GPIO).
|
|
CONFIRM at layout: the RV-8803-C7 footprint, and cross-check the App Manual's recommended
|
|
backup circuit.
|
|
"""
|
|
import os
|
|
from skidl import *
|
|
set_default_tool(KICAD9)
|
|
P = Pin.types
|
|
R = Part("Device","R", dest=TEMPLATE, footprint="Resistor_SMD:R_0402_1005Metric")
|
|
def C(v): return Part("Device","C", value=v, footprint="Capacitor_SMD:C_0402_1005Metric")
|
|
DS = Part("Device","D_Schottky", dest=TEMPLATE, footprint="Diode_SMD:D_SOD-323")
|
|
|
|
p3v3, gnd = Net("+3V3"), Net("GND")
|
|
p3v3.drive = POWER; gnd.drive = POWER
|
|
i2c_sda, i2c_scl = Net("I2C_SDA"), Net("I2C_SCL") # shared bus (RP2350 GPIO8/9 + touch)
|
|
vdd_rtc, rtc_int = Net("VDD_RTC"), Net("RTC_INT")
|
|
|
|
RV8803 = Part(name="RV-8803-C7", tool=SKIDL, dest=TEMPLATE, ref_prefix="U",
|
|
footprint="RTC_MicroCrystal:RV-8803-C7", # footprint: confirm at layout
|
|
pins=[Pin(num=1,name="SDA",func=P.BIDIR),Pin(num=2,name="CLKOUT",func=P.OUTPUT),
|
|
Pin(num=3,name="VDD",func=P.PWRIN),Pin(num=4,name="CLKOE",func=P.INPUT),
|
|
Pin(num=5,name="VSS",func=P.PWRIN),Pin(num=6,name="INT",func=P.OPENCOLL),
|
|
Pin(num=7,name="EVI",func=P.INPUT),Pin(num=8,name="SCL",func=P.INPUT)])
|
|
u = RV8803(ref="U7")
|
|
|
|
u["VDD"] += vdd_rtc; u["VSS"] += gnd
|
|
u["SDA"] += i2c_sda; u["SCL"] += i2c_scl
|
|
u["CLKOE"] += gnd # disable CLKOUT
|
|
u["EVI"] += gnd # unused event input
|
|
u["INT"] += rtc_int # open-drain alarm (optional)
|
|
# CLKOUT left unconnected
|
|
|
|
# diode-OR backup: 3V3 -> D1 -> VDD_RTC ; CR2032 -> D2 -> VDD_RTC
|
|
d1, d2 = DS(value="BAT54"), DS(value="BAT54")
|
|
p3v3 += d1[2]; d1[1] += vdd_rtc # D_Schottky pin1=K, pin2=A : anode at 3V3, cathode at VDD_RTC
|
|
bt = Part("Device","Battery_Cell", value="CR2032",
|
|
footprint="Battery:BatteryHolder_Keystone_1066_1x2032", ref="BT1")
|
|
bt["+"] += d2[2]; d2[1] += vdd_rtc; bt["-"] += gnd
|
|
crtc = C("100nF"); vdd_rtc += crtc[1]; crtc[2] += gnd
|
|
|
|
# I2C pull-ups (bus shared with touch) + /INT pull-up, to 3V3
|
|
for net in (i2c_sda, i2c_scl):
|
|
r = R(value="4.7k"); net += r[1]; r[2] += p3v3
|
|
rint = R(value="10k"); rtc_int += rint[1]; rint[2] += p3v3
|
|
|
|
ERC()
|
|
out = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "kicad", "rtc.net"))
|
|
generate_netlist(file_=out)
|
|
print("RTC netlist ->", out)
|