Modern day potential of J3 devices beyond TwEECer and QH

This is where the BIN Hackers and definition junkies discuss the inner workings of the EEC code and hardware. General tuning questions do not go here. Only technical/hardware-specific/code questions and discussions belong here.

Moderators: cgrey8, EDS50, Jon 94GT, 2Shaker

jsa
Tuning Addict
Posts: 519
Joined: Sat Nov 23, 2013 7:28 pm
Location: 'straya

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by jsa » Tue Nov 06, 2018 6:47 pm

Ah yes, the upper 10 bits, now you have bumped my memory.
See page A5 of EEC Pocket Reference guide.
For R4 & R5
Bits 0 to 3 are the AD channels.
Bits 4 & 5 are read as zero's
Bits 6 to 15 are the AD result

So it is baked into the A/D register silicon.
Cheers

John

95 Escort RS Cosworth - GHAJ0 / ANTI on a COSY box code
Moates QH & BE
ForDiag

tvrfan
Tuning Addict
Posts: 368
Joined: Sat May 14, 2011 11:41 pm
Location: New Zealand

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by tvrfan » Tue Nov 06, 2018 7:33 pm

Probably redundant, but I've just realised I got the voltage wrong for that circuit
The maximum voltage grounded pin 48 is 2.56 as I said, but
not grounded would be 1/2.82 * 5 = 1.77+0.6 = 2.37, so it possibly would overlap....
but I think principle of the self/test shared HEGO may still work.

if it's any help -

The GUFB EGO (using A9L) are narrow band I believe, and the box keeps EGO_CROSSING flags for each bank. (got those in code listing)
As I understand, the box continuously varies AFR around the crossing point of each EGO, as it's the only way to tell at that time (before wide band)
that your AFR is right.
TVR, Triumph (cars), kit cars, classics. Ex IT geek, development and databases.

https://github.com/tvrfan/EEC-IV-disassembler

User avatar
cgrey8
Administrator
Posts: 10565
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by cgrey8 » Tue Nov 06, 2018 7:38 pm

jsa wrote:
Tue Nov 06, 2018 6:47 pm
Ah yes, the upper 10 bits, now you have bumped my memory.
See page A5 of EEC Pocket Reference guide.
For R4 & R5
Bits 0 to 3 are the AD channels.
Bits 4 & 5 are read as zero's
Bits 6 to 15 are the AD result...
Correct me if I'm wrong, but that is because you read all the analog inputs from the same memory-mapped register/address. So when you read a value, you need to know which input you are receiving A/D values for.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, 1.6RRs, FMS Explorer (GT40p) headers, Slot Style MAF, aftermarket T5 'Z-Spec', 8.8" rear w/3.27s, Powertrax Locker, Innovate LC-1, GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

jsa
Tuning Addict
Posts: 519
Joined: Sat Nov 23, 2013 7:28 pm
Location: 'straya

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by jsa » Wed Nov 07, 2018 12:12 am

Tvrfan, I think in practice the HEGO sensor can't output a high enough voltage to get anywhere near the 2.5ish level. In any case component tolerance and sensor voltage not being ratiometric to the EEC sensor +5V would further skew things.

I would need to retest what happens for a grounded STI, as at the time my interest was in spare 0-5V inputs.
Looking back at my notes applying 0-2.98V to pin 44 would see the stored value increase in 64bit steps. greater input values would see a freeze in stored value. Applying 0-5V on pin 48 behaved the same.

cgey8, upon reading, the lowest four bits are cleared by AND.

Code: Select all

b1,06,04            ldb   R4,6             AD_Cmd = 6;
33,0a,fd            jnb   B3,Ra,4370       if (AD_Rdy = 0) goto 4370 ;
51,f0,04,42         an3b  R42,R4,f0        R42 = AD_Low & f0;         0xF0 is bin 11110000
b0,05,43            ldb   R43,R5           R43 = AD_High;
Cheers

John

95 Escort RS Cosworth - GHAJ0 / ANTI on a COSY box code
Moates QH & BE
ForDiag

User avatar
cgrey8
Administrator
Posts: 10565
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by cgrey8 » Wed Nov 07, 2018 6:18 am

Hmm...so code doesn't care about the low-bits.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, 1.6RRs, FMS Explorer (GT40p) headers, Slot Style MAF, aftermarket T5 'Z-Spec', 8.8" rear w/3.27s, Powertrax Locker, Innovate LC-1, GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

tvrfan
Tuning Addict
Posts: 368
Joined: Sat May 14, 2011 11:41 pm
Location: New Zealand

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by tvrfan » Wed Nov 07, 2018 1:41 pm

cgrey8 wrote:
Wed Nov 07, 2018 6:18 am
Hmm...so code doesn't care about the low-bits.
Yes, I've noticed this in many bins, the code doesn't check where the AD answer comes from. The AD_complete flag stays low until the command is complete, and you can't queue therefore queue AD requests in the CPU.

What's actually worse is that the CPU simply loops until the request is complete, and this takes quite a while - that seems common too.

The Ford handbook says 8061 AD time is 174 states, most of the simple instructions are 4 state times, with only things like multiply and divide being over 20, so that means an AD request takes approx 40 equivalent instructions, that's quite a lot. It's even 7 divides ...(25 states each).

I can't help but see that as inefficient, especially when there's an interrupt available for it, but I guess it makes the code simpler.
An interrupt service is 21/23 states and a return is 12/16, which is still a lot less......
TVR, Triumph (cars), kit cars, classics. Ex IT geek, development and databases.

https://github.com/tvrfan/EEC-IV-disassembler

User avatar
cgrey8
Administrator
Posts: 10565
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by cgrey8 » Wed Nov 07, 2018 2:47 pm

tvrfan wrote:
Wed Nov 07, 2018 1:41 pm
...The AD_complete flag stays low until the command is complete, and you can't queue therefore queue AD requests in the CPU...
You can't queue as in the hardware forces the 174 states despite an interrupt being available?
Or is the code opting into being subject to this stall, but could've been written more efficiently using interrupts?
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, 1.6RRs, FMS Explorer (GT40p) headers, Slot Style MAF, aftermarket T5 'Z-Spec', 8.8" rear w/3.27s, Powertrax Locker, Innovate LC-1, GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

tvrfan
Tuning Addict
Posts: 368
Joined: Sat May 14, 2011 11:41 pm
Location: New Zealand

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by tvrfan » Wed Nov 07, 2018 3:32 pm

Yes, as I see it.

The code as seen (a LOT) simply loops around the AD_complete flag, whereas there is an interrupt available in the hardware.

Yes the 174 state times is indivisible for each command, so that AD_complete flag would take 174 state times to be set after the command is written to R4. (8061 time is 176, 8065 is 174) . So you can't get AD to work any faster in actual time, and it's single threaded, it's just that you could be doing something else in the meantime instead of looping.

As I understand the hardware for AD conversion, the 806x uses "successive approximation" which effectively evaluates the test voltage for fitting in a range for each bit of the answer, in a loop. This loop is very similar to the way a 'binary chop' search works, so the embedded algorithm has to loop at least 10 times for 10 bits of AtoD. 17 states per loop seems quite reasonable.

So an interrupt (IMHO) would leave more time for instructions to do something else.
=> You handle the interrupt, by writing the value to a 'raw' location (Register or RAM), and flag it as being ready.....
Still faster I reckon....
TVR, Triumph (cars), kit cars, classics. Ex IT geek, development and databases.

https://github.com/tvrfan/EEC-IV-disassembler

User avatar
cgrey8
Administrator
Posts: 10565
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by cgrey8 » Wed Nov 07, 2018 4:50 pm

tvrfan wrote:
Wed Nov 07, 2018 3:32 pm
...The code as seen (a LOT) simply loops around the AD_complete flag, whereas there is an interrupt available in the hardware...So you can't get AD to work any faster in actual time, and it's single threaded, it's just that you could be doing something else in the meantime instead of looping...
That's what I was trying to get at. I get that the A/D takes settling time before it's ready. Most of this era do that. Settling time in modern day A/Ds has gotten a lot better, but it's only been fairly recent that they've gotten better. But what I was after is you could have the processor doing something else while the A/D settles.

So in the capacity of a BBB commanding the EEC, the BBB could send the EEC processor commands to read an input. And while the A/D settles, the BBB could instruct the EEC to do other stuff, like read/write from the HSI or HSO co-processors. Then get back to the A/D and read the value after it's become ready. If you know the state times, the BBB could either just keep up with that and know to read the A/D after that amount of time has passed or check the flag to see that it's cleared prior to reading the value. I'm assuming it's not a requirement to read the flag before the register is filled with the A/D value.
tvrfan wrote:
Wed Nov 07, 2018 3:32 pm
...As I understand the hardware for AD conversion, the 806x uses "successive approximation" which effectively evaluates the test voltage for fitting in a range for each bit of the answer, in a loop. This loop is very similar to the way a 'binary chop' search works, so the embedded algorithm has to loop at least 10 times for 10 bits of AtoD. 17 states per loop seems quite reasonable...
I know an old product we used to have muxed all our Analog inputs on to the same A/D. And using shift registers, we landed each input onto the A/D, waited the settle time, got the value, then shifted the register. We repeated the sequence for each analog input. At the time, A/D chips were expensive so this was the most cost-effective option. And we didn't need blazingly fast update times for analog inputs. The speed we got from this approach was sufficient for our purposes. I wouldn't be surprised if, internally, they are doing something similar and muxing the various analog inputs onto the same A/D silicon.
tvrfan wrote:
Wed Nov 07, 2018 3:32 pm
...So an interrupt (IMHO) would leave more time for instructions to do something else.
=> You handle the interrupt, by writing the value to a 'raw' location (Register or RAM), and flag it as being ready.....
Still faster I reckon....
If the EEC processor is the only processor in the mix, I agree. However with the BBB hosting a Linux capable 1GHz ARM Cortex processor and two 200MHz Real Time Units (simple processors without interrupts), there are more options.

Thanks for all the followup from everybody responding. This is all great information...
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, 1.6RRs, FMS Explorer (GT40p) headers, Slot Style MAF, aftermarket T5 'Z-Spec', 8.8" rear w/3.27s, Powertrax Locker, Innovate LC-1, GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

jsa
Tuning Addict
Posts: 519
Joined: Sat Nov 23, 2013 7:28 pm
Location: 'straya

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by jsa » Wed Nov 07, 2018 4:53 pm

cgrey8 wrote:
Wed Nov 07, 2018 6:18 am
Hmm...so code doesn't care about the low-bits.
The previous example was for reading a single channel uninterrupted.

Elsewhere in the bin, the remaining channels are read in a loop which can be interrupted.

Code: Select all

#################################################################
# Save A to D values.
#################################################################
   Sub_AD_Read:
93af: a1,e0,93,30         ldw   R30,93e0         R30 = 93e0;                       # A/D Lookup Structure at 93E0
93b3: fb                  ei                     enable ints;
93b4: 56,30,00,04         ad3b  R4,R0,[R30]      AD_Cmd = [R30];                   # get, and set, AD channel reqd
93b8: de,22               jlt   93dc             if (AD_Cmd >= 0)  {               # exit if no more channels
93ba: 33,0a,fd            jnb   B3,Ra,93ba       if (AD_Rdy = 0) goto 93ba ;       # wait for AD ready
93bd: fa                  di                     disable ints;
93be: ff                  nop                    
93bf: 51,0f,04,34         an3b  R34,R4,f         R34 = AD_Low & f;                 # get channel returned
93c3: 9a,30,34            cmpb  R34,[R30]                                          # check correct channel
93c6: d7,eb               jne   93b3             if (R34 != [R30]) goto 93b3 ;     # No, try read again
93c8: 51,f0,04,34         an3b  R34,R4,f0        R34 = AD_Low & f0;                # AD Low value
93cc: b0,05,35            ldb   R35,R5           R35 = AD_High;                    # AD High value
93cf: 07,30               incw  R30              R30++;                            # incr ptr to save address
93d1: b2,31,32            ldb   R32,[R30++]      R32 = [R30++];
93d4: b2,31,33            ldb   R33,[R30++]      R33 = [R30++];                    # get destination address (hi+lo)
93d7: c2,32,34            stw   R34,[R32]        [R32] = R34;                      # save AD value to destination.
93da: 27,d7               sjmp  93b3             goto 93b3 ; }                     # next AD
tvrfan wrote:
Wed Nov 07, 2018 1:41 pm
What's actually worse is that the CPU simply loops until the request is complete, and this takes quite a while - that seems common too.

The Ford handbook says 8061 AD time is 174 states, most of the simple instructions are 4 state times, with only things like multiply and divide being over 20, so that means an AD request takes approx 40 equivalent instructions, that's quite a lot. It's even 7 divides ...(25 states each).

I can't help but see that as inefficient, especially when there's an interrupt available for it, but I guess it makes the code simpler.
An interrupt service is 21/23 states and a return is 12/16, which is still a lot less......
In the previous post, the code disables interrupts right before AD_Cmd and waits, but not so this code.

Is it better to have the AD loop interrupted, like this code, or have AD completion interrupt something else???
Thinking about coding for AD to interrupt other code and be interrupted by other code, how many interrupts deep can code go before it breaks?
Does having interrupt driven AD conversion readout cause issues for the foreground loop???
Cheers

John

95 Escort RS Cosworth - GHAJ0 / ANTI on a COSY box code
Moates QH & BE
ForDiag

tvrfan
Tuning Addict
Posts: 368
Joined: Sat May 14, 2011 11:41 pm
Location: New Zealand

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by tvrfan » Wed Nov 07, 2018 5:29 pm

A generalised answer to that I reckon....

really, you should only use intr inhibit when you truly have a sequence of code which cannot be interrupted by anything - either it's time critical, or the sequence of instructions, what you write (i.e. commands) have to occur in a defined sequence or time slot. Such code sequences should be as short as possible. Otherwise you may screw up event times, or miss them altogether. I think a few things on EEC fall into this category. Ignition spark is always a prime example for EEC boxes. Capture of PIP that is, relatively, you have quite a bit of time before generating the actual spark event.....

Always, you have to keep in the back of your mind that ANYWHERE in your code, an interrupt may occur. Therefore the interrupt handler code must make sure it restores the exact conditions of its call when it returns, hence the PUSHP / POP around intr handlers to restore the PSW, later boxes often save a bunch of registers, and some use an alternate stack pointer.

So typically this means hardware commands which write more than one register (HSO?) tend to be protected from being interrupted, and interrupt handlers themselves run with int inhibit set, so they themselves can't be interrupted. But if you code is clever enough, there's no reason why a higher priority interrupt can't interrupt a current int handler..... it just gets very messy if you're not very careful (been there in commercial stuff, not EEC) as you have to save and restore multiple statuses (stati?) for each interrupt handler. It's much simpler to do one int. at once and handle each one as fast as poss.

IMHO (adding this as others may disagree - which is fine...)
AD command is a single write, so that should be OK without inhibit, but the read involves two reads R4 and R5 so it's possible something could get in between these two and mess it up. So inhibit around these two is probably a good idea

Here's the A9L AD read, it does AD all at once, and it does call this in the main code loop, which is (again IMHO) a HORRIBLE WASTE of CPU bandwidth, as it reads ELEVEN A/D inputs from struct at 225f (each entry being AD command, raw location) each with a 146 state wait in one big loop PLUS code inhibits interrupts for more than it needs to. I think you could put the enable at 224e. But at least it doesn't inhibit for the AD wait loop.....

SURELY an int handler would be better than this ..... ?? But hey that's just my opinion, and it DOES WORK, which is always important
(Old time coders rule - "make it work first before you make it work fast")

But then, what's really important ? Sparks and knock sensors ? Int inhibit is set for 11 instructions at a time, so perhaps not all THAT bad....

Code: Select all


222e: a1,5f,22,30         ldw   R30,225f         R30 = 225f;                        # A/D Lookup Structure
2232: fb                  ei                     enable ints;
2233: 56,30,00,04         ad3b  R4,R0,[R30]      AD_Cmd = [R30];                    # get, and set, AD channel reqd
2237: de,22               jlt   225b             if (AD_Cmd >= 0)  {                # exit if no more channels
2239: 33,0a,fd            jnb   B3,Ra,2239       if (AD_Ready = 0) goto 2239;       # wait for AD ready
223c: fa                  di                     disable ints;
223d: ff                  nop                    
223e: 51,0f,04,34         an3b  R34,R4,f         R34 = AD_Low & f;                  # get channel returned - !! THIS ONE CHECKS !!
2242: 9a,30,34            cmpb  R34,[R30]                                           # check correct channel
2245: d7,eb               jne   2232             if (R34 != [R30]) goto 2232;      # No, try read again
2247: 51,f0,04,34         an3b  R34,R4,f0        R34 = AD_Low & f0;                 # AD Low value
224b: b0,05,35            ldb   R35,R5           R35 = AD_High;                     # AD High value
224e: 07,30               incw  R30              R30++;                             # increment ptr to save address
2250: b2,31,32            ldb   R32,[R30++]      R32 = [R30++]; 
2253: b2,31,33            ldb   R33,[R30++]      R33 = [R30++];                     # get destination address (hi+lo)
2256: c2,32,34            stw   R34,[R32]        [R32] = R34;                       # save AD value to destination.
2259: 27,d7               sjmp  2232             goto 2232; }                       # next AD

225b: 91,40,29            orb   R29,40           R29 |= 40; 
225e: f0                  ret                    return;
Last edited by tvrfan on Wed Nov 07, 2018 5:51 pm, edited 1 time in total.
TVR, Triumph (cars), kit cars, classics. Ex IT geek, development and databases.

https://github.com/tvrfan/EEC-IV-disassembler

jsa
Tuning Addict
Posts: 519
Joined: Sat Nov 23, 2013 7:28 pm
Location: 'straya

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by jsa » Wed Nov 07, 2018 5:50 pm

TVRfan, oh yeah, thanks for the A9L comments and directive files :lol:, evidence suggests I have put your good work to further use.
Cheers

John

95 Escort RS Cosworth - GHAJ0 / ANTI on a COSY box code
Moates QH & BE
ForDiag

tvrfan
Tuning Addict
Posts: 368
Joined: Sat May 14, 2011 11:41 pm
Location: New Zealand

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by tvrfan » Wed Nov 07, 2018 5:53 pm

Edited after your post , to fix up some wording - hope it explains...
TVR, Triumph (cars), kit cars, classics. Ex IT geek, development and databases.

https://github.com/tvrfan/EEC-IV-disassembler

jsa
Tuning Addict
Posts: 519
Joined: Sat Nov 23, 2013 7:28 pm
Location: 'straya

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by jsa » Wed Nov 07, 2018 6:17 pm

tvrfan, yes I'm thinking how to re-order that loop to do some of the loop stuff between AD write command and AD read.
It would not help state count for the first channel in the loop, but it could help subsequent channels.

I think line 223E is all about handling possible changes caused by an interrupt going to other code that does an AD write, otherwise why bother.
Indeed, R30 to R35 are temporary registers, so any interrupt code must not pollute those.
Cheers

John

95 Escort RS Cosworth - GHAJ0 / ANTI on a COSY box code
Moates QH & BE
ForDiag

User avatar
cgrey8
Administrator
Posts: 10565
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by cgrey8 » Wed Nov 07, 2018 7:01 pm

tvrfan wrote:
Wed Nov 07, 2018 5:29 pm
...if you code is clever enough, there's no reason why a higher priority interrupt can't interrupt a current int handler..... it just gets very messy if you're not very careful (been there in commercial stuff, not EEC) as you have to save and restore multiple statuses (stati?) for each interrupt handler. It's much simpler to do one int. at once and handle each one as fast as poss...
I wonder if Ford did this to simply side-step problems like priority inversions. Also I wonder if there were some kind of requirements at the time that engineers account for every clock cycle and writing code that guaranteed no deeper than 1 level of interrupts made doing that easier. I know some old government and life-safety kinds of things have criteria the code must follow to be considered reliable hard real time systems.
tvrfan wrote:
Wed Nov 07, 2018 5:29 pm
...IMHO (adding this as others may disagree - which is fine...)
AD command is a single write, so that should be OK without inhibit, but the read involves two reads R4 and R5 so it's possible something could get in between these two and mess it up. So inhibit around these two is probably a good idea...
In our code at work, we often have to disable interrupts when we are trying to do read-modify-write procedures that must be atomic in order to maintain data integrity. The only interrupt that doesn't get disabled in these cases is the non-maskable interrupt. But we are also diligent about making sure the deactivation and reactivation of interrupts is only a few C-lines away from each other.
tvrfan wrote:
Wed Nov 07, 2018 5:29 pm
...Here's the A9L AD read, it does AD all at once, and it does call this in the main code loop, which is (again IMHO) a HORRIBLE WASTE of CPU bandwidth, as it reads ELEVEN A/D inputs from struct at 225f (each entry being AD command, raw location) each with a 146 state wait in one big loop PLUS code inhibits interrupts for more than it needs to. I think you could put the enable at 224e. But at least it doesn't inhibit for the AD wait loop...
I guess this is a testament to just how fast the 15MHz processor is relative to the engine's real time needs.
tvrfan wrote:
Wed Nov 07, 2018 5:29 pm
...SURELY an int handler would be better than this ..... ?? But hey that's just my opinion, and it DOES WORK, which is always important
(Old time coders rule - "make it work first before you make it work fast")...
I agree. We have a similar saying that's saying basically the same thing, but from a different angle. "Don't prematurely optimize." Make it work first, then optimize it later if you determine optimizations are required. The belief here is that if you pretend to know what optimizations you'll need, you may spend a lot of time optimizing something that wasn't a problem to start with OR you structure the code in such a way that it's difficult to work with later.
tvrfan wrote:
Wed Nov 07, 2018 5:29 pm
...Int inhibit is set for 11 instructions at a time...
I wouldn't think 11 instructions is actually that bad. But I see what you mean. It doesn't look necessary for a good many of them. I suspect our disable/enable routines might exceed that on occasion...but our old hardware, despite being old, is over a decade newer than the 8061. Is there a chance this is because Ford doesn't push/pop the status registers on interrupts and some of these instructions rely on the registers to reflect things done by previous instructions? I'm just speculating here and probably showing more of my ignorance of Ford code.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, 1.6RRs, FMS Explorer (GT40p) headers, Slot Style MAF, aftermarket T5 'Z-Spec', 8.8" rear w/3.27s, Powertrax Locker, Innovate LC-1, GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

tvrfan
Tuning Addict
Posts: 368
Joined: Sat May 14, 2011 11:41 pm
Location: New Zealand

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by tvrfan » Wed Nov 07, 2018 7:52 pm

Yep, I think we're all in agreement here !

JSA, Yes, dead right. if you DID move the enable, then you would indeed have to make sure R34 and R35 in that example were not written to by anything else. I also wonder why Ford didn't simply do a LDW to get both registers in one hit, and after reading address from struct, couldn't do a direct STW [location],R4 (as an indirect) and then mask the bottom off later. (there might be a good reason to be honest - I haven't checked)

Cgrey - yes - mostly real time isn't actually all THAT critical when you are looking at CPU ticks... and there's 'plenty' of time, even at 15Mhz !!.
Even a V8 at 12,000 rpm (!!!) only sparks 800 times a second, or every 1.25 millisecs, which is pretty much forever on a modern CPU, and still 6000 states on a 15Mhz cpu, which is (er....) about 1500 instructions ?

At work a while ago, we mostly did interrupts one at a time just like the EEC does, it's far simpler and less error prone. But I did once work on a truly high speed process control system for a research project which really WAS sub millisecond, and it had nested interrupt handling for sensor events and special super high speed I/O hardware (~80's. I suspect now it would be super S-L-O-W compared to an ordinary modern day 3GHz PC bus !!). And it was a real pain to code ...

Then I ended up with Linux and Databases, a totally different kind of 'tuning' required there...
TVR, Triumph (cars), kit cars, classics. Ex IT geek, development and databases.

https://github.com/tvrfan/EEC-IV-disassembler

User avatar
cgrey8
Administrator
Posts: 10565
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by cgrey8 » Wed Nov 07, 2018 8:20 pm

tvrfan wrote:
Wed Nov 07, 2018 7:52 pm
...Cgrey - yes - mostly real time isn't actually all THAT critical when you are looking at CPU ticks... and there's 'plenty' of time, even at 15Mhz !!.
Even a V8 at 12,000 rpm (!!!) only sparks 800 times a second, or every 1.25 millisecs, which is pretty much forever on a modern CPU, and still 6000 states on a 15Mhz cpu, which is (er....) about 1500 instructions ?...
I looked into this and tried to calculate just how many instructions I could get into the EEC for every cylinder fire. And I was worried for a while thinking I only had time for about 125 PRU instructions per cylinder fire. But I realized I was off by an order of magnitude. Engine events are in milliseconds. The PRUs work in nanoseconds. And my math forgot there's microseconds in the middle. As it turns out, I have thousands of PRU instructions per cylinder fire which is more than plenty for what I intend with this project.
tvrfan wrote:
Wed Nov 07, 2018 7:52 pm
...At work a while ago, we mostly did interrupts one at a time just like the EEC does, it's far simpler and less error prone. But I did once work on a truly high speed process control system for a research project which really WAS sub millisecond, and it had nested interrupt handling for sensor events and special super high speed I/O hardware (~80's. I suspect now it would be super S-L-O-W compared to an ordinary modern day 3GHz PC bus !!). And it was a real pain to code ...
The code we have in our legacy products is all in an RTOS environment...no foreground/background stuff. So having priorities is just part of that world. But the RTOS makes managing things far easier. If we had to do it manually the way Ford is in the EECs, I expect things do get a lot more difficult.
tvrfan wrote:
Wed Nov 07, 2018 7:52 pm
...Then I ended up with Linux and Databases, a totally different kind of 'tuning' required there...
That's where I live today. Our current gen product is all in a custom-rolled YOCTO baked Linux distro. So I've had to become familiar with development for SystemV Linux. Now I'm onto Java development with the intention of running our next generation product in an ARM-compiled JRE running in Linux.

I've learned enough from this experience at work to give me the confidence to look more seriously at using a BBB as a J3 device. I've even got a breadboard laid out with level translator/bus isolator chips for handling the J3's bus lines. The BBB is not 5v tolerant, so I have to run all the EEC's J3's MBus lines through these devices to do the 5v-3.3v conversion. And because the PRUs on the BBB cannot command GPIOs as tri-states (technical limitation with the microcontroller), if you have pins that need to be both in and out, as the MBus's 8 data/address lines need to be, this burns 2 pins per line. That brings the BBB GPIO pin count to 16 GPIOs + the STB, DI, and IT command lines. Then you have to bus-isolate the output pins when the BBB isn't supposed to be driving the MBus, so there's a 20th pin to activate/deactivate the BBB output pins. Fortunately whoever designed the BBB took into account that people might want to use those PRUs so nearly all the GPIO pins that mux to the PRUs are available on the BBB's headers. I think there's 2 extra pins to do other J3 port stuff like control whether the processor or ROM is disabled. At present, I don't know that I'll actually need them. But it's nice to know I have the pins available if I need them for something, even if it's only development that they get used.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, 1.6RRs, FMS Explorer (GT40p) headers, Slot Style MAF, aftermarket T5 'Z-Spec', 8.8" rear w/3.27s, Powertrax Locker, Innovate LC-1, GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

sailorbob
BIN Hacker
Posts: 1650
Joined: Tue Jul 12, 2005 6:10 am

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by sailorbob » Thu Nov 08, 2018 3:19 am

tvrfan wrote:
Wed Nov 07, 2018 7:52 pm
I also wonder why Ford didn't simply do a LDW to get both registers in one hit
Bits 8-15 of some special function registers are only accessible using a word sized read or write of an even valued memory address. This feature of the MCU looks like it's only used on the 8065 (for example, see the HSO interrupt pending and mask registers) but maybe the concept was in place on the 8061.

tvrfan
Tuning Addict
Posts: 368
Joined: Sat May 14, 2011 11:41 pm
Location: New Zealand

Re: Modern day potential of J3 devices beyond TwEECer and QH

Post by tvrfan » Thu Nov 08, 2018 12:22 pm

Bob, Yes looks like that's true ...

I've found this snippet which is a little shorter, and DOES store a word via indirect STW, but R4 and R5 still read as separate bytes.
Interestingly, it doesn't seem to have any DI, EI protection around it that I can find. (AA)

Code: Select all

213b: b0,bb,04            ldb   R4,Rbb           AD_Cmd = Rbb;
213e: 33,0a,fd            jnb   B3,Ra,213e       if (AD_Ready = 0) goto 213e;
2141: c4,32,04            stb   R4,R32           R32 = AD_Low;
2144: c4,33,05            stb   R5,R33           R33 = AD_High;
2147: 61,c0,ff,32         an2w  R32,ffc0         R32 &= ffc0;
214b: c2,31,32            stw   R32,[R30++]      [R30++] = R32;
214e: 17,bb               incb  Rbb              Rbb++;
2150: 99,0d,bb            cmpb  Rbb,d            
2153: de,e6               jlt   213b             if (Rbb < d) goto 213b;
TVR, Triumph (cars), kit cars, classics. Ex IT geek, development and databases.

https://github.com/tvrfan/EEC-IV-disassembler

Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests