3 Copyright 2008 Fred Cooke
5 This file is part of the FreeEMS project.
7 FreeEMS software is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 FreeEMS software is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with any FreeEMS software. If not, see http://www.gnu.org/licenses/
20 We ask that if you make any changes to this file you email them upstream to
21 us at admin(at)diyefi(dot)org or, even better, fork the code on github.com!
23 Thank you for choosing FreeEMS to run your engine! */
27 #include "inc/freeEMS.h"
28 #include "inc/interrupts.h"
29 #include "inc/utils.h"
30 #include "inc/commsISRs.h"
31 #include "inc/pagedLocationBuffers.h"
36 /* Main init function to be called from main.c before entering the main loop */
38 ATOMIC_START(); /* Disable ALL interrupts while we configure the board ready for use */
39 initPLL(); /* Set up the PLL and use it */
40 initIO(); /* TODO make this config dependent. Set up all the pins and modules to be in low power harmless states */
41 initAllPagedRAM(); /* Copy table and config blocks of data from flash to the paged ram blocks for fast data lookup */
42 initVariables(); /* Initialise the rest of the running variables etc */
43 initFlash(); /* TODO, populate */
44 initECTTimer(); /* TODO move this to inside config in an organised way. Set up the timer module and its various aspects */
45 initPITTimer(); /* TODO ditto... */
46 initSCIStuff(); /* Setup the sci module(s) that we will use. */
47 initConfiguration(); /* TODO Set user/feature/config up here! */
48 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 */
49 ATOMIC_END(); /* Re-enable any configured interrupts */
53 /* used to chop out all the init stuff at compile time for hardware testing. */
57 /* Set the Phase Locked Loop to our desired frequency (80MHz) and switch to using it for clock (40MHz bus speed) */
59 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) */
60 PLLCTL
&= PLLOFF
; /* Turn the PLL device off to adjust its speed (on by default out of reset) */
61 REFDV
= PLLDIVISOR
; /* 16MHz / (3 + 1) = 4MHz Bus frequency */
62 SYNR
= PLLMULTIPLIER
; /* 4MHz * (9 + 1) = 40MHz Bus frequency */
63 PLLCTL
|= PLLON
; /* Turn the PLL device back on again at 80MHz */
65 while (!(CRGFLG
& PLLLOCK
)){
66 /* Do nothing while we wait till the PLL loop locks onto the target frequency. */
67 /* Target frequency is given by (2 * (crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
68 /* Bus frequency is half PLL frequency and given by ((crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
71 CLKSEL
= PLLSELON
; /* Switches to PLL clock for internal bus frequency */
72 /* from MC9S12XDP512V2.pdf Section 2.4.1.1.2 page 101 Third paragraph */
73 /* "This takes a MAXIMUM of 4 OSCCLK clock cylces PLUS 4 PLL clock cycles" */
74 /* "During this time ALL clocks freeze, and CPU activity ceases" */
75 /* Therefore there is no point waiting for this to occur, we already are... */
79 /* Configure all the I/O to default values to keep power use down etc */
81 /* for now, hard code all stuff to be outputs as per Freescale documentation, */
82 /* later what to do will be pulled from flash configuration such that all */
83 /* things are setup at once, and not messed with thereafter. when the port */
84 /* something uses is changed via the tuning interface, the confuration will be */
85 /* done on the fly, and the value burned to flash such that next boot happens */
86 /* correctly and current running devices are used in that way. */
88 /* Turn off and on and configure all the modules in an explicit way */
89 // TODO set up and turn off all modules (CAN,SCI,SPI,IIC,etc)
91 /* Turn off the digital input buffers on the ATD channels */
92 ATD0DIEN
= ZEROS
; /* You are out of your mind if you waste this on digital Inputs */
93 ATD1DIEN0
= ZEROS
; /* You are out of your mind if you waste this on digital Inputs (NOT-bonded, can't use) */
94 ATD1DIEN1
= ZEROS
; /* You are out of your mind if you waste this on digital Inputs */
95 /* TODO Second half of ATD1 - can we disable this somehow */
97 /* And configure them all for analog input */
98 ATD0CTL2
= 0x80; /* Turns on the ADC block. */
99 ATD0CTL3
= 0x40; /* Set sequence length = 8 */
100 ATD0CTL5
= 0xB0; /* Sets justification to right, multiplex and scan all channels. */
101 // TODO find out if this is the default (i suspect it is)
102 // TODO look into sampling techniques
104 /* And configure them all for analog input */
105 ATD1CTL0
= 0x07; /* Sets wrap on 8th ADC because we can't use the other 8 */
106 ATD1CTL2
= 0x80; /* Turns on the ADC block. */
107 ATD1CTL3
= 0x40; /* Set sequence length = 8 */
108 ATD1CTL5
= 0xB0; /* Sets justification to right, multiplex and scan all channels. */
109 // TODO find out if this is the default (i suspect it is)
110 // TODO look into sampling techniques
113 /* Set up the PWM component and initialise its values to off */
114 PWME
= 0x7F; /* Turn on PWM 0 - 6 (7 is user LED on main board) */
115 PWMCLK
= ZEROS
; /* The fastest we can go for all channels */
116 PWMPRCLK
= ZEROS
; /* The fastest prescaler we can go for all channels */
117 PWMSCLA
= ZEROS
; /* The fastest we can go */
118 PWMSCLB
= ZEROS
; /* The fastest we can go */
119 /* TODO PWM channel concatenation for high resolution */
120 // join channel pairs together here (needs 16 bit regs enabled too)
121 /* TODO Initialise pwm channels with frequency, and initial duty for real use */
122 // initial PWM settings for testing
124 PWMPER0
= 0xFF; // 255 for ADC0 testing
125 PWMPER1
= 0xFF; // 255 for ADC1 testing
126 PWMPER2
= 0xFF; // 255 for ADC1 testing
127 PWMPER3
= 0xFF; // 255 for ADC1 testing
128 PWMPER4
= 0xFF; // 255 for ADC1 testing
129 PWMPER5
= 0xFF; // 255 for ADC1 testing
130 PWMPER6
= 0xFF; // 255 for ADC1 testing
131 PWMPER7
= 0xFF; // 255 for ADC1 testing
143 /* Initialise the state of pins configured as output */
144 /* Initialise to low such that transistor grounded things are all turned off by default. */
145 PORTA
= ZEROS
; /* The serial monitor pin is on 0x40, and could cause problems if capacitance at the output is large when a reset occurs. */
146 PORTB
= ZEROS
; /* Init the rest of the spark outputs as off */
147 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 */
150 PORTT
= ZEROS
; /* All pins in off state at boot up (only matters for 2 - 7) */
152 PORTP
= ZEROS
; // TODO hook these up to the adc channels such that you can vary the brightness of an led with a pot.
155 /* AD0PT1 You are out of your mind if you waste this on digital Inputs */
156 /* AD1PT1 You are out of your mind if you waste this on digital Inputs */
158 /* Initialise the Data Direction Registers */
159 /* To outputs based on the note at the end of chapter 1.2.2 of MC9S12XDP512V2.pdf */
160 DDRA
= ONES
; /* GPIO (8) */
161 DDRB
= ONES
; /* GPIO (8) */
162 DDRE
= 0xFC; /* 0b_1111_1100 : Clock and mode pins PE0,PE1 are input only pins, the rest are GPIO */
163 DDRK
= ONES
; /* Only 0,1,2,3,4,5,7, NOT 6 (7) */
164 DDRS
= ONES
; /* SCI0, SCI1, SPI0 (8) */
165 DDRT
= 0xFC; /* 0b_1111_1100 set ECT pins 0,1 to IC and 2:7 to OC (8) */
166 DDRM
= ONES
; /* CAN 0 - 3 (8) */
167 DDRP
= ONES
; /* PWM pins (8) */
168 DDRH
= ZEROS
; /* All pins configured as input for misc isrs (SPI1, SPI2) (8) */
169 DDRJ
= ONES
; /* Only 0,1,6,7 are brought out on the 112 pin chip (4) */
170 /* Configure the non bonded pins to output to avoid current drain (112 pin package) */
171 DDRC
= ONES
; /* NON-bonded external data bus pins */
172 DDRD
= ONES
; /* NON-bonded external data bus pins */
173 /* AD0DDR1 You are out of your mind if you waste this on digital Inputs */
174 /* AD1DDR1 You are out of your mind if you waste this on digital Inputs */
179 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
180 void initLookupAddresses(void){
181 IATTransferTableLocation
= (void*)&IATTransferTable
;
182 CHTTransferTableLocation
= (void*)&CHTTransferTable
;
183 MAFTransferTableLocation
= (void*)&MAFTransferTable
;
184 TestTransferTableLocation
= (void*)&TestTransferTable
;
188 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
189 void initPagedRAMFuel(void){
190 /* Setup addresses within the page to avoid warnings */
191 VETableMainFlashLocation
= (void*)&VETableMainFlash
;
192 VETableSecondaryFlashLocation
= (void*)&VETableSecondaryFlash
;
193 VETableTertiaryFlashLocation
= (void*)&VETableTertiaryFlash
;
194 LambdaTableFlashLocation
= (void*)&LambdaTableFlash
;
195 VETableMainFlash2Location
= (void*)&VETableMainFlash2
;
196 VETableSecondaryFlash2Location
= (void*)&VETableSecondaryFlash2
;
197 VETableTertiaryFlash2Location
= (void*)&VETableTertiaryFlash2
;
198 LambdaTableFlash2Location
= (void*)&LambdaTableFlash2
;
199 /* Copy the tables from flash to RAM */
201 RPAGE
= RPAGE_FUEL_ONE
;
202 memcpy((void*)&TablesA
, VETableMainFlashLocation
, MAINTABLE_SIZE
);
203 memcpy((void*)&TablesB
, (void*)&VETableSecondaryFlash
, MAINTABLE_SIZE
);
204 memcpy((void*)&TablesC
, (void*)&VETableTertiaryFlash
, MAINTABLE_SIZE
);
205 memcpy((void*)&TablesD
, (void*)&LambdaTableFlash
, MAINTABLE_SIZE
);
206 RPAGE
= RPAGE_FUEL_TWO
;
207 memcpy((void*)&TablesA
, (void*)&VETableMainFlash2
, MAINTABLE_SIZE
);
208 memcpy((void*)&TablesB
, (void*)&VETableSecondaryFlash2
, MAINTABLE_SIZE
);
209 memcpy((void*)&TablesC
, (void*)&VETableTertiaryFlash2
, MAINTABLE_SIZE
);
210 memcpy((void*)&TablesD
, (void*)&LambdaTableFlash2
, MAINTABLE_SIZE
);
214 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
215 void initPagedRAMTime(void){
216 /* Setup addresses within the page to avoid warnings */
217 IgnitionAdvanceTableMainFlashLocation
= (void*)&IgnitionAdvanceTableMainFlash
;
218 IgnitionAdvanceTableSecondaryFlashLocation
= (void*)&IgnitionAdvanceTableSecondaryFlash
;
219 InjectionAdvanceTableMainFlashLocation
= (void*)&InjectionAdvanceTableMainFlash
;
220 InjectionAdvanceTableSecondaryFlashLocation
= (void*)&InjectionAdvanceTableSecondaryFlash
;
221 IgnitionAdvanceTableMainFlash2Location
= (void*)&IgnitionAdvanceTableMainFlash2
;
222 IgnitionAdvanceTableSecondaryFlash2Location
= (void*)&IgnitionAdvanceTableSecondaryFlash2
;
223 InjectionAdvanceTableMainFlash2Location
= (void*)&InjectionAdvanceTableMainFlash2
;
224 InjectionAdvanceTableSecondaryFlash2Location
= (void*)&InjectionAdvanceTableSecondaryFlash2
;
225 /* Copy the tables from flash to RAM */
227 RPAGE
= RPAGE_TIME_ONE
;
228 memcpy((void*)&TablesA
, IgnitionAdvanceTableMainFlashLocation
, MAINTABLE_SIZE
);
229 memcpy((void*)&TablesB
, IgnitionAdvanceTableSecondaryFlashLocation
, MAINTABLE_SIZE
);
230 memcpy((void*)&TablesC
, InjectionAdvanceTableMainFlashLocation
, MAINTABLE_SIZE
);
231 memcpy((void*)&TablesD
, InjectionAdvanceTableSecondaryFlashLocation
, MAINTABLE_SIZE
);
232 RPAGE
= RPAGE_TIME_TWO
;
233 memcpy((void*)&TablesA
, IgnitionAdvanceTableMainFlash2Location
, MAINTABLE_SIZE
);
234 memcpy((void*)&TablesB
, IgnitionAdvanceTableSecondaryFlash2Location
, MAINTABLE_SIZE
);
235 memcpy((void*)&TablesC
, InjectionAdvanceTableMainFlash2Location
, MAINTABLE_SIZE
);
236 memcpy((void*)&TablesD
, InjectionAdvanceTableSecondaryFlash2Location
, MAINTABLE_SIZE
);
240 /* Many thanks to Jean Bélanger for the inspiration/idea to do this! */
241 void initPagedRAMTune(void){
242 /* Setup addresses within the page to avoid warnings */
243 SmallTablesAFlashLocation
= (void*)&SmallTablesAFlash
;
244 SmallTablesBFlashLocation
= (void*)&SmallTablesBFlash
;
245 SmallTablesCFlashLocation
= (void*)&SmallTablesCFlash
;
246 SmallTablesDFlashLocation
= (void*)&SmallTablesDFlash
;
247 SmallTablesAFlash2Location
= (void*)&SmallTablesAFlash2
;
248 SmallTablesBFlash2Location
= (void*)&SmallTablesBFlash2
;
249 SmallTablesCFlash2Location
= (void*)&SmallTablesCFlash2
;
250 SmallTablesDFlash2Location
= (void*)&SmallTablesDFlash2
;
253 dwellDesiredVersusVoltageTableLocation
= (void*)&SmallTablesAFlash
.dwellDesiredVersusVoltageTable
;
254 dwellDesiredVersusVoltageTable2Location
= (void*)&SmallTablesAFlash2
.dwellDesiredVersusVoltageTable
;
255 injectorDeadTimeTableLocation
= (void*)&SmallTablesAFlash
.injectorDeadTimeTable
;
256 injectorDeadTimeTable2Location
= (void*)&SmallTablesAFlash2
.injectorDeadTimeTable
;
257 postStartEnrichmentTableLocation
= (void*)&SmallTablesAFlash
.postStartEnrichmentTable
;
258 postStartEnrichmentTable2Location
= (void*)&SmallTablesAFlash2
.postStartEnrichmentTable
;
259 engineTempEnrichmentTableFixedLocation
= (void*)&SmallTablesAFlash
.engineTempEnrichmentTableFixed
;
260 engineTempEnrichmentTableFixed2Location
= (void*)&SmallTablesAFlash2
.engineTempEnrichmentTableFixed
;
261 primingVolumeTableLocation
= (void*)&SmallTablesAFlash
.primingVolumeTable
;
262 primingVolumeTable2Location
= (void*)&SmallTablesAFlash2
.primingVolumeTable
;
263 engineTempEnrichmentTablePercentLocation
= (void*)&SmallTablesAFlash
.engineTempEnrichmentTablePercent
;
264 engineTempEnrichmentTablePercent2Location
= (void*)&SmallTablesAFlash2
.engineTempEnrichmentTablePercent
;
265 dwellMaxVersusRPMTableLocation
= (void*)&SmallTablesAFlash
.dwellMaxVersusRPMTable
;
266 dwellMaxVersusRPMTable2Location
= (void*)&SmallTablesAFlash2
.dwellMaxVersusRPMTable
;
269 perCylinderFuelTrimsLocation
= (void*)&SmallTablesBFlash
.perCylinderFuelTrims
;
270 perCylinderFuelTrims2Location
= (void*)&SmallTablesBFlash2
.perCylinderFuelTrims
;
279 fillerALocation
= (void*)&SmallTablesAFlash
.filler
;
280 fillerA2Location
= (void*)&SmallTablesAFlash2
.filler
;
281 fillerBLocation
= (void*)&SmallTablesBFlash
.filler
;
282 fillerB2Location
= (void*)&SmallTablesBFlash2
.filler
;
283 fillerCLocation
= (void*)&SmallTablesCFlash
.filler
;
284 fillerC2Location
= (void*)&SmallTablesCFlash2
.filler
;
285 fillerDLocation
= (void*)&SmallTablesDFlash
.filler
;
286 fillerD2Location
= (void*)&SmallTablesDFlash2
.filler
;
288 /* Copy the tables from flash to RAM */
289 RPAGE
= RPAGE_TUNE_ONE
;
290 memcpy((void*)&TablesA
, SmallTablesAFlashLocation
, MAINTABLE_SIZE
);
291 memcpy((void*)&TablesB
, SmallTablesBFlashLocation
, MAINTABLE_SIZE
);
292 memcpy((void*)&TablesC
, SmallTablesCFlashLocation
, MAINTABLE_SIZE
);
293 memcpy((void*)&TablesD
, SmallTablesDFlashLocation
, MAINTABLE_SIZE
);
294 RPAGE
= RPAGE_TUNE_TWO
;
295 memcpy((void*)&TablesA
, SmallTablesAFlash2Location
, MAINTABLE_SIZE
);
296 memcpy((void*)&TablesB
, SmallTablesBFlash2Location
, MAINTABLE_SIZE
);
297 memcpy((void*)&TablesC
, SmallTablesCFlash2Location
, MAINTABLE_SIZE
);
298 memcpy((void*)&TablesD
, SmallTablesDFlash2Location
, MAINTABLE_SIZE
);
302 /* Take the tables and config from flash up to RAM and initialise pointers to them.
304 * For the main tables and other paged config we need to adjust
305 * the RPAGE value to the appropriate one before copying up.
307 void initAllPagedRAM(){
308 /* Setup pointers to lookup tables */
309 initLookupAddresses();
311 /* Copy the tables up to their paged ram blocks through the window from flash */
316 /* Init all pointers to tunable items with direct addresses */
317 /* Pointers remain the same when switching pages so are initialised only once */
318 // VETableMain = &TablesA.VETableMain;
319 // VETableSecondary = &TablesB.VETableSecondary;
320 // VETableTertiary = &TablesC.VETableMainTertiary;
321 // LambdaTable = &TablesD.LambdaTable;
323 // IgnitionAdvanceTableMain = &TablesA.IgnitionAdvanceTableMain;
324 // IgnitionAdvanceTableSecondary = &TablesB.IgnitionAdvanceTableSecondary;
325 // InjectionAdvanceTableMain = &TablesC.InjectionAdvanceTableMain;
326 // InjectionAdvanceTableSecondary = &TablesD.InjectionAdvanceTableSecondary;
328 // dwellDesiredVersusVoltageTable = &TablesA.SmallTablesA.dwellDesiredVersusVoltageTable;
329 // injectorDeadTimeTable = &TablesA.SmallTablesA.injectorDeadTimeTable;
330 // postStartEnrichmentTable = &TablesA.SmallTablesA.postStartEnrichmentTable;
331 // engineTempEnrichmentTableFixed = &TablesA.SmallTablesA.engineTempEnrichmentTableFixed;
332 // primingVolumeTable = &TablesA.SmallTablesA.primingVolumeTable;
333 // engineTempEnrichmentTablePercent = &TablesA.SmallTablesA.engineTempEnrichmentTablePercent;
334 // dwellMaxVersusRPMTable = &TablesA.SmallTablesA.dwellMaxVersusRPMTable;
336 // perCylinderFuelTrims = TablesB.SmallTablesB.perCylinderFuelTrims;
338 /* Default to page one for now, perhaps read the configured port straight out of reset in future? TODO */
339 setupPagedRAM(TRUE
); // probably something like (PORTA & TableSwitchingMask)
343 /* Initialise and set up all running variables that require a non-zero start value here */
344 /* All other variables are initialised to zero by the premain built in code */
345 void initVariables(){
346 /* And the opposite for the other halves */
347 CoreVars
= &CoreVars0
;
348 DerivedVars
= &DerivedVars0
;
349 ADCArrays
= &ADCArrays0
;
350 ADCArraysRecord
= &ADCArrays1
;
351 asyncADCArrays
= &asyncADCArrays0
;
352 asyncADCArraysRecord
= &asyncADCArrays1
;
353 currentDwellMath
= ¤tDwell0
;
354 currentDwellRealtime
= ¤tDwell1
;
356 injectorMainPulseWidthsMath
= injectorMainPulseWidths0
;
357 injectorMainPulseWidthsRealtime
= injectorMainPulseWidths1
;
358 injectorStagedPulseWidthsMath
= injectorStagedPulseWidths0
;
359 injectorStagedPulseWidthsRealtime
= injectorStagedPulseWidths1
;
361 mathSampleTimeStamp
= &ISRLatencyVars
.mathSampleTimeStamp0
; // TODO temp, remove
362 mathSampleTimeStampRecord
= &ISRLatencyVars
.mathSampleTimeStamp1
; // TODO temp, remove
363 RPM
= &RPM0
; // TODO temp, remove
364 RPMRecord
= &RPM1
; // TODO temp, remove
366 /* Setup the pointers to the registers for fueling use, this does NOT work if done in global.c, I still don't know why. */
367 injectorMainTimeRegisters
[0] = TC2_ADDR
;
368 injectorMainTimeRegisters
[1] = TC3_ADDR
;
369 injectorMainTimeRegisters
[2] = TC4_ADDR
;
370 injectorMainTimeRegisters
[3] = TC5_ADDR
;
371 injectorMainTimeRegisters
[4] = TC6_ADDR
;
372 injectorMainTimeRegisters
[5] = TC7_ADDR
;
373 injectorMainControlRegisters
[0] = TCTL2_ADDR
;
374 injectorMainControlRegisters
[1] = TCTL2_ADDR
;
375 injectorMainControlRegisters
[2] = TCTL1_ADDR
;
376 injectorMainControlRegisters
[3] = TCTL1_ADDR
;
377 injectorMainControlRegisters
[4] = TCTL1_ADDR
;
378 injectorMainControlRegisters
[5] = TCTL1_ADDR
;
380 configuredBasicDatalogLength
= maxBasicDatalogLength
;
382 // 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
385 /* TODO initialise the flash burning configuration regs */
388 unsigned char flashclock
;
389 unsigned short SysClock
= 16000; //TODO see if Fred already specified this var and/or move to configs/constants
391 if (SysClock
>= 12000){
392 flashclock
= (unsigned char) (SysClock
/8/200 );
395 flashclock
= (unsigned char) (SysClock
/200 +1);
397 // TODO FIX SO EQUASION WORKS
398 // FCLKDIV = FCLKDIV|flashclock;
401 FPROT
= 0xFF; //disable all flash protection
402 FSTAT
= FSTAT
|(PVIOL
|ACCERR
); //clear any errors
406 /* Set up the timer module and its various interrupts */
409 // TODO rearrange the order of this stuff and pull enable and interrupt enable out to the last function call of init.
412 /* Timer channel interrupts */
413 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 */
414 TFLG
= ONES
; /* Clear all the flags such that we are up and running before they first occur */
415 TFLGOF
= ONES
; /* Clear all the flags such that we are up and running before they first occur */
417 /* TODO Turn the timer on and set the rate and overflow interrupt */
418 TSCR1
= 0x88; /* 0b_1000_1000 Timer enabled, and precision timer turned on */
419 TSCR2
= 0x87; /* 0b_1000_0111 Overflow interrupt enable, divide by 256 if precision turned off */
420 // PTPSR = 0x03; /* 4 prescaler gives .1uS resolution and max period of 7ms measured */
421 PTPSR
= 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
422 // PTPSR = 0x3F; /* 64 prescaler gives 1.6uS resolution and max period of 105ms measured */
423 // PTPSR = 0xFF; /* 256 prescaler gives 6.4uS resolution and max period of 400ms measured */
424 // PTPSR = 0x7F; /* 128 prescaler gives 3.2uS resolution and max period of 200ms measured */
425 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29&btnG=Search */
426 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29+*+2%5E16&btnG=Search */
427 /* www.mecheng.adelaide.edu.au/robotics_novell/WWW_Devs/Dragon12/LM4_Timer.pdf */
429 /* Initial actions */
430 TIOS
= 0xFC; /* 0b_1111_1100 0 and 1 are input capture, 2 through 7 are output compare */
431 TCTL1
= ZEROS
; /* Set disabled at startup time, use these and other flags to switch fueling on and off inside the decoder */
432 TCTL2
= ZEROS
; /* 0,1 have compare turned off regardless as they are in IC mode. */
433 TCTL3
= ZEROS
; /* Capture off for 4 - 7 */
434 TCTL4
= 0x0F; /* Capture on both edges of two pins for IC (0,1), capture off for 2,3 */
436 // TODO setup delay counters on 0 and 1 to filter noise (nice feature!)
437 //DLYCT = ??; built in noise filter
439 /* Configurable tachometer output */
440 PTMCPSR
= fixedConfigs2
.tachoTickFactor
- 1; // Precision prescaler - fastest is 1 represented by 0, slowest/longest possible is 256 represented by 255 or 0xFF
441 MCCNT
= ONES16
; // init to slowest possible, first
442 MCCTL
= 0xC4; // turn on and setup the mod down counter
443 MCFLG
= 0x80; // clear the flag up front
447 /* Configure the PIT timers for their various uses. */
452 PITMTLD0
= 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
453 PITMTLD1
= 0x1F; /* ditto */
454 /* http://www.google.com/search?hl=en&safe=off&q=1+%2F+%2840MHz+%2F+32+%29 Exactly the same as for ECT */
456 // set timers running
457 // PITLD0 = dwellPeriod;
469 /* Setup the sci module(s) that we need to use. */
471 /* The alternative register set selector defaults to zero */
473 // set the baud/data speed
474 SCI0BD
= fixedConfigs2
.baudDivisor
;
478 /* Switch to alternative register set? */
482 /* Switch back again? */
485 * 0 = LOOPS (normal two wire operation)
486 * 0 = SCISWAI (Wait mode on)
487 * 0 = RSRC (if loops=1, int/ext wiring)
488 * 1 = M MODE (9 bit operation)
489 * 0 = WAKE (idle line wakeup)
490 * 0 = ILT (idle line type count start pos)
492 * 1 = PT (odd parity) (minicom defaults to no parity)
499 * 0 = TIE (tx data empty isr disabled)
500 * 0 = TCIE (tx complete isr disabled)
501 * 1 = RIE (rx full isr enabled)
502 * 0 = ILIE (idle line isr disabled)
503 * 1 = TE (transmit enabled)
504 * 1 = RE (receive enabled)
505 * 0 = RWU (rx wake up normal)
506 * 0 = SBK (send break off)
513 /* TODO Load and calculate all configuration data required to run */
514 void initConfiguration(){
515 // // 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.
518 /* Add in tunable physical parameters at boot time TODO move to init.c TODO duplicate for secondary fuel? or split somehow?
519 *nstant = ((masterConst * perCylinderVolume) / (stoichiometricAFR * injectorFlow));
520 *nstant = ((139371764 * 16384 ) / (15053 * 4096 ));
522 *nstant = ((masterConst / injectorFlow) * perCylinderVolume) / stoichiometricAFR;
523 *nstant = ((139371764 / 4096 ) * 16384 ) / 15053 ;
524 * http://www.google.com/search?hl=en&safe=off&q=((139371764++%2F+4096+++++)+*+16384+++)+%2F+15053++++&btnG=Search */
525 bootFuelConst
= ((unsigned long)(masterFuelConstant
/ fixedConfigs1
.injectorFlow
) * fixedConfigs1
.perCylinderVolume
) / fixedConfigs1
.stoichiometricAFR
;
527 /* The MAP range used to convert fake TPS from MAP and vice versa */
528 TPSMAPRange
= fixedConfigs1
.TPSOpenMAP
- fixedConfigs1
.TPSClosedMAP
;
530 /* The ADC range used to generate TPS percentage */
531 TPSADCRange
= fixedConfigs1
.TPSMaximumADC
- fixedConfigs1
.TPSMinimumADC
;
534 /* Use like flags for now, just add one for each later */
535 unsigned char cumulativeConfigErrors
= 0;
537 /* Check various aspects of config which will cause problems */
539 /* BRV max bigger than variable that holds it */
540 if(((unsigned long)fixedConfigs1
.BRVMinimum
+ fixedConfigs1
.BRVRange
) > 65535){
541 //sendError(BRV_MAX_TOO_LARGE);
542 cumulativeConfigErrors
++;
545 // TODO check all critical variables here!
548 * check ignition settings for range etc, possibly check some of those on the fly too
549 * check fuel settings for being reasonable
550 * check all variable tables for correct sizing
554 while(cumulativeConfigErrors
> 0){
556 PORTS_BA
^= ONES16
; // flash leds
557 //send("There were ");
558 //sendUC(cumulativeConfigErrors);
559 //send(" config errors, init aborted!");
560 } // 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.
564 /* Set up all the remaining interrupts */
565 void initInterrupts(){
566 /* IMPORTANT : Set the s12x vector base register (Thanks Karsten!!) */
567 IVBR
= 0xF7; /* Without this the interrupts will never find your code! */
569 /* Set up the Real Time Interrupt */
570 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 */
571 // 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 */
572 CRGINT
|= 0x80; /* Enable the RTI */
573 CRGFLG
= 0x80; /* Clear the RTI flag */
576 // set up port H for testing
577 PPSH
= ZEROS
; // falling edge/pull up for all
578 PIEH
= ONES
; // enable all pins interrupts
579 PIFH
= ONES
; // clear all port H interrupt flags
582 // TODO set up irq and xirq for testing
586 /* VReg API setup (only for wait mode? i think so) */
587 // VREGAPIR = 0x09C3; /* For 500ms period : (500ms - 0.2ms) / 0.2ms = 0b100111000011 = 2499 */
588 // VREGAPICL = 0x02; /* Enable the interrupt */
589 // VREGAPICL = 0x04; /* Start the counter running */
590 /* 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 */
592 /* LVI Low Voltage Interrupt enable */
593 VREGCTRL
= 0x02; // Counts bad power events for diagnosis reasons