init.c

Go to the documentation of this file.
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 /* If these are moved back to the header then   */
00034 /* wrap them in an if to keep them hidden away  */
00035 void initPLL(void) FPAGE_FE;
00036 void initIO(void) FPAGE_FE;
00037 void initAllPagedRAM(void) FPAGE_FE;
00038 void initVariables(void) FPAGE_FE;
00039 void initFlash(void) FPAGE_FE;
00040 void initECTTimer(void) FPAGE_FE;
00041 void initPITTimer(void) FPAGE_FE;
00042 void initSCIStuff(void) FPAGE_FE;
00043 void initConfiguration(void) FPAGE_FE;
00044 void initInterrupts(void) FPAGE_FE;
00045 
00046 void initLookupAddresses(void) LOOKUPF;
00047 void initPagedRAMFuel(void) FUELTABLESF;
00048 void initPagedRAMTime(void) TIMETABLESF;
00049 void initPagedRAMTune(void) TUNETABLESF;
00050 
00051 
00052 /* Main init function to be called from main.c before entering the main loop */
00053 void init(){
00054         ATOMIC_START();                 /* Disable ALL interrupts while we configure the board ready for use */
00055         initPLL();                              /* Set up the PLL and use it */
00056         initIO();                               /* TODO make this config dependent. Set up all the pins and modules to be in low power harmless states */
00057         initAllPagedRAM();                      /* Copy table and config blocks of data from flash to the paged ram blocks for fast data lookup */
00058         initVariables();                /* Initialise the rest of the running variables etc */
00059         initFlash();                    /* TODO, populate */
00060         initECTTimer();                 /* TODO move this to inside config in an organised way. Set up the timer module and its various aspects */
00061         initPITTimer();                 /* TODO ditto... */
00062         initSCIStuff();                 /* Setup the sci module(s) that we will use. */
00063         initConfiguration();    /* TODO Set user/feature/config up here! */
00064         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 */
00065         ATOMIC_END(); /* Re-enable any configured interrupts */
00066 }
00067 
00068 
00069 /* used to chop out all the init stuff at compile time for hardware testing. */
00070 //#define NO_INIT
00071 
00072 
00073 /* Set the Phase Locked Loop to our desired frequency (80MHz) and switch to using it for clock (40MHz bus speed) */
00074 void initPLL(){
00075         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) */
00076         PLLCTL &= PLLOFF;               /* Turn the PLL device off to adjust its speed (on by default out of reset) */
00077         REFDV = PLLDIVISOR;             /* 16MHz / (3 + 1) = 4MHz Bus frequency */
00078         SYNR = PLLMULTIPLIER;   /* 4MHz * (9 + 1) = 40MHz Bus frequency */
00079         PLLCTL |= PLLON;                /* Turn the PLL device back on again at 80MHz */
00080 
00081         while (!(CRGFLG & PLLLOCK)){
00082                 /* Do nothing while we wait till the PLL loop locks onto the target frequency. */
00083                 /* Target frequency is given by (2 * (crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
00084                 /* Bus frequency is half PLL frequency and given by ((crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
00085         }
00086 
00087         CLKSEL = PLLSELON;              /* Switches to PLL clock for internal bus frequency     */
00088         /* from MC9S12XDP512V2.pdf Section 2.4.1.1.2 page 101 Third paragraph           */
00089         /* "This takes a MAXIMUM of 4 OSCCLK clock cylces PLUS 4 PLL clock cycles"      */
00090         /* "During this time ALL clocks freeze, and CPU activity ceases"                        */
00091         /* Therefore there is no point waiting for this to occur, we already are...     */
00092 }
00093 
00094 
00095 /* Configure all the I/O to default values to keep power use down etc */
00096 void initIO(){
00097         /* for now, hard code all stuff to be outputs as per Freescale documentation,   */
00098         /* later what to do will be pulled from flash configuration such that all               */
00099         /* things are setup at once, and not messed with thereafter. when the port              */
00100         /* something uses is changed via the tuning interface, the confuration will be  */
00101         /* done on the fly, and the value burned to flash such that next boot happens   */
00102         /* correctly and current running devices are used in that way.                                  */
00103 
00104         /* Turn off and on and configure all the modules in an explicit way */
00105         // TODO set up and turn off all modules (CAN,SCI,SPI,IIC,etc)
00106 
00107         /* Turn off the digital input buffers on the ATD channels */
00108         ATD0DIEN = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
00109         ATD1DIEN0 = ZEROS; /* You are out of your mind if you waste this on digital Inputs (NOT-bonded, can't use) */
00110         ATD1DIEN1 = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
00111         /* TODO Second half of ATD1 - can we disable this somehow */
00112 
00113         /* And configure them all for analog input */
00114         ATD0CTL2 = 0x80; /* Turns on the ADC block. */
00115         ATD0CTL3 = 0x40; /* Set sequence length = 8 */
00116         ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. */
00117         // TODO find out if this is the default (i suspect it is)
00118         // TODO look into sampling techniques
00119 
00120         /* And configure them all for analog input */
00121         ATD1CTL0 = 0x07; /* Sets wrap on 8th ADC because we can't use the other 8 */
00122         ATD1CTL2 = 0x80; /* Turns on the ADC block. */
00123         ATD1CTL3 = 0x40; /* Set sequence length = 8 */
00124         ATD1CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. */
00125         // TODO find out if this is the default (i suspect it is)
00126         // TODO look into sampling techniques
00127 
00128 #ifndef NO_INIT
00129         /* Set up the PWM component and initialise its values to off */
00130         PWME = 0x7F; /* Turn on PWM 0 - 6 (7 is user LED on main board) */
00131         PWMCLK = ZEROS; /* The fastest we can go for all channels */
00132         PWMPRCLK = ZEROS; /* The fastest prescaler we can go for all channels */
00133         PWMSCLA = ZEROS; /* The fastest we can go */
00134         PWMSCLB = ZEROS; /* The fastest we can go */
00135         /* TODO PWM channel concatenation for high resolution */
00136         // join channel pairs together here (needs 16 bit regs enabled too)
00137         /* TODO Initialise pwm channels with frequency, and initial duty for real use */
00138         // initial PWM settings for testing
00139         /* PWM periods */
00140         PWMPER0 = 0xFF; // 255 for ADC0 testing
00141         PWMPER1 = 0xFF; // 255 for ADC1 testing
00142         PWMPER2 = 0xFF; // 255 for ADC1 testing
00143         PWMPER3 = 0xFF; // 255 for ADC1 testing
00144         PWMPER4 = 0xFF; // 255 for ADC1 testing
00145         PWMPER5 = 0xFF; // 255 for ADC1 testing
00146         PWMPER6 = 0xFF; // 255 for ADC1 testing
00147         PWMPER7 = 0xFF; // 255 for ADC1 testing
00148         /* PWM duties */
00149         PWMDTY0 = 0;
00150         PWMDTY1 = 0;
00151         PWMDTY2 = 0;
00152         PWMDTY3 = 0;
00153         PWMDTY4 = 0;
00154         PWMDTY5 = 0;
00155         PWMDTY6 = 0;
00156         PWMDTY7 = 0;
00157 
00158 
00159         /* Initialise the state of pins configured as output */
00160         /* Initialise to low such that transistor grounded things are all turned off by default. */
00161         PORTA = ZEROS; /* The serial monitor pin is on 0x40, and could cause problems if capacitance at the output is large when a reset occurs. */
00162         PORTB = ZEROS; /* Init the rest of the spark outputs as off */
00163         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 */
00164         PORTK = ZEROS;
00165         PORTS = ZEROS;
00166         PORTT = ZEROS; /* All pins in off state at boot up (only matters for 2 - 7) */
00167         PORTM = ZEROS;
00168         PORTP = ZEROS; // TODO hook these up to the adc channels such that you can vary the brightness of an led with a pot.
00169         PORTH = ZEROS;
00170         PORTJ = ZEROS;
00171         /* AD0PT1 You are out of your mind if you waste this on digital Inputs */
00172         /* AD1PT1 You are out of your mind if you waste this on digital Inputs */
00173 
00174         /* Initialise the Data Direction Registers */
00175         /* To outputs based on the note at the end of chapter 1.2.2 of MC9S12XDP512V2.pdf */
00176         DDRA = ONES; /* GPIO (8) */
00177         DDRB = ONES; /* GPIO (8) */
00178         DDRE = 0xFC; /* 0b_1111_1100 : Clock and mode pins PE0,PE1 are input only pins, the rest are GPIO */
00179         DDRK = ONES; /* Only 0,1,2,3,4,5,7, NOT 6 (7) */
00180         DDRS = ONES; /* SCI0, SCI1, SPI0 (8) */
00181         DDRT = 0xFC; /* 0b_1111_1100 set ECT pins 0,1 to IC and 2:7 to OC (8) */
00182         DDRM = ONES; /* CAN 0 - 3 (8) */
00183         DDRP = ONES; /* PWM pins (8) */
00184         DDRH = ZEROS; /* All pins configured as input for misc isrs (SPI1, SPI2) (8) */
00185         DDRJ = ONES; /* Only 0,1,6,7 are brought out on the 112 pin chip (4) */
00186         /* Configure the non bonded pins to output to avoid current drain (112 pin package) */
00187         DDRC = ONES; /* NON-bonded external data bus pins */
00188         DDRD = ONES; /* NON-bonded external data bus pins */
00189         /* AD0DDR1 You are out of your mind if you waste this on digital Inputs */
00190         /* AD1DDR1 You are out of your mind if you waste this on digital Inputs */
00191 #endif
00192 }
00193 
00194 
00195 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
00196 void initLookupAddresses(void){
00197         IATTransferTableLocation = (void*)&IATTransferTable;
00198         CHTTransferTableLocation = (void*)&CHTTransferTable;
00199         MAFTransferTableLocation = (void*)&MAFTransferTable;
00200         TestTransferTableLocation = (void*)&TestTransferTable;
00201 }
00202 
00203 
00204 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
00205 void initPagedRAMFuel(void){
00206         /* Setup addresses within the page to avoid warnings */
00207         VETableMainFlashLocation                = (void*)&VETableMainFlash;
00208         VETableSecondaryFlashLocation   = (void*)&VETableSecondaryFlash;
00209         VETableTertiaryFlashLocation    = (void*)&VETableTertiaryFlash;
00210         LambdaTableFlashLocation                = (void*)&LambdaTableFlash;
00211         VETableMainFlash2Location               = (void*)&VETableMainFlash2;
00212         VETableSecondaryFlash2Location  = (void*)&VETableSecondaryFlash2;
00213         VETableTertiaryFlash2Location   = (void*)&VETableTertiaryFlash2;
00214         LambdaTableFlash2Location               = (void*)&LambdaTableFlash2;
00215         /* Copy the tables from flash to RAM */
00216         RPAGE = RPAGE_FUEL_ONE;
00217         memcpy((void*)&TablesA, VETableMainFlashLocation,               MAINTABLE_SIZE);
00218         memcpy((void*)&TablesB, (void*)&VETableSecondaryFlash,  MAINTABLE_SIZE);
00219         memcpy((void*)&TablesC, (void*)&VETableTertiaryFlash,   MAINTABLE_SIZE);
00220         memcpy((void*)&TablesD, (void*)&LambdaTableFlash,               MAINTABLE_SIZE);
00221         RPAGE = RPAGE_FUEL_TWO;
00222         memcpy((void*)&TablesA, (void*)&VETableMainFlash2,              MAINTABLE_SIZE);
00223         memcpy((void*)&TablesB, (void*)&VETableSecondaryFlash2, MAINTABLE_SIZE);
00224         memcpy((void*)&TablesC, (void*)&VETableTertiaryFlash2,  MAINTABLE_SIZE);
00225         memcpy((void*)&TablesD, (void*)&LambdaTableFlash2,              MAINTABLE_SIZE);
00226 }
00227 
00228 
00229 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
00230 void initPagedRAMTime(void){
00231         /* Setup addresses within the page to avoid warnings */
00232         IgnitionAdvanceTableMainFlashLocation                   = (void*)&IgnitionAdvanceTableMainFlash;
00233         IgnitionAdvanceTableSecondaryFlashLocation              = (void*)&IgnitionAdvanceTableSecondaryFlash;
00234         InjectionAdvanceTableMainFlashLocation                  = (void*)&InjectionAdvanceTableMainFlash;
00235         InjectionAdvanceTableSecondaryFlashLocation             = (void*)&InjectionAdvanceTableSecondaryFlash;
00236         IgnitionAdvanceTableMainFlash2Location                  = (void*)&IgnitionAdvanceTableMainFlash2;
00237         IgnitionAdvanceTableSecondaryFlash2Location             = (void*)&IgnitionAdvanceTableSecondaryFlash2;
00238         InjectionAdvanceTableMainFlash2Location                 = (void*)&InjectionAdvanceTableMainFlash2;
00239         InjectionAdvanceTableSecondaryFlash2Location    = (void*)&InjectionAdvanceTableSecondaryFlash2;
00240         /* Copy the tables from flash to RAM */
00241         RPAGE = RPAGE_TIME_ONE;
00242         memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlashLocation,                  MAINTABLE_SIZE);
00243         memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlashLocation,             MAINTABLE_SIZE);
00244         memcpy((void*)&TablesC, InjectionAdvanceTableMainFlashLocation,                 MAINTABLE_SIZE);
00245         memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlashLocation,    MAINTABLE_SIZE);
00246         RPAGE = RPAGE_TIME_TWO;
00247         memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlash2Location,                 MAINTABLE_SIZE);
00248         memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlash2Location,    MAINTABLE_SIZE);
00249         memcpy((void*)&TablesC, InjectionAdvanceTableMainFlash2Location,                MAINTABLE_SIZE);
00250         memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlash2Location,   MAINTABLE_SIZE);
00251 }
00252 
00253 
00254 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
00255 void initPagedRAMTune(void){
00256         /* Setup addresses within the page to avoid warnings */
00257         SmallTablesAFlashLocation       = (void*)&SmallTablesAFlash;
00258         SmallTablesBFlashLocation       = (void*)&SmallTablesBFlash;
00259         SmallTablesCFlashLocation       = (void*)&SmallTablesCFlash;
00260         SmallTablesDFlashLocation       = (void*)&SmallTablesDFlash;
00261         SmallTablesAFlash2Location      = (void*)&SmallTablesAFlash2;
00262         SmallTablesBFlash2Location      = (void*)&SmallTablesBFlash2;
00263         SmallTablesCFlash2Location      = (void*)&SmallTablesCFlash2;
00264         SmallTablesDFlash2Location      = (void*)&SmallTablesDFlash2;
00265         /* Copy the tables from flash to RAM */
00266         RPAGE = RPAGE_TUNE_ONE;
00267         memcpy((void*)&TablesA, SmallTablesAFlashLocation,      MAINTABLE_SIZE);
00268         memcpy((void*)&TablesB, SmallTablesBFlashLocation,      MAINTABLE_SIZE);
00269         memcpy((void*)&TablesC, SmallTablesCFlashLocation,      MAINTABLE_SIZE);
00270         memcpy((void*)&TablesD, SmallTablesDFlashLocation,      MAINTABLE_SIZE);
00271         RPAGE = RPAGE_TUNE_TWO;
00272         memcpy((void*)&TablesA, SmallTablesAFlash2Location,     MAINTABLE_SIZE);
00273         memcpy((void*)&TablesB, SmallTablesBFlash2Location,     MAINTABLE_SIZE);
00274         memcpy((void*)&TablesC, SmallTablesCFlash2Location,     MAINTABLE_SIZE);
00275         memcpy((void*)&TablesD, SmallTablesDFlash2Location,     MAINTABLE_SIZE);
00276 }
00277 
00278 
00279 /* Take the tables and config from flash up to RAM and initialise pointers to them.
00280  *
00281  * For the main tables and other paged config we need to adjust
00282  * the RPAGE value to the appropriate one before copying up.
00283  */
00284 void initAllPagedRAM(){
00285         /* Setup pointers to lookup tables */
00286         initLookupAddresses();
00287 
00288         /* Copy the tables up to their paged ram blocks through the window from flash */
00289         initPagedRAMFuel();
00290         initPagedRAMTime();
00291         initPagedRAMTune();
00292 
00293         /* Init all pointers to tunable items with direct addresses */
00294         /* Pointers remain the same when switching pages so are initialised only once */
00295 //      VETableMain = &TablesA.VETableMain;
00296 //      VETableSecondary = &TablesB.VETableSecondary;
00297 //      VETableTertiary = &TablesC.VETableMainTertiary;
00298 //      LambdaTable = &TablesD.LambdaTable;
00299 //
00300 //      IgnitionAdvanceTableMain = &TablesA.IgnitionAdvanceTableMain;
00301 //      IgnitionAdvanceTableSecondary = &TablesB.IgnitionAdvanceTableSecondary;
00302 //      InjectionAdvanceTableMain = &TablesC.InjectionAdvanceTableMain;
00303 //      InjectionAdvanceTableSecondary = &TablesD.InjectionAdvanceTableSecondary;
00304 //
00305 //      dwellDesiredVersusVoltageTable = &TablesA.SmallTablesA.dwellDesiredVersusVoltageTable;
00306 //      injectorDeadTimeTable = &TablesA.SmallTablesA.injectorDeadTimeTable;
00307 //      postStartEnrichmentTable = &TablesA.SmallTablesA.postStartEnrichmentTable;
00308 //      engineTempEnrichmentTableFixed = &TablesA.SmallTablesA.engineTempEnrichmentTableFixed;
00309 //      primingVolumeTable = &TablesA.SmallTablesA.primingVolumeTable;
00310 //      engineTempEnrichmentTablePercent = &TablesA.SmallTablesA.engineTempEnrichmentTablePercent;
00311 //      dwellMaxVersusRPMTable = &TablesA.SmallTablesA.dwellMaxVersusRPMTable;
00312 //
00313 //      perCylinderFuelTrims = TablesB.SmallTablesB.perCylinderFuelTrims;
00314 
00315         /* Default to page one for now, perhaps read the configured port straight out of reset in future? TODO */
00316         setupPagedRAM(TRUE); // probably something like (PORTA & TableSwitchingMask)
00317 }
00318 
00319 
00320 /* Initialise and set up all running variables that require a non-zero start value here */
00321 /* All other variables are initialised to zero by the premain built in code                             */
00322 void initVariables(){
00323         /* And the opposite for the other halves */
00324         CoreVars = &CoreVars0;
00325         DerivedVars = &DerivedVars0;
00326         ADCArrays = &ADCArrays0;
00327         ADCArraysRecord = &ADCArrays1;
00328         asyncADCArrays = &asyncADCArrays0;
00329         asyncADCArraysRecord = &asyncADCArrays1;
00330         currentDwellMath = &currentDwell0;
00331         currentDwellRealtime = &currentDwell1;
00332 
00333         injectorMainPulseWidthsMath = injectorMainPulseWidths0;
00334         injectorMainPulseWidthsRealtime = injectorMainPulseWidths1;
00335         injectorStagedPulseWidthsMath = injectorStagedPulseWidths0;
00336         injectorStagedPulseWidthsRealtime = injectorStagedPulseWidths1;
00337 
00338         mathSampleTimeStamp = &ISRLatencyVars.mathSampleTimeStamp0; // TODO temp, remove
00339         mathSampleTimeStampRecord = &ISRLatencyVars.mathSampleTimeStamp1; // TODO temp, remove
00340         RPM = &RPM0; // TODO temp, remove
00341         RPMRecord = &RPM1; // TODO temp, remove
00342 
00343         /* Setup the pointers to the registers for fueling use, this does NOT work if done in global.c, I still don't know why. */
00344         injectorMainTimeRegisters[0] = TC2_ADDR;
00345         injectorMainTimeRegisters[1] = TC3_ADDR;
00346         injectorMainTimeRegisters[2] = TC4_ADDR;
00347         injectorMainTimeRegisters[3] = TC5_ADDR;
00348         injectorMainTimeRegisters[4] = TC6_ADDR;
00349         injectorMainTimeRegisters[5] = TC7_ADDR;
00350         injectorMainControlRegisters[0] = TCTL2_ADDR;
00351         injectorMainControlRegisters[1] = TCTL2_ADDR;
00352         injectorMainControlRegisters[2] = TCTL1_ADDR;
00353         injectorMainControlRegisters[3] = TCTL1_ADDR;
00354         injectorMainControlRegisters[4] = TCTL1_ADDR;
00355         injectorMainControlRegisters[5] = TCTL1_ADDR;
00356 
00357         configuredBasicDatalogLength = maxBasicDatalogLength;
00358 
00359         // 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
00360 }
00361 
00362 /* TODO initialise the flash burning configuration regs */
00363 void initFlash(){
00364         // TBC
00365         unsigned char flashclock;
00366         unsigned short SysClock = 16000;    //TODO see if Fred already specified this var and/or move to configs/constants
00367 
00368         if (SysClock >= 12000){
00369                 flashclock = (unsigned char) (SysClock/8/200 );
00370         }
00371         else{
00372                 flashclock = (unsigned char) (SysClock/200 +1);
00373         }
00374 // TODO FIX SO EQUASION WORKS
00375 //      FCLKDIV = FCLKDIV|flashclock;
00376         FCLKDIV = 0x4A;
00377 
00378         FPROT = 0xFF;  //disable all flash protection
00379         FSTAT = FSTAT|(PVIOL|ACCERR);  //clear any errors
00380 
00381 }
00382 
00383 /* Set up the timer module and its various interrupts */
00384 void initECTTimer(){
00385 
00386         // TODO rearrange the order of this stuff and pull enable and interrupt enable out to the last function call of init.
00387 
00388 #ifndef NO_INIT
00389         /* Timer channel interrupts */
00390         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 */
00391         TFLG = ONES; /* Clear all the flags such that we are up and running before they first occur */
00392         TFLGOF = ONES; /* Clear all the flags such that we are up and running before they first occur */
00393 
00394         /* TODO Turn the timer on and set the rate and overflow interrupt */
00395         TSCR1 = 0x88; /* 0b_1000_1000 Timer enabled, and precision timer turned on */
00396         TSCR2 = 0x87; /* 0b_1000_0111 Overflow interrupt enable, divide by 256 if precision turned off */
00397 //      PTPSR = 0x03; /* 4 prescaler gives .1uS resolution and max period of 7ms measured */
00398         PTPSR = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
00399 //      PTPSR = 0x3F; /* 64 prescaler gives 1.6uS resolution and max period of 105ms measured */
00400 //      PTPSR = 0xFF; /* 256 prescaler gives 6.4uS resolution and max period of 400ms measured */
00401 //      PTPSR = 0x7F; /* 128 prescaler gives 3.2uS resolution and max period of 200ms measured */
00402         /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29&btnG=Search */
00403         /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29+*+2%5E16&btnG=Search */
00404         /* www.mecheng.adelaide.edu.au/robotics_novell/WWW_Devs/Dragon12/LM4_Timer.pdf */
00405 
00406         /* Initial actions */
00407         TIOS = 0xFC; /* 0b_1111_1100 0 and 1 are input capture, 2 through 7 are output compare */
00408         TCTL1 = ZEROS; /* Set disabled at startup time, use these and other flags to switch fueling on and off inside the decoder */
00409         TCTL2 = ZEROS; /* 0,1 have compare turned off regardless as they are in IC mode. */
00410         TCTL3 = ZEROS; /* Capture off for 4 - 7 */
00411         TCTL4 = 0x0F; /* Capture on both edges of two pins for IC (0,1), capture off for 2,3 */
00412 
00413         // TODO setup delay counters on 0 and 1 to filter noise (nice feature!)
00414         //DLYCT = ??; built in noise filter
00415 
00416         /* Configurable tachometer output */
00417         PTMCPSR = fixedConfigs2.tachoTickFactor - 1; // Precision prescaler - fastest is 1 represented by 0, slowest/longest possible is 256 represented by 255 or 0xFF
00418         MCCNT = ONES16; // init to slowest possible, first
00419         MCCTL = 0xC4; // turn on and setup the mod down counter
00420         MCFLG = 0x80; // clear the flag up front
00421 #endif
00422 }
00423 
00424 /* Configure the PIT timers for their various uses. */
00425 void initPITTimer(){
00426 #ifndef NO_INIT
00427         /*  */
00428         // set micro periods
00429         PITMTLD0 = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
00430         PITMTLD1 = 0x1F; /* ditto */
00431         /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29 Exactly the same as for ECT */
00432 
00433         // set timers running
00434 //      PITLD0 = dwellPeriod;
00435         // enable module
00436         PITCFLMT = 0x80;
00437         // enable channels
00438         //PITCE = 0x03;
00439         // enable interrupt
00440 //      PITINTE = 0x01;
00441         // clear flags
00442         //PITFLT = ONES;
00443 #endif
00444 }
00445 
00446 /* Setup the sci module(s) that we need to use. */
00447 void initSCIStuff(){
00448         /* The alternative register set selector defaults to zero */
00449 
00450         // set the baud/data speed
00451         SCI0BD = fixedConfigs2.baudDivisor;
00452 
00453         // etc
00454 
00455         /* Switch to alternative register set? */
00456 
00457         // etc
00458 
00459         /* Switch back again? */
00460 
00461         /*
00462          * 0 = LOOPS (normal two wire operation)
00463          * 0 = SCISWAI (Wait mode on)
00464          * 0 = RSRC (if loops=1, int/ext wiring)
00465          * 1 = M MODE (9 bit operation)
00466          * 0 = WAKE (idle line wakeup)
00467          * 0 = ILT (idle line type count start pos)
00468          * 1 = PE (parity on)
00469          * 1 = PT (odd parity) (minicom defaults to no parity)
00470          *
00471          * 00010011 = 0x13
00472          */
00473         SCI0CR1 = 0x13;
00474 
00475         /*
00476          * 0 = TIE (tx data empty isr disabled)
00477          * 0 = TCIE (tx complete isr disabled)
00478          * 1 = RIE (rx full isr enabled)
00479          * 0 = ILIE (idle line isr disabled)
00480          * 1 = TE (transmit enabled)
00481          * 1 = RE (receive enabled)
00482          * 0 = RWU (rx wake up normal)
00483          * 0 = SBK (send break off)
00484          *
00485          * 00101100 = 0x2C
00486          */
00487         SCI0CR2 = 0x2C;
00488 }
00489 
00490 /* TODO Load and calculate all configuration data required to run */
00491 void initConfiguration(){
00492 //      // 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.
00493 
00494 
00495         /* Add in tunable physical parameters at boot time TODO move to init.c TODO duplicate for secondary fuel? or split somehow?
00496          *nstant = ((masterConst * perCylinderVolume) / (stoichiometricAFR * injectorFlow));
00497          *nstant = ((139371764   * 16384                        ) / (15053                         * 4096                ));
00498          * OR
00499          *nstant = ((masterConst / injectorFlow) * perCylinderVolume) / stoichiometricAFR;
00500          *nstant = ((139371764   / 4096            ) * 16384                    ) / 15053                        ;
00501          * http://www.google.com/search?hl=en&safe=off&q=((139371764++%2F+4096+++++)+*+16384+++)+%2F+15053++++&btnG=Search */
00502         bootFuelConst = ((unsigned long)(masterFuelConstant / fixedConfigs1.injectorFlow) * fixedConfigs1.perCylinderVolume) / fixedConfigs1.stoichiometricAFR;
00503 
00504         /* The MAP range used to convert fake TPS from MAP and vice versa */
00505         TPSMAPRange = fixedConfigs1.TPSOpenMAP - fixedConfigs1.TPSClosedMAP;
00506 
00507         /* The ADC range used to generate TPS percentage */
00508         TPSADCRange = fixedConfigs1.TPSMaximumADC - fixedConfigs1.TPSMinimumADC;
00509 
00510 
00511         /* Use like flags for now, just add one for each later */
00512         unsigned char cumulativeConfigErrors = 0;
00513 
00514         /* Check various aspects of config which will cause problems */
00515 
00516         /* BRV max bigger than variable that holds it */
00517         if(((unsigned long)fixedConfigs1.BRVMinimum + fixedConfigs1.BRVRange) > 65535){
00518                 //sendError(BRV_MAX_TOO_LARGE);
00519                 cumulativeConfigErrors++;
00520         }
00521 
00522         // TODO check all critical variables here!
00523 
00524         /*
00525          * check ignition settings for range etc, possibly check some of those on the fly too
00526          * check fuel settings for being reasonable
00527          * check all variable tables for correct sizing
00528          * etc
00529          */
00530 
00531         while(cumulativeConfigErrors > 0){
00532                 sleep(1000);
00533                 PORTS_BA ^= ONES16; // flash leds
00534                 //send("There were ");
00535                 //sendUC(cumulativeConfigErrors);
00536                 //send(" config errors, init aborted!");
00537         } // 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.
00538 }
00539 
00540 
00541 /* Set up all the remaining interrupts */
00542 void initInterrupts(){
00543         /* IMPORTANT : Set the s12x vector base register (Thanks Karsten!!) */
00544         IVBR = 0xF7; /* Without this the interrupts will never find your code! */
00545 
00546         /* Set up the Real Time Interrupt */
00547         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 */
00548 //      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 */
00549         CRGINT |= 0x80; /* Enable the RTI */
00550         CRGFLG = 0x80; /* Clear the RTI flag */
00551 
00552 #ifndef NO_INIT
00553         // set up port H for testing
00554         PPSH = ZEROS; // falling edge/pull up for all
00555         PIEH = ONES; // enable all pins interrupts
00556         PIFH = ONES; // clear all port H interrupt flags
00557 #endif
00558 
00559         // TODO set up irq and xirq for testing
00560         // IRQCR for IRQ
00561         //
00562 
00563         /* VReg API setup (only for wait mode? i think so) */
00564 //      VREGAPIR = 0x09C3; /* For 500ms period : (500ms - 0.2ms) / 0.2ms = 0b100111000011 = 2499 */
00565 //      VREGAPICL = 0x02; /* Enable the interrupt */
00566 //      VREGAPICL = 0x04; /* Start the counter running */
00567         /* 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 */
00568 
00569         /* LVI Low Voltage Interrupt enable */
00570         VREGCTRL = 0x02; // Counts bad power events for diagnosis reasons
00571 }

Generated on Mon Dec 22 21:29:18 2008 for freeems by  doxygen 1.5.2