GARTHWILSON wrote:
Do they both have RS-232? That would be easiest.
The software at both ends may get complex, but not very complicated.
You don't need to make it complex, either. It seems that all modern-day networking protocols are now attempting to emulate memory transfer transactions, and it seems logical that we should learn from this as well. (Note: this trend appears to have started with Firewire.)
Each command packet includes some kind of transaction code. For now, I'll stick with READ and WRITE, although others are conceptually possible too (e.g., interrupts). In addition to the command byte, you would need to include a start address, and a length. This lets a single command read anything from a single byte up to a 64KB chunk, or more if you wish.
Commands for reading/writing from a 64KB address space, up to 64KB at a time, would look like this (using C-style structure notation for clarity):
Code:
struct CommandPacket
{
char command;
unsigned short startAddress;
unsigned short length;
/* if command == WRITE, then append data here. */
};
A response would just be another packet, sent the other direction, but with some kind of special flag bit set saying it's a response, not a command. This works great over a point-to-point link.
Higher-level functions (suppose you want to talk to it via a "terminal" interface) are supported by reading and writing to/from well-known memory locations. For instance, writing a chunk of text starting at location $0000 would print the text to a device's printer, while writing it starting at $0001 would print the text to the device's LCD, etc. Reading data starting at the same location might cause it to read from the keyboard.
In this manner, the function is determined by its start address. This is finding application in most high-end TCP/IP networks now, under the guise of "TCP/IP-without-copying," where IP routing is performed 100% in hardware, without any CPU intervention. This is also the fundamental concept behind Firewire.
If you have an actual bus-style or other topology network connection, where you need to address multiple nodes, then you can use the network address as the upper bits of the virtual address to read/write to. For example, we can extend our command packet above thusly:
Code:
struct CommandPacket
{
char command;
unsigned long replyAddress;
unsigned long startAddress;
unsigned short length;
/* if command == WRITE, then append data here. */
};
In this case, we're arbitrarily assigning the upper 16-bits of the startAddress field to be the target node we wish to read/write from. The lower 16 bits is the offset within that node's "address space."
The replyAddress field is structured similarly -- the upper 16 bits contains the sending node address so that the device knows where to send the reply. This is necessary since we're no longer assuming a point-to-point link, and hence this information is required to properly route the packet to its rightful destination.
The advantage of this approach is its universality. You can easily use this to perform control functions, to upload or download software, and to commence remote execution at a specific address, in addition to higher-level I/O such as file transfer.