test_math: make unit tests pass on Teensy (#1137)
Required converting dwell, actualDwell, dwellCrank & dwellRun to unsigned.
This commit is contained in:
parent
3a712baf23
commit
e08d5dab25
|
@ -842,7 +842,7 @@ void sendValuesLegacy(void)
|
|||
bytestosend -= Serial.write(temp >> 8); // MAPdot
|
||||
bytestosend -= Serial.write(temp); // MAPdot
|
||||
|
||||
temp = currentStatus.dwell * 10;
|
||||
temp = currentStatus.dwell * 10U;
|
||||
bytestosend -= Serial.write(temp>>8); // dwell
|
||||
bytestosend -= Serial.write(temp); // dwell
|
||||
|
||||
|
|
|
@ -607,8 +607,8 @@ struct statuses {
|
|||
int batADC;
|
||||
int O2ADC;
|
||||
int O2_2ADC;
|
||||
int dwell; ///< dwell (coil primary winding/circuit on) time (in ms * 10 ? See @ref correctionsDwell)
|
||||
volatile int16_t actualDwell; ///< actual dwell time if new ignition mode is used (in uS)
|
||||
uint16_t dwell; ///< dwell (coil primary winding/circuit on) time (in ms * 10 ? See @ref correctionsDwell)
|
||||
volatile uint16_t actualDwell; ///< actual dwell time if new ignition mode is used (in uS)
|
||||
byte dwellCorrection; /**< The amount of correction being applied to the dwell time (in unit ...). */
|
||||
byte battery10; /**< The current BRV in volts (multiplied by 10. Eg 12.5V = 125) */
|
||||
int8_t advance; /**< The current advance value being used in the spark calculation. Can be the same as advance1 or advance2, or a calculated value of both */
|
||||
|
@ -909,8 +909,8 @@ struct config4 {
|
|||
byte triggerFilter : 2; //The mode of trigger filter being used (0=Off, 1=Light (Not currently used), 2=Normal, 3=Aggressive)
|
||||
byte ignCranklock : 1; //Whether or not the ignition timing during cranking is locked to a CAS (crank) pulse. Only currently valid for Basic distributor and 4G63.
|
||||
|
||||
byte dwellCrank; ///< Dwell time whilst cranking
|
||||
byte dwellRun; ///< Dwell time whilst running
|
||||
uint8_t dwellCrank; ///< Dwell time whilst cranking
|
||||
uint8_t dwellRun; ///< Dwell time whilst running
|
||||
byte triggerTeeth; ///< The full count of teeth on the trigger wheel if there were no gaps
|
||||
byte triggerMissingTeeth; ///< The size of the tooth gap (ie number of missing teeth)
|
||||
byte crankRPM; ///< RPM below which the engine is considered to be cranking
|
||||
|
|
|
@ -269,7 +269,7 @@ int16_t getReadableLogEntry(uint16_t logIndex)
|
|||
|
||||
case 60: statusValue = currentStatus.fuelLoad; break;
|
||||
case 61: statusValue = currentStatus.ignLoad; break;
|
||||
case 62: statusValue = currentStatus.dwell; break;
|
||||
case 62: statusValue = (int16_t)currentStatus.dwell; break;
|
||||
case 63: statusValue = currentStatus.CLIdleTarget; break;
|
||||
case 64: statusValue = currentStatus.mapDOT; break;
|
||||
case 65: statusValue = currentStatus.vvt1Angle; break;
|
||||
|
|
|
@ -144,7 +144,7 @@ static inline uint32_t div100(uint32_t n) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__arm__) && !defined(CORE_TEENSY)
|
||||
static inline int div100(int n) {
|
||||
return DIV_ROUND_CLOSEST(n, 100U, int);
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ static inline int32_t div100(int32_t n) {
|
|||
}
|
||||
return libdivide::libdivide_s32_do_raw(n + (DIV_ROUND_CORRECT(UINT16_C(100), uint32_t) * (n<0 ? -1 : 1)), 1374389535L, 5);
|
||||
#else
|
||||
return DIV_ROUND_CLOSEST(n, UINT32_C(100), int32_t);
|
||||
return DIV_ROUND_CLOSEST(n, INT32_C(100), int32_t);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -61,10 +61,10 @@ static inline uint16_t __attribute__((always_inline)) calculateInjectorStartAngl
|
|||
|
||||
static inline uint32_t __attribute__((always_inline)) calculateInjectorTimeout(const FuelSchedule &schedule, int channelInjDegrees, int injectorStartAngle, int crankAngle);
|
||||
|
||||
static inline void __attribute__((always_inline)) calculateIgnitionAngle(const int dwellAngle, const uint16_t channelIgnDegrees, int8_t advance, int *pEndAngle, int *pStartAngle);
|
||||
static inline void __attribute__((always_inline)) calculateIgnitionAngle(const uint16_t dwellAngle, const uint16_t channelIgnDegrees, int8_t advance, int *pEndAngle, int *pStartAngle);
|
||||
|
||||
// Ignition for rotary.
|
||||
static inline void __attribute__((always_inline)) calculateIgnitionTrailingRotary(int dwellAngle, int rotarySplitDegrees, int leadIgnitionAngle, int *pEndAngle, int *pStartAngle);
|
||||
static inline void __attribute__((always_inline)) calculateIgnitionTrailingRotary(uint16_t dwellAngle, int rotarySplitDegrees, int leadIgnitionAngle, int *pEndAngle, int *pStartAngle);
|
||||
|
||||
static inline uint32_t __attribute__((always_inline)) calculateIgnitionTimeout(const IgnitionSchedule &schedule, int startAngle, int channelIgnDegrees, int crankAngle);
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static inline uint32_t calculateInjectorTimeout(const FuelSchedule &schedule, in
|
|||
return _calculateInjectorTimeout(schedule, _adjustToInjChannel(openAngle, channelInjDegrees), _adjustToInjChannel(crankAngle, channelInjDegrees));
|
||||
}
|
||||
|
||||
static inline void calculateIgnitionAngle(const int dwellAngle, const uint16_t channelIgnDegrees, int8_t advance, int *pEndAngle, int *pStartAngle)
|
||||
static inline void calculateIgnitionAngle(const uint16_t dwellAngle, const uint16_t channelIgnDegrees, int8_t advance, int *pEndAngle, int *pStartAngle)
|
||||
{
|
||||
*pEndAngle = (int16_t)(channelIgnDegrees==0U ? (uint16_t)CRANK_ANGLE_MAX_IGN : channelIgnDegrees) - (int16_t)advance;
|
||||
if(*pEndAngle > CRANK_ANGLE_MAX_IGN) {*pEndAngle -= CRANK_ANGLE_MAX_IGN;}
|
||||
|
@ -65,7 +65,7 @@ static inline void calculateIgnitionAngle(const int dwellAngle, const uint16_t c
|
|||
if(*pStartAngle < 0) {*pStartAngle += CRANK_ANGLE_MAX_IGN;}
|
||||
}
|
||||
|
||||
static inline void calculateIgnitionTrailingRotary(int dwellAngle, int rotarySplitDegrees, int leadIgnitionAngle, int *pEndAngle, int *pStartAngle)
|
||||
static inline void calculateIgnitionTrailingRotary(uint16_t dwellAngle, int rotarySplitDegrees, int leadIgnitionAngle, int *pEndAngle, int *pStartAngle)
|
||||
{
|
||||
*pEndAngle = leadIgnitionAngle + rotarySplitDegrees;
|
||||
*pStartAngle = *pEndAngle - dwellAngle;
|
||||
|
|
|
@ -22,7 +22,7 @@ byte getVE1(void);
|
|||
byte getAdvance1(void);
|
||||
uint16_t calculatePWLimit();
|
||||
void calculateStaging(uint32_t);
|
||||
void calculateIgnitionAngles(int dwellAngle);
|
||||
void calculateIgnitionAngles(uint16_t dwellAngle);
|
||||
void checkLaunchAndFlatShift();
|
||||
|
||||
extern uint16_t req_fuel_uS; /**< The required fuel variable (As calculated by TunerStudio) in uS */
|
||||
|
|
|
@ -716,24 +716,23 @@ void loop(void)
|
|||
//Set dwell
|
||||
//Dwell is stored as ms * 10. ie Dwell of 4.3ms would be 43 in configPage4. This number therefore needs to be multiplied by 100 to get dwell in uS
|
||||
if ( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) {
|
||||
currentStatus.dwell = (configPage4.dwellCrank * 100); //use cranking dwell
|
||||
currentStatus.dwell = (configPage4.dwellCrank * 100U); //use cranking dwell
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( configPage2.useDwellMap == true )
|
||||
{
|
||||
currentStatus.dwell = (get3DTableValue(&dwellTable, currentStatus.ignLoad, currentStatus.RPM) * 100); //use running dwell from map
|
||||
currentStatus.dwell = (get3DTableValue(&dwellTable, currentStatus.ignLoad, currentStatus.RPM) * 100U); //use running dwell from map
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStatus.dwell = (configPage4.dwellRun * 100); //use fixed running dwell
|
||||
currentStatus.dwell = (configPage4.dwellRun * 100U); //use fixed running dwell
|
||||
}
|
||||
}
|
||||
currentStatus.dwell = correctionsDwell(currentStatus.dwell);
|
||||
|
||||
int dwellAngle = timeToAngleDegPerMicroSec(currentStatus.dwell); //Convert the dwell time to dwell angle based on the current engine speed
|
||||
|
||||
calculateIgnitionAngles(dwellAngle);
|
||||
// Convert the dwell time to dwell angle based on the current engine speed
|
||||
calculateIgnitionAngles(timeToAngleDegPerMicroSec(currentStatus.dwell));
|
||||
|
||||
//If ignition timing is being tracked per tooth, perform the calcs to get the end teeth
|
||||
//This only needs to be run if the advance figure has changed, otherwise the end teeth will still be the same
|
||||
|
@ -1323,10 +1322,8 @@ byte getAdvance1(void)
|
|||
* both start and end angles are calculated for each channel.
|
||||
* Also the mode of ignition firing - wasted spark vs. dedicated spark per cyl. - is considered here.
|
||||
*/
|
||||
void calculateIgnitionAngles(int dwellAngle)
|
||||
void calculateIgnitionAngles(uint16_t dwellAngle)
|
||||
{
|
||||
|
||||
|
||||
//This test for more cylinders and do the same thing
|
||||
switch (configPage2.nCylinders)
|
||||
{
|
||||
|
|
|
@ -63,7 +63,7 @@ void test_maths_div100_S16(void)
|
|||
void test_maths_div100_S32(void)
|
||||
{
|
||||
//Check both the signed and unsigned results
|
||||
#if defined(__arm__)
|
||||
#if defined(__arm__) && !defined(CORE_TEENSY)
|
||||
test_div100_Seed<int>(100U);
|
||||
test_div100_Seed<int>(10000U);
|
||||
test_div100_Seed<int>(100000000UL);
|
||||
|
@ -107,6 +107,7 @@ void assert_udiv_32_16(uint32_t dividend, uint16_t divisor) {
|
|||
|
||||
void test_maths_udiv_32_16(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
// Divide by zero
|
||||
TEST_ASSERT_EQUAL_UINT16(UINT16_MAX, udiv_32_16(0, 0));
|
||||
|
||||
|
@ -121,6 +122,7 @@ void test_maths_udiv_32_16(void)
|
|||
assert_udiv_32_16(MICROS_PER_MIN, 7590); // 7905 RPM
|
||||
assert_udiv_32_16(MICROS_PER_MIN, 7715); // 7777 RPM
|
||||
assert_udiv_32_16(MICROS_PER_MIN, 3333); // 18000 RPM
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,6 +132,7 @@ void assert_udiv_32_16_closest(uint32_t dividend, uint16_t divisor) {
|
|||
|
||||
void test_maths_udiv_32_16_closest(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
// Divide by zero
|
||||
TEST_ASSERT_EQUAL_UINT16(UINT16_MAX, udiv_32_16_closest(0, 0));
|
||||
|
||||
|
@ -145,6 +148,7 @@ void test_maths_udiv_32_16_closest(void)
|
|||
assert_udiv_32_16(MICROS_PER_MIN, 7590); // 7905 RPM
|
||||
assert_udiv_32_16(MICROS_PER_MIN, 7715); // 7777 RPM
|
||||
assert_udiv_32_16(MICROS_PER_MIN, 3333); // 18000 RPM
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t indexToDividend(int16_t index) {
|
||||
|
@ -152,6 +156,7 @@ static uint32_t indexToDividend(int16_t index) {
|
|||
}
|
||||
void test_maths_udiv_32_16_perf(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
uint16_t iters = 32;
|
||||
uint16_t start_index = UINT16_MAX/3;
|
||||
uint16_t end_index = UINT16_MAX/3*2;
|
||||
|
@ -167,10 +172,12 @@ void test_maths_udiv_32_16_perf(void)
|
|||
TEST_ASSERT_INT32_WITHIN(UINT32_MAX/2, comparison.timeA.result, comparison.timeB.result);
|
||||
|
||||
TEST_ASSERT_LESS_THAN(comparison.timeA.durationMicros, comparison.timeB.durationMicros);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_maths_div100_s16_perf(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
constexpr int16_t iters = 1;
|
||||
constexpr int16_t start_index = -10000;
|
||||
constexpr int16_t end_index = -1;
|
||||
|
@ -186,11 +193,13 @@ void test_maths_div100_s16_perf(void)
|
|||
TEST_ASSERT_INT32_WITHIN(UINT32_MAX/2, comparison.timeA.result, comparison.timeB.result);
|
||||
|
||||
TEST_ASSERT_LESS_THAN(comparison.timeA.durationMicros, comparison.timeB.durationMicros);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void test_maths_div100_s32_perf(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
constexpr int32_t iters = 1;
|
||||
constexpr int32_t start_index = -1439190;
|
||||
constexpr int32_t end_index = -1;
|
||||
|
@ -206,6 +215,7 @@ void test_maths_div100_s32_perf(void)
|
|||
TEST_ASSERT_INT32_WITHIN(UINT32_MAX/2, comparison.timeA.result, comparison.timeB.result);
|
||||
|
||||
TEST_ASSERT_LESS_THAN(comparison.timeA.durationMicros, comparison.timeB.durationMicros);
|
||||
#endif
|
||||
}
|
||||
|
||||
void testDivision(void) {
|
||||
|
|
|
@ -1,14 +1,37 @@
|
|||
#include <stdio.h>
|
||||
#include <unity.h>
|
||||
#include "test_fp_support.h"
|
||||
|
||||
float64_t floatDivision(int32_t a, int32_t b) {
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
#include <fp64lib.h>
|
||||
using test_float_t = float64_t;
|
||||
#else
|
||||
using test_float_t = double;
|
||||
#endif
|
||||
|
||||
test_float_t floatDivision(int32_t a, int32_t b) {
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
return fp64_div(fp64_int32_to_float64(a), fp64_int32_to_float64(b));
|
||||
#else
|
||||
return (double)a/(double)b;
|
||||
#endif
|
||||
}
|
||||
|
||||
void assert_rounded_div(int32_t a, int32_t b, int32_t actual) {
|
||||
float64_t fExpected = floatDivision(a, b);
|
||||
int32_t expected = fp64_lround(fExpected);
|
||||
int32_t round_float(test_float_t f) {
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
return fp64_lround(f);
|
||||
#else
|
||||
return round(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
char msg[64];
|
||||
sprintf(msg, "a: %" PRIi32 ", b: %" PRIi32 " fExpected: %s", a, b, fp64_to_string(fExpected, 17, 15));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(expected, actual, msg);
|
||||
|
||||
void assert_rounded_div(int32_t a, int32_t b, int32_t actual) {
|
||||
test_float_t fExpected = floatDivision(a, b);
|
||||
int32_t expected = round_float(fExpected);
|
||||
|
||||
// char msg[64];
|
||||
// sprintf(msg, "a: %" PRIi32 ", b: %" PRIi32 " fExpected: %s", a, b, fp64_to_string(fExpected, 17, 15));
|
||||
// TEST_ASSERT_EQUAL_MESSAGE(expected, actual, msg);
|
||||
TEST_ASSERT_EQUAL(expected, actual);
|
||||
}
|
|
@ -1,8 +1,4 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <unity.h>
|
||||
#include <fp64lib.h>
|
||||
|
||||
float64_t floatDivision(int32_t a, int32_t b);
|
||||
#include <stdint.h>
|
||||
|
||||
void assert_rounded_div(int32_t a, int32_t b, int32_t actual);
|
|
@ -62,6 +62,7 @@ void test_maths_halfpercent_U16(void)
|
|||
|
||||
void test_maths_halfPercentage_perf(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
constexpr int16_t iters = 4;
|
||||
constexpr uint8_t start_index = 3;
|
||||
constexpr uint8_t end_index = 99;
|
||||
|
@ -78,11 +79,13 @@ void test_maths_halfPercentage_perf(void)
|
|||
TEST_ASSERT_INT32_WITHIN(UINT32_MAX/2, comparison.timeA.result, comparison.timeB.result);
|
||||
|
||||
TEST_ASSERT_LESS_THAN(comparison.timeA.durationMicros, comparison.timeB.durationMicros);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void test_maths_percentage_perf(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
constexpr uint16_t iters = 4;
|
||||
constexpr uint8_t start_index = 3;
|
||||
constexpr uint8_t end_index = 99;
|
||||
|
@ -99,6 +102,7 @@ void test_maths_percentage_perf(void)
|
|||
TEST_ASSERT_INT32_WITHIN(UINT32_MAX/2, comparison.timeA.result, comparison.timeB.result);
|
||||
|
||||
TEST_ASSERT_LESS_THAN(comparison.timeA.durationMicros, comparison.timeB.durationMicros);
|
||||
#endif
|
||||
}
|
||||
|
||||
void testPercent()
|
||||
|
|
Loading…
Reference in New Issue