Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Turnout vs. Accessory Packet format once and for all #141

Open
FrightRisk opened this issue Apr 10, 2021 · 12 comments
Open

Handle Turnout vs. Accessory Packet format once and for all #141

FrightRisk opened this issue Apr 10, 2021 · 12 comments
Assignees
Labels
Needs Clarification Need more information from the requestor

Comments

@FrightRisk
Copy link
Member

The NMRA spec says that "C" below is activate/deactivate and the X in DDX handles which pair of outputs and the DD specifies which of the 4 outputs is being controlled. But... some decoders can allow DDX to be DDD so you can control 3 things or 2^3 thing (8)

Here is another wording of how acc. packets are being used in practice, despite how I read the specification:
Accessory decoder packet format:

 10AAAAAA 1aaaCDDX

A = Address LSB part
a = Address MSB part in 2s complement
C = individual outputs: 1=0n, 0=0ff,
DD= Turnout number within decoder: 00=>1 .. 11=>4
X = coil select: 0=> straight, 1=> diverging

UKBloke (AKA Chris) — 01/02/2021
But that's not an "accessory" its a "turnout"... and that's where we have so many issues when it comes to non-turnout accessories or non-dcc turnouts!
... and does that mean that to switch this turnout you need to send an "on" and an "off" with some delay between?
FlightRisk — 01/02/2021
True, thanks for making the distinction
But they don't make the distinction in the spec. So I'm not sure if a light or a servo is handled differently. You have 2 bytes and you fill them with 1s and 0s. So a light can be on/off which corresponds to throw/close. What are you seeing with non turnout accessories?
UKBloke (AKA Chris) — 01/02/2021
I'm not even looking........ I'm just trying to imagine the mess....
I'm presuming these accessory messages are coming from JMRI... so why do we have a command at all?
FlightRisk — 01/02/2021
Well the spec briefly mentions this: "Note if the duration the device is intended to be on is less than
or equal the set duration, no deactivation is necessary"
And the "duration" is what is set in CVs515-518 of the decoder
I think our command came from making an artificial distinction between turnouts and other accessories to make it easier to address and save them in EEPROM. We can assign an ID to turnouts internally. It may have also come from how Gregg wanted to code his throttle software.
UKBloke (AKA Chris) — 01/02/2021
I can understand that... we need it similar for ED and RMFT without JMRI..
FlightRisk — 01/02/2021
Honestly, what is the purpose of have 3 bits of the address be in 1s complement form??? Just to make it more difficult to program? I think that came from Lenz in a closed door political thing where the general group was not consulted. But, it is what we have to work with 😉
UKBloke (AKA Chris) — 01/02/2021
We have the accessory command which generates the packet you describe...
FlightRisk — 01/02/2021
Yes, you are right. Well, now is a good time to think it through and do it right.
Happy New Year, BTW 😉
It is still the new year on the other side of the ocean, isn't it?
haha
UKBloke (AKA Chris) — 01/02/2021
I'm not sure what you have in mind... we can't change the packet format because the decoders read that
FlightRisk — 01/02/2021
No, just how we implement our scheme and what has to go in ED, JMRI and RMFT. It plays into my desire to be able to use the JMRI linear addressing directly with one of our commands. It is much easier to say turn whatever responds to address 2045 to ON, than compute an address and subaddress.
UKBloke (AKA Chris) — 01/02/2021
How do you expect to get from address 2045 to addr/subaddr? (obviously the code can do all the bit twiddling but you still need the numbers)
FlightRisk — 01/02/2021
Right. I'll look again at my notes, but if we are just putting bits into a packet, it doesn't matter whether the user inputs a long linear address and on/off or addr/subaddr/on. The packet is created by us. Maybe I am misunderstanding
Shufti:
ok, this seems to work due to weird premises:

  1. accessory only being turnouts (or treating all other accessory as such)
  2. decoder automatically switching off the output

why?
for a turnout with the decoder automatically switching off the output it is sufficient to power on either of the coils via DCC to switch between straight/diverge. So in DCC one only needs "power on" command (bit 3 in byte 2 can be fixed to "on") for either of the usually paired outputs. So bit 0, indicating which of the paired outputs to use, translates the on/off to straight/diverge.

problem (as I see it):
since there is no actual DCC++ command to send "switch off" for a specific decoder output, all accessories need to be treated as turnouts, using one address to switch on and another to switch off, reducing the useable addresses to 50%.

Don_Willsmer — 02/06/2021
For an example with the Lenz 110 you can isssue a command to operate 9 and it will also set 10,11 and 12 the four outputs. However you couldn't set the addresses as 11,12,13 and 14 because they cross two blocks of four. If you set the address to 11 it will assume you are setting the third output . So although you are using a linear address the system knows it is dealing with an address and sub addresses.

From analysing the packet used by Lenz (Compact / Atlas) for points control:
tunAddr = 1 //Accessory decoder address
Turnout 1a : 1000 0001 1111 1000
Turnout 1b : 1000 0001 1111 1001
Turnout 2a : 1000 0001 1111 1010
Turnout 2b : 1000 0001 1111 1011
Turnout 3a : 1000 0001 1111 1100
Turnout 3b : 1000 0001 1111 1101
Turnout 4a : 1000 0001 1111 1110
Turnout 4b : 1000 0001 1111 1111

tunAddr = 2
Turnout 5a : 1000 0010 1111 1000
Turnout 5b : 1000 0010 1111 1001
Turnout 6a : 1000 0010 1111 1010
Turnout 6b : 1000 0010 1111 1011
Turnout 7a : 1000 0010 1111 1100
Turnout 7b : 1000 0010 1111 1101
Turnout 8a : 1000 0010 1111 1110
Turnout 8b : 1000 0010 1111 1111

tunAddr = 3
Turnout 9a : 1000 0011 1111 1000
Turnout 9b : 1000 0011 1111 1001

etc

NMRA Specification:

Basic Accessory Decoder Packet Format:
The format for packets intended for Accessory Digital Decoders is:
{preamble} 0 10AAAAAA 0 1AAACDDD 0 EEEEEEEE 1
Accessory Digital Decoders can be designed to control momentary or constant-on devices, the duration of time each output is active being controlled by configuration variables CVs #515 through 518. Bit 3 of the second byte "C" is used to activate or deactivate the addressed device. (Note if the duration the device is intended to be on is less than or equal the set duration, no deactivation is necessary.) Since most devices are paired, the convention is that bit "0" of the second byte is used to distinguish between which of a pair of outputs the accessory decoder is activating or deactivating. Bits 1 and 2 of byte two are used to indicate which of 4 pairs of outputs the packet is controlling. The most significant bits of the 9-bit address are bits 4-6 of the second data byte. By convention these bits (bits 4-6 of the second data byte) are in ones complement.

@FrightRisk FrightRisk added the Needs Clarification Need more information from the requestor label Apr 10, 2021
@Neil-McK
Copy link
Contributor

Reading the NMRA spec, there are 9 bits allocated to the decoder address (0-511). And there are three bits allocated DDD (0-7) to specify the output to be set or reset.

So it seems rather strange that most documentation refers to address and subaddress, with subaddress only being in the range of 0-3 or 1-4. There seem to be a few possibilities:

  • setting subaddress n on or off causes two pins to be set on or off respectively

  • setting subaddress n on causes one pin to be set on and another to be set off, and vice versa for off.

  • setting subaddress n to a value of 0, 1, 2 or 3 causes two pins to be set accordingly to the MSB and LSB.

  • something else?

Surely the accessory command should be able to address all 8 outputs (4 pairs) on a decoder?

@FrightRisk
Copy link
Member Author

FrightRisk commented May 26, 2021

This is one thing I've become an expert on ;) And once again, there are multiple standards. Most decoders use the address/subaddress method with bit 0 controlling closed/throw and bits 1 and 2 controlling the port (0-3). Maybe I'll write a paper on it with a pretty graphic, but it all comes down to twin coil switch machines which is before a lot of modelers time. and how they worked with 2 solenoids. And then a lot of the decoder manufacturers created decoders with 4 outputs to control 4 turnouts. Depending on the decoder or it's mode selection, you can control 4 turnouts or 8 single outputs. Controlling 8 means you use all three lower order bits and the C bit is activate/deactivate. According to the Wiki, "C activates/deactivates the addressed decoder as needed. The three data bits allow control of up to 8 functions (0-7), split into 2 pairs of 4 outputs."

The question I have is how the 8 functions are supported by us. We don't currently touch the C bit. So how can we support a decoder with 8 outputs?

@Neil-McK
Copy link
Contributor

By 'don't currently touch the C bit' I assume you mean it's 1 in every packet. So on receipt of the command, the decoder sets one or the other of the pair of outputs identified by bit zero, and then de-energises it after a time.

@atanisoft
Copy link
Member

atanisoft commented May 26, 2021

By 'don't currently touch the C bit' I assume you mean it's 1 in every packet.

Very few (if any) modern decoders reference this bit for their runtime usage. It was intended to be used to activate/deactivate dual coil switch machines. However, this functionality has been replaced over time with CDU or alternative switch machines. It does not pertain to selecting an output (0-7) on the decoder.

So how can we support a decoder with 8 outputs?

It is already being supported (indirectly). DCC++ currently supports the board:address (0-511 : 0-3) address format, when converting this to the on-the-wire DCC address the address selects which dcc output pair is selected to be acted upon and the least significant bit in the address selects which output of the pair is "active".

@Neil-McK
Copy link
Contributor

Neil-McK commented May 26, 2021

Assume we continue to use the address/subaddress parameters as is. Then for a specific address/subaddress there are two outputs that can each be set to either of two states, by specifying a 0 or 1 in the LSB of the DDD field and a 0 or 1 in the C bit.

D0  C.   Action
0   1.   Set output 0 of pair
1   1.   Set output 1 of pair
0   0.   Reset output 0 of pair
1   0.   Reset output 1 of pair

(The latter two commands being unnecessary when the decoder automatically resets the output).

One possible way of doing this would seem, to me, to add a command which allows the D bit to be treated as a sub-sub-address and the C bit as the output state. This would allow each of the eight outputs to be set on or off independently. A separate command form would be retained to address a pair of outputs.

For example,
<T 1 DCC 5 3 0> to define a turnout which switches the first output of pair 3 on accessory address 5, with pair 3 being treated as two independent outputs. This output corresponds to DDD=110 binary.
Then <T 1 1> would send a packet with DDD=110 binary, with C=1, and <T 1 0> would send C=0.

<T 2 DCC 7 1> to define a turnout which switches both the outputs in pair 1 on accessory address 7. Pair 1 is addressed by DDD=01x.
Now, <T 2 1> would send C=1, DDD=011 to get the decoder to pulse the second output of the pair, while <T 2 0> would send C=1, DDD=010 to pulse the first output of the pair.

A command in the form <T 2 7 1> would define a turnout as in the T 2 case above, for compatibility with the current commands.

Note: I've used zero base for address, subaddress, and output number above for simplicity. They can equally well be 1 based where convention dictates (e.g. subaddress 1-4).

@atanisoft
Copy link
Member

The most rational way of doing this would seem, to me, to add a command which allows the D bit to be treated as a sub-sub-address and the C bit as the output state. This would allow each of the eight outputs to be set on or off independently. A separate command form would be retained to address a pair of outputs.

The C bit is not used by any commercial decoders that I'm aware of and is always sent as "1" by virtually all DCC Command Stations (including the upcoming TCS one from my understanding). Additionally, all eight outputs are already controlled via the available commands using the least significant bit by DCC++ as a direction bit.

Virtually all decoders on the market today use paired output mode with only one output active at any time. In the case of DIY decoders (arduino based) it is possible to control individual outputs BUT it is an optional configuration on the decoder, see the NmraDcc library code.

However, the current board:index addressing scheme used in DCC++ has caused a lot of confusion and complications for users and switching to using the DCC address for a decoder (individual output or direction based output) can simplify this considerably for the users.

@habazut
Copy link
Contributor

habazut commented May 26, 2021

I heared that there are CS (Roco Maus2 for example) which when you operate a turnout first send the command with C=1 (coil on) and then some ms later to the same address but with C=0 (coil off). But as I do not have the HW I can not verify this.

Regards,
Harald.

@Neil-McK
Copy link
Contributor

Neil-McK commented May 27, 2021

I'm not an expert on accessory decoders, I don't own one of any brand. I'm relying on the manuals to understand what you can do with the various types on the market.

The first manual I find on Google is the Hornby R8247. This has the ability to drive four output pairs, or eight independent outputs. Each of the outputs can be placed in 'continuous' mode where, once turned on, they stay on (rather than pulsing a fixed number of times).

Can you explain how the output is turned off? Looks like a candidate for a packet with C=0?

@atanisoft
Copy link
Member

Can you explain how the output is turned off? Looks like a candidate for a packet with C=0?

If it is "continuous" then yes the "C" bit could in theory be being used by the decoder when configured to use independent outputs mode.

@Neil-McK
Copy link
Contributor

Neil-McK commented May 27, 2021

I may have found the answer myself. It looks like the decoder is able to take up eight consecutive sub addresses, i.e. sub addresses 0-3 (1-4) on two consecutive addresses. The manual doesn't go into details of the DCC commands but could feasibly be set on/off by toggling D bit 0.

If other decoders all operate the same way then, as @atanisoft says, all eight outputs can be driven independently without changing the CS.

The addressing style is a separate issue ..

@Neil-McK
Copy link
Contributor

Neil-McK commented May 27, 2021

Very few (if any) modern decoders reference this bit for their runtime usage.

It would be very strange if any NMRA compliant decoders ignored the C-bit, as it is a requirement of the standard. Likewise, command stations that were not capable of generating packets with C=0 would surely be non-compliant too? So perhaps we still need to change the CS code to cover all bases.

@madmetz
Copy link

madmetz commented Mar 27, 2022

After a while I would like to bring up this issue again. (Please excuse my English in case of mistakes.)
I'm running a DCC++ (not DCC++EX) server on an Arduino Mega 2560 and I've had major problems with RocRail forum members regarding this topic.
For several days I've been trying to get an accessory decoder to work as a controller for an MP3 board.
The issue described here is exactly my problem. I cannot generate an off command for the relevant output.
So I'm not able to use all 8 (4 red, 4 green) outputs of my ESU SwichPilot or my Arduino based accessory decoder.
Since there is no off command, I have to toggle the outputs between red and green to be able to use the same output again.
I.e. I cannot use the same output twice or more.
Almost all accessory decoders on the market have an internal lock (permanently or by timer) that prevents multiple use of the same output.
In my opinion it is therefore absolutely necessary to send the status bit (byte 2 bit 3) to the decoder (at least if it is not working in turnout mode).
Without this bit I can only use 50% of the outputs in case I want to switch e.g. lamps or the inputs of an MP3 decoder.
So instead of sending <a 1 0 0> it should be <a 1 0 0 0> for OFF or <a 1 0 0 1> for ON respectively.
Attached is an NMRA "DCC 8-Turnout Accessory Decoder" trace, if someone is interested in. (Sorry but comments are in German.)
220325_184500_esu_nmra-decoder.log

daniviga pushed a commit to daniviga/CommandStation-EX that referenced this issue Mar 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Clarification Need more information from the requestor
Projects
None yet
Development

No branches or pull requests

8 participants