/* * can_schema.h * * Created on: Sep 16, 2025 * Author: herli */ #ifndef INC_CAN_SCHEMA_H_ #define INC_CAN_SCHEMA_H_ #ifndef CAN_SCHEMA_H #define CAN_SCHEMA_H #include #include #include typedef enum { CAN_DIR_RX = 0, // incoming from bus -> decode into RAM CAN_DIR_TX = 1 // outgoing to bus -> encode from RAM } CanDirection; typedef enum { CAN_ENDIAN_INTEL = 0, // DBC "Intel" (little-endian bit numbering): bit 0 = LSB of byte 0 CAN_ENDIAN_MOTOROLA = 1 // DBC "Motorola" (big-endian bit numbering) } CanEndian; typedef enum { CAN_SYM_UX = 0, // unsigned raw CAN_SYM_SX = 1, // signed two's complement raw CAN_SYM_FLOAT = 2 // (kept for future use) } CanRawType; typedef enum { NOMINAL = 0, INVERTED = 1 } CanInversion; /* Shared scale (optional): if a symbol sets factor==0 && offset==0 and scale!=NULL, * the effective factor/offset comes from this struct. If symbol.factor/offset is non-zero, * it overrides the scale. */ typedef struct CanScaleDef { const char *unit; // informational, may be NULL float factor; float offset; } CanScaleDef; typedef enum { CAN_STORE_FLOAT = 0, // ptr -> float (uses factor/offset) CAN_STORE_U32, // ptr -> uint32_t (raw integer) CAN_STORE_S32, // ptr -> int32_t (raw integer) CAN_STORE_U16, // ptr -> uint16_t (raw integer) CAN_STORE_S16, // ptr -> int16_t (raw integer) CAN_STORE_U8, // ptr -> uint8_t (raw integer) CAN_STORE_S8 // ptr -> int8_t (raw integer) } CanStorage; struct CanMessageDef; // fwd // User-provided TX function that actually hands frames to HAL typedef bool (*CanTxFn)(uint16_t id, const uint8_t data[8], uint8_t dlc); // Optional per-message RX handler (called AFTER any symbol decode) typedef void (*CanRxHandler)( const struct CanMessageDef *msg, const uint8_t in_data[8], CanTxFn tx ); typedef struct { const char *name; uint8_t start_bit, bit_len; CanEndian endian; CanRawType raw_type; // UX / SX (bit interpretation) float factor, offset; void *ptr; const CanScaleDef *scale; CanStorage storage; // NEW: how to read/write *ptr CanInversion inverted; } CanSymbolDef; typedef struct CanMessageDef { uint16_t can_id; // 11-bit standard ID CanDirection dir; // RX or TX uint8_t dlc; // 0..8 const char *name; // message name const CanSymbolDef *symbols; // array of symbols (NULL if template-only) uint8_t symbol_count; // number of symbols // Optional template payload (used for TX): copied first, then symbols packed on top. const uint8_t *tx_template; // 0..8 bytes in flash (NULL if none) uint8_t send_on_boot; // if 1 and TX, manager will send at init // Optional RX handler (for custom behaviors like address-based replies) CanRxHandler rx_handler; } CanMessageDef; typedef struct { uint16_t addr; // request address void *ptr; // pointer to physical value (usually float*) CanRawType raw_type; // how to quantize (unsigned/signed) const CanScaleDef *scale; // scaling used for inverse transform CanStorage storage; // NEW: how to read ptr (FLOAT/U16/U32/…) } CanAddressEntry; /* Registry access (implemented in can_db.c) */ const CanMessageDef* can_db_find(uint16_t can_id, CanDirection dir); const CanMessageDef* can_db_all(size_t *count); /* Bit-pack engine (implemented in can_encode.c) */ void can_encode_message(const CanMessageDef *msg, uint8_t out_data[8]); void can_decode_message(const CanMessageDef *msg, const uint8_t in_data[8]); #endif /* CAN_SCHEMA_H */ #endif /* INC_CAN_SCHEMA_H_ */