Sunday, May 25, 2014

PL-2303HX bit-bang AVR programmer

I've blogged before about PL-2303HX USB-TTL adapters.  In some ways they are even better than the expensive FTDI adapters - for example they work at 6mbps.  In conjunction with a cheap Pro Mini clone it's possible to get started with Arduino/AVR programming for $5.  For more advanced use such as burning bootloaders or directly programming AVR chips, I usually recommend a USBasp.  While writing picoboot-avrdude, I noticed avrdude supports bit-bang SPI programming not just with a parallel port, but also with a serial port.  Here's how hacked a PL-2303HX module so I could use it as a bit banging SPI AVR programmer.

The programmer type in the avrdude.conf file is "serbb".  Here's the description line from the "ponyser" programmer in avrdude.conf:
desc  = "design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts";
I needed to break out the RTS, DTR, and CTS lines in order to make it work.  I found a pinout diagram of the PL2303HX, and marked the pins with a green star:
The modules come with a translucent shrink wrap protecting them, so I cut that off with a utility knife.  I tinned the ends of some pin headers, and attached them to the back side of the module with some contact cement - other types of glue would likely work fine as well.  Although I have the extra pins at the top of the board, it might be better to have them going out to the side so it doesn't cover the silk-screen labels for the Tx/Rx lines.  The hard part is soldering wires to the .65mm pitch pins on the SSOP-28 package.

I used 30AWG wire-wrap, and initially tried tinning the end of the wire.  I didn't have enough solder to make a good connection so I tried with a small ball of solder at the end of my soldering iron.  It was too much, and bridged a few of the pins, requiring solder wick to clean it up.  Eventually after a few more tries of tinning followed by attempts at soldering to the pin, I got a good connection.  I think it would be easier using solder paste.  Once I had the 3 wires connected, I used a multimeter to verify continuity and ensure I had no shorts.

With the hardware verified, I was ready to test it out.  I made the connections from the module to an ATtiny88 I had on a breadboard.  The USB-TTL adapter was com16, so I used the following avrdude options:
$ avrdude -C /etc/avrdude.conf -c ponyser -p t88 -P com16
But it didn't work:
avrdude.exe: ser_open(): can't open device "com16": The system cannot find the file specified.

I tried the same adapter with a pro mini with an arduino-compatible bootloader, and had no problems using the following command line:
$ avrdude -C /etc/avrdude.conf -c arduino -p m328p -P com16

A comparison of ser_win32.c and serbb_win32.c revealed some extra code at line 134 for dealing with high com port numbers.  It prepends "\\\\.\\" to the port name, so I did the same thing on the command line (I hope to clean up the avrdude serbb code in the longer term):
$ ./avrdude -C /etc/avrdude.conf -c ponyser -p t88 -P \\\\.\\com16
Now instead of "can't open device" I was getting a "device not responding" error.  I used an LED to verify that there were pulses on the SCK and MOSI lines, and could tell from the Tx LED on the module that Tx was being pulled low for the RST line.  I then remembered that TTL signals are inverted vs RS232, so I created a new programmer type in the avrdude.conf file:
  id    = "pl2303";
  desc  = "pl2303 serial, reset=!txd sck=!rts mosi=!dtr miso=!cts";
  type  = "serbb";
  connection_type = serial;
  reset = ~3;
  sck   = ~7;
  mosi  = ~4;
  miso  = ~8;
With that, combined with slowing down the communication speed by adding -i 500, I got it to work:

Monday, May 12, 2014

2.4 megasamples per second continuous AVR logic capture

In my last post I got an ATmega8A outputting a 6mbps serial UART data stream.  In this post I'll show how to use that as a way to sample 2 inputs (a USB data signal) at 2.4msps.  The reason the sample rate is not 6mbps/2 is due to the overhead of 1 start bit and 1 stop bit for every byte transmitted.  After accounting for that overhead, the data rate is 4.8mbps, and with 2 bits per sample, the sample rate is 2.4msps.

A look at the USBasp schematic shows USB D- and D+ connected to PB0 and PB1.  With the UART output rate of 6mbps and a 12Mhz CPU clock rate, a full 10-bit frame takes 20 cycles.  To take 4 2-bit samples every 20cycles requires taking a sample and packing those two bits into a byte every 5 cycles.  Single-cycle timing is very difficult to do in C, so I wrote the code in AVR assembler.

in sample, PINB
out UDR, tmp
andi sample, 0x03
lsl sample
lsl sample
in tmp, PINB
andi tmp, 0x03
or sample, tmp
lsl sample
lsl sample
in tmp, PINB
andi tmp, 0x03
or sample, tmp
lsl sample
lsl sample
in tmp, PINB
andi tmp, 0x03
or tmp, sample
rjmp capture2
The output data is valid after the first loop itteration, so the first byte (4 samples) should be discarded.  I added code to capture a full 8 bits (at 600ksps), and a simple trigger that waits for the state of the input to change.  For the full code see sniffASM.S and sniff.c.  I've also posted sniff.hex if you don't want to build the code yourself.  With the Rx line (PD0) on the AVR high (idle state), 8-bit capture mode will be use.  If the Rx line is grounded, 2-bit capture mode will be used.

To be able to view the captured data, I like OLS.  It will read a simple text-based input file, which I wrote a small perl progam to output.  It takes a single argument, which is the serial port to read from.  Under windows I had problems getting perl to open high com ports (i.e. com10 or above), so I used the device manager advanced properties to change the port number to com2.  I also wrote a similar program for the 8-bit mode.  One second of samples will be recorded, although there is no technical limit to how long can be recorded.

Here's a portion of a screen shot of OLS showing a USB setup packet followed by 2 re-transmits after ~10us without receiving an ACK:

It's not as fast as the Logic Shrimp, but considering unlimited sampling length and the required hardware is a USB-TTL adapter that costs barely over $1 and a ~$3 USBasp that many people already have, now anyone can afford a basic logic analyzer.

Thursday, May 8, 2014

high-speed UART: pumping out the data at 6mbps

TTL UART communication is the most common way to send data from a micro-controller to a PC.  It is simple and requires very little code in the MCU.  It's fine for configuration and debugging, but usually limited to low-speed (<=115.2kbps) communication.  With a 16Mhz AVR, USART timing is off by > 3% at 230.4kbps.  My bit-bang half-duplex UART can go up to 460.8kbps while keeping timing within 2.1%, and even 921.6kbps with a small tweak (a nop instruction) to the code.  This is still far short of the maximum 3mbps supported by FTDI FT232 chips and the 6mbps supported by Prolific's PL2303 chips.

There is a way to transmit at 6mbps with the AVR USART - synchronous master mode with a 12MHz system clock.
Rather than building a circuit with an AVR and a 12MHz crystal, I used a cheap USBasp.  The version made by Shenzhen LC Tech has the UART Rx and Tx pins connected to the 10-pin header, and has a 12Mhz crystal.  For power, it just plugs into a USB port.

The code isn't much different than regular asynchronous UART mode.  UMSEL needs to be set in UCSRC in order to turn on synchronous mode, and the XCK pin needs to be set to output for master mode.  The XCK pin is not connected on the USBasp, but it is not needed as the UART outputs a valid frame with start and stop bits.  Here's the initialization code:
#define XCKPIN 4

static void uartInit()
    XCKDDR |= (1<<XCKPIN);       // output mode for master 
    UCSRC = (1<<URSEL)|(1<<UMSEL)|(1<<UCSZ1)|(1<<UCSZ0);
    UCSRB |= (1<<TXEN);
    UBRRL = 1;
Defining HALF_SPEED will output at 3mbps, for use with FTDI chips.  I set the self-program jumper (JP2) on the USBasp, connected the 10-pin ribbon cable to another USBasp, and flashed the code.  Then I plugged the USBasp into a free USB port, and connected the Tx pin to the Rx pin of a PL2303HX module.
To test the data reception, I could tell data was being received by looking at the Rx activity LED, so I tried a terminal program.  There were no errors in the data stream, however there were lots of dropped characters.  Suspecting the problem was receive buffer overruns while updating the display, I wrote a perl program to receive the data:

# 1st argument must be port name
$port = $ARGV[0];

# open port in read/write mode
open(UART, "+<$port") or die "$port ", $!;
binmode UART;
my ($buf, $count);
$count = read (UART, $buf, 240);
print "read:\n";
print "$buf";
close(UART) or die $!;

The baud rate for the port needs to be set in advance - use mode or stty for Windows or Linux respectively.  Without the delays for displaying the characters as they are received, there were no errors:

You might ask when would you need to transmit data at such high speeds.  Using an AVR as a logic analyzer is the first thing I intend to try.  Watch for it in my next post.

Tuesday, May 6, 2014

PC storage oscilloscope and logic analyzer

A logic analyzer is a useful tool when working with micro-controllers, but when compared to the price of Arduino compatible boards, they are expensive.  While the ability to decode different protocols is a nice convenience, the key functionality of a logic analyzer is the ability to record a signal over a period of time.  For low-speed signals in the tens of kbps, a PC audio codec can perform this function.

The audio codecs in most modern PCs are capable of at least 96kbps stereo sampling at 16 bits per sample, with 192kbps/24-bit "HD audio" being relatively common.  This is enough to analyze a 38.4kbps UART signal in modest detail (5 samples per bit).  With some hardware to connect to the audio input and software to record and view the signal data it is possible to have the functionality of a basic storage oscilloscope and logic analyzer.

What's needed for the hardware is a 3.5mm stereo plug and 3 wires.  The largest tab is ground, and the smaller two are the left and right channels.  I used 24awg wire from a spool of ethernet cable since its cheap (~10c/ft), and when the ends are stripped it easily plugs into breadboards.
I initially had some problems recording from line input until I figured out I had to unplug the microphone - I guess the recording inputs are multiplexed.

For my testing, I recorded the 2kbps output of a pro mini running VirtualWire.  The pro mini is running at 5V, while line input voltages should be ~1V peak, so I used a 100kOhm resistor in series with pin 12 to limit the voltage at the line input.

For recording software, Audacity is probably the most popular free audio program, and one that I tested.  Here is a view of one of the output pulses captured at 192kbps:
The fluctuations at the corners of the square wave is something you would not see with a digital logic analyzer.  What you see above is normal, as a true square wave is a physical impossibility - all signals are summations of sinusoidal waveforms.  The straight lines audacity draws between points doesn't reflect that reality, so I tried resampling to a higher frequency (768kbps):
The corner of the signal looks much better, but the low amplitude ripple that was visible before seems to have been filtered out.  In the resampled signal the slight downward slope of the signal is more visible.  That is because the line input has a DC blocking capacitor which causes the 0-1V signal peak to drift down until it is roughly balanced around 0V.

Another program I tested is GoldWave 5.70.  I didn't find the interface very intuitive.  My first problem was getting it to record at 192kbps.  I eventually found the control properties, which indicated the default WASAPI maxed out at 96kbps.  Switching to DirectSound allowed me to use 192kbps.
Here's a capture from GoldWave using 192ksps:
I find the grid makes analyzing the signal easier than with Audacity.  I also tested resampling, which is limited to a maximum of 500ksps:
It seems to do a better job at resampling than Audacity.

I also tested Soundcard Oscilloscope.  It seems to be limited to 44ksps 16-bit samples and doesn't support viewing of recorded signals.  Visual Analyzer allows for analyzing a signal in many different ways, however I could not find a way to record at more than 96ksps.

I'll finish by pointing out that when trying to analyze faster communications, rather than getting a faster scope or analyzer, consider slowing down the transmitter.  For example it would not be practical to analyze 230.4kbps serial UART output when logging at 192ksps.  However setting the CKDIV8 fuse on an AVR MCU when running the same code would output a 28.8kbps signal, which can easily be captured with a PC audio codec.