speeduino/speeduino/comms_secondary.cpp

225 lines
8.6 KiB
C++

/*
Speeduino - Simple engine management for the Arduino Mega 2560 platform
Copyright (C) Josh Stewart
A full copy of the license may be found in the projects root directory
can_comms was originally contributed by Darren Siepka
*/
/*
secondserial_command is called when a command is received from the secondary serial port
It parses the command and calls the relevant function.
can_command is called when a command is received by the onboard/attached canbus module
It parses the command and calls the relevant function.
sendcancommand is called when a command is to be sent either to serial3
,to the external Can interface, or to the onboard/attached can interface
*/
#include "globals.h"
#include "comms_secondary.h"
#include "comms_CAN.h"
#include "maths.h"
#include "errors.h"
#include "utilities.h"
#include "comms_legacy.h"
#include "logger.h"
#include "page_crc.h"
#include BOARD_H
uint8_t currentSecondaryCommand;
SECONDARY_SERIAL_T* pSecondarySerial;
void secondserial_Command(void)
{
#if defined(secondarySerial_AVAILABLE)
if ( serialSecondaryStatusFlag == SERIAL_INACTIVE ) { currentSecondaryCommand = secondarySerial.read(); }
switch (currentSecondaryCommand)
{
case 'A':
// sends a fixed 75 bytes of data. Used by Real Dash (Among others)
if(configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC_FIXED) { sendValues(0, CAN_PACKET_SIZE, 0x31, secondarySerial, serialSecondaryStatusFlag, &getLegacySecondarySerialLogEntry); } // Send values using the legacy fixed byte order
else { sendValues(0, CAN_PACKET_SIZE, 0x31, secondarySerial, serialSecondaryStatusFlag); } //send values to serial3 using the order in the ini file
break;
case 'b': // New EEPROM burn command to only burn a single page at a time
legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag);
break;
case 'B': // AS above but for the serial compatibility mode.
BIT_SET(currentStatus.status4, BIT_STATUS4_COMMS_COMPAT); //Force the compat mode
legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag);
break;
case 'd': // Send a CRC32 hash of a given page
legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag);
break;
case 'G': // this is the reply command sent by the Can interface
serialSecondaryStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY;
byte destcaninchannel;
if (secondarySerial.available() >= 9)
{
serialSecondaryStatusFlag = SERIAL_INACTIVE;
uint8_t cmdSuccessful = secondarySerial.read(); //0 == fail, 1 == good.
destcaninchannel = secondarySerial.read(); // the input channel that requested the data value
if (cmdSuccessful != 0)
{ // read all 8 bytes of data.
uint8_t Gdata[9];
uint8_t Glow, Ghigh;
for (byte Gx = 0; Gx < 8; Gx++) // first two are the can address the data is from. next two are the can address the data is for.then next 1 or two bytes of data
{
Gdata[Gx] = secondarySerial.read();
}
Glow = Gdata[(configPage9.caninput_source_start_byte[destcaninchannel]&7)];
if ((BIT_CHECK(configPage9.caninput_source_num_bytes,destcaninchannel) > 0)) //if true then num bytes is 2
{
if ((configPage9.caninput_source_start_byte[destcaninchannel]&7) < 8) //you can't have a 2 byte value starting at byte 7(8 on the list)
{
Ghigh = Gdata[((configPage9.caninput_source_start_byte[destcaninchannel]&7)+1)];
}
else { Ghigh = 0; }
}
else
{
Ghigh = 0;
}
currentStatus.canin[destcaninchannel] = (Ghigh<<8) | Glow;
}
else{} //continue as command request failed and/or data/device was not available
}
break;
case 'k': //placeholder for new can interface (toucan etc) commands
break;
case 'L':
{
//uint8_t Llength;
while (secondarySerial.available() == 0) { }
uint8_t canListen = secondarySerial.read();
if (canListen == 0)
{
//command request failed and/or data/device was not available
break;
}
while (secondarySerial.available() == 0) { }
/*
Unclear what the below is trying to achieve. Commenting out for now to avoid compiler warnings for unused variables
Llength = secondarySerial.read(); // next the number of bytes expected value
uint8_t Lbuffer[8]; //8 byte buffer to store incoming can data
for (uint8_t Lcount = 0; Lcount <Llength ;Lcount++)
{
while (secondarySerial.available() == 0){}
// receive all x bytes into "Lbuffer"
Lbuffer[Lcount] = secondarySerial.read();
}
*/
break;
}
case 'M':
legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag);
break;
case 'n': // sends the bytes of realtime values from the NEW CAN list
//sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, secondarySerial, serialSecondaryStatusFlag); //send values to serial3
if(configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC_FIXED) { sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, secondarySerial, serialSecondaryStatusFlag, &getLegacySecondarySerialLogEntry); } // Send values using the legacy fixed byte order
else { sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, secondarySerial, serialSecondaryStatusFlag); } //send values to serial3 using the order in the ini file
break;
case 'p':
legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag);
break;
case 'Q': // send code version
legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag);
break;
case 'r': //New format for the optimised OutputChannels over CAN
legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag);
break;
case 's': // send the "a" stream code version
secondarySerial.print(F("Speeduino csx02019.8"));
break;
case 'S': // send code version
if(configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_MSDROID) { legacySerialHandler('Q', secondarySerial, serialSecondaryStatusFlag); } //Note 'Q', this is a workaround for msDroid
else { legacySerialHandler(currentSecondaryCommand, secondarySerial, serialSecondaryStatusFlag); }
break;
case 'Z': //dev use
break;
default:
break;
}
#endif
}
// this routine sends a request(either "0" for a "G" , "1" for a "L" , "2" for a "R" to the Can interface or "3" sends the request via the actual local canbus
void sendCancommand(uint8_t cmdtype, uint16_t canaddress, uint8_t candata1, uint8_t candata2, uint16_t sourcecanAddress)
{
#if defined(secondarySerial_AVAILABLE)
switch (cmdtype)
{
case 0:
secondarySerial.print("G");
secondarySerial.write(canaddress); //tscanid of speeduino device
secondarySerial.write(candata1); // table id
secondarySerial.write(candata2); //table memory offset
break;
case 1: //send request to listen for a can message
secondarySerial.print("L");
secondarySerial.write(canaddress); //11 bit canaddress of device to listen for
break;
case 2: // requests via serial3
secondarySerial.print("R"); //send "R" to request data from the sourcecanAddress whose value is sent next
secondarySerial.write(candata1); //the currentStatus.current_caninchannel
secondarySerial.write(lowByte(sourcecanAddress) ); //send lsb first
secondarySerial.write(highByte(sourcecanAddress) );
break;
case 3:
//send to truecan send routine
//canaddress == speeduino canid, candata1 == canin channel dest, paramgroup == can address to request from
//This section is to be moved to the correct can output routine later
#if defined(NATIVE_CAN_AVAILABLE)
outMsg.id = (canaddress);
outMsg.len = 8;
outMsg.buf[0] = 0x0B ; //11;
outMsg.buf[1] = 0x15;
outMsg.buf[2] = candata1;
outMsg.buf[3] = 0x24;
outMsg.buf[4] = 0x7F;
outMsg.buf[5] = 0x70;
outMsg.buf[6] = 0x9E;
outMsg.buf[7] = 0x4D;
CAN_write();
#endif
break;
default:
break;
}
#else
UNUSED(cmdtype);
UNUSED(canaddress);
UNUSED(candata1);
UNUSED(candata2);
UNUSED(sourcecanAddress);
#endif
}