dcc.lua 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. -- Simple example for responding to NMRA DCC commands
  2. -- author @voborsky
  3. local PIN = 2 -- GPIO4
  4. local addr = 0x12a
  5. local CV = {[29]=0,
  6. [1]=bit.band(addr, 0x3f), --CV_ACCESSORY_DECODER_ADDRESS_LSB (6 bits)
  7. [9]=bit.band(bit.rshift(addr,6), 0x7) --CV_ACCESSORY_DECODER_ADDRESS_MSB (3 bits)
  8. }
  9. local function deepcopy(orig)
  10. local orig_type = type(orig)
  11. local copy
  12. if orig_type == 'table' then
  13. copy = {}
  14. for orig_key, orig_value in next, orig, nil do
  15. copy[deepcopy(orig_key)] = deepcopy(orig_value)
  16. end
  17. setmetatable(copy, deepcopy(getmetatable(orig)))
  18. else -- number, string, boolean, etc
  19. copy = orig
  20. end
  21. return copy
  22. end
  23. local cmd_last
  24. local params_last
  25. local function is_new(cmd, params)
  26. if cmd ~= cmd_last then return true end
  27. for i,j in pairs(params) do
  28. if params_last[i] ~= j then return true end
  29. end
  30. return false
  31. end
  32. local function DCC_command(cmd, params)
  33. if not is_new(cmd, params) then return end
  34. if cmd == dcc.DCC_IDLE then
  35. return
  36. elseif cmd == dcc.DCC_TURNOUT then
  37. print("Turnout command")
  38. elseif cmd == dcc.DCC_SPEED then
  39. print("Speed command")
  40. elseif cmd == dcc.DCC_FUNC then
  41. print("Function command")
  42. else
  43. print("Other command", cmd)
  44. end
  45. for i,j in pairs(params) do
  46. print(i, j)
  47. end
  48. print(("="):rep(80))
  49. cmd_last = cmd
  50. params_last = deepcopy(params)
  51. end
  52. local function CV_callback(operation, param)
  53. local oper = ""
  54. local result
  55. if operation == dcc.CV_WRITE then
  56. oper = "Write"
  57. CV[param.CV]=param.Value
  58. elseif operation == dcc.CV_READ then
  59. oper = "Read"
  60. result = CV[param.CV]
  61. elseif operation == dcc.CV_VALID then
  62. oper = "Valid"
  63. result = 1
  64. elseif operation == dcc.CV_RESET then
  65. oper = "Reset"
  66. CV = {}
  67. end
  68. print(("[CV_callback] %s CV %d%s")
  69. :format(oper, param.CV, param.Value and "\tValue: "..param.Value or "\tValue: nil"))
  70. return result
  71. end
  72. dcc.setup(PIN,
  73. DCC_command,
  74. dcc.MAN_ID_DIY, 1,
  75. -- Accessories (turnouts) decoder:
  76. --bit.bor(dcc.FLAGS_AUTO_FACTORY_DEFAULT, dcc.FLAGS_DCC_ACCESSORY_DECODER, dcc.FLAGS_MY_ADDRESS_ONLY),
  77. -- Cab (train) decoder
  78. bit.bor(dcc.FLAGS_AUTO_FACTORY_DEFAULT),
  79. 0, -- ???
  80. CV_callback)