"""Update NPC-DATA-HW-ESP32 with sourced specs, test spec, impl code, and test code.""" import json import urllib.request API = "http://localhost:8100/api" # Auth login = urllib.request.Request(f"{API}/auth/login", data=json.dumps({"password": "what_is_this_2"}).encode(), headers={"Content-Type": "application/json"}) TOKEN = json.loads(urllib.request.urlopen(login).read())["token"] data = { "acceptance_criteria": """- 8 RMT channels (0-7), each independently configurable as TX or RX - RMT RAM: 512 x 32-bit words shared across all 8 channels - Default: 1 memory block (64 x 32-bit words = 256 bytes) per channel - Channel N can use up to (8-N) blocks (borrows from adjacent higher channels) - NO DMA for RMT on original ESP32 — uses interrupt-driven successive copying - 3 SPI peripherals: SPI (flash-only), HSPI (general), VSPI (general) - HSPI default pins: MOSI=GPIO13, MISO=GPIO12, CLK=GPIO14, CS=GPIO15 - VSPI default pins: MOSI=GPIO23, MISO=GPIO19, CLK=GPIO18, CS=GPIO5 - GPIO 6-11: connected to internal flash, NOT usable - GPIO 34-39: input-only, no pull-up/pull-down resistors - Strapping pins: GPIO 0, 2, 4, 5, 12, 15 (affect boot mode) - Safe output GPIOs for LED data: 2, 4, 5, 13, 14, 16-19, 21-23, 25-27, 32-33 - CPU frequency: 240 MHz (default), dual-core Xtensa LX6 - Flash: 4MB (WROOM-32D standard) - SRAM: 520 KB""", "test_spec": """GIVEN the ESP32-WROOM-32D hardware profile defined in code WHEN each field is compared against the official Espressif documentation THEN the following must match: RMT Channels (source: ESP-IDF v4.4.1 RMT docs): - channelCount equals 8 - each channel type is "rmt" - each channel supportedSignalTypes includes "one-wire" - no channel has dmaSupported set to true SPI Buses (source: ESP32 TRM + GPIO reference): - exactly 2 general-purpose SPI buses (HSPI, VSPI) - HSPI defaultGpio is 13 (MOSI) - VSPI defaultGpio is 23 (MOSI) - each SPI channel supportedSignalTypes includes "spi" GPIO Safety (source: ESP32-WROOM-32D datasheet): - no channel defaultGpio is in [6,7,8,9,10,11] (flash pins) - no channel defaultGpio is in [34,35,36,39] (input-only) - all defaultGpio values are in the safe-output set CPU/Memory (source: ESP32-WROOM-32D datasheet): - cpuFreqMhz equals 240""", "test_code": """/** * Verification sources (datasheets/docs to compare against): * * 1. ESP-IDF v4.4.1 RMT Reference * https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/api-reference/peripherals/rmt.html * - 8 channels, 512x32-bit shared RAM, 64-word blocks * - No DMA: "interrupt to successively copy new data chunks" * * 2. ESP32-WROOM-32D Datasheet * https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32d_esp32-wroom-32u_datasheet_en.pdf * - 240MHz dual-core, 4MB flash, 520KB SRAM * - GPIO 6-11 flash, GPIO 34-39 input-only * * 3. ESP32 GPIO Reference (RandomNerdTutorials) * https://randomnerdtutorials.com/esp32-pinout-reference-gpios/ * - Strapping pins: 0, 2, 4, 5, 12, 15 * - VSPI: MOSI=23, MISO=19, CLK=18, CS=5 * - HSPI: MOSI=13, MISO=12, CLK=14, CS=15 * - Safe outputs: 2,4,5,13,14,16-19,21-23,25-27,32-33 */""", "impl_code": """// src/data/hardware-profiles.ts const SAFE_OUTPUT_GPIOS = [2,4,5,13,14,16,17,18,19,21,22,23,25,26,27,32,33]; const FLASH_GPIOS = [6,7,8,9,10,11]; const INPUT_ONLY_GPIOS = [34,35,36,39]; const STRAPPING_GPIOS = [0,2,4,5,12,15]; export const ESP32_WROOM_32D: HardwareProfile = { id: "esp32-wroom-32d", name: "ESP32-WROOM-32D", cpuFreqMhz: 240, dmaBufferBytes: 0, // No DMA for RMT on original ESP32 rmtMemoryBlocks: 8, // 8 blocks x 64 words = 512 x 32-bit rmtWordsPerBlock: 64, channels: [ // 8 RMT channels for one-wire protocols { id: "RMT0", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 16, maxMemoryBlocks: 8 }, { id: "RMT1", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 17, maxMemoryBlocks: 7 }, { id: "RMT2", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 18, maxMemoryBlocks: 6 }, { id: "RMT3", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 19, maxMemoryBlocks: 5 }, { id: "RMT4", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 21, maxMemoryBlocks: 4 }, { id: "RMT5", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 22, maxMemoryBlocks: 3 }, { id: "RMT6", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 23, maxMemoryBlocks: 2 }, { id: "RMT7", type: "rmt", supportedSignalTypes: ["one-wire"], defaultGpio: 25, maxMemoryBlocks: 1 }, // 2 SPI buses for clock-based protocols (APA102) { id: "HSPI", type: "spi", supportedSignalTypes: ["spi"], defaultGpio: 13 }, { id: "VSPI", type: "spi", supportedSignalTypes: ["spi"], defaultGpio: 23 }, ], notes: "RMT uses interrupt-driven successive copying (no DMA). GPIO 6-11 reserved for flash. GPIO 34-39 input-only.", };""", "code_language": "typescript", "target_impl_file": "src/data/hardware-profiles.ts", "target_test_file": "test/data/hardware-profiles.test.ts", } body = json.dumps(data).encode() req = urllib.request.Request( f"{API}/requirements/NPC-DATA-HW-ESP32", data=body, method="PUT", headers={ "Content-Type": "application/json", "Authorization": f"Bearer {TOKEN}", }, ) resp = urllib.request.urlopen(req) result = json.loads(resp.read()) print(f"Updated: {result['id']} - {result['title']}") print(f"Has test_spec: {bool(result.get('test_spec'))}") print(f"Has impl_code: {bool(result.get('impl_code'))}") print(f"Has test_code: {bool(result.get('test_code'))}")