Software Serial on the Arduino NG

As mentioned before, I have a really old Arduino, the Arduino NG with an Atmega8 on board. No fancy embedded Linux wifi-enabled SoC on that thing.

Recently, I found myself doing a bit of yak shaving when I was trying to use a code that was meant for Arduinos of a more recent vintage. And here is what I learned:

The Atmega8 does not have the PCICR (which I believe stands for “pin change interrupt control”) register. This feature allows multiplexing of interrupts so that you can have multiple pins signal the same external interrupt, and the pins that trigger interrupts are programmable. On the Atmega8, you can only use Arduino pins D2 and D3 to directly signal interrupts 0 and 1 respectively.

So the device I was trying to use operates over serial, and the supplied code uses the built-in SoftwareSerial bit-banging serial library to talk to it.
The SoftwareSerial library attaches an interrupt to the configured Arduino RX pin (device TX) to trigger when it goes low, indicating the start of a transmission from the device. This library was only written with the more configurable chips in mind, so didn’t support direct interrupts like on the Atmega8. Google didn’t turn up any obvious fixes other than people running into the same compiler error I initially hit:

error: 'PCICR' was not declared in this scope.

In the end a few short changes are needed to make it work: one to disable digitalPinToPCICR() and related macros (as there is no such register on this device); and another change to attach the proper interrupt inside SoftwareSerial. A patch is here.

To debug this, I hooked up the TX side of a USB-serial adapter to the RX pin on the Arduino, ran screen(1) on the computer to control it, and started mashing keys. Until I got the irq triggering working properly, I also monitored the output with a DMM just to make sure the output was going low when I held down a key. A test sketch for that looks like this:

SoftwareSerial port2(2, 3);

void setup()
{
  Serial.begin(9600);
  port2.begin(9600);
  Serial.println("Listening...");
}

void loop()
{
  while (port2.available()) {
    Serial.write(port2.read());
  }
}

It works fine. I’ll write about what I was doing with it in some future installment.