00001 /* FreeEMS - the open source engine management system 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 email them upstream to 00021 us at admin(at)diyefi(dot)org or, even better, fork the code on github.com! 00022 00023 Thank you for choosing FreeEMS to run your engine! */ 00024 00025 00044 #define INIT_C 00045 #include "inc/freeEMS.h" 00046 #include "inc/interrupts.h" 00047 #include "inc/utils.h" 00048 #include "inc/commsISRs.h" 00049 #include "inc/pagedLocationBuffers.h" 00050 #include "inc/init.h" 00051 #include <string.h> 00052 00053 00062 void init(){ 00063 ATOMIC_START(); /* Disable ALL interrupts while we configure the board ready for use */ 00064 initPLL(); /* Set up the PLL and use it */ 00065 initIO(); /* TODO make this config dependent. Set up all the pins and modules to be in low power harmless states */ 00066 initAllPagedRAM(); /* Copy table and config blocks of data from flash to the paged ram blocks for fast data lookup */ 00067 initAllPagedAddresses(); /* Save the paged memory addresses to variables such that we can access them from another paged block with no warnings */ 00068 initVariables(); /* Initialise the rest of the running variables etc */ 00069 initFlash(); /* TODO, finalise this */ 00070 initECTTimer(); /* TODO move this to inside config in an organised way. Set up the timer module and its various aspects */ 00071 initPITTimer(); /* TODO ditto... */ 00072 initSCIStuff(); /* Setup the sci module(s) that we will use. */ 00073 initConfiguration(); /* TODO Set user/feature/config up here! */ 00074 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 */ 00075 ATOMIC_END(); /* Re-enable any configured interrupts */ 00076 } 00077 00078 00079 /* used to chop out all the init stuff at compile time for hardware testing. */ 00080 //#define NO_INIT 00081 00082 00090 void initPLL(){ 00091 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) */ 00092 PLLCTL &= PLLOFF; /* Turn the PLL device off to adjust its speed (on by default out of reset) */ 00093 REFDV = PLLDIVISOR; /* 16MHz / (3 + 1) = 4MHz Bus frequency */ 00094 SYNR = PLLMULTIPLIER; /* 4MHz * (9 + 1) = 40MHz Bus frequency */ 00095 PLLCTL |= PLLON; /* Turn the PLL device back on again at 80MHz */ 00096 00097 while (!(CRGFLG & PLLLOCK)){ 00098 /* Do nothing while we wait till the PLL loop locks onto the target frequency. */ 00099 /* Target frequency is given by (2 * (crystal frequency / (REFDV + 1)) * (SYNR + 1)) */ 00100 /* Bus frequency is half PLL frequency and given by ((crystal frequency / (REFDV + 1)) * (SYNR + 1)) */ 00101 } 00102 00103 CLKSEL = PLLSELON; /* Switches to PLL clock for internal bus frequency */ 00104 /* from MC9S12XDP512V2.pdf Section 2.4.1.1.2 page 101 Third paragraph */ 00105 /* "This takes a MAXIMUM of 4 OSCCLK clock cylces PLUS 4 PLL clock cycles" */ 00106 /* "During this time ALL clocks freeze, and CPU activity ceases" */ 00107 /* Therefore there is no point waiting for this to occur, we already are... */ 00108 } 00109 00110 00111 /* Configure all the I/O to default values to keep power use down etc */ 00112 void initIO(){ 00113 /* for now, hard code all stuff to be outputs as per Freescale documentation, */ 00114 /* later what to do will be pulled from flash configuration such that all */ 00115 /* things are setup at once, and not messed with thereafter. when the port */ 00116 /* something uses is changed via the tuning interface, the confuration will be */ 00117 /* done on the fly, and the value burned to flash such that next boot happens */ 00118 /* correctly and current running devices are used in that way. */ 00119 00120 /* Turn off and on and configure all the modules in an explicit way */ 00121 // TODO set up and turn off all modules (CAN,SCI,SPI,IIC,etc) 00122 00123 /* Turn off the digital input buffers on the ATD channels */ 00124 ATD0DIEN = ZEROS; /* You are out of your mind if you waste this on digital Inputs */ 00125 ATD1DIEN0 = ZEROS; /* You are out of your mind if you waste this on digital Inputs (NOT-bonded, can't use) */ 00126 ATD1DIEN1 = ZEROS; /* You are out of your mind if you waste this on digital Inputs */ 00127 /* TODO Second half of ATD1 - can we disable this somehow */ 00128 00129 /* And configure them all for analog input */ 00130 ATD0CTL2 = 0x80; /* Turns on the ADC block. */ 00131 ATD0CTL3 = 0x40; /* Set sequence length = 8 */ 00132 ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. */ 00133 // TODO find out if this is the default (i suspect it is) 00134 // TODO look into sampling techniques 00135 00136 /* And configure them all for analog input */ 00137 ATD1CTL0 = 0x07; /* Sets wrap on 8th ADC because we can't use the other 8 */ 00138 ATD1CTL2 = 0x80; /* Turns on the ADC block. */ 00139 ATD1CTL3 = 0x40; /* Set sequence length = 8 */ 00140 ATD1CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. */ 00141 // TODO find out if this is the default (i suspect it is) 00142 // TODO look into sampling techniques 00143 00144 #ifndef NO_INIT 00145 /* Set up the PWM component and initialise its values to off */ 00146 PWME = 0x7F; /* Turn on PWM 0 - 6 (7 is user LED on main board) */ 00147 PWMCLK = ZEROS; /* The fastest we can go for all channels */ 00148 PWMPRCLK = ZEROS; /* The fastest prescaler we can go for all channels */ 00149 PWMSCLA = ZEROS; /* The fastest we can go */ 00150 PWMSCLB = ZEROS; /* The fastest we can go */ 00151 /* TODO PWM channel concatenation for high resolution */ 00152 // join channel pairs together here (needs 16 bit regs enabled too) 00153 /* TODO Initialise pwm channels with frequency, and initial duty for real use */ 00154 // initial PWM settings for testing 00155 /* PWM periods */ 00156 PWMPER0 = 0xFF; // 255 for ADC0 testing 00157 PWMPER1 = 0xFF; // 255 for ADC1 testing 00158 PWMPER2 = 0xFF; // 255 for ADC1 testing 00159 PWMPER3 = 0xFF; // 255 for ADC1 testing 00160 PWMPER4 = 0xFF; // 255 for ADC1 testing 00161 PWMPER5 = 0xFF; // 255 for ADC1 testing 00162 PWMPER6 = 0xFF; // 255 for ADC1 testing 00163 PWMPER7 = 0xFF; // 255 for ADC1 testing 00164 /* PWM duties */ 00165 PWMDTY0 = 0; 00166 PWMDTY1 = 0; 00167 PWMDTY2 = 0; 00168 PWMDTY3 = 0; 00169 PWMDTY4 = 0; 00170 PWMDTY5 = 0; 00171 PWMDTY6 = 0; 00172 PWMDTY7 = 0; 00173 00174 00175 /* Initialise the state of pins configured as output */ 00176 /* Initialise to low such that transistor grounded things are all turned off by default. */ 00177 PORTA = ZEROS; /* The serial monitor pin is on 0x40, and could cause problems if capacitance at the output is large when a reset occurs. */ 00178 PORTB = ZEROS; /* Init the rest of the spark outputs as off */ 00179 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 */ 00180 PORTK = ZEROS; 00181 PORTS = ZEROS; 00182 PORTT = ZEROS; /* All pins in off state at boot up (only matters for 2 - 7) */ 00183 PORTM = ZEROS; 00184 PORTP = ZEROS; // TODO hook these up to the adc channels such that you can vary the brightness of an led with a pot. 00185 PORTH = ZEROS; 00186 PORTJ = ZEROS; 00187 /* AD0PT1 You are out of your mind if you waste this on digital Inputs */ 00188 /* AD1PT1 You are out of your mind if you waste this on digital Inputs */ 00189 00190 /* Initialise the Data Direction Registers */ 00191 /* To outputs based on the note at the end of chapter 1.2.2 of MC9S12XDP512V2.pdf */ 00192 DDRA = ONES; /* GPIO (8) */ 00193 DDRB = ONES; /* GPIO (8) */ 00194 DDRE = 0xFC; /* 0b_1111_1100 : Clock and mode pins PE0,PE1 are input only pins, the rest are GPIO */ 00195 DDRK = ONES; /* Only 0,1,2,3,4,5,7, NOT 6 (7) */ 00196 DDRS = ONES; /* SCI0, SCI1, SPI0 (8) */ 00197 DDRT = 0xFC; /* 0b_1111_1100 set ECT pins 0,1 to IC and 2:7 to OC (8) */ 00198 DDRM = ONES; /* CAN 0 - 3 (8) */ 00199 DDRP = ONES; /* PWM pins (8) */ 00200 DDRH = ZEROS; /* All pins configured as input for misc isrs (SPI1, SPI2) (8) */ 00201 DDRJ = ONES; /* Only 0,1,6,7 are brought out on the 112 pin chip (4) */ 00202 /* Configure the non bonded pins to output to avoid current drain (112 pin package) */ 00203 DDRC = ONES; /* NON-bonded external data bus pins */ 00204 DDRD = ONES; /* NON-bonded external data bus pins */ 00205 /* AD0DDR1 You are out of your mind if you waste this on digital Inputs */ 00206 /* AD1DDR1 You are out of your mind if you waste this on digital Inputs */ 00207 #endif 00208 } 00209 00210 00219 void initLookupAddresses(){ 00220 IATTransferTableLocation = (void*)&IATTransferTable; 00221 CHTTransferTableLocation = (void*)&CHTTransferTable; 00222 MAFTransferTableLocation = (void*)&MAFTransferTable; 00223 TestTransferTableLocation = (void*)&TestTransferTable; 00224 } 00225 00226 00235 void initFuelAddresses(){ 00236 /* Setup addresses within the page to avoid warnings */ 00237 VETableMainFlashLocation = (void*)&VETableMainFlash; 00238 VETableSecondaryFlashLocation = (void*)&VETableSecondaryFlash; 00239 VETableTertiaryFlashLocation = (void*)&VETableTertiaryFlash; 00240 LambdaTableFlashLocation = (void*)&LambdaTableFlash; 00241 VETableMainFlash2Location = (void*)&VETableMainFlash2; 00242 VETableSecondaryFlash2Location = (void*)&VETableSecondaryFlash2; 00243 VETableTertiaryFlash2Location = (void*)&VETableTertiaryFlash2; 00244 LambdaTableFlash2Location = (void*)&LambdaTableFlash2; 00245 } 00246 00247 00254 void initPagedRAMFuel(void){ 00255 /* Copy the tables from flash to RAM */ 00256 RPAGE = RPAGE_FUEL_ONE; 00257 memcpy((void*)&TablesA, VETableMainFlashLocation, MAINTABLE_SIZE); 00258 memcpy((void*)&TablesB, (void*)&VETableSecondaryFlash, MAINTABLE_SIZE); 00259 memcpy((void*)&TablesC, (void*)&VETableTertiaryFlash, MAINTABLE_SIZE); 00260 memcpy((void*)&TablesD, (void*)&LambdaTableFlash, MAINTABLE_SIZE); 00261 RPAGE = RPAGE_FUEL_TWO; 00262 memcpy((void*)&TablesA, (void*)&VETableMainFlash2, MAINTABLE_SIZE); 00263 memcpy((void*)&TablesB, (void*)&VETableSecondaryFlash2, MAINTABLE_SIZE); 00264 memcpy((void*)&TablesC, (void*)&VETableTertiaryFlash2, MAINTABLE_SIZE); 00265 memcpy((void*)&TablesD, (void*)&LambdaTableFlash2, MAINTABLE_SIZE); 00266 } 00267 00268 00277 void initTimingAddresses(){ 00278 /* Setup addresses within the page to avoid warnings */ 00279 IgnitionAdvanceTableMainFlashLocation = (void*)&IgnitionAdvanceTableMainFlash; 00280 IgnitionAdvanceTableSecondaryFlashLocation = (void*)&IgnitionAdvanceTableSecondaryFlash; 00281 InjectionAdvanceTableMainFlashLocation = (void*)&InjectionAdvanceTableMainFlash; 00282 InjectionAdvanceTableSecondaryFlashLocation = (void*)&InjectionAdvanceTableSecondaryFlash; 00283 IgnitionAdvanceTableMainFlash2Location = (void*)&IgnitionAdvanceTableMainFlash2; 00284 IgnitionAdvanceTableSecondaryFlash2Location = (void*)&IgnitionAdvanceTableSecondaryFlash2; 00285 InjectionAdvanceTableMainFlash2Location = (void*)&InjectionAdvanceTableMainFlash2; 00286 InjectionAdvanceTableSecondaryFlash2Location = (void*)&InjectionAdvanceTableSecondaryFlash2; 00287 } 00288 00289 00296 void initPagedRAMTime(){ 00297 /* Copy the tables from flash to RAM */ 00298 RPAGE = RPAGE_TIME_ONE; 00299 memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlashLocation, MAINTABLE_SIZE); 00300 memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlashLocation, MAINTABLE_SIZE); 00301 memcpy((void*)&TablesC, InjectionAdvanceTableMainFlashLocation, MAINTABLE_SIZE); 00302 memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlashLocation, MAINTABLE_SIZE); 00303 RPAGE = RPAGE_TIME_TWO; 00304 memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlash2Location, MAINTABLE_SIZE); 00305 memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlash2Location, MAINTABLE_SIZE); 00306 memcpy((void*)&TablesC, InjectionAdvanceTableMainFlash2Location, MAINTABLE_SIZE); 00307 memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlash2Location, MAINTABLE_SIZE); 00308 } 00309 00310 00320 void initTunableAddresses(){ 00321 /* Setup addresses within the page to avoid warnings */ 00322 SmallTablesAFlashLocation = (void*)&SmallTablesAFlash; 00323 SmallTablesBFlashLocation = (void*)&SmallTablesBFlash; 00324 SmallTablesCFlashLocation = (void*)&SmallTablesCFlash; 00325 SmallTablesDFlashLocation = (void*)&SmallTablesDFlash; 00326 SmallTablesAFlash2Location = (void*)&SmallTablesAFlash2; 00327 SmallTablesBFlash2Location = (void*)&SmallTablesBFlash2; 00328 SmallTablesCFlash2Location = (void*)&SmallTablesCFlash2; 00329 SmallTablesDFlash2Location = (void*)&SmallTablesDFlash2; 00330 00331 /* TablesA */ 00332 dwellDesiredVersusVoltageTableLocation = (void*)&SmallTablesAFlash.dwellDesiredVersusVoltageTable; 00333 dwellDesiredVersusVoltageTable2Location = (void*)&SmallTablesAFlash2.dwellDesiredVersusVoltageTable; 00334 injectorDeadTimeTableLocation = (void*)&SmallTablesAFlash.injectorDeadTimeTable; 00335 injectorDeadTimeTable2Location = (void*)&SmallTablesAFlash2.injectorDeadTimeTable; 00336 postStartEnrichmentTableLocation = (void*)&SmallTablesAFlash.postStartEnrichmentTable; 00337 postStartEnrichmentTable2Location = (void*)&SmallTablesAFlash2.postStartEnrichmentTable; 00338 engineTempEnrichmentTableFixedLocation = (void*)&SmallTablesAFlash.engineTempEnrichmentTableFixed; 00339 engineTempEnrichmentTableFixed2Location = (void*)&SmallTablesAFlash2.engineTempEnrichmentTableFixed; 00340 primingVolumeTableLocation = (void*)&SmallTablesAFlash.primingVolumeTable; 00341 primingVolumeTable2Location = (void*)&SmallTablesAFlash2.primingVolumeTable; 00342 engineTempEnrichmentTablePercentLocation = (void*)&SmallTablesAFlash.engineTempEnrichmentTablePercent; 00343 engineTempEnrichmentTablePercent2Location = (void*)&SmallTablesAFlash2.engineTempEnrichmentTablePercent; 00344 dwellMaxVersusRPMTableLocation = (void*)&SmallTablesAFlash.dwellMaxVersusRPMTable; 00345 dwellMaxVersusRPMTable2Location = (void*)&SmallTablesAFlash2.dwellMaxVersusRPMTable; 00346 00347 /* TablesB */ 00348 perCylinderFuelTrimsLocation = (void*)&SmallTablesBFlash.perCylinderFuelTrims; 00349 perCylinderFuelTrims2Location = (void*)&SmallTablesBFlash2.perCylinderFuelTrims; 00350 00351 /* TablesC */ 00352 // TODO 00353 00354 /* TablesD */ 00355 // TODO 00356 00357 /* filler defs */ 00358 fillerALocation = (void*)&SmallTablesAFlash.filler; 00359 fillerA2Location = (void*)&SmallTablesAFlash2.filler; 00360 fillerBLocation = (void*)&SmallTablesBFlash.filler; 00361 fillerB2Location = (void*)&SmallTablesBFlash2.filler; 00362 fillerCLocation = (void*)&SmallTablesCFlash.filler; 00363 fillerC2Location = (void*)&SmallTablesCFlash2.filler; 00364 fillerDLocation = (void*)&SmallTablesDFlash.filler; 00365 fillerD2Location = (void*)&SmallTablesDFlash2.filler; 00366 } 00367 00368 00372 void initPagedRAMTune(){ 00373 /* Copy the tables from flash to RAM */ 00374 RPAGE = RPAGE_TUNE_ONE; 00375 memcpy((void*)&TablesA, SmallTablesAFlashLocation, MAINTABLE_SIZE); 00376 memcpy((void*)&TablesB, SmallTablesBFlashLocation, MAINTABLE_SIZE); 00377 memcpy((void*)&TablesC, SmallTablesCFlashLocation, MAINTABLE_SIZE); 00378 memcpy((void*)&TablesD, SmallTablesDFlashLocation, MAINTABLE_SIZE); 00379 RPAGE = RPAGE_TUNE_TWO; 00380 memcpy((void*)&TablesA, SmallTablesAFlash2Location, MAINTABLE_SIZE); 00381 memcpy((void*)&TablesB, SmallTablesBFlash2Location, MAINTABLE_SIZE); 00382 memcpy((void*)&TablesC, SmallTablesCFlash2Location, MAINTABLE_SIZE); 00383 memcpy((void*)&TablesD, SmallTablesDFlash2Location, MAINTABLE_SIZE); 00384 } 00385 00386 00397 void initAllPagedAddresses(){ 00398 /* Setup pointers to lookup tables */ 00399 initLookupAddresses(); 00400 /* Setup pointers to the main tables */ 00401 initFuelAddresses(); 00402 initTimingAddresses(); 00403 initTunableAddresses(); 00404 } 00405 00406 00419 void initAllPagedRAM(){ 00420 /* Copy the tables up to their paged ram blocks through the window from flash */ 00421 initPagedRAMFuel(); 00422 initPagedRAMTime(); 00423 initPagedRAMTune(); 00424 00425 /* Default to page one for now, perhaps read the configured port straight out of reset in future? TODO */ 00426 setupPagedRAM(TRUE); // probably something like (PORTA & TableSwitchingMask) 00427 } 00428 00429 00430 /* Init all pointers to tunable items with direct addresses */ 00431 /* Pointers remain the same when switching pages so are initialised only once */ 00432 // VETableMain = &TablesA.VETableMain; 00433 // VETableSecondary = &TablesB.VETableSecondary; 00434 // VETableTertiary = &TablesC.VETableMainTertiary; 00435 // LambdaTable = &TablesD.LambdaTable; 00436 // 00437 // IgnitionAdvanceTableMain = &TablesA.IgnitionAdvanceTableMain; 00438 // IgnitionAdvanceTableSecondary = &TablesB.IgnitionAdvanceTableSecondary; 00439 // InjectionAdvanceTableMain = &TablesC.InjectionAdvanceTableMain; 00440 // InjectionAdvanceTableSecondary = &TablesD.InjectionAdvanceTableSecondary; 00441 // 00442 // dwellDesiredVersusVoltageTable = &TablesA.SmallTablesA.dwellDesiredVersusVoltageTable; 00443 // injectorDeadTimeTable = &TablesA.SmallTablesA.injectorDeadTimeTable; 00444 // postStartEnrichmentTable = &TablesA.SmallTablesA.postStartEnrichmentTable; 00445 // engineTempEnrichmentTableFixed = &TablesA.SmallTablesA.engineTempEnrichmentTableFixed; 00446 // primingVolumeTable = &TablesA.SmallTablesA.primingVolumeTable; 00447 // engineTempEnrichmentTablePercent = &TablesA.SmallTablesA.engineTempEnrichmentTablePercent; 00448 // dwellMaxVersusRPMTable = &TablesA.SmallTablesA.dwellMaxVersusRPMTable; 00449 // 00450 // perCylinderFuelTrims = TablesB.SmallTablesB.perCylinderFuelTrims; 00451 00452 00453 /* Initialise and set up all running variables that require a non-zero start value here */ 00454 /* All other variables are initialised to zero by the premain built in code */ 00455 void initVariables(){ 00456 /* And the opposite for the other halves */ 00457 CoreVars = &CoreVars0; 00458 DerivedVars = &DerivedVars0; 00459 ADCArrays = &ADCArrays0; 00460 ADCArraysRecord = &ADCArrays1; 00461 asyncADCArrays = &asyncADCArrays0; 00462 asyncADCArraysRecord = &asyncADCArrays1; 00463 currentDwellMath = ¤tDwell0; 00464 currentDwellRealtime = ¤tDwell1; 00465 00466 injectorMainPulseWidthsMath = injectorMainPulseWidths0; 00467 injectorMainPulseWidthsRealtime = injectorMainPulseWidths1; 00468 injectorStagedPulseWidthsMath = injectorStagedPulseWidths0; 00469 injectorStagedPulseWidthsRealtime = injectorStagedPulseWidths1; 00470 00471 mathSampleTimeStamp = &ISRLatencyVars.mathSampleTimeStamp0; // TODO temp, remove 00472 mathSampleTimeStampRecord = &ISRLatencyVars.mathSampleTimeStamp1; // TODO temp, remove 00473 RPM = &RPM0; // TODO temp, remove 00474 RPMRecord = &RPM1; // TODO temp, remove 00475 00476 /* Setup the pointers to the registers for fueling use, this does NOT work if done in global.c, I still don't know why. */ 00477 injectorMainTimeRegisters[0] = TC2_ADDR; 00478 injectorMainTimeRegisters[1] = TC3_ADDR; 00479 injectorMainTimeRegisters[2] = TC4_ADDR; 00480 injectorMainTimeRegisters[3] = TC5_ADDR; 00481 injectorMainTimeRegisters[4] = TC6_ADDR; 00482 injectorMainTimeRegisters[5] = TC7_ADDR; 00483 injectorMainControlRegisters[0] = TCTL2_ADDR; 00484 injectorMainControlRegisters[1] = TCTL2_ADDR; 00485 injectorMainControlRegisters[2] = TCTL1_ADDR; 00486 injectorMainControlRegisters[3] = TCTL1_ADDR; 00487 injectorMainControlRegisters[4] = TCTL1_ADDR; 00488 injectorMainControlRegisters[5] = TCTL1_ADDR; 00489 00490 configuredBasicDatalogLength = maxBasicDatalogLength; 00491 00492 // 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 00493 } 00494 00495 00522 void initFlash(){ 00523 FCLKDIV = 0x4A; /* Set the flash clock frequency */ 00524 FPROT = 0xFF; /* Disable all flash protection */ 00525 FSTAT = FSTAT | (PVIOL | ACCERR); /* Clear any errors */ 00526 } 00527 00528 00529 /* Set up the timer module and its various interrupts */ 00530 void initECTTimer(){ 00531 00532 // TODO rearrange the order of this stuff and pull enable and interrupt enable out to the last function call of init. 00533 00534 00535 #ifndef NO_INIT 00536 /* Timer channel interrupts */ 00537 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 */ 00538 TFLG = ONES; /* Clear all the flags such that we are up and running before they first occur */ 00539 TFLGOF = ONES; /* Clear all the flags such that we are up and running before they first occur */ 00540 00541 /* TODO Turn the timer on and set the rate and overflow interrupt */ 00542 TSCR1 = 0x88; /* 0b_1000_1000 Timer enabled, and precision timer turned on */ 00543 TSCR2 = 0x87; /* 0b_1000_0111 Overflow interrupt enable, divide by 256 if precision turned off */ 00544 // PTPSR = 0x03; /* 4 prescaler gives .1uS resolution and max period of 7ms measured */ 00545 PTPSR = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */ 00546 // PTPSR = 0x3F; /* 64 prescaler gives 1.6uS resolution and max period of 105ms measured */ 00547 // PTPSR = 0xFF; /* 256 prescaler gives 6.4uS resolution and max period of 400ms measured */ 00548 // PTPSR = 0x7F; /* 128 prescaler gives 3.2uS resolution and max period of 200ms measured */ 00549 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29&btnG=Search */ 00550 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29+*+2%5E16&btnG=Search */ 00551 /* www.mecheng.adelaide.edu.au/robotics_novell/WWW_Devs/Dragon12/LM4_Timer.pdf */ 00552 00553 /* Initial actions */ 00554 TIOS = 0xFC; /* 0b_1111_1100 0 and 1 are input capture, 2 through 7 are output compare */ 00555 TCTL1 = ZEROS; /* Set disabled at startup time, use these and other flags to switch fueling on and off inside the decoder */ 00556 TCTL2 = ZEROS; /* 0,1 have compare turned off regardless as they are in IC mode. */ 00557 TCTL3 = ZEROS; /* Capture off for 4 - 7 */ 00558 TCTL4 = 0x0F; /* Capture on both edges of two pins for IC (0,1), capture off for 2,3 */ 00559 00560 // TODO setup delay counters on 0 and 1 to filter noise (nice feature!) 00561 //DLYCT = ??; built in noise filter 00562 00563 /* Configurable tachometer output */ 00564 PTMCPSR = fixedConfigs1.tachoSettings.tachoTickFactor - 1; // Precision prescaler - fastest is 1 represented by 0, slowest/longest possible is 256 represented by 255 or 0xFF 00565 MCCNT = ONES16; // init to slowest possible, first 00566 MCCTL = 0xC4; // turn on and setup the mod down counter 00567 MCFLG = 0x80; // clear the flag up front 00568 #endif 00569 } 00570 00571 00572 /* Configure the PIT timers for their various uses. */ 00573 void initPITTimer(){ 00574 #ifndef NO_INIT 00575 /* */ 00576 // set micro periods 00577 PITMTLD0 = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */ 00578 PITMTLD1 = 0x1F; /* ditto */ 00579 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29 Exactly the same as for ECT */ 00580 00581 // set timers running 00582 // PITLD0 = dwellPeriod; 00583 // enable module 00584 PITCFLMT = 0x80; 00585 // enable channels 00586 //PITCE = 0x03; 00587 // enable interrupt 00588 // PITINTE = 0x01; 00589 // clear flags 00590 //PITFLT = ONES; 00591 #endif 00592 } 00593 00594 /* Setup the sci module(s) that we need to use. */ 00595 void initSCIStuff(){ 00596 /* The alternative register set selector defaults to zero */ 00597 00598 // set the baud/data speed 00599 SCI0BD = fixedConfigs1.serialSettings.baudDivisor; 00600 00601 // etc 00602 00603 /* Switch to alternative register set? */ 00604 00605 // etc 00606 00607 /* Switch back again? */ 00608 00609 /* 00610 * 0 = LOOPS (normal two wire operation) 00611 * 0 = SCISWAI (Wait mode on) 00612 * 0 = RSRC (if loops=1, int/ext wiring) 00613 * 1 = M MODE (9 bit operation) 00614 * 0 = WAKE (idle line wakeup) 00615 * 0 = ILT (idle line type count start pos) 00616 * 1 = PE (parity on) 00617 * 1 = PT (odd parity) (minicom defaults to no parity) 00618 * 00619 * 00010011 = 0x13 00620 */ 00621 SCI0CR1 = 0x13; 00622 00623 /* 00624 * 0 = TIE (tx data empty isr disabled) 00625 * 0 = TCIE (tx complete isr disabled) 00626 * 1 = RIE (rx full isr enabled) 00627 * 0 = ILIE (idle line isr disabled) 00628 * 1 = TE (transmit enabled) 00629 * 1 = RE (receive enabled) 00630 * 0 = RWU (rx wake up normal) 00631 * 0 = SBK (send break off) 00632 * 00633 * 00101100 = 0x2C 00634 */ 00635 SCI0CR2 = 0x2C; 00636 } 00637 00638 /* TODO Load and calculate all configuration data required to run */ 00639 void initConfiguration(){ 00640 // // 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. 00641 00642 00643 /* Add in tunable physical parameters at boot time TODO move to init.c TODO duplicate for secondary fuel? or split somehow? 00644 *nstant = ((masterConst * perCylinderVolume) / (stoichiometricAFR * injectorFlow)); 00645 *nstant = ((139371764 * 16384 ) / (15053 * 4096 )); 00646 * OR 00647 *nstant = ((masterConst / injectorFlow) * perCylinderVolume) / stoichiometricAFR; 00648 *nstant = ((139371764 / 4096 ) * 16384 ) / 15053 ; 00649 * http://www.google.com/search?hl=en&safe=off&q=((139371764++%2F+4096+++++)+*+16384+++)+%2F+15053++++&btnG=Search */ 00650 bootFuelConst = ((unsigned long)(masterFuelConstant / fixedConfigs1.engineSettings.injectorFlow) * fixedConfigs1.engineSettings.perCylinderVolume) / fixedConfigs1.engineSettings.stoichiometricAFR; 00651 00652 /* The MAP range used to convert fake TPS from MAP and vice versa */ 00653 TPSMAPRange = fixedConfigs2.sensorRanges.TPSOpenMAP - fixedConfigs2.sensorRanges.TPSClosedMAP; 00654 00655 /* The ADC range used to generate TPS percentage */ 00656 TPSADCRange = fixedConfigs2.sensorRanges.TPSMaximumADC - fixedConfigs2.sensorRanges.TPSMinimumADC; 00657 00658 00659 /* Use like flags for now, just add one for each later */ 00660 unsigned char cumulativeConfigErrors = 0; 00661 00662 /* Check various aspects of config which will cause problems */ 00663 00664 /* BRV max bigger than variable that holds it */ 00665 if(((unsigned long)fixedConfigs2.sensorRanges.BRVMinimum + fixedConfigs2.sensorRanges.BRVRange) > 65535){ 00666 //sendError(BRV_MAX_TOO_LARGE); 00667 cumulativeConfigErrors++; 00668 } 00669 00670 // TODO check all critical variables here! 00671 00672 /* 00673 * check ignition settings for range etc, possibly check some of those on the fly too 00674 * check fuel settings for being reasonable 00675 * check all variable tables for correct sizing 00676 * etc 00677 */ 00678 00679 while(cumulativeConfigErrors > 0){ 00680 sleep(1000); 00681 PORTS_BA ^= ONES16; // flash leds 00682 //send("There were "); 00683 //sendUC(cumulativeConfigErrors); 00684 //send(" config errors, init aborted!"); 00685 } // 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. 00686 } 00687 00688 00689 /* Set up all the remaining interrupts */ 00690 void initInterrupts(){ 00691 /* IMPORTANT : Set the s12x vector base register (Thanks Karsten!!) */ 00692 IVBR = 0xF7; /* Without this the interrupts will never find your code! */ 00693 00694 /* Set up the Real Time Interrupt */ 00695 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 */ 00696 // 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 */ 00697 CRGINT |= 0x80; /* Enable the RTI */ 00698 CRGFLG = 0x80; /* Clear the RTI flag */ 00699 00700 #ifndef NO_INIT 00701 // set up port H for testing 00702 PPSH = ZEROS; // falling edge/pull up for all 00703 PIEH = ONES; // enable all pins interrupts 00704 PIFH = ONES; // clear all port H interrupt flags 00705 #endif 00706 00707 // TODO set up irq and xirq for testing 00708 // IRQCR for IRQ 00709 // 00710 00711 /* VReg API setup (only for wait mode? i think so) */ 00712 // VREGAPIR = 0x09C3; /* For 500ms period : (500ms - 0.2ms) / 0.2ms = 0b100111000011 = 2499 */ 00713 // VREGAPICL = 0x02; /* Enable the interrupt */ 00714 // VREGAPICL = 0x04; /* Start the counter running */ 00715 /* 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 */ 00716 00717 /* LVI Low Voltage Interrupt enable */ 00718 VREGCTRL = 0x02; // Counts bad power events for diagnosis reasons 00719 }