The very early motronics had the bosch code on the 8051's internal ROM, but they stopped that around the time they moved to 8052 mcus.
The ECU you're looking at is newer than the 3.1/4.1, and they have the bosch code on the eprom. If you disassemble the 4.1 bin I posted, you'll see the bosch routines in the 0-1fff area.
It's things like map lookup, 16 bit multiplication, ADC reading etc. They routines are pretty much the same for all motronics.
Here's some info on some of them - it's from a 4.1 perspective so the ADC channels etc might be different.
I assume the 7.1 has external SRAM like the others?
Code: Select all
SEG CODE
;----------------------------------------------------------------
; to read from ext sRAM (256 bytes)
; mov P2, #07Fh
; movx A, @R0
;----------------------------------------------------------------
; DPTR = BC0n (n - channel #)
; 0 - AFM
; 1 - 12v level
; 2 - Tair
; 3 - Teng
; 4 - CO pot
; 5 - lambda
; 6 - aux inputs (4 digit inputs)
; 7 - octan correction switch (can be used as an AN input)
;-------------------------------------------
BoschADCRead:
L0247:
movx A, @DPTR
nop
nop
; start conversion and wait
; the datasheet specifies (not clearly) max conv time of
; 115 clock cycles. The clock is 10Mhz/12 (i.e. ALE / 2)
; The max conversion time I've observed is 90us, which gives 75 clock cycles
movx A, @DPTR
; save R0
mov A, R0 ; 1c
; mov R0, #45h ; 1c - original Bosch delay
mov R0, #42 ; 1c
L0248:
djnz R0, L0248 ; 2c
mov R0, A
movx A, @DPTR
ret
;----------------------------------------------------------------
; Decode octan switch position on AN7, usefull on Alfa 75
; input
; A - contains ADC7 value
; output
; A - 0-7 value
; uses
; R0, R1
DecodeOctanPosition:
mov R1, #7h
mov DPTR, #T8values
lcall L0992
ret
;----------------------------------------------------------------
; Decode 4 auxiliary digit inputs connected to AN6
; input
; A - contains ADC6 value
; output
; A - 0-15 value
; uses
; R0, R1
DecodeAuxInputs:
mov R1, #0Fh
mov DPTR, #T16values
lcall L0992
ret
L0992:
mov R0, A
L1021:
mov A, R1
movc A, @A+DPTR
add A, R0
jc L1020
djnz R1, L1021
L1020:
mov A, R1
ret
T8values:
db 0FFh,0E8h,0BFh,0A0h,083h,062h,03Fh,018h
T16values:
db 0FFh,0F7h,0E6h,0D5h,0C4h,0B3h,0A2h,091h
db 080h,06Fh,05Eh,04Dh,03Ch,02Bh,01Ah,009h
;----------------------------------------------------------------
READ_DIGIT_INPUTS MACRO
mov DPH, #0F7h
movx A, @DPTR
ENDM
; Read 6 input digit inputs
; output
; A - the digit port flags (inverted bits, 1 means ON)
ReadDigitInputs:
; Bosch code, does not work with Atmel derivatives as by default
; movx accesses the internal XRAM
; mov P2, #0F7h
; movx A, @R0 ; R0 content does not matter
; mov P2, #0FFh
READ_DIGIT_INPUTS
xrl A, #3Fh ; 6 LSB only
ret
;----------------------------------------------------------------
; Bosch: get the absolute temperature value from the temp sensor measure
; input
; A - ADC value
; output
; A - linearized positive value
; uses
; R4, DPTR
TranslateTempMeasure:
cpl A
mov R4, A ; the map reads from R4B0
mov DPTR, #TempTranslMap
lcall Read1dMap
ret
TempTranslMap:
; out 0 11 24 45 70 101 133 157 189 218 234 235
; [04] 7 10 16 30 56 98 144 176 203 221 227 235
; [ADC] 248 245 239 225 199 157 111 79 52 34 28 20
db 004h,00Ch,003h,006h,00Eh,01Ah
db 02Ah,02Eh,020h,01Bh,012h,006h,008h,015h
db 000h,00Bh,018h,02Dh,046h,065h,085h,09Dh
db 0BDh,0DAh,0EAh,0EBh
;----------------------------------------------------------------
; 1D/2D maps access routines
; input
; DPTR - addr of the map
; the X and Y value addresses are stored in the map
; output
; A - map value
; uses
; A, reg bank 2
Read1dMap:
push PSW
push B
setb RS1
clr RS0
lcall L0004
lcall L0005
sjmp L0002
Read2dMap:
push PSW
push B
setb RS1
clr RS0
lcall L0004
mov B, R1
mov A, R0
mov R6, A
mov A, R3
mov R7, A
lcall L0004
mov A, R2
mul AB
add A, R1
mov R1, A
mov A, R7
jz L0014
lcall L0005
L0014:
xch A, R2
cpl A
inc A
add A, R1
mov R1, A
lcall L0005
xch A, R7
jnz L0015
xch A, R7
sjmp L0002
L0015:
mov R3, A
mov B, R6
xch A, R7
mov R5, A
mov A, R2
lcall L0016
L0002: ; exit from map procedures, switch to reg bank 0
pop B
pop PSW
ret
; Find 1D map range
L0004:
clr A
movc A, @A+DPTR ; fetch axis param addr
mov R0, A
inc DPTR
clr A
movc A, @A+DPTR ; fetch axis length -> R2 and R1
mov R2, A
mov R1, A
mov A, @R0
mov R0, A ; R0: axis input param value
L0012:
mov A, R1
movc A, @A+DPTR
add A, R0
mov R0, A
jc L0011
djnz R1, L0012
; the input value is < leftest value, take the leftest value
inc R1
clr A
sjmp L0013
L0011:
mov A, R1
xrl A, R2
jz L0013 ; the input value is >= rightest axis value, take the rightest value
mov A, R1
movc A, @A+DPTR
L0013:
mov R3, A
; R3 is the first left axis value less then the input value
inc DPTR
mov A, R2
add A, DPL
mov DPL, A
clr A
addc A, DPH
mov DPH, A
; DPTR points at the first byte after the axis bytes
ret
; Find the map Z value
L0005:
mov A, R3
jnz L0006
mov A, R1
dec A
movc A, @A+DPTR
ret
L0006:
mov B, R0
mov A, R1
dec A
movc A, @A+DPTR
mov R5, A
mov A, R1
movc A, @A+DPTR
L0016:
clr C
subb A, R5
mov F0, C
jnc L0007
cpl A
inc A
L0007:
mul AB ; A * B -> B:A
; -------------- Start of the fix
; Division B:A / R3 -> R4:A , B - remainder
lcall Div_BA_R3
jnb F0, L00100
cpl A
inc A
L00100:
add A, R5
ret
; -------------- End of the fix
;;;; not used code because it did not work in some cases and I
; suspect it's a bug (or limitation)
; C == 0
; division A,B / R3
; I dont understand how all the following works except
; if I assume B is == 0
; in which case the dX * dZ should be < 256
; and there is nothing to garantee that
; mov R4, #8h
;L0009:
; rlc A
; xch A, B
; rlc A
; subb A, R3
; jnc L0008
; add A, R3
;L0008:
; xch A, B
; djnz R4, L0009
; rlc A
; cpl A
; ; division finished, result in A
; ; now do an additional division step
; ; I dont understand why
; xch A, B
; rlc A
; subb A, R3
; cpl C
; clr A
; addc A, B
; jnb F0, L0010
; cpl A
; inc A
;L0010:
; add A, R5
; ret
;----------------------------------------------------------------
; shift 0 -> R7:R6:R5 -> until R7:R6 == 0, with arithm round
; incr R4 for every shift
; if R7:R6:R5 was FFh:1xxx xxxx:00h then behave as if it was 1:00:00:00
; input
; R7-R5, R4
; output
; A, R4
ShiftR_R765:
mov A, R7
jz L1085
xch A, R4
add A, #8h
xch A, R4
sjmp L1086
L1085:
mov A, R6
jnz L1088
mov A, R5
ret
L1088:
clr C
rrc A
xch A, R5
rrc A
xch A, R5
inc R4
jnz L1088
addc A, R5
jnc L1089
; the result was FF
mov A, #80h
inc R4
L1089:
ret
;----------------------------------------------
; Called from ShiftR_R765 above
; shift 0 -> R7:R6 -> until R7 == 0, with arithm round
; incr R4 for every shift
; if R7:R6 was FFh:1xxx xxxx then behave as if it was 1:00:00
; output
; A
ShiftR_R76:
mov A, R7
jnz L1086
mov A, R6
ret
L1086:
clr C
rrc A
xch A, R6
rrc A
xch A, R6
inc R4
jnz L1086
addc A, R6
jnc L1087
mov A, #80h
inc R4
L1087:
ret
;----------------------------------------------------------------
; Shift R7:R6:R5 right or left
; if A < 0 then 0 -> R7:R6:R5 >> (-A)
; if A > 0 then R7:R6:R5 << A or until R7.7 == 1
L0065: ; [@0C49]
jnb ACC.7, L0394 ; @0C6A ; @0C49 [30E71E]
L0395: ; [@0C4C]
; Jump from: 0C57
clr C ; @0C4C [C3]
xch A, R7 ; @0C4D [CF]
rrc A ; @0C4E [13]
xch A, R7 ; @0C4F [CF]
xch A, R6 ; @0C50 [CE]
rrc A ; @0C51 [13]
xch A, R6 ; @0C52 [CE]
xch A, R5 ; @0C53 [CD]
rrc A ; @0C54 [13]
xch A, R5 ; @0C55 [CD]
inc A ; @0C56 [04]
jnz L0395 ; @0C4C ; @0C57 [70F3]
ret ; @0C59 [22]
L0396: ; [@0C5A]
; Jump from: 0C6A
xch A, R7 ; @0C5A [CF]
jnb ACC.7, L0397 ; @0C60 ; @0C5B [30E702]
xch A, R7 ; @0C5E [CF]
ret ; @0C5F [22]
L0397: ; [@0C60]
; Jump from: 0C5B
clr C ; @0C60 [C3]
xch A, R5 ; @0C61 [CD]
rlc A ; @0C62 [33]
xch A, R5 ; @0C63 [CD]
xch A, R6 ; @0C64 [CE]
rlc A ; @0C65 [33]
xch A, R6 ; @0C66 [CE]
rlc A ; @0C67 [33]
xch A, R7 ; @0C68 [CF]
dec A ; @0C69 [14]
L0394: ; [@0C6A]
; Jump from: 0C49
; Called from: 13DC 0806 081E 0885
jnz L0396 ; @0C5A ; @0C6A [70EE]
ret ; @0C6C [22]
;----------------------------------------------------------------
; R7:R6 * A -> R7:R6:R5
; preserves B
Mul_R7R6_A:
mov R5, A ; copy A
xch A, B ;
xch A, R6 ; R6 = B orig : save B
mul AB ; B:A = R6 * A
xch A, R5 ; R5 = A - partial result
xch A, B ;
xch A, R6 ; R6 = B - partial result
xch A, R7 ; R7 = B orig
mul AB ; B:A = R7 * A
add A, R6 ;
mov R6, A ;
clr A ;
addc A, B ;
xch A, R7 ;
mov B, A ; restore B
ret ;
;----------------------------------------------------------------
; B:A * R3 -> B:A:R3
; uses R4
Mul_BA_R3:
; B:A * R3
xch A, R3
mov R4, A
; A: orig R3, R3: orig A, R4: orig R3
mul AB
; B:A:00 = B * R3
; now do A * R3, so R3 * R4
xch A, R3
xch A, B
xch A, R4
; B:A:00 is in R4:R3:00
mul AB ; B:A - result
xch A, R3
add A, B
mov B, A
mov A, R4
addc A, #0
xch A, B
ret
;----------------------------------------------------------------
; R6:R5 * A -> R7:R6:R5 (A == R5)
; preserves B
Mul_R6R5_A:
mov R7, A ; copy A
xch A, B ;
xch A, R5 ; R5 = B orig : save B
mul AB ; B:A = R5 * A
xch A, R7 ; R7 = A
xch A, B ;
xch A, R5 ; R5 = B
xch A, R6 ; R6 = B orig
mul AB ; B:A = R6 * A
; B:A:00 + 00:R5:R7 -> R7:R6:R5
add A, R5 ;
xch A, R6
xch A, B
addc A, #0
xch A, R7
mov R5, A
ret ;
;----------------------------------------------------------------
; R7:R6:R5 * A -> B:R7:R6:R5
Mul_R7R6R5_A:
mov B, A
xch A, R5 ;
mul AB ; B:A = R5 * A
xch A, R5 ; R5 = A, restore A
push ACC
xch A, B
xch A, R6 ; R6 = B
mul AB ; B:A = R6 * A
add A, R6
mov R6, A ; R6
clr A
addc A, B ; A = B + carry , FF*FF=FE01
xch A, R7 ; R7 = B
pop B ; restore A
mul AB ; B:A = R7 * A
add A, R7
mov R7, A
clr A ; A = B + carry
addc A, B
mov B, A
ret ;
;----------------------------------------------------------------
; (R1:A * R7:R6)[31:8] -> R7:R6:R5
Mul_R1A_R7R6:
mov R5, A ; @0C04 [FD]
mov B, R6 ; @0C05 [8EF0]
mul AB ; @0C07 [A4]
mov A, B ; @0C08 [E5F0]
xch A, R6 ; @0C0A [CE]
mov B, R1 ; @0C0B [89F0]
mul AB ; @0C0D [A4]
add A, R6 ; @0C0E [2E]
xch A, R5 ; @0C0F [CD]
xch A, B ; @0C10 [C5F0]
addc A, #0h ; @0C12 [3400]
mov R6, A ; @0C14 [FE]
mov A, R7 ; @0C15 [EF]
mul AB ; @0C16 [A4]
add A, R5 ; @0C17 [2D]
mov R5, A ; @0C18 [FD]
mov A, R6 ; @0C19 [EE]
addc A, B ; @0C1A [35F0]
mov R6, A ; @0C1C [FE]
clr A ; @0C1D [E4]
rlc A ; @0C1E [33]
xch A, R7 ; @0C1F [CF]
mov B, A ; @0C20 [F5F0]
mov A, R1 ; @0C22 [E9]
mul AB ; @0C23 [A4]
add A, R6 ; @0C24 [2E]
mov R6, A ; @0C25 [FE]
mov A, R7 ; @0C26 [EF]
addc A, B ; @0C27 [35F0]
mov R7, A ; @0C29 [FF]
ret ; @0C2A [22]
;----------------------------------------------------------------
; Division step 8/8 -> 8:8
; A,R7/B -> A,R7
; where R7 is remainder, not the fractional part
; B is not changed
; input
; A : divident
; R7 : remainder of the previous byte division, must be
; set 0 for the first (MSB) byte division
; uses
; R4
Div8_step:
mov R4, #8
Div8_step_2:
rlc A
xch A, R7
rlc A
jbc CY, Div8_step_4
; C == 0
subb A, B
jnc Div8_step_3
add A, B
; C == 1
Div8_step_3:
xch A, R7 ; 1c
djnz R4, Div8_step_2
rlc A
; invert and store result
cpl A
ret
Div8_step_4:
; the remainder is > 0xFF (9 bits)
subb A, B
; C may be == 1
clr C
xch A, R7
djnz R4, Div8_step_2
rlc A
; invert and store result
cpl A
ret
;----------------------------------------------------------------
; Division R7:R6:R5 / B -> R7:R6:R5 , A - remainder
; uses A, R4
Div_R7R6R5:
mov A, B
jnz Div_R7R6R5_1
; B == 0
clr A
mov R7, A
mov R6, A
mov R5, A
ret
Div_R7R6R5_1:
; do the first step R7/B using DIV
; save divisor
mov R4, B
; divide
mov A, R7
div AB ; 4c
; save R7 result in R6
; get new divident
xch A, R6
; set remainder
mov R7, B
; restore divisor
mov B, R4
; remainder R7 is already set by the previous division step
; A/B -> A:R7, uses R4
lcall Div8_step
; store R6 result, get back R7 value
xch A, R6
; save R7 value and get R5
xch A, R5
; remainder R7 is already set by the previous division step
; A/B -> A:R7, uses R4
lcall Div8_step
; store R5 result, get back R7 value
xch A, R5
; store R7 value and get remainder
xch A, R7
ret
;----------------------------------------------------------------
; Division step 8/8 -> 8:8
; A,B/R3 -> A,B
; where B is remainder, not the fractional part
; R3 is unchanged
; input
; A : divident
; B : remainder of the previous byte division, must be
; set 0 for the first (MSB) byte division
; uses
; R4
Div8_R3_step:
mov R4, #8
Div8_R3_step_2:
rlc A
xch A, B
rlc A
jbc CY, Div8_R3_step_4
; C == 0
subb A, R3
jnc Div8_R3_step_3
add A, R3
; C == 1
Div8_R3_step_3:
xch A, B ; 1c
djnz R4, Div8_R3_step_2
rlc A
; invert and store result
cpl A
ret
Div8_R3_step_4:
; the remainder is > 0xFF (9 bits)
subb A, R3
; C may be == 1
clr C
xch A, B
djnz R4, Div8_R3_step_2
rlc A
; invert and store result
cpl A
ret
;----------------------------------------------------------------
; Division B:A / R3 -> R4:A , B - remainder
Div_BA_R3:
mov R4, A
xch A, R3
jnz Div_BA_R3_1
; B == 0
clr A
mov B, A
mov R4, A
ret
Div_BA_R3_1:
; B:R4 / A
; R3 == R4
; save divisor
mov R3, A
xch A, B
div AB ; A/B -> A,B
; save B/R3 result
push ACC
; get new divident
mov A, R4
; remainder B is already set by the previous division step
; A,B/R3 -> A,B uses R4
lcall Div8_R3_step
mov R4, A
pop ACC
xch A, R4
ret
;----------------------------------------------------------------
; Convert a hex A value into a BCD dec value
; input
; A - input hex value
; output
; R0:R1 - BCD packed decimal value [0:0 - 02:55h]
; uses
; DPTR
ConvByteToBCD:
mov R1, A
anl A, #0Fh
; reset AC and C
add A, #0
da A
; [7:4] - overflow, [3:0] - digit
xch A, R1
swap A
anl A, #0Fh
mov R0, A
mov DPTR, #conv74bitBCDValueL
movc A, @A+DPTR
add A, R1
da A
; A - BCD image of digits 0 and 1
; C - a possible carry
mov R1, A
mov A, R0
mov DPTR, #conv74bitBCDValueH
movc A, @A+DPTR
addc A, #0
mov R0, A
ret
; 0, 10, 20, 30, 40, ... F0
conv74bitBCDValueH: db 0,0,0,0,0,0,0,1,1,1,1,1,1,2,2,2
conv74bitBCDValueL: db 0,16h,32h,48h,64h,80h,96h,12h,28h,44h,60h,76h,92h,08h,24h,40h
;----------------------------------------------------------------
; Convert a hex B:A 16bit value into a BCD dec value
; input
; B:A - input hex value
; output
; R0:R1:R2 - BCD packed decimal value [0:0:0 - 06:55h:35h]
; uses
; DPTR
Conv16bitToBCD:
lcall ConvByteToBCD
; R0:R1 - A conversion
; convert B[3:0] and shift R0:R1 to R1:R2
mov A, B
anl A, #0Fh
mov DPTR, #conv11_8bitBCDValueL
movc A, @A+DPTR
add A, R1
da A
mov R2, A
mov A, R0
addc A, #0
da A
mov R1, A
; here R0 is still not initialized
mov A, B
anl A, #0Fh
mov DPTR, #conv11_8bitBCDValueH
movc A, @A+DPTR
add A, R1
da A
mov R1, A
; convert B[7:4]
mov A, B
swap A
anl A, #0Fh
mov B, A
mov DPTR, #conv15_12bitBCDValue2
movc A, @A+DPTR
mov R0, A
mov A, B
mov DPTR, #conv15_12bitBCDValue1
movc A, @A+DPTR
add A, R1
da A
mov R1, A
; here R0 is < #7
jnc Conv16bitToBCD_2
inc R0
Conv16bitToBCD_2:
mov A, B
mov DPTR, #conv15_12bitBCDValue0
movc A, @A+DPTR
add A, R2
da A
mov R2, A
mov A, R1
addc A, #0
da A
mov R1, A
mov A, R0
addc A, #0
da A
mov R0, A
ret
conv11_8bitBCDValueH: db 0,2,5,7,10h,12h,15h,17h,20h,23h,25h,28h,30h,33h,35h,38h
conv11_8bitBCDValueL: db 0,56h,12h,68h,24h,80h,36h,92h,48h,04h,60h,16h,72h,28h,84h,40h
conv15_12bitBCDValue2: db 0,0,0,1,1,2,2,2,3,3,4,4,4,5,5,6
conv15_12bitBCDValue1: db 0,40h,81h,22h,63h,04h,45h,86h,27h,68h,09h,50h,91h,32h,73h,14h
conv15_12bitBCDValue0: db 0,96h,92h,88h,84h,80h,76h,72h,68h,64h,60h,56h,52h,48h,44h,40h
;----------------------------------------------------------------
; Return the ASCII code of a digit which is the first after the floating point
; and which corresponds to the value of fractbits[7:3] of the value
; <intbyte>.<fractbits>
; input
; A - fractbits
; output
; A - the ASCII code of <fractbits>
; uses
; DPTR
GetFractDigitBit7_3:
rr A
rr A
rr A
anl A, #00011111b
mov DPTR, #GetFractDigitBit7_3_table
movc A, @A+DPTR
ret
; values of this table reflect the first fract digit of [7:3]/32
GetFractDigitBit7_3_table: db "00001112223334445555666777888999"
;----------------------------------------------------------------
; B:A = -(B:A)
NegateBA:
cpl A
add A, #1
xch A, B
cpl A
addc A, #0
xch A, B
ret
;----------------------------------------------------------------