Isolate table3D member access in comms.ino (#545)
* fix!: fix ODR violations * refactor: move page specific code into a separate CPP file * refactor: page getter/setter share mapping logic Extract common page-to-entity mapping logic from getPageValue() & setPageValue() - place in map_page_offset_to_entity() and share. * performance: optimize CRC calc Calculate page CRC by iterating over entities & tables. * CRC table calculation - use table iterator * refactor: use iterators for sendPage() Re-implement sendPage() using page & table iterators Future proof & fast * refactor: sendPageASCII() Pull put shared code into functions. Use table iterator * refactor: use shared axis factor This puts the axis factor usage in one place * refactor: encapsulate page size & count Added getPageCount() & getPageSize() * Added static_assert for all pages. * Remove C++ language elements namesapces, scope resolution, enum struct * Rename comms.ino to comms.cpp Provides better encapsulation of non-global data & functions. INO files are all mashed together by some custom process. So everything becomes global and static functions/variables aren't really private to the translation unit. Thus breaking encapsulation :-(
This commit is contained in:
parent
dd3847bfd3
commit
02cb7bebd6
|
@ -37,9 +37,9 @@
|
|||
#if defined(FRAM_AS_EEPROM)
|
||||
#include <Fram.h>
|
||||
#if defined(STM32F407xx)
|
||||
FramClass EEPROM(PB5, PB4, PB3, PB0); /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
extern FramClass EEPROM; /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
#else
|
||||
FramClass EEPROM(PB15, PB14, PB13, PB12); //Blue/Black Pills
|
||||
extern FramClass EEPROM; //Blue/Black Pills
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
#include "scheduler.h"
|
||||
#include "HardwareTimer.h"
|
||||
|
||||
#if defined(FRAM_AS_EEPROM)
|
||||
#if defined(STM32F407xx)
|
||||
FramClass EEPROM(PB5, PB4, PB3, PB0); /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
#else
|
||||
FramClass EEPROM(PB15, PB14, PB13, PB12); //Blue/Black Pills
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -77,42 +77,42 @@ extern "C" char* sbrk(int incr);
|
|||
#if defined(SRAM_AS_EEPROM)
|
||||
#define EEPROM_LIB_H "src/BackupSram/BackupSramAsEEPROM.h"
|
||||
#include EEPROM_LIB_H
|
||||
BackupSramAsEEPROM EEPROM;
|
||||
extern BackupSramAsEEPROM EEPROM;
|
||||
|
||||
#elif defined(USE_SPI_EEPROM)
|
||||
#define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h"
|
||||
#include EEPROM_LIB_H
|
||||
SPIClass SPI_for_flash(PB5, PB4, PB3); //SPI1_MOSI, SPI1_MISO, SPI1_SCK
|
||||
extern SPIClass SPI_for_flash; //SPI1_MOSI, SPI1_MISO, SPI1_SCK
|
||||
|
||||
//windbond W25Q16 SPI flash EEPROM emulation
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{255UL, 4096UL, 31, 0x00100000UL};
|
||||
Flash_SPI_Config SPIconfig{USE_SPI_EEPROM, SPI_for_flash};
|
||||
SPI_EEPROM_Class EEPROM(EmulatedEEPROMMconfig, SPIconfig);
|
||||
extern EEPROM_Emulation_Config EmulatedEEPROMMconfig;
|
||||
extern Flash_SPI_Config SPIconfig;
|
||||
extern SPI_EEPROM_Class EEPROM;
|
||||
|
||||
#elif defined(FRAM_AS_EEPROM) //https://github.com/VitorBoss/FRAM
|
||||
#define EEPROM_LIB_H <Fram.h>
|
||||
#include EEPROM_LIB_H
|
||||
#if defined(STM32F407xx)
|
||||
FramClass EEPROM(PB5, PB4, PB3, PB0); /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
extern FramClass EEPROM; /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
#else
|
||||
FramClass EEPROM(PB15, PB14, PB13, PB12); //Blue/Black Pills
|
||||
extern FramClass EEPROM; //Blue/Black Pills
|
||||
#endif
|
||||
|
||||
#elif defined(STM32F7xx)
|
||||
#define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h"
|
||||
#include EEPROM_LIB_H
|
||||
#if defined(DUAL_BANK)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08120000UL};
|
||||
extern EEPROM_Emulation_Config EmulatedEEPROMMconfig;
|
||||
#else
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 262144UL, 4095UL, 0x08180000UL};
|
||||
extern EEPROM_Emulation_Config EmulatedEEPROMMconfig;
|
||||
#endif
|
||||
InternalSTM32F7_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
extern InternalSTM32F7_EEPROM_Class EEPROM;
|
||||
|
||||
#elif defined(STM32F411xE)
|
||||
#define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h"
|
||||
#include EEPROM_LIB_H
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 131072UL, 4095UL, 0x08040000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
extern EEPROM_Emulation_Config EmulatedEEPROMMconfig;
|
||||
extern InternalSTM32F4_EEPROM_Class EEPROM;
|
||||
|
||||
#elif defined(STM32F401xC)
|
||||
//when using with internal falsh not enough rom is available so small flash mode is enabled
|
||||
|
@ -126,8 +126,8 @@ extern "C" char* sbrk(int incr);
|
|||
#else //default case, internal flash as EEPROM for STM32F407
|
||||
#define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h"
|
||||
#include EEPROM_LIB_H
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08080000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
extern EEPROM_Emulation_Config EmulatedEEPROMMconfig;
|
||||
extern InternalSTM32F4_EEPROM_Class EEPROM;
|
||||
#endif
|
||||
|
||||
#define RTC_LIB_H "STM32RTC.h"
|
||||
|
@ -267,16 +267,16 @@ extern "C" char* sbrk(int incr);
|
|||
* Timers
|
||||
*/
|
||||
|
||||
HardwareTimer Timer1(TIM1);
|
||||
HardwareTimer Timer2(TIM2);
|
||||
HardwareTimer Timer3(TIM3);
|
||||
HardwareTimer Timer4(TIM4);
|
||||
extern HardwareTimer Timer1;
|
||||
extern HardwareTimer Timer2;
|
||||
extern HardwareTimer Timer3;
|
||||
extern HardwareTimer Timer4;
|
||||
#if !defined(ARDUINO_BLUEPILL_F103C8) && !defined(ARDUINO_BLUEPILL_F103CB) //F103 just have 4 timers
|
||||
HardwareTimer Timer5(TIM5);
|
||||
extern HardwareTimer Timer5;
|
||||
#if defined(TIM11)
|
||||
HardwareTimer Timer11(TIM11);
|
||||
extern HardwareTimer Timer11;
|
||||
#elif defined(TIM7)
|
||||
HardwareTimer Timer11(TIM7);
|
||||
extern HardwareTimer Timer11;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -328,7 +328,7 @@ void ignitionSchedule8Interrupt(HardwareTimer*);
|
|||
//HardwareSerial CANSerial(PD6, PD5);
|
||||
#include <src/STM32_CAN/STM32_CAN.h>
|
||||
//This activates CAN1 interface on STM32, but it's named as Can0, because that's how Teensy implementation is done
|
||||
STM32_CAN Can0 (_CAN1,DEF);
|
||||
extern STM32_CAN Can0;
|
||||
/*
|
||||
Second CAN interface is also available if needed or it can be used also as primary CAN interface.
|
||||
for STM32F4 the default CAN1 pins are PD0 & PD1. Alternative (ALT) pins are PB8 & PB9 and ALT2 pins are PA11 and PA12:
|
||||
|
|
|
@ -6,6 +6,56 @@
|
|||
#include "scheduler.h"
|
||||
#include "HardwareTimer.h"
|
||||
|
||||
#if defined(STM32F407xx) || defined(STM32F103xB) || defined(STM32F405xx)
|
||||
#define NATIVE_CAN_AVAILABLE
|
||||
//This activates CAN1 interface on STM32, but it's named as Can0, because that's how Teensy implementation is done
|
||||
STM32_CAN Can0 (_CAN1,DEF);
|
||||
#endif
|
||||
|
||||
#if defined(SRAM_AS_EEPROM)
|
||||
BackupSramAsEEPROM EEPROM;
|
||||
#elif defined(USE_SPI_EEPROM)
|
||||
SPIClass SPI_for_flash(PB5, PB4, PB3); //SPI1_MOSI, SPI1_MISO, SPI1_SCK
|
||||
|
||||
//windbond W25Q16 SPI flash EEPROM emulation
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{255UL, 4096UL, 31, 0x00100000UL};
|
||||
Flash_SPI_Config SPIconfig{USE_SPI_EEPROM, SPI_for_flash};
|
||||
SPI_EEPROM_Class EEPROM(EmulatedEEPROMMconfig, SPIconfig);
|
||||
#elif defined(FRAM_AS_EEPROM) //https://github.com/VitorBoss/FRAM
|
||||
#if defined(STM32F407xx)
|
||||
FramClass EEPROM(PB5, PB4, PB3, PB0); /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
#else
|
||||
FramClass EEPROM(PB15, PB14, PB13, PB12); //Blue/Black Pills
|
||||
#endif
|
||||
#elif defined(STM32F7xx)
|
||||
#if defined(DUAL_BANK)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08120000UL};
|
||||
#else
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 262144UL, 4095UL, 0x08180000UL};
|
||||
#endif
|
||||
InternalSTM32F7_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#elif defined(STM32F401xC)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 131072UL, 4095UL, 0x08040000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#else //default case, internal flash as EEPROM for STM32F4
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08080000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#endif
|
||||
|
||||
|
||||
HardwareTimer Timer1(TIM1);
|
||||
HardwareTimer Timer2(TIM2);
|
||||
HardwareTimer Timer3(TIM3);
|
||||
HardwareTimer Timer4(TIM4);
|
||||
#if !defined(ARDUINO_BLUEPILL_F103C8) && !defined(ARDUINO_BLUEPILL_F103CB) //F103 just have 4 timers
|
||||
HardwareTimer Timer5(TIM5);
|
||||
#if defined(TIM11)
|
||||
HardwareTimer Timer11(TIM11);
|
||||
#elif defined(TIM7)
|
||||
HardwareTimer Timer11(TIM7);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
STM32RTC& rtc = STM32RTC::getInstance();
|
||||
|
||||
void initBoard()
|
||||
|
|
|
@ -144,10 +144,10 @@
|
|||
#define USE_SERIAL3 // Secondary serial port to use
|
||||
#include <FlexCAN_T4.h>
|
||||
#if defined(__MK64FX512__) // use for Teensy 3.5 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
extern FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
#elif defined(__MK66FX1M0__) // use for Teensy 3.6 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
extern FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
extern FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
#endif
|
||||
static CAN_message_t outMsg;
|
||||
static CAN_message_t inMsg;
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
#if defined(__MK64FX512__) // use for Teensy 3.5 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
#elif defined(__MK66FX1M0__) // use for Teensy 3.6 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
#endif
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -154,9 +154,9 @@
|
|||
*/
|
||||
#define USE_SERIAL3
|
||||
#include <FlexCAN_T4.h>
|
||||
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can2;
|
||||
extern FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
extern FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
extern FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can2;
|
||||
static CAN_message_t outMsg;
|
||||
static CAN_message_t inMsg;
|
||||
//#define NATIVE_CAN_AVAILABLE //Disable for now as it causes lockup
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can2;
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
|
|
|
@ -4,32 +4,22 @@
|
|||
#define NEW_CAN_PACKET_SIZE 75
|
||||
#define CAN_PACKET_SIZE 75
|
||||
|
||||
uint8_t currentsecondserialCommand;
|
||||
uint8_t currentCanPage = 1;//Not the same as the speeduino config page numbers
|
||||
uint8_t nCanretry = 0; //no of retrys
|
||||
uint8_t cancmdfail = 0; //command fail yes/no
|
||||
uint8_t canlisten = 0;
|
||||
uint8_t Lbuffer[8]; //8 byte buffer to store incomng can data
|
||||
uint8_t Gdata[9];
|
||||
uint8_t Glow, Ghigh;
|
||||
bool canCmdPending = false;
|
||||
|
||||
#if ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) )
|
||||
#define CANSerial_AVAILABLE
|
||||
HardwareSerial &CANSerial = Serial3;
|
||||
extern HardwareSerial &CANSerial;
|
||||
#elif defined(CORE_STM32)
|
||||
#define CANSerial_AVAILABLE
|
||||
#ifndef Serial2
|
||||
#define Serial2 Serial1
|
||||
#endif
|
||||
#if defined(STM32GENERIC) // STM32GENERIC core
|
||||
SerialUART &CANSerial = Serial2;
|
||||
extern SerialUART &CANSerial;
|
||||
#else //libmaple core aka STM32DUINO
|
||||
HardwareSerial &CANSerial = Serial2;
|
||||
extern HardwareSerial &CANSerial;
|
||||
#endif
|
||||
#elif defined(CORE_TEENSY)
|
||||
#define CANSerial_AVAILABLE
|
||||
HardwareSerial &CANSerial = Serial2;
|
||||
extern HardwareSerial &CANSerial;
|
||||
#endif
|
||||
|
||||
void secondserial_Command();//This is the heart of the Command Line Interpeter. All that needed to be done was to make it human readable.
|
||||
|
|
|
@ -21,6 +21,34 @@ sendcancommand is called when a command is to be sent either to serial3
|
|||
#include "errors.h"
|
||||
#include "utilities.h"
|
||||
|
||||
uint8_t currentsecondserialCommand;
|
||||
uint8_t currentCanPage = 1;//Not the same as the speeduino config page numbers
|
||||
uint8_t nCanretry = 0; //no of retrys
|
||||
uint8_t cancmdfail = 0; //command fail yes/no
|
||||
uint8_t canlisten = 0;
|
||||
uint8_t Lbuffer[8]; //8 byte buffer to store incomng can data
|
||||
uint8_t Gdata[9];
|
||||
uint8_t Glow, Ghigh;
|
||||
bool canCmdPending = false;
|
||||
|
||||
#if ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) )
|
||||
#define CANSerial_AVAILABLE
|
||||
HardwareSerial &CANSerial = Serial3;
|
||||
#elif defined(CORE_STM32)
|
||||
#define CANSerial_AVAILABLE
|
||||
#ifndef Serial2
|
||||
#define Serial2 Serial1
|
||||
#endif
|
||||
#if defined(STM32GENERIC) // STM32GENERIC core
|
||||
SerialUART &CANSerial = Serial2;
|
||||
#else //libmaple core aka STM32DUINO
|
||||
HardwareSerial &CANSerial = Serial2;
|
||||
#endif
|
||||
#elif defined(CORE_TEENSY)
|
||||
#define CANSerial_AVAILABLE
|
||||
HardwareSerial &CANSerial = Serial2;
|
||||
#endif
|
||||
|
||||
void secondserial_Command()
|
||||
{
|
||||
#if defined(CANSerial_AVAILABLE)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,21 +9,6 @@
|
|||
|
||||
#ifndef COMMS_H
|
||||
#define COMMS_H
|
||||
//These are the page numbers that the Tuner Studio serial protocol uses to transverse the different map and config pages.
|
||||
#define veMapPage 2
|
||||
#define veSetPage 1 //Note that this and the veMapPage were swapped in Feb 2019 as the 'algorithm' field must be declared in the ini before it's used in the fuel table
|
||||
#define ignMapPage 3
|
||||
#define ignSetPage 4//Config Page 2
|
||||
#define afrMapPage 5
|
||||
#define afrSetPage 6//Config Page 3
|
||||
#define boostvvtPage 7
|
||||
#define seqFuelPage 8
|
||||
#define canbusPage 9//Config Page 9
|
||||
#define warmupPage 10 //Config Page 10
|
||||
#define fuelMap2Page 11
|
||||
#define wmiMapPage 12
|
||||
#define progOutsPage 13
|
||||
#define ignMap2Page 14
|
||||
|
||||
//Hardcoded TunerStudio addresses/commands for various SD/RTC commands
|
||||
#define SD_READWRITE_PAGE 0x11
|
||||
|
@ -50,45 +35,26 @@
|
|||
#define SD_RTC_READ_LENGTH 0x0800
|
||||
|
||||
|
||||
byte currentPage = 1;//Not the same as the speeduino config page numbers
|
||||
bool isMap = true; /**< Whether or not the currentPage contains only a 3D map that would require translation */
|
||||
unsigned long requestCount = 0; /**< 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 */
|
||||
byte currentCommand; /**< The serial command that is currently being processed. This is only useful when cmdPending=True */
|
||||
bool cmdPending = false; /**< Whether or not a serial request has only been partially received. This occurs when a command character has been received in the serial buffer, but not all of its arguments have yet been received. If true, the active command will be stored in the currentCommand variable */
|
||||
bool chunkPending = false; /**< Whether or not the current chucnk write is complete or not */
|
||||
uint16_t chunkComplete = 0; /**< The number of bytes in a chunk write that have been written so far */
|
||||
uint16_t chunkSize = 0; /**< The complete size of the requested chunk write */
|
||||
int valueOffset; /**< THe memory offset within a given page for a value to be read from or written to. Note that we cannot use 'offset' as a variable name, it is a reserved word for several teensy libraries */
|
||||
byte tsCanId = 0; // current tscanid requested
|
||||
byte inProgressOffset;
|
||||
byte inProgressLength;
|
||||
uint32_t inProgressCompositeTime;
|
||||
bool serialInProgress = false;
|
||||
bool toothLogSendInProgress = false;
|
||||
bool compositeLogSendInProgress = false;
|
||||
|
||||
const char pageTitles[] PROGMEM //This is being stored in the avr flash instead of SRAM which there is not very much of
|
||||
{
|
||||
"\nVE Map\0"//This is an alternative to using a 2D array which would waste space because of the different lengths of the strings
|
||||
"\nPg 1 Config\0"// 21-The configuration page titles' indexes are found by counting the chars
|
||||
"\nIgnition Map\0"//35-The map page titles' indexes are put into a var called currentTitleIndex. That represents the first char of each string.
|
||||
"\nPg 2 Config\0" //48
|
||||
"\nAFR Map\0" //56
|
||||
"\nPg 3 Config\0" //69
|
||||
"\nPg 4 Config\0" //82
|
||||
"\nBoost Map\0" //93
|
||||
"\nVVT Map\0"//102-No need to put a trailing null because it's the last string and the compliler does it for you.
|
||||
"\nPg 10 Config\0"//116
|
||||
"\n2nd Fuel Map\0"//130
|
||||
"\nWMI Map\0"//139
|
||||
"\nPrgm IO\0"//148
|
||||
"\n2nd Ignition Map"
|
||||
};
|
||||
extern byte currentPage;//Not the same as the speeduino config page numbers
|
||||
extern bool isMap; /**< Whether or not the currentPage contains only a 3D map that would require translation */
|
||||
extern unsigned long requestCount; /**< 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 */
|
||||
extern byte currentCommand; /**< The serial command that is currently being processed. This is only useful when cmdPending=True */
|
||||
extern bool cmdPending; /**< Whether or not a serial request has only been partially received. This occurs when a command character has been received in the serial buffer, but not all of its arguments have yet been received. If true, the active command will be stored in the currentCommand variable */
|
||||
extern bool chunkPending; /**< Whether or not the current chucnk write is complete or not */
|
||||
extern uint16_t chunkComplete; /**< The number of bytes in a chunk write that have been written so far */
|
||||
extern uint16_t chunkSize; /**< The complete size of the requested chunk write */
|
||||
extern int valueOffset; /**< THe memory offset within a given page for a value to be read from or written to. Note that we cannot use 'offset' as a variable name, it is a reserved word for several teensy libraries */
|
||||
extern byte tsCanId; // current tscanid requested
|
||||
extern byte inProgressOffset;
|
||||
extern byte inProgressLength;
|
||||
extern uint32_t inProgressCompositeTime;
|
||||
extern bool serialInProgress;
|
||||
extern bool toothLogSendInProgress;
|
||||
extern bool compositeLogSendInProgress;
|
||||
|
||||
void command();//This is the heart of the Command Line Interpeter. All that needed to be done was to make it human readable.
|
||||
void sendValues(uint16_t, uint16_t,byte, byte);
|
||||
void sendValuesLegacy();
|
||||
void receiveValue(uint16_t, byte);
|
||||
void saveConfig();
|
||||
void sendPage();
|
||||
void sendPageASCII();
|
||||
|
@ -97,7 +63,6 @@ void sendToothLog(uint8_t);
|
|||
void testComm();
|
||||
void commandButtons(int16_t);
|
||||
void sendCompositeLog(uint8_t);
|
||||
byte getPageValue(byte, uint16_t);
|
||||
byte getStatusEntry(uint16_t);
|
||||
|
||||
#endif // COMMS_H
|
||||
|
|
2316
speeduino/comms.ino
2316
speeduino/comms.ino
File diff suppressed because it is too large
Load Diff
|
@ -49,8 +49,4 @@ struct packedError
|
|||
byte getNextError();
|
||||
byte setError(byte);
|
||||
|
||||
byte errorCount = 0;
|
||||
byte errorCodes[4];
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,9 @@ A full copy of the license may be found in the projects root directory
|
|||
#include "globals.h"
|
||||
#include "errors.h"
|
||||
|
||||
byte errorCount = 0;
|
||||
byte errorCodes[4];
|
||||
|
||||
byte setError(byte errorID)
|
||||
{
|
||||
if(errorCount < MAX_ERRORS)
|
||||
|
|
|
@ -377,9 +377,6 @@
|
|||
extern const char TSfirmwareVersion[] PROGMEM;
|
||||
|
||||
extern const byte data_structure_version; //This identifies the data structure when reading / writing.
|
||||
#define NUM_PAGES 15
|
||||
extern const uint16_t npage_size[NUM_PAGES]; /**< This array stores the size (in bytes) of each configuration page */
|
||||
#define MAP_PAGE_SIZE 288
|
||||
|
||||
extern struct table3D fuelTable; //16x16 fuel map
|
||||
extern struct table3D fuelTable2; //16x16 fuel map
|
||||
|
@ -1430,10 +1427,4 @@ extern struct table2D cltCalibrationTable; /**< A 32 bin array containing the co
|
|||
extern struct table2D iatCalibrationTable; /**< A 32 bin array containing the inlet air temperature sensor calibration values */
|
||||
extern struct table2D o2CalibrationTable; /**< A 32 bin array containing the O2 sensor calibration values */
|
||||
|
||||
static_assert(sizeof(struct config2) == 128, "configPage2 size is not 128");
|
||||
static_assert(sizeof(struct config4) == 128, "configPage4 size is not 128");
|
||||
static_assert(sizeof(struct config6) == 128, "configPage6 size is not 128");
|
||||
static_assert(sizeof(struct config9) == 192, "configPage9 size is not 192");
|
||||
static_assert(sizeof(struct config10) == 192, "configPage10 size is not 192");
|
||||
static_assert(sizeof(struct config13) == 128, "configPage13 size is not 128");
|
||||
#endif // GLOBALS_H
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
const char TSfirmwareVersion[] PROGMEM = "Speeduino";
|
||||
|
||||
const byte data_structure_version = 2; //This identifies the data structure when reading / writing.
|
||||
const uint16_t npage_size[NUM_PAGES] = {0,128,288,288,128,288,128,240,384,192,192,288,192,128,288}; /**< This array stores the size (in bytes) of each configuration page */
|
||||
|
||||
struct table3D fuelTable; //16x16 fuel map
|
||||
struct table3D fuelTable2; //16x16 fuel map
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
#include "page_crc.h"
|
||||
#include "pages.h"
|
||||
#include "src/FastCRC/FastCRC.h"
|
||||
#include "table_iterator.h"
|
||||
|
||||
static FastCRC32 CRC32;
|
||||
|
||||
typedef uint32_t (FastCRC32::*pCrcCalc)(const uint8_t *, const uint16_t, bool);
|
||||
|
||||
static inline uint32_t compute_raw_crc(const page_iterator_t &entity, pCrcCalc calcFunc)
|
||||
{
|
||||
return (CRC32.*calcFunc)((uint8_t*)entity.pData, entity.size, false);
|
||||
}
|
||||
|
||||
static inline uint32_t compute_tablevalues_crc(table_row_iterator_t it, pCrcCalc calcFunc)
|
||||
{
|
||||
table_row_t row = get_row(it);
|
||||
uint32_t crc = (CRC32.*calcFunc)(row.pValue, row.pEnd-row.pValue, false);
|
||||
advance_row(it);
|
||||
|
||||
while (!at_end(it))
|
||||
{
|
||||
row = get_row(it);
|
||||
crc = CRC32.crc32_upd(row.pValue, row.pEnd-row.pValue, false);
|
||||
advance_row(it);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
static inline uint32_t compute_tableaxis_crc(table_axis_iterator_t it, uint32_t crc)
|
||||
{
|
||||
byte values[32]; // Fingers crossed we don't have a table bigger than 32x32
|
||||
byte *pValue = values;
|
||||
while (!at_end(it))
|
||||
{
|
||||
*pValue++ = get_value(it);
|
||||
it = advance_axis(it);
|
||||
}
|
||||
return pValue-values==0 ? crc : CRC32.crc32_upd(values, pValue-values, false);
|
||||
}
|
||||
|
||||
static inline uint32_t compute_table_crc(table3D *pTable, pCrcCalc calcFunc)
|
||||
{
|
||||
return compute_tableaxis_crc(y_begin(pTable),
|
||||
compute_tableaxis_crc(x_begin(pTable),
|
||||
compute_tablevalues_crc(rows_begin(pTable), calcFunc)));
|
||||
}
|
||||
|
||||
static inline uint32_t pad_crc(uint16_t padding, uint32_t crc)
|
||||
{
|
||||
uint8_t raw_value = 0u;
|
||||
while (padding>0)
|
||||
{
|
||||
crc = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
--padding;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
static inline uint32_t compute_crc(page_iterator_t &entity, pCrcCalc calcFunc)
|
||||
{
|
||||
switch (entity.type)
|
||||
{
|
||||
case Raw:
|
||||
return compute_raw_crc(entity, calcFunc);
|
||||
break;
|
||||
|
||||
case Table:
|
||||
return compute_table_crc(entity.pTable, calcFunc);
|
||||
break;
|
||||
|
||||
case NoEntity:
|
||||
return pad_crc(entity.size, 0U);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t calculateCRC32(byte pageNum)
|
||||
{
|
||||
page_iterator_t entity = page_begin(pageNum);
|
||||
// Initial CRC calc
|
||||
uint32_t crc = compute_crc(entity, &FastCRC32::crc32);
|
||||
|
||||
entity = advance(entity);
|
||||
while (entity.type!=End)
|
||||
{
|
||||
crc = compute_crc(entity, &FastCRC32::crc32_upd /* Note that we are *updating* */);
|
||||
entity = advance(entity);
|
||||
}
|
||||
return ~pad_crc(getPageSize(pageNum) - entity.size, crc);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
/*
|
||||
* Calculates and returns the CRC32 value of a given page of memory
|
||||
*/
|
||||
uint32_t calculateCRC32(byte pageNum /**< [in] The page number to compute CRC for. */);
|
|
@ -0,0 +1,372 @@
|
|||
#include "pages.h"
|
||||
#include "globals.h"
|
||||
#include "utilities.h"
|
||||
#include "table_iterator.h"
|
||||
|
||||
// This namespace maps from virtual page "addresses" to addresses/bytes of real in memory entities
|
||||
//
|
||||
// For TunerStudio:
|
||||
// 1. Each page has a numeric identifier (0 to N-1)
|
||||
// 2. A single page is a continguous block of data.
|
||||
// So individual bytes are identified by a page number + offset
|
||||
//
|
||||
// The TS layout is not what is in memory. E.g.
|
||||
//
|
||||
// TS Page 2 |0123456789ABCD|0123456789ABCDEF|
|
||||
// | |
|
||||
// Arduino In Memory |--- Entity A ---| |--- Entity B -----|
|
||||
//
|
||||
// Further, the in memory entity may also not be contiguous or in the same
|
||||
// order that TS expects
|
||||
//
|
||||
// So there is a 2 stage mapping:
|
||||
// 1. Page # + Offset to entity
|
||||
// 2. Offset to intra-entity byte
|
||||
|
||||
// Page sizes as defined in the .ini file
|
||||
constexpr const uint16_t ini_page_sizes[] = { 0, 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288 };
|
||||
|
||||
// What section of a 3D table the offset mapped to
|
||||
enum table3D_section_t {
|
||||
Value, // The values
|
||||
axisX, // X axis
|
||||
axisY, // Y axis
|
||||
TableSectionNone // Should never happen!
|
||||
};
|
||||
|
||||
// Stores enough information to access a table element
|
||||
struct table_entity_t {
|
||||
table3D *pTable;
|
||||
uint8_t xIndex; // Value X index or X axis index
|
||||
uint8_t yIndex; // Value Y index or Y axis index
|
||||
table3D_section_t section;
|
||||
};
|
||||
|
||||
struct entity_t {
|
||||
// The entity that the offset mapped to
|
||||
union {
|
||||
table_entity_t table;
|
||||
void *pData;
|
||||
};
|
||||
uint8_t page; // The page the entity belongs to
|
||||
uint16_t start; // The start position of the entity, in bytes, from the start of the page
|
||||
uint16_t size; // Size of the entity in bytes
|
||||
entity_type type;
|
||||
};
|
||||
|
||||
// This will fail AND print the page number and required size
|
||||
template <uint8_t pageNum, uint16_t min>
|
||||
static inline void check_size() {
|
||||
static_assert(ini_page_sizes[pageNum] >= min, "Size is off!");
|
||||
}
|
||||
|
||||
// Handy table macros
|
||||
#define TABLE_VALUE_END(size) ((uint16_t)size*(uint16_t)size)
|
||||
#define TABLE_AXISX_END(size) (TABLE_VALUE_END(size)+(uint16_t)size)
|
||||
#define TABLE_AXISY_END(size) (TABLE_AXISX_END(size)+(uint16_t)size)
|
||||
#define TABLE_SIZE(size) TABLE_AXISY_END(size)
|
||||
|
||||
// Precompute for performance
|
||||
#define TABLE16_SIZE TABLE_SIZE(16)
|
||||
#define TABLE8_SIZE TABLE_SIZE(8)
|
||||
#define TABLE6_SIZE TABLE_SIZE(6)
|
||||
#define TABLE4_SIZE TABLE_SIZE(4)
|
||||
|
||||
// Macros + compile time constants = fast division/modulus
|
||||
//
|
||||
// The various fast division libraries, E.g. libdivide, use
|
||||
// 32-bit operations for 16-bit division. Super slow.
|
||||
#define OFFSET_TOVALUE_YINDEX(offset, size) ((uint8_t)((size-1) - (offset / size)))
|
||||
#define OFFSET_TOVALUE_XINDEX(offset, size) ((uint8_t)(offset % size))
|
||||
#define OFFSET_TOAXIS_XINDEX(offset, size) ((uint8_t)(offset - TABLE_VALUE_END(size)))
|
||||
#define OFFSET_TOAXIS_YINDEX(offset, size) ((uint8_t)((size-1) - (offset - TABLE_AXISX_END(size))))
|
||||
|
||||
#define NULL_TABLE \
|
||||
{ nullptr, 0, 0, TableSectionNone }
|
||||
|
||||
#define CREATE_PAGE_END(pageNum, pageSize) \
|
||||
{ NULL_TABLE, .page = pageNum, .start = 0, .size = pageSize, .type = End }
|
||||
|
||||
// Signal the end of a page
|
||||
#define END_OF_PAGE(pageNum, pageSize) \
|
||||
check_size<pageNum, pageSize>(); \
|
||||
return CREATE_PAGE_END(pageNum, pageSize);
|
||||
|
||||
// If the offset is in range, create a None entity_t
|
||||
#define CHECK_NOENTITY(offset, startByte, blockSize, pageNum) \
|
||||
if (offset < (startByte)+blockSize) \
|
||||
{ \
|
||||
return { NULL_TABLE, .page = pageNum, .start = (startByte), .size = blockSize, .type = NoEntity }; \
|
||||
}
|
||||
|
||||
//
|
||||
#define TABLE_VALUE(offset, startByte, pTable, tableSize) \
|
||||
{ pTable, \
|
||||
OFFSET_TOVALUE_XINDEX((offset-(startByte)), tableSize), \
|
||||
OFFSET_TOVALUE_YINDEX((offset-(startByte)), tableSize), \
|
||||
Value }
|
||||
|
||||
#define TABLE_XAXIS(offset, startByte, pTable, tableSize) \
|
||||
{ pTable, \
|
||||
OFFSET_TOAXIS_XINDEX((offset-(startByte)), tableSize), \
|
||||
0U, \
|
||||
axisX }
|
||||
|
||||
#define TABLE_YAXIS(offset, startByte, pTable, tableSize) \
|
||||
{ pTable, \
|
||||
0U, \
|
||||
OFFSET_TOAXIS_YINDEX((offset-(startByte)), tableSize), \
|
||||
axisY }
|
||||
|
||||
#define TABLE_ENTITY(table_type, pageNum, startByte, tableSize) \
|
||||
{ table_type, .page = pageNum, .start = (startByte), .size = TABLE_SIZE(tableSize), .type = Table }
|
||||
|
||||
// If the offset is in range, create a Table entity_t
|
||||
#define CHECK_TABLE(offset, startByte, pTable, tableSize, pageNum) \
|
||||
if (offset < (startByte)+TABLE_VALUE_END(tableSize)) \
|
||||
{ \
|
||||
return TABLE_ENTITY(TABLE_VALUE(offset, startByte, pTable, tableSize), pageNum, startByte, tableSize); \
|
||||
} \
|
||||
if (offset < (startByte)+TABLE_AXISX_END(tableSize)) \
|
||||
{ \
|
||||
return TABLE_ENTITY(TABLE_XAXIS(offset, startByte, pTable, tableSize), pageNum, startByte, tableSize); \
|
||||
} \
|
||||
if (offset < (startByte)+TABLE_AXISY_END(tableSize)) \
|
||||
{ \
|
||||
return TABLE_ENTITY(TABLE_YAXIS(offset, startByte, pTable, tableSize), pageNum, startByte, tableSize); \
|
||||
}
|
||||
|
||||
// If the offset is in range, create a Raw entity_t
|
||||
#define CHECK_RAW(offset, startByte, pDataBlock, blockSize, pageNum) \
|
||||
if (offset < (startByte)+blockSize) \
|
||||
{ \
|
||||
return { { (table3D*)pDataBlock, 0, 0, TableSectionNone }, .page = pageNum, .start = (startByte), .size = blockSize, .type = Raw }; \
|
||||
}
|
||||
|
||||
// Does the heavy lifting of mapping page+offset to an entity
|
||||
//
|
||||
// Alternative implementation would be to encode the mapping into data structures
|
||||
// That uses flash memory, which is scarce. And it was too slow.
|
||||
static inline __attribute__((always_inline)) // <-- this is critical for performance
|
||||
entity_t map_page_offset_to_entity_inline(uint8_t pageNumber, uint16_t offset)
|
||||
{
|
||||
switch (pageNumber)
|
||||
{
|
||||
case 0:
|
||||
return CREATE_PAGE_END(0, 0);
|
||||
|
||||
case veMapPage:
|
||||
CHECK_TABLE(offset, 0U, &fuelTable, 16, pageNumber)
|
||||
END_OF_PAGE(veMapPage, TABLE16_SIZE);
|
||||
break;
|
||||
|
||||
case ignMapPage: //Ignition settings page (Page 2)
|
||||
CHECK_TABLE(offset, 0U, &ignitionTable, 16, pageNumber)
|
||||
END_OF_PAGE(ignMapPage, TABLE16_SIZE);
|
||||
break;
|
||||
|
||||
case afrMapPage: //Air/Fuel ratio target settings page
|
||||
CHECK_TABLE(offset, 0U, &afrTable, 16, pageNumber)
|
||||
END_OF_PAGE(afrMapPage, TABLE16_SIZE);
|
||||
break;
|
||||
|
||||
case boostvvtPage: //Boost, VVT and staging maps (all 8x8)
|
||||
CHECK_TABLE(offset, 0U, &boostTable, 8, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE8_SIZE, &vvtTable, 8, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE8_SIZE*2, &stagingTable, 8, pageNumber)
|
||||
END_OF_PAGE(boostvvtPage, TABLE8_SIZE*3);
|
||||
break;
|
||||
|
||||
case seqFuelPage:
|
||||
CHECK_TABLE(offset, 0U, &trim1Table, 6, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE6_SIZE*1, &trim2Table, 6, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE6_SIZE*2, &trim3Table, 6, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE6_SIZE*3, &trim4Table, 6, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE6_SIZE*4, &trim5Table, 6, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE6_SIZE*5, &trim6Table, 6, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE6_SIZE*6, &trim7Table, 6, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE6_SIZE*7, &trim8Table, 6, pageNumber)
|
||||
END_OF_PAGE(seqFuelPage, TABLE6_SIZE*8);
|
||||
break;
|
||||
|
||||
case fuelMap2Page:
|
||||
CHECK_TABLE(offset, 0U, &fuelTable2, 16, pageNumber)
|
||||
END_OF_PAGE(fuelMap2Page, TABLE16_SIZE);
|
||||
break;
|
||||
|
||||
case wmiMapPage:
|
||||
CHECK_TABLE(offset, 0U, &wmiTable, 8, pageNumber)
|
||||
CHECK_NOENTITY(offset, TABLE8_SIZE, 80, pageNumber)
|
||||
CHECK_TABLE(offset, TABLE8_SIZE + 80, &dwellTable, 4, pageNumber)
|
||||
END_OF_PAGE(wmiMapPage, TABLE8_SIZE + 80 + TABLE4_SIZE);
|
||||
break;
|
||||
|
||||
case ignMap2Page:
|
||||
CHECK_TABLE(offset, 0U, &ignitionTable2, 16, pageNumber)
|
||||
END_OF_PAGE(ignMap2Page, TABLE16_SIZE);
|
||||
break;
|
||||
|
||||
case veSetPage:
|
||||
CHECK_RAW(offset, 0U, &configPage2, sizeof(configPage2), pageNumber)
|
||||
END_OF_PAGE(veSetPage, sizeof(configPage2));
|
||||
break;
|
||||
|
||||
case ignSetPage:
|
||||
CHECK_RAW(offset, 0U, &configPage4, sizeof(configPage4), pageNumber)
|
||||
END_OF_PAGE(ignSetPage, sizeof(configPage4));
|
||||
break;
|
||||
|
||||
case afrSetPage:
|
||||
CHECK_RAW(offset, 0U, &configPage6, sizeof(configPage6), pageNumber)
|
||||
END_OF_PAGE(afrSetPage, sizeof(configPage6));
|
||||
break;
|
||||
|
||||
case canbusPage:
|
||||
CHECK_RAW(offset, 0U, &configPage9, sizeof(configPage9), pageNumber)
|
||||
END_OF_PAGE(canbusPage, sizeof(configPage9));
|
||||
break;
|
||||
|
||||
case warmupPage:
|
||||
CHECK_RAW(offset, 0U, &configPage10, sizeof(configPage10), pageNumber)
|
||||
END_OF_PAGE(warmupPage, sizeof(configPage10));
|
||||
break;
|
||||
|
||||
case progOutsPage:
|
||||
CHECK_RAW(offset, 0U, &configPage13, sizeof(configPage13), pageNumber)
|
||||
END_OF_PAGE(progOutsPage, sizeof(configPage13));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort(); // Unkown page number. Not a lot we can do.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Tables do not map linearly to the TS page address space, so special
|
||||
// handling is necessary (we do not use the normal array layout for
|
||||
// performance reasons elsewhere)
|
||||
//
|
||||
// We take the offset & map it to a single value, x-axis or y-axis element
|
||||
static inline byte get_table_value(const table_entity_t &table)
|
||||
{
|
||||
switch (table.section)
|
||||
{
|
||||
case Value:
|
||||
return table.pTable->values[table.yIndex][table.xIndex];
|
||||
|
||||
case axisX:
|
||||
return (byte)(table.pTable->axisX[table.xIndex] / getTableXAxisFactor(table.pTable));
|
||||
|
||||
case axisY:
|
||||
return (byte)(table.pTable->axisY[table.yIndex] / getTableYAxisFactor(table.pTable));
|
||||
|
||||
default: return 0; // no-op
|
||||
}
|
||||
return 0U;
|
||||
}
|
||||
|
||||
static inline void set_table_value(const table_entity_t &table, int8_t value)
|
||||
{
|
||||
switch (table.section)
|
||||
{
|
||||
case Value:
|
||||
table.pTable->values[table.yIndex][table.xIndex] = value;
|
||||
break;
|
||||
|
||||
case axisX:
|
||||
table.pTable->axisX[table.xIndex] = (int16_t)(value) * getTableXAxisFactor(table.pTable);
|
||||
break;
|
||||
|
||||
case axisY:
|
||||
table.pTable->axisY[table.yIndex]= (int16_t)(value) * getTableYAxisFactor(table.pTable);
|
||||
break;
|
||||
|
||||
default: ; // no-op
|
||||
}
|
||||
table.pTable->cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||
}
|
||||
|
||||
static inline byte* get_raw_value(const entity_t &entity, uint16_t offset)
|
||||
{
|
||||
return (byte*)entity.pData + offset;
|
||||
}
|
||||
|
||||
// ============================ Page iteration support ======================
|
||||
|
||||
// Because the page iterators will not be called for every single byte
|
||||
// inlining the mapping function is not performance critical.
|
||||
//
|
||||
// So save some memory.
|
||||
static entity_t map_page_offset_to_entity(uint8_t pageNumber, uint16_t offset)
|
||||
{
|
||||
return map_page_offset_to_entity_inline(pageNumber, offset);
|
||||
}
|
||||
|
||||
static inline page_iterator_t to_page_entity(entity_t mapped)
|
||||
{
|
||||
return { { mapped.type==Table ? mapped.table.pTable : (table3D*)mapped.pData },
|
||||
.page=mapped.page, .start = mapped.start, .size = mapped.size, .type = mapped.type };
|
||||
}
|
||||
|
||||
// ====================================== External functions ====================================
|
||||
|
||||
uint8_t getPageCount()
|
||||
{
|
||||
return _countof(ini_page_sizes);
|
||||
}
|
||||
|
||||
uint16_t getPageSize(byte pageNum)
|
||||
{
|
||||
return ini_page_sizes[pageNum];
|
||||
}
|
||||
|
||||
void setPageValue(byte pageNum, uint16_t offset, byte value)
|
||||
{
|
||||
entity_t entity = map_page_offset_to_entity_inline(pageNum, offset);
|
||||
|
||||
switch (entity.type)
|
||||
{
|
||||
case Table:
|
||||
set_table_value(entity.table, value);
|
||||
break;
|
||||
|
||||
case Raw:
|
||||
*get_raw_value(entity, offset-entity.start) = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte getPageValue(byte page, uint16_t offset)
|
||||
{
|
||||
entity_t entity = map_page_offset_to_entity_inline(page, offset);
|
||||
|
||||
switch (entity.type)
|
||||
{
|
||||
case Table:
|
||||
return get_table_value(entity.table);
|
||||
break;
|
||||
|
||||
case Raw:
|
||||
return *get_raw_value(entity, offset);
|
||||
break;
|
||||
|
||||
default: return 0U;
|
||||
}
|
||||
return 0U;
|
||||
}
|
||||
|
||||
// Support iteration over a pages entities.
|
||||
// Check for entity.type==End
|
||||
page_iterator_t page_begin(byte pageNum)
|
||||
{
|
||||
return to_page_entity(map_page_offset_to_entity(pageNum, 0U));
|
||||
}
|
||||
|
||||
page_iterator_t advance(const page_iterator_t &it)
|
||||
{
|
||||
return to_page_entity(map_page_offset_to_entity(it.page, it.start+it.size));
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "table.h"
|
||||
|
||||
/**
|
||||
* Page count, as defined in the INI file
|
||||
*/
|
||||
uint8_t getPageCount();
|
||||
|
||||
/**
|
||||
* Page size in bytes
|
||||
*/
|
||||
uint16_t getPageSize(byte pageNum /**< [in] The page number */ );
|
||||
|
||||
// These are the page numbers that the Tuner Studio serial protocol uses to transverse the different map and config pages.
|
||||
#define veMapPage 2
|
||||
#define veSetPage 1 //Note that this and the veMapPage were swapped in Feb 2019 as the 'algorithm' field must be declared in the ini before it's used in the fuel table
|
||||
#define ignMapPage 3
|
||||
#define ignSetPage 4//Config Page 2
|
||||
#define afrMapPage 5
|
||||
#define afrSetPage 6//Config Page 3
|
||||
#define boostvvtPage 7
|
||||
#define seqFuelPage 8
|
||||
#define canbusPage 9//Config Page 9
|
||||
#define warmupPage 10 //Config Page 10
|
||||
#define fuelMap2Page 11
|
||||
#define wmiMapPage 12
|
||||
#define progOutsPage 13
|
||||
#define ignMap2Page 14
|
||||
|
||||
// ============================== Per-byte page access ==========================
|
||||
|
||||
/**
|
||||
* Gets a single value from a page, with data aligned as per the ini file
|
||||
*/
|
||||
byte getPageValue( byte pageNum, /**< [in] The page number to retrieve data from. */
|
||||
uint16_t offset); /**< [in] The address in the page that should be returned. This is as per the page definition in the ini. */
|
||||
|
||||
/**
|
||||
* Sets a single value from a page, with data aligned as per the ini file
|
||||
*/
|
||||
void setPageValue( byte pageNum, /**< [in] The page number to retrieve data from. */
|
||||
uint16_t offset, /**< [in] The address in the page that should be returned. This is as per the page definition in the ini. */
|
||||
byte value); /**< [in] The new value */
|
||||
|
||||
// ============================== Page Iteration ==========================
|
||||
|
||||
// A logical TS page is actually multiple in memory entities. Allow iteration
|
||||
// over those entities.
|
||||
|
||||
// Type of entity
|
||||
enum entity_type {
|
||||
Raw, // A block of memory
|
||||
Table, // A 3D table
|
||||
NoEntity, // No entity, but a valid offset
|
||||
End // The offset was past any known entity for the page
|
||||
};
|
||||
|
||||
// A entity on a logical page.
|
||||
struct page_iterator_t {
|
||||
union {
|
||||
table3D *pTable;
|
||||
void *pData;
|
||||
};
|
||||
uint8_t page; // The page the entity belongs to
|
||||
uint16_t start; // The start position of the entity, in bytes, from the start of the page
|
||||
uint16_t size; // Size of the entity in bytes
|
||||
entity_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiates iteration over a pages entities.
|
||||
* Test `entity.type==End` to determine the end of the page.
|
||||
*/
|
||||
page_iterator_t page_begin(byte pageNum /**< [in] The page number to iterate over. */);
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next sub-entity on the page
|
||||
*/
|
||||
page_iterator_t advance(const page_iterator_t &it /**< [in] The current iterator */);
|
|
@ -12,6 +12,7 @@ A full copy of the license may be found in the projects root directory
|
|||
#include "idle.h"
|
||||
#include "errors.h"
|
||||
#include "corrections.h"
|
||||
#include "pages.h"
|
||||
|
||||
void initialiseADC()
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ uint32_t readPageCRC32(byte);
|
|||
#else
|
||||
#define EEPROM_MAX_WRITE_BLOCK 30 //The maximum number of write operations that will be performed in one go. If we try to write to the EEPROM too fast (Each write takes ~3ms) then the rest of the system can hang)
|
||||
#endif
|
||||
bool eepromWritesPending = false;
|
||||
extern bool eepromWritesPending;
|
||||
|
||||
/*
|
||||
Current layout of EEPROM data (Version 3) is as follows (All sizes are in bytes):
|
||||
|
|
|
@ -10,6 +10,9 @@ A full copy of the license may be found in the projects root directory
|
|||
#include "comms.h"
|
||||
#include EEPROM_LIB_H //This is defined in the board .h files
|
||||
#include "storage.h"
|
||||
#include "table_iterator.h"
|
||||
|
||||
bool eepromWritesPending = false;
|
||||
|
||||
void writeAllConfig()
|
||||
{
|
||||
|
@ -78,13 +81,13 @@ namespace {
|
|||
return counter;
|
||||
}
|
||||
|
||||
inline int16_t writeTable(const table3D *pTable, int16_t xAxisDivisor, int16_t yAxisDivisor, int &index, int16_t counter)
|
||||
inline int16_t writeTable(const table3D *pTable, int &index, int16_t counter)
|
||||
{
|
||||
counter = update(index, pTable->xSize, counter); ++index;
|
||||
counter = update(index, pTable->ySize, counter); ++index;
|
||||
counter = writeTableValues(pTable, index, counter);
|
||||
counter = write_range_divisor(index, xAxisDivisor, pTable->axisX, pTable->axisX+pTable->xSize, counter);
|
||||
return write_range_divisor(index, yAxisDivisor, pTable->axisY, pTable->axisY+pTable->ySize, counter);
|
||||
counter = write_range_divisor(index, getTableXAxisFactor(pTable), pTable->axisX, pTable->axisX+pTable->xSize, counter);
|
||||
return write_range_divisor(index, getTableYAxisFactor(pTable), pTable->axisY, pTable->axisY+pTable->ySize, counter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +113,7 @@ void writeConfig(byte tableNum)
|
|||
| 16x16 table itself + the 16 values along each of the axis
|
||||
-----------------------------------------------------*/
|
||||
index = EEPROM_CONFIG1_XSIZE;
|
||||
writeCounter = writeTable(&fuelTable, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&fuelTable, index, writeCounter);
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
//That concludes the writing of the VE table
|
||||
|
@ -132,7 +135,7 @@ void writeConfig(byte tableNum)
|
|||
-----------------------------------------------------*/
|
||||
//Begin writing the Ignition table, basically the same thing as above
|
||||
index = EEPROM_CONFIG3_XSIZE;
|
||||
writeCounter = writeTable(&ignitionTable, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&ignitionTable, index, writeCounter);
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
|
||||
|
@ -153,7 +156,7 @@ void writeConfig(byte tableNum)
|
|||
-----------------------------------------------------*/
|
||||
//Begin writing the Ignition table, basically the same thing as above
|
||||
index = EEPROM_CONFIG5_XSIZE;
|
||||
writeCounter = writeTable(&afrTable, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&afrTable, index, writeCounter);
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
|
||||
|
@ -174,11 +177,11 @@ void writeConfig(byte tableNum)
|
|||
-----------------------------------------------------*/
|
||||
//Begin writing the 2 tables, basically the same thing as above but we're doing these 2 together (2 tables per page instead of 1)
|
||||
index = EEPROM_CONFIG7_XSIZE1;
|
||||
writeCounter = writeTable(&boostTable, TABLE_RPM_MULTIPLIER, 1, index, writeCounter);
|
||||
writeCounter = writeTable(&boostTable, index, writeCounter);
|
||||
index = EEPROM_CONFIG7_XSIZE2;
|
||||
writeCounter = writeTable(&vvtTable, TABLE_RPM_MULTIPLIER, 1, index, writeCounter);
|
||||
writeCounter = writeTable(&vvtTable, index, writeCounter);
|
||||
index = EEPROM_CONFIG7_XSIZE3;
|
||||
writeCounter = writeTable(&stagingTable, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&stagingTable, index, writeCounter);
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
|
||||
|
@ -189,21 +192,21 @@ void writeConfig(byte tableNum)
|
|||
-----------------------------------------------------*/
|
||||
//Begin writing the 2 tables, basically the same thing as above but we're doing these 2 together (2 tables per page instead of 1)
|
||||
index = EEPROM_CONFIG8_XSIZE1;
|
||||
writeCounter = writeTable(&trim1Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim1Table, index, writeCounter);
|
||||
index = EEPROM_CONFIG8_XSIZE2;
|
||||
writeCounter = writeTable(&trim2Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim2Table, index, writeCounter);
|
||||
index = EEPROM_CONFIG8_XSIZE3;
|
||||
writeCounter = writeTable(&trim3Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim3Table, index, writeCounter);
|
||||
index = EEPROM_CONFIG8_XSIZE4;
|
||||
writeCounter = writeTable(&trim4Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim4Table, index, writeCounter);
|
||||
index = EEPROM_CONFIG8_XSIZE5;
|
||||
writeCounter = writeTable(&trim5Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim5Table, index, writeCounter);
|
||||
index = EEPROM_CONFIG8_XSIZE6;
|
||||
writeCounter = writeTable(&trim6Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim6Table, index, writeCounter);
|
||||
index = EEPROM_CONFIG8_XSIZE7;
|
||||
writeCounter = writeTable(&trim7Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim7Table, index, writeCounter);
|
||||
index = EEPROM_CONFIG8_XSIZE8;
|
||||
writeCounter = writeTable(&trim8Table, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&trim8Table, index, writeCounter);
|
||||
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
|
@ -234,7 +237,7 @@ void writeConfig(byte tableNum)
|
|||
| 16x16 table itself + the 16 values along each of the axis
|
||||
-----------------------------------------------------*/
|
||||
index = EEPROM_CONFIG11_XSIZE;
|
||||
writeCounter = writeTable(&fuelTable2, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&fuelTable2, index, writeCounter);
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
//That concludes the writing of the 2nd fuel table
|
||||
|
@ -246,9 +249,9 @@ void writeConfig(byte tableNum)
|
|||
| 4x4 Dwell table itself + the 4 values along each of the axis
|
||||
-----------------------------------------------------*/
|
||||
index = EEPROM_CONFIG12_XSIZE;
|
||||
writeCounter = writeTable(&wmiTable, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&wmiTable, index, writeCounter);
|
||||
index = EEPROM_CONFIG12_XSIZE3;
|
||||
writeCounter = writeTable(&dwellTable, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&dwellTable, index, writeCounter);
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
|
||||
|
@ -268,7 +271,7 @@ void writeConfig(byte tableNum)
|
|||
-----------------------------------------------------*/
|
||||
//Begin writing the Ignition table, basically the same thing as above
|
||||
index = EEPROM_CONFIG14_XSIZE;
|
||||
writeCounter = writeTable(&ignitionTable2, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER, index, writeCounter);
|
||||
writeCounter = writeTable(&ignitionTable2, index, writeCounter);
|
||||
eepromWritesPending = writeCounter > EEPROM_MAX_WRITE_BLOCK;
|
||||
break;
|
||||
|
||||
|
@ -319,29 +322,27 @@ namespace
|
|||
return index;
|
||||
}
|
||||
|
||||
inline int loadTableAxisX(table3D *pTable, int index, int xAxisMultiplier)
|
||||
inline int loadTableAxisX(table3D *pTable, int index)
|
||||
{
|
||||
return load_range_multiplier(index, pTable->axisX, pTable->axisX+pTable->xSize, xAxisMultiplier);
|
||||
return load_range_multiplier(index, pTable->axisX, pTable->axisX+pTable->xSize, getTableXAxisFactor(pTable));
|
||||
}
|
||||
|
||||
inline int loadTableAxisY(table3D *pTable, int index, int yAxisMultiplier)
|
||||
inline int loadTableAxisY(table3D *pTable, int index)
|
||||
{
|
||||
return load_range_multiplier(index, pTable->axisY, pTable->axisY+pTable->ySize, yAxisMultiplier);
|
||||
return load_range_multiplier(index, pTable->axisY, pTable->axisY+pTable->ySize, getTableYAxisFactor(pTable));
|
||||
}
|
||||
|
||||
inline int loadTable(table3D *pTable, int index, int xAxisMultiplier, int yAxisMultiplier)
|
||||
inline int loadTable(table3D *pTable, int index)
|
||||
{
|
||||
return loadTableAxisY(pTable,
|
||||
loadTableAxisX(pTable,
|
||||
loadTableValues(pTable, index),
|
||||
xAxisMultiplier),
|
||||
yAxisMultiplier);
|
||||
loadTableValues(pTable, index)));
|
||||
}
|
||||
}
|
||||
|
||||
void loadConfig()
|
||||
{
|
||||
loadTable(&fuelTable, EEPROM_CONFIG1_MAP, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&fuelTable, EEPROM_CONFIG1_MAP);
|
||||
load_range(EEPROM_CONFIG2_START, (byte *)&configPage2, (byte *)&configPage2+sizeof(configPage2));
|
||||
//That concludes the reading of the VE table
|
||||
|
||||
|
@ -349,32 +350,32 @@ void loadConfig()
|
|||
//IGNITION CONFIG PAGE (2)
|
||||
|
||||
//Begin writing the Ignition table, basically the same thing as above
|
||||
loadTable(&ignitionTable, EEPROM_CONFIG3_MAP, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&ignitionTable, EEPROM_CONFIG3_MAP);
|
||||
load_range(EEPROM_CONFIG4_START, (byte *)&configPage4, (byte *)&configPage4+sizeof(configPage4));
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
//AFR TARGET CONFIG PAGE (3)
|
||||
|
||||
//Begin writing the Ignition table, basically the same thing as above
|
||||
loadTable(&afrTable, EEPROM_CONFIG5_MAP, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&afrTable, EEPROM_CONFIG5_MAP);
|
||||
load_range(EEPROM_CONFIG6_START, (byte *)&configPage6, (byte *)&configPage6+sizeof(configPage6));
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
// Boost and vvt tables load
|
||||
loadTable(&boostTable, EEPROM_CONFIG7_MAP1, TABLE_RPM_MULTIPLIER, 1);
|
||||
loadTable(&vvtTable, EEPROM_CONFIG7_MAP2, TABLE_RPM_MULTIPLIER, 1);
|
||||
loadTable(&stagingTable, EEPROM_CONFIG7_MAP3, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&boostTable, EEPROM_CONFIG7_MAP1);
|
||||
loadTable(&vvtTable, EEPROM_CONFIG7_MAP2);
|
||||
loadTable(&stagingTable, EEPROM_CONFIG7_MAP3);
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
// Fuel trim tables load
|
||||
loadTable(&trim1Table, EEPROM_CONFIG8_MAP1, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim2Table, EEPROM_CONFIG8_MAP2, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim3Table, EEPROM_CONFIG8_MAP3, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim4Table, EEPROM_CONFIG8_MAP4, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim5Table, EEPROM_CONFIG8_MAP5, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim6Table, EEPROM_CONFIG8_MAP6, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim7Table, EEPROM_CONFIG8_MAP7, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim8Table, EEPROM_CONFIG8_MAP8, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&trim1Table, EEPROM_CONFIG8_MAP1);
|
||||
loadTable(&trim2Table, EEPROM_CONFIG8_MAP2);
|
||||
loadTable(&trim3Table, EEPROM_CONFIG8_MAP3);
|
||||
loadTable(&trim4Table, EEPROM_CONFIG8_MAP4);
|
||||
loadTable(&trim5Table, EEPROM_CONFIG8_MAP5);
|
||||
loadTable(&trim6Table, EEPROM_CONFIG8_MAP6);
|
||||
loadTable(&trim7Table, EEPROM_CONFIG8_MAP7);
|
||||
loadTable(&trim8Table, EEPROM_CONFIG8_MAP8);
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
//canbus control page load
|
||||
|
@ -387,12 +388,12 @@ void loadConfig()
|
|||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
//Fuel table 2 (See storage.h for data layout)
|
||||
loadTable(&fuelTable2, EEPROM_CONFIG11_MAP, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&fuelTable2, EEPROM_CONFIG11_MAP);
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
// WMI and Dwell table load
|
||||
loadTable(&wmiTable, EEPROM_CONFIG12_MAP, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&dwellTable, EEPROM_CONFIG12_MAP3, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&wmiTable, EEPROM_CONFIG12_MAP);
|
||||
loadTable(&dwellTable, EEPROM_CONFIG12_MAP3);
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
//CONFIG PAGE (13)
|
||||
|
@ -402,7 +403,7 @@ void loadConfig()
|
|||
//SECOND IGNITION CONFIG PAGE (14)
|
||||
|
||||
//Begin writing the Ignition table, basically the same thing as above
|
||||
loadTable(&ignitionTable2, EEPROM_CONFIG14_MAP, TABLE_RPM_MULTIPLIER, TABLE_LOAD_MULTIPLIER);
|
||||
loadTable(&ignitionTable2, EEPROM_CONFIG14_MAP);
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
}
|
||||
|
@ -469,7 +470,7 @@ Note: Each pages requires 4 bytes for its CRC32. These are stored in reverse pag
|
|||
void storePageCRC32(byte pageNo, uint32_t crc32_val)
|
||||
{
|
||||
uint16_t address; //Start address for the relevant page
|
||||
address = EEPROM_PAGE_CRC32 + ((NUM_PAGES - pageNo) * 4);
|
||||
address = EEPROM_PAGE_CRC32 + ((getPageCount() - pageNo) * 4);
|
||||
|
||||
//One = Most significant -> Four = Least significant byte
|
||||
byte four = (crc32_val & 0xFF);
|
||||
|
@ -490,7 +491,7 @@ Retrieves and returns the 4 byte CRC32 for a given page from EEPROM
|
|||
uint32_t readPageCRC32(byte pageNo)
|
||||
{
|
||||
uint16_t address; //Start address for the relevant page
|
||||
address = EEPROM_PAGE_CRC32 + ((NUM_PAGES - pageNo) * 4);
|
||||
address = EEPROM_PAGE_CRC32 + ((getPageCount() - pageNo) * 4);
|
||||
|
||||
//Read the 4 bytes from the eeprom memory.
|
||||
uint32_t four = EEPROM.read(address);
|
||||
|
|
|
@ -44,8 +44,6 @@ YOU MUST UPDATE THE TABLE COUNTS IN THE LINE BELOW WHENEVER A NEW TABLE IS ADDED
|
|||
*/
|
||||
#define TABLE_HEAP_SIZE ((5 * TABLE3D_SIZE_16) + (4 * TABLE3D_SIZE_8) + (8 * TABLE3D_SIZE_6) + (1 * TABLE3D_SIZE_4) + 1)
|
||||
|
||||
static uint8_t _3DTable_heap[TABLE_HEAP_SIZE];
|
||||
static uint16_t _heap_pointer = 0;
|
||||
|
||||
/*
|
||||
The 2D table can contain either 8-bit (byte) or 16-bit (int) values
|
||||
|
|
|
@ -36,6 +36,9 @@ void table2D_setSize(struct table2D* targetTable, byte newSize)
|
|||
}
|
||||
*/
|
||||
|
||||
static uint8_t _3DTable_heap[TABLE_HEAP_SIZE];
|
||||
static uint16_t _heap_pointer = 0;
|
||||
|
||||
void* heap_alloc(uint16_t size)
|
||||
{
|
||||
uint8_t* value = nullptr;
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "table.h"
|
||||
#include "globals.h"
|
||||
|
||||
inline int8_t getTableYAxisFactor(const table3D *pTable)
|
||||
{
|
||||
return pTable==&boostTable || pTable==&vvtTable ? 1 : TABLE_LOAD_MULTIPLIER;
|
||||
}
|
||||
|
||||
inline int8_t getTableXAxisFactor(const table3D *)
|
||||
{
|
||||
return TABLE_RPM_MULTIPLIER;
|
||||
}
|
||||
|
||||
// ========================= AXIS ITERATION =========================
|
||||
typedef struct table_axis_iterator_t
|
||||
{
|
||||
int16_t *_pAxis;
|
||||
int16_t *_pAxisEnd;
|
||||
int16_t _axisFactor;
|
||||
int8_t _stride;
|
||||
} table_axis_iterator_t;
|
||||
|
||||
inline table_axis_iterator_t& advance_axis(table_axis_iterator_t &it)
|
||||
{
|
||||
it._pAxis += it._stride;
|
||||
return it;
|
||||
}
|
||||
|
||||
inline bool at_end(const table_axis_iterator_t &it)
|
||||
{
|
||||
return it._pAxis == it._pAxisEnd;
|
||||
}
|
||||
|
||||
inline byte get_value(const table_axis_iterator_t &it)
|
||||
{
|
||||
return *it._pAxis / it._axisFactor;
|
||||
}
|
||||
|
||||
inline void set_value(table_axis_iterator_t &it, byte value)
|
||||
{
|
||||
*it._pAxis = value * it._axisFactor;
|
||||
}
|
||||
|
||||
inline table_axis_iterator_t y_begin(const table3D *pTable)
|
||||
{
|
||||
return { pTable->axisY+(pTable->ySize-1),
|
||||
(pTable->axisY)-1, getTableYAxisFactor(pTable),
|
||||
-1 };
|
||||
}
|
||||
|
||||
inline table_axis_iterator_t x_begin(const table3D *pTable)
|
||||
{
|
||||
return { pTable->axisX, pTable->axisX+pTable->xSize, getTableXAxisFactor(pTable), 1 };
|
||||
}
|
||||
|
||||
// ========================= INTRA-ROW ITERATION =========================
|
||||
|
||||
// A table row is directly iterable & addressable.
|
||||
typedef struct table_row_t {
|
||||
byte *pValue;
|
||||
byte *pEnd;
|
||||
} table_row_t;
|
||||
|
||||
inline bool at_end(const table_row_t &it)
|
||||
{
|
||||
return it.pValue == it.pEnd;
|
||||
}
|
||||
|
||||
// ========================= INTER-ROW ITERATION =========================
|
||||
typedef struct table_row_iterator_t
|
||||
{
|
||||
byte **pRowsStart;
|
||||
byte **pRowsEnd;
|
||||
uint8_t rowWidth;
|
||||
} table_row_iterator_t;
|
||||
|
||||
inline table_row_iterator_t rows_begin(const table3D *pTable)
|
||||
{
|
||||
return { pTable->values + (pTable->ySize-1),
|
||||
pTable->values - 1,
|
||||
pTable->xSize
|
||||
};
|
||||
};
|
||||
|
||||
inline bool at_end(const table_row_iterator_t &it)
|
||||
{
|
||||
return it.pRowsStart == it.pRowsEnd;
|
||||
}
|
||||
|
||||
inline table_row_t get_row(const table_row_iterator_t &it)
|
||||
{
|
||||
return { *it.pRowsStart, (*it.pRowsStart) + it.rowWidth };
|
||||
}
|
||||
|
||||
inline table_row_iterator_t& advance_row(table_row_iterator_t &it)
|
||||
{
|
||||
--it.pRowsStart;
|
||||
return it;
|
||||
}
|
|
@ -21,16 +21,19 @@ These are some utility functions and variables used through the main code
|
|||
#define BITWISE_OR 2
|
||||
#define BITWISE_XOR 3
|
||||
|
||||
uint16_t ioDelay[sizeof(configPage13.outputPin)];
|
||||
uint8_t pinIsValid = 0;
|
||||
extern uint16_t ioDelay[sizeof(configPage13.outputPin)];
|
||||
extern uint8_t pinIsValid;
|
||||
//uint8_t outputPin[sizeof(configPage13.outputPin)];
|
||||
|
||||
void setResetControlPinState();
|
||||
byte pinTranslate(byte);
|
||||
byte pinTranslateAnalog(byte);
|
||||
uint32_t calculateCRC32(byte);
|
||||
void initialiseProgrammableIO();
|
||||
void checkProgrammableIO();
|
||||
int16_t ProgrammableIOGetData(uint16_t index);
|
||||
|
||||
#define _countof(x) (sizeof(x) / sizeof (x[0]))
|
||||
#define _end_range_address(array) (array + _countof(array))
|
||||
#define _end_range_byte_address(array) (((byte*)array) + sizeof(array))
|
||||
|
||||
#endif // UTILS_H
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
#include "utilities.h"
|
||||
#include "decoders.h"
|
||||
#include "comms.h"
|
||||
#include "src/FastCRC/FastCRC.h"
|
||||
|
||||
FastCRC32 CRC32;
|
||||
uint16_t ioDelay[sizeof(configPage13.outputPin)];
|
||||
uint8_t pinIsValid = 0;
|
||||
|
||||
|
||||
//This function performs a translation between the pin list that appears in TS and the actual pin numbers
|
||||
//For the digital IO, this will simply return the same number as the rawPin value as those are mapped directly.
|
||||
|
@ -99,167 +100,6 @@ void setResetControlPinState()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Calculates and returns the CRC32 value of a given page of memory
|
||||
*/
|
||||
uint32_t calculateCRC32(byte pageNo)
|
||||
{
|
||||
uint32_t CRC32_val;
|
||||
byte raw_value;
|
||||
void* pnt_configPage;
|
||||
|
||||
//This sucks (again) for all the 3D map pages that have to have a translation performed
|
||||
switch(pageNo)
|
||||
{
|
||||
case veMapPage:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(veMapPage, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[veMapPage]; x++)
|
||||
//for(uint16_t x=1; x< 288; x++)
|
||||
{
|
||||
raw_value = getPageValue(veMapPage, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
case veSetPage:
|
||||
//Confirmed working
|
||||
pnt_configPage = &configPage2; //Create a pointer to Page 1 in memory
|
||||
CRC32_val = CRC32.crc32((byte *)pnt_configPage, sizeof(configPage2) );
|
||||
break;
|
||||
|
||||
case ignMapPage:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(ignMapPage, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[ignMapPage]; x++)
|
||||
{
|
||||
raw_value = getPageValue(ignMapPage, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
case ignSetPage:
|
||||
//Confirmed working
|
||||
pnt_configPage = &configPage4; //Create a pointer to Page 4 in memory
|
||||
CRC32_val = CRC32.crc32((byte *)pnt_configPage, sizeof(configPage4) );
|
||||
break;
|
||||
|
||||
case afrMapPage:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(afrMapPage, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[afrMapPage]; x++)
|
||||
{
|
||||
raw_value = getPageValue(afrMapPage, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
case afrSetPage:
|
||||
//Confirmed working
|
||||
pnt_configPage = &configPage6; //Create a pointer to Page 4 in memory
|
||||
CRC32_val = CRC32.crc32((byte *)pnt_configPage, sizeof(configPage6) );
|
||||
break;
|
||||
|
||||
case boostvvtPage:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(boostvvtPage, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[boostvvtPage]; x++)
|
||||
{
|
||||
raw_value = getPageValue(boostvvtPage, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
case seqFuelPage:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(seqFuelPage, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[seqFuelPage]; x++)
|
||||
{
|
||||
raw_value = getPageValue(seqFuelPage, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
case canbusPage:
|
||||
//Confirmed working
|
||||
pnt_configPage = &configPage9; //Create a pointer to Page 9 in memory
|
||||
CRC32_val = CRC32.crc32((byte *)pnt_configPage, sizeof(configPage9) );
|
||||
break;
|
||||
|
||||
case warmupPage:
|
||||
//Confirmed working
|
||||
pnt_configPage = &configPage10; //Create a pointer to Page 10 in memory
|
||||
CRC32_val = CRC32.crc32((byte *)pnt_configPage, sizeof(configPage10) );
|
||||
break;
|
||||
|
||||
case fuelMap2Page:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(fuelMap2Page, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[fuelMap2Page]; x++)
|
||||
//for(uint16_t x=1; x< 288; x++)
|
||||
{
|
||||
raw_value = getPageValue(fuelMap2Page, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
case wmiMapPage:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(wmiMapPage, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[wmiMapPage]; x++)
|
||||
{
|
||||
raw_value = getPageValue(wmiMapPage, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
case progOutsPage:
|
||||
//Confirmed working
|
||||
pnt_configPage = &configPage13; //Create a pointer to Page 10 in memory
|
||||
CRC32_val = CRC32.crc32((byte *)pnt_configPage, sizeof(configPage13) );
|
||||
break;
|
||||
|
||||
case ignMap2Page:
|
||||
//Confirmed working
|
||||
raw_value = getPageValue(ignMap2Page, 0);
|
||||
CRC32_val = CRC32.crc32(&raw_value, 1, false);
|
||||
for(uint16_t x=1; x< npage_size[ignMap2Page]; x++)
|
||||
{
|
||||
raw_value = getPageValue(ignMap2Page, x);
|
||||
CRC32_val = CRC32.crc32_upd(&raw_value, 1, false);
|
||||
}
|
||||
//Do a manual reflection of the CRC32 value
|
||||
CRC32_val = ~CRC32_val;
|
||||
break;
|
||||
|
||||
default:
|
||||
CRC32_val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return CRC32_val;
|
||||
}
|
||||
|
||||
//*********************************************************************************************************************************************************************************
|
||||
void initialiseProgrammableIO()
|
||||
|
|
Loading…
Reference in New Issue