Earlier in the year I purchased a a FLIR PM695 as my first thermal camera. I always intended on it being a bit of a project and to make addons to improve features/usability. I later learned about a factory option that was available for the PM series that added live 14-bit radiometric data output. Unfortunately, my camera didn't have the option installed. Even if it did, the receive hardware is very rare and expensive. So, implementing this myself would become the first project
The factory option for digital out involved installing an extra PCB that connects to a spare connector on the main processor PCB. This PCB is fairly simple: it has an FPGA, some ROM for the FPGA bitsream, and an AMD AM7968 TAXIchip transmitter. Then the serial output from the TAXIchip goes out on the 10pin LEMO connector, replacing the S-Video output.
I started out by opening up the camera and beeping out pins on the header to figure out the power/ground pins. It's difficult to power up the camera with it disassembled enough to get to that connector, so I spun a couple of PCBs to break it out via some FFC. The interface on the header is just a standard parallel camera interface: a few pins for clock, vsync, and hsync, then a bunch of data pins. The plan was to hook the breakout up to an iCE40 FPGA to serialise the data and put it out over an LVDS pair or something. Then I could put all that on a PCB to install in the camera, where the TAXI board would usually go.
At this point I got a surprise opportunity to buy one of the TAXI PCBs from a forum member who had one going spare! I did a bit of research and found I could get the AM7969 receiver IC as new-old stock on eBay/Aliexpress with no trouble and it looked easy enough to drive, so I bought the TAXI board and could now concentrate on just making a custom receive side.
Once the board arrived, I got it installed in the camera with no troubles. For the serial output, it has a 4-pin header that's of the same Hirose DF11 series as the mainboard connector that carries S-Video/-RS232/etc.. I was able to source the right housing (Hirose DF11-4DS-2C), pop the crimps out of the larger housing for the S-Video wires, and pop them into the 4-pin housing for the TAXI board. Not sure if that's what FLIR do in the proper installs (would be interesting to see some photos if anyone's got one?) but it seems to work well enough for now.
With all that done, I fired up the camera and... no digital out.
I planned to do some probing around on the board when I could dedicate some time to open up the camera again. In the meantime, I went and did a bit of research and had a look at Fraser's photos of the official PCMCIA receiver. I noticed that it had the RS232 hooked up - maybe they were sending a command to turn things on? I also had a look at docs for the official receiver software, which had some specific start & stop UI which suggested there would be a way to turn on/off the data output.
I connected up the RS232 and had a play around, trying to guess at any undocumented commands. I did find a command "DIGITAL" that would return error code "16" which was different to the normal error code for an unknown command. I tried all sorts of different arguments to it but couldn't get anything other than that error 16.
I continued looking around for undocumented commands and found the rather fun "MEM" command. After some experimentation, I learned that this took two arguments: a memory address and an optional length. With these, it would return a hexdump of that chunk of memory. Helpfully, the boot messages over serial tell me that the image is loaded at 0xff030100 so I wrote up a quick python script to dump chunks of memory around that area and started looking for interesting strings & code. Later I learned a bit more about the memory map and ended up dumping the full flash from 0xff000000 to 0xff200000. I also dumped out the full RAM contents based at 0x0 to help with reverse engineering later.
I ended up loading the images up in Ghidra, so I could do some reverse engineering & figure out some of the firmware's secrets. It was easy enough to search for some of the known commands and find a big table of each command string along with a function for handling it:
I scrolled through the table and found that yes, there was indeed a "DIGITAL" command and jumped to the handler for it. The following image shows the decompiled function with a bunch of my manual naming added, and you can see that right at the start it checks a global flag that I've named `_allow_digital_command` and if it's 0 it bails out and returns error 16!
I looked around for other references to that global and found that there's a table of installed options stored in flash and, at startup, if the TAXI board is in that table then the global is set. I've not got into modifying the flash yet, so I just used the "MEMW" serial command to write a 1 to the RAM address for that global. I tried the "DIGITAL" command again and success, data!
I bodged together a quick breadboard setup for the TAXI receiver & everything was looking good: VLTN (data error) stayed low and there were bursts of activity on dstrb & the data lines that seemed to line up with field periods:
Next up was to spin a PCB to connect all of this a bit more reliably, to figure out the exact format, and to shuttle in the data over USB. But more on that next time.