/** * @file DCCDecoder.h * @brief DCC Signal Decoder for locomotive control * * Decodes DCC packets from the track signal, extracts speed and function commands, * and manages locomotive addressing (short/long address support). */ #ifndef DCC_DECODER_H #define DCC_DECODER_H #include // DCC Timing constants (in microseconds) #define DCC_ONE_BIT_MIN 52 #define DCC_ONE_BIT_MAX 64 #define DCC_ZERO_BIT_MIN 95 #define DCC_ZERO_BIT_MAX 9900 // Maximum packet size #define MAX_DCC_PACKET_SIZE 6 class DCCDecoder { public: DCCDecoder(); /** * @brief Initialize the DCC decoder * @param dccPin GPIO pin for DCC signal input * @return true if initialization successful */ bool begin(uint8_t dccPin); /** * @brief Process DCC signal (call frequently from loop or ISR) */ void process(); /** * @brief Get current speed value (0-126, 0=stop, 1=emergency stop) * @return Current speed */ uint8_t getSpeed() const { return currentSpeed; } /** * @brief Get current direction * @return true = forward, false = reverse */ bool getDirection() const { return direction; } /** * @brief Get function state (F0-F28) * @param functionNum Function number (0-28) * @return Function state (true = on) */ bool getFunction(uint8_t functionNum) const; /** * @brief Check if decoder has received valid packets recently * @return true if signal is valid */ bool hasValidSignal() const; /** * @brief Set locomotive address * @param address Locomotive address (1-10239) */ void setAddress(uint16_t address); /** * @brief Get current locomotive address */ uint16_t getAddress() const { return locoAddress; } private: static void IRAM_ATTR dccISR(); static DCCDecoder* instance; void decodeDCCPacket(); void processSpeedPacket(uint8_t* data, uint8_t len); void processFunctionPacket(uint8_t* data, uint8_t len); uint8_t dccInputPin; uint16_t locoAddress; uint8_t currentSpeed; bool direction; uint32_t functions; // Bit field for F0-F28 // Packet assembly uint8_t packetBuffer[MAX_DCC_PACKET_SIZE]; uint8_t packetIndex; uint8_t bitCount; bool assemblingPacket; // Timing unsigned long lastBitTime; unsigned long lastValidPacket; }; #endif // DCC_DECODER_H