Teensy groundwork (Many to come)
This commit is contained in:
parent
cb4d0b9ab6
commit
983e365dd7
|
@ -1,4 +1,9 @@
|
||||||
|
#ifndef AUX_H
|
||||||
|
#define AUX_H
|
||||||
|
|
||||||
|
void initialiseAuxPWM();
|
||||||
|
void boostControl();
|
||||||
|
void vvtControl();
|
||||||
|
|
||||||
volatile byte *boost_pin_port;
|
volatile byte *boost_pin_port;
|
||||||
volatile byte boost_pin_mask;
|
volatile byte boost_pin_mask;
|
||||||
|
@ -16,4 +21,4 @@ unsigned int vvt_pwm_max_count; //Used for variable PWM frequency
|
||||||
volatile unsigned int vvt_pwm_cur_value;
|
volatile unsigned int vvt_pwm_cur_value;
|
||||||
long vvt_pwm_target_value;
|
long vvt_pwm_target_value;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@ void fanControl()
|
||||||
else if (currentStatus.coolant <= (configPage4.fanSP - configPage4.fanHyster)) { digitalWrite(pinFan, fanLOW); }
|
else if (currentStatus.coolant <= (configPage4.fanSP - configPage4.fanHyster)) { digitalWrite(pinFan, fanLOW); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
void initialiseAuxPWM()
|
void initialiseAuxPWM()
|
||||||
{
|
{
|
||||||
TCCR1B = 0x00; //Disbale Timer1 while we set it up
|
TCCR1B = 0x00; //Disbale Timer1 while we set it up
|
||||||
|
@ -53,9 +54,7 @@ void boostControl()
|
||||||
boostPID.Compute();
|
boostPID.Compute();
|
||||||
TIMSK1 |= (1 << OCIE1A); //Turn on the compare unit (ie turn on the interrupt)
|
TIMSK1 |= (1 << OCIE1A); //Turn on the compare unit (ie turn on the interrupt)
|
||||||
}
|
}
|
||||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
|
||||||
else { TIMSK1 &= ~(1 << OCIE1A); } // Disable timer channel
|
else { TIMSK1 &= ~(1 << OCIE1A); } // Disable timer channel
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvtControl()
|
void vvtControl()
|
||||||
|
@ -71,7 +70,6 @@ void vvtControl()
|
||||||
}
|
}
|
||||||
|
|
||||||
//The interrupt to control the Boost PWM
|
//The interrupt to control the Boost PWM
|
||||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
|
||||||
ISR(TIMER1_COMPA_vect)
|
ISR(TIMER1_COMPA_vect)
|
||||||
{
|
{
|
||||||
if (boost_pwm_state)
|
if (boost_pwm_state)
|
||||||
|
@ -107,6 +105,11 @@ ISR(TIMER1_COMPB_vect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(PROCESSOR_TEENSY_3_1) || defined(PROCESSOR_TEENSY_3_2)
|
#elif defined (CORE_TEENSY) && defined (__MK20DX256__)
|
||||||
|
//YET TO BE IMPLEMENTED ON TEENSY
|
||||||
|
void initialiseAuxPWM() { }
|
||||||
|
void boostControl() { }
|
||||||
|
void vvtControl() { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
90
comms.ino
90
comms.ino
|
@ -75,7 +75,7 @@ void command()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'W': // receive new VE obr constant at 'W'+<offset>+<newbyte>
|
case 'W': // receive new VE obr constant at 'W'+<offset>+<newbyte>
|
||||||
int offset;
|
int valueOffset; //cannot use offset as a variable name, it is a reserved word for several teensy libraries
|
||||||
while (Serial.available() == 0) { }
|
while (Serial.available() == 0) { }
|
||||||
|
|
||||||
if (isMap)
|
if (isMap)
|
||||||
|
@ -84,15 +84,15 @@ void command()
|
||||||
offset1 = Serial.read();
|
offset1 = Serial.read();
|
||||||
while (Serial.available() == 0) { }
|
while (Serial.available() == 0) { }
|
||||||
offset2 = Serial.read();
|
offset2 = Serial.read();
|
||||||
offset = word(offset2, offset1);
|
valueOffset = word(offset2, offset1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offset = Serial.read();
|
valueOffset = Serial.read();
|
||||||
}
|
}
|
||||||
while (Serial.available() == 0) { }
|
while (Serial.available() == 0) { }
|
||||||
|
|
||||||
receiveValue(offset, Serial.read());
|
receiveValue(valueOffset, Serial.read());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't': // receive new Calibration info. Command structure: "t", <tble_idx> <data array>. This is an MS2/Extra command, NOT part of MS1 spec
|
case 't': // receive new Calibration info. Command structure: "t", <tble_idx> <data array>. This is an MS2/Extra command, NOT part of MS1 spec
|
||||||
|
@ -267,7 +267,7 @@ void sendValues(int packetlength, byte portNum)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void receiveValue(int offset, byte newValue)
|
void receiveValue(int valueOffset, byte newValue)
|
||||||
{
|
{
|
||||||
|
|
||||||
void* pnt_configPage;//This only stores the address of the value that it's pointing to and not the max size
|
void* pnt_configPage;//This only stores the address of the value that it's pointing to and not the max size
|
||||||
|
@ -275,24 +275,24 @@ void receiveValue(int offset, byte newValue)
|
||||||
switch (currentPage)
|
switch (currentPage)
|
||||||
{
|
{
|
||||||
case veMapPage:
|
case veMapPage:
|
||||||
if (offset < 256) //New value is part of the fuel map
|
if (valueOffset < 256) //New value is part of the fuel map
|
||||||
{
|
{
|
||||||
fuelTable.values[15 - offset / 16][offset % 16] = newValue;
|
fuelTable.values[15 - valueOffset / 16][valueOffset % 16] = newValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
|
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
|
||||||
if (offset < 272)
|
if (valueOffset < 272)
|
||||||
{
|
{
|
||||||
//X Axis
|
//X Axis
|
||||||
fuelTable.axisX[(offset - 256)] = ((int)(newValue) * 100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct
|
fuelTable.axisX[(valueOffset - 256)] = ((int)(newValue) * 100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Y Axis
|
//Y Axis
|
||||||
offset = 15 - (offset - 272); //Need to do a translation to flip the order (Due to us using (0,0) in the top left rather than bottom right
|
valueOffset = 15 - (valueOffset - 272); //Need to do a translation to flip the order (Due to us using (0,0) in the top left rather than bottom right
|
||||||
fuelTable.axisY[offset] = (int)(newValue);
|
fuelTable.axisY[valueOffset] = (int)(newValue);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -301,31 +301,31 @@ void receiveValue(int offset, byte newValue)
|
||||||
case veSetPage:
|
case veSetPage:
|
||||||
pnt_configPage = &configPage1; //Setup a pointer to the relevant config page
|
pnt_configPage = &configPage1; //Setup a pointer to the relevant config page
|
||||||
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
||||||
if ( offset < page_size)
|
if (valueOffset < page_size)
|
||||||
{
|
{
|
||||||
*((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages
|
*((byte *)pnt_configPage + (byte)valueOffset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ignMapPage: //Ignition settings page (Page 2)
|
case ignMapPage: //Ignition settings page (Page 2)
|
||||||
if (offset < 256) //New value is part of the ignition map
|
if (valueOffset < 256) //New value is part of the ignition map
|
||||||
{
|
{
|
||||||
ignitionTable.values[15 - offset / 16][offset % 16] = newValue;
|
ignitionTable.values[15 - valueOffset / 16][valueOffset % 16] = newValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
|
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
|
||||||
if (offset < 272)
|
if (valueOffset < 272)
|
||||||
{
|
{
|
||||||
//X Axis
|
//X Axis
|
||||||
ignitionTable.axisX[(offset - 256)] = (int)(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct
|
ignitionTable.axisX[(valueOffset - 256)] = (int)(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Y Axis
|
//Y Axis
|
||||||
offset = 15 - (offset - 272); //Need to do a translation to flip the order
|
valueOffset = 15 - (valueOffset - 272); //Need to do a translation to flip the order
|
||||||
ignitionTable.axisY[offset] = (int)(newValue);
|
ignitionTable.axisY[valueOffset] = (int)(newValue);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -333,31 +333,31 @@ void receiveValue(int offset, byte newValue)
|
||||||
case ignSetPage:
|
case ignSetPage:
|
||||||
pnt_configPage = &configPage2;
|
pnt_configPage = &configPage2;
|
||||||
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
||||||
if ( offset < page_size)
|
if (valueOffset < page_size)
|
||||||
{
|
{
|
||||||
*((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages
|
*((byte *)pnt_configPage + (byte)valueOffset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case afrMapPage: //Air/Fuel ratio target settings page
|
case afrMapPage: //Air/Fuel ratio target settings page
|
||||||
if (offset < 256) //New value is part of the afr map
|
if (valueOffset < 256) //New value is part of the afr map
|
||||||
{
|
{
|
||||||
afrTable.values[15 - offset / 16][offset % 16] = newValue;
|
afrTable.values[15 - valueOffset / 16][valueOffset % 16] = newValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
|
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
|
||||||
if (offset < 272)
|
if (valueOffset < 272)
|
||||||
{
|
{
|
||||||
//X Axis
|
//X Axis
|
||||||
afrTable.axisX[(offset - 256)] = int(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiply it back by 100 to make it correct
|
afrTable.axisX[(valueOffset - 256)] = int(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiply it back by 100 to make it correct
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Y Axis
|
//Y Axis
|
||||||
offset = 15 - (offset - 272); //Need to do a translation to flip the order
|
valueOffset = 15 - (valueOffset - 272); //Need to do a translation to flip the order
|
||||||
afrTable.axisY[offset] = int(newValue);
|
afrTable.axisY[valueOffset] = int(newValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -366,52 +366,52 @@ void receiveValue(int offset, byte newValue)
|
||||||
case afrSetPage:
|
case afrSetPage:
|
||||||
pnt_configPage = &configPage3;
|
pnt_configPage = &configPage3;
|
||||||
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
||||||
if ( offset < page_size)
|
if (valueOffset < page_size)
|
||||||
{
|
{
|
||||||
*((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages
|
*((byte *)pnt_configPage + (byte)valueOffset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iacPage: //Idle Air Control settings page (Page 4)
|
case iacPage: //Idle Air Control settings page (Page 4)
|
||||||
pnt_configPage = &configPage4;
|
pnt_configPage = &configPage4;
|
||||||
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
//For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size
|
||||||
if ( offset < page_size)
|
if (valueOffset < page_size)
|
||||||
{
|
{
|
||||||
*((byte *)pnt_configPage + (byte)offset) = newValue;
|
*((byte *)pnt_configPage + (byte)valueOffset) = newValue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case boostvvtPage: //Boost and VVT maps (8x8)
|
case boostvvtPage: //Boost and VVT maps (8x8)
|
||||||
if (offset < 64) //New value is part of the boost map
|
if (valueOffset < 64) //New value is part of the boost map
|
||||||
{
|
{
|
||||||
boostTable.values[7 - offset / 8][offset % 8] = newValue;
|
boostTable.values[7 - valueOffset / 8][valueOffset % 8] = newValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (offset < 72) //New value is on the X (RPM) axis of the boost table
|
else if (valueOffset < 72) //New value is on the X (RPM) axis of the boost table
|
||||||
{
|
{
|
||||||
boostTable.axisX[(offset - 64)] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct
|
boostTable.axisX[(valueOffset - 64)] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (offset < 80) //New value is on the Y (TPS) axis of the boost table
|
else if (valueOffset < 80) //New value is on the Y (TPS) axis of the boost table
|
||||||
{
|
{
|
||||||
boostTable.axisY[(7 - (offset - 72))] = int(newValue);
|
boostTable.axisY[(7 - (valueOffset - 72))] = int(newValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (offset < 144) //New value is part of the vvt map
|
else if (valueOffset < 144) //New value is part of the vvt map
|
||||||
{
|
{
|
||||||
offset = offset - 80;
|
valueOffset = valueOffset - 80;
|
||||||
vvtTable.values[7 - offset / 8][offset % 8] = newValue;
|
vvtTable.values[7 - valueOffset / 8][valueOffset % 8] = newValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (offset < 152) //New value is on the X (RPM) axis of the vvt table
|
else if (valueOffset < 152) //New value is on the X (RPM) axis of the vvt table
|
||||||
{
|
{
|
||||||
offset = offset - 144;
|
valueOffset = valueOffset - 144;
|
||||||
vvtTable.axisX[offset] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct
|
vvtTable.axisX[valueOffset] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else //New value is on the Y (Load) axis of the vvt table
|
else //New value is on the Y (Load) axis of the vvt table
|
||||||
{
|
{
|
||||||
offset = offset - 152;
|
valueOffset = valueOffset - 152;
|
||||||
vvtTable.axisY[(7 - offset)] = int(newValue);
|
vvtTable.axisY[(7 - valueOffset)] = int(newValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
3
idle.h
3
idle.h
|
@ -36,4 +36,5 @@ long idle_pwm_target_value;
|
||||||
long idle_cl_target_rpm;
|
long idle_cl_target_rpm;
|
||||||
|
|
||||||
void initialiseIdle();
|
void initialiseIdle();
|
||||||
|
static inline void disableIdle();
|
||||||
|
static inline void enableIdle();
|
||||||
|
|
32
idle.ino
32
idle.ino
|
@ -53,7 +53,7 @@ void initialiseIdle()
|
||||||
idle2_pin_port = portOutputRegister(digitalPinToPort(pinIdle2));
|
idle2_pin_port = portOutputRegister(digitalPinToPort(pinIdle2));
|
||||||
idle2_pin_mask = digitalPinToBitMask(pinIdle2);
|
idle2_pin_mask = digitalPinToBitMask(pinIdle2);
|
||||||
idle_pwm_max_count = 1000000L / (16 * configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
|
idle_pwm_max_count = 1000000L / (16 * configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
|
||||||
TIMSK4 |= (1 << OCIE4C); //Turn on the C compare unit (ie turn on the interrupt)
|
enableIdle();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -141,8 +141,8 @@ void idleControl()
|
||||||
{
|
{
|
||||||
//Standard running
|
//Standard running
|
||||||
currentStatus.idleDuty = table2D_getValue(&iacPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
|
currentStatus.idleDuty = table2D_getValue(&iacPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
|
||||||
if( currentStatus.idleDuty == 0 ) { TIMSK4 &= ~(1 << OCIE4C); digitalWrite(pinIdle1, LOW); break; }
|
if( currentStatus.idleDuty == 0 ) { disableIdle(); break; }
|
||||||
TIMSK4 |= (1 << OCIE4C); //Turn on the C compare unit (ie turn on the interrupt)
|
enableIdle();
|
||||||
idle_pwm_target_value = percentage(currentStatus.idleDuty, idle_pwm_max_count);
|
idle_pwm_target_value = percentage(currentStatus.idleDuty, idle_pwm_max_count);
|
||||||
idleOn = true;
|
idleOn = true;
|
||||||
}
|
}
|
||||||
|
@ -154,8 +154,8 @@ void idleControl()
|
||||||
//idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
|
//idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
|
||||||
|
|
||||||
idlePID.Compute();
|
idlePID.Compute();
|
||||||
if( idle_pwm_target_value == 0 ) { TIMSK4 &= ~(1 << OCIE4C); digitalWrite(pinIdle1, LOW); }
|
if( idle_pwm_target_value == 0 ) { disableIdle(); }
|
||||||
else{ TIMSK4 |= (1 << OCIE4C); } //Turn on the C compare unit (ie turn on the interrupt)
|
else{ enableIdle(); } //Turn on the C compare unit (ie turn on the interrupt)
|
||||||
//idle_pwm_target_value = 104;
|
//idle_pwm_target_value = 104;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -240,6 +240,20 @@ void homeStepper()
|
||||||
|
|
||||||
//The interrupt to turn off the idle pwm
|
//The interrupt to turn off the idle pwm
|
||||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
//This function simply turns off the idle PWM and sets the pin low
|
||||||
|
static inline void disableIdle()
|
||||||
|
{
|
||||||
|
TIMSK4 &= ~(1 << OCIE4C); //Turn off interrupt
|
||||||
|
digitalWrite(pinIdle1, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Any common functions associated with starting the Idle
|
||||||
|
//Typically this is enabling the PWM interrupt
|
||||||
|
static inline void enableIdle()
|
||||||
|
{
|
||||||
|
TIMSK4 |= (1 << OCIE4C); //Turn on the C compare unit (ie turn on the interrupt)
|
||||||
|
}
|
||||||
|
|
||||||
ISR(TIMER4_COMPC_vect)
|
ISR(TIMER4_COMPC_vect)
|
||||||
{
|
{
|
||||||
if (idle_pwm_state)
|
if (idle_pwm_state)
|
||||||
|
@ -280,5 +294,11 @@ ISR(TIMER4_COMPC_vect)
|
||||||
|
|
||||||
}
|
}
|
||||||
#elif defined(PROCESSOR_TEENSY_3_1) || defined(PROCESSOR_TEENSY_3_2)
|
#elif defined(PROCESSOR_TEENSY_3_1) || defined(PROCESSOR_TEENSY_3_2)
|
||||||
void idle_off() { }
|
//This function simply turns off the idle PWM and sets the pin low
|
||||||
|
static inline void disableIdle()
|
||||||
|
{
|
||||||
|
digitalWrite(pinIdle1, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void enableIdle() { }
|
||||||
#endif
|
#endif
|
||||||
|
|
102
scheduler.ino
102
scheduler.ino
|
@ -10,7 +10,8 @@ A full copy of the license may be found in the projects root directory
|
||||||
void initialiseSchedulers()
|
void initialiseSchedulers()
|
||||||
{
|
{
|
||||||
nullSchedule.Status = OFF;
|
nullSchedule.Status = OFF;
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
|
||||||
// Much help in this from http://arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html
|
// Much help in this from http://arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html
|
||||||
//Fuel Schedules, which uses timer 3
|
//Fuel Schedules, which uses timer 3
|
||||||
TCCR3B = 0x00; //Disable Timer3 while we set it up
|
TCCR3B = 0x00; //Disable Timer3 while we set it up
|
||||||
|
@ -19,15 +20,6 @@ void initialiseSchedulers()
|
||||||
TCCR3A = 0x00; //Timer3 Control Reg A: Wave Gen Mode normal
|
TCCR3A = 0x00; //Timer3 Control Reg A: Wave Gen Mode normal
|
||||||
TCCR3B = (1 << CS12); //Timer3 Control Reg B: Timer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
TCCR3B = (1 << CS12); //Timer3 Control Reg B: Timer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
||||||
//TCCR3B = 0x03; //Timer3 Control Reg B: Timer Prescaler set to 64. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
//TCCR3B = 0x03; //Timer3 Control Reg B: Timer Prescaler set to 64. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
||||||
fuelSchedule1.Status = OFF;
|
|
||||||
fuelSchedule2.Status = OFF;
|
|
||||||
fuelSchedule3.Status = OFF;
|
|
||||||
|
|
||||||
fuelSchedule5.Status = OFF;
|
|
||||||
|
|
||||||
fuelSchedule1.schedulesSet = 0;
|
|
||||||
fuelSchedule2.schedulesSet = 0;
|
|
||||||
fuelSchedule3.schedulesSet = 0;
|
|
||||||
|
|
||||||
//Ignition Schedules, which uses timer 5
|
//Ignition Schedules, which uses timer 5
|
||||||
TCCR5B = 0x00; //Disable Timer3 while we set it up
|
TCCR5B = 0x00; //Disable Timer3 while we set it up
|
||||||
|
@ -36,26 +28,40 @@ void initialiseSchedulers()
|
||||||
TCCR5A = 0x00; //Timer5 Control Reg A: Wave Gen Mode normal
|
TCCR5A = 0x00; //Timer5 Control Reg A: Wave Gen Mode normal
|
||||||
//TCCR5B = (1 << CS12); //Timer5 Control Reg B: Timer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
//TCCR5B = (1 << CS12); //Timer5 Control Reg B: Timer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
||||||
TCCR5B = 0x03; //aka Divisor = 64 = 490.1Hz
|
TCCR5B = 0x03; //aka Divisor = 64 = 490.1Hz
|
||||||
ignitionSchedule1.Status = OFF;
|
|
||||||
ignitionSchedule2.Status = OFF;
|
|
||||||
ignitionSchedule3.Status = OFF;
|
|
||||||
|
|
||||||
ignitionSchedule1.schedulesSet = 0;
|
|
||||||
ignitionSchedule2.schedulesSet = 0;
|
|
||||||
ignitionSchedule3.schedulesSet = 0;
|
|
||||||
|
|
||||||
//The remaining Schedules (Schedules 4 for fuel and ignition) use Timer4
|
//The remaining Schedules (Schedules 4 for fuel and ignition) use Timer4
|
||||||
TCCR4B = 0x00; //Disable Timer4 while we set it up
|
TCCR4B = 0x00; //Disable Timer4 while we set it up
|
||||||
TCNT4 = 0; //Reset Timer Count
|
TCNT4 = 0; //Reset Timer Count
|
||||||
TIFR4 = 0x00; //Timer4 INT Flag Reg: Clear Timer Overflow Flag
|
TIFR4 = 0x00; //Timer4 INT Flag Reg: Clear Timer Overflow Flag
|
||||||
TCCR4A = 0x00; //Timer4 Control Reg A: Wave Gen Mode normal
|
TCCR4A = 0x00; //Timer4 Control Reg A: Wave Gen Mode normal
|
||||||
TCCR4B = (1 << CS12); //Timer4 Control Reg B: aka Divisor = 256 = 122.5HzTimer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
TCCR4B = (1 << CS12); //Timer4 Control Reg B: aka Divisor = 256 = 122.5HzTimer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
||||||
ignitionSchedule4.Status = OFF;
|
#elif defined (CORE_TEENSY) && defined (__MK20DX256__)
|
||||||
fuelSchedule4.Status = OFF;
|
//Configure ARM timers here
|
||||||
|
#endif
|
||||||
|
|
||||||
ignitionSchedule4.schedulesSet = 0;
|
|
||||||
|
fuelSchedule1.Status = OFF;
|
||||||
|
fuelSchedule2.Status = OFF;
|
||||||
|
fuelSchedule3.Status = OFF;
|
||||||
|
fuelSchedule4.Status = OFF;
|
||||||
|
fuelSchedule5.Status = OFF;
|
||||||
|
|
||||||
|
fuelSchedule1.schedulesSet = 0;
|
||||||
|
fuelSchedule2.schedulesSet = 0;
|
||||||
|
fuelSchedule3.schedulesSet = 0;
|
||||||
fuelSchedule4.schedulesSet = 0;
|
fuelSchedule4.schedulesSet = 0;
|
||||||
//Note that timer4 compare channel C is used by the idle control
|
fuelSchedule5.schedulesSet = 0;
|
||||||
|
|
||||||
|
ignitionSchedule1.Status = OFF;
|
||||||
|
ignitionSchedule2.Status = OFF;
|
||||||
|
ignitionSchedule3.Status = OFF;
|
||||||
|
ignitionSchedule4.Status = OFF;
|
||||||
|
|
||||||
|
ignitionSchedule1.schedulesSet = 0;
|
||||||
|
ignitionSchedule2.schedulesSet = 0;
|
||||||
|
ignitionSchedule3.schedulesSet = 0;
|
||||||
|
ignitionSchedule4.schedulesSet = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -82,6 +88,7 @@ void setFuelSchedule1(void (*startCallback)(), unsigned long timeout, unsigned l
|
||||||
* As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
* As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
||||||
* unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
|
* unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
|
||||||
*/
|
*/
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
fuelSchedule1.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
fuelSchedule1.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
||||||
fuelSchedule1.endCompare = fuelSchedule1.startCompare + (duration >> 4);
|
fuelSchedule1.endCompare = fuelSchedule1.startCompare + (duration >> 4);
|
||||||
|
@ -91,6 +98,7 @@ void setFuelSchedule1(void (*startCallback)(), unsigned long timeout, unsigned l
|
||||||
else { timer3Aqueue[0] = &fuelSchedule1; timer3Aqueue[1] = &fuelSchedule1; timer3Aqueue[2] = &fuelSchedule1; timer3Aqueue[3] = &fuelSchedule1; OCR3A = fuelSchedule1.startCompare; }
|
else { timer3Aqueue[0] = &fuelSchedule1; timer3Aqueue[1] = &fuelSchedule1; timer3Aqueue[2] = &fuelSchedule1; timer3Aqueue[3] = &fuelSchedule1; OCR3A = fuelSchedule1.startCompare; }
|
||||||
interrupts();
|
interrupts();
|
||||||
TIMSK3 |= (1 << OCIE3A); //Turn on the A compare unit (ie turn on the interrupt)
|
TIMSK3 |= (1 << OCIE3A); //Turn on the A compare unit (ie turn on the interrupt)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void setFuelSchedule2(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
void setFuelSchedule2(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
||||||
{
|
{
|
||||||
|
@ -106,6 +114,7 @@ void setFuelSchedule2(void (*startCallback)(), unsigned long timeout, unsigned l
|
||||||
* As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
* As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
||||||
* unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
|
* unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
|
||||||
*/
|
*/
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
fuelSchedule2.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
fuelSchedule2.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
||||||
fuelSchedule2.endCompare = fuelSchedule2.startCompare + (duration >> 4);
|
fuelSchedule2.endCompare = fuelSchedule2.startCompare + (duration >> 4);
|
||||||
|
@ -114,40 +123,57 @@ void setFuelSchedule2(void (*startCallback)(), unsigned long timeout, unsigned l
|
||||||
fuelSchedule2.schedulesSet++; //Increment the number of times this schedule has been set
|
fuelSchedule2.schedulesSet++; //Increment the number of times this schedule has been set
|
||||||
interrupts();
|
interrupts();
|
||||||
TIMSK3 |= (1 << OCIE3B); //Turn on the B compare unit (ie turn on the interrupt)
|
TIMSK3 |= (1 << OCIE3B); //Turn on the B compare unit (ie turn on the interrupt)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void setFuelSchedule3(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
void setFuelSchedule3(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
||||||
{
|
{
|
||||||
if(fuelSchedule3.Status == RUNNING) { return; } //Check that we're not already part way through a schedule
|
if(fuelSchedule3.Status == RUNNING) { return; } //Check that we're not already part way through a schedule
|
||||||
|
|
||||||
|
fuelSchedule3.StartCallback = startCallback; //Name the start callback function
|
||||||
|
fuelSchedule3.EndCallback = endCallback; //Name the end callback function
|
||||||
|
fuelSchedule3.duration = duration;
|
||||||
|
|
||||||
//We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
|
/*
|
||||||
//As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
* The following must be enclosed in the noIntterupts block to avoid contention caused if the relevant interrupts fires before the state is fully set
|
||||||
//unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as require
|
* We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
|
||||||
|
* As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
||||||
|
* unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
|
||||||
|
*/
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
|
||||||
|
noInterrupts();
|
||||||
fuelSchedule3.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
fuelSchedule3.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
||||||
fuelSchedule3.endCompare = fuelSchedule3.startCompare + (duration >> 4);
|
fuelSchedule3.endCompare = fuelSchedule3.startCompare + (duration >> 4);
|
||||||
OCR3C = fuelSchedule3.startCompare; //Use the C copmare unit of timer 3
|
OCR3C = fuelSchedule3.startCompare; //Use the C copmare unit of timer 3
|
||||||
fuelSchedule3.duration = duration;
|
|
||||||
fuelSchedule3.StartCallback = startCallback; //Name the start callback function
|
|
||||||
fuelSchedule3.EndCallback = endCallback; //Name the end callback function
|
|
||||||
fuelSchedule3.Status = PENDING; //Turn this schedule on
|
fuelSchedule3.Status = PENDING; //Turn this schedule on
|
||||||
fuelSchedule3.schedulesSet++; //Increment the number of times this schedule has been set
|
fuelSchedule3.schedulesSet++; //Increment the number of times this schedule has been set
|
||||||
|
interrupts();
|
||||||
TIMSK3 |= (1 << OCIE3C); //Turn on the C compare unit (ie turn on the interrupt)
|
TIMSK3 |= (1 << OCIE3C); //Turn on the C compare unit (ie turn on the interrupt)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void setFuelSchedule4(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)()) //Uses timer 4 compare B
|
void setFuelSchedule4(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)()) //Uses timer 4 compare B
|
||||||
{
|
{
|
||||||
if(fuelSchedule4.Status == RUNNING) { return; } //Check that we're not already part way through a schedule
|
if(fuelSchedule4.Status == RUNNING) { return; } //Check that we're not already part way through a schedule
|
||||||
|
|
||||||
|
fuelSchedule4.StartCallback = startCallback; //Name the start callback function
|
||||||
|
fuelSchedule4.EndCallback = endCallback; //Name the end callback function
|
||||||
|
fuelSchedule4.duration = duration;
|
||||||
|
|
||||||
//We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
|
/*
|
||||||
//As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
* The following must be enclosed in the noIntterupts block to avoid contention caused if the relevant interrupts fires before the state is fully set
|
||||||
//unsigned int absoluteTimeout = TCNT4 + (timeout / 4); //Each tick occurs every 4uS with the 128 prescaler, so divide the timeout by 4 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
|
* We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
|
||||||
|
* As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
|
||||||
|
* unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
|
||||||
|
*/
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
|
||||||
|
noInterrupts();
|
||||||
fuelSchedule4.startCompare = TCNT4 + (timeout >> 4);
|
fuelSchedule4.startCompare = TCNT4 + (timeout >> 4);
|
||||||
fuelSchedule4.endCompare = fuelSchedule4.startCompare + (duration >> 4);
|
fuelSchedule4.endCompare = fuelSchedule4.startCompare + (duration >> 4);
|
||||||
OCR4B = fuelSchedule4.startCompare; //Use the C copmare unit of timer 3
|
OCR4B = fuelSchedule4.startCompare; //Use the C copmare unit of timer 3
|
||||||
fuelSchedule4.duration = duration;
|
|
||||||
fuelSchedule4.StartCallback = startCallback; //Name the start callback function
|
|
||||||
fuelSchedule4.EndCallback = endCallback; //Name the end callback function
|
|
||||||
fuelSchedule4.Status = PENDING; //Turn this schedule on
|
fuelSchedule4.Status = PENDING; //Turn this schedule on
|
||||||
fuelSchedule4.schedulesSet++; //Increment the number of times this schedule has been set
|
fuelSchedule4.schedulesSet++; //Increment the number of times this schedule has been set
|
||||||
|
interrupts();
|
||||||
TIMSK4 |= (1 << OCIE4B); //Turn on the B compare unit (ie turn on the interrupt)
|
TIMSK4 |= (1 << OCIE4B); //Turn on the B compare unit (ie turn on the interrupt)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void setFuelSchedule5(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
void setFuelSchedule5(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
||||||
{
|
{
|
||||||
|
@ -163,6 +189,7 @@ void setFuelSchedule5(void (*startCallback)(), unsigned long timeout, unsigned l
|
||||||
/*
|
/*
|
||||||
* The following must be enclosed in the noIntterupts block to avoid contention caused if the relevant interrupts fires before the state is fully set
|
* The following must be enclosed in the noIntterupts block to avoid contention caused if the relevant interrupts fires before the state is fully set
|
||||||
*/
|
*/
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
fuelSchedule5.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
fuelSchedule5.startCompare = TCNT3 + (timeout >> 4); //As above, but with bit shift instead of / 16
|
||||||
fuelSchedule5.endCompare = fuelSchedule5.startCompare + (duration >> 4);
|
fuelSchedule5.endCompare = fuelSchedule5.startCompare + (duration >> 4);
|
||||||
|
@ -171,6 +198,7 @@ void setFuelSchedule5(void (*startCallback)(), unsigned long timeout, unsigned l
|
||||||
OCR3A = setQueue(timer3Aqueue, &fuelSchedule1, &fuelSchedule5, TCNT3); //Schedule 1 shares a timer with schedule 5
|
OCR3A = setQueue(timer3Aqueue, &fuelSchedule1, &fuelSchedule5, TCNT3); //Schedule 1 shares a timer with schedule 5
|
||||||
interrupts();
|
interrupts();
|
||||||
TIMSK3 |= (1 << OCIE3A); //Turn on the A compare unit (ie turn on the interrupt)
|
TIMSK3 |= (1 << OCIE3A); //Turn on the A compare unit (ie turn on the interrupt)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
//Ignition schedulers use Timer 5
|
//Ignition schedulers use Timer 5
|
||||||
void setIgnitionSchedule1(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
void setIgnitionSchedule1(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
|
||||||
|
@ -252,7 +280,11 @@ void setIgnitionSchedule5(void (*startCallback)(), unsigned long timeout, unsign
|
||||||
//This calls the relevant callback function (startCallback or endCallback) depending on the status of the schedule.
|
//This calls the relevant callback function (startCallback or endCallback) depending on the status of the schedule.
|
||||||
//If the startCallback function is called, we put the scheduler into RUNNING state
|
//If the startCallback function is called, we put the scheduler into RUNNING state
|
||||||
//Timer3A (fuel schedule 1) Compare Vector
|
//Timer3A (fuel schedule 1) Compare Vector
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
|
||||||
ISR(TIMER3_COMPA_vect, ISR_NOBLOCK) //fuelSchedules 1 and 5
|
ISR(TIMER3_COMPA_vect, ISR_NOBLOCK) //fuelSchedules 1 and 5
|
||||||
|
#elif defined (CORE_TEENSY) && defined (__MK20DX256__)
|
||||||
|
void timer3compareAinterrupt() //Most ARM chips can simply call a function
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (timer3Aqueue[0]->Status == OFF) { TIMSK3 &= ~(1 << OCIE3A); return; } //Safety check. Turn off this output compare unit and return without performing any action
|
if (timer3Aqueue[0]->Status == OFF) { TIMSK3 &= ~(1 << OCIE3A); return; } //Safety check. Turn off this output compare unit and return without performing any action
|
||||||
if (timer3Aqueue[0]->Status == PENDING) //Check to see if this schedule is turn on
|
if (timer3Aqueue[0]->Status == PENDING) //Check to see if this schedule is turn on
|
||||||
|
@ -270,7 +302,11 @@ ISR(TIMER3_COMPA_vect, ISR_NOBLOCK) //fuelSchedules 1 and 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
|
||||||
ISR(TIMER3_COMPB_vect, ISR_NOBLOCK) //fuelSchedule2
|
ISR(TIMER3_COMPB_vect, ISR_NOBLOCK) //fuelSchedule2
|
||||||
|
#elif defined (CORE_TEENSY) && defined (__MK20DX256__)
|
||||||
|
void timer3compareBinterrupt() //Most ARM chips can simply call a function
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (fuelSchedule2.Status == PENDING) //Check to see if this schedule is turn on
|
if (fuelSchedule2.Status == PENDING) //Check to see if this schedule is turn on
|
||||||
{
|
{
|
||||||
|
|
|
@ -460,7 +460,7 @@ void setup()
|
||||||
currentLoopTime = micros();
|
currentLoopTime = micros();
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
|
||||||
//This sets the ADC (Analog to Digitial Converter) to run at 1Mhz, greatly reducing analog read times (MAP/TPS)
|
//This sets the ADC (Analog to Digitial Converter) to run at 1Mhz, greatly reducing analog read times (MAP/TPS)
|
||||||
//1Mhz is the fastest speed permitted by the CPU without affecting accuracy
|
//1Mhz is the fastest speed permitted by the CPU without affecting accuracy
|
||||||
//Please see chapter 11 of 'Practical Arduino' (http://books.google.com.au/books?id=HsTxON1L6D4C&printsec=frontcover#v=onepage&q&f=false) for more details
|
//Please see chapter 11 of 'Practical Arduino' (http://books.google.com.au/books?id=HsTxON1L6D4C&printsec=frontcover#v=onepage&q&f=false) for more details
|
||||||
|
@ -470,6 +470,7 @@ void setup()
|
||||||
cbi(ADCSRA,ADPS1);
|
cbi(ADCSRA,ADPS1);
|
||||||
cbi(ADCSRA,ADPS0);
|
cbi(ADCSRA,ADPS0);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
mainLoopCount = 0;
|
mainLoopCount = 0;
|
||||||
|
@ -817,7 +818,7 @@ void loop()
|
||||||
fuelOn = false;
|
fuelOn = false;
|
||||||
if (fpPrimed) { digitalWrite(pinFuelPump, LOW); } //Turn off the fuel pump, but only if the priming is complete
|
if (fpPrimed) { digitalWrite(pinFuelPump, LOW); } //Turn off the fuel pump, but only if the priming is complete
|
||||||
fuelPumpOn = false;
|
fuelPumpOn = false;
|
||||||
TIMSK4 &= ~(1 << OCIE4C); digitalWrite(pinIdle1, LOW); //Turns off the idle control PWM. This REALLY needs to be cleaned up into a general PWM controller class
|
disableIdle(); //Turn off the idle PWM
|
||||||
}
|
}
|
||||||
|
|
||||||
//Uncomment the following for testing
|
//Uncomment the following for testing
|
||||||
|
@ -1002,7 +1003,6 @@ void loop()
|
||||||
if( !BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
|
if( !BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
|
||||||
{
|
{
|
||||||
unsigned long pwLimit = percentage(configPage1.dutyLim, revolutionTime); //The pulsewidth limit is determined to be the duty cycle limit (Eg 85%) by the total time it takes to perform 1 revolution
|
unsigned long pwLimit = percentage(configPage1.dutyLim, revolutionTime); //The pulsewidth limit is determined to be the duty cycle limit (Eg 85%) by the total time it takes to perform 1 revolution
|
||||||
if (
|
|
||||||
if (currentStatus.PW > pwLimit) { currentStatus.PW = pwLimit; }
|
if (currentStatus.PW > pwLimit) { currentStatus.PW = pwLimit; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue