1
0
mirror of https://github.com/halleysfifthinc/Toyota-AVC-LAN synced 2025-06-06 15:36:47 +00:00

Setup timing better (fuses, clock speed, TCB clock speed)

This commit is contained in:
Allen Hill 2023-09-10 16:02:06 -04:00
parent 09bcd75811
commit 7245695bc7
4 changed files with 153 additions and 35 deletions

View File

@ -1,11 +1,50 @@
cmake_minimum_required(VERSION 3.24)
include(CMakeDependentOption)
set(WITH_MCU OFF)
set(AVR_MCU "attiny3216")
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/avr-gcc-toolchain.cmake")
project(avr-avc-lan VERSION 1 LANGUAGES C CXX ASM)
project(avclan-mockingboard VERSION 1 LANGUAGES C CXX ASM)
set(FREQSEL 16MHz CACHE STRING "Select the operating frequency")
set_property(CACHE FREQSEL PROPERTY STRINGS "20MHz" "16MHz")
if(FREQSEL MATCHES "20MHz")
set(F_CPU 20000000L)
set(AVR_UPLOADTOOL_BASE_OPTIONS ${AVR_UPLOADTOOL_BASE_OPTIONS} -U osccfg:w:0x2:m)
else()
set(F_CPU 16000000L)
set(AVR_UPLOADTOOL_BASE_OPTIONS ${AVR_UPLOADTOOL_BASE_OPTIONS} -U osccfg:w:0x1:m)
endif()
option(CLK_PRESCALE "Enable the main clock prescaler")
cmake_dependent_option(CLK_PRESCALE_DIV "Prescaler divisor" CLKCTRL_PDIV_2X_gc STRING "CLK_PRESCALE")
if(DEFINED CACHE{CLK_PRESCALE_DIV})
set_property(CACHE CLK_PRESCALE_DIV PROPERTY STRINGS
CLKCTRL_PDIV_2X_gc
CLKCTRL_PDIV_4X_gc
CLKCTRL_PDIV_8X_gc
CLKCTRL_PDIV_16X_gc
CLKCTRL_PDIV_32X_gc
CLKCTRL_PDIV_64X_gc
CLKCTRL_PDIV_6X_gc
CLKCTRL_PDIV_10X_gc
CLKCTRL_PDIV_12X_gc
CLKCTRL_PDIV_24X_gc
CLKCTRL_PDIV_48X_gc
)
else()
set(CLK_PRESCALE_DIV CLKCTRL_PDIV_2X_gc)
endif()
set(TCB_CLKSEL "TCB_CLKSEL_CLKDIV2_gc" CACHE STRING "Choose the clock for TCB")
set_property(CACHE TCB_CLKSEL PROPERTY STRINGS
TCB_CLKSEL_CLKDIV1_gc
TCB_CLKSEL_CLKDIV2_gc
TCB_CLKSEL_CLKTCA_gc
)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.3")
@ -61,18 +100,24 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_C_FLAGS_DEBUG "-O0 -save-temps -g -gdwarf-3 -gstrict-dwarf")
endif(CMAKE_BUILD_TYPE MATCHES Debug)
add_avr_executable(sniffer
# Set startup time to 8 ms (0x4)
set(AVR_UPLOADTOOL_BASE_OPTIONS ${AVR_UPLOADTOOL_BASE_OPTIONS} -U syscfg1:w:0x4:m)
add_avr_executable(mockingboard
src/sniffer.c
src/com232.c
src/avclandrv.c)
target_link_options(sniffer PUBLIC
target_link_options(mockingboard PUBLIC
-B "${attiny_atpack_SOURCE_DIR}/gcc/dev/${AVR_MCU}"
)
target_compile_definitions(sniffer PRIVATE
F_CPU=16000000L
target_compile_definitions(mockingboard PRIVATE
F_CPU=${F_CPU}
CLK_PRESCALE=$<IF:$<BOOL:${CLK_PRESCALE}>,0x01,0x00>
CLK_PRESCALE_DIV=${CLK_PRESCALE_DIV}
TCB_CLKSEL=${TCB_CLKSEL}
)
target_compile_options(sniffer PRIVATE
target_compile_options(mockingboard PRIVATE
--param=min-pagesize=0
-ffunction-sections
-fdata-sections

View File

@ -92,6 +92,7 @@
#include "avclandrv.h"
#include "com232.h"
#include "timing.h"
// Enable AVC bus Tx
#define AVC_OUT_EN() \
@ -265,12 +266,12 @@ void AVCLAN_init() {
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;
TCB0.CTRLA = TCB_CLKSEL | TCB_ENABLE_bm;
// TCB1 for send bit timing
TCB1.CTRLB = TCB_CNTMODE_INT_gc;
TCB1.CCMP = 0xFFFF;
TCB1.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm;
TCB1.CTRLA = TCB_CLKSEL | TCB_ENABLE_bm;
answerReq = cm_Null;
@ -293,34 +294,36 @@ void set_AVC_logic_for(uint8_t val, uint16_t period) {
return;
}
uint8_t AVCLAN_sendbit_start() {
set_AVC_logic_for(1, 1328); // 166 us @ 125 ns tick (for F_CPU = 16MHz)
set_AVC_logic_for(0, 152); // 19 us @ 125 ns tick (for F_CPU = 16MHz)
return 1;
void AVCLAN_sendbit_start() {
set_AVC_logic_for(0, AVCLAN_STARTBIT_LOGIC_0); // 166 us
set_AVC_logic_for(1, AVCLAN_STARTBIT_LOGIC_1); // 19 us
}
void AVCLAN_sendbit_1() {
set_AVC_logic_for(1, 164); // 20.5 us @ 125 ns tick (for F_CPU = 16MHz)
set_AVC_logic_for(0, 152); // 19 us @ 125 ns tick (for F_CPU = 16MHz)
set_AVC_logic_for(0, AVCLAN_BIT1_LOGIC_0); // 20.5 us
set_AVC_logic_for(1, AVCLAN_BIT1_LOGIC_1); // 19 us
}
void AVCLAN_sendbit_0() {
set_AVC_logic_for(1, 272); // 34 us @ 125 ns tick (for F_CPU = 16MHz)
set_AVC_logic_for(0, 44); // 5.5 us @ 125 ns tick (for F_CPU = 16MHz)
set_AVC_logic_for(0, AVCLAN_BIT0_LOGIC_0); // 34 us
set_AVC_logic_for(1, AVCLAN_BIT0_LOGIC_1); // 5.5 us
}
void AVCLAN_sendbit_ACK() {
TCB1.CNT = 0;
// Wait for controller to begin ACK bit
while (INPUT_IS_CLEAR) {
if (TCB1.CNT >= 900)
return; // max wait time
// Wait for approx the length of a bit; any longer and something has clearly
// gone wrong
if (TCB1.CNT >= AVCLAN_BIT_LENGTH)
return;
}
AVC_OUT_EN();
set_AVC_logic_for(1, 272); // 34 us @ 125 ns tick (for F_CPU = 16MHz)
set_AVC_logic_for(0, 44); // 5.5 us @ 125 ns tick (for F_CPU = 16MHz)
set_AVC_logic_for(0, AVCLAN_BIT0_LOGIC_0); // 34 us
set_AVC_logic_for(1, AVCLAN_BIT0_LOGIC_1); // 5.5 us
AVC_OUT_DIS();
}
@ -395,7 +398,7 @@ uint8_t AVCLAN_sendbyte(const uint8_t *byte) {
ISR(TCB0_INT_vect) {
// If input was set for less than 26 us (a generous half period), bit was a 1
if (TCB0.CCMP < 208) {
if (TCB0.CCMP < (uint16_t)AVCLAN_READBIT_THRESHOLD) {
READING_BYTE++;
READING_PARITY++;
}
@ -418,7 +421,15 @@ uint8_t AVCLAN_readbitsi(uint8_t *bits, uint8_t len) {
READING_NBITS = len;
sei();
while (READING_NBITS != 0) {};
TCB1.CNT = 0;
while (READING_NBITS != 0) {
// Duration of `len` bits + 10%
if (TCB1.CNT > (((uint16_t)AVCLAN_BIT_LENGTH * 11 * len) / 10)) {
READING_BYTE = 0;
READING_PARITY = 0;
break; // Should have finished by now; something's wrong
}
};
cli();
*bits = READING_BYTE;
@ -448,7 +459,15 @@ uint8_t AVCLAN_readbyte(uint8_t *byte) {
READING_NBITS = 8;
sei();
while (READING_NBITS != 0) {};
TCB1.CNT = 0;
while (READING_NBITS != 0) {
// Duration of byte + 10%
if (TCB1.CNT > (((uint16_t)AVCLAN_BIT_LENGTH * 11 * 8) / 10)) {
READING_BYTE = 0;
READING_PARITY = 0;
break; // Should have finished by now; something's wrong
}
};
cli();
*byte = READING_BYTE;
@ -459,20 +478,19 @@ uint8_t AVCLAN_readbyte(uint8_t *byte) {
}
uint8_t AVCLAN_readbit_ACK() {
set_AVC_logic_for(1, 152); // 34 us @ 125 ns tick (for F_CPU = 16MHz)
AVC_SET_LOGICAL_0(); // Replace with AVC_ReleaseLine?
AVC_OUT_DIS(); // switch to read mode
TCB1.CNT = 0;
set_AVC_logic_for(0, AVCLAN_BIT1_LOGIC_0); // 20.5 us
AVC_SET_LOGICAL_1();
AVC_OUT_DIS();
while (1) {
if (INPUT_IS_SET && (TCB1.CNT > 208))
break; // Make sure INPUT is not still set from us
// Line of experimentation: Try changing TCNT0 comparison value or remove
// check entirely
if (TCB1.CNT > 300)
return 1; // Not sure if this fix is intent correct
if (INPUT_IS_SET && (TCB1.CNT > AVCLAN_READBIT_THRESHOLD))
break; // ACK
if (TCB1.CNT > AVCLAN_BIT_LENGTH)
return 1; // NAK
}
// Check/wait in case we get here before peripheral finishes ACK bit
while (INPUT_IS_SET) {}
AVC_OUT_EN(); // back to write mode
return 0;
@ -669,7 +687,8 @@ uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
TCB1.CNT = 0;
do {
while (INPUT_IS_CLEAR) {
if (TCB1.CNT >= 900)
// Wait for 120% of a bit length
if (TCB1.CNT >= (uint16_t)(AVCLAN_BIT_LENGTH * 12 / 10))
break;
}
if (TCB1.CNT > 864)

View File

@ -23,6 +23,7 @@
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/sfr_defs.h>
#include <avr/xmega.h>
#include <stdint.h>
#include "avclandrv.h"
@ -217,6 +218,8 @@ void Setup() {
printAllFrames = 1;
echoCharacters = 1;
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, (CLK_PRESCALE | CLK_PRESCALE_DIV));
general_GPIO_init();
// Setup RTC as 1 sec periodic timer

51
src/timing.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef _TIMING_HPP_
#define _TIMING_HPP_
#if CLK_PRESCALE == 0x01
#error "Not implemented"
#else
#if F_CPU == 20000000L
#define CPU_CYCLE 50
#elif F_CPU == 16000000L
#define CPU_CYCLE 62.5
#else
#error "Not implemented"
#endif
#ifndef TCB_CLKSEL_CLKDIV1_gc
#define TCB_CLKSEL_CLKDIV1_gc (0x00 << 1)
#endif
#ifndef TCB_CLKSEL_CLKDIV2_gc
#define TCB_CLKSEL_CLKDIV2_gc (0x01 << 1)
#endif
#ifndef TCB_CLKSEL_CLKTCA_gc
#define TCB_CLKSEL_CLKTCA_gc (0x02 << 1)
#endif
#if TCB_CLKSEL == TCB_CLKSEL_CLKDIV1_gc
#define TCB_TICK (CPU_CYCLE)
#elif TCB_CLKSEL == TCB_CLKSEL_CLKDIV2_gc
#define TCB_TICK (CPU_CYCLE * 2)
#elif TCB_CLKSEL == TCB_CLKSEL_CLKTCA_gc
#error "Not implemented"
#endif
#define AVCLAN_STARTBIT_LOGIC_0 (166e3 / TCB_TICK)
#define AVCLAN_STARTBIT_LOGIC_1 (19e3 / TCB_TICK)
#define AVCLAN_BIT1_LOGIC_0 (20.5e3 / TCB_TICK)
#define AVCLAN_BIT1_LOGIC_1 (19e3 / TCB_TICK)
#define AVCLAN_BIT0_LOGIC_0 (34e3 / TCB_TICK)
#define AVCLAN_BIT0_LOGIC_1 (5.5e3 / TCB_TICK)
#define AVCLAN_READBIT_THRESHOLD (26e3 / TCB_TICK)
#define AVCLAN_BIT_LENGTH (39.5e3 / TCB_TICK)
#endif
#endif