Monthly Archives: March 2013

Use a TRS-80 Model 100 keyboard on a PC

Over on the Color Computer mailing list, Frank Swygert (editor of American Motors Cars Magazine) mentioned a project where someone else was using a Teensy to hook an old matrix-style keyboard up to a modern PC.

A bit of Googling led me to a similar project where someone built a Radio Shack TRS-80 Model 100 keyboard interface that lets you use it on a PC via USB. This is precisely one of the things I will be doing with a Radio Shack Color Computer keyboard (also planned to use the Teensy 2.0, since it has enough I/O lines and is very inexpensive). Share and enjoy:

http://www.seanet.com/~karllunt/M100_usb_keyboard.html

I have also been informed that Chris Hawks of HawkSoft has already done this, using a Raspberry Pi running a version of the MESS emulator. He created a scaled down version of MESS to emulate the Radio Shack Color Computer, then used Teensy to interface an actual CoCo keyboard to the Pi. Very cool.

Parsing Hayes modem AT commands, part 2

See also: Part 1

I know I am supposed to be posting my updated joystick code, which I will do as soon as I have a moment, but I wanted to share some other new stuff first so it can start getting in to the Google indexes.

I have created the first part of some quick-n-dirty code to handle Hayes modem “AT” commands. For a bit of background on the Hayes modem command set, check this Wikipedia entry:

http://en.wikipedia.org/wiki/Hayes_command_set

For some more specific details, check out this Wikibooks entry:

http://en.wikibooks.org/wiki/Serial_Programming/Modems_and_AT_Commands

The Hayes modem company needed a way for the controlling system (user, terminal program, BBS, whatever) to switch the modem from Data Mode (where bytes come in, and bytes go out) to Command Mode, where the modem could be controlled (dial a number, hang up, configure how many rings to answer on).

To get in to Data Mode, a series of three characters is sent – the default being “+++” – with a one second pause (called the “guard time”) before and after them. That way, if the string “+++” appears in normal data being transmitted (like this article), the modem doesn’t respond to it. It would take a pause, then the “+++”, then another pause, and the modem would stop sending and receiving data and present the host system/user with an “OK” prompt and then accept commands.

My code was designed to be used in the main loop() where data would be processed. Code would check for incoming data from the remote device and handle it (such as seeing bytes come in over a modem or serial port), and then look for local input (like the user typing, or a program sending data out). If it was a dumb terminal program, that loop might look like this pseudo code:

loop()
{
  char ch;

  ch = readIncomingData(); // Get byte from remote system.
  Serial.write(ch);        // Print byte to local screen.
  ch = Serial.read()       // Get byte from local input.
  writeOutgoingData(ch);   // Print byte to remote system.
}

This, of course, is not working code. A few more lines would be needed to check for valid data and such, but hopefully you get the idea. The loop would continuously run, reading data if it were there, or moving on to the next instruction.

My code is designed to plug in to that loop, after each byte is read from the local user:

loop()
{
  char ch;

  ch = readIncomingData(); // Get byte from remote system.
  Serial.write(ch);        // Print byte to local screen.
  ch = Serial.read()       // Get byte from local input.
  if (cmdModeCheck(ch)==true) cmdMode(); // ADDED
  writeOutgoingData(ch);   // Print byte to remote system.
}

The idea is to let me code inspect each character that comes from the host system, and then see if there has been a pause of at least “guard time” since the previous character, and if so, start evaluating the characters to see if they are the “+++” escape sequence. If three plusses are seen in a row, it then sees if “guard time” has elapsed and, if so, return a true value to let the calling function know it is time to switch in to Command Mode.

According to the Hayes modem standard, the character used for the escape sequence (“+”) is configurable, as is the guard time. Because of this, I use two global variables for these, so the user can modify them and affect my cmdModeCheck() function:

// Define the escape sequence.
#define ESC_GUARD_TIME 1000 // Seconds required before/after escape sequence.
#define ESC_CHARACTER  '+'  // Default escape character.

// For Command Mode.
unsigned int escGuardTime = ESC_GUARD_TIME; // Delay before/after esc sequence.
static char  escCharacter = ESC_CHARACTER;  // Escape character

I am just using the #defines for default values. A function will be written later that will let the user set them, like setCmdModeCharacter(‘?’) to make it “???” or setCmdModeGuardTime(2) to change the guard time to two seconds.

Not much here so far, so let’s look at the actual function. I will insert some comments

// Magic numbers.
#define ESC_TIMES       3    // Number of escape characters ("+++").

boolean cmdModeCheck(char ch)
{
  static unsigned long escCheckTime = 0; // Next time to check.
  static byte          escCounter = 0;   // Number of esc chars seen.

  // If no character is being passed in, we are just doing a check to see if
  // we are in a "wait for end guard time" mode.
  if (ch==0)
  {
    // See if we are waiting to enter command mode.
    if(escCounter==ESC_TIMES)
    {
      // Yep, we have already found all the escape sequence characters.
      if ((long)(millis()-escCheckTime) >= 0)
      {
        // And the pause has been long enough! We found an escape sequence.
        escCounter = 0;
        escCheckTime = millis()+escGuardTime;

        return true; // Yes, it is time for Command Mode.
      }
    }
  }
  else // if (ch==0)
  {
    // If there has been a pause since the last input character...
    if ((long)(millis()-escCheckTime) >= 0)
    {
      // Check to see if it's an escape byte.
      if (ch==escCharacter)
      {
        // Move to next character to look for.
        escCounter++;

        // Are we out of escape characters to check for?
        if (escCounter>=ESC_TIMES)
        {
          // Set after delay to signify end of escape sequence.
          escCheckTime = millis()+escGuardTime;
        }  
      }
      else
      {
        // Reset. Not an escape character.
        escCounter = 0;
        escCheckTime = millis()+escGuardTime;
      }
    }
    else
    {
      // Reset. Not an escape character.
      escCounter = 0;
      escCheckTime = millis()+escGuardTime;
    }
  } // end of if (ch==0) else

    return false; // No, it is not time for Command Mode.
}

I should explain that, in order for this function to work, it needs to be called often enough to determine if the guard time (1 second) has elapsed between incoming data. If the input is idle, the function still must be called, but with ch=0 (no data) which is why, at the top, it looks for an incoming character of 0 then it will handle timing stuff.

The way it works is by keeping a count of how many escape characters in a row we have seen so far. I use static variables so they maintain their values between calls to the function. Since I do not use them anywhere outside of this function, I saw no reason to make them global.

“escCounter” starts out at 0. If we get a “ch=0” value, we want to see if we are waiting on the ending guard time. i.e., have we gotten as far that we’ve seen 3 escape characters in a row, and are now looking for a 1 second pause? If escCounter is 3 (ESC_TIMES), we use a nice timing rollover routine from the Arduino.cc Playground to see if it’s been at least guard time with no other characters coming in. If it has been that long, we reset out escCounter back to 0, and make a note of some future time (representing now + guard time in the future). More on this in a moment, but by returning “true” at this point, we have reported back that we have seen “(pause)+++(pause)”.

Ideally, I should have explained the previous code after explaining this next bit first, since it is setting some things up we haven’t discussed yet. Hang in there and things should become clearer…

At the else, we handle a situation if “ch!=0” (i.e., if we were passed in a character from the host system/user). When we initialized this function, there was an “escCheckTime” variable set to 0. In this loop, we test to see if the time difference between now “escCheckTime” to see if we have gone past it. The very first time this runs, that will be some number minus 0, which will always be greater than 0, and thus always look like it’s been that long. Since we are just starting up, we always want to consider the first character we see. Subsequent calls will be using an “escCheckTime” that is generated based on “now + guard time”, so we are really checking to see if we have passed that future moment in time.

As you will see in a moment, every time a non escape character comes in, or anything else comes in during our guard time wait period, we just reset everything since it’s clearly not an escape sequence.

BUT, if the character we receive IS our escape character (“+”), we increment our “escCounter” to indicate how many of them we have seen in a row. It would go from 0 to 1 this first time.

If the counter gets up to 3 (ESC_TIMES), we have seen three of the escape characters in a row without being reset, so we set our escCheckTime to be “now plus guard time”. If you go back a few paragraphs, you will see we check this in the “nothing to do here, move along” function, so it can say “oh, it’s been at least guard time, AND we have seen our escape character sequence. Must be Command Mode time!”

But if it was NOT our escape character (else), we reset escCounter back to 0, and reset our check time yet again to “now plus guard time” to start the whole process over.

The next else is from the “has it been longer than guard time” if statement, and if we got a character before our guard time elapsed, we know it’s not an escape character so reset everything (just like the previous paragraph).

I hope to clean that up a bit so it doesn’t have to do it in two places like that.

At the end, we return false, because if we got there, we are in the process of either normal data, or scanning through a potential escape character sequence.

When I return, I will provide a full code example, and hopefully have some enhancements to the above function. Until then… I have to get back to packing. My rent is going up and it looks like I will be moving soon.

Parsing Hayes modem AT commands, part 1

2014-03-03: Latest source code is on GitHub.

Several of my Arduino plans involve the old 1980’s Radio Shack Color Computer (CoCo). I have previously discussed plans to use modern USB mice, joysticks and keyboards with this old home computer, as well as going the other way and allowing old CoCo joysticks to be used on modern PCs.

That seemed like an easy first step, and one I hope to find time for some time before I retire. I haven’t had time to touch any of this for awhile. That, however, does not stop me from planning even more projects.

There is an Arduino Ethernet shield currently available for $17.99 from Sainsmart in China. They ship free to the USA, but it takes awhile. For a bit more, you can buy it from Amazon and have it shipped 2nd day via Amazon Prime.

These shields provide an Ethernet port for the Arduino, and library code is provided to do basic things such as make a TCP socket connection. Samples exist showing how to go retrieve a web page, FTP put/get a file, or even serve up web content so you can create an HTML interface to interact with the device. With the Arduino doing the physical interfacing to the wire, and heavy lifting of the TCP/UDP/IP protocol stack, this might be an easy way to bring internet connectivity to the CoCo.

Over a decade ago at the 2001 Chicago CoCoFEST! convention, Minnesota-based Cloud-9 Tech announced plans for the “Superboard” hardware add-on. It would be a secondary I/O board that would connect inside a CoCo case and bring all kinds of hardware add ons, such as a hard disk interface. The product has yet to be completed, but many spinoff items have been released during development.

One of the proposed features of the Superboard was the addition of an iChip from ConnectOne. This chip implemented TCP/IP as well as common internet protocols like FTP, Telnet and mail. Small devices could talk to the chip via serial (like talking to a modem) and send commands, then the chip would go do the actual work via a dialup ISP or ethernet link. I thought this was the killer feature, and started referring to this project as the “Internet CoCo.”

I even looked in to making an RS232 adapter that would have an iChip in it, so you could plug a cable from an RS232 pak on the CoCo to this adapter, then to a modem and get all the features that way. But, at the time, I didn’t have the money to invest in the ConnectOne reference platform (a modem with iChip built in) to work on it.

Well, today the iChip is still made and only cost $25 in single unit quantities. I still think this adapter would be a great idea, but perhaps there is another way…

It would be relatively trivial to write Arduino code that would do this. A CoCo (or any device with RS232) could send commands to the device to establish network connections and then the data could be passed back as serial data. The only tricky bit would be allowing multiple socket connections (FTP, for instance, uses two at a time). For that, some form of serial multiplexing (using one serial line with a protocol on it to act as multiple lines) could be used.

Side Note: There is an absolutely amazing thing called DriveWire created by a former coworker of mine, Boisy Pitre. He created a serial protocol to allow a PC to host disk files for a CoCo via the bitbanger serial port. Over the years, the protocol has evolved and gained many features well beyond virtual disks. It’s truly amazing.

Well, today, the DriveWire server already implements much of what I am talking about doing, including multiplexing serial ports so a CoCo, connected by a single serial cable at 115Kbaud, can have multiple virtual serial ports, MIDI ports, disks, hard drives, etc. DriveWire even runs on a $25 Raspberry Pi, so one could do this without even needing a full PC nearby…

…but that won’t stop me from learning and experimenting. In fact, after I started my current job almost a year ago, I got access to a Raspberry Pi which I hooked up recently for the first time. I expect whatever I develop for Arduino I will also port to Raspberry Pi. Perhaps I can even make the Arduino code speak some of the DW protocol for virtual serial ports and such.

We shall see.

But I digress.

The real focus of this posting is to share my code for a Hayes modem “AT” command parser. In olden days of dial up modems, there were certain “smart” modems that could dial the phone on their very own. Amazing. On power up, these modems were in “command mode” and you could type commands to them like “ATDT 555-1212”. This mean “(At)tention. (D)ial using (T)ouch tone. 555-1212”. “ATH” was the hang up command. Various other commands existed for things like telling the modem if it should auto-answer the phone after a certain amount of rings, or specify how fast the touch tone dialing should be.

The “AT” command set was created by the Hayes Modem company, and other manufactures had their own system for interacting with their modems, but eventually the Hayes command set won out and became a standard. (There’s a great Wikipedia article on this.)

Since the iChip (and pretty much everything else, including modern cell phone modems) makes use of a Hayes-style command set, I thought I would implement something similar myself.

So, coming up soon, I will share code that handles the basics of this, and then will start piecing things together to interface it to the Arduino Ethernet port so you could do something like “ATDI 127.0.0.1:80″ (Attention, dial over the internet to IP address 127.0.0.1 port 80”.

Sounds fun. If I can find the time.

USB host (read a USB keyboard/mouse) without hardware

I have not had time to spend on any research lately, but I did want to pass along this link:

https://courses.cit.cornell.edu/ee476/FinalProjects/s2007/blh36_cdl28_dct23/blh36_cdl28_dct23/

These folks have a software-only implementation of USB host for the AVR chip like the Arduino uses. It allows, with software only and some wires to a USB connector, the device to read a basic USB device like a mouse or keyboard.

The only thing I noticed was it requires a 16Mhz crystal, instead of the stock 15mhz. They did it by building their own system, but someone wanting to do it on an Arduino would need to desolder and replace the crystal.

However, there are some pretty simple plans to “build a $5 Arduino” with minimal parts — so perhaps it would be very cheap to breadboard something that supports this.