PageRenderTime 29ms CodeModel.GetById 2ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 1ms

/src/init.c

https://github.com/AbeFM/freeems-vanilla
C | 752 lines | 301 code | 99 blank | 352 comment | 2 complexity | 261ddcce55acd5403ac45f654bdf12ee MD5 | raw file
  1/* FreeEMS - the open source engine management system
  2 *
  3 * Copyright 2008-2011 Fred Cooke
  4 *
  5 * This file is part of the FreeEMS project.
  6 *
  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.
 11 *
 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.
 16 *
 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/
 19 *
 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!
 22 *
 23 * Thank you for choosing FreeEMS to run your engine!
 24 */
 25
 26
 27/** @file
 28 *
 29 * @brief Initialise the devices state
 30 *
 31 * Setup, configure and initialise all aspects of the devices state including
 32 * but not limited to:
 33 *
 34 * - Setup the bus clock speed
 35 * - Configuration based variable initialisation
 36 * - I/O register behaviour and initial state
 37 * - Configure and enable interrupts
 38 * - Copy tunable data up to RAM from flash
 39 * - Configure peripheral module behaviour
 40 *
 41 * @author Fred Cooke
 42 */
 43
 44
 45#define INIT_C
 46#include "inc/freeEMS.h"
 47#include "inc/interrupts.h"
 48#include "inc/utils.h"
 49#include "inc/commsISRs.h"
 50#include "inc/pagedLocationBuffers.h"
 51#include "inc/init.h"
 52#include "inc/decoderInterface.h"
 53#include "inc/xgateVectors.h"
 54#include <string.h>
 55
 56
 57/** @brief The main top level init
 58 *
 59 * The main init function to be called from main.c before entering the main
 60 * loop. This function is simply a delegator to the finer grained special
 61 * purpose init functions.
 62 *
 63 * @author Fred Cooke
 64 */
 65void init(){
 66	ATOMIC_START();         /* Disable ALL interrupts while we configure the board ready for use */
 67	initPLL();              /* Set up the PLL and use it */
 68	initIO();               /* TODO make this config dependent. Set up all the pins and modules to be in low power harmless states */
 69	initAllPagedRAM();      /* Copy table and config blocks of data from flash to the paged RAM blocks for fast data lookup */
 70	initVariables();        /* Initialise the rest of the running variables etc */
 71	initFlash();            /* TODO, finalise this */
 72	initECTTimer();         /* TODO move this to inside config in an organised way. Set up the timer module and its various aspects */
 73//	initPITTimer();         /* TODO ditto... */
 74	initSCIStuff();         /* Setup the sci module(s) that we will use. */
 75	initConfiguration();    /* TODO Set user/feature/config up here! */
 76#ifdef XGATE
 77	initXgate();            /* Fred is a legend, for good reason as of now */
 78#endif
 79	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 */
 80	ATOMIC_END();           /* Re-enable any configured interrupts */
 81}
 82
 83
 84#ifdef XGATE
 85#include "xgateInit.c"
 86#endif
 87
 88
 89/* used to chop out all the init stuff at compile time for hardware testing. */
 90//#define NO_INIT
 91
 92
 93/** @brief Set the PLL clock frequency
 94 *
 95 * Set the Phase Locked Loop to our desired frequency (80MHz) and switch to
 96 * using it for clock (40MHz bus speed).
 97 *
 98 * @author Fred Cooke
 99 */
100void initPLL(){
101	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) */
102	PLLCTL &= PLLOFF;		/* Turn the PLL device off to adjust its speed (on by default out of reset) */
103	REFDV = PLLDIVISOR;		/* 16MHz / (3 + 1) = 4MHz Bus frequency */
104	SYNR = PLLMULTIPLIER;	/* 4MHz * (9 + 1) = 40MHz Bus frequency */
105	PLLCTL |= PLLON;		/* Turn the PLL device back on again at 80MHz */
106
107	while (!(CRGFLG & PLLLOCK)){
108		/* Do nothing while we wait till the PLL loop locks onto the target frequency. */
109		/* Target frequency is given by (2 * (crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
110		/* Bus frequency is half PLL frequency and given by ((crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
111	}
112
113	CLKSEL = PLLSELON;		/* Switches to PLL clock for internal bus frequency	*/
114	/* from MC9S12XDP512V2.pdf Section 2.4.1.1.2 page 101 Third paragraph		*/
115	/* "This takes a MAXIMUM of 4 OSCCLK clock cylces PLUS 4 PLL clock cycles"	*/
116	/* "During this time ALL clocks freeze, and CPU activity ceases"			*/
117	/* Therefore there is no point waiting for this to occur, we already are...	*/
118}
119
120
121/* Configure all the I/O to default values to keep power use down etc */
122void initIO(){
123	/* for now, hard code all stuff to be outputs as per Freescale documentation,	*/
124	/* later what to do will be pulled from flash configuration such that all		*/
125	/* things are setup at once, and not messed with thereafter. when the port		*/
126	/* something uses is changed via the tuning interface, the confuration will be	*/
127	/* done on the fly, and the value burned to flash such that next boot happens	*/
128	/* correctly and current running devices are used in that way.					*/
129
130	/* Turn off and on and configure all the modules in an explicit way */
131	// TODO set up and turn off all modules (CAN,SCI,SPI,IIC,etc)
132
133	/* Digital input buffers on the ATD channels are off by default, leave them this way! */
134	//ATD0DIEN = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
135	//ATD1DIEN0 = ZEROS; /* You are out of your mind if you waste this on digital Inputs (NOT-bonded, can't use) */
136	//ATD1DIEN1 = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
137
138	/* And configure them all for analog input */
139	//ATD0CTL0 = 0x07/* With mult turned on this is required to be set to cause wrap around, but is correct out of reset */
140	//ATD0CTL1 = 0x07/* Trigger and interrupt configuration, unused for now. */
141	ATD0CTL2 = 0xC0; /* Turns on the ADC block and sets auto flag clear */
142	ATD0CTL3 = 0x40; /* Set sequence length = 8 */
143	ATD0CTL4 = 0x73; /* Set the ADC clock and sample period for best accuracy */
144	ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. Writing to this causes conversions to begin */
145
146	/* And configure them all for analog input */
147	ATD1CTL0 = 0x07; /* TODO bring this out of config based on chip variant variable. Sets wrap on 8th ADC because we can't use the other 8 on 112 pin version */
148	//ATD0CTL1 = 0x07/* Trigger and interrupt configuration, unused for now. */
149	ATD1CTL2 = 0xC0; /* Turns on the ADC block and sets auto flag clear */
150	ATD1CTL3 = 0x40; /* Set sequence length = 8 */
151	ATD0CTL4 = 0x73; /* Set the ADC clock and sample period for best accuracy */
152	ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. Writing to this causes conversions to begin */
153
154#ifndef NO_INIT
155	/* Set up the PWM component and initialise its values to off */
156	PWME = 0x7F; /* Turn on PWM 0 - 6 (7 is user LED on main board) */
157	PWMCLK = ZEROS; /* The fastest we can go for all channels */
158	PWMPRCLK = ZEROS; /* The fastest prescaler we can go for all channels */
159	PWMSCLA = ZEROS; /* The fastest we can go */
160	PWMSCLB = ZEROS; /* The fastest we can go */
161	/* TODO PWM channel concatenation for high resolution */
162	// join channel pairs together here (needs 16 bit regs enabled too)
163	/* TODO Initialise pwm channels with frequency, and initial duty for real use */
164	// initial PWM settings for testing
165	/* PWM periods */
166	PWMPER0 = 0xFF; // 255 for ADC0 testing
167	PWMPER1 = 0xFF; // 255 for ADC1 testing
168	PWMPER2 = 0xFF; // 255 for ADC1 testing
169	PWMPER3 = 0xFF; // 255 for ADC1 testing
170	PWMPER4 = 0xFF; // 255 for ADC1 testing
171	PWMPER5 = 0xFF; // 255 for ADC1 testing
172	PWMPER6 = 0xFF; // 255 for ADC1 testing
173	PWMPER7 = 0xFF; // 255 for ADC1 testing
174	/* PWM duties */
175	PWMDTY0 = 0;
176	PWMDTY1 = 0;
177	PWMDTY2 = 0;
178	PWMDTY3 = 0;
179	PWMDTY4 = 0;
180	PWMDTY5 = 0;
181	PWMDTY6 = 0;
182	PWMDTY7 = 0;
183
184
185	/* Initialise the state of pins configured as output */
186	/* Initialise to low such that transistor grounded things are all turned off by default. */
187	PORTA = BIT7; /* Set fuel pump on at boot time. The serial monitor pin is on 0x40, and could cause problems if capacitance at the output is large when a reset occurs. */
188	PORTB = ZEROS; /* Init the rest of the spark outputs as off */
189	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 */
190	PORTK = ZEROS;
191	PORTS = 0x02; // Set TX0 pin to high between transmissions!
192	PORTT = ZEROS; /* All pins in off state at boot up (only matters for 2 - 7) */
193	PORTM = ZEROS;
194	PORTP = ZEROS; // TODO hook these up to the adc channels such that you can vary the brightness of an led with a pot.
195	PORTH = ZEROS;
196	PORTJ = ZEROS;
197	/* AD0PT1 You are out of your mind if you waste this on digital Inputs */
198	/* AD1PT1 You are out of your mind if you waste this on digital Inputs */
199
200	/* Initialise the Data Direction Registers */
201	/* To outputs based on the note at the end of chapter 1.2.2 of MC9S12XDP512V2.pdf */
202	DDRA = ONES; /* GPIO (8) */
203	DDRB = ONES; /* GPIO (8) */
204	DDRE = 0xFC; /* 0b_1111_1100 : Clock and mode pins PE0,PE1 are input only pins, the rest are GPIO */
205	DDRK = ONES; /* Only 0,1,2,3,4,5,7, NOT 6 (7) */
206	DDRS = 0xFE; /* RX0 as input: SCI0 (RX,TX), SCI1 (RX,TX), SPI0 (MISO,MOSI,SCK,SS) (8) */
207	DDRT = 0xFC; /* 0b_1111_1100 set ECT pins 0,1 to IC and 2:7 to OC (8) */
208	DDRM = ONES; /* CAN 0 - 3 (8) */
209	DDRP = ONES; /* PWM pins (8) */
210	DDRH = ZEROS; /* All pins configured as input for misc isrs (SPI1, SPI2) (8) */
211	DDRJ = ONES; /* Only 0,1,6,7 are brought out on the 112 pin chip (4) */
212	/* Configure the non bonded pins to output to avoid current drain (112 pin package) */
213	DDRC = ONES; /* NON-bonded external data bus pins */
214	DDRD = ONES; /* NON-bonded external data bus pins */
215	/* AD0DDR1 You are out of your mind if you waste this on digital Inputs */
216	/* AD1DDR1 You are out of your mind if you waste this on digital Inputs */
217#endif
218}
219
220
221/** @brief Buffer lookup tables addresses
222 *
223 * Save pointers to the lookup tables which live in paged flash.
224 *
225 * @note Many thanks to Jean Bélanger for the inspiration/idea to do this!
226 *
227 * @author Fred Cooke
228 */
229void initLookupAddresses(){
230	IATTransferTableLocation = (void*)&IATTransferTable;
231	CHTTransferTableLocation = (void*)&CHTTransferTable;
232	MAFTransferTableLocation = (void*)&MAFTransferTable;
233	TestTransferTableLocation = (void*)&TestTransferTable;
234}
235
236
237/** @brief Buffer fuel tables addresses
238 *
239 * Save pointers to the fuel tables which live in paged flash.
240 *
241 * @note Many thanks to Jean Bélanger for the inspiration/idea to do this!
242 *
243 * @author Fred Cooke
244 */
245void initFuelAddresses(){
246	/* Setup addresses within the page to avoid warnings */
247	VETableMainFlashLocation		= (void*)&VETableMainFlash;
248	VETableSecondaryFlashLocation	= (void*)&VETableSecondaryFlash;
249	VETableTertiaryFlashLocation	= (void*)&VETableTertiaryFlash;
250	LambdaTableFlashLocation		= (void*)&LambdaTableFlash;
251	VETableMainFlash2Location		= (void*)&VETableMainFlash2;
252	VETableSecondaryFlash2Location	= (void*)&VETableSecondaryFlash2;
253	VETableTertiaryFlash2Location	= (void*)&VETableTertiaryFlash2;
254	LambdaTableFlash2Location		= (void*)&LambdaTableFlash2;
255}
256
257
258/** @brief Copy fuel tables to RAM
259 *
260 * Initialises the fuel tables in RAM by copying them up from flash.
261 *
262 * @author Fred Cooke
263 */
264void initPagedRAMFuel(void){
265	/* Copy the tables from flash to RAM */
266	RPAGE = RPAGE_FUEL_ONE;
267	memcpy((void*)&TablesA,	VETableMainFlashLocation,		sizeof(mainTable));
268	memcpy((void*)&TablesB,	VETableSecondaryFlashLocation,	sizeof(mainTable));
269	memcpy((void*)&TablesC,	VETableTertiaryFlashLocation,	sizeof(mainTable));
270	memcpy((void*)&TablesD,	LambdaTableFlashLocation,		sizeof(mainTable));
271	RPAGE = RPAGE_FUEL_TWO;
272	memcpy((void*)&TablesA,	VETableMainFlash2Location,		sizeof(mainTable));
273	memcpy((void*)&TablesB,	VETableSecondaryFlash2Location,	sizeof(mainTable));
274	memcpy((void*)&TablesC,	VETableTertiaryFlash2Location,	sizeof(mainTable));
275	memcpy((void*)&TablesD,	LambdaTableFlash2Location,		sizeof(mainTable));
276}
277
278
279/** @brief Buffer timing tables addresses
280 *
281 * Save pointers to the timing tables which live in paged flash.
282 *
283 * @note Many thanks to Jean Bélanger for the inspiration/idea to do this!
284 *
285 * @author Fred Cooke
286 */
287void initTimingAddresses(){
288	/* Setup addresses within the page to avoid warnings */
289	IgnitionAdvanceTableMainFlashLocation			= (void*)&IgnitionAdvanceTableMainFlash;
290	IgnitionAdvanceTableSecondaryFlashLocation		= (void*)&IgnitionAdvanceTableSecondaryFlash;
291	InjectionAdvanceTableMainFlashLocation			= (void*)&InjectionAdvanceTableMainFlash;
292	InjectionAdvanceTableSecondaryFlashLocation		= (void*)&InjectionAdvanceTableSecondaryFlash;
293	IgnitionAdvanceTableMainFlash2Location			= (void*)&IgnitionAdvanceTableMainFlash2;
294	IgnitionAdvanceTableSecondaryFlash2Location		= (void*)&IgnitionAdvanceTableSecondaryFlash2;
295	InjectionAdvanceTableMainFlash2Location			= (void*)&InjectionAdvanceTableMainFlash2;
296	InjectionAdvanceTableSecondaryFlash2Location	= (void*)&InjectionAdvanceTableSecondaryFlash2;
297}
298
299
300/** @brief Copy timing tables to RAM
301 *
302 * Initialises the timing tables in RAM by copying them up from flash.
303 *
304 * @author Fred Cooke
305 */
306void initPagedRAMTime(){
307	/* Copy the tables from flash to RAM */
308	RPAGE = RPAGE_TIME_ONE;
309	memcpy((void*)&TablesA,	IgnitionAdvanceTableMainFlashLocation,			sizeof(mainTable));
310	memcpy((void*)&TablesB,	IgnitionAdvanceTableSecondaryFlashLocation,		sizeof(mainTable));
311	memcpy((void*)&TablesC,	InjectionAdvanceTableMainFlashLocation,			sizeof(mainTable));
312	memcpy((void*)&TablesD,	InjectionAdvanceTableSecondaryFlashLocation,	sizeof(mainTable));
313	RPAGE = RPAGE_TIME_TWO;
314	memcpy((void*)&TablesA,	IgnitionAdvanceTableMainFlash2Location,			sizeof(mainTable));
315	memcpy((void*)&TablesB,	IgnitionAdvanceTableSecondaryFlash2Location,	sizeof(mainTable));
316	memcpy((void*)&TablesC,	InjectionAdvanceTableMainFlash2Location,		sizeof(mainTable));
317	memcpy((void*)&TablesD,	InjectionAdvanceTableSecondaryFlash2Location,	sizeof(mainTable));
318}
319
320
321/** @brief Buffer tunable tables addresses
322 *
323 * Save pointers to the tunable tables which live in paged flash and their
324 * sub-sections too.
325 *
326 * @note Many thanks to Jean Bélanger for the inspiration/idea to do this!
327 *
328 * @author Fred Cooke
329 */
330void initTunableAddresses(){
331	/* Setup addresses within the page to avoid warnings */
332	SmallTablesAFlashLocation 	= (void*)&SmallTablesAFlash;
333	SmallTablesBFlashLocation 	= (void*)&SmallTablesBFlash;
334	SmallTablesCFlashLocation 	= (void*)&SmallTablesCFlash;
335	SmallTablesDFlashLocation 	= (void*)&SmallTablesDFlash;
336	SmallTablesAFlash2Location	= (void*)&SmallTablesAFlash2;
337	SmallTablesBFlash2Location	= (void*)&SmallTablesBFlash2;
338	SmallTablesCFlash2Location	= (void*)&SmallTablesCFlash2;
339	SmallTablesDFlash2Location	= (void*)&SmallTablesDFlash2;
340
341	/* TablesA */
342	dwellDesiredVersusVoltageTableLocation    = (void*)&SmallTablesAFlash.dwellDesiredVersusVoltageTable;
343	dwellDesiredVersusVoltageTable2Location   = (void*)&SmallTablesAFlash2.dwellDesiredVersusVoltageTable;
344	injectorDeadTimeTableLocation             = (void*)&SmallTablesAFlash.injectorDeadTimeTable;
345	injectorDeadTimeTable2Location            = (void*)&SmallTablesAFlash2.injectorDeadTimeTable;
346	postStartEnrichmentTableLocation          = (void*)&SmallTablesAFlash.postStartEnrichmentTable;
347	postStartEnrichmentTable2Location         = (void*)&SmallTablesAFlash2.postStartEnrichmentTable;
348	engineTempEnrichmentTableFixedLocation    = (void*)&SmallTablesAFlash.engineTempEnrichmentTableFixed;
349	engineTempEnrichmentTableFixed2Location   = (void*)&SmallTablesAFlash2.engineTempEnrichmentTableFixed;
350	primingVolumeTableLocation                = (void*)&SmallTablesAFlash.primingVolumeTable;
351	primingVolumeTable2Location               = (void*)&SmallTablesAFlash2.primingVolumeTable;
352	engineTempEnrichmentTablePercentLocation  = (void*)&SmallTablesAFlash.engineTempEnrichmentTablePercent;
353	engineTempEnrichmentTablePercent2Location = (void*)&SmallTablesAFlash2.engineTempEnrichmentTablePercent;
354	dwellMaxVersusRPMTableLocation            = (void*)&SmallTablesAFlash.dwellMaxVersusRPMTable;
355	dwellMaxVersusRPMTable2Location           = (void*)&SmallTablesAFlash2.dwellMaxVersusRPMTable;
356
357	/* TablesB */
358	loggingSettingsLocation       = (void*)&SmallTablesBFlash.loggingSettings;
359	loggingSettings2Location      = (void*)&SmallTablesBFlash2.loggingSettings;
360	perCylinderFuelTrimsLocation  = (void*)&SmallTablesBFlash.perCylinderFuelTrims;
361	perCylinderFuelTrims2Location = (void*)&SmallTablesBFlash2.perCylinderFuelTrims;
362
363	/* TablesC */
364	// TODO
365
366	/* TablesD */
367	// TODO
368
369	/* filler defs */
370	fillerALocation  = (void*)&SmallTablesAFlash.filler;
371	fillerA2Location = (void*)&SmallTablesAFlash2.filler;
372	fillerBLocation  = (void*)&SmallTablesBFlash.filler;
373	fillerB2Location = (void*)&SmallTablesBFlash2.filler;
374	fillerCLocation  = (void*)&SmallTablesCFlash.filler;
375	fillerC2Location = (void*)&SmallTablesCFlash2.filler;
376	fillerDLocation  = (void*)&SmallTablesDFlash.filler;
377	fillerD2Location = (void*)&SmallTablesDFlash2.filler;
378}
379
380
381/**
382 *
383 */
384void initPagedRAMTune(){
385	/* Copy the tables from flash to RAM */
386	RPAGE = RPAGE_TUNE_ONE;
387	memcpy((void*)&TablesA,	SmallTablesAFlashLocation,	sizeof(mainTable));
388	memcpy((void*)&TablesB,	SmallTablesBFlashLocation,	sizeof(mainTable));
389	memcpy((void*)&TablesC,	SmallTablesCFlashLocation,	sizeof(mainTable));
390	memcpy((void*)&TablesD,	SmallTablesDFlashLocation,	sizeof(mainTable));
391	RPAGE = RPAGE_TUNE_TWO;
392	// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& WARNING &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
393	//    You will get garbage if you use table switching at this time!!!    //
394	//         XGATE code being run from this region temporarily!!!          //
395	//   Writing to these tables WILL corrupt XGATE code/kill your engine!   //
396	// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& WARNING &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
397	//memcpy(xgateSchedRAMAddress, xgateSchedFlashAddress, (xgateSchedEnd - xgateSched));
398	//memcpy(xgateInjectorsOnRAMAddress, xgateInjectorsOnFlashAddress, (xgateInjectorsOnEnd - xgateInjectorsOn));
399	//memcpy(xgateInjectorsOffRAMAddress, xgateInjectorsOffFlashAddress, (xgateInjectorsOffEnd - xgateInjectorsOff));
400//	memcpy((void*)&TablesA,	SmallTablesAFlash2Location,	sizeof(mainTable));
401//	memcpy((void*)&TablesB,	SmallTablesBFlash2Location,	sizeof(mainTable));
402//	memcpy((void*)&TablesC,	SmallTablesCFlash2Location,	sizeof(mainTable));
403//	memcpy((void*)&TablesD,	SmallTablesDFlash2Location,	sizeof(mainTable));
404}
405
406
407/** @brief Buffer addresses of paged data
408 *
409 * Save the paged memory addresses to variables such that we can access them
410 * from another paged block with no warnings.
411 *
412 * If you try to access paged data from the wrong place you get nasty warnings.
413 * These calls to functions that live in the same page that they are addressing
414 * prevent those warnings.
415 *
416 * @note Many thanks to Jean Bélanger for the inspiration/idea to do this!
417 *
418 * @author Fred Cooke
419 */
420void initAllPagedAddresses(){
421	/* Setup pointers to lookup tables */
422	initLookupAddresses();
423	/* Setup pointers to the main tables */
424	initFuelAddresses();
425	initTimingAddresses();
426	initTunableAddresses();
427}
428
429
430/** @brief Copies paged flash to RAM
431 *
432 * Take the tables and config from flash up to RAM to allow live tuning.
433 *
434 * For the main tables and other paged config we need to adjust
435 * the RPAGE value to the appropriate one before copying up.
436 *
437 * This function is simply a delegator to the ones for each flash page. Each
438 * one lives in the same paged space as the data it is copying up.
439 *
440 * @author Fred Cooke
441 */
442void initAllPagedRAM(){
443	/* Setup the flash block pointers before copying flash to RAM using them */
444	initAllPagedAddresses();
445
446	/* Copy the tables up to their paged RAM blocks through the window from flash */
447	initPagedRAMFuel();
448	initPagedRAMTime();
449	initPagedRAMTune();
450
451	/* Default to page one for now, perhaps read the configured port straight out of reset in future? TODO */
452	setupPagedRAM(TRUE); // probably something like (PORTA & TableSwitchingMask)
453}
454
455
456/* Initialise and set up all running variables that require a non-zero start value here */
457/* All other variables are initialised to zero by the premain built in code				*/
458void initVariables(){
459	/* And the opposite for the other halves */
460	CoreVars = &CoreVars0;
461	DerivedVars = &DerivedVars0;
462	ADCBuffers = &ADCBuffers0;
463	ADCBuffersRecord = &ADCBuffers1;
464
465	ticksPerDegree = &ticksPerDegree0; // TODO temp, remove, maybe
466	ticksPerDegreeRecord = &ticksPerDegree1; // TODO temp, remove, maybe
467
468	/* Setup the pointers to the registers for fueling use, this does NOT work if done in global.c, I still don't know why. */
469	injectorMainTimeRegisters[0] = TC2_ADDR;
470	injectorMainTimeRegisters[1] = TC3_ADDR;
471	injectorMainTimeRegisters[2] = TC4_ADDR;
472	injectorMainTimeRegisters[3] = TC5_ADDR;
473	injectorMainTimeRegisters[4] = TC6_ADDR;
474	injectorMainTimeRegisters[5] = TC7_ADDR;
475	injectorMainControlRegisters[0] = TCTL2_ADDR;
476	injectorMainControlRegisters[1] = TCTL2_ADDR;
477	injectorMainControlRegisters[2] = TCTL1_ADDR;
478	injectorMainControlRegisters[3] = TCTL1_ADDR;
479	injectorMainControlRegisters[4] = TCTL1_ADDR;
480	injectorMainControlRegisters[5] = TCTL1_ADDR;
481
482	coreStatusA |= FUEL_PUMP_PRIME;
483
484	// Initial state is NOT to fire... can be configured by scheduler if required.
485	outputEventInputEventNumbers[0] = 0xFF;
486	outputEventInputEventNumbers[1] = 0xFF;
487	outputEventInputEventNumbers[2] = 0xFF;
488	outputEventInputEventNumbers[3] = 0xFF;
489	outputEventInputEventNumbers[4] = 0xFF;
490	outputEventInputEventNumbers[5] = 0xFF;
491	outputEventInputEventNumbers[6] = 0xFF;
492	outputEventInputEventNumbers[7] = 0xFF;
493	outputEventInputEventNumbers[8] = 0xFF;
494	outputEventInputEventNumbers[9] = 0xFF;
495	outputEventInputEventNumbers[10] = 0xFF;
496	outputEventInputEventNumbers[11] = 0xFF;
497	outputEventInputEventNumbers[12] = 0xFF;
498	outputEventInputEventNumbers[13] = 0xFF;
499	outputEventInputEventNumbers[14] = 0xFF;
500	outputEventInputEventNumbers[15] = 0xFF;
501	outputEventInputEventNumbers[16] = 0xFF;
502	outputEventInputEventNumbers[17] = 0xFF;
503	outputEventInputEventNumbers[18] = 0xFF;
504	outputEventInputEventNumbers[19] = 0xFF;
505	outputEventInputEventNumbers[20] = 0xFF;
506	outputEventInputEventNumbers[21] = 0xFF;
507	outputEventInputEventNumbers[22] = 0xFF;
508	outputEventInputEventNumbers[23] = 0xFF;
509
510	// 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
511}
512
513
514/** @brief Flash module setup
515 *
516 * Initialise configuration registers for the flash module to allow burning of
517 * non-volatile flash memory from within the firmware.
518 *
519 * The FCLKDIV register can be written once only after reset, thus the lower
520 * seven bits and the PRDIV8 bit must be set at the same time.
521 *
522 * We want to put the flash clock as high as possible between 150kHz and 200kHz
523 *
524 * The oscillator clock is 16MHz and because that is above 12.8MHz we will set
525 * the PRDIV8 bit to further divide by 8 bits as per the manual.
526 *
527 * 16MHz = 16000KHz which pre-divided by 8 is 2000kHz
528 *
529 * 2000kHz / 200kHz = 10 thus we want to set the divide register to 10 or 0x0A
530 *
531 * Combining 0x0A with PRDIV8 gives us 0x4A (0x0A | 0x40 = 0x4A) so we use that
532 *
533 * @author Sean Keys
534 *
535 * @note If you use a different crystal lower than 12.8MHz PRDIV8 should not be set.
536 *
537 * @warning If the frequency you end up with is outside 150kHz - 200kHz you may
538 *          damage your flash module or get corrupt data written to it.
539 */
540void initFlash(){
541	FCLKDIV = 0x4A;                  	/* Set the flash clock frequency	*/
542	FPROT = 0xFF;                    	/* Disable all flash protection 	*/
543	FSTAT = FSTAT | (PVIOL | ACCERR);	/* Clear any errors             	*/
544}
545
546
547/* Set up the timer module and its various interrupts */
548void initECTTimer(){
549	/** @todo TODO Take the configuration from the decoder (as is) and mask it such that it does not affect the 6 other channels.
550	 * Take the the number of output channels required from configuration and configure that many as outputs
551	 * Configure the balance in whatever way is specified in the GPIO configuration - allow second input to be reused as GPI only.
552	 *
553	 * This stuff affects:
554	 * - TIE = 0x01 or 0x03, only. OC channels enabled as required and IC only for RPM/position.
555	 * - TIOS = nope, always 0xFC for 2 IC and 6 OC
556	 * - TCTL (1,2,3,4) 4 = 0x0? mask off high 4 bits and allow low 4 to come from decoder config/init
557	 * - PORTT = zeros, with balance from config
558	 * - DDRT = 0,1 inputs, or if unused by decoder, from config
559	 */
560
561
562
563	// TODO rearrange the order of this stuff and pull enable and interrupt enable out to the last function call of init.
564
565
566#ifndef NO_INIT
567	/* Timer channel interrupts */
568	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 */
569	TFLG = ONES; /* Clear all the flags such that we are up and running before they first occur */
570	TFLGOF = ONES; /* Clear all the flags such that we are up and running before they first occur */
571
572	/* TODO Turn the timer on and set the rate and overflow interrupt */
573//	DLYCT = 0xFF; /* max noise filtering as experiment for volvo this will come from flash config */ // just hiding a wiring/circuit issue...
574	TSCR1 = 0x88; /* 0b_1000_1000 Timer enabled, and precision timer turned on */
575	TSCR2 = 0x87; /* 0b_1000_0111 Overflow interrupt enable, divide by 256 if precision turned off */
576//	PTPSR = 0x03; /* 4 prescaler gives .1uS resolution and max period of 7ms measured */
577	PTPSR = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
578//	PTPSR = 0x3F; /* 64 prescaler gives 1.6uS resolution and max period of 105ms measured */
579//	PTPSR = 0xFF; /* 256 prescaler gives 6.4uS resolution and max period of 400ms measured */
580//	PTPSR = 0x7F; /* 128 prescaler gives 3.2uS resolution and max period of 200ms measured */
581	/* http://duckduckgo.com/?q=1+%2F+%2840MHz+%2F+32+%29 */
582	/* http://duckduckgo.com/?q=%281+%2F+%2840MHz+%2F+32+%29%29+*+2^16 */
583	/* www.mecheng.adelaide.edu.au/robotics_novell/WWW_Devs/Dragon12/LM4_Timer.pdf */
584
585	/* Initial actions */
586	TIOS = 0xFC; /* 0b_1111_1100 0 and 1 are input capture, 2 through 7 are output compare */
587	TCTL1 = ZEROS; /* Set disabled at startup time, use these and other flags to switch fueling on and off inside the decoder */
588	TCTL2 = ZEROS; /* 0,1 have compare turned off regardless as they are in IC mode. */
589	TCTL3 = ZEROS; /* Capture off for 4 - 7 */
590	TCTL4 = 0x0F; /* Capture on both edges of two pins for IC (0,1), capture off for 2,3 */
591
592	// TODO setup delay counters on 0 and 1 to filter noise (nice feature!)
593	//DLYCT = ??; built in noise filter
594
595//	PTMCPSR = 0xFF // Precision prescaler - fastest is 1 represented by 0, slowest/longest possible is 256 represented by 255 or 0xFF
596//	MCCNT = ONES16; // init to slowest possible, first
597//	MCCTL = 0xC4; // turn on and setup the mod down counter
598//	MCFLG = 0x80; // clear the flag up front
599
600	decoderInitPreliminary();
601#endif
602}
603
604
605/* Configure the PIT timers for their various uses. */
606void initPITTimer(){
607#ifndef NO_INIT
608//	/*  */
609//	// set micro periods
610//	PITMTLD0 = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
611//	PITMTLD1 = 0x1F; /* ditto */
612//	/* http://duckduckgo.com/?q=1+%2F+%2840MHz+%2F+32+%29 Exactly the same as for ECT */
613//
614//	// set timers running
615//	PITLD0 = dwellPeriod;
616//	// enable module
617//	PITCFLMT = 0x80;
618//	// enable channels
619//	//PITCE = 0x03;
620//	// enable interrupt
621//	PITINTE = 0x01;
622//	// clear flags
623//	//PITFLT = ONES;
624#endif
625}
626
627/* Setup the sci module(s) that we need to use. */
628void initSCIStuff(){
629	/* The alternative register set selector defaults to zero */
630
631	// set the baud/data speed
632	SCI0BD = fixedConfigs1.serialSettings.baudDivisor;
633
634	// etc
635
636	/* Switch to alternative register set? */
637
638	// etc
639
640	/* Switch back again? */
641
642	/*
643	 * 0 = LOOPS (normal two wire operation)
644	 * 0 = SCISWAI (Wait mode on)
645	 * 0 = RSRC (if loops=1, int/ext wiring)
646	 * 1 = M MODE (9 bit operation)
647	 * 0 = WAKE (idle line wakeup)
648	 * 0 = ILT (idle line type count start pos)
649	 * 1 = PE (parity on)
650	 * 1 = PT (odd parity)
651	 *
652	 * 0x13 = ODD (default)
653	 * 0x12 = EVEN
654	 * 0x00 = NONE
655	 */
656	SCI0CR1 = 0x13;
657
658	/*
659	 * 0 = TIE (tx data empty isr disabled)
660	 * 0 = TCIE (tx complete isr disabled)
661	 * 1 = RIE (rx full isr enabled)
662	 * 0 = ILIE (idle line isr disabled)
663	 * 0 = TE (transmit disabled)
664	 * 1 = RE (receive enabled)
665	 * 0 = RWU (rx wake up normal)
666	 * 0 = SBK (send break off)
667	 */
668	SCI0CR2 = 0x24;
669}
670
671/* TODO Load and calculate all configuration data required to run */
672void initConfiguration(){
673//	// 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.
674
675
676	/* Add in tunable physical parameters at boot time TODO move to init.c TODO duplicate for secondary fuel? or split somehow?
677	 *nstant = ((masterConst * perCylinderVolume) / (stoichiometricAFR * injectorFlow));
678	 *nstant = ((139371764	 * 16384			) / (15053			   * 4096		 ));
679	 * OR
680	 *nstant = ((masterConst / injectorFlow) * perCylinderVolume) / stoichiometricAFR;
681	 *nstant = ((139371764	 / 4096		   ) * 16384			) / 15053			 ;
682	 * http://duckduckgo.com/?q=%28%28139371764++%2F+4096%29+*+16384%29+%2F+15053 */
683	bootFuelConst = ((unsigned long)(masterFuelConstant / fixedConfigs1.engineSettings.injectorFlow) * fixedConfigs1.engineSettings.perCylinderVolume) / fixedConfigs1.engineSettings.stoichiometricAFR;
684
685	/* The MAP range used to convert fake TPS from MAP and vice versa */
686	TPSMAPRange = fixedConfigs2.sensorRanges.TPSOpenMAP - fixedConfigs2.sensorRanges.TPSClosedMAP;
687
688	/* The ADC range used to generate TPS percentage */
689	TPSADCRange = fixedConfigs2.sensorRanges.TPSMaximumADC - fixedConfigs2.sensorRanges.TPSMinimumADC;
690
691
692	/* Use like flags for now, just add one for each later */
693	unsigned char cumulativeConfigErrors = 0;
694
695	/* Check various aspects of config which will cause problems */
696
697	/* BRV max bigger than variable that holds it */
698	if(((unsigned long)fixedConfigs2.sensorRanges.BRVMinimum + fixedConfigs2.sensorRanges.BRVRange) > 65535){
699		//sendError(BRV_MAX_TOO_LARGE);
700		cumulativeConfigErrors++;
701	}
702
703	// TODO check all critical variables here!
704
705	/*
706	 * check ignition settings for range etc, possibly check some of those on the fly too
707	 * check fuel settings for being reasonable
708	 * check all variable tables for correct sizing
709	 * etc
710	 */
711
712	while(cumulativeConfigErrors > 0){
713		sleep(1000);
714		/// @todo TODO send an async error of some sort here, perhaps upgrade errors to handle args for this purpose, or perhaps send an async error for each error, inc this var, then send a "errors occurred, reset and listen to see what they were" packet?
715		//send("There were ");
716		//sendUC(cumulativeConfigErrors);
717		//send(" config errors, init aborted!");
718	} /// @todo 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.
719}
720
721
722/* Set up all the remaining interrupts */
723void initInterrupts(){
724	/* IMPORTANT : Set the s12x vector base register (Thanks Karsten!!) */
725	IVBR = 0xF7; /* Without this the interrupts will never find your code! */
726
727	/* Set up the Real Time Interrupt */
728	RTICTL = 0x81; /* 0b_1000_0001 0.125ms/125us period http://duckduckgo.com/?q=1+%2F+%2816MHz+%2F+%282+*+10^3%29+%29 */
729//	RTICTL = 0xF9; /* 0b_1111_1001 0.125s/125ms period http://duckduckgo.com/?q=1+%2F+%2816MHz+%2F+%282*10^6%29+%29 */
730	CRGINT |= 0x80; /* Enable the RTI */
731	CRGFLG = 0x80; /* Clear the RTI flag */
732
733#ifndef NO_INIT
734	// set up port H for testing
735	PPSH = ZEROS; // falling edge/pull up for all
736	PIEH = ONES; // enable all pins interrupts
737	PIFH = ONES; // clear all port H interrupt flags
738#endif
739
740	// TODO set up irq and xirq for testing
741	// IRQCR for IRQ
742	//
743
744	/* VReg API setup (only for wait mode? i think so) */
745//	VREGAPIR = 0x09C3; /* For 500ms period : (500ms - 0.2ms) / 0.2ms = 0b100111000011 = 2499 */
746//	VREGAPICL = 0x02; /* Enable the interrupt */
747//	VREGAPICL = 0x04; /* Start the counter running */
748	/* 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 */
749
750	/* LVI Low Voltage Interrupt enable */
751	VREGCTRL = 0x02; // Counts bad power events for diagnosis reasons
752}