first added to GitHub
This commit is contained in:
206
DCC_Decoder.h
Normal file
206
DCC_Decoder.h
Normal file
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// DCC_Decoder.h - Arduino library for NMRA DCC Decoding.
|
||||
// Written by Kevin Snow, MynaBay.com, November, 2011.
|
||||
// Questions: dcc@mynabay.com
|
||||
// Released into the public domain.
|
||||
//
|
||||
|
||||
#ifndef __DCC_DECODER_H__
|
||||
#define __DCC_DECODER_H__
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define kDCC_STOP_SPEED 0xFE
|
||||
#define kDCC_ESTOP_SPEED 0xFF
|
||||
|
||||
// Multifunction Decoders
|
||||
#define kCV_PrimaryAddress 1
|
||||
#define kCV_Vstart 2
|
||||
#define kCV_AccelerationRate 3
|
||||
#define kCV_Deceleration Rate 4
|
||||
#define kCV_ManufacturerVersionNo 7
|
||||
#define kCV_ManufacturedID 8
|
||||
#define kCV_ExtendedAddress1 17
|
||||
#define kCV_ExtendedAddress2 18
|
||||
#define kCV_ConfigurationData1 29
|
||||
|
||||
// Accessory Decoders
|
||||
#define kCV_AddressLSB 1
|
||||
#define kCV_AddressMSB 9
|
||||
|
||||
|
||||
// DCC_Decoder results/errors
|
||||
#define kDCC_OK 0
|
||||
#define kDCC_OK_UNHANDLED 1
|
||||
#define kDCC_OK_BOOT 2
|
||||
#define kDCC_OK_IDLE 3
|
||||
#define kDCC_OK_RESET 4
|
||||
#define kDCC_OK_RAW 5
|
||||
#define kDCC_OK_BASELINE 6
|
||||
#define kDCC_OK_BASIC_ACCESSORY 7
|
||||
#define kDCC_OK_EXTENDED_ACCESSORY 8
|
||||
#define kDCC_OK_MAX 99
|
||||
|
||||
#define kDCC_ERR_DETECTION_FAILED 100
|
||||
#define kDCC_ERR_BASELINE_ADDR 101
|
||||
#define kDCC_ERR_BASELINE_INSTR 102 // Baseline packet instruction isn't 0x01DCSSSS
|
||||
#define kDCC_ERR_MISSED_BITS 103
|
||||
#define kDCC_ERR_NOT_0_OR_1 104
|
||||
#define kDCC_ERR_INVALID_LENGTH 105
|
||||
#define kDCC_ERR_MISSING_END_BIT 106
|
||||
|
||||
// Min and max valid packet lengths
|
||||
#define kPACKET_LEN_MIN 3
|
||||
#define kPACKET_LEN_MAX 6
|
||||
|
||||
// CV 1..256 are supported
|
||||
#define kCV_MAX 257
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boolean (*RawPacket)(byte byteCount, byte* packetBytes);
|
||||
|
||||
typedef void (*IdleResetPacket)(byte byteCount, byte* packetBytes);
|
||||
|
||||
typedef void (*BaselineControlPacket)(int address, int speed, int direction);
|
||||
|
||||
typedef void (*BasicAccDecoderPacket)(int address, boolean activate, byte data);
|
||||
typedef void (*ExtendedAccDecoderPacket)(int address, byte data);
|
||||
|
||||
typedef void (*DecodingEngineCompletion)(byte resultOfLastPacket);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef void(*StateFunc)();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DCC_Decoder
|
||||
{
|
||||
public:
|
||||
DCC_Decoder();
|
||||
|
||||
// Called from setup in Arduino Sketch. Set mfgID, mfgVers and interrupt. Call one SetupXXX
|
||||
void SetupDecoder(byte mfgID, byte mfgVers, byte interrupt); // Used for Decoder
|
||||
void SetupMonitor(byte interrupt); // Used when building a monitor
|
||||
|
||||
// All packets are sent to RawPacketHandler. Return true to stop dispatching to other handlers.
|
||||
void SetRawPacketHandler(RawPacket func);
|
||||
|
||||
// S 9.2 defines two special packets. Idle and reset.
|
||||
void SetIdlePacketHandler(IdleResetPacket func);
|
||||
void SetResetPacketHandler(IdleResetPacket func);
|
||||
|
||||
// Handler for S 9.2 baseline packets. Speed value will be 1-14, 1-28, kDCC_STOP_SPEED or kDCC_ESTOP_SPEED
|
||||
void SetBaselineControlPacketHandler(BaselineControlPacket func, boolean allPackets);
|
||||
|
||||
// Handler for RP 9.2.1 Accessory Decoders.
|
||||
void SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket func, boolean allPackets);
|
||||
void SetExtendedAccessoryDecoderPacketHandler(ExtendedAccDecoderPacket func, boolean allPackets);
|
||||
|
||||
// Read/Write CVs
|
||||
byte ReadCV(int cv);
|
||||
void WriteCV(int cv, byte data);
|
||||
|
||||
// Helper function to read decoder address
|
||||
int Address();
|
||||
|
||||
// Call at least once from mainloop. Not calling frequently enough and library will miss data bits!
|
||||
void loop();
|
||||
|
||||
// Returns the packet data in string form.
|
||||
char* MakePacketString(char* buffer60Bytes, byte packetByteCount, byte* packet);
|
||||
|
||||
// Returns the number of bits in last preamble
|
||||
int LastPreambleBitCount();
|
||||
|
||||
// Timing functions. These return MS since various packets
|
||||
unsigned long MillisecondsSinceLastValidPacket();
|
||||
unsigned long MillisecondsSinceLastPacketToThisDecoder();
|
||||
unsigned long MillisecondsSinceLastIdlePacket();
|
||||
unsigned long MillisecondsSinceLastResetPacket();
|
||||
|
||||
|
||||
//======================= Debugging =======================//
|
||||
// Everytime the DCC Decoder engine starts looking for preamble bits this will be
|
||||
// called with result of last packet. (Debugging)
|
||||
void SetDecodingEngineCompletionStatusHandler(DecodingEngineCompletion func);
|
||||
// Converts code passed into completionStatusHandler to human readable string.
|
||||
const char PROGMEM* ResultString(byte resultCode);
|
||||
|
||||
//======================= Library Internals =======================//
|
||||
private:
|
||||
// State machine functions
|
||||
static void State_Boot();
|
||||
static void State_ReadPreamble();
|
||||
static void State_ReadPacket();
|
||||
static void State_Execute();
|
||||
static void State_Reset();
|
||||
|
||||
// Function pointers for the library callbacks
|
||||
static RawPacket func_RawPacket;
|
||||
static IdleResetPacket func_IdlePacket;
|
||||
static IdleResetPacket func_ResetPacket;
|
||||
|
||||
static BasicAccDecoderPacket func_BasicAccPacket;
|
||||
static boolean func_BasicAccPacket_All_Packets;
|
||||
static ExtendedAccDecoderPacket func_ExtdAccPacket;
|
||||
static boolean func_ExtdAccPacket_All_Packets;
|
||||
|
||||
static BaselineControlPacket func_BaselineControlPacket;
|
||||
static boolean func_BaselineControlPacket_All_Packets;
|
||||
|
||||
static DecodingEngineCompletion func_DecodingEngineCompletion;
|
||||
|
||||
// Current state function pointer
|
||||
static StateFunc gState; // Current state function pointer
|
||||
|
||||
// Timing data from last interrupt
|
||||
static unsigned int gLastChaos; // Interrupt chaos count we processed
|
||||
|
||||
// Preamble bit count
|
||||
static int gPreambleCount; // Bit count for reading preamble
|
||||
|
||||
// Reset reason
|
||||
static byte gResetReason; // Result code of last reason decoder was reset
|
||||
static boolean gHandledAsRawPacket;
|
||||
|
||||
// Packet data
|
||||
static byte gPacket[kPACKET_LEN_MAX]; // The packet data.
|
||||
static byte gPacketIndex; // Byte index to write to.
|
||||
static byte gPacketMask; // Bit index to write to. 0x80,0x40,0x20,...0x01
|
||||
static boolean gPacketEndedWith1; // Set true if packet ended on 1. Spec requires that the
|
||||
// packet end bit can count as a bit in next preamble.
|
||||
// CV Storage
|
||||
static byte gCV[kCV_MAX]; // CV Storage (TODO - Storage in PROGMEM)
|
||||
|
||||
// Packet arrival timing
|
||||
static unsigned long gThisPacketMS; // Milliseconds of this packet being parsed
|
||||
static boolean gLastPacketToThisAddress; // Was last pack processed to this decoder's address?
|
||||
|
||||
static unsigned long gLastValidPacketMS; // Milliseconds of last valid packet
|
||||
static unsigned long gLastValidPacketToAddressMS; // Milliseconds of last valid packet to this decoder
|
||||
static unsigned long gLastValidIdlePacketMS; // Milliseconds of last valid idle packet
|
||||
static unsigned long gLastValidResetPacketMS; // Milliseconds of last valid reset packet
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Interrupt Support
|
||||
static void StartInterrupt(byte interrupt);
|
||||
static void DCC_Interrupt();
|
||||
static void ShiftInterruptAlignment();
|
||||
|
||||
static unsigned long gInterruptMicros;
|
||||
static byte gInterruptTimeIndex;
|
||||
static volatile unsigned int gInterruptTime[2];
|
||||
static volatile unsigned int gInterruptChaos;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern DCC_Decoder DCC;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user