From d0c0884c67f589113707cfe6316426d6da5dfd60 Mon Sep 17 00:00:00 2001 From: flxkrmr Date: Sat, 11 Feb 2023 20:57:36 +0100 Subject: [PATCH] Add CART abstraction. Not yet fully working --- platformio.ini | 5 -- src/Cart.cpp | 175 ++++++++++++++++++++++++++++++++++++++ src/Cart.h | 64 ++++++++++++++ src/EecIv.cpp | 203 +++++++++++++++++++++++--------------------- src/EecIv.h | 32 ++++--- src/EecIvCommon.cpp | 29 ------- src/EecIvCommon.h | 27 ------ src/EecIvReader.cpp | 2 - 8 files changed, 362 insertions(+), 175 deletions(-) create mode 100644 src/Cart.cpp create mode 100644 src/Cart.h delete mode 100644 src/EecIvCommon.cpp delete mode 100644 src/EecIvCommon.h diff --git a/platformio.ini b/platformio.ini index adc0f61..8285f48 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,8 +16,3 @@ monitor_speed = 19200 lib_deps = olikraus/U8g2@^2.34.4 mathertel/OneButton@^2.0.3 - -[env:native] -platform = native -debug_test = * -lib_deps = mathertel/OneButton@^2.0.3 diff --git a/src/Cart.cpp b/src/Cart.cpp new file mode 100644 index 0000000..092dbe8 --- /dev/null +++ b/src/Cart.cpp @@ -0,0 +1,175 @@ +#include "Cart.h" + +const uint8_t Cart::startMessage[18] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, + 0x00, 0x05 +}; + +Cart::Cart(SoftwareSerial* softwareSerial, uint8_t pin_re) { + this->softwareSerial = softwareSerial; + this->pin_re = pin_re; + pinMode(pin_re, OUTPUT); +} + +void Cart::sendStartMessage() { + digitalWrite(pin_re, RE_WRITE); + + for(uint8_t i = 0; iwrite(startMessage[i]); + delayMicroseconds(420); + } + + digitalWrite(pin_re, RE_READ); +} + +void Cart::setBaudrate(long baudrate) { + softwareSerial->begin(baudrate); + switch (baudrate) { + case 2400: + delay.word = 1420; + delay.byte = 60; + break; + case 9600: + delay.word = 426; + delay.byte = 15; + break; + } + + isSynced = false; +} + + +void Cart::loop() { + + // if in diag param slot, we don't wait for bytes + // just send the parameter and return + if (mode == DIAG_PARAM_SLOT) { + if (sentDiagnosticParameter && diagnosticParameterPointer == (frameNumber-1)*2) { + //Serial.println("Sending diag params"); + delayMicroseconds(delay.word); + digitalWrite(pin_re, RE_WRITE); + softwareSerial->write(diagnosticParameter[diagnosticParameterPointer]); + delayMicroseconds(delay.byte); + softwareSerial->write(diagnosticParameter[diagnosticParameterPointer+1]); + digitalWrite(pin_re, RE_READ); + + diagnosticParameterPointer+=2; + + if (diagnosticParameterPointer > 7) { + diagnosticParameterPointer = 0; + diagnosticParameterSend = true; + } + + } + + mode = DATA_SLOT; + return; + } + + // read next byte and check if we have a full word already + if (pushAvailableToBuffer()) { + + wordBufferPointer++; + if (wordBufferPointer < 2) { + // buffer not full, wait for next byte + return; + } + + // always look out for sync word and stop everything else if + // we find one + if (isBufferSync()) { + // look for ID slot + mode = ID_SLOT; + + // reset for next word + wordBufferPointer = 0; + resetBuffer(); + return; + } + + switch(mode) { + case WAIT_SYNC: + // do nothing as we wait for next sync; + break; + case ID_SLOT: + if (frameNumber > 15) { + frameNumber = 0; + isSynced = true; + Serial.println("Sync full"); + } + + // if the we find the wrong frame number, we start again + if (frameNumber != (wordBuffer[1] & 0xF)) { + frameNumber = 0; + mode = WAIT_SYNC; + Serial.println("Found id slot with invalid frame number"); + break; + } + // increase the frameNumber here. + // like this we can be sure that we don't miss a frame. + // downside is, that we always have to subtract one to check the frameNumber afterwards... + frameNumber++; + + // for now don't care about the rest of the id slot + + if (frameNumber-1 < 4) { + mode = DIAG_PARAM_SLOT; + } else { + mode = STATUS_SLOT; + } + break; + case DIAG_PARAM_SLOT: + // this cannot be reached, as we don't care about word + // reading in this mode + break; + case STATUS_SLOT: + if (frameNumber-1 == 4) { + currentDiagnosticMode = wordBuffer[0]; + } + mode = DATA_SLOT; + break; + case DATA_SLOT: + // only read one word and wait for next frame + //onReadDataMessage(wordBuffer[0], wordBuffer[1]); + mode = WAIT_SYNC; + break; + } + + // reset for next word + wordBufferPointer = 0; + resetBuffer(); + } + +} + +void Cart::setDiagnosticParameter(const uint8_t diagnosticParameter[]) { + memcpy(this->diagnosticParameter, diagnosticParameter, 8); + sentDiagnosticParameter = true; + diagnosticParameterSend = false; +} + +bool Cart::isBufferSync() { + return !(wordBuffer[0] | wordBuffer[1]); +} + +uint8_t Cart::pushAvailableToBuffer() { + if (softwareSerial->available()) { + pushBuffer(softwareSerial->read()); + return 1; + } else { + return 0; + } +} + +void Cart::pushBuffer(uint8_t val) { + wordBuffer[0] = wordBuffer[1]; + wordBuffer[1] = val; +} + +void Cart::resetBuffer() { + wordBuffer[0] = 0xff; + wordBuffer[1] = 0xff; +} \ No newline at end of file diff --git a/src/Cart.h b/src/Cart.h new file mode 100644 index 0000000..3037e41 --- /dev/null +++ b/src/Cart.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include + +#define RE_READ 0x0 +#define RE_WRITE 0x1 + +class Cart { + + public: + typedef void (*callback_t)(const uint8_t, const uint8_t); + + callback_t onReadDataMessage; + + void setDiagnosticParameter(const uint8_t diagnosticParameter[]); + // when false, sending diagnostic parameter is disabled + bool sentDiagnosticParameter = false; + // when true, the diagnostic parameter has been send at least one time + bool diagnosticParameterSend = false; + + uint8_t currentDiagnosticMode = 0; + + void setBaudrate(long baudrate); + void sendStartMessage(); + + void loop(); + bool isSynced = false; + + Cart(SoftwareSerial* softwareSerial, uint8_t pin_re); + + private: + + enum Mode { + WAIT_SYNC, + ID_SLOT, + DIAG_PARAM_SLOT, + STATUS_SLOT, + DATA_SLOT, + } mode = WAIT_SYNC; + + struct delay_s { + uint16_t word; // ns + uint16_t byte; // ns + } delay; + + const static uint8_t startMessage[18]; + + SoftwareSerial *softwareSerial; + uint8_t pin_re; + + void pushBuffer(uint8_t val); + uint8_t pushAvailableToBuffer(); + void resetBuffer(); + + uint8_t diagnosticParameter[8]; + uint8_t diagnosticParameterPointer = 0; + + uint8_t frameNumber = 0; + bool isBufferSync(); + + uint8_t wordBufferPointer = 0; + uint8_t wordBuffer[2]; +}; \ No newline at end of file diff --git a/src/EecIv.cpp b/src/EecIv.cpp index 2119df0..6d487ff 100644 --- a/src/EecIv.cpp +++ b/src/EecIv.cpp @@ -9,48 +9,13 @@ const uint8_t EecIv::startSig[18] = { }; EecIv::EecIv(int di, int ro, int re) { - pin_re = re; - softwareSerial = new SoftwareSerial(di, ro); + cart = new Cart(new SoftwareSerial(di, ro), re); } void EecIv::restartReading() { debugPrint("Restart reading"); - currentState = ENABLE_READING_SLOW_SYNC; // if there is already a sync signal, we start here and not send the start message -} - -void EecIv::setup() { - pinMode(pin_re,OUTPUT); -} - -void EecIv::answer(uint8_t message[], int delay) { - enableWriteMode(); - softwareSerial->write(message[0]); - delayMicroseconds(delay); - softwareSerial->write(message[1]); - enableReadMode(); -} - -void EecIv::sendStartMessage() { - softwareSerial->begin(2400); - enableWriteMode(); - - for(uint8_t i = 0; iwrite(startSig[i]); // using softwareSerial as it can be timed better! - delayMicroseconds(420); // try and error. Off delay has to be ~850 us - } -} - -void EecIv::rxMode(int baudrate) { - softwareSerial->begin(baudrate); - enableReadMode(); -} - -void EecIv::enableWriteMode() { - digitalWrite(pin_re, HIGH); -} - -void EecIv::enableReadMode() { - digitalWrite(pin_re, LOW); + currentState = SEND_START_MESSAGE; + //currentState = ENABLE_READING_SLOW_SYNC; // if there is already a sync signal, we start here and not send the start message } void EecIv::setMode(EecIv::OperationMode mode) { @@ -69,20 +34,23 @@ void EecIv::mainLoop() { currentState = IDLE; break; } - sendStartMessage(); + cart->setBaudrate(2400); + cart->sendStartMessage(); + startMessageCounter++; debugPrint("Send start message"); - currentState = ENABLE_READING_FAST_SYNC; + currentState = CHANGE_BAUD_RATE_9600; break; - case ENABLE_READING_FAST_SYNC: - rxMode(9600); + case CHANGE_BAUD_RATE_9600: + cart->setBaudrate(9600); initTimeoutTimer(); - currentState = WAIT_FAST_SYNC; - case WAIT_FAST_SYNC: - if (waitSyncLoop()) { + currentState = WAIT_FOR_SYNC_9600; + break; + case WAIT_FOR_SYNC_9600: + if (cart->isSynced) { startMessageCounter = 0; - currentState = ANSWER_FAST_SYNC; + currentState = REQUEST_BAUD_RATE_CHANGE; } else { if(exceededTimeout()) { debugPrint("Exceeded fast sync timeout"); @@ -91,15 +59,42 @@ void EecIv::mainLoop() { } break; - case ANSWER_FAST_SYNC: - if (answerFastSyncLoop()) { - currentState = ENABLE_READING_SLOW_SYNC; + case REQUEST_BAUD_RATE_CHANGE: + { + const uint8_t baudMessage[8] = { + 0x01, 0xb0, 0xff, 0x5f, 0x81, 0x74, 0x00, 0xa0 + }; + cart->setDiagnosticParameter(baudMessage); + currentState = WAIT_REQUEST_BAUD_RATE_CHANGE_DONE; + break; + } + case WAIT_REQUEST_BAUD_RATE_CHANGE_DONE: + if (cart->diagnosticParameterSend) { + currentState = CHANGE_BAUD_RATE_2400; + } + break; + case CHANGE_BAUD_RATE_2400: + cart->setBaudrate(2400); + //initTimeoutTimer(); + currentState = WAIT_FOR_SYNC_2400; + case WAIT_FOR_SYNC_2400: + if (cart->isSynced) { + currentState = REQUEST_CLEAR_DCL_ERRORS; + } + break; + case REQUEST_CLEAR_DCL_ERRORS: + { + const uint8_t clearDclMessage[8] = { + 0x01, 0xb0, 0xff, 0x5f, 0x01, 0xf4, 0x00, 0xa0 + }; + cart->setDiagnosticParameter(clearDclMessage); + break; + } + case WAIT_REQUEST_CLEAR_DCL_ERRORS: + if (cart->diagnosticParameterSend) { + currentState = IDLE; } break; - case ENABLE_READING_SLOW_SYNC: - rxMode(2400); - initTimeoutTimer(); - currentState = ANSWER_SLOW_SYNC; case ANSWER_SLOW_SYNC: if(answerSlowSyncLoop()) { loopCounter++; @@ -202,6 +197,8 @@ void EecIv::mainLoop() { break; } + + cart->loop(); } int EecIv::exceededTimeout() { @@ -215,22 +212,14 @@ void EecIv::initTimeoutTimer() { timeoutTimer = millis(); } -int EecIv::pushAvailableToBuffer() { - if (softwareSerial->available()) { - pushBuffer(softwareSerial->read()); - return 1; - } else { - return 0; - } -} - int EecIv::waitSyncLoop() { if (pushAvailableToBuffer()) { if (isBufferSync(syncPointer)) { + resetBuffer(); syncPointer++; - if (syncPointer > 3) { + if (syncPointer > 15) { syncPointer = 0; return 1; } @@ -242,14 +231,10 @@ int EecIv::waitSyncLoop() { int EecIv::waitSyncLoopShort() { - if (softwareSerial->available()) { - pushBuffer(softwareSerial->read()); - - if (isBufferSync(syncPointer)) { - return 1; - } - } + return 0; +} +int EecIv::pushAvailableToBuffer() { return 0; } @@ -264,12 +249,15 @@ int EecIv::answerFastSyncLoop() { if (pushAvailableToBuffer()) { if (isBufferSync(syncPointer)) { - delayMicroseconds(426); - answer(answerSig[syncPointer], 15); + if (syncPointer < 4) { + delayMicroseconds(426); + //answer(answerSig[syncPointer], 15); + } + resetBuffer(); syncPointer++; - if (syncPointer > 3) { + if (syncPointer > 15) { syncPointer = 0; return 1; } @@ -290,12 +278,18 @@ int EecIv::answerSlowSyncLoop() { if (pushAvailableToBuffer()) { if (isBufferSync(syncPointer)) { - delayMicroseconds(1420); - answer(answerSig[syncPointer], 60); + sprintf(printBuffer, "%02X %02X %02X %02X", buffer[0], buffer[1], buffer[2], buffer[3]); + debugPrint(printBuffer); + + if (syncPointer < 4) { + delayMicroseconds(1420); + //answer(answerSig[syncPointer], 60); + } + resetBuffer(); syncPointer++; - if (syncPointer > 3) { + if (syncPointer > 15) { syncPointer = 0; return 1; } @@ -314,12 +308,15 @@ int EecIv::answerRequestFaultCode() { if (pushAvailableToBuffer()) { if (isBufferSync(syncPointer)) { - delayMicroseconds(1420); - answer(answerSig[syncPointer], 60); + if (syncPointer < 4) { + delayMicroseconds(1420); + //answer(answerSig[syncPointer], 60); + } + resetBuffer(); syncPointer++; - if (syncPointer > 3) { + if (syncPointer > 15) { syncPointer = 0; return 1; } @@ -339,9 +336,12 @@ int EecIv::answerRequestKoeo() { if (pushAvailableToBuffer()) { if (isBufferSync(syncPointer)) { - delayMicroseconds(1420); - answer(answerSig[syncPointer], 60); + if (syncPointer < 4) { + delayMicroseconds(1420); + //answer(answerSig[syncPointer], 60); + } + resetBuffer(); syncPointer++; if (syncPointer > 3) { @@ -364,9 +364,12 @@ int EecIv::answerRequestLiveData() { if (pushAvailableToBuffer()) { if (isBufferSync(syncPointer)) { - delayMicroseconds(1420); - answer(answerSig[syncPointer], 60); + if (syncPointer < 4) { + delayMicroseconds(1420); + //answer(answerSig[syncPointer], 60); + } + resetBuffer(); syncPointer++; if (syncPointer > 3) { @@ -390,7 +393,7 @@ int EecIv::answerRequestLiveDataShort() { if (pushAvailableToBuffer()) { if (isBufferSync(syncPointer)) { delayMicroseconds(1420); - answer(answerSig[syncPointer], 60); + //answer(answerSig[syncPointer], 60); syncPointer++; @@ -408,12 +411,12 @@ int EecIv::answerRequestLiveDataShort() { int EecIv::answerRequestFaultCodeShort() { uint8_t answerSig[2] = {0x01, 0xb0 }; - if (softwareSerial->available()) { - pushBuffer(softwareSerial->read()); + if (false) { if (isBufferSync(syncPointer)) { + resetBuffer(); delayMicroseconds(1420); - answer(answerSig, 60); + //answer(answerSig, 60); syncPointer++; return 1; @@ -431,15 +434,16 @@ int EecIv::answerRequestKoeoShort() { {0x00, 0xa0 } }; - if (softwareSerial->available()) { - pushBuffer(softwareSerial->read()); + if (false) { if (isBufferSync(syncPointer)) { - delayMicroseconds(1420); - answer(answerSig[syncPointer], 60); + if (syncPointer < 4) { + delayMicroseconds(1420); + //answer(answerSig[syncPointer], 60); + } syncPointer++; - if (syncPointer > 3) { + if (syncPointer > 15) { syncPointer = 0; } return 1; @@ -469,10 +473,12 @@ int EecIv::readRequestKoeo() { } int EecIv::waitByte() { + /* if (softwareSerial->available()) { softwareSerial->read(); return 1; } + */ return 0; } @@ -496,9 +502,10 @@ int EecIv::readRequestFaultCode() { } bool EecIv::isBufferSync(uint8_t syncPointer) { - return buffer[0] == 0x00 && - buffer[1] == 0x00 && - buffer[2] == 0x00 && + return buffer[0] == 0x00 && + buffer[1] == 0x00 && // first two are always 0x00 + //buffer[2] == 0x00 && // this is 0x25 or 0x26 when engine is running, othewise 0x00... + //(buffer[3] & 0xF0) != 0x00 && // chek for != 0 for snycPointer == 0 (buffer[3] & 0x0F) == syncPointer; } @@ -508,3 +515,9 @@ void EecIv::pushBuffer(uint8_t val) { } buffer[sizeof(buffer)-1] = val; } + +void EecIv::resetBuffer() { + for (uint8_t i = 0; i < sizeof(buffer)-1; i++) { + buffer[i] = 0xFF; + } +} diff --git a/src/EecIv.h b/src/EecIv.h index bbc035c..e3d1c7c 100644 --- a/src/EecIv.h +++ b/src/EecIv.h @@ -1,8 +1,9 @@ #ifndef EEC_IV_H #define EEC_IV_H -#include "arduino.h" +#include #include +#include "Cart.h" class EecIv { @@ -24,7 +25,6 @@ class EecIv { EecIv(int di, int ro, int re); - void setup(); void setMode(EecIv::OperationMode mode); void restartReading(); @@ -32,12 +32,21 @@ class EecIv { private: + Cart* cart; + enum State { IDLE, SEND_START_MESSAGE, - ENABLE_READING_FAST_SYNC, - WAIT_FAST_SYNC, - ANSWER_FAST_SYNC, + CHANGE_BAUD_RATE_9600, + WAIT_FOR_SYNC_9600, + + REQUEST_BAUD_RATE_CHANGE, + WAIT_REQUEST_BAUD_RATE_CHANGE_DONE, + CHANGE_BAUD_RATE_2400, + WAIT_FOR_SYNC_2400, + + REQUEST_CLEAR_DCL_ERRORS, + WAIT_REQUEST_CLEAR_DCL_ERRORS, ENABLE_READING_SLOW_SYNC, ANSWER_SLOW_SYNC, @@ -56,8 +65,6 @@ class EecIv { ANSWER_REQUEST_LIVE_DATA_INIT_SHIT } currentState = IDLE; - uint8_t pin_re; - uint8_t syncPointer = 0; uint8_t errorCodePointer = 0; uint8_t loopCounter = 0; @@ -67,7 +74,6 @@ class EecIv { uint8_t startMessageCounter = 0; const uint8_t startMessageCounterMax = 5; - void sendStartMessage(); int waitSyncLoop(); int waitSyncLoopShort(); @@ -89,25 +95,17 @@ class EecIv { int exceededTimeout(); void initTimeoutTimer(); - void answer(uint8_t message[], int delay); - - - void rxMode(int baudrate); - void enableWriteMode(); - void enableReadMode(); - unsigned char errorCodeBuffer[2]; char printBuffer[90]; uint8_t buffer[4]; + void resetBuffer(); void pushBuffer(uint8_t val); int pushAvailableToBuffer(); bool isBufferSync(uint8_t syncPointer); const static uint8_t startSig[18]; - - SoftwareSerial *softwareSerial; }; #endif /* EEC_IV_H */ diff --git a/src/EecIvCommon.cpp b/src/EecIvCommon.cpp deleted file mode 100644 index 2080060..0000000 --- a/src/EecIvCommon.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "EecIvCommon.h" - -const unsigned char EecIvCommon::syncSig[4][4] = { - {0x00, 0x00, 0x00, 0xa0 }, - {0x00, 0x00, 0x00, 0xb1 }, - {0x00, 0x00, 0x00, 0x82 }, - {0x00, 0x00, 0x00, 0x93 } -}; - -void EecIvCommon::answer(unsigned char message[], int delay) { - enableWriteMode(); - softwareSerial->write(message[0]); - delayMicroseconds(delay); - softwareSerial->write(message[1]); - enableReadMode(); -} - -void EecIvCommon::rxMode(int baudrate) { - softwareSerial->begin(baudrate); - enableReadMode(); -} - -void EecIvCommon::enableWriteMode() { - digitalWrite(pin_re, HIGH); -} - -void EecIvCommon::enableReadMode() { - digitalWrite(pin_re, LOW); -} diff --git a/src/EecIvCommon.h b/src/EecIvCommon.h deleted file mode 100644 index 6649eda..0000000 --- a/src/EecIvCommon.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef EEC_IV_COMMON_H -#define EEC_IV_COMMON_H - -#include "arduino.h" -#include - -class EecIvCommon { - public: - typedef void (*callback_t)(char []); - - protected: - void answer(unsigned char message[], int delay); - - void rxMode(int baudrate); - void enableWriteMode(); - void enableReadMode(); - void doNothing(char []); - - - int pin_re; - SoftwareSerial *softwareSerial; - - const static unsigned char syncSig[4][4]; -}; - - -#endif /* EEC_IV_COMMON_H */ \ No newline at end of file diff --git a/src/EecIvReader.cpp b/src/EecIvReader.cpp index edef10b..a0ea8b2 100644 --- a/src/EecIvReader.cpp +++ b/src/EecIvReader.cpp @@ -110,8 +110,6 @@ void setup() { eecIv.onKoeoFinished = &onKoeoFinished; eecIv.onStartMessageTimeout = &onStartMessageTimeout; - eecIv.setup(); - voltageReader.onVoltage = &drawVoltageScreen; drawWelcomeScreen();