Yet another sofware serial library

I recently put work into an alternate software serial library. I've contacted Mikal Hart, author of NewSoftSerial (which is SoftwareSerial in Arduino 1.0) and we've discussed it briefly. It's not clear yet if we're going to merge these efforts or keep them as separate projects. Ultimately, we both want to provide the community with the best possible software, and discussion is ongoing as to how we'll do that.

At this early stage, I'm looking for a few good beta testers. If you're interested, and you have the time to provide quality feedback, please email me directly: paul at pjrc dot com.

You don't need to read or understand the rest of this message, but if you're curious how my new implementation works and why it's different, read on....

My alternate code uses a 16 bit timer input capture to receive and the output compare to transmit. This means you must connect to specific pins, and the other PWM pin(s) from that timer can no longer generate PWM. Since it grabs a timer, any other library which needs that timer can't be used (my code has compile-time options to use different timers, on boards which have more than one 16 bit timer).

For reception, instead of using a pin change interrupt followed by software busy loop polling, the start bit and each input transition is received by the timer's input capture hardware. A very quick interrupt routine grabs the input capture data, but otherwise interrupts remain enabled for other libraries while data is incoming. For transmission, again instead of using a software busy loop that locks out interrupts, the timer's output compare unit creates the bits. A very quick interrupt updates the timer's output compare after each output change. Both transmission and reception use buffers, so the behavior is very similar to Arduino 1.0's HardwareSerial. Transmitting with write() or print() only blocks if the buffer is full.

At least in theory, this approach should allow software serial to be much more compatible with other libraries which require low-latency interrupts (as long as they don't need the same timer!) Slower baud rates should not interfere with millis & delay. It should also be able to receive and transmit simultaneously, which isn't possible with currently used software serial approaches.

Like the current implementations, other libraries that disable interrupts for 1 bit time or longer can cause errors in reception. But because precise hardware-based input capture is used, less than 1 bit time interrupt latency does not skew the bit detection times and degrade mismatched baud rate performance. Current implementations disable interrupts, which guarantees perfect output from software busy loops. Because output is interrupt based, longer than 1 bit time latency from other libraries also impacts transmission, but as long as latency is less than 1 bit time, perfect output is created by the timer's output compare hardware.

At least that's the theory. I've done a lot of testing with tiny programs, an oscilloscope, and looping back to hardware serial. Higher-level beta testing, especially in combination with other libraries in real applications is now needed to verify this approach really works in practice, and of course to discover any bugs I've overlooked.

Sounds complicated - I think I'd rather use a chip with 2 hardware UARTs.
Maybe that's just my hardware design background clouding my vision 8)

Like many libraries, how it works internally it is indeed complicated.

Yes, it's always best to use HardwareSerial if you can. The AVR uart can receive properly with up to 20 bit times of interrupt latency (minus overhead in the ISR... and Arduino's HardwareSerial code isn't a model of efficient programming), whereas software serial can usually only withstand 1 bit time latency.

But lots of people have the Uno board where the only hardware serial is dedicated to uploading and debug, or Teensy, Sanguino, '1284-based board or others, where there's only 1 extra hardware serial port available for general use. If you want to connect 2 serial devices, and also be able to upload, your choice is stepping up to Mega, or using one of these libraries.

Software serial is indeed pretty popular, enough so to be included in Arduino itself, because there are lots of people who need it.

Paul, can the lib do any baudrate?

purpose:
I used pseudo random baudrates once as form of (weak) encryption. The baudrate between the devices was set Serial.begin(1200 + random(10000)); for every byte. Worked quite well.

robtillaart:
Paul, can the lib do any baudrate?

Yes. It works at arbitrary baud rates, not a pre-defined list like the current SoftwareSerial does.

On a 16 MHz board, the minimum is 283 baud. The maximum depends on the interrupt latency imposed by other libraries, including Arduino's HardwareSerial, Tone and timer0 (millis) interrupt usage.

Would you like to beta test? Please email me direct for the code, paul at pjrc dot com.

Regarding encryption, once someone knew the baud rate mattered, it'd be pretty easy to measure the elapsed time between transitions with a logic analyzer, or even an Arduino using the timer1 input capture.