/* AVCLAN-Mockingboard Copyright (C) 2015 Allen Hill Portions of the following source code are based on code that is copyright (C) 2006 Marcin Slonicki copyright (C) 2007 Louis Frigon 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 3 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, see . */ #include #include #include #include "avclandrv.h" #include "com232.h" // Enable AVC bus Tx #define AVC_OUT_EN() \ cbi(AC2_CTRLA, AC_ENABLE_bp); \ sbi(VPORTA_DIR, 6); // Disable AVC bus Tx #define AVC_OUT_DIS() \ cbi(VPORTA_DIR, 6); \ sbi(AC2_CTRLA, AC_ENABLE_bp); #define AVC_SET_LOGICAL_1() \ __asm__ __volatile__( \ "sbi %[vporta_out], 6;" ::[vporta_out] "I"(_SFR_IO_ADDR(VPORTA_OUT))); #define AVC_SET_LOGICAL_0() \ __asm__ __volatile__( \ "cbi %[vporta_out], 6;" ::[vporta_out] "I"(_SFR_IO_ADDR(VPORTA_OUT))); // Name difference between avr-libc and Microchip pack #if defined(EVSYS_ASYNCCH00_bm) #define EVSYS_ASYNCCH0_0_bm EVSYS_ASYNCCH00_bm #endif uint16_t CD_ID; uint16_t HU_ID; uint8_t printAllFrames; uint8_t playMode; uint8_t cd_Track; uint8_t cd_Time_Min; uint8_t cd_Time_Sec; uint8_t answerReq; cd_modes CD_Mode; #define SW_ID 0x11 // 11 For my stereo // commands const uint8_t stat1[] = {0x4, 0x00, 0x00, 0x01, 0x0A}; const uint8_t stat2[] = {0x4, 0x00, 0x00, 0x01, 0x08}; const uint8_t stat3[] = {0x4, 0x00, 0x00, 0x01, 0x0D}; const uint8_t stat4[] = {0x4, 0x00, 0x00, 0x01, 0x0C}; // broadcast const uint8_t lan_stat1[] = {0x3, 0x00, 0x01, 0x0A}; const uint8_t lan_reg[] = {0x3, SW_ID, 0x01, 0x00}; const uint8_t lan_init[] = {0x3, SW_ID, 0x01, 0x01}; const uint8_t lan_check[] = {0x3, SW_ID, 0x01, 0x20}; const uint8_t lan_playit[] = {0x4, SW_ID, 0x01, 0x45, 0x63}; const uint8_t play_req1[] = {0x4, 0x00, 0x25, 0x63, 0x80}; #ifdef __AVENSIS__ const uint8_t play_req2[] = {0x6, 0x00, SW_ID, 0x63, 0x42}; #else const uint8_t play_req2[] = {0x6, 0x00, SW_ID, 0x63, 0x42, 0x01, 0x00}; #endif const uint8_t play_req3[] = {0x5, 0x00, SW_ID, 0x63, 0x42, 0x41}; const uint8_t stop_req[] = {0x5, 0x00, SW_ID, 0x63, 0x43, 0x01}; const uint8_t stop_req2[] = {0x5, 0x00, SW_ID, 0x63, 0x43, 0x41}; // Init commands const AVCLAN_KnownMessage_t c8 = { BROADCAST, 11, {0x63, 0x31, 0xF1, 0x00, 0x90, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80}}; const AVCLAN_KnownMessage_t c1 = { BROADCAST, 10, {0x63, 0x31, 0xF1, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80}}; const AVCLAN_KnownMessage_t cA = { BROADCAST, 11, {0x63, 0x31, 0xF1, 0x00, 0x30, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80}}; const AVCLAN_KnownMessage_t c2 = { BROADCAST, 10, {0x63, 0x31, 0xF3, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x02}}; const AVCLAN_KnownMessage_t c3 = { BROADCAST, 10, {0x63, 0x31, 0xF3, 0x00, 0x3F, 0x00, 0x01, 0x00, 0x01, 0x02}}; const AVCLAN_KnownMessage_t c4 = { BROADCAST, 10, {0x63, 0x31, 0xF3, 0x00, 0x3D, 0x00, 0x01, 0x00, 0x01, 0x02}}; const AVCLAN_KnownMessage_t c5 = { BROADCAST, 10, {0x63, 0x31, 0xF3, 0x00, 0x39, 0x00, 0x01, 0x00, 0x01, 0x02}}; const AVCLAN_KnownMessage_t c6 = { BROADCAST, 10, {0x63, 0x31, 0xF3, 0x00, 0x31, 0x00, 0x01, 0x00, 0x01, 0x02}}; const AVCLAN_KnownMessage_t c7 = { BROADCAST, 10, {0x63, 0x31, 0xF3, 0x00, 0x21, 0x00, 0x01, 0x00, 0x01, 0x02}}; const AVCLAN_KnownMessage_t c9 = { BROADCAST, 10, {0x63, 0x31, 0xF3, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x02}}; // answers const AVCLAN_KnownMessage_t CMD_REGISTER = { UNICAST, 5, {0x00, 0x01, SW_ID, 0x10, 0x63}}; const AVCLAN_KnownMessage_t CMD_STATUS1 = { UNICAST, 4, {0x00, 0x01, 0x00, 0x1A}}; const AVCLAN_KnownMessage_t CMD_STATUS2 = { UNICAST, 4, {0x00, 0x01, 0x00, 0x18}}; const AVCLAN_KnownMessage_t CMD_STATUS3 = { UNICAST, 4, {0x00, 0x01, 0x00, 0x1D}}; const AVCLAN_KnownMessage_t CMD_STATUS4 = { UNICAST, 5, {0x00, 0x01, 0x00, 0x1C, 0x00}}; AVCLAN_KnownMessage_t CMD_CHECK = { UNICAST, 6, {0x00, 0x01, SW_ID, 0x30, 0x00, 0x00}}; const AVCLAN_KnownMessage_t CMD_STATUS5 = { UNICAST, 5, {0x00, 0x5C, 0x12, 0x53, 0x02}}; const AVCLAN_KnownMessage_t CMD_STATUS5A = { BROADCAST, 5, {0x5C, 0x31, 0xF1, 0x00, 0x00}}; const AVCLAN_KnownMessage_t CMD_STATUS6 = { UNICAST, 6, {0x00, 0x5C, 0x32, 0xF0, 0x02, 0x00}}; const AVCLAN_KnownMessage_t CMD_PLAY_OK1 = { UNICAST, 5, {0x00, 0x63, SW_ID, 0x50, 0x01}}; const AVCLAN_KnownMessage_t CMD_PLAY_OK2 = { UNICAST, 5, {0x00, 0x63, SW_ID, 0x52, 0x01}}; const AVCLAN_KnownMessage_t CMD_PLAY_OK3 = { BROADCAST, 11, {0x63, 0x31, 0xF1, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80}}; AVCLAN_KnownMessage_t CMD_PLAY_OK4 = { BROADCAST, 11, {0x63, 0x31, 0xF1, 0x01, 0x28, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80}}; const AVCLAN_KnownMessage_t CMD_STOP1 = { UNICAST, 5, {0x00, 0x63, SW_ID, 0x53, 0x01}}; AVCLAN_KnownMessage_t CMD_STOP2 = { BROADCAST, 11, {0x63, 0x31, 0xF1, 0x00, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80}}; const AVCLAN_KnownMessage_t CMD_BEEP = { UNICAST, 5, {0x00, 0x63, 0x29, 0x60, 0x02}}; void AVCLAN_init() { // Pull-ups are disabled by default // Set pin 6 and 7 as input PORTA.DIRCLR = (PIN6_bm | PIN7_bm); PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; // Disable input buffer; PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc; // recommended when using AC // Analog comparator config AC2.CTRLA = AC_OUTEN_bm | AC_HYSMODE_25mV_gc | AC_ENABLE_bm; PORTB.DIRSET = PIN2_bm; // Enable AC2 OUT for LED PORTB.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc; // Output only // TCB1 for send bit timing TCB1.CTRLB = TCB_CNTMODE_INT_gc; TCB1.CCMP = 0xFFFF; TCB1.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm; answerReq = cm_Null; cd_Track = 1; cd_Time_Min = 0; cd_Time_Sec = 0; playMode = 0; CD_Mode = stStop; } void set_AVC_logic_for(uint8_t val, uint16_t period) { TCB1.CNT = 0; if (val) { AVC_SET_LOGICAL_1(); } else { AVC_SET_LOGICAL_0(); } while (TCB1.CNT <= 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_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) } 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) } void AVCLAN_sendbit_ACK() { TCB1.CNT = 0; while (INPUT_IS_CLEAR) { if (TCB1.CNT >= 900) return; // 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(); } void AVCLAN_sendbit_parity(uint8_t parity) { if (parity) { AVCLAN_sendbit_1(); } else { AVCLAN_sendbit_0(); } } #define AVCLAN_sendbits(bits, len) \ _Generic((bits), \ const uint16_t *: AVCLAN_sendbitsl, \ uint16_t *: AVCLAN_sendbitsl, \ const uint8_t *: AVCLAN_sendbitsi, \ uint8_t *: AVCLAN_sendbitsi)(bits, len) // Send `len` bits on the AVCLAN bus; returns the even parity uint8_t AVCLAN_sendbitsi(const uint8_t *byte, int8_t len) { uint8_t b = *byte; uint8_t parity = 0; int8_t len_mod8 = 8; if (len & 0x7) { len_mod8 = (int8_t)(len & 0x7); b <<= (uint8_t)(8 - len_mod8); } while (len > 0) { len -= len_mod8; for (; len_mod8 > 0; len_mod8--) { if (b & 0x80) { AVCLAN_sendbit_1(); parity++; } else { AVCLAN_sendbit_0(); } b <<= 1; } len_mod8 = 8; b = *--byte; } return (parity & 1); } // Send `len` bits on the AVCLAN bus; returns the even parity uint8_t AVCLAN_sendbitsl(const uint16_t *word, int8_t len) { return AVCLAN_sendbitsi((const uint8_t *)word + 1, len); } uint8_t AVCLAN_sendbyte(const uint8_t *byte) { uint8_t b = *byte; uint8_t parity = 0; for (uint8_t nbits = 8; nbits > 0; nbits--) { if (b & 0x80) { AVCLAN_sendbit_1(); parity++; } else { AVCLAN_sendbit_0(); } b <<= 1; } return (parity & 1); } uint8_t AVCLAN_readbyte(uint8_t length, uint8_t *parity) { uint8_t byte = 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 byte++; (*parity)++; } length--; if (!length) return byte; byte = byte << 1; } } 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; 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; } uint8_t CheckCmd(const AVCLAN_frame_t *frame, const uint8_t *cmd) { uint8_t l = *cmd++; for (uint8_t i = 0; i < l; i++) { if (frame->data[i] != *cmd++) return 0; } return 1; } uint8_t AVCLAN_readframe() { STOPEvent; // disable timer1 interrupt uint8_t i; uint8_t for_me = 0; AVCLAN_frame_t frame = {}; // RS232_Print("$ "); // 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("LAN>T1\n"); // return 0; // } // } // // if ( TCNT0 < 20 ) { // 20 us // // TCCR1B = 0; // // TCCR1B |= (1 << WGM12)|(1 << CS12); // STARTEvent; // RS232_Print("LAN>T2\n"); // return 0; // } uint8_t parity = 0; uint8_t parity_check = 0; AVCLAN_readbyte(1, &parity); // Start bit frame.broadcast = AVCLAN_readbyte(1, &parity); parity = 0; uint8_t *controller_hi = ((uint8_t *)&frame.controller_addr) + 1; uint8_t *controller_lo = ((uint8_t *)&frame.controller_addr) + 0; *controller_hi = AVCLAN_readbyte(4, &parity); *controller_lo = AVCLAN_readbyte(8, &parity); if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { STARTEvent; return 0; } parity = 0; uint8_t *peripheral_hi = ((uint8_t *)&frame.peripheral_addr) + 1; uint8_t *peripheral_lo = ((uint8_t *)&frame.peripheral_addr) + 0; *peripheral_hi = AVCLAN_readbyte(4, &parity); *peripheral_lo = AVCLAN_readbyte(8, &parity); if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { STARTEvent; return 0; } // is this command for me ? for_me = (frame.peripheral_addr == CD_ID); if (for_me) AVCLAN_sendbit_ACK(); else AVCLAN_readbyte(1, &parity); parity = 0; frame.control = AVCLAN_readbyte(4, &parity); if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { STARTEvent; return 0; } else if (for_me) { AVCLAN_sendbit_ACK(); } else { AVCLAN_readbyte(1, &parity); } parity = 0; frame.length = AVCLAN_readbyte(8, &parity); if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { STARTEvent; return 0; } else if (for_me) { AVCLAN_sendbit_ACK(); } else { AVCLAN_readbyte(1, &parity); } if (frame.length > MAXMSGLEN) { // RS232_Print("LAN> Command error"); STARTEvent; return 0; } for (i = 0; i < frame.length; i++) { parity = 0; frame.data[i] = AVCLAN_readbyte(8, &parity); if ((parity & 1) != AVCLAN_readbyte(1, &parity_check)) { STARTEvent; return 0; } else if (for_me) { AVCLAN_sendbit_ACK(); } else { AVCLAN_readbyte(1, &parity); } } STARTEvent; if (printAllFrames) AVCLAN_printframe(&frame); if (for_me) { if (CheckCmd(&frame, stat1)) { answerReq = cm_Status1; return 1; } if (CheckCmd(&frame, stat2)) { answerReq = cm_Status2; return 1; } if (CheckCmd(&frame, stat3)) { answerReq = cm_Status3; return 1; } if (CheckCmd(&frame, stat4)) { answerReq = cm_Status4; return 1; } // if (CheckCmd((uint8_t*)stat5)) { answerReq = cm_Status5; return 1; } if (CheckCmd(&frame, play_req1)) { answerReq = cm_PlayReq1; return 1; } if (CheckCmd(&frame, play_req2)) { answerReq = cm_PlayReq2; return 1; } if (CheckCmd(&frame, play_req3)) { answerReq = cm_PlayReq3; return 1; } if (CheckCmd(&frame, stop_req)) { answerReq = cm_StopReq; return 1; } if (CheckCmd(&frame, stop_req2)) { answerReq = cm_StopReq2; return 1; } } else { // broadcast check if (CheckCmd(&frame, lan_playit)) { answerReq = cm_PlayIt; return 1; } if (CheckCmd(&frame, lan_check)) { answerReq = cm_Check; CMD_CHECK.data[4] = frame.data[3]; return 1; } if (CheckCmd(&frame, lan_reg)) { answerReq = cm_Register; return 1; } if (CheckCmd(&frame, lan_init)) { answerReq = cm_Init; return 1; } if (CheckCmd(&frame, lan_stat1)) { answerReq = cm_Status1; return 1; } } answerReq = cm_Null; return 1; } uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) { STOPEvent; // wait for free line uint8_t line_busy = 1; uint8_t parity = 0; 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_sendbit_start(); AVCLAN_sendbits((uint8_t *)&frame->broadcast, 1); parity = AVCLAN_sendbits(&frame->controller_addr, 12); AVCLAN_sendbit_parity(parity); parity = AVCLAN_sendbits(&frame->peripheral_addr, 12); AVCLAN_sendbit_parity(parity); if (!frame->broadcast && AVCLAN_readbit_ACK()) { AVC_OUT_DIS(); STARTEvent; RS232_Print("Error NAK: Addresses\n"); return 1; } parity = AVCLAN_sendbits(&frame->control, 4); AVCLAN_sendbit_parity(parity); if (!frame->broadcast && AVCLAN_readbit_ACK()) { AVC_OUT_DIS(); STARTEvent; RS232_Print("Error NAK: Control\n"); return 2; } parity = AVCLAN_sendbyte(&frame->length); // data length AVCLAN_sendbit_parity(parity); if (!frame->broadcast && AVCLAN_readbit_ACK()) { AVC_OUT_DIS(); STARTEvent; RS232_Print("Error NAK: Message length\n"); return 3; } for (uint8_t i = 0; i < frame->length; i++) { parity = AVCLAN_sendbyte(&frame->data[i]); AVCLAN_sendbit_parity(parity); // Based on the µPD6708 datasheet, ACK bit for broadcast doesn't seem // necessary (i.e. This deviates from the previous broadcast specific // function that sent an extra `1` bit after each byte/parity) if (!frame->broadcast && AVCLAN_readbit_ACK()) { AVC_OUT_DIS(); STARTEvent; RS232_Print("Error ACK 4 (Data uint8_t: "); RS232_PrintDec(i); RS232_Print(")\n"); return 4; } } // back to read mode AVC_OUT_DIS(); STARTEvent; if (printAllFrames) AVCLAN_printframe(frame); return 0; } uint8_t AVCLan_SendInitCommands() { uint8_t r; AVCLAN_frame_t frame = {.broadcast = BROADCAST, .controller_addr = CD_ID, .peripheral_addr = HU_ID, .control = 0xF, .length = c1.length}; frame.data = (uint8_t *)&c1.data[0]; r = AVCLAN_sendframe(&frame); if (!r) { frame.length = c2.length; frame.data = (uint8_t *)&c2.data[0]; r = AVCLAN_sendframe(&frame); // c2 } if (!r) { frame.length = c3.length; frame.data = (uint8_t *)&c3.data[0]; r = AVCLAN_sendframe(&frame); // c3 } if (!r) { frame.length = c4.length; frame.data = (uint8_t *)&c4.data[0]; r = AVCLAN_sendframe(&frame); // c4 } if (!r) { frame.length = c5.length; frame.data = (uint8_t *)&c5.data[0]; r = AVCLAN_sendframe(&frame); // c5 } if (!r) { frame.length = c6.length; frame.data = (uint8_t *)&c6.data[0]; r = AVCLAN_sendframe(&frame); // c6 } if (!r) { frame.length = c7.length; frame.data = (uint8_t *)&c7.data[0]; r = AVCLAN_sendframe(&frame); // c7 } if (!r) { frame.length = c8.length; frame.data = (uint8_t *)&c8.data[0]; r = AVCLAN_sendframe(&frame); // c8 } if (!r) { frame.length = c9.length; frame.data = (uint8_t *)&c9.data[0]; r = AVCLAN_sendframe(&frame); // c9 } if (!r) { frame.length = cA.length; frame.data = (uint8_t *)&cA.data[0]; r = AVCLAN_sendframe(&frame); // cA } // const uint8_t c1[] = { 0x0, 0x0B, 0x63, 0x31, 0xF1, 0x00, 0x80, // 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80 }; r = // AVCLan_SendAnswerFrame((uint8_t*)c1); return r; } void AVCLan_Send_Status() { uint8_t STATUS[] = {0x63, 0x31, 0xF1, 0x01, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x80}; STATUS[6] = cd_Track; STATUS[7] = cd_Time_Min; STATUS[8] = cd_Time_Sec; STATUS[9] = 0; AVCLAN_frame_t status = {.broadcast = UNICAST, .controller_addr = CD_ID, .peripheral_addr = HU_ID, .control = 0xF, .length = 11, .data = &STATUS[0]}; AVCLAN_sendframe(&status); } uint8_t AVCLan_SendAnswer() { uint8_t r = 0; AVCLAN_frame_t frame = {.broadcast = UNICAST, .controller_addr = CD_ID, .peripheral_addr = HU_ID, .control = 0xF, .length = 0}; switch (answerReq) { case cm_Status1: frame.broadcast = CMD_STATUS1.broadcast; frame.length = CMD_STATUS1.length; frame.data = (uint8_t *)&CMD_STATUS1.data[0]; r = AVCLAN_sendframe(&frame); break; case cm_Status2: frame.broadcast = CMD_STATUS2.broadcast; frame.length = CMD_STATUS2.length; frame.data = (uint8_t *)&CMD_STATUS2.data[0]; r = AVCLAN_sendframe(&frame); break; case cm_Status3: frame.broadcast = CMD_STATUS3.broadcast; frame.length = CMD_STATUS3.length; frame.data = (uint8_t *)&CMD_STATUS3.data[0]; r = AVCLAN_sendframe(&frame); break; case cm_Status4: frame.broadcast = CMD_STATUS4.broadcast; frame.length = CMD_STATUS4.length; frame.data = (uint8_t *)&CMD_STATUS4.data[0]; r = AVCLAN_sendframe(&frame); break; case cm_Register: frame.broadcast = CMD_REGISTER.broadcast; frame.length = CMD_REGISTER.length; frame.data = (uint8_t *)&CMD_REGISTER.data[0]; r = AVCLAN_sendframe(&frame); break; case cm_Init: // RS232_Print("INIT\n"); r = AVCLan_SendInitCommands(); break; case cm_Check: frame.broadcast = CMD_CHECK.broadcast; frame.length = CMD_CHECK.length; frame.data = &CMD_CHECK.data[0]; r = AVCLAN_sendframe(&frame); CMD_CHECK.data[6]++; RS232_Print("AVCCHK\n"); break; case cm_PlayReq1: playMode = 0; frame.broadcast = CMD_PLAY_OK1.broadcast; frame.length = CMD_PLAY_OK1.length; frame.data = (uint8_t *)&CMD_PLAY_OK1.data[0]; r = AVCLAN_sendframe(&frame); break; case cm_PlayReq2: case cm_PlayReq3: playMode = 0; frame.broadcast = CMD_PLAY_OK2.broadcast; frame.length = CMD_PLAY_OK2.length; frame.data = (uint8_t *)&CMD_PLAY_OK2.data[0]; r = AVCLAN_sendframe(&frame); if (!r) { frame.broadcast = CMD_PLAY_OK3.broadcast; frame.length = CMD_PLAY_OK3.length; frame.data = (uint8_t *)&CMD_PLAY_OK3.data[0]; r = AVCLAN_sendframe(&frame); } CD_Mode = stPlay; break; case cm_PlayIt: playMode = 1; RS232_Print("PLAY\n"); frame.broadcast = CMD_PLAY_OK4.broadcast; frame.length = CMD_PLAY_OK4.length; frame.data = (uint8_t *)&CMD_PLAY_OK4.data[0]; CMD_PLAY_OK4.data[8] = cd_Track; CMD_PLAY_OK4.data[9] = cd_Time_Min; CMD_PLAY_OK4.data[10] = cd_Time_Sec; r = AVCLAN_sendframe(&frame); if (!r) AVCLan_Send_Status(); CD_Mode = stPlay; break; case cm_StopReq: case cm_StopReq2: CD_Mode = stStop; playMode = 0; frame.broadcast = CMD_STOP1.broadcast; frame.length = CMD_STOP1.length; frame.data = (uint8_t *)&CMD_STOP1.data[0]; r = AVCLAN_sendframe(&frame); CMD_STOP2.data[8] = cd_Track; CMD_STOP2.data[9] = cd_Time_Min; CMD_STOP2.data[10] = cd_Time_Sec; frame.broadcast = CMD_STOP2.broadcast; frame.length = CMD_STOP2.length; frame.data = (uint8_t *)&CMD_STOP2.data[0]; r = AVCLAN_sendframe(&frame); break; case cm_Beep: frame.broadcast = CMD_BEEP.broadcast; frame.length = CMD_BEEP.length; frame.data = (uint8_t *)&CMD_BEEP.data[0]; r = AVCLAN_sendframe(&frame); break; } answerReq = cm_Null; return r; } void AVCLan_Register() { AVCLAN_frame_t register_frame = {.broadcast = CMD_REGISTER.broadcast, .controller_addr = CD_ID, .peripheral_addr = HU_ID, .control = 0xF, .length = CMD_REGISTER.length, .data = (uint8_t *)&CMD_REGISTER.data[0]}; RS232_Print("REG_ST\n"); AVCLAN_sendframe(®ister_frame); RS232_Print("REG_END\n"); // AVCLan_Command( cm_Register ); answerReq = cm_Init; AVCLan_SendAnswer(); } void AVCLAN_printframe(const AVCLAN_frame_t *frame) { if (frame->peripheral_addr == CD_ID || (frame->broadcast && frame->peripheral_addr == 0x1FF)) RS232_Print(" < "); else RS232_Print(">< "); RS232_PrintHex4(frame->broadcast); RS232_Print(" 0x"); RS232_PrintHex4(*(((uint8_t *)&frame->controller_addr) + 1)); RS232_PrintHex8(*(((uint8_t *)&frame->controller_addr) + 0)); RS232_Print(" 0x"); RS232_PrintHex4(*(((uint8_t *)&frame->peripheral_addr) + 1)); RS232_PrintHex8(*(((uint8_t *)&frame->peripheral_addr) + 0)); RS232_Print(" 0x"); RS232_PrintHex4(frame->control); RS232_Print(" 0x"); RS232_PrintHex4(frame->length); for (uint8_t i = 0; i < frame->length; i++) { RS232_Print(" 0x"); RS232_PrintHex8(frame->data[i]); } RS232_Print("\n"); } #ifdef SOFTWARE_DEBUG uint16_t temp_b[100]; void AVCLan_Measure() { STOPEvent; // uint16_t tmp, tmp1, tmp2, bit0, bit1; uint8_t 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("1,"); // RS232_PrintDec(bit1); // RS232_Print("\n"); // // RS232_Print("0,"); // RS232_PrintDec(bit0); // RS232_Print("\n"); n += 10; } for (uint8_t i = 0; i < 100; i++) { itoa(temp_b[i], str); if (i & 1) { RS232_Print("High,"); } else { RS232_Print("Low,"); } RS232_Print(str); RS232_Print("\n"); } RS232_Print("\nDone.\n"); cbi(TCCR1B, CS10); TCCR1B = _BV(CS12); STARTEvent; } #endif #ifdef HARDWARE_DEBUG void SetHighLow() { AVC_OUT_EN(); sbi(TCCR1B, CS10); uint16_t 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