Tuners Rejoice! Free Tuning For M4.4!


Recommended Posts

I've finished my newest mod, and I've tested it as far as I could with my tiny 15g.

I need another tester though.
Tester should have:

-a large turbocharger
-a large maf sensor (both should be large enough to easily hit the load cap @ 12.24 ms)
-opportunity to do some highway pullage

Preferably the stock manner of boost control would still be in use as well.
Please send a PM with the bin, adx, and xdf you're using atm if you want to help.

​Hi Venderbroeck,

How's your testing coming along?  ;)

Edited by gdog
Link to post
Share on other sites
  • Replies 7.5k
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

Attention: The first 30 or so pages of this thread are outdated. Please refer to the M4.4 Wikia article where all the relevant information is currently being collated. Before asking any questions p

Crush it.

After alot of testing and rewriting code, we finally got a useful new mod working. As we all know, some time ago my dad Piet found out how to convert to bigger maf housings with the maf factor. Conver

Posted Images

​Hi Venderbroeck,

How's your testing coming along?  ;)

​I have yet to find someone who generates enough load.
Hussein will be testing my mod, so that should do the trick.
It's been a little frantic at uni as well the last couple of weeks, so didn't have much time.

It's still progressing though, no worries.

Link to post
Share on other sites

The T-5 have it because small bumps in the road could be interpreted as knocking, and therefore the accelerometer is put there to avoid misinterpretation of knocks.

​850T5 don't have an accelerometer, it  isn't even wired in in the ECU connector.

It doesn't give much problems, not having one.

Edited by Piet
Link to post
Share on other sites

​I have yet to find someone who generates enough load.Hussein will be testing my mod, so that should do the trick.
It's been a little frantic at uni as well the last couple of weeks, so didn't have much time.

It's still progressing though, no worries.

​Looking forward to it :D

  • Upvote 1
Link to post
Share on other sites

Im trying to reverse engineer the RPM calculation logic. I've made a decent amount of progress, but need some help from some fellow VS'ers. Im looking for a way to increase the max rpm limit from 7650.

If anyone has time, could they replace their MAF logging with 0x3D and 0x3E, and record a short 10 second log or so of their engine idling and then giving it a rev.

These bytes seem to correspond to some sort of 16bit floating point number, maybe the time between teeth or the time it takes for 120 degrees, i am not sure.

3D - /UMP,%UR_RAM1,TN_M,{tn-Mantisse: 6zyl: 120gradKW},$003D,1,9,DEZ,2,$00FF,K;
3E - /UMP,%UR_RAM1,TN_E,{tn-Exponent: 6zyl: 120gradKW},$003E,1,9,DEZ,2,$00FF,K;

If i had actual values it would really help with me running through the MULT/DIV unit logic.

EDIT: Found some more stuff in the damos:

/UMP,%UR_RAM1,TN6E,{corresponds to TN6_E aus Syncro},$009D,1,9,DEZ,2,$00FF,K;
/UMP,%UR_RAM1,TN6M,{corresponds to TN6_M aus Syncro      |=Zeit für 1.5°KW; timer2-},$009C,1,9,DEZ,2,$00FF,K;

This seems to be a 16 bit IEEE754 floating point number that corresponds to the time for 1.5 degrees of rotation. Im 99% sure that TN_M and TN_E is a IEEE754 half precision floating point number of the amount of time (in seconds i assume) that it takes for 120 degrees of rotation. This means that the RPM is only updated every 120 degrees, which make sense, because that will eliminate any flicker or extremely rapid changes in RPM.

Been doing more research, I think Bosch is using a modified version of IEEE754, or maybe just a form of floating point representation.

It looks like they're using 8 bits for the exponent and 8 bits for the mantissa with no bit for signed numbers (time can't be negative, so theres no need).

Here's what I'm thinking it looks like, Lets say the motor is running at 840 RPM, thats 14 RPS. So 1 rev would take 0.07 sec. Since it stores time for 120 degrees we can simply divide 0.07 by 3, to get 0.023 sec for 120 degrees.

In order to represent this in binary representation we have to multiply this by 2 until we reach one, then take decimal part and multiply by 2, continue.

Exponent     Mantissa

00000000   00000000

0.023 x 2 = 0.046 = 0     0.046 x 2 = 0.092 = 0     0.092 x 2 = 0.184 = 0     0.184 x 2 = 0.368  = 0     0.386 x 2 = 0.736 = 0     0.736 x 2 = 1.472 = 1     0.472 x 2 = 0.944 = 0     0.944 x 2 = 1.888 = 1     .888 x 2 = 1.776 = 1     .776 x 2 = 1.552 = 1

So since we have nothing before the decimal point we leave that as a 0, then put in all of the x2's in order.

0.0000010111, now lets move the decimal point and put it into binary scientific notation, 1.0111 x 2^-6

So the exponent will be -6 + 127, and the mantissa whatever is after the 1.

Exponent     Mantissa

121              0111

01111001 01110000, so hopefully this is what the bytes look like at idle (around 840 rpm).

We can check it by doing 2^-6 x 1.4375 aka ((1/2^2) + (1/2^3) + (1/2^4)) = 0.0224

Here is some more stuff I found:

Some sort of exponent, includes an exponent and Mantissa. Maybe some sort of floating point representation?
Looks like bosch never renamed this for the 5cyl or reused 6cyl code?
(360 * 2) / 6 = 120
(360 * 2) / 5 = 144

3D - /UMP,%UR_RAM1,TN_M,{tn-Mantisse: 6zyl: 120gradKW},$003D,1,9,DEZ,2,$00FF,K;
3E - /UMP,%UR_RAM1,TN_E,{tn-Exponent: 6zyl: 120gradKW},$003E,1,9,DEZ,2,$00FF,K;

From my findings, 3D and 3E are only populated in 0x3D72 0x1BF5A, once, using MOV iram addr,A.

I need to find more information on what tn-exponent and tn-mantisse are and what they do.

Here is some annotated code :

code:00003D41
code:00003D41 code_3D41:                              ; CODE XREF: RESET_0+E33j
code:00003D41                 clr     C
code:00003D42                 mov     A, R6
code:00003D43                 subb    A, R4
code:00003D44                 mov     A, R7
code:00003D45                 subb    A, R5
code:00003D46   
code:00003D48                 mov     A, R4
code:00003D49                 mov     R6, A
code:00003D4A                 mov     A, R5
code:00003D4B
code_3D4C:              ; Multiplication/Division Register 0
mov     MD0, R6
mov     MD4, #0         ; Multiplication/Division Register 4
mov     MD1, R7         ; Multiplication/Division Register 1
mov     MD5, #0x18      ; Multiplication/Division Register 5
nop
nop
nop
nop
mov     ARCON, #0       ; Arithmetic Control Register
clr     C
mov     R4, #0x10
mov     A, #0x1F
anl     A, ARCON        ; Arithmetic Control Register
xch     A, R4
subb    A, R4
mov     R4, A
mov     A, MD2          ; Multiplication/Division Register 2
rlc     A
clr     A
addc    A, MD3          ; Multiplication/Division Register 3
jnc     code_3D72
mov     A, #0x80 ; 'Ç'
inc     R4
code_3D72:
mov     RAM_3D, A
mov     RAM_3E, R4

Two main RPM variables are populated, 3B and 3C:

/UMP,%UR_RAM1,NMOT,{Drehzahl               |umr:nmot, 30 [1/min]|},$003B,1,120,N,2,$00FF,K;
/UMP,%UR_RAM1,N10,{Drehzahl               |umr:N10, 10 [1/min]|},$003C,1,121,N10,2,$00FF,K;

120,/REG,N,{Drehzahl},6,0,{1/min},4,6,  0., 7650.
/REP, 1.,  0.,  0., 30.,  0.,  0.;

121,/REG,N10,{Drehzahl in 10 Umdr. Quantisiert},6,0,{1/min},4,5,  0., 2550.
/REP, 1.,  0.,  0., 10.,  0.,  0.;

You can see the obvious difference, 3B's conversion factor is 30 (byte * 30) and 3C's conersion factor is 10 (byte * 10).

Also 121 seems to be a quantized meaning it must be reduced from a larger variable.

I found this... 

/UMP,%UR_RAM1,NFI,{antiruckel: Drehzahlfilter HOB    |umr:N|},$008A,1,120,N,2,$00FF,K;

Some sort of speed filter high order byte, its related to 120 (3B), so I wonder if the crank signal is filtered (quantized) 
aka reduced.

OK So now onto how 3B and 3C are populated.

3B and 3C are populated at 0x1434D and 0x1434A using MOV iram addr,A and MOV iram addr,B respectively.

Code runs from 0x14303 - 0x1434D

Here is some annotated code:

ROM:14303                 setb    RAM_29.3
ROM:14305                 clr     A
ROM:14306                 mov     MD0, #0         ; Multiplication/Division Register 0
ROM:14309                 mov     MD1, #0x6A ; 'j' ; Multiplication/Division Register 1
ROM:1430C                 mov     MD2, #0x18      ; Multiplication/Division Register 2
ROM:1430F                 mov     MD3, A          ; Multiplication/Division Register 3
ROM:14311                 mov     MD4, RAM_3D     ; Multiplication/Division Register 4
ROM:14314                 mov     MD5, A          ; Multiplication/Division Register 5
ROM:14316                 mov     A, RAM_3E
ROM:14318                 setb    ACC.5           ; Accumulator
ROM:1431A                 nop
ROM:1431B                 nop
ROM:1431C                 nop
ROM:1431D                 nop
ROM:1431E                 mov     ARCON, A        ; Arithmetic Control Register
ROM:14320                 nop
ROM:14321                 mov     A, MD1          ; Multiplication/Division Register 1
ROM:14323                 jz      code_4328+2
ROM:14325                 mov     B, #0xFF        ; B-Register
ROM:14328                 sjmp    code_432D
ROM:1432A ; ---------------------------------------------------------------------------
ROM:1432A                 mov     B, MD0          ; Multiplication/Division Register 0
ROM:1432D                 mov     MD0, MD0        ; Multiplication/Division Register 0
ROM:14330                 mov     MD1, MD1        ; Multiplication/Division Register 1
ROM:14333                 mov     MD4, #3         ; Multiplication/Division Register 4
ROM:14336                 mov     MD5, #0         ; Multiplication/Division Register 5
ROM:14339                 nop
ROM:1433A                 nop
ROM:1433B                 nop
ROM:1433C                 nop
ROM:1433D                 mov     A, MD1          ; Multiplication/Division Register 1
ROM:1433F                 jz      code_4343+2
ROM:14341                 mov     A, #0xFF
ROM:14343                 sjmp    code_4346+1
ROM:14345 ; ---------------------------------------------------------------------------
ROM:14345                 mov     A, MD0          ; Multiplication/Division Register 0
ROM:14347                 jnb     RAM_29.3, code_4301+2
ROM:1434A                 mov     RAM_3C, B       ; B-Register
ROM:1434D                 mov     RAM_3B, A


Steps:
1. 0x00186A00 / RAM_3D, result stored in MD0 MD1
2. Move RAM_3E to A
3. Set ACC.5 (shift direction right)
4. Move A to ARCON to start the shift
5. If acc is zero jump go to sjmp

Based on all of this if 3D and 3E do turn out to be time in seconds for 120 degree rotation it should be very simple to calculate a new variable with say 40 resolution instead of 30 in which the max rpm will now be 10200.

I tried running my made-up 3D 3E through the code, not much success i dont think.

E               M

01111001 01110000

0x14309 - 00000000000110000110101000000000 / 01110000 = 11011111001101

0x14318 - Shift answer to right 1001 (9) = 11011 = 27 * 10 = 270.

0x1432D - 11011  / 11 = 1001 = 9 * 30 = 270.

Maybe i made a mistake somewhere.

I may have figured it out...

Basically the ECU actually represents rpm in 16 bit (with 10 rpm increments) and divides by 3 to create a scaling factor of 30 so it can fit 7650 rpm in 1 byte.

Basically all you need to do is modify this piece of code

ROM:1432A                 mov     B, MD0          ; Multiplication/Division Register 0
ROM:1432D                 mov     MD0, MD0        ; Multiplication/Division Register 0
ROM:14330                 mov     MD1, MD1        ; Multiplication/Division Register 1
ROM:14333                 mov     MD4, #3         ; Multiplication/Division Register 4
ROM:14336                 mov     MD5, #0         ; Multiplication/Division Register 5

Change that move MD4, #3 to MD4, #4 for a scaling factor of 4.

Lets say the 16 bit number (which keep track in 10 rpm increments), is 800 dec, if you div by 4 you get 200 * 40 = 8000 rpm.

Edited by Simply Volvo
  • Upvote 1
Link to post
Share on other sites

Im trying to reverse engineer the RPM calculation logic. I've made a decent amount of progress, but need some help from some fellow VS'ers. Im looking for a way to increase the max rpm limit from 7650.

If anyone has time, could they replace their MAF logging with 0x3D and 0x3E, and record a short 10 second log or so of their engine idling and then giving it a rev.

These bytes seem to correspond to some sort of 16bit floating point number, maybe the time between teeth or the time it takes for 120 degrees, i am not sure.

3D - /UMP,%UR_RAM1,TN_M,{tn-Mantisse: 6zyl: 120gradKW},$003D,1,9,DEZ,2,$00FF,K;
3E - /UMP,%UR_RAM1,TN_E,{tn-Exponent: 6zyl: 120gradKW},$003E,1,9,DEZ,2,$00FF,K;

​This would be cool. I don't like NOT having a rev limit at all.

What EXACTLY do I enter for those areas? I could do this over the weekend & run it to 8K for a wider spread, if that helps

 

Link to post
Share on other sites

I may have figured it out...

Basically the ECU actually represents rpm in 16 bit (with 10 rpm increments) and divides by 3 to create a scaling factor of 30 so it can fit 7650 rpm in 1 byte.

Basically all you need to do is modify this piece of code

ROM:1432A                 mov     B, MD0          ; Multiplication/Division Register 0
ROM:1432D                 mov     MD0, MD0        ; Multiplication/Division Register 0
ROM:14330                 mov     MD1, MD1        ; Multiplication/Division Register 1
ROM:14333                 mov     MD4, #3         ; Multiplication/Division Register 4
ROM:14336                 mov     MD5, #0         ; Multiplication/Division Register 5

Change that move MD4, #3 to MD4, #4 for a scaling factor of 4.

Lets say the 16 bit number (which keep track in 10 rpm increments), is 800 dec, if you div by 4 you get 200 * 40 = 8000 rpm.

​This is correct!

Maarten already saw this when developing load 24.48.

I made a subroutine witch put the outcome of the new RPM calculation into $FABF wich can be added to the logging frame.

Maximum RPM that can be measured with it is 10200 RPM with a resolution of 40 RPM

nop
mov     B, MD0      
push    B             
mov     A, MD1        
push    ACC            
mov     MD0, B        
mov     MD1, A         
mov     MD4, #4      
mov     MD5, #0        
nop
nop
nop
nop
mov     A, MD1          
jz      code_X
-------------------
mov     A, #0xFF
sjmp    code_Y
-------------------
CODE-Y
mov     A, MD0  
CODE_X        
mov     DPTR, #0xFABF
movx    @DPTR, A
pop     ACC           
pop     B             
mov     MD0, B        
mov     MD1, A         
ret
 

The routine is LCALLed from $14320, where it replaces a nop and mov A,MD1

I tested it and it turns out to be ok. That is....It's values are the same as the original RPM. I have not tested it, nor do I intent to do that,  beyond 6500 RPM.

But there's no doubt it will go as far as 10200 RPM

 

Edited by Piet
  • Upvote 2
Link to post
Share on other sites

​This is correct!

Maarten already saw this when developing load 24.48.

I made a subroutine witch put the outcome of the new RPM calculation into $FABF wich can be added to the logging frame.

Maximum RPM that can be measured with it is 10200 RPM with a resolution of 40 RPM

As for having a higher rev limiter.
Converting the rev limiter code should be quite easy.
Converting some maps to make them use the new rpm variable is child's play.
I also did this for my load mod.

​Very cool. Looking forward to using these new methods when I get my car running.

And yes browsing through the rev limiter code, looks very simple, just a matter of swapping a few bytes. Same with the Major RPM axis.

M44 is starting to become quite the EMS.

Also, have either of you experimented with the idea of using this new scaled rpm variable in the load calculation? It could help with people revving above 7650 rpm. Ill have to browse around and see where load is calculated. It doesn't look like the 16bit rpm is stored anywhere long term, so i would assume the load calculation uses the 8 bit value.

Edited by Simply Volvo
Link to post
Share on other sites

Load is also stored in a 16-bit word.
I wouldn't be surprized if it doesn't use a direct rpm value at all, but maybe uses the timing values instead.

That said, I wouldn't alter the major rpm axis, but instead create a new major rpm axis.
Then you can just let the tables you want to convert make use of the new axis, and other (possibly unknown) tables would be unaffected.

  • Upvote 1
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.