1271 lines
30 KiB
C++
1271 lines
30 KiB
C++
/**
|
|
* @file can_dash.cpp
|
|
*
|
|
* This file handles transmission of ECU data to various OE dashboards.
|
|
*
|
|
* @date Mar 19, 2020
|
|
* @author Matthew Kennedy, (c) 2020
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
#if EFI_CAN_SUPPORT
|
|
#include "can_dash.h"
|
|
#include "can_msg_tx.h"
|
|
#include "can_bmw.h"
|
|
#include "can_vag.h"
|
|
|
|
#include "rtc_helper.h"
|
|
#include "fuel_math.h"
|
|
// CAN Bus ID for broadcast
|
|
#define CAN_FIAT_MOTOR_INFO 0x561
|
|
#define CAN_MAZDA_RX_RPM_SPEED 0x201
|
|
#define CAN_MAZDA_RX_STEERING_WARNING 0x300
|
|
#define CAN_MAZDA_RX_STATUS_1 0x212
|
|
#define CAN_MAZDA_RX_STATUS_2 0x420
|
|
|
|
//w202 DASH
|
|
#define W202_STAT_1 0x308 /* _20ms cycle */
|
|
#define W202_STAT_2 0x608 /* _100ms cycle */
|
|
#define W202_ALIVE 0x210 /* _200ms cycle */
|
|
#define W202_STAT_3 0x310 /* _200ms cycle */
|
|
|
|
//BMW E90 DASH
|
|
#define E90_ABS_COUNTER 0x0C0
|
|
#define E90_SEATBELT_COUNTER 0x0D7
|
|
#define E90_T15 0x130
|
|
#define E90_RPM 0x175
|
|
#define E90_BRAKE_COUNTER 0x19E
|
|
#define E90_SPEED 0x1A6
|
|
#define E90_TEMP 0x1D0
|
|
#define E90_GEAR 0x1D2
|
|
#define E90_FUEL 0x349
|
|
#define E90_EBRAKE 0x34F
|
|
#define E90_TIME 0x39E
|
|
|
|
#define HONDA_SPEED_158 0x158
|
|
#define HONDA_TACH_1DC 0x1DC
|
|
|
|
static time_msecs_t mph_timer;
|
|
static time_msecs_t mph_ctr;
|
|
|
|
/**
|
|
* https://docs.google.com/spreadsheets/d/1IkP05ODpjNt-k4YQLYl58_TNlN9U4IBu5z7i0BPVEM4
|
|
*/
|
|
#define GENESIS_COUPLE_RPM_316 0x316
|
|
#define GENESIS_COUPLE_COOLANT_329 0x329
|
|
#define GENESIS_COUPLE_SENSORS_382 0x382
|
|
// when A/C compressor is allowed to be on, these values need to be sent so the A/C panel activates the compressor
|
|
#define GENESIS_COUPLE_AC_ENABLE_18F 0x18F
|
|
|
|
#define NISSAN_RPM_1F9 0x1F9
|
|
// Nissan z33 350Z and else
|
|
// 0x23d = 573
|
|
#define NISSAN_RPM_CLT 0x23D
|
|
|
|
#define NISSAN_VEHICLE_SPEED_280 0x280
|
|
// wheel speed see "102 CAN Communication decoded"
|
|
// 19500 value would be 100 kph
|
|
#define NISSAN_WHEEL_SPEED 0x285
|
|
|
|
#define NISSAN_CLT_551 0x551
|
|
|
|
static uint8_t rpmcounter;
|
|
static uint8_t seatbeltcnt;
|
|
static uint8_t abscounter = 0xF0;
|
|
static uint8_t brakecnt_1 = 0xF0, brakecnt_2 = 0xF0;
|
|
static uint8_t mph_a, mph_2a, mph_last, tmp_cnt, gear_cnt;
|
|
static uint16_t mph_counter = 0xF000;
|
|
static bool cluster_time_set;
|
|
|
|
constexpr uint8_t e90_temp_offset = 49;
|
|
|
|
// todo: those forward declarations are out of overall code style
|
|
void canDashboardBMW(CanCycle cycle);
|
|
void canDashboardFiat(CanCycle cycle);
|
|
void canMazdaRX8(CanCycle cycle);
|
|
void canDashboardW202(CanCycle cycle);
|
|
void canDashboardBMWE90(CanCycle cycle);
|
|
void canDashboardVagMqb(CanCycle cycle);
|
|
void canDashboardNissanVQ(CanCycle cycle);
|
|
void canDashboardGenesisCoupe(CanCycle cycle);
|
|
void canDashboardAim(CanCycle cycle);
|
|
void canDashboardHaltech(CanCycle cycle);
|
|
|
|
void updateDash(CanCycle cycle) {
|
|
|
|
// Transmit dash data, if enabled
|
|
switch (engineConfiguration->canNbcType) {
|
|
case CAN_BUS_NBC_NONE:
|
|
break;
|
|
case CAN_BUS_NBC_BMW:
|
|
canDashboardBMW(cycle);
|
|
break;
|
|
case CAN_BUS_Haltech:
|
|
canDashboardHaltech(cycle);
|
|
break;
|
|
case CAN_BUS_NBC_FIAT:
|
|
canDashboardFiat(cycle);
|
|
break;
|
|
case CAN_BUS_NBC_VAG:
|
|
canDashboardVAG(cycle);
|
|
break;
|
|
case CAN_BUS_MAZDA_RX8:
|
|
canMazdaRX8(cycle);
|
|
break;
|
|
case CAN_BUS_W202_C180:
|
|
canDashboardW202(cycle);
|
|
break;
|
|
case CAN_BUS_BMW_E90:
|
|
canDashboardBMWE90(cycle);
|
|
break;
|
|
case CAN_BUS_MQB:
|
|
canDashboardVagMqb(cycle);
|
|
break;
|
|
case CAN_BUS_NISSAN_VQ:
|
|
canDashboardNissanVQ(cycle);
|
|
break;
|
|
case CAN_BUS_GENESIS_COUPE:
|
|
canDashboardGenesisCoupe(cycle);
|
|
break;
|
|
case CAN_AIM_DASH:
|
|
canDashboardAim(cycle);
|
|
break;
|
|
default:
|
|
firmwareError(OBD_PCM_Processor_Fault, "Nothing for canNbcType %s", getCan_nbc_e(engineConfiguration->canNbcType));
|
|
break;
|
|
}
|
|
}
|
|
|
|
//BMW Dashboard
|
|
//todo: we use 50ms fixed cycle, trace is needed to check for correct period
|
|
void canDashboardBMW(CanCycle cycle) {
|
|
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_BMW_E46_SPEED);
|
|
msg.setShortValue(10 * 8, 1);
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_BMW_E46_RPM);
|
|
msg.setShortValue((int) (Sensor::getOrZero(SensorType::Rpm) * 6.4), 2);
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_BMW_E46_DME2);
|
|
msg.setShortValue((int) ((Sensor::getOrZero(SensorType::Clt) + 48.373) / 0.75), 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//todo: we use 50ms fixed cycle, trace is needed to check for correct period
|
|
void canMazdaRX8(CanCycle cycle) {
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_MAZDA_RX_STEERING_WARNING);
|
|
// todo: something needs to be set here? see http://rusefi.com/wiki/index.php?title=Vehicle:Mazda_Rx8_2004
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_MAZDA_RX_RPM_SPEED);
|
|
|
|
float kph = Sensor::getOrZero(SensorType::VehicleSpeed);
|
|
|
|
msg.setShortValue(SWAP_UINT16(Sensor::getOrZero(SensorType::Rpm) * 4), 0);
|
|
msg.setShortValue(0xFFFF, 2);
|
|
msg.setShortValue(SWAP_UINT16((int )(100 * kph + 10000)), 4);
|
|
msg.setShortValue(0, 6);
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_MAZDA_RX_STATUS_1);
|
|
msg[0] = 0xFE; //Unknown
|
|
msg[1] = 0xFE; //Unknown
|
|
msg[2] = 0xFE; //Unknown
|
|
msg[3] = 0x34; //DSC OFF in combo with byte 5 Live data only seen 0x34
|
|
msg[4] = 0x00; // B01000000; // Brake warning B00001000; //ABS warning
|
|
msg[5] = 0x40; // TCS in combo with byte 3
|
|
msg[6] = 0x00; // Unknown
|
|
msg[7] = 0x00; // Unused
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_MAZDA_RX_STATUS_2);
|
|
auto clt = Sensor::get(SensorType::Clt);
|
|
msg[0] = (uint8_t)(clt.value_or(0) + 69); //temp gauge //~170 is red, ~165 last bar, 152 centre, 90 first bar, 92 second bar
|
|
// TODO: fixme!
|
|
//msg[1] = ((int16_t)(engine->engineState.vssEventCounter*(engineConfiguration->vehicleSpeedCoef*0.277*2.58))) & 0xff;
|
|
msg[2] = 0x00; // unknown
|
|
msg[3] = 0x00; //unknown
|
|
msg[4] = 0x01; //Oil Pressure (not really a gauge)
|
|
msg[5] = 0x00; //check engine light
|
|
msg[6] = 0x00; //Coolant, oil and battery
|
|
if ((Sensor::getOrZero(SensorType::Rpm)>0) && (Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE)<13)) {
|
|
msg.setBit(6, 6); // battery light
|
|
}
|
|
if (!clt.Valid || clt.Value > 105) {
|
|
// coolant light, 101 - red zone, light means its get too hot
|
|
// Also turn on the light in case of sensor failure
|
|
msg.setBit(6, 1);
|
|
}
|
|
//oil pressure warning lamp bit is 7
|
|
msg[7] = 0x00; //unused
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void canDashboardFiat(CanCycle cycle) {
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
{
|
|
//Fiat Dashboard
|
|
CanTxMessage msg(CanCategory::NBC, CAN_FIAT_MOTOR_INFO);
|
|
msg.setShortValue((int) (Sensor::getOrZero(SensorType::Clt) - 40), 3); //Coolant Temp
|
|
msg.setShortValue(Sensor::getOrZero(SensorType::Rpm) / 32, 6); //RPM
|
|
}
|
|
}
|
|
}
|
|
|
|
void canDashboardVAG(CanCycle cycle) {
|
|
if (cycle.isInterval(CI::_10ms)) {
|
|
{
|
|
// https://github.com/commaai/opendbc/blob/57c8340a180dd8c75139b18050eb17c72c9cb6e4/vw_golf_mk4.dbc#L394
|
|
//VAG Dashboard
|
|
CanTxMessage msg(CanCategory::NBC, CAN_VAG_Motor_1);
|
|
msg.setShortValue(Sensor::getOrZero(SensorType::Rpm) * 4, 2); //RPM
|
|
}
|
|
|
|
float clt = Sensor::getOrZero(SensorType::Clt);
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_VAG_Motor_2);
|
|
msg.setShortValue((int) ((clt + 48.373) / 0.75), 1); //Coolant Temp
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_VAG_CLT_V2);
|
|
msg.setShortValue((int) ((clt + 48.373) / 0.75), 4); //Coolant Temp
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, CAN_VAG_IMMO);
|
|
msg.setShortValue(0x80, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void canDashboardW202(CanCycle cycle) {
|
|
if (cycle.isInterval(CI::_20ms)) {
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, W202_STAT_1);
|
|
uint16_t tmp = Sensor::getOrZero(SensorType::Rpm);
|
|
msg[0] = 0x08; // Unknown
|
|
msg[1] = (tmp >> 8); //RPM
|
|
msg[2] = (tmp & 0xff); //RPM
|
|
msg[3] = 0x00; // 0x01 - tank blink, 0x02 - EPC
|
|
msg[4] = 0x00; // Unknown
|
|
msg[5] = 0x00; // Unknown
|
|
msg[6] = 0x00; // Unknown - oil info
|
|
msg[7] = 0x00; // Unknown - oil info
|
|
}
|
|
}
|
|
|
|
if (cycle.isInterval(CI::_100ms)) {
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, W202_STAT_2); //dlc 7
|
|
msg[0] = (int)(Sensor::getOrZero(SensorType::Clt) + 40); // CLT -40 offset
|
|
msg[1] = 0x3D; // TBD
|
|
msg[2] = 0x63; // Const
|
|
msg[3] = 0x41; // Const
|
|
msg[4] = 0x00; // Unknown
|
|
msg[5] = 0x05; // Const
|
|
msg[6] = 0x50; // TBD
|
|
msg[7] = 0x00; // Unknown
|
|
}
|
|
}
|
|
|
|
if (cycle.isInterval(CI::_200ms)) {
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, W202_ALIVE);
|
|
msg[0] = 0x0A; // Const
|
|
msg[1] = 0x18; // Const
|
|
msg[2] = 0x00; // Const
|
|
msg[3] = 0x00; // Const
|
|
msg[4] = 0xC0; // Const
|
|
msg[5] = 0x00; // Const
|
|
msg[6] = 0x00; // Const
|
|
msg[7] = 0x00; // Const
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, W202_STAT_3);
|
|
msg[0] = 0x00; // Const
|
|
msg[1] = 0x00; // Const
|
|
msg[2] = 0x6D; // TBD
|
|
msg[3] = 0x7B; // Const
|
|
msg[4] = 0x21; // TBD
|
|
msg[5] = 0x07; // Const
|
|
msg[6] = 0x33; // Const
|
|
msg[7] = 0x05; // Const
|
|
}
|
|
}
|
|
}
|
|
|
|
static int rollingId = 0;
|
|
|
|
void canDashboardGenesisCoupe(CanCycle cycle) {
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, GENESIS_COUPLE_RPM_316, 8);
|
|
int rpm8 = Sensor::getOrZero(SensorType::Rpm) * 4;
|
|
msg[3] = rpm8 >> 8;
|
|
msg[4] = rpm8 & 0xFF;
|
|
}
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, GENESIS_COUPLE_COOLANT_329, 8);
|
|
int clt = Sensor::getOrZero(SensorType::Clt) * 2;
|
|
msg[1] = clt;
|
|
}
|
|
}
|
|
}
|
|
|
|
void canDashboardNissanVQ(CanCycle cycle) {
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, NISSAN_RPM_1F9, 8);
|
|
msg[0] = 0x20;
|
|
int rpm8 = (int)(Sensor::getOrZero(SensorType::Rpm) * 8);
|
|
msg[2] = rpm8 >> 8;
|
|
msg[3] = rpm8 & 0xFF;
|
|
}
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::OBD, NISSAN_CLT_551, 8);
|
|
|
|
int clt = Sensor::getOrZero(SensorType::Clt);
|
|
msg[0] = clt + 45;
|
|
}
|
|
|
|
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, NISSAN_RPM_CLT, 8);
|
|
|
|
rollingId = (rollingId + 1) % 4;
|
|
const uint8_t magicByte[4] = {0x03, 0x23, 0x42, 0x63};
|
|
|
|
msg[0] = magicByte[rollingId];
|
|
msg[1] = (int)(Sensor::getOrZero(SensorType::AcceleratorPedal) * 255 / 100);
|
|
|
|
// thank you "102 CAN Communication decoded"
|
|
#define CAN_23D_RPM_MULT 3.15
|
|
int rpm315 = (int)(Sensor::getOrZero(SensorType::Rpm) / CAN_23D_RPM_MULT);
|
|
msg[3] = rpm315 & 0xFF;
|
|
msg[4] = rpm315 >> 8;
|
|
|
|
msg[7] = 0x70; // todo: CLT decoding?
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* https://docs.google.com/spreadsheets/d/1XMfeGlhgl0lBL54lNtPdmmFd8gLr2T_YTriokb30kJg
|
|
*/
|
|
void canDashboardVagMqb(CanCycle cycle) {
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
|
|
{ // 'turn-on'
|
|
CanTxMessage msg(CanCategory::NBC, 0x3C0, 4);
|
|
// ignition ON
|
|
msg[2] = 3;
|
|
}
|
|
|
|
{ //RPM
|
|
CanTxMessage msg(CanCategory::NBC, 0x107, 8);
|
|
msg[3] = ((int)(Sensor::getOrZero(SensorType::Rpm) / 3.5)) & 0xFF;
|
|
msg[4] = ((int)(Sensor::getOrZero(SensorType::Rpm) / 3.5)) >> 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
void canDashboardBMWE90(CanCycle cycle)
|
|
{
|
|
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
|
|
{ //T15 'turn-on'
|
|
CanTxMessage msg(CanCategory::NBC, E90_T15, 5);
|
|
msg[0] = 0x45;
|
|
msg[1] = 0x41;
|
|
msg[2] = 0x61;
|
|
msg[3] = 0x8F;
|
|
msg[4] = 0xFC;
|
|
}
|
|
|
|
{ //Ebrake light
|
|
CanTxMessage msg(CanCategory::OBD, E90_EBRAKE, 2);
|
|
msg[0] = 0xFD;
|
|
msg[1] = 0xFF;
|
|
}
|
|
|
|
{ //RPM
|
|
rpmcounter++;
|
|
if (rpmcounter > 0xFE)
|
|
rpmcounter = 0xF0;
|
|
CanTxMessage msg(CanCategory::OBD, E90_RPM, 3);
|
|
msg[0] = rpmcounter;
|
|
msg[1] = ((int)(Sensor::getOrZero(SensorType::Rpm)) * 4) & 0xFF;
|
|
msg[2] = ((int)(Sensor::getOrZero(SensorType::Rpm)) * 4) >> 8;
|
|
}
|
|
|
|
{ //oil & coolant temp (all in C, despite gauge being F)
|
|
tmp_cnt++;
|
|
if (tmp_cnt >= 0x0F)
|
|
tmp_cnt = 0x00;
|
|
CanTxMessage msg(CanCategory::OBD, E90_TEMP, 8);
|
|
msg[0] = (int)(Sensor::getOrZero(SensorType::Clt) + e90_temp_offset); //coolant
|
|
msg[1] = (int)(Sensor::getOrZero(SensorType::AuxTemp1) + e90_temp_offset); //oil (AuxTemp1)
|
|
msg[2] = tmp_cnt;
|
|
msg[3] = 0xC8;
|
|
msg[4] = 0xA7;
|
|
msg[5] = 0xD3;
|
|
msg[6] = 0x0D;
|
|
msg[7] = 0xA8;
|
|
}
|
|
}
|
|
|
|
if (cycle.isInterval(CI::_100ms)) {
|
|
{
|
|
//Seatbelt counter
|
|
seatbeltcnt++;
|
|
if (seatbeltcnt > 0xFE)
|
|
seatbeltcnt = 0x00;
|
|
CanTxMessage msg(CanCategory::NBC, E90_SEATBELT_COUNTER, 2);
|
|
msg[0] = seatbeltcnt;
|
|
msg[1] = 0xFF;
|
|
}
|
|
|
|
{
|
|
//Brake counter 100ms
|
|
brakecnt_1 += 16;
|
|
brakecnt_2 += 16;
|
|
if (brakecnt_1 > 0xEF)
|
|
brakecnt_1 = 0x0F;
|
|
if (brakecnt_2 > 0xF0)
|
|
brakecnt_2 = 0xA0;
|
|
CanTxMessage msg(CanCategory::NBC, E90_BRAKE_COUNTER, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0xE0;
|
|
msg[2] = brakecnt_1;
|
|
msg[3] = 0xFC;
|
|
msg[4] = 0xFE;
|
|
msg[5] = 0x41;
|
|
msg[6] = 0x00;
|
|
msg[7] = brakecnt_2;
|
|
}
|
|
|
|
{ //ABS counter
|
|
abscounter++;
|
|
if (abscounter > 0xFE)
|
|
abscounter = 0xF0;
|
|
CanTxMessage msg(CanCategory::NBC, E90_ABS_COUNTER, 2);
|
|
msg[0] = abscounter;
|
|
msg[1] = 0xFF;
|
|
}
|
|
|
|
{ //Fuel gauge
|
|
CanTxMessage msg(CanCategory::NBC, E90_FUEL, 5); //fuel gauge
|
|
msg[0] = 0x76;
|
|
msg[1] = 0x0F;
|
|
msg[2] = 0xBE;
|
|
msg[3] = 0x1A;
|
|
msg[4] = 0x00;
|
|
}
|
|
|
|
{ //Gear indicator/counter
|
|
gear_cnt++;
|
|
if (gear_cnt >= 0x0F)
|
|
gear_cnt = 0x00;
|
|
CanTxMessage msg(CanCategory::NBC, E90_GEAR, 6);
|
|
msg[0] = 0x78;
|
|
msg[1] = 0x0F;
|
|
msg[2] = 0xFF;
|
|
msg[3] = (gear_cnt << 4) | 0xC;
|
|
msg[4] = 0xF1;
|
|
msg[5] = 0xFF;
|
|
}
|
|
|
|
{ //E90_SPEED
|
|
auto vehicleSpeed = Sensor::getOrZero(SensorType::VehicleSpeed);
|
|
float mph = vehicleSpeed * 0.6213712;
|
|
mph_ctr = ((TIME_I2MS(chVTGetSystemTime()) - mph_timer) / 50);
|
|
mph_a = (mph_ctr * mph / 2);
|
|
mph_2a = mph_a + mph_last;
|
|
mph_last = mph_2a;
|
|
mph_counter += mph_ctr * 100;
|
|
if(mph_counter >= 0xFFF0)
|
|
mph_counter = 0xF000;
|
|
mph_timer = TIME_I2MS(chVTGetSystemTime());
|
|
CanTxMessage msg(CanCategory::NBC, E90_SPEED, 8);
|
|
msg[0] = mph_2a & 0xFF;
|
|
msg[1] = mph_2a >> 8;
|
|
msg[2] = mph_2a & 0xFF;
|
|
msg[3] = mph_2a >> 8;
|
|
msg[4] = mph_2a & 0xFF;
|
|
msg[5] = mph_2a >> 8;
|
|
msg[6] = mph_counter & 0xFF;
|
|
msg[7] = (mph_counter >> 8) | 0xF0;
|
|
}
|
|
}
|
|
|
|
{
|
|
if (!cluster_time_set) {
|
|
struct tm timp;
|
|
date_get_tm(&timp);
|
|
CanTxMessage msg(CanCategory::NBC, E90_TIME, 8);
|
|
msg[0] = timp.tm_hour;
|
|
msg[1] = timp.tm_min;
|
|
msg[2] = timp.tm_sec;
|
|
msg[3] = timp.tm_mday;
|
|
msg[4] = (((timp.tm_mon + 1) << 4) | 0x0F);
|
|
msg[5] = (timp.tm_year + 1900) & 0xFF;
|
|
msg[6] = ((timp.tm_year + 1900) >> 8) | 0xF0;
|
|
msg[7] = 0xF2;
|
|
cluster_time_set = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void canDashboardHaltech(CanCycle cycle) {
|
|
|
|
uint16_t tmp;
|
|
|
|
if (cycle.isInterval(CI::_20ms)) {
|
|
/* 0x360 - 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x360, 8);
|
|
tmp = Sensor::getOrZero(SensorType::Rpm);
|
|
/* RPM */
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* MAP */
|
|
tmp = (((uint16_t)(Sensor::getOrZero(SensorType::Map))) * 10);
|
|
msg[2] = (tmp >> 8);
|
|
msg[3] = (tmp & 0x00ff);
|
|
/* TPS y = x/10 */
|
|
tmp = (uint16_t)((float)(Sensor::getOrZero(SensorType::Tps1)) * 10);
|
|
msg[4] = (tmp >> 8);
|
|
msg[5] = (tmp & 0x00ff);
|
|
/* Coolant pressure */
|
|
msg[6] = 0;
|
|
msg[7] = 0;
|
|
}
|
|
|
|
/* 0x361 - 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x361, 8);
|
|
/* Fuel pressure */
|
|
tmp = (uint16_t)(Sensor::getOrZero(SensorType::FuelPressureLow));
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp&0x00ff);
|
|
/* Oil pressure */
|
|
tmp = (uint16_t)(Sensor::getOrZero(SensorType::OilPressure));
|
|
msg[2] = (tmp >> 8);
|
|
msg[3] = (tmp & 0x00ff);
|
|
/* Engine Demand */
|
|
tmp = (uint16_t)(Sensor::getOrZero(SensorType::Map));
|
|
msg[4] = (tmp >> 8);
|
|
msg[5] = (tmp & 0x00ff);
|
|
/* Wastegate Pressure */
|
|
msg[6] = 0;
|
|
msg[7] = 0;
|
|
}
|
|
|
|
/* 0x362 - 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x362, 6);
|
|
/* Injection Stage 1 Duty Cycle - y = x/10 */
|
|
uint16_t rpm = Sensor::getOrZero(SensorType::Rpm);
|
|
tmp = (uint16_t)( getInjectorDutyCycle(rpm) * 10) ;
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* Injcetion Stage 2 Duty Cycle */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Ignition Angle (Leading) - y = x/10 */
|
|
float timing = engine->engineState.timingAdvance[0];
|
|
int16_t ignAngle = ((timing > 360 ? timing - 720 : timing) * 10);
|
|
msg[4] = (ignAngle >> 8);
|
|
msg[5] = (ignAngle & 0x00ff);
|
|
}
|
|
|
|
/* todo: 0x3E5 = 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E5, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3EA = 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3EA, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3EB = 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3EB, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3EC = 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3EC, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3ED = 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3ED, 2);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x471 = 50Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x471, 2);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
}
|
|
}
|
|
|
|
if (cycle.isInterval(CI::_50ms)) {
|
|
|
|
/* 0x363 - 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x363, 4);
|
|
/* Wheel Slip */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* Wheel Diff */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00 ;
|
|
}
|
|
|
|
/* 0x368 - 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x368, 8);
|
|
/* Wideband Sensor 1 */
|
|
tmp = (uint16_t)(Sensor::getOrZero(SensorType::Lambda1)) * 1000;
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* Wideband Sensor 2 */
|
|
tmp = (uint16_t)(Sensor::getOrZero(SensorType::Lambda2) * 1000);
|
|
msg[2] = (tmp >> 8);
|
|
msg[3] = (tmp & 0x00ff);
|
|
/* Wideband Sensor 3 */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Wideband Sensor 4 */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
#if EFI_SHAFT_POSITION_INPUT
|
|
/* 0x369 - 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x369, 8);
|
|
/* Trigger System Error Count */
|
|
tmp = engine->triggerCentral.triggerState.totalTriggerErrorCounter;
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* Trigger Counter ?? */
|
|
tmp = engine->triggerCentral.getHwEventCounter((int)SHAFT_PRIMARY_FALLING);
|
|
msg[2] = (tmp >> 8);
|
|
msg[3] = (tmp & 0x00ff);
|
|
/* unused */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Trigger Sync Level ?? */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
#endif // EFI_SHAFT_POSITION_INPUT
|
|
|
|
/* 0x36A - 20Hz rate */
|
|
/* todo: one day we should split this */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x36A, 4);
|
|
/* Knock Level 1 */
|
|
tmp = (engine->outputChannels.knockLevel * 100);
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* Knock Level 2 */
|
|
msg[2] = (tmp >> 8);
|
|
msg[3] = (tmp * 0x00ff);
|
|
}
|
|
|
|
/* 0x36B - 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x36B, 8);
|
|
/* Break Pressure */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* NOS pressure Sensor 1 */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Turbo Speed Sensor 1 */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Lateral G */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* 0x36C = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x36C, 8);
|
|
/* Wheel Speed Front Left */
|
|
auto vehicleSpeed = Sensor::getOrZero(SensorType::VehicleSpeed);
|
|
tmp = (vehicleSpeed * 10 );
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* Wheel Speed Front Right */
|
|
msg[2] = (tmp >> 8);
|
|
msg[3] = (tmp & 0x00ff);
|
|
/* Wheel Speed Read Left */
|
|
msg[4] = (tmp >> 8);
|
|
msg[5] = (tmp & 0x00ff);
|
|
/* Wheel Speed Read Right */
|
|
msg[6] = (tmp >> 8);
|
|
msg[7] = (tmp & 0x00ff);
|
|
}
|
|
|
|
/* 0x36D = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x36D, 8);
|
|
/* Unused */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Exhaust Cam Angle 1 */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Exhaust Cam Angle 2 */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* 0x36E = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x36E, 8);
|
|
/* Engine Limiting Active 0 = off/1=on*/
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* Launch Control Ignition Retard */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Launch Control Fuel Enrich */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Longitudinal G */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* 0x36F = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x36F, 4);
|
|
/* Generic Output 1 Duty Cycle */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* Boost Control Output */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
}
|
|
|
|
/* 0x370 = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x370, 8);
|
|
/* Vehicle Speed */
|
|
auto vehicleSpeed = Sensor::getOrZero(SensorType::VehicleSpeed);
|
|
tmp = (vehicleSpeed * 10 );
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* unused */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Intake Cam Angle 1 */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Intake Cam Angle 2 */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3E6 = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E6, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3E7 = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E7, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3E8 = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E8, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3E9 = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E9, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3EE = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3EE, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3EF = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3EF, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x470 = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x470, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x472 = 20Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x472, 8);
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
}
|
|
|
|
if (cycle.isInterval(CI::_100ms)) {
|
|
|
|
/* 0x371 = 10Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x371, 4);
|
|
/* Fuel Flow */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* Fuel Flow Return */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
}
|
|
|
|
/* 0x372 = 10Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x372, 8);
|
|
/* Battery Voltage */
|
|
tmp = (uint16_t)(Sensor::getOrZero(SensorType::BatteryVoltage) * 10);
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* unused */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Target Boost Level todo */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Barometric pressure */
|
|
tmp = (uint16_t)(Sensor::getOrZero(SensorType::BarometricPressure) * 10);
|
|
msg[6] = (tmp >> 8);
|
|
msg[7] = (tmp & 0x00ff);
|
|
}
|
|
|
|
/* 0x373 = 10Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x373, 8);
|
|
/* EGT1 */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* EGT2 */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* EGT3 */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* EGT4 */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* 0x374 = 10Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x374, 8);
|
|
/* EGT5 */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* EGT6 */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* EGT7 */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* EGT8 */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* 0x375 = 10Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x375, 8);
|
|
/* EGT9 */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* EGT10 */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* EGT11 */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* EGT12 */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* 0x376 = 10Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x376, 8);
|
|
/* Ambient Air Temperature */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* Relative Humidity */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Specific Humidity */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Absolute Humidity */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
}
|
|
|
|
if (cycle.isInterval(CI::_200ms)) {
|
|
/* 0x3E0 = 5Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E0, 8);
|
|
/* Coolant temperature in K y = x/10 */
|
|
tmp = ((Sensor::getOrZero(SensorType::Clt) + 273.15) * 10);
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
/* Air Temperature */
|
|
tmp = ((Sensor::getOrZero(SensorType::Iat) + 273.15) * 10);
|
|
msg[2] = (tmp >> 8);
|
|
msg[3] = (tmp & 0x00ff);
|
|
/* Fuel Temperature */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Oil Temperature */
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* 0x3E1 = 5Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E1, 6);
|
|
/* Gearbox Oil Temperature */
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* Diff oil Temperature */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Fuel Composition */
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
}
|
|
|
|
/* 0x3E2 = 5Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E2, 2);
|
|
/* Fuel Level in Liters */
|
|
tmp = (Sensor::getOrZero(SensorType::FuelLevel)* 10);
|
|
msg[0] = (tmp >> 8);
|
|
msg[1] = (tmp & 0x00ff);
|
|
}
|
|
|
|
/* 0x3E3 = 5Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E3, 8);
|
|
/* Fuel Trim Short Term Bank 1*/
|
|
msg[0] = 0x00;
|
|
msg[1] = 0x00;
|
|
/* Fuel Trim Short Term Bank 2*/
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
/* Fuel Trim Long Term Bank 1*/
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
/* Fuel Trim Long Term Bank 2*/
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
/* todo: 0x3E4 = 5Hz rate */
|
|
{
|
|
CanTxMessage msg(CanCategory::NBC, 0x3E4, 8);
|
|
msg[0] = 0x00; //unused
|
|
/* Switch status */
|
|
msg[1] = 0x00;
|
|
/* Switch status */
|
|
msg[2] = 0x00;
|
|
msg[3] = 0x00;
|
|
msg[4] = 0x00;
|
|
msg[5] = 0x00;
|
|
msg[6] = 0x00;
|
|
msg[7] = 0x00;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//Based on AIM can protocol
|
|
//https://www.aimtechnologies.com/support/racingecu/AiM_CAN_101_eng.pdf
|
|
|
|
struct Aim5f0 {
|
|
scaled_channel<uint16_t, 1> Rpm;
|
|
scaled_channel<uint16_t, 650> Tps;
|
|
scaled_channel<uint16_t, 650> Pps;
|
|
scaled_channel<uint16_t, 100> Vss;
|
|
};
|
|
|
|
static void populateFrame(Aim5f0& msg) {
|
|
msg.Rpm = Sensor::getOrZero(SensorType::Rpm);
|
|
msg.Tps = Sensor::getOrZero(SensorType::Tps1);
|
|
msg.Pps = Sensor::getOrZero(SensorType::AcceleratorPedal);
|
|
msg.Vss = Sensor::getOrZero(SensorType::VehicleSpeed);
|
|
}
|
|
|
|
struct Aim5f1 {
|
|
scaled_channel<uint16_t, 10> WheelSpeedFR;
|
|
scaled_channel<uint16_t, 10> WheelSpeedFL;
|
|
scaled_channel<uint16_t, 10> WheelSpeedRR;
|
|
scaled_channel<uint16_t, 10> WheelSpeedRL;
|
|
};
|
|
|
|
static void populateFrame(Aim5f1& msg) {
|
|
// We don't handle wheel speed, just set to 0?
|
|
msg.WheelSpeedFR = 0;
|
|
msg.WheelSpeedFL = 0;
|
|
msg.WheelSpeedRR = 0;
|
|
msg.WheelSpeedRL = 0;
|
|
}
|
|
|
|
struct Aim5f2 {
|
|
scaled_channel<uint16_t, 190> Iat;
|
|
scaled_channel<uint16_t, 190> Ect;
|
|
scaled_channel<uint16_t, 190> FuelT;
|
|
scaled_channel<uint16_t, 190> OilT;
|
|
};
|
|
|
|
static void populateFrame(Aim5f2& msg) {
|
|
msg.Iat = Sensor::getOrZero(SensorType::Iat) + 45;
|
|
msg.Ect = Sensor::getOrZero(SensorType::Clt) + 45;
|
|
msg.FuelT = Sensor::getOrZero(SensorType::AuxTemp1) + 45;
|
|
msg.OilT = Sensor::getOrZero(SensorType::AuxTemp2) + 45;
|
|
}
|
|
|
|
struct Aim5f3 {
|
|
scaled_channel<uint16_t, 10> Map;
|
|
scaled_channel<uint16_t, 10> Baro;
|
|
scaled_channel<uint16_t, 1000> OilP;
|
|
scaled_channel<uint16_t, 20> FuelP;
|
|
};
|
|
|
|
static void populateFrame(Aim5f3& msg) {
|
|
// MAP/Baro are sent in millibar -> 10 millibar per kpa
|
|
msg.Map = 10 * Sensor::getOrZero(SensorType::Map);
|
|
msg.Baro = 10 * Sensor::getOrZero(SensorType::BarometricPressure);
|
|
|
|
// Oil/Fuel P use bar -> 100 kpa per bar
|
|
msg.OilP = Sensor::getOrZero(SensorType::OilPressure) / 100;
|
|
msg.FuelP = Sensor::getOrZero(SensorType::FuelPressureInjector) / 100;
|
|
}
|
|
|
|
struct Aim5f4 {
|
|
scaled_channel<uint16_t, 10000> Boost;
|
|
scaled_channel<uint16_t, 3200> Vbat;
|
|
scaled_channel<uint16_t, 10> FuelUse;
|
|
scaled_channel<uint16_t, 10> Gear;
|
|
};
|
|
|
|
static void populateFrame(Aim5f4& msg) {
|
|
float deltaKpa = Sensor::getOrZero(SensorType::Map)
|
|
- Sensor::get(SensorType::BarometricPressure).value_or(101.325);
|
|
float boostBar = deltaKpa / 100;
|
|
|
|
msg.Boost = boostBar;
|
|
msg.Vbat = Sensor::getOrZero(SensorType::BatteryVoltage);
|
|
msg.FuelUse = 0;
|
|
msg.Gear = 0;
|
|
}
|
|
|
|
struct Aim5f5 {
|
|
scaled_channel<uint16_t, 1> ShiftFlag;
|
|
scaled_channel<uint16_t, 1> GearTime;
|
|
scaled_channel<uint16_t, 1> TpsV;
|
|
scaled_channel<uint16_t, 100> FuelLevel;
|
|
};
|
|
|
|
static void populateFrame(Aim5f5& msg) {
|
|
msg.FuelLevel = Sensor::getOrZero(SensorType::FuelLevel);
|
|
|
|
// Dunno what to do with these
|
|
msg.ShiftFlag = 0;
|
|
msg.GearTime = 0;
|
|
msg.TpsV = 0;
|
|
}
|
|
|
|
struct Aim5f6 {
|
|
scaled_channel<uint16_t, 2000> Lambda1;
|
|
scaled_channel<uint16_t, 2000> Lambda2;
|
|
scaled_channel<uint16_t, 10> LambdaTemp1;
|
|
scaled_channel<uint16_t, 10> LambdaTemp2;
|
|
};
|
|
|
|
static void populateFrame(Aim5f6& msg) {
|
|
msg.Lambda1 = Sensor::getOrZero(SensorType::Lambda1);
|
|
msg.Lambda2 = Sensor::getOrZero(SensorType::Lambda2);
|
|
msg.LambdaTemp1 = 0;
|
|
msg.LambdaTemp2 = 0;
|
|
}
|
|
|
|
struct Aim5f7 {
|
|
scaled_channel<uint16_t, 10> LambdaErr1;
|
|
scaled_channel<uint16_t, 10> LambdaErr2;
|
|
scaled_channel<uint16_t, 2000> LambdaTarget1;
|
|
scaled_channel<uint16_t, 2000> LambdaTarget2;
|
|
};
|
|
|
|
static void populateFrame(Aim5f7& msg) {
|
|
// We don't handle wheel speed, just set to 0?
|
|
msg.LambdaErr1 = 0;
|
|
msg.LambdaErr2 = 0;
|
|
// both targets are the same for now
|
|
msg.LambdaTarget1 = engine->fuelComputer->targetLambda;
|
|
msg.LambdaTarget2 = engine->fuelComputer->targetLambda;
|
|
}
|
|
|
|
void canDashboardAim(CanCycle cycle) {
|
|
if (!cycle.isInterval(CI::_10ms)) {
|
|
return;
|
|
}
|
|
|
|
transmitStruct<Aim5f0>(CanCategory::NBC, 0x5f0, false);
|
|
transmitStruct<Aim5f1>(CanCategory::NBC, 0x5f1, false);
|
|
transmitStruct<Aim5f2>(CanCategory::NBC, 0x5f2, false);
|
|
transmitStruct<Aim5f3>(CanCategory::NBC, 0x5f3, false);
|
|
transmitStruct<Aim5f4>(CanCategory::NBC, 0x5f4, false);
|
|
transmitStruct<Aim5f5>(CanCategory::NBC, 0x5f5, false);
|
|
transmitStruct<Aim5f6>(CanCategory::NBC, 0x5f6, false);
|
|
transmitStruct<Aim5f7>(CanCategory::NBC, 0x5f7, false);
|
|
|
|
// there are more, but less important for us
|
|
// transmitStruct<Aim5f8>(0x5f8, false);
|
|
// transmitStruct<Aim5f9>(0x5f9, false);
|
|
// transmitStruct<Aim5fa>(0x5fa, false);
|
|
// transmitStruct<Aim5fb>(0x5fb, false);
|
|
// transmitStruct<Aim5fc>(0x5fc, false);
|
|
// transmitStruct<Aim5fd>(0x5fd, false);
|
|
}
|
|
|
|
#endif // EFI_CAN_SUPPORT
|