Skip to content

Commit 4379a11

Browse files
Reduce table2d memory size - part 2 (150+ bytes) (speeduino#1307)
* Convert table2D to a template * MISRA fixes: add temperature conversion functions temperatureToStorage() and temperatureToInternal() * Change order of table2D constructor parameters to match template parameters * Simplify: add constructor to _table2d_detail::Bin<T> * Specialized interpolation for uint8_t * Fix STM & Teensy compiles: use array references in table2d * Add fast_map() - break out 8-bit interpolation into it's own method * Spelling error * Make 2d tables mutable so they can be used in I/O * Use calibration table for I/O - can now encapsulate the actual storage arrays (in sensors.cpp) * Formatting and naming changes --------- Co-authored-by: Josh Stewart <josh@noisymime.org>
1 parent ca242ad commit 4379a11

27 files changed

+664
-601
lines changed

speeduino/auxiliaries.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A full copy of the license may be found in the projects root directory
1010
#include "decoders.h"
1111
#include "timers.h"
1212
#include "utilities.h"
13+
#include "units.h"
1314

1415
static long vvt1_pwm_value;
1516
static long vvt2_pwm_value;
@@ -54,7 +55,7 @@ uint16_t fan_pwm_max_count; //Used for variable PWM frequency
5455
volatile unsigned int fan_pwm_cur_value;
5556
long fan_pwm_value;
5657
#endif
57-
static constexpr table2D fanPWMTable(_countof(configPage9.PWMFanDuty), configPage9.PWMFanDuty, configPage6.fanPWMBins);
58+
static table2D_u8_u8_4 fanPWMTable(&configPage6.fanPWMBins, &configPage9.PWMFanDuty);
5859

5960
bool acIsEnabled;
6061
bool acStandAloneFanIsEnabled;
@@ -73,7 +74,7 @@ bool vvtIsHot;
7374
bool vvtTimeHold;
7475
uint16_t vvt_pwm_max_count; //Used for variable PWM frequency
7576
uint16_t boost_pwm_max_count; //Used for variable PWM frequency
76-
static constexpr table2D flexBoostTable(_countof(configPage10.flexBoostAdj), configPage10.flexBoostAdj, configPage10.flexBoostBins);
77+
static table2D_u8_s16_6 flexBoostTable(&configPage10.flexBoostBins, &configPage10.flexBoostAdj);
7778

7879
//Old PID method. Retained in case the new one has issues
7980
//integerPID boostPID(&MAPx100, &boost_pwm_target_value, &boostTargetx100, configPage6.boostKP, configPage6.boostKI, configPage6.boostKD, DIRECT);
@@ -232,7 +233,7 @@ static inline void checkAirConCoolantLockout(void)
232233
// ---------------------------
233234
// Coolant Temperature Lockout
234235
// ---------------------------
235-
int offTemp = (int)configPage15.airConClTempCut - CALIBRATION_TEMPERATURE_OFFSET;
236+
int offTemp = temperatureRemoveOffset(configPage15.airConClTempCut);
236237
if (currentStatus.coolant > offTemp)
237238
{
238239
// A/C is cut off due to high coolant
@@ -339,7 +340,7 @@ void fanControl(void)
339340
{
340341
if( configPage2.fanEnable == 1 ) // regular on/off fan control
341342
{
342-
int onTemp = (int)configPage6.fanSP - CALIBRATION_TEMPERATURE_OFFSET;
343+
int onTemp = temperatureRemoveOffset(configPage6.fanSP);
343344
int offTemp = onTemp - configPage6.fanHyster;
344345
bool fanPermit = false;
345346

@@ -389,7 +390,7 @@ void fanControl(void)
389390
}
390391
else
391392
{
392-
byte tempFanDuty = table2D_getValue(&fanPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //In normal situation read PWM duty from the table
393+
byte tempFanDuty = table2D_getValue(&fanPWMTable, temperatureAddOffset(currentStatus.coolant)); //In normal situation read PWM duty from the table
393394
if((configPage15.airConTurnsFanOn) == 1 &&
394395
BIT_CHECK(currentStatus.airConStatus, BIT_AIRCON_TURNING_ON) == true)
395396
{
@@ -512,7 +513,7 @@ void initialiseAuxPWM(void)
512513
BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT1_ERROR);
513514
BIT_CLEAR(currentStatus.status4, BIT_STATUS4_VVT2_ERROR);
514515
vvtTimeHold = false;
515-
if (currentStatus.coolant >= (int)(configPage4.vvtMinClt - CALIBRATION_TEMPERATURE_OFFSET)) { vvtIsHot = true; } //Checks to see if coolant's already at operating temperature
516+
if (currentStatus.coolant >= temperatureRemoveOffset(configPage4.vvtMinClt)) { vvtIsHot = true; } //Checks to see if coolant's already at operating temperature
516517
}
517518

518519
if( (configPage6.vvtEnabled == 0) && (configPage10.wmiEnabled >= 1) )
@@ -781,7 +782,7 @@ void boostControl(void)
781782

782783
void vvtControl(void)
783784
{
784-
if( (configPage6.vvtEnabled == 1) && (currentStatus.coolant >= (int)(configPage4.vvtMinClt - CALIBRATION_TEMPERATURE_OFFSET)) && (BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN)))
785+
if( (configPage6.vvtEnabled == 1) && (currentStatus.coolant >= temperatureRemoveOffset(configPage4.vvtMinClt)) && (BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN)))
785786
{
786787
if(vvtTimeHold == false)
787788
{
@@ -984,7 +985,7 @@ void nitrousControl(void)
984985
if (configPage10.n2o_pin_polarity == 1) { isArmed = !isArmed; } //If nitrous is active when pin is low, flip the reading (n2o_pin_polarity = 0 = active when High)
985986

986987
//Perform the main checks to see if nitrous is ready
987-
if( (isArmed == true) && (currentStatus.coolant > (configPage10.n2o_minCLT - CALIBRATION_TEMPERATURE_OFFSET)) && (currentStatus.TPS > configPage10.n2o_minTPS) && (currentStatus.O2 < configPage10.n2o_maxAFR) && (currentStatus.MAP < (uint16_t)(configPage10.n2o_maxMAP * 2)) )
988+
if( (isArmed == true) && (currentStatus.coolant > temperatureRemoveOffset(configPage10.n2o_minCLT)) && (currentStatus.TPS > configPage10.n2o_minTPS) && (currentStatus.O2 < configPage10.n2o_maxAFR) && (currentStatus.MAP < (uint16_t)(configPage10.n2o_maxMAP * 2)) )
988989
{
989990
//Config page values are divided by 100 to fit within a byte. Multiply them back out to real values.
990991
uint16_t realStage1MinRPM = (uint16_t)configPage10.n2o_stage1_minRPM * 100;
@@ -1042,7 +1043,7 @@ void wmiControl(void)
10421043
if( WMI_TANK_IS_EMPTY() )
10431044
{
10441045
BIT_CLEAR(currentStatus.status4, BIT_STATUS4_WMI_EMPTY);
1045-
if( (currentStatus.TPS >= configPage10.wmiTPS) && (currentStatus.RPMdiv100 >= configPage10.wmiRPM) && ( (currentStatus.MAP / 2) >= configPage10.wmiMAP) && ( (currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET) >= configPage10.wmiIAT) )
1046+
if( (currentStatus.TPS >= configPage10.wmiTPS) && (currentStatus.RPMdiv100 >= configPage10.wmiRPM) && ( (currentStatus.MAP / 2) >= configPage10.wmiMAP) && ( temperatureAddOffset(currentStatus.IAT) >= configPage10.wmiIAT) )
10461047
{
10471048
switch(configPage10.wmiMode)
10481049
{

speeduino/comms.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ A full copy of the license may be found in the projects root directory
2727
#ifdef SD_LOGGING
2828
#include "SD_logger.h"
2929
#endif
30+
#include "units.h"
31+
#include "sensors.h"
3032

3133
/** @defgroup group-serial-comms-impl Serial comms implementation
3234
* @{
@@ -395,8 +397,8 @@ static void loadO2CalibrationChunk(uint16_t offset, uint16_t chunkSize)
395397
//As we're using an interpolated 2D table, we only need to store 32 values out of this 1024
396398
if( (x % 32U) == 0U )
397399
{
398-
o2Calibration_values[offset/32U] = serialPayload[x+7U]; //O2 table stores 8 bit values
399-
o2Calibration_bins[offset/32U] = offset;
400+
o2CalibrationTable.values[offset/32U] = serialPayload[x+7U]; //O2 table stores 8 bit values
401+
o2CalibrationTable.axis[offset/32U] = offset;
400402
}
401403

402404
//Update the CRC
@@ -415,15 +417,15 @@ static void loadO2CalibrationChunk(uint16_t offset, uint16_t chunkSize)
415417

416418
/**
417419
* @brief Convert 2 bytes into an offset temperature in degrees Celsius
418-
* @attention Returned value will be offset CALIBRATION_TEMPERATURE_OFFSET
420+
* @attention Returned value will be in storage temperatures
419421
*/
420-
static uint16_t toTemperature(byte lo, byte hi)
422+
static uint8_t toTemperature(byte lo, byte hi)
421423
{
422424
int16_t tempValue = (int16_t)(word(hi, lo)); //Combine the 2 bytes into a single, signed 16-bit value
423425
tempValue = tempValue / 10; //TS sends values multiplied by 10 so divide back to whole degrees.
424426
tempValue = ((tempValue - 32) * 5) / 9; //Convert from F to C
425427
//Apply the temp offset and check that it results in all values being positive
426-
return max( tempValue + CALIBRATION_TEMPERATURE_OFFSET, 0 );
428+
return max( temperatureAddOffset(tempValue), (uint8_t)0U );
427429
}
428430

429431
/**
@@ -434,15 +436,15 @@ static uint16_t toTemperature(byte lo, byte hi)
434436
* @param values The table values
435437
* @param bins The table bin values
436438
*/
437-
static void processTemperatureCalibrationTableUpdate(uint16_t calibrationLength, uint8_t calibrationPage, uint16_t *values, uint16_t *bins)
439+
static void processTemperatureCalibrationTableUpdate(uint16_t calibrationLength, uint8_t calibrationPage, table2D_u16_u16_32 &table)
438440
{
439441
//Temperature calibrations are sent as 32 16-bit values
440442
if(calibrationLength == 64U)
441443
{
442444
for (uint16_t x = 0; x < 32U; x++)
443445
{
444-
values[x] = toTemperature(serialPayload[(2U * x) + 7U], serialPayload[(2U * x) + 8U]);
445-
bins[x] = (x * 33U); // 0*33=0 to 31*33=1023
446+
table.values[x] = toTemperature(serialPayload[(2U * x) + 7U], serialPayload[(2U * x) + 8U]);
447+
table.axis[x] = (x * 33U); // 0*33=0 to 31*33=1023
446448
}
447449
storeCalibrationCRC32(calibrationPage, CRC32_calibration.crc32(&serialPayload[7], 64));
448450
writeCalibrationPage(calibrationPage);
@@ -897,11 +899,11 @@ void processSerialCommand(void)
897899
}
898900
else if(cmd == IAT_CALIBRATION_PAGE)
899901
{
900-
processTemperatureCalibrationTableUpdate(calibrationLength, IAT_CALIBRATION_PAGE, iatCalibration_values, iatCalibration_bins);
902+
processTemperatureCalibrationTableUpdate(calibrationLength, IAT_CALIBRATION_PAGE, iatCalibrationTable);
901903
}
902904
else if(cmd == CLT_CALIBRATION_PAGE)
903905
{
904-
processTemperatureCalibrationTableUpdate(calibrationLength, CLT_CALIBRATION_PAGE, cltCalibration_values, cltCalibration_bins);
906+
processTemperatureCalibrationTableUpdate(calibrationLength, CLT_CALIBRATION_PAGE, cltCalibrationTable);
905907
}
906908
else
907909
{

speeduino/comms_CAN.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This is for handling the data broadcasted to various CAN dashes and instrument c
1313
#include "comms_CAN.h"
1414
#include "utilities.h"
1515
#include "maths.h"
16+
#include "units.h"
1617

1718
CAN_message_t inMsg;
1819
CAN_message_t outMsg;
@@ -468,7 +469,7 @@ void obd_response(uint8_t PIDmode, uint8_t requestedPIDlow, uint8_t requestedPID
468469
outMsg.buf[0] = 0x03; // sending 3 bytes
469470
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
470471
outMsg.buf[2] = 0x05; // pid code
471-
outMsg.buf[3] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //the data value A
472+
outMsg.buf[3] = temperatureAddOffset(currentStatus.coolant); //the data value A
472473
outMsg.buf[4] = 0x00; //the data value B which is 0 as unused
473474
outMsg.buf[5] = 0x00;
474475
outMsg.buf[6] = 0x00;
@@ -542,7 +543,7 @@ void obd_response(uint8_t PIDmode, uint8_t requestedPIDlow, uint8_t requestedPID
542543
outMsg.buf[0] = 0x03; // sending 3 bytes
543544
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
544545
outMsg.buf[2] = 0x0F; // pid code
545-
outMsg.buf[3] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); // A
546+
outMsg.buf[3] = temperatureAddOffset(currentStatus.IAT); // A
546547
outMsg.buf[4] = 0x00; // B
547548
outMsg.buf[5] = 0x00;
548549
outMsg.buf[6] = 0x00;
@@ -686,7 +687,7 @@ void obd_response(uint8_t PIDmode, uint8_t requestedPIDlow, uint8_t requestedPID
686687
case 70: //PID-0x46 Ambient Air Temperature , range is -40 to 215 deg C , formula == A-40
687688
uint16_t temp_ambientair;
688689
temp_ambientair = 11; // TEST VALUE !!!!!!!!!!
689-
obdcalcA = temp_ambientair + 40 ; // maybe later will be (byte)(currentStatus.AAT + CALIBRATION_TEMPERATURE_OFFSET)
690+
obdcalcA = temperatureAddOffset(temp_ambientair);
690691
outMsg.buf[0] = 0x03; // sending 3 byte
691692
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
692693
outMsg.buf[2] = 0x46; // pid code
@@ -714,7 +715,7 @@ void obd_response(uint8_t PIDmode, uint8_t requestedPIDlow, uint8_t requestedPID
714715
case 92: //PID-0x5C Engine oil temperature , range is -40 to 210 deg C , formula == A-40
715716
uint16_t temp_engineoiltemp;
716717
temp_engineoiltemp = 40; // TEST VALUE !!!!!!!!!!
717-
obdcalcA = temp_engineoiltemp+40 ; // maybe later will be (byte)(currentStatus.EOT + CALIBRATION_TEMPERATURE_OFFSET)
718+
obdcalcA = temperatureAddOffset(temp_engineoiltemp);
718719
outMsg.buf[0] = 0x03; // sending 3 byte
719720
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
720721
outMsg.buf[2] = 0x5C; // pid code

speeduino/comms_legacy.cpp

Lines changed: 25 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ A full copy of the license may be found in the projects root directory
2323
#ifdef RTC_ENABLED
2424
#include "rtc_common.h"
2525
#endif
26+
#include "units.h"
27+
#include "sensors.h"
2628

2729
static byte currentPage = 1;//Not the same as the speeduino config page numbers
2830
bool firstCommsRequest = true; /**< The number of times the A command has been issued. This is used to track whether a reset has recently been performed on the controller */
@@ -439,23 +441,23 @@ void legacySerialCommand(void)
439441
primarySerial.println(F("Coolant"));
440442
for (int x = 0; x < 32; x++)
441443
{
442-
primarySerial.print(cltCalibration_bins[x]);
444+
primarySerial.print(cltCalibrationTable.axis[x]);
443445
primarySerial.print(", ");
444-
primarySerial.println(cltCalibration_values[x]);
446+
primarySerial.println(cltCalibrationTable.values[x]);
445447
}
446448
primarySerial.println(F("Inlet temp"));
447449
for (int x = 0; x < 32; x++)
448450
{
449-
primarySerial.print(iatCalibration_bins[x]);
451+
primarySerial.print(iatCalibrationTable.axis[x]);
450452
primarySerial.print(", ");
451-
primarySerial.println(iatCalibration_values[x]);
453+
primarySerial.println(iatCalibrationTable.values[x]);
452454
}
453455
primarySerial.println(F("O2"));
454456
for (int x = 0; x < 32; x++)
455457
{
456-
primarySerial.print(o2Calibration_bins[x]);
458+
primarySerial.print(o2CalibrationTable.axis[x]);
457459
primarySerial.print(", ");
458-
primarySerial.println(o2Calibration_values[x]);
460+
primarySerial.println(o2CalibrationTable.values[x]);
459461
}
460462
primarySerial.println(F("WUE"));
461463
for (int x = 0; x < 10; x++)
@@ -1178,81 +1180,47 @@ void sendPageASCII(void)
11781180
*/
11791181
void receiveCalibration(byte tableID)
11801182
{
1181-
void* pnt_TargetTable_values; //Pointer that will be used to point to the required target table values
1182-
uint16_t* pnt_TargetTable_bins; //Pointer that will be used to point to the required target table bins
1183-
int OFFSET, DIVISION_FACTOR;
1184-
1185-
switch (tableID)
1186-
{
1187-
case 0:
1188-
//coolant table
1189-
pnt_TargetTable_values = (uint16_t *)&cltCalibration_values;
1190-
pnt_TargetTable_bins = (uint16_t *)&cltCalibration_bins;
1191-
OFFSET = CALIBRATION_TEMPERATURE_OFFSET; //
1192-
DIVISION_FACTOR = 10;
1193-
break;
1194-
case 1:
1195-
//Inlet air temp table
1196-
pnt_TargetTable_values = (uint16_t *)&iatCalibration_values;
1197-
pnt_TargetTable_bins = (uint16_t *)&iatCalibration_bins;
1198-
OFFSET = CALIBRATION_TEMPERATURE_OFFSET;
1199-
DIVISION_FACTOR = 10;
1200-
break;
1201-
case 2:
1202-
//O2 table
1203-
pnt_TargetTable_values = (uint8_t *)&o2Calibration_values;
1204-
pnt_TargetTable_bins = (uint16_t *)&o2Calibration_bins;
1205-
OFFSET = 0;
1206-
DIVISION_FACTOR = 1;
1207-
break;
1208-
1209-
default:
1210-
OFFSET = 0;
1211-
pnt_TargetTable_values = (uint16_t *)&iatCalibration_values;
1212-
pnt_TargetTable_bins = (uint16_t *)&iatCalibration_bins;
1213-
DIVISION_FACTOR = 10;
1214-
break; //Should never get here, but if we do, just fail back to main loop
1215-
}
1216-
1217-
int16_t tempValue;
1218-
byte tempBuffer[2];
1219-
12201183
if(tableID == 2)
12211184
{
12221185
//O2 calibration. Comes through as 1024 8-bit values of which we use every 32nd
12231186
for (int x = 0; x < 1024; x++)
12241187
{
12251188
while ( primarySerial.available() < 1 ) {}
1226-
tempValue = primarySerial.read();
1189+
uint8_t tempValue = (uint8_t)primarySerial.read();
12271190

12281191
if( (x % 32) == 0)
12291192
{
1230-
((uint8_t*)pnt_TargetTable_values)[(x/32)] = (byte)tempValue; //O2 table stores 8 bit values
1231-
pnt_TargetTable_bins[(x/32)] = (x);
1193+
o2CalibrationTable.values[(x/32)] = (byte)tempValue; //O2 table stores 8 bit values
1194+
o2CalibrationTable.axis[(x/32)] = x;
12321195
}
12331196

12341197
}
12351198
}
12361199
else
12371200
{
1201+
table2D_u16_u16_32 *pTargetTable;
1202+
if (tableID == 0)
1203+
{
1204+
pTargetTable = &cltCalibrationTable;
1205+
}
1206+
else
1207+
{
1208+
pTargetTable = &iatCalibrationTable;
1209+
}
12381210
//Temperature calibrations are sent as 32 16-bit values
12391211
for (uint16_t x = 0; x < 32; x++)
12401212
{
12411213
while ( primarySerial.available() < 2 ) {}
1214+
byte tempBuffer[2];
12421215
tempBuffer[0] = primarySerial.read();
12431216
tempBuffer[1] = primarySerial.read();
12441217

1245-
tempValue = (int16_t)(word(tempBuffer[1], tempBuffer[0])); //Combine the 2 bytes into a single, signed 16-bit value
1246-
tempValue = div(tempValue, DIVISION_FACTOR).quot; //TS sends values multiplied by 10 so divide back to whole degrees.
1218+
int16_t tempValue = (int16_t)(word(tempBuffer[1], tempBuffer[0])); //Combine the 2 bytes into a single, signed 16-bit value
1219+
tempValue = div(tempValue, 10).quot; //TS sends values multiplied by 10 so divide back to whole degrees.
12471220
tempValue = ((tempValue - 32) * 5) / 9; //Convert from F to C
12481221

1249-
//Apply the temp offset and check that it results in all values being positive
1250-
tempValue = tempValue + OFFSET;
1251-
if (tempValue < 0) { tempValue = 0; }
1252-
1253-
1254-
((uint16_t*)pnt_TargetTable_values)[x] = tempValue; //Both temp tables have 16-bit values
1255-
pnt_TargetTable_bins[x] = (x * 32U);
1222+
pTargetTable->values[x] = temperatureAddOffset(tempValue);
1223+
pTargetTable->axis[x] = (x * 32U);
12561224
writeCalibration();
12571225
}
12581226
}

0 commit comments

Comments
 (0)