The Intelligent Interconnect board's main function is to receive packets from the sign controller and forward them on to the modules. Secondarily, it's purpose is to allow the controller to figure out the configuration of the sign (# of rows). Thirdly, it may have sensors attached and report their data to the sign controller.
On bootup, the IIB should send several handshake packets down each of its strings and determine what's connected to it based on which strings it receives any sort of answer (including error packets) from. If none of the strings return anything, it's probably first generation modules connected. To determine that, it should send a few first-generation global packets (e.g. 0x50 — global clear) and see if we get any back.
Once it determines how many strings are attached, it should query each string to find out what sort of modules are attached. If it's second generation modules, it should send out a what-the-heck-are-you packet to determine the string's length and what modules are on it. If it's first generation modules, the IIB should determine the length of each string attached to it (see below).
It's an error condition if there are any gaps. E.g. if rows 0, 1, and 3 respond, but row 2 doesn't, it's a gap and therefore an error. However, if rows 0, 1, and 2 respond but row 3 doesn't, it's not a gap, it's simply a 3-row sign.
The IIB should be prepared to respond to handshake and what-the-heck-are-you packets from the sign controller based on the information it got during the probing phase.
On bootup, the IIB should run at 9600 on all of its connections. If its probing reveals second generation modules attached, it should negotiate with them to operate at the fastest speed they're capable of. That does not affect the speed of its connection to the sign controller — it's up to the sign controller to try to negotiate that.
Ideally, the interconnect board will run its line to the sign controller at the combined speed of all of its attached strings. That is, if there are three strings running at 115200, the interconnect board will talk to the sign controller at 345600. That speed is what it should advertise as its maximum speed in any sign description packets which it sends out. It's important that the IIB not communicate with the sign faster than it can communicate with all of its strings of modules, because it doesn't have the buffering space.
Note: it is the responsibility of the sign controller not to overload the IIB, and hence the sign controller is responsible for interleaving the data packets by row.
The address is stored in a single byte (in every packet with an address), which is broken into two pieces: the top two bits indicate the row, and the bottom six bits indicate the position within the row.
Modules are required to ignore the top two bits of the addresses in packets, so the IIB is free to forward packets with their addresses unchanged.
The IIB should check all of the incoming packets from the sign controller for a valid CRC
When the IIB receives a global packet, it should simultaneously forward the packet on to each row. It's important that the IIB make sure that this is actually simultaneous — it should hold up sending on any string until it is clear to send on every string.
(Note: it should not be necessary to create separate copies of a global packet to send down each string — every global packet as so far designed should be able to go down each string without change.)
Once the IIB gets a global packet back from at least one string, it should forward it on to the sign controller, so that the sign controller knows that all is well. This should not be forwarded more than once, so it's probably best to simply always forward global packets from the first string.
Note: the IIB should check the other strings to make sure that communication with them hasn't been lost. It's not required to use a timer for this; it's sufficient to make sure that you've gotten the last global packet when the next global arrives. (That is, it's acceptable to put the check for the previous global packet returning from each string when the next global packet from the controller arrives.) That's not required, but since timers are in short supply on the micro, this is probably the easiest behavior.
For local packets (i.e. the data packets) the IIB should forward each packet to only the row indicated in the packet's address.
The IIB is responsible for using No-Op packets to resynchronize communications with the modules on a string when iti gets back a protocol error packet from a module.
When the IIB receives an error packet from a module, it's responsible for modifying the packet so that the address in the error packet contains the row information. (The module will have sent it out with a row of 0.)
In compatibility mode, for each byte that comes in from the sign, the IIB first examines it to see if it's a handshake packet. If it is, the IIB switches into second generation mode. If it isn't, the IIB forwards the byte on to the first row. Anything coming back from the first row gets forwarded to the second row. Anything coming back from the second row gets forwarded to the third row. Anything coming back from the third row gets forwarded back to the sign controller.
Optionally, the IIB can recognize global packets in the original protocol and forward them on to each row simultaneously. This is probably not worth the development work, but it wouldn't hurt.
Since all packets to be forwarded should be forwardable without any changes, the IIB should be able to send the packets out of its input buffer without doing any copying. This was a design goal of the second generation protocol.
Due to the way that the sign controller sends data continuously but the IIB has to wait until a packet has arrived entirely before it can re-send the packet down a string (so that it can check the CRC), there will be a little lag introduced. The lag should, however, be fixed and should not accumulate. The input buffer does, therefore, have to be big enough to accomodate at least two of the largest packets for each row. In practice, it should be a little bit larger to accomodate global packets.
The IIB will therefore need to be able to queue packets to be send down each pipe. Queueing also allows the IIB to satisfy the simultaneity requirement for global packets.
Because the sign controller will interleave packets for the rows, the IIB should never have to queue up more than 3 packets for any given row.
From com/solartechnology/display/StringDriver31b.java:
public static int readModuleCount(final int stringNumber) { /** * Technique: * * We send out a local clear display message (a 2-byte * message) with an address of 31, followed by two global * clear display messages (1 byte each). If there are fewer * than 32 modules on the string, we'll get back the local * clear display command with the leftover, so we can just * subtract the return address from 32 to get the count. If * there are 32 modules on the string, we won't get back the * local clear display command, hence the two global clear * display commands -- so if we read them in the first read, * we know that we have 32 modules. (finally, we might just * get an error back) */