1
0
mirror of https://github.com/halleysfifthinc/Toyota-AVC-LAN synced 2025-06-07 16:06:12 +00:00

Implement bit-read timing with TCB0 pulse-width measurement

This commit is contained in:
Allen Hill 2023-09-03 21:22:26 -04:00
parent d6d1995ae4
commit 09bcd75811

View File

@ -85,6 +85,7 @@
-------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------
*/ */
#include <avr/interrupt.h>
#include <avr/io.h> #include <avr/io.h>
#include <avr/sfr_defs.h> #include <avr/sfr_defs.h>
#include <stdint.h> #include <stdint.h>
@ -256,6 +257,16 @@ void AVCLAN_init() {
PORTB.DIRSET = PIN2_bm; // Enable AC2 OUT for LED PORTB.DIRSET = PIN2_bm; // Enable AC2 OUT for LED
PORTB.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc; // Output only PORTB.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc; // Output only
// Set AC2 to generate events on async channel 0
EVSYS.ASYNCCH0 = EVSYS_ASYNCCH0_AC2_OUT_gc;
EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH0_gc; // USER0 is TCB0
// TCB0 for read bit timing
TCB0.CTRLB = TCB_CNTMODE_PW_gc;
TCB0.INTCTRL = TCB_CAPT_bm;
TCB0.EVCTRL = TCB_CAPTEI_bm;
TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm;
// TCB1 for send bit timing // TCB1 for send bit timing
TCB1.CTRLB = TCB_CNTMODE_INT_gc; TCB1.CTRLB = TCB_CNTMODE_INT_gc;
TCB1.CCMP = 0xFFFF; TCB1.CCMP = 0xFFFF;
@ -330,8 +341,8 @@ void AVCLAN_sendbit_parity(uint8_t parity) {
uint8_t *: AVCLAN_sendbitsi)(bits, len) uint8_t *: AVCLAN_sendbitsi)(bits, len)
// Send `len` bits on the AVCLAN bus; returns the even parity // Send `len` bits on the AVCLAN bus; returns the even parity
uint8_t AVCLAN_sendbitsi(const uint8_t *byte, int8_t len) { uint8_t AVCLAN_sendbitsi(const uint8_t *bits, int8_t len) {
uint8_t b = *byte; uint8_t b = *bits;
uint8_t parity = 0; uint8_t parity = 0;
int8_t len_mod8 = 8; int8_t len_mod8 = 8;
@ -352,14 +363,14 @@ uint8_t AVCLAN_sendbitsi(const uint8_t *byte, int8_t len) {
b <<= 1; b <<= 1;
} }
len_mod8 = 8; len_mod8 = 8;
b = *--byte; b = *--bits;
} }
return (parity & 1); return (parity & 1);
} }
// Send `len` bits on the AVCLAN bus; returns the even parity // Send `len` bits on the AVCLAN bus; returns the even parity
uint8_t AVCLAN_sendbitsl(const uint16_t *word, int8_t len) { uint8_t AVCLAN_sendbitsl(const uint16_t *bits, int8_t len) {
return AVCLAN_sendbitsi((const uint8_t *)word + 1, len); return AVCLAN_sendbitsi((const uint8_t *)bits + 1, len);
} }
uint8_t AVCLAN_sendbyte(const uint8_t *byte) { uint8_t AVCLAN_sendbyte(const uint8_t *byte) {
@ -378,22 +389,73 @@ uint8_t AVCLAN_sendbyte(const uint8_t *byte) {
return (parity & 1); return (parity & 1);
} }
uint8_t AVCLAN_readbyte(uint8_t length, uint8_t *parity) { #define READING_BYTE GPIOR1
uint8_t byte = 0; #define READING_NBITS GPIOR2
#define READING_PARITY GPIOR3
while (1) { ISR(TCB0_INT_vect) {
while (INPUT_IS_CLEAR) {}; // If input was set for less than 26 us (a generous half period), bit was a 1
TCB1.CNT = 0; if (TCB0.CCMP < 208) {
while (INPUT_IS_SET) {}; // If input was set for less than 26 us READING_BYTE++;
if (TCB1.CNT < 208) { // (a generous half period), bit was a 1 READING_PARITY++;
byte++;
(*parity)++;
}
length--;
if (!length)
return byte;
byte = byte << 1;
} }
READING_BYTE <<= 1;
READING_NBITS--;
}
#define AVCLAN_readbits(bits, len) \
_Generic((bits), \
const uint16_t *: AVCLAN_readbitsl, \
uint16_t *: AVCLAN_readbitsl, \
const uint8_t *: AVCLAN_readbitsi, \
uint8_t *: AVCLAN_readbitsi)(bits, len)
// Send `len` bits on the AVCLAN bus; returns the even parity
uint8_t AVCLAN_readbitsi(uint8_t *bits, uint8_t len) {
cli();
READING_BYTE = 0;
READING_PARITY = 0;
READING_NBITS = len;
sei();
while (READING_NBITS != 0) {};
cli();
*bits = READING_BYTE;
uint8_t parity = READING_PARITY;
sei();
return (parity & 1);
}
// Send `len` bits on the AVCLAN bus; returns the even parity
uint8_t AVCLAN_readbitsl(uint16_t *bits, int8_t len) {
uint8_t parity = 0;
if (len > 8) {
uint8_t over = len - 8;
parity = AVCLAN_readbitsi((uint8_t *)bits + 0, over);
len -= over;
}
parity += AVCLAN_readbitsi((uint8_t *)bits + 1, len);
return (parity & 1);
}
// Read a byte on the AVCLAN bus
uint8_t AVCLAN_readbyte(uint8_t *byte) {
cli();
READING_BYTE = 0;
READING_NBITS = 8;
sei();
while (READING_NBITS != 0) {};
cli();
*byte = READING_BYTE;
uint8_t parity = READING_PARITY;
sei();
return (parity & 1);
} }
uint8_t AVCLAN_readbit_ACK() { uint8_t AVCLAN_readbit_ACK() {
@ -455,27 +517,21 @@ uint8_t AVCLAN_readframe() {
// return 0; // return 0;
// } // }
uint8_t parity = 0; uint8_t parity = 0;
uint8_t parity_check = 0; uint8_t tmp = 0;
AVCLAN_readbyte(1, &parity); // Start bit AVCLAN_readbits(&tmp, 1); // Start bit
frame.broadcast = AVCLAN_readbyte(1, &parity); AVCLAN_readbits((uint8_t *)&frame.broadcast, 1);
parity = 0; parity = AVCLAN_readbits(&frame.controller_addr, 12);
uint8_t *controller_hi = ((uint8_t *)&frame.controller_addr) + 1; AVCLAN_readbits(&tmp, 1);
uint8_t *controller_lo = ((uint8_t *)&frame.controller_addr) + 0; if (parity != tmp) {
*controller_hi = AVCLAN_readbyte(4, &parity);
*controller_lo = AVCLAN_readbyte(8, &parity);
if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) {
STARTEvent; STARTEvent;
return 0; return 0;
} }
parity = 0; parity = AVCLAN_readbits(&frame.peripheral_addr, 12);
uint8_t *peripheral_hi = ((uint8_t *)&frame.peripheral_addr) + 1; AVCLAN_readbits(&tmp, 1);
uint8_t *peripheral_lo = ((uint8_t *)&frame.peripheral_addr) + 0; if (parity != tmp) {
*peripheral_hi = AVCLAN_readbyte(4, &parity);
*peripheral_lo = AVCLAN_readbyte(8, &parity);
if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) {
STARTEvent; STARTEvent;
return 0; return 0;
} }
@ -486,28 +542,28 @@ uint8_t AVCLAN_readframe() {
if (for_me) if (for_me)
AVCLAN_sendbit_ACK(); AVCLAN_sendbit_ACK();
else else
AVCLAN_readbyte(1, &parity); AVCLAN_readbits(&tmp, 1);
parity = 0; parity = AVCLAN_readbits(&frame.control, 4);
frame.control = AVCLAN_readbyte(4, &parity); AVCLAN_readbits(&tmp, 1);
if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { if (parity != tmp) {
STARTEvent; STARTEvent;
return 0; return 0;
} else if (for_me) { } else if (for_me) {
AVCLAN_sendbit_ACK(); AVCLAN_sendbit_ACK();
} else { } else {
AVCLAN_readbyte(1, &parity); AVCLAN_readbits(&tmp, 1);
} }
parity = 0; parity = AVCLAN_readbyte(&frame.length);
frame.length = AVCLAN_readbyte(8, &parity); AVCLAN_readbits(&tmp, 1);
if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { if (parity != tmp) {
STARTEvent; STARTEvent;
return 0; return 0;
} else if (for_me) { } else if (for_me) {
AVCLAN_sendbit_ACK(); AVCLAN_sendbit_ACK();
} else { } else {
AVCLAN_readbyte(1, &parity); AVCLAN_readbits(&tmp, 1);
} }
if (frame.length > MAXMSGLEN) { if (frame.length > MAXMSGLEN) {
@ -517,15 +573,15 @@ uint8_t AVCLAN_readframe() {
} }
for (i = 0; i < frame.length; i++) { for (i = 0; i < frame.length; i++) {
parity = 0; parity = AVCLAN_readbyte(&frame.data[i]);
frame.data[i] = AVCLAN_readbyte(8, &parity); AVCLAN_readbits(&tmp, 1);
if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { if (parity != tmp) {
STARTEvent; STARTEvent;
return 0; return 0;
} else if (for_me) { } else if (for_me) {
AVCLAN_sendbit_ACK(); AVCLAN_sendbit_ACK();
} else { } else {
AVCLAN_readbyte(1, &parity); AVCLAN_readbits(&tmp, 1);
} }
} }