///////////////////////////////////////////////////////////////////////////////////////////////////////// // // Name: ipc_protocol.h // Created: Mar 2025 // Author(s): Philip Smart // Description: Binary IPC frame protocol shared between RP2350 and ESP32. // Commands and data are sent over SPI as packed binary frames. // UART is retained only for firmware update paths and OOB commands. // Copyright: (c) 2019-2026 Philip Smart // // History: Mar 2025 v1.0 - Initial write. // ///////////////////////////////////////////////////////////////////////////////////////////////////////// // This source file is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This source file is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. ///////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef IPC_PROTOCOL_H_ #define IPC_PROTOCOL_H_ #include // --------------------------------------------------------------------------- // Frame type field (t_IpcFrameHdr::frameType) // --------------------------------------------------------------------------- #define IPCF_TYPE_NOP 0x00 // No-operation / dummy TX during full-duplex read #define IPCF_TYPE_COMMAND 0x01 // Command frame from RP2350 → ESP32 #define IPCF_TYPE_RESPONSE 0x02 // Response frame from ESP32 → RP2350 // --------------------------------------------------------------------------- // Command opcodes (t_IpcFrameHdr::command) // --------------------------------------------------------------------------- #define IPCF_CMD_NOP 0x00 // No-operation #define IPCF_CMD_RDS 0x01 // Read single 512-byte sector #define IPCF_CMD_WRS 0x02 // Write single 512-byte sector #define IPCF_CMD_RBURST 0x03 // Read burst: 1-16 sectors in one SPI transaction #define IPCF_CMD_WBURST 0x04 // Write burst: 1-16 sectors in one SPI transaction #define IPCF_CMD_RFILE 0x05 // Read whole file (chunked if > max payload) #define IPCF_CMD_WFILE 0x06 // Write whole file #define IPCF_CMD_INF 0x07 // Transfer RP2350 version/partition info to ESP32 #define IPCF_CMD_RFD 0x08 // Read floppy disk image file #define IPCF_CMD_RQD 0x09 // Read quick-disk image file #define IPCF_CMD_RRF 0x0A // Read RAM-file backup image #define IPCF_CMD_DIR 0x0B // Read directory listing (returns text in payload) // Network commands (Celestite W5100 emulation) #define IPCF_CMD_NET_CFG 0x10 // Get ESP32 network config (IP, gateway, subnet, MAC) #define IPCF_CMD_NET_SOCK 0x11 // Socket operation (open/connect/listen/close/discon) #define IPCF_CMD_NET_SEND 0x12 // Send data to socket (payload = data to send) #define IPCF_CMD_NET_RECV 0x13 // Receive data from socket (response payload = data) #define IPCF_CMD_NET_PING 0x14 // ICMP echo request (ping) // --------------------------------------------------------------------------- // Status codes (t_IpcFrameHdr::status — response frames only) // --------------------------------------------------------------------------- #define IPCF_STATUS_OK 0x00 // Success #define IPCF_STATUS_ERR 0x01 // Generic error #define IPCF_STATUS_BUSY 0x02 // Resource busy #define IPCF_STATUS_CRCFAIL 0x03 // CRC32 mismatch detected by receiver #define IPCF_STATUS_NOTFOUND 0x04 // File or sector not found #define IPCF_STATUS_PARTIAL 0x05 // Partial data — more chunks follow (file streaming) // --------------------------------------------------------------------------- // Flags field (t_IpcFrameHdr::flags) // --------------------------------------------------------------------------- #define IPCF_FLAG_LAST_CHUNK 0x01 // This is the last chunk of a multi-chunk file transfer #define IPCF_FLAG_MORE_DATA 0x02 // More data chunks follow // --------------------------------------------------------------------------- // Frame sizing constants // --------------------------------------------------------------------------- #define IPCF_HEADER_SIZE 64 // Fixed header size — must stay 64 bytes #define IPCF_MAX_SECTORS 16 // Maximum sectors per burst command #define IPCF_SECTOR_SIZE 512 // Bytes per sector #define IPCF_CRC_SIZE 4 // CRC32 trailer (bytes) #define IPCF_FILENAME_LEN 48 // Max filename length including path + null #define IPCF_MAX_PAYLOAD (IPCF_MAX_SECTORS * IPCF_SECTOR_SIZE) // 8192 bytes #define IPCF_MAX_FRAME_SIZE (IPCF_HEADER_SIZE + IPCF_MAX_PAYLOAD + IPCF_CRC_SIZE) // 8260 bytes // --------------------------------------------------------------------------- // IPC frame header — 64 bytes packed, shared by command and response frames. // Byte offsets must stay stable; add fields only in the reserved area. // Both RP2350 (arm-none-eabi-gcc) and ESP32 (xtensa-esp32-elf-gcc) support // __attribute__((packed)). // --------------------------------------------------------------------------- typedef struct __attribute__((packed)) { uint8_t frameType; // 0: IPCF_TYPE_* uint8_t command; // 1: IPCF_CMD_* uint8_t status; // 2: IPCF_STATUS_* (response) / 0 (command) uint8_t seqNum; // 3: Sequence number — used for retry detection uint16_t payloadLen; // 4: Bytes of payload that follow the header (LE) uint16_t sectorCount; // 6: Sectors in burst (command) or returned (response) uint32_t fileOffset; // 8: Byte offset in file (sector-read / write position) uint8_t diskNo; // 12: Drive number for floppy / QD commands uint8_t flags; // 13: IPCF_FLAG_* uint16_t reserved; // 14: Reserved — keep zero char filename[IPCF_FILENAME_LEN]; // 16: Null-terminated path/filename // Total: 16 + 48 = 64 bytes exactly } t_IpcFrameHdr; #endif // IPC_PROTOCOL_H_