Ryan Kim

Reverse Engineering a Welch Allyn Propaq Encore ECG

Disclaimer

This project is for research and educational purposes only. All software or hardware described below is provided as-is for educational purposes and is not intended to diagnose, treat, or cure any medical conditions. Always consult a licensed healthcare professional for medical concerns.

Background

The Welch Allyn Propaq Encore is a vital sign monitor that was first released in 1995 and was widely used in hospitals and emergency services until it reached end-of-life on December 31, 2012. Parts and support for the device ended five years later. As a result, many of these devices are available for low-cost on resale markets.

I first acquired a Propaq Encore for around $20 from the University of Michigan property disposition. It was a model 206EL with the SpO2 module. Unfortunately, the device was broken during a move, but this led me to acquire a second model. This time, it has an AcuityLink modem port, which should allow me to digitize the output.

The model 206EL (and the associated SpO2 module) can provide a multitude of vital signs. Namely,

For the purposes of this project, I will focus on retrieving all data except for the invasive blood pressure readings (because this requires placing a arterial catheterization, which I am unwilling and unqualified to do).

Initial Impressions

The initial step is reading through the device manuals. According to the service manual, the AcuityLink has a seven wire internal connection (the physical connector is an RJ12 6P6C connector with the seventh wire being a ground shield). The pins are as follows:

  1. TXD_GND
  2. TXD
  3. RXD
  4. CTS
  5. RTS
  6. RXDCOM
  7. 423 SHLD
This strongly suggests that the device uses a serial connection. The 423 in the pinout refers to the RS-423, which was a standard intended to replace RS-232, but was never widely adopted. Fortunately, the protocol is mostly compatible with RS-232. Unfortunately, the logic levels for RS-423 are +- 6 volts instead of the +- 12 volts used by RS-232. This means that the device probably shouldn't be connected directly, however inspection of the hardware reveals tolerances for RS-232 logic levels in the circuitry used (the warning above applies here as well, so please be careful if you attempt to connect the device directly). For the rest of this project, I am going to directly connect to my USB-to-RS232 adapter, which outputs +- 8 volts. Interestingly, even my non-acuity enabled Propaq Encore has the physical modem connector, but it is hidden behind a plastic cover.

Ideally, the ECG would begin transmitting data as soon as it is powered on, however it appears to be silent on the initial start. Looking through the service menus on the device, there are two tests that can be run:

The ECG appears to transmit at 38400 baud, 8 data bits, 1 stop bit, no parity. The logic levels appear to be tolerated by both the Propaq Encore as well as my USB-to-RS232 adapter. Loop test is a very simple test, the ECG sends 0x55 and 0xAA and expects the same data back. If the data is received correctly, the ECG will display passed, otherwise it will display failed. The output test streams 0xff 0x55 0xaa 0x00 for many iterations. Unfortunatelyj, neither of these tests appear to send any particularly useful data from the perspective of data framing and decoding. They seem to be quite simple serial tests.

In general, the ECG seems to be quite the black box. The device does not broadcast on power on. It doesn't not seem to respond in any meaningful way to data that is sent (which probably means I've only sent it malformed data). Of note is that sending data quickly (like serial writing more than around 16 bytes) seems to cause the device to warn that the serial communication is not working properly. This could suggest that the expected data frame is quite small.

Reading the manual for the AcuityLink that the Propaq Encore was designed to work with, it appears that the device may be waiting to receive a patient configuration before it begins transmitting data. Without a priori knowledge of the format it is expecting, it appears that I need to dig deeper into the device to find a path forward.

The Hardware

The Propaq Encore is designed with a series of modular circuit boards. For the purposes of this project, I only care about the analog board and the digital board, because these boards are connected closely to the location where the AcuityLink connects. Both of these boards possess a Dallas Semiconductor DS80C320 microcontroller, which is an 8051-compatible microcontroller. Each one is connected to an M27C2001 EPROM in a PLCC32 package. These appear to contain the programs for the device as well as data for things like languages.

Both of these boards have fairly complex PCB layouts, so I would prefer to avoid tracing the connections if I can avoid it. I hope that the ROMs will contain enough information in one or the other to determine how the serial is passing through the device.

Dumping the binaries

The first step to the analysis is to dump the binaries from the ROMs. I used a T48 programmer to read the ROMs, and it appears that both are have 256 kB of data. The data appears to be split into four pages of 64 kB each. The first page of both is certainly the program. The last two pages of both appear to be data with obvious strings in them. The second page requires further analysis but it could be additional program memory.

The original 8051 only supported 64 kB of program memory (16-bit, big-endian) architecture, but the DS80C320 can support more through the use of paging.

Disassembling the binaries with Ghidra reveals a fairly complex program in both of the ROMs. It appears that the serial for both of them is used with multiple accesses to the SBUF register. This means that additional work is need to determine how serial data is being used on the board, and how to isolate the serial data coming from the AcuityLink.

A New Hope

The ECG is really a sandwich of two boards: the analog and the digital board. Both of these boards have a DS80C320 microcontroller, and the pinout notes the pins for rx and tx between the two boards. Since the analog board has the ADCs collecting the data that we care about, and the digital board has the display controller and the AcuityLink, this means that the data we care about must go from the analog board to the digital board. So what if we ignored the operation of the system and just treated it as a black box of data?

Now this becomes three problems: snooping the data between the two boards, sending the data through the existing modem port, and interpreting the data.

The first problem is the most annoying, because the DS80C320 microcontrollers are running in a 9-bit serial configuration mode (I know this from the deocompilation of the binaries, so dumping them wasn't a waster after all). The extra bit is used to denote whether the byte is an address or data. Most devices don't support this mode, so this limits the microcontrollers that I can use to snoop the data. In practice I could use another 8051 microcontroller, but I don't want to particularly want to bringup a new board. Another option is to use a Raspberry Pi Pico, which has a programmable IO (PIO) system that should be able to handle the 9-bit serial fast enough.

After using my oscilloscope to look at the 9-bit packets and after analyzing the binary handlers for the data from the TL16C550C UART handling chip, I determined that the baud rate between the analog and the digital board is at 168000 baud, which is rather non-standard, but that's actually okay because the PIO on the pico is tied to the system clock, so as long as the cycle dividing is right, it will work. The data is sent in multibyte packets where the first byte is one with the 9th bit set. Instead of using it to denote the address, it appears that it uses the data of that byte to denote the type of data that will follow.

The second problem (that being how we get the data off of the device) is a little more straightforward at least in theory. The tricky bit is that because this device is medical equipment, maintaining electrical isolation is important. Fortunately, the TL16C550C is already connected to the optocouplers needed for isolation. So we can just solder some wires to the output and the input of the TL16C550C and use the existing trace paths for the output and input to the pico. The AcuityLink as mentioned earlier in this writeup is very non-reactive, so we can just leave it connected without any apparent issues.

As far as some of the nitty gritty of the firmware for the pico, I also need input from my computer because I want to be able to timesync data for my future project. Additionally, the optocouplers can't seem to transmit data very fast, so I need to run it at 38400 baud (I tested bauds about this and the waveforms start to look too sinusoidal to be reliably decoded). The data comes in pretty fast, so we need to use DMA and keep everything as lightweight as possible to not drop data. As far as framing, I went for consistent overhead byte stuffing (COBS), which isn't the fastest framing because it needs encoding and decoding, but it is robust and allows my to remove 9 bit data and just use the type as the first byte of the decoded data. You can see the code for this project here

The final problem is interpreting the data. Now I haven't fully decoded every packet, and I don't have the proper units for some of the data. However, I've decoded the data that I care about (ECG, SpO2, NIBP, and temperature) The SpO2, ECG, and NIBP are all waveform data streams so the heart rate can be derived from any of them. I wrote a viewer in Rust that can display the data in real time, and it seems to line up with the display. Unfortunately for the ECG data, it would appear that despite the device being a 5-lead ECG, the data steam is actually multiplexed so that you can only get one lead at a time. This is somewhat unfortunate, but it is still suitable for my echotomography project and this device is still much less expensive than buying a modern ECG that has a digital data feed.