//------------------------------------------------------------------------ // // Model Railroading with Arduino - NmraDcc.h // // Copyright (c) 2008 - 2018 Alex Shepherd // // This source file is subject of the GNU general public license 2, // that is available at the world-wide-web at // http://www.gnu.org/licenses/gpl.txt // //------------------------------------------------------------------------ // // file: NmraDcc.h // author: Alex Shepherd // webpage: http://mrrwa.org/ // history: 2008-03-20 Initial Version // 2011-06-26 Migrated into Arduino library from OpenDCC codebase // 2014 Added getAddr to NmraDcc Geoff Bunza // 2015-11-06 Martin Pischky (martin@pischky.de): // Experimental Version to support 14 speed steps // and new signature of notifyDccSpeed and notifyDccFunc // 2017-11-29 Ken West (kgw4449@gmail.com): // Added method and callback headers. // //------------------------------------------------------------------------ // // purpose: Provide a simplified interface to decode NMRA DCC packets // and build DCC MutliFunction and Stationary Decoders // //------------------------------------------------------------------------ // NodeMCU Lua port by @voborsky // #define NODE_DEBUG // #define DCC_DEBUG // #define DCC_DBGVAR // Uncomment the following Line to Enable Service Mode CV Programming #define NMRA_DCC_PROCESS_SERVICEMODE // Uncomment the following line to Enable MultiFunction Decoder Operations #define NMRA_DCC_PROCESS_MULTIFUNCTION // #ifndef NMRADCC_IS_IN // #define NMRADCC_IS_IN #define NMRADCC_VERSION 201 // Version 2.0.1 #define MAX_DCC_MESSAGE_LEN 6 // including XOR-Byte typedef struct { uint8_t Size ; uint8_t PreambleBits ; uint8_t Data[MAX_DCC_MESSAGE_LEN] ; } DCC_MSG ; //-------------------------------------------------------------------------- // This section contains the NMRA Assigned DCC Manufacturer Id Codes that // are used in projects // // This value is to be used for CV8 //-------------------------------------------------------------------------- #define MAN_ID_JMRI 0x12 #define MAN_ID_DIY 0x0D #define MAN_ID_SILICON_RAILWAY 0x21 //-------------------------------------------------------------------------- // This section contains the Product/Version Id Codes for projects // // This value is to be used for CV7 // // NOTE: Each Product/Version Id Code needs to be UNIQUE for that particular // the DCC Manufacturer Id Code //-------------------------------------------------------------------------- // Product/Version Id Codes allocated under: MAN_ID_JMRI // Product/Version Id Codes allocated under: MAN_ID_DIY // Standard CV Addresses #define CV_ACCESSORY_DECODER_ADDRESS_LSB 1 #define CV_ACCESSORY_DECODER_ADDRESS_MSB 9 #define CV_MULTIFUNCTION_PRIMARY_ADDRESS 1 #define CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB 17 #define CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB 18 #define CV_VERSION_ID 7 #define CV_MANUFACTURER_ID 8 #define CV_29_CONFIG 29 typedef enum { CV29_LOCO_DIR = 0b00000001, /** bit 0: Locomotive Direction: "0" = normal, "1" = reversed */ CV29_F0_LOCATION = 0b00000010, /** bit 1: F0 location: "0" = bit 4 in Speed and Direction instructions, "1" = bit 4 in function group one instruction */ CV29_APS = 0b00000100, /** bit 2: Alternate Power Source (APS) "0" = NMRA Digital only, "1" = Alternate power source set by CV12 */ CV29_ADV_ACK = 0b00001000, /** bit 3: ACK, Advanced Acknowledge mode enabled if 1, disabled if 0 */ CV29_SPEED_TABLE_ENABLE = 0b00010000, /** bit 4: STE, Speed Table Enable, "0" = values in CVs 2, 4 and 6, "1" = Custom table selected by CV 25 */ CV29_EXT_ADDRESSING = 0b00100000, /** bit 5: "0" = one byte addressing, "1" = two byte addressing */ CV29_OUTPUT_ADDRESS_MODE = 0b01000000, /** bit 6: "0" = Decoder Address Mode "1" = Output Address Mode */ CV29_ACCESSORY_DECODER = 0b10000000, /** bit 7: "0" = Multi-Function Decoder Mode "1" = Accessory Decoder Mode */ } CV_29_BITS; typedef enum { #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE SPEED_STEP_14 = 15, /**< ESTOP=0, 1 to 15 */ #endif SPEED_STEP_28 = 29, /**< ESTOP=0, 1 to 29 */ SPEED_STEP_128 = 127 /**< ESTOP=0, 1 to 127 */ } DCC_SPEED_STEPS; typedef enum { DCC_DIR_REV = 0, /** The locomotive to go in the reverse direction */ DCC_DIR_FWD = 1, /** The locomotive should move in the forward direction */ } DCC_DIRECTION; typedef enum { DCC_ADDR_SHORT, /** Short address is used. The range is 0 to 127. */ DCC_ADDR_LONG, /** Long Address is used. The range is 1 to 10239 */ } DCC_ADDR_TYPE; typedef enum { FN_0_4 = 1, FN_5_8, FN_9_12, FN_13_20, FN_21_28, #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE FN_0 /** function light is controlled by base line package (14 speed steps) */ #endif } FN_GROUP; #define FN_BIT_00 0x10 #define FN_BIT_01 0x01 #define FN_BIT_02 0x02 #define FN_BIT_03 0x04 #define FN_BIT_04 0x08 #define FN_BIT_05 0x01 #define FN_BIT_06 0x02 #define FN_BIT_07 0x04 #define FN_BIT_08 0x08 #define FN_BIT_09 0x01 #define FN_BIT_10 0x02 #define FN_BIT_11 0x04 #define FN_BIT_12 0x08 #define FN_BIT_13 0x01 #define FN_BIT_14 0x02 #define FN_BIT_15 0x04 #define FN_BIT_16 0x08 #define FN_BIT_17 0x10 #define FN_BIT_18 0x20 #define FN_BIT_19 0x40 #define FN_BIT_20 0x80 #define FN_BIT_21 0x01 #define FN_BIT_22 0x02 #define FN_BIT_23 0x04 #define FN_BIT_24 0x08 #define FN_BIT_25 0x10 #define FN_BIT_26 0x20 #define FN_BIT_27 0x40 #define FN_BIT_28 0x80 #ifdef DCC_DBGVAR typedef struct countOf_t { unsigned long Tel; unsigned long Err; }countOf_t ; countOf_t countOf; #endif // Flag values to be logically ORed together and passed into the init() method #define FLAGS_MY_ADDRESS_ONLY 0x01 // Only process DCC Packets with My Address #define FLAGS_AUTO_FACTORY_DEFAULT 0x02 // Call notifyCVResetFactoryDefault() if CV 7 & 8 == 255 #define FLAGS_SETCV_CALLED 0x10 // only used internally !! #define FLAGS_OUTPUT_ADDRESS_MODE 0x40 // CV 29/541 bit 6 #define FLAGS_DCC_ACCESSORY_DECODER 0x80 // CV 29/541 bit 7 // Flag Bits that are cloned from CV29 relating the DCC Accessory Decoder #define FLAGS_CV29_BITS (FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER) #define DCC_RESET 1 #define DCC_IDLE 2 #define DCC_SPEED 3 #define DCC_SPEED_RAW 4 #define DCC_FUNC 5 #define DCC_TURNOUT 6 #define DCC_ACCESSORY 7 #define DCC_RAW 8 #define DCC_SERVICEMODE 9 #define CV_VALID 10 #define CV_READ 11 #define CV_WRITE 12 #define CV_RESET 13 void dcc_setup(uint8_t pin, uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV ); void dcc_close(); void dcc_init(); /************************************************************************************ Call-back functions ************************************************************************************/ /*+ * notifyDccReset(uint8_t hardReset) Callback for a DCC reset command. * * Inputs: * hardReset - 0 normal reset command. * 1 hard reset command. * * Returns: * None */ extern void notifyDccReset(uint8_t hardReset ) __attribute__ ((weak)); /*+ * notifyDccIdle() Callback for a DCC idle command. * * Inputs: * None * * Returns: * None */ extern void notifyDccIdle(void) __attribute__ ((weak)); /*+ * notifyDccSpeed() Callback for a multifunction decoder speed command. * The received speed and direction are unpacked to separate values. * * Inputs: * Addr - Active decoder address. * AddrType - DCC_ADDR_SHORT or DCC_ADDR_LONG. * Speed - Decoder speed. 0 = Emergency stop * 1 = Regular stop * 2 to SpeedSteps = Speed step 1 to max. * Dir - DCC_DIR_REV or DCC_DIR_FWD * SpeedSteps - Highest speed, SPEED_STEP_14 = 15 * SPEED_STEP_28 = 29 * SPEED_STEP_128 = 127 * * Returns: * None */ extern void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps ) __attribute__ ((weak)); /*+ * notifyDccSpeedRaw() Callback for a multifunction decoder speed command. * The value in Raw is the unpacked speed command. * * Inputs: * Addr - Active decoder address. * AddrType - DCC_ADDR_SHORT or DCC_ADDR_LONG. * Raw - Raw decoder speed command. * * Returns: * None */ extern void notifyDccSpeedRaw( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Raw) __attribute__ ((weak)); /*+ * notifyDccFunc() Callback for a multifunction decoder function command. * * Inputs: * Addr - Active decoder address. * AddrType - DCC_ADDR_SHORT or DCC_ADDR_LONG. * FuncGrp - Function group. FN_0 - 14 speed step headlight function. * Mask FN_BIT_00. * FN_0_4 - Functions 0 to 4. Mask FN_BIT_00 - FN_BIT_04 * FN_5_8 - Functions 5 to 8. Mask FN_BIT_05 - FN_BIT_08 * FN_9_12 - Functions 9 to 12. Mask FN_BIT_09 - FN_BIT_12 * FN_13_20 - Functions 13 to 20. Mask FN_BIT_13 - FN_BIT_20 * FN_21_28 - Functions 21 to 28. Mask FN_BIT_21 - FN_BIT_28 * FuncState - Function state. Bitmask where active functions have a 1 at that bit. * You must & FuncState with the appropriate * FN_BIT_nn value to isolate a given bit. * * Returns: * None */ extern void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) __attribute__ ((weak)); /*+ * notifyDccAccTurnoutBoard() Board oriented callback for a turnout accessory decoder. * Most useful when CV29_OUTPUT_ADDRESS_MODE is not set. * Decoders of this type have 4 paired turnout outputs per board. * OutputPower is 1 if the power is on, and 0 otherwise. * * Inputs: * BoardAddr - Per board address. Equivalent to CV 1 LSB & CV 9 MSB. * OutputPair - Output pair number. It has a range of 0 to 3. * Equivalent to upper 2 bits of the 3 DDD bits in the accessory packet. * Direction - Turnout direction. It has a value of 0 or 1. * It is equivalent to bit 0 of the 3 DDD bits in the accessory packet. * OutputPower - Output On/Off. Equivalent to packet C bit. It has these values: * 0 - Output pair is off. * 1 - Output pair is on. * * Returns: * None */ extern void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t Direction, uint8_t OutputPower ) __attribute__ ((weak)); /*+ * notifyDccAccTurnoutOutput() Output oriented callback for a turnout accessory decoder. * Most useful when CV29_OUTPUT_ADDRESS_MODE is not set. * Decoders of this type have 4 paired turnout outputs per board. * OutputPower is 1 if the power is on, and 0 otherwise. * * Inputs: * Addr - Per output address. There will be 4 Addr addresses * per board for a standard accessory decoder with 4 output pairs. * Direction - Turnout direction. It has a value of 0 or 1. * Equivalent to bit 0 of the 3 DDD bits in the accessory packet. * OutputPower - Output On/Off. Equivalent to packet C bit. It has these values: * 0 - Output is off. * 1 - Output is on. * * Returns: * None */ extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) __attribute__ ((weak)); /*+ * notifyDccAccBoardAddrSet() Board oriented callback for a turnout accessory decoder. * This notification is when a new Board Address is set to the * address of the next DCC Turnout Packet that is received * * This is enabled via the setAccDecDCCAddrNextReceived() method above * * Inputs: * BoardAddr - Per board address. Equivalent to CV 1 LSB & CV 9 MSB. * per board for a standard accessory decoder with 4 output pairs. * * Returns: * None */ extern void notifyDccAccBoardAddrSet( uint16_t BoardAddr) __attribute__ ((weak)); /*+ * notifyDccAccOutputAddrSet() Output oriented callback for a turnout accessory decoder. * This notification is when a new Output Address is set to the * address of the next DCC Turnout Packet that is received * * This is enabled via the setAccDecDCCAddrNextReceived() method above * * Inputs: * Addr - Per output address. There will be 4 Addr addresses * per board for a standard accessory decoder with 4 output pairs. * * Returns: * None */ extern void notifyDccAccOutputAddrSet( uint16_t Addr) __attribute__ ((weak)); /*+ * notifyDccSigOutputState() Callback for a signal aspect accessory decoder. * Defined in S-9.2.1 as the Extended Accessory Decoder Control Packet. * * Inputs: * Addr - Decoder address. * State - 6 bit command equivalent to S-9.2.1 00XXXXXX. * * Returns: * None */ extern void notifyDccSigOutputState( uint16_t Addr, uint8_t State) __attribute__ ((weak)); /*+ * notifyDccMsg() Raw DCC packet callback. * Called with raw DCC packet bytes. * * Inputs: * Msg - Pointer to DCC_MSG structure. The values are: * Msg->Size - Number of Data bytes in the packet. * Msg->PreambleBits - Number of preamble bits in the packet. * Msg->Data[] - Array of data bytes in the packet. * * Returns: * None */ extern void notifyDccMsg( DCC_MSG * Msg ) __attribute__ ((weak)); /*+ * notifyCVValid() Callback to determine if a given CV is valid. * This is called when the library needs to determine * if a CV is valid. Note: If defined, this callback * MUST determine if a CV is valid and return the * appropriate value. If this callback is not defined, * the library will determine validity. * * Inputs: * CV - CV number. * Writable - 1 for CV writes. 0 for CV reads. * * Returns: * 1 - CV is valid. * 0 - CV is not valid. */ extern uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) __attribute__ ((weak)); /*+ * notifyCVRead() Callback to read a CV. * This is called when the library needs to read * a CV. Note: If defined, this callback * MUST return the value of the CV. * If this callback is not defined, * the library will read the CV from EEPROM. * * Inputs: * CV - CV number. * * Returns: * Value - Value of the CV. */ extern uint8_t notifyCVRead( uint16_t CV) __attribute__ ((weak)); /*+ * notifyCVWrite() Callback to write a value to a CV. * This is called when the library needs to write * a CV. Note: If defined, this callback * MUST write the Value to the CV and return the value of the CV. * If this callback is not defined, * the library will read the CV from EEPROM. * * Inputs: * CV - CV number. * Value - Value of the CV. * * Returns: * Value - Value of the CV. */ extern uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) __attribute__ ((weak)); /*+ * notifyCVResetFactoryDefault() Called when CVs must be reset. * This is called when CVs must be reset * to their factory defaults. This callback * should write the factory default value of * relevent CVs using the setCV() method. * setCV() must not block whens this is called. * Test with isSetCVReady() prior to calling setCV() * * Inputs: * None * * * Returns: * None */ extern void notifyCVResetFactoryDefault(void) __attribute__ ((weak)); /*+ * notifyServiceMode(bool) Called when state of 'inServiceMode' changes * * Inputs: * bool state of inServiceMode * * * Returns: * None */ extern void notifyServiceMode(bool) __attribute__ ((weak)); // Deprecated, only for backward compatibility with version 1.4.2. // Don't use in new designs. These functions may be dropped in future versions // extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State ) __attribute__ ((weak)); // extern void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State) __attribute__ ((weak));