00001 /* init.c 00002 00003 Copyright 2008 Fred Cooke 00004 00005 This file is part of the FreeEMS project. 00006 00007 FreeEMS software is free software: you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation, either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 FreeEMS software is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with any FreeEMS software. If not, see <http://www.gnu.org/licenses/>. 00019 00020 We ask that if you make any changes to this file you send them upstream to us at admin@diyefi.org 00021 00022 Thank you for choosing FreeEMS to run your engine! */ 00023 00024 #define INIT_C 00025 #include "inc/freeEMS.h" 00026 #include "inc/interrupts.h" 00027 #include "inc/utils.h" 00028 #include "inc/commsISRs.h" 00029 #include "inc/init.h" 00030 #include <string.h> 00031 00032 00033 /* Set the Phase Locked Loop to our desired frequency (80MHz) and switch to using it for clock (40MHz bus speed) */ 00034 void initPLL(){ 00035 CLKSEL &= PLLSELOFF; /* Switches to base external OSCCLK to ensure PLL is not being used (off out of reset, but not sure if the monitor turns it on before passing control or not) */ 00036 PLLCTL &= PLLOFF; /* Turn the PLL device off to adjust its speed (on by default out of reset) */ 00037 REFDV = PLLDIVISOR; /* 16MHz / (3 + 1) = 4MHz Bus frequency */ 00038 SYNR = PLLMULTIPLIER; /* 4MHz * (9 + 1) = 40MHz Bus frequency */ 00039 PLLCTL |= PLLON; /* Turn the PLL device back on again at 80MHz */ 00040 00041 while (!(CRGFLG & PLLLOCK)){ 00042 /* Do nothing while we wait till the PLL loop locks onto the target frequency. */ 00043 /* Target frequency is given by (2 * (crystal frequency / (REFDV + 1)) * (SYNR + 1)) */ 00044 /* Bus frequency is half PLL frequency and given by ((crystal frequency / (REFDV + 1)) * (SYNR + 1)) */ 00045 } 00046 00047 CLKSEL = PLLSELON; /* Switches to PLL clock for internal bus frequency */ 00048 /* from MC9S12XDP512V2.pdf Section 2.4.1.1.2 page 101 Third paragraph */ 00049 /* This takes a MAXIMUM of 4 OSCCLK clock cylces PLUS 4 PLL clock cycles */ 00050 /* During this time ALL clocks freeze, and CPU activity ceases */ 00051 /* For this reason there is no point in waiting for this to occur, we already are */ 00052 } 00053 00054 /* TODO Check the code for flash errors based on stored checksum */ 00055 void checkChecksum(){ 00056 // 00057 } 00058 00059 /* Configure all the I/O to default values to keep power use down etc */ 00060 void initIO(){ 00061 /* for now, hard code all stuff to be outputs as per Freescale documentation, */ 00062 /* later what to do will be pulled from flash configuration such that all */ 00063 /* things are setup at once, and not messed with thereafter. when the port */ 00064 /* something uses is changed via the tuning interface, the confuration will be */ 00065 /* done on the fly, and the value burned to flash such that next boot happens */ 00066 /* correctly and current running devices are used in that way. */ 00067 00068 /* Turn off and on and configure all the modules in an explicit way */ 00069 // TODO set up and turn off all modules (CAN,SCI,SPI,IIC,etc) 00070 00071 /* Turn off the digital input buffers on the ATD channels */ 00072 ATD0DIEN = ZEROS; /* You are out of your mind if you waste this on digital Inputs */ 00073 ATD1DIEN0 = ZEROS; /* You are out of your mind if you waste this on digital Inputs (NOT-bonded, can't use) */ 00074 ATD1DIEN1 = ZEROS; /* You are out of your mind if you waste this on digital Inputs */ 00075 /* TODO Second half of ATD1 - can we disable this somehow */ 00076 00077 /* And configure them all for analog input */ 00078 ATD0CTL2 = 0x80; /* Turns on the ADC block. */ 00079 ATD0CTL3 = 0x40; /* Set sequence length = 8 */ 00080 ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. */ 00081 // TODO find out if this is the default (i suspect it is) 00082 // TODO look into sampling techniques 00083 00084 /* And configure them all for analog input */ 00085 ATD1CTL0 = 0x07; /* Sets wrap on 8th ADC because we can't use the other 8 */ 00086 ATD1CTL2 = 0x80; /* Turns on the ADC block. */ 00087 ATD1CTL3 = 0x40; /* Set sequence length = 8 */ 00088 ATD1CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. */ 00089 // TODO find out if this is the default (i suspect it is) 00090 // TODO look into sampling techniques 00091 00092 /* Set up the PWM component and initialise its values to off */ 00093 PWME = 0x7F; /* Turn on PWM 0 - 6 (7 is user LED on main board) */ 00094 PWMCLK = ZEROS; /* The fastest we can go for all channels */ 00095 PWMPRCLK = ZEROS; /* The fastest prescaler we can go for all channels */ 00096 PWMSCLA = ZEROS; /* The fastest we can go */ 00097 PWMSCLB = ZEROS; /* The fastest we can go */ 00098 /* TODO PWM channel concatenation for high resolution */ 00099 // join channel pairs together here (needs 16 bit regs enabled too) 00100 /* TODO Initialise pwm channels with frequency, and initial duty for real use */ 00101 // intitial PWM settings for testing 00102 /* PWM periods */ 00103 PWMPER0 = 0xFF; // 255 for ADC0 testing 00104 PWMPER1 = 0xFF; // 255 for ADC1 testing 00105 PWMPER2 = 0xFF; // 255 for ADC1 testing 00106 PWMPER3 = 0xFF; // 255 for ADC1 testing 00107 PWMPER4 = 0xFF; // 255 for ADC1 testing 00108 PWMPER5 = 0xFF; // 255 for ADC1 testing 00109 PWMPER6 = 0xFF; // 255 for ADC1 testing 00110 PWMPER7 = 0xFF; // 255 for ADC1 testing 00111 /* PWM duties */ 00112 PWMDTY0 = 0; 00113 PWMDTY1 = 0; 00114 PWMDTY2 = 0; 00115 PWMDTY3 = 0; 00116 PWMDTY4 = 0; 00117 PWMDTY5 = 0; 00118 PWMDTY6 = 0; 00119 PWMDTY7 = 0; 00120 00121 00122 /* TODO Set up the SCI0 interface for basic comms here */ 00123 00124 00125 /* Initialise the state of pins configured as output */ 00126 /* Initialise to low such that transistor grounded things are all turned off by default. */ 00127 PORTA = ZEROS; /* The serial monitor pin is on 0x40, and could cause problems if capacitance at the output is large when a reset occurs. */ 00128 PORTB = ZEROS; /* Init the rest of the spark outputs as off */ 00129 PORTE = 0x1F; /* 0b_0001_1111 : when not in use 0b_1001_1111 PE7 should be high PE5 and PE6 should be low, the rest high */ 00130 PORTK = ZEROS; 00131 PORTS = ZEROS; 00132 PORTT = ZEROS; /* All pins in off state at boot up (only matters for 2 - 7) */ 00133 PORTM = ZEROS; 00134 PORTP = ZEROS; // TODO hook these up to the adc channels such that you can vary the brightness of an led with a pot. 00135 PORTH = ZEROS; 00136 PORTJ = ZEROS; 00137 /* AD0PT1 You are out of your mind if you waste this on digital Inputs */ 00138 /* AD1PT1 You are out of your mind if you waste this on digital Inputs */ 00139 00140 /* Initialise the Data Direction Registers */ 00141 /* To outputs based on the note at the end of chapter 1.2.2 of MC9S12XDP512V2.pdf */ 00142 DDRA = ONES; /* GPIO (8) */ 00143 DDRB = ONES; /* GPIO (8) */ 00144 DDRE = 0xFC; /* 0b_1111_1100 : Clock and mode pins PE0,PE1 are input only pins, the rest are GPIO */ 00145 DDRK = ONES; /* Only 0,1,2,3,4,5,7, NOT 6 (7) */ 00146 DDRS = ONES; /* SCI0, SCI1, SPI0 (8) */ 00147 DDRT = 0xFC; /* 0b_1111_1100 set ECT pins 0,1 to IC and 2:7 to OC (8) */ 00148 DDRM = ONES; /* CAN 0 - 3 (8) */ 00149 DDRP = ONES; /* PWM pins (8) */ 00150 DDRH = ZEROS; /* All pins configured as input for misc isrs (SPI1, SPI2) (8) */ 00151 DDRJ = ONES; /* Only 0,1,6,7 are brought out on the 112 pin chip (4) */ 00152 /* Configure the non bonded pins to output to avoid current drain (112 pin package) */ 00153 DDRC = ONES; /* NON-bonded external data bus pins */ 00154 DDRD = ONES; /* NON-bonded external data bus pins */ 00155 /* AD0DDR1 You are out of your mind if you waste this on digital Inputs */ 00156 /* AD1DDR1 You are out of your mind if you waste this on digital Inputs */ 00157 } 00158 00159 00160 void initPagedRam(){ 00161 /* Take the tables and config from flash up to RAM. 00162 * 00163 * For the main tables and other paged config we need to adjust 00164 * the RPAGE value to the appropriate one before copying up. 00165 */ 00166 00167 /* Copy the tables up to their paged ram blocks through the window from flash */ 00168 RPAGE = RPAGE_FUEL_ONE; 00169 memcpy((void*)&TablesA, (void*)&VETableMainFlash, 1024); 00170 memcpy((void*)&TablesB, (void*)&VETableSecondaryFlash, 1024); 00171 memcpy((void*)&TablesC, (void*)&VETableTertiaryFlash, 1024); 00172 memcpy((void*)&TablesD, (void*)&LambdaTableFlash, 1024); 00173 RPAGE = RPAGE_FUEL_TWO; 00174 memcpy((void*)&TablesA, (void*)&VETableMainFlash2, 1024); 00175 memcpy((void*)&TablesB, (void*)&VETableSecondaryFlash2, 1024); 00176 memcpy((void*)&TablesC, (void*)&VETableTertiaryFlash2, 1024); 00177 memcpy((void*)&TablesD, (void*)&LambdaTableFlash2, 1024); 00178 RPAGE = RPAGE_TIME_ONE; 00179 memcpy((void*)&TablesA, (void*)&IgnitionAdvanceTableMainFlash, 1024); 00180 memcpy((void*)&TablesB, (void*)&IgnitionAdvanceTableSecondaryFlash, 1024); 00181 memcpy((void*)&TablesC, (void*)&InjectionAdvanceTableMainFlash, 1024); 00182 memcpy((void*)&TablesD, (void*)&InjectionAdvanceTableSecondaryFlash, 1024); 00183 RPAGE = RPAGE_TIME_TWO; 00184 memcpy((void*)&TablesA, (void*)&IgnitionAdvanceTableMainFlash2, 1024); 00185 memcpy((void*)&TablesB, (void*)&IgnitionAdvanceTableSecondaryFlash2, 1024); 00186 memcpy((void*)&TablesC, (void*)&InjectionAdvanceTableMainFlash2, 1024); 00187 memcpy((void*)&TablesD, (void*)&InjectionAdvanceTableSecondaryFlash2, 1024); 00188 RPAGE = RPAGE_TUNE_ONE; 00189 memcpy((void*)&TablesA, (void*)&SmallTablesAFlash, 1024); 00190 memcpy((void*)&TablesB, (void*)&SmallTablesBFlash, 1024); 00191 memcpy((void*)&TablesC, (void*)&SmallTablesCFlash, 1024); 00192 memcpy((void*)&TablesD, (void*)&SmallTablesDFlash, 1024); 00193 RPAGE = RPAGE_TUNE_TWO; 00194 memcpy((void*)&TablesA, (void*)&SmallTablesAFlash2, 1024); 00195 memcpy((void*)&TablesB, (void*)&SmallTablesBFlash2, 1024); 00196 memcpy((void*)&TablesC, (void*)&SmallTablesCFlash2, 1024); 00197 memcpy((void*)&TablesD, (void*)&SmallTablesDFlash2, 1024); 00198 00199 /* Default to page one for now, perhaps read the configured port straight out of reset in future? TODO */ 00200 setupPagedRAM(TRUE); // probably something like (PORTA & TableSwitchingMask) 00201 00202 // Set to four locations in page window 00203 // VETableMain = (mainTable*)0x1000; 00204 // VETableSecondary = (mainTable*)0x1400; 00205 // AdvanceTableMain = (mainTable*)0x1800; 00206 // AdvanceTableSecondary = (mainTable*)0x1C00; 00207 // 00208 // // Over write with locations of flash to ensure the rest works 00209 // VETableMain = (mainTable*)&VETableMainFlash; 00210 // VETableSecondary = (mainTable*)&VETableSecondaryFlash; 00211 // AdvanceTableMain = (mainTable*)&AdvanceTableMainFlash; 00212 // AdvanceTableSecondary = (mainTable*)&AdvanceTableSecondaryFlash; 00213 // VETableMain = &VETableMainFlash; 00214 // VETableSecondary = &VETableSecondaryFlash; 00215 // AdvanceTableMain = &AdvanceTableMainFlash; 00216 // AdvanceTableSecondary = &AdvanceTableSecondaryFlash; // warning assignment discards qualifiers from pointer target type 00217 00218 00219 // VETableTertiary = 0x1800; 00220 // LambdaTable = 0x1C00; 00221 } 00222 00223 void initStats(){ 00224 /* This should not be necessary as C defines new vars as 0 on this platform anyway, 00225 * however we'll do it just in case because it's the right thing to do. */ 00226 00227 /* Zero all the counters for various conditions */ 00228 Counters.UISRCounter = 0; 00229 Counters.lowVoltISRCounter = 0; 00230 Counters.lostCamSyncCounter = 0; 00231 Counters.lostCrankSyncCounter = 0; 00232 Counters.lostRPMValidityCounter = 0; 00233 Counters.primaryTeethCounter = 0; 00234 Counters.secondaryTeethCounter = 0; 00235 Counters.syncedADCreadingCounter = 0; 00236 Counters.timeoutADCreadingCounter = 0; 00237 Counters.calcsPerformedCounter = 0; 00238 Counters.logsSentCounter = 0; 00239 00240 00241 /* Real Time Clocks */ 00242 Clocks.millisToTenths = 0; 00243 Clocks.tenthsToSeconds = 0; 00244 Clocks.secondsToMinutes = 0; 00245 Clocks.realTimeClockMain = 0; 00246 Clocks.realTimeClockMillis = 0; 00247 Clocks.realTimeClockTenths = 0; 00248 Clocks.realTimeClockSeconds = 0; 00249 Clocks.realTimeClockMinutes = 0; 00250 Clocks.timeoutADCreadingClock = 0; 00251 00252 00253 /* These here for clarity only */ 00254 // Clocks.timerExtensionClock = 0; This does not need to be inited because we do not care what value it has 00255 // CoreVars.* = 0; These do not need to be inited as they will quickly be overwritten anyway 00256 // RuntimeVars.* = 0; These do not need to be inited as they will quickly be overwritten anyway 00257 // ADCArrays.* = 0; These do not need to be inited as they will quickly be overwritten anyway 00258 // asyncADCArrays.* = 0; These do not need to be inited as they will quickly be overwritten anyway 00259 00260 } 00261 00262 /* Initialise and set up some running variables etc here */ 00263 void initVariables(){ 00264 /* State */ 00265 coreStatusA = ZEROS16; /* See definitions in freeems.h */ 00266 mainOn = ZEROS; 00267 stagedOn = ZEROS; 00268 dwellOn = ZEROS16; 00269 selfSetTimer = ZEROS; 00270 rescheduleFuelFlags = ZEROS; 00271 00272 // Values for testing 00273 masterPulseWidth = 10; 00274 totalAngleAfterReferenceIgnition = 540; 00275 totalAngleAfterReferenceInjection = 180; 00276 00277 /* Set the banks to be the same at boot */ 00278 recordADCBank = 0; 00279 realTimeUseBank = 0; 00280 realTimeUseInjectionOffset = 0; 00281 realTimeUseIgnitionOffset = 0; 00282 /* And the opposite for the other halves */ 00283 mathInputBank = 1; 00284 mathInternalBank = 1; 00285 mathInternalInjectionOffset = INJECTION_CHANNELS; 00286 mathInternalIgnitionOffset = IGNITION_CHANNELS; 00287 00288 /* Setup the pointers to the registers for fueling use, this does NOT work if done in global.c, I still don't know why. */ 00289 injectorMainTimeRegisters[0] = TC2_ADDR; 00290 injectorMainTimeRegisters[1] = TC3_ADDR; 00291 injectorMainTimeRegisters[2] = TC4_ADDR; 00292 injectorMainTimeRegisters[3] = TC5_ADDR; 00293 injectorMainTimeRegisters[4] = TC6_ADDR; 00294 injectorMainTimeRegisters[5] = TC7_ADDR; 00295 injectorMainControlRegisters[0] = TCTL2_ADDR; 00296 injectorMainControlRegisters[1] = TCTL2_ADDR; 00297 injectorMainControlRegisters[2] = TCTL1_ADDR; 00298 injectorMainControlRegisters[3] = TCTL1_ADDR; 00299 injectorMainControlRegisters[4] = TCTL1_ADDR; 00300 injectorMainControlRegisters[5] = TCTL1_ADDR; 00301 00302 /* Ignition stuff */ 00303 dwellQueueLength = 0; 00304 ignitionQueueLength = 0; 00305 00306 // TODO perhaps read from the ds1302 once at start up and init the values or different ones with the actual time and date then update them in RTI 00307 00308 // TODO do these require init???? 00309 primaryPulsesPerSecondaryPulse = 0; 00310 primaryPulsesPerSecondaryPulseBuffer = 0; 00311 primaryLeadingEdgeTimeStamp = 0; 00312 timeBetweenSuccessivePrimaryPulses = 0; 00313 timeBetweenSuccessivePrimaryPulsesBuffer = 0; 00314 lastPrimaryPulseTimeStamp = 0; 00315 lastSecondaryOddTimeStamp = 0; 00316 00317 /* Setup so that the tacho reads low when the engine isn't running */ 00318 engineCyclePeriod = ticksPerCycleAtOneRPM; 00319 00320 // TODO remove this : Test stuff 00321 portHDebounce = 0; 00322 } 00323 00324 /* TODO initialise the flash burning configuration regs */ 00325 void initFlash(){ 00326 // TBC 00327 unsigned char flashclock; 00328 unsigned short SysClock = 16000; //TODO see if Fred already specified this var and/or move to configs/constants 00329 00330 if (SysClock >= 12000){ 00331 flashclock = (unsigned char) (SysClock/8/200 ); 00332 } 00333 else{ 00334 flashclock = (unsigned char) (SysClock/200 +1); 00335 } 00336 // TODO FIX SO EQUASION WORKS 00337 // FCLKDIV = FCLKDIV|flashclock; 00338 FCLKDIV = 0x4A; 00339 00340 FPROT = 0xFF; //disable all flash protection 00341 FSTAT = FSTAT|(PVIOL|ACCERR); //clear any errors 00342 00343 } 00344 00345 /* Set up the timer module and its various interrupts */ 00346 void initECTTimer(){ 00347 00348 // TODO rearrange the order of this stuff and pull enable and interrupt enable out to the last function call of init. 00349 00350 /* Timer channel interrupts */ 00351 TIE = 0x03; /* 0,1 IC interrupts enabled for reading engine position and RPM, 6 OC channels disabled such that no injector switching happens till scheduled */ 00352 TFLG = ONES; /* Clear all the flags such that we are up and running before they first occur */ 00353 TFLGOF = ONES; /* Clear all the flags such that we are up and running before they first occur */ 00354 00355 /* TODO Turn the timer on and set the rate and overflow interrupt */ 00356 TSCR1 = 0x88; /* 0b_1000_1000 Timer enabled, and precision timer turned on */ 00357 TSCR2 = 0x87; /* 0b_1000_0111 Overflow interrupt enable, divide by 256 if precision turned off */ 00358 // PTPSR = 0x03; /* 4 prescaler gives .1uS resolution and max period of 7ms measured */ 00359 PTPSR = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */ 00360 // PTPSR = 0x3F; /* 64 prescaler gives 1.6uS resolution and max period of 105ms measured */ 00361 // PTPSR = 0xFF; /* 256 prescaler gives 6.4uS resolution and max period of 400ms measured */ 00362 // PTPSR = 0x7F; /* 128 prescaler gives 3.2uS resolution and max period of 200ms measured */ 00363 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29&btnG=Search */ 00364 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29+*+2%5E16&btnG=Search */ 00365 /* www.mecheng.adelaide.edu.au/robotics_novell/WWW_Devs/Dragon12/LM4_Timer.pdf */ 00366 00367 /* Initial actions */ 00368 TIOS = 0xFC; /* 0b_1111_1100 0 and 1 are input capture, 2 through 7 are output compare */ 00369 TCTL1 = ZEROS; /* Set disabled at startup time, use these and other flags to switch fueling on and off inside the decoder */ 00370 TCTL2 = ZEROS; /* 0,1 have compare turned off regardless as they are in IC mode. */ 00371 TCTL3 = ZEROS; /* Capture off for 4 - 7 */ 00372 TCTL4 = 0x0F; /* Capture on both edges of two pins for IC (0,1), capture off for 2,3 */ 00373 00374 // TODO setup delay counters on 0 and 1 to filter noise (nice feature!) 00375 //DLYCT = ??; built in noise filter 00376 00377 /* Configurable tachometer output */ 00378 PTMCPSR = fixedConfigs.tachoTickFactor - 1; // Precision prescaler - fastest is 1 represented by 0, slowest/longest possible is 256 represented by 255 or 0xFF 00379 MCCNT = ONES16; // init to slowest possible, first 00380 MCCTL = 0xC4; // turn on and setup the mod down counter 00381 MCFLG = 0x80; // clear the flag up front 00382 00383 } 00384 00385 /* Configure the PIT timers for their various uses. */ 00386 void initPITTimer(){ 00387 /* */ 00388 // set micro periods 00389 PITMTLD0 = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */ 00390 PITMTLD1 = 0x1F; /* ditto */ 00391 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29 Exactly the same as for ECT */ 00392 00393 // set timers running 00394 // PITLD0 = dwellPeriod; 00395 // enable module 00396 PITCFLMT = 0x80; 00397 // enable channels 00398 //PITCE = 0x03; 00399 // enable interrupt 00400 // PITINTE = 0x01; 00401 // clear flags 00402 //PITFLT = ONES; 00403 } 00404 00405 /* Setup the sci module(s) that we need to use. */ 00406 void initSCIStuff(){ 00407 /* The alternative register set selector defaults to zero */ 00408 00409 // set the baud/data speed 00410 SCI0BD = fixedConfigs.baudDivisor; 00411 00412 // etc 00413 00414 /* Switch to alternative register set? */ 00415 00416 // etc 00417 00418 /* Switch back again? */ 00419 00420 /* 00421 * 0 = LOOPS (normal two wire operation) 00422 * 0 = SCISWAI (Wait mode on) 00423 * 0 = RSRC (if loops=1, int/ext wiring) 00424 * 1 = M MODE (9 bit operation) 00425 * 0 = WAKE (idle line wakeup) 00426 * 0 = ILT (idle line type count start pos) 00427 * 1 = PE (parity on) 00428 * 1 = PT (odd parity) (minicom defaults to no parity) 00429 * 00430 * 00010011 = 0x13 00431 */ 00432 SCI0CR1 = 0x13; 00433 00434 /* 00435 * 0 = TIE (tx data empty isr disabled) 00436 * 0 = TCIE (tx complete isr disabled) 00437 * 1 = RIE (rx full isr enabled) 00438 * 0 = ILIE (idle line isr disabled) 00439 * 1 = TE (transmit enabled) 00440 * 1 = RE (receive enabled) 00441 * 0 = RWU (rx wake up normal) 00442 * 0 = SBK (send break off) 00443 * 00444 * 00101100 = 0x2C 00445 */ 00446 SCI0CR2 = 0x2C; 00447 } 00448 00449 /* TODO Load and calculate all configuration data required to run */ 00450 void initConfiguration(){ 00451 // // TODO Calc TPS ADC range on startup or every time? this depends on whether we ensure that things work without a re init or reset or not. 00452 00453 00454 /* Add in tunable physical parameters at boot time TODO move to init.c TODO duplicate for secondary fuel? or split somehow? 00455 *nstant = ((masterConst * perCylinderVolume) / (stoichiometricAFR * injectorFlow)); 00456 *nstant = ((139371764 * 16384 ) / (15053 * 4096 )); 00457 * OR 00458 *nstant = ((masterConst / injectorFlow) * perCylinderVolume) / stoichiometricAFR; 00459 *nstant = ((139371764 / 4096 ) * 16384 ) / 15053 ; 00460 * http://www.google.com/search?hl=en&safe=off&q=((139371764++%2F+4096+++++)+*+16384+++)+%2F+15053++++&btnG=Search */ 00461 bootFuelConst = ((unsigned long)(masterFuelConstant / fixedConfigs.injectorFlow) * fixedConfigs.perCylinderVolume) / fixedConfigs.stoichiometricAFR; 00462 00463 /* The MAP range used to convert fake TPS from MAP and vice versa */ 00464 TPSMAPRange = fixedConfigs.TPSOpenMAP - fixedConfigs.TPSClosedMAP; 00465 00466 /* The ADC range used to generate TPS percentage */ 00467 TPSADCRange = fixedConfigs.TPSMaximumADC - fixedConfigs.TPSMinimumADC; 00468 00469 00470 /* Use like flags for now, just add one for each later */ 00471 unsigned char cumulativeConfigErrors = 0; 00472 00473 /* Check various aspects of config which will cause problems */ 00474 00475 /* BRV max bigger than variable that holds it */ 00476 if(((unsigned long)fixedConfigs.BRVMinimum + fixedConfigs.BRVRange) > 65535){ 00477 //sendError(BRV_MAX_TOO_LARGE); 00478 cumulativeConfigErrors++; 00479 } 00480 00481 /* Check lengths of main VE table TODO refactor into function for all main tables! */ 00482 if((VETableMainFlash.LoadLength * VETableMainFlash.RPMLength) > MAINTABLE_MAX_MAIN_LENGTH){ 00483 //sendError(VE_TABLE_MAIN_MAIN_LENGTH_TOO_LONG); 00484 cumulativeConfigErrors += 2; 00485 } 00486 if(VETableMainFlash.LoadLength > MAINTABLE_MAX_LOAD_LENGTH){ 00487 //sendError(VE_TABLE_MAIN_LOAD_LENGTH_TOO_LONG); 00488 cumulativeConfigErrors += 4; 00489 } 00490 if(VETableMainFlash.RPMLength > MAINTABLE_MAX_RPM_LENGTH){ 00491 //sendError(VE_TABLE_MAIN_RPM_LENGTH_TOO_LONG); 00492 cumulativeConfigErrors += 8; 00493 } 00494 // TODO factor the above out. 00495 00496 // TODO check all table sizes and other critical variables here! 00497 00498 /* 00499 * check ignition settings for range etc, possibly check some of those on the fly too 00500 * check fuel settings for being reasonable 00501 * check all variable tables for correct sizing 00502 * etc 00503 */ 00504 00505 while(cumulativeConfigErrors > 0){ 00506 sleep(1000); 00507 PORTS_BA ^= ONES16; // flash leds 00508 //send("There were "); 00509 //sendUC(cumulativeConfigErrors); 00510 //send(" config errors, init aborted!"); 00511 } // TODO ensure that we can recieve config and settings via serial while this is occuring! If not a bad config will lock us out all together. 00512 } 00513 00514 00515 /* Set up all the remaining interrupts */ 00516 void initInterrupts(){ 00517 /* IMPORTANT : Set the s12x vector base register (Thanks Karsten!!) */ 00518 IVBR = 0xF7; /* Without this the interrupts will never find your code! */ 00519 00520 /* Set up the Real Time Interrupt */ 00521 RTICTL = 0x81; /* 0b_1000_0001 0.125ms/125us period http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2816MHz+%2F+%282+*+10%5E3%29+%29&btnG=Search */ 00522 // RTICTL = 0xF9; /* 0b_1111_1001 0.125s/125ms period http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2816MHz+%2F+%282*10%5E6%29+%29&btnG=Search */ 00523 CRGINT |= 0x80; /* Enable the RTI */ 00524 CRGFLG = 0x80; /* Clear the RTI flag */ 00525 00526 // set up port H for testing 00527 PPSH = ZEROS; // falling edge/pull up for all 00528 PIEH = ONES; // enable all pins interrupts 00529 PIFH = ONES; // clear all port H interrupt flags 00530 00531 // TODO set up irq and xirq for testing 00532 // IRQCR for IRQ 00533 // 00534 00535 /* VReg API setup (only for wait mode? i think so) */ 00536 // VREGAPIR = 0x09C3; /* For 500ms period : (500ms - 0.2ms) / 0.2ms = 0b100111000011 = 2499 */ 00537 // VREGAPICL = 0x02; /* Enable the interrupt */ 00538 // VREGAPICL = 0x04; /* Start the counter running */ 00539 /* Writing a one to the flag will set it if it is unset, so best not to mess with it here as it probably starts off unset */ 00540 00541 /* LVI Low Voltage Interrupt enable */ 00542 VREGCTRL = 0x02; // Counts bad power events for diagnosis reasons 00543 } 00544 00545 /* Main init function to be called from main.c before enterring the main loop */ 00546 void init(){ 00547 ATOMIC_START(); /* Disable ALL interrupts while we configure the board ready for use */ 00548 initPLL(); /* Set up the PLL and use it */ 00549 checkChecksum(); /* TODO maybe checksum the code base excluding the areas of flash used for tuning data OR, include the tuning data and write a checksum in with it each time. display a warning via tacho, shiftlights, etc if stuffed. */ 00550 initIO(); /* TODO make this config dependent. Set up all the pins and modules to be in low power harmless states */ 00551 initPagedRam(); /* Copy table and config blocks of data from flash to the paged ram blocks for fast data lookup */ 00552 initStats(); /* Initialise all statistics variables */ 00553 initVariables(); /* Initialise the rest of the running variables etc */ 00554 initFlash(); /* TODO, populate */ 00555 initECTTimer(); /* TODO move this to inside config in an organised way. Set up the timer module and its various aspects */ 00556 initPITTimer(); /* TODO ditto... */ 00557 initSCIStuff(); /* Setup the sci module(s) that we will use. */ 00558 initConfiguration(); /* TODO Set user/feature/config up here! */ 00559 initInterrupts(); /* still last, reset timers, enable interrupts here TODO move this to inside config in an organised way. Set up the rest of the individual interrupts */ 00560 ATOMIC_END(); /* Re-enable any configured interrupts */ 00561 }