/* Copyright (C) 2015 Allen Hill . Portions of the following source code are: Copyright (C) 2006 Marcin Slonicki . 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 #include #include #include "avclandrv.h" #include "com232.h" #include "GlobalDef.h" //------------------------------------------------------------------------------ #define AVC_OUT_EN() sbi(PORTD, 6); sbi(DDRD, 6); sbi(DDRD, 7); sbi(ACSR, ACD); #define AVC_OUT_DIS() cbi(PORTD, 6); cbi(DDRD, 6); cbi(DDRD, 7); cbi(ACSR, ACD); #define AVC_SET_1() sbi(PORTD, 6); #define AVC_SET_0() cbi(PORTD, 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[] = { 0x6, 0x00, SW_ID, 0x63, 0x42, 0x41, 0x00 }; 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; TCNT0 = 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 (TCNT0 >= 225) break; } if (TCNT0 > 216) line_busy=0; } while (line_busy); // switch to out mode AVC_OUT_EN(); AVC_SET_1(); STARTEvent; } // DONE: No changes necessary //------------------------------------------------------------------------------ void AVC_ReleaseLine() { AVC_SET_0(); AVC_OUT_DIS(); } //------------------------------------------------------------------------------ // DONE: No changes necessary //------------------------------------------------------------------------------ void AVCLan_Init() { // OUTPUT ( set as input for comparator ) cbi(PORTD, 6); cbi(DDRD, 6); // INPUT cbi(PORTD, 7); cbi(DDRD, 7); // Analog comparator cbi(ADCSRB, ACME); // Analog Comparator Multiplexer Enable - NO /* cbi(ACSR, ACBG); // Analog Comparator Bandgap Select // ACI: Analog Comparator Interrupt Flag 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; 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); TCNT0 = 0; while (INPUT_IS_SET); if ( TCNT0 < 72 ) { bite++; parity_bit++; } length--; if (!length) return bite; bite = bite << 1; } } // DONE: Timing adjusted //------------------------------------------------------------------------------ byte AVCLan_Send_StartBit() { AVC_SET_1(); TCNT0 = 0; while( TCNT0 < 333 ); AVC_SET_0(); TCNT0 = 0; while( TCNT0 < 61 ); return 1; } // DONE: Timing adjusted. Comparison values are timer ticks, not us. //------------------------------------------------------------------------------ void AVCLan_Send_Bit1() { AVC_SET_1(); TCNT0 = 0; while( TCNT0 < 41 ); AVC_SET_0(); TCNT0 = 0; while( TCNT0 < 33 ); // 12-21 us } // DONE: Timing adjusted //------------------------------------------------------------------------------ void AVCLan_Send_Bit0() { AVC_SET_1(); TCNT0 = 0; while( TCNT0 < 65 ); // 28-37 us AVC_SET_0(); TCNT0 = 0; while( TCNT0 < 9 ); // 00-09 us } // DONE: Timing adjusted. //------------------------------------------------------------------------------ byte AVCLan_Read_ACK() { AVC_SET_1(); TCNT0 = 0; while( TCNT0 < 39 ); AVC_SET_0(); TCNT0 = 0; while( TCNT0 < 3 ); AVC_OUT_DIS(); // switch to read mode TCNT0 = 1; while(1) { if (INPUT_IS_SET && (TCNT0 > 2)) break; if (TCNT0 > 41) return 1; // Not sure if this fix is intent correct } while(INPUT_IS_SET); AVC_OUT_EN(); // back to write mode return 0; } // DONE: Timing adjusted. //------------------------------------------------------------------------------ byte AVCLan_Send_ACK() { TCNT0 = 0; while (INPUT_IS_CLEAR) { if (TCNT0 >= 225) return 0; // max wait time } AVC_OUT_EN(); AVC_SET_1(); TCNT0 = 0; while( TCNT0 < 65 ); //28-37 AVC_SET_0(); TCNT0 = 0; while( TCNT0 < 9 ); //00-09 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_S((unsigned char)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 2286 ) { // Originally 254 STARTEvent; RS232_S((unsigned char)PSTR("LAN>T1\n")); return 0; } } if ( TCNT0 < 90 ) { // !!!!!!! 20 !!!!!!!!!!! (Originally 10) STARTEvent; RS232_S((unsigned char)PSTR("LAN>T2\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==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_S((unsigned char)PSTR("LAN> Command error")); STARTEvent; return 0; } for (i=0; i= 225 ) break; } if ( TCNT0 > 216 ) 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_S((unsigned char)PSTR("E1\n")); return 1; } AVCLan_Send_Byte(0xF, 4); // 0xf - control -> COMMAND WRITE AVCLan_Send_ParityBit(); if (AVCLan_Read_ACK()) { AVC_OUT_DIS(); STARTEvent; RS232_S((unsigned char)PSTR("E2\n")); return 2; } AVCLan_Send_Byte(data_len, 8);// data length AVCLan_Send_ParityBit(); if (AVCLan_Read_ACK()) { AVC_OUT_DIS(); STARTEvent; RS232_S((unsigned char)PSTR("E3\n")); return 3; } for (i=0;i= 225 ) break; } if ( TCNT0 > 216 ) 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 ")); for (i=0; i