1
0
mirror of https://github.com/halleysfifthinc/Toyota-AVC-LAN synced 2025-06-07 16:06:12 +00:00
Toyota-AVC-LAN/avclandrv.c
Allen Hill feccda9e69 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
2023-08-03 11:01:45 -04:00

1014 lines
27 KiB
C

/*
Copyright (C) 2015 Allen Hill <allenofthehills@gmail.com>.
Portions of the following source code are:
Copyright (C) 2006 Marcin Slonicki <marcin@softservice.com.pl>.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-----------------------------------------------------------------------
this file is a part of the TOYOTA Corolla MP3 Player Project
-----------------------------------------------------------------------
http://www.softservice.com.pl/corolla/avc
May 28 / 2009 - version 2
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "avclandrv.h"
#include "com232.h"
#include "GlobalDef.h"
//------------------------------------------------------------------------------
#define AVC_OUT_EN() cbi(AC2_CTRLA, AC_ENABLE_bp); sbi(VPORTA_DIR, 6); // Write mode
#define AVC_OUT_DIS() cbi(VPORTA_DIR, 6); sbi(AC2_CTRLA, AC_ENABLE_bp); // Read mode
#define AVC_SET_LOGICAL_1() \
__asm__ __volatile__ ("sbi VPORTA_OUT, 6;");
#define AVC_SET_LOGICAL_0() \
__asm__ __volatile__ ("cbi VPORTA_OUT, 6;");
byte CD_ID_1;
byte CD_ID_2;
byte HU_ID_1;
byte HU_ID_2;
byte parity_bit;
byte repeatMode;
byte randomMode;
byte playMode;
byte cd_Disc;
byte cd_Track;
byte cd_Time_Min;
byte cd_Time_Sec;
byte answerReq;
cd_modes CD_Mode;
byte broadcast;
byte master1;
byte master2;
byte slave1;
byte slave2;
byte message_len;
byte message[MAXMSGLEN];
byte data_control;
byte data_len;
byte data[MAXMSGLEN];
// we need check answer (to avclan check) timeout
// when is more then 1 min, FORCE answer.
byte check_timeout;
#define SW_ID 0x11 // 11 For my stereo
// commands
const byte stat1[] = { 0x4, 0x00, 0x00, 0x01, 0x0A };
const byte stat2[] = { 0x4, 0x00, 0x00, 0x01, 0x08 };
const byte stat3[] = { 0x4, 0x00, 0x00, 0x01, 0x0D };
const byte stat4[] = { 0x4, 0x00, 0x00, 0x01, 0x0C };
// broadcast
const byte lan_stat1[] = { 0x3, 0x00, 0x01, 0x0A };
const byte lan_reg[] = { 0x3, SW_ID, 0x01, 0x00 };
const byte lan_init[] = { 0x3, SW_ID, 0x01, 0x01 };
const byte lan_check[] = { 0x3, SW_ID, 0x01, 0x20 };
const byte lan_playit[] = { 0x4, SW_ID, 0x01, 0x45, 0x63 };
const byte play_req1[] = { 0x4, 0x00, 0x25, 0x63, 0x80 };
#ifdef __AVENSIS__
const byte play_req2[] = { 0x6, 0x00, SW_ID, 0x63, 0x42 };
#else
const byte play_req2[] = { 0x6, 0x00, SW_ID, 0x63, 0x42, 0x01, 0x00 };
#endif
const byte play_req3[] = { 0x5, 0x00, SW_ID, 0x63, 0x42, 0x41 };
const byte stop_req[] = { 0x5, 0x00, SW_ID, 0x63, 0x43, 0x01 };
const byte stop_req2[] = { 0x5, 0x00, SW_ID, 0x63, 0x43, 0x41 };
// answers
const byte CMD_REGISTER[] = {0x1, 0x05, 0x00, 0x01, SW_ID, 0x10, 0x63 };
const byte CMD_STATUS1[] = {0x1, 0x04, 0x00, 0x01, 0x00, 0x1A };
const byte CMD_STATUS2[] = {0x1, 0x04, 0x00, 0x01, 0x00, 0x18 };
const byte CMD_STATUS3[] = {0x1, 0x04, 0x00, 0x01, 0x00, 0x1D };
const byte CMD_STATUS4[] = {0x1, 0x05, 0x00, 0x01, 0x00, 0x1C, 0x00 };
byte CMD_CHECK[] = {0x1, 0x06, 0x00, 0x01, SW_ID, 0x30, 0x00, 0x00 };
const byte CMD_STATUS5[] = {0x1, 0x05, 0x00, 0x5C, 0x12, 0x53, 0x02 };
const byte CMD_STATUS5A[] = {0x0, 0x05, 0x5C, 0x31, 0xF1, 0x00, 0x00 };
const byte CMD_STATUS6[] = {0x1, 0x06, 0x00, 0x5C, 0x32, 0xF0, 0x02, 0x00 };
const byte CMD_PLAY_OK1[] = {0x1, 0x05, 0x00, 0x63, SW_ID, 0x50, 0x01 };
const byte CMD_PLAY_OK2[] = {0x1, 0x05, 0x00, 0x63, SW_ID, 0x52, 0x01 };
const byte CMD_PLAY_OK3[] = {0x0, 0x0B, 0x63, 0x31, 0xF1, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80 };
byte CMD_PLAY_OK4[] = {0x0, 0x0B, 0x63, 0x31, 0xF1, 0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 };
const byte CMD_STOP1[] = {0x1, 0x05, 0x00, 0x63, SW_ID, 0x53, 0x01 };
byte CMD_STOP2[] = {0x0, 0x0B, 0x63, 0x31, 0xF1, 0x00, 0x30, 0x00, 0x00,0x00, 0x00, 0x00, 0x80 };
const byte CMD_BEEP[] = {0x1, 0x05, 0x00, 0x63, 0x29, 0x60, 0x02 };
//------------------------------------------------------------------------------
// DONE: Timing adjusted, however refactoring may make code more clear/efficient
//------------------------------------------------------------------------------
void AVC_HoldLine()
{
STOPEvent;
// wait for free line
byte line_busy = 1;
TCB1.CNT = 0;
do {
while (INPUT_IS_CLEAR) {
/* The comparison value was originally 25 with CK64 (tick period of 4.34 us)
at a clock frequency 14.7456MHz.
For a more accurate tick period of .5 us at 16MHz, the value should be approximately 225*/
if (TCB1.CNT >= 900) break;
}
if (TCB1.CNT > 864) line_busy=0;
} while (line_busy);
// switch to out mode
AVC_OUT_EN();
AVC_SET_LOGICAL_1();
STARTEvent;
}
// DONE: No changes necessary
//------------------------------------------------------------------------------
void AVC_ReleaseLine()
{
AVC_SET_LOGICAL_0();
AVC_OUT_DIS();
}
//------------------------------------------------------------------------------
// DONE: No changes necessary
//------------------------------------------------------------------------------
void AVCLan_Init()
{
PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; // Disable input buffer; recommended when using AC
PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc;
// Pull-ups are disabled by default
VPORTA.DIR &= ~(PIN6_bm | PIN7_bm); // Zero pin 6 and 7 to set as input
// Analog comparator
AC2.CTRLA = AC_OUTEN_bm | AC_HYSMODE_25mV_gc | AC_ENABLE_bm;
TCB1.CTRLB = TCB_ASYNC_bm | TCB_CNTMODE_SINGLE_gc;
TCB1.EVCTRL = TCB_CAPTEI_bm;
TCB1.INTCTRL = TCB_CAPT_bm;
EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH0_gc;
TCB1.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm;
message_len = 0;
answerReq = cmNull;
check_timeout = 0;
cd_Disc = 1;
cd_Track = 1;
cd_Time_Min = 0;
cd_Time_Sec = 0;
repeatMode = 0;
randomMode = 0;
playMode = 0;
CD_Mode = stStop;
}
// DONE: Timing adjusted, however refactoring may make code more clear/efficient
//------------------------------------------------------------------------------
byte AVCLan_Read_Byte(byte length)
{
byte bite = 0;
while (1) {
while (INPUT_IS_CLEAR);
TCB1.CNT = 0;
while (INPUT_IS_SET); // If input was set for less than 26 us
if ( TCB1.CNT < 208 ) { // (a generous half period), bit was a 1
bite++;
parity_bit++;
}
length--;
if (!length) return bite;
bite = bite << 1;
}
}
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
//------------------------------------------------------------------------------
byte AVCLan_Send_StartBit()
{
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;
}
// DONE: Timing adjusted. Comparison values are timer ticks, not us.
//------------------------------------------------------------------------------
void AVCLan_Send_Bit1()
{
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)
}
void AVCLan_Send_Bit0()
{
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)
}
// DONE: Timing adjusted.
//------------------------------------------------------------------------------
byte AVCLan_Read_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;
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
}
while(INPUT_IS_SET);
AVC_OUT_EN(); // back to write mode
return 0;
}
byte AVCLan_Send_ACK()
{
TCB1.CNT = 0;
while (INPUT_IS_CLEAR) {
if (TCB1.CNT >= 900) return 0; // max wait time
}
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)
AVC_OUT_DIS();
return 1;
}
// DONE: var 'byte' adjusted to 'bite' to avoid reserved word conflict
//------------------------------------------------------------------------------
byte AVCLan_Send_Byte(byte bite, byte len)
{
byte b;
if (len==8) {
b = bite;
} else {
b = bite << (8-len);
}
while (1) {
if ( (b & 128)!=0 ) {
AVCLan_Send_Bit1();
parity_bit++;
} else {
AVCLan_Send_Bit0();
}
len--;
if (!len) {
//if (INPUT_IS_SET) RS232_Print_P(PSTR("SBER\n")); // Send Bit ERror
return 1;
}
b = b << 1;
}
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte AVCLan_Send_ParityBit()
{
if ( (parity_bit & 1)!=0 ) {
AVCLan_Send_Bit1();
//parity_bit++;
} else {
AVCLan_Send_Bit0();
}
parity_bit=0;
return 1;
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte CheckCmd(byte *cmd)
{
byte i;
byte *c;
byte l;
c = cmd;
l = *c++;
for (i=0; i<l; i++) {
if (message[i] != *c) return 0;
c++;
}
return 1;
}
// DONE: Timing adjusted.
//------------------------------------------------------------------------------
byte AVCLan_Read_Message()
{
STOPEvent; // disable timer1 interrupt
byte i;
byte for_me = 0;
//RS232_Print_P(PSTR("$ "));
// TCCR1B |= (1 << CS11)|(1 << CS10); // Timer1 prescaler at 64
// TCNT1 = 0;
// TCNT0 = 0;
// while (INPUT_IS_SET) {
// if ( TCNT0 > 255 ) { // 170 us
// // TCCR1B = 0;
// // TCCR1B |= (1 << WGM12)|(1 << CS12); // Set CTC, prescaler at 256
// STARTEvent;
// RS232_Print_P(PSTR("LAN>T1\n"));
// return 0;
// }
// }
//
// if ( TCNT0 < 20 ) { // 20 us
// // TCCR1B = 0;
// // TCCR1B |= (1 << WGM12)|(1 << CS12);
// STARTEvent;
// RS232_Print_P(PSTR("LAN>T2\n"));
// return 0;
// }
AVCLan_Read_Byte(1);
broadcast = AVCLan_Read_Byte(1);
parity_bit = 0;
master1 = AVCLan_Read_Byte(4);
master2 = AVCLan_Read_Byte(8);
if ((parity_bit&1)!=AVCLan_Read_Byte(1)) {
STARTEvent;
return 0;
}
parity_bit = 0;
slave1 = AVCLan_Read_Byte(4);
slave2 = AVCLan_Read_Byte(8);
if ((parity_bit&1)!=AVCLan_Read_Byte(1)) {
STARTEvent;
return 0;
}
// is this command for me ?
if ((slave1==CD_ID_1)&&(slave2==CD_ID_2)) {
for_me=1;
}
if (for_me) AVCLan_Send_ACK();
else AVCLan_Read_Byte(1);
parity_bit = 0;
AVCLan_Read_Byte(4); // control - always 0xF
if ((parity_bit&1)!=AVCLan_Read_Byte(1)) {
STARTEvent;
return 0;
}
if (for_me) AVCLan_Send_ACK();
else AVCLan_Read_Byte(1);
parity_bit = 0;
message_len = AVCLan_Read_Byte(8);
if ((parity_bit&1)!=AVCLan_Read_Byte(1)) {
STARTEvent;
return 0;
}
if (for_me) AVCLan_Send_ACK();
else AVCLan_Read_Byte(1);
if (message_len > MAXMSGLEN) {
// RS232_Print_P(PSTR("LAN> Command error"));
STARTEvent;
return 0;
}
for (i=0; i<message_len; i++) {
parity_bit = 0;
message[i] = AVCLan_Read_Byte(8);
if ((parity_bit&1)!=AVCLan_Read_Byte(1)) {
STARTEvent;
return 0;
}
if (for_me) {
AVCLan_Send_ACK();
} else {
AVCLan_Read_Byte(1);
}
}
STARTEvent;
if (showLog) ShowInMessage();
if (for_me) {
if (CheckCmd((byte*)stat1)) { answerReq = cmStatus1; return 1; }
if (CheckCmd((byte*)stat2)) { answerReq = cmStatus2; return 1; }
if (CheckCmd((byte*)stat3)) { answerReq = cmStatus3; return 1; }
if (CheckCmd((byte*)stat4)) { answerReq = cmStatus4; return 1; }
// if (CheckCmd((byte*)stat5)) { answerReq = cmStatus5; return 1; }
if (CheckCmd((byte*)play_req1)) { answerReq = cmPlayReq1; return 1; }
if (CheckCmd((byte*)play_req2)) { answerReq = cmPlayReq2; return 1; }
if (CheckCmd((byte*)play_req3)) { answerReq = cmPlayReq3; return 1; }
if (CheckCmd((byte*)stop_req)) { answerReq = cmStopReq; return 1; }
if (CheckCmd((byte*)stop_req2)) { answerReq = cmStopReq2; return 1; }
} else { // broadcast check
if (CheckCmd((byte*)lan_playit)) { answerReq = cmPlayIt; return 1; }
if (CheckCmd((byte*)lan_check)) {
answerReq = cmCheck;
CMD_CHECK[6]=message[3];
return 1;
}
if (CheckCmd((byte*)lan_reg)) { answerReq = cmRegister; return 1; }
if (CheckCmd((byte*)lan_init)) { answerReq = cmInit; return 1; }
if (CheckCmd((byte*)lan_stat1)) { answerReq = cmStatus1; return 1; }
}
answerReq = cmNull;
return 1;
}
// DONE: Timing adjusted.
//------------------------------------------------------------------------------
byte AVCLan_SendData()
{
byte i;
STOPEvent;
// wait for free line
byte line_busy = 1;
TCB1.CNT = 0;
do {
while (INPUT_IS_CLEAR) {
if ( TCB1.CNT >= 900 ) break;
}
if ( TCB1.CNT > 864 ) line_busy=0;
} while (line_busy);
// switch to output mode
AVC_OUT_EN();
AVCLan_Send_StartBit();
AVCLan_Send_Byte(0x1, 1); // regular communication
parity_bit = 0;
AVCLan_Send_Byte(CD_ID_1, 4); // CD Changer ID as master
AVCLan_Send_Byte(CD_ID_2, 8);
AVCLan_Send_ParityBit();
AVCLan_Send_Byte(HU_ID_1, 4); // HeadUnit ID as slave
AVCLan_Send_Byte(HU_ID_2, 8);
AVCLan_Send_ParityBit();
if (AVCLan_Read_ACK()) {
AVC_OUT_DIS();
STARTEvent;
RS232_Print_P(PSTR("Error ACK 1 (Transmission ACK)\n"));
return 1;
}
AVCLan_Send_Byte(0xF, 4); // 0xf - control -> COMMAND WRITE
AVCLan_Send_ParityBit();
if (AVCLan_Read_ACK()) {
AVC_OUT_DIS();
STARTEvent;
RS232_Print_P(PSTR("Error ACK 2 (COMMMAND WRITE)\n"));
return 2;
}
AVCLan_Send_Byte(data_len, 8);// data length
AVCLan_Send_ParityBit();
if (AVCLan_Read_ACK()) {
AVC_OUT_DIS();
STARTEvent;
RS232_Print_P(PSTR("Error ACK 3 (Data Length)\n"));
return 3;
}
for (i=0;i<data_len;i++) {
AVCLan_Send_Byte(data[i], 8);// data byte
AVCLan_Send_ParityBit();
if (AVCLan_Read_ACK()) {
AVC_OUT_DIS();
STARTEvent;
RS232_Print_P(PSTR("Error ACK 4 (Data Byte: "));
RS232_PrintDec(i);
RS232_Print_P(PSTR(")\n"));
return 4;
}
}
// back to read mode
AVC_OUT_DIS();
STARTEvent;
if (showLog) ShowOutMessage();
return 0;
}
// DONE: Timing adjusted.
//------------------------------------------------------------------------------
byte AVCLan_SendDataBroadcast()
{
byte i;
STOPEvent;
// wait for free line
byte line_busy = 1;
TCB1.CNT = 0;
do {
while (INPUT_IS_CLEAR) {
if ( TCB1.CNT >= 900 ) break;
}
if ( TCB1.CNT > 864 ) line_busy=0;
} while (line_busy);
AVC_OUT_EN();
AVCLan_Send_StartBit();
AVCLan_Send_Byte(0x0, 1); // broadcast
parity_bit = 0;
AVCLan_Send_Byte(CD_ID_1, 4); // CD Changer ID as master
AVCLan_Send_Byte(CD_ID_2, 8);
AVCLan_Send_ParityBit();
AVCLan_Send_Byte(0x1, 4); // all audio devices
AVCLan_Send_Byte(0xFF, 8);
AVCLan_Send_ParityBit();
AVCLan_Send_Bit1();
AVCLan_Send_Byte(0xF, 4); // 0xf - control -> COMMAND WRITE
AVCLan_Send_ParityBit();
AVCLan_Send_Bit1();
AVCLan_Send_Byte(data_len, 8); // data lenght
AVCLan_Send_ParityBit();
AVCLan_Send_Bit1();
for (i=0;i<data_len;i++) {
AVCLan_Send_Byte(data[i], 8); // data byte
AVCLan_Send_ParityBit();
AVCLan_Send_Bit1();
}
AVC_OUT_DIS();
STARTEvent;
if (showLog) ShowOutMessage();
return 0;
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte AVCLan_SendAnswerFrame(byte *cmd)
{
byte i;
byte *c;
byte b;
c = cmd;
b = *c++;
data_control = 0xF;
data_len = *c++;
for (i=0; i<data_len; i++) {
data[i]= *c++;
}
if (b)
return AVCLan_SendData();
else
return AVCLan_SendDataBroadcast();
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte AVCLan_SendMyData(byte *data_tmp, byte s_len)
{
byte i;
byte *c;
c = data_tmp;
data_control = 0xF;
data_len = s_len;
for (i=0; i<data_len; i++) {
data[i]= *c++;
}
return AVCLan_SendData();
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte AVCLan_SendMyDataBroadcast(byte *data_tmp, byte s_len)
{
byte i;
byte *c;
c = data_tmp;
data_control = 0xF;
data_len = s_len;
for (i=0; i<data_len; i++) {
data[i]= *c++;
}
return AVCLan_SendDataBroadcast();
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte AVCLan_SendInitCommands()
{
byte r;
const byte c1[] = { 0x0, 0x0B, 0x63, 0x31, 0xF1, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80 };
const byte c2[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x02 };
const byte c3[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x3F, 0x00, 0x01, 0x00, 0x01, 0x02 };
const byte c4[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x3D, 0x00, 0x01, 0x00, 0x01, 0x02 };
const byte c5[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x39, 0x00, 0x01, 0x00, 0x01, 0x02 };
const byte c6[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x31, 0x00, 0x01, 0x00, 0x01, 0x02 };
const byte c7[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x21, 0x00, 0x01, 0x00, 0x01, 0x02 };
const byte c8[] = { 0x0, 0x0B, 0x63, 0x31, 0xF1, 0x00, 0x90, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80 };
const byte c9[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x02 };
const byte cA[] = { 0x0, 0x0B, 0x63, 0x31, 0xF1, 0x00, 0x30, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80 };
r = AVCLan_SendAnswerFrame((byte*)c1);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c2);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c3);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c4);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c5);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c6);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c7);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c8);
if (!r) r = AVCLan_SendAnswerFrame((byte*)c9);
if (!r) r = AVCLan_SendAnswerFrame((byte*)cA);
//const byte c1[] = { 0x0, 0x0B, 0x63, 0x31, 0xF1, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80 };
//r = AVCLan_SendAnswerFrame((byte*)c1);
return r;
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
void AVCLan_Send_Status()
{
// disc track t_min t_sec
byte STATUS[] = {0x0, 0x0B, 0x63, 0x31, 0xF1, 0x01, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x80 };
STATUS[7] = cd_Disc;
STATUS[8] = cd_Track;
STATUS[9] = cd_Time_Min;
STATUS[10] = cd_Time_Sec;
STATUS[11] = 0;
AVCLan_SendAnswerFrame((byte*)STATUS);
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte AVCLan_SendAnswer()
{
byte r = 0 ;
switch (answerReq) {
case cmStatus1: r = AVCLan_SendAnswerFrame((byte*)CMD_STATUS1);
break;
case cmStatus2: r = AVCLan_SendAnswerFrame((byte*)CMD_STATUS2);
break;
case cmStatus3: r = AVCLan_SendAnswerFrame((byte*)CMD_STATUS3);
break;
case cmStatus4: r = AVCLan_SendAnswerFrame((byte*)CMD_STATUS4);
break;
case cmRegister: r = AVCLan_SendAnswerFrame((byte*)CMD_REGISTER);
break;
case cmInit: //RS232_Print_P(PSTR("INIT\n"));
r = AVCLan_SendInitCommands();
break;
case cmCheck: r = AVCLan_SendAnswerFrame((byte*)CMD_CHECK);
check_timeout = 0;
CMD_CHECK[6]++;
RS232_Print_P(PSTR("AVCCHK\n"));
break;
case cmPlayReq1: playMode = 0;
r = AVCLan_SendAnswerFrame((byte*)CMD_PLAY_OK1);
break;
case cmPlayReq2:
case cmPlayReq3: playMode = 0;
r = AVCLan_SendAnswerFrame((byte*)CMD_PLAY_OK2);
if (!r) r = AVCLan_SendAnswerFrame((byte*)CMD_PLAY_OK3);
CD_Mode = stPlay;
break;
case cmPlayIt: playMode = 1;
RS232_Print_P(PSTR("PLAY\n"));
CMD_PLAY_OK4[7]=cd_Disc;
CMD_PLAY_OK4[8]=cd_Track;
CMD_PLAY_OK4[9]=cd_Time_Min;
CMD_PLAY_OK4[10]=cd_Time_Sec;
r = AVCLan_SendAnswerFrame((byte*)CMD_PLAY_OK4);
if (!r) AVCLan_Send_Status();
CD_Mode = stPlay;
break;
case cmStopReq:
case cmStopReq2: CD_Mode = stStop;
playMode = 0;
r = AVCLan_SendAnswerFrame((byte*)CMD_STOP1);
CMD_STOP2[7]=cd_Disc;
CMD_STOP2[8]=cd_Track;
CMD_STOP2[9]=cd_Time_Min;
CMD_STOP2[10]=cd_Time_Sec;
r = AVCLan_SendAnswerFrame((byte*)CMD_STOP2);
break;
case cmBeep: AVCLan_SendAnswerFrame((byte*)CMD_BEEP);
break;
}
answerReq = cmNull;
return r;
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
void AVCLan_Register()
{
RS232_Print_P(PSTR("REG_ST\n"));
AVCLan_SendAnswerFrame((byte*)CMD_REGISTER);
RS232_Print_P(PSTR("REG_END\n"));
//AVCLan_Command( cmRegister );
AVCLan_Command( cmInit );
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte AVCLan_Command(byte command)
{
byte r;
answerReq = command;
r = AVCLan_SendAnswer();
/*
RS232_Print_P(PSTR("ret="));
RS232_PrintHex8(r);
RS232_Print_P(PSTR("\n"));
*/
return r;
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte HexInc(byte data)
{
if ((data & 0x9)==0x9)
return (data + 7);
return (data+1);
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
byte HexDec(byte data)
{
if ((data & 0xF)==0)
return (data - 7);
return (data-1);
}
// DONE: Nothing needed.
//------------------------------------------------------------------------------
// encode decimal valute to 'toyota' format :-)
// ex. 42 (dec) = 0x42 (toy)
byte Dec2Toy(byte data)
{
byte d,d1;
d = (unsigned int)data/(unsigned int)10;
d1 = d * 16;
d = d1 + (data - 10*d);
return d;
}
// DONE: No timing adjustment needed.
//------------------------------------------------------------------------------
void ShowInMessage()
{
if (message_len==0) return;
AVC_HoldLine();
RS232_Print_P(PSTR("HU < ("));
if (broadcast==0) RS232_Print_P(PSTR("bro) "));
else RS232_Print_P(PSTR("dir) "));
RS232_PrintHex4(master1);
RS232_PrintHex8(master2);
RS232_Print_P(PSTR("| "));
RS232_PrintHex4(slave1);
RS232_PrintHex8(slave2);
RS232_Print_P(PSTR("| "));
byte i;
for (i=0;i<message_len;i++) {
RS232_PrintHex8(message[i]);
RS232_Print_P(PSTR(" "));
}
RS232_Print_P(PSTR("\n"));
AVC_ReleaseLine();
}
//------------------------------------------------------------------------------
void ShowOutMessage()
{
byte i;
AVC_HoldLine();
RS232_Print_P(PSTR(" out > "));
for (i=0; i<data_len; i++) {
RS232_PrintHex8(data[i]);
RS232_SendByte(' ');
}
RS232_Print_P(PSTR("\n"));
AVC_ReleaseLine();
}
#ifdef SOFTWARE_DEBUG
word temp_b[100];
void AVCLan_Measure()
{
STOPEvent;
//word tmp, tmp1, tmp2, bit0, bit1;
byte n = 0;
cbi(TCCR1B,CS12);
TCCR1B = _BV(CS10);
TCNT1 = 0;
char str[5];
while ( n < 100 )
{
temp_b[n] = TCNT1;
while(INPUT_IS_CLEAR);
temp_b[n+1] = TCNT1;
while(INPUT_IS_SET);
temp_b[n+2] = TCNT1;
while(INPUT_IS_CLEAR);
temp_b[n+3] = TCNT1;
while(INPUT_IS_SET);
temp_b[n+4] = TCNT1;
while(INPUT_IS_CLEAR);
temp_b[n+5] = TCNT1;
while(INPUT_IS_SET);
temp_b[n+6] = TCNT1;
while(INPUT_IS_CLEAR);
temp_b[n+7] = TCNT1;
while(INPUT_IS_SET);
temp_b[n+8] = TCNT1;
while(INPUT_IS_CLEAR);
temp_b[n+9] = TCNT1;
while(INPUT_IS_SET);
//
// while(INPUT_IS_CLEAR);
//
// tmp1 = TCNT1;
//
// while(INPUT_IS_SET);
//
// tmp2 = TCNT1;
//
// bit0 = tmp1-tmp;
// bit1 = tmp2-tmp1;
//
// RS232_Print_P(PSTR("1,"));
// RS232_PrintDec(bit1);
// RS232_Print_P(PSTR("\n"));
//
// RS232_Print_P(PSTR("0,"));
// RS232_PrintDec(bit0);
// RS232_Print_P(PSTR("\n"));
n += 10;
}
for(byte i =0; i < 100; i++)
{
itoa(temp_b[i],str);
if(i & 1) {
RS232_Print_P(PSTR("High,"));
} else {
RS232_Print_P(PSTR("Low,"));
}
RS232_Print(str);
RS232_Print_P(PSTR("\n"));
}
RS232_Print_P(PSTR("\nDone.\n"));
cbi(TCCR1B,CS10);
TCCR1B = _BV(CS12);
STARTEvent;
}
#endif
#ifdef HARDWARE_DEBUG
void SetHighLow() {
AVC_OUT_EN();
sbi(TCCR1B, CS10);
word n = 60000;
TCNT1 = 0;
AVC_SET_LOGICAL_1();
while ( TCNT1 < n );
TCNT1 = 0;
AVC_SET_LOGICAL_0();
while ( TCNT1 < n );
cbi(TCCR1B, CS10);
AVC_OUT_DIS();
}
#endif
//------------------------------------------------------------------------------