After reading a lot about CALCnet2.2, I was hoping that it would support IP and other protocols (eg, ICMP) running on top of it, much as IP runs over Ethernet. However, the Cn2.2 protocol is not very well suited for some protocols that run over IP. In particular, Cn2.2 re-sends frames until they are delivered to the destination (except for broadcasts), whereas UDP by itself does not resend frames (except in the case of collision). There are workarounds for this, but that's what they are--workarounds.

Also, there is already globalCALCnet, which is a means of allowing calculators to communicate over the Internet using CALCnet, but it is achieved by running the CALCnet protocol on top of TCP/IP, rather than the other way around. Trying to use IP over CALCnet will make it incompatible with gCn anyway (since that would be IP over CALCnet over TCP/IP), so I figure it's best to design a different protocol with IP in mind.


Given these limitations/issues with Cn2.2 (due to different design goals and not any fault of the protocol), what I am hoping to do is develop a frame-based protocol somewhat similar to Cn2.2 which performs the role of the Data Link layer in the OSI model, and which allows IP and other protocols to run on top of it (much like Ethernet). Of course, this means the protocol may be limited to more-powerful calcs, such as the 68k calcs and the Nspire, which are capable of running a usable TCP/IP stack and Internet applications on top of it.

I already have some ideas for the bit-level, byte-level, and frame-level protocols, but I want to get a feel for whether there would be any support/demand for this new protocol before I spend much more time designing it. (Though, even if there is little demand for it, those few individuals who would use it could still communicate with other hosts, calculators or not, over the Internet, since that is the point of the protocol Wink)


NOTE: I am not trying to compete with or "rip off" CALCnet. I am trying to develop another protocol with different goals and purposes than CALCnet. I am hoping to use any knowledge and insight that Kerm (or others) gained while designing CALCnet, since this new protocol will inevitably have some similarities to CALCnet (such as at the physical layer).

NOTE2: This new protocol could also use Direct-USB, like CALCnet, but it would just use a computer as a standard network bridge/router.
I can't conceive of any situation where running IP over Calcnet would make sense. What are you envisioning?
I envision running IP over a different protocol than CALCnet (one that is more suitable for IP) so that calculators can communicate directly with other hosts over the Internet, peer-to-peer, without any proxy servers between them (as globalCALCnet requires).

Who knows, maybe someone can make a calculator network-to-Ethernet adapter (with Arduino perhaps) so you would only need an Ethernet cable to get on the Internet with your calc (no computer at all). That shouldn't be terribly difficult since the adapter would only have to translate the Layer 2 protocols between network segments. It wouldn't have to be a proxy server like gcnclient.
Aren't you talking about simply TCP/IP, not really over anything at all? Wouldn't you therefore want to just use the actual Ethernet physical/link and TCP/IP data and higher levels? Or am I missing something?
KermMartian wrote:
Aren't you talking about simply TCP/IP, not really over anything at all? Wouldn't you therefore want to just use the actual Ethernet physical/link and TCP/IP data and higher levels? Or am I missing something?

A direct Ethernet connection is not really suitable for calculators for a number of reasons (mostly due to differences in electrical levels), which is why I'm trying to design a physical and data-link layer protocol that is suitable.

With my protocol, as with Cn2.2, multiple calculators can communicate with each other on a simple network consisting of nothing but spliced cables or an equally simple hub. Unlike Cn2.2, my protocol will allow the calculators also to speak in IP and other higher protocols as found on "real" computer networks so they can communicate with other "real" computers unassisted (ie, no proxy servers).
christop wrote:
KermMartian wrote:
Aren't you talking about simply TCP/IP, not really over anything at all? Wouldn't you therefore want to just use the actual Ethernet physical/link and TCP/IP data and higher levels? Or am I missing something?

A direct Ethernet connection is not really suitable for calculators for a number of reasons (mostly due to differences in electrical levels), which is why I'm trying to design a physical and data-link layer protocol that is suitable.
Which of course makes perfect sense. Thanks for the clarification.

Quote:
With my protocol, as with Cn2.2, multiple calculators can communicate with each other on a simple network consisting of nothing but spliced cables or an equally simple hub. Unlike Cn2.2, my protocol will allow the calculators also to speak in IP and other higher protocols as found on "real" computer networks so they can communicate with other "real" computers unassisted (ie, no proxy servers).
Well, you still need a proxy hardware module of sorts on the client end to translate the link-level protocol, but that's about it, which sounds cool to me. There are Ethernet shields for Arduinos, for instance, which would make a PC-less bridge possible. Indeed, one of these days I want to try one with CALCnet to enable PC-less gCn.
Here's a rough draft of what my protocol will look like, starting at the bit level:

To send a single bit, invert the level of one line:
  • for a 0 bit, invert the tip
  • for a 1 bit, invert the ring
  • for an invalid bit, invert both (the sender should never do this! (although this may be useful as a jamming signal))
Each bit should last approximately 69 microseconds (416 cycles at 6MHz) after changing the appropriate line level. Experimentation will be needed to determine if this length can be shortened, or if it needs to be lengthened. The bus lines take a short time to float high after being pulled low (due to a small input capacitance), but according to Cn2.2, 69 microseconds should be long enough (see periods 3 + 1 of the bit-level protocol). Pulling a line low is nearly instantaneous, so theoretically each bit represented by a high-to-low line transition can be much shorter than a low-to-high transition, but doing this would probably add complexity to the transmitter code for little gain.

I've already hammered out some Z80 assembly code that demonstrates that this bit-level protocol is fairly easy to implement.

The byte-level protocol will be similar to that in Cn2.2: a short synchronization signal followed by 8 bits (as described above), and then possibly another synchronization period after the last bit. The LSb in each byte is sent first, as opposed to the MSb as in Cn2.2. This is fairly arbitrary, but it follows Ethernet's and the TI link protocol's examples.

I haven't worked out the frame-level protocol much yet, but it looks somewhat like Cn2.2:
  1. send attention-grabbing signal (~10ms)
  2. send destination id
  3. send source id
  4. ? send version/options byte(s) ?
  5. ? send protocol number (2 bytes) (eg, IPv4) ?
  6. send payload length (2 bytes)
  7. send payload
  8. send 16-bit (or 32-bit) checksum/CRC for the entire frame, starting with destination id's and ending before the checksum

All multi-byte values are stored in big endian, as that is the network byte order.
Looking good, Christopher. Smile Those all seem like solid design decisions thus far to me.
A wild idea: would http://www.ftdichip.com/Products/Cables/USBRS232.htm (connecting only the GND, TX and RX lines onto the male 2.5mm stereo jack) + SLIP work ?
Lionel Debroux wrote:
A wild idea: would http://www.ftdichip.com/Products/Cables/USBRS232.htm (connecting only the GND, TX and RX lines onto the male 2.5mm stereo jack) + SLIP work ?
Huh, that's an interesting idea. Would you need line leveling though? RS232 uses voltages like +/- 5V instead of 0V/5V. Smile
Maybe http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm , then ? That's more like what we have where I work, actually Smile
Lionel Debroux wrote:
Maybe http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm , then ? That's more like what we have where I work, actually Smile
There you go, that's more like it. Smile
Other cables based on the CP21xx and PL2303 chips could seem to do the job as well.
For example, http://bearbonessolutions.com/index.php?main_page=product_info&cPath=2&products_id=3 / http://cgi.ebay.com/USB-UART-TTL-Cable-AVR-MSP-430-Arduino-Free-Ship-/120632799950#shId


Bending the USB controller in the 84+(SE) and the 89T to our will of emulating a FT232, CP21xx, PL2303 or whatever chip, could also do the job.
Lionel Debroux wrote:
Other cables based on the CP21xx and PL2303 chips could seem to do the job as well.
Bending the USB controller in the 84+(SE) and the 89T to our will of emulating a FT232, CP21xx, PL2303 or whatever chip, could also do the job.
I'm under the impression that emulating FTDI is extremely difficult; there's an Arduino package for USB HID bitbanging, but I seem to recall them saying that FTDI was prohibitively expensive. Maybe having a USB controller rather than bitbanging makes it possible.
Wow. Where has the time gone...? Every year is getting shorter, never seem to find the time.... Reminds me of a Pink Floyd song. Very Happy

Anyway, I've finally designed and developed this protocol fairly completely, but after reading about other existing two-wire protocols, I'm wondering if there would be any value in designing a protocol with a shared clock. That is, the clock is controlled by all receivers on the bus to ensure that every host is ready to receive another bit (only interested receivers need to participate in the clock). What this means is that the clock line is pulled low until all participating hosts are ready for the next bit. This includes the sender as well. As soon as the sender has the next bit ready, it releases the clock signal, waits for the clock to go high, waits for a short time (perhaps a few microseconds) for all hosts to read the current data line, and then pulls the clock low again to change the data line to the next bit.

This protocol would run only as fast as the slowest receiver, but it ensures that all receivers are ready for the data without inserting arbitrary delays into each phase of the bit transmission (except for the small delay to let receivers read the current data signal before pulling the clock low). It's kind of like flow control at the bit level.
Ok, so I worked out the bit-level protocol for such a "shared clock" protocol. I haven't implemented it or anything, and I probably never will, but I'm dumping out my ideas here in case anyone else is interested in using this in a protocol:

Transmitter:
Code:
start loop:
set a bit of data
wait a short time (about 20us) for receivers to see the data
pull clock low for a short time (about 20us)
release clock and set the next bit of data
wait for clock to go high
goto start of loop if more bits to transmit


Receiver:

Code:
start of loop:
wait for clock to go low
  on timeout (eg, 500us) end receiving
read data and pull clock low
save data and prepare for the next bit
release clock
wait for clock to go high
goto start of loop
I don't really have hardly any time to work on this project right now, but I've had some ideas lately that I want to write down for future reference.

First things first: the working name for my frame-level protocol is "Chrisnet". It's obviously very narcissistic so I will change it later if I ever release a working implementation.

A few months ago I started thinking about designs for a Chrisnet router/hub, much like a CALCnet hub with multiple 2.5mm ports and a shared bus, but also including a second port to talk to the outside world (basically like gCn). I first thought about using an RJ45 port so it can plug straight into an Ethernet network, no computer necessary (only a router/switch is needed). Then I looked at prices for an RJ45 port with built-in magnetics, as well as the required circuitry/microcontroller to drive the port (Arduino being an obvious candidate, but certainly not the only one). All parts came out to at least $100+ for a single hub. That feels a little rich for my blood. Besides, the slowest Ethernet speeds (10Base-T) are about two orders of magnitude faster than the calculators can send or receive anyway. So I recently thought of an alternative....

My recent idea is to communicate over a serial line using the SLIP protocol. A serial speed of 115200bps ought to be fast enough, since the calculators won't be speaking anywhere near that fast.

The Chrisnet hub will listen for Chrisnet frames directed at it and then stream each frame within a SLIP frame, and vice versa (all SLIP frames are inherently directed at the hub and are transmitted on the Chrisnet side).

To facilitate using IP over Chrisnet, the Chrisnet hub will respond to ARP requests on the Chrisnet side, and it will also make ARP requests on the Chrisnet side to determine the Chrisnet address for a given IP datagram. This is conceptually the same as on any other layer-2 network, such as Ethernet. Obviously ARP is not needed on the SLIP side since it has only two endpoints.

Why did I choose SLIP over PPP? SLIP is much easier to implement on a microcontroller, and it should be sufficient for a simple hub. PPP may turn out to be necessary if the hub needs an IP address. (Of course, it would be relatively easy to implement PPP on something like an ATmel or Raspberry Pi as it can easily be written in C).

Some questions remain, such as whether the hub should have its own IP address.

If the hub doesn't have an IP address, then it also doesn't need a Chrisnet address, and the hub will have to forward all Chrisnet frames over SLIP, which should be ok (the bandwidth on the Chrisnet side is the bottleneck). Chrisnet hosts will then have a route entry like the following:


Code:
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         *               0.0.0.0         U     0      0        0 chrisnet


which will work properly if all packets get forwarded automatically by the hub. Obviously the hub will not have to respond to ARP requests nor make ARP requests if it doesn't have its own IP address.

Otherwise Chrisnet hosts will need the following entries:


Code:
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.1.0.0        *               255.255.0.0     U     0      0        0 chrisnet
default         10.1.0.1        0.0.0.0         UG    0      0        0 chrisnet


(assuming Chrisnet uses a 10.1.0.0/16 network and the hub is at 10.1.0.1).

If the hub does have an IP address, how should it be assigned to the hub? Statically or with PPP (instead of SLIP)?

Another remaining question is how Chrisnet hosts are assigned IP addresses. They can indeed be assigned statically but this requires setting up each host individually (which isn't that big of an issue with only a handful of hosts and with a simple configuration script on each host). If DHCP is used instead, the hub will need to have its own IP address and then act as a DHCP relay (which adds more complexity to the hub), and the PPP/SLIP server will either have to handle DHCP requests or act as a DHCP relay. Either way, the PPP/SLIP server will have to have routes to forward IP datagrams to the serial line if they are destined for Chrisnet hosts.

I'll work out these issues in the back of my mind over the next several months (or years).
I looked again at possible platforms to build a Chrisnet hub, and the Nanode ($40) looks like a suitable development system. It has ethernet, USB, and digital and analog pins. It still seems a little expensive, though.

Then I researched USB network devices. Perhaps a USB-equipped calculator could emulate an ethernet-over-USB (USB CDC) device. Or it could act as a serial device so I could run PPP over it.

I'm just throwing out ideas now; I haven't determined the practicality or feasibility of any of these ideas.
A little update: I thought about the hub issues more recently and found an elegant solution!

The SLIP-to-Chrisnet hub will not have an IP address nor a Chrisnet address. The hub will have an ARP cache, which it will update for every IP datagram that it receives from either side. This will tell the hub whether it should forward datagrams to the other side (and if it forwards to the Chrisnet side, what the Chrisnet address is). If the hub receives a frame containing IP datagram with an unknown destination, it will forward the frame to the other side as a broadcast (though since SLIP doesn't really support broadcast, it will simply forward the frame from the Chrisnet side to the SLIP side).

Each record in the ARP table will be "aged" to ensure the table doesn't get stale. When a datagram coming from an IP hasn't been seen for a period of time (10 minutes or so), the ARP record will be dropped.

The hub will have to store up to two full outgoing Chrisnet frames (1020 bytes each, which is 1006 bytes for a maximum SLIP frame plus 14 bytes for the Chrisnet frame overhead), plus a small (16 bytes) serial output buffer. Since the serial side is asynchronous, the hub can send bytes while it is receiving data from the Chrisnet side, which is why only a small serial buffer is needed. The Chrisnet side is synchronous (the entire frame must be received before sending begins), which is why full-frame Chrisnet buffers are needed. I will use two buffers so another SLIP frame can be received while a frame is being sent on the Chrisnet side (otherwise the frame will be dropped).


I'm still thinking about the proper way to use the hub on the Chrisnet side. Here are my current thoughts....

Hosts on the Chrisnet side will need to be configured with a default route pointing at an IP address (ie, the IP address that the hub would have if it actually had one) and a static ARP record for that IP pointing at the Chrisnet address 0:0:0:0:0. The hub will listen for only frames sent to that address.


Here's what will happen when a Chrisnet host (Host A) sends an IP datagram to a remote host (Host B):
  1. Host A sees that the IP address is not on the local link (by looking at its routing table).
  2. Host A sends an IP datagram with Host B's IP address in a Chrisnet frame addressed to 0:0:0:0:0.
  3. Hub sees the Chrisnet frame and saves Host A's IP address and Chrisnet address in its ARP cache.
  4. Hub forwards the frame to the SLIP side.
Here's what will happen when Host B sends an IP datagram back to Host A (assuming Host A's ARP record is still in the hub's ARP cache):
  1. Hub receives a SLIP frame from Hub B into a buffer.
  2. Hub sees that Host A is the destination.
  3. Hub locates Host A's Chrisnet address and sets it as the destination in the outgoing Chrisnet frame.
  4. Hub sends the Chrisnet frame.
  5. Host A receives the Chrisnet frame.
If the hub did not have an ARP cache record for Host A, the hub will send a broadcast Chrisnet frame instead of a unicast Chrisnet frame in steps 3 and 4, and all Chrisnet hosts will receive the frame (but only Host A's IP stack will accept it) in step 5.


The SLIP server (and perhaps one or more routers in the network) will also need to have forwarding and routing properly set up in order to pass IP datagrams to the hub. I haven't set up SLIP on a PC on either OS (Linux or FreeBSD) so I can't really say what will need to be done there.
christop wrote:
The hub will have to store up to two full outgoing Chrisnet frames (1020 bytes each, which is 1006 bytes for a maximum SLIP frame plus 14 bytes for the Chrisnet frame overhead), plus a small (16 bytes) serial output buffer. Since the serial side is asynchronous, the hub can send bytes while it is receiving data from the Chrisnet side, which is why only a small serial buffer is needed. The Chrisnet side is synchronous (the entire frame must be received before sending begins), which is why full-frame Chrisnet buffers are needed. I will use two buffers so another SLIP frame can be received while a frame is being sent on the Chrisnet side (otherwise the frame will be dropped).

Now that I think about it even more, buffers for two outgoing Chrisnet frames might not be needed after all. With only one buffer, another frame cannot be received (it must be dropped) until the single Chrisnet buffer is drained. Dropping the frame should have little impact on TCP, which will automatically retransmit segments if it detects loss due to congestion. UDP will be affected more because the application (on the remote side) will have to perform its own retransmissions or simply accept the packet loss. This won't affect sending packets from Chrisnet to SLIP, as all frames are transmitted immediately in this direction*.

The serial (SLIP) side of the hub will be much faster than the Chrisnet side (115200bps or so), so multiple TCP retransmissions should have little impact on performance.

I could probably even get away with a smaller frame size (with the appropriate MTU setting in the SLIP server), such as 576 (minimum MTU for IPv4) or even 296 (typical recommended SLIP frame size). IP can deal with such small MTU's just fine, and smaller frames will reduce latency at the expense of slightly higher overhead (lower bandwidth).

I want to minimize the buffer sizes so I can use an AVR or PIC (I'm leaning toward an AVR, but I have no real problem using a PIC if it works) with the smallest amount of RAM, so it will be the least expensive. I found a couple of IC's (a PIC and an AVR) with 1.5kB (PIC) and 2kB (AVR) of RAM for under $3 at Digikey, so I'll probably go for one of those once I'm ready to build a hub (I haven't even written Chrisnet for the calculator yet, so I need to get that working first).

* The Chrisnet checksum cannot be verified until the complete frame is received. This means the hub cannot verify frames and will forward garbage IP frames over SLIP. The receiving IP stack will drop the garbage packets in this case, so this shouldn't be a problem in practice.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement