/* IKW1281Connection.h — non-blocking byte-pump + proper timings */ #ifndef INC_IKW1281CONNECTION_H_ #define INC_IKW1281CONNECTION_H_ #include #include "stdint.h" extern uint8_t K_RxData[]; extern volatile uint8_t rx_done_flag; #define KLINE_BUFFER_SIZE 20 #define PACKET_END_EXPECTED 0x03 // === Protocol sizing === #define MAX_PACKET_SIZE 16 // KWP1281 block size // === Timings (per ISO 9141-2 / KWP1281) === #define KWP_P4_MIN_MS 5U // tester inter-byte (P4) 5..20 ms #define KWP_P4_MAX_MS 20U #define KWP_P1_GAP_MS 5U // ECU inter-byte (P1) target #define KWP_ECHO_SUPPRESS_MS 3U // ~3 ms window after TX to drop self-echo // 5-baud init post-switch delays #define KWP_W1_MS 300U // ECU internal time before 0x55 (20..300 ms allowed) #define KWP_W2_MS 10U // 0x55 -> first keyword (5..20 ms) #define KWP_W3_MS 10U // KW LSB -> KW MSB (0..20 ms) // RX FIFO #define KLINE_RX_FIFO_SZ 64 typedef struct { char client_ident[13]; char unk_ident1[11]; char soft_info[11]; char unk_ident2[11]; char unk_ident3[11]; char unk_ident4[7]; } ControllerInfo; typedef enum { PACKET_CMD_ReadIdent = 0x00, PACKET_CMD_ReadIdentAdress = 0x01, PACKET_CMD_ReadRomEeprom = 0x03, PACKET_CMD_ActuatorTest = 0x04, PACKET_CMD_FaultCodesDelete = 0x05, PACKET_CMD_End = 0x06, PACKET_CMD_FaultCodesRead = 0x07, PACKET_CMD_ACK = 0x09, PACKET_CMD_NAK = 0x0A, PACKET_CMD_SoftwareCoding = 0x10, PACKET_CMD_LoginEeprom = 0x18, PACKET_CMD_ReadEeprom = 0x19, PACKET_CMD_WriteEeprom = 0x1A, PACKET_CMD_Custom = 0x1B, PACKET_CMD_GroupReading = 0x29, PACKET_CMD_Login = 0x2B, PACKET_CMD_GroupReadingResponse = 0xE7, PACKET_CMD_ReadEepromResponse = 0xEF, PACKET_CMD_ActuatorTestResponse = 0xF5, PACKET_CMD_AsciiData = 0xF6, PACKET_CMD_WriteEepromResponse = 0xF9, PACKET_CMD_FaultCodesResponse = 0xFC, PACKET_CMD_ReadRomEepromResponse = 0xFD } PacketCommand; typedef enum { PACKET_TYPE_UNKNOWN = 0, PACKET_TYPE_ACK, PACKET_TYPE_NAK, PACKET_TYPE_ASCII_DATA, PACKET_TYPE_CODING_WSC, PACKET_TYPE_READ_EEPROM_RESPONSE, PACKET_TYPE_READ_ROM_EEPROM_RESPONSE } PacketType; typedef struct { PacketType type; uint8_t title; uint8_t length; uint8_t raw[MAX_PACKET_SIZE]; uint8_t isAckNak; } ParsedPacket; #define KLINE_TXBUF_MAX 32 // enough for KWP1281: 2 header + 16 data + 0x03 + margins // === Non-blocking TX "byte pump" === typedef struct { uint8_t active; const uint8_t *buf; uint16_t len; uint16_t idx; uint8_t append_end; // append 0x03 uint8_t last_tx; uint8_t awaiting_echo; // waiting for complement uint8_t require_ack; // expect complement per byte? uint8_t tx_inflight; // HAL_UART_Transmit_IT in progress uint32_t next_time_ms; // next earliest send time uint32_t last_tx_done_ms; // last send time uint8_t ibuf[KLINE_TXBUF_MAX]; uint8_t using_ibuf; } KTxEngine; extern volatile KTxEngine ktx; void KLine_BytePump_Init(void); void KLine_BytePump_Service(void); int KLine_TxStart(const uint8_t *data, uint16_t len, uint8_t append_end, uint8_t require_ack); int KLine_TxBusy(void); // RX FIFO helpers int KLine_RxFifo_Pop(uint8_t *out); void KLine_OnByteReceived(uint8_t byte); // Legacy/blocking API (still available) void SendPacket(uint8_t* payload, uint8_t length); void SendAckPacket(void); void WriteByteAndReadAck(uint8_t b); void WriteByteRaw(uint8_t b); void WriteComplement(uint8_t b); extern ParsedPacket ReceivePacket(void); extern uint8_t ReadByte(void); extern uint8_t ReadAndAckByte(void); extern void ResetPacketCounter(void); extern uint8_t ReadPacketCounter(void); extern inline int32_t tick_diff(uint32_t a, uint32_t b); // Timed reads used by higher layers int ReadByte_Tmo(uint32_t ms, uint8_t *out); int ReadPacketCounter_Tmo(uint32_t ms, uint8_t *out); int ReadAndAckByte_Tmo(uint32_t ms, uint8_t *out); #endif /* INC_IKW1281CONNECTION_H_ */