Parallax USB Oscilloscope - on FreeBSD??? (skip to the bottom for poorly written sample code) This is very much a work in progress. Don't expect much. Using a serial port sniffer/analyzer, I've made the following observations about the scope's protocol: The serial port settings are 9600-8-N-1. There is a periodic keep-alive which is sent when the scope is inactive. This command and response look like this: > ? < OX207A2 In watching data stream back from the device, it appears that both data channels are always sent. Furthermore, it appears that both data channels are always the full scale -10 to +10 volts. The command to activate the scope is nine bytes, and is sent periodically; the last command is followed with a 10th byte, which is always 0xFF. The command structure of 9 bytes is split into six logical groups, described below. Byte 1 - "Hi, there!" The first byte is always 0xAA. Byte 2 - Trigger voltage The second byte represents the trigger voltage, with 0x01 corresponding to -10v, 0x81 as 0v, and 0xFF as +10v. So, you are limited to the even 256 divisions of the 20v range in selecting a trigger voltage. The read from the data channels follows the same logic. Byte 3 - Trigger slope The third byte represents the first of some complexities or idiosynchracies about the protocol. It defines trigger slope, but maybe some other things. This is still under investigation. Byte 4 - Trigger "details" The fourth byte is a bitmap of 5 options Bit 8 (high-order bit) is unused or unknown, and is always 0. Bits 7 through 4 represent the selected time division for sampling. The list below identifies the settings: x0000xxx - 10 us (microsecond) x0001xxx - 20 us x0010xxx - 50 us x0011xxx - 100 us x0100xxx - 200 us x0101xxx - 500 us x0110xxx - 1 ms (millisecond) x0111xxx - 2 ms x1000xxx - 5 ms x1001xxx - 10 ms x1010xxx - 20 ms x1011xxx - 50 ms x1100xxx - 100 ms x1101xxx - 200 ms x1110xxx - 500 ms x1111xxx - 1 second Bit 3 is unused or unknown, and is always 0. Bit 2 represents the trigger mode; 0 for normal, 1 for auto. Bit 1 represents the trigger channel (partly). Channel 1 is a 0, Channel 2 and TTL are a 1. Byte 5 - Trigger channel (part deux) Channels 1 and 2 are represented by 0x00, while TTL is 0x40. Bytes 6 through 9 - Trigger position I'm a little unsure of this, but I believe that trigger position works a little like a slidebar in a GUI. There is a "left" side and a "right" side of the trigger position. The value for the sum of both side is 3262. Be careful, the bytes are in LSB order (2 bytes per side). For example, a 50% trigger position would be encoded as 0x5F in byte 6, 0x06 in 7, and 0x5F in 8, and 0x06. In my sniffed packets, however, the 50% trigger position (selected from the GUI) is represented by 0xD0 0x08 0xED 0x03, which is more like a 70/30 split. As such, this is still under investigation. Response Format: U (0x55), followed by 1500 samples for channel1, followed by 1500 samples for channel2. 0v seems to be in the range of 0x7e to 0x81, so I'd say this follows the same logic as the trigger voltage from the command spec. Sample code: To get things going, you will need to have uftdi and ucom in the kernel so that you get a /dev/cuaU? node for the USB TTY. You may kldload them or compile them static. If you kldload, make sure they're loaded before you plug in the scope. Then, you can download and compile my play-code, which (unmodified) should give you 1500 samples every 100ms into an output file. I say "should," because it doesn't quite work, yet. But, if you have a sufficiently long waveform, you will be able to get at least some of the data. You will probably need to be root to run the code. My limited understanding of termios (first-time serial coder, I am) leads me to believe that this code may just work in platforms other than FreeBSD, including Linux, with only minor modifications. As with all things, you take full responsibility for any and all damage, fines, penalties, lawsuits, or other adverse effects that may be caused by use of this "knowledge," or this program.