e67fb754c2
Session kxkm-ai 25-26 mars 2026 — 98/98 tâches TODO complétées. Hardware: - KiCad 10.0.0 native avec sym/fp-lib-table locales - Nouveau block SPI (gen_spi_header.py), ERC clean - Module partagé hardware/lib/kicad_gen.py (5 générateurs refactorisés) - Pipeline export: tools/hw/hw_export.sh (ERC + SVG + PDF + netlist) - KiBot 1.8.5 installé, .kibot.yaml configuré Firmware: - Fix I2S driver conflict: migration I2sMic vers nouvelle API i2s_channel_* - Fix WDT risk: yield() dans CompletePushToTalk (voice_controller.cpp) - Fix XSS wifi_manager.cpp: innerHTML → createElement/textContent - Fix null check FwIsValidWavHeader - Dead code supprimé: i2s_audio.cpp.bak, i2s_audio.h Simulation MCU: - QEMU ESP32-S3 v9.2.2 installé (tools/sim/) - Script run_qemu_esp32s3.sh — boot OK vérifié - [env:esp32s3_qemu] dans platformio.ini - Wokwi CI: wokwi.toml + diagram.json + scenario.yaml - SPICE bridge POC: tools/sim/spice_bridge.py (ngspice → ADC/brownout) Compliance: - Profil iot_wifi_eu validé (16 standards, 8 evidence) - 4 evidence remplis: risk_assessment, security_architecture, test_plan_radio_emc, supply_chain_declarations - plan.yaml complété avec données produit réelles CI: - Job hardware-export (KiCad 10 ERC + SVG + PDF + netlist) - Job firmware-sim (Wokwi, conditionnel WOKWI_CLI_TOKEN) - evidence_pack.yml enrichi avec exports hardware Docs & RAG: - specs/02_arch.md complet (481 lignes, 4 ADR, diagrammes) - docs/SIMULATION.md (3 niveaux: native, QEMU, Wokwi) - 6 chunks ingérés dans kb-kicad RAG - Dataset HF: tools/generate_hf_dataset.py + datasets/kb_kicad_qa.jsonl - Rapport analyse: docs/plans/ANALYSIS_REPORT_2026-03-25.md - Recherche OSS: docs/research/oss_similar_projects.md Infra: - ZeroClaw 0.1.7 installé (cargo install) - APIFY_API_KEY configurée, smoke OK - Tests: 39/39 firmware + 26/26 Python stable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
166 lines
6.4 KiB
Python
166 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate i2s_dac.kicad_sch for KiCad 10 — ERC-clean.
|
|
|
|
Block: I2S DAC interface connector (Conn_01x06_Pin)
|
|
Pin 1: GND
|
|
Pin 2: +3V3 (net label)
|
|
Pin 3: I2S_BCK (net label)
|
|
Pin 4: I2S_WS (net label)
|
|
Pin 5: I2S_DOUT (net label)
|
|
Pin 6: I2S_DIN (net label)
|
|
|
|
Connector pin connection points (Conn_01x06_Pin, angle=0):
|
|
Pin "at" position in lib space IS the net node (not the visual tip).
|
|
Pin 1: at lib (5.08, 5.08, 180) → screen (SX+5.08, SY-5.08)
|
|
Pin 2: at lib (5.08, 2.54, 180) → screen (SX+5.08, SY-2.54)
|
|
Pin 3: at lib (5.08, 0.00, 180) → screen (SX+5.08, SY)
|
|
Pin 4: at lib (5.08, -2.54, 180) → screen (SX+5.08, SY+2.54)
|
|
Pin 5: at lib (5.08, -5.08, 180) → screen (SX+5.08, SY+5.08)
|
|
Pin 6: at lib (5.08, -7.62, 180) → screen (SX+5.08, SY+7.62)
|
|
|
|
All placements at multiples of 1.27 mm.
|
|
"""
|
|
|
|
import sys
|
|
import pathlib
|
|
|
|
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "lib"))
|
|
from kicad_gen import (gen_uuid, pin_screen, extract_symbol, lib_sym_entry,
|
|
prop, sym_inst, power_sym, no_connect, text, net_lbl,
|
|
SYMLIB)
|
|
|
|
|
|
# ── Build schematic ──────────────────────────────────────────────────────────
|
|
|
|
def build(output: pathlib.Path):
|
|
print("Extracting symbols from KiCad 10 libraries...")
|
|
|
|
lib_symbols_entries = [
|
|
lib_sym_entry("power", "GND"),
|
|
lib_sym_entry("power", "PWR_FLAG"),
|
|
lib_sym_entry("Connector", "Conn_01x06_Pin"),
|
|
]
|
|
print(f" Extracted {len(lib_symbols_entries)} symbols.")
|
|
lib_symbols_block = "\t(lib_symbols\n" + "\n".join(lib_symbols_entries) + "\n\t)"
|
|
|
|
placements = []
|
|
pwr_syms = []
|
|
labels = []
|
|
pwr_n = [1]
|
|
|
|
def next_pwr():
|
|
n = pwr_n[0]
|
|
pwr_n[0] += 1
|
|
return n
|
|
|
|
placed_pwr_keys = set()
|
|
|
|
def add_pwr(lib_id, x, y):
|
|
key = (lib_id, round(x, 3), round(y, 3))
|
|
if key not in placed_pwr_keys:
|
|
placed_pwr_keys.add(key)
|
|
pwr_syms.append(power_sym(lib_id, x, y, next_pwr()))
|
|
|
|
# ── J1: Conn_01x06_Pin at (30.48, 63.50) ─────────────────────────────────
|
|
# Conn_01x06_Pin: 6 pins, all exit right side at x_lib=1.27, angle=0
|
|
# Pin 1 tip: lib (1.27, 5.08) → screen (SX+1.27, SY-5.08)
|
|
# Pin 2 tip: lib (1.27, 2.54) → screen (SX+1.27, SY-2.54)
|
|
# Pin 3 tip: lib (1.27, 0.00) → screen (SX+1.27, SY)
|
|
# Pin 4 tip: lib (1.27, -2.54) → screen (SX+1.27, SY+2.54)
|
|
# Pin 5 tip: lib (1.27, -5.08) → screen (SX+1.27, SY+5.08)
|
|
# Pin 6 tip: lib (1.27, -7.62) → screen (SX+1.27, SY+7.62)
|
|
J1X, J1Y = 30.48, 63.50
|
|
placements.append(sym_inst(
|
|
lib_id="Connector:Conn_01x06_Pin",
|
|
x=J1X, y=J1Y, angle=0,
|
|
ref="J1", value="I2S DAC",
|
|
footprint="Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical",
|
|
datasheet="~",
|
|
props_extra={"Pitch": "2.54mm", "Interface": "I2S"},
|
|
pin_numbers=["1", "2", "3", "4", "5", "6"],
|
|
))
|
|
|
|
# Connection points for Conn_01x06_Pin:
|
|
# In KiCad, the pin "at" position IS the electrical connection point.
|
|
# Library definition: (at 5.08, Y, 180)(length 3.81)
|
|
# The "at" coord (5.08, Y) in lib space is the net node.
|
|
# pin_screen(SX, SY, angle, 5.08, Y_lib) gives the screen connection point.
|
|
# Pin 1: at lib (5.08, 5.08, 180) → screen (SX+5.08, SY-5.08)
|
|
# Pin 2: at lib (5.08, 2.54, 180) → screen (SX+5.08, SY-2.54)
|
|
# Pin 3: at lib (5.08, 0.00, 180) → screen (SX+5.08, SY)
|
|
# Pin 4: at lib (5.08, -2.54, 180) → screen (SX+5.08, SY+2.54)
|
|
# Pin 5: at lib (5.08, -5.08, 180) → screen (SX+5.08, SY+5.08)
|
|
# Pin 6: at lib (5.08, -7.62, 180) → screen (SX+5.08, SY+7.62)
|
|
p1x, p1y = pin_screen(J1X, J1Y, 0, 5.08, 5.08) # Pin 1: GND
|
|
p2x, p2y = pin_screen(J1X, J1Y, 0, 5.08, 2.54) # Pin 2: +3V3
|
|
p3x, p3y = pin_screen(J1X, J1Y, 0, 5.08, 0.00) # Pin 3: I2S_BCK
|
|
p4x, p4y = pin_screen(J1X, J1Y, 0, 5.08, -2.54) # Pin 4: I2S_WS
|
|
p5x, p5y = pin_screen(J1X, J1Y, 0, 5.08, -5.08) # Pin 5: I2S_DOUT
|
|
p6x, p6y = pin_screen(J1X, J1Y, 0, 5.08, -7.62) # Pin 6: I2S_DIN
|
|
|
|
print(f"\nPin endpoints (screen coords, all on 1.27mm grid):")
|
|
print(f" J1 Pin 1 (GND) : ({p1x}, {p1y})")
|
|
print(f" J1 Pin 2 (+3V3) : ({p2x}, {p2y})")
|
|
print(f" J1 Pin 3 (I2S_BCK) : ({p3x}, {p3y})")
|
|
print(f" J1 Pin 4 (I2S_WS) : ({p4x}, {p4y})")
|
|
print(f" J1 Pin 5 (I2S_DOUT) : ({p5x}, {p5y})")
|
|
print(f" J1 Pin 6 (I2S_DIN) : ({p6x}, {p6y})")
|
|
|
|
# Pin 1: GND power symbol
|
|
add_pwr("power:GND", p1x, p1y)
|
|
# Add PWR_FLAG for GND net
|
|
add_pwr("power:PWR_FLAG", p1x, p1y)
|
|
|
|
# Pin 2: +3V3 net label (passive connector — net label connects to rail in parent)
|
|
labels.append(net_lbl("+3V3", p2x, p2y, 0))
|
|
|
|
# Pins 3-6: I2S signal net labels
|
|
labels.append(net_lbl("I2S_BCK", p3x, p3y, 0))
|
|
labels.append(net_lbl("I2S_WS", p4x, p4y, 0))
|
|
labels.append(net_lbl("I2S_DOUT", p5x, p5y, 0))
|
|
labels.append(net_lbl("I2S_DIN", p6x, p6y, 0))
|
|
|
|
annotations = [
|
|
text("Kill_LIFE I2S DAC Interface Block (6-pin 2.54mm)", 10, 6, size=1.5),
|
|
text("Pin 1: GND | Pin 2: +3V3 | Pin 3: I2S_BCK | Pin 4: I2S_WS", 10, 10, size=1.0),
|
|
text("Pin 5: I2S_DOUT (DAC data out) | Pin 6: I2S_DIN (ADC data in)", 10, 13, size=1.0),
|
|
text("Footprint: PinHeader_1x06_P2.54mm_Vertical", 10, 16, size=1.0),
|
|
]
|
|
|
|
all_elements = placements + pwr_syms + labels + annotations
|
|
body = "\n".join(all_elements)
|
|
|
|
sch = f"""(kicad_sch
|
|
\t(version 20260101)
|
|
\t(generator "kill_life_gen")
|
|
\t(generator_version "10.0")
|
|
\t(uuid "{gen_uuid()}")
|
|
\t(paper "A4")
|
|
\t(title_block
|
|
\t\t(title "Kill_LIFE I2S DAC Interface Block")
|
|
\t\t(date "2026-03-25")
|
|
\t\t(rev "1.0")
|
|
\t\t(company "Kill_LIFE")
|
|
\t\t(comment 1 "6-pin 2.54mm connector for I2S DAC/ADC interface")
|
|
\t\t(comment 2 "Pin 1 GND, Pin 2 +3V3, Pin 3 I2S_BCK, Pin 4 I2S_WS")
|
|
\t\t(comment 3 "Pin 5 I2S_DOUT (to DAC DIN), Pin 6 I2S_DIN (from ADC DOUT)")
|
|
\t)
|
|
{lib_symbols_block}
|
|
|
|
{body}
|
|
|
|
\t(sheet_instances
|
|
\t\t(path "/"
|
|
\t\t\t(page "1")
|
|
\t\t)
|
|
\t)
|
|
)
|
|
"""
|
|
output.write_text(sch)
|
|
print(f"\nWritten: {output} ({len(sch):,} bytes)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
out = pathlib.Path(sys.argv[1]) if len(sys.argv) > 1 else pathlib.Path("i2s_dac.kicad_sch")
|
|
build(out)
|