Introduction

Select Monitor Adapter
Subaru Diagnostic Ports
How to build a PC adapter
Protocol
Software
Troubleshooting
Eavesdropping

Engine Control Unit (ECU)
Description
Reading Error Codes
Reverse Engineering
Modifying
ROM images

Transmission Control Unit (TCU)
Description
Reading Error Codes
Reverse Engineering
Power Mode
Modifying
ROM images

Other Control Units
Air Conditioning Unit
4WS Control Unit
Cruise Control Unit

OBD2 Information
Select Monitor Cartridge

Downloads
Links to other sites

Custom TCU Development



Subaru Select Monitor Protocol

Binary Mode

The communication protocol is 1953 baud, 8 data bits, 1 stop bit, Even Parity and no flow control (1953-8E1). The commands (in hex) are given in the table below. When you send a read command, the control unit will send back data from that address until you tell it to stop. In order to write data, you must be receiving data. ie. To write FF to address 1234 in the ECU, you would first issue an ECU read command 78123400 and then a write command AA1234FF. Similarly the "Get ROM ID" function only works if you are receiving data.


Byte 1Byte 2Byte 3Byte 4Function
12000000Stop
78msblsb00Read data from ECU address
45msblsb00Read data from TCU address
8900lsb Read data from AirCon address
9200lsb Read data from 4WS address
AAmsblsbdataWrite data to address
AB00lsb Read data from Cruise address
00464849Get ROM ID

The reply format for read and write commands as shown in the table below.
msblsbdata

In the tables above, msb is geekspeak for "most significant byte" meaning the first byte of the address. Similarly lsb refers to "least significant byte", meaning the second byte of the address. For the hex address 12AB (hex), the msb is 12 and the lsb is AB.

According to Kashima, the 4th byte of the read command is supposed to indicate how many bytes to read. This does not seem to work on the cars I have tested. The byte must be sent, but its value seems to be ignored.

ASCII Mode

There is also an ASCII mode which runs at 4808 baud, 8 data bits, 1 stop bit, No parity (4808-8N1). We are still investigating the proper method to switch the ECU into ASCII mode. At present we achieve it by manually setting the mode flag at location 12CF to 1.

Byte 1Byte 2Byte 3Byte 4Byte 5Byte 6Byte 7Function
7Faddr1addr2addr3addr43030Read data from ECU address
20addr1addr2addr3addr4msblsbWrite data to address

The reply format for ASCII read and write commands as shown in the table below :
addr1addr2addr3addr4msblsb0A0D
For example, to read address 12AB, you send "7F313241423030" and the ECU will send back "3132414230300A0D". It does not repeat like the binary mode. 31 is the ASCII code for "1", 32 is the code for "2", 41 is the code for "A" etc.

Other Considerations

The baud rate is quite slow, realistically you can only query about 5 memory locations per second. A dump of the entire address space from 0000 to FFFF takes between 3 and 4 hours and can flatten your car battery.

We have experimented with increasing the baud rate but this alone is not sufficient to increase the speed at which data can be read from the ECU. The ECU sends one result each time it calls the comms routine. The baud rate only determines how quickly that result reaches the PC. In order to speed up the data tranfer it would be necessary to modify the ECU program to call the comms routine more often.

When writing software to access the select monitor port, there are a few important considerations to ensure the accuracy of the data returned. There is no flow control, so you must read the data as fast as the ECU is sending it, otherwise your serial port input buffer will overflow and your program will get out of sync with the data. With this in mind, it makes sense to sanity check the returned msb and lsb bytes, before reporting the data byte.

I have developed an open source C library for linux that contains all the calls you need to reliably query the Select Monitor port. The serial port is programmed to generate an interrupt when data is received and then an interrupt handler reads the received data into a 3-byte circular buffer. This prevents the serial port input buffer from overflowing. The API function sends the read command to the ECU and then polls the circular buffer until a valid result has been returned for the queried address. This mechanism has been proven to work well.