Feb 16, 2020
is this functionality not available with the Classic?
Technically yes. The question is if we cover that for Classic or just make a passing reference but fully support it in EX. All this is great for discussion. As soon as we move from a USB connection from a PC/Mac/Pi to wireless, we are getting into more advanced installation. Using VNC to remote into the desktop of a computer to use a phone or tablet (other than just using the JMRI server for a throttle) is also advanced. Maybe we put this into the UNU/Classic docs or maybe we say, "for information on this, see the full user guide/technical reference guide". Everyone's input here is going to be valuable in adhering to your mantra of keep it simple, but yet giving people options beyond the basic setup.
I was just thinking that someone interested in using a phone throttle might feel forced up from the entry level. You might loose some on the decision and others in trying to implement the more advanced solution. I would recommend not underselling the Classic.
Thanks @bocabob. If anyone wants to contribute ideas or work to the documentation portion of this, please take a look at an update I posted to our documentation thread.
DCC++ 2020 Update Project documentation
you can still use a phone throttle with Engine Driver or whatever the Apple version is for JMRI so I agree with keeping wireless out of classic. I do agree we need to market it as the easy setup, cheapest, fastest to implement, etc but honestly it's still quite a powerful system that will meet probably 90% of modelers needs. We need to document (or link to documents) using JMRI for phone throttle but this has nothing to do with the actual code or hardware for classic.
To be clear though I don't think our purpose is really to extend functionality (aka add wireless) to Classic. Thats's what EX is for.
I agree. I think somehow make it clear that with a Pi and Steve's SD image wireless throttles are already functional without any other setup needed as it uses the Pi as a dedicated wireless network. Looks like it is also an option with a computer as long as there is an available network to use (more steps for someone new).
Having wireless throttles was one of the main selling points why I finally decided to try DCC++/Arduino/Pi over a commercial alternative. About any commercial system I looked at I'd have at least $300 or more to get setup and also have a wireless throttle.
I think we are just not on the same page in our what we are referring to regarding "wireless". We are talking about networking the Arduino, not on a Pi or computer. As Keith mentioned, The Pi is already setup to allow a wireless throttle through JMRI. Installing a wifi shield or some other method to have direct control into the Arduino or to remove the USB cable and have JMRI connect to the Arduino wirelessly is not in the scope of the basic system.
I agree with that and understood. Just think the wording has to be clear that the basic will still provide the option of wireless throttles, since it is a big deal to some of us. I feel that most new comers to DCC will associate the mention of wireless to mean throttles and if they see wording that basic doesn't support wireless they will think that means throttles.
I misunderstood then If you have any verbiage to add or subtract, please do! I hope someone on the other threat volunteers to help with documentation.
@haba Harald, PM ing you to ask some questions, but posting here so people see we are looking at your code and seeing how to utilize that. Maybe others have questions too.
I'll try to answer some questions about what I've done to the code here
> Gregg had packet->register->registerlist you renamed packet to register and removed register. Why?
In Greggs code a registerlist has registers and these registers contain 2 packets (active and inactive) each. To safe space I removed one packet and then that level was not necessary any more. Because it was less coding work what was previous called packet is now called register (packet and register are now the same thing). Instead of dubble buffering now a new incoming command is now always written into a new place in the package list and thn the old one is invalidated and recycled later. The bit that is controlling "invalid" is the last of the 72 bits in the packet. A DCC packet is never 72 bits long so there was space left.
> You created "isProgRegister". Is this to simplify the code and know if you have a program track register or a main track register?
Normal comands are OK with a 14 bit preamble. The standars says service commands use a longer preamble. So there we use 22 bit. But this is only neccessary on the programming track and the progranming commands are shorter so we in that case use a longer preamble and use "of" (offset) to move everything 1 byte to the right. The isProgRegister is not strictly necessary because if (nBytes <= 5) would be enough but this way we can get out more commands in the same time on the main track.
> RegisterList(int, byte=0); <-- added a byte parameter
This is the isProgReg parameter
> byte ackdetect(int) volatile;
There was a lot of duplicated code which waited for the ack. I moved it all into one place. I now use both prog register 0 and prog register 1 (for commands that should be repeated until something happens).
You may have spotted the packetsTransmitted counter which is used when the standard says "wait for X packets".
acktime = (unsigned long)(lowflankMicros - upflankMicros);
This is a horrible cluge as on the UNO these are _not_ micros but the TIMER0 runs approx 8-10 times faster depending what bits go out on the PWM. So I plan to rework this by counting DCC-one-bit-times in the interrupt routine and then using that as a time base to measure the ack pulse. All calculations of timeouts etc are done as (unsigned long)(COUTERNOW-COUNTERBEFORE) because like this you can handle overflows automatically.
The code in ackdetect is a bit hairy but if you uncomment all the print statements you can see on the serial line a dot for every iteration, the current, the upflank detection "^" and the downflank "v" and the return. Good decoders like Zimo have exact 6ms ack pulses.
> byte poweron() volatile;
Automatic poweron of the programming track when such a command comes in (if necessary). Returns previous state of prog track power so we know if we should turn off the light again when leaving.
> int readBaseCurrent() volatile;
reuturns the base current level (removing duplicated code)
> In packetRegister.cpp:
> You changed from a "while loop" to an "if/then" and have nReg as a "direct out" register. What are you doing here? > You added code here to check for a recycleReg.
I moved where the busy wait happens (as late as possible)
The recycleReg is part of the strategy to get rid of double buffering (see above)
I think it's more clear to see what happened if you look at the old and new versions side by side and orient yourself at the lines where the comments are still the same (modulo whitespace).
If I'm following the code correctly, I don't think I'm on board with this variance in lines 72-75 to use a 22-bit preamble for service mode programming and use a 14-bit preamble otherwise.
Circling back to an earlier post to bring some more recent folks up to speed, a minimum 16-bit preamble is needed to facilitate full RailCom capabilities. Note that by saying facilitate I am not saying that this project needs to implement RailCom capabilities right now; rather, by facilitate, I mean that the end-users have the option to add a RailCom cutout device to their setup if they so choose.
As was also noted in that post, the SPROG unfortunately does not facilitate full RailCom capabilities because it only outputs a 14-bit preamble.
Ensuring a minimum 16-bit preamble would (I hope) be a minor consideration compared to the benefit of not restricting/limiting end-users in how they might wish to expand their system.
…I guess to even take a step back, and I see it is in both code bases we are looking at, but does the preamble need to be stored along with the rest of the packet register?
I realize it's a bit different animal, but the H8/300 implementation I'm a little familiar with dynamically generates the protocol structure that envelopes a packet (including the preamble), so those bits that are part of the protocol structure aren't consuming storage space in the master packet record.
That may be a good way to rewrite this. Preamble is static, so why not just wrap it around the data packet outside of that struct? Let's see if we are missing something that would prevent doing that.
Also, how critical is timing here if we used a 16bit and 22bit preamble? Do we cut it too close with 16?
Other standard protocol structure bits such as the packet start bit, the data byte start bit, and the packet end bit are also generated in the H8/300 code. Implementing it that way also helped line up the DCC "bytes" with the bytes in the software, instead of having to bit-shift things around before storing in the master packet/register list.
While by spec a 16-bit preamble is the minimum to support full RailCom, more certainly wouldn't hurt. I'm not sure how rigid-to-spec the DCC timing would remain if the device gets busy.
No, of course not, I was already thinking about removing the preamble from the register. But I was a bit reluctant as it is a big code change and I do not have a DCC packet sniffer to verify if I coded right.
I think it is possible to do RailCom cutouts and 14 bit preamble but some devices might have difficulties with that. So yes we should have 16 bit there if that makes live easier.
So let's look at the code again and figure out how to only store the actual data part of the packet.
Oh yes, I certainly hear you on that in trying to update "inherited" code! :-O
Per my understanding, only a short RailCom cutout is possible with anything less than a 16-bit preamble, and a short cutout is not enough to fully utilize all RailCom capabilities. With a 16-bit or greater preamble, a long cutout is possible, which opens up the full set of RailCom capabilities.
If it might be of any help for comparative reference to a different style of DCC implementation, the pertinent H8/300 DCC code is as follows:
Low-level assembly routines
Again, this is just intended for comparative reference; I'm certainly not proposing it as the gold standard for implementation. I don't know if anyone has ever even hooked up a packet inspector to the output, so it might be a #WorksForMe kind of thing. DCC was also add-on functionality in this system and not the primary function, so there's that, too. Still, if it might be of use…
I think I implemented it. Have a look at the branch generatepreamble and find if I introduced any bugs ;-)
It still runs with 14 on the main and 22 on the prog track because I wanted now to keep the output the same. But you can change the 14 to a 16 and get a 16 bit preamble if you want.
Thanks for the pointer, I'm not sure if that amount of assembly helps me or scares me ;-) A first look shows me that comments are not that frequent in that code. There I like the DCC++ code so much better.