mirror of
https://github.com/halleysfifthinc/Toyota-AVC-LAN
synced 2025-06-07 16:06:12 +00:00
Update to use attiny1616 AC2 and TCB1
- Change AVC output enable/disable to only change input/output of pin 7; only one pin should need to be used to send (i.e. actual differential signaling isn't being used, therefore, we can achieve the necessary (single-ended) differential voltage using only one pin, leaving the other outputting low) - Use virtual ports to enable setting output status with single instruction
This commit is contained in:
parent
0a9bd4d988
commit
feccda9e69
13
GlobalDef.h
13
GlobalDef.h
@ -18,14 +18,11 @@
|
|||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE (!FALSE)
|
#define TRUE (!FALSE)
|
||||||
|
|
||||||
// AVC LAN bus directly connected to internal analog comparator (PD6/7)
|
// AVC LAN bus on AC2 (PA6/7)
|
||||||
// PD6 AIN0 +
|
// PA6 AINP0 +
|
||||||
// PD7 AIN1 -
|
// PA7 AINN1 -
|
||||||
#define DATAIN_PIN ACSR
|
#define INPUT_IS_SET ( bit_is_set( AC2_STATUS, AC_STATE_bp ) )
|
||||||
#define DATAIN ACO
|
#define INPUT_IS_CLEAR ( bit_is_clear( AC2_STATUS, AC_STATE_bp ) )
|
||||||
|
|
||||||
#define INPUT_IS_SET ( bit_is_set( DATAIN_PIN, DATAIN ) )
|
|
||||||
#define INPUT_IS_CLEAR ( bit_is_clear( DATAIN_PIN, DATAIN ) )
|
|
||||||
|
|
||||||
#define LED_DDR DDRB
|
#define LED_DDR DDRB
|
||||||
#define LED_PORT PORTB
|
#define LED_PORT PORTB
|
||||||
|
145
avclandrv.c
145
avclandrv.c
@ -38,10 +38,12 @@
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define AVC_OUT_EN() sbi(PORTD, 6); sbi(DDRD, 6); sbi(DDRD, 7); sbi(ACSR, ACD); // Write mode
|
#define AVC_OUT_EN() cbi(AC2_CTRLA, AC_ENABLE_bp); sbi(VPORTA_DIR, 6); // Write mode
|
||||||
#define AVC_OUT_DIS() cbi(PORTD, 6); cbi(DDRD, 6); cbi(DDRD, 7); cbi(ACSR, ACD); // Read mpde
|
#define AVC_OUT_DIS() cbi(VPORTA_DIR, 6); sbi(AC2_CTRLA, AC_ENABLE_bp); // Read mode
|
||||||
#define AVC_SET_1() sbi(PORTD, 6);
|
#define AVC_SET_LOGICAL_1() \
|
||||||
#define AVC_SET_0() cbi(PORTD, 6);
|
__asm__ __volatile__ ("sbi VPORTA_OUT, 6;");
|
||||||
|
#define AVC_SET_LOGICAL_0() \
|
||||||
|
__asm__ __volatile__ ("cbi VPORTA_OUT, 6;");
|
||||||
|
|
||||||
|
|
||||||
byte CD_ID_1;
|
byte CD_ID_1;
|
||||||
@ -147,20 +149,20 @@ void AVC_HoldLine()
|
|||||||
// wait for free line
|
// wait for free line
|
||||||
byte line_busy = 1;
|
byte line_busy = 1;
|
||||||
|
|
||||||
TCNT0 = 0;
|
TCB1.CNT = 0;
|
||||||
do {
|
do {
|
||||||
while (INPUT_IS_CLEAR) {
|
while (INPUT_IS_CLEAR) {
|
||||||
/* The comparison value was originally 25 with CK64 (tick period of 4.34 us)
|
/* The comparison value was originally 25 with CK64 (tick period of 4.34 us)
|
||||||
at a clock frequency 14.7456MHz.
|
at a clock frequency 14.7456MHz.
|
||||||
For a more accurate tick period of .5 us at 16MHz, the value should be approximately 225*/
|
For a more accurate tick period of .5 us at 16MHz, the value should be approximately 225*/
|
||||||
if (TCNT0 >= 225) break;
|
if (TCB1.CNT >= 900) break;
|
||||||
}
|
}
|
||||||
if (TCNT0 > 216) line_busy=0;
|
if (TCB1.CNT > 864) line_busy=0;
|
||||||
} while (line_busy);
|
} while (line_busy);
|
||||||
|
|
||||||
// switch to out mode
|
// switch to out mode
|
||||||
AVC_OUT_EN();
|
AVC_OUT_EN();
|
||||||
AVC_SET_1();
|
AVC_SET_LOGICAL_1();
|
||||||
|
|
||||||
STARTEvent;
|
STARTEvent;
|
||||||
}
|
}
|
||||||
@ -169,7 +171,7 @@ void AVC_HoldLine()
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void AVC_ReleaseLine()
|
void AVC_ReleaseLine()
|
||||||
{
|
{
|
||||||
AVC_SET_0();
|
AVC_SET_LOGICAL_0();
|
||||||
AVC_OUT_DIS();
|
AVC_OUT_DIS();
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -179,31 +181,21 @@ void AVC_ReleaseLine()
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void AVCLan_Init()
|
void AVCLan_Init()
|
||||||
{
|
{
|
||||||
// OUTPUT ( set as input for comparator )
|
PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; // Disable input buffer; recommended when using AC
|
||||||
cbi(PORTD, 6);
|
PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc;
|
||||||
cbi(DDRD, 6);
|
|
||||||
|
// Pull-ups are disabled by default
|
||||||
|
VPORTA.DIR &= ~(PIN6_bm | PIN7_bm); // Zero pin 6 and 7 to set as input
|
||||||
|
|
||||||
// INPUT
|
|
||||||
cbi(PORTD, 7);
|
|
||||||
cbi(DDRD, 7);
|
|
||||||
|
|
||||||
// Analog comparator
|
// Analog comparator
|
||||||
|
AC2.CTRLA = AC_OUTEN_bm | AC_HYSMODE_25mV_gc | AC_ENABLE_bm;
|
||||||
|
|
||||||
cbi(ADCSRB, ACME); // Analog Comparator Multiplexer Enable - NO
|
TCB1.CTRLB = TCB_ASYNC_bm | TCB_CNTMODE_SINGLE_gc;
|
||||||
//cbi(ADCSRA, ADEN);
|
TCB1.EVCTRL = TCB_CAPTEI_bm;
|
||||||
/*
|
TCB1.INTCTRL = TCB_CAPT_bm;
|
||||||
cbi(ACSR, ACBG); // Analog Comparator Bandgap Select
|
EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH0_gc;
|
||||||
// ACI: Analog Comparator Interrupt Flag
|
TCB1.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm;
|
||||||
|
|
||||||
cbi(ACSR, ACIE); // Analog Comparator Interrupt Enable - NO
|
|
||||||
cbi(ACSR, ACIC); // Analog Comparator Input Capture Enable - NO
|
|
||||||
*/
|
|
||||||
cbi(ACSR, ACIS1); // Analog Comparator Interrupt Mode Select
|
|
||||||
cbi(ACSR, ACIS0); // Comparator Interrupt on Output Toggle
|
|
||||||
|
|
||||||
cbi(ACSR, ACD); // Analog Comparator Disable - NO
|
|
||||||
|
|
||||||
TCCR0B = _BV(CS01); // Timer 0 prescaler = 8 ( 2 count / us )
|
|
||||||
|
|
||||||
message_len = 0;
|
message_len = 0;
|
||||||
answerReq = cmNull;
|
answerReq = cmNull;
|
||||||
@ -228,9 +220,9 @@ byte AVCLan_Read_Byte(byte length)
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
while (INPUT_IS_CLEAR);
|
while (INPUT_IS_CLEAR);
|
||||||
TCNT0 = 0;
|
TCB1.CNT = 0;
|
||||||
while (INPUT_IS_SET); // If input was set for less than a
|
while (INPUT_IS_SET); // If input was set for less than 26 us
|
||||||
if ( TCNT0 < 52 ) { // generous half period, bit was a 1
|
if ( TCB1.CNT < 208 ) { // (a generous half period), bit was a 1
|
||||||
bite++;
|
bite++;
|
||||||
parity_bit++;
|
parity_bit++;
|
||||||
}
|
}
|
||||||
@ -240,19 +232,24 @@ byte AVCLan_Read_Byte(byte length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_AVC_logic_for(uint8_t val, uint16_t period) {
|
||||||
|
if (val == 1) {
|
||||||
|
AVC_SET_LOGICAL_1();
|
||||||
|
} else {
|
||||||
|
AVC_SET_LOGICAL_0();
|
||||||
|
}
|
||||||
|
TCB1.CCMP = period;
|
||||||
|
EVSYS.ASYNCSTROBE = EVSYS_ASYNCCH00_bm;
|
||||||
|
loop_until_bit_is_set(TCB1_INTFLAGS, 0);
|
||||||
|
TCB1_INTFLAGS = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// DONE: Timing adjusted
|
// DONE: Timing adjusted
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
byte AVCLan_Send_StartBit()
|
byte AVCLan_Send_StartBit()
|
||||||
{
|
{
|
||||||
AVC_SET_1();
|
set_AVC_logic_for(1, 1328); // 166 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
TCNT0 = 0;
|
set_AVC_logic_for(0, 152); // 19 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
while( TCNT0 < 255 );
|
|
||||||
TCNT0 = 0;
|
|
||||||
while( TCNT0 < 77 );
|
|
||||||
|
|
||||||
AVC_SET_0();
|
|
||||||
TCNT0 = 0;
|
|
||||||
while( TCNT0 < 38 );
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -261,69 +258,47 @@ byte AVCLan_Send_StartBit()
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void AVCLan_Send_Bit1()
|
void AVCLan_Send_Bit1()
|
||||||
{
|
{
|
||||||
AVC_SET_1();
|
set_AVC_logic_for(1, 164); // 20.5 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
TCNT0 = 0;
|
set_AVC_logic_for(0, 152); // 19 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
while( TCNT0 < 41 );
|
|
||||||
|
|
||||||
AVC_SET_0();
|
|
||||||
TCNT0 = 0;
|
|
||||||
while( TCNT0 < 38 ); // 12-21 us
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DONE: Timing adjusted
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void AVCLan_Send_Bit0()
|
void AVCLan_Send_Bit0()
|
||||||
{
|
{
|
||||||
AVC_SET_1();
|
set_AVC_logic_for(1, 272); // 34 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
TCNT0 = 0;
|
set_AVC_logic_for(0, 44); // 5.5 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
while( TCNT0 < 68 ); // 28-37 us
|
|
||||||
|
|
||||||
AVC_SET_0();
|
|
||||||
TCNT0 = 0;
|
|
||||||
while( TCNT0 < 11 ); // 00-09 us
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DONE: Timing adjusted.
|
// DONE: Timing adjusted.
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
byte AVCLan_Read_ACK()
|
byte AVCLan_Read_ACK()
|
||||||
{
|
{
|
||||||
AVC_SET_1();
|
set_AVC_logic_for(1, 152); // 34 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
TCNT0 = 0;
|
AVC_SET_LOGICAL_0(); // Replace with AVC_ReleaseLine?
|
||||||
while( TCNT0 < 38 );
|
|
||||||
|
|
||||||
AVC_SET_0(); // Replace with AVC_ReleaseLine?
|
|
||||||
AVC_OUT_DIS(); // switch to read mode
|
AVC_OUT_DIS(); // switch to read mode
|
||||||
|
|
||||||
|
TCB1.CNT = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
if (INPUT_IS_SET && (TCNT0 > 52 )) break; // Make sure INPUT is not still set from us
|
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
|
// Line of experimentation: Try changing TCNT0 comparison value or remove check entirely
|
||||||
if (TCNT0 > 75 ) return 1; // Not sure if this fix is intent correct
|
if (TCB1.CNT > 300 ) return 1; // Not sure if this fix is intent correct
|
||||||
}
|
}
|
||||||
|
|
||||||
while(INPUT_IS_SET);
|
while(INPUT_IS_SET);
|
||||||
AVC_OUT_EN(); // back to write mode
|
AVC_OUT_EN(); // back to write mode
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DONE: Timing adjusted.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
byte AVCLan_Send_ACK()
|
byte AVCLan_Send_ACK()
|
||||||
{
|
{
|
||||||
TCNT0 = 0;
|
TCB1.CNT = 0;
|
||||||
while (INPUT_IS_CLEAR) {
|
while (INPUT_IS_CLEAR) {
|
||||||
if (TCNT0 >= 225) return 0; // max wait time
|
if (TCB1.CNT >= 900) return 0; // max wait time
|
||||||
}
|
}
|
||||||
|
|
||||||
AVC_OUT_EN();
|
AVC_OUT_EN();
|
||||||
|
|
||||||
AVC_SET_1();
|
set_AVC_logic_for(1, 272); // 34 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
TCNT0 = 0;
|
set_AVC_logic_for(0, 44); // 5.5 us @ 125 ns tick (for F_CPU = 16MHz)
|
||||||
while( TCNT0 < 68 ); //28-37
|
|
||||||
|
|
||||||
AVC_SET_0();
|
|
||||||
TCNT0 = 0;
|
|
||||||
while( TCNT0 < 11 ); //00-09
|
|
||||||
|
|
||||||
AVC_OUT_DIS();
|
AVC_OUT_DIS();
|
||||||
|
|
||||||
@ -533,12 +508,12 @@ byte AVCLan_SendData()
|
|||||||
// wait for free line
|
// wait for free line
|
||||||
byte line_busy = 1;
|
byte line_busy = 1;
|
||||||
|
|
||||||
TCNT0 = 0;
|
TCB1.CNT = 0;
|
||||||
do {
|
do {
|
||||||
while (INPUT_IS_CLEAR) {
|
while (INPUT_IS_CLEAR) {
|
||||||
if ( TCNT0 >= 225 ) break;
|
if ( TCB1.CNT >= 900 ) break;
|
||||||
}
|
}
|
||||||
if ( TCNT0 > 216 ) line_busy=0;
|
if ( TCB1.CNT > 864 ) line_busy=0;
|
||||||
} while (line_busy);
|
} while (line_busy);
|
||||||
|
|
||||||
|
|
||||||
@ -617,12 +592,12 @@ byte AVCLan_SendDataBroadcast()
|
|||||||
// wait for free line
|
// wait for free line
|
||||||
byte line_busy = 1;
|
byte line_busy = 1;
|
||||||
|
|
||||||
TCNT0 = 0;
|
TCB1.CNT = 0;
|
||||||
do {
|
do {
|
||||||
while (INPUT_IS_CLEAR) {
|
while (INPUT_IS_CLEAR) {
|
||||||
if ( TCNT0 >= 225 ) break;
|
if ( TCB1.CNT >= 900 ) break;
|
||||||
}
|
}
|
||||||
if ( TCNT0 > 216 ) line_busy=0;
|
if ( TCB1.CNT > 864 ) line_busy=0;
|
||||||
} while (line_busy);
|
} while (line_busy);
|
||||||
|
|
||||||
|
|
||||||
@ -1025,10 +1000,10 @@ void ShowOutMessage()
|
|||||||
sbi(TCCR1B, CS10);
|
sbi(TCCR1B, CS10);
|
||||||
word n = 60000;
|
word n = 60000;
|
||||||
TCNT1 = 0;
|
TCNT1 = 0;
|
||||||
AVC_SET_1();
|
AVC_SET_LOGICAL_1();
|
||||||
while ( TCNT1 < n );
|
while ( TCNT1 < n );
|
||||||
TCNT1 = 0;
|
TCNT1 = 0;
|
||||||
AVC_SET_0();
|
AVC_SET_LOGICAL_0();
|
||||||
while ( TCNT1 < n );
|
while ( TCNT1 < n );
|
||||||
cbi(TCCR1B, CS10);
|
cbi(TCCR1B, CS10);
|
||||||
AVC_OUT_DIS();
|
AVC_OUT_DIS();
|
||||||
|
@ -119,8 +119,8 @@ int main()
|
|||||||
break;
|
break;
|
||||||
case 'R': RS232_Print_P(PSTR("REGIST:\n"));
|
case 'R': RS232_Print_P(PSTR("REGIST:\n"));
|
||||||
AVCLan_Command( cmRegister );
|
AVCLan_Command( cmRegister );
|
||||||
TCNT0 = 0;
|
TCB1.CNT = 0;
|
||||||
while( TCNT0 < 135 );
|
while( TCB1.CNT < 540 );
|
||||||
CHECK_AVC_LINE;
|
CHECK_AVC_LINE;
|
||||||
break;
|
break;
|
||||||
case 'r': AVCLan_Register();
|
case 'r': AVCLan_Register();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user