2013-07-16 20:09:18 -07:00
/*
This is called when a command is received over serial from TunerStudio / Megatune
It parses the command and calls the relevant function
A detailed description of each call can be found at : http : //www.msextra.com/doc/ms1extra/COM_RS232.htm
*/
2013-07-08 17:43:41 -07:00
void command ( )
{
switch ( Serial . read ( ) )
{
case ' A ' : // send 22 bytes of realtime values
sendValues ( 22 ) ;
break ;
2013-07-16 20:09:18 -07:00
case ' B ' : // Burn current values to eeprom
2013-07-18 04:53:40 -07:00
writeConfig ( ) ;
2013-07-08 17:43:41 -07:00
break ;
2013-07-16 20:09:18 -07:00
case ' C ' : // test communications. This is used by Tunerstudio to see whether there is an ECU on a given serial port
2013-07-08 17:43:41 -07:00
testComm ( ) ;
break ;
case ' P ' : // set the current page
2013-07-09 05:12:35 -07:00
//Blue
2013-07-08 17:43:41 -07:00
digitalWrite ( 10 , HIGH ) ;
digitalWrite ( 9 , LOW ) ;
digitalWrite ( 13 , LOW ) ;
2013-07-16 20:09:18 -07:00
//A 2nd byte of data is required after the 'P' specifying the new page number.
//This loop should never need to run as the byte should already be in the buffer, but is here just in case
while ( Serial . available ( ) = = 0 ) { }
2013-07-09 05:12:35 -07:00
currentPage = Serial . read ( ) ;
2013-07-08 17:43:41 -07:00
break ;
case ' R ' : // send 39 bytes of realtime values
sendValues ( 39 ) ;
break ;
case ' S ' : // send code version
Serial . write ( ms_version ) ;
break ;
case ' Q ' : // send code version
2013-07-09 05:12:35 -07:00
//Off
2013-07-08 17:43:41 -07:00
digitalWrite ( 9 , LOW ) ;
digitalWrite ( 10 , LOW ) ;
digitalWrite ( 13 , LOW ) ;
Serial . write ( ms_version ) ;
break ;
case ' V ' : // send VE table and constants
2013-07-09 05:12:35 -07:00
//Red
2013-07-08 17:43:41 -07:00
digitalWrite ( 9 , LOW ) ;
digitalWrite ( 10 , LOW ) ;
digitalWrite ( 13 , HIGH ) ;
sendPage ( ) ;
break ;
case ' W ' : // receive new VE or constant at 'W'+<offset>+<newbyte>
2013-07-09 05:12:35 -07:00
//Green
2013-07-08 17:43:41 -07:00
digitalWrite ( 9 , HIGH ) ;
digitalWrite ( 10 , LOW ) ;
digitalWrite ( 13 , LOW ) ;
2013-07-16 20:09:18 -07:00
2013-07-18 00:26:24 -07:00
receiveValue ( Serial . read ( ) , Serial . read ( ) ) ;
2013-07-08 17:43:41 -07:00
break ;
default :
break ;
}
}
2013-07-16 20:09:18 -07:00
/*
This function returns the current values of a fixed group of variables
*/
2013-07-08 17:43:41 -07:00
void sendValues ( int length )
{
byte response [ 22 ] ;
response [ 0 ] = ( uint8_t ) 1 ; //rtc.sec;
boolean a = 0 ; //inj_port1.status;
boolean b = 0 ; //inj_port2.status;
2013-08-25 21:11:47 -07:00
response [ 1 ] = currentStatus . squirt ; //((a & 0x01) << 0) | ((a & 0x02) << 1) | ((a & 0x04) << 1) | ((b & 0x01) << 1) | ((b & 0x02) << 3) | ((b & 0x04) << 3); //squirt NOT YET WORKING
2013-07-08 17:43:41 -07:00
2013-08-25 21:11:47 -07:00
response [ 2 ] = currentStatus . engine ; // Engine Status NOT YET WORKING
2013-07-08 17:43:41 -07:00
response [ 3 ] = 0x00 ; //baro
2013-07-09 17:26:16 -07:00
response [ 4 ] = currentStatus . MAP ; //map
2013-07-08 17:43:41 -07:00
response [ 5 ] = 0x00 ; //mat
response [ 6 ] = 0x00 ; //Coolant
response [ 7 ] = 0x00 ; //TPS
response [ 8 ] = 0x00 ; //battery voltage
response [ 9 ] = 0x00 ; //O2
response [ 10 ] = 0x00 ; //Exhaust gas correction (%)
response [ 11 ] = 0x00 ; //Air Correction (%)
response [ 12 ] = 0x00 ; //Warmup enrichment (%)
2013-07-09 17:26:16 -07:00
response [ 13 ] = ( currentStatus . RPM / 100 ) ; //rpm / 100
response [ 14 ] = currentStatus . PW / 100 ; //Pulsewidth 1 divided by 10 (in ms)
2013-07-08 17:43:41 -07:00
response [ 15 ] = 0x00 ; //acceleration enrichment (ms)
response [ 16 ] = 0x00 ; //Barometer correction (%)
response [ 17 ] = 0x00 ; //Total GammaE (%)
2013-07-09 17:26:16 -07:00
response [ 18 ] = currentStatus . VE ; //Current VE 1 (%)
2013-07-08 17:43:41 -07:00
response [ 19 ] = 0x00 ; //Pulsewidth 2 divided by 10 (in ms)
response [ 20 ] = 0x00 ; //mCurrent VE 2 (%)
response [ 21 ] = 0x00 ; //Idle
Serial . write ( response , ( size_t ) 22 ) ;
return ;
}
2013-07-18 00:26:24 -07:00
void receiveValue ( byte offset , byte newValue )
{
2013-07-18 03:36:36 -07:00
byte * pnt_configPage ;
switch ( currentPage )
{
case vePage :
2013-07-19 04:02:19 -07:00
pnt_configPage = ( byte * ) & configPage1 ; //Setup a pointer to the relevant config page
2013-07-18 03:36:36 -07:00
if ( offset < 64 ) //New value is part of the fuel map
{
2013-07-19 04:02:19 -07:00
fuelTable . values [ 7 - offset / 8 ] [ offset % 8 ] = newValue ;
2013-07-18 03:36:36 -07:00
}
else if ( offset < 80 ) //New value is one of the X or Y axis bins
{
2013-07-19 04:02:19 -07:00
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
if ( offset < 72 )
{
//X Axis
2013-08-25 21:11:47 -07:00
//*(pnt_configPage + offset) = 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 [ ( offset - 64 ) ] = newValue * 100 ; //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct
2013-07-19 04:02:19 -07:00
}
else
{
//Y Axis
offset = 7 - ( offset - 72 ) ; //Need to do a translation to flip the order (Due to us using (0,0) in the top left rather than bottom right
2013-08-25 21:11:47 -07:00
//*(pnt_configPage + offset) = newValue;
fuelTable . axisY [ offset ] = newValue ;
2013-07-19 04:02:19 -07:00
}
2013-07-18 03:36:36 -07:00
}
else //New value is one of the remaining config items
{
* ( pnt_configPage + offset ) = newValue ;
}
break ;
case ignPage : //Ignition settings page (Page 2)
pnt_configPage = ( byte * ) & configPage2 ;
if ( offset < 64 ) //New value is part of the ignition map
{
2013-07-19 04:02:19 -07:00
ignitionTable . values [ 7 - offset / 8 ] [ offset % 8 ] = newValue ;
2013-07-18 03:36:36 -07:00
}
else if ( offset < 80 ) //New value is one of the X or Y axis bins
{
2013-07-19 04:02:19 -07:00
//Check whether this is on the X (RPM) or Y (MAP/TPS) axis
if ( offset < 72 )
{
//X Axis
* ( pnt_configPage + offset ) = newValue * 100 ;
}
else
{
//Y Axis
offset = 7 - ( offset - 72 ) ; //Need to do a translation to flip the order
* ( pnt_configPage + offset ) = newValue ;
}
2013-07-18 03:36:36 -07:00
}
else //New value is one of the remaining config items
{
* ( pnt_configPage + offset ) = newValue ;
}
break ;
default :
break ;
}
2013-07-18 00:26:24 -07:00
}
2013-08-25 21:11:47 -07:00
/*
sendPage ( ) packs the data within the current page ( As set with the ' P ' command )
into a buffer and sends it .
Note that some translation of the data is required to lay it out in the way Megasqurit / TunerStudio expect it
*/
2013-07-08 17:43:41 -07:00
void sendPage ( )
{
2013-07-18 03:36:36 -07:00
byte response [ page_size ] ;
2013-07-18 00:26:24 -07:00
byte offset ;
byte * pnt_configPage ;
2013-07-08 21:06:45 -07:00
2013-07-09 05:12:35 -07:00
switch ( ( int ) currentPage )
2013-07-08 21:06:45 -07:00
{
case vePage :
2013-07-09 05:12:35 -07:00
//Need to perform a translation of the values[MAP/TPS][RPM] into the MS expected format
2013-07-16 20:09:18 -07:00
//MS format has origin (0,0) in the bottom left corner, we use the top left for efficiency reasons
2013-08-25 21:11:47 -07:00
for ( byte x = 0 ; x < 64 ; x + + ) { response [ x ] = fuelTable . values [ 7 - x / 8 ] [ x % 8 ] ; } //This is slightly non-intuitive, but essentially just flips the table vertically (IE top line becomes the bottom line etc). Columns are unchanged
2013-07-18 00:26:24 -07:00
for ( byte x = 64 ; x < 72 ; x + + ) { response [ x ] = fuelTable . axisX [ ( x - 64 ) ] / 100 ; } //RPM Bins for VE table (Need to be dvidied by 100)
2013-07-16 05:31:01 -07:00
for ( byte y = 72 ; y < 80 ; y + + ) { response [ y ] = fuelTable . axisY [ 7 - ( y - 72 ) ] ; } //MAP or TPS bins for VE table
2013-07-18 00:26:24 -07:00
//All other bytes can simply be copied from the config table
pnt_configPage = ( byte * ) & configPage1 ; //Create a pointer to Page 1 in memory
offset = 80 ; //Offset is based on the amount already copied above (table + bins)
2013-07-18 03:36:36 -07:00
for ( byte x = offset ; x < page_size ; x + + )
2013-07-18 00:26:24 -07:00
{
response [ offset ] = * ( pnt_configPage + offset + x ) ; //Each byte is simply the location in memory of configPage1 + the offset + the variable number (x)
}
2013-07-18 03:36:36 -07:00
Serial . write ( ( byte * ) & response , sizeof ( response ) ) ;
2013-07-08 21:06:45 -07:00
break ;
2013-07-10 04:18:18 -07:00
2013-07-08 21:06:45 -07:00
case ignPage :
2013-07-09 05:12:35 -07:00
//Need to perform a translation of the values[MAP/TPS][RPM] into the MS expected format
for ( byte x = 0 ; x < 64 ; x + + ) { response [ x ] = ignitionTable . values [ 7 - x / 8 ] [ x % 8 ] ; }
for ( byte x = 64 ; x < 72 ; x + + ) { response [ x ] = ignitionTable . axisX [ ( x - 64 ) ] / 100 ; }
for ( byte y = 72 ; y < 80 ; y + + ) { response [ y ] = ignitionTable . axisY [ 7 - ( y - 72 ) ] ; }
2013-07-08 21:06:45 -07:00
2013-07-18 00:26:24 -07:00
//All other bytes can simply be copied from the config table
2013-07-18 03:36:36 -07:00
pnt_configPage = ( byte * ) & configPage2 ; //Create a pointer to Page 2 in memory
2013-07-18 00:26:24 -07:00
offset = 80 ; //Offset is based on the amount already copied above (table + bins)
2013-07-18 03:36:36 -07:00
for ( byte x = offset ; x < page_size ; x + + )
2013-07-18 00:26:24 -07:00
{
response [ offset ] = * ( pnt_configPage + offset + x ) ; //Each byte is simply the location in memory of configPage + the offset + the variable number (x)
}
Serial . write ( ( byte * ) & response , sizeof ( response ) ) ;
2013-07-10 04:18:18 -07:00
break ;
2013-07-08 21:06:45 -07:00
default :
break ;
}
2013-07-08 17:43:41 -07:00
return ;
}
void testComm ( )
{
Serial . write ( 1 ) ;
return ;
}