Instructions to change fuel maps on 14CUX Griffith, Chimaera

Instructions to change fuel maps on 14CUX Griffith, Chimaera

Author
Discussion

terryg82

5 posts

109 months

Saturday 4th April 2015
quotequote all
More surprising than some things being awol on the 4 pot ecu to the 8 pot one is i can spot a couple in the reverse too.
It's almost worth buying one and taking a trip to RS to fill in the gaps to see if it can be done.

stevesprint

Original Poster:

1,114 posts

179 months

Monday 13th April 2015
quotequote all
Joolz
Please can you confirm the Emerald system when fitted to a V8 only uses a crankshaft sensor and therefore the ECU doesn't know if the cam is at 0 or 180 degrees. Does this mean the ECU wastes sparks and the injectors are fired in groups like the 14CUX and not just before the cylinder intake.
Cheers, Steve

spitfire4v8

3,992 posts

181 months

Tuesday 14th April 2015
quotequote all
You can have a cam sensor but you can't run full sequential on a 8 cylinder as there aren't enough outputs so no point really.
You could have it running batch fire injection (2 injector drivers used, each firing 4 injectors or 4 injector drivers used each firing 2 injectors to share the load) or semi-sequential (4 injector drivers used each firing 2 injectors following the firing order pattern )
In either case the ignition is 4 drivers firing 4 pairs of coils for wasted spark.

blitzracing

6,387 posts

220 months

Saturday 18th April 2015
quotequote all
Well Ive now put some of this theory into practice, and its much easier than ever expected, albeit on a non cat catalyst engine, so I dont need to worry about Lambda feedback getting in the way and changing the AFR ratio all the time.

Hardware was a spare ECU fitted with a Moats emulator, a laptop, with RoverGauge cable and dash mounted AFR gauge.
Software was Tunerpro, 14CUX tool kit, and EMutility (for the Moats).

The basic process was to use RoverGauge to show the load points, whilst monitoring the AF ratio with a gauge Ive fitted to the dash. This was done with a highly technical process of a clear plastic sheet over my laptop screen displaying RoverGauge, and my 10 year old daughter noting down the AFR ratio on top of the displayed load points with a spirit pen.

You can then simply cross reference the load points with the ones displayed in Tuner Pro for whatever map you are running. Now the really nice bit- I was concerned you would have to be working out appropriate Hex values to increase or decrease the fuel as required, but Tuner pro has a really nice graphics feature to show the 3D map, showing RPM, load from 0 to 100% (from the AFM) and fuel value where you simply drag a load point up or down to increase or decrease the amount of fuel Intersections or the load points are marked as blue dots. It also smooths out the surrounding load points so you dont get a ragged map. Here are the 2 maps- original and modified. The differenced are hardly noticeable unless you look closely but you can see it in the raw data.




[url]

|http://thumbsnap.com/OAOsyjvN[/url][url]

|http://thumbsnap.com/0NsWYWnc[/url]

Each time you make a change to the map, you simply save the file through tune pro, and then use the EMutility to squirt it into the ECU, then go for another road test until you are happy.

Edited by blitzracing on Saturday 18th April 20:11

spitfire4v8

3,992 posts

181 months

Monday 20th April 2015
quotequote all
You don't even need to keep sending the new map file to the emulator through emutility .. run the tunerpro in emulation mode and it sends the changes to the emulator in real time, then just save the map file when you're finished (I always save the map file by using the map read function in rovergauge just to make sure what I save is actually what the ecu is reading .. just to be safe )

keza87

6 posts

110 months

Tuesday 28th April 2015
quotequote all
Thought you guys might be interested in something a bit older to see the evolution of the tunes the 14CUX has.
Salvaged an ECU out of a 1990 model Range Rover classic that had been burnt out interior wise.
This was running a 3.9 multi-v motor with an auto running tune 1. Plugged it into my Discovery to see if it ran and got the tune out of it.
Link to my dropbox https://dl.dropboxusercontent.com/u/32915860/R2161...
Tune is R2161 with an ID of 1700 and checksum 2D.
Haven't had a look inside the file yet but will let you all decode it all.

I did run the 3.5 with this ecu but it did smell a tad rich but did idle differently to my ecu.
Regards,
Kieran.

keza87

6 posts

110 months

Tuesday 28th April 2015
quotequote all
Also interesting to note that RoverGauge couldn't read the idle and the MAF in tune R2161.
Did some logging with both ECU's to check some things but the data is not present in the log when running the ECU with tune R2161.
I would still assume the ECU was reading the MAF just maybe not at the location RoverGauge expected it? I don't expect this to be fixed as it's such an old tune now.

Can post up the logs if you are interested as well.
And yes I did close and re-open RoverGauge just in case.

For reference the part number of the ECU is PRC7081 with a date code of 2090
Regards,
Kieran.

danbourassa

246 posts

137 months

Tuesday 28th April 2015
quotequote all
Kieran, thanks for posting this binary. Land Rover documentation notes R2161 as "Desensitized OBD, IAC refinements". I'm aware of only two versions older than this one. The RoverGauge author (Colin) knows about the target idle problem with older versions. The target value was calculated on the fly and never stored in memory, so it's simply not available. I don't remember the MAF being a problem on old tune versions but I'm curious enough to look into it.

stevesprint

Original Poster:

1,114 posts

179 months

Tuesday 12th May 2015
quotequote all
Dan, Dave or Colin

I've been asked if a 512K EPROM with 4 prom images would work in the 14CUX or would it be safe to try?

Cheers
Steve


davep

1,143 posts

284 months

Wednesday 13th May 2015
quotequote all
stevesprint said:
Dan, Dave or Colin

I've been asked if a 512K EPROM with 4 prom images would work in the 14CUX or would it be safe to try?

Cheers
Steve
IMO no, the current memory map and operating mode that the 14CUX processor uses is way under 512K. And why?

stevesprint

Original Poster:

1,114 posts

179 months

Tuesday 26th May 2015
quotequote all
As several people have mentioned upgrading from R2967 to R3652 causes the initial 5 seconds cold start idle to raise I decided to use this as another excuse for some more experimenting. Fortunately I soon spotted the data difference between R2967 and R3652 at chip offset 15D that causes the increase in the initial cold start idle speed.

However, I now feel further improvements are possible mainly because TVR’s generally run with 200 to 300 rpm higher base idle than Land Rovers and could possibly be one of the causes of the unnecessary higher initial cold start idle speed. I soon managed to reduce the cold start target idle (idle after 5 seconds) down to a more civilised level by simply removing one line of code but sadly that’s not the main issue.

Dan, any chance you can include this target idle adjustment mod in your next release as a configurable option, I’m sure you realise I simply commented out the following line in idleControl.asm (line 51)
asld ; return (2 * (ECT - $27))

This now just leaves the initial 5 seconds idle speed immediately after cranking to be lowered and must be a good sign if that’s the main issue I’ve currently got to resolve.

Next, I proved the initial 5 seconds idle speed after cranking (before the idle settles down) is controlled by the coolant base idle control table at prom offset 17B. I did this by changing the code in idleControl.asm & stepperMtr2.asm to ignore the coolant table and always set iacvECTValue to a fixed value of $98 (a hot value). After cold cranking (16 deg C ish) the idle instantly jumped to 1,000 rpm (instead of the usual 1,600rpm) even before my lower target idle took over and combined my cold start idle finally stayed low like a modern car. However, I did notice that I still have to wait 5 seconds for the target idle to take over before moving off otherwise the idle kept creeping up while warming up on the move, as it does, that I also hope can be controlled with the same coolant table.

You can see from the coolant base idle control tables below that Land Rover updated the table for 4.2 but worryingly TVR didn’t update the table for its larger capacity engines. This table at chip offset 17B seems unnecessarily complicated and as a result I may need some help to understand the code below that reads the table. If I’m following the sub routine indexIntoTable correctly then column 7 (25 deg c) would come into play with a coolant temp of 35 deg C (coolant count $70). I also just about understand down to the double asld that seems a really neat way to multiply by 4. I now realise I need a lesson in assembler programming basics and more time to get my head around the code but at least I’m quietly making good progress.

Dave, I hope you don’t mind if I call you one evening for help.


Coolant base idle control tables at prom offset 17B

Deg C 130 114 94 87 55 50 25 -14 –21
Land Rover 3.9: R3652, R3383 & all TVR 2967 4L - 5L
DB $00,$0B,$1C,$23,$48,$51,$88,$E4,$F2 ; Coolant temp table -- 9 values
DB $78,$78,$A0,$A0,$88,$85,$72,$50,$1E ; Offset 9
DB $00,$97,$00,$2A,$15,$16,$18,$E5,$08 ; Offset 18

Land Rover 4.2: R3116, R3361, R3384
DB $00,$0B,$1C,$23,$48,$51,$88,$E4,$F2 ; Coolant temp table -- 9 values
DB $78,$78,$A0,$A0,$88,$85,$72,$48,$1E ; Offset 9
DB $00,$97,$00,$2A,$15,$16,$1E,$C0,$00 ; Offset 18

;------------------------------------------------------------------------------
; *** Calculate 'iacvEctValue' ***
;
; This code is the same as that embedded subroutine 'idleControl' which is
; called by the main loop both when ADC table ends and every 80th time through.
;
; It was made into a separate routine here, to be called from the ICI.
;
; As the coolant temp count goes down (as temperature rises), iacvEctValue goes
; up from about 100 to 160 dec.
;------------------------------------------------------------------------------
My comments Instructions Dan’s comments
LF9A1
LoadIndexReg ldx #$C17B ; coolant temperature table (9 values)
Load Accumulator A ldaa coolantTempCount ; load coolant sensor count
Load Accumulator B ldab #$09 ; data table length is 9
Jump to SubRoutine jsr indexIntoTable ; call the std temp based indexer
Subtract A suba $00,x ; subtract table value from coolant temp
Push Data B pshb ; push count value

Load Accumulator ldab $12,x ; load B from 3rd row of data table
Multiply mul ; mpy remainder by 3rd row table value
Arithmetic Shift.. asld
....Left Double asld ; mpy results by 4
PullB pulb ; pull B (count) preserving just upper byte of mpy
Compare B cmpb #$08 ; compare index counter with 8
Branch if Carry Set bcs .LF9BC ; branch ahead if B is < 8
Add A Accumulator adda $09,x ; add value from 2nd row of data table
Branch (always) bra .LF9BF ; and branch ahead to store and return
; B < 8

.LF9BC
Subtract A suba $09,x ; subtract value from 2nd row of data table
Negate A nega ; negate it

.LF9BF
Transfer Accumlr a to b tab ; xfr A to B
Store Accumulator stab iacvEctValue ; store calculated value
Return from Subroutine rts

;------------------------------------------------------------------------------
; Index Into Table
; This is used often to select a column of data from a table based on a
; comparison between a value (usually a temperature count) and the top row
; of the table. The values passed in are:
;
; X = Index to start of table
; B = Number of columns in table B= No of COLUMNS
; A = Value to compare (usually coolant temp count) A= ECT
;
; The routine increments the index in a loop and returns the updated index
; when the table value exceeds the value in A (or when B becomes zero).
;------------------------------------------------------------------------------
My comments Instructions Dan’s comments

indexIntoTable
Compare AccumlatorA cmpa $01,x ; subtract table value from coolant temp
Branch if carry set bcs .indexingRet ; return if result is LT zero
Decrement decb ; decrement counter
Branch if 0 beq .indexingRet ; return if counter is zero
inx ; increment index to next higher value in table
branch (always) bra indexIntoTable
.indexingRet
Return from Subroutine rts ; Return when exceeds

In addition to the above I’ve also been trying to determine why cranking the engine with a coolant temperature of 86 deg C the stepper motor is opened 100% and then suddenly only 35% open at 87 Deg C. As 1 deg C difference makes such a drastic difference and can make hot starting tricky I tried increasing the hot temperature thresholds at prom offset 246 & 247 but sadly made no difference. Whilst studying the code further I now realised offset 246 & 247 only effects map 4 & 5.

Although the main aim is to keep the idle speed below 1,500rpm I can’t help but thinking it might be worth investigating the following to try and understand why the idle takes longer to come down once above 1670rpm.

rpmIndicatorDelay at prom offset 240 is used above 1670rpm to delay idle control (maybe to enable stepper motor fault testing)

Ignition pulse period at prom offset 253 contains the 1670 RPM idle threshold used above.

Main loop uses prom offset 259 to determine how often to adjust the idle speed and test for stepper motor fault.

Wish me luck
Steve

Edited by stevesprint on Wednesday 27th May 19:55

davep

1,143 posts

284 months

Monday 1st June 2015
quotequote all
stevesprint said:
As several people have mentioned upgrading from R2967 to R3652 causes the initial 5 seconds cold start idle to raise I decided to use this as another excuse for some more experimenting. Fortunately I soon spotted the data difference between R2967 and R3652 at chip offset 15D that causes the increase in the initial cold start idle speed.

However, I now feel further improvements are possible mainly because TVR’s generally run with 200 to 300 rpm higher base idle than Land Rovers and could possibly be one of the causes of the unnecessary higher initial cold start idle speed. I soon managed to reduce the cold start target idle (idle after 5 seconds) down to a more civilised level by simply removing one line of code but sadly that’s not the main issue.

Dan, any chance you can include this target idle adjustment mod in your next release as a configurable option, I’m sure you realise I simply commented out the following line in idleControl.asm (line 51)
asld ; return (2 * (ECT - $27))

This now just leaves the initial 5 seconds idle speed immediately after cranking to be lowered and must be a good sign if that’s the main issue I’ve currently got to resolve.

Next, I proved the initial 5 seconds idle speed after cranking (before the idle settles down) is controlled by the coolant base idle control table at prom offset 17B. I did this by changing the code in idleControl.asm & stepperMtr2.asm to ignore the coolant table and always set iacvECTValue to a fixed value of $98 (a hot value). After cold cranking (16 deg C ish) the idle instantly jumped to 1,000 rpm (instead of the usual 1,600rpm) even before my lower target idle took over and combined my cold start idle finally stayed low like a modern car. However, I did notice that I still have to wait 5 seconds for the target idle to take over before moving off otherwise the idle kept creeping up while warming up on the move, as it does, that I also hope can be controlled with the same coolant table.

You can see from the coolant base idle control tables below that Land Rover updated the table for 4.2 but worryingly TVR didn’t update the table for its larger capacity engines. This table at chip offset 17B seems unnecessarily complicated and as a result I may need some help to understand the code below that reads the table. If I’m following the sub routine indexIntoTable correctly then column 7 (25 deg c) would come into play with a coolant temp of 35 deg C (coolant count $70). I also just about understand down to the double asld that seems a really neat way to multiply by 4. I now realise I need a lesson in assembler programming basics and more time to get my head around the code but at least I’m quietly making good progress.

Dave, I hope you don’t mind if I call you one evening for help.


Coolant base idle control tables at prom offset 17B

Deg C 130 114 94 87 55 50 25 -14 –21
Land Rover 3.9: R3652, R3383 & all TVR 2967 4L - 5L
DB $00,$0B,$1C,$23,$48,$51,$88,$E4,$F2 ; Coolant temp table -- 9 values
DB $78,$78,$A0,$A0,$88,$85,$72,$50,$1E ; Offset 9
DB $00,$97,$00,$2A,$15,$16,$18,$E5,$08 ; Offset 18

Land Rover 4.2: R3116, R3361, R3384
DB $00,$0B,$1C,$23,$48,$51,$88,$E4,$F2 ; Coolant temp table -- 9 values
DB $78,$78,$A0,$A0,$88,$85,$72,$48,$1E ; Offset 9
DB $00,$97,$00,$2A,$15,$16,$1E,$C0,$00 ; Offset 18

;------------------------------------------------------------------------------
; *** Calculate 'iacvEctValue' ***
;
; This code is the same as that embedded subroutine 'idleControl' which is
; called by the main loop both when ADC table ends and every 80th time through.
;
; It was made into a separate routine here, to be called from the ICI.
;
; As the coolant temp count goes down (as temperature rises), iacvEctValue goes
; up from about 100 to 160 dec.
;------------------------------------------------------------------------------
My comments Instructions Dan’s comments
LF9A1
LoadIndexReg ldx #$C17B ; coolant temperature table (9 values)
Load Accumulator A ldaa coolantTempCount ; load coolant sensor count
Load Accumulator B ldab #$09 ; data table length is 9
Jump to SubRoutine jsr indexIntoTable ; call the std temp based indexer
Subtract A suba $00,x ; subtract table value from coolant temp
Push Data B pshb ; push count value

Load Accumulator ldab $12,x ; load B from 3rd row of data table
Multiply mul ; mpy remainder by 3rd row table value
Arithmetic Shift.. asld
....Left Double asld ; mpy results by 4
PullB pulb ; pull B (count) preserving just upper byte of mpy
Compare B cmpb #$08 ; compare index counter with 8
Branch if Carry Set bcs .LF9BC ; branch ahead if B is < 8
Add A Accumulator adda $09,x ; add value from 2nd row of data table
Branch (always) bra .LF9BF ; and branch ahead to store and return
; B < 8

.LF9BC
Subtract A suba $09,x ; subtract value from 2nd row of data table
Negate A nega ; negate it

.LF9BF
Transfer Accumlr a to b tab ; xfr A to B
Store Accumulator stab iacvEctValue ; store calculated value
Return from Subroutine rts

;------------------------------------------------------------------------------
; Index Into Table
; This is used often to select a column of data from a table based on a
; comparison between a value (usually a temperature count) and the top row
; of the table. The values passed in are:
;
; X = Index to start of table
; B = Number of columns in table B= No of COLUMNS
; A = Value to compare (usually coolant temp count) A= ECT
;
; The routine increments the index in a loop and returns the updated index
; when the table value exceeds the value in A (or when B becomes zero).
;------------------------------------------------------------------------------
My comments Instructions Dan’s comments

indexIntoTable
Compare AccumlatorA cmpa $01,x ; subtract table value from coolant temp
Branch if carry set bcs .indexingRet ; return if result is LT zero
Decrement decb ; decrement counter
Branch if 0 beq .indexingRet ; return if counter is zero
inx ; increment index to next higher value in table
branch (always) bra indexIntoTable
.indexingRet
Return from Subroutine rts ; Return when exceeds
This thread deserves a bump up the line, so:

Indexed Addressing mode and 2s complement are where things can get a bit complicated. The maths used in the code obviously mirror some function or other that I cannot recognise at the moment as it is a bit convoluted, sometimes I think Assembler programmers would dream up little code sequences to exercise as many operations and instructions as possible.

First here’s my take on this area of code, which is according to how I have (mis)read the Assembler documentation so I hope it's of some help to you.

iacvEctValue
After initialising the Index Register with the first column address of the Coolant Temperature Table ($C17B), the coolantTempCount (#00 - #FF) into Accumulator A and the column count or table width (#09) into Accumulator B, the subroutine jumps to indexIntoTable at LF0F1.

indexIntoTable or Finding the Table Column
This subroutine selects the table column corresponding but not exceeding a count representing the current temperature. Key to understanding what’s going on in indexIntoTable is its BCS instruction. Simply put: the key words here are relative magnitude, where the CMPA data test compares the relative magnitude of the current coolantTempCount value (00 to FF) to each column/range index in the Coolant Temperature Table (start address $C17B).

If the result of the compare causes a borrow, then coolantTempCount value is lower than the indexed range entry in the table, which are, reading from left to right in decimal: 4 (4), 11 (7), 28 (17), 35 (7), 72 (37), 81 (9), 136 (55), 228 (92), 242 (14), and the C flag in CCR is set, then a BCS causes an immediate branch back to iacvEctValue, with the selected column details.

When the value is higher, the CTT column count is decremented by 1 and the compare repeated (INX and BEQ) until the coolantTempCount is lower or all columns of CTT have been checked.

For example: with a coolantTempCount of 33, the subroutine compares 33 against 4, not lower, so now compare with 11, not lower, lower than 28, no so now compare with 35, eureka! count is lower so this is the column iacvEctValue will now use.

Notes: Opcode for CMPA (A1 for INX/X) data test also adds an 8-bit forward offset of $01 to X (X + 1). The selection of the range span in the column selection process, shown in brackets, would only result from detailed analysis of the coolant temperature distribution function.

Return to iacvEctValue
Upon returning, the column index 35 dec or #23 is subtracted from the coolantTempCount in AccA (33-35 = -2), and the result is stored back in AccA. Having pushed the column offset count in AccB (now #06 in our example) onto the program stack, AccB is loaded with INX/12, which gives us 18 positions on from column index #23, and a value of #2A. Now the clever bit:

Multiply AccA (unsigned #02) by AccB (unsigned #2A) gives us #54 (84 dec) stored in AccD, like this (I must double check this for endian purposes but it makes most sense):

0000 0000 0101 0100

… now shift left (ASLD) twice to multiply by 4:

0000 0001 0101 0000

Result is #0150 or 336.

The column offset count is pulled back into AccB (#06 in our example). So now:

0000 0001 0000 0110

Compare AccB with #08, if lower, as in our example, subtract the value INX/09, which is the value 9 positions on from the column index #23, giving us #A0, from AccA. Subtracting AccB (#A0) from AccA (#01), results in -159 dec in AccA. Now negate AccA to 2s complement, giving #41 (65 dec).

If the column offset count is higher than 8, which occurs only for the first loop round (#09), then the value 9 positions on, #78 in our example, is added, giving #79 (121 dec).

Finally, move the contents of AccA to AccB, and store the resultant value as iacvEctValue.

Dan can you check the sums out and correct where wrong.


Edited by davep on Monday 1st June 16:59

stevesprint

Original Poster:

1,114 posts

179 months

Monday 1st June 2015
quotequote all
This is really important and much appreciated as I’ve written a c program to simulate the 14CUX code so I can safely amend this coolant idle table to lower the warming up idle speed that several people have commented on.

davep said:
Opcode for CMPA (A1 for INX/X) data test also adds an 8-bit forward offset of $01 to X (X + 1)
Thanks, this confirms the comparison is against one column ahead of X (X+1) and in your example column 35 (7) exceeds CoolantTempCount of 33 but X (column 28 (17)) is returned not X+1 column 35 (7) and therefore the column to the left (column 28 (17)) comes into play.

This is all for the good of the 14CUX.

stevesprint

Original Poster:

1,114 posts

179 months

Tuesday 2nd June 2015
quotequote all
Dave,
Thanks for your time and patience talking me through the assembler program instructions. It was a huge help and I finally have my coolant based stepper motor control simulation program working so I can now safely start trying to lower the initial cold starting idle.

Dan
Do you think this graph looks correct? in particular the stepper motor re-opening as the temperature rises above 94 degs C. I imagine the steeper decline past –14 degs C is to aid starting in severe cold weather.


Table for above (Prom offset 17B)
130 114 94 87 55 50 25 -14 -21 Degs C

00 0B 1C 23 48 51 88 E4 F2 ; Coolant temperature (Compared one ahead)
78 78 A0 A0 88 85 72 50 1E ; Column starting Y Axis
00 97 00 2A 15 16 18 E5 08 ; Rate of increase or decrease to the right (00 is flat)

Edited by stevesprint on Friday 5th June 19:24

danbourassa

246 posts

137 months

Wednesday 3rd June 2015
quotequote all
Steve, Dave,

You are making great progress and it seems that I have some catching up to do. You have fearlessly dived into one of the most complex parts of this code. Normally we're in the garage this time of year but I feel like I'm missing out on the fun. I will try to review what you've accomplished and hopefully even contribute something useful. Keep up the good work.

stevesprint

Original Poster:

1,114 posts

179 months

Wednesday 3rd June 2015
quotequote all
danbourassa said:
Steve, Dave,
You are making great progress and it seems that I have some catching up to do. You have fearlessly dived into one of the most complex parts of this code. Normally we're in the garage this time of year but I feel like I'm missing out on the fun. I will try to review what you've accomplished and hopefully even contribute something useful. Keep up the good work.
Dan
You certainly are missing out on all the fun. I hope this experimental & extreme temperature based idle control table proves the theory. I know you realise this isn't the warming up target idle speed, that was actually easy to reduce.

You'll be pleased to hear we don't need you anymore (only joking) as your rebuild program code is so well documented I'm starting to answer my own questions plus Dave helps when I'm stuck.
Good luck in the garage and in the mean time I'll document and summaries everything useful I learn on my 14CUX webpages.
Good to hear from you & Cheers
Steve

davep

1,143 posts

284 months

Thursday 4th June 2015
quotequote all
stevesprint said:
Dan
You certainly are missing out on all the fun. I hope this experimental & extreme temperature based idle control table proves the theory. I know you realise this isn't the warming up target idle speed, that was actually easy to reduce.

You'll be pleased to hear we don't need you anymore (only joking) as your rebuild program code is so well documented I'm starting to answer my own questions plus Dave helps when I'm stuck.
Good luck in the garage and in the mean time I'll document and summaries everything useful I learn on my 14CUX webpages.
Good to hear from you & Cheers
Steve
Steve don't jump the gun, we still need Dan I think.

I have a small problem with the way that the Coolant Temp Table row0 (offset $C17B) column selection is done. Looking at the machine code entry of the A1 01 CMPA $01/x in indexIntoTable, I read it as follows:

OP A1 Opcode address for A1 (subtract the value in the indexed memory location from AccA)
OP+1 ff Operand of 01
FFFF -
X +ff An 8-bit forward offset added to index (sic), in this case 01.

Assuming X +ff means set $C17C in the Index Register upon completion of CMPA, if the subroutine loops around again the value in the Index Register will now be $C17D by virtue of an INX add 1 to the Index Register, effectively stepping across two columns which doesn't make sense to me.


danbourassa

246 posts

137 months

Thursday 4th June 2015
quotequote all
Dave, the $01 operand does not post-increment the index. It's temporarily added to the index before the address is read. This means that the first value in the table is never used by the cmpa operation. In other words, the compare operation leads the index pointer by one column. Does that answer your question?


Edited by danbourassa on Thursday 4th June 01:40

davep

1,143 posts

284 months

Thursday 4th June 2015
quotequote all
danbourassa said:
Dave, the $01 operand does not post-increment the index. It's temporarily added to the index before the address is read. This means that the first value in the table is never used by the cmpa operation. In other words, the compare operation leads the index pointer by one column. Does that answer your question?


Edited by danbourassa on Thursday 4th June 01:40
Thanks Dan, I'm not sure where the machine code does the actual temporary write to index (wherever that is), it cannot be the Index Register because there's no reset. Given that indexIntoTable is used in at least seven instances with various data tables that's a lot of redundant first columns, and why populate them with values? Also why the offset operand in cmpa is not set with $00 is puzzling.

Anyhow the code seems to work and as a bonus Steve's simulation program can also be used with the other instances of indexIntoTable.

stevesprint

Original Poster:

1,114 posts

179 months

Thursday 4th June 2015
quotequote all
davep said:
Thanks Dan, I'm not sure where the machine code does the actual temporary write to index (wherever that is), it cannot be the Index Register because there's no reset. Given that indexIntoTable is used in at least seven instances with various data tables that's a lot of redundant first columns, and why populate them with values? Also why the offset operand in cmpa is not set with $00 is puzzling.

Anyhow the code seems to work and as a bonus Steve's simulation program can also be used with the other instances of indexIntoTable.
Dave
Although first compare is with the second column the first column’s row 2 and 3 come into play and are used to create the beginning of the graph. This means the compare is always one column ahead of the active column. The last column is used to create the last section of the graph.

 Row    Function
1 Coolant temperature (Compared one ahead)
2 Column starting Y Axis
3 Rate of increase or decrease to the right (00 is flat)

Its hard coded so the first 2 columns increase and the remaining 7 columns decrease, see the following compare and branch.

Compare B cmpb #$08 ; compare index counter with 8
Branch if Carry Set bcs .LF9BC ; branch ahead if B is < 8