File CANProtocol.h
File List > CANProtocol > CANProtocol.h
Go to the documentation of this file
#pragma once
#include <stdint.h>
#include <HIDControls.h>
// ── Types ─────────────────────────────────────────────────────────────────────
struct __attribute__((packed)) ControlPacket {
uint16_t controlId;
uint16_t value;
};
struct __attribute__((packed)) ControlPacketPair {
ControlPacket a;
ControlPacket b;
};
struct __attribute__((packed)) HeartbeatPayload {
uint8_t nodeId;
uint8_t flags;
uint16_t uptime;
uint16_t rxCount;
uint16_t esr;
};
enum class CanStatus {
STARTING,
NORMAL,
TX_ERROR,
BUS_OFF,
};
// ── Fixed CAN arbitration IDs (PanelBridge -> All) ───────────────────────────
static constexpr uint32_t CAN_ID_CTRL_BCAST = 0x010;
static constexpr uint32_t CAN_ID_TEST_SEQ = 0x011;
static constexpr uint32_t CAN_ID_SYNC_REQ = 0x012;
// ── CAN ID functions (per-node IDs computed from NODE_ID) ─────────────────────
constexpr uint32_t canIdHb(uint8_t n) { return 0x100 + n; }
constexpr uint32_t canIdEvt(uint8_t n) { return 0x200 + n; }
constexpr uint32_t canIdEvtRel(uint8_t n) { return 0x500 + n; }
constexpr uint32_t canIdEvtDir(uint8_t n) { return 0x600 + n; }
constexpr uint32_t canIdEcho(uint8_t n) { return 0x300 + n; }
constexpr uint32_t canIdReady(uint8_t n) { return 0x400 + n; }
// ── controlId namespace ───────────────────────────────────────────────────────
// Payload controlIds live inside ControlPacket data bytes. They are intentionally
// separate from the 11-bit CAN arbitration IDs above.
// CTRL_ID_HID_MIN / CTRL_ID_HID_MAX are defined as macros in HIDControls.h (included above).
// Do not redeclare them here — macro expansion would cause a syntax error.
static constexpr uint16_t CTRL_ID_DCS_MIN = 0x8000;
static constexpr uint16_t CTRL_ID_DCS_MAX = 0x86FF;
// ── UART diagnostic framing constants (PanelBridge -> SimGateway) ─────────────
// Used by SimGateway to parse the UART diagnostic stream from PanelBridge.
static constexpr uint8_t DIAG_MAGIC = 0xAA;
static constexpr uint8_t DIAG_RTT = 0x01;
static constexpr uint8_t DIAG_HB = 0x02;
static constexpr uint8_t DIAG_ERR = 0x03;
static constexpr uint8_t DIAG_EVT = 0x04;
// ── Callback types ────────────────────────────────────────────────────────────
using CanStatusCallback = void(*)(CanStatus status);
using CanRxCallback = void(*)(uint32_t canId, const uint8_t* data, uint8_t len);
using CanSyncReqCallback = void(*)();
// ── Runtime API (STM32 only) ──────────────────────────────────────────────────
#ifdef ARDUINO_ARCH_STM32
namespace CANProtocol {
// ── Filter configuration (call before start()) ────────────────────────────
void filterAcceptAll();
void filterAcceptId(uint32_t canId);
// ── Lifecycle ─────────────────────────────────────────────────────────────
void start();
void startLoopback();
void drain();
// ── Transmit ──────────────────────────────────────────────────────────────
void send(uint32_t canId, const uint8_t* data, uint8_t len);
void sendBatched(uint32_t canId, const ControlPacket& pkt);
void flushBatched(uint32_t canId);
// ── Callbacks ─────────────────────────────────────────────────────────────
void onStatusChange(CanStatusCallback cb);
void onSyncReq(CanSyncReqCallback cb);
void onReceive(CanRxCallback cb);
// ── Diagnostics ───────────────────────────────────────────────────────────
uint8_t tec();
uint8_t rec();
bool busOff();
HeartbeatPayload makeHeartbeatPayload(uint8_t nodeId, uint16_t rxCount);
uint32_t txDropCount();
} // namespace CANProtocol
#endif // ARDUINO_ARCH_STM32