/* Copyright (C) 2006 Marcin Slonicki . Some parts modify from original file written by: Vitaliy Koutchaev - part of the IP-Bus emu system. 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 part of TOYOTA AVC-Lan CD-Changer Emulator */ #include #include #include #include #include #include #include "timer.h" #include "avclandrv.h" #include "delay.h" #include "const.h" #include "com232.h" #include "sniffit.h" //------------------------------------------------------------------------------ u08 parity_bit; u08 scanMode; u08 playMode; u08 retries; // cd changer commands const u08 stat1[] PROGMEM = { 0x4, 0x00, 0x00, 0x01, 0x0A }; const u08 stat2[] PROGMEM = { 0x4, 0x00, 0x00, 0x01, 0x08 }; const u08 stat3[] PROGMEM = { 0x4, 0x00, 0x00, 0x01, 0x0D }; const u08 stat4[] PROGMEM = { 0x4, 0x00, 0x00, 0x01, 0x0C }; const u08 play_req1[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0x80 }; u08 play_req2[] = { 0x5, 0x00, 0xFF, 0x63, 0x42, 0x01}; //version dependant u08 play_req3[] = { 0x6, 0x00, 0xFF, 0x63, 0x42, 0x41, 0x00 }; //version dependant u08 play_req4[] = { 0x6, 0x00, 0xFF, 0x63, 0x42, 0x41, 0x01 }; //version dependant u08 stop_req[] = { 0x5, 0x00, 0xFF, 0x63, 0x43, 0x01 }; //version dependant u08 stop_req2[] = { 0x5, 0x00, 0xFF, 0x63, 0x43, 0x41 }; //version dependant const u08 PROGMEM next_track[] = { 0x4, 0x00, 0x25, 0x63, 0x94 }; const u08 PROGMEM prev_track[] = { 0x4, 0x00, 0x25, 0x63, 0x95 }; const u08 next_cd[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0x90 }; const u08 prev_cd[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0x91 }; const u08 CD[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0x92}; const u08 fast_forward[] PROGMEM= { 0x4, 0x00, 0x25, 0x63, 0x98 }; const u08 fast_back[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0x99 }; const u08 scan_on[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xA6 }; const u08 scan_off[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xA7 }; const u08 scan_d_on[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xA9 }; const u08 scan_d_off[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xAA }; const u08 repeat_on[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xA0 }; const u08 repeat_off[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xA1 }; const u08 repeat_d_on[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xA3 }; const u08 repeat_d_off[] PROGMEM= { 0x4, 0x00, 0x25, 0x63, 0xA4 }; const u08 random_on[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xB0 }; const u08 random_off[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xB1 }; const u08 random_d_on[] PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xB3 }; const u08 random_d_off[]PROGMEM = { 0x4, 0x00, 0x25, 0x63, 0xB4 }; const u08 trackdiscstatus[] PROGMEM= {0x4, 0x00, 0x31, 0x63, 0xE2 }; const u08 discstatus[] PROGMEM = {0x4, 0x00, 0x31, 0x63, 0xE0 }; const u08 broadcastyourstatus[] PROGMEM={0x4, 0x00, 0x12, 0x63, 0x8E }; const u08 changerstatus2[] PROGMEM= {0x4, 0x00, 0x31, 0x63, 0xE4 }; const u08 aslon[] PROGMEM = { 0x4, 0x00, 0x25,0x74,0xB0 }; const u08 asloff[] PROGMEM = { 0x4, 0x00, 0x25,0x74,0xB0 }; // broadcast const u08 lan_stat1[] PROGMEM = { 0x3, 0x00, 0x01, 0x0A }; const u08 lan_reg_11[] PROGMEM = { 0x3, 0x11, 0x01, 0x00 }; const u08 lan_init_11[] PROGMEM = { 0x3, 0x11, 0x01, 0x01 }; const u08 lan_reg_12[] PROGMEM = { 0x3, 0x12, 0x01, 0x00 }; const u08 lan_init_12[] PROGMEM = { 0x3, 0x12, 0x01, 0x01 }; u08 lan_check[] = { 0x3, 0xFF, 0x01, 0x20 }; //version dependent u08 lan_check2[] = { 0x4, 0x00, 0xFF, 0x01, 0x20 }; //version dependent u08 lan_playit[] = { 0x4, 0xFF, 0x01, 0x45, 0x63 };;//version dependant // answers u08 CMD_REGISTER[] = {0x1, 0x05, 0x00, 0x01, 0xFF, 0x10, 0x63 }; //version dependant u08 CMD_PLAY_OK1[] = {0x1, 0x05, 0x00, 0x63, 0xFF, 0x50, 0x01 }; //version dependant u08 CMD_PLAY_OK2[] = {0x1, 0x05, 0x00, 0x63, 0xFF, 0x52, 0x01 }; //version dependant u08 CMD_STOP1[] = {0x1, 0x05, 0x00, 0x63, 0xFF, 0x53, 0x01 }; //version dependant const u08 CMD_STATUS1[] = {0x1, 0x04, 0x00, 0x01, 0x00, 0x1A }; const u08 CMD_STATUS2[] = {0x1, 0x04, 0x00, 0x01, 0x00, 0x18 }; const u08 CMD_STATUS3[] = {0x1, 0x04, 0x00, 0x01, 0x00, 0x1D }; const u08 CMD_STATUS4[] = {0x1, 0x05, 0x00, 0x01, 0x00, 0x1C, 0x00 }; u08 CMD_CHECK[] = {0x1, 0x06, 0x00, 0x01, 0x12, 0x30, 0x05, 0x00 }; const u08 CMD_NOCART[] = {0x0, 0x04, 0x63, 0x31, 0x9F, 0x00}; u08 CMD_PLAY_OK3[] = {0x0, 0x0B, 0x63, 0x31, 0xF1, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80 }; u08 CMD_PLAY_OK4[] = {0x0, 0x0B, 0x63, 0x31, 0xF1, 0x05, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }; u08 CMD_PLAY_OK5[] = {0x0, 0x05, 0x63, 0x31, 0xF7, 0x05, 0x63}; u08 CMD_STOP2[] = {0x0, 0x0B, 0x63, 0x31, 0xF1, 0x00, 0x30, 0x00, 0x00,0x00, 0x00, 0x00, 0x80 }; u08 CMD_DISCS_INCHANGER_BC[] = { 0x0, 0x0A, 0x63, 0x31, 0xF3, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x05}; u08 CMD_DISCS_INCHANGER_DR[] = { 0x2, 0x0B, 0x00, 0x63, 0x31, 0xF3, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x05}; //------------------------------------------------------------------------------ void Set_AVC_Version(u08 *cmd,u08 avcversion,int i) { cmd[i] = avcversion; return; } void Init_Commands(u08 avcversion) { Set_AVC_Version(lan_check, avcversion,1); Set_AVC_Version(lan_check2, avcversion,2); Set_AVC_Version(lan_playit, avcversion,1); Set_AVC_Version(play_req2, avcversion,2); Set_AVC_Version(play_req3, avcversion,2); Set_AVC_Version(play_req4, avcversion,2); Set_AVC_Version(stop_req, avcversion,2); Set_AVC_Version(stop_req2, avcversion,2); Set_AVC_Version(CMD_PLAY_OK1, avcversion,4); Set_AVC_Version(CMD_PLAY_OK2, avcversion,4); Set_AVC_Version(CMD_STOP1, avcversion,4); } //------------------------------------------------------------------------------ void AVCLan_Init() { // AVCLan TX+/TX- write line OUTPUT sbi(DATAOUT_DDR, DATAOUT); sbi(DATAOUT_PORT, DATAOUT); //message_len = 0; answerReq = cmNull; cd_Disc = 1; cd_Track = 1; //cd_Time_Min = 0; //cd_Time_Sec = 0; //repeatMode = 0; //randomMode = 0; //playMode = 0; CD_Mode = stStop; masterDevice1 = eeprom_read_byte(EEPROM_MasterDevice1); masterDevice2 = eeprom_read_byte(EEPROM_MasterDevice2); Init_Commands(eeprom_read_byte(EEPROM_AVCVersion)); //masterDevice1 = 0x04; //masterDevice2 = 0x40; } //------------------------------------------------------------------------------ u08 AVCLan_Read_Byte(u08 length) { u08 byte = 0; u08 wT; while (1) { while (INPUT_IS_CLEAR); timer0_start(); while (INPUT_IS_SET); wT = inp(TCNT0); if (wT<8) { byte++; parity_bit++; } length--; if (!length) return byte; byte = byte << 1; } } //------------------------------------------------------------------------------ u08 AVCLan_Send_StartBit() { cbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to output and this be = 1 on IP-Bus delay1(166); // 141-192 sbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to input delay1(30); // 02-57 return 1; } //------------------------------------------------------------------------------ void AVCLan_Send_Bit1() { cbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to output and this be = 1 on IP-Bus delay1(20); // 17-23 sbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to input delay1(16); // 12-21 } //------------------------------------------------------------------------------ void AVCLan_Send_Bit0() { cbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to output and this be = 1 on IP-Bus delay1(32); // 28-37 sbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to input delay1(4); // 00-09 } //------------------------------------------------------------------------------ u08 AVCLan_Read_ACK() { u08 time = 0; cbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to output and this be = 1 on IP-Bus delay1(19); sbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to input timer0_source(CK64); timer0_start(); while(1) { time = inp(TCNT0); if (INPUT_IS_SET && (time > 1)) break; if (time > 5) return 1; } while(INPUT_IS_SET); return 0; } //------------------------------------------------------------------------------ u08 AVCLan_Send_ACK() { timer0_source(CK64); //update every 1us timer0_start(); while (INPUT_IS_CLEAR) { if (inp(TCNT0) >= 25) return 0; // max wait time } cbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to output and this be = 1 on IP-Bus delay1(32); //28-37 sbi(DATAOUT_PORT, DATAOUT); // DATA_OUT pin set to input delay1(4); //00-09 return 1; } //------------------------------------------------------------------------------ u08 AVCLan_Send_Byte(u08 byte, u08 len) { u08 b; if (len==8) { b = byte; } else { b = byte << (8-len); } while (1) { if ( b & 128 ) { AVCLan_Send_Bit1(); parity_bit++; } else { AVCLan_Send_Bit0(); } len--; if (!len) { return 1; } b = b << 1; } } //------------------------------------------------------------------------------ u08 AVCLan_Send_ParityBit() { if ( parity_bit & 1 ) { AVCLan_Send_Bit1(); parity_bit++; } else { AVCLan_Send_Bit0(); } parity_bit=0; return 1; } //------------------------------------------------------------------------------ u08 CheckCmd(u08 *cmd) { u08 i; u08 *c; u08 l; c = cmd; l = *c++; for (i=0; i254) { STARTEvent; //RS232_Print("err1\n"); return 0; } } if (T<10) { STARTEvent; //RS232_Print("err2\n"); return 0; } ; 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==MY_ID_1)&&(slave2==MY_ID_2)) { for_me=1; } #ifdef SNIFFER { // never for me for_me=0; }; #endif 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) { STARTEvent; return 0; } for (i=0; i1) { cd_Disc--; }; return 1; } if (CheckCmd_P((u08*)fast_forward)) { #ifdef SNIFFER RS232_Print("P_FF\n"); #endif CD_Mode= stFF; return 1; } if (CheckCmd_P((u08*)fast_back)) { #ifdef SNIFFER RS232_Print("P_FB\n"); #endif CD_Mode = stRR; return 1; } if (CheckCmd_P((u08*)repeat_on)) { repeatMode = 1; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("REP1\n"); #endif return 1; } if (CheckCmd_P((u08*)repeat_off)) { repeatMode = 0; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("REP0\n"); #endif return 1; } if (CheckCmd_P((u08*)repeat_d_on)) { repeatMode = 2; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("REP2\n"); #endif return 1; } if (CheckCmd_P((u08*)repeat_d_off)) { repeatMode = 0; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("REP0\n"); #endif return 1; } if (CheckCmd_P((u08*)random_on)) { randomMode = 1; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("RND1\n"); #endif return 1; } if (CheckCmd_P((u08*)random_off)) { randomMode = 0; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("RND0\n"); #endif return 1; } if (CheckCmd_P((u08*)random_d_on)) { randomMode = 2; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("RND2\n"); #endif return 1; } if (CheckCmd_P((u08*)random_d_off)) { randomMode = 0; Event |= EV_STATUS; #ifdef SNIFFER RS232_Print("RND0\n"); #endif return 1; } if (CheckCmd_P((u08*)scan_on)) { //scanMode = 1; SwitchInputs(); #ifdef SNIFFER RS232_Print("SCN1\n"); #endif return 1; } if (CheckCmd_P((u08*)scan_off)) { scanMode = 0; #ifdef SNIFFER RS232_Print("SCN0\n"); #endif return 1; } if (CheckCmd_P((u08*)scan_d_on)) { //scanMode = 2; #ifdef SNIFFER RS232_Print("SCN2\n"); #endif return 1; } if (CheckCmd_P((u08*)scan_d_off)) { scanMode = 0; #ifdef SNIFFER RS232_Print("SCN0\n"); #endif return 1; } if (CheckCmd_P((u08*)stat1)) { answerReq = cmStatus1; return 1; } if (CheckCmd_P((u08*)stat2)) { answerReq = cmStatus2; return 1; } if (CheckCmd_P((u08*)stat3)) { answerReq = cmStatus3; return 1; } if (CheckCmd_P((u08*)stat4)) { answerReq = cmStatus4; return 1; } if (CheckCmd_P((u08*)play_req1)) { #ifdef SNIFFER RS232_Print("play_req1\n"); #endif if (1) answerReq = cmNoCart; else answerReq = cmPlayReq1; return 1; } if (CheckCmd((u08*)play_req2)) { #ifdef SNIFFER RS232_Print("play_req2\n"); #endif answerReq = cmPlayReq2; return 1; } if (CheckCmd((u08*)play_req3)) { #ifdef SNIFFER RS232_Print("play_req3\n"); #endif answerReq = cmPlayReq3; return 1; } if (CheckCmd((u08*)play_req4)) { #ifdef SNIFFER RS232_Print("play_req4\n"); #endif answerReq = cmPlayReq4; return 1; } if (CheckCmd((u08*)stop_req)) { #ifdef SNIFFER RS232_Print("stop_req\n"); #endif answerReq = cmStopReq; return 1; } if (CheckCmd_P((u08*)discstatus)) { #ifdef SNIFFER RS232_Print("discstatus\n"); #endif answerReq = cmDiscStatus; return 1; } if (CheckCmd_P((u08*)trackdiscstatus)) { #ifdef SNIFFER RS232_Print("trackdiscstatus\n"); #endif answerReq = cmTrackDiscStatus; return 1; } if (CheckCmd_P((u08*)broadcastyourstatus)) { //broadcast your info #ifdef SNIFFER RS232_Print("changerstatus\n"); #endif answerReq = cmInit; return 1; } if (CheckCmd_P((u08*)changerstatus2)) { //direct response back #ifdef SNIFFER RS232_Print("changerstatus\n"); #endif answerReq = cmCartStatus; return 1; } if (CheckCmd((u08*)lan_check2)) { #ifdef SNIFFER RS232_Print("lan_check2\n"); #endif answerReq = cmCheck; CMD_CHECK[6]=message[4]; CMD_CHECK[4]=message[1]; return 1; } // unknown command received, log it u08 i; eeprom_write_byte(EEPROM_UnknownCommand,message_len); for (i=0;i= 25) break; } if (T > 24) line_busy=0; } while (line_busy); STOPEvent; AVCLan_Send_StartBit(); AVCLan_Send_Byte(0x1, 1); // regular communication parity_bit = 0; AVCLan_Send_Byte(MY_ID_1, 4); // CD Changer ID as master AVCLan_Send_Byte(MY_ID_2, 8); AVCLan_Send_ParityBit(); AVCLan_Send_Byte(m1, 4); // HeadUnit ID as slave AVCLan_Send_Byte(m2, 8); AVCLan_Send_ParityBit(); if (AVCLan_Read_ACK()) { STARTEvent; return 1; } AVCLan_Send_Byte(0xF, 4); // 0xf - control -> COMMAND WRITE AVCLan_Send_ParityBit(); if (AVCLan_Read_ACK()) { STARTEvent; return 2; } AVCLan_Send_Byte(data_len, 8);// data lenght AVCLan_Send_ParityBit(); if (AVCLan_Read_ACK()) { STARTEvent; return 3; } for (i=0;i= 25) break; } if (T > 24) line_busy=0; } while (line_busy); STOPEvent; AVCLan_Send_StartBit(); AVCLan_Send_Byte(0x0, 1); // broadcast parity_bit = 0; AVCLan_Send_Byte(MY_ID_1, 4); // CD Changer ID as master AVCLan_Send_Byte(MY_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 5) { answerReq= cmNull; retries=0; }; }; }; return r; } //------------------------------------------------------------------------------ u08 HexInc(u08 data) { if ((data & 0x9)==0x9) return (data + 7); return (data+1); } //------------------------------------------------------------------------------ u08 HexDec(u08 data) { if ((data & 0xF)==0) return (data - 7); return (data-1); } //------------------------------------------------------------------------------