First drafted in log 3. Even more drafting
n00n is not a traditional network protocol and this is obvious when looking at the naming system. It borrows a few principles from MIDI of course, and some fuzzy ideas from ATM and DHCP might also linger somewhere.
n00n has 3 complementary levels or types of naming:
- the device-level ID or address,
- the logic-level Serial string
- the user-defined Label for convenience.
At the very bottom, there is only one 16-bit ID (or "address") field in the packets (of course associated to only one device). As noted before, this is overkill for the expected type of application (a dozen devices at most, maybe) but the first argument is "hey, they are available". And from there, it enables new constructs, such as dynamically allocated addresses (unlike MIDI which requires careful manual configuration because the range is pretty narrow: only 16 channels !). A 16-bit space is great because it keeps the chances of collisions low if the addresses are "chosen at random" (but see The Birthday problem). This way, a device can be plugged and operational in the n00n signal path with almost no effort : a new stream appears from a given address and that would be all.
In practice it's a bit more complex because collisions remain possible and must be avoided. The first draft proposed that an "upstream" device could force downstream devices to reallocate to new addresses, because the serial link is considered as a "one-way path" and an upstream device can not know what's going on at the end of the daisy chain. An ID reallocation could eventually cause an avalanche of reallocations downstream so it's not a preferred method.
This is solved by closing the daisy-chain and turning it into a ring. The Global Timestamp Generator can also serve as the closing point, filtering all the raw instrument data and letting the control messages pass for one more round in the ring (eventually setting a bit to prevent more than one round). This way, a device can "probe" the ring by sending a "-2: ping" to the desired address, and if it comes back unaltered, then the candidate address is adopted (otherwise, try another pseudo-random address).
Of course the system is different for a star topology.
The candidate address can be generated from any source of entropy, one of them is consecutive checksums of the unique Serial string. When it is adopted, the known-good address is stored in non-volatile memory to reduce the chances of collisions in the future.
There is no "special" address. There is no "broadcast" system because the daisy-chain or ring transmit all the data to all the devices downstream, unless one device recognises its own address : the 16-bit ID is thus both a source and destination address. Of course this makes a driver a bit more delicate for star topologies likes USB and Ethernet but it's not impossible to solve with enough embedding and extra parameters.
The device ID (address) is implicitly handled in the protocol stack, however the Label and the Serial are explicit higher-level messages whose values are stored in non-volatile memories. Here are relevant Packet types:
-3 : Label
This packet allows getting and setting the "label" of a device (when possible). This packet can be emitted when the user changes the label on the device itself, so the DAW can update its display. But the DAW can also send this packet to inquire and/or change the label remotely.
When receiving a Label message, check if the ID matches, otherwise forward.
If the ID matches, check the set/get flag : if the flag is "set" then update the device's local label.
Then confirm by sending a Label message containing the device's label (1 to 256 UTF-8 bytes).
-4 : Serial
Get the non-volatile identification of the device : manufacturer, model, revision, date, serial number...
When receiving an empty Serial message with an ID that matches the device, the device sends a Serial message with a UTF-8 payload containing the detailed information.
More options or details could be obtained or selected using the Flags field. TBD.
So the label is what gets displayed on the DAW's GUI, next to the relevant information. It could change from project to project, it's totally dynamic but this ephemeral short string is meant to be practical and configurable. It could be displayed on the device's screen and/or edited there as well.
The Serial string is guaranteed unique and fixed so it is certain to identify a single device, and it doesn't change, so this is what the DAW uses to internally identify the device. The volatile ID and label are associated to this internal string.
In the end, the whole system built from these devices should be "plug and play", with a very short automatic setup. Any new data stream that is detected from an unknown address can be immediately classified by the DAW which will enquire the capabilities, the eventual existing label, the Serial string, and deduce some temporary label name from the type of packets that are received, which the user can later edit in the project. The DAW can keep a small archive of already plugged devices to remember the label and address, as well.
The only problem with the ring topology is when a device is plugged or unplugged, which breaks the ring and interrupts the stream. Each device must be able to detect when its input is "disconnected" (nothing is received) so only it sends replacement timestamps. Otherwise, other devices downstream may also decide to fire their own timestamps and that would break all the timings. But these are considerations for another log.