PageRenderTime 50ms CodeModel.GetById 2ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 1ms

/src/init.c

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