mirror of
https://github.com/halleysfifthinc/AVCLAN-Mockingboard.git
synced 2026-08-07 01:13:18 +00:00
Refactor error handling in read/send frame
This commit is contained in:
+145
-82
@@ -542,10 +542,36 @@ uint8_t AVCLAN_readbyte(uint8_t *byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t AVCLAN_readframe() {
|
uint8_t AVCLAN_readframe() {
|
||||||
|
typedef enum : uint8_t {
|
||||||
|
STARTBIT_TIMEOUT = 0x01,
|
||||||
|
STARTBIT_LENGTH,
|
||||||
|
BAD_CONTROLLER_PARITY,
|
||||||
|
BAD_PERIPHERAL_PARITY,
|
||||||
|
BAD_CONTROL_PARITY,
|
||||||
|
BAD_LENGTH_PARITY,
|
||||||
|
BAD_LENGTH_RANGE,
|
||||||
|
BAD_DATA_PARITY
|
||||||
|
} errno_t;
|
||||||
|
struct errtype {
|
||||||
|
errno_t errno;
|
||||||
|
union {
|
||||||
|
uint8_t val; // BAD_LENGTH_RANGE: the out-of-range length value
|
||||||
|
struct {
|
||||||
|
uint16_t read_val;
|
||||||
|
uint8_t parity; // received (bad) parity bit
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} err = {0};
|
||||||
|
|
||||||
stopEvent(); // disable timer1 interrupt
|
stopEvent(); // disable timer1 interrupt
|
||||||
|
|
||||||
uint8_t data[MAXMSGLEN];
|
uint8_t data[MAXMSGLEN] = {0};
|
||||||
AVCLAN_frame_t frame = {
|
AVCLAN_frame_t frame = {
|
||||||
|
.broadcast = BROADCAST,
|
||||||
|
.controller_addr = 0x000,
|
||||||
|
.peripheral_addr = 0x000,
|
||||||
|
.control = 0xF,
|
||||||
|
.length = 0,
|
||||||
.data = data,
|
.data = data,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -555,15 +581,14 @@ uint8_t AVCLAN_readframe() {
|
|||||||
TCB1.CNT = 0;
|
TCB1.CNT = 0;
|
||||||
while (!BUS_IS_IDLE) {
|
while (!BUS_IS_IDLE) {
|
||||||
if (TCB1.CNT > (uint16_t)AVCLAN_STARTBIT_LOGIC_0 * 1.2) {
|
if (TCB1.CNT > (uint16_t)AVCLAN_STARTBIT_LOGIC_0 * 1.2) {
|
||||||
startEvent();
|
err.errno = STARTBIT_TIMEOUT;
|
||||||
return 0;
|
goto handle_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint16_t startbitlen = TCB1.CNT;
|
uint16_t startbitlen = TCB1.CNT;
|
||||||
if (startbitlen < (uint16_t)(AVCLAN_STARTBIT_LOGIC_0 * 0.8)) {
|
if (startbitlen < (uint16_t)(AVCLAN_STARTBIT_LOGIC_0 * 0.8)) {
|
||||||
RS232_Print("ERR: 1.\n");
|
err.errno = STARTBIT_LENGTH;
|
||||||
startEvent();
|
goto handle_err;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
// Otherwise that was a start bit
|
// Otherwise that was a start bit
|
||||||
|
|
||||||
@@ -572,35 +597,23 @@ uint8_t AVCLAN_readframe() {
|
|||||||
parity = AVCLAN_readbits(&frame.controller_addr, 12);
|
parity = AVCLAN_readbits(&frame.controller_addr, 12);
|
||||||
AVCLAN_readbits(&tmp, 1);
|
AVCLAN_readbits(&tmp, 1);
|
||||||
if (parity != (tmp & 1)) {
|
if (parity != (tmp & 1)) {
|
||||||
RS232_Print("ERR: Bad controller addr. parity");
|
err.errno = BAD_CONTROLLER_PARITY;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
RS232_Print("; read 0x");
|
err.read_val = frame.controller_addr;
|
||||||
RS232_PrintHex12(frame.controller_addr);
|
err.parity = tmp & 1;
|
||||||
RS232_Print(" and calculated parity=");
|
|
||||||
RS232_PrintHex4(parity);
|
|
||||||
RS232_Print(" but got ");
|
|
||||||
RS232_PrintHex4(tmp & 1);
|
|
||||||
}
|
}
|
||||||
RS232_Print(".\n");
|
goto handle_err;
|
||||||
startEvent();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parity = AVCLAN_readbits(&frame.peripheral_addr, 12);
|
parity = AVCLAN_readbits(&frame.peripheral_addr, 12);
|
||||||
AVCLAN_readbits(&tmp, 1);
|
AVCLAN_readbits(&tmp, 1);
|
||||||
if (parity != (tmp & 1)) {
|
if (parity != (tmp & 1)) {
|
||||||
RS232_Print("Bad peripheral addr. parity");
|
err.errno = BAD_PERIPHERAL_PARITY;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
RS232_Print("; read 0x");
|
err.read_val = frame.peripheral_addr;
|
||||||
RS232_PrintHex12(frame.peripheral_addr);
|
err.parity = tmp & 1;
|
||||||
RS232_Print(" and calculated parity=");
|
|
||||||
RS232_PrintHex4(parity);
|
|
||||||
RS232_Print(" but got ");
|
|
||||||
RS232_PrintHex4(tmp & 1);
|
|
||||||
}
|
}
|
||||||
RS232_Print(".\n");
|
goto handle_err;
|
||||||
startEvent();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t shouldACK =
|
uint8_t shouldACK =
|
||||||
@@ -614,18 +627,12 @@ uint8_t AVCLAN_readframe() {
|
|||||||
parity = AVCLAN_readbits(&frame.control, 4);
|
parity = AVCLAN_readbits(&frame.control, 4);
|
||||||
AVCLAN_readbits(&tmp, 1);
|
AVCLAN_readbits(&tmp, 1);
|
||||||
if (parity != (tmp & 1)) {
|
if (parity != (tmp & 1)) {
|
||||||
RS232_Print("Bad control parity");
|
err.errno = BAD_CONTROL_PARITY;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
RS232_Print("; read 0x");
|
err.read_val = frame.control;
|
||||||
RS232_PrintHex4(frame.control);
|
err.parity = tmp & 1;
|
||||||
RS232_Print(" and calculated parity=");
|
|
||||||
RS232_PrintHex4(parity);
|
|
||||||
RS232_Print(" but got ");
|
|
||||||
RS232_PrintHex4(tmp & 1);
|
|
||||||
}
|
}
|
||||||
RS232_Print(".\n");
|
goto handle_err;
|
||||||
startEvent();
|
|
||||||
return 0;
|
|
||||||
} else if (shouldACK) {
|
} else if (shouldACK) {
|
||||||
AVCLAN_sendbit_ACK();
|
AVCLAN_sendbit_ACK();
|
||||||
} else {
|
} else {
|
||||||
@@ -635,18 +642,12 @@ uint8_t AVCLAN_readframe() {
|
|||||||
parity = AVCLAN_readbyte(&frame.length);
|
parity = AVCLAN_readbyte(&frame.length);
|
||||||
AVCLAN_readbits(&tmp, 1);
|
AVCLAN_readbits(&tmp, 1);
|
||||||
if (parity != (tmp & 1)) {
|
if (parity != (tmp & 1)) {
|
||||||
RS232_Print("Bad length parity");
|
err.errno = BAD_LENGTH_PARITY;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
RS232_Print("; read 0x");
|
err.read_val = frame.length;
|
||||||
RS232_PrintHex4(frame.length);
|
err.parity = tmp & 1;
|
||||||
RS232_Print(" and calculated parity=");
|
|
||||||
RS232_PrintHex4(parity);
|
|
||||||
RS232_Print(" but got ");
|
|
||||||
RS232_PrintHex4(tmp & 1);
|
|
||||||
}
|
}
|
||||||
RS232_Print(".\n");
|
goto handle_err;
|
||||||
startEvent();
|
|
||||||
return 0;
|
|
||||||
} else if (shouldACK) {
|
} else if (shouldACK) {
|
||||||
AVCLAN_sendbit_ACK();
|
AVCLAN_sendbit_ACK();
|
||||||
} else {
|
} else {
|
||||||
@@ -654,29 +655,21 @@ uint8_t AVCLAN_readframe() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (frame.length == 0 || frame.length > MAXMSGLEN) {
|
if (frame.length == 0 || frame.length > MAXMSGLEN) {
|
||||||
RS232_Print("Bad length; got 0x");
|
err.errno = BAD_LENGTH_RANGE;
|
||||||
RS232_PrintHex4(frame.length);
|
err.val = frame.length;
|
||||||
RS232_Print(".\n");
|
goto handle_err;
|
||||||
startEvent();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < frame.length; i++) {
|
for (uint8_t i = 0; i < frame.length; i++) {
|
||||||
parity = AVCLAN_readbyte(&frame.data[i]);
|
parity = AVCLAN_readbyte(&frame.data[i]);
|
||||||
AVCLAN_readbits(&tmp, 1);
|
AVCLAN_readbits(&tmp, 1);
|
||||||
if (parity != (tmp & 1)) {
|
if (parity != (tmp & 1)) {
|
||||||
RS232_Print("Bad data parity");
|
err.errno = BAD_DATA_PARITY;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
RS232_Print("; read 0x");
|
err.read_val = frame.data[i];
|
||||||
RS232_PrintHex4(frame.data[i]);
|
err.parity = tmp & 1;
|
||||||
RS232_Print(" and calculated parity=");
|
|
||||||
RS232_PrintHex4(parity);
|
|
||||||
RS232_Print(" but got ");
|
|
||||||
RS232_PrintHex4(tmp & 1);
|
|
||||||
}
|
}
|
||||||
RS232_Print(".\n");
|
goto handle_err;
|
||||||
startEvent();
|
|
||||||
return 0;
|
|
||||||
} else if (shouldACK) {
|
} else if (shouldACK) {
|
||||||
AVCLAN_sendbit_ACK();
|
AVCLAN_sendbit_ACK();
|
||||||
} else {
|
} else {
|
||||||
@@ -684,21 +677,73 @@ uint8_t AVCLAN_readframe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
handle_err:;
|
||||||
startEvent();
|
startEvent();
|
||||||
|
RS232_Print("ERR: ");
|
||||||
|
switch (err.errno) {
|
||||||
|
case STARTBIT_TIMEOUT: break;
|
||||||
|
case STARTBIT_LENGTH: RS232_Print("reading start bit length\n"); break;
|
||||||
|
case BAD_CONTROLLER_PARITY:
|
||||||
|
RS232_Print("reading controller addr.");
|
||||||
|
goto VERBOSE;
|
||||||
|
case BAD_PERIPHERAL_PARITY:
|
||||||
|
RS232_Print("reading peripheral addr.");
|
||||||
|
goto VERBOSE;
|
||||||
|
case BAD_CONTROL_PARITY: RS232_Print("reading control"); goto VERBOSE;
|
||||||
|
case BAD_LENGTH_PARITY: RS232_Print("reading length"); goto VERBOSE;
|
||||||
|
case BAD_LENGTH_RANGE:
|
||||||
|
RS232_Print("bad length 0x");
|
||||||
|
RS232_PrintHex4(err.val);
|
||||||
|
RS232_Print("\n");
|
||||||
|
break;
|
||||||
|
case BAD_DATA_PARITY: RS232_Print("reading data"); goto VERBOSE;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
VERBOSE:
|
||||||
|
if (verbose) {
|
||||||
|
RS232_Print("; read 0x");
|
||||||
|
RS232_PrintHex(err.read_val);
|
||||||
|
RS232_Print(" and got bad parity ");
|
||||||
|
RS232_PrintHex4(err.parity);
|
||||||
|
}
|
||||||
|
RS232_Print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (printAllFrames)
|
RS232_Print("\n");
|
||||||
|
} else {
|
||||||
|
startEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printAllFrames &&
|
||||||
|
(!err.errno ||
|
||||||
|
err.errno > STARTBIT_LENGTH)) // At least partially successful read
|
||||||
AVCLAN_printframe(&frame, printBinary);
|
AVCLAN_printframe(&frame, printBinary);
|
||||||
|
|
||||||
if (!AVCLAN_ismuted())
|
if (!!err.errno && !AVCLAN_ismuted()) // Only handle if successful
|
||||||
AVCLAN_handleframe(&frame);
|
AVCLAN_handleframe(&frame);
|
||||||
|
|
||||||
answerReq = cm_Null;
|
answerReq = cm_Null;
|
||||||
return 1;
|
|
||||||
|
return err.errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
|
uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
|
||||||
if (AVCLAN_ismuted())
|
typedef enum : uint8_t {
|
||||||
return 1;
|
MUTED = 0x01,
|
||||||
|
BUSY,
|
||||||
|
NAK_ADDRESS = 0x10,
|
||||||
|
NAK_CONTROL,
|
||||||
|
NAK_MESSAGE_LENGTH,
|
||||||
|
NAK_DATA
|
||||||
|
} errno_t;
|
||||||
|
struct errtype {
|
||||||
|
errno_t errno;
|
||||||
|
uint8_t val;
|
||||||
|
} err = {0};
|
||||||
|
|
||||||
|
if (err.errno = AVCLAN_ismuted())
|
||||||
|
goto handle_err;
|
||||||
|
|
||||||
stopEvent();
|
stopEvent();
|
||||||
|
|
||||||
@@ -715,7 +760,8 @@ uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
|
|||||||
if (!BUS_IS_IDLE) {
|
if (!BUS_IS_IDLE) {
|
||||||
// Some other device started sending
|
// Some other device started sending
|
||||||
// Can't yet simultaneously send and recieve to do proper CSMA/CD
|
// Can't yet simultaneously send and recieve to do proper CSMA/CD
|
||||||
return 1;
|
err.errno = BUSY;
|
||||||
|
goto handle_err;
|
||||||
|
|
||||||
// Beginnings of CSMA/CD
|
// Beginnings of CSMA/CD
|
||||||
// do {
|
// do {
|
||||||
@@ -740,27 +786,24 @@ uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
|
|||||||
AVCLAN_sendbit(parity);
|
AVCLAN_sendbit(parity);
|
||||||
|
|
||||||
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
||||||
startEvent();
|
err.errno = NAK_ADDRESS;
|
||||||
RS232_Print("Error NAK: Addresses\n");
|
goto handle_err;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parity = AVCLAN_sendbits(&frame->control, 4);
|
parity = AVCLAN_sendbits(&frame->control, 4);
|
||||||
AVCLAN_sendbit(parity);
|
AVCLAN_sendbit(parity);
|
||||||
|
|
||||||
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
||||||
startEvent();
|
err.errno = NAK_CONTROL;
|
||||||
RS232_Print("Error NAK: Control\n");
|
goto handle_err;
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parity = AVCLAN_sendbyte(&frame->length); // data length
|
parity = AVCLAN_sendbyte(&frame->length); // data length
|
||||||
AVCLAN_sendbit(parity);
|
AVCLAN_sendbit(parity);
|
||||||
|
|
||||||
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
||||||
startEvent();
|
err.errno = NAK_MESSAGE_LENGTH;
|
||||||
RS232_Print("Error NAK: Message length\n");
|
goto handle_err;
|
||||||
return 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < frame->length; i++) {
|
for (uint8_t i = 0; i < frame->length; i++) {
|
||||||
@@ -770,23 +813,43 @@ uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
|
|||||||
// necessary (i.e. This deviates from the previous broadcast specific
|
// necessary (i.e. This deviates from the previous broadcast specific
|
||||||
// function that sent an extra `1` bit after each byte/parity)
|
// function that sent an extra `1` bit after each byte/parity)
|
||||||
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
if (frame->broadcast && !AVCLAN_readbit_ACK()) {
|
||||||
startEvent();
|
err.errno = NAK_DATA;
|
||||||
RS232_Print("Error NAK (Data: ");
|
err.val = i;
|
||||||
RS232_PrintHex8(i);
|
goto handle_err;
|
||||||
RS232_Print(")\n");
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
// AVCLAN_sendbit_1();
|
// AVCLAN_sendbit_1();
|
||||||
}
|
}
|
||||||
|
|
||||||
// back to read mode
|
// back to read mode
|
||||||
|
if (0) {
|
||||||
|
handle_err:;
|
||||||
startEvent();
|
startEvent();
|
||||||
|
RS232_Print("Error");
|
||||||
|
switch (err.errno) {
|
||||||
|
case MUTED: break;
|
||||||
|
case BUSY: RS232_Print(": Busy bus\n"); break;
|
||||||
|
default:
|
||||||
|
RS232_Print("NAK: ");
|
||||||
|
switch (err.errno) {
|
||||||
|
case NAK_CONTROL: RS232_Print("Control\n"); break;
|
||||||
|
case NAK_MESSAGE_LENGTH: RS232_Print("Message length\n"); break;
|
||||||
|
case NAK_DATA:
|
||||||
|
RS232_Print(" data[");
|
||||||
|
RS232_PrintDec(err.val);
|
||||||
|
RS232_Print("]\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startEvent();
|
||||||
|
}
|
||||||
|
|
||||||
if (printAllFrames)
|
if (printAllFrames)
|
||||||
AVCLAN_printframe(frame, printBinary);
|
AVCLAN_printframe(frame, printBinary);
|
||||||
|
|
||||||
return 0;
|
return err.errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AVCLAN_frame_t *frameQueue[4];
|
const AVCLAN_frame_t *frameQueue[4];
|
||||||
|
|||||||
@@ -101,6 +101,19 @@ void RS232_PrintHex12(uint16_t x) {
|
|||||||
RS232_PrintHex8(*(((uint8_t *)&x) + 0));
|
RS232_PrintHex8(*(((uint8_t *)&x) + 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RS232_PrintHex(uint16_t x) {
|
||||||
|
if (x > 0x0fff) {
|
||||||
|
RS232_PrintHex8(*(((uint8_t *)&x) + 1));
|
||||||
|
} else if (x > 0xff) {
|
||||||
|
RS232_PrintHex4(*(((uint8_t *)&x) + 1));
|
||||||
|
}
|
||||||
|
if (x > 0x0f) {
|
||||||
|
RS232_PrintHex8(*(((uint8_t *)&x) + 0));
|
||||||
|
} else {
|
||||||
|
RS232_PrintHex4(*(((uint8_t *)&x) + 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RS232_PrintDec(uint8_t Data) {
|
void RS232_PrintDec(uint8_t Data) {
|
||||||
if (Data > 99) {
|
if (Data > 99) {
|
||||||
RS232_SendByte('*');
|
RS232_SendByte('*');
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ void RS232_Print(const char *pBuf);
|
|||||||
void RS232_PrintHex4(uint8_t Data);
|
void RS232_PrintHex4(uint8_t Data);
|
||||||
void RS232_PrintHex8(uint8_t Data);
|
void RS232_PrintHex8(uint8_t Data);
|
||||||
void RS232_PrintHex12(uint16_t x);
|
void RS232_PrintHex12(uint16_t x);
|
||||||
|
void RS232_PrintHex(uint16_t x);
|
||||||
void RS232_PrintDec(uint8_t Data);
|
void RS232_PrintDec(uint8_t Data);
|
||||||
void RS232_PrintDec2(uint8_t Data);
|
void RS232_PrintDec2(uint8_t Data);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user