mrrwa/NmraDcc

OPS mode programming for Accessory Decoder does not work for extended address, missing support?

Opened this issue · 14 comments

I'm using this Wonderfull library to build out an accessory decoder for my layout. I wanted the ability to use OPS mode programming to change some of my custom defined CV's. I'm not sure if I really understand the NMRA standard for handing accessory addressing. It seem both NCE and JRMI systems use extended addressing.
At line 1409 there is this code....

	  else if(pDccMsg->Size == 6) // Accessory Decoder OPS Mode Programming
	  {
        DB_PRINT("eDP: OPS Mode CV Programming Command");
          // Check for unsupported OPS Mode Addressing mode
	  	if(((pDccMsg->Data[1] & 0b10001001) != 1) && ((pDccMsg->Data[1] & 0b10001111) != 0x80))
	  	{
          DB_PRINT("eDP: Unsupported OPS Mode CV Addressing Mode");
          return;
        }
        
          // Check if this command is for our address or the broadcast address
        if(DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE)
        {
          DB_PRINT("eDP: Check Output Address:%d", OutputAddress);
          if((OutputAddress != getMyAddr()) && ( OutputAddress < 2045 ))
          {
            DB_PRINT("eDP: Output Address Not Matched");
          	return;
          }
        }

Both NCE and JMRI seems to send extended addresses for OPS Accessory Decoder programing.
If I make the following changes it seems to work, but I'm not sure if I understand the addressing completely

	  else if(pDccMsg->Size == 6) // Accessory Decoder OPS Mode Programming                       
	  {
            DB_PRINT("eDP: OPS Mode CV Programming Command");
          // Check for unsupported OPS Mode Addressing mode     JMS seems like we dont support extended addr
	  	if((pDccMsg->Data[1] & 0b10001100) == 0b00001100)                    // JMS enabled extended addresses
	  	{
              myDB_PRINT("eDP: Unsupported OPS Mode CV Addressing Mode");                                   
          return;
        }
          // Check if this command is for our address or the broadcast address
        if(DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE)
        {
          //JMS new code to fix address if CDDD = 0
          if((pDccMsg->Data[1] & 0b10001111) == 0x80)                        // JMS NEW
          {                                                                                                      // JMS NEW
            OutputAddress = BoardAddress;                                              // JMS NEW
            DB_PRINT("eDP: Updated Address");                                      // JMS NEW
          }                                                                                                     // JMS NEW

Are my changes correct? I can only test with NCE and JMRI with SPROG but so far seems to work as expected.

Hi Alex,

Thanks for taking a look into this! Now it was my turn to be slow to respond. :). Took me a while to recreate my environment to test this.

I'm not sure what happening, but when use this branch, my code stops received any accessory commands. What I did to verify is I took the master, rebuilt my code. On my "test Arduino", I sent basic turnout commands and they are received as expected. Both with JMRI and Sprog3 and NCE. If I use the Accessory-OPS-CV branch, my test code does not even receive any accessory commands. I also tested the original OPS programming and that does not seem to work either.

My original changes was based on the 2.0.6 release, not sure if this changes or something in between created this new behavior.

Jonathan

Quick update... version 2.0.10 or Last release seems to work with accessory commands, but the Accessory-OPS-CV branch does not seem to receive any accessory commands.

Into Accessory Decoder Mode ops Mode not work, i can't write CV on POM.
Is this library obsolent?

Good day Alex
First of all: Unfortunately, I am not able to express myself precisely and that is why there are sometimes a lot of misunderstandings.
In English, everything is even more difficult and the translation sometimes doesn't work.

First of all, I would like to thank you for programming the library. It works well so far and you can also program the CVs using the service mode.
I just know that reading in POM mode definitely doesn't work because the CPU is too weak/slow and the timing is difficult to achieve.

But at least the writing processes work with APP_DCC (same hardware), which doesn't work with NMRADcc. I think if AP_DCC can do it, why can't NMRAdcc?
I just don't understand that.

NMRAdcc supports the ESP32, which is unfortunately not possible with AP_DCC.
I have made various attempts with NMRAdcc and AP_DCC library. What I have seen is that there is an identifier that is not supported when the CV is written. Trying to find something in debug mode is very difficult for me because I don't know the whole subject of DCC signals very well.
When debugging, I saw that the identifier is returned as «...1100» when writing CVs, but the code only asks for «...0101».

My problem: Unfortunately, I can't remove the device every time I reprogram it and program it in service mode. Or configure the software with the PC via USB. So I used APP_DCC where it works from the hardware.

So is the NMRAdcc library actually still up to date?!

Thanks for your help anyway, I'll keep trying to solve the problem. Although I don't understand how the OPS mode and the address to be passed on work at all. I haven't found any acceptable instructions anywhere (or understood them) on how to pass it on and what exactly happens in the background. It's all very unclear to me.

I used opendcc system and dcc-ex.

Regards
Andrew

I have debuged this. before i have removed the return.
The cv will be written!

DB_PRINT ("eDP: OPS Mode CV Programming Command");
// Check for unsupported OPS Mode Addressing mode
if ( ( (pDccMsg->Data[1] & 0b10001001) != 1) && ( (pDccMsg->Data[1] & 0b10001111) != 0x80))
{
  DB_PRINT("%d", pDccMsg->Data[1]);
    DB_PRINT ("eDP: Unsupported OPS Mode CV Addressing Mode");
   **// return;**
}

Debug result:

eDP: AccCmd: 8F FE EC 23 04 BA 
eDP: BAddr:15, Index:3
eDP: OAddr:60
eDP: OPS Mode CV Programming Command
254
eDP: Unsupported OPS Mode CV Addressing Mode
eDP: Check Output Address:60
eDP: OPS Mode Instruction:3
eDP: CV:36 Value:4
notifyDccCVChange cv:36 val:4
eDP: AccCmd: 8F FE EC 23 04 BA 
eDP: BAddr:15, Index:3
eDP: OAddr:60
eDP: OPS Mode CV Programming Command
254
eDP: Unsupported OPS Mode CV Addressing Mode
eDP: Check Output Address:60
eDP: OPS Mode Instruction:3
eDP: CV:36 Value:4
eDP: AccCmd: 8F FE EC 23 04 BA 
eDP: BAddr:15, Index:3
eDP: OAddr:60
eDP: OPS Mode CV Programming Command
254
eDP: Unsupported OPS Mode CV Addressing Mode
eDP: Check Output Address:60
eDP: OPS Mode Instruction:3
eDP: CV:36 Value:4

Not known what value i musst be add to the "if" of pDccMsg->Data[1] to accept this command cv write.
regards

?:

      // PoM messages (long form)
      // Basic Accesory:    10AA AAAA 1AAA-1AA0 1110-CCVV VVVV-VVVV DDDD-DDDD EEEE-EEEE
      // Extended Accesory: 10AA-AAAA 0AAA-0AA1 1110-CCVV VVVV-VVVV DDDD-DDDD EEEE-EEEE
      if ( ( (pDccMsg->Data[1] & 0b10001001) != 1) 
          && ( (pDccMsg->Data[1] & 0b10001111) != 0x80) // include AA ????
          && ( (pDccMsg->Data[1] & 0b10001001) != 0x88)) 

I used only DCC-EX with iTrain to send the CV change code: Address 60, CV 36 = 4, with opsmode 0 on dcc.init (last param)
AccCmd: 8F FE EC 23 04 BA (6 Byte Accessory Command)
On Menus you can find Decoder programing and DCC-EX is supportet on interface.
On layout drop a signal with dcc addr 60.

You can download iTrain for testing free:
(https://www.berros.eu/de/itrain/)

I not have a command station for open-dcc only a roco maus over wifi and itrain.
the if2 i not use at this time.

hi, i have tested again yesterday and found this solution for me.
But not known is this right.
And unknow if 0b10001111 what you make with this.

      if ( ( (pDccMsg->Data[1] & 0b10001001) != 0b00000001) 
          && ( (pDccMsg->Data[1] & 0b10001001) != 0x10001000)        /////!!!!!andrew add 
          && ( (pDccMsg->Data[2] &  0b11110000) != 0b11100000))         /////!!!!!andrew add 
          //&& ( (pDccMsg->Data[1] & 0b10001111) != 0x80))                /////!!!!!andrew remove, why include AA ????

is this the solution?
regards

OPS mode programming for Accessory Decoder Extended Address work for me.
I have a suggestion.
In NmraDcc.cpp line 1486:
if ( (OutputAddress != getMyAddr()) && (OutputAddress < 2045))
tests the address from DCC packet with Address from CV1 & CV9. These addresses are different. In JMRI Simple Programmer - Program On Main - Ops Accessory Extended Byte - I must use option Offset Address.
It would be possible to build this option into the library and enable it for example:
Dcc.initAccessoryDecoder(MAN_ID_DIY, SW_VERSION, FLAGS_OUTPUT_ADDRESS_MODE, 0, 4) ;
Then the line would look like this:
if ( (OutputAddress + offset != getMyAddr()) && (OutputAddress < 2045))
Then the correction would not be done on the throttle side and it would not be confusing for the user.