| 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 Build your own community today with the largest message board hosting company. |