
########################################################################
#
#  Disassembly listing of binary 'aa' (8061, 1 bank)
#
#  See 'aa_msg.txt' for warnings, command list and other info
#
########################################################################
 


######################################################################################
# CATCH CODE    AA  (VM100 circuit board)   1985 UK Ford Granada Scorpio 2.8, 5 speed manual.
#
# 2.8 Litre V6 'Cologne' engine 1985.  UK LEADED 4 Star (~98 octane).
#
# Open loop - no EGO.  Basic 2 digit error codes.  Twin VAFS - one per bank with split inlet manifold.
# Bank Fired Injection, NOT SYNCED. Simply injects every 3 sparks, twice per cycle.
# TFI distributor - no cyl 1 narrow slot in dizzy.
# Seems to have NDS, ACC, but no coded ACC cutoff ?   Optional BAP, EGR. Fixed Octane adjustments 0, 3, 6 degree retard
# One idle speed adjust, by 75 rpm
# Static Timing in this code appears to be 10 BTDC, but UK Haynes workshop manual states 12.
# Injectors are Bosch 0 280 150 219  (-> 168cc/min, 121 gms/min, 16 lbs/hr ?)
# Calibration of sensors, tables etc. appears to be metric.
# Auto versions used 'BA'.   This code has some NDS handling in code, but workshop manual says to ground NDS for manuals.
# No switches on manual gearbox.  No KAM and small RAM.  CPU marked 'T6126' (= 8061 with no KAM ?)
#
# From inspection of board 7.5 Mhz crystal clock = 4.8uS IOTIMER in hardware.
################################################################################
# AD Channels:
# 0 VAF1  1 VCAL  2 ACC  3 x   4 x  5 x  6 OCT  7 TP  8 ECT  9 ACT  A NDS  B x   C VAF2
#
# I/0 mappings:    0    1     2     3     4     5       6       7      8     9     10
# HSI: (bit)      PIP    x    BAP   STI    x    Idle     x       x
# HSO: (chno)     EGR    x     x     x     x    SPOUT  INJ1    INJ2    ISC   STO   S/W
# LSO: (bit)       x     x     x     x     x     x     CPUOK   Pump
# BIDI:(bit)       - - - Not used - - -
#####################################################################################################
# A/D Inputs 0-12 mapped to R7e - R96.    AD 3 4 5 11 not used, but occupy space 
#
# Internal Voltages measured by DVM from actual circuit board.
# Pin Action  AD and Result       Code trigger points     Description/Notes
# 24  ground  AD6  5v => 2.536v   1.92 < V <= 3.845,      3 degrees ign delay
# 23  ground  AD6  5v => 1.245v   0    < V <= 1.92V       6 degrees ign delay
#
# 30  ground? AD10 5v => 3.453v   4.165V, 2.76V, 1.885V   P,D,N by resistor network ?
# 10  12V in? AD2      >=2.56v    EEC schematic has 3.3K/2.7K divider = 5.4V)
#                                 Raw A/D input > 5.69V ?
# 30? ground  HSI 5  High->Low    add 75rpm to Idle speed (in ISC routine)
# ?  ground  HSI 3  High->Low    STI    Self test
#####################################################################################
#    Registers -
#
# Base Regs 0-0x10
# 0   (Zero)    always zero 
# 2    LSO_Port             
# 2  7   FPUMP_DRV             Fuel Pump Drive
# 2  6   CPU_OK                Hardware Watchdog - keep alive signal  [4mS tick]
# 3    LIO_Port             
# 4    AD_Low               
# 5    AD_High              
# 6    IO_Timer             
# 8    INT_Mask             
# 9    INT_Pend             
# a    IO_Status            
#    0 HSO_OVF              
#    1 HSI_OVF              
#    2 HSI_Ready            
#    3 AD_Ready             
#    4 INT_Service          
# b   HSI_Sample           
# c   HSI_Mask             
# d   HSI_Data             
# e   HSI_Time             
# 10  STACK                
# (bit 7 (15) Most significant, bit 0 Least)
# Add Bit    Name             Description
#
#
# 12     T_OVF_CNT             Timer Overflow counter  (~0.3 secs) not accessed anywhere
# 14                           general - used in error code/sensor check
# 15     test_flags            TEST MODE FLAGS word
#    1   EndTest               Shutdown/end of Self test ? not sure
#    2   KOEO                  Engine Off Self test
#    3   KOER                  Engine On self Test
#
# 16     codeflags             Failure flags - Used for STI testing and output codes
#    1   VAF2code              First 6 match 'master' copy (R18)
#    2   TPScode              
#    3   ECTcode              
#    4   ACTcode              
#    5   VAF1code             
#    6   BAPcode              
#    7   VAF_TPSCode           Vaf 1 or 2 out of range in KOEO static test ?
#    8   RAM_code             
#    9   ROM_code             
#
# 18     Fail_flags            Sensor failed flags - from std regular checks.
#    1   VAF2Fail             
#    2   TPSFail              
#    3   ECTFail              
#    4   ACTFail              
#    5   VAF1Fail             
#    6   BAPFail               This code is masked out in code - BAP is optional.
#
# 1a     IgnFlags              Ignition status flags
#    0   SPK_off_pend          missed 'off' event
#    1   SPK_on_pend           missed 'on' event
#    2   SPK_state             current state
#    3   Ign_Adv               stops PIP being locked for 1 event (for calc or sync to take place ?)
#    4   Lock_Ign              Spark locked to PIP signal, below specified rpm (1000)
#    5   Prev_underspd         Mark transition (for spark syncing ?)
#    6   Underspeed            < 600 rpm. Use Underspeed Strategy. (rich mixture etc) Clear >650 rpm
#    7   Cranking              < 450 rpm  Use Cranking Strategy.   Clear > 500 rpm
#
# 1b     flagsw5              
#    7   Base_ign_rqd          New base calc required
#
# 1c     Ign_Advance           Calculated Ignition advance
# 1d     Last_Ign_adv          Last calc Ignition Advance
# 1e     PIP_High_PW           PIP High Time - Length of PIP 'ON' waveform (in IOTIMER ticks) 
#
# 20     TPS_flags            
#    0   TPS_Closed            Zero or negative change (delta). No Accel pump reqd (part throttle or closed ?)
#    1   TPS_TClosed           used only in STI test sequence, with VAFs? 
#    2   TPS_Wide              Large throttle pedal change (WOT ?)
#    6   TPS_Vaf1              VAF out of range flags ( > 1V with engine off ?) Used in STI test
#    7   TPS_Vaf2             
#
# 21     mS_Count              Elapsed Millisecs count. Cycles 0-125 mS to drive eights of sec counter (R2a)
# 22     Inj_Scaler            Injection scaler. Fixed at 0x4000 here, probably fuel ratio for EGO adjustment.
# 24     Coldstart_secs        Set to time in secs for special 'cold start' handling.(sets B0 R2c)
# 26     ACT_start_W           High byte of ACT_START value
# 27     ACT_start             smoothed ACT value at startup. F for alternate Ignition advance for defined time (243c)
# 28     Load_BK1              Bank 1 Load value/base fuel by bank, as looked up from Load table (24b8)
# 29     Load_BK2              Bank 2 Load
# 2a     8ths_sec              Eights sec counter. Counts DOWN for some reason 8 -> 1. Set to 8 at 'New second' event 
#
# 2c     RPM_flags            
#    0   Cold_start            Set if less than 'cold secs' (R24) expired, changes ISC handling (RPM, anti stall)
#    1   No_Fuel               Fuel cutoff, throttle closed ?
#    2   Fuel_Clip             Fuel Weaken instead of cutoff below defined rpm, (anti stall/backfire ?)
#    3   Knock_Risk            Set if wide throttle (and rpm threshold) - sets minimum fuel, adds ign delay, etc
#
# 2d     Pwrd_tmr              Elapsed Seconds counter. (Self Test routine checks more than 2 secs elapsed).
# 2e     Last_ISC_Time         Last ISC (output) state change time (IOTIMER)
#
# 30-3f                        General purpose registers - used everywhere
#
# 40     Last_PIP_High         Last PIP Low->High event time (IOTIMER)
# 42     Last_Ign_delay        Last ign delay time (120 degrees - ign advance)(from R58)
# 44     PIP_Intrvl            Time between PIP High events (i.e Low->High transitions) in IOTIMER ticks 
# 46     LastPipHiPW           Last PIP High Pulsewidth time (IOTIMER ticks) 
# 48     Cyl_no                Cylinder number. Actually only counts 1-3.  For bank injection triggers.
#
# 49                          
#    0   On_pend_BK2           Bank 2 injection 'on' was delayed/is pending
#    2   Off_pend_BK2          Bank 2 injection 'off'was delayed/is pending
#
# 4a                           R4a and R4c are time holders used in ignition interrupt handler
# 4c                          
# 4e     FuelClip_timer        Fuel Clip Timer for fuel weaken on throttle close (600mS)
# 50     Inj_slope             Injector slope. Lookup value via function from VBATT (R52)
# 52     VBATT                 Battery voltage lookup value - used only for injector slope calc.
# 54     Last_HSI              Last HSI state - track bit changes (= interrupt)
# 55     FPUMP_Ticks           Counts IOTIMER overflows. 3 events = ~1 sec,  for fuel pump driver
# 56     Last_KA_Time          Last Keep Alive time  (IOTIME for 'CPU OK' keepalive pulses)
# 58     Ign_Delay             Calculated Ignition Delay time
#
# 5a     Svc_flags            
#    2   PUMP_Reqd             Markers for required functions, subroutines
#    3   STO_Reqd             
#    4   STI_Reqd             
#    5   TRIP_Reqd            
#    6   ISC_Calc_reqd         Set when New ISC calc (by RPM ?)reqd
#    7   ISC_Tmr_reqd          Set when ISC timer reset -> 2 secs ?
#
# 5b     MainTaskNum           Main Task loop count (1-4)
# 5c     RPM_Smooth            Filtered RPM.  Used for PIP Calculation switch 
# 5e     Last_SPK_On           Last SPARK OUT ON and OFF times (IOTIMER) - for ign calcs
# 60     Last_SPK_Off         
# 62     Cyl_Mass_BK1         
# 64     Cyl_Mass_BK2          Cyl charge by bank - grams air? (mass flow/rpm/3 effectively)
# 66                           used in sensor check
# 67     STI_timer             Timer, Eights sec,  used for STO code output ?
# 68                           used in sensor check
#
# 69     OVF_flags            
#     0  VAF_OVF               Overflow markers - for debug only ? Not used anywhere
#     2  ACCL_OVF             
#     3  Flow_OVF             
#     5  InjC_OVF             
#
# 6a                           General use
# 6c
# 6e     ECT_comp_BK1          temp compensation 
# 70     RPM                   RPM times 4, so 0.25 resolution
# 72     ECT_val               ECT after conversion, degrees C/2
# 73     ACT_val               ACT after conversion, Degrees C/2
# 74     DBG_BK1_flow          Only ever written - DEBUG ?
# 76     TRIP_PW_Time          Width of trip pulse => STO , always 50% duty cycle
# 78     TRIP_Time             Last O/P time
# 7a     TaskListCnt           used only in main loop (main task number ? 1-4)
# 7b     AE_readcnt            number of sensor reads for START value (=10) 
# 7c     Octane_adj            ignition delay in degrees*4 ( 0, 3, 6 degrees)
# 7d                           not used ?
####   7e to 97 are RAW A/D inputs ####
# 7e     VAF2_raw              VAF2 - Word, high byte used as coarse value (cranking and accel pump ?)
# 7f     VAF2_raw/256          VAF2_raw high byte
# 80     Vss_raw               Vss supply - Battery level 
# 82     ACC_raw               Air Con Clutch
# 84-88                        not used
# 8a     OCT_raw               Octane adjust (2 wires for 3 voltage levels)
# 8c     TPS_raw               Throttle position
# 8e     ECT_raw               Engine block temp
# 90     ACT_raw               Air charge temp
# 92     NDS_raw               Neutral Drive SW
# 94                           not used
# 96     VAF1_raw              VAF1
# 97     VAF1_raw/256          VAF1_raw high byte
#
# 98     SubTaskNum            Task number for 2nd task list lookup
# 9a     VAF1_Mflow            Mass flow after calculations (BAP, ACT etc)
# 9c     VAF2_Mflow           
# 9e     ECT_Start_hb         
# 9f     ECT_start             Initial Start value ECT - choke/enrich ?
# a0     ECT_comp_BK2         
# a2     Enrich_factor         result of ECT (= block temp) and other calcs for enrich of base fuel 16384 = 1:1
# a4     ECT_PAR_X             used in VAF calc
# a6     VAF1_coarse_Val       Top byte of VAF val - used for accel pump and cranking calcs
# a8     New_HSI              
#
# a9     IgnFlags2            
#    1   PIP_Lead_Calc         set if ign delay calc 120 degree (60 degree if clear)
#    2   PIP_Trail_Calc        swopping lead/trail edge ? Skip one PIP signal and clear spout_rqd
#    3   PIP_Trail             PIP Trigger (lead or trail edge) - set/clear hysteresis <=1000 >= 1050.
#    5   PIP_State            
#
# aa     TPS_Posn              TPS 'angle' (current voltage - min voltage) - for accel pump function
# ac     Ign_DELTA             Ignition delay delta. smoothed and limited, for ign changes
#
# ae     flags1               
#    1   Running               Standard 'Run Mode'.  Continue 'Engine Running' timer
#    5   First_PIP             Set at initialise clears after first PIP.  Stops the 'Cranking' timer
#    6   First_PIP_hi          set at initialise, clears after first PIP high.
# af                           used in accel calc ?
# b0                           not used ?
#
# b2     HSO_Flags             Output subroutine flags
#    0   HSO_BUSY              O/P event was missed as HSO_OVF set (event list full)
#    4   Option_3              O/P NOW, otherwise at specified time
#    5   HSO_ontime            O/P on time or delayed by 200uS
#    6   Option_2             
#    7   Option_1             
#
# b3     State_flags          
#    0   Base_Calc_OK          Marker to sync two subroutine calcs
#    2   Trip_state           
#    3   EGR_State            
#    4   ISC_off              
#    5   ISC_state             Status telltales for various outputs
#    6   STO_state            
#
# b4     OP_Reqd_flags         Output services required
#    0   Inj_rqd_BK1          
#    1   Inj_rqd_BK2          
#    2   SPARK_rqd            
#    6   DOL_rqd              
#    7   ISC_rqd              
#
# b5     flags3               
#    0   TimerOVF              Timer overflow (every 0.3 secs)
#    1   NDS_Drive             'Drive' selected ?     Affects ISC.
#    2   NDS_Neutral           'Neutral' selected ?
#    3   ACC_On                ACC switched on ?
#    4   NDS_Change            NDS slection change ?
#    5   No_Lock_Ign_ISC       set base 10 BTDC if set, 12 degrees if unset (from ISC calc)
#    6   New_PIP               new PIP (ign calc required)
#    7   New_RPM               new RPM (rpm calc required)
#
# b6                           Missed/pending events
#    2   Off_pend_BK1         
#    4   Spark_Missed         
#    6   On_pend_BK1          
#
# b7                          
#    5   Idle_Adjust           change idle RPM by 75 rpm (in ISC calc)
#
# b8
# ba                           gen registers
# bc     VAF2_coarse_Val      
# be     Averaged_RPM          Filtered RPM used for ISC calc
# c0     Cranktime             Cranking Timer - secs - for preset Pulswidth injection calcs
# c2     TimeOn_BK1            Actual Inject event start time Bank 1 (IOTIMER)
# c4     TimeOff_BK1           Actual Inject event stop time Bank 1
# c6     Length_BK1            Actual Inject time Bank 1
# c8     TPS_Min               TPS Minimum Raw value - for TPS flags
# ca     ACL_Enrich_BK1        Enrich Factor value from accel pump calc - per bank
# cc     ACL_enrich_BK2       
# ce     Inj_Cyl_BK1           Base injection charge (fuel) calc results (flow/14.64)
# d0     Inj_Cyl_BK2          
# d2                           not used ?
# d4     TimeOn_BK2            Actual on and off, and length inject times Bank 2 (IOTIMER)
# d6     TimeOff_BK2          
# d8     Length_BK2           
# da     Par_16_BK1            Bank Injection Scalers for ?  Fixed at 16
# db     Par_16_BK2           
# dc     APenr_BK1             Accel pump enrich Scalers used in main injection calc. Base 1:1 = 64
# dd     APenr_BK2            
# de     Accl_Timer_BK1        Accel pump timers in millisecs - run for ~1 second whilst Accel Pump active
# e0     Accl_Timer_BK2        
# e2     Last_TPS_Pos_BK1      Track TPS position for Accel pump recalc
# e4     Last_TPS_Pos_BK2     
# e6     Timer6                ISC - 20 mSecs ?
# e8     Ign_Cyl_Mass          copied from cyl flow calc
# ea     Run_Time              ENGINE RUNNING Timer, seconds - Elapsed time since first PIP ?
# ec     TPS_val               Filtered, Smoothed TPS value/angle
# ee     Last_PIP_Low          Last PIP high_low transition time (IOTIMER)
#
# f0     Ign_Delta             Ignition change (after calc) - limited to 10%
# f2     Base_ign_delay        temp result holder, for DEBUG ?
# f4     ISCTimer              ISC timer 2 secs ?
#
# f6                          
#    0   Neg_flag              Bits for signed and unsigned lookup functions
#    1   Unsigned             
#
# f7                           Dummy timer entries, f7->fc also used in sensor check subroutines
# f8
# f9
# fa
# fb
# fc
# fd
# fe     NDS_Timer                NDS timer - 1 second ?
#
############## DATA and other RAM locations
#
# 100-11a    Stack
#    NB> some DEBUG items seem to be written but not read - assumed to be for cal console.
#
# 128 Last_PIP_Intvl        Last PIP pulsewidth, used for ignition delay delta & smoothing
# 12a DBG_BK2_Flow          DEBUG? Base airflow value, VAF2
# 130 ISC_PW_Final          final calculated value for ISC pulsewidth, after slope compensation
# 132 Reqd_idle_RPM         Calculated idle speed (RPM) after corrections etc.
# 134 Delta_ISC_RPM         DEBUG ? calculated Idle speed delta.
# 136 ISC_val3              used in ISC calc - multiplier from 29fc table ?
# 138 DBG_ISC_V5            DEBUG? Value from ECTXRPM lookup table in ISC calc
# 13a Last_ISC_L            Double length result of calc for ISC - something pulswidth or time ?
# 13c Last_ISC_H             "
# 140 EGR_PW                EGR calculated pulswidth
# 142 EGR_Last_time         EGR last output time
# 144 Timers_last_run       IOTimer value when timer list last run - for accurate time delta
# 146 Last_TPS              TPS Last time read (IOtimer)
# 148 TPS_Interval          TPS interval between reads (for delta calc)
# 14a DBG_BK1_Par           DEBUG ? result of main injection time calc for bank 1 (Timer ticks)
# 14c DBG_BK2_Par           DEBUG ?  " for bank 2
# 152 Last_BAP              BAP Last read time (for delta calc)
# 154 BAP_Interval          BAP Interval between state changes (1/2 of frequency) 
# 156 BAP_Freq              BAP input frequency * 2 
# 158 BAP_Val               BAP value from lookup = inches Hg*8 (atmospheric pressure*8)
# 159 Inject_Clip           Fuel clip ratio (both Injection banks)
# 15a DBG_Rpm_Flags         DEBUG ?  FLAG BITS. RPM,Ign, Fail flags (R1a, R2c, R18) pump rqd etc
# 15c Tot_Inj_L             Injection time (double word) without VBATT compensation, not yet output to trip.
# 15e Tot_Inj_H             "
# 160 Inj_Crank_Time        Inject time for Cranking 
# 162 TRIP_CTimeH           (double word) Counter for trip. (1 sec trip update ? not sure)
# 164 TRIP_CTimeL          
# 166 OCT_flt               AD7 smoothed voltage - for OCTANE ADJUST 0,3,6 degrees)

################################# Data,Cal,Params ############
#
# 2400 VAF1_Scaler           Scaler = VAF raw/2
# 2402 VAF1_Trim             VAF Post processing adjustments - not used
# 2404 VAF1_Trimx            
# 2406 VAF2_Scaler           Same for 2nd VAF.
# 2408 VAF2_Trim             
# 240a VAF2_Trimx            
# 240c BAP_Dflt              (239)     Default BAP value = 29.875*8    1 atmosphere = 29.92
# 2410 CnkSetRPM             (450rpm)  Cranking set below this speed. Cleared at this + hysteresis (24ae below)
# 2412 UspClrRPM             (600rpm)  Underspeed cleared above this
# 2414 UspSetRPM             (505rpm)  Underspeed set below this
# 2416 RPM_1500              (1500rpm) Fuel Weakened instead of full cutoff below this RPM (stall risk ?)
# 2418 RPM_1800              (1800rpm) Knock risk (if WOT) above here. Used for fuel and ignition
# 241a C250deg               (250C)    Max ECT start value (deg C) This and timer used for ignition
# 241b C-40deg               (-40C)    Min ECT start value and fuel weaken/cutoff - for cold starts, but would never be used !
# 241c Tmr_Lim_0             (0 secs)  Timer Limit for cold start conditions (not used)
# 241e InjSize               Injector size, possibly to scale for 0.25 grams fuel per 125mS (=32768 in calcs) ?
# 2420 CylChMax              (7.97mS)  Max cyl charge BEFORE Corrections. (12:1, or 3380cc max at 14.64:1).
# 2422 CylChKMin             (0.19g)   Min charge applied if knock risk flag set => 0.19g air => 35% Cyl fill
# 2424 TP_Accel_min          (0.1v)    Stops accel pump recalc if TPS delta/change below this value (0.025v*4)
# 2426 EmgyEnrich            (130%)    Underspeed emergency fuel enrich => 83/64 => 130 %
# 2427 KnckEnrich            (0%)      Knock risk fuel enrich, base 128
# 2428 C80deg                (80c)     'Cold Start' condition below here, with timer defined by lookup table (2818)
# 2429 RPM_CLC_0             RPM flags preset for RPM_flags (R2c)
# 242a Sensor_1              Used in sensor check - not sure what this does
# 242b sensorx_1             Used in sensor check
# 242c DenseScaler           Multiplier for density table scaler for injection/air flow calcs
# 242e IGN_TRIM_0           
# 2430 IGNKnckLow            above this and if knock risk, ignition knock increment (2468) added (big throttle change)
# 2432 IGNRegMin            
# 2433 IGNRegMax             50 degrees max advance => rotor register
# 2434 IgnScaler            
# 2435 C36_deg               ACT and ECT Limits for alternate Ignition Advance with ECT/ACT_START Values upon initial startup
# 2436 C-40_deg             
# 2437 C100_deg              Default value if ECT fail => 100 deg C
# 2438 C20_deg               Default value if ACT fail => 20 Deg C
# 243a VAF_dflt              Default value if VAF fail => 400 L/min ?
# 243b VAF_Coarse_dflt       Default value top byte of VAF default, for accel pump and cranking calcs
# 243c 650_Secs              Used with ign table choice (safety limits ?)
# 243e AccelPump_Time        Accel pump time, 1 second (16*63 = 1008 mS) If no TPS changes/recalc
# 243f AccelP_min_Time       Minimum time expired before recalc of accel pump allowed (30mS)
# 2440 DOL_scaler            divider for Trip frequency = 1 o/p tick per 0.01 grams ?
# 2442 Ign_flt_sc           
# 2444 1000RPM               Ign calc swops here from 'locked to PIP' to 'calced advance'
# 2446 50RPM                 Hysteresis - 'dead band' for swop
# 2448 0.065V                TPS trigger points (0.065v) - No delta set if smaller than this
# 244a 3.25V                 TPS 'Big Delta' set if change bigger than this (0.25v) ('goosed' or WOT ?)
# 244c FLGS_B3_B0            Controls injection calcs 
# 244e RPM_VFilter          
# 2450 UspISC_PW             Underspeed ISC setting - 80% - goes in top byte
# 2451 CrnKISC_PW            Cranking ISC setting - 100% goes in top byte
# 2452 ISC_FixPW             Set fixed ISC if not zero
# 2453 ISC_FPW               Fixed PW if ISC_Lock set. (50% open)
# 2454 20mSec                Used with ISC
# 2456 RPM_1430              Used with 'cold start' affects ISC
# 2458 EGR_Present           0 - No EGR, 1 - Fixed pulse width PW1 (245a)
# 245a EGR_PW1              
# 245c EGR_LIM1             
# 245e EGR_lim2             
# 2460 600mSec              
# 2462 Snip_58              
# 2464 Max_RPM               Max RPM - ignition cutoff
# 2466 ISC_Freq              Base ISC frequency. 160Hz (1302 * 4.8uS = 6.25 mS)
# 2468 IGN_KnckDly           Ign delay to prevent Knocking - wide throttle and 2500 RPM (see 2430)
# 246a Crank_1              
# 246c Stall_Ctime           if failed start or stall, begin crank PW calc from here (12 secs)
# 2470 BAP_MAX              
# 2472 BAP_MIN              
# 2474 0deg                  Preset ignition delay, as selected via AD7 (OCTANE)
# 2475 3deg                 
# 2476 6deg                 
# 2477 defdeg                Default - also 6 degrees.
# 2478 EGR_chan              EGR is Output channel 1 if set, 0 otherwise
# 247a 3_secs               
# 247c ISC_Min               Min ISC pulswidth = 10%
# 247e ISC_ACC_0             ACC additional ISC pulswidth - if ACC_on set (0%)
# 2480 ISC_NDS_4260          NDS additional ISC pulswidth - if NDS_drive set (6.5%)
# 2482 ISC_2_secs           
# 2484 5V                    Min and max raw sensor voltages
# 2486 0.125V               
# 2488 4.6V                 
# 248a 0.15V                
# 248c 4.6V                 
# 248e 0.26V                
# 2490 5V                   
# 2492 0.2V                  
# 2494 IGN_12                12 degrees ign advance (set in ISC calc, when ?)
# 2496 EGR_PW2              
# 2498 EGR_PW3              
# 249a 32_secs               EGR behaviour against run time
# 249b                       secs
# 249c 1_sec_T9             
# 249e 1_sec_T9x            
# 24a0 InjScaler            
# 24a2 InjTrimB2            
# 24a4 InjMax                Max Injection (cyl charge) allowed
# 24a6 IdleAdjRPM            Idle speed adjust - 75 rpm
# 24a8 DOL_Freq              calculated Trip ?
# 24aa NDS_Scaler            NDS scaler if flag set - for ISC base 128 so this is 1.
# 24ac IGN_NDS_0             NDS additional ignition delay
# 24ae CrankHystRPM          Cranking set/clear hysteresis, 50 rpm
# 24b0 3.845V                Ignition Preset Delay select voltage points
# 24b2 1.92V                
# 24b4 0.0V                 
# 24b6 RPM_1200              ISC...something to do with calc
#
######################## Tables and function data
#
# 24b8 Load                  LOAD - Adjust fueling [RPM x Flow]
# 2531 Cold_Enrich           Enrich if cold [RPM and ECT]
# 2579 Ign_Adv_Cold          Ignition advance cold, used after startup conditions
# 25f2 Ign_Adv_Hot           Ign Advance Hot (interpolated with either 2579 or 25f2)
# 266b Ign_Adv_ECTFlow       Extra ign advance if cold, by flow and temp
# 269b Ign_Adv_ColdStart     Ign Advance for cold startup.
#
# 2714 EGR_PW_Tab           
# 2754 Cranking_Fuel         Cranking_Fuel -> crank time X temp
# 279c Inj_slope             Raw volts to TFR factor -> linear
# 27b4 ECT_Mult_temp        
# 27cc ECT_Time_temp        
# 27d8 ECT_Accel_LU          Accel pump by temp ?
# 27e4 VAF_Coarse_TFR        VAF Transfer for Cranking ?
# 2802 Accel_LU              Multiplier for accel pump
# 2818 ECT_Coldstart_Time    Coldstart strategy time reqd - indexed by ECT startup value
# 2838 ECT_SCALE_11          ECT Scale for lookups ans 0-11
# 2858 RPM_SCALE_10          RPM scale for loopkups ans 0-10 (not linear)
# 2874 FLOW_SCALE_10         (Mass) Flow Scale 0-10
# 2884 ECT_SCALE_7           ECT scale 0-7
# 28a0 FLOW_SCALE_5          (Mass) Flow scale 0-5
# 28b0 Ign_Interp            Interpolate factors by temp, for ign hot and cold tables
# 28c0 Vss_TFR               Vss raw to factor (for slope)
# 28cc VAF_TFR               VAF raw to volume flow (scaled Litres/min ?)
# 2918 ECT_TFR               ECT raw to degrees C
# 296c ACT_TFR               ACT raw to degrees C
# 29c0 Air_Density           Air density from pressure and temp -> mass flow calc
# 29e8 IDLE_ECT              Reqd idle speed by block temp ?
# 29fc ISCxRPM              
# 2a24 ECT_LU2              
# 2a3c ISC_Slope             Slope for ISC, a large solenoid ? looks suitably geometric
# 2a64 ISC_RPM_2            
# 2a7c ISC_Start_PW         
# 2a94 EGR_ECT              
# 2a9e EGR_ACT              
# 2aa8 RPM_SCALE_7          
# 2abc FLOW_SCALE_7         
# 2ad0 SCALE_CrankTime       Timer scale 0-15 secs for cranking
# 2adc BAP_TFR               BAP frequency to pressure (inches Hg * 8)
# 2af0 RPM_Crank_LU          Crank inject multiplier by RPM ?
# 2b04 NDS_IDLE_CHANGE      
# 30e5 Timer_List            Definition of timers and their registers
#
# NB. first entry point does not conform to 'standard' ff,fa,21 of later binaries
#
####################################################################

2000: e7,1d,00            jump  2020             goto 2020;


2003: ff,ff,ff,ff,ff,ff,ff,41 ??                                                   # checksum adjust ?
200b: 84,00,60,5d,00      ??                                                       # end of Hardware ROM ?

# interrupt vectors (service routines)

2010: 04,d0               word  d004,                                              # HSO Port Output 2 = cal console (external)
2012: a0,2c               vect  2ca0,            I_Timer_OVF                       # I/O Timer Overflow
2014: b2,2c               vect  2cb2,            I_Ignore                          # A/D End of Conversion
2016: b3,2c               vect  2cb3,            I_HSI_Data                        # HSI Port Input Data Available
2018: b2,2c               vect  2cb2,            I_Ignore                          # External Interrupt Vector
201a: b0,2d               vect  2db0,            I_HSO_1                           # HSO Port Output  1
201c: b2,2c               vect  2cb2,            I_Ignore                          # HSI 1 Interrupt Vector
201e: b2,2c               vect  2cb2,            I_Ignore                          # HSI 0 Interrupt Vector

##########################
# INITIALISE AND START UP
##########################

2020: fa                  di                     disable ints;                     # "ff,fa" standard start is here !
2021: ff                  nop                    
2022: 01,16               clrw  R16              codeflags = 0;
2024: 11,02               clrb  R2               LSO_Port = 0;                     # Initialise low speed Out
2026: a3,01,50,20,30      ldw   R30,[R0+2050]    R30 = ROMStart;
202b: a3,01,5e,20,32      ldw   R32,[R0+205e]    R32 = ROMEnd;                     # ROM checksum loop start and stop (2000-3fff)
2030: 01,34               clrw  R34              R34 = 0;
2032: 95,40,02            xorb  R2,40            CPU_OK ^= 1;                      # Flip CPU_OK and back 
2035: ff                  nop                    
2036: ff                  nop                    
2037: 11,05               clrb  R5               WDG_Timer = 0;                    # Watchdog Timer reset
2039: 95,40,02            xorb  R2,40            CPU_OK ^= 1;
203c: 66,31,34            ad2w  R34,[R30++]      R34 += [R30++];                   # add each word
203f: 88,32,30            cmpw  R30,R32          
2042: da,ee               jle   2032             if (R30 <= R32) goto 2032;
2044: 89,00,00,34         cmpw  R34,0            
2048: df,04               je    204e             if (R34 != 0)  {                  # if result not zero, then
204a: 81,00,02,16         orw   R16,200          ROM_code = 1; }                   # ROM Checksum fail
204e: 20,12               sjmp  2062             goto 2062;


2050: 00,20               word   2000            ROMStart                          # Checksum segments

2052: ff,27,00,28,ff,2f,00,30 ??                                                   # but only [2050] and [205e] used
205a: ff,37,00,38         ??    

205e: ff,3f               word   3fff            ROMEnd

2060: 00,00                     

2062: b1,ff,08            ldb   R8,ff            INT_Mask = ff;
2065: b1,55,0c            ldb   Rc,55            HSI_Mask = 55;
2068: a1,67,01,18         ldw   R18,167          Fail_flags = 167;                 # RAM Test loop  20-17f
206c: 3f,08,03            jb    B7,R8,2072       if (B7_INT_Mask = 0)  {           # two passes (55 and aa patterns)
206f: b1,aa,0c            ldb   Rc,aa            HSI_Mask = aa; }                  # this for 2nd pass
2072: 05,18               decw  R18              Fail_flags--;
2074: df,1a               je    2090             if (Fail_flags = 0) goto 2090;
2076: 95,40,02            xorb  R2,40            CPU_OK ^= 1;
2079: ff                  nop                    
207a: ff                  nop                    
207b: 11,05               clrb  R5               WDG_Timer = 0;                    # Watchdog Timer reset
207d: 95,40,02            xorb  R2,40            CPU_OK ^= 1;                      # Flip CPU OK 
2080: c7,18,19,0c         stb   Rc,[R18+19]      [Fail_flags+19] = HSI_Mask;
2084: 9b,18,19,0c         cmpb  Rc,[R18+19]      
2088: df,e8               je    2072             if (HSI_Mask = [Fail_flags+19]) goto 2072;
208a: 81,00,01,16         orw   R16,100          RAM_code = 1;                     # RAM test fail
208e: 20,08               sjmp  2098             goto 2098;
2090: 17,08               incb  R8               INT_Mask++;
2092: df,d4               je    2068             if (INT_Mask = 0) goto 2068;      # reset for 2nd pass
2094: 61,ff,fe,16         an2w  R16,feff         RAM_code = 0;

 # RAM and ROM tests done, now do the true startup.
2098: 01,30               clrw  R30              R30 = 0;                          # Clear all regs & RAM (except failflags)
209a: c2,31,00            stw   R0,[R30++]       [R30++] = 0;
209d: 89,16,00,30         cmpw  R30,16           
20a1: df,06               je    20a9             if (R30 = 16) goto 20a9;
20a3: 89,30,00,30         cmpw  R30,30           
20a7: d7,04               jne   20ad             if (R30 = 30)  {
20a9: 65,02,00,30         ad2w  R30,2            R30 += 2; }
20ad: 89,00,02,30         cmpw  R30,200          
20b1: d7,e7               jne   209a             if (R30 != 200) goto 209a;

# Now do presets
20b3: b1,2a,08            ldb   R8,2a            INT_Mask = 2a;                    # Intrs 1,3 5 only allowed
20b6: b1,0f,0d            ldb   Rd,f             HSO_Cmd = f;                      # Set HSO interrupt #2  (cal console)
20b9: a1,b2,00,0e         ldw   Re,b2            HSO_Time = b2;                    # in 4.8 * 178 = 0.854 mSecs
20bd: a1,1a,01,10         ldw   R10,11a          STACK = 11a;                      # stack has 28 entries
20c1: a1,32,00,98         ldw   R98,32           SubTaskNum = 32;
20c5: b1,64,ae            ldb   Rae,64           flags1 = 64;                      # set B2?, First_PIP, First_PIP_hi
20c8: a1,ff,ff,4e         ldw   R4e,ffff         FuelClip_timer = ffff;            # set max
20cc: a1,00,80,c8         ldw   Rc8,8000         TPS_Min = 8000;
20d0: a1,00,80,ec         ldw   Rec,8000         TPS_val = 8000;                   # Max TPS vals
20d4: b1,40,b4            ldb   Rb4,40           OP_Reqd_flags = 40;               # Set DOL_rqd
20d7: b1,05,0c            ldb   Rc,5             HSI_Mask = 5;
20da: b1,08,2a            ldb   R2a,8            8ths_sec = 8;                     # New second for timer (at next 1/8 sec)
20dd: b1,c0,1a            ldb   R1a,c0           IgnFlags = c0;                    # Set Underspeed, Cranking
20e0: a0,06,56            ldw   R56,R6           Last_KA_Time = IO_Timer;          # last keep_alive was NOW
20e3: 11,05               clrb  R5               WDG_Timer = 0;
20e5: 11,05               clrb  R5               WDG_Timer = 0;                    # watchdog reset
20e7: b1,0b,30            ldb   R30,b            R30 = b;
20ea: b0,0d,32            ldb   R32,Rd           R32 = HSI_Data;                   # Clear HSI store, do 12 reads regardless
20ed: ff                  nop                    
20ee: ff                  nop                    
20ef: 15,30               decb  R30              R30--;
20f1: d7,f7               jne   20ea             if (R30 != 0) goto 20ea;
20f3: fb                  ei                     enable ints;


#########################
## MAIN (BASE) CODE STARTS HERE
#########################

  main_loop:
20f4: c9,f4,20            push  20f4             push(main_loop);                  # ALL tasks return here
20f7: 28,9e               scall 2197             Do_outputs();
20f9: 99,01,5b            cmpb  R5b,1            
20fc: d7,02               jne   2100             if (MainTaskNum != 1) goto 2100;  # Do subtask list
20fe: 20,69               sjmp  2169             goto Run_SubTasks;
2100: 99,04,5b            cmpb  R5b,4            
2103: d1,03               jleu  2108             if ((uns) MainTaskNum > 4 )  {
2105: 91,02,b7            orb   Rb7,2            Task_Fail = 1; }
2108: b1,02,5b            ldb   R5b,2            MainTaskNum = 2;
210b: 39,b7,08            jb    B1,Rb7,2116      if (Task_Fail = 1) goto 2116;
210e: 89,00,00,98         cmpw  R98,0            
2112: d7,04               jne   2118             if (SubTaskNum != 0) goto Check_KA;
2114: 20,1c               sjmp  2132             goto Read_AD;
2116: 27,08               sjmp  2020             goto 2020;                        # MainTaskNum out of range, Restart

  Check_KA:
2118: 45,42,03,56,30      ad3w  R30,R56,342      R30 = Last_KA_Time + 342;         # Keep Alive reqd every 4 mS
211d: 88,30,06            cmpw  R6,R30           
2120: de,04               jlt   2126             if (IO_Timer < R30) goto 2126;
2122: d5,32               jnv   2156             if (OVF = 0) goto Keep_Alive;
2124: 20,02               sjmp  2128             goto 2128;
2126: dd,2e               jv    2156             if (OVF = 1) goto Keep_Alive;
2128: 3a,b7,46            jb    B2,Rb7,2171      if (B2_Rb7 = 1) goto Pump_Sto;
212b: 99,02,7a            cmpb  R7a,2            
212e: d1,39               jleu  2169             if ((uns) TaskListCnt <= 2) goto Run_SubTasks;
2130: 20,3f               sjmp  2171             goto Pump_Sto;

  Read_AD:
2132: b1,01,5b            ldb   R5b,1            MainTaskNum = 1;                  # Here when Task = 0, set next task
2135: 11,bb               clrb  Rbb              Rbb = 0;                          # Read A/D Inputs 0-12
2137: a1,7e,00,30         ldw   R30,7e           R30 = 7e;                         # Store in R7e - R96
213b: b0,bb,04            ldb   R4,Rbb           AD_Cmd = Rbb;                     # command = read A/D channel
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;                      # clear channel etc, 10 bits A/D (5mV resolution)
214b: c2,31,32            stw   R32,[R30++]      [R30++] = R32;                    # A/D value stored
214e: 17,bb               incb  Rbb              Rbb++;
2150: 99,0d,bb            cmpb  Rbb,d            
2153: de,e6               jlt   213b             if (Rbb < d) goto 213b;
2155: f0                  ret                    return;

######### Keep Alive ##########
# Entered every 4 mS
# flip bit 6 of LS_PORT (CPU_OK) twice for a short pulse
# Reset watchdog
###############################


  Keep_Alive:
2156: 17,05               incb  R5               WDG_Timer++;                      # reset watchdog
2158: fa                  di                     disable ints;
2159: ff                  nop                    
215a: 95,40,02            xorb  R2,40            CPU_OK ^= 1;
215d: ff                  nop                    
215e: ff                  nop                    
215f: 17,05               incb  R5               WDG_Timer++;                      # reset watchdog (again)
2161: 95,40,02            xorb  R2,40            CPU_OK ^= 1;                      # flip CPU_OK (= LOS logic reset)
2164: fb                  ei                     enable ints;
2165: a0,06,56            ldw   R56,R6           Last_KA_Time = IO_Timer;
2168: f0                  ret                    return;

########### Do next task in (secondary) tasklist


  Run_SubTasks:
2169: 11,5b               clrb  R5b              MainTaskNum = 0;
216b: 17,7a               incb  R7a              TaskListCnt++;
216d: e7,37,0a            jump  2ba7             goto Do_subTaskList;
2170: f0                  ret                    return;

########### Do PUMP, STO, etc ########


  Pump_Sto:
2171: b1,03,5b            ldb   R5b,3            MainTaskNum = 3;
2174: 3a,5a,05            jb    B2,R5a,217c      if (PUMP_Reqd = 0)  {
2177: 71,7f,02            an2b  R2,7f            FPUMP_DRV = 0;
217a: 20,03               sjmp  217f             goto 217f; }
217c: 91,80,02            orb   R2,80            FPUMP_DRV = 1;
217f: 71,ef,5a            an2b  R5a,ef           STI_Reqd = 0;
2182: 3b,0b,03            jb    B3,Rb,2188       if (B3_HSI_Sample = 0)  {
2185: 91,10,5a            orb   R5a,10           STI_Reqd = 1; }
2188: 71,df,b7            an2b  Rb7,df           Idle_Adjust = 0;
218b: 3d,0b,03            jb    B5,Rb,2191       if (B5_HSI_Sample = 0)  {
218e: 91,20,b7            orb   Rb7,20           Idle_Adjust = 1; }
2191: ef,f6,09            call  2b8a             STO_OUT();
2194: 11,7a               clrb  R7a              TaskListCnt = 0;
2196: f0                  ret                    return;


#########################
#    END of MAIN TASK LOOP
########################



########### Do outputs #########


  Do_outputs:
2197: 32,b4,02            jnb   B2,Rb4,219c      if (SPARK_rqd = 1)  {
219a: 28,19               scall 21b5             Do_SPARK(); }
219c: 30,b4,02            jnb   B0,Rb4,21a1      if (Inj_rqd_BK1 = 1)  {
219f: 29,0e               scall 22af             Do_InjBank1(); }
21a1: 31,b4,02            jnb   B1,Rb4,21a6      if (Inj_rqd_BK2 = 1)  {
21a4: 29,61               scall 2307             Do_InjBank2(); }
21a6: 36,b4,02            jnb   B6,Rb4,21ab      if (DOL_rqd = 1)  {
21a9: 29,b4               scall 235f             Do_Trip_Dbl(); }
21ab: 37,b4,03            jnb   B7,Rb4,21b1      if (ISC_rqd = 1)  {
21ae: ef,0a,0a            call  2bbb             Do_ISC_OUT(); }
21b1: ef,74,0a            call  2c28             Do_EGR_OUT();
21b4: f0                  ret                    return;

########### Spark Out Routine ##########
# Rev limit at 6600 rpm
# Spark cutoff at max RPM (so will not be smooth...)
# Ign_delta is +/- 5% max (elsewhere) to soothe change rate
# 120 degrees appears scaled to 32768
###############################


  Do_SPARK:
21b5: 8b,01,64,24,70      cmpw  R70,[R0+2464]    
21ba: d1,0a               jleu  21c6             if ((uns) RPM > Max_RPM )  {
21bc: a0,06,5e            ldw   R5e,R6           Last_SPK_On = IO_Timer;
21bf: a0,06,60            ldw   R60,R6           Last_SPK_Off = IO_Timer;
21c2: 11,1a               clrb  R1a              IgnFlags = 0;
21c4: 20,e8               sjmp  22ae             return; }
21c6: 3d,1a,05            jb    B5,R1a,21ce      if (Prev_underspd = 0)  {
21c9: 3c,1a,02            jb    B4,R1a,21ce      if (Lock_Ign = 1) goto 21ce;      # Both bits clear - ign advance in play
21cc: 20,3c               sjmp  220a             goto 220a; }
21ce: 3b,1a,34            jb    B3,R1a,2205      if (Ign_Adv = 1) goto 2205;       # Advance Event(s) outstanding - ignore this PIP

######## Spark locked to PIP (immediate O/P) ###############
21d1: 11,b2               clrb  Rb2              HSO_Flags = 0;                    # set immediate 0/P
21d3: 30,54,12            jnb   B0,R54,21e8      if (Last_SP_state = 0) goto 21e8; # On or Off Reqd
21d6: b1,15,ba            ldb   Rba,15           Rba = 15;
21d9: 29,ba               scall 2395             Do_OUTPUT();                      # SPARK on - Now
21db: 30,b2,02            jnb   B0,Rb2,21e0      if (HSO_BUSY = 0) goto 21e0;
21de: 20,10               sjmp  21f0             goto 21f0;
21e0: 91,04,1a            orb   R1a,4            SPK_state = 1;
21e3: a0,30,5e            ldw   R5e,R30          Last_SPK_On = R30;
21e6: 20,13               sjmp  21fb             goto 21fb;
21e8: b1,05,ba            ldb   Rba,5            Rba = 5;
21eb: 29,a8               scall 2395             Do_OUTPUT();                      # SPARK off - Now
21ed: 30,b2,05            jnb   B0,Rb2,21f5      if (HSO_BUSY = 1)  {
21f0: 91,10,b6            orb   Rb6,10           Spark_Missed = 1;                 # Debug Flag? - used only here
21f3: 20,b9               sjmp  22ae             return; }
21f5: 71,fb,1a            an2b  R1a,fb           SPK_state = 0;
21f8: a0,30,60            ldw   R60,R30          Last_SPK_Off = R30;
21fb: 35,1a,02            jnb   B5,R1a,2200      if (Prev_underspd = 0) goto 2200;
21fe: 20,ab               sjmp  22ab             goto ClearReqd;
2200: 3c,1a,07            jb    B4,R1a,220a      if (Lock_Ign = 1) goto 220a;
2203: 20,a6               sjmp  22ab             goto ClearReqd;
2205: 71,f7,1a            an2b  R1a,f7           Ign_Adv = 0;
2208: 20,a1               sjmp  22ab             goto ClearReqd;


######## (Calced) Timing Advance in use #############
220a: 91,08,1a            orb   R1a,8            Ign_Adv = 1;                      # Flag = advance in use
220d: 30,1a,02            jnb   B0,R1a,2212      if (SPK_off_pend = 0) goto 2212;
2210: 20,6c               sjmp  227e             goto 227e;
2212: 39,1a,05            jb    B1,R1a,221a      if (SPK_on_pend = 0)  {
2215: 32,1a,02            jnb   B2,R1a,221a      if (SPK_state = 0) goto 221a;
2218: 20,64               sjmp  227e             goto 227e; }                      # do any pending (missed) events
221a: a0,42,58            ldw   R58,R42          Ign_Delay = Last_Ign_delay;
221d: 91,80,1b            orb   R1b,80           Base_ign_rqd = 1;                 # Set 'calc required'

###############################################
# Delay calc - scaled at 32768 = 120 degrees, and then +/- adjust
# flag indicates leading or trailing PIP edge (60 or 120 deg).
# Calc is -
# from PIP LOW - delta(delay+120 deg) * 60 degrees (in timer ticks)
# from PIP HIGH - delay * 120 degrees (in timer ticks). For < 1000 rpm
# Spark is ALWAYS calculated for NEXT spark
###############################################

2220: 3d,a9,2a            jb    B5,Ra9,224d      if (PIP_State = 0)  {

##### PIP Low (trailing edge) processing #####

2223: 31,a9,03            jnb   B1,Ra9,2229      if (PIP_Lead_Calc = 1)  {
2226: ef,1c,0d            call  2f45             Ign_Delay_Calc(); }               # recalc for 60 degree multiplier(delay*2)
2229: 91,04,a9            orb   Ra9,4            PIP_Trail_Calc = 1;
222c: 4c,58,f0,30         ml3w  R30,Rf0,R58      R30 = Ign_Delta * Ign_Delay;
2230: 0d,01,30            shldw R30,1            R30 *= 2;                         # R32 = delay*delta/32768, = delta(delay)
2233: 49,00,80,f0,30      sb3w  R30,Rf0,8000     R30 = Ign_Delta - 8000;
2238: 03,30               negw  R30              R30 = -R30;                       # R30 = -32768-delta (sign preserved ?)
223a: 48,30,32,34         sb3w  R34,R32,R30      R34 = R32 - R30;                  # R34 = delta(delay)+delta(120)
223e: 6c,1e,34            ml2w  R34,R1e          R34 *= PIP_High_PW;
2241: 0d,01,34            shldw R34,1            R34 *= 2;                         # times 60 degrees in ticks ?
2244: a0,36,34            ldw   R34,R36          R34 = R36;                        # = delta(delay+120)* PIP_High_PW; (scaled)
2247: a1,ee,00,3c         ldw   R3c,ee           R3c = ee;                         # SPOUT On at LAST_PIP_Low + delta(delay+120)*PIP_Hi_PW
224b: 20,17               sjmp  2264             goto 2264; }

##### PIP High (leading edge) processing #####
224d: 39,a9,03            jb    B1,Ra9,2253      if (PIP_Lead_Calc = 0)  {
2250: ef,f2,0c            call  2f45             Ign_Delay_Calc(); }               # recalc for 120 degree multiplier
2253: 71,fb,a9            an2b  Ra9,fb           PIP_Trail_Calc = 0;
2256: 4c,44,58,30         ml3w  R30,R58,R44      R30 = Ign_Delay * PIP_Intrvl;     # delay * 120 degrees in ticks ?
225a: 0d,01,30            shldw R30,1            R30 *= 2;
225d: a0,32,34            ldw   R34,R32          R34 = R32;                        # R34 = delay*pip_Hi_intvl (scaled)
2260: a1,40,00,3c         ldw   R3c,40           R3c = 40;                         # SPOUT On at LAST_PIP_HIGH + delay*PIP_Hi_Intvl

 ### Resume Main Flow ###

2264: b1,15,ba            ldb   Rba,15           Rba = 15;                         # SPOUT ON
2267: b1,c0,b2            ldb   Rb2,c0           HSO_Flags = c0;                   # single event at R34+[R3c]
226a: ef,28,01            call  2395             Do_OUTPUT();                      # do output as set above
226d: 30,b2,05            jnb   B0,Rb2,2275      if (HSO_BUSY = 1)  {
2270: 91,02,1a            orb   R1a,2            SPK_on_pend = 1;
2273: 20,39               sjmp  22ae             return; }
2275: a0,30,5e            ldw   R5e,R30          Last_SPK_On = R30;
2278: 71,fd,1a            an2b  R1a,fd           SPK_on_pend = 0;
227b: 91,04,1a            orb   R1a,4            SPK_state = 1;
227e: a0,1e,34            ldw   R34,R1e          R34 = PIP_High_PW;
2281: 89,30,01,34         cmpw  R34,130          
2285: d3,06               jnc   228d             if ((uns) R34 < 130) goto 228d;
2287: 89,b1,28,34         cmpw  R34,28b1         
228b: d1,04               jleu  2291             if ((uns) R34 > 28b1 )  {         # Fit 1.4mS <= PIP_High_PW <= 50mS
228d: a1,30,01,34         ldw   R34,130          R34 = ISC_PW_Final; }             # or 14K rpm <= PIP_PW <= 400 rpm
2291: a1,5e,00,3c         ldw   R3c,5e           R3c = 5e;                         # -> Last_SPK_On
2295: b1,05,ba            ldb   Rba,5            Rba = 5;
2298: b1,c0,b2            ldb   Rb2,c0           HSO_Flags = c0;                   # SPOUT Off at PIP_High_PW + Last_SPK_On
229b: 28,f8               scall 2395             Do_OUTPUT();                      # with checked pulsewidth.
229d: 30,b2,05            jnb   B0,Rb2,22a5      if (HSO_BUSY = 1)  {
22a0: 91,01,1a            orb   R1a,1            SPK_off_pend = 1;
22a3: 20,09               sjmp  22ae             return; }
22a5: 71,fa,1a            an2b  R1a,fa           SPK_off_pend = 0;
                                                 SPK_state = 0;
22a8: a0,30,60            ldw   R60,R30          Last_SPK_Off = R30;

  ClearReqd:
22ab: 71,fb,b4            an2b  Rb4,fb           SPARK_rqd = 0;
22ae: f0                  ret                    return;

##################
# Injection Bank 1 Output.
# schedules on and off events for Injectors
####################


  Do_InjBank1:
22af: 3e,b6,19            jb    B6,Rb6,22cb      if (On_pend_BK1 = 1) goto 22cb;   # delayed On - do now
22b2: 3a,b6,2b            jb    B2,Rb6,22e0      if (Off_pend_BK1 = 1) goto 22e0;  # delayed Off - retry
22b5: 31,2c,05            jnb   B1,R2c,22bd      if (No_Fuel = 1)  {
22b8: a0,06,c4            ldw   Rc4,R6           TimeOff_BK1 = IO_Timer;           # Nothing to do
22bb: 20,43               sjmp  2300             goto 2300; }
22bd: 48,c4,06,30         sb3w  R30,R6,Rc4       R30 = IO_Timer - TimeOff_BK1;
22c1: d5,04               jnv   22c7             if (OVF = 0) goto 22c7;
22c3: de,06               jlt   22cb             if (R30 < 0) goto B1_on;
22c5: 20,3f               sjmp  2306             goto 2306;
22c7: d6,02               jge   22cb             if (R30 < 0)  {
22c9: 20,3b               sjmp  2306             return; }

  B1_on:
22cb: 11,b2               clrb  Rb2              HSO_Flags = 0;
22cd: b1,16,ba            ldb   Rba,16           Rba = 16;                         # Inj On - Now
22d0: 28,c3               scall 2395             Do_OUTPUT();
22d2: 30,b2,05            jnb   B0,Rb2,22da      if (HSO_BUSY = 1)  {
22d5: 91,40,b6            orb   Rb6,40           On_pend_BK1 = 1;
22d8: 20,2c               sjmp  2306             return; }
22da: a0,30,c2            ldw   Rc2,R30          TimeOn_BK1 = R30;                 # Save actual start time
22dd: 71,bf,b6            an2b  Rb6,bf           On_pend_BK1 = 0;

  B1_off:
22e0: b1,c0,b2            ldb   Rb2,c0           HSO_Flags = c0;
22e3: b1,06,ba            ldb   Rba,6            Rba = 6;
22e6: a1,c2,00,3c         ldw   R3c,c2           R3c = c2;                         # -> TimeOn_BK1
22ea: a0,c6,34            ldw   R34,Rc6          R34 = Length_BK1;
22ed: 28,a6               scall 2395             Do_OUTPUT();                      # Inj Bank 1 Off at TimeOn_BK1 + Length_BK1
22ef: 30,b2,05            jnb   B0,Rb2,22f7      if (HSO_BUSY = 1)  {
22f2: 91,04,b6            orb   Rb6,4            Off_pend_BK1 = 1;
22f5: 20,0f               sjmp  2306             return; }
22f7: a0,30,c4            ldw   Rc4,R30          TimeOff_BK1 = R30;
22fa: a0,c6,32            ldw   R32,Rc6          R32 = Length_BK1;
22fd: ef,47,08            call  2b47             Inc_Injtime();
2300: 71,fe,b4            an2b  Rb4,fe           Inj_rqd_BK1 = 0;
2303: 71,bb,b6            an2b  Rb6,bb           Off_pend_BK1 = 0;
                                                 On_pend_BK1 = 0;
2306: f0                  ret                    return;

##################
# Injection Bank 2 Output.
# schedules on and off events for Injectors
####################


  Do_InjBank2:
2307: 38,49,19            jb    B0,R49,2323      if (On_pend_BK2 = 1) goto 2323;   # delayed On - do now
230a: 3a,49,2b            jb    B2,R49,2338      if (Off_pend_BK2 = 1) goto 2338;  # delayed Off - retry
230d: 31,2c,05            jnb   B1,R2c,2315      if (No_Fuel = 1)  {
2310: a0,06,d6            ldw   Rd6,R6           TimeOff_BK2 = IO_Timer;           # Nothing to do
2313: 20,43               sjmp  2358             goto Clearfexit; }
2315: 48,d6,06,30         sb3w  R30,R6,Rd6       R30 = IO_Timer - TimeOff_BK2;
2319: d5,04               jnv   231f             if (OVF = 0) goto 231f;
231b: de,06               jlt   2323             if (R30 < 0) goto 2323;
231d: 20,3f               sjmp  235e             goto 235e;
231f: d6,02               jge   2323             if (R30 < 0)  {
2321: 20,3b               sjmp  235e             return; }
2323: 11,b2               clrb  Rb2              HSO_Flags = 0;
2325: b1,17,ba            ldb   Rba,17           Rba = 17;
2328: 28,6b               scall 2395             Do_OUTPUT();                      # Inj On - Now
232a: 30,b2,05            jnb   B0,Rb2,2332      if (HSO_BUSY = 1)  {
232d: 91,01,49            orb   R49,1            On_pend_BK2 = 1;
2330: 20,2c               sjmp  235e             return; }
2332: a0,30,d4            ldw   Rd4,R30          TimeOn_BK2 = R30;                 # Save actual start time
2335: 71,fe,49            an2b  R49,fe           On_pend_BK2 = 0;
2338: b1,c0,b2            ldb   Rb2,c0           HSO_Flags = c0;
233b: b1,07,ba            ldb   Rba,7            Rba = 7;
233e: a1,d4,00,3c         ldw   R3c,d4           R3c = d4;                         # -> TimeOn_BK2
2342: a0,d8,34            ldw   R34,Rd8          R34 = Length_BK2;
2345: 28,4e               scall 2395             Do_OUTPUT();                      # Inj Bank 2 Off at TimeOn_BK2 + Length_BK2
2347: 30,b2,05            jnb   B0,Rb2,234f      if (HSO_BUSY = 1)  {
234a: 91,04,49            orb   R49,4            Off_pend_BK2 = 1;
234d: 20,0f               sjmp  235e             return; }
234f: a0,30,d6            ldw   Rd6,R30          TimeOff_BK2 = R30;
2352: a0,d8,32            ldw   R32,Rd8          R32 = Length_BK2;
2355: ef,ef,07            call  2b47             Inc_Injtime();

  Clearfexit:
2358: 71,fd,b4            an2b  Rb4,fd           Inj_rqd_BK2 = 0;
235b: 71,fa,49            an2b  R49,fa           On_pend_BK2 = 0;
                                                 Off_pend_BK2 = 0;
235e: f0                  ret                    return;


##########################################################
# DOL - Output for trip computer - STO has separate routine (below)
# 50% duty cycle at variable freq as ON and OFF are the same value
# for slow frequencies use version with single event (to save O/P slots ?)
# otherwise use this func for double event. Swops over at approx. half scale (0x4000)
##########################################################


  Do_Trip_Dbl:
235f: 3d,5a,05            jb    B5,R5a,2367      if (TRIP_Reqd = 0)  {
2362: a0,06,78            ldw   R78,R6           TRIP_Time = IO_Timer;
2365: 20,2d               sjmp  2394             return; }
2367: 3a,b3,06            jb    B2,Rb3,2370      if (Trip_state = 1) goto 2370;
236a: 89,00,40,76         cmpw  R76,4000         
236e: d3,03               jnc   2373             if ((uns) TRIP_PW_Time < 4000) goto 2373;
2370: e7,f4,07            jump  2b67             goto Do_Trip_Single;              # >= 12.7 Hz - use single event routine
2373: a0,76,34            ldw   R34,R76          R34 = TRIP_PW_Time;               # 50% duty cycle at variable Freq
2376: a0,76,36            ldw   R36,R76          R36 = TRIP_PW_Time;
2379: a1,78,00,3c         ldw   R3c,78           R3c = 78;                         # -> TRIP_Time (2nd event)
237d: b1,80,b2            ldb   Rb2,80           HSO_Flags = 80;
2380: b1,19,ba            ldb   Rba,19           Rba = 19;
2383: b1,29,bb            ldb   Rbb,29           Rbb = 29;
2386: 28,0d               scall 2395             Do_OUTPUT();                      # 2 events.On, Off with interrupt
2388: 38,b2,09            jb    B0,Rb2,2394      if (HSO_BUSY = 1) return;
238b: 71,bf,b4            an2b  Rb4,bf           DOL_rqd = 0;
238e: 71,fb,b3            an2b  Rb3,fb           Trip_state = 0;
2391: a0,32,78            ldw   R78,R32          TRIP_Time = R32;                  # Off event start time/On event end
2394: f0                  ret                    return;

####################################################
# main output routine - 1 or 2 events supported.
# calls low level output routine for each event reqd.
# Rb2 = flags (in and out)
# Rba = event 1 definition (channel + state)
# Rbb = event 2 definition
# R34 = event 1 start time  (+[R3c] if B7 set)
# R36 = event 2 start time  (as increment from actual event 1 time)
# R3c = pointer to additional delay (word) 
# Rb2 flags IN
#  B7 SET    Event 1 time = R34 + [R3c],  Event 2 time = R34 + [R3c] + R36
#  B6 SET    No event 2 if B7 set (=> extra delay R3c)
#  B7 CLEAR  Event 1 NOW (immediate output)
#  B4 SET    Event 1 time = NOW, Event 2 time = NOW+R36
# ANSWERS
#  R30    = actual start time of event 1
#  R32    = actual start time of event 2
#  Rb2 B5   output delayed if clear (but not used elsewhere)
#  Rb2 B0   output busy = event(s) missed
####################################################


  Do_OUTPUT:
2395: 71,fe,b2            an2b  Rb2,fe           HSO_BUSY = 0;
2398: 38,0a,4c            jb    B0,Ra,23e7       if (HSO_OVF = 1) goto 23e7;
239b: 05,34               decw  R34              R34--;
239d: 3f,b2,05            jb    B7,Rb2,23a5      if (Option_1 = 0)  {
23a0: a0,06,30            ldw   R30,R6           R30 = IO_Timer;
23a3: 20,07               sjmp  23ac             goto 23ac; }
23a5: 46,3c,34,30         ad3w  R30,R34,[R3c]    R30 = R34 + [R3c];
23a9: 91,20,b2            orb   Rb2,20           HSO_ontime = 1;
23ac: b0,ba,3e            ldb   R3e,Rba          R3e = Rba;                        # Event 1 state + chl
23af: a0,30,b8            ldw   Rb8,R30          Rb8 = R30;                        # Event 1 time reqd
23b2: 48,30,06,3a         sb3w  R3a,R6,R30       R3a = IO_Timer - R30;             # Event interval from now (negated)
23b6: ef,63,07            call  2b1c             HSOUT();
23b9: d3,06               jnc   23c1             if ((uns) R3a >= 0)  {
23bb: 71,df,b2            an2b  Rb2,df           HSO_ontime = 0;
23be: a0,b8,30            ldw   R30,Rb8          R30 = Rb8; }                      # output delayed, save true event time
23c1: 3f,b2,05            jb    B7,Rb2,23c9      if (Option_1 = 1) goto 23c9;
23c4: 3c,b2,05            jb    B4,Rb2,23cc      if (Option_3 = 1) goto 23cc;
23c7: 20,21               sjmp  23ea             return;
23c9: 3e,b2,1e            jb    B6,Rb2,23ea      if (Option_2 = 1) return;
23cc: 38,0a,18            jb    B0,Ra,23e7       if (HSO_OVF = 0)  {
23cf: 44,30,36,32         ad3w  R32,R36,R30      R32 = R36 + R30;
23d3: b0,bb,3e            ldb   R3e,Rbb          R3e = Rbb;                        # Event 2 state + chl
23d6: a0,32,b8            ldw   Rb8,R32          Rb8 = R32;                        # Event 2 time reqd
23d9: 48,32,06,3a         sb3w  R3a,R6,R32       R3a = IO_Timer - R32;             # Event interval from now (negated)
23dd: ef,3c,07            call  2b1c             HSOUT();
23e0: d3,08               jnc   23ea             if ((uns) R3a < 0) return;
23e2: a0,b8,32            ldw   R32,Rb8          R32 = Rb8;                        # Save actual event time
23e5: 20,03               sjmp  23ea             return; }

  Busy_exit:
23e7: 91,01,b2            orb   Rb2,1            HSO_BUSY = 1;
23ea: f0                  ret                    return;



23eb: ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff  
23fb: ff,ff,ff,ff,ff            


###########################################
#    DATA Parameters and Tables main block
###########################################

2400: 00,80               word   8000            VAF1_Scaler                       # Flow scaler for VAF    (= 1/2)
2402: 00,00               word      0            VAF1_Trim                         # trim scale 1
2404: 00,00               word      0            VAF1_Trimx                        # trim scale 2
2406: 00,80               word   8000            VAF2_Scaler                       # and same for second VAF
2408: 00,00               word      0            VAF2_Trim
240a: 00,00               word      0            VAF2_Trimx

240c: ef                  byte   ef              BAP_Dflt                          # 239 = 29.875 inches Hg (1 std atmo)

240d: ff,e5,3d            ??    

2410: 08,07               word    708            CnkSetRPM                         # 450 rpm, cranking set (& underspeed)
2412: 60,09               word    960            UspClrRPM                         # 600 rpm, underspeed cleared
2414: e4,07               word    7e4            UspSetRPM                         # 505 rpm, underspeed set
2416: 70,17               word   1770            RPM_1500                          # 1500 rpm, Min RPM for fuel cutoff, weaken fuel instead on TPS close
2418: 20,1c               word   1c20            RPM_1800                          # 1800 rpm, Min RPM for fuel cutoff when cold start, AND knock risk above this.

241a: 7f                  byte   7f              C250deg                           # ECT Start max
241b: ec                  byte   ec              C-40deg                           # ECT start min

241c: 00,00               word      0            Tmr_Lim_0                         # mSecs - Timer from engine start to force snip instead of cutoff ?
241e: 4e,62               word   624e            InjSize                           # 167cc/min    25166 ticks = 0.25 gram fuel ?.
2420: f0,16               word   16f0            CylChMax                          # Max (base) injection charge. (563 cc at 1.2058 g/L)
2422: 31,08               word    831            CylChKMin                         # Min (base) injection charge whilst knock risk flag set
2424: 00,05               word    500            TP_Accel_min                      # TPS delta to force accel pump recalc

2426: 53                  byte   53              EmgyEnrich                        # Enrich 30% if underspeed (and cranking). Scale 64, 83/64 = 1.297.
                                                                                   # Crank scale 32 => 2.594
2427: 80                  byte   80              KnckEnrich                        # Enrich if Knock Risk. scale 128 so this is 1:1 (no additional)
2428: 28                  byte   28              C80deg                            # max temp to inhibit fuel cut off
2429: 00                  byte    0              RPM_CLC_0
242a: 01                  byte    1              Sensor_1                          # used in sensor check...
242b: 01                  byte    1              sensorx_1

242c: 60,3c               word   3c60            DenseScaler                       # Density scaler for Air Density table. = 1.206 at default values (1g air at STP)
242e: 00,00               word      0            IGN_TRIM_0
2430: 10,27               word   2710            IGNKnckLow                        # 2500 rpm - add knock spark delay if above here

2432: 00                  byte    0              IGNRegMin
2433: c8                  byte   c8              IGNRegMax                         # Ignition register, max and min.
2434: 80                  byte   80              IgnScaler                         # Ignition Scaler (128 is x1)
2435: 12                  byte   12              C36_deg
2436: ec                  byte   ec              C-40_deg
2437: 32                  byte   32              C100_deg
2438: 0a                  byte    a              C20_deg                           # various temp triggers for cold start etc.

2439: ff                        

243a: 80,57               word   5780            VAF_dflt                          # 1.75v = 2800 L/min => 1000rpm ?
243c: 8a,02               word    28a            650_Secs                          # Secs - (~ 11 mins) IGN table swopover from cold start conditions

243e: 3f                  byte   3f              AccelPump_Time
243f: 1e                  byte   1e              AccelP_min_Time

2440: 4b,03               word    34b            DOL_scaler
2442: 00,20               word   2000            Ign_flt_sc
2444: a0,0f               word    fa0            1000RPM
2446: c8,00               word     c8            50RPM                             # Hysteresis for flag at value above (1k rpm)
2448: 40,03               word    340            0.065V
244a: 80,a2               word   a280            3.25V

244c: 09                  byte    9              FLGS_B3_B0                        # Flags (when set)
                                                                                   # B0 (set)   but not used anywhere ?
 
                                                                                   # B2 (clear) Force bank 2 = Bank 1 calculated injection time
 
                                                                                   # B3 (Set)   Average the cyl mass calcs unless cranking 
                                                                                   #(otherwise done separately per bank - for filtering ?)
 
                                                                                   # B4 (Clear) Allow Tmr9 flag [from NDS, affects idle/ISC]
                                                                                   #    (3 NDS flags total)

244d: ff                        

244e: ff,ff               word   ffff            RPM_VFilter                       # Digital Filter for ISC rpm (100%, reverse delta ?)

2450: 66                  byte   66              UspISC_PW                         # Underspeed ISC - Top Byte = 26112 = 4.98mS (79.7%)
2451: 80                  byte   80              CrnKISC_PW                        # Cranking ISC Pulswidth - Top Byte = 32768 = 6.25mS (100%)
2452: 00                  byte    0              ISC_FixPW                         # b0 - set fixed ISC pulsewidth of [2453]
                                                                                   # b1 - allow 200rpm increase (STI ? COld ?)
2453: 40                  byte   40              ISC_FPW                           # Fixed ISC pulsewidth 50% , top byte = 16384 => 3.125mS (50%)

2454: 14,00               word     14            20mSec                            # mSecs ISC
2456: 58,16               word   1658            RPM_1430                          # 1430 rpm, ISC something

2458: 00                  byte    0              EGR_Present

2459: ff                        

245a: 00,20               word   2000            EGR_PW1
245c: 9a,09               word    99a            EGR_LIM1
245e: 66,36               word   3666            EGR_lim2
2460: 58,02               word    258            600mSec                           # mSecs. Timer for Fuel clip.

2462: 3a                  byte   3a              Snip_58

2463: ff                        

2464: 20,67               word   6720            Max_RPM                           # 6600 rpm = rev limit (spark cutoff)
2466: 16,05               word    516            ISC_Freq                          # ISC Base multiplier/freq (=> 6.25mS =>160Hz)
2468: 00,00               word      0            IGN_KnckDly                       # additional spark delay if knock risk

246a: 01                  byte    1              Crank_1                           # Always force averaged cyl mass if set to zero

246b: ff                        

246c: e0,2e               word   2ee0            Stall_Ctime                       # Restart cranking lookup here (12 secs) => stall or fail to start

246e: f0,ff               ??    

2470: 00,af               word   af00            BAP_MAX                           # => 240- 350 ticks/sec => 120-175 Hz
2472: 00,78               word   7800            BAP_MIN

2474: 00                  byte    0              0deg                              # 0 degree retard
2475: f4                  byte   f4              3deg                              # 3 deg retard
2476: e8                  byte   e8              6deg                              # 6 deg retard
2477: e8                  byte   e8              defdeg                            # safety default retard, but not used
2478: 00                  byte    0              EGR_chan                          # set if EGR connected to chan 1 instead of chan 0

2479: ff                        

247a: 03,00               word      3            3_secs                            # = Secs
247c: cd,0c               word    ccd            ISC_Min                           # 10% Minimum opening for ISC
247e: 00,00               word      0            ISC_ACC_0                         # added to ISC if ACC flag
2480: a4,10               word   10a4            ISC_NDS_4260                      # added to ISC if NDS 1 Flag (DRIVE - 6.5% extra ?)
2482: d0,07               word    7d0            ISC_2_secs                        # = mSecs
2484: 00,fa               word   fa00            5V                                # = 5.0 Volts
2486: 40,06               word    640            0.125V                            # = 0.125 Volts
2488: 00,e6               word   e600            4.6V                              # = 4.6 Volts
248a: 80,07               word    780            0.15V                             # = 0.15 Volts
248c: 00,e6               word   e600            4.6V                              # = 4.6 Volts
248e: 00,0d               word    d00            0.26V                             # = 0.26 Volts
2490: 00,fa               word   fa00            5V                                # = 5.0 Volts
2492: 00,0a               word    a00            0.2V                              # = 0.2 Volts
2494: 30,00               word     30            IGN_12                            # Base IGN 12 degrees (via ISC)
2496: 33,33               word   3333            EGR_PW2
2498: cd,0c               word    ccd            EGR_PW3

249a: 20                  byte   20              32_secs                           # = Secs
249b: 20                  byte   20

249c: e8,03               word    3e8            1_sec_T9                          # = Secs
249e: e8,03               word    3e8            1_sec_T9x                         # = Secs
24a0: 00,40               word   4000            InjScaler                         # Injection scaler for calc - is x1
24a2: 0d,00               word      d            InjTrimB2                         # Added Only to bank1 time. For Crankcase breather ?
24a4: 00,80               word   8000            InjMax                            # Max inject value (32768 = 125mS = 0.25 gms fuel)
24a6: 2c,01               word    12c            IdleAdjRPM                        # Idle Adject = 75 rpm
24a8: 90,65               word   6590            DOL_Freq                          # Trip computer. Update period 1/8 sec in ticks (x8 in code = 1 sec)
24aa: 80,00               word     80            NDS_Scaler                        # Scale ISC if NDS (128 is x1)
24ac: 00,00               word      0            IGN_NDS_0                         # Add ign if NDS
24ae: c8,00               word     c8            CrankHystRPM                      # = 50 rpm hysteresis (cranking)
24b0: 40,c0               word   c040            3.845V                            # below 3.845v for 3 degree retard [2475] (0 [2474] if above)
24b2: 00,60               word   6000            1.92V                             # below 1.92v    for 6 degree retard [2476]
24b4: 00,00               word      0            0.0V                              # below 0v for DEFAULT [2477]
24b6: c0,12               word   12c0            RPM_1200                          # = 1200 rpm

##########################################################
# Load - Base Fuel Adjustment - Flow(down+) x RPM(across+) 11 x 11 (shown scaled, base = 0x80 = 1:1)
##########################################################


  Load:
24b8: 8d,8d,8d,8d,80,80,7a,7a,7a,7a,7a  table 141,141,141,141,128,128,122,122,122,122,122
24c3: 86,86,85,81,7f,84,89,8d,8d,8d,8d  table 134,134,133,129,127,132,137,141,141,141,141
24ce: 86,86,82,80,7d,84,89,8e,92,93,93  table 134,134,130,128,125,132,137,142,146,147,147
24d9: 86,88,84,84,84,86,88,8e,8e,8d,98  table 134,136,132,132,132,134,136,142,142,141,152
24e4: 86,80,86,86,86,85,86,8c,88,8e,93  table 134,128,134,134,134,133,134,140,136,142,147
24ef: 8a,8c,85,89,88,85,83,89,8a,93,92  table 138,140,133,137,136,133,131,137,138,147,146
24fa: 8a,86,8c,84,7d,83,85,89,86,89,97  table 138,134,140,132,125,131,133,137,134,137,151
2505: 8a,7c,86,84,88,83,88,86,8d,97,96  table 138,124,134,132,136,131,136,134,141,151,150
2510: 88,77,77,7a,73,7d,7b,8a,8f,97,96  table 136,119,119,122,115,125,123,138,143,151,150
251b: 88,77,77,74,7d,78,73,88,8f,97,96  table 136,119,119,116,125,120,115,136,143,151,150
2526: 88,77,77,7b,74,77,7d,88,8f,97,96  table 136,119,119,123,116,119,125,136,143,151,150

##########################################################
# Flow & Temp enrichment [i.e. choke] Cyl Flow (down+) x ECT (across+) 12 X 6
# used as multiplier factor => 32 is base (default 10th col (=hot))
##########################################################


  Cold_Enrich:
2531: 43,3c,36,33,31,2e,2b,29,27,25,20,20  table  67, 60, 54, 51, 49, 46, 43, 41, 39, 37, 32, 32
253d: 43,3b,35,32,2d,2a,26,24,23,20,20,20  table  67, 59, 53, 50, 45, 42, 38, 36, 35, 32, 32, 32
2549: 43,3b,35,32,2d,2a,26,24,23,20,20,20  table  67, 59, 53, 50, 45, 42, 38, 36, 35, 32, 32, 32
2555: 43,3b,35,32,2d,2a,26,24,23,20,20,20  table  67, 59, 53, 50, 45, 42, 38, 36, 35, 32, 32, 32
2561: 43,3b,35,32,2d,2a,26,24,23,20,20,20  table  67, 59, 53, 50, 45, 42, 38, 36, 35, 32, 32, 32
256d: 43,3b,35,32,2d,2a,26,24,23,20,20,20  table  67, 59, 53, 50, 45, 42, 38, 36, 35, 32, 32, 32

##########################################################
# Ignition Timing COLD - Flow (down+) x RPM (across+) 11 X 11
# Used with HOT table and interpolated via ACT
# RPM Cols    700 1000 1300 1600 2000 2500 3000 3500 4000 5000 6000
##########################################################


  Ign_Adv_Cold:
2579: 30,30,30,50,58,54,64,68,70,70,70  table  48, 48, 48, 80, 88, 84,100,104,112,112,112
2584: 30,42,58,58,80,a0,a8,ac,a0,a8,a8  table  48, 66, 88, 88,128,160,168,172,160,168,168
258f: 30,8a,8c,94,a4,ac,b4,b4,ac,a8,a8  table  48,138,140,148,164,172,180,180,172,168,168
259a: 60,80,7c,88,90,98,a8,a4,a4,98,8c  table  96,128,124,136,144,152,168,164,164,152,140
25a5: 48,70,74,84,88,90,a4,a4,a4,98,8c  table  72,112,116,132,136,144,164,164,164,152,140
25b0: 48,6c,68,70,84,8c,90,9c,a4,a0,8c  table  72,108,104,112,132,140,144,156,164,160,140
25bb: 22,4c,5c,6c,78,8c,8c,94,a4,a0,90  table  34, 76, 92,108,120,140,140,148,164,160,144
25c6: 18,3c,5c,74,78,88,88,8c,98,98,90  table  24, 60, 92,116,120,136,136,140,152,152,144
25d1: 12,2e,4c,68,74,80,84,90,98,8c,90  table  18, 46, 76,104,116,128,132,144,152,140,144
25dc: 12,2c,48,54,68,78,7c,88,88,8c,90  table  18, 44, 72, 84,104,120,124,136,136,140,144
25e7: 12,2c,48,54,64,74,78,88,88,8c,90  table  18, 44, 72, 84,100,116,120,136,136,140,144

##########################################################
# Ignition Timing HOT - Flow (down+) x RPM (across+) 11 X 11
# Used with COLD table and interpolated via ACT lookup table
##########################################################


  Ign_Adv_Hot:
25f2: 30,30,30,50,58,54,64,68,70,70,70  table  48, 48, 48, 80, 88, 84,100,104,112,112,112
25fd: 30,42,58,58,80,a0,a8,ac,a0,a8,a8  table  48, 66, 88, 88,128,160,168,172,160,168,168
2608: 30,8a,8c,94,a4,ac,b4,b4,ac,a8,a8  table  48,138,140,148,164,172,180,180,172,168,168
2613: 60,80,7c,88,90,98,a8,a4,a4,98,8c  table  96,128,124,136,144,152,168,164,164,152,140
261e: 48,70,74,84,88,90,a4,a4,a4,98,8c  table  72,112,116,132,136,144,164,164,164,152,140
2629: 40,64,60,68,7c,84,88,94,9c,98,84  table  64,100, 96,104,124,132,136,148,156,152,132
2634: 1a,44,54,64,70,84,84,8c,9c,98,88  table  26, 68, 84,100,112,132,132,140,156,152,136
263f: 0c,30,50,68,6c,7c,7c,80,8c,8c,84  table  12, 48, 80,104,108,124,124,128,140,140,132
264a: 06,22,40,5c,68,74,78,84,8c,80,84  table   6, 34, 64, 92,104,116,120,132,140,128,132
2655: 00,1c,38,44,58,68,6c,78,78,7c,80  table   0, 28, 56, 68, 88,104,108,120,120,124,128
2660: 00,1c,38,44,54,64,68,78,78,7c,80  table   0, 28, 56, 68, 84,100,104,120,120,124,128

##########################################################
# Additional Ign advance if engine block cold - Flow (down+) x ECT (across+)
##########################################################


  Ign_Adv_ECTFlow:
266b: 1c,1c,1c,1c,14,00,00,00  table  28, 28, 28, 28, 20,  0,  0,  0
2673: 1c,1c,1c,1c,14,00,00,00  table  28, 28, 28, 28, 20,  0,  0,  0
267b: 1c,1c,1c,1c,14,00,00,00  table  28, 28, 28, 28, 20,  0,  0,  0
2683: 1c,1c,1c,1c,14,00,00,00  table  28, 28, 28, 28, 20,  0,  0,  0
268b: 1c,1c,1c,1c,14,00,00,00  table  28, 28, 28, 28, 20,  0,  0,  0
2693: 1c,1c,1c,1c,14,00,00,00  table  28, 28, 28, 28, 20,  0,  0,  0

##########################################################
# Alternate (Safety ?) Cold Ign Timing    Flow (down+) x RPM (across+) 11 X 11
# used for cold start conditions (ECT ACT) and with time limit.
# Still interpolated with HOT table, not quite same as std COLD table, but close.....
##########################################################


  Ign_Adv_ColdStart:
269b: 30,30,30,50,58,54,64,68,70,70,70  table  48, 48, 48, 80, 88, 84,100,104,112,112,112
26a6: 30,30,44,48,70,a0,a8,ac,a0,a8,a8  table  48, 48, 68, 72,112,160,168,172,160,168,168
26b1: 30,78,78,84,88,ac,b4,b4,ac,a8,a8  table  48,120,120,132,136,172,180,180,172,168,168
26bc: 60,6c,68,78,78,98,a8,a4,a4,98,8c  table  96,108,104,120,120,152,168,164,164,152,140
26c7: 48,50,64,74,78,90,a4,a4,a4,98,8c  table  72, 80,100,116,120,144,164,164,164,152,140
26d2: 48,5c,68,64,70,8c,90,9c,a4,a0,8c  table  72, 92,104,100,112,140,144,156,164,160,140
26dd: 22,32,5c,6c,68,8c,8c,94,a4,a0,90  table  34, 50, 92,108,104,140,140,148,164,160,144
26e8: 18,3c,5c,74,78,88,88,8c,98,98,90  table  24, 60, 92,116,120,136,136,140,152,152,144
26f3: 12,2e,4c,68,74,80,84,90,98,8c,90  table  18, 46, 76,104,116,128,132,144,152,140,144
26fe: 12,2c,48,54,68,78,7c,88,88,8c,90  table  18, 44, 72, 84,104,120,124,136,136,140,144
2709: 12,2c,48,54,64,74,78,90,88,8c,90  table  18, 44, 72, 84,100,116,120,144,136,140,144

## EGR Dummy (referenced at 3f80 )


  EGR_PW_Tab:
2714: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32
271c: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32
2724: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32
272c: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32
2734: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32
273c: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32
2744: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32
274c: 20,20,20,20,20,20,20,20  table  32, 32, 32, 32, 32, 32, 32, 32

##########################################################
# Cranking Fuel -> Crank Time (down+) ECT (across+)    used as multiplier ##
# Crank/Timer0 is a 15 sec timer    then multiplied by RPM lookup...
##########################################################


  Cranking_Fuel:
2754: 73,62,46,33,23,1b,14,12,10,0d,09,09  table 115, 98, 70, 51, 35, 27, 20, 18, 16, 13,  9,  9 # 0 secs
2760: 73,62,3b,2b,1b,0f,0e,0c,0b,09,07,07  table 115, 98, 59, 43, 27, 15, 14, 12, 11,  9,  7,  7 # 3 secs
276c: 04,62,3b,27,13,0f,0a,08,07,06,06,06  table   4, 98, 59, 39, 19, 15, 10,  8,  7,  6,  6,  6 # 6 secs
2778: 00,5c,35,21,11,0d,09,07,06,06,06,06  table   0, 92, 53, 33, 17, 13,  9,  7,  6,  6,  6,  6 # 9 secs
2784: 23,48,27,1b,10,0b,08,07,06,06,06,06  table  35, 72, 39, 27, 16, 11,  8,  7,  6,  6,  6,  6 #12 secs
2790: 5c,33,27,14,0e,0a,08,07,06,06,06,06  table  92, 51, 39, 20, 14, 10,  8,  7,  6,  6,  6,  6 #15 secs or more

##########################################################
# Injector Slope lookup. lookup via battery Voltage). O/P Value is added to inject time calc
# scaled 0-32768 = 0-125ms.
##########################################################


  Inj_slope:
279c: ff,ff,4f,00  func         65535,   79
27a0: 00,88,4f,00  func         34816,   79                                        # 0.3   mS
27a4: 00,68,e1,00  func         26624,  225                                        # 0.858 mS
27a8: 00,50,b1,01  func         20480,  433                                        # 1.65  mS
27ac: 00,38,ca,03  func         14336,  970
27b0: 00,00,ca,03  func             0,  970                                        # 3.7   mS

##########################################################
##  next two tables used with Timer2 - Accel Pump ? ########
# used if Timer2 < LU8 lookup
# LU7 as multiplier LU8 as divider/time frame (secs) - code ~ 3605
# could be fading enrich for 'n' secs ....
# 'Base' scale appears to be 16384 ... (128 x 128 ...)
##########################################################


  ECT_Mult_temp:
27b4: 7f,0a  func                127,  10
27b6: 1e,0a  func                 30,  10                                          # 60C Hot
27b8: 19,0d  func                 25,  13
27ba: 0a,10  func                 10,  16
27bc: 00,1a  func                  0,  26                                          # 0C
27be: fb,22  func                 -5,  34
27c0: f6,30  func                -10,  48                                          # -20C Cold
27c2: 80,30  func               -128,  48
27c4: 80,30  func               -128,  48
27c6: 80,30  func               -128,  48
27c8: 80,30  func               -128,  48
27ca: 80,30  func               -128,  48

######### ECT to timer ########
# Output Value is SECONDS used against Timer 2
# some kind of enrichment applied if less than time below in secs (3605)
#################


  ECT_Time_temp:
27cc: 7f,0a  func                127,  10
27ce: 18,0a  func                 24,  10                                          # 48C Hot
27d0: 0a,19  func                 10,  25
27d2: f6,3c  func                -10,  60                                          # -20C Cold
27d4: 80,3c  func               -128,  60
27d6: 80,3c  func               -128,  60

####################################
# Accel pump lookup, ECT modifier
# IN ECT Value
# OUT multiplier factor
# Linked to Accel pump multiplier (2802, below) for Accel Pump Calc
###################################################


  ECT_Accel_LU:
27d8: 7f,13  func                127,  19
27da: 26,13  func                 38,  19                                          # 76C Hot
27dc: 1e,25  func                 30,  37
27de: 12,4d  func                 18,  77
27e0: 0d,7f  func                 13, 127                                          # 26C Cold
27e2: 80,7f  func               -128, 127

###################################
# Coarse VAF Transfer
# IN - Top byte of VAF Raw (VAF/256).
# OUT - multiplier ? used with accel lookup below
###################################


  VAF_Coarse_TFR:
27e4: ff,05  func               255,  5
27e6: eb,05  func               235,  5
27e8: da,08  func               218,  8
27ea: ab,15  func               171, 21
27ec: 9c,1b  func               156, 27
27ee: 89,26  func               137, 38
27f0: 74,34  func               116, 52
27f2: 62,44  func                98, 68
27f4: 50,59  func                80, 89
27f6: 46,66  func                70,102
27f8: 3a,7a  func                58,122
27fa: 2b,9a  func                43,154
27fc: 1e,ba  func                30,186
27fe: 0d,ff  func                13,255
2800: 00,ff  func                 0,255

###############################
# Accel pump multiplier [Fixed value ?]
# IN - VAF coarse (Reversed though = 256 - R3c (code at 3850) 
# OUT - FIXED at 131 ?
# then mulitplied by ECT (block temp) lookup (at 3867)
###################################


  Accel_LU:
2802: ff,83  func               255,131
2804: 00,83  func                 0,131
2806: 00,83  func                 0,131
2808: 00,83  func                 0,131
280a: 00,83  func                 0,131

280c: ff,20,00,00,00,00,00,00 ??                                                   # Separate Table ? Not used anywhere

2814: 00                  byte    0

2815: 00,00,00                  

###############################
# Coldstart Strategy time ? Used with ECT_Start value
# output is secs. Affects ISC (1200/1430 rpm) and EGR (to fixed PW)
##########################################################


  ECT_Coldstart_Time:
2818: ff,7f,00,00  func          32767,     0
281c: 28,00,00,00  func             40,     0                                      # Hot, 0 mins >= 80C
2820: 12,00,f0,00  func             18,   240
2824: 08,00,f0,00  func              8,   240                                      # 16C, 4 mins
2828: 05,00,f4,01  func              5,   500                                      # <=10C, 8.3 mins
282c: ec,ff,08,02  func            -20,   520
2830: 00,80,08,02  func         -32768,   520
2834: 00,80,08,02  func         -32768,   520                                      # Cold. 8.6 mins

#### ECT (block temp) Scaler #####


  ECT_SCALE_11:
2838: ff,7f,00,0b  func          32767,  2816                                      # Hot - scaled in with byte in TOP
283c: 00,4b,00,0b  func          19200,  2816
2840: 00,23,00,0a  func           8960,  2560                                      # default return is 10 (70 - 150C)
2844: 00,1e,00,09  func           7680,  2304
2848: 80,16,00,08  func           5760,  2048
284c: 80,ee,00,00  func          -4480,     0
2850: 00,80,00,00  func         -32768,     0
2854: 00,80,00,00  func         -32768,     0                                      # Cold
##### RPM scaler ##############


  RPM_SCALE_10:
2858: ff,ff,00,0a  func         65535, 2560
285c: c0,5d,00,0a  func         24000, 2560                                        # 8=4000, 9=5000, 10=6000 & up
2860: 80,3e,00,08  func         16000, 2048                                        # 5=2500, 6=3000, 7=3500
2864: 40,1f,00,04  func          8000, 1024                                        # 2=1300, 3=1600, 4=2000
2868: 00,19,00,03  func          6400,  768                                        # 0=0-700, 1=1000,
286c: f0,0a,00,00  func          2800,    0
2870: 00,00,00,00  func             0,    0

##### Flow scaler (cylinder) ######
# Linear scale over small number range.  Is this full range of flow ?.


  FLOW_SCALE_10:
2874: ff,ff,00,0a  func         65535, 2560
2878: a1,14,00,0a  func          5281, 2560
287c: c5,02,00,00  func           709,    0
2880: 00,00,00,00  func             0,    0

###########


  ECT_SCALE_7:
2884: ff,7f,00,07  func          32767,  1792                                      # Hot
2888: 00,28,00,07  func          10240,  1792                                      # default return is 7 (in 50)
288c: 00,23,00,06  func           8960,  1536
2890: 00,0a,00,05  func           2560,  1280
2894: 00,00,00,04  func              0,  1024
2898: 00,ec,00,00  func          -5120,     0
289c: 00,80,00,00  func         -32768,     0                                      # Cold

#### Flow Scaler 2 ###########
# Enrichment FLOW scaler used with 2531 when ECT cold => choke
# This is identical calibration to 2874 to half of scale then cuts off


  FLOW_SCALE_5:
28a0: ff,ff,00,05  func         65535, 1280
28a4: b3,0b,00,05  func          2995, 1280
28a8: c5,02,00,00  func           709,    0
28ac: 00,00,00,00  func             0,    0

## ACT temp interpolate - for IGN HOT and COLD tables. in = ACT , OUT 0(hot) - 128 (cold)


  Ign_Interp:
28b0: ff,7f,00,00  func          32767,     0                                      # Hot
28b4: 17,00,00,00  func             23,     0
28b8: 0d,00,80,00  func             13,   128                                      # full swopover between 26C and 46C
28bc: 00,80,80,00  func         -32768,   128                                      # Cold


  Vss_TFR:
28c0: ff,ff,00,c8  func         65535,51200                                        # Linear transfer as proportion of Battery voltage
28c4: 00,ed,00,c8  func         60672,51200
28c8: 00,00,00,00  func             0,    0

#####################################################
# VAF Transfer.  Input scaled to Volts.
# Output may be scaled at 32768 = 2800L/min ?
#####################################################


  VAF_TFR:
28cc: ff,ff,63,5a  func         65535,23139
28d0: 00,eb,63,5a  func         60160,23139
28d4: 00,ea,b1,53  func         59904,21425
28d8: 40,e4,ba,44  func         58432,17594
28dc: 80,d9,45,39  func         55680,14661
28e0: c0,c4,17,28  func         50368,10263
28e4: 00,b1,a3,1c  func         45312, 7331
28e8: 40,9c,0c,14  func         40000, 5132
28ec: 80,88,52,0e  func         34944, 3666
28f0: 80,7b,74,0b  func         31616, 2932
28f4: c0,6a,97,08  func         27328, 2199
28f8: c0,58,4d,06  func         22720, 1613
28fc: 40,46,94,04  func         17984, 1172
2900: 00,3a,b8,03  func         14848,  952
2904: c0,2a,dd,02  func         10944,  733
2908: c0,1d,4a,02  func          7616,  586
290c: c0,0c,b8,01  func          3264,  440
2910: 00,00,00,00  func             0,    0
2914: 00,00,00,00  func             0,    0

#############################################################
# ECT Transfer - Upper byte used for scale funcs and table lookup
# input scaled to volts, output to degrees C
##########################################################


  ECT_TFR:
2918: ff,7f,00,ec  func          32767, -5120
291c: e0,73,00,ec  func          29664, -5120
2920: e0,71,00,f1  func          29152, -3840
2924: c0,6e,00,f6  func          28352, -2560
2928: e0,69,00,fb  func          27104, -1280
292c: 00,63,00,00  func          25344,     0
2930: 00,5a,00,05  func          23040,  1280
2934: 00,4f,00,0a  func          20224,  2560
2938: 20,43,00,0f  func          17184,  3840
293c: 20,37,00,14  func          14112,  5120
2940: 00,2c,00,19  func          11264,  6400
2944: 60,22,00,1e  func           8800,  7680
2948: 80,1a,00,23  func           6784,  8960
294c: 40,14,00,28  func           5184, 10240
2950: 80,0f,00,2d  func           3968, 11520
2954: e0,0b,00,32  func           3040, 12800                                      # ECT default value (std normal hot)
2958: 20,09,00,37  func           2336, 14080
295c: 00,07,00,3c  func           1792, 15360
2960: 80,05,00,41  func           1408, 16640
2964: 60,03,00,4b  func            864, 19200
2968: 00,80,00,4b  func         -32768, 19200

#####################################################
# ACT (VAT) Transfer - Upper byte used for later scale and table lookup
# Input scaled to volts, output to degrees C
##########################################################


  ACT_TFR:
296c: ff,7f,00,ec  func          32767, -5120
2970: 30,73,00,ec  func          29488, -5120
2974: d3,70,00,f1  func          28883, -3840
2978: 3d,6d,00,f6  func          27965, -2560
297c: 1d,68,00,fb  func          26653, -1280
2980: 33,61,00,00  func          24883,     0
2984: 86,58,00,05  func          22662,  1280
2988: 80,4e,00,0a  func          20096,  2560                                      # ACT default value (std temp 20C)
298c: c3,43,00,0f  func          17347,  3840
2990: 0a,39,00,14  func          14602,  5120
2994: ea,2e,00,19  func          12010,  6400
2998: 03,26,00,1e  func           9731,  7680
299c: 7d,1e,00,23  func           7805,  8960
29a0: 43,18,00,28  func           6211, 10240
29a4: 4d,13,00,2d  func           4941, 11520
29a8: 46,0f,00,32  func           3910, 12800
29ac: d6,0b,00,37  func           3030, 14080
29b0: c3,09,00,3c  func           2499, 15360
29b4: d6,07,00,41  func           2006, 16640
29b8: 00,00,00,7f  func              0, 32512                                      # very HOT !!
29bc: 00,80,00,7f  func         -32768, 32512

##################################################################
# Air Density compensation - applied after raw air density calculation
# of Pressure/Temp.  Reduces high pressure multipliers and increases
# low pressure from mid point (1.2).
# This is probably a version of the flow/drag equation, i.e.
# force on flap proportional to velocity squared (=volume)*density
# May also include other VE scavenging aspects against density
#####################################################################


  Air_Density:
29c0: ff,ff,fd,ff  func         65535,65533                                        # high density, reduce sensor reading
29c4: ad,af,11,d4  func         44973,54289
29c8: 5c,8f,92,bf  func         36700,49042
29cc: 66,66,e8,a1  func         26214,41448                                        # default = 1.2
29d0: 33,33,7c,72  func         13107,29308
29d4: 7b,14,69,48  func          5243,18537
29d8: 3d,0a,32,33  func          2621,13106
29dc: 1f,05,6a,24  func          1311, 9322                                        # low density, increase sensor reading
29e0: 06,01,3c,12  func           262, 4668
29e4: 00,00,00,00  func             0,    0

#################################################
# idle speed versus ECT - added into calculation 
#################################################


  IDLE_ECT:
29e8: ff,7f,48,0d  func          32767,  3400                                      # 850  rpm - Hot, > 76 C
29ec: 26,00,48,0d  func             38,  3400
29f0: 00,00,30,11  func              0,  4400                                      # 1100 rpm
29f4: ec,ff,50,14  func            -20,  5200
29f8: 00,80,50,14  func         -32768,  5200                                      # 1300 rpm - Cold -40C

#####################################################
### Pulsewidth adjustment for ISC Valve - used as multiplier in code
# appears to be +/- 25rpm resolution , 50 rpm deadband
# Scaled /65536 (2621 = 0.04, 1835 = 0.028, 52 = 0.008 )
##########################################################


  ISCxRPM:
29fc: ff,7f,c3,f5  func          32767, -2621
2a00: f0,0a,c3,f5  func           2800, -2621
2a04: d0,07,d5,f8  func           2000, -1835
2a08: c8,00,cc,ff  func            200,   -52
2a0c: 64,00,00,00  func            100,     0
2a10: 9c,ff,00,00  func           -100,     0
2a14: 38,ff,34,00  func           -200,    52
2a18: 30,f8,3d,0a  func          -2000,  2621
2a1c: 00,80,3d,0a  func         -32768,  2621
2a20: 00,80,3d,0a  func         -32768,  2621

######################################################
# with above ISC table - ECT in , multiplied with ISC table ...result scaled in 32 bits and then div 65536
# for 0-65536 and rescaled via ISC_PW_TFR below. (after some adjustments)
# effectively governs rate of change by RPMxECT, max 0.25%, min 0.1%
# at 1638 multiply gives 52 => 1.3 (0.002%),    1835 => 45.86,    2621 => 65.5 (1%)
# at 4096 multiply gives 52 => 3.25 (0.005%), 1835 => 114.6875, 2621 => 163.8125 (2.5%)
######################################################


  ECT_LU2:
2a24: ff,7f,00,10  func          32767,  4096                                      # Hot and default (100C)
2a28: 26,00,00,10  func             38,  4096
2a2c: 20,00,66,06  func             32,  1638                                      # Swops between 64 and 76 C
2a30: 00,80,66,06  func         -32768,  1638
2a34: 00,80,66,06  func         -32768,  1638
2a38: 00,80,66,06  func         -32768,  1638                                      # Cold

######################################################
# ISC Pulsewidth Transfer
# may be solenoid lag/slope adjustment ? looks like quadratic curve.
# OUTPUT scaled as 0-32768 = 0 - 6.25mS. Input 0-32767 ? 3277 min...
######################################################


  ISC_Slope:
2a3c: ff,ff,00,80  func         65535,32768
2a40: 33,73,00,80  func         29491,32768                                        # 100% 6.25 mS  90% and up
2a44: 66,66,3d,6a  func         26214,27197                                        # 83%  5.1875   80%
2a48: 9a,59,0a,57  func         22938,22282                                        # 68%  4.25     70%
2a4c: cd,4c,5c,4f  func         19661,20316                                        # 60%  3.875    60%
2a50: 00,40,66,46  func         16384,18022                                        # 55%  3.4375   50%
2a54: 33,33,b8,3e  func         13107,16056                                        # 49%  3.0625   40%
2a58: 66,26,c3,35  func          9830,13763                                        # 42%  2.625    30%
2a5c: 9a,19,a4,30  func          6554,12452                                        # 38%  2.375    20% (19% for 10% ?)
2a60: 00,00,00,00  func             0,    0

######################################################
# ISC Pulsewidth lookup against Filtered RPM scaled 0-32768 = 6.25mS
######################################################


  ISC_RPM_2:
2a64: ff,ff,33,33  func         65535,13107                                        # 40% = 2.5mS
2a68: 58,16,33,33  func          5720,13107
2a6c: 30,11,3d,2a  func          4400,10813                                        # 33% = 2.0625mS
2a70: 00,00,3d,2a  func             0,10813
2a74: 00,00,3d,2a  func             0,10813
2a78: 00,00,3d,2a  func             0,10813

# ISC Pulsewidth lookup against ECT - used directly if TPS fail


  ISC_Start_PW:
2a7c: ff,7f,29,1c  func          32767,  7209                                      # Hot (22% = 1.375mS)
2a80: 28,00,29,1c  func             40,  7209
2a84: 1e,00,00,20  func             30,  8192                                      # 25% (1.5625mS)
2a88: f6,ff,cd,4c  func            -10, 19661                                      # 60% (3.75mS)
2a8c: f1,ff,33,73  func            -15, 29491
2a90: 00,80,33,73  func         -32768, 29491                                      # Cold (90% 5.625mS)

# Lookups for EGR (not used here) against ECT and ACT (as multipliers to PW table)
# and scalers below them (flow and RPM, both 0-7)


  EGR_ECT:
2a94: 7f,40  func                127,  64
2a96: 80,40  func               -128,  64
2a98: 80,40  func               -128,  64
2a9a: 80,40  func               -128,  64
2a9c: 80,40  func               -128,  64


  EGR_ACT:
2a9e: 7f,40  func                127,  64
2aa0: 80,40  func               -128,  64
2aa2: 80,40  func               -128,  64
2aa4: 80,40  func               -128,  64
2aa6: 80,40  func               -128,  64


  RPM_SCALE_7:
2aa8: ff,ff,00,07  func         65535, 1792
2aac: c0,5d,00,07  func         24000, 1792
2ab0: f0,0a,00,00  func          2800,    0
2ab4: 00,00,00,00  func             0,    0
2ab8: 00,00,00,00  func             0,    0


  FLOW_SCALE_7:
2abc: ff,ff,00,07  func         65535, 1792
2ac0: d7,12,00,07  func          4823, 1792
2ac4: 00,00,00,00  func             0,    0
2ac8: 00,00,00,00  func             0,    0
2acc: 00,00,00,00  func             0,    0

## Cranking Scaler (Timer 0).    Linear. mSecs IN. Cranking Time    Linear 0-15 secs for 0-5 scale
## against Crank Fuel table (2754)


  SCALE_CrankTime:
2ad0: ff,ff,00,05  func         65535, 1280
2ad4: 98,3a,00,05  func         15000, 1280
2ad8: 00,00,00,00  func             0,    0

# BAP convertor to air pressure. Input range is 44800 - 30720 (175Hz - 120Hz)
# Book indicates range 80-160 Hz for 0-1 atmo. 159 Hz => default = 239 (1 atmo)
# looks like this is inches Hg * 8 (240 = 30 in Hg => 29.92, 239 = 29.875)


  BAP_TFR:
2adc: ff,ff,f8,00  func         65535,  248
2ae0: 5a,a2,f8,00  func         41562,  248                                        # 162.7 Hz [1.033] (1.037 atmo 31 in Hg)
2ae4: 46,8a,b8,00  func         35398,  184                                        # 138.3 Hz [0.766] (0.7 atmo = 23 in Hg)
2ae8: cc,74,78,00  func         29900,  120                                        # 116.8 Hz [0.5]   (0.5 atmo = 15 in Hg)
2aec: 00,00,78,00  func             0,  120

## RPM lookup for Cranking.    Used as multiplier of Crank fuel table ###


  RPM_Crank_LU:
2af0: ff,ff,50,00  func         65535,   80
2af4: d0,07,50,00  func          2000,   80
2af8: 40,06,60,00  func          1600,   96
2afc: b0,04,80,00  func          1200,  128
2b00: 00,00,80,00  func             0,  128

# lookup against ECT if timer below threshold  RPM value subtracted from ISC calculation
# effective change range -40 through 20C.


  NDS_IDLE_CHANGE:
2b04: ff,7f,20,03  func          32767,   800                                      # Hot
2b08: 0a,00,20,03  func             10,   800
2b0c: ec,ff,40,06  func            -20,  1600
2b10: 00,80,40,06  func         -32768,  1600
2b14: 00,80,40,06  func         -32768,  1600
2b18: 00,80,40,06  func         -32768,  1600                                      # Cold


#############################################
# Physical output routine - called only from HS_OUT routine
# Rb8  - time reqd
# R3e  - Event state and channel
# R3a  - Event time reqd from now, NEGATED if time is left
# Auto delay to 200uS from now if less than 200uS left.
# set carry if delayed Output, cleared otherwise
# Rb8 as return par, TRUE start time of event.
#############################################


  HSOUT:
2b1c: de,04               jlt   2b22             if (HSO_Flags < 0) goto 2b22;     # is really    if (R3a < 0)
2b1e: dd,04               jv    2b24             if (OVF = 1) goto Out_Now;
2b20: 20,15               sjmp  2b37             goto Out_Dly;
2b22: dd,13               jv    2b37             if (OVF = 0)  {

  Out_Now:
2b24: fa                  di                     disable ints;
2b25: ff                  nop                    
2b26: 03,3a               negw  R3a              R3a = -R3a;                       # make positive value
2b28: 89,2a,00,3a         cmpw  R3a,2a                                             # check at least 200uS to go
2b2c: d3,09               jnc   2b37             if ((uns) R3a >= 2a)  {           # OK - use orig time
2b2e: a0,b8,0e            ldw   Re,Rb8           HSO_Time = Rb8;
2b31: b0,3e,0d            ldb   Rd,R3e           HSO_Cmd = R3e;
2b34: f8                  clc                    CY = 0
2b35: 20,0e               sjmp  2b45             goto Exit; } }

  Out_Dly:
2b37: fa                  di                     disable ints;
2b38: ff                  nop                    
2b39: 45,2a,00,06,b8      ad3w  Rb8,R6,2a        Rb8 = IO_Timer + 2a;              # add 200 uS to event time
2b3e: a0,b8,0e            ldw   Re,Rb8           HSO_Time = Rb8;
2b41: b0,3e,0d            ldb   Rd,R3e           HSO_Cmd = R3e;
2b44: f9                  stc                    CY = 1

  Exit:
2b45: fb                  ei                     enable ints;
2b46: f0                  ret                    return;

#######################
# Increment total Injection time for trip computer (shares STO output)
# input - R32 = ACTUAL Inject time - in 'ticks' (of 4.8 uS)
# Called separately for each bank,
# 15c (as double word) = Cumulative inject time in ticks for both banks since last trip Output.
# This is recalculated in Trip_calc (3947). 
######################


  Inc_Injtime:
2b47: 4d,74,cb,50,38      ml3w  R38,R50,cb74     R38 = Inj_slope * cb74;
2b4c: 68,3a,32            sb2w  R32,R3a          R32 -= R3a;                       # remove Inject Slope compensation
2b4f: 67,01,5c,01,32      ad2w  R32,[R0+15c]     R32 += Tot_Inj_L;
2b54: a3,01,5e,01,34      ldw   R34,[R0+15e]     R34 = Tot_Inj_H;
2b59: a4,00,34            adcw  R34,R0           R34 += CY;                        # is a 32 bit addition
2b5c: c3,01,5e,01,34      stw   R34,[R0+15e]     Tot_Inj_H = R34;
2b61: c3,01,5c,01,32      stw   R32,[R0+15c]     Tot_Inj_L = R32;                  # save new inject time
2b66: f0                  ret                    return;

##########################################################
# TRIP Output - for trip computer - single event.
# 50% duty cycle as ON and OFF are the same value
# for fast frequencies uses double event version at 235f
# swops over at approx. half scale (0x4000)
##########################################################



  Do_Trip_Single:
2b67: a0,76,34            ldw   R34,R76          R34 = TRIP_PW_Time;
2b6a: a1,78,00,3c         ldw   R3c,78           R3c = 78;                         # -> = TRIP_Time
2b6e: b1,c0,b2            ldb   Rb2,c0           HSO_Flags = c0;                   # O/P time = TRIP_PW_Time+TRIP_Time - single event
2b71: b1,39,ba            ldb   Rba,39           Rba = 39;
2b74: 32,b3,03            jnb   B2,Rb3,2b7a      if (Trip_state = 1)  {
2b77: b1,29,ba            ldb   Rba,29           Rba = 29; }                       # set reqd TRIP state + interrupt
2b7a: ef,18,f8            call  2395             Do_OUTPUT();
2b7d: 38,b2,09            jb    B0,Rb2,2b89      if (HSO_BUSY = 1) return;
2b80: a0,30,78            ldw   R78,R30          TRIP_Time = R30;
2b83: 71,bf,b4            an2b  Rb4,bf           DOL_rqd = 0;
2b86: 95,04,b3            xorb  Rb3,4            Trip_state ^= 1; }                # flip (save) TRIP state
2b89: f0                  ret                    return;

##########################################################
# STO Output
# A straight follow of STO_REQD bit to output line.
# stops output if STI not active/dropped.
##########################################################


  STO_OUT:
2b8a: 33,5a,08            jnb   B3,R5a,2b95      if (STO_Reqd = 0) goto 2b95;
2b8d: 3e,b3,16            jb    B6,Rb3,2ba6      if (STO_state = 0)  {
2b90: b1,19,ba            ldb   Rba,19           Rba = 19;
2b93: 20,06               sjmp  2b9b             goto 2b9b;
2b95: 36,b3,0e            jnb   B6,Rb3,2ba6      if (STO_state = 0) return;
2b98: b1,09,ba            ldb   Rba,9            Rba = 9;
2b9b: 11,b2               clrb  Rb2              HSO_Flags = 0;                    # STO off - immediate
2b9d: ef,f5,f7            call  2395             Do_OUTPUT();
2ba0: 38,b2,03            jb    B0,Rb2,2ba6      if (HSO_BUSY = 1) return;
2ba3: 95,40,b3            xorb  Rb3,40           STO_state ^= 1; }                 # flip (keep) STO state
2ba6: f0                  ret                    return;


  Do_subTaskList:
2ba7: 65,02,00,98         ad2w  R98,2            SubTaskNum += 2;
2bab: 89,32,00,98         cmpw  R98,32           
2baf: d3,02               jnc   2bb3             if ((uns) SubTaskNum >= 32)  {
2bb1: 01,98               clrw  R98              SubTaskNum = 0; }
2bb3: cb,99,9a,3f         push  [R98+3f9a]       push([SubTaskNum+SubTaskList]);
2bb7: f0                  ret                    return;

##############################
# Common return point for many subroutines (2170 = 'ret')
# probably for cal con monitoring ?
############################### 


  Main_EXIT:
2bb8: e7,b5,f5            jump  2170             return;

#################################################
# Do_ISC    Idle control valve driver
# R30 (PulseWidth length) calibrated as 328-32768 = ~0 - 6.25mS
# which is then subtracted from 6.25mS
# to get 1-100% duty cycle at 160hz
#
# 'off' = last event time + scaled R34 (Idle_PW)
# 'on'  = 6.25ms - scaled R34.
####################################################

  Do_ISC_OUT:
2bbb: 34,b3,16            jnb   B4,Rb3,2bd4      if (ISC_off = 0) goto 2bd4;       # NEVER set ?, always jumps
2bbe: 35,b3,66            jnb   B5,Rb3,2c27      if (ISC_state = 1)  {
2bc1: 11,b2               clrb  Rb2              HSO_Flags = 0;
2bc3: b1,08,ba            ldb   Rba,8            Rba = 8;                          # IDL off - immediate
2bc6: ef,cc,f7            call  2395             Do_OUTPUT();
2bc9: 38,b2,5b            jb    B0,Rb2,2c27      if (HSO_BUSY = 1) return;
2bcc: a0,30,2e            ldw   R2e,R30          Last_ISC_Time = R30;
2bcf: 71,df,b3            an2b  Rb3,df           ISC_state = 0;
2bd2: 20,53               sjmp  2c27             return;
2bd4: a3,01,30,01,30      ldw   R30,[R0+130]     R30 = ISC_PW_Final;
2bd9: 89,00,80,30         cmpw  R30,8000         
2bdd: d1,04               jleu  2be3             if ((uns) R30 > 8000 )  {
2bdf: a1,00,80,30         ldw   R30,8000         R30 = 8000; }
2be3: 89,48,01,30         cmpw  R30,148          
2be7: db,04               jc    2bed             if (R30 > 148)  {
2be9: a1,48,01,30         ldw   R30,148          R30 = TPS_Interval; }             # force 328 <= R30 <= 32768
2bed: a3,01,66,24,ba      ldw   Rba,[R0+2466]    Rba = ISC_Freq;                   # 1302*4.8uS = 6.25ms
2bf2: 09,01,ba            shlw  Rba,1            Rba *= 2;
2bf5: 6c,ba,30            ml2w  R30,Rba          R30 *= Rba;
2bf8: a0,32,34            ldw   R34,R32          R34 = R32;                        # R34 = ISC_PW*6.25/32768
2bfb: a3,01,66,24,30      ldw   R30,[R0+2466]    R30 = ISC_Freq;
2c00: 48,32,30,36         sb3w  R36,R30,R32      R36 = R30 - R32;                  # this is remainder, 6.25mS - R34
2c04: db,05               jc    2c0b             if (R36 > 0)  {
2c06: a3,01,66,24,36      ldw   R36,[R0+2466]    R36 = ISC_Freq; }
2c0b: a1,2e,00,3c         ldw   R3c,2e           R3c = 2e;                         # -> Last_ISC_Time
2c0f: b1,80,b2            ldb   Rb2,80           HSO_Flags = 80;
2c12: b1,08,ba            ldb   Rba,8            Rba = 8;
2c15: b1,38,bb            ldb   Rbb,38           Rbb = 38;                         # 2 events: off, then on with interrupt
2c18: ef,7a,f7            call  2395             Do_OUTPUT();
2c1b: 38,b2,09            jb    B0,Rb2,2c27      if (HSO_BUSY = 1) return;
2c1e: a0,32,2e            ldw   R2e,R32          Last_ISC_Time = R32;
2c21: 71,7f,b4            an2b  Rb4,7f           ISC_rqd = 0;
2c24: 71,df,b3            an2b  Rb3,df           ISC_state = 0; }
2c27: f0                  ret                    return;

################################################
# Do_EGR    EGR control is not fitted in this vehicle.
# EGR_Present [2458] is zero.
# Calc below R32 is time in ticks, so R32 = R36*208c/65536
# seems EGR_PW is scaled as 0-32768 = 0-20mS
# limited in calc (3f93) to 16384 max (10 mS) ON,
# which defines 30ms OFF, or 25% open ?
################################################


  Do_EGR_OUT:
2c28: 9b,01,58,24,00      cmpb  R0,[R0+2458]     
2c2d: df,70               je    2c9f             if (0 != EGR_Present)  {
2c2f: 8b,01,42,01,06      cmpw  R6,[R0+142]      
2c34: de,04               jlt   2c3a             if (IO_Timer >= EGR_Last_time)  {
2c36: dd,67               jv    2c9f             if (OVF = 1) return;
2c38: 20,02               sjmp  2c3c             goto 2c3c; }
2c3a: d5,63               jnv   2c9f             if (OVF = 0) return;
2c3c: a3,01,40,01,36      ldw   R36,[R0+140]     R36 = EGR_PW;
2c41: 4d,8c,20,36,30      ml3w  R30,R36,208c     R30 = R36 * 208c;                 # 40 mSec 'ticks'
2c46: 3b,b3,23            jb    B3,Rb3,2c6c      if (EGR_State = 1) goto 2c6c;
2c49: 8b,01,5c,24,36      cmpw  R36,[R0+245c]    
2c4e: d9,07               jgtu  2c57             if ((uns) R36 <= EGR_LIM1)  {
2c50: c3,01,42,01,06      stw   R6,[R0+142]      EGR_Last_time = IO_Timer;
2c55: 20,48               sjmp  2c9f             return; }
2c57: 69,23,08,32         sb2w  R32,823          R32 -= 823;                       # Rounding ?
2c5b: 03,32               negw  R32              R32 = -R32;                       # negate to get 65536-x 'inverse'
2c5d: b1,10,ba            ldb   Rba,10           Rba = 10;                         # Ch0 (or 1) ON
2c60: 9b,01,78,24,00      cmpb  R0,[R0+2478]     
2c65: df,20               je    2c87             if (0 != EGR_chan)  {
2c67: b1,11,ba            ldb   Rba,11           Rba = 11;
2c6a: 20,1b               sjmp  2c87             goto 2c87;
2c6c: 8b,01,5e,24,36      cmpw  R36,[R0+245e]    
2c71: d3,07               jnc   2c7a             if ((uns) R36 >= EGR_lim2)  {
2c73: c3,01,42,01,06      stw   R6,[R0+142]      EGR_Last_time = IO_Timer;
2c78: 20,25               sjmp  2c9f             return; }
2c7a: b1,00,ba            ldb   Rba,0            Rba = 0;                          # ch0 (or 1) OFF
2c7d: 9b,01,78,24,00      cmpb  R0,[R0+2478]     
2c82: df,03               je    2c87             if (0 != EGR_chan)  {
2c84: b1,01,ba            ldb   Rba,1            Rba = 1; } }

# do event, on or off at time R34

2c87: a1,42,01,3c         ldw   R3c,142          R3c = EGR_Last_time;
2c8b: a0,32,34            ldw   R34,R32          R34 = R32;
2c8e: b1,c0,b2            ldb   Rb2,c0           HSO_Flags = c0;                   # Single event EGR_last + R34
2c91: ef,01,f7            call  2395             Do_OUTPUT();
2c94: 38,b2,08            jb    B0,Rb2,2c9f      if (HSO_BUSY = 1) return;
2c97: c3,01,42,01,30      stw   R30,[R0+142]     EGR_Last_time = R30;
2c9c: 95,08,b3            xorb  Rb3,8            EGR_State ^= 1; }                 # flip (save) EGR_state
2c9f: f0                  ret                    return;

################################################
# Timer overflow interrupt handler
# Occurs every 0.31 secs (4.8 uS * 65536)
################################################


  I_Timer_OVF:
2ca0: f2                  pushp                  push(PSW);
2ca1: 07,12               incw  R12              T_OVF_CNT++;                      # R12 not used anywhere else
2ca3: d7,03               jne   2ca8             if (T_OVF_CNT = 0)  {
2ca5: 91,01,b5            orb   Rb5,1            TimerOVF = 1; }                   # set after 5 hrs 43 mins elapsed, not used
2ca8: 17,55               incb  R55              FPUMP_Ticks++;                    # Fuel pump timeout (3 ticks = 1 sec, (refer 39c2)
2caa: d7,02               jne   2cae             if (FPUMP_Ticks = 0)  {
2cac: 15,55               decb  R55              FPUMP_Ticks--; }
2cae: fa                  di                     disable ints;
2caf: ff                  nop                    
2cb0: f3                  popp                   PSW = pop();
2cb1: f1                  reti                   return;

####### Dummy Interrupt Handler ###########


  I_Ignore:
2cb2: f1                  reti                   return;

####### High Speed Data IN Handler ###########


  I_HSI_Data:
2cb3: f2                  pushp                  push(PSW);
2cb4: fa                  di                     disable ints;
2cb5: ff                  nop                    
2cb6: a0,0e,4c            ldw   R4c,Re           R4c = HSI_Time;
2cb9: b0,0d,a8            ldb   Ra8,Rd           New_HSI = HSI_Data;
2cbc: b0,a8,4b            ldb   R4b,Ra8          This_HSI = New_HSI;
2cbf: fb                  ei                     enable ints;
2cc0: 94,54,a8            xorb  Ra8,R54          New_HSI ^= Last_HSI;              # only interested in state changes
2cc3: b0,4b,54            ldb   R54,R4b          Last_HSI = This_HSI;              # PREV_HSI = THIS HSI before compare ...

  Do_Next_HSI:
2cc6: 38,a8,3b            jb    B0,Ra8,2d04      if (New_PIP = 0)  {               # Not Spark, check others
2cc9: 3a,a8,19            jb    B2,Ra8,2ce5      if (New_BAP = 1) goto 2ce5;       # BAP - handler is here, optional fitment.
2ccc: 3b,a8,11            jb    B3,Ra8,2ce0      if (New_STI = 1) goto 2ce0;       # Ignore (see main loop)
2ccf: 3c,a8,28            jb    B4,Ra8,2cfa      if (B4_New_HSI = 1) goto Ignore_SB4; # Ignore
2cd2: 3d,a8,2a            jb    B5,Ra8,2cff      if (New_IDL = 1) goto 2cff;       # Ignore (see main loop)
2cd5: 11,a8               clrb  Ra8              New_HSI = 0;

  Check_Next_HSI:
2cd7: 99,00,a8            cmpb  Ra8,0            
2cda: d7,ea               jne   2cc6             if (New_HSI != 0) goto Do_Next_HSI;
2cdc: fa                  di                     disable ints;
2cdd: ff                  nop                    
2cde: f3                  popp                   PSW = pop();
2cdf: f1                  reti                   return;


  Ignore_STI:
2ce0: 71,35,a8            an2b  Ra8,35           B1_New_HSI = 0;
                                                 New_STI = 0;
                                                 B6_New_HSI = 0;
                                                 B7_New_HSI = 0;
2ce3: 27,f2               sjmp  2cd7             goto Check_Next_HSI;

  BAP_Int:
2ce5: 4b,01,52,01,4c,4a   sb3w  R4a,R4c,[R0+152] R4a = R4c+Last_BAP;               # no high/low tracked, interval = 1/2 cycle of freq
2ceb: c3,01,52,01,4c      stw   R4c,[R0+152]     Last_BAP = R4c;
2cf0: c3,01,54,01,4a      stw   R4a,[R0+154]     BAP_Interval = R4a;
2cf5: 71,39,a8            an2b  Ra8,39           B1_New_HSI = 0;
                                                 New_BAP = 0;
                                                 B6_New_HSI = 0;
                                                 B7_New_HSI = 0;
2cf8: 27,dd               sjmp  2cd7             goto Check_Next_HSI;

  Ignore_SB4:
2cfa: 71,2d,a8            an2b  Ra8,2d           B1_New_HSI = 0;
                                                 B4_New_HSI = 0;
                                                 B6_New_HSI = 0;
                                                 B7_New_HSI = 0;
2cfd: 27,d8               sjmp  2cd7             goto Check_Next_HSI;

  Ignore_IDL:
2cff: 71,1d,a8            an2b  Ra8,1d           B1_New_HSI = 0;
                                                 New_IDL = 0;
                                                 B6_New_HSI = 0;
                                                 B7_New_HSI = 0;
2d02: 27,d3               sjmp  2cd7             goto Check_Next_HSI; }

## SPARK handling from here ## 

  PIP_INTH:
2d04: 05,4c               decw  R4c              R4c--;
2d06: 05,4c               decw  R4c              R4c--;                            # Subtract propogation delay
2d08: 38,4b,23            jb    B0,R4b,2d2e      if (B0_This_HSI = 1) goto 2d2e;   # is PIP HIGH or LOW ?

##### LOW event processing from here #####
2d0b: 71,df,a9            an2b  Ra9,df           PIP_State = 0;
2d0e: 48,40,4c,4a         sb3w  R4a,R4c,R40      R4a = R4c - Last_PIP_High;
2d12: 89,a0,00,4a         cmpw  R4a,a0           
2d16: db,05               jc    2d1d             if (R4a > a0)  {                  # <= less than 768uS - ignore low event
2d18: 91,01,54            orb   R54,1            Last_SP_state = 1;                # set PIP high, wait for true Low event
2d1b: 20,89               sjmp  2da6             goto HSI_Next; }
2d1d: a0,4c,ee            ldw   Ree,R4c          Last_PIP_Low = R4c;
2d20: 3d,ae,06            jb    B5,Rae,2d29      if (First_PIP = 0)  {
2d23: a0,1e,46            ldw   R46,R1e          LastPipHiPW = PIP_High_PW;        # Not if first startup (no events yet)
2d26: a0,4a,1e            ldw   R1e,R4a          PIP_High_PW = R4a; }
2d29: 71,df,ae            an2b  Rae,df           First_PIP = 0;                    # start Crank Timer from first PIP rec'd
2d2c: 20,37               sjmp  2d65             goto 2d65;

##### HIGH processing from here #####
2d2e: 48,40,4c,4a         sb3w  R4a,R4c,R40      R4a = R4c - Last_PIP_High;
2d32: 89,40,01,4a         cmpw  R4a,140                                            # <= 1.536mS (>12K rpm)- Ignore event, reset to Low state
2d36: db,05               jc    2d3d             if (R4a > 140)  {
2d38: 71,3c,54            an2b  R54,3c           Last_SP_state = 0;
                                                 B1_Last_HSI = 0;
                                                 B6_Last_HSI = 0;
                                                 B7_Last_HSI = 0;
2d3b: 20,69               sjmp  2da6             goto HSI_Next; }
2d3d: a0,4c,40            ldw   R40,R4c          Last_PIP_High = R4c;
2d40: 3e,ae,08            jb    B6,Rae,2d4b      if (First_PIP_hi = 0)  {
2d43: c3,01,28,01,44      stw   R44,[R0+128]     Last_PIP_Intvl = PIP_Intrvl;
2d48: a0,4a,44            ldw   R44,R4a          PIP_Intrvl = R4a; }
2d4b: 71,bf,ae            an2b  Rae,bf           First_PIP_hi = 0;
2d4e: 91,20,a9            orb   Ra9,20           PIP_State = 1;
2d51: 91,c0,b5            orb   Rb5,c0           New_PIP = 1;
                                                 New_RPM = 1;
2d54: 17,48               incb  R48              Cyl_no++;                         # inc cyl no, spark and RPM calcs reqd.
2d56: 99,01,48            cmpb  R48,1            
2d59: d7,03               jne   2d5e             if (Cyl_no = 1)  {
2d5b: 91,03,b4            orb   Rb4,3            Inj_rqd_BK1 = 1;
                                                 Inj_rqd_BK2 = 1; }                # BOTH Inject BANKS SYNCed for injection
2d5e: 99,03,48            cmpb  R48,3            
2d61: d7,02               jne   2d65             if (Cyl_no = 3)  {                # Trigger every 3 sparks = Inject EVERY revolution, TWICE per cycle
2d63: 11,48               clrb  R48              Cyl_no = 0; }


############## Resume main flow ####
2d65: 11,55               clrb  R55              FPUMP_Ticks = 0;                  # Keep fuel pump running
2d67: 91,04,b4            orb   Rb4,4            SPARK_rqd = 1;
2d6a: 35,1a,0b            jnb   B5,R1a,2d78      if (Prev_underspd = 1)  {
2d6d: 3e,1a,06            jb    B6,R1a,2d76      if (Underspeed = 0)  {
2d70: 71,df,1a            an2b  R1a,df           Prev_underspd = 0;
2d73: 91,10,1a            orb   R1a,10           Lock_Ign = 1; }                   # just escaped an 'underspeed' state - no advance
2d76: 20,2e               sjmp  2da6             goto HSI_Next; }
2d78: 36,1a,05            jnb   B6,R1a,2d80      if (Underspeed = 1)  {
2d7b: 91,30,1a            orb   R1a,30           Lock_Ign = 1;
                                                 Prev_underspd = 1;                # entered or in an 'underspeed' state - no advance
2d7e: 20,26               sjmp  2da6             goto HSI_Next; }
2d80: 3c,1a,20            jb    B4,R1a,2da3      if (Lock_Ign = 1) goto 2da3;
2d83: 3d,a9,10            jb    B5,Ra9,2d96      if (PIP_State = 1) goto 2d96;

#########PIP STATE LOW #########
2d86: 3b,a9,05            jb    B3,Ra9,2d8e      if (PIP_Trail = 1) goto 2d8e;
2d89: 32,a9,1f            jnb   B2,Ra9,2dab      if (PIP_Trail_Calc = 1)  {
2d8c: 20,18               sjmp  2da6             goto HSI_Next;
2d8e: 3a,a9,15            jb    B2,Ra9,2da6      if (PIP_Trail_Calc = 1) goto 2da6;
2d91: 91,04,a9            orb   Ra9,4            PIP_Trail_Calc = 1;
2d94: 20,15               sjmp  2dab             goto Clear_Spark_Reqd;

#########PIP STATE HIGH #########
2d96: 3b,a9,02            jb    B3,Ra9,2d9b      if (PIP_Trail = 1) goto 2d9b;
2d99: 20,0b               sjmp  2da6             goto HSI_Next;
2d9b: 3a,a9,0d            jb    B2,Ra9,2dab      if (PIP_Trail_Calc = 0)  {
2d9e: 91,04,a9            orb   Ra9,4            PIP_Trail_Calc = 1;
2da1: 20,08               sjmp  2dab             goto Clear_Spark_Reqd;

  Clear_ign_lock:
2da3: 71,ef,1a            an2b  R1a,ef           Lock_Ign = 0;

  HSI_Next:
2da6: 71,3c,a8            an2b  Ra8,3c           New_PIP = 0;
                                                 B1_New_HSI = 0;
                                                 B6_New_HSI = 0;
                                                 B7_New_HSI = 0;
2da9: 27,2c               sjmp  2cd7             goto Check_Next_HSI; } }

  Clear_Spark_Reqd:
2dab: 71,fb,b4            an2b  Rb4,fb           SPARK_rqd = 0;
2dae: 27,f6               sjmp  2da6             goto HSI_Next;

##############################################
 High Speed OUT interrupt handler
 for ISC and TRIP outputs...
##############################################


  I_HSO_1:
2db0: f2                  pushp                  push(PSW);
2db1: 3e,b4,0e            jb    B6,Rb4,2dc2      if (DOL_rqd = 0)  {
2db4: 88,78,06            cmpw  R6,R78           
2db7: de,04               jlt   2dbd             if (IO_Timer < TRIP_Time) goto 2dbd;
2db9: dd,07               jv    2dc2             if (OVF = 0)  {
2dbb: 20,02               sjmp  2dbf             goto 2dbf;
2dbd: d5,03               jnv   2dc2             if (OVF = 1)  {
2dbf: 91,40,b4            orb   Rb4,40           DOL_rqd = 1; } } }
2dc2: 3f,b4,11            jb    B7,Rb4,2dd6      if (ISC_rqd = 0)  {
2dc5: 88,2e,06            cmpw  R6,R2e           
2dc8: de,04               jlt   2dce             if (IO_Timer < Last_ISC_Time) goto 2dce;
2dca: d5,04               jnv   2dd0             if (OVF = 0) goto 2dd0;
2dcc: 20,08               sjmp  2dd6             goto 2dd6;
2dce: d5,06               jnv   2dd6             if (OVF = 1)  {
2dd0: 91,20,b3            orb   Rb3,20           ISC_state = 1;
2dd3: 91,80,b4            orb   Rb4,80           ISC_rqd = 1; } }
2dd6: fa                  di                     disable ints;
2dd7: ff                  nop                    
2dd8: f3                  popp                   PSW = pop();
2dd9: f1                  reti                   return;

##############################################


  Spark_calc_1:
2dda: a0,62,e8            ldw   Re8,R62          Ign_Cyl_Mass = Cyl_Mass_BK1;
2ddd: b0,1d,1c            ldb   R1c,R1d          Ign_Advance = Last_Ign_adv;
2de0: a0,42,58            ldw   R58,R42          Ign_Delay = Last_Ign_delay;
2de3: 37,1b,02            jnb   B7,R1b,2de8      if (Base_ign_rqd = 1)  {
2de6: 28,0e               scall 2df6             Base_Ign_Lookup(); }
2de8: e7,cd,fd            jump  2bb8             goto Main_EXIT;

##############################################

  IGN_clc3:
2deb: 28,9f               scall 2e8c             IGN_Temp_Calc();
2ded: b0,1c,1d            ldb   R1d,R1c          Last_Ign_adv = Ign_Advance;
2df0: a0,58,42            ldw   R42,R58          Last_Ign_delay = Ign_Delay;
2df3: e7,c2,fd            jump  2bb8             goto Main_EXIT;


##############################################
# Base Ignition Calc (RPM, Flow, ACT)
#
# Stage 1. Looks up timing via Scaled RPM and Flow and then
# interpolates between HOT and COLD Ignition tables
# via ACT lookup table to give 3D mapping.
#
# Uses alternate Cold table if Cold Start conditions detected
#
# Interpolate calculation is
# ((ADV_COLD*ACT) + ADV_HOT*(127-ACT))/128;
# where ACT lookup maps 0 to 128
#
# If underspeed, fix Advance at 10 degrees and inhibit next
# subroutine (no point if fixed timing...)
# (0x28 = 40) base 10 BTDC physical assumed
###############################################


  Base_Ign_Lookup:
2df6: 36,1a,04            jnb   B6,R1a,2dfd      if (Underspeed = 1)  {
2df9: b1,28,1c            ldb   R1c,28           Ign_Advance = 28;
2dfc: f0                  ret                    return; }

2dfd: a1,58,28,32         ldw   R32,2858         R32 = RPM_SCALE_10;
2e01: a0,70,34            ldw   R34,R70          R34 = RPM;
2e04: ef,b5,04            call  32bc             WFuncLu1();
2e07: a0,38,6a            ldw   R6a,R38          R6a = R38;
2e0a: a1,74,28,32         ldw   R32,2874         R32 = FLOW_SCALE_10;
2e0e: a0,e8,34            ldw   R34,Re8          R34 = Ign_Cyl_Mass;
2e11: ef,a8,04            call  32bc             WFuncLu1();
2e14: a0,38,6c            ldw   R6c,R38          R6c = R38;
2e17: a0,6a,30            ldw   R30,R6a          R30 = R6a;
2e1a: a0,6c,32            ldw   R32,R6c          R32 = R6c;
2e1d: a1,0b,00,34         ldw   R34,b            R34 = b;
2e21: 9b,01,35,24,27      cmpb  R27,[R0+2435]    
2e26: d2,22               jgt   2e4a             if (ACT_start <= C36_deg)  {      # ACT dft = 10
2e28: 9b,01,36,24,27      cmpb  R27,[R0+2436]    
2e2d: da,1b               jle   2e4a             if ((uns) ACT_start < C-40_deg)  {
2e2f: 9b,01,35,24,9f      cmpb  R9f,[R0+2435]    
2e34: d2,14               jgt   2e4a             if (ECT_start <= C36_deg)  {      # ECT dft = 50
2e36: 9b,01,36,24,9f      cmpb  R9f,[R0+2436]    
2e3b: da,0d               jle   2e4a             if ((uns) ECT_start < C-40_deg)  {
2e3d: 8b,01,3c,24,ea      cmpw  Rea,[R0+243c]    
2e42: d9,06               jgtu  2e4a             if ((uns) Run_Time <= 650_Secs)  {
2e44: a1,9b,26,38         ldw   R38,269b         R38 = Ign_Adv_ColdStart;
2e48: 20,04               sjmp  2e4e             goto 2e4e; } } } } }
2e4a: a1,79,25,38         ldw   R38,2579         R38 = Ign_Adv_Cold;
2e4e: ef,26,04            call  3277             TabLu1();
2e51: ac,3b,3c            ldzbw R3c,R3b          R3c = (uns)R3b;
2e54: a1,b0,28,32         ldw   R32,28b0         R32 = Ign_Interp;
2e58: bc,73,34            ldsbw R34,R73          R34 = (int)ACT_val;
2e5b: ef,61,04            call  32bf             WFuncLu2();                       # interpolate answer in R38 (0 to 128)
2e5e: ad,7f,b8            ldzbw Rb8,7f           Rb8 = (uns)7f;
2e61: 68,38,b8            sb2w  Rb8,R38          Rb8 -= R38;                       # Rb8 = 127 - R38; ('reverse' of R38 for interpolate)
2e64: 28,d7               scall 2f3d             Scale_R3c();
2e66: a0,3c,ba            ldw   Rba,R3c          Rba = R3c;                        # Rba = ADV_COLD * Ans/128;
2e69: a0,6a,30            ldw   R30,R6a          R30 = R6a;                        # = scaled RPM
2e6c: a0,6c,32            ldw   R32,R6c          R32 = R6c;                        # = scaled (mass) Flow
2e6f: a1,0b,00,34         ldw   R34,b            R34 = b;
2e73: a1,f2,25,38         ldw   R38,25f2         R38 = Ign_Adv_Hot;
2e77: ef,fd,03            call  3277             TabLu1();
2e7a: ac,3b,38            ldzbw R38,R3b          R38 = (uns)R3b;
2e7d: a0,b8,3c            ldw   R3c,Rb8          R3c = Rb8;
2e80: 28,bb               scall 2f3d             Scale_R3c();                      # R3c = ADV_HOT *(127 - Ans)/128;
2e82: 64,3c,ba            ad2w  Rba,R3c          Rba += R3c;                       # = cold fraction + hot fraction 
2e85: a0,ba,f2            ldw   Rf2,Rba          Base_ign_delay = Rba;             # Result passed to next subroutine
2e88: 91,01,b3            orb   Rb3,1            Base_Calc_OK = 1;                 # OK for next subroutine
2e8b: f0                  ret                    return;


##########################################################
# Stage 2 ignition Calc
# Skip if underspeed (base ignition set)
# add additional ignition advance from ECT (block temp) and flow,
# NDS, Knock Delay and selected delay (via outside pins)
# Can also swop to alternate calc if demanded by Flag from ISC.
# (throttle closed or anti-stall below defined RPM ?)
# then apply limit check and smoothing.
##################################################


  IGN_Temp_Calc:
2e8c: 38,b3,02            jb    B0,Rb3,2e91      if (Base_Calc_OK = 1) goto 2e91;  # Need OK from previous subroutine
2e8f: 20,ab               sjmp  2f3c             return;
2e91: 71,fe,b3            an2b  Rb3,fe           Base_Calc_OK = 0;
2e94: a0,f2,ba            ldw   Rba,Rf2          Rba = Base_ign_delay;             # from previous subroutine, first calc of ign
2e97: a1,84,28,32         ldw   R32,2884         R32 = ECT_SCALE_7;
2e9b: b0,72,35            ldb   R35,R72          R35 = ECT_val;
2e9e: 11,34               clrb  R34              R34 = 0;
2ea0: ef,1c,04            call  32bf             WFuncLu2();
2ea3: a0,38,6a            ldw   R6a,R38          R6a = R38;                        # scaled ECT (block temp)
2ea6: a1,a0,28,32         ldw   R32,28a0         R32 = FLOW_SCALE_5;
2eaa: a0,e8,34            ldw   R34,Re8          R34 = Ign_Cyl_Mass;
2ead: ef,0c,04            call  32bc             WFuncLu1();
2eb0: a0,38,6c            ldw   R6c,R38          R6c = R38;                        # scaled (mass) Flow
2eb3: a0,6a,30            ldw   R30,R6a          R30 = R6a;
2eb6: a0,6c,32            ldw   R32,R6c          R32 = R6c;
2eb9: a1,08,00,34         ldw   R34,8            R34 = 8;
2ebd: a1,6b,26,38         ldw   R38,266b         R38 = Ign_Adv_ECTFlow;
2ec1: ef,b3,03            call  3277             TabLu1();
2ec4: ac,3b,3c            ldzbw R3c,R3b          R3c = (uns)R3b;
2ec7: 3d,b5,10            jb    B5,Rb5,2eda      if (No_Lock_Ign_ISC = 1) goto 2eda; # Alternate (fixed base) from ISC subroutine
2eca: 47,01,94,24,3c,ba   ad3w  Rba,R3c,[R0+2494] Rba = R3c+IGN_12;                # fixed advance + ECT advance
2ed0: 31,b5,26            jnb   B1,Rb5,2ef9      if (NDS_Drive = 1)  {
2ed3: 67,01,ac,24,ba      ad2w  Rba,[R0+24ac]    Rba += IGN_NDS_0;                 # NDS additional advance?
2ed8: 20,1f               sjmp  2ef9             goto 2ef9;                        # skip knock check
2eda: 64,ba,3c            ad2w  R3c,Rba          R3c += Rba;                       # std (base calc + ECT advance)
2edd: af,01,34,24,38      ldzbw R38,[R0+2434]    R38 = (uns)IgnScaler;
2ee2: 28,59               scall 2f3d             Scale_R3c();
2ee4: 47,01,2e,24,3c,ba   ad3w  Rba,R3c,[R0+242e] Rba = R3c+IGN_TRIM_0;            # scale and trim (redundant)
2eea: 33,2c,0c            jnb   B3,R2c,2ef9      if (Knock_Risk = 1)  {
2eed: 8b,01,30,24,70      cmpw  R70,[R0+2430]    
2ef2: d1,05               jleu  2ef9             if ((uns) RPM > IGNKnckLow )  {
2ef4: 67,01,68,24,ba      ad2w  Rba,[R0+2468]    Rba += IGN_KnckDly; } } }         # add knock delay (-ve advance)
2ef9: bc,7c,30            ldsbw R30,R7c          R30 = (int)Octane_adj;
2efc: 64,30,ba            ad2w  Rba,R30          Rba += R30;                       # add Octane Adjust (-ve)

### limit and delta (smoothing) from here ###

2eff: 3f,bb,0c            jb    B7,Rbb,2f0e      if (B7_Rbb = 1) goto 2f0e;        # clip to min (zero) if -ve
2f02: 99,00,bb            cmpb  Rbb,0            
2f05: d7,13               jne   2f1a             if (Rbb != 0) goto 2f1a;          # clip to max (50) if overflow
2f07: 9b,01,32,24,ba      cmpb  Rba,[R0+2432]    
2f0c: d9,05               jgtu  2f13             if ((uns) Rba <= IGNRegMin)  {
2f0e: b3,01,32,24,ba      ldb   Rba,[R0+2432]    Rba = IGNRegMin; }
2f13: 9b,01,33,24,ba      cmpb  Rba,[R0+2433]    
2f18: d3,05               jnc   2f1f             if ((uns) Rba >= IGNRegMax)  {
2f1a: b3,01,33,24,ba      ldb   Rba,[R0+2433]    Rba = IGNRegMax; }
2f1f: b1,18,30            ldb   R30,18           R30 = 18;                         # 6 degrees ?
2f22: 58,1c,ba,38         sb3b  R38,Rba,R1c      R38 = Rba - Ign_Advance;          # Delta of this and last advance ?
2f26: 37,38,04            jnb   B7,R38,2f2d      if (B7_R38 = 1)  {
2f29: 13,30               negb  R30              R30 = -R30;
2f2b: 13,38               negb  R38              R38 = -R38; }                     # => abs(R30), abs(R38)
2f2d: 99,18,38            cmpb  R38,18           
2f30: d1,04               jleu  2f36             if ((uns) R38 > 18 )  {
2f32: 54,30,1c,ba         ad3b  Rba,R1c,R30      Rba = Ign_Advance + R30; }        # limit to 6 deg max change +/-
2f36: b0,ba,1c            ldb   R1c,Rba          Ign_Advance = Rba;
2f39: ef,09,00            call  2f45             Ign_Delay_Calc();                 # call delay calc (angular delay for spark out)
2f3c: f0                  ret                    return;

##########################
# Scale R3c
# R38 defines 128ths fraction of R3c (signed)
# ANS  R3c = R3c * (R38/128)
##########################


  Scale_R3c:
2f3d: fe,6c,38,3c         sml2w R3c,R38          R3c *= R38;
2f41: 0c,07,3c            shrdw R3c,7            R3c /= 80;
2f44: f0                  ret                    return;

##########################
# Returns with Ignition angular DELAY.
# Scaled 0-32768 as 0-120 degrees. Sets timing for NEXT CYL.
# Degrees actually scaled *4 (0.25 degree).
# This value is then multiplied by ticks to get trigger time value - elsewhere (2200 ish).
# IGN_DELAY = (120 + 10 - Ign_Advance)*32768/120; [works as PIP_Interval = 120 degrees]
# and 10 BTDC (base) = 32768, => 120 degrees 'delay' for next cyl
#
# Ignition advance can legally be less than 10, and so calc checks 32768 boundary to do + or - calc.
# Multipled by PIP_interval [120 degrees] and triggered from PIP leading edge (Lo_Hi transition).
#
# If flag set, Calc doubles value so that delay works correctly when multiplied by PIP_HIGH_PW
# [60 degrees] and triggered from PIP trailing edge (Hi-Lo transition)
##########################


  Ign_Delay_Calc:
2f45: a1,03,00,32         ldw   R32,3            R32 = 3;                          # # 3 sparks per revolution
2f49: 01,36               clrw  R36              R36 = 0;
2f4b: a1,a0,05,34         ldw   R34,5a0          R34 = 5a0;                        # R34L = 1440 = 360 degrees *4
2f4f: 8c,32,34            divw  R34,R32          R34 /= R32;                       # R34 = 120 deg *4, spark gap in degrees
2f52: 45,28,00,34,36      ad3w  R36,R34,28       R36 = R34 + 28;                   # R36 = 130 deg (static timing ?)
2f57: ac,1c,38            ldzbw R38,R1c          R38 = (uns)Ign_Advance;
2f5a: 48,38,36,32         sb3w  R32,R36,R38      R32 = R36 - R38;                  # R32 = 130 - Ign_Adv
2f5e: 01,30               clrw  R30              R30 = 0;                          # R30 = (130 - Ign_Adv)*65536
2f60: 09,01,34            shlw  R34,1            R34 *= 2;
2f63: 8c,34,30            divw  R30,R34          R30 /= R34;                       # IGN_delay = R30 = (130 - IGN_ADV)*32768/120;
2f66: dd,32               jv    2f9a             if (OVF = 1) goto 2f9a;
2f68: a0,30,58            ldw   R58,R30          Ign_Delay = R30;
2f6b: 91,02,a9            orb   Ra9,2            PIP_Lead_Calc = 1;
2f6e: 33,a9,2a            jnb   B3,Ra9,2f9b      if (PIP_Trail = 0) return;
2f71: 71,fd,a9            an2b  Ra9,fd           PIP_Lead_Calc = 0;
2f74: 89,00,80,30         cmpw  R30,8000         
2f78: d3,0f               jnc   2f89             if ((uns) R30 >= 8000)  {         # IGN_ADV < 10 [>32768], so Delay > 120 deg.
2f7a: 49,00,80,30,32      sb3w  R32,R30,8000     R32 = R30 - 8000;                 # R32 = IGN_delay - 120 Degrees (in -ve)
2f7f: 09,01,32            shlw  R32,1            R32 *= 2;                         # R32 = (IGN_delay - 120 deg) * 2
2f82: 45,00,80,32,58      ad3w  R58,R32,8000     Ign_Delay = R32 + 8000;           # = 120 deg + (Ign_delay - 120 deg)*2
2f87: 20,12               sjmp  2f9b             return; }
2f89: a1,00,80,32         ldw   R32,8000         R32 = 8000;                       # IGN_ADV >=10....
2f8d: 48,30,32,34         sb3w  R34,R32,R30      R34 = R32 - R30;                  # R34 = 120 deg - ign_delay
2f91: 09,01,34            shlw  R34,1            R34 *= 2;
2f94: 48,34,32,58         sb3w  R58,R32,R34      Ign_Delay = R32 - R34;            # = 120 deg - (120 deg - Ign_delay)*2
2f98: 20,01               sjmp  2f9b             return;
2f9a: ff                  nop                     }
2f9b: f0                  ret                    return;

#############################
# BYTE function lookup with linear interpolate
# Signed and Unsigned Byte
# R32 = lookup table
# R34 = value in
# R38 = value out (Byte)
#############################


  BFuncLu1:
2f9c: 91,02,f6            orb   Rf6,2            Unsigned = 1;

  BFuncLu2:
2f9f: 9b,32,02,34         cmpb  R34,[R32+2]      
2fa3: 31,f6,04            jnb   B1,Rf6,2faa      if (Unsigned = 0) goto 2faa;
2fa6: db,0a               jc    2fb2             if (R34 > [R32+2])  {
2fa8: 20,02               sjmp  2fac             goto 2fac;
2faa: d6,06               jge   2fb2             if (R34 < [R32+2])  {
2fac: 65,02,00,32         ad2w  R32,2            R32 += 2;
2fb0: 27,ed               sjmp  2f9f             goto BFuncLu2; } }
2fb2: b2,33,36            ldb   R36,[R32++]      R36 = [R32++];
2fb5: b2,33,38            ldb   R38,[R32++]      R38 = [R32++];
2fb8: 7a,32,36            sb2b  R36,[R32]        R36 -= [R32];
2fbb: 7a,33,34            sb2b  R34,[R32++]      R34 -= [R32++];
2fbe: 7a,32,38            sb2b  R38,[R32]        R38 -= [R32];
2fc1: 31,f6,04            jnb   B1,Rf6,2fc8      if (Unsigned = 0) goto 2fc8;
2fc4: db,09               jc    2fcf             if (R38 > 0)  {
2fc6: 20,02               sjmp  2fca             goto 2fca;
2fc8: d6,05               jge   2fcf             if (R38 < 0)  {
2fca: 91,01,f6            orb   Rf6,1            Neg_flag = 1;
2fcd: 13,38               negb  R38              R38 = -R38; } }
2fcf: 7c,34,38            ml2b  R38,R34          R38 *= R34;
2fd2: 9c,36,38            divb  R38,R36          R38 /= R36;
2fd5: 30,f6,02            jnb   B0,Rf6,2fda      if (Neg_flag = 1)  {
2fd8: 13,38               negb  R38              R38 = -R38; }
2fda: 76,32,38            ad2b  R38,[R32]        R38 += [R32];
2fdd: 71,fc,f6            an2b  Rf6,fc           Neg_flag = 0;
                                                 Unsigned = 0;
2fe0: f0                  ret                    return;

###########################
# Digital Filter (for rolling averages) - Signed or Unsigned WORD
# (NB Unsigned Filter not used in this code)
# Val_out = orig_val + (val_delta) * Filter_Constant
# R32 = Original Value
# R34 = New value
# R36 = Filter Constant (fraction of 65536)
# ANSWER
# R3e = R32 + (( R34 - R32) * R36)/65536
###############################


  SWfilter:
2fe1: b1,02,ba            ldb   Rba,2            Rba = 2;
2fe4: 20,02               sjmp  2fe8             goto 2fe8;



  UWfilter:
2fe6: 11,ba               ??    

2fe8: 48,32,34,3c         sb3w  R3c,R34,R32      R3c = R34 - R32;                  # R3c = difference in values
2fec: 31,ba,04            jnb   B1,Rba,2ff3      if (B1_Rba = 0) goto 2ff3;
2fef: db,09               jc    2ffa             if (R3c > 0)  {
2ff1: 20,02               sjmp  2ff5             goto 2ff5;
2ff3: d6,05               jge   2ffa             if (R3c < 0)  {
2ff5: 91,01,ba            orb   Rba,1            Rba |= 1;                         # +ve or -ve marker
2ff8: 03,3c               negw  R3c              R3c = -R3c; } }
2ffa: 89,01,00,3c         cmpw  R3c,1            
2ffe: d9,05               jgtu  3005             if ((uns) R3c <= 1)  {
3000: a0,32,3e            ldw   R3e,R32          R3e = R32;                        # No change - return orig value
3003: 20,11               sjmp  3016             return; }
3005: 6c,36,3c            ml2w  R3c,R36          R3c *= R36;                       # R3c = (( R34 - R32) * R36)
3008: 03,3e               negw  R3e              R3e = -R3e;
300a: d7,02               jne   300e             if (R3e = 0)  {
300c: 05,3e               decw  R3e              R3e--; }                          # if top of Dword zero, make -1
300e: 38,ba,02            jb    B0,Rba,3013      if (B0_Rba = 0)  {
3011: 03,3e               negw  R3e              R3e = -R3e; }
3013: 64,32,3e            ad2w  R3e,R32          R3e += R32;                       # R3e is R3c/65536 ....
3016: f0                  ret                    return;


############################################
# Process other sensors, ACT,ECT,Oct Adjust,ACC,NDS
# If startup, average first 10 readings of ACT and ECT
# and assign to 'start' values, assign initial ISC PW, Octane, etc.
#############################################


  Process_Sensors:
3017: a1,6c,29,32         ldw   R32,296c         R32 = ACT_TFR;
301b: a0,90,34            ldw   R34,R90          R34 = ACT_raw;
301e: 08,01,34            shrw  R34,1            R34 /= 2;                         # 10mV resolution
3021: ef,9b,02            call  32bf             WFuncLu2();
3024: 45,80,00,38,3a      ad3w  R3a,R38,80       R3a = R38 + 80;                   # rounding
3029: b0,3b,73            ldb   R73,R3b          ACT_val = R3b;
302c: 99,0a,7b            cmpb  R7b,a            
302f: db,08               jc    3039             if (AE_readcnt > a)  {
3031: fe,6d,9a,19,38      sml2w R38,199a         R38 *= 199a;                      # R3a = ACT_val/10
3036: 64,3a,26            ad2w  R26,R3a          ACT_start_W += R3a; }             # ACT_start = ACT_start + ACT_OrigLU/10;
3039: a1,18,29,32         ldw   R32,2918         R32 = ECT_TFR;
303d: a0,8e,34            ldw   R34,R8e          R34 = ECT_raw;
3040: 08,01,34            shrw  R34,1            R34 /= 2;                         # 10mV resolution
3043: ef,79,02            call  32bf             WFuncLu2();
3046: 45,80,00,38,3a      ad3w  R3a,R38,80       R3a = R38 + 80;                   # rounding
304b: b0,3b,72            ldb   R72,R3b          ECT_val = R3b;
304e: 99,0a,7b            cmpb  R7b,a                                              # loop 10 times for ECT and ACT start values
3051: db,27               jc    307a             if (AE_readcnt > a)  {
3053: fe,6d,9a,19,38      sml2w R38,199a         R38 *= 199a;                      # R3a = ECT_start/10 
3058: 64,3a,9e            ad2w  R9e,R3a          ECT_Start_hb += R3a;              # ECT_start = ECT_start + ECT_OrigLU/10;
305b: a1,7c,2a,32         ldw   R32,2a7c         R32 = ISC_Start_PW;
305f: bc,9f,34            ldsbw R34,R9f          R34 = (int)ECT_start;
3062: ef,5a,02            call  32bf             WFuncLu2();
3065: c3,01,3c,01,38      stw   R38,[R0+13c]     Last_ISC_H = R38;
306a: a1,00,19,38         ldw   R38,1900         R38 = 1900;                       # ISC pulswidth & 1600 rpm Idle if startup
306e: c3,01,32,01,38      stw   R38,[R0+132]     Reqd_idle_RPM = R38;
3073: c3,01,66,01,8a      stw   R8a,[R0+166]     OCT_flt = OCT_raw;
3078: 17,7b               incb  R7b              AE_readcnt++; }
307a: 34,18,08            jnb   B4,R18,3085      if (ACTFail = 1)  {
307d: b3,01,38,24,73      ldb   R73,[R0+2438]    ACT_val = C20_deg;
3082: b0,73,27            ldb   R27,R73          ACT_start = ACT_val; }            # Fail - set defaults
3085: 33,18,08            jnb   B3,R18,3090      if (ECTFail = 1)  {
3088: b3,01,37,24,72      ldb   R72,[R0+2437]    ECT_val = C100_deg;
308d: b0,72,9f            ldb   R9f,R72          ECT_start = ECT_val; }            # Fail - set defaults
3090: a3,01,66,01,32      ldw   R32,[R0+166]     R32 = OCT_flt;
3095: a0,8a,34            ldw   R34,R8a          R34 = OCT_raw;
3098: a1,05,05,36         ldw   R36,505          R36 = 505;                        # => 2% of change for octane select
309c: 2f,43               scall 2fe1             SWfilter();
309e: c3,01,66,01,3e      stw   R3e,[R0+166]     OCT_flt = R3e;
30a3: 8b,01,b0,24,3e      cmpw  R3e,[R0+24b0]    
30a8: d3,07               jnc   30b1             if ((uns) R3e >= 3.845V)  {
30aa: b3,01,74,24,7c      ldb   R7c,[R0+2474]    Octane_adj = 0deg;                # no Octane Adjust
30af: 20,21               sjmp  30d2             goto 30d2; }
30b1: 8b,01,b2,24,3e      cmpw  R3e,[R0+24b2]    
30b6: d3,07               jnc   30bf             if ((uns) R3e >= 1.92V)  {
30b8: b3,01,75,24,7c      ldb   R7c,[R0+2475]    Octane_adj = 3deg;                # 3 degrees retard (ground pin 24)
30bd: 20,13               sjmp  30d2             goto 30d2; }
30bf: 8b,01,b4,24,3e      cmpw  R3e,[R0+24b4]    
30c4: d3,07               jnc   30cd             if ((uns) R3e >= 0.0V)  {
30c6: b3,01,76,24,7c      ldb   R7c,[R0+2476]    Octane_adj = 6deg;                # 6 degrees retard (ground pin 23)
30cb: 20,05               sjmp  30d2             goto 30d2; }
30cd: b3,01,77,24,7c      ldb   R7c,[R0+2477]    Octane_adj = defdeg;              # 6 degrees retard (safety default)

30d2: 71,f1,b5            an2b  Rb5,f1           NDS_Drive = 0;
                                                 NDS_Neutral = 0;
                                                 ACC_On = 0;
30d5: 89,00,80,82         cmpw  R82,8000         
30d9: d3,03               jnc   30de             if ((uns) ACC_raw >= 8000)  {     # 2.56V
30db: 91,08,b5            orb   Rb5,8            ACC_On = 1; }
30de: 89,40,d0,92         cmpw  R92,d040         
30e2: d3,05               jnc   30e9             if ((uns) NDS_raw >= d040)  {     # 4.165v
30e4: 91,04,b5            orb   Rb5,4            NDS_Neutral = 1;
30e7: 20,14               sjmp  30fd             goto 30fd; }
30e9: 89,00,8a,92         cmpw  R92,8a00         
30ed: db,0e               jc    30fd             if (NDS_raw > 8a00)  {            # 2.76v
30ef: 89,40,5e,92         cmpw  R92,5e40         
30f3: d3,05               jnc   30fa             if ((uns) NDS_raw >= 5e40)  {     # 1.885v
30f5: 91,06,b5            orb   Rb5,6            NDS_Drive = 1;
                                                 NDS_Neutral = 1;
30f8: 20,03               sjmp  30fd             goto 30fd; }
30fa: 91,02,b5            orb   Rb5,2            NDS_Drive = 1; }
30fd: b3,01,4c,24,32      ldb   R32,[R0+244c]    R32 = FLGS_B3_B0;
3102: 3c,32,03            jb    B4,R32,3108      if (B4_R32 = 0)  {
3105: 71,fb,b5            an2b  Rb5,fb           NDS_Neutral = 0; }                # b4=0, Always cleared
3108: a1,18,28,32         ldw   R32,2818         R32 = ECT_Coldstart_Time;
310c: bc,9f,34            ldsbw R34,R9f          R34 = (int)ECT_start;
310f: ef,ad,01            call  32bf             WFuncLu2();
3112: a0,38,24            ldw   R24,R38          Coldstart_secs = R38;
3115: a1,c0,28,32         ldw   R32,28c0         R32 = Vss_TFR;
3119: a0,80,34            ldw   R34,R80          R34 = Vss_raw;
311c: ef,9d,01            call  32bc             WFuncLu1();
311f: a0,38,52            ldw   R52,R38          VBATT = R38;
3122: e7,93,fa            jump  2bb8             goto Main_EXIT;


########## VAF flow calc ###################
# VAF, BAP, ACT to calculate true MASS air flow
# Sets VAF1_flow & VAF2_Flow as MASS value.
#
# Mass = Volume * Pressure/temp;  (Effectively)
# Answer scaled as 8192 = density 1.0
#
# Gas law (approx) Density =  (Pressure * 11.796)/Temp K
# looks like R3e (density multiplier) is scaled as
# 65536 = 3 atmospheres (3*8192)
# Default BAP and ACT_val = 0 (Std atmo at 0c) this subr sets
# multipler (density)= 1.2469, but 1.2929 expected, 3.5% low.
# default BAP and default ACT (20 C) gives 1.206
# Density correction table probably carries out a version of the
# 'drag equation' = force on flap proportional to Volume*density 
# Answer is scaled by final scaler (94%) and divided by 4 
#############################################

  Main_airflow_calc:
3125: a3,01,54,01,34      ldw   R34,[R0+154]     R34 = BAP_Interval;               # each state change
312a: a1,96,01,32         ldw   R32,196          R32 = 196;
312e: a1,aa,e6,30         ldw   R30,e6aa         R30 = e6aa;                       # = 26,666,666 = 128 secs in IO ticks 
3132: 8c,34,30            divw  R30,R34          R30 /= R34;
3135: c3,01,56,01,30      stw   R30,[R0+156]     BAP_Freq = R30;                   # = 2* BAP frequency (Hz)
313a: a0,30,34            ldw   R34,R30          R34 = R30;
313d: a1,dc,2a,32         ldw   R32,2adc         R32 = BAP_TFR;
3141: ef,78,01            call  32bc             WFuncLu1();
3144: 36,18,05            jnb   B6,R18,314c      if (BAPFail = 1)  {
3147: b3,01,0c,24,38      ldb   R38,[R0+240c]    R38 = BAP_Dflt; }
314c: c7,01,58,01,38      stb   R38,[R0+158]     BAP_Val = R38;                    # = inches Hg*8
3151: b0,38,37            ldb   R37,R38          R37 = R38;
3154: 11,36               clrb  R36              R36 = 0;
3156: 08,03,36            shrw  R36,3            R36 /= 8;                         # R36 = InHg*256
3159: 01,34               clrw  R34              R34 = 0;                          # R34L = Pressure (scaled)
315b: b0,73,31            ldb   R31,R73          R31 = ACT_val;
315e: 1a,01,31            asrb  R31,1            R31 /= 2;
3161: 75,44,31            ad2b  R31,44           R31 += 44;                        # add absolute zero (272) 
3164: 11,30               clrb  R30              R30 = 0;                          # R30 = degrees Kelvin (scaled) 
3166: 8c,30,34            divw  R34,R30          R34 /= R30;                       # R34 = Pressure/temp (scaled)
3169: a1,c0,29,32         ldw   R32,29c0         R32 = Air_Density;                # Correction table
316d: ef,4c,01            call  32bc             WFuncLu1();
3170: 6f,01,2c,24,38      ml2w  R38,[R0+242c]    R38 *= DenseScaler;               # Scale by 94% and divide by 4
3175: a0,3a,3e            ldw   R3e,R3a          R3e = R3a;                        # R3e is 'Vol->Mass' converter
3178: 35,18,0f            jnb   B5,R18,318a      if (VAF1Fail = 0) goto 318a;
317b: 31,18,07            jnb   B1,R18,3185      if (VAF2Fail = 1)  {
317e: a3,01,3a,24,34      ldw   R34,[R0+243a]    R34 = VAF_dflt;
3183: 20,08               sjmp  318d             goto 318d; }
3185: a0,7e,34            ldw   R34,R7e          R34 = VAF2_raw;
3188: 20,03               sjmp  318d             goto 318d;
318a: a0,96,34            ldw   R34,R96          R34 = VAF1_raw;
318d: 28,20               scall 31af             Mass_Flow();
318f: a0,3a,9a            ldw   R9a,R3a          VAF1_Mflow = R3a;
3192: 31,18,0f            jnb   B1,R18,31a4      if (VAF2Fail = 0) goto 31a4;
3195: 35,18,07            jnb   B5,R18,319f      if (VAF1Fail = 1)  {
3198: a3,01,3a,24,34      ldw   R34,[R0+243a]    R34 = VAF_dflt;
319d: 20,08               sjmp  31a7             goto 31a7; }
319f: a0,96,34            ldw   R34,R96          R34 = VAF1_raw;
31a2: 20,03               sjmp  31a7             goto 31a7;
31a4: a0,7e,34            ldw   R34,R7e          R34 = VAF2_raw;
31a7: 28,06               scall 31af             Mass_Flow();
31a9: a0,3a,9c            ldw   R9c,R3a          VAF2_Mflow = R3a;
31ac: e7,09,fa            jump  2bb8             goto Main_EXIT;

###################################
# VAF MASS Flow calc - used within above subroutine -
# IN  R34 = raw VAF (volume flow),
# IN  R3e = density factor
# Returns    R3a = MASS FLOW = volume * density
# assumes R32 set to VAF TFR table
# Converts volume to MASS
# final multiply makes this a straight vol*density conversion
# Limit check at 8192*65536, VAF lookup is unsigned word
###################################

  Mass_Flow:
31af: a1,cc,28,32         ldw   R32,28cc         R32 = VAF_TFR;
31b3: ef,06,01            call  32bc             WFuncLu1();
31b6: 6c,3e,38            ml2w  R38,R3e          R38 *= R3e;                       # Volume*density/8
31b9: 99,20,3b            cmpb  R3b,20           
31bc: d3,07               jnc   31c5             if ((uns) R3b >= 20)  {           # max = 8192*65536
31be: a1,ff,ff,3a         ldw   R3a,ffff         R3a = ffff;
31c2: 91,01,69            orb   R69,1            VAF_OVF = 1; }
31c5: 0d,03,38            shldw R38,3            R38 *= 8;                         # R3a = Volume * density
31c8: f0                  ret                    return;

##################################################
# TPS, do filter and set TPS flags.
# Calcs TPS_Difference, flags and TPS_read Interval
##################################################


  Process_TPS:
31c9: 32,18,09            jnb   B2,R18,31d5      if (TPSFail = 1)  {
31cc: a1,00,80,c8         ldw   Rc8,8000         TPS_Min = 8000;
31d0: a0,c8,ec            ldw   Rec,Rc8          TPS_val = TPS_Min;
31d3: 20,36               sjmp  320b             goto 320b; }
31d5: a0,ec,32            ldw   R32,Rec          R32 = TPS_val;
31d8: a0,8c,34            ldw   R34,R8c          R34 = TPS_raw;
31db: a1,31,0c,36         ldw   R36,c31          R36 = c31;                        # => 4.76 % of change
31df: ef,ff,fd            call  2fe1             SWfilter();
31e2: a0,3e,ec            ldw   Rec,R3e          TPS_val = R3e;                    # New smoothed value
31e5: 88,c8,ec            cmpw  Rec,Rc8          
31e8: db,03               jc    31ed             if (TPS_val > TPS_Min)  {
31ea: a0,ec,c8            ldw   Rc8,Rec          TPS_Min = TPS_val; }
31ed: 48,c8,8c,aa         sb3w  Raa,R8c,Rc8      TPS_Posn = TPS_raw - TPS_Min;
31f1: d9,02               jgtu  31f5             if ((uns) TPS_Posn <= 0)  {
31f3: 01,aa               clrw  Raa              TPS_Posn = 0; }                   # Throttle must be closed if equal/lower

### Throttle closed ###
31f5: 8b,01,48,24,aa      cmpw  Raa,[R0+2448]    
31fa: d9,08               jgtu  3204             if ((uns) TPS_Posn <= 0.065V)  {
31fc: 91,03,20            orb   R20,3            TPS_Closed = 1;
                                                 TPS_TClosed = 1;                  # TPS_TClosed used in test (STI) sequence
31ff: 71,fb,20            an2b  R20,fb           TPS_Wide = 0;
3202: 20,12               sjmp  3216             goto 3216; }

### Part throttle, small difference  (< 3.25v) ###
3204: 8b,01,4a,24,aa      cmpw  Raa,[R0+244a]    
3209: d9,05               jgtu  3210             if ((uns) TPS_Posn <= 3.25V)  {
320b: 71,f8,20            an2b  R20,f8           TPS_Closed = 0;
                                                 TPS_TClosed = 0;
                                                 TPS_Wide = 0;
320e: 20,06               sjmp  3216             goto 3216; }

### Wide throttle, large difference  (> 3.25V ) ###
3210: 91,04,20            orb   R20,4            TPS_Wide = 1;
3213: 71,fc,20            an2b  R20,fc           TPS_Closed = 0;
                                                 TPS_TClosed = 0;

### resume main code ####
3216: a0,06,30            ldw   R30,R6           R30 = IO_Timer;
3219: a3,01,46,01,32      ldw   R32,[R0+146]     R32 = Last_TPS;
321e: 68,32,30            sb2w  R30,R32          R30 -= R32;
3221: c3,01,48,01,30      stw   R30,[R0+148]     TPS_Interval = R30;
3226: c3,01,46,01,06      stw   R6,[R0+146]      Last_TPS = IO_Timer;
322b: e7,8a,f9            jump  2bb8             goto Main_EXIT;

#############################
# Main RPM Calculation
# do filter and set which PIP calculation to use
#############################

  RPM_calc:
322e: 37,b5,1d            jnb   B7,Rb5,324e      if (New_RPM = 1)  {
3231: a1,fe,00,36         ldw   R36,fe           R36 = fe;
3235: a1,2a,50,34         ldw   R34,502a         R34 = 502a;                       # 16666666 / elapsed time is RPM/4 on 6 cyl
3239: 8c,44,34            divw  R34,R44          R34 /= PIP_Intrvl;
323c: a0,34,70            ldw   R70,R34          RPM = R34;
323f: 71,7f,b5            an2b  Rb5,7f           New_RPM = 0;
3242: a0,5c,32            ldw   R32,R5c          R32 = RPM_Smooth;
3245: a1,09,03,36         ldw   R36,309          R36 = 309;                        # 1.2% of change, heavy filter
3249: 2d,96               scall 2fe1             SWfilter();
324b: a0,3e,5c            ldw   R5c,R3e          RPM_Smooth = R3e; }
324e: 3a,5a,02            jb    B2,R5a,3253      if (PUMP_Reqd = 0)  {
3251: 01,70               clrw  R70              RPM = 0; }
3253: 33,a9,14            jnb   B3,Ra9,326a      if (PIP_Trail = 0) goto 326a;
3256: a3,01,44,24,32      ldw   R32,[R0+2444]    R32 = 1000RPM;
325b: 67,01,46,24,32      ad2w  R32,[R0+2446]    R32 += 50RPM;                     ## Flip PIP calc at 1050 and greater (50 rpm hysteresis)
3260: 88,32,5c            cmpw  R5c,R32          
3263: d3,0f               jnc   3274             if ((uns) RPM_Smooth >= R32)  {
3265: 71,f7,a9            an2b  Ra9,f7           PIP_Trail = 0;
3268: 20,0a               sjmp  3274             goto 3274;
326a: 8b,01,44,24,5c      cmpw  R5c,[R0+2444]                                      ## Flip PIP calc at 1000 and below
326f: db,03               jc    3274             if (RPM_Smooth > 1000RPM)  {
3271: 91,08,a9            orb   Ra9,8            PIP_Trail = 1; } }
3274: e7,41,f9            jump  2bb8             goto Main_EXIT;


########################################################################
# Table lookup subroutine with 2Dimension interpolate - byte
# Pars In -
# R38 = Table Address
# R30 = X value. (column)   'whole' in top byte (R31), fraction in lower (R30)
# R32 = Y value  (row       'whole' in top byte (R33), fraction in lower (R32)
# R34 = table size  (columns + 1)
# Pars out -
# R3b = returned value (R3a =80 for rounding )
#
# R30-R33 trashed in this function
# Neatly interpolates by interpolating this and next columns at row X
# to make a 'slope', and then interpolating that slope in Y. (uses 4 values in table)
###########################################################################

  TabLu1:
3277: 5c,33,34,36         ml3b  R36,R34,R33      R36 = R34 * R33;                  # Y*cols. Get into correct row.
327b: 74,31,36            ad2b  R36,R31          R36 += R31;                       # (Y*cols)+X. = Correct (lower) cell offset.
327e: d3,02               jnc   3282             if ((uns) R36 >= 0)  {
3280: 17,37               incb  R37              R37++; }                          # Add carry if byte o/flow.
3282: 64,36,38            ad2w  R38,R36          R38 += R36;                       # Real cell address, table+offset
3285: b2,39,31            ldb   R31,[R38++]      R31 = [R38++];                    # R31 = [0,0] BASE cell, below input value.
3288: b2,38,33            ldb   R33,[R38]        R33 = [R38];                      # R33 = [1,0] cell, [ next X value]
328b: 28,1c               scall 32a9             TabInterp();                      # R3b = Interpolated X,0 (R31, R33) by fract X
328d: 64,34,38            ad2w  R38,R34          R38 += R34;
3290: b2,38,33            ldb   R33,[R38]        R33 = [R38];                      # R33 = [1,1] cell (next x, next y)
3293: 05,38               decw  R38              R38--;
3295: b2,38,31            ldb   R31,[R38]        R31 = [R38];                      # R31 = [0,1] cell (this x, next y)
3298: b0,3b,34            ldb   R34,R3b          R34 = R3b;                        # save interpolated X
329b: 28,0c               scall 32a9             TabInterp();                      # Interpolated (X,1) value by fract X.
329d: b0,3b,33            ldb   R33,R3b          R33 = R3b;                        # intpolated (X,1)
32a0: b0,34,31            ldb   R31,R34          R31 = R34;                        # intpolated (X,0)
32a3: b0,32,30            ldb   R30,R32          R30 = R32;                        # set interpolate fraction to Y value
32a6: 28,01               scall 32a9             TabInterp();                      # Interpolate intpld(x,0), intpld(x,1) in fraction Y
32a8: f0                  ret                    return;

#############################
# UNSIGNED one dimension byte interpolate for tablookup - answer in R3b
# R30 = fraction 0-255
# R31 = lower cell value
# R33 = upper cell value
# R3b = (upper-lower)*fraction/256 + lower
# R3b = interpolated answer between R31 and R33 by R30
# Answer in R3b.
#############################


  TabInterp:
32a9: 5c,33,30,3a         ml3b  R3a,R30,R33      R3a = R30 * R33;                  # R3a = fraction * high val
32ad: 5c,31,30,36         ml3b  R36,R30,R31      R36 = R30 * R31;                  # R36 = fraction * low val
32b1: 68,36,3a            sb2w  R3a,R36          R3a -= R36;                       # R3a = (fract*high)-(fract*low) [= increment*fract]
32b4: 74,31,3b            ad2b  R3b,R31          R3b += R31;                       # R3b = increment*fract/256 + low
32b7: 65,80,00,3a         ad2w  R3a,80           R3a += 80;                        # round up for answer in R3b
32bb: f0                  ret                    return;

#############################
 WORD function lookup with linear interpolate
 Signed and Unsigned Word
 R32 = lookup table
 R34 = value in    (Vin)
 R38 = value out (Vout) (Word)
 (LU = lookup)
#############################


  WFuncLu1:
32bc: 91,02,f6            orb   Rf6,2            Unsigned = 1;                     # set unsigned compare

  WFuncLu2:
32bf: 8b,32,04,34         cmpw  R34,[R32+4]                                        # compare IN to next table row
32c3: 31,f6,04            jnb   B1,Rf6,32ca      if (Unsigned = 0) goto 32ca;      # jump if signed compare
32c6: db,0a               jc    32d2             if (R34 > [R32+4])  {             # do unsigned compare
32c8: 20,02               sjmp  32cc             goto 32cc;
32ca: d6,06               jge   32d2             if (R34 < [R32+4])  {             # do signed compare
32cc: 65,04,00,32         ad2w  R32,4            R32 += 4;                         # skip to next table row
32d0: 27,ed               sjmp  32bf             goto WFuncLu2; } }
32d2: a2,33,36            ldw   R36,[R32++]      R36 = [R32++];                    # R36 = high VOUT value
32d5: a2,33,38            ldw   R38,[R32++]      R38 = [R32++];                    # R38 = low  (next)LU value (R34>Vin>R38)
32d8: 6a,32,36            sb2w  R36,[R32]        R36 -= [R32];                     # R36 = LU gap (between rows)
32db: 6a,33,34            sb2w  R34,[R32++]      R34 -= [R32++];                   # R34 = Vin_Delta (VIN - low LU)
32de: 6a,32,38            sb2w  R38,[R32]        R38 -= [R32];                     # R38 = Vout gap (between rows)
32e1: 31,f6,04            jnb   B1,Rf6,32e8      if (Unsigned = 0) goto 32e8;      # Is this Signed lookup
32e4: db,09               jc    32ef             if (R38 > 0)  {                   # VOUT increment is Y +ve or unsigned lookup
32e6: 20,02               sjmp  32ea             goto 32ea;
32e8: d6,05               jge   32ef             if (R38 < 0)  {
32ea: 91,01,f6            orb   Rf6,1            Neg_flag = 1;                     # remember negative LU for later ...
32ed: 03,38               negw  R38              R38 = -R38; } }
32ef: 6c,34,38            ml2w  R38,R34          R38 *= R34;
32f2: 8c,36,38            divw  R38,R36          R38 /= R36;                       # R38 = (Vout_gap*VIN_delta)/LU_gap = Vout_Delta
32f5: 30,f6,02            jnb   B0,Rf6,32fa      if (Neg_flag = 1)  {
32f8: 03,38               negw  R38              R38 = -R38; }
32fa: 66,32,38            ad2w  R38,[R32]        R38 += [R32];                     # R38 = Vout_delta+lower_LU;
32fd: 71,fc,f6            an2b  Rf6,fc           Neg_flag = 0;
                                                 Unsigned = 0;
3300: f0                  ret                    return;


####################################
# This calculates rate of change & averages (?)
# for PIP intervals (last and this) to give improved
# and smoothed response for next SPOUT.
#
# SPOUT = (120 + fixed - Advance)/120 - (ThisPIP + lastPIP)/lastPIP
# and limited within an envelope - delta set at 10% increments and
# 'nibbled' off at 1% for smoothed ignition response (?)
# Called only from task list
# limit checked (33aa) to 10% max either way with 32768 'base'
#
# is R3a passed out of this func ? No next func in list writes to R3a
#####################################


  Ign_Delta_Calc:
3301: 3e,b5,02            jb    B6,Rb5,3306      if (New_PIP = 1) goto 3306;
3304: 20,eb               sjmp  33f1             goto endfunc;
3306: fa                  di                     disable ints;
3307: ff                  nop                    
3308: a0,44,ba            ldw   Rba,R44          Rba = PIP_Intrvl;
330b: a3,01,28,01,b8      ldw   Rb8,[R0+128]     Rb8 = Last_PIP_Intvl;
3310: a0,46,3e            ldw   R3e,R46          R3e = LastPipHiPW;
3313: a0,1e,3c            ldw   R3c,R1e          R3c = PIP_High_PW;                # is PIP_high_PW = 60 degrees in ticks ?
3316: fb                  ei                     enable ints;
3317: 71,bf,b5            an2b  Rb5,bf           New_PIP = 0;
331a: 48,b8,ba,36         sb3w  R36,Rba,Rb8      R36 = Rba - Rb8;                  # Difference in PIP (High?) intervals
331e: db,02               jc    3322             if (R36 > 0)  {
3320: 03,36               negw  R36              R36 = -R36; }                     # abs (difference)
3322: 4c,ac,ba,30         ml3w  R30,Rba,Rac      R30 = Rba * Ign_DELTA;            # First time used - start at zero => delta
3326: 88,32,36            cmpw  R36,R32          
3329: d1,02               jleu  332d             if ((uns) R36 <= R32) goto 332d;  # abs(diff) > (PIP_Hi_Intvl * IDelta)/65536
332b: 20,b4               sjmp  33e1             goto Set_delta;                   # always jumps for first change ?
332d: 01,34               clrw  R34              R34 = 0;
332f: 8c,ba,34            divw  R34,Rba          R34 /= Rba;                       # abs (PIP_HI_intvl - Last_PIP_Intvl)*65536 / PIP_Hi_Intvl (Delta)
3332: d5,02               jnv   3336             if (OVF = 0) goto 3336;
3334: 20,bb               sjmp  33f1             goto endfunc;
3336: a0,34,30            ldw   R30,R34          R30 = R34;
3339: 6c,3c,30            ml2w  R30,R3c          R30 *= R3c;                       # R32 = Delta/65536 * PIP_HI_PW
333c: 48,3e,3c,30         sb3w  R30,R3c,R3e      R30 = R3c - R3e;                  # (Delta * PIP_Hi_PW) - LastPipHiPW
3340: db,02               jc    3344             if (R30 > 0)  {
3342: 03,30               negw  R30              R30 = -R30; }                     # ABS Value (timediff?)
3344: 4d,99,19,ac,38      ml3w  R38,Rac,1999     R38 = 2665;                       # R3a = I_Delta/10;
3349: a0,3a,36            ldw   R36,R3a          R36 = R3a;                        # move in R36
334c: 89,41,00,34         cmpw  R34,41           
3350: d3,70               jnc   33c2             if ((uns) R34 < 41) goto 33c2;    # change < 1% (PIP)
3352: 08,01,3a            shrw  R3a,1            R3a /= 2;
3355: a1,00,80,38         ldw   R38,8000         R38 = 8000;
3359: 68,3a,38            sb2w  R38,R3a          R38 -= R3a;                       # R38 = 32768 - (I_Delta * 0.5)
335c: db,02               jc    3360             if ((uns) R38 >= 0) goto 3360;
335e: 20,91               sjmp  33f1             goto endfunc;
3360: 6c,32,38            ml2w  R38,R32          R38 *= R32;                       # R38L = 32768-(I_Delta*0.5)*(Delta/65536)*PIP_HI_PW
3363: 0d,01,38            shldw R38,1            R38 *= 2;
3366: 88,3a,30            cmpw  R30,R3a          
3369: d3,76               jnc   33e1             if ((uns) R30 < R3a) goto Set_delta;
336b: 08,01,36            shrw  R36,1            R36 /= 2;
336e: 65,00,80,36         ad2w  R36,8000         R36 += 8000;
3372: db,7d               jc    33f1             if (R36 > 0)  {
3374: 4c,32,36,38         ml3w  R38,R36,R32      R38 = R36 * R32;
3378: 0d,01,38            shldw R38,1            R38 *= 2;
337b: 88,3a,30            cmpw  R30,R3a          
337e: d9,61               jgtu  33e1             if ((uns) R30 > R3a ) goto Set_delta;
3380: 44,b8,ba,36         ad3w  R36,Rba,Rb8      R36 = Rba + Rb8;
3384: dd,6b               jv    33f1             if (OVF = 1) goto endfunc;
3386: 01,34               clrw  R34              R34 = 0;
3388: 44,3e,3c,30         ad3w  R30,R3c,R3e      R30 = R3c + R3e;
338c: dd,63               jv    33f1             if (OVF = 1) goto endfunc;
338e: 0c,02,34            shrdw R34,2            R34 /= 4;
3391: 8c,30,34            divw  R34,R30          R34 /= R30;
3394: dd,5b               jv    33f1             if (OVF = 1) goto endfunc;
3396: a0,f0,32            ldw   R32,Rf0          R32 = Ign_Delta;
3399: a3,01,42,24,36      ldw   R36,[R0+2442]    R36 = Ign_flt_sc;                 # => 12.5% of change
339e: ef,40,fc            call  2fe1             SWfilter();
33a1: a0,3e,f0            ldw   Rf0,R3e          Ign_Delta = R3e;
33a4: 89,33,73,f0         cmpw  Rf0,7333         
33a8: db,04               jc    33ae             if (Ign_Delta > 7333)  {
33aa: a1,33,73,f0         ldw   Rf0,7333         Ign_Delta = 7333; }               # = 0.45
33ae: 89,cc,8c,f0         cmpw  Rf0,8ccc         
33b2: d1,04               jleu  33b8             if ((uns) Ign_Delta > 8ccc )  {
33b4: a1,cc,8c,f0         ldw   Rf0,8ccc         Ign_Delta = 8ccc; }               # = 0.55
33b8: 69,47,01,ac         sb2w  Rac,147          Ign_DELTA -= 147;                 # 0.5%, rounding ?
33bc: d6,02               jge   33c0             if (Ign_DELTA < 0)  {
33be: 01,ac               clrw  Rac              Ign_DELTA = 0; }                  # < 1%, ignore
33c0: 20,2f               sjmp  33f1             goto endfunc;
33c2: a0,30,34            ldw   R34,R30          R34 = R30;
33c5: 08,01,36            shrw  R36,1            R36 /= 2;
33c8: 65,00,80,36         ad2w  R36,8000         R36 += 8000;
33cc: dd,23               jv    33f1             if (OVF = 1) goto endfunc;
33ce: a0,36,38            ldw   R38,R36          R38 = R36;
33d1: 4d,41,00,3c,30      ml3w  R30,R3c,41       R30 = R3c * 41;
33d6: 6c,32,38            ml2w  R38,R32          R38 *= R32;
33d9: 0d,01,38            shldw R38,1            R38 *= 2;
33dc: 88,3a,34            cmpw  R34,R3a          
33df: d1,9f               jleu  3380             if ((uns) R34 <= R3a) goto 3380;

  Set_delta:
33e1: 65,cc,0c,ac         ad2w  Rac,ccc          Ign_DELTA += ccc;                 # 3276, add 5%
33e5: dd,06               jv    33ed             if (OVF = 1) goto 33ed;
33e7: 89,00,80,ac         cmpw  Rac,8000         
33eb: d3,04               jnc   33f1             if ((uns) Ign_DELTA >= 8000)  {
33ed: a1,00,80,ac         ldw   Rac,8000         Ign_DELTA = 8000; } }             # max 32768, 50% ?

  endfunc:
33f1: e7,c4,f7            jump  2bb8             goto Main_EXIT;

############################################
# Base Injection calc from mass flow.
# Sets base flow after calc cylinder flow per bank from VAFs
# appears 4000 In to Calc_Cyl_Charge = 1.208g (1 litre) cyl charge
# at 1000rpm, so vaf_MFlow must be 8000 = 1500L/min or 750L/min?
############################################

  Base_inj_calc:
33f4: b3,01,4c,24,30      ldb   R30,[R0+244c]    R30 = FLGS_B3_B0;
33f9: a1,00,40,22         ldw   R22,4000         Inj_Scaler = 4000;                # would EGO feedback change this ??
33fd: a0,9c,38            ldw   R38,R9c          R38 = VAF2_Mflow;
3400: 6f,01,06,24,38      ml2w  R38,[R0+2406]    R38 *= VAF2_Scaler;               # R3a = (mass) flow/2 ;
3405: 67,01,0a,24,3a      ad2w  R3a,[R0+240a]    R3a += VAF2_Trimx;
340a: 47,01,08,24,3a,3e   ad3w  R3e,R3a,[R0+2408] R3e = R3a+VAF2_Trim;
3410: 37,3f,05            jnb   B7,R3f,3418      if (B7_R3f = 1)  {
3413: 01,3e               clrw  R3e              R3e = 0;
3415: 91,01,69            orb   R69,1            VAF_OVF = 1; }
3418: c3,01,2a,01,3e      stw   R3e,[R0+12a]     DBG_BK2_Flow = R3e;
341d: 28,4d               scall 346c             Calc_Cyl_AirMass();
341f: a0,3c,64            ldw   R64,R3c          Cyl_Mass_BK2 = R3c;
3422: 28,7d               scall 34a1             Base_Cyl_Inj_calc();
3424: a0,3c,d0            ldw   Rd0,R3c          Inj_Cyl_BK2 = R3c;
3427: a0,9a,38            ldw   R38,R9a          R38 = VAF1_Mflow;
342a: 6f,01,00,24,38      ml2w  R38,[R0+2400]    R38 *= VAF1_Scaler;
342f: 67,01,04,24,3a      ad2w  R3a,[R0+2404]    R3a += VAF1_Trimx;
3434: 47,01,02,24,3a,3e   ad3w  R3e,R3a,[R0+2402] R3e = R3a+VAF1_Trim;
343a: 37,3f,05            jnb   B7,R3f,3442      if (B7_R3f = 1)  {
343d: 01,3e               clrw  R3e              R3e = 0;
343f: 91,01,69            orb   R69,1            VAF_OVF = 1; }
3442: a0,3e,74            ldw   R74,R3e          DBG_BK1_flow = R3e;
3445: 28,25               scall 346c             Calc_Cyl_AirMass();
3447: a0,3c,62            ldw   R62,R3c          Cyl_Mass_BK1 = R3c;
344a: 33,30,17            jnb   B3,R30,3464      if (B3_R30 = 1)  {
344d: 9b,01,6a,24,00      cmpb  R0,[R0+246a]     
3452: df,03               je    3457             if (0 = Crank_1) goto 3457;
3454: 3f,1a,0d            jb    B7,R1a,3464      if (Cranking = 0)  {
3457: 44,62,64,3c         ad3w  R3c,R64,R62      R3c = Cyl_Mass_BK2 + Cyl_Mass_BK1;
345b: 08,01,3c            shrw  R3c,1            R3c /= 2;
345e: a0,3c,62            ldw   R62,R3c          Cyl_Mass_BK1 = R3c;               # average both cyl flows
3461: a0,3c,64            ldw   R64,R3c          Cyl_Mass_BK2 = R3c; } }           # R62 used in EGR and Ign calcs.
3464: 28,3b               scall 34a1             Base_Cyl_Inj_calc();
3466: a0,3c,ce            ldw   Rce,R3c          Inj_Cyl_BK1 = R3c;                # and then recalc B1 only ? Odd.
3469: e7,4c,f7            jump  2bb8             goto Main_EXIT;

############################################
# Calc cyl mass charge from bank mass flow and RPM
# Input  = R3e Bank Flow (half after scaler [around 3410] ?)
# Answer = R3c Cyl Charge, limit checked (grams air ?)
# R3c = (R3c*65536/(RPMx4))/6 
# ANS = (Bank Charge*65536/RPMx4)/6.
#
# VAF feeds 1 bank, 3 cyls, injects every rev.
# so cyl charge = (Mass*16384)/(RPM*6) = Mass*8196/(rpm*3)
# 4000 IN at 1000 rpm in gives 10927 out (= 1 litre cyl charge)
# implying that 4000 in = 1500 L/min bank flow ?
############################################

  Calc_Cyl_AirMass:
346c: 01,3c               clrw  R3c              R3c = 0;                          # for double length div of R3e
346e: 8c,70,3c            divw  R3c,R70          R3c /= RPM;                       # R3e = Bank_Mass_Flow*32768/RPMx4
3471: dd,16               jv    3489             if (OVF = 1) goto 3489;
3473: 01,3e               clrw  R3e              R3e = 0;                          # safety clamp ?
3475: 3a,30,06            jb    B2,R30,347e      if (B2_R30 = 0)  {                # Not set - do this part
3478: 8d,06,00,3c         divw  R3c,6            R3c /= 6;                         # R3c = Bnk_Mass*16384/(RPM*6)=> cyl charge
347c: 20,04               sjmp  3482             goto 3482; }
347e: 8d,0c,00,3c         divw  R3c,c            R3c /= c;                         # Different scale ?, ONE VAF ? - NOT USED
3482: 8b,01,20,24,3c      cmpw  R3c,[R0+2420]    
3487: d1,08               jleu  3491             if ((uns) R3c > CylChMax )  {
3489: a3,01,20,24,3c      ldw   R3c,[R0+2420]    R3c = CylChMax;
348e: 91,01,69            orb   R69,1            VAF_OVF = 1; }
3491: 33,2c,0c            jnb   B3,R2c,34a0      if (Knock_Risk = 0) return;
3494: 8b,01,22,24,3c      cmpw  R3c,[R0+2422]    
3499: db,05               jc    34a0             if ((uns) R3c >= CylChKMin) return;
349b: a3,01,22,24,3c      ldw   R3c,[R0+2422]    R3c = CylChKMin; }
34a0: f0                  ret                    return;

###########################################################
# base injection time calc
# Input  = R3c, Cyl mass flow (half ?  scaled 65536 = 6 Litres ?)
# Output = R3c, Base inject time
# CALC   = (R3c * 2238)/ (INJECT_SIZE * 16384/65536) 
# 
# this is AFTER RPM calc included (i.e. = True Cyl charge)
# Later inj calc (at 38ba) is effectively 1:1 with no enrichments where 32768 = 125ms injection
# so calc becomes
# INJECT Time = (cyl_mass*4 /14.64)/INJECT_SIZE 
#
# Notes:
# 92112 in gives 32768 (125mS) out, or 0.3479cc (0.252 grams ?)
# 5872 (max cyl_charge ?) gives 8mS (0.022 cc or 0.016gms ?)
# if 2 injections = 0.044 cc, implies 10.5:1 max fuel mixture
# 10924 = 1 litre air charge (1.208g) for TWO injection events (ans 3886)
# 10924*6 = 65544 (within 0.001% of 65536) implying that scale (in) is 65536 = 6 litres. 
# 5083 gives 6.9mS for 100% VE charge at 14.64:1 (ans = 1808)
# R22 is fixed, but is probably adjusted ratio if this vehicle had an EGO ?
###############################################################


  Base_Cyl_Inj_calc:
34a1: 6d,be,08,3c         ml2w  R3c,8be          R3c *= 8be;
34a5: a3,01,1e,24,34      ldw   R34,[R0+241e]    R34 = InjSize;
34aa: 6c,22,34            ml2w  R34,R22          R34 *= Inj_Scaler;                # R22 = 0x4000 (16384)
34ad: a0,36,34            ldw   R34,R36          R34 = R36;                        # R34 = Injector size/4
34b0: 8c,34,3c            divw  R3c,R34          R3c /= R34;
34b3: d5,08               jnv   34bd             if (OVF = 0) return;
34b5: a3,01,a4,24,3c      ldw   R3c,[R0+24a4]    R3c = InjMax;
34ba: 91,01,69            orb   R69,1            VAF_OVF = 1; }
34bd: f0                  ret                    return;

#########################################################
# set various flags against RPM, checks for Cranking, underspeed,
# fuel clip (clsosing throttle) , knock risk etc
#########################################################


  Set_RPM_flags:
34be: b3,01,29,24,34      ldb   R34,[R0+2429]    R34 = RPM_CLC_0;
34c3: 99,00,34            cmpb  R34,0            
34c6: df,2f               je    34f7             if (R34 = 0) goto 34f7;           # always JUMPS

 ################## code ignored to 34f5 #################
34c8: 11,2c               clrb  R2c              RPM_flags = 0;
34ca: 3f,34,05            jb    B7,R34,34d2      if (B7_R34 = 0)  {
34cd: 71,3f,1a            an2b  R1a,3f           Underspeed = 0;
                                                 Cranking = 0;
34d0: 20,15               sjmp  34e7             goto 34e7; }
34d2: 3f,1a,0c            jb    B7,R1a,34e1      if (Cranking = 0)  {
34d5: 8b,01,6c,24,c0      cmpw  Rc0,[R0+246c]    
34da: d3,05               jnc   34e1             if ((uns) Cranktime >= Stall_Ctime)  {
34dc: a3,01,6c,24,c0      ldw   Rc0,[R0+246c]    Cranktime = Stall_Ctime; } }
34e1: 91,80,1a            orb   R1a,80           Cranking = 1;
34e4: 71,bf,1a            an2b  R1a,bf           Underspeed = 0;
34e7: 36,34,05            jnb   B6,R34,34ef      if (B6_R34 = 1)  {
34ea: 91,40,1a            orb   R1a,40           Underspeed = 1;
34ed: 20,a8               sjmp  3597             goto main_seq; }
34ef: b0,34,2c            ldb   R2c,R34          RPM_flags = R34;
34f2: 71,3f,2c            an2b  R2c,3f           B6_RPM_flags = 0;
                                                 B7_RPM_flags = 0;
34f5: 20,a0               sjmp  3597             goto main_seq;
################### end of ignored block #################

34f7: a3,01,10,24,30      ldw   R30,[R0+2410]    R30 = CnkSetRPM;
34fc: 37,1a,0c            jnb   B7,R1a,350b      if (Cranking = 0) goto 350b;
34ff: 67,01,ae,24,30      ad2w  R30,[R0+24ae]    R30 += CrankHystRPM;
3504: 88,30,70            cmpw  R70,R30          
3507: d9,24               jgtu  352d             if ((uns) RPM > R30 ) goto 352d;  # cranking cleared at 500 rpm, underspeed set.
3509: 20,8c               sjmp  3597             goto main_seq;
350b: 36,1a,29            jnb   B6,R1a,3537      if (Underspeed = 0) goto 3537;
350e: 88,30,70            cmpw  R70,R30          
3511: d9,13               jgtu  3526             if ((uns) RPM > R30 ) goto 3526;
3513: 91,c0,1a            orb   R1a,c0           Underspeed = 1;
                                                 Cranking = 1;                     # flags set if below 450 rpm
3516: 11,2c               clrb  R2c              RPM_flags = 0;
3518: 8b,01,6c,24,c0      cmpw  Rc0,[R0+246c]    
351d: d3,78               jnc   3597             if ((uns) Cranktime >= Stall_Ctime)  {
351f: a3,01,6c,24,c0      ldw   Rc0,[R0+246c]    Cranktime = Stall_Ctime;          # fail to start or stall ?
3524: 20,71               sjmp  3597             goto main_seq;
3526: 8b,01,12,24,70      cmpw  R70,[R0+2412]    
352b: d9,11               jgtu  353e             if ((uns) RPM > UspClrRPM ) goto 353e;
352d: 71,7f,1a            an2b  R1a,7f           Cranking = 0;                     # 450 < RPM < 600 ?
3530: 91,40,1a            orb   R1a,40           Underspeed = 1;
3533: 11,2c               clrb  R2c              RPM_flags = 0;
3535: 20,60               sjmp  3597             goto main_seq;
3537: 8b,01,14,24,70      cmpw  R70,[R0+2414]    
353c: d3,ef               jnc   352d             if ((uns) RPM < UspSetRPM) goto 352d;
353e: 71,3f,1a            an2b  R1a,3f           Underspeed = 0;
                                                 Cranking = 0;                     # RPM > 505 (RPM > 600 from above - hysteresis?)
3541: 9b,01,28,24,9f      cmpb  R9f,[R0+2428]    
3546: d6,0a               jge   3552             if (ECT_start < C80deg)  {
3548: 88,24,ea            cmpw  Rea,R24          
354b: db,05               jc    3552             if (Run_Time > Coldstart_secs)  {
354d: b1,01,2c            ldb   R2c,1            RPM_flags = 1;                    # Set Cold_start
3550: 20,45               sjmp  3597             goto main_seq; } }
3552: 30,20,37            jnb   B0,R20,358c      if (TPS_Closed = 0) goto 358c;
3555: 3a,2c,07            jb    B2,R2c,355f      if (Fuel_Clip = 1) goto 355f;
3558: 8b,01,16,24,70      cmpw  R70,[R0+2416]    
355d: db,11               jc    3570             if ((uns) RPM >= RPM_1500) goto 3570;
355f: 8b,01,18,24,70      cmpw  R70,[R0+2418]    
3564: db,26               jc    358c             if ((uns) RPM >= RPM_1800) goto 358c;
3566: 31,2c,02            jnb   B1,R2c,356b      if (No_Fuel = 1)  {               # RPM < 1800, throttle closed. Clip fuel instead of cutoff.
3569: 01,4e               clrw  R4e              FuelClip_timer = 0; }
356b: b1,04,2c            ldb   R2c,4            RPM_flags = 4;                    # set Fuel_Clip, clear others
356e: 20,27               sjmp  3597             goto main_seq;
3570: 9b,01,1a,24,9f      cmpb  R9f,[R0+241a]                                      # no cutoff if engine just started, or ECT out of range
3575: d2,10               jgt   3587             if (ECT_start <= C250deg)  {
3577: 9b,01,1b,24,9f      cmpb  R9f,[R0+241b]    
357c: da,09               jle   3587             if ((uns) ECT_start < C-40deg)  {
357e: 8b,01,1c,24,ea      cmpw  Rea,[R0+241c]    
3583: d9,02               jgtu  3587             if ((uns) Run_Time > Tmr_Lim_0 ) goto 3587;
3585: 27,d8               sjmp  355f             goto 355f; } }

## Not cranking ###
3587: b1,02,2c            ldb   R2c,2            RPM_flags = 2;                    # Set No_Fuel (Fuel cutoff) if > 1500 RPM, ECT OK, etc.
358a: 20,0b               sjmp  3597             goto main_seq;

# end of TPS Closing ##
358c: 32,20,05            jnb   B2,R20,3594      if (TPS_Wide = 1)  {
358f: b1,08,2c            ldb   R2c,8            RPM_flags = 8;                    # set Knock_Risk if > 1800 RPM.  Others = 0
3592: 20,03               sjmp  3597             goto main_seq; }
3594: b1,10,2c            ldb   R2c,10           RPM_flags = 10; }                 # Part Throttle = 1 [not used] others = 0 

  main_seq:
3597: 01,30               clrw  R30              R30 = 0;
3599: 51,c0,1a,30         an3b  R30,R1a,c0       R30 = IgnFlags & c0;              # get Underspeed and Cranking
359d: 90,2c,30            orb   R30,R2c          R30 |= RPM_flags;
35a0: 32,5a,04            jnb   B2,R5a,35a7      if (PUMP_Reqd = 1)  {
35a3: 81,00,01,30         orw   R30,100          R30 |= 100; }
35a7: 88,00,18            cmpw  R18,R0           
35aa: df,04               je    35b0             if (Fail_flags != 0)  {
35ac: 81,00,02,30         orw   R30,200          R30 |= 200; }                     # now have pump, fail, etc flags in one word
35b0: c3,01,5a,01,30      stw   R30,[R0+15a]     DBG_Rpm_Flags = R30;              # DEBUG? IGN + TPS flag states at func exit
35b5: e7,00,f6            jump  2bb8             goto Main_EXIT;

######################
# Compensate base flow (from cyl) for ECT and other
# Note that Inj_slope is added to inj time so must also be calibrated
# as 0-32768 -> 0-125mS ...
######################


  Enrich_Flow_calc:
35b8: a1,9c,27,32         ldw   R32,279c         R32 = Inj_slope;
35bc: a0,52,34            ldw   R34,R52          R34 = VBATT;                      # Vss-Val used only here
35bf: ef,fa,fc            call  32bc             WFuncLu1();
35c2: a0,38,50            ldw   R50,R38          Inj_slope = R38;                  # Inj_slope set only here
35c5: a1,38,28,32         ldw   R32,2838         R32 = ECT_SCALE_11;
35c9: b0,72,35            ldb   R35,R72          R35 = ECT_val;
35cc: 11,34               clrb  R34              R34 = 0;
35ce: ef,ee,fc            call  32bf             WFuncLu2();
35d1: a0,38,6a            ldw   R6a,R38          R6a = R38;                        # R6a scaled ECT 0 - 11
35d4: a1,31,25,ba         ldw   Rba,2531         Rba = Cold_Enrich;
35d8: a0,62,34            ldw   R34,R62          R34 = Cyl_Mass_BK1;
35db: ef,a7,01            call  3785             enrich_viaECT_calc();
35de: a0,3a,6e            ldw   R6e,R3a          ECT_comp_BK1 = R3a;               # 64 is 'base' answer
35e1: a1,31,25,ba         ldw   Rba,2531         Rba = Cold_Enrich;
35e5: a0,64,34            ldw   R34,R64          R34 = Cyl_Mass_BK2;
35e8: ef,9a,01            call  3785             enrich_viaECT_calc();
35eb: a0,3a,a0            ldw   Ra0,R3a          ECT_comp_BK2 = R3a;
35ee: a1,00,40,a2         ldw   Ra2,4000         Enrich_factor = 4000;             # set 16384 if cranking
35f2: 3f,1a,49            jb    B7,R1a,363e      if (Cranking = 0)  {
35f5: a1,cc,27,32         ldw   R32,27cc         R32 = ECT_Time_temp;
35f9: b0,72,34            ldb   R34,R72          R34 = ECT_val;
35fc: ef,a0,f9            call  2f9f             BFuncLu2();
35ff: ac,38,a4            ldzbw Ra4,R38          ECT_PAR_X = (uns)R38;             # Time lookup from ECT
3602: 88,ea,a4            cmpw  Ra4,Rea          
3605: d1,37               jleu  363e             if ((uns) ECT_PAR_X > Run_Time )  {
3607: a1,b4,27,32         ldw   R32,27b4         R32 = ECT_Mult_temp;
360b: b0,72,34            ldb   R34,R72          R34 = ECT_val;
360e: ef,8e,f9            call  2f9f             BFuncLu2();
3611: ac,38,3a            ldzbw R3a,R38          R3a = (uns)R38;
3614: 09,01,3a            shlw  R3a,1            R3a *= 2;
3617: 4c,ea,3a,34         ml3w  R34,R3a,Rea      R34 = R3a * Run_Time;
361b: 8c,a4,34            divw  R34,Ra4          R34 /= ECT_PAR_X;
361e: d5,05               jnv   3625             if (OVF = 1)  {
3620: 91,08,69            orb   R69,8            Flow_OVF = 1;
3623: 20,19               sjmp  363e             goto endfunc; }
3625: 09,07,3a            shlw  R3a,7            R3a *= 80;
3628: 65,00,40,3a         ad2w  R3a,4000         R3a += 4000;
362c: db,09               jc    3637             if ((uns) R3a >= 0) goto 3637;
362e: 09,07,34            shlw  R34,7            R34 *= 80;
3631: 48,34,3a,a2         sb3w  Ra2,R3a,R34      Enrich_factor = R3a - R34;        # Ra2 then used in InjCalc    (38ba)
3635: db,07               jc    363e             if (Enrich_factor > 0)  {
3637: a1,00,40,a2         ldw   Ra2,4000         Enrich_factor = 4000;
363b: 91,08,69            orb   R69,8            Flow_OVF = 1; } } }

  endfunc:
363e: e7,77,f5            jump  2bb8             goto Main_EXIT;

#######################################################################
#    Cranking calculation ?
#######################################################################

  Cranking_Inj_Calc:
3641: b0,97,34            ldb   R34,R97          R34 = VAF1_raw/256;
3644: 35,18,0b            jnb   B5,R18,3652      if (VAF1Fail = 1)  {
3647: b0,7f,34            ldb   R34,R7f          R34 = VAF2_raw/256;
364a: 31,18,05            jnb   B1,R18,3652      if (VAF2Fail = 1)  {
364d: b3,01,3b,24,34      ldb   R34,[R0+243b]    R34 = VAF_Coarse_dflt; } }
3652: 29,7c               scall 37d0             Crank_Inj_calc();
3654: c3,01,60,01,38      stw   R38,[R0+160]     Inj_Crank_Time = R38;
3659: a0,3c,a6            ldw   Ra6,R3c          VAF1_coarse_Val = R3c;
365c: b0,7f,34            ldb   R34,R7f          R34 = VAF2_raw/256;
365f: 31,18,0b            jnb   B1,R18,366d      if (VAF2Fail = 1)  {
3662: b0,97,34            ldb   R34,R97          R34 = VAF1_raw/256;
3665: 35,18,05            jnb   B5,R18,366d      if (VAF1Fail = 1)  {
3668: b3,01,3b,24,34      ldb   R34,[R0+243b]    R34 = VAF_Coarse_dflt; } }
366d: 29,61               scall 37d0             Crank_Inj_calc();
366f: c3,01,60,01,38      stw   R38,[R0+160]     Inj_Crank_Time = R38;
3674: a0,3c,bc            ldw   Rbc,R3c          VAF2_coarse_Val = R3c;
3677: 3f,1a,06            jb    B7,R1a,3680      if (Cranking = 0)  {
367a: b1,10,da            ldb   Rda,10           Par_16_BK1 = 10;
367d: b1,10,db            ldb   Rdb,10           Par_16_BK2 = 10; }
3680: e7,35,f5            jump  2bb8             goto Main_EXIT;

#################################################
# Accel pump (top level) Calculation
# includes cranking check
# base is 128 so no enrich whilst cranking
##############################################


  Calc_Accelpump:
3683: 37,1a,08            jnb   B7,R1a,368e      if (Cranking = 1)  {
3686: b1,80,dc            ldb   Rdc,80           APenr_BK1 = 80;
3689: b1,80,dd            ldb   Rdd,80           APenr_BK2 = 80;                   # fix value if cranking 1:1 (128)
368c: 20,43               sjmp  36d1             goto endfunc; }
368e: a0,e2,32            ldw   R32,Re2          R32 = Last_TPS_Pos_BK1;
3691: a0,aa,b8            ldw   Rb8,Raa          Rb8 = TPS_Posn;
3694: b0,dc,3e            ldb   R3e,Rdc          R3e = APenr_BK1;
3697: a0,a6,3c            ldw   R3c,Ra6          R3c = VAF1_coarse_Val;
369a: a0,de,30            ldw   R30,Rde          R30 = Accl_Timer_BK1;
369d: a0,ca,ba            ldw   Rba,Rca          Rba = ACL_Enrich_BK1;
36a0: 29,82               scall 3824             Accel_pump();
36a2: 3f,3f,0c            jb    B7,R3f,36b1      if (B7_R3f = 0)  {
36a5: b0,3e,dc            ldb   Rdc,R3e          APenr_BK1 = R3e;                  # NEW accel pump values to save
36a8: a0,aa,e2            ldw   Re2,Raa          Last_TPS_Pos_BK1 = TPS_Posn;
36ab: a0,ba,ca            ldw   Rca,Rba          ACL_Enrich_BK1 = Rba;
36ae: a0,30,de            ldw   Rde,R30          Accl_Timer_BK1 = R30; }
36b1: a0,e4,32            ldw   R32,Re4          R32 = Last_TPS_Pos_BK2;
36b4: b0,dd,3e            ldb   R3e,Rdd          R3e = APenr_BK2;
36b7: a0,bc,3c            ldw   R3c,Rbc          R3c = VAF2_coarse_Val;
36ba: a0,e0,30            ldw   R30,Re0          R30 = Accl_Timer_BK2;
36bd: a0,cc,ba            ldw   Rba,Rcc          Rba = ACL_enrich_BK2;
36c0: 29,62               scall 3824             Accel_pump();
36c2: 3f,3f,0c            jb    B7,R3f,36d1      if (B7_R3f = 0)  {                # NEW accel pump values to save
36c5: b0,3e,dd            ldb   Rdd,R3e          APenr_BK2 = R3e;
36c8: a0,aa,e4            ldw   Re4,Raa          Last_TPS_Pos_BK2 = TPS_Posn;
36cb: a0,ba,cc            ldw   Rcc,Rba          ACL_enrich_BK2 = Rba;
36ce: a0,30,e0            ldw   Re0,R30          Accl_Timer_BK2 = R30; }

  endfunc:
36d1: e7,e4,f4            jump  2bb8             goto Main_EXIT;

#######################################################################
#######################################################################

  Load_Calc:
36d4: a1,b8,24,3c         ldw   R3c,24b8         R3c = Load;
36d8: a0,62,30            ldw   R30,R62          R30 = Cyl_Mass_BK1;
36db: ef,c7,00            call  37a5             Load_lookup();
36de: b0,3b,28            ldb   R28,R3b          Load_BK1 = R3b;
36e1: a1,b8,24,3c         ldw   R3c,24b8         R3c = Load;
36e5: a0,64,30            ldw   R30,R64          R30 = Cyl_Mass_BK2;
36e8: ef,ba,00            call  37a5             Load_lookup();
36eb: b0,3b,29            ldb   R29,R3b          Load_BK2 = R3b;
36ee: e7,c7,f4            jump  2bb8             goto Main_EXIT;

##############################
 Fuel Clip calculation
# weaken mixture for timer7 if flag set. (600 mS)
# R30 = 64 (dflt) base = 64 (see later)
# R30 -= 58, R30 = 6.
# (timer7 * 6)/600 + 58 while timer7 < 600mS
# i.e. 58 - 64 in 600mS (1 per 100mS)
# This proc weakens mixture by 10% instantly, gradually raising back
# to 100% after time expired (600mS). triggered when throttle closing
# so prevents over rich mix (and surge ?)
##############################

  Clip_Inj_Calc:
36f1: b1,40,30            ldb   R30,40           R30 = 40;
36f4: 32,2c,1b            jnb   B2,R2c,3712      if (Fuel_Clip = 1)  {
36f7: 8b,01,60,24,4e      cmpw  R4e,[R0+2460]    
36fc: db,14               jc    3712             if (FuelClip_timer > 600mSec)  {
36fe: 7b,01,62,24,30      sb2b  R30,[R0+2462]    R30 -= Snip_58;
3703: 11,31               clrb  R31              R31 = 0;
3705: 6c,4e,30            ml2w  R30,R4e          R30 *= FuelClip_timer;
3708: 8f,01,60,24,30      divw  R30,[R0+2460]    R30 /= 600mSec;
370d: 77,01,62,24,30      ad2b  R30,[R0+2462]    R30 += Snip_58; } }
3712: c7,01,59,01,30      stb   R30,[R0+159]     Inject_Clip = R30;
3717: e7,9e,f4            jump  2bb8             goto Main_EXIT;


######################################
#    Master Inject Time Calculation
######################################

  Inject_Time_calc:
371a: a0,ce,32            ldw   R32,Rce          R32 = Inj_Cyl_BK1;
371d: b0,28,2b            ldb   R2b,R28          R2b = Load_BK1;
3720: a0,6e,ba            ldw   Rba,R6e          Rba = ECT_comp_BK1;               # 64 by default
3723: b0,dc,3e            ldb   R3e,Rdc          R3e = APenr_BK1;
3726: b0,da,b8            ldb   Rb8,Rda          Rb8 = Par_16_BK1;
3729: a3,01,60,01,38      ldw   R38,[R0+160]     R38 = Inj_Crank_Time;
372e: 29,8a               scall 38ba             Main_Inj_Calc();
3730: c3,01,4a,01,30      stw   R30,[R0+14a]     DBG_BK1_Par = R30;                # used only here (debug)
3735: a0,3a,c6            ldw   Rc6,R3a          Length_BK1 = R3a;
3738: a0,d0,32            ldw   R32,Rd0          R32 = Inj_Cyl_BK2;
373b: b0,29,2b            ldb   R2b,R29          R2b = Load_BK2;
373e: a0,a0,ba            ldw   Rba,Ra0          Rba = ECT_comp_BK2;
3741: b0,dd,3e            ldb   R3e,Rdd          R3e = APenr_BK2;
3744: b0,db,b8            ldb   Rb8,Rdb          Rb8 = Par_16_BK2;
3747: a3,01,60,01,38      ldw   R38,[R0+160]     R38 = Inj_Crank_Time;
374c: 29,6c               scall 38ba             Main_Inj_Calc();
374e: c3,01,4c,01,30      stw   R30,[R0+14c]     DBG_BK2_Par = R30;                # used only here    (debug)
3753: a0,3a,d8            ldw   Rd8,R3a          Length_BK2 = R3a;
3756: b3,01,4c,24,30      ldb   R30,[R0+244c]    R30 = FLGS_B3_B0;
375b: 3a,30,05            jb    B2,R30,3763      if (B2_R30 = 1) goto 3763;
375e: 3b,30,07            jb    B3,R30,3768      if (B3_R30 = 1) goto 3768;
3761: 20,1f               sjmp  3782             goto 3782;
3763: a0,c6,d8            ldw   Rd8,Rc6          Length_BK2 = Length_BK1;
3766: 20,1a               sjmp  3782             goto 3782;
3768: 4d,74,cb,50,34      ml3w  R34,R50,cb74     R34 = Inj_slope * cb74;           # Inj_slope in true ticks
376d: 48,36,c6,30         sb3w  R30,Rc6,R36      R30 = Length_BK1 - R36;           # R30 = Bnk1Length - Inj_slope (true ticks)
3771: 6f,01,a0,24,30      ml2w  R30,[R0+24a0]    R30 *= InjScaler;
3776: 0d,02,30            shldw R30,2            R30 *= 4;                         # R30 *= 65536, R32 = R30;
3779: 67,01,a2,24,32      ad2w  R32,[R0+24a2]    R32 += InjTrimB2;
377e: 44,32,36,d8         ad3w  Rd8,R36,R32      Length_BK2 = R36 + R32;           # Bnk2 = Bnk1 + Inj_slope + 13 (Why ? crankcase breather ?)
3782: e7,33,f4            jump  2bb8             goto Main_EXIT;


######################################
# Calculate Enrich_factor (choke equiv?) from Cyl mass Flow and ECT
# called separately for each bank (- 35db, 35e8)
# Inputs
# R6a is scaled ECT (0-11)
# R34 is Cyl_Flow
# Rba is LU table (always 2531) 12 rows...
# Tablookup answer in R3b (32 for hot engine) gives R3a 
# Output in R3a - 16384 for hot engine
######################################

  enrich_viaECT_calc:
3785: a1,a0,28,32         ldw   R32,28a0         R32 = FLOW_SCALE_5;
3789: ef,30,fb            call  32bc             WFuncLu1();
378c: a0,38,6c            ldw   R6c,R38          R6c = R38;
378f: a0,6a,30            ldw   R30,R6a          R30 = R6a;
3792: a0,6c,32            ldw   R32,R6c          R32 = R6c;
3795: a1,0c,00,34         ldw   R34,c            R34 = c;
3799: a0,ba,38            ldw   R38,Rba          R38 = Rba;
379c: ef,d8,fa            call  3277             TabLu1();                         #  answer in R3b (32 for hot engine)
379f: 11,3a               clrb  R3a              R3a = 0;
37a1: 09,01,3a            shlw  R3a,1            R3a *= 2;                         # WORD answer = table LU*2*256 (16384 hot)
37a4: f0                  ret                    return;

######################################
# Base injection Lookup
# scales flow, rpm and looks up in LOAD table.
# Answer in R3b. called separately for each bank (36d4)
######################################


  Load_lookup:
37a5: a1,58,28,32         ldw   R32,2858         R32 = RPM_SCALE_10;
37a9: a0,70,34            ldw   R34,R70          R34 = RPM;
37ac: ef,0d,fb            call  32bc             WFuncLu1();
37af: a0,38,6a            ldw   R6a,R38          R6a = R38;
37b2: a1,74,28,32         ldw   R32,2874         R32 = FLOW_SCALE_10;
37b6: a0,30,34            ldw   R34,R30          R34 = R30;
37b9: ef,00,fb            call  32bc             WFuncLu1();
37bc: a0,38,6c            ldw   R6c,R38          R6c = R38;
37bf: a0,6a,30            ldw   R30,R6a          R30 = R6a;
37c2: a0,6c,32            ldw   R32,R6c          R32 = R6c;
37c5: a1,0b,00,34         ldw   R34,b            R34 = b;
37c9: a0,3c,38            ldw   R38,R3c          R38 = R3c;
37cc: ef,a8,fa            call  3277             TabLu1();
37cf: f0                  ret                    return;

#################################
# Cranking PW calculation
# Input is R34 top of VAF Raw (VAF coarse )
# ANSWERS
# R3c plain answer to lookup table from VAF Coarse...
# ONLY IF FLAG SET - (Cranking )
# R38 is scaled as main Inj Calc where
#    0-32768 maps to 0-125mS injection time
#    R38 in 3.8147 uS units (262 ~ 1 mS).
#
#    R38 = Crank_LU * Crank_Fuel(ECT,Timer) * 83/32;
# as Crank_LU appears base 96 ?, then this is Crank_Fuel * 249
#################################


  Crank_Inj_calc:
37d0: a1,e4,27,32         ldw   R32,27e4         R32 = VAF_Coarse_TFR;
37d4: ef,c5,f7            call  2f9c             BFuncLu1();
37d7: ac,38,3c            ldzbw R3c,R38          R3c = (uns)R38;                   # R3c used as answer (~3641)
37da: 37,1a,46            jnb   B7,R1a,3823      if (Cranking = 0) return;
37dd: a0,70,34            ldw   R34,R70          R34 = RPM;                        # Crank PW calc from here
37e0: a1,f0,2a,32         ldw   R32,2af0         R32 = RPM_Crank_LU;
37e4: ef,d5,fa            call  32bc             WFuncLu1();
37e7: b0,38,b9            ldb   Rb9,R38          Rb9 = R38;                        # base is 128 ?
37ea: a1,38,28,32         ldw   R32,2838         R32 = ECT_SCALE_11;
37ee: b0,72,35            ldb   R35,R72          R35 = ECT_val;
37f1: 11,34               clrb  R34              R34 = 0;
37f3: ef,c9,fa            call  32bf             WFuncLu2();
37f6: a0,38,3e            ldw   R3e,R38          R3e = R38;
37f9: a1,d0,2a,32         ldw   R32,2ad0         R32 = SCALE_CrankTime;
37fd: a0,c0,34            ldw   R34,Rc0          R34 = Cranktime;
3800: ef,b9,fa            call  32bc             WFuncLu1();
3803: a0,38,32            ldw   R32,R38          R32 = R38;
3806: a0,3e,30            ldw   R30,R3e          R30 = R3e;
3809: a1,0c,00,34         ldw   R34,c            R34 = c;
380d: a1,54,27,38         ldw   R38,2754         R38 = Cranking_Fuel;
3811: ef,63,fa            call  3277             TabLu1();
3814: 5c,3b,b9,38         ml3b  R38,Rb9,R3b      R38 = Rb9 * R3b;
3818: af,01,26,24,34      ldzbw R34,[R0+2426]    R34 = (uns)EmgyEnrich;
381d: 6c,34,38            ml2w  R38,R34          R38 *= R34;
3820: 0c,05,38            shrdw R38,5            R38 /= 20; }
3823: f0                  ret                    return;

#################################
# Accel Pump Enrichment - called PER BANK
# Appears base scale (1:1) is 128 with min of 9 (7%), max of 64 (50% enrich)
# Calc below would define accel pump runtime is 1 sec (1008 mS) if no TPS change,
# and Rba is a 'Calc Enrich Factor' which is about 5.2 times (512/1008) ? the actual 
# enrich to feed into the linear reduction calcuation, effectively (1 sec - runtime) * Enrich factor
# Params - (apart from TPS_angle, these are PER BANK)
#
# IN     Rb8 = TPS_angle
# IN/OUT R32 = (Bx_last_TPS) Last TPS angle
#
# IN/OUT R3e = (BxAclEnr)   Enrichment factor, used in MAIN injection Calc
# IN/OUT R3c = (VAFx_coarse) Coarse VAF value (base 256 ?)
# IN/OUT R30 = (BxAccel_timer) Timer per bank (mS)
# IN/OUT Rba = (BXAccel_Factor) Original calc, ~5 times enrich 
#
# OUT    B7 R3f no change to enrich values if set
#################################


  Accel_pump:
3824: 11,3f               clrb  R3f              R3f = 0;
3826: af,01,3f,24,38      ldzbw R38,[R0+243f]    R38 = (uns)AccelP_min_Time;
382b: 88,38,30            cmpw  R30,R38          
382e: db,07               jc    3837             if ((uns) R30 >= R38) goto Accel_recalc; # remaining bank timer >= 30mS ?
3830: 99,80,3e            cmpb  R3e,80           
3833: d9,55               jgtu  388a             if ((uns) R3e > 80 ) goto Reduce_Accel_pump; # If Enriching, jump to snip_calc to fade away the enrich
3835: 20,7f               sjmp  38b6             goto No_Pchange;

##### here if accel timers > 30mS

  Accel_recalc:
3837: 48,32,b8,38         sb3w  R38,Rb8,R32      R38 = Rb8 - R32;                  # New TPS position (Angle) for this bank
383b: db,02               jc    383f             if (R38 > 0)  {
383d: 01,38               clrw  R38              R38 = 0; }
383f: a3,01,24,24,34      ldw   R34,[R0+2424]    R34 = TP_Accel_min;
3844: 08,02,34            shrw  R34,2            R34 /= 4;                         # R34 = 320 (0.025V)
3847: 88,34,38            cmpw  R38,R34          
384a: d3,3e               jnc   388a             if ((uns) R38 < R34) goto Reduce_Accel_pump; # Not enough change...
# accel pump calc
384c: a1,00,01,34         ldw   R34,100          R34 = 100;
3850: 68,3c,34            sb2w  R34,R3c          R34 -= R3c;                       # R34 = 256 - FLow (VAF_Coarse)
3853: a1,02,28,32         ldw   R32,2802         R32 = Accel_LU;
3857: ef,42,f7            call  2f9c             BFuncLu1();
385a: b0,38,af            ldb   Raf,R38          Raf = R38;                        # always returns 131
385d: a1,d8,27,32         ldw   R32,27d8         R32 = ECT_Accel_LU;
3861: b0,72,34            ldb   R34,R72          R34 = ECT_val;
3864: ef,38,f7            call  2f9f             BFuncLu2();                       # returns [19 (hot) - 127 (cold)]
3867: 7c,af,38            ml2b  R38,Raf          R38 *= Raf;                       # R38 = func(ECT)* 131 (2489 <= R38 <= 16637)
386a: 55,80,39,3e         ad3b  R3e,R39,80       R3e = R39 + 80;                   # ANSWER R3e = R38/256 + 128 (137 <= R3e <= 192)
386e: db,3c               jc    38ac             if ((uns) R3e >= 0) goto ACl_OVF;
3870: 01,30               clrw  R30              R30 = 0;
3872: 11,33               clrb  R33              R33 = 0;
3874: b0,39,32            ldb   R32,R39          R32 = R39;                        # R32 (word) = R39 (9 <= R39 <= 64)
3877: b3,01,3e,24,3b      ldb   R3b,[R0+243e]    R3b = AccelPump_Time;             # = 63
387c: 11,3a               clrb  R3a              R3a = 0;                          # R3a = 16128
387e: 8c,3a,30            divw  R30,R3a          R30 /= R3a;                       # R30 = R32*4.06 = 36 <= R30 <= 260
3881: dd,29               jv    38ac             if (OVF = 1) goto ACl_OVF;
3883: a0,30,ba            ldw   Rba,R30          Rba = R30;                        # Enrich local factor (5x actual enrichment) is saved outside proc
3886: 01,30               clrw  R30              R30 = 0;                          # Clear timer => start enrichment (outside proc)
3888: 20,2f               sjmp  38b9             return;

### gradually reduce enrich factor as time goes on #### 

  Reduce_Accel_pump:
388a: 99,80,3e            cmpb  R3e,80           
388d: d1,20               jleu  38af             if ((uns) R3e > 80 )  {
388f: a0,30,3a            ldw   R3a,R30          R3a = R30;
3892: 08,04,3a            shrw  R3a,4            R3a /= 10;                        # current enrich time/16
3895: af,01,3e,24,34      ldzbw R34,[R0+243e]    R34 = (uns)AccelPump_Time;
389a: 68,3a,34            sb2w  R34,R3a          R34 -= R3a;                       # = 63 - (timer/16)
389d: d1,10               jleu  38af             if ((uns) R34 > 0 )  {
389f: 6c,ba,34            ml2w  R34,Rba          R34 *= Rba;                       # Timer < 1008 to get here ?
38a2: dd,08               jv    38ac             if (OVF = 0)  {
38a4: 55,80,35,3e         ad3b  R3e,R35,80       R3e = R35 + 80;                   # R3e = 63-(timer/16)*Max_timer/256 + 128. Reduce enrich by time left
38a8: db,02               jc    38ac             if (R3e > 0)  {
38aa: 20,0d               sjmp  38b9             return; } }

  ACl_OVF:
38ac: 91,04,69            orb   R69,4            ACCL_OVF = 1; } }                 # DEBUG ? used only here. Calc Oflow

  Acl_pump_off:
38af: b1,80,3e            ldb   R3e,80           R3e = 80;
38b2: 01,ba               clrw  Rba              Rba = 0;                          # Reset values, Accel pump OFF.
38b4: 20,03               sjmp  38b9             return;

  No_Pchange:
38b6: 91,80,3f            orb   R3f,80           R3f |= 80;

  endfunc:
38b9: f0                  ret                    return;

################################################################
# Bank Injection time returned from here in R3a (in WDTimer ticks)
# called separately for each bank.    [- and something put in R30 for monitoring    ]
#
# Inputs
# R32  = Base cyl injection             Cyl mass flow/14.64
# Ra2  = ECT choke Scaler               16384 by default
# Rba  = Bank ECT compensation (choke)  16384    for 100% (hot engine)
# R2b  = Load compensation (VE trim ?)  128 for 100% 
# R3e  = InjnAclenr                     128 is 'base'
# Rb8  = InjnPar3                       16 (fixed in code, Always)
# R38  = Inj_Crank_PW                   If Cranking () otherwise ignored
# [159] = Time_enrich                   64 = 'base', range 58-64
#
# ANSWERS
#    R3a  =  Injection Time in CPU Timer ticks (of 4.8uS)
#    R30  =  set for debug? = Answer before base and Vss comp applied
#
#    cb74 (=52084) ticks = 0.25 secs, so R38 (in this routine) is scaled as (unsigned) 0-32768 => 0-125mS,
#    multiplied by 52084, giving 'timer ticks' in R3a (R3a = R38 * 52084/65536)
#    so 32768 = 0.3479cc of fuel (167cc/min /(60*8) for each cyl.
#    max charge for 2.792 Litre engine is 1.206 * 465cc = 0.561 grams making max injection requirement 0.3833g
#    at 14.64:1    This code does TWO injections per charge, so actual max is 0.1917g, 6.89mS or R38 = 1808 when
#    everything else is 1:1
#    calc operations in order ....
#
# R3a = enrich * Temp_Comp/65536 * Load /128*Accel_enrich /128
#       * Time_enrich /64 * Base_inj /4096 + Inj_slope * 52084/65536;
#
# (where enrich * Temp_Comp/65536 at hot engine = 4096...)
#    EQUATES TO
# Inj_Time = Choke * Load * Accel_F * Time_F * Base + Inj Slope ;
# (100% )    4096    128    128    64    256
# from 16384*16384/65536 and 16/4096
#
# If flag set (Cranking ) simply add Inj_slope to R38 and convert - 
#
# ANSWER in    R3a    =    Inj_Crank_time + Inj_slope * 52084/65536;
###############################################################


  Main_Inj_Calc:
38ba: 3f,1a,6b            jb    B7,R1a,3928      if (Cranking = 1) goto 3928;
38bd: 4c,ba,a2,38         ml3w  R38,Ra2,Rba      R38 = Enrich_factor * Rba;
38c1: a0,3a,38            ldw   R38,R3a          R38 = R3a;                        # Scale *ECT comp (4096 = 1:1 ?)
38c4: ac,2b,34            ldzbw R34,R2b          R34 = (uns)R2b;
38c7: 6c,34,38            ml2w  R38,R34          R38 *= R34;                       # * Load comp. (128 = 1:1) 
38ca: 0c,07,38            shrdw R38,7            R38 /= 80;
38cd: ac,3e,34            ldzbw R34,R3e          R34 = (uns)R3e;                   # * accel enrich (128 = 1:1)
38d0: 6c,34,38            ml2w  R38,R34          R38 *= R34;
38d3: 0c,07,38            shrdw R38,7            R38 /= 80;
38d6: af,01,59,01,34      ldzbw R34,[R0+159]     R34 = (uns)Inject_Clip;
38db: 6c,34,38            ml2w  R38,R34          R38 *= R34;
38de: 0c,06,38            shrdw R38,6            R38 /= 40;
38e1: 88,00,3a            cmpw  R3a,R0           
38e4: d7,4c               jne   3932             if (R3a != 0) goto I_Overf;
38e6: ac,b8,34            ldzbw R34,Rb8          R34 = (uns)Rb8;                   # Rb8 = 16 (could otherwise be EGR ? )
38e9: 6c,34,38            ml2w  R38,R34          R38 *= R34;
38ec: 0c,04,38            shrdw R38,4            R38 /= 10;
38ef: 88,00,3a            cmpw  R3a,R0           
38f2: d7,3e               jne   3932             if (R3a != 0) goto I_Overf;
38f4: 36,1a,10            jnb   B6,R1a,3907      if (Underspeed = 0) goto 3907;
38f7: af,01,26,24,34      ldzbw R34,[R0+2426]    R34 = (uns)EmgyEnrich;
38fc: 6c,34,38            ml2w  R38,R34          R38 *= R34;
38ff: 0c,06,38            shrdw R38,6            R38 /= 40;                        # approx 30% richen if Underspeed -
3902: 88,00,3a            cmpw  R3a,R0           
3905: d7,2b               jne   3932             if (R3a != 0) goto I_Overf;
3907: 33,2c,10            jnb   B3,R2c,391a      if (Knock_Risk = 0) goto 391a;
390a: af,01,27,24,34      ldzbw R34,[R0+2427]    R34 = (uns)KnckEnrich;            # Knock Enrich - Times 1 => redundant
390f: 6c,34,38            ml2w  R38,R34          R38 *= R34;
3912: 0c,07,38            shrdw R38,7            R38 /= 80;
3915: 88,00,3a            cmpw  R3a,R0           
3918: d7,18               jne   3932             if (R3a != 0) goto I_Overf;
391a: a0,38,30            ldw   R30,R38          R30 = R38;                        # R30 is enrich factor, base 4096 - for debug ?
391d: 6c,32,38            ml2w  R38,R32          R38 *= R32;                       # Base_inj * enrich_factor/4096 
3920: 0c,0c,38            shrdw R38,c            R38 /= 1000;
3923: 88,00,3a            cmpw  R3a,R0           
3926: d7,0a               jne   3932             if (R3a != 0) goto I_Overf;
3928: 64,50,38            ad2w  R38,R50          R38 += Inj_slope;                 # Add injector slope
392b: 8b,01,a4,24,38      cmpw  R38,[R0+24a4]    
3930: d1,08               jleu  393a             if ((uns) R38 > InjMax )  {

  I_Overf:
3932: a3,01,a4,24,38      ldw   R38,[R0+24a4]    R38 = InjMax;                     # => 125mS max
3937: 91,20,69            orb   R69,20           InjC_OVF = 1; }                   # Used only here - calc o/flow
393a: 6d,74,cb,38         ml2w  R38,cb74         R38 *= cb74;                      # effectively times 0.25 secs
393e: 37,1a,05            jnb   B7,R1a,3946      if (Cranking = 0) return;
3941: 32,20,02            jnb   B2,R20,3946      if (TPS_Wide = 0) return;
3944: 01,3a               clrw  R3a              R3a = 0; }                        # set limit if cranking and WOT
3946: f0                  ret                    return;


##########################################################
# Trip PW Output ( =>freq) calculation.
# PW limited 169 - 7fff no output if RPM = 0
# faster freq = more fuel injected
# 0x169 (361) implies 361*2*4.8uS = 288 Hz
# 0x7fff (32767) implies 32767*2*4.8uS = 3.17 Hz
# inject time is in timer ticks
# 843 ticks inject time for 3 injectors is 0.0249 grams.
# so (Elapsed Time/0.025g shots of fuel ?)
# 26000/1 = 4 hz = 0.024 grams/sec => 0.06g per Hz/'tick' ?
# 26000/72 = 288Hz = 1.75g/sec = 6.3Kg/hr = 6.3/hr = 1.389 gals/hr.
# 100Hz would be 0.6g/sec , 200Hz 1.2g ?
# so is calibration actually 1Hz = 0.01g Fuel per cyl?
##################################################


  Trip_Calc:
3947: 39,2c,0a            jb    B1,R2c,3954      if (No_Fuel = 1) goto 3954;
394a: 98,00,15            cmpb  R15,R0           
394d: d7,05               jne   3954             if (test_flags != 0) goto 3954;
394f: 88,00,70            cmpw  R70,R0           
3952: d7,05               jne   3959             if (RPM = 0)  {
3954: 71,df,5a            an2b  R5a,df           TRIP_Reqd = 0;
3957: 20,66               sjmp  39bf             goto endfunc; }
3959: a3,01,48,01,34      ldw   R34,[R0+148]     R34 = TPS_Interval;               # Why not IOTIMER ?
395e: 67,01,62,01,34      ad2w  R34,[R0+162]     R34 += TRIP_CTimeH;
3963: a3,01,64,01,36      ldw   R36,[R0+164]     R36 = TRIP_CTimeL;
3968: a4,00,36            adcw  R36,R0           R36 += CY;                        # 32 bit add CTIME + TPS_Intvl
396b: a0,34,38            ldw   R38,R34          R38 = R34;
396e: a0,36,3a            ldw   R3a,R36          R3a = R36;
3971: 0c,03,38            shrdw R38,3            R38 /= 8;
3974: 8b,01,a8,24,38      cmpw  R38,[R0+24a8]    
3979: d3,3a               jnc   39b5             if ((uns) R38 >= DOL_Freq)  {

## enter here (approx) every second (26000*8*4.8 uS [double]) 

397b: a3,01,5c,01,30      ldw   R30,[R0+15c]     R30 = Tot_Inj_L;
3980: a3,01,5e,01,32      ldw   R32,[R0+15e]     R32 = Tot_Inj_H;                  # (DBL) total injection time (- batt compensation)
3985: 8f,01,40,24,30      divw  R30,[R0+2440]    R30 /= DOL_scaler;                # R30 = Trip_Inj/843 ()
398a: c3,01,5c,01,32      stw   R32,[R0+15c]     Tot_Inj_L = R32;
398f: c3,01,5e,01,00      stw   R0,[R0+15e]      Tot_Inj_H = 0;                    # keep remainder => mod(Trip_inj,843); double
3994: 8c,30,34            divw  R34,R30          R34 /= R30;
3997: a0,34,76            ldw   R76,R34          TRIP_PW_Time = R34;               # = (Elapsed Time/(total_inj_time/843) ;
399a: 89,69,01,76         cmpw  R76,169          
399e: db,04               jc    39a4             if (TRIP_PW_Time > 169)  {
39a0: a1,69,01,76         ldw   R76,169          TRIP_PW_Time = 169; }
39a4: 89,ff,7f,76         cmpw  R76,7fff         
39a8: d1,04               jleu  39ae             if ((uns) TRIP_PW_Time > 7fff )  {
39aa: a1,ff,7f,76         ldw   R76,7fff         TRIP_PW_Time = 7fff; }
39ae: 01,34               clrw  R34              R34 = 0;
39b0: 01,36               clrw  R36              R36 = 0;                          # clear Ctime.
39b2: 91,20,5a            orb   R5a,20           TRIP_Reqd = 1; }                  # END of one sec update
39b5: c3,01,62,01,34      stw   R34,[R0+162]     TRIP_CTimeH = R34;
39ba: c3,01,64,01,36      stw   R36,[R0+164]     TRIP_CTimeL = R36;                # save Ctime (zero or accum. total)

  endfunc:
39bf: e7,f6,f1            jump  2bb8             goto Main_EXIT;

###############################################
# Fuel Pump driver, timeout check (~ 1 sec)
###############################################

  Fuel_Pump:
39c2: 91,04,5a            orb   R5a,4            PUMP_Reqd = 1;
39c5: 99,03,55            cmpb  R55,3            
39c8: d3,03               jnc   39cd             if ((uns) FPUMP_Ticks >= 3)  {
39ca: 71,fb,5a            an2b  R5a,fb           PUMP_Reqd = 0; }
39cd: e7,e8,f1            jump  2bb8             goto Main_EXIT;

#########################################################
# sensor check and STI handler
# - called from tasklist for sensor check.
# looks like R2d is simply "time powered up" - not used anywhere else
###############################################################

  Sensor_Test:
39d0: 28,b7               scall 3a89             Check_Sensors();
39d2: 99,02,2d            cmpb  R2d,2                                              # not until 2 secs since powered on ? 
39d5: d1,30               jleu  3a07             if ((uns) Pwrd_tmr <= 2) goto 3a07;
39d7: 99,00,15            cmpb  R15,0            
39da: d7,02               jne   39de             if (test_flags = 0)  {
39dc: 11,14               clrb  R14              R14 = 0; }
39de: 3a,5a,0e            jb    B2,R5a,39ef      if (PUMP_Reqd = 1) goto 39ef;
39e1: 34,5a,18            jnb   B4,R5a,39fc      if (STI_Reqd = 0) goto 39fc;
39e4: 3a,15,26            jb    B2,R15,3a0d      if (KOEO = 1) goto 3a0d;
39e7: 3b,15,10            jb    B3,R15,39fa      if (KOER = 1) goto 39fa;
39ea: b1,04,15            ldb   R15,4            test_flags = 4;                   # set KOEO STI - Engine Off
39ed: 20,1e               sjmp  3a0d             goto 3a0d;
39ef: 34,5a,15            jnb   B4,R5a,3a07      if (STI_Reqd = 0) goto 3a07;
39f2: 3b,15,05            jb    B3,R15,39fa      if (KOER = 0)  {
39f5: b1,08,15            ldb   R15,8            test_flags = 8;                   # set KOER STI - Engine Running
39f8: 11,14               clrb  R14              R14 = 0; }
39fa: 21,7c               sjmp  3b78             goto 3b78;
39fc: 39,15,64            jb    B1,R15,3a63      if (EndTest = 1) goto 3a63;
39ff: b1,02,15            ldb   R15,2            test_flags = 2;                   # SET EndTest STI reset - KOEO only
3a02: 71,f7,5a            an2b  R5a,f7           STO_Reqd = 0;
3a05: 20,5c               sjmp  3a63             goto 3a63;
3a07: 11,15               clrb  R15              test_flags = 0;
3a09: 11,14               clrb  R14              R14 = 0;
3a0b: 21,f9               sjmp  3c06             goto endfunc;

###### KOEO Test from here ########
3a0d: 99,08,67            cmpb  R67,8            
3a10: de,03               jlt   3a15             if (STI_timer >= 8)  {            # clear STO after 1 sec or more
3a12: 71,f7,5a            an2b  R5a,f7           STO_Reqd = 0; }
3a15: 71,3f,20            an2b  R20,3f           TPS_Vaf1 = 0;
                                                 TPS_Vaf2 = 0;
3a18: 3d,16,0e            jb    B5,R16,3a29      if (VAF1code = 1) goto 3a29;
3a1b: 89,00,32,96         cmpw  R96,3200         
3a1f: d3,0b               jnc   3a2c             if ((uns) VAF1_raw >= 3200)  {    # 1 volt
3a21: 99,02,14            cmpb  R14,2            
3a24: df,06               je    3a2c             if (R14 != 2)  {
3a26: 91,40,20            orb   R20,40           TPS_Vaf1 = 1;                     # VAF 1 > 1V
3a29: b1,01,14            ldb   R14,1            R14 = 1; } }
3a2c: 39,16,17            jb    B1,R16,3a46      if (VAF2code = 0)  {
3a2f: 89,00,32,7e         cmpw  R7e,3200         
3a33: d3,11               jnc   3a46             if ((uns) VAF2_raw >= 3200)  {    # 1 volt
3a35: 99,01,14            cmpb  R14,1            
3a38: de,05               jlt   3a3f             if (R14 >= 1)  {
3a3a: 91,80,20            orb   R20,80           TPS_Vaf2 = 1;                     # VAF 1 AND 2 > 1V
3a3d: 20,07               sjmp  3a46             goto 3a46; }
3a3f: 81,80,00,16         orw   R16,80           VAF_TPSCode = 1;                  # Mark fail in 'master' failflags
3a43: b1,02,14            ldb   R14,2            R14 = 2; } }
3a46: b0,b5,30            ldb   R30,Rb5          R30 = flags3;
3a49: 71,0e,30            an2b  R30,e            R30 &= e;                         # Keep Flags - NDS_Drive, NDS_Neutral, ACC_On
3a4c: 98,20,68            cmpb  R68,R20          
3a4f: d7,05               jne   3a56             if (R68 != TPS_flags) goto 3a56;
3a51: 98,30,f7            cmpb  Rf7,R30          
3a54: df,05               je    3a5b             if (Rf7 != R30)  {
3a56: 91,08,5a            orb   R5a,8            STO_Reqd = 1;
3a59: 11,67               clrb  R67              STI_timer = 0; }                  # set STO for 1 sec - TPS or NDS changed ?
3a5b: b0,20,68            ldb   R68,R20          R68 = TPS_flags;
3a5e: b0,30,f7            ldb   Rf7,R30          Rf7 = R30;                        # remember TPS and NDS flags
3a61: 21,a3               sjmp  3c06             goto endfunc;

# this is something TPS and VAF related as an end test ?    (KOEO only Engine off, no STI ) ####

3a63: ac,14,30            ldzbw R30,R14          R30 = (uns)R14;                   # 0 (OK), 1 or 2 if VAf fail
3a66: b3,31,84,3a,32      ldb   R32,[R30+3a84]   R32 = [R30+3a84];
3a6b: 71,07,20            an2b  R20,7            B3_TPS_flags = 0;
                                                 B4_TPS_flags = 0;
                                                 B5_TPS_flags = 0;
                                                 TPS_Vaf1 = 0;
                                                 TPS_Vaf2 = 0;
3a6e: 98,20,32            cmpb  R32,R20          
3a71: d7,0f               jne   3a82             if (R32 = TPS_flags)  {
3a73: 17,14               incb  R14              R14++;
3a75: 99,04,14            cmpb  R14,4            
3a78: da,08               jle   3a82             if ((uns) R14 < 4)  {
3a7a: 88,00,16            cmpw  R16,R0           
3a7d: d7,03               jne   3a82             if (codeflags = 0)  {
3a7f: 91,08,5a            orb   R5a,8            STO_Reqd = 1; } } }
3a82: 21,82               sjmp  3c06             goto endfunc;

# next table is mapped in sequence against R20 (TPS flags ) and therefore represents...
# TPS_TClosed+TPS_Closed, 0   , TPS_Wide, 0   , TPS_TClosed+TPS_Closed
# closed,                 Part, Wide,     Part, Closed  = Throttle position


3a84: 03                  byte    3

3a85: 00,04,00,03         ??    

#################################################
# check sensors function from raw A/D readings
# and update flag bits accordingly - called regularly
# This function keeps Fail_flags (R18) up to date
# and also stores flags in Rf8 - Rfd (if KOER)
#################################################


  Check_Sensors:
3a89: b1,01,66            ldb   R66,1            R66 = 1;                          # index counter to traverse vector list
3a8c: a1,01,00,38         ldw   R38,1            R38 = 1;                          # sensor_number, used for bitmap
3a90: ac,66,3a            ldzbw R3a,R66          R3a = (uns)R66;
3a93: 09,01,3a            shlw  R3a,1            R3a *= 2;                         # index*2 for word offset
3a96: a0,18,36            ldw   R36,R18          R36 = Fail_flags;                 # get current fail flags
3a99: 0c,38,34            shrdw R34,R38          R34 >>= R38;                      # B0 R36 = Fail Flag for this sensor
3a9c: a3,3a,7c,30         ldw   R30,[R3a+7c]     R30 = [R3a+7c];                   # Each (raw) sensor value
3aa0: cb,3b,a4,3a         push  [R3a+3aa4]       push([R3a+3aa4]);                 # Call checker for each sensor type
3aa4: f0                  ret                    return;



3aa5: ff                        

3aa6: c2,3a               vect  3ac2,            VAF_Check
3aa8: 6e,3b               vect  3b6e,            Skip_Sensor
3aaa: 6e,3b               vect  3b6e,            Skip_Sensor
3aac: 6e,3b               vect  3b6e,            Skip_Sensor
3aae: 6e,3b               vect  3b6e,            Skip_Sensor
3ab0: 6e,3b               vect  3b6e,            Skip_Sensor
3ab2: 6e,3b               vect  3b6e,            Skip_Sensor
3ab4: d2,3a               vect  3ad2,            TPS_Check
3ab6: e2,3a               vect  3ae2,            ECT_Check
3ab8: f2,3a               vect  3af2,            ACT_Check
3aba: 6e,3b               vect  3b6e,            Skip_Sensor
3abc: 6e,3b               vect  3b6e,            Skip_Sensor
3abe: c2,3a               vect  3ac2,            VAF_Check
3ac0: 02,3b               vect  3b02,            BAP_Check


  VAF_Check:
3ac2: 8b,01,90,24,30      cmpw  R30,[R0+2490]    
3ac7: d9,75               jgtu  3b3e             if ((uns) R30 > 5V ) goto Sensor_fail;
3ac9: 8b,01,92,24,30      cmpw  R30,[R0+2492]    
3ace: d3,6e               jnc   3b3e             if ((uns) R30 < 0.2V) goto Sensor_fail;
3ad0: 20,43               sjmp  3b15             goto Sensor_pass;

  TPS_Check:
3ad2: 8b,01,84,24,30      cmpw  R30,[R0+2484]    
3ad7: d9,65               jgtu  3b3e             if ((uns) R30 > 5V ) goto Sensor_fail;
3ad9: 8b,01,86,24,30      cmpw  R30,[R0+2486]    
3ade: d3,5e               jnc   3b3e             if ((uns) R30 < 0.125V) goto Sensor_fail;
3ae0: 20,33               sjmp  3b15             goto Sensor_pass;

  ECT_Check:
3ae2: 8b,01,88,24,30      cmpw  R30,[R0+2488]    
3ae7: d9,55               jgtu  3b3e             if ((uns) R30 > 4.6V ) goto Sensor_fail;
3ae9: 8b,01,8a,24,30      cmpw  R30,[R0+248a]    
3aee: d3,4e               jnc   3b3e             if ((uns) R30 < 0.15V) goto Sensor_fail;
3af0: 20,23               sjmp  3b15             goto Sensor_pass;

  ACT_Check:
3af2: 8b,01,8c,24,30      cmpw  R30,[R0+248c]    
3af7: d9,45               jgtu  3b3e             if ((uns) R30 > 4.6V ) goto Sensor_fail;
3af9: 8b,01,8e,24,30      cmpw  R30,[R0+248e]    
3afe: d3,3e               jnc   3b3e             if ((uns) R30 < 0.26V) goto Sensor_fail;
3b00: 20,13               sjmp  3b15             goto Sensor_pass;

  BAP_Check:
3b02: a3,01,56,01,30      ldw   R30,[R0+156]     R30 = BAP_Freq;
3b07: 8b,01,70,24,30      cmpw  R30,[R0+2470]    
3b0c: d9,30               jgtu  3b3e             if ((uns) R30 > BAP_MAX ) goto Sensor_fail;
3b0e: 8b,01,72,24,30      cmpw  R30,[R0+2472]    
3b13: d3,29               jnc   3b3e             if ((uns) R30 < BAP_MIN) goto Sensor_fail;

  Sensor_pass:
3b15: 39,15,0d            jb    B1,R15,3b25      if (EndTest = 1) goto 3b25;
3b18: 3a,15,0a            jb    B2,R15,3b25      if (KOEO = 1) goto 3b25;
3b1b: 38,36,09            jb    B0,R36,3b27      if (B0_R36 = 0)  {                # already flagged as failed ?
3b1e: 11,ba               clrb  Rba              Rba = 0;
3b20: c7,39,f7,00,ba      stb   Rba,[R38+f7]     [R38+f7] = Rba;                   # clear [f7+sensor no]
3b25: 20,45               sjmp  3b6c             goto Next_Sensor; }
3b27: b3,39,f7,00,32      ldb   R32,[R38+f7]     R32 = [R38+f7];                   # engine running (KOER), clear fail flag 
3b2c: 9b,01,2a,24,32      cmpb  R32,[R0+242a]    
3b31: d3,39               jnc   3b6c             if ((uns) R32 >= Sensor_1)  {
3b33: 71,fe,36            an2b  R36,fe           R36 &= fe;
3b36: 0d,38,34            shldw R34,R38          R34 <<= R38;
3b39: a0,36,18            ldw   R18,R36          Fail_flags = R36;                 # update 'master' copy
3b3c: 20,2e               sjmp  3b6c             goto Next_Sensor;

  Sensor_fail:
3b3e: 39,15,1b            jb    B1,R15,3b5c      if (EndTest = 1) goto 3b5c;
3b41: 3a,15,18            jb    B2,R15,3b5c      if (KOEO = 1) goto 3b5c;
3b44: 30,36,09            jnb   B0,R36,3b50      if (B0_R36 = 1)  {                # already flagged as failed ?
3b47: 11,ba               clrb  Rba              Rba = 0;
3b49: c7,39,f7,00,ba      stb   Rba,[R38+f7]     [R38+f7] = Rba;                   # clear [f7+sensor no]
3b4e: 20,1c               sjmp  3b6c             goto Next_Sensor; }
3b50: b3,39,f7,00,32      ldb   R32,[R38+f7]     R32 = [R38+f7];                   # no, new fail state
3b55: 9b,01,2b,24,32      cmpb  R32,[R0+242b]    
3b5a: d3,10               jnc   3b6c             if ((uns) R32 >= sensorx_1)  {
3b5c: 91,01,36            orb   R36,1            R36 |= 1;
3b5f: 0d,38,34            shldw R34,R38          R34 <<= R38;                      # set [f7+sensor no]
3b62: a0,36,18            ldw   R18,R36          Fail_flags = R36;
3b65: 80,36,16            orw   R16,R36          codeflags |= R36;                 # update 'master' and 'test' copies
3b68: 61,bf,ff,16         an2w  R16,ffbf         BAPcode = 0; } }                  # ignore BAP error

  Next_Sensor:
3b6c: 07,38               incw  R38              R38++;

  Skip_Sensor:
3b6e: 17,66               incb  R66              R66++;
3b70: 99,0e,66            cmpb  R66,e            
3b73: d9,02               jgtu  3b77             if ((uns) R66 > e ) return;
3b75: 27,19               sjmp  3a90             goto 3a90;
3b77: f0                  ret                    return;

###### KOER Test from Here #####

3b78: 99,00,14            cmpb  R14,0            
3b7b: d7,10               jne   3b8d             if (R14 = 0)  {
3b7d: 3d,5a,0b            jb    B5,R5a,3b8b      if (TRIP_Reqd = 0)  {
3b80: 36,b4,08            jnb   B6,Rb4,3b8b      if (DOL_rqd = 1)  {
3b83: 91,08,5a            orb   R5a,8            STO_Reqd = 1;
3b86: 11,67               clrb  R67              STI_timer = 0;                    # Timer = 16 secs (effectively)
3b88: b1,ff,14            ldb   R14,ff           R14 = ff; } }
3b8b: 20,79               sjmp  3c06             goto endfunc; }
3b8d: 99,ff,14            cmpb  R14,ff           
3b90: d7,0f               jne   3ba1             if (R14 != ff) goto 3ba1;
3b92: 99,28,67            cmpb  R67,28           
3b95: de,6f               jlt   3c06             if (STI_timer >= 28)  {           #  < 5 seconds
3b97: 71,f7,5a            an2b  R5a,f7           STO_Reqd = 0;
3b9a: 11,67               clrb  R67              STI_timer = 0;                    # reset timer to 16 secs (256) ? 
3b9c: b1,01,14            ldb   R14,1            R14 = 1;                          # start output here after 5 secs
3b9f: 20,65               sjmp  3c06             goto endfunc;
3ba1: b0,67,31            ldb   R31,R67          R31 = STI_timer;
3ba4: 08,04,30            shrw  R30,4            R30 /= 10;                        # R30 = Timer*16
3ba7: 3f,30,05            jb    B7,R30,3baf      if (B7_R30 = 0)  {
3baa: 71,f7,5a            an2b  R5a,f7           STO_Reqd = 0;                     # Timer < 16, (2 secs) skip ?
3bad: 20,57               sjmp  3c06             goto endfunc; }
3baf: 99,10,31            cmpb  R31,10           
3bb2: de,0f               jlt   3bc3             if (R31 < 10) goto 3bc3;          # Timer < 1 sec
3bb4: 11,67               clrb  R67              STI_timer = 0;
3bb6: 88,00,16            cmpw  R16,R0           
3bb9: d7,04               jne   3bbf             if (codeflags = 0)  {
3bbb: 11,14               clrb  R14              R14 = 0;
3bbd: 20,47               sjmp  3c06             goto endfunc; }
3bbf: 17,14               incb  R14              R14++;                            # R14 is sensor number
3bc1: 20,43               sjmp  3c06             goto endfunc;
3bc3: 88,00,16            cmpw  R16,R0           
3bc6: d7,07               jne   3bcf             if (codeflags = 0)  {
3bc8: a3,01,0a,3c,34      ldw   R34,[R0+3c0a]    R34 = Err_codes;                  # code 11 - all OK
3bcd: 20,1f               sjmp  3bee             goto 3bee; }
3bcf: a0,16,32            ldw   R32,R16          R32 = codeflags;
3bd2: 08,14,32            shrw  R32,R14          R32 >>= R14;
3bd5: 38,32,0b            jb    B0,R32,3be3      if (B0_R32 = 1) goto 3be3;
3bd8: 17,14               incb  R14              R14++;
3bda: 99,10,14            cmpb  R14,10           
3bdd: da,f0               jle   3bcf             if (R14 <= 10) goto 3bcf;         # all 16 bits scanned...
3bdf: 11,14               clrb  R14              R14 = 0;
3be1: 20,23               sjmp  3c06             goto endfunc;
3be3: ac,14,38            ldzbw R38,R14          R38 = (uns)R14;
3be6: 09,01,38            shlw  R38,1            R38 *= 2;                         # times 2 for word offset
3be9: a3,39,0a,3c,34      ldw   R34,[R38+3c0a]   R34 = [R38+Err_codes];
3bee: 01,36               clrw  R36              R36 = 0;                          # actual output from here
3bf0: 0d,31,34            shldw R34,R31          R34 <<= R31;
3bf3: 3f,35,05            jb    B7,R35,3bfb      if (B7_R35 = 0)  {
3bf6: 71,f7,5a            an2b  R5a,f7           STO_Reqd = 0;
3bf9: 20,03               sjmp  3bfe             goto 3bfe; }
3bfb: 91,08,5a            orb   R5a,8            STO_Reqd = 1;
3bfe: 0c,03,34            shrdw R34,3            R34 /= 8;                         # bits in groups of 3
3c01: 88,00,34            cmpw  R34,R0           
3c04: df,ae               je    3bb4             if (R34 = 0) goto 3bb4; }

  endfunc:
3c06: e7,af,ef            jump  2bb8             goto Main_EXIT;


3c09: ff                        


################ error code table ##################################
# Indexed by bit position [within word] from test subroutine - in order
# [All OK], VAF1 Fail, TPS Fail, ECT Fail, ACT Fail, VAF2 Fail, BAP Fail,
# VAF out of range, RAM Fail, ROM Fail.
####################################################################
# Haynes book indicates    11 - OK, 12 VAF1, 13 CTS, 14 ACT, 15 TPS, 22 VAF2
# 23 VAF1 and VAF2, 31 Wiring/circuit fault    32 Wiring/circuit fault.
####################################################################

3c0a: 00,48               word   4800            Err_codes                         # 11 (OK) , 22 (VAF1)

3c0c: 00,66,80,4f,00,4e,00,4f ??                                                   # 15 (TPS), 13 (ECT)
 # 14 (ACT), 12 (VAF2)
3c14: 00,4c,c0,67,00,67,00,72 ??                                                   # 25 (BAP), 23 (VAF_OR)
 # 31 (RAM), 32 (ROM)
3c1c: 00,73               ??    

#######################################
#    ISC Pulsewdith Calculation
# R38 is answer at final exit to ISC_PW
# ISC_PW is 0-32768 => 6.25mS
#######################################


  ISC_pw_calc:
3c1e: 91,20,b5            orb   Rb5,20           No_Lock_Ign_ISC = 1;              # set std 10 degrees BTDC (12 if cleared)
3c21: 3a,5a,05            jb    B2,R5a,3c29      if (PUMP_Reqd = 0)  {
3c24: a0,00,38            ldw   R38,R0           R38 = 0;                          # No ISC required if no Fuel Pump
3c27: 21,c1               sjmp  3dea             goto endfunc; }
3c29: a0,be,32            ldw   R32,Rbe          R32 = Averaged_RPM;
3c2c: a0,70,34            ldw   R34,R70          R34 = RPM;
3c2f: a3,01,4e,24,36      ldw   R36,[R0+244e]    R36 = RPM_VFilter;                # 100% of change but negated
3c34: ef,aa,f3            call  2fe1             SWfilter();
3c37: a0,3e,be            ldw   Rbe,R3e          Averaged_RPM = R3e;
3c3a: 01,38               clrw  R38              R38 = 0;
3c3c: b3,01,52,24,30      ldb   R30,[R0+2452]    R30 = ISC_FixPW;                  # fixed pulsewidth if = 1 (is zero)
3c41: 99,01,30            cmpb  R30,1            
3c44: d7,07               jne   3c4d             if (R30 = 1)  {
3c46: b3,01,53,24,39      ldb   R39,[R0+2453]    R39 = ISC_FPW;                    # Fixed ISC pulswidth in TICKS
3c4b: 21,9d               sjmp  3dea             goto endfunc; }
3c4d: 01,b8               clrw  Rb8              Rb8 = 0;                          # start PW calc
3c4f: 34,5a,0f            jnb   B4,R5a,3c61      if (STI_Reqd = 0) goto 3c61;
3c52: af,01,9a,24,32      ldzbw R32,[R0+249a]    R32 = (uns)32_secs;
3c57: 67,01,7a,24,32      ad2w  R32,[R0+247a]    R32 += 3_secs;
3c5c: 88,32,ea            cmpw  Rea,R32          
3c5f: d1,05               jleu  3c66             if ((uns) Run_Time <= R32) goto 3c66;
3c61: 99,02,30            cmpb  R30,2            
3c64: d7,07               jne   3c6d             if (R30 = 2)  {                   # always jumps...2452 is zero
3c66: 3a,ea,04            jb    B2,Rea,3c6d      if (B2_Run_Time = 0)  {
3c69: a1,20,03,b8         ldw   Rb8,320          Rb8 = 320; } }                    # add 200 rpm for 4 sec intervals ? part of self test ?
3c6d: a3,01,3c,01,3e      ldw   R3e,[R0+13c]     R3e = Last_ISC_H;
3c72: a3,01,3a,01,3c      ldw   R3c,[R0+13a]     R3c = Last_ISC_L;                 # from last calc
3c77: a1,7c,2a,32         ldw   R32,2a7c         R32 = ISC_Start_PW;
3c7b: bc,72,34            ldsbw R34,R72          R34 = (int)ECT_val;
3c7e: ef,3e,f6            call  32bf             WFuncLu2();
3c81: a0,38,ba            ldw   Rba,R38          Rba = R38;                        # Value  Used directly if TPS fail
3c84: 37,1a,0a            jnb   B7,R1a,3c91      if (Cranking = 1)  {
3c87: b3,01,51,24,39      ldb   R39,[R0+2451]    R39 = CrnKISC_PW;                 # Cranking - fixed ISC (100%) and exit
3c8c: 71,bf,5a            an2b  R5a,bf           ISC_Calc_reqd = 0;
3c8f: 21,59               sjmp  3dea             goto endfunc; }
3c91: 36,1a,0a            jnb   B6,R1a,3c9e      if (Underspeed = 1)  {
3c94: b3,01,50,24,39      ldb   R39,[R0+2450]    R39 = UspISC_PW;                  # Underspeed - fixed (80%) ISC and exit
3c99: 71,bf,5a            an2b  R5a,bf           ISC_Calc_reqd = 0;
3c9c: 21,4c               sjmp  3dea             goto endfunc; }
3c9e: 31,2c,1b            jnb   B1,R2c,3cbc      if (No_Fuel = 0) goto 3cbc;
3ca1: 3e,5a,0a            jb    B6,R5a,3cae      if (ISC_Calc_reqd = 1) goto 3cae;
3ca4: 3f,5a,38            jb    B7,R5a,3cdf      if (ISC_Tmr_reqd = 1) goto 3cdf;
3ca7: 01,f4               clrw  Rf4              ISCTimer = 0;
3ca9: 91,80,5a            orb   R5a,80           ISC_Tmr_reqd = 1;
3cac: 20,31               sjmp  3cdf             goto ISC_TimCheck;
3cae: 01,f4               clrw  Rf4              ISCTimer = 0;                     # Fuel cutoff and/or NEW TPS are set
3cb0: a0,be,34            ldw   R34,Rbe          R34 = Averaged_RPM;
3cb3: a1,64,2a,32         ldw   R32,2a64         R32 = ISC_RPM_2;                  # Straight lookup and exit
3cb7: ef,02,f6            call  32bc             WFuncLu1();
3cba: 21,2e               sjmp  3dea             goto endfunc;
3cbc: 32,18,05            jnb   B2,R18,3cc4      if (TPSFail = 1)  {               # Fuel cutoff NOT set
3cbf: a0,ba,3e            ldw   R3e,Rba          R3e = Rba;
3cc2: 20,f6               sjmp  3dba             goto ISC_Set_Final; }
3cc4: 30,20,0c            jnb   B0,R20,3cd3      if (TPS_Closed = 0) goto 3cd3;
3cc7: 38,2c,0e            jb    B0,R2c,3cd8      if (Cold_start = 1) goto 3cd8;
3cca: 8b,01,b6,24,70      cmpw  R70,[R0+24b6]    
3ccf: db,d0               jc    3ca1             if ((uns) RPM >= RPM_1200) goto 3ca1;
3cd1: 20,0c               sjmp  3cdf             goto ISC_TimCheck;
3cd3: 91,40,5a            orb   R5a,40           ISC_Calc_reqd = 1;                # TPS position changed - only called from 3cc4
3cd6: 20,e2               sjmp  3dba             goto ISC_Set_Final;
3cd8: 8b,01,56,24,70      cmpw  R70,[R0+2456]    
3cdd: db,c2               jc    3ca1             if ((uns) RPM >= RPM_1430) goto 3ca1;

  ISC_TimCheck:
3cdf: 8b,01,7a,24,ea      cmpw  Rea,[R0+247a]    
3ce4: db,05               jc    3ceb             if (Run_Time > 3_secs)  {
3ce6: a0,ba,3e            ldw   R3e,Rba          R3e = Rba;
3ce9: 20,cf               sjmp  3dba             goto ISC_Set_Final; }
3ceb: 71,df,b5            an2b  Rb5,df           No_Lock_Ign_ISC = 0;              # set 12 degree base ignition.
3cee: 71,bf,5a            an2b  R5a,bf           ISC_Calc_reqd = 0;
3cf1: a3,01,54,24,34      ldw   R34,[R0+2454]    R34 = 20mSec;
3cf6: 88,e6,34            cmpw  R34,Re6          
3cf9: d1,02               jleu  3cfd             if ((uns) R34 <= Timer6) goto 3cfd;
3cfb: 20,f2               sjmp  3def             goto 3def;
3cfd: 01,e6               clrw  Re6              Timer6 = 0;
3cff: a1,e8,29,32         ldw   R32,29e8         R32 = IDLE_ECT;
3d03: bc,72,34            ldsbw R34,R72          R34 = (int)ECT_val;
3d06: ef,b6,f5            call  32bf             WFuncLu2();
3d09: 64,38,b8            ad2w  Rb8,R38          Rb8 += R38;
3d0c: 32,b5,11            jnb   B2,Rb5,3d20      if (NDS_Neutral = 0) goto 3d20;
3d0f: 3c,b5,05            jb    B4,Rb5,3d17      if (NDS_Change = 0)  {
3d12: 91,10,b5            orb   Rb5,10           NDS_Change = 1;
3d15: 01,fe               clrw  Rfe              NDS_Timer = 0; }
3d17: 8b,01,9c,24,fe      cmpw  Rfe,[R0+249c]    
3d1c: d3,1e               jnc   3d3c             if ((uns) NDS_Timer >= 1_sec_T9)  {
3d1e: 20,0f               sjmp  3d2f             goto 3d2f;
3d20: 34,b5,05            jnb   B4,Rb5,3d28      if (NDS_Change = 1)  {
3d23: 71,ef,b5            an2b  Rb5,ef           NDS_Change = 0;
3d26: 01,fe               clrw  Rfe              NDS_Timer = 0; }
3d28: 8b,01,9e,24,fe      cmpw  Rfe,[R0+249e]    
3d2d: d9,0d               jgtu  3d3c             if ((uns) NDS_Timer <= 1_sec_T9x)  {
3d2f: bc,72,34            ldsbw R34,R72          R34 = (int)ECT_val;
3d32: a1,04,2b,32         ldw   R32,2b04         R32 = NDS_IDLE_CHANGE;
3d36: ef,86,f5            call  32bf             WFuncLu2();
3d39: 68,38,b8            sb2w  Rb8,R38          Rb8 -= R38; } }
3d3c: 35,b7,05            jnb   B5,Rb7,3d44      if (Idle_Adjust = 1)  {
3d3f: 67,01,a6,24,b8      ad2w  Rb8,[R0+24a6]    Rb8 += IdleAdjRPM; }              # add 75 rpm - Idle Speed Adjust
3d44: c3,01,32,01,b8      stw   Rb8,[R0+132]     Reqd_idle_RPM = Rb8;
3d49: 48,b8,be,34         sb3w  R34,Rbe,Rb8      R34 = Averaged_RPM - Rb8;
3d4d: c3,01,34,01,34      stw   R34,[R0+134]     Delta_ISC_RPM = R34;
3d52: 3f,35,0c            jb    B7,R35,3d61      if (B7_R35 = 0)  {
3d55: 8b,01,82,24,f4      cmpw  Rf4,[R0+2482]    
3d5a: d9,05               jgtu  3d61             if ((uns) ISCTimer <= ISC_2_secs)  {
3d5c: a0,ba,3e            ldw   R3e,Rba          R3e = Rba;
3d5f: 20,59               sjmp  3dba             goto ISC_Set_Final; } }
3d61: 71,7f,5a            an2b  R5a,7f           ISC_Tmr_reqd = 0;
3d64: a1,fc,29,32         ldw   R32,29fc         R32 = ISCxRPM;
3d68: ef,54,f5            call  32bf             WFuncLu2();
3d6b: c3,01,36,01,38      stw   R38,[R0+136]     ISC_val3 = R38;
3d70: bc,72,34            ldsbw R34,R72          R34 = (int)ECT_val;
3d73: a1,24,2a,32         ldw   R32,2a24         R32 = ECT_LU2;
3d77: ef,45,f5            call  32bf             WFuncLu2();
3d7a: c3,01,38,01,38      stw   R38,[R0+138]     DBG_ISC_V5 = R38;
3d7f: 31,b5,08            jnb   B1,Rb5,3d8a      if (NDS_Drive = 1)  {
3d82: 6f,01,aa,24,38      ml2w  R38,[R0+24aa]    R38 *= NDS_Scaler;
3d87: 0c,07,38            shrdw R38,7            R38 /= 80; }
3d8a: a3,01,36,01,32      ldw   R32,[R0+136]     R32 = ISC_val3;
3d8f: 3f,33,17            jb    B7,R33,3da9      if (B7_R33 = 1) goto 3da9;
3d92: 6c,32,38            ml2w  R38,R32          R38 *= R32;                       # R38 = ECT_LU2(ECT_val)*ISC_PW_RPM(delta_rpm) (scale redundant)
3d95: 64,38,3c            ad2w  R3c,R38          R3c += R38;
3d98: a4,3a,3e            adcw  R3e,R3a          R3e += R3a + CY;                  # 32 bit addition and overflow check follows
3d9b: 89,00,80,3e         cmpw  R3e,8000         
3d9f: d3,19               jnc   3dba             if ((uns) R3e >= 8000)  {
3da1: a1,00,80,3e         ldw   R3e,8000         R3e = 8000;
3da5: 01,3c               clrw  R3c              R3c = 0;
3da7: 20,11               sjmp  3dba             goto ISC_Set_Final;
3da9: 03,32               negw  R32              R32 = -R32;
3dab: 6c,32,38            ml2w  R38,R32          R38 *= R32;
3dae: 68,38,3c            sb2w  R3c,R38          R3c -= R38;
3db1: a8,3a,3e            sbbw  R3e,R3a          R3e -= R3a - CY;                  # 32 bit subtract
3db4: db,04               jc    3dba             if (R3e > 0)  {
3db6: 01,3c               clrw  R3c              R3c = 0;
3db8: 01,3e               clrw  R3e              R3e = 0; } }                      # add/subtract R38 from/to ISC_val_last (32 bit)

#### final ISC value in 32 bits, limit check, add NDS, ACC and lookup (slope ?) for final value ####

  ISC_Set_Final:
3dba: 8b,01,7c,24,3e      cmpw  R3e,[R0+247c]    
3dbf: d9,05               jgtu  3dc6             if ((uns) R3e <= ISC_Min)  {
3dc1: a3,01,7c,24,3e      ldw   R3e,[R0+247c]    R3e = ISC_Min; }                  # 10% minimum
3dc6: c3,01,3c,01,3e      stw   R3e,[R0+13c]     Last_ISC_H = R3e;
3dcb: c3,01,3a,01,3c      stw   R3c,[R0+13a]     Last_ISC_L = R3c;
3dd0: a0,3e,34            ldw   R34,R3e          R34 = R3e;                        # R34 = ISC_Val / 65536
3dd3: 33,b5,05            jnb   B3,Rb5,3ddb      if (ACC_On = 1)  {
3dd6: 67,01,7e,24,34      ad2w  R34,[R0+247e]    R34 += ISC_ACC_0; }               # +0%
3ddb: 31,b5,05            jnb   B1,Rb5,3de3      if (NDS_Drive = 1)  {
3dde: 67,01,80,24,34      ad2w  R34,[R0+2480]    R34 += ISC_NDS_4260; }            # +6.5% (65536 base)
3de3: a1,3c,2a,32         ldw   R32,2a3c         R32 = ISC_Slope;
3de7: ef,d2,f4            call  32bc             WFuncLu1();                       # R34 is 0-65535 for 0-100% at this point

  endfunc:
3dea: c3,01,30,01,38      stw   R38,[R0+130]     ISC_PW_Final = R38;
3def: e7,c6,ed            jump  2bb8             goto Main_EXIT;


#######################################
#    Main Timer Update function
#######################################

  Timer_Update:
3df2: 3f,1a,05            jb    B7,R1a,3dfa      if (Cranking = 0)  {
3df5: 91,02,ae            orb   Rae,2            Running = 1;                      # Continue/Start 'Engine Runnning' Timer
3df8: 20,05               sjmp  3dff             goto 3dff; }
3dfa: 71,fd,ae            an2b  Rae,fd           Running = 0;                      # Cranking -> Stop 'Engine Runnning' Timer
3dfd: 01,ea               clrw  Rea              Run_Time = 0;                     # and Zero it
3dff: ef,28,00            call  3e2a             Upd_Timers();                     # do all the other timers.
3e02: e7,b3,ed            jump  2bb8             goto Main_EXIT;


#######################################
#    Timer list and update subroutine
#######################################
#
# Rde Accl_Timer_BK1         Bank 1 Accel pump Timer (mSecs).
# Re0 Accl_Timer_BK2         Bank 2 Accel pump Timer (mSecs).
# Rea Run_Time               Engine run Timer in secs (from Cranking END, wrap at 9 hours)
# R67 STI_timer              Used for 1 second 'ticks' for STO self test codes ?
# R2d Pwrd_tmr               ? 
# Rf8-Rfd       Dummy ?
# Re6 Timer6                 related to ISC (20 msec)
# R4e FuelClip_timer         Injection weaken for 600 mS    
# Rf4 ISCTimer               ?
# Rfe NDS_Timer              NDS ?Not used ?
# Rc0 Cranktime              Cranking Timer (secs from first PIP) set at 12 for restart.
#######################################
# List Structure -> Flags, Timer location (pointer)    [Flags2, Reg ptr2 - if B0 set]
# Looks like counter values are always unsigned 2 or 4 byte entries.
# Flag (SET,    CLEAR,   description)
# B0    four,   two      byte table entry
# B1    word,   byte     count register size UNSIGNED
# B2    down,   up       count direction. Will wrap around correctly
# B3    run,    stop     counting if mask of flags2 & Reg2 zero    ** 4 entry only **
#                        (i.e. specifies stop and/or run flags for this timer)
#
# B5    count in  mSecs
# B6    count in  1/8ths sec
# B7    count in  1 sec     These bits used in a mask op at 3e91 ish.
#######################################



  Timer_List:
3e05: 22,de               struct 22, Accl_Timer_BK1,                               # Word, mSecs, Up (and next one)
3e07: 22,e0               struct 22, Accl_Timer_BK2, 
3e09: 83,ea,02,ae         struct 83, Run_Time, Running,                            # Word, secs , Up  Count if Running = 1
3e0d: 40,67               struct 40, STI_timer,                                    # Byte, 1/8s , Up
3e0f: 80,2d               struct 80, Pwrd_tmr,                                     # Byte, secs , Up
3e11: 80,f8               struct 80,    f8,                                        # Byte, secs , Up   f8 - fd
3e13: 80,f9               struct 80,    f9, 
3e15: 80,fa               struct 80,    fa,                                        #  Are these dummy or for self test ?
3e17: 80,fb               struct 80,    fb, 
3e19: 80,fc               struct 80,    fc, 
3e1b: 80,fd               struct 80,    fd, 
3e1d: 22,e6               struct 22, Timer6,                                       # Word, mSecs, Up (next 4)
3e1f: 22,4e               struct 22, FuelClip_timer, 
3e21: 22,f4               struct 22, ISCTimer, 
3e23: 22,fe               struct 22, NDS_Timer, 
3e25: 2b,c0,20,ae         struct 2b, Cranktime, First_PIP,                         # Word, mSecs, Up  Count if First_PIP = 0
3e29: 00                  byte                                                     #### end of list ####

############################################################
# Update Timers.
# NB. at 3e3c  R38 =(R38*256)/d055 is elapsed integer mSecs for 4.8uS timer [208.33 ticks per mS]
###########################################################


  Upd_Timers:
3e2a: a1,05,3e,30         ldw   R30,3e05         R30 = Timer_List;
3e2e: a0,06,36            ldw   R36,R6           R36 = IO_Timer;
3e31: 4b,01,44,01,36,38   sb3w  R38,R36,[R0+144] R38 = R36+Timers_last_run;
3e37: 01,3a               clrw  R3a              R3a = 0;
3e39: 0d,08,38            shldw R38,8            R38 *= 100;
3e3c: 8d,55,d0,38         divw  R38,d055         R38 /= d055;                      # mS elapsed since last run 
3e40: 89,00,00,38         cmpw  R38,0            
3e44: d7,02               jne   3e48             if (R38 != 0) goto 3e48;          # return if 0 mSec elapsed
3e46: 20,88               sjmp  3ed0             goto 3ed0;
3e48: 65,80,00,3a         ad2w  R3a,80           R3a += 80;                        # rounding (effectively +0.5)
3e4c: 08,08,3a            shrw  R3a,8            R3a /= 100;
3e4f: 48,3a,36,b8         sb3w  Rb8,R36,R3a      Rb8 = R36 - R3a;
3e53: c3,01,44,01,b8      stw   Rb8,[R0+144]     Timers_last_run = Rb8;
3e58: b1,20,3e            ldb   R3e,20           R3e = 20;                         # New mSec(s)
3e5b: 74,38,21            ad2b  R21,R38          mS_Count += R38;
3e5e: 59,7d,21,3f         sb3b  R3f,R21,7d       R3f = mS_Count - 7d;
3e62: d3,0f               jnc   3e73             if ((uns) R3f >= 0)  {
3e64: b0,3f,21            ldb   R21,R3f          mS_Count = R3f;                   # cycle mS count around 0-125 mSecs i.e. 1/8ths sec
3e67: 91,40,3e            orb   R3e,40           R3e |= 40;                        # New 8th sec
3e6a: e0,2a,06            djnz  R2a,3e73         8ths_sec--;
                                                 if (8ths_sec != 0) goto Next_item;
3e6d: 91,80,3e            orb   R3e,80           R3e |= 80;                        # New sec
3e70: b1,08,2a            ldb   R2a,8            8ths_sec = 8; } }

  Next_item:
3e73: b2,31,3c            ldb   R3c,[R30++]      R3c = [R30++];                    # get next entry (R3c = flags)
3e76: 99,00,3c            cmpb  R3c,0            
3e79: df,55               je    3ed0             if (R3c = 0) goto 3ed0;           # end of list, return
3e7b: ae,31,32            ldzbw R32,[R30++]      R32 = (uns)[R30++];               # register (value) pointer
3e7e: 30,3c,12            jnb   B0,R3c,3e93      if (B0_R3c = 0) goto 3e93;        # 2 word entry, skip mask check
3e81: b2,31,3d            ldb   R3d,[R30++]      R3d = [R30++];                    # 4 word entry, get flags mask
3e84: ae,31,34            ldzbw R34,[R30++]      R34 = (uns)[R30++];               # get actual flags/register
3e87: 72,34,3d            an2b  R3d,[R34]        R3d &= [R34];                     # and mask them 
3e8a: 33,3c,04            jnb   B3,R3c,3e91      if (B3_R3c = 0) goto 3e91;        # Result <> 0 to count
3e8d: df,04               je    3e93             if (R3d = 0) goto 3e93;           # Result == 0 to count
3e8f: 27,e2               sjmp  3e73             goto Next_item;
3e91: df,e0               je    3e73             if (R3d = 0) goto Next_item;      # !B3&&(3e87) mask = 0, skip count
3e93: 50,3c,3e,00         an3b  R0,R3e,R3c       R0 = R3e & R3c;                   # mask for time bits.
3e97: df,da               je    3e73             if (R0 = 0) goto Next_item;       # No time bits overlap - skip count
3e99: 31,3c,05            jnb   B1,R3c,3ea1      if (B1_R3c = 1)  {
3e9c: a2,32,36            ldw   R36,[R32]        R36 = [R32];                      # Count size is word
3e9f: 20,03               sjmp  3ea4             goto 3ea4; }
3ea1: be,32,36            ldsbw R36,[R32]        R36 = (int)[R32];                 # Count size is byte
3ea4: 32,3c,04            jnb   B2,R3c,3eab      if (B2_R3c = 0) goto 3eab;
3ea7: 03,36               negw  R36              R36 = -R36;                       # Negate if counting DOWN
3ea9: df,18               je    3ec3             if (R36 != 0)  {                  # Skip ovf checks if cntg down and zero
3eab: 3d,3c,04            jb    B5,R3c,3eb2      if (B5_R3c = 0)  {
3eae: 07,36               incw  R36              R36++;                            # inc (dec) timer value if not mS based
3eb0: 20,03               sjmp  3eb5             goto 3eb5; }
3eb2: 64,38,36            ad2w  R36,R38          R36 += R38;                       # or add true mS elapsed.
3eb5: d3,07               jnc   3ebe             if ((uns) R36 < 0) goto 3ebe;
3eb7: 01,36               clrw  R36              R36 = 0;                          # overflow - reset value to zero (up).
3eb9: 3a,3c,07            jb    B2,R3c,3ec3      if (B2_R3c = 0)  {
3ebc: 05,36               decw  R36              R36--;                            # overflow - reset value to max  (down)
3ebe: 32,3c,02            jnb   B2,R3c,3ec3      if (B2_R3c = 1)  {
3ec1: 03,36               negw  R36              R36 = -R36; } } }                 # Negate (restore) if counting down

  Save_Timer:
3ec3: 31,3c,05            jnb   B1,R3c,3ecb      if (B1_R3c = 1)  {
3ec6: c2,32,36            stw   R36,[R32]        [R32] = R36;                      # save timer - word
3ec9: 27,a8               sjmp  3e73             goto Next_item; }
3ecb: c6,32,36            stb   R36,[R32]        [R32] = R36;                      # save timer - byte
3ece: 27,a3               sjmp  3e73             goto Next_item;
3ed0: e7,e5,ec            jump  2bb8             goto Main_EXIT;

###########################################################################

  CAL_CON:
3ed3: f2                  pushp                  push(PSW);
3ed4: a3,01,00,0d,30      ldw   R30,[R0+d00]     R30 = [d00];
3ed9: 99,2a,31            cmpb  R31,2a           
3edc: df,0a               je    3ee8             if (R31 != 2a)  {
3ede: a1,5a,00,30         ldw   R30,5a           R30 = 5a;
3ee2: 05,30               decw  R30              R30--;
3ee4: d2,fc               jgt   3ee2             if (R30 > 0) goto 3ee2;           # Delay, 90 loops and then skip CALCON call
3ee6: 20,03               sjmp  3eeb             goto 3eeb; }
3ee8: ef,15,91            call  d000             d000();                           # Calibration Console code entry point
3eeb: fa                  di                     disable ints;
3eec: ff                  nop                    
3eed: f3                  popp                   PSW = pop();
3eee: e7,c7,ec            jump  2bb8             goto Main_EXIT;

###################################################
# Answer EGR_PW appears scaled as 0-32768 = 20mS  #
###################################################

  Calc_EGR_PW:
3ef1: b3,01,58,24,ba      ldb   Rba,[R0+2458]    Rba = EGR_Present;
3ef6: 99,00,ba            cmpb  Rba,0            
3ef9: df,70               je    3f6b             if (Rba != 0)  {
3efb: 99,01,ba            cmpb  Rba,1            
3efe: df,61               je    3f61             if (Rba = 1) goto 3f61;           # Fixed EGR pulswidth
3f00: 34,5a,2b            jnb   B4,R5a,3f2e      if (STI_Reqd = 0) goto 3f2e;      # not in test mode
3f03: af,01,9a,24,32      ldzbw R32,[R0+249a]    R32 = (uns)32_secs;
3f08: 67,01,7a,24,32      ad2w  R32,[R0+247a]    R32 += 3_secs;
3f0d: 88,32,ea            cmpw  Rea,R32          
3f10: d1,1c               jleu  3f2e             if ((uns) Run_Time <= R32) goto 3f2e; # less than 35 secs
3f12: af,01,9b,24,30      ldzbw R30,[R0+249b]    R30 = (uns)[249b];
3f17: 64,30,32            ad2w  R32,R30          R32 += R30;
3f1a: 88,32,ea            cmpw  Rea,R32          
3f1d: d9,0f               jgtu  3f2e             if ((uns) Run_Time > R32 ) goto 3f2e; # Greater than 67 secs
3f1f: a3,01,96,24,ba      ldw   Rba,[R0+2496]    Rba = EGR_PW2;                    # 20% on
3f24: 39,ea,3f            jb    B1,Rea,3f66      if (B1_Run_Time = 1) goto 3f66;   # 2 sec intervals ?
3f27: a3,01,98,24,ba      ldw   Rba,[R0+2498]    Rba = EGR_PW3;                    # 5% on
3f2c: 20,38               sjmp  3f66             goto 3f66;
3f2e: b0,72,34            ldb   R34,R72          R34 = ECT_val;
3f31: a1,94,2a,32         ldw   R32,2a94         R32 = EGR_ECT;
3f35: ef,67,f0            call  2f9f             BFuncLu2();
3f38: b0,38,b8            ldb   Rb8,R38          Rb8 = R38;
3f3b: b0,73,34            ldb   R34,R73          R34 = ACT_val;
3f3e: a1,9e,2a,32         ldw   R32,2a9e         R32 = EGR_ACT;
3f42: ef,5a,f0            call  2f9f             BFuncLu2();
3f45: 7c,38,b8            ml2b  Rb8,R38          Rb8 *= R38;                       # both tabs fixed at 64 (=4096)
3f48: a0,70,34            ldw   R34,R70          R34 = RPM;
3f4b: a1,a8,2a,32         ldw   R32,2aa8         R32 = RPM_SCALE_7;
3f4f: ef,6a,f3            call  32bc             WFuncLu1();
3f52: a0,38,ba            ldw   Rba,R38          Rba = R38;
3f55: a0,62,34            ldw   R34,R62          R34 = Cyl_Mass_BK1;
3f58: 28,14               scall 3f6e             EGR_AECT_calc();
3f5a: c3,01,40,01,32      stw   R32,[R0+140]     EGR_PW = R32;
3f5f: 20,0a               sjmp  3f6b             goto 3f6b;
3f61: a3,01,5a,24,ba      ldw   Rba,[R0+245a]    Rba = EGR_PW1;                    # 12.5% on
3f66: c3,01,40,01,ba      stw   Rba,[R0+140]     EGR_PW = Rba; }
3f6b: e7,4a,ec            jump  2bb8             goto Main_EXIT;

  EGR_AECT_calc:
3f6e: a1,bc,2a,32         ldw   R32,2abc         R32 = FLOW_SCALE_7;
3f72: ef,47,f3            call  32bc             WFuncLu1();
3f75: a0,38,32            ldw   R32,R38          R32 = R38;                        # scaled flow
3f78: a0,ba,30            ldw   R30,Rba          R30 = Rba;                        # multiplier from above
3f7b: a1,08,00,34         ldw   R34,8            R34 = 8;
3f7f: a1,14,27,38         ldw   R38,2714         R38 = EGR_PW_Tab;                 # all 32 in table
3f83: ef,f1,f2            call  3277             TabLu1();
3f86: 11,3a               clrb  R3a              R3a = 0;
3f88: 4c,3a,b8,30         ml3w  R30,Rb8,R3a      R30 = Rb8 * R3a;                  # =4096*32 = 131072
3f8c: 0d,04,30            shldw R30,4            R30 *= 10;                        # R32 = 32 
 
3f8f: 89,00,40,32         cmpw  R32,4000         
3f93: d1,04               jleu  3f99             if ((uns) R32 > 4000 )  {
3f95: a1,00,40,32         ldw   R32,4000         R32 = 4000; }
3f99: f0                  ret                    return;




  SubTaskList:
3f9a: d3,3e               vect  3ed3,            CAL_CON
3f9c: 17,30               vect  3017,            Process_Sensors
3f9e: 25,31               vect  3125,            Main_airflow_calc
3fa0: c9,31               vect  31c9,            Process_TPS
3fa2: 2e,32               vect  322e,            RPM_calc
3fa4: f2,3d               vect  3df2,            Timer_Update
3fa6: f4,33               vect  33f4,            Base_inj_calc
3fa8: b8,35               vect  35b8,            Enrich_Flow_calc
3faa: 41,36               vect  3641,            Cranking_Inj_Calc
3fac: 83,36               vect  3683,            Calc_Accelpump
3fae: d4,36               vect  36d4,            Load_Calc
3fb0: f1,36               vect  36f1,            Clip_Inj_Calc
3fb2: f2,3d               vect  3df2,            Timer_Update
3fb4: 1a,37               vect  371a,            Inject_Time_calc
3fb6: 47,39               vect  3947,            Trip_Calc
3fb8: da,2d               vect  2dda,            Spark_calc_1
3fba: eb,2d               vect  2deb,            IGN_clc3
3fbc: be,34               vect  34be,            Set_RPM_flags
3fbe: f2,3d               vect  3df2,            Timer_Update
3fc0: c2,39               vect  39c2,            Fuel_Pump
3fc2: 01,33               vect  3301,            Ign_Delta_Calc
3fc4: d0,39               vect  39d0,            Sensor_Test
3fc6: 1e,3c               vect  3c1e,            ISC_pw_calc
3fc8: f1,3e               vect  3ef1,            Calc_EGR_PW
3fca: f2,3d               vect  3df2,            Timer_Update



## 3fcc to 3fff = 0xff  (filler ?) ## 





