mrrwa / NmraDcc

NMRA Digital Command Control (DCC) Library
GNU Lesser General Public License v2.1
137 stars 53 forks source link

Signal decoder save state to EEPROM #69

Closed adrianleh closed 1 year ago

adrianleh commented 1 year ago

Hi,

I'm building my own signal (as in railway signal) decoder using your library. For this to work correctly, I need to persist the signal state to EEPROM, so that signals still show the same value after a reboot.

Hence, I have two questions:

  1. How do I best store the state? Do I use the CV library or are there EEPROM addresses I can mess with myself such that the library is not impacted?
  2. Does DCC specify (and your library support) a shutdown command? (This would be useful to have fewer write cycles and only persist at shutdown time, instead of multiple times throughout the operation)

Thanks!

kiwi64ajs commented 1 year ago

Hi Adrian,

On 21/02/2023, at 1:13 PM, Adrian Lehmann @.***> wrote: Hi, I'm building my own signal (as in railway signal) decoder using your library. For this to work correctly, I need to persist the signal state to EEPROM, so that signals still show the same value after a reboot.

Ok, sounds good.

Hence, I have two questions:

How do I best store it? Do I use the CV library or are the EEPROM addresses I can mess with myself such that the library is not impacted? The library learns the EEPROM size based on various C MACRO definitions on the different platforms and sets MAXCV. This effectively sets the upper bound for CV addressing, but that is about all.

Nothing would stop you from defining your own CVs to store the dynamic state to restore on start-up and use the CV Read/Write methods in the library or just access the EEPROM.Read/Write functions and know to avoid used addresses. There isn’t anything magic about how the EEPROM is accessed, except some platforms might have tried to use deferred writes because they emulate EEPROM with FLASH.

You should cache the state in RAM and defer writing every change until some idle timeout or a Reset/Reboot condition is met.

Does DCC specify (and your library support) a shutdown command? (This would be useful to have fewer write cycles and only persist at shutdown time, instead of every time a signal is changed) I’m not really aware of such a thing, although it would be useful. There are the Decoder “Reset" and "Hard Reset” commands which may help. They are defined on lines 100..131 of the DCC spec document here:

https://www.nmra.org/sites/default/files/s-9.2.1_2012_07.pdf <https://www.nmra.org/sites/default/files/s-9.2.1_2012_07.pdf>

The main issue will be to cause the DCC Command Station to generate that Reset when you want it. You might be better off adopting a Broadcast CV Write to a particular CV Address to cause the persist and Reset, say.

Not as tidy as you’d hope, huh…

What DCC System do you have?

Alex

adrianleh commented 1 year ago

Hi Alex,

thanks for the super detailed response. Thanks for the idea of the custom CV definition, that sounds like a clean way to solve the issue. I have also already wrote scripts that wait until there has been no writes for 10sec and then writes.

As for your latter point to the Reset and my DCC system: I currently test with a DCCex system but am planning on integrating this with a Maerklin Central Station 2 once I know it works. So I think generating resets will be quite tough, unfortunately. But if you have any ideas or other insight on Maerklin DCC systems, that'd be super helpful.

Thanks!

kiwi64ajs commented 1 year ago

Hi Adrian,

On 21/02/2023, at 3:59 PM, Adrian Lehmann @.***> wrote: Hi Alex, thanks for the super detailed response. Thanks for the idea of the custom CV definition, that sounds like a clean way to solve the issue. I have also already wrote scripts that wait until there has been no writes for 10sec and then writes.

Yep, that’s the right type of thing. As for your latter point to the Reset and my DCC system: I currently test with a DCCex system but am planning on integrating this with a Maerklin Central Station 2 once I know it works. So I think generating resets will be quite tough, unfortunately.

Unfortunately, your most accessible option may be to write a special CV value to a Custom CV Address in your decoders to do the Save/Reset.

Depending on what else is on your local DCC Track/Signal, you could survey the various values other decoders use to reset factory defaults by writing special values to CV8.

The DCC Wiki might help here, but the key is to find a CV8 value that doesn’t clash with other decoder resets so that it will be ignored except for your decoders.

Have a look at the library source code for:

notifyCVResetFactoryDefault()
notifyCVValid()
notifyCVRead()
notifyCVWrite()

as you might come up with a strategy that works for you, else maybe suggest an enhancement to the library and I can probably add it.

But if you have any ideas or other insight on Maerklin DCC systems, that'd be super helpful.

Sorry, I don’t have any exposure or experience with anything Maerklin so not much help.

Alex

adrianleh commented 1 year ago

The custom CV idea sounds interesting. I'll see what I can implement with that and if something useful should fall out of it, I'll make a PR.

I think that answers the questions of the issue and I'll go ahead and close it. Thank you for your help, Alex!