Skip to content

Commit

Permalink
Add CART abstraction. Not yet fully working
Browse files Browse the repository at this point in the history
  • Loading branch information
flxkrmr committed Feb 11, 2023
1 parent 9c37a02 commit d0c0884
Show file tree
Hide file tree
Showing 8 changed files with 362 additions and 175 deletions.
5 changes: 0 additions & 5 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
175 changes: 175 additions & 0 deletions src/Cart.cpp
Original file line number Diff line number Diff line change
@@ -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; i<sizeof(startMessage); i++) {
softwareSerial->write(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;
}
64 changes: 64 additions & 0 deletions src/Cart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once

#include <Arduino.h>
#include <SoftwareSerial.h>

#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];
};
Loading

0 comments on commit d0c0884

Please sign in to comment.