Commit f0173382 authored by Lukáš Voborský's avatar Lukáš Voborský Committed by Nathaniel Wesley Filardo
Browse files

NmraDcc port to NodeMCU Lua

Merging @pjsg's ack functionalities and other fixes
parent e2c7ee41
This diff is collapsed.
...@@ -39,6 +39,13 @@ ...@@ -39,6 +39,13 @@
// //
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// NodeMCU Lua port by @voborsky
#define NODEMCUDCC
// #define NODE_DEBUG
// #define DCC_DEBUG
// #define DCC_DBGVAR
// Uncomment the following Line to Enable Service Mode CV Programming // Uncomment the following Line to Enable Service Mode CV Programming
#define NMRA_DCC_PROCESS_SERVICEMODE #define NMRA_DCC_PROCESS_SERVICEMODE
...@@ -50,6 +57,7 @@ ...@@ -50,6 +57,7 @@
#if defined(ARDUINO) && ARDUINO >= 100 #if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h" #include "Arduino.h"
#elif defined(NODEMCUDCC)
#else #else
#include "WProgram.h" #include "WProgram.h"
#endif #endif
...@@ -204,9 +212,14 @@ typedef struct countOf_t { ...@@ -204,9 +212,14 @@ typedef struct countOf_t {
unsigned long Err; unsigned long Err;
}countOf_t ; }countOf_t ;
#ifdef NODEMCUDCC
countOf_t countOf;
#else
extern struct countOf_t countOf; extern struct countOf_t countOf;
#endif #endif
#endif
#ifndef NODEMCUDCC
class NmraDcc class NmraDcc
{ {
private: private:
...@@ -214,6 +227,7 @@ class NmraDcc ...@@ -214,6 +227,7 @@ class NmraDcc
public: public:
NmraDcc(); NmraDcc();
#endif
// Flag values to be logically ORed together and passed into the init() method // 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_MY_ADDRESS_ONLY 0x01 // Only process DCC Packets with My Address
...@@ -225,7 +239,7 @@ class NmraDcc ...@@ -225,7 +239,7 @@ class NmraDcc
// Flag Bits that are cloned from CV29 relating the DCC Accessory Decoder // 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 FLAGS_CV29_BITS (FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER)
#ifndef NODEMCUDCC
/*+ /*+
* pin() is called from setup() and sets up the pin used to receive DCC packets. * pin() is called from setup() and sets up the pin used to receive DCC packets.
* *
...@@ -403,6 +417,32 @@ void pin( uint8_t ExtIntPinNum, uint8_t EnablePullup); ...@@ -403,6 +417,32 @@ void pin( uint8_t ExtIntPinNum, uint8_t EnablePullup);
}; };
#else
#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
#define CV_ACK_COMPLETE 14
void dcc_setup(uint8_t pin, uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV);
void dcc_close();
void dcc_init();
#endif //#ifndef NODEMCUDCC
/************************************************************************************ /************************************************************************************
Call-back functions Call-back functions
************************************************************************************/ ************************************************************************************/
...@@ -608,7 +648,11 @@ extern void notifyDccMsg( DCC_MSG * Msg ) __attribute__ ((weak)); ...@@ -608,7 +648,11 @@ extern void notifyDccMsg( DCC_MSG * Msg ) __attribute__ ((weak));
* 1 - CV is valid. * 1 - CV is valid.
* 0 - CV is not valid. * 0 - CV is not valid.
*/ */
#ifdef NODEMCUDCC
extern uint16_t notifyCVValid( uint16_t CV, uint8_t Writable ) __attribute__ ((weak));
#else
extern uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) __attribute__ ((weak)); extern uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) __attribute__ ((weak));
#endif
/*+ /*+
* notifyCVRead() Callback to read a CV. * notifyCVRead() Callback to read a CV.
...@@ -622,10 +666,13 @@ extern uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) __attribute__ ((we ...@@ -622,10 +666,13 @@ extern uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) __attribute__ ((we
* CV - CV number. * CV - CV number.
* *
* Returns: * Returns:
* Value - Value of the CV. * Value - Value of the CV. Or a value > 255 to indicate error.
*/ */
#ifdef NODEMCUDCC
extern uint16_t notifyCVRead( uint16_t CV) __attribute__ ((weak));
#else
extern uint8_t notifyCVRead( uint16_t CV) __attribute__ ((weak)); extern uint8_t notifyCVRead( uint16_t CV) __attribute__ ((weak));
#endif
/*+ /*+
* notifyCVWrite() Callback to write a value to a CV. * notifyCVWrite() Callback to write a value to a CV.
* This is called when the library needs to write * This is called when the library needs to write
...@@ -639,10 +686,15 @@ extern uint8_t notifyCVRead( uint16_t CV) __attribute__ ((weak)); ...@@ -639,10 +686,15 @@ extern uint8_t notifyCVRead( uint16_t CV) __attribute__ ((weak));
* Value - Value of the CV. * Value - Value of the CV.
* *
* Returns: * Returns:
* Value - Value of the CV. * Value - Value of the CV. Or a value > 255 to signal error.
*/ */
#ifdef NODEMCUDCC
extern uint16_t notifyCVWrite( uint16_t CV, uint8_t Value) __attribute__ ((weak));
#else
extern uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) __attribute__ ((weak)); extern uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) __attribute__ ((weak));
#endif
#ifndef NODEMCUDCC
/*+ /*+
* notifyIsSetCVReady() Callback to to determine if CVs can be written. * notifyIsSetCVReady() Callback to to determine if CVs can be written.
* This is called when the library needs to determine * This is called when the library needs to determine
...@@ -681,6 +733,7 @@ extern uint8_t notifyIsSetCVReady(void) __attribute__ ((weak)); ...@@ -681,6 +733,7 @@ extern uint8_t notifyIsSetCVReady(void) __attribute__ ((weak));
*/ */
extern void notifyCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak)); extern void notifyCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak));
extern void notifyDccCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak)); extern void notifyDccCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak));
#endif
/*+ /*+
* notifyCVResetFactoryDefault() Called when CVs must be reset. * notifyCVResetFactoryDefault() Called when CVs must be reset.
...@@ -743,3 +796,4 @@ extern void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State ...@@ -743,3 +796,4 @@ extern void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State
#endif #endif
#endif #endif
// NodeMCU Lua port by @voborsky // NodeMCU Lua port by @voborsky, @pjsg
// Module for handling NMRA DCC protocol // Module for handling NMRA DCC protocol
// #define NODE_DEBUG // #define NODE_DEBUG
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "platform.h" #include "platform.h"
#include "driver/NmraDcc.h" #include "driver/NmraDcc.h"
#include "hw_timer.h"
#ifdef LUA_USE_MODULES_DCC #ifdef LUA_USE_MODULES_DCC
#if !defined(GPIO_INTERRUPT_ENABLE) || !defined(GPIO_INTERRUPT_HOOK_ENABLE) #if !defined(GPIO_INTERRUPT_ENABLE) || !defined(GPIO_INTERRUPT_HOOK_ENABLE)
...@@ -16,6 +17,8 @@ ...@@ -16,6 +17,8 @@
#define TYPE "Type" #define TYPE "Type"
#define OPERATION "Operation" #define OPERATION "Operation"
#define TIMER_OWNER (('D' << 8) + 'C')
static inline void register_lua_cb(lua_State* L,int* cb_ref){ static inline void register_lua_cb(lua_State* L,int* cb_ref){
int ref=luaL_ref(L, LUA_REGISTRYINDEX); int ref=luaL_ref(L, LUA_REGISTRYINDEX);
if( *cb_ref != LUA_NOREF){ if( *cb_ref != LUA_NOREF){
...@@ -33,6 +36,15 @@ static inline void unregister_lua_cb(lua_State* L, int* cb_ref){ ...@@ -33,6 +36,15 @@ static inline void unregister_lua_cb(lua_State* L, int* cb_ref){
static int notify_cb = LUA_NOREF; static int notify_cb = LUA_NOREF;
static int CV_cb = LUA_NOREF; static int CV_cb = LUA_NOREF;
static int CV_ref = LUA_NOREF;
static int8_t ackPin;
static char ackInProgress;
static platform_task_handle_t tasknumber;
typedef struct {
uint16_t cv;
uint8_t value;
} CVData;
// DCC commands // DCC commands
...@@ -154,8 +166,11 @@ void notifyServiceMode(bool InServiceMode){ ...@@ -154,8 +166,11 @@ void notifyServiceMode(bool InServiceMode){
// CV handling // CV handling
uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) { uint16_t notifyCVValid( uint16_t CV, uint8_t Writable ) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
if (CV_ref != LUA_NOREF) {
return 1;
}
if(notify_cb == LUA_NOREF) if(notify_cb == LUA_NOREF)
return 0; return 0;
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb); lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb);
...@@ -165,13 +180,45 @@ uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) { ...@@ -165,13 +180,45 @@ uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) {
cbAddFieldInteger(L, Writable, "Writable"); cbAddFieldInteger(L, Writable, "Writable");
if (luaL_pcallx(L, 2, 1) != LUA_OK) if (luaL_pcallx(L, 2, 1) != LUA_OK)
return 0; return 0;
uint8 result = lua_tointeger(L, -1); uint8 result = lua_tointeger(L, -1) || lua_toboolean(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
return result; return result;
} }
uint8_t notifyCVRead( uint16_t CV) { static int doDirectCVRead(lua_State *L) {
CVData *data = (CVData*) lua_touserdata(L, -1);
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_ref);
lua_pushinteger(L, data->cv);
lua_gettable(L, -2);
data->value = (uint8_t) luaL_checkinteger(L, -1);
return 0;
}
static int doDirectCVWrite(lua_State *L) {
CVData *data = (CVData*) lua_touserdata(L, -1);
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_ref);
lua_pushinteger(L, data->cv);
lua_pushinteger(L, data->value);
lua_settable(L, -3);
return 0;
}
uint16_t notifyCVRead( uint16_t CV) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
if (CV_ref != LUA_NOREF) {
CVData data;
data.cv = CV;
lua_pushcfunction(L, doDirectCVRead);
lua_pushlightuserdata(L, &data);
if (lua_pcall(L, 1, 0, 0)) {
// An error.
lua_pop(L, 1);
return 256;
}
return data.value;
}
if(notify_cb == LUA_NOREF) if(notify_cb == LUA_NOREF)
return 0; return 0;
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb); lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb);
...@@ -185,8 +232,23 @@ uint8_t notifyCVRead( uint16_t CV) { ...@@ -185,8 +232,23 @@ uint8_t notifyCVRead( uint16_t CV) {
return result; return result;
} }
uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) { uint16_t notifyCVWrite( uint16_t CV, uint8_t Value) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
if (CV_ref != LUA_NOREF) {
CVData data;
data.cv = CV;
data.value = Value;
lua_pushcfunction(L, doDirectCVWrite);
lua_pushlightuserdata(L, &data);
if (lua_pcall(L, 1, 0, 0)) {
// An error.
lua_pop(L, 1);
return 256;
}
return data.value;
}
if(notify_cb == LUA_NOREF) if(notify_cb == LUA_NOREF)
return 0; return 0;
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb); lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb);
...@@ -194,53 +256,106 @@ uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) { ...@@ -194,53 +256,106 @@ uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) {
lua_newtable(L); lua_newtable(L);
cbAddFieldInteger(L, CV, "CV"); cbAddFieldInteger(L, CV, "CV");
cbAddFieldInteger(L, Value, "Value"); cbAddFieldInteger(L, Value, "Value");
luaL_pcallx(L, 2, 0); luaL_pcallx(L, 2, 1);
// Return is an optional value (if integer). If nil, then it is old style
if (!lua_isnil(L, -1)) {
Value = lua_tointeger(L, -1);
}
lua_pop(L, 1);
return Value; return Value;
} }
void notifyCVResetFactoryDefault(void) { static void notifyCVNoArgs(int callback_type) {
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
if(notify_cb == LUA_NOREF) if (notify_cb == LUA_NOREF) {
return; return;
}
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb); lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb);
lua_pushinteger(L, CV_RESET); lua_pushinteger(L, callback_type);
luaL_pcallx(L, 1, 0); luaL_pcallx(L, 1, 0);
} }
void notifyCVResetFactoryDefault(void) {
notifyCVNoArgs(CV_RESET);
}
void notifyCVAck(void) {
// Invoked when we should generate an ack pulse (if possible)
if (ackPin >= 0 && !ackInProgress) {
// Duration is 6ms +/- 1ms
platform_hw_timer_arm_us(TIMER_OWNER, 6 * 1000);
platform_gpio_write(ackPin, 1);
ackInProgress = TRUE;
}
}
static void ICACHE_RAM_ATTR cvAckComplete(os_param_t param) {
// Invoked when we should end the ack pulse
ackInProgress = FALSE;
platform_gpio_write(ackPin, 0);
if (CV_ref == LUA_NOREF) {
platform_post_high(tasknumber, CV_ACK_COMPLETE);
}
}
static int dcc_lua_setup(lua_State* L) { static int dcc_lua_setup(lua_State* L) {
NODE_DBG("[dcc_lua_setup]\n"); NODE_DBG("[dcc_lua_setup]\n");
if (!lua_isnumber(L, 6) && !lua_isnumber(L, 7)) { int narg = 1;
return luaL_error(L, "wrong arg range"); uint8_t pin = luaL_checkinteger(L, narg);
} luaL_argcheck(L, platform_gpio_exists(pin) && pin>0, narg, "Invalid interrupt pin");
uint8_t pin = luaL_checkinteger(L, 1); narg++;
luaL_argcheck(L, platform_gpio_exists(pin) && pin>0, 1, "Invalid interrupt pin");
int8_t ackpin = -1;
if (lua_type(L, narg) == LUA_TNUMBER) {
ackpin = luaL_checkinteger(L, narg);
luaL_argcheck(L, platform_gpio_exists(ackpin), narg, "Invalid ack pin");
narg++;
}
if (lua_type(L, 2) == LUA_TFUNCTION) if (lua_isfunction(L, narg)) {
{ lua_pushvalue(L, narg++);
lua_pushvalue(L, 2);
register_lua_cb(L, &notify_cb); register_lua_cb(L, &notify_cb);
} } else {
else
{
unregister_lua_cb(L, &notify_cb); unregister_lua_cb(L, &notify_cb);
} }
uint8_t ManufacturerId = luaL_checkinteger(L, 3); uint8_t ManufacturerId = luaL_checkinteger(L, narg++);
uint8_t VersionId = luaL_checkinteger(L, 4); uint8_t VersionId = luaL_checkinteger(L, narg++);
uint8_t Flags = luaL_checkinteger(L, 5); uint8_t Flags = luaL_checkinteger(L, narg++);
uint8_t OpsModeAddressBaseCV = luaL_checkinteger(L, 6); uint8_t OpsModeAddressBaseCV = luaL_checkinteger(L, narg++);
if (lua_type(L, 7) == LUA_TFUNCTION) if (lua_istable(L, narg)) {
{ // This is the raw CV table
lua_pushvalue(L, 7); lua_pushvalue(L, narg++);
register_lua_cb(L, &CV_cb); register_lua_cb(L, &CV_ref);
} else {
unregister_lua_cb(L, &CV_ref);
} }
else
{ if (lua_isfunction(L, narg)) {
lua_pushvalue(L, narg++);
register_lua_cb(L, &CV_cb);
} else {
unregister_lua_cb(L, &CV_cb); unregister_lua_cb(L, &CV_cb);
} }
if (ackpin >= 0) {
// Now start things up
if (!platform_hw_timer_init(TIMER_OWNER, FRC1_SOURCE, FALSE)) {
// Failed to init the timer
luaL_error(L, "Unable to initialize timer");
}
platform_hw_timer_set_func(TIMER_OWNER, cvAckComplete, 0);
platform_gpio_write(ackpin, 0);
platform_gpio_mode(ackpin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT);
}
NODE_DBG("[dcc_lua_setup] Enabling interrupt on PIN %d\n", pin); NODE_DBG("[dcc_lua_setup] Enabling interrupt on PIN %d\n", pin);
ackPin = ackpin;
ackInProgress = FALSE;
dcc_setup(pin, ManufacturerId, VersionId, Flags, OpsModeAddressBaseCV ); dcc_setup(pin, ManufacturerId, VersionId, Flags, OpsModeAddressBaseCV );
return 0; return 0;
...@@ -249,13 +364,22 @@ static int dcc_lua_setup(lua_State* L) { ...@@ -249,13 +364,22 @@ static int dcc_lua_setup(lua_State* L) {
static int dcc_lua_close(lua_State* L) { static int dcc_lua_close(lua_State* L) {
dcc_close(); dcc_close();
unregister_lua_cb(L, &notify_cb); unregister_lua_cb(L, &notify_cb);
unregister_lua_cb(L, &CV_cb);
unregister_lua_cb(L, &CV_ref);
return 0; return 0;
} }
int luaopen_dcc( lua_State *L ) { static void dcc_task(os_param_t param, uint8_t prio)
NODE_DBG("[dcc_luaopen]\n"); {
(void) prio;
notifyCVNoArgs(param);
}
int dcc_lua_init( lua_State *L ) {
NODE_DBG("[dcc_lua_init]\n");
dcc_init(); dcc_init();
//DccRx.lua_cb_ref = LUA_NOREF; tasknumber = platform_task_get_id(dcc_task);
return 0; return 0;
} }
...@@ -278,6 +402,7 @@ LROT_BEGIN(dcc, NULL, 0) ...@@ -278,6 +402,7 @@ LROT_BEGIN(dcc, NULL, 0)
LROT_NUMENTRY( CV_READ, CV_READ ) LROT_NUMENTRY( CV_READ, CV_READ )
LROT_NUMENTRY( CV_WRITE, CV_WRITE ) LROT_NUMENTRY( CV_WRITE, CV_WRITE )
LROT_NUMENTRY( CV_RESET, CV_RESET ) LROT_NUMENTRY( CV_RESET, CV_RESET )
LROT_NUMENTRY( CV_ACK_COMPLETE, CV_ACK_COMPLETE )
LROT_NUMENTRY( MAN_ID_JMRI, MAN_ID_JMRI) LROT_NUMENTRY( MAN_ID_JMRI, MAN_ID_JMRI)
LROT_NUMENTRY( MAN_ID_DIY, MAN_ID_DIY) LROT_NUMENTRY( MAN_ID_DIY, MAN_ID_DIY)
...@@ -289,4 +414,4 @@ LROT_BEGIN(dcc, NULL, 0) ...@@ -289,4 +414,4 @@ LROT_BEGIN(dcc, NULL, 0)
LROT_NUMENTRY( FLAGS_DCC_ACCESSORY_DECODER, FLAGS_DCC_ACCESSORY_DECODER ) LROT_NUMENTRY( FLAGS_DCC_ACCESSORY_DECODER, FLAGS_DCC_ACCESSORY_DECODER )
LROT_END(dcc, NULL, 0) LROT_END(dcc, NULL, 0)
NODEMCU_MODULE(DCC, "dcc", dcc, luaopen_dcc); NODEMCU_MODULE(DCC, "dcc", dcc, dcc_lua_init);
...@@ -7,23 +7,25 @@ The dcc module implements decoder of the [National Model Railroad Association](h ...@@ -7,23 +7,25 @@ The dcc module implements decoder of the [National Model Railroad Association](h
The hardware needed to decode the DCC signal can be built based on different DCC decoders implementation for Arduino, for inspiration see [https://mrrwa.org/dcc-decoder-interface/](https://mrrwa.org/dcc-decoder-interface/). Basically the signal from the DCC bus is connected via an optocoupler to any GPIO pin. The DCC bus can be also used to power the ESP. The hardware needed to decode the DCC signal can be built based on different DCC decoders implementation for Arduino, for inspiration see [https://mrrwa.org/dcc-decoder-interface/](https://mrrwa.org/dcc-decoder-interface/). Basically the signal from the DCC bus is connected via an optocoupler to any GPIO pin. The DCC bus can be also used to power the ESP.
The module is based on the project NmraDcc [https://github.com/mrrwa/NmraDcc](https://github.com/mrrwa/NmraDcc) by Alex Shepherd. The module is based on the version from May 2005, commit [6d12e6cd3f5f520020d49946652a94c1e3473f6b](https://github.com/mrrwa/NmraDcc/tree/6d12e6cd3f5f520020d49946652a94c1e3473f6b). The module is based on the project NmraDcc [https://github.com/mrrwa/NmraDcc](https://github.com/mrrwa/NmraDcc) by Alex Shepherd (@kiwi64ajs). The module is based on latest commit from Oct 2020, commit [7e3b3e346991d74926e6c4f6fb46e27156b08578](https://github.com/mrrwa/NmraDcc/tree/7e3b3e346991d74926e6c4f6fb46e27156b08578).
## dcc.setup() ## dcc.setup()
Initializes the dcc module and links callback functions. Initializes the dcc module and links callback functions.
#### Syntax #### Syntax
`dcc.setup(DCC_command, ManufacturerId, VersionId, Flags, OpsModeAddressBaseCV, CV_callback)` `dcc.setup(Pin, [AckPin, ] DCC_command, ManufacturerId, VersionId, Flags, OpsModeAddressBaseCV [, CV_table] [, CV_callback])`
#### Parameters #### Parameters
- `Pin` the GPIO pin number connected to the DCC detector (must be interrupt capable pin).
- `AckPin` the (optional) GPIO pin number connected to the ACK mechanism. Will be set HIGH to signal an ACK.
- `DCC_command(cmd, params)` calllback function that is called when a DCC command is decoded. `cmd` parameters is one of the following values. `params` contains a collection of parameters specific to given command. - `DCC_command(cmd, params)` calllback function that is called when a DCC command is decoded. `cmd` parameters is one of the following values. `params` contains a collection of parameters specific to given command.
- `dcc.DCC_RESET` no additional parameters, `params` is `nil`. - `dcc.DCC_RESET` no additional parameters, `params` is `nil`.
- `dcc.DCC_IDLE` no additional parameters, `params` is `nil`. - `dcc.DCC_IDLE` no additional parameters, `params` is `nil`.
- `dcc.DCC_SPEED` parameters collection members are `Addr`, `AddrType`, `Speed`,`Dir`, `SpeedSteps`. - `dcc.DCC_SPEED` parameters collection members are `Addr`, `AddrType`, `Speed`, `Dir`, `SpeedSteps`.
- `dcc.DCC_SPEED_RAW` parameters collection members are `Addr`, `AddrType`, `Raw`. - `dcc.DCC_SPEED_RAW` parameters collection members are `Addr`, `AddrType`, `Raw`.
- `dcc.DCC_FUNC` parameters collection members are `Addr`, `AddrType`, `FuncGrp`,`FuncState`. - `dcc.DCC_FUNC` parameters collection members are `Addr`, `AddrType`, `FuncGrp`, `FuncState`.
- `dcc.DCC_TURNOUT` parameters collection members are `BoardAddr`, `OutputPair`, `Direction`,`OutputPower` or `Addr`, `Direction`,`OutputPower`. - `dcc.DCC_TURNOUT` parameters collection members are `BoardAddr`, `OutputPair`, `Direction`, `OutputPower` or `Addr`, `Direction`, `OutputPower`.
- `dcc.DCC_ACCESSORY` parameters collection has one member `BoardAddr` or `Addr` or `State`. - `dcc.DCC_ACCESSORY` parameters collection has one member `BoardAddr` or `Addr` or `State`.
- `dcc.DCC_RAW` parameters collection member are `Size`, `PreambleBits`, `Data1` to `Data6`. - `dcc.DCC_RAW` parameters collection member are `Size`, `PreambleBits`, `Data1` to `Data6`.
- `dcc.DCC_SERVICEMODE` parameters collection has one member `InServiceMode`. - `dcc.DCC_SERVICEMODE` parameters collection has one member `InServiceMode`.
...@@ -35,11 +37,13 @@ Initializes the dcc module and links callback functions. ...@@ -35,11 +37,13 @@ Initializes the dcc module and links callback functions.
- `dcc.FLAGS_OUTPUT_ADDRESS_MODE` This flag applies to accessory decoders only. Accessory decoders normally have 4 paired outputs and a single address refers to all 4 outputs. Setting this flag causes each address to refer to a single output. - `dcc.FLAGS_OUTPUT_ADDRESS_MODE` This flag applies to accessory decoders only. Accessory decoders normally have 4 paired outputs and a single address refers to all 4 outputs. Setting this flag causes each address to refer to a single output.
- `dcc.FLAGS_AUTO_FACTORY_DEFAULT` Call DCC command callback with `dcc.CV_RESET` command if CV 7 & 8 == 255. - `dcc.FLAGS_AUTO_FACTORY_DEFAULT` Call DCC command callback with `dcc.CV_RESET` command if CV 7 & 8 == 255.
- `OpsModeAddressBaseCV` Ops Mode base address. Set it to 0? - `OpsModeAddressBaseCV` Ops Mode base address. Set it to 0?
- `CV_table` The CV values will be directly accessed from this table. metamethods will be invoked if needed. Any errors thrown will cause the CV to be considered invalid. Using this option will prevent `CV_VALID`, `CV_READ`, `CV_WRITE` and `CV_ACK_COMPLETE` from happening.
- `CV_callback(operation, param)` callback function that is called when any manipulation with CV ([Configuarion Variable](https://dccwiki.com/Configuration_Variable)) is requested. - `CV_callback(operation, param)` callback function that is called when any manipulation with CV ([Configuarion Variable](https://dccwiki.com/Configuration_Variable)) is requested.
- `dcc.CV_VALID`to determine if a given CV is valid. This callback must determine if a CV is valid and return the appropriate value. `param` collection has members `CV` and `Value`. - `dcc.CV_VALID` to determine if a given CV is valid and (possibly) writable. This callback must determine if a CV is readable or writable and return the appropriate value(0/1/true/false). The `param` collection has members `CV` and `Writable`.
- `dcc.CV_READ` to read a CV. This callback must return the value of the CV. `param` collection has one member `CV` determing the CV number to be read. - `dcc.CV_READ` to read a CV. This callback must return the value of the CV. The `param` collection has one member `CV` determing the CV number to be read.
- `dcc.CV_WRITE` to write a value to a CV. This callback must write the Value to the CV and return the value of the CV. `param` collection has members `CV` and `Value`. - `dcc.CV_WRITE` to write a value to a CV. This callback must write the Value to the CV and return the value of the CV. The `param` collection has members `CV` and `Value`. Ideally, the final value should be returned -- this may differ from the requested value.
- `dcc.CV_RESET` Called when CVs must be reset to their factory defaults. - `dcc.CV_RESET` Called when CVs must be reset to their factory defaults.
- `dcc.CV_ACK_COMPLETE` Called when an ACK pulse has finished being sent. Only invoked if `AckPin` is specified.
#### Returns #### Returns
`nil` `nil`
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment