Dev: Making new datalogging definitions for QuarterHorse


Creating definitions for datalogging with the QH is a complicated, involved process.   Regardless of which software is being used, there is a common core set of tasks that need to be done to allow meaningful real-world data to get spit out.


Before I get into the specifics, it probably helps to understand how the QH works a little better.

The QH sits on the J3 port of the ECM, which is a bus connected to the processor.  On a stock ECU, both the external program memory (RAM) that stores active processor states and the internal program memory (“ROM”) which stores the strategy and calibration are present on this bus.  The QH overrides addresses on the bus allowing the processor to use RAM on the QH instead of ROM native to the ECM.  You can make changes while tuning by modifying the contents of RAM on the QH.  This is the same mechanism that F3/F5/F8 chips use to allow you change the program on the ECM.

The QH also builds a “shadow” copy of external RAM used by the processor by passively observing communication between the processor and RAM over the J3 port.  Where things get complicated is that not all RAM can be observed by the QH – a portion of it remains internal to the processor, unable to be seen by the QH.  Patch code exists to move or copy memory addresses that we care about from memory the QH cannot see to memory the QH can access, allowing you to log these items.  To reiterate – the QH doesn’t interfere or change communication between the processor and RAM on the ECM – it just observes all transactions, building a “shadow” copy of RAM that is used to supply logging data.

A Datalogging Definition, Dissected

In order to understand the software tasks involved in QH communication, we are going to examine a TunerPro ADX for the CBAZA strategy.  Other software follows the same steps to initialize and log from the QH, so you can read between the lines if you’re not using TunerPro.  The TunerPro definition is open so you can download it ( here ) and follow along because the whole initialization and logging process is broken down step by step.

Fire up TunerPro.  Load one of the existing Ford ADX files. (CBAZA.ADX)

Go to Acquisition menu… Edit Definition

Looking at the ADX Header Data, you will see 3 important commands:

  • Connection Command (run when you connect to datalog)
  • Monitor Command (run continuously while logging to gather data)
  • Disconnect Command (run when you disconnect)

Next, lets examine the Connection Command closer, as it has most of the magic in it.

Go to Commands… Configure QH for Payload.  This is a Macro command that simply executes a bunch of other commands:

  1. Pause for Data Rate (simple pause to let things settle)
  2. Write Patch Code (modify the ECU program to allow the QH to log all items – more on this later)
  3. Write Patch Response (wait for a valid response from the QH to the code modification)
  4. Config Part 1 of Q (configure the QH to watch the RAM locations we desire – more on this later)
  5. Config Reply to Q (make sure QH gives a valid response to the configure command)

Step #2 writes the patch code needed to move things we care about from private internal RAM to RAM the QH can snoop on.  This patch code is UNIQUE to each strategy.  It must be hand-crafted by someone with knowledge of the internal workings of the ford processor.

Step #4 configures which bytes of RAM the QH is monitoring.  The bytes used are unique to each strategy and are also dependent on how the patch code is written.

Continuing, logging happens by the Harvest Data Macro.

  1. Pause for Data Rate (this controls how fast the QH logs data, in hertz)
  2. Query (retrieve a frame of data, as configured by Config Part 1 of Q command)
  3. Data Packet (retrieve a packet.  fixed size is used here because the same packet is always configured by the Config Part 1 of Q command)

Datalogging values are defined relative to their spot in the packet you’ve requested in the format specified by the Config Part 1 of Q command.  Same deal for bitmasks.  Formulas for turning raw data into real world values can vary but are generally at least somewhat consistent among ECMs of comparable generations.


If you want to make a datalogging definition for a processor, you’re going to need to:

  • disassemble the code well enough to pinpoint RAM locations for things you care to log.
  • For any items that are stored in ram locations 0x0000 through 0x0100 (EECIV) and 0x0000 through 0x0400 (EECV ??? need to verify, may be different for 2 vs. 4 bank.  You can generally tell because private locations will always return the same data), you are going to need to write patch code to relocate these items to blank/unused space.  You can relocate items to either RAM or “ROM” space (because the QH gives read-write access via the J3 port to “ROM” locations stored in RAM on the QH) but you need to make sure NOTHING ELSE IS USING THE ADDRESS SPACE.  If you use RAM or “ROM” that is already in use for other things, you will end up with a processor that does not run properly!!!
  • build a definition including the patch code you’ve come up with
  • create an initialization macro for the QH specifying which RAM addresses need to be included in each data packet, using both stock and patch-code-remapped locations
  • do some analysis to come up with formulas for converting from raw values to real world data
  • build the data values using the formulas you’ve come up with and the packet structure you’ve specified with the QH initialization packet

I know that’s a lot to chew on, but the QH isn’t exactly a simple tool…  You can find more information about QH command structure by reading the Hardware Interfacing guide.  We’re always excited to have more people getting involved in the task of building definitions so feel free to email us if you get confused or stuck.

Memory Addressing – EECIV

Note: these addresses are for the QH’s addressing scheme.  If you want to use the 16 bit addressing of the ECU, lop off the MSB of 0x03 present in each one.  Ever wonder why chips get programmed from 0x032000 to 0x03FFFF ?

0x03 00 00 – bottom of memory
0x03 00 FF – top of internal 8061 MCU memory
0x03 01 00 – start of xram/others
0x03 1F FF – end of externally addressable memory
0x03 20 00 – start of ROM
0x03 FF FF – end of ROM

This PDF should be very helpful for understanding what is going on. (thanks Tom Cloud)


CATS Disassembler – a disassembler which can be used for the processor found in EEC-IV