Full Version : MegaSquirt V2.986 Engine Control (ASM)
avr >>AUTOMOTIVE >>MegaSquirt V2.986 Engine Control (ASM)


AVR_Admin- 04-18-2006
CODE
***************************************************************************
***************************************************************************
**   M E G A S Q U I R T - 2 0 0 1 - V2.986
**
**   (C) 2002 - B. A. Bowling And A. C. Grippo
**
**   This header must appear on all derivatives of this code.
**
***************************************************************************
***************************************************************************


;-----------------------
; Version 2.986
;-----------------------
; Modified boot_r12 file to raise the LVI trip point.
; Fill unused RAM locations with $32, an illegal opcode to force a reset. Done
;  to prevent flash erasure if code ever gets into a runaway state - for protection only.
; Put in interlocks to prevent VE/Constant section flash erasure unless specifically
;  invoked by a flash burn command.
; Put in Odd-fire RPM averaging (Willitte) for odd-fire engines.
; Added new calculation structure to code - same calculation as HI-RES code, but results
;  are in 0.1 millisecond units. Calculation overflow fixed.
; Flyback damping code installed - jumper port X0 for INJ1 and jumper port X1 for INJ2.
; Fixed display of WARMCOR variable (no flickering).
; Inhibit PWM mode while cranking.
; Made "ADC" into "ADD in ADC interrupt section (Tom D) to properly perform the sum
;  without a carry.
; Perform 12 ms time compare for re-enabling of tach IRQ interrupt (fix for random tach problem) -
;  original trial time of 20 ms too long (Magnus Bjelk fix - also for high/low byte check).
; Moved after-start enrichment to increment after "N" tach pulses have occurred,
;  with N being the number of cylinders. This will lengthen the afterstart enrichment
;  time by an amount scaled by the number of cylinders (Tom).
; Fix display of barometer correction (no screen flicker if 100% barometer is selected).
; Fixed IRQ counter to work properly for NCYL above 8 cylinders.
;
;-----------------------
; Version 2.0
;-----------------------
; Acceleration Enrichment Cold Multiplier added - now cold accel enrichment in form of a + b * x
; Barometer Correction Selection Mode put in Config13
; Bootloader Bug (lda vs ldx) fixed for this version
; RPM Calc made more efficient and bug fix for RPM exclusion values (Konstantin)
; Changed Flood clear value to 0.3 ms
; Added the "Guy ROM Offset" to fix the bootloader erase problem
; Added Embedded Code revision number SCI query command ("Q")
; Fixed SCI "C" transfer mode
; Added Alpha-N mode
; Added O2 target voltage constant and DIY-WB O2 sensor support, and bit for Odd-Fire Mode
;  (no odd-code mode in embedded code yet).
; Fixed Battery voltage correction roll-over problem.
; Fixed Lininterp problem with large negative numerator spans
; Fixed "sticky" decel bit
; Added both MPX4115 and MPX4250 KPA and Barofac tables in flash - selected by config register
; Prime Pulses and Adjustable RPM for entry into closed-loop added 4/2/02
;
;-----------------------
; Version 1.5
;-----------------------
; O2 closed-loop mode added 11/1/01
;
;-----------------------
; Version 1.01
;-----------------------
; Inverted Injector driver MC33151 implemented:
; To change output from inverted to non-inverted, change
;  all of the bset and bclr calls for inject1 and inject2 to their inverse.

.header 'MegaSquirt'
;.base 10t
.pagewidth 130
.pagelength 90
;.set simulate

.nolist
include "gp32.equ"
.list
org ram_start
include "megasquirt.h"


***************************************************************************
**
** Main Routine Here - Initialization and main loop
**
** Note: Org down 128 bytes below the "rom_start" point
**       because of erase bug in bootloader routine
**
** Note: Items commented out after the Start entry point are
**       taken care of in the Boot_R12.asm code
**
***************************************************************************
org {rom_start + 128}
Start:
;       *** Note - uncomment this code if you do not use the Bootloader to initilize ***
;        clra
; sta copctl
; mov #%00000001,config2
; mov #%00001001,config1
; mov #%00000001,config1
; ldhx #ram_last+1 ; Set the stack Pointer
; txs   ;  to the bottom of RAM

;PllSet:
; bclr BCS,pctl ; Select external Clock Reference
; bclr PLLON,pctl ; Turn Of PLL
; mov #$02,pctl ; Set P and E Bits
; mov #$C0,pmrs ; Set L
; mov #$03,pmsh ; Set N (MSB)
; mov #$84,pmsl ; Set N (LSB)
; bset AUTO,pbwc
; bset PLLON,pctl ; Turn back on PLL
;PLLwait:
;        brclr   LOCK,pbwc,PLLwait
;        bset    BCS,pctl



;
;   Set all RAM to known value - for code runaway protection.
;   If there is ever a code runaway, and processor tries
;    executing this as an opcode ($32) then a reset will occur.
;
ldhx   #ram_start;Point to start of RAM
ClearRAM:
lda #$32 ; This is an illegal op-code - cause reset if executed
sta    ,x ;Set RAM location
aix    #1 ;advance pointer
cphx   #ram_last+1;done ?
bne    ClearRAM ;loop back if not





; Set up the port data-direction registers
       lda     #%00000000
       sta     ddrb                  ; Set as inputs (ADC will select which channel later)
       lda     #%00110000            ; Turn off injectors (inverted output)
       sta     portd
       lda     #%11110000
       sta     ddrd                ; Outputs for injector
       clr     porta
       lda     #%11111111
       sta     ddra                  ; Outputs for Fp and Idle
       lda     #$00
       sta     portc
       lda     #%00011111            ; ** Was 11111111
       sta     ddrc                  ; Outputs for LED
       lda     #%00000001            ; Serial Comm Port
       sta     ddre

; Set up the Real-time clock Timer (TIM2)
       MOV     #Timerstop,t2sc       ; Stop Timer so it can be set up
       mov     #$00,T2MODH
       mov     #$B8,T2MODL           ; set timer modulus register to 184 decimal
       mov     #T2SC0_No_PWM,T2SC0   ; make this normal port output (PWM MODE is #$5E)
       mov     #$00,T2CH0H
       mov     #$00,T2CH0L
       MOV     #Timergo,T2SC         ;  set timer prescaler to divide by 4

; Set up the PWM for the Injector (for current limit mode)
       MOV     #Timerstop,t1sc       ; Stop Timer so it can be set up
       mov     #$00,T1MODH
       mov     #$64,T1MODL           ; set timer modulus register to 100 decimal
       mov     #T1SCX_NO_PWM,T1SC0   ; make this normal port output (PWM MODE is #$5E)
       mov     #T1SCX_NO_PWM,T1SC1   ; make this normal port output (PWM MODE is #$5E)
       mov     #$00,T1CH0H
       mov     INJPWM,T1CH0L
       mov     #$00,T1CH1H
       mov     INJPWM,T1CH1L


; Set up SCI port
lda #$12  ; This is 9600 baud w/ the osc frequency selected
sta scbr
bset ensci,scc1 ; Enable SCI
bset RE,SCC2  ; Enable receiver
       bset    SCRIE,SCC2             ; Enable Receive interrupt
lda SCS1  ; Clear SCI transmitter Empty Bit
       clr     txcnt
       clr     txgoal

; Set up Interrupts
       mov     #%00000100,INTSCR;Enable IRQ



; Set up RAM Variable
       clr     mms
       clr     ms
       clr     tenth
       clr     secl
       clr     sech
       lda     #$FF
       clr     squirt
       lda     #$32
       sta     pw
       clr     engine
       clr     rpmph
       clr     rpmch
       clr     rpm
clr old_rpm1
clr flocker
       lda     #$00
       sta     pwcalc
       sta     pw
       clr     pwrun1
       clr     pwrun2
       lda     #$FF
       sta     last_tps
       clr     egocount

       lda     #$BB
       sta     baro
       sta     map
       sta     mat
       sta     clt
       sta     tps
       sta     batt

       lda     #$64
       sta     aircor
       sta     vecurr
       sta     barocor
       sta     warmcor
       sta     egocorr
sta tpsfuelcut
       clr     gammae
       lda     #$46
       sta     map
       lda     #$65
       sta     baro
clr tpsaccel

       clr     igncount

; Fire up the ADC, and perform one conversion to get the baro value
lda #%01110000; Set up divide 8 and internal bus clock source
sta adclk
lda #%00000000; Select one conversion, no interrupt, AD0
sta adscr
brclr   coco,adscr,*; wait until conversion is finished

lda adr
sta baro ; Store value in Barometer


clr adsel ; Clear the channel selector

TURN_ON_INTS:
       cli ; Turn on all interrupts now

; Load the constants (VE Table, etc) from Flash to RAM - the program uses the RAM values

       clrh
       clrx
XXVV:
       lda     VETABLE,x      ; This is the FLASH table for all inputs
       sta     VE,x           ; This is the RAM-based table - this is what is used by pgm.
       incx
       cbeqx  #$80,XXXV
       bra    XXVV
XXXV:



; Load the Flash Programming Routine into RAM - it will sit there until invoked

       clrh
       clrx
NEXTRAM:
       lda    ERASE_N_BURN,x  ; Programmer routine to be copied
       sta    BURNER,x        ; RAM Location that keep the burner code
       incx
       cbeqx  #$FF,DONE_LOAD_BURN
       bra    NEXTRAM

DONE_LOAD_BURN:

***************************************************************************
**
** Prime Pulse - Shoot out one priming pulse of length PRIMEP
**
***************************************************************************
       lda    PRIMEP
       beq    LOOPER          ; Branch around priming pulse if zero

       sta    pw
       sta    pw2
       bset   fuelp,porta
       clr    pwrun1
       clr    pwrun2
       bset   sched1,squirt
       bset   inj1,squirt
       bset   sched2,squirt
       bset   inj2,squirt
       bset   running,engine

***************************************************************************
********************    M A I N  E V E N T  L O O P     *******************
***************************************************************************

LOOPER:

***************************************************************************
**
**  Correction Factor Lookup Table Access
**
**   Perform table lookup for barometer and air density correction factors,
**    and performs coolant temperature conversion from counts to degrees F
**
**   All tables are pre-computed for all 256 different values
**    and stored in FLASH
**
**   Note: Coolant temperature is in degrees F plus 40 - this allows
**    unsigned numbers for full temperature range
**
**
***************************************************************************

       clrh

lda config11
and #$01
bne TurboMap

NaMap:
       lda     baro
       tax
       lda     BAROFAC4115,x
       sta     tmp11        ; Barometer Correction Gamma

       lda     map
       tax
       lda     KPAFACTOR4115,x
       sta     kpa            ; Manifold Air Pressure in Kilopascals

       lda     config13               ; Check if we use baro correction mode (bit=1) or not (bit=0)
       bit     #$08                   ; Use BIT instead of brset because outside of zero-page
bne     NaBaroUse              ; Branch if the bit is set - we use the MAP-obtained barometer

       lda     #$64
       sta     barocor                ; Store 100% barometer correction (correction not used)
bra CltCalc

NaBaroUse:
lda tmp11  ; Use the saved MAP-derived barometer value
sta barocor
bra CltCalc

TurboMap:
       lda     baro
       tax
       lda     BAROFAC4250,x
       sta     tmp11          ; Barometer Correction Gamma

       lda     map
       tax
       lda     KPAFACTOR4250,x
       sta     kpa            ; Manifold Air Pressure in Kilopascals

       lda     config13               ; Check if we use baro correction mode (bit=1) or not (bit=0)
       bit     #$08                   ; Use BIT instead of brset because outside of zero-page
bne     TurboBaroUse           ; Branch if the bit is set - we use the MAP-obtained barometer

       lda     #$64
       sta     barocor                ; Store 100% barometer correction (correction not used)
bra CltCalc

TurboBaroUse:
lda tmp11  ; Use the saved MAP-derived barometer value
sta barocor


CltCalc:
       lda     clt
       tax
       lda     THERMFACTOR,x
       sta     coolant        ; Coolant temperature in degrees F + 40

       lda     mat
       tax
       lda     AIRDENFACTOR,x
       sta     aircor         ; Air Density Correction Factor

***************************************************************************
**
** Fast Idle Comparison - fast idle set is coolant below FAST IDLE value
**
***************************************************************************
       lda     fastidle
       cmp     coolant
       bhi     SLOW_IDLE_SET
FAST_IDLE_SET:
       bclr    iasc,porta
       bra     RPM_COMP
SLOW_IDLE_SET:
       bset    iasc,porta

***************************************************************************
**
** Computation of RPM
**
**   rpmk:rpmk+1
**   ----------- = rpm
**   rpmph:rpmpl
**
**  rpmk:rpmK+1 = RPM constant = (6,000 * (stroke/2))/ncyl
**  rpmph:rpmpl = period count between IRQ pulsed lines, in 0.1 millisecond resolution
**
****************************************************************************
RPM_COMP:

       brclr   running,engine,LOOPER
ldhx    rpmph
       beq     LOOPER

       pshh
       pula
       tsta
       beq        FAST_RPM_CALC

SLOW_RPM_CALC:
       clr       intacc1
       clr       intacc1+1

       sthx      intacc2

       ldhx      rpmk
       sthx      intacc1+2

       jsr       udvd32             ; 32 x 32 divide
       lda       intacc1+3          ; get 8-bit RPM result
       bra       RPM_CALC_DONE

FAST_RPM_CALC:
       lda       rpmk
       psha
       pulh
       lda       rpmk+1
       div                          ; A = (H:A) / X

RPM_CALC_DONE:
sta   tmp1      ; Will move this later on...

; If odd-fire is set (bit zero of Config13), then average RPM values
       lda       config13
       and       #$01
       beq       NO_ODD_FIRE

YES_ODD_FIRE:
lda   tmp1
add   old_rpm1   ; this variable is updated in the IRQ section to latch last RPM
rora
sta   rpm
bra   CHK_FOR_WENRCH

NO_ODD_FIRE:
lda   tmp1
       sta       rpm

CHK_FOR_WENRCH:
       cmp       #$03               ; Check if we are cranking
       bhi       WARM_UP_ENRICH


***************************************************************************
**
** Cranking Mode
**
** Pulsewidth is directly set by the coolant temperature value of
**  CWU (at -40 degrees) and CWH (at 165 degrees) - value is interpolated
**
***************************************************************************

CRANKING_SET:
       bset    crank,engine
       bclr    startw,engine
       bclr    warmup,engine

       lda     #155T  ; 3 Volts comparison value for TPS - flood clear trigger
       cmp     tps
       bhi     INTERP_CRANK_PW

FLOOD_CLEAR:
       lda     #$03   ; 0.3 ms pulsewidth - just opening...
       sta     pwcalc
       jmp     LOOPER

INTERP_CRANK_PW:
       lda     #$00
       sta     tmp1
       lda     #205T  ; 165 + 40 degrees (because of offset in lookup table)
       sta     tmp2
       mov     cwu,tmp3
       mov     cwh,tmp4
       mov     coolant,tmp5
       jsr     lininterp
       mov     tmp6,pwcalc
       jmp     LOOPER

***************************************************************************
**
** Warm-up and After-start Enrichment Section
**
** The Warm-up enrichment is a linear interpolated value from WWU (10 points)
**  which are placed at different temperatures
**
** Method:
**
** 1) Perform ordered table search of WWU (using coolant variable) to determine
**  which bin.
** 2) Perform linear interpolation to get interpolated warmup enrichment
**
** Also, the after-start enrichment value is calculated and applied here - it
**  is an added percent value on top of the warmup enrichment, and it is applied
**  for the number of ignition cycles specified in AWC. This enrichment starts
**  at a value of AWEV at first, then it linearly interpolates down to zero
**  after AWC cycles.
**
** 3) If (startw, engine is set) then:
** 4)  compare if (awc < asecount) then:
** 5)   x1=0, x2=AWC, y1=AWEV, y2=0, x=asecount, y=ASEenrichment
** 6)  else clear startw bit in engine
**
***************************************************************************
WARM_UP_ENRICH:
       brclr   crank,engine,WUE1
       bclr    crank,engine
       bset    startw,engine
       bset    warmup,engine
       clr     asecount
WUE1:
       ldhx    #WWURANGE
       sthx    tmp1
       lda     #$09
       sta     tmp3
       lda     coolant
       sta     tmp4
       jsr     ORD_TABLE_FIND

WUE4:
       clrh
       lda     tmp5
       tax
       lda     WWU,x
       sta     tmp4
       decx
       lda     WWU,x
       sta     tmp3
       mov     coolant,tmp5
       jsr     lininterp

       mov     tmp6,tmp12
;        mov     tmp6,warmcor
;        lda     warmcor
       lda     tmp12
       cmp     #$64
       bne     ASE1

; Outside of warmup range - clear warmup enrichment mode
       lda     #$64
       sta     warmcor
       bclr    startw,engine
       bclr    warmup,engine
       bclr    wled,portc
       bra     ASE_FINAL

ASE1:
       bset    wled,portc
       bset    warmup,engine
       brclr   startw,engine,ASE_FINAL
       lda     asecount
       cmp     awc
       bhi     ASE_END
ASE2:
       clr     tmp1
       mov     AWC,tmp2
       mov     AWEV,tmp3
       clr     tmp4
       mov     asecount,tmp5
       jsr     lininterp
       lda     tmp6
       bcs     ASE_RAIL
       add     tmp12
       sta     warmcor
       bra     TAE

ASE_RAIL:
       lda     #$FE
       sta     warmcor        ; Rail warmcor value
       bra     TAE

ASE_END:
       bclr    startw,engine

ASE_FINAL:
       mov     tmp12,warmcor

***************************************************************************
**
**  Throttle Position Acceleration Enrichment
**
**   Method is the following:
**
**
**   ACCELERATION ENRICHMENT:
**   If (tps < last_tps) goto DEACCELERATION_ENRICHMENT
**   If (tps - last_tps) > tpsthresh and TPSAEN = 0 then (acceleration enrichemnt):
**   {
**    1) Set accelration mode
**    2) Continuously determine rate-of-change of throttle, and perform
**        interpolation of TPSAQ values to determine acceleration
**        enrichment amount to apply.
**   }
**   If (TPSACLK > TPSACLKCMP) and TPSAEN is set then:
**   {
**    1) Clear TPSAEN bit in engine
**    2) Set TPSACCEL to 100%
**    3) Go to EGO Delta Step Check Section
**   }
**
**
**   DEACCELERATION ENRICHMENT:
**   If (last_tps - tps) > tpsthresh then (deacceleration fuel cut)
**   {
**    If (TPSAEN = 1) then:
**    {
**      1) TPSACCEL = 100 percent (no acceleration)
**      2) Clear TPSAEN bit in ENGINE
**      3) Go to EGO Delta Step
**    }
**    If (RPM > 15 (corresponding to 1500 RPM)) then (fuel cut mode):
**    {
**      1) Set TPSACCEL value to TPSDQ
**      2) Set TPSDEN bit in ENGINE
**      3) Go to EGO Delta Step Check Section
**    }
**   }
**   else
**   {
**    If (TPSDEN = 1) then
**    {
**     1) Clear TPSDEN bit in ENGINE
**     2) TPSACCEL = 100%
**     3) Go to EGO Delta Step Check Section
**    }
**   }
**
***************************************************************************
TAE:
       sei
       mov     tps,tmp1
       mov     last_tps,tmp2
       cli
       lda     tmp1
       cmp     tmp2
       blo     TDE2
AE_CHK:
       lda     tmp1
       sub     tmp2
       cmp     tpsthresh
       blo     B_LO_CONT
       brset   TPSAEN,ENGINE,AE_COMP_SHOOT_AMT

; Add in accel enrichement
       lda     TPSAQ          ; start out using first element - will determine actual next time around
       sta     TPSACCEL       ; Acceleration percent amount - used in later calculations
       clr     TPSACLK
       lda     TPSASYNC
       sta     tpsaclkcmp     ; Shoot time comparison value
       bset    TPSAEN,ENGINE
       bclr    TPSDEN,ENGINE
       bset    aled,portc
       bclr    wled,portc
       jmp     MAE

;TDE2:   bra     TDE            ; Only to extend branch for assembler


; First, calculate Cold temperature add-on enrichment value from coolant value TPSACOLD,
; from -40 degrees to 165 degrees.
;
; Then determine cold temperature multiplier value ACCELMULT (in percent), from -40 degrees to 165 degrees.
;
; Next, Calculate Shoot amount (quantity) for acceleration enrichment from table.
;  Find bins (between) for corresponding TPSDOT, and linear interpolate
;  to find enrichment amount (from TPSAQ). This is continuously
;  checked every time thru main loop while in acceleration mode,
;  and the highest value is latched and used.
;
; The final acceleration applied is AE = Alookup(TPSDOT) * (ACCELMULT/100) + TPSACOLD


AE_COMP_SHOOT_AMT:
; First, the "added" amount based on cold temperatures
       lda     #$00   ; 0 -> - 40 degrees
       sta     tmp1
       lda     #205T  ; 165 + 40 degrees (because of offset in lookup table)
       sta     tmp2
       mov     TPSACOLD,tmp3  ; This is the amount at coldest
       mov     #$00,tmp4      ; no enrichemnt addon at warm temperature
       mov     coolant,tmp5
       jsr     lininterp
       mov     tmp6,tmp13     ; result - save here temporarily

; Second, find the multiplier (ACCELMULT) amount based on cold temperatures
       lda     #$00   ; 0 -> - 40 degrees
       sta     tmp1
       lda     #205T  ; 165 + 40 degrees (because of offset in lookup table)
       sta     tmp2
       lda     ACMULT
       sta     tmp3  ; This is the amount at coldest
       mov     #100T,tmp4      ; 1.00 multiplier at 165 degrees
       mov     coolant,tmp5
       jsr     lininterp
       mov     tmp6,tmp14     ; result - save here temporarily


; Now the lookup table amount based on TPSDOT
       ldhx    #tpsdotrate
       sthx    tmp1
       lda     #$03
       sta     tmp3
       lda     tps
       sub     last_tps
       sta     tmp4   ; TPSDOT
       sta     tmp10  ; Save away for later use below
       jsr     ord_table_find

       clrh
       lda     tmp5
       tax
       lda     TPSAQ,x
       sta     tmp4
       decx
       lda     TPSAQ,x
       sta     tmp3
       lda     tmp10
       sta     tmp5
       jsr     lininterp      ; tmp6 has the result
       bra     FIND_TOTAL_A

; This is here to extend the jump range for the checks at the beginning (long-jumps)
B_LO_CONT:
       bra     TAE_CHK_TIME
TDE2:   bra     TDE            ; Only to extend branch for assembler


; Now, the final applied acceleration enrichment amount is ((TMP6 * tmp14)/100) + tmp13
FIND_TOTAL_A:
       lda     tmp6
       tax
       lda     tmp14
       mul
       pshx
       pulh
       ldx     #$64
       div
       bcs     UPPER_RAIL_AE
       psha
       pshh
       pula
       cmp     #$32
       ble     NDA1
       pula
       inca
       bra     ADD_TO_AE
NDA1:
       pula
       bra     ADD_TO_AE

UPPER_RAIL_AE:
       lda     #200T          ; Set to 20 milliseconds railed
       bra     ADD_TO_AE

ADD_TO_AE:

       add     tmp13          ; Add on the amount computed in cold temperature enrich above
       sta     tmp6
       cmp     TPSACCEL
       blo     TAE_CHK_TIME
       lda     tmp6           ; Replace with this higher value
       sta     TPSACCEL

; Check if acceleration done
TAE_CHK_TIME:
       brset   TPSDEN,ENGINE,RST_ACCEL
       lda     tpsaclk
       cmp     tpsaclkcmp
       blo     MAE
RST_ACCEL:
       bclr    TPSAEN,ENGINE
       lda     #$64
sta tpsfuelcut
       clr     TPSACCEL
       bclr    aled,portc
bclr TPSDEN,ENGINE

       bra     MAE

; deaccel
TDE:
       lda     tmp2
       sub     tmp1

       cmp     tpsthresh
       blo     TDE_CHK_DONE
       brclr   TPSAEN,ENGINE,TDE_CHK_FUEL_CUT
       lda     #$64
sta TPSFUELCUT
       clr     TPSACCEL
       bclr    TPSAEN,ENGINE
       bclr    aled,portc
bclr TPSDEN,ENGINE
       bra     MAE
TDE_CHK_FUEL_CUT:
       lda     rpm
       cmp     #$0F
       blo     MAE
       lda     TPSDQ
       sta     TPSFUELCUT
       bset    TPSDEN,ENGINE
       bclr    TPSAEN,ENGINE
       bclr    aled,portc
       bra     MAE
TDE_CHK_DONE:
       brclr   TPSDEN,ENGINE,MAE
       bclr    TPSDEN,ENGINE
       lda     #$64
       sta     TPSFUELCUT
       clr     TPSACCEL
       bra     MAE

***************************************************************************
**
**  Exhaust Gas Oxygen Sensor Measurement Section
**
**   Steps are the following:
**
**   If egodelta = 0 then goto skipo2
**   If RPM < RPMOXLIMIT then goto skipo2
**   If TPSAEN in ENGINE or TPSDEN in ENGINE are set, then goto skipo2
**   If coolant < egotemp then goto skipo2
**   If sech = 0 and secl < 30 seconds then got skipo2 (skip first 30 seconds)
**   If tps > 3.5 volts then goto skipo2
**
**   If egocount > egocountcmp
**   {
**      egocount = 0
**      If ego > 26 (counts, or 0.5 Volts) then (rich)
**      {
**         tmp = egocurr - egodelta
**         if tmp < egolimit then goto VETABLELOOKUP
**         egocorr = tmp
**         goto VETABLELOOKUP
**      }
**      else (lean)
**      {
**         tmp = egocorr + egodelta
**         if tmp > egolimit then goto VETABLELOOKUP
**         egocorr = tmp
**         goto VETABLELOOKUP
**      }
**   }
**
**   skipo2:
**   egocorr = 100%
**   goto VETABLELOOKUP
**
**
**
***************************************************************************
MAE:
       lda     egodelta
beq SKIPO2
lda rpm
cmp RPMOXLIMIT; Low-end of RPM
blo SKIPO2
brset TPSAEN,ENGINE,SKIPO2
brset TPSDEN,ENGINE,SKIPO2
lda coolant
cmp egotemp
blo SKIPO2
lda tps
cmp #$B2
bhi SKIPO2
       lda     sech
       bne     chk_o2_lag     ; if high seconds set then we can check o2
       lda     secl
       cmp     #$1E   ; 30 seconds threshold
       blo     SKIPO2

; Check if exceeded lag time - if so then we can modify egocorr
CHK_O2_LAG:
lda egocount
cmp egocountcmp
blo VETABLELOOKUP

; Check if rich/lean
clr egocount

       lda     config13               ; Check if Narrow-band (bit=0) or DIY-WB (bit=1)
       bit     #$02                   ; Use BIT instead of brset because outside of zero-page
bne     WBO2TYPE               ; Branch if the bit is set
NBO2TYPE:
lda ego
cmp VOLTOXTARGET
blo O2_IS_LEAN
       bra     O2_IS_RICH
WBO2TYPE:
lda ego
cmp VOLTOXTARGET
blo O2_IS_RICH
       bra     O2_IS_LEAN

; rich o2 - lean out egocorr
O2_IS_RICH:
       lda     #$64
       sub     egolimit   ; Generate the lower limit rail point
       sta     tmp2
lda egocorr
sub egodelta
sta tmp1
cmp tmp2
blo VETABLELOOKUP; railed at egolimit value
lda tmp1
sta egocorr
bra VETABLELOOKUP

; lean o2 - richen egocorr
O2_IS_LEAN:
       lda     #$64
       add     egolimit   ; Generate the upper limit rail point
       sta     tmp2

lda egocorr
add egodelta
sta tmp1
cmp tmp2
bhi VETABLELOOKUP; railed at egolimit value
lda tmp1
sta egocorr
bra VETABLELOOKUP

; reset egocorr to 100%
SKIPO2:
lda #$64
sta egocorr
bra VETABLELOOKUP


***************************************************************************
**
**  VE 3-D Table Lookup
**
**   This is used to determine value of VE based on RPM and MAP
**   The table looks like:
**
**      105 +....+....+....+....+....+....+....+
**          ....................................
**      100 +....+....+....+....+....+....+....+
**                     ...
**   KPA                 ...
**                         ...
**       35 +....+....+....+....+....+....+....+
**          5    15   25   35   45   55   65   75 RPM/100
**
**
**  Steps:
**   1) Find the bracketing KPA positions via ORD_TABLE_FIND, put index in tmp8 and
**       bounding values in tmp9(kpa1) and tmp10(kpa2)
**   2) Find the bracketing RPM positions via ORD_TABLE_FIND, store index in tmp11 and
**       bounding values in tmp13(rpm1) and tmp14(rpm2)
**   3) Using the VE table, find the table VE values for tmp15=VE(kpa1,rpm1),
**       tmp16=VE(kpa1,rpm2), tmp17 = VE(kpa2,rpm1), and tmp18 = VE(kpa2,rpm2)
**   4) Find the interpolated VE value at the lower KPA range :
**       x1=rpm1, x2=rpm2, y1=VE(kpa1,rpm1), y2=VE(kpa1,rpm2) - put in tmp19
**   5) Find the interpolated VE value at the upper KPA range :
**       x1=rpm1, x2=rpm2, y1=VE(kpa2,rpm1), y2=VE(kpa2,rpm2) - put in tmp11
**   6) Find the final VE value using the two interpolated VE values:
**       x1=kpa1, x2=kpa2, y1=VE_FROM_STEP_4, y2=VE_FROM_STEP_5
**
***************************************************************************
VETABLELOOKUP:

; First, determine if in Speed-density or Alpha-N mode. If in Alpha-N mode, then
;  replace the variable "kpa" with the contents of "tps". This will not break anything, since
;  this check is performed again when multiplying MAP against the enrichments, and
;  the SCI version of the variable is MAP, not kpa

       lda     config13               ; Check if in speed-density or Aplha-N mode
       bit     #$04                   ; Use BIT instead of brset because outside of zero-page
beq     VE_STEP_1              ; Branch if the bit is clear

       lda     tps
       sta     kpa

VE_STEP_1:
       ldhx    #KPARANGEVEFLASH
       sthx    tmp1
       lda     #$07
       sta     tmp3
       lda     kpa
       sta     tmp4
       jsr     ORD_TABLE_FIND
       lda     tmp1
       lda     tmp2
       mov     tmp5,tmp8   ;Index
       mov     tmp1,tmp9   ;X1
       mov     tmp2,tmp10   ;X2
VE_STEP_2:
       ldhx    #RPMRANGEVEFLASH
       sthx    tmp1
       lda     #$07
       sta     tmp3
       lda     rpm
       sta     tmp4
       jsr     ORD_TABLE_FIND
       mov     tmp5,tmp11    ;Index
       mov     tmp1,tmp13    ;X1
       mov     tmp2,tmp14    ;X2

VE_STEP_3:

;TABLEWALK:
       clrh
       lda     #$08
       psha
       pulx
       lda     tmp8
       deca
       mul
       add     tmp11
       deca
       tax
       lda     VE,x
       sta     tmp15
       incx
       lda     VE,x
       sta     tmp16
       lda     #$08
       psha
       pulx
       lda     tmp8
       mul
       add     tmp11
       deca
       tax
       lda     VE,x
       sta     tmp17
       incx
       lda     VE,x
       sta     tmp18
       jmp     VE_STEP_4


VE_STEP_4:
       mov     tmp13,tmp1
       mov     tmp14,tmp2
       mov     tmp15,tmp3
       mov     tmp16,tmp4
       mov     rpm,tmp5
       jsr     lininterp
       mov     tmp6,tmp19

VE_STEP_5:
       mov     tmp13,tmp1
       mov     tmp14,tmp2
       mov     tmp17,tmp3
       mov     tmp18,tmp4
       mov     rpm,tmp5
       jsr     lininterp
       mov     tmp6,tmp11

VE_STEP_6:
       mov     tmp9,tmp1
       mov     tmp10,tmp2
       mov     tmp19,tmp3
       mov     tmp11,tmp4
       mov     kpa,tmp5
       lda     kpa
       jsr     lininterp
       mov     tmp6,vecurr


***************************************************************************
**
** Computation of Fuel Parameters
**
** Remainders are maintained for hi-resolution calculations - results
**  converted back to 100 microsecond resolution at end.
**
** (Warm * Tpsfuelcut)/100 = R1 + rem1/100
** (Barcor * Aircor)/100 = R2 + rem2/100
** ((R1 + rem1/100) * (R2 + rem2/100)) / 100 = R3 + rem3/100
** (EGO * MAP)/100 = R4 + rem4/100
** ((R3 + rem3/100) * (R4 + rem4/100)) /100 = R5 + rem5/100
** (VE * REQ_FUEL)/100 = R6 + rem6/100
** ((R5 + rem5/100) * (R6 + rem6/100))  = R7
**
**
**
** Note that GAMMAE only includes Warm, Tpsfuelcut, Barocor, and Aircor (EGO no longer included)
**
** Rationle on ordering: to prevent calculation overflow for boosted operations,
**  the variables have been ordered in specific "pairs" in the calculation:
**     EGO * MAP - when at WOT, EGO is set to 100%, so MAP can run up to 255% without overflow
**     VE * REQ_FUEL - for boosted applications, REQ_FUEL tends to be low (below 10 ms) due to the
**                     added fuel requirements (i.e. large injectors), so VE entries can
**                     be well above 100%.
**
***************************************************************************


WARMACCEL_COMP:

       mov     warmcor,tmp10 ; Warmup Correction in tmp10
       clr     tmp11  ; tmp11 is zero
       mov     tpsfuelcut,tmp12; tpsfuelcut in tmp12
       clr     tmp13  ; tmp13 is zero
       jsr     Supernorm ; do the multiply and normalization
       mov     tmp10,tmp1 ; save whole result in tmp1
       mov     tmp11,tmp2 ; save remainder in tmp2

       mov     barocor,tmp10 ; tmp10 is barometer percent
       clr     tmp11  ; zero to tmp11
       mov     aircor,tmp12 ; air temp correction % in tmp12
       clr     tmp13  ; tmp13 is zero
       jsr     Supernorm ; multiply and divide by 100
   ; result in tmp10:tmp11
       mov     tmp1,tmp12 ; move saved tmp1 into tmp12
       mov     tmp2,tmp13 ; move saved tmp2 into tmp13
       jsr     Supernorm ; multiply/divide
       mov     tmp10,tmp5 ; save whole result into tmp5
       mov     tmp11,tmp6 ; save remainder into tmp6
       lda     tmp10
       sta     gammae

       mov     egocorr,tmp10 ; closed-loop correction percent into tmp10
       clr     tmp11  ; remainder is zero
       mov     kpa,tmp12 ; MAP into tmp12
       clr     tmp13  ; no remainder
       jsr     Supernorm ; do the multiply and divide

       mov     tmp5,tmp12 ; take saved result in tmp5 and put into tmp12
       mov     tmp6,tmp13 ; tmp6 into tmp13
       jsr     Supernorm ; mult/div
       mov     tmp10,tmp3 ; result (whole) save in tmp3
       mov     tmp11,tmp4 ; remainder result save in tmp4

       mov     vecurr,tmp10 ; VE into tmp10
       clr     tmp11  ; no remainder value for VE
       mov     REQ_FUEL,tmp12 ; req-fuel into tmp12
       clr     tmp13  ; no remainder
       jsr     Supernorm ; mult/div

       mov     tmp3,tmp12 ; take previous result and put in tmp12
       mov     tmp4,tmp13 ; again for remainder
       jsr     Supernorm ; multiply/divide

       mov     tmp10,tmp11

***************************************************************************
**
** Calculation of Battery Voltage Correction for Injector Opening Time
**
** Injector open time is implemented as a linear function of
**  battery voltage, from 7.2 volts (61 ADC counts) to 19.2 volts (164 counts),
**  with 13.2 volts (113 counts) being the nominal operating voltage
**
** INJOPEN = injector open time at 13.2 volts in mms
** BATTFAC = injector open adjustment factor 6 volts from 13.2V in mms
**
**
** + (INJOPEN + BATTFAC)
** +   *
** +                     (INJOPEN)
** +                         *
** +                                       (INJOPEN - BATTFAC)
** +                                               *
** +
** ++++++++++++++++++++++++++++++++++++++++++++++++++++++
**    7.2V                 13.2V                19.2
**
***************************************************************************
BATT_CORR_COMP:
       lda     #61T
       sta     tmp1
       lda     #164T
       sta     tmp2
       lda     injopen
       add     battfac
       sta     tmp3
       lda     injopen
       sub     battfac
       sta     tmp4
       bpl     MBFF   ; Check if minus comdition
       clr     tmp4
MBFF:
       mov     batt,tmp5
       jsr     lininterp ; injector open time in tmp6
**
;        clr     tmp6
**
***************************************************************************
**
** Calculation of Final Pulse Width
**
**  The following equation is evaluated here:
**
**  PWCALC = TMP6 + TMP11 + TPSACCEL - INJOCFUEL
**
**  Note that INJOCFUEL (injected fuel during injector open and close) is currently a
**    constant - eventually it will be a function
**    of battery voltage.
***************************************************************************
ADD_INJ_OFFSET:
       lda     tmp11
       add     tmp6
       bcs     MAX_PWM_ALLOWED
add TPSACCEL
bcs MAX_PWM_ALLOWED
       sub     InjOCFuel
       sta     pwcalc
       jmp     FINISHED_PW_COMP

MAX_PWM_ALLOWED:
       lda     #$FE
       sta     pwcalc

FINISHED_PW_COMP:
       jmp       LOOPER

***************************************************************************
**
** * * * * Interrupt Section * * * * *
**
** Following interrupt service routines:
**  - Timer Overflow
**  - ADC Conversion Complete
**  - IRQ input line transistion from high to low
**  - Serial Communication received character
**  - Serial Communications transmit buffer empty (send another character)
**
***************************************************************************



***************************************************************************
**
** Timer Rollover - Occurs every 1/10 of a millisecond - main timing clock
**
**
** Generate time rates:
**  1/10 milliseconds
**  1 milliseconds
**  1/10 seconds
**  seconds
**
** Also, in 1/10 millisecond section, turn on/off injector and
**  check RPM for stall condition
** In milliseconds section, fire off ADC conversion for next channel (5 total),
**  and wrap back when all channels done
**
***************************************************************************

TIMERROLL:
;==========================================================================
;***************** 0.1 millesecond section ********************************
;==========================================================================
       inc      mms ; bump up 0.1 millisec variable

;======== Injector Firing Control ========
;===== Main Injector Control Logic =======
       brset    sched1,squirt,NEW_SQUIRT1
INJF1:
       brset    sched2,squirt,NEW_SQUIRT2
INJF2:
       brset    firing1,squirt,CHK_DONE_1
INJF3:
       brset    firing2,squirt,CHK_DONE_2
       jmp      CHECK_RPM

;=== Injector #1 - Start New Injection ===
NEW_SQUIRT1:
       bset     firing1,squirt ; Turn on "firing" bit
       bclr     sched1,squirt  ; Turn off schedule bit (is now current operation)
       bset     inj1,squirt
       bset     sled,portc     ; squrt LED is ON

       mov      #$00,T1CH0H
       mov      INJPWM,T1CH0L
bset  7,PORTA; ** Flyback Damper - turn on X0 for Inj1
       bclr     inject1,portd ;^* * * Turn on Injector #1 (inverted drive)
bra  INJF1

;=== Injector #2 - Start New Injection ===
NEW_SQUIRT2:
       bset     firing2,squirt ; Turn on "firing" bit
       bclr     sched2,squirt  ; Turn off schedule bit (is now current operation)
       bset     inj2,squirt
       bset     sled,portc    ; squrt LED is ON

       mov      #$00,T1CH1H
       mov      INJPWM,T1CH1L
bset  6,PORTA; ** Flyback Damper - turn on X1 for Injector 2
       bclr     inject2,portd ;^* * * Turn on Injector #1 (inverted drive)
bra  INJF2

;=== In


Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.