diff --git a/CMakeLists.txt b/CMakeLists.txt index 9eb037a..ad20784 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,22 +33,25 @@ set(AVCLAN_TARGET avr-attiny3216 CACHE STRING "Hardware target (port) to build") add_library(avclan STATIC src/avclan/avclan_frame.c src/avclan/avclan_protocol.c - src/avclan/cdchanger.c) + src/avclan/cdchanger.c + src/avclan/peripheral.cc +) -add_executable(mockingboard - src/sniffer.cc - src/com232.c) - # avclan exports its public generic headers (src/avclan) to consumers and # reaches into src/ for sibling headers (com232.h, board.h) during its own # build. The selected target adds its own per-target include path. -target_include_directories(avclan - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/avclan - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - -target_link_libraries(mockingboard avclan) +target_include_directories(avclan PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/avclan + ${CMAKE_CURRENT_SOURCE_DIR}/src) # Pull in the selected hardware target: its port sources, per-target headers, # hardware-specific compile options/definitions, device-pack handling, and the # flashing target. Added after the targets above so it can extend them. add_subdirectory(src/avclan/target/${AVCLAN_TARGET}) + +add_executable(mockingboard + src/sniffer.cc + src/com232.c +) + +target_link_libraries(mockingboard avclan) diff --git a/src/avclan/avclan_defs.h b/src/avclan/avclan_defs.h index 71c7803..778e531 100644 --- a/src/avclan/avclan_defs.h +++ b/src/avclan/avclan_defs.h @@ -137,7 +137,7 @@ typedef enum avclan_bit : uint8_t { // progress/success before an error occured, with 0 being no errors typedef enum : uint8_t { rNO_ERROR = 0x00, - rBAD_DATA_PARITY, + rBAD_DATA_PARITY = 0x01, rBAD_LENGTH_RANGE, rBAD_LENGTH_PARITY, rBAD_PERIPHERAL_PARITY, @@ -150,7 +150,7 @@ typedef enum : uint8_t { typedef enum : uint8_t { sNO_ERROR = 0x00, - sNAK_DATA, + sNAK_DATA = 0x01, sNAK_MESSAGE_LENGTH, sNAK_CONTROL, sNAK_ADDRESS, diff --git a/src/avclan/avclan_frame.c b/src/avclan/avclan_frame.c index 03feb3a..c3830b3 100644 --- a/src/avclan/avclan_frame.c +++ b/src/avclan/avclan_frame.c @@ -10,262 +10,6 @@ #include "avclan_phy.h" // bus symbol I/O + transaction guard (target-provided) #include "com232.h" // error logging -avclan_readerr_t AVCLAN_readframe(AVCLAN_frame_t *frame, log_t print) { - struct errtype { - avclan_readerr_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}; - - AVCLAN_stopEvent(); // quiesce contending sources during the read - - uint8_t tmp = 0; - - err.errno = AVCLAN_readstartbit(); - if (err.errno) - goto handle_err; - - AVCLAN_readbits(&tmp, 1); - frame->is_unicast = tmp; - - uint8_t parity = AVCLAN_readbits(&frame->controller_addr, 12); - AVCLAN_readbits(&tmp, 1); - if (parity != (tmp &= 1)) { - err.errno = rBAD_CONTROLLER_PARITY; - if (print.verbose) { - err.read_val = frame->controller_addr; - err.parity = tmp; - } - goto handle_err; - } - - parity = AVCLAN_readbits(&frame->peripheral_addr, 12); - AVCLAN_readbits(&tmp, 1); - if (parity != (tmp &= 1)) { - err.errno = rBAD_PERIPHERAL_PARITY; - if (print.verbose) { - err.read_val = frame->peripheral_addr; - err.parity = tmp; - } - goto handle_err; - } - - bool shouldACK = !AVCLAN_ismuted() && (frame->peripheral_addr == DEVICE_ADDR); - - if (shouldACK) - AVCLAN_sendbit_ACK(); - else - AVCLAN_readbits(&tmp, 1); - - parity = AVCLAN_readbits(&frame->control, 4); - AVCLAN_readbits(&tmp, 1); - if (parity != (tmp &= 1)) { - err.errno = rBAD_CONTROL_PARITY; - if (print.verbose) { - err.read_val = frame->control; - err.parity = tmp; - } - goto handle_err; - } else if (shouldACK) { - AVCLAN_sendbit_ACK(); - } else { - AVCLAN_readbits(&tmp, 1); - } - - parity = AVCLAN_readbyte(&frame->length); - AVCLAN_readbits(&tmp, 1); - if (parity != (tmp &= 1)) { - err.errno = rBAD_LENGTH_PARITY; - if (print.verbose) { - err.read_val = frame->length; - err.parity = tmp; - } - goto handle_err; - } else if (shouldACK) { - AVCLAN_sendbit_ACK(); - } else { - AVCLAN_readbits(&tmp, 1); - } - - if (frame->length == 0 || frame->length > MAXMSGLEN) { - err.errno = rBAD_LENGTH_RANGE; - err.val = frame->length; - goto handle_err; - } - - for (uint8_t i = 0; i < frame->length; i++) { - parity = AVCLAN_readbyte(&frame->data[i]); - AVCLAN_readbits(&tmp, 1); - if (parity != (tmp &= 1)) { - err.errno = rBAD_DATA_PARITY; - if (print.verbose) { - err.read_val = frame->data[i]; - err.parity = tmp; - } - goto handle_err; - } else if (shouldACK) { - AVCLAN_sendbit_ACK(); - } else { - AVCLAN_readbits(&tmp, 1); - } - } - - if (false) { - handle_err:; - AVCLAN_startEvent(); - RS232_Print("ERR(read): "); - switch (err.errno) { - case rLATCHED_COMPARATOR: RS232_Print("latched comparator"); break; - case rSTARTBIT_TOO_SHORT: RS232_Print("start bit too short"); break; - case rSTARTBIT_TOO_LONG: RS232_Print("start bit too long"); break; - case rBAD_CONTROLLER_PARITY: - RS232_Print("reading controller addr."); - goto VERBOSE; - case rBAD_PERIPHERAL_PARITY: - RS232_Print("reading peripheral addr."); - goto VERBOSE; - case rBAD_CONTROL_PARITY: RS232_Print("reading control"); goto VERBOSE; - case rBAD_LENGTH_PARITY: RS232_Print("reading length"); goto VERBOSE; - case rBAD_LENGTH_RANGE: - RS232_Print("bad length 0x"); - RS232_PrintHex4(err.val); - break; - case rBAD_DATA_PARITY: RS232_Print("reading data"); goto VERBOSE; - case rNO_ERROR: - __builtin_unreachable(); - VERBOSE: - if (print.verbose) { - RS232_Print("; read 0x"); - RS232_PrintHex(err.read_val); - RS232_Print(" and got bad parity "); - RS232_PrintHex4(err.parity); - } - } - RS232_Print("\n"); - } else { - AVCLAN_startEvent(); - } - - // Only print if some data has been correctly received - if (print.print && (err.errno < rSTARTBIT_TOO_SHORT)) { - if (err.errno > rBAD_DATA_PARITY) - frame->length = 0; - AVCLAN_printframe(frame, print.binary); - } - - return err.errno; -} - -avclan_senderr_t AVCLAN_sendframe(const AVCLAN_frame_t *frame, log_t print) { - struct errtype { - // Error enum is ordered such that a lower numeric value corresponds to more - // success - avclan_senderr_t errno; - uint8_t val; - } err = {0}; - - if (AVCLAN_ismuted()) { - err.errno = sMUTED; - goto handle_err; - } - - AVCLAN_stopEvent(); - - if (!AVCLAN_sendstartbit()) { - // Some other device is already driving the bus - err.errno = sBUSY; - goto handle_err; - } - - AVCLAN_sendbits(&(uint8_t){frame->is_unicast}, 1); - - avclan_bit_t parity = AVCLAN_sendbits(&frame->controller_addr, 12); - AVCLAN_sendbit(parity); - - parity = AVCLAN_sendbits(&frame->peripheral_addr, 12); - AVCLAN_sendbit(parity); - - if (frame->is_unicast && !AVCLAN_readbit_ACK()) { - err.errno = sNAK_ADDRESS; - goto handle_err; - } - - parity = AVCLAN_sendbits(&frame->control, 4); - AVCLAN_sendbit(parity); - - if (frame->is_unicast && !AVCLAN_readbit_ACK()) { - err.errno = sNAK_CONTROL; - goto handle_err; - } - - parity = AVCLAN_sendbyte(&frame->length); // data length - AVCLAN_sendbit(parity); - - if (frame->is_unicast && !AVCLAN_readbit_ACK()) { - err.errno = sNAK_MESSAGE_LENGTH; - goto handle_err; - } - - for (uint8_t i = 0; i < frame->length; i++) { - parity = AVCLAN_sendbyte(&frame->data[i]); - AVCLAN_sendbit(parity); - // Based on the µPD6708 datasheet, ACK bit for broadcast doesn't seem - // necessary (i.e. This deviates from the previous broadcast specific - // function that sent an extra `1` bit after each byte/parity) - if (frame->is_unicast && !AVCLAN_readbit_ACK()) { - err.errno = sNAK_DATA; - err.val = i; - goto handle_err; - } - // else - // AVCLAN_sendbit_1(); - } - - // back to read mode - if (false) { - handle_err:; - AVCLAN_startEvent(); - RS232_Print("Error"); - switch (err.errno) { - case sMUTED: RS232_Print(": Device muted"); break; - case sBUSY: RS232_Print(": Busy bus"); break; - case sNAK_ADDRESS: - case sNAK_CONTROL: - case sNAK_MESSAGE_LENGTH: - case sNAK_DATA: - RS232_Print(" NAK: "); - switch (err.errno) { - case sNAK_ADDRESS: RS232_Print("address"); break; - case sNAK_CONTROL: RS232_Print("Control"); break; - case sNAK_MESSAGE_LENGTH: RS232_Print("Message length"); break; - case sNAK_DATA: - RS232_Print(" data["); - RS232_PrintDec(err.val); - RS232_Print("]"); - break; - case sNO_ERROR: - case sMUTED: - case sBUSY: __builtin_unreachable(); - } - break; - case sNO_ERROR: __builtin_unreachable(); - } - RS232_Print("\n"); - } else { - AVCLAN_startEvent(); - } - - if (print.print) - AVCLAN_printframe(frame, print.binary); - - return err.errno; -} - void AVCLAN_printframe(const AVCLAN_frame_t *frame, bool binary) { if (binary) { uint8_t buffer[8]; diff --git a/src/avclan/avclan_frame.h b/src/avclan/avclan_frame.h index 708ce08..f62ce77 100644 --- a/src/avclan/avclan_frame.h +++ b/src/avclan/avclan_frame.h @@ -39,8 +39,6 @@ extern "C" { #endif -avclan_readerr_t AVCLAN_readframe(AVCLAN_frame_t *frame, log_t print); -avclan_senderr_t AVCLAN_sendframe(const AVCLAN_frame_t *frame, log_t print); void AVCLAN_printframe(const AVCLAN_frame_t *frame, bool binary); uint8_t AVCLAN_parseframe(const uint8_t *bytes, uint8_t len, AVCLAN_frame_t *frame); diff --git a/src/avclan/avclan_phy.h b/src/avclan/avclan_phy.h index 7864b9c..eccefcc 100644 --- a/src/avclan/avclan_phy.h +++ b/src/avclan/avclan_phy.h @@ -53,20 +53,6 @@ uint8_t AVCLAN_readbitsi(uint8_t *bits, uint8_t len); uint8_t AVCLAN_readbitsl(uint16_t *bits, int8_t len); uint8_t AVCLAN_readbyte(uint8_t *byte); -#define AVCLAN_sendbits(bits, len) \ - _Generic((bits), \ - const uint16_t *: AVCLAN_sendbitsl, \ - uint16_t *: AVCLAN_sendbitsl, \ - const uint8_t *: AVCLAN_sendbitsi, \ - uint8_t *: AVCLAN_sendbitsi)(bits, len) - -#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) - #ifndef NDEBUG // Sample and dump bus bit timing over the serial link (REPL `M`). void AVCLan_Measure(void); @@ -75,3 +61,38 @@ void AVCLan_Measure(void); #ifdef __cplusplus } #endif + +#ifdef __cplusplus +template avclan_bit_t AVCLAN_sendbits(T bits); +template avclan_bit_t AVCLAN_readbits(T *bits); + +// Temporary specializations bridging to legacy C API +// Replace with proper (single?) template when phy has been ported +template + requires(N <= 8) +avclan_bit_t AVCLAN_sendbits(uint8_t bits) { + return AVCLAN_sendbitsi(&bits, N); +} +template + requires(N <= 16) +avclan_bit_t AVCLAN_sendbits(uint16_t bits) { + return AVCLAN_sendbitsl(&bits, N); +} +template <> inline avclan_bit_t AVCLAN_sendbits<8>(uint8_t byte) { + return AVCLAN_sendbyte(&byte); +} + +template + requires(N <= 8) +avclan_bit_t AVCLAN_readbits(uint8_t *bits) { + return static_cast(AVCLAN_readbitsi(bits, N)); +} +template + requires(N <= 16) +avclan_bit_t AVCLAN_readbits(uint16_t *bits) { + return static_cast(AVCLAN_readbitsl(bits, N)); +} +template <> inline avclan_bit_t AVCLAN_readbits<8>(uint8_t *byte) { + return static_cast(AVCLAN_readbyte(byte)); +} +#endif diff --git a/src/avclan/peripheral.cc b/src/avclan/peripheral.cc new file mode 100644 index 0000000..8e3b66d --- /dev/null +++ b/src/avclan/peripheral.cc @@ -0,0 +1,278 @@ +// copyright (C) 2006 Marcin Slonicki +// copyright (C) 2007 Louis Frigon +// Copyright (C) 2015 Allen Hill +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "peripheral.hpp" +#include "avclan_defs.h" +#include "avclan_frame.h" +#include "avclan_phy.h" // bus symbol I/O + transaction guard (target-provided) +#include "com232.h" // error logging + +#include + +namespace avclan { + +Peripheral::Error::Read Peripheral::read(AVCLAN_frame_t *in, log_t print) { + struct errtype { + Error::Read errno; + union { + uint8_t val; // BAD_LENGTH_RANGE: the out-of-range length value + struct { + uint8_t parity; // received (bad) parity bit + uint16_t read_val; + }; + }; + } err = {}; + + using enum Error::Read; + + AVCLAN_stopEvent(); // quiesce contending sources during the read + + bool shouldACK = false; + uint8_t tmp = 0, parity = 0; + + err.errno = Error::Read{AVCLAN_readstartbit()}; + if (static_cast(err.errno)) + goto handle_err; + + AVCLAN_readbits<1>(&tmp); + in->is_unicast = tmp; + + parity = AVCLAN_readbits<12>(&in->controller_addr); + AVCLAN_readbits<1>(&tmp); + if (parity != (tmp &= 1)) { + err.errno = BAD_CONTROLLER_PARITY; + if (print.verbose) { + err.read_val = in->controller_addr; + err.parity = tmp; + } + goto handle_err; + } + + parity = AVCLAN_readbits<12>(&in->peripheral_addr); + AVCLAN_readbits<1>(&tmp); + if (parity != (tmp &= 1)) { + err.errno = BAD_PERIPHERAL_PARITY; + if (print.verbose) { + err.read_val = in->peripheral_addr; + err.parity = tmp; + } + goto handle_err; + } + + shouldACK = !AVCLAN_ismuted() && (in->peripheral_addr == address); + + if (shouldACK) + AVCLAN_sendbit_ACK(); + else + AVCLAN_readbits<1>(&tmp); + + parity = AVCLAN_readbits<4>(&in->control); + AVCLAN_readbits<1>(&tmp); + if (parity != (tmp &= 1)) { + err.errno = BAD_CONTROL_PARITY; + if (print.verbose) { + err.read_val = in->control; + err.parity = tmp; + } + goto handle_err; + } else if (shouldACK) { + AVCLAN_sendbit_ACK(); + } else { + AVCLAN_readbits<1>(&tmp); + } + + parity = AVCLAN_readbyte(&in->length); + AVCLAN_readbits<1>(&tmp); + if (parity != (tmp &= 1)) { + err.errno = BAD_LENGTH_PARITY; + if (print.verbose) { + err.read_val = in->length; + err.parity = tmp; + } + goto handle_err; + } else if (shouldACK) { + AVCLAN_sendbit_ACK(); + } else { + AVCLAN_readbits<1>(&tmp); + } + + if (in->length == 0 || in->length > MAXMSGLEN) { + err.errno = BAD_LENGTH_RANGE; + err.val = in->length; + goto handle_err; + } + + for (uint8_t i = 0; i < in->length; i++) { + parity = AVCLAN_readbits<8>(&in->data[i]); + AVCLAN_readbits<1>(&tmp); + if (parity != (tmp &= 1)) { + err.errno = BAD_DATA_PARITY; + if (print.verbose) { + err.read_val = in->data[i]; + err.parity = tmp; + } + goto handle_err; + } else if (shouldACK) { + AVCLAN_sendbit_ACK(); + } else { + AVCLAN_readbits<1>(&tmp); + } + } + + if (false) { + handle_err:; + AVCLAN_startEvent(); + RS232_Print("ERR(read): "); + switch (err.errno) { + case BAD_STARTBIT: RS232_Print("bad start bit (other)"); break; + case STARTBIT_TOO_SHORT: RS232_Print("bad start bit (short)"); break; + case STARTBIT_TOO_LONG: RS232_Print("bad start bit (long)"); 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); + break; + case BAD_DATA_PARITY: + RS232_Print("reading data"); + goto VERBOSE; + VERBOSE: + if (print.verbose) { + RS232_Print("; read 0x"); + RS232_PrintHex(err.read_val); + RS232_Print(" and got bad parity "); + RS232_PrintHex4(err.parity); + } + } + RS232_Print("\n"); + } else { + AVCLAN_startEvent(); + } + + // Only print if some data has been correctly received + if (print.print && (err.errno < STARTBIT_TOO_SHORT)) { + if (err.errno > BAD_DATA_PARITY) + in->length = 0; + AVCLAN_printframe(in, print.binary); + } + + return err.errno; +} + +Peripheral::Error::Send Peripheral::send(const AVCLAN_frame_t *out, + log_t print) { + struct errtype { + // Error enum is ordered such that a lower numeric value corresponds to + // more success + Error::Send errno; + uint8_t val; + } err = {}; + + using enum Error::Send; + + avclan_bit_t parity; + + if (AVCLAN_ismuted()) { + err.errno = MUTED; + goto handle_err; + } + + AVCLAN_stopEvent(); + + if (!AVCLAN_sendstartbit()) { + // Some other device is already driving the bus + err.errno = BUSY; + goto handle_err; + } + + AVCLAN_sendbits<1>(static_cast(out->is_unicast)); + + parity = AVCLAN_sendbits<12>(out->controller_addr); + AVCLAN_sendbit(parity); + + parity = AVCLAN_sendbits<12>(address); + AVCLAN_sendbit(parity); + + if (out->is_unicast && !AVCLAN_readbit_ACK()) { + err.errno = NAK_ADDRESS; + goto handle_err; + } + + parity = AVCLAN_sendbits<4>(out->control); + AVCLAN_sendbit(parity); + + if (out->is_unicast && !AVCLAN_readbit_ACK()) { + err.errno = NAK_CONTROL; + goto handle_err; + } + + parity = AVCLAN_sendbits<8>(out->length); // data length + AVCLAN_sendbit(parity); + + if (out->is_unicast && !AVCLAN_readbit_ACK()) { + err.errno = NAK_MESSAGE_LENGTH; + goto handle_err; + } + + for (uint8_t i = 0; i < out->length; i++) { + parity = AVCLAN_sendbits<8>(out->data[i]); + AVCLAN_sendbit(parity); + // Based on the µPD6708 datasheet, ACK bit for broadcast doesn't seem + // necessary (i.e. This deviates from the previous broadcast specific + // function that sent an extra `1` bit after each byte/parity) + if (out->is_unicast && !AVCLAN_readbit_ACK()) { + err.errno = NAK_DATA; + err.val = i; + goto handle_err; + } + // else + // AVCLAN_sendbit_1(); + } + + // back to read mode + if (false) { + handle_err:; + AVCLAN_startEvent(); + RS232_Print("Error"); + switch (err.errno) { + case MUTED: RS232_Print(": Device muted"); break; + case BUSY: RS232_Print(": Busy bus"); break; + case NAK_ADDRESS: + case NAK_CONTROL: + case NAK_MESSAGE_LENGTH: + case NAK_DATA: + RS232_Print(" NAK: "); + switch (err.errno) { + case NAK_ADDRESS: RS232_Print("address"); break; + case NAK_CONTROL: RS232_Print("Control"); break; + case NAK_MESSAGE_LENGTH: RS232_Print("Message length"); break; + case NAK_DATA: + RS232_Print(" data["); + RS232_PrintDec(err.val); + RS232_Print("]"); + break; + case MUTED: + case BUSY: __builtin_unreachable(); + } + break; + } + RS232_Print("\n"); + } else { + AVCLAN_startEvent(); + } + + if (print.print) + AVCLAN_printframe(out, print.binary); + + return err.errno; +} + +} // namespace avclan diff --git a/src/avclan/peripheral.hpp b/src/avclan/peripheral.hpp new file mode 100644 index 0000000..10da2fb --- /dev/null +++ b/src/avclan/peripheral.hpp @@ -0,0 +1,46 @@ +// copyright (C) 2006 Marcin Slonicki +// copyright (C) 2007 Louis Frigon +// Copyright (C) 2015 Allen Hill +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include "avclan_defs.h" +#include + +namespace avclan { +class Peripheral { +public: + struct Error { + // Error enums are ordered such that a lower numeric value corresponds to + // more progress/success before an error occured, with 0 being no errors + enum class Read : uint8_t { + BAD_DATA_PARITY = rBAD_DATA_PARITY, // = 0x01 + BAD_LENGTH_RANGE = rBAD_LENGTH_RANGE, + BAD_LENGTH_PARITY = rBAD_LENGTH_PARITY, + BAD_PERIPHERAL_PARITY = rBAD_PERIPHERAL_PARITY, + BAD_CONTROLLER_PARITY = rBAD_CONTROLLER_PARITY, + BAD_CONTROL_PARITY = rBAD_CONTROL_PARITY, + STARTBIT_TOO_SHORT = rSTARTBIT_TOO_SHORT, + STARTBIT_TOO_LONG = rSTARTBIT_TOO_LONG, + BAD_STARTBIT = rLATCHED_COMPARATOR, + }; + + enum class Send : uint8_t { + NAK_DATA = sNAK_DATA, // = 0x01 + NAK_MESSAGE_LENGTH = sNAK_MESSAGE_LENGTH, + NAK_CONTROL = sNAK_CONTROL, + NAK_ADDRESS = sNAK_ADDRESS, + BUSY = sBUSY, + MUTED = sMUTED, + }; + }; + + Peripheral(uint16_t address) : address{address} {} + + Error::Read read(AVCLAN_frame_t *in, log_t print); + Error::Send send(const AVCLAN_frame_t *out, log_t print); + +private: + const uint16_t address; +}; +} // namespace avclan diff --git a/src/avclan/target/avr-attiny3216/CMakeLists.txt b/src/avclan/target/avr-attiny3216/CMakeLists.txt index dd5dfbc..4b1c97f 100644 --- a/src/avclan/target/avr-attiny3216/CMakeLists.txt +++ b/src/avclan/target/avr-attiny3216/CMakeLists.txt @@ -89,7 +89,7 @@ FetchContent_MakeAvailable(avr_libstdcpp) add_library(libstdcpp INTERFACE) target_include_directories(libstdcpp SYSTEM INTERFACE ${avr_libstdcpp_SOURCE_DIR}/include) -target_link_libraries(avclan INTERFACE libstdcpp) +target_link_libraries(avclan PUBLIC libstdcpp) endif() diff --git a/src/sniffer.cc b/src/sniffer.cc index dc4b7e1..6aaa8c5 100644 --- a/src/sniffer.cc +++ b/src/sniffer.cc @@ -10,6 +10,7 @@ #include "avclandrv.h" #include "board.h" #include "com232.h" +#include "peripheral.hpp" #include "queue.hpp" const char *const offon[] = {"OFF", "ON"}; @@ -59,7 +60,6 @@ int main() { uint8_t data_tmp[MAXMSGLEN + sizeof(AVCLAN_frame_t)]; uint8_t seqIdx = 0; // current index in data_tmp - uint8_t err = 0; uint8_t failedStatusReports = 0; // Temporary, direct access is questionable since cache has ownership @@ -69,16 +69,19 @@ int main() { const AVCLAN_frame_t *lastStatus = nullptr; + avclan::Peripheral cd_changer(0x360); + using Error = avclan::Peripheral::Error; + Setup(); print_help(); while (true) { if (AVCLAN_busActive()) { if (auto msg = cache.pop()) { - err = AVCLAN_readframe(msg.get(), (log_t){.print = printAllFrames, - .binary = printBinary, - .verbose = verbose}); - if (!err) + auto err = cd_changer.read(msg.get(), (log_t){.print = printAllFrames, + .binary = printBinary, + .verbose = verbose}); + if (err == Error::Read{0x00}) incoming.push(std::move(msg)); } else { RS232_Print("!! Dropping an incoming message; cache is empty !!\n"); @@ -108,18 +111,18 @@ int main() { } if (auto out = outgoing.pop()) { - err = AVCLAN_sendframe( + auto err = cd_changer.send( out.get(), (log_t){.print = printAllFrames, .binary = printBinary}); - if (err || (reaction_t)out->reaction == r_SendOnly) { - if (err && out.get() == lastStatus && ++failedStatusReports > 1) { - failedStatusReports = 0; - AVCLAN_stopPlaying(); // Disable periodic updates if e.g. no-one's - // listening (car was turned off?) - } - } else { + if (err == Error::Send{0x00} && (reaction_t)out->reaction > r_SendOnly) { AVCLAN_statemachine(out.get()); if (out->reaction) outgoing.push(std::move(out)); + + } else if (err == Error::Send::NAK_ADDRESS && out.get() == lastStatus && + ++failedStatusReports > 1) { + failedStatusReports = 0; + AVCLAN_stopPlaying(); // Disable periodic updates if e.g. no-one's + // listening (car was turned off?) } }