Now lets look for the code that sets an error. We'll start with an easy one, the TPS.
From the table in the previous post, you can see that the TPS error flag is bit 4 of 4042. We count bit numbers from right to left, starting at zero.
00000000 (00) 00010000 (10) 00000000 (00) 31 Throttle Sensor
To find the subroutine that sets this flag do the following:
findstr 4042 Sub-*
This gives a list of all the subroutines that access address 4042. Somewhere in the list you will find:
Sub-9E69.txt:009E8A 0C424010 seb #0x10, 0x4042
Sub-9E69.txt:009E93 1C424010 clb #0x10, 0x4042
The "seb" instruction means
SEt
Bits (to 1). the "clb" instruction means
CLear
Bits (to 0). The #0x10 is the hex code for the TPS error bit in the table. So we have found that subroutine 9E69 turns the TPS error flag on and off. The location for the TPS parameter will probably be somewhere in that subroutine.
009E69 D8 clm ; m:0 x:0, Calltarget from 9CF9
009E6A A90004 lda ax, #0x0400
009E6D 38 sec
009E6E ED5140 sbc ax, 0x4051
009E71 AA tax
009E72 F8 sem ; m:1 x:0
This says:
- load the AX register with the value 400 hex
- subtract the 16bit value stored at 4051 from the AX register
- transfer the AX register to the X register.
This is probably the TPS signal. The A/D converter in the ECU probably reads the TPS voltage as a number between 0 (being 0 volts) and 0x400 (being 5 volts). I remember you saying that your TPS works backwards to normal, so that is probably why it is subtracting from 0x400.
009E73 EC9C8C cpx 0x8c9c
009E76 F007 beq 0x9e7f
009E78 9005 bcc 0x9e7f
- Compare the X register to the value at 8C9C (using the hex editor you can see this is 0x2889)
- If "equal" then branch to 9E7F
- if "less than" then branch to 9E7F
009E7A EC9E8C cpx 0x8c9e
009E7D 9010 bcc 0x9e8f
- Compare the X register to the value at 8C9E (using the hex editor you can see this is 0x8578)
- If "less then" then branch to 9E7D
The TPS signal is being compared against a lower and upper limit. If it falls inside these limits, then the program branches to 9E8F.
009E8F 9CB24100 ldm #0x00, 0x41b2 ; Branch targetfrom 9E7D
009E93 1C424010 clb #0x10, 0x4042
009E97 60 rts
This clears the error flag and exits.
However, if the signal falls outside the limits then the following happens:
009E7F A2B241 ldx #0x41b2 ; Branch targetfrom 9E76, Branch target from 9E78
009E82 20DFA3 jsr 0xa3df
009E85 CDA08C cmp al, 0x8ca0
009E88 9004 bcc 0x9e8e
009E8A 0C424010 seb #0x10, 0x4042
009E8E 60 rts ; Branch targetfrom 9E88
I have decoded the subroutine at A3DF. It basically says "add 1 to the memory address pointed at by the X register and load it into the al register". So the variable at 41B2 is an error counter. Every time the TPS signal falls outside the limits, it adds one to the counter. When the counter is less than the value at 8CA0 (this is 04) it branches to 9E8E and exits. But when the counter exceeds 4, the TPS error bit gets set.
To summarize, the TPS signal is a 16bit value stored at 4051. The TPS check engine code will be set when the TPS signal falls outside the valid range for more than 4 consecutive cycles of the program.
In this case, we didn't get lucky. We know the TPS signal is at 4051, but this is a 16bit value and the select monitor values are all 8bit. So now we need to look where the value in 4051 comes from.
findstr 4051 Sub-*
Sub-EFAE.txt:00EFE6 EC5140 cpx 0x4051
Sub-A06A.txt:00A094 ED5140 sbc ax, 0x4051
Sub-F170.txt:00F175 AE5140 ldx 0x4051
Sub-9E69.txt:009E6E ED5140 sbc ax, 0x4051
Sub-DFEA.txt:00DFEA AE5140 ldx 0x4051
Sub-DFEA.txt:00E042 8D5140 sta ax, 0x4051Sub-DFEA.txt:00E0EC 8E5140 stx 0x4051The interesting one here is Sub-DFEA because it contains "store" commands: sta,stx
00DFF0 342008FC bbc #0x08, dp + 0x20, 0xdff0 ; Read from A/D control register
00DFF4 A622 ldx dp + 0x22 ; Read from A/D successive approximation register
00DFF6 8EC142 stx 0x42c1
00DFF9 642004 ldm #0x04, dp + 0x20 ; Write to A/D control register
00DFFC 8622 stx dp + 0x22 ; Write to A/D successive approximation register
00DFFE 342008FC bbc #0x08, dp + 0x20, 0xdffe ; Read from A/D control register
00E002 D8 clm ; m:0 x:0
00E003 A522 lda ax, dp + 0x22 ; Read from A/Dsuccessive approximation register
blah blah blah
From the disassembler comments we can see that this subroutine is reading from an A/D converter. We don't need to worry too much about how it works.
00E031 48 pha
00E032 4A lsr ax
00E033 4A lsr ax
00E034 F8 sem ; m:1 x:0
00E035 8D8447 sta al, 0x4784
00E038 D8 clm ; m:0 x:0
The value from the A/D converter gets shifted right by 2 digits. In binary terms, that means divided by 4. So instead of a number from 0 to 400. We get a value from 0 to 100, that fits nicely into a single byte and gets stored at 4784.
00E039 68 pla
00E03A 38 sec
00E03B E90004 sbc ax, #0x0400
00E03E 49FFFF eor ax, #0xffff
00E041 3A inc ax
00E042 8D5140 sta ax, 0x4051
The same original value gets processed in some way and written to 4051. At this stage it is not important to understand what math is done on it. The important thing to see is that 4784 and 4051 are both derived from the A/D converter that reads the TPS signal.
4784 is an 8 bit value and is probably the one that the select monitor uses.
We found our first parameter.