From 94d0e5d3fe8215581057759edff790dc89f75bf4 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 20 Jun 2017 02:51:35 +0300 Subject: [PATCH] Move one variant, create other for sniffing --- .../{ => mini1}/AVCLan_mini/AVCLan_mini.ino | 0 .../libraries/AVCLanDrv/AVCLanDrv.cpp | 0 .../libraries/AVCLanDrv/AVCLanDrv.h | 0 .../libraries/AVCLanDrv/WProgram.h | 0 .../{ => mini1}/libraries/AVCLanDrv/config.h | 0 .../libraries/BuffSerial/BuffSerial.cpp | 0 .../libraries/BuffSerial/BuffSerial.h | 0 arduino/mini2/AVCLan_mini/AVCLan_mini.ino | 212 +++++++ arduino/mini2/AVCLan_mini/changelog.txt | 20 + .../mini2/libraries/AVCLanCDch/AVCLanCDch.cpp | 293 +++++++++ .../mini2/libraries/AVCLanCDch/AVCLanCDch.h | 102 +++ .../mini2/libraries/AVCLanCDch/changelog.txt | 11 + .../mini2/libraries/AVCLanDrv/AVCLanDrv.cpp | 579 ++++++++++++++++++ arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.h | 131 ++++ .../mini2/libraries/AVCLanDrv/changelog.txt | 15 + arduino/mini2/libraries/AVCLanDrv/config.h | 137 +++++ .../mini2/libraries/AVCLanNavi/AVCLanNavi.cpp | 64 ++ .../mini2/libraries/AVCLanNavi/AVCLanNavi.h | 41 ++ .../mini2/libraries/AVCLanNavi/changelog.txt | 0 .../mini2/libraries/BuffSerial/BuffSerial.cpp | 176 ++++++ .../mini2/libraries/BuffSerial/BuffSerial.h | 54 ++ .../mini2/libraries/BuffSerial/changelog.txt | 2 + arduino/mini2/libraries/readme.txt | 1 + 23 files changed, 1838 insertions(+) rename arduino/{ => mini1}/AVCLan_mini/AVCLan_mini.ino (100%) rename arduino/{ => mini1}/libraries/AVCLanDrv/AVCLanDrv.cpp (100%) rename arduino/{ => mini1}/libraries/AVCLanDrv/AVCLanDrv.h (100%) rename arduino/{ => mini1}/libraries/AVCLanDrv/WProgram.h (100%) rename arduino/{ => mini1}/libraries/AVCLanDrv/config.h (100%) rename arduino/{ => mini1}/libraries/BuffSerial/BuffSerial.cpp (100%) rename arduino/{ => mini1}/libraries/BuffSerial/BuffSerial.h (100%) create mode 100644 arduino/mini2/AVCLan_mini/AVCLan_mini.ino create mode 100644 arduino/mini2/AVCLan_mini/changelog.txt create mode 100644 arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.cpp create mode 100644 arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.h create mode 100644 arduino/mini2/libraries/AVCLanCDch/changelog.txt create mode 100644 arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.cpp create mode 100644 arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.h create mode 100644 arduino/mini2/libraries/AVCLanDrv/changelog.txt create mode 100644 arduino/mini2/libraries/AVCLanDrv/config.h create mode 100644 arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.cpp create mode 100644 arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.h create mode 100644 arduino/mini2/libraries/AVCLanNavi/changelog.txt create mode 100644 arduino/mini2/libraries/BuffSerial/BuffSerial.cpp create mode 100644 arduino/mini2/libraries/BuffSerial/BuffSerial.h create mode 100644 arduino/mini2/libraries/BuffSerial/changelog.txt create mode 100644 arduino/mini2/libraries/readme.txt diff --git a/arduino/AVCLan_mini/AVCLan_mini.ino b/arduino/mini1/AVCLan_mini/AVCLan_mini.ino similarity index 100% rename from arduino/AVCLan_mini/AVCLan_mini.ino rename to arduino/mini1/AVCLan_mini/AVCLan_mini.ino diff --git a/arduino/libraries/AVCLanDrv/AVCLanDrv.cpp b/arduino/mini1/libraries/AVCLanDrv/AVCLanDrv.cpp similarity index 100% rename from arduino/libraries/AVCLanDrv/AVCLanDrv.cpp rename to arduino/mini1/libraries/AVCLanDrv/AVCLanDrv.cpp diff --git a/arduino/libraries/AVCLanDrv/AVCLanDrv.h b/arduino/mini1/libraries/AVCLanDrv/AVCLanDrv.h similarity index 100% rename from arduino/libraries/AVCLanDrv/AVCLanDrv.h rename to arduino/mini1/libraries/AVCLanDrv/AVCLanDrv.h diff --git a/arduino/libraries/AVCLanDrv/WProgram.h b/arduino/mini1/libraries/AVCLanDrv/WProgram.h similarity index 100% rename from arduino/libraries/AVCLanDrv/WProgram.h rename to arduino/mini1/libraries/AVCLanDrv/WProgram.h diff --git a/arduino/libraries/AVCLanDrv/config.h b/arduino/mini1/libraries/AVCLanDrv/config.h similarity index 100% rename from arduino/libraries/AVCLanDrv/config.h rename to arduino/mini1/libraries/AVCLanDrv/config.h diff --git a/arduino/libraries/BuffSerial/BuffSerial.cpp b/arduino/mini1/libraries/BuffSerial/BuffSerial.cpp similarity index 100% rename from arduino/libraries/BuffSerial/BuffSerial.cpp rename to arduino/mini1/libraries/BuffSerial/BuffSerial.cpp diff --git a/arduino/libraries/BuffSerial/BuffSerial.h b/arduino/mini1/libraries/BuffSerial/BuffSerial.h similarity index 100% rename from arduino/libraries/BuffSerial/BuffSerial.h rename to arduino/mini1/libraries/BuffSerial/BuffSerial.h diff --git a/arduino/mini2/AVCLan_mini/AVCLan_mini.ino b/arduino/mini2/AVCLan_mini/AVCLan_mini.ino new file mode 100644 index 0000000..cc3de48 --- /dev/null +++ b/arduino/mini2/AVCLan_mini/AVCLan_mini.ino @@ -0,0 +1,212 @@ +/* + AVCLan mini, connecting 'duino to AVCLan bus. + Created by Kochetkov Aleksey, 04.08.2010 + Version 0.1.7 +*/ + +#define AVCLAN_VERSION "0.1.7" + +#include +#include +#include +#include +#include + +byte readSeq = 0; +byte s_len = 0; +byte s_dig = 0; +byte s_c[2]; +byte data_tmp[32]; +byte i; + +// адреса eeprom +#define E_MASTER1 0 // адрес головы, старший байт +#define E_MASTER2 1 // адрес головы, младший байт +#define E_READONLY 2 // режим "только чтение", если 1, то устройств не регистрируем, только слушаем шину +#define E_INIT 3 // признак инициализации EEPROM + +#define LED_ON sbi(LED_PORT, LED_OUT); +#define LED_OFF cbi(LED_PORT, LED_OUT); + +void setup(){ + // setup led + sbi(LED_DDR, LED_OUT); + cbi(LED_PORT, LED_OUT); + + bSerial.begin(250000); + avclan.begin(); + avclanDevice.begin(); + EERPOM_read_config(); + bSerial.print_p(PSTR("AVCLan mini. Kochetkov Aleksey. v")); + bSerial.println(AVCLAN_VERSION); + bSerial.println(); +} + +void loop(){ + + if (INPUT_IS_SET){ + LED_ON; + byte res = avclan.readMessage(); + LED_OFF; + if (!res){ + if (!avclan.readonly) avclanDevice.getActionID(); + if (avclan.actionID != ACT_NONE) { + avclanDevice.processAction((AvcActionID)avclan.actionID); + } + } + } + + if (avclan.event != EV_NONE){ + avclanDevice.processEvent((AvcEventID)avclan.event); + avclan.event = EV_NONE; + } + + if (bSerial.rxEnabled()) { + uint8_t readkey = bSerial.rxRead(); + + switch (readkey){ + case 'P': // print config + bSerial.print_p(PSTR("head=")); + bSerial.printHex8(avclan.headAddress >> 8); + bSerial.printHex8(avclan.headAddress); + bSerial.print_p(PSTR(", eeprom=")); + bSerial.printHex8(EEPROM.read(E_MASTER1)); + bSerial.printHex8(EEPROM.read(E_MASTER2)); + bSerial.println(); + bSerial.print_p(PSTR("device=")); + bSerial.printHex8(avclan.deviceAddress >> 8); + bSerial.printHex8(avclan.deviceAddress); + bSerial.println(); + bSerial.print_p(PSTR("readonly=")); + bSerial.printHex8(avclan.readonly); + bSerial.println(); + bSerial.print_p(PSTR("Overflow: ")); + bSerial.printHex8(bSerial.txOverflow >> 8); + bSerial.printHex8(bSerial.txOverflow); + bSerial.println(); + break; + case 'T': //send test message + bSerial.println("S"); + sendMess(); + break; + case 'M': //readonly mode on/off + avclan.readonly ^= (1 << 0); + EEPROM.write(E_READONLY, avclan.readonly); + break; + case 'h': // set hi level + bSerial.println("H set"); + AVC_OUT_EN; + OUTPUT_SET_1; + break; + case 'l': // set low level + bSerial.println("L set"); + AVC_OUT_EN; + OUTPUT_SET_0; + break; + case 'i': // output disable. Input mode on + bSerial.println("Out dis"); + AVC_OUT_DIS; + break; + case 'V': // version + bSerial.print_p (PSTR("AVCLan mini. Kochetkov Aleksey. v")); + bSerial.println_p(PSTR(AVCLAN_VERSION)); + bSerial.print_p (PSTR(" Driver type: ")); + bSerial.println_p(PSTR(AVCLANDRIVER_TYPE)); + bSerial.print_p (PSTR(" BuffServial v")); + bSerial.println_p(PSTR(BUFFSERIAL_VERSION)); + bSerial.print_p (PSTR(" AVCLanDrv v")); + bSerial.println_p(PSTR(AVCLANDRV_VERSION)); + bSerial.print_p (PSTR(AVCLANDEVICE_NAME)); + bSerial.print_p (PSTR(". v")); + bSerial.println_p(PSTR(AVCLANDEVICE_VERSION)); + break; + case '?': + bSerial.println_p(PSTR("P - config\r\nV - version\r\nM - readonly mode on/off\r\n-- send command --\r\nS - start\r\nW - end direct\r\nQ - end broadcast\r\nH - end of set Head ID, 0000 - auto\r\n-- debug command --\r\nh - Output mode. Set Hi level\r\nl - Output mode. Set Low level\r\ni - Input mode")); + break; + case 'S': // start command + readSeq = 1; + s_len=0; + s_dig=0; + s_c[0] = s_c[1] = 0; + break; + case 'W': // end of direct command + readSeq=0; + avclan.dataSize = s_len; + avclan.broadcast = AVC_MSG_DIRECT; + avclan.masterAddress = avclan.deviceAddress; + avclan.slaveAddress = avclan.headAddress; + for (i=0; i + +const AvcInMessageTable mtMain[] PROGMEM = { + {ACT_REGISTER, 0x03, {0x12, 0x01, 0x00}}, + {ACT_PLAY_REQ1, 0x04, {0x00, 0x25, 0x43, 0x80}}, + {ACT_PLAY_IT, 0x04, {0x12, 0x01, 0x45, 0x43 }}, + {ACT_LAN_STATUS1, 0x03, {0x00, 0x01, 0x0A}}, + {ACT_LAN_STATUS2, 0x03, {0x00, 0x01, 0x08}}, + {ACT_LAN_STATUS3, 0x03, {0x00, 0x01, 0x0D}}, + {ACT_LAN_STATUS4, 0x03, {0x00, 0x01, 0x0C}}, + {ACT_LAN_STATUS5, 0x04, {0x00, 0x00, 0x01, 0x08}}, + {ACT_SCAN_ON, 0x04, {0x00, 0x25, 0x43, 0xA6}}, + {ACT_SCAN_OFF, 0x04, {0x00, 0x25, 0x43, 0xA7}}, + {ACT_SCAN_D_ON, 0x04, {0x00, 0x25, 0x43, 0xA9}}, + {ACT_SCAN_D_OFF, 0x04, {0x00, 0x25, 0x43, 0xAA}}, + {ACT_REPEAT_ON, 0x04, {0x00, 0x25, 0x43, 0xA0}}, + {ACT_REPEAT_OFF, 0x04, {0x00, 0x25, 0x43, 0xA1}}, + {ACT_REPEAT_D_ON, 0x04, {0x00, 0x25, 0x43, 0xA3}}, + {ACT_REPEAT_D_OFF, 0x04, {0x00, 0x25, 0x43, 0xA4}}, + {ACT_RANDOM_ON, 0x04, {0x00, 0x25, 0x43, 0xB0}}, + {ACT_RANDOM_OFF, 0x04, {0x00, 0x25, 0x43, 0xB1}}, + {ACT_RANDOM_D_ON, 0x04, {0x00, 0x25, 0x43, 0xB3}}, + {ACT_RANDOM_D_OFF, 0x04, {0x00, 0x25, 0x43, 0xB4}}, + // power off 0401015F01 +}; +const byte mtMainSize = sizeof(mtMain) / sizeof(AvcInMessageTable); + +const AvcInMaskedMessageTable mtMaskedMain[] PROGMEM = { + {ACT_DEVSTATUS_E0, 0x04, {0x00, 0, 0x43, 0xE0}, _BV(1)}, + {ACT_DEVSTATUS_E2, 0x04, {0x00, 0, 0x43, 0xE2}, _BV(1)}, + {ACT_DEVSTATUS_E4, 0x04, {0x00, 0, 0x43, 0xE4}, _BV(1)}, + {ACT_LAN_CHECK, 0x04, {0x12, 0x01, 0x20, 0}, _BV(3)}, + {ACT_PLAY_REQ2, 0x06, {0x00, 0x12, 0x43, 0x42, 0, 0x00}, _BV(4)}, + {ACT_STOP_REQ1, 0x05, {0x00, 0x12, 0x43, 0x43, 0}, _BV(4)}, + {ACT_STOP_REQ2, 0x06, {0x00, 0x12, 0x43, 0x43, 0, 0x00}, _BV(4)}, +}; +const byte mtMaskedMainSize = sizeof(mtMaskedMain) / sizeof(AvcInMaskedMessageTable); + +const AvcInMessageTable mtSearchHead[] PROGMEM = { + {ACT_REGISTER, 0x03, {0x12, 0x01, 0x00}}, // AVC LAN register + {ACT_REGISTER, 0x03, {0x12, 0x01, 0x01}}, // AVC LAN init + {ACT_REGISTER, 0x03, {0x01, 0x01, 0x58}}, + {ACT_REGISTER, 0x03, {0x01, 0x01, 0x5B}}, + {ACT_REGISTER, 0x04, {0x01, 0x01, 0x5F, 0x01}}, + {ACT_REGISTER, 0x04, {0x01, 0x01, 0x5F, 0x00}}, +}; +const byte mtSearchHeadSize = sizeof(mtSearchHead) / sizeof(AvcInMessageTable); + +const AvcOutMessage CmdReset PROGMEM = {AVC_MSG_BROADCAST, 0x05, {0x00, 0x00, 0x00, 0x00, 0x00}}; // reset AVCLan. This causes HU to send ACT_REGISTER +const AvcOutMessage CmdRegister PROGMEM = {AVC_MSG_DIRECT, 0x05, {0x00, 0x01, 0x12, 0x10, 0x43}}; // register CD-changer +const AvcOutMessage CmdInit1 PROGMEM = {AVC_MSG_BROADCAST, 0x05, {0x43, 0x31, 0xF7, 0x00, 0x43}}; // init command 1 +const AvcOutMessage CmdInit2 PROGMEM = {AVC_MSG_BROADCAST, 0x0B, {0x43, 0x31, 0xF1, 0x00, 0x30, 0x01, 0x01, 0x00, 0x01, 0x00, 0x80}}; // init command 2 +const AvcOutMessage CmdInit3 PROGMEM = {AVC_MSG_BROADCAST, 0x0A, {0x43, 0x31, 0xF3, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03}}; // init command 3 +const AvcOutMessage CmdDevStatusE0 PROGMEM = {AVC_MSG_DIRECT, 0x06, {0x00, 0x43, 0, 0xF0, 0x06, 0xA0}}; // Device status E0 +const AvcOutMessage CmdDevStatusE2 PROGMEM = {AVC_MSG_DIRECT, 0x0C, {0x00, 0x43, 0, 0xF2, 0x00, 0x30, 0x01, 0x01, 0x00, 0x01, 0x00, 0x80}}; // Device status E2 +const AvcOutMessage CmdDevStatusE4 PROGMEM = {AVC_MSG_DIRECT, 0x0B, {0x00, 0x43, 0, 0xF4, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03}}; // Device status E4 +const AvcOutMessage CmdPlayOk1 PROGMEM = {AVC_MSG_DIRECT, 0x05, {0x00, 0x43, 0x12, 0x50, 0x01}}; // Play begin message 1 +const AvcOutMessage CmdPlayOk2 PROGMEM = {AVC_MSG_DIRECT, 0x05, {0x00, 0x43, 0x12, 0x52, 0x01}}; // Play begin message 2 +const AvcOutMessage CmdPlayOk3 PROGMEM = {AVC_MSG_BROADCAST, 0x0B, {0x43, 0x31, 0xF1, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80}}; // Play begin message 3, ch changer open +const AvcOutMessage CmdPlayOk4 PROGMEM = {AVC_MSG_BROADCAST, 0x0B, {0x43, 0x31, 0xF1, 0x05, 0x28, 0x01, 0x02, 0x00, 0x25, 0x00, 0x80}}; // Play begin message 4 +const AvcOutMessage CmdPlayOk5 PROGMEM = {AVC_MSG_BROADCAST, 0x05, {0x43, 0x31, 0xF7, 0x05, 0x43}}; // Play begin message 5 +const AvcOutMessage CmdStopOk1 PROGMEM = {AVC_MSG_DIRECT, 0x05, {0x00, 0x43, 0x12, 0x53, 0x01}}; // Stop ok message 1 +const AvcOutMessage CmdStopOk2 PROGMEM = {AVC_MSG_BROADCAST, 0x0B, {0x43, 0x31, 0xF1, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x80}}; // Stop ok message 2 +const AvcOutMessage CmdPlayStatus PROGMEM = {AVC_MSG_BROADCAST, 0x0B, {0x43, 0x31, 0xF1, 0x05, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x80}}; // CD-changer play status +const AvcOutMessage CmdLanStatus1 PROGMEM = {AVC_MSG_DIRECT, 0x04, {0x00, 0x01, 0x00, 0x1A}}; // Lan status 1 +const AvcOutMessage CmdLanStatus2 PROGMEM = {AVC_MSG_DIRECT, 0x04, {0x00, 0x01, 0x00, 0x18}}; // Lan status 2 +const AvcOutMessage CmdLanStatus3 PROGMEM = {AVC_MSG_DIRECT, 0x04, {0x00, 0x01, 0x00, 0x1D}}; // Lan status 3 +const AvcOutMessage CmdLanStatus4 PROGMEM = {AVC_MSG_DIRECT, 0x05, {0x00, 0x01, 0x00, 0x1C, 0x00}}; // Lan status 4 +const AvcOutMessage CmdLanStatus5 PROGMEM = {AVC_MSG_DIRECT, 0x04, {0x00, 0x01, 0x00, 0x18}}; // Lan status 5 +const AvcOutMessage CmdLanCheckOk PROGMEM = {AVC_MSG_DIRECT, 0x06, {0x00, 0x01, 0x12, 0x30, 0, 0x00}}; // Check, device ok + +// AVCLan CDchanger & timer1 init, +void AVCLanCDch::begin(){ + avclan.deviceAddress = 0x0240; + + // timer1 setup, prescaler factor - 1024 + TCCR1A = 0; // normal mode + TCCR1B = 5; // Prescaler /1024 + TCNT1H = TI1_H; // Load counter value hi + TCNT1L = TI1_L; // Load counter value lo + DISABLE_TIMER1_INT; + AZFM_INIT; + cd_min = cd_sec = cd_playmode = 0; + cd_status = stWait; +} + +// Use the last received message to determine the corresponding action ID, store it in avclan object +void AVCLanCDch::getActionID(){ + if (avclan.headAddress == 0){ + avclan.actionID = avclan.getActionID(mtSearchHead, mtSearchHeadSize); + }else{ + avclan.actionID = avclan.getActionID(mtMain, mtMainSize); + if (avclan.actionID == ACT_NONE) avclan.actionID = avclan.getActionID(mtMaskedMain, mtMaskedMainSize); + } +}; + +// process action +void AVCLanCDch::processAction(AvcActionID ActionID){ + byte r; + switch (ActionID){ + case ACT_REGISTER: // register device + if (avclan.headAddress == 0) avclan.headAddress = avclan.masterAddress; + avclan.sendMessage(&CmdRegister); + break; + case ACT_INIT: // init device + r = avclan.sendMessage(&CmdInit1); + if (!r) r = avclan.sendMessage(&CmdInit2); + if (!r) r = avclan.sendMessage(&CmdInit3); + break; + case ACT_DEVSTATUS_E0: // Device status E0 + r = avclan.message[1]; + avclan.loadMessage(&CmdDevStatusE0); + avclan.message[2] = r; + avclan.sendMessage(); + break; + case ACT_DEVSTATUS_E2: // Device status E2 + r = avclan.message[1]; + avclan.loadMessage(&CmdDevStatusE2); + avclan.message[2] = r; + avclan.sendMessage(); + break; + case ACT_DEVSTATUS_E4: // Device status E4 + r = avclan.message[1]; + avclan.loadMessage(&CmdDevStatusE4); + avclan.message[2] = r; + avclan.sendMessage(); + break; + case ACT_PLAY_REQ1: // Play request 1 + avclan.sendMessage(&CmdPlayOk1); + break; + case ACT_PLAY_REQ2: // Play request 2 + r = avclan.sendMessage(&CmdPlayOk2); + //if (!r) avclan.sendMessage(&CmdPlayOk3); + break; + case ACT_PLAY_IT: // device play + if (cd_status != stPlay || (cd_min == 0 && cd_sec == 0)){ + avclan.loadMessage(&CmdPlayOk4); + avclan.message[5] = 1; // cd disk + avclan.message[6] = 1; // cd track + avclan.message[7] = cd_min; // play tme min + avclan.message[8] = cd_sec; // play time sec + r = avclan.sendMessage(); + } + if (!r && cd_status != stPlay) avclan.sendMessage(&CmdPlayOk5); + ENABLE_TIMER1_INT; + AZFM_ON; + cd_status = stPlay; + break; + case ACT_STOP_REQ1: // Stop request + case ACT_STOP_REQ2: + avclan.sendMessage(&CmdStopOk1); + DISABLE_TIMER1_INT; + AZFM_OFF; + cd_status = stStop; + cd_min = cd_sec = 0; + avclan.sendMessage(&CmdStopOk2); + avclan.sendMessage(&CmdInit1); + avclan.loadMessage(&CmdStopOk2); + avclan.message[4] = 0x30; + avclan.sendMessage(); + break; + case ACT_LAN_STATUS1: // Lan status 1 + avclan.sendMessage(&CmdLanStatus1); + DISABLE_TIMER1_INT; + break; + case ACT_LAN_STATUS2: // Lan status 2 + avclan.sendMessage(&CmdLanStatus2); + DISABLE_TIMER1_INT; + break; + case ACT_LAN_STATUS3: // Lan status 3 + avclan.sendMessage(&CmdLanStatus3); + break; + case ACT_LAN_STATUS4: // Lan status 4 + avclan.sendMessage(&CmdLanStatus4); + break; + case ACT_LAN_STATUS5: // Lan status 5 + avclan.sendMessage(&CmdLanStatus5); + break; + case ACT_LAN_CHECK: // Lan status 5 + r = avclan.message[3]; + avclan.loadMessage(&CmdLanCheckOk); + avclan.message[4] = r; + avclan.sendMessage(); + break; + case ACT_SCAN_ON: // Scan mode on + cd_playmode |= pmScan; + sendStatus(); + break; + case ACT_SCAN_OFF: // Scan mode off + cd_playmode &= ~pmScan; + sendStatus(); + break; + case ACT_SCAN_D_ON: // Scan directory mode on + cd_playmode |= pmScanD; + sendStatus(); + break; + case ACT_SCAN_D_OFF: // Scan directory mode off + cd_playmode &= ~pmScanD; + sendStatus(); + break; + case ACT_REPEAT_ON: // Repeat mode on + cd_playmode |= pmRepeat; + sendStatus(); + break; + case ACT_REPEAT_OFF: // Repeat mode off + cd_playmode &= ~pmRepeat; + sendStatus(); + break; + case ACT_REPEAT_D_ON: // Repeat directory mode on + cd_playmode |= pmRepeatD; + sendStatus(); + break; + case ACT_REPEAT_D_OFF: // Repeat directory mode off + cd_playmode &= ~pmRepeatD; + sendStatus(); + break; + case ACT_RANDOM_ON: // Random mode on + cd_playmode |= pmRandom; + sendStatus(); + break; + case ACT_RANDOM_OFF: // Random mode off + cd_playmode &= ~pmRandom; + sendStatus(); + break; + case ACT_RANDOM_D_ON: // Random directory mode on + cd_playmode |= pmRandomD; + sendStatus(); + break; + case ACT_RANDOM_D_OFF: // Random directory mode off + cd_playmode &= ~pmRandomD; + sendStatus(); + break; + } +}; + +// process event +void AVCLanCDch::processEvent(AvcEventID EventID){ + switch (EventID){ + case EV_STATUS: + sendStatus(); + avclan.event &= ~EV_STATUS; + break; + } +}; + +// send CD-changer status to head +byte AVCLanCDch::sendStatus(){ + avclan.loadMessage(&CmdPlayStatus); + avclan.message[4] = cd_status; // cd changer status: 10-play, 80-load, 01-open, 02=err1, 03-wait + avclan.message[5] = 1; // cd disk + avclan.message[6] = 1; // cd track + avclan.message[7] = cd_min; // play tme min + avclan.message[8] = cd_sec; // play time sec + avclan.message[9] = cd_playmode; // play mode: 0-normal, 2-disc rand, 4-rand, 8-disc repeat, 10-repeat, 20-disc scan, 40-scan + + return avclan.sendMessage(); +} + +byte AVCLanCDch::hexInc(byte data){ + if ((data & 0x9) == 0x9) return (data + 7); + return (data + 1); +} + +byte AVCLanCDch::hexDec(byte data){ + if ((data & 0xF) == 0) return (data - 7); + return (data - 1); +} + + +// timer1 overflow +ISR(TIMER1_OVF_vect){ + TCNT1H = TI1_H; // Load counter value hi + TCNT1L = TI1_L; // Load counter value lo + avclanDevice.cd_sec = avclanDevice.hexInc(avclanDevice.cd_sec); + if (avclanDevice.cd_sec == 0x60) { + avclanDevice.cd_sec = 0; + avclanDevice.cd_min = avclanDevice.hexInc(avclanDevice.cd_min); + if (avclanDevice.cd_min == 0xA0) { + avclanDevice.cd_min=0x0; + } + } + avclan.event = EV_STATUS; +} + +AVCLanCDch avclanDevice; diff --git a/arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.h b/arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.h new file mode 100644 index 0000000..5a18790 --- /dev/null +++ b/arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.h @@ -0,0 +1,102 @@ +/* + AVCLanDrv.h - AVCLan CD changer library for 'duino / Wiring + Created by Kochetkov Aleksey, 04.08.2010 + Version 0.2.2 +*/ + +#ifndef AVCLanCDch_h +#define AVCLanCDch_h + +#include +#include "AVCLanDrv.h" +#include "Arduino.h" + +// timer1 overflow every 1 sec +#define TI1_H (((word)-(F_CPU / 1024)) >> 8) +#define TI1_L (((word)-(F_CPU / 1024)) & 0xff ) + +#if defined(__AVR_ATmega8__) +#define ENABLE_TIMER1_INT (sbi(TIMSK, TOIE1)); +#define DISABLE_TIMER1_INT (cbi(TIMSK, TOIE1)); +#else +#define ENABLE_TIMER1_INT (sbi(TIMSK1, TOIE1)); +#define DISABLE_TIMER1_INT (cbi(TIMSK1, TOIE1)); +#endif + +#define AVCLANDEVICE_NAME " CD changer" +#define AVCLANDEVICE_VERSION "0.2.2" + +//extern AvcOutMessage CmdReset; // reset AVCLan. This causes HU to send ACT_REGISTER +//extern AvcOutMessage CmdRegister; // register CD changer +// extern AvcOutMessage *CmdTest; // test message + + + +typedef enum{ + ACT_REGISTER = 1, + ACT_INIT, + ACT_DEVSTATUS_E0, + ACT_DEVSTATUS_E2, + ACT_DEVSTATUS_E4, + ACT_PLAY_REQ1, + ACT_PLAY_REQ2, + ACT_PLAY_IT, + ACT_STOP_REQ1, + ACT_STOP_REQ2, + ACT_LAN_STATUS1, + ACT_LAN_STATUS2, + ACT_LAN_STATUS3, + ACT_LAN_STATUS4, + ACT_LAN_STATUS5, + ACT_LAN_CHECK, + ACT_SCAN_ON, + ACT_SCAN_OFF, + ACT_SCAN_D_ON, + ACT_SCAN_D_OFF, + ACT_REPEAT_ON, + ACT_REPEAT_OFF, + ACT_REPEAT_D_ON, + ACT_REPEAT_D_OFF, + ACT_RANDOM_ON, + ACT_RANDOM_OFF, + ACT_RANDOM_D_ON, + ACT_RANDOM_D_OFF, +} AvcActionID; + +typedef enum{ + EV_STATUS = 1, +} AvcEventID; + +typedef enum{ + stWait = 0x03, + stPlay = 0x10, + stStop = 0x30, +} cdStatus; + +typedef enum{ + pmScan = 0x40, + pmScanD = 0x20, + pmRepeat = 0x10, + pmRepeatD = 0x08, + pmRandom = 0x04, + pmRandomD = 0x02, + pmNormal = 0x00, +} cdPlayMode; + +class AVCLanCDch{ + public: + byte cd_min; // minutes play + byte cd_sec; // seconds play + cdStatus cd_status; // cd changer status + byte cd_playmode; // play mode (scan, random etc..) + void begin (); // initialisation, obligatory method + void getActionID(); // get action id by recieved message, obligatory method + void processAction(AvcActionID); // process action, obligatory method + void processEvent(AvcEventID); // process event, obligatory method + byte sendStatus(); // send CD-changer status to head + byte hexInc(byte data); + byte hexDec(byte data); +}; +#endif + +extern AVCLanCDch avclanDevice; diff --git a/arduino/mini2/libraries/AVCLanCDch/changelog.txt b/arduino/mini2/libraries/AVCLanCDch/changelog.txt new file mode 100644 index 0000000..f488de5 --- /dev/null +++ b/arduino/mini2/libraries/AVCLanCDch/changelog.txt @@ -0,0 +1,11 @@ +2010-08-04 0.2.2 + * rand, scan, repeat .. . . + +2010-07-24 0.2.1 + + + + normal, disc rand, rand, disc repeat, repeat, disc scan, scan + +2010-07-22 0.2.0 + + CD changer' + + + diff --git a/arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.cpp b/arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.cpp new file mode 100644 index 0000000..d6e1bf7 --- /dev/null +++ b/arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.cpp @@ -0,0 +1,579 @@ +/* + AVCLanDrv.cpp - AVCLan Library for 'duino / Wiring + Created by Kochetkov Aleksey, 04.08.2010 + Version 0.3.1 +*/ + +#include "AVCLanDrv.h" +#include "BuffSerial.h" + +// AVCLan driver & timer2 init, +void AVCLanDrv::begin (){ + // AVCLan TX+/TX- read line INPUT + cbi(DATAIN_DDR, DATAIN); +#ifdef AVCLAN_ST485 + sbi(DATAIN_PORT, DATAIN); +#else + cbi(DATAIN_PORT, DATAIN); +#endif + + // AVCLan TX+/TX- write line OUTPUT +#ifdef AVCLAN_RESISTOR + cbi(DATAOUT_DDR, DATAOUT); + cbi(DATAOUT_PORT, DATAOUT); + cbi(ADCSRB, ACME); // Analog Comparator Multiplexer Enable - NO + cbi(ACSR, ACIS1); // Analog Comparator Interrupt Mode Select + cbi(ACSR, ACIS0); // Comparator Interrupt on Output Toggle + cbi(ACSR, ACD); // Analog Comparator Disbale - NO +#else +#ifdef AVCLAN_ST485 + sbi(DATAOUT_DDR, DATAOUT); + sbi(OUTEN_DDR, OUTEN); + AVC_OUT_DIS; + OUTPUT_SET_0; +#else +//avclan driver on PCA82C250 & LM239N + sbi(DATAOUT_DDR, DATAOUT); + AVC_OUT_DIS; + OUTPUT_SET_0; +#endif +#endif + +// timer2 setup, prescaler factor - 8 +#if defined(__AVR_ATmega8__) +// ASSR=0x00; + TCCR2=0x02; +// TCNT2=0x00; +// OCR2=0x00; +#else // ATMega168 +// ASSR=0x00; +// TCCR2A=0x00; + TCCR2B=0x02; +// TCNT2=0x00; +// OCR2A=0x00; +// OCR2B=0x00; +#endif + headAddress = 0x0000; + deviceAddress = 0x0000; + event = EV_NONE; + actionID = ACT_NONE; +} + +// Reads specified number of bits from the AVCLan. +// nbBits (byte) -> Number of bits to read. +// Return (word) -> Data value read. +word AVCLanDrv::readBits (byte nbBits){ + word data = 0; + _parityBit = 0; + + while (nbBits-- > 0){ + // Insert new bit + data <<= 1; + // Wait until rising edge of new bit. + while (INPUT_IS_CLEAR){ + // Reset watchdog. + //wdt_reset(); + } + + // Reset timer to measure bit length. + TCNT2 = 0; + // Wait until falling edge. + while (INPUT_IS_SET); + // Compare half way between a '1' (20 us) and a '0' (32 us ): 32 - (32 - 20) /2 = 26 us + if (TCNT2 < AVC_BIT_0_HOLD_ON_MIN_LENGTH){ + // Set new bit. + data |= 0x0001; + // Adjust parity. + _parityBit = ! _parityBit; + } + } + while (INPUT_IS_CLEAR && TCNT2 < AVC_NORMAL_BIT_LENGTH); + return data; +} + +// Read incoming messages on the AVCLan. +// Return true if success. +byte AVCLanDrv::_readMessage (){ + uint8_t t = 0; + uint8_t oldSREG = SREG; + cli(); // disable interrupts + + // Start bit. + while (INPUT_IS_CLEAR); + TCCR2B=0x03; // prescaler 32 + TCNT2 = 0; + // Wait until falling edge. + while (INPUT_IS_SET){ + t = TCNT2; + if (t > 0xFF) { + TCCR2B=0x02; // prescaler 8 + SREG = oldSREG; + return 1; + } + } + TCCR2B=0x02; // prescaler 8 + + if (t < AVC_START_BIT_HOLD_ON_MIN_LENGTH){ + //if (t < 0x16){ + SREG = oldSREG; + return 2; + } + + broadcast = readBits(1); + + masterAddress = readBits(12); + bool p = _parityBit; + if (p != readBits(1)){ + SREG = oldSREG; + return 3; + } + + slaveAddress = readBits(12); + p = _parityBit; + if (p != readBits(1)){ + SREG = oldSREG; + return 4; + } + + bool forMe = ( slaveAddress == deviceAddress ); + + if (forMe){ + // Send ACK. + AVC_OUT_EN; + send1BitWord(0); + AVC_OUT_DIS; + }else{ + readBits(1); + } + + // Control + readBits(4); + p = _parityBit; + if (p != readBits(1)){ + SREG = oldSREG; + return 5; + } + + if (forMe){ + // Send ACK. + AVC_OUT_EN; + send1BitWord(0); + AVC_OUT_DIS; + }else{ + readBits(1); + } + + dataSize = readBits(8); + p = _parityBit; + if (p != readBits(1)){ + SREG = oldSREG; + return 6; + } + + if (forMe){ + // Send ACK. + AVC_OUT_EN; + send1BitWord(0); + AVC_OUT_DIS; + }else{ + readBits(1); + } + if (dataSize > AVC_MAXMSGLEN){ + SREG = oldSREG; + return 7; + } + byte i; + for (i = 0; i < dataSize; i++ ){ + message[i] = readBits(8); + p = _parityBit; + if (p != readBits(1)){ + SREG = oldSREG; + return 8; + } + + if (forMe){ + // Send ACK. + AVC_OUT_EN; + send1BitWord(0); + AVC_OUT_DIS; + }else{ + readBits(1); + } + } + SREG = oldSREG; + return 0; +} + +// Read incoming messages on the AVCLan, log message through serial port +// Return true if success. +byte AVCLanDrv::readMessage (){ + byte res = avclan._readMessage(); + if (!res){ + avclan.printMessage(true); + }else{ + bSerial.print("R"); + bSerial.printHex4(res); + bSerial.println(); + while (!avclan.isAvcBusFree()); + } + return res; +} + +// Send a start bit to the AVCLan +void AVCLanDrv::sendStartBit (){ + // Reset timer to measure bit length. + TCCR2B=0x03; // prescaler 32 + TCNT2 = 0; + OUTPUT_SET_1; + + // Pulse level high duration. + while ( TCNT2 < AVC_START_BIT_HOLD_ON_LENGTH ); + OUTPUT_SET_0; + + // Pulse level low duration until ~185 us. + while ( TCNT2 < AVC_START_BIT_LENGTH ); + TCCR2B=0x02; // prescaler 8 + +} + +// Send a 1 bit word to the AVCLan +void AVCLanDrv::send1BitWord (bool data){ + // Reset timer to measure bit length. + TCNT2 = 0; + OUTPUT_SET_1; + + if (data){ + while (TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH); + }else{ + while (TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH); + } + + OUTPUT_SET_0; + while (TCNT2 < AVC_NORMAL_BIT_LENGTH); +} + +// Send a 4 bit word to the AVCLan +void AVCLanDrv::send4BitWord (byte data){ + _parityBit = 0; + + // Most significant bit out first. + for ( char nbBits = 0; nbBits < 4; nbBits++ ){ + // Reset timer to measure bit length. + TCNT2 = 2; + OUTPUT_SET_1; + + if (data & 0x8){ + // Adjust parity. + _parityBit = ! _parityBit; + while ( TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH ); + }else{ + while ( TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH ); + } + + OUTPUT_SET_0; + // Hold output low until end of bit. + while ( TCNT2 < AVC_NORMAL_BIT_LENGTH ); + + // Fetch next bit. + data <<= 1; + } +} + +// Send a 8 bit word to the AVCLan +void AVCLanDrv::send8BitWord (byte data){ + _parityBit = 0; + + // Most significant bit out first. + for ( char nbBits = 0; nbBits < 8; nbBits++ ){ + // Reset timer to measure bit length. + TCNT2 = 2; + OUTPUT_SET_1; + + if (data & 0x80){ + // Adjust parity. + _parityBit = ! _parityBit; + while ( TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH ); + }else{ + while ( TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH ); + } + + OUTPUT_SET_0; + // Hold output low until end of bit. + while ( TCNT2 < AVC_NORMAL_BIT_LENGTH ); + + // Fetch next bit. + data <<= 1; + } +} + +// Send a 12 bit word to the AVCLan +void AVCLanDrv::send12BitWord (word data){ + _parityBit = 0; + + // Most significant bit out first. + for ( char nbBits = 0; nbBits < 12; nbBits++ ){ + // Reset timer to measure bit length. + TCNT2 = 2; + OUTPUT_SET_1; + + if (data & 0x0800){ + // Adjust parity. + _parityBit = ! _parityBit; + while ( TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH ); + }else{ + while ( TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH ); + } + + OUTPUT_SET_0; + // Hold output low until end of bit. + while ( TCNT2 < AVC_NORMAL_BIT_LENGTH ); + + // Fetch next bit. + data <<= 1; + } +} + +// determine whether the bus is free (no tx/rx). +// return TRUE is bus is free. +bool AVCLanDrv::isAvcBusFree (void){ + // Reset timer. + TCNT2 = 0; + + while (INPUT_IS_CLEAR){ + // We assume the bus is free if anything happens for the length of 1 bit. + if (TCNT2 > AVC_NORMAL_BIT_LENGTH){ + return true; + } + } + + return false; +} + +// reads the acknowledge bit the AVCLan +// return TRUE if ack detected else FALSE. +bool AVCLanDrv::readAcknowledge (void){ + // The acknowledge pattern is very tricky: the sender shall drive the bus for the equivalent + // of a bit '1' (20 us) then release the bus and listen. At this point the target shall have + // taken over the bus maintaining the pulse until the equivalent of a bit '0' (32 us) is formed. + + // Reset timer to measure bit length. + TCNT2 = 0; + OUTPUT_SET_1; + + // Generate bit '0'. + while (TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH); + OUTPUT_SET_0; + + AVC_OUT_DIS; + + while (TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH + AVC_1U_LENGTH); + // Measure final resulting bit. + while ( INPUT_IS_SET ); + + // Sample half-way through bit '0' (26 us) to detect whether the target is acknowledging. + if (TCNT2 > AVC_BIT_0_HOLD_ON_MIN_LENGTH){ + // Slave is acknowledging (ack = 0). Wait until end of ack bit. + while (INPUT_IS_SET ); + AVC_OUT_EN; + return true; + } + + // No sign of life on the bus. + return false; +} + +// sends ack bit if I am broadcasting otherwise wait and return received ack bit. +// return FALSE if ack bit not detected. +bool AVCLanDrv::handleAcknowledge (void){ + if (broadcast == AVC_MSG_BROADCAST){ + // Acknowledge. + send1BitWord(0); + return true; + } + + // Return acknowledge bit. + return readAcknowledge(); +} + +// sends the message in global registers on the AVC LAN bus. +// return 0 if successful else error code +byte AVCLanDrv::_sendMessage (void){ + uint8_t oldSREG = SREG; + cli(); // disable interrupts + while (!isAvcBusFree()); + + AVC_OUT_EN; + + // Send start bit. + sendStartBit(); + + // Broadcast bit. + send1BitWord(broadcast); + + // Master address = me. + send12BitWord(masterAddress); + send1BitWord(_parityBit); + + // Slave address = head unit (HU). + send12BitWord(slaveAddress); + send1BitWord(_parityBit); + if (!handleAcknowledge()){ + AVC_OUT_DIS; + SREG = oldSREG; + return 1; + } + + // Control flag + parity. + send4BitWord(AVC_CONTROL_FLAGS); + send1BitWord(_parityBit); + if (!handleAcknowledge()){ + AVC_OUT_DIS; + SREG = oldSREG; + return 2; + } + + // Data length + parity. + send8BitWord(dataSize); + send1BitWord(_parityBit); + if (!handleAcknowledge()){ + AVC_OUT_DIS; + SREG = oldSREG; + return 3; + } + + for (byte i = 0; i < dataSize; i++){ + send8BitWord(message[i]); + send1BitWord(_parityBit); + if (!handleAcknowledge()){ + AVC_OUT_DIS; + SREG = oldSREG; + return false; + } + } + AVC_OUT_DIS; + SREG = oldSREG; + return 0; +} + +// sends the message in global registers on the AVC LAN bus, log message through serial port +// return 0 if successful else error code +byte AVCLanDrv::sendMessage (void){ + byte sc = MAXSENDATTEMP; + byte res; + do{ + res = avclan._sendMessage(); + if (!res){ + avclan.printMessage(false); + }else{ + bSerial.print("W"); + bSerial.printHex4(res); + bSerial.println(); + while (!avclan.isAvcBusFree()); + } + sc--; + }while (sc && res); + return res; +} + +// sends the message for given mesage ID on the AVC LAN bus, log message through serial port +// return 0 if successful else error code +byte AVCLanDrv::sendMessage (AvcOutMessage *msg){ + loadMessage(msg); + return sendMessage(); +} +// print message to serial port +void AVCLanDrv::printMessage(bool incoming){ + if (incoming){ + bSerial.print("< "); + }else{ + bSerial.print("> "); + } + if (broadcast == AVC_MSG_BROADCAST){ + bSerial.print("b "); + }else{ + bSerial.print("d "); + } + bSerial.printHex4(masterAddress >> 8); + bSerial.printHex8(masterAddress); + bSerial.print(" "); + + bSerial.printHex4(slaveAddress >> 8); + bSerial.printHex8(slaveAddress); + bSerial.print(" "); + bSerial.printHex8(dataSize); + + for (byte i = 0; i < dataSize; i++){ + bSerial.printHex8(message[i]); + } + bSerial.println(); + +} + +// Use the last received message to determine the corresponding action ID +byte AVCLanDrv::getActionID(AvcInMessageTable messageTable[], byte mtSize){ + if (slaveAddress != deviceAddress && slaveAddress != 0x0FFF) return ACT_NONE; + for (byte msg = 0; msg < mtSize; msg++){ + bool found = true; + + if (dataSize != pgm_read_byte_near(&messageTable[msg].dataSize)){ + continue; + } + for (byte i = 0; i < dataSize; i++){ + if (message[i] != pgm_read_byte_near(&messageTable[msg].data[i])){ + found = false; + break; + } + } + + if (found){ + return pgm_read_byte_near(&messageTable[msg].actionID); + } + } + + return ACT_NONE; +} + +// Use the last received message to determine the corresponding action ID, use masked message table +byte AVCLanDrv::getActionID(AvcInMaskedMessageTable messageTable[], byte mtSize){ + if (slaveAddress != deviceAddress && slaveAddress != 0x0FFF) return ACT_NONE; + for (byte msg = 0; msg < mtSize; msg++){ + bool found = true; + + if (dataSize != pgm_read_byte_near(&messageTable[msg].dataSize)){ + continue; + } + word mask = pgm_read_byte_near(&messageTable[msg].mask); + for (byte i = 0; i < dataSize; i++){ + if (mask & _BV(i)) continue; + if (message[i] != pgm_read_byte_near(&messageTable[msg].data[i])){ + found = false; + break; + } + } + + if (found){ + return pgm_read_byte_near(&messageTable[msg].actionID); + } + } + + return ACT_NONE; +} + +// Loads message data for given mesage ID. +void AVCLanDrv::loadMessage(AvcOutMessage *msg){ + broadcast = pgm_read_byte_near(&msg->broadcast); + masterAddress = deviceAddress; + + if (broadcast == AVC_MSG_BROADCAST) + slaveAddress = 0x01FF; + else + slaveAddress = headAddress; + + dataSize = pgm_read_byte_near( &msg->dataSize ); + + for (byte i = 0; i < dataSize; i++ ){ + message[i] = pgm_read_byte_near( &msg->data[i] ); + } +}; + +AVCLanDrv avclan; \ No newline at end of file diff --git a/arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.h b/arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.h new file mode 100644 index 0000000..2a7526d --- /dev/null +++ b/arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.h @@ -0,0 +1,131 @@ +/* + AVCLanDrv.h - AVCLan Library for 'duino / Wiring + Created by Kochetkov Aleksey, 04.08.2010 + Version 0.3.1 +*/ + +#ifndef AVCLanDrv_h +#define AVCLanDrv_h + +#include "Arduino.h" +#include "config.h" + +#define AVCLANDRV_VERSION "0.3.1" + + +#ifdef AVCLAN_RESISTOR +// avclan driver on resistor +#define INPUT_IS_SET (ACSR & _BV(ACO)) +#define INPUT_IS_CLEAR (!(ACSR & _BV(ACO))) +#define OUTPUT_SET_1 sbi(PORTD, DATAOUT); +#define OUTPUT_SET_0 cbi(PORTD, DATAOUT); +#define AVC_OUT_EN sbi(PORTD, DATAOUT); sbi(DDRD, DATAOUT); sbi(DDRD, DATAIN); sbi(ACSR, ACD); +#define AVC_OUT_DIS cbi(PORTD, DATAOUT); cbi(DDRD, DATAOUT); cbi(DDRD, DATAIN); cbi(ACSR, ACD); +#else +#ifdef AVCLAN_ST485 +// avclan driver on ST485 +#define INPUT_IS_SET (bit_is_clear(DATAIN_PIN, DATAIN)) +#define INPUT_IS_CLEAR (bit_is_set(DATAIN_PIN, DATAIN)) +#define OUTPUT_SET_1 (cbi(DATAOUT_PORT, DATAOUT)); +#define OUTPUT_SET_0 (sbi(DATAOUT_PORT, DATAOUT)); +#define AVC_OUT_EN (sbi(OUTEN_PORT, OUTEN));; +#define AVC_OUT_DIS (cbi(OUTEN_PORT, OUTEN));; +#else +//avclan driver on PCA82C250 & LM239N +#define INPUT_IS_SET (bit_is_set(DATAIN_PIN, DATAIN)) +#define INPUT_IS_CLEAR (bit_is_clear(DATAIN_PIN, DATAIN)) +#define OUTPUT_SET_1 (cbi(DATAOUT_PORT, DATAOUT)); +#define OUTPUT_SET_0 (sbi(DATAOUT_PORT, DATAOUT)); +#define AVC_OUT_EN ; +#define AVC_OUT_DIS ; +#endif +#endif + +#define AVC_NORMAL_BIT_LENGTH 0x4A // 37 * (F_CPU / 1000000L / 8) +#define AVC_BIT_1_HOLD_ON_LENGTH 0x28 // 20 uS * (F_CPU / 1000000L / 8) +#define AVC_BIT_0_HOLD_ON_LENGTH 0x40 // 32 uS * (F_CPU / 1000000L / 8) +//#define AVC_BIT_0_HOLD_ON_MIN_LENGTH 0x34 // 26 uS * (F_CPU / 1000000L / 8) Compare half way between a '1' (20 us) and a '0' (32 us ): 32 - (32 - 20) /2 = 26 us +#define AVC_BIT_0_HOLD_ON_MIN_LENGTH 0x3C // 30 uS * (F_CPU / 1000000L / 8) Compare half way between a '1' (20 us) and a '0' (32 us ): 32 - (32 - 20) /2 = 26 us +#define AVC_START_BIT_LENGTH 0x5D // 186 uS * (F_CPU / 1000000L / 32) , prescaler 32 +#define AVC_START_BIT_HOLD_ON_LENGTH 0x54 // 168 uS * (F_CPU / 1000000L / 32) prescaler 32 +#define AVC_START_BIT_HOLD_ON_MIN_LENGTH 0x16 // 44 uS * (F_CPU / 1000000L / 32) grater that AVC_NORMAL_BIT_LENGTH, prescaler 32 +#define AVC_1U_LENGTH 0x02 // 1 uS * (F_CPU / 1000000L / 8) + +#define AVC_MAXMSGLEN 32 +#define AVC_CONTROL_FLAGS 0xF + +typedef enum +{ // No this is not a mistake, broadcast = 0! + AVC_MSG_DIRECT = 1, + AVC_MSG_BROADCAST = 0 +} AvcTransmissionMode; + +#define ACT_NONE 0 // no action +#define EV_NONE 0 // no event + +typedef struct +{ + byte actionID; // Action id + byte dataSize; // message size (bytes) + byte data[12]; // message +} AvcInMessageTable; + +typedef struct +{ + byte actionID; // Action id + byte dataSize; // message size (bytes) + byte data[14]; // message + word mask; // mask, set bit = 1 in not checked position (1<<5 or _BV(5) - datap[5] not checked) +} AvcInMaskedMessageTable; + +typedef struct +{ + AvcTransmissionMode broadcast; // Transmission mode: normal (1) or broadcast (0). + byte dataSize; // message size (bytes) + byte data[14]; // message +} AvcOutMessage; + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +class AVCLanDrv{ + public: + bool broadcast; + word masterAddress; + word slaveAddress; + word deviceAddress; + word headAddress; + byte dataSize; + byte message[AVC_MAXMSGLEN]; + byte event; + byte actionID; + bool readonly; + void begin (); + byte readMessage (void); + byte sendMessage (void); + byte sendMessage (AvcOutMessage*); + void printMessage (bool incoming); + bool isAvcBusFree (void); + byte getActionID (AvcInMessageTable messageTable[], byte mtSize); + byte getActionID (AvcInMaskedMessageTable messageTable[], byte mtSize); + void loadMessage (AvcOutMessage*); + private: + bool _parityBit; + word readBits (byte nbBits); + byte _readMessage (void); + byte _sendMessage (void); + void sendStartBit (void); + void send1BitWord (bool data); + void send4BitWord (byte data); + void send8BitWord (byte data); + void send12BitWord (word data); + bool readAcknowledge (void); + bool handleAcknowledge (void); +}; + +extern AVCLanDrv avclan; +#endif diff --git a/arduino/mini2/libraries/AVCLanDrv/changelog.txt b/arduino/mini2/libraries/AVCLanDrv/changelog.txt new file mode 100644 index 0000000..dc0c31d --- /dev/null +++ b/arduino/mini2/libraries/AVCLanDrv/changelog.txt @@ -0,0 +1,15 @@ +2010-08-04 0.3.1 + + . config.h MAXSENDATTEMP + +2010-07-22 0.3.0 + * + + id ( ) + + 14 + + bSerial + +2010-04-26 0.2.5 + + readMessage sendMessage bSerial + +2009-11-31 0.2.4 + + id , PROGMEM (sendMessage(AvcOutMessage*), getActionID, loadMessage) + diff --git a/arduino/mini2/libraries/AVCLanDrv/config.h b/arduino/mini2/libraries/AVCLanDrv/config.h new file mode 100644 index 0000000..81c6cf1 --- /dev/null +++ b/arduino/mini2/libraries/AVCLanDrv/config.h @@ -0,0 +1,137 @@ +/* + config.h - AVCLan driver config + Created by Kochetkov Aleksey, 04.08.2010 +*/ + +// type of AVCLan hardwire driver +//#define AVCLAN_ST485 +#define AVCLAN_PCA82C250 +//#define AVCLAN_MINI_PCA82C250 +//#define AVCLAN_RESISTOR + +// maximum number of attempts to send a message +#define MAXSENDATTEMP 3 + +//********** arduino & driver based on ST485 ********** +#ifdef AVCLAN_ST485 +#define AVCLANDRIVER_TYPE "Arduino - ST485" +// define out pin (pin 11 arduino) for ST485 +#define DATAOUT_DDR DDRB +#define DATAOUT_PORT PORTB +#define DATAOUT_PIN PINB +#define DATAOUT 3 + +// define out control pin (pin 10 arduino) for ST485 +#define OUTEN_DDR DDRB +#define OUTEN_PORT PORTB +#define OUTEN_PIN PINB +#define OUTEN 2 + +// define in pin (pin 9 arduino) for ST485 +#define DATAIN_DDR DDRB +#define DATAIN_PORT PORTB +#define DATAIN_PIN PINB +#define DATAIN 1 + +// LED connected to digital pin 13 +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED_OUT 5 + +// AZFM board activate +#define AZFM_INIT +#define AZFM_ON +#define AZFM_OFF + +#endif + +//********** arduino & driver based on PCA82C250 ********** +#ifdef AVCLAN_PCA82C250 +#define AVCLANDRIVER_TYPE "Arduino - PCA82C250" +// define out pin (pin 8 arduino) for AVCLAN_PCA82C250 +#define DATAOUT_DDR DDRB +#define DATAOUT_PORT PORTB +#define DATAOUT_PIN PINB +#define DATAOUT 0 + +// define in pin (pin 9 arduino) for AVCLAN_PCA82C250 +#define DATAIN_DDR DDRB +#define DATAIN_PORT PORTB +#define DATAIN_PIN PINB +#define DATAIN 1 + +// LED connected to digital pin 13 +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED_OUT 5 + +// AZFM board activate +#define AZFM_INIT +#define AZFM_ON +#define AZFM_OFF + +#endif + +//********** avclan-mini board based on PCA82C250 ********** +#ifdef AVCLAN_MINI_PCA82C250 +#define AVCLANDRIVER_TYPE "AVCLan-mini - PCA82C250" +// define out pin D7 for AVCLAN_MINI_PCA82C250 +#define DATAOUT_DDR DDRD +#define DATAOUT_PORT PORTD +#define DATAOUT_PIN PIND +#define DATAOUT 7 + +// define in pin B0 for AVCLAN_MINI_PCA82C250 +#define DATAIN_DDR DDRB +#define DATAIN_PORT PORTB +#define DATAIN_PIN PINB +#define DATAIN 0 + +// LED connected to digital pin 13 +#define LED_DDR DDRC +#define LED_PORT PORTC +#define LED_PIN PINC +#define LED_OUT 0 + +// AZFM board activate +#define AZFM_DDR DDRD +#define AZFM_PORT PORTD +#define AZFM_PIN PIND +#define AZFMOUT 6 +#define AZFM_INIT sbi(AZFM_DDR, AZFMOUT); cbi(AZFM_PORT, AZFMOUT); +#define AZFM_ON sbi(AZFM_PORT, AZFMOUT); +#define AZFM_OFF cbi(AZFM_PORT, AZFMOUT); + +#endif + +//********** arduino & driver based on resistors ********** +#ifdef AVCLAN_RESISTOR +#define AVCLANDRIVER_TYPE "Arduino - resistor" +// define out pin (pin 6 arduino) for AVCLAN_RESISTOR +#define DATAOUT_DDR DDRD +#define DATAOUT_PORT PORTD +#define DATAOUT_PIN PIND +#define DATAOUT 6 + +// define in pin (pin 7 arduino) for AVCLAN_RESISTOR +#define DATAIN_DDR DDRD +#define DATAIN_PORT PORTD +#define DATAIN_PIN PIND +#define DATAIN 7 + +// LED connected to digital pin 13 +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED_OUT 5 + +// AZFM board activate +#define AZFM_INIT +#define AZFM_ON +#define AZFM_OFF + +#endif + + diff --git a/arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.cpp b/arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.cpp new file mode 100644 index 0000000..dee0b15 --- /dev/null +++ b/arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.cpp @@ -0,0 +1,64 @@ +/* + AVCLanDrv.cpp - AVCLan CD changer library for 'duino / Wiring + Created by Kochetkov Aleksey, 06.04.2010 + Version 0.1.1 +*/ + +#include "AVCLanDrv.h" +#include "AVCLanNavi.h" +#include + +AvcInMessageTable mtMain[] PROGMEM = { + {ACT_REGISTER, 0x03, {0x12, 0x01, 0x00}}, + {ACT_INIT, 0x03, {0x12, 0x01, 0x01}}, +}; + +const byte mtMainSize = sizeof(mtMain) / sizeof(AvcInMessageTable); + +AvcInMessageTable mtSearchHead[] PROGMEM = { + {ACT_REGISTER, 0x03, {0x12, 0x01, 0x00}}, // AVC LAN register + {ACT_REGISTER, 0x03, {0x12, 0x01, 0x01}}, // AVC LAN init + {ACT_REGISTER, 0x03, {0x01, 0x01, 0x58}}, + {ACT_REGISTER, 0x03, {0x01, 0x01, 0x5B}}, + {ACT_REGISTER, 0x04, {0x01, 0x01, 0x5F, 0x01}}, +}; +const byte mtSearchHeadSize = sizeof(mtSearchHead) / sizeof(AvcInMessageTable); + +AvcOutMessage CmdReset PROGMEM = {AVC_MSG_BROADCAST, 0x05, {0x00, 0x00, 0x00, 0x00, 0x00}}; // reset AVCLan. This causes HU to send ACT_REGISTER +AvcOutMessage CmdRegister PROGMEM = {AVC_MSG_DIRECT, 0x0D, {0x00, 0x01, 0x12, 0x10, 0x58, 0x24, 0x5A, 0x85, 0x59, 0x6D, 0x57, 0x68, 0xAE}}; // register navi +AvcOutMessage CmdInit PROGMEM = {AVC_MSG_BROADCAST, 0x09, {0x6D, 0x31, 0xF1, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}}; // init command + +// AVCLan Navi init, +void AVCLanNavi::begin(){ + avclan.deviceAddress = 0x0178; +} + +// Use the last received message to determine the corresponding action ID, store it in avclan object +void AVCLanNavi::getActionID(){ + if (avclan.headAddress == 0){ + avclan.actionID = avclan.getActionID(mtSearchHead, mtSearchHeadSize); + }else{ + avclan.actionID = avclan.getActionID(mtMain, mtMainSize); + } +}; + +// process action +void AVCLanNavi::processAction(AvcActionID ActionID){ + byte r; + switch (ActionID){ + case ACT_REGISTER: // register device + if (avclan.headAddress == 0) avclan.headAddress = avclan.masterAddress; + avclan.sendMessage(&CmdRegister); + break; + } +}; + +// process event +void AVCLanNavi::processEvent(AvcEventID EventID){ + switch (EventID){ + case EV_STATUS: + break; + } +}; + +AVCLanNavi avclanDevice; \ No newline at end of file diff --git a/arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.h b/arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.h new file mode 100644 index 0000000..b1664a4 --- /dev/null +++ b/arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.h @@ -0,0 +1,41 @@ +/* + AVCLanNavi.h - AVCLan Navi library for 'duino / Wiring + Created by Kochetkov Aleksey, 16.06.2010 + Version 0.0.1 +*/ + +#ifndef AVCLanNavi_h +#define AVCLanNavi_h + +#include +#include "AVCLanDrv.h" +#include "WProgram.h" + +#define AVCLANDEVICE_NAME " Navi" +#define AVCLANDEVICE_VERSION "0.0.1" + +extern AvcOutMessage CmdReset; // reset AVCLan. This causes HU to send ACT_REGISTER +extern AvcOutMessage CmdRegister; // register CD changer +// extern AvcOutMessage *CmdTest; // test message + + + +typedef enum{ + ACT_REGISTER = 1, + ACT_INIT, +} AvcActionID; + +typedef enum{ + EV_STATUS = 1, +} AvcEventID; + +class AVCLanNavi{ + public: + void begin (); // initialisation, obligatory method + void getActionID(); // get action id by recieved message, obligatory method + void processAction(AvcActionID); // process action, obligatory method + void processEvent(AvcEventID); // process event, obligatory method +}; +#endif + +extern AVCLanNavi avclanDevice; diff --git a/arduino/mini2/libraries/AVCLanNavi/changelog.txt b/arduino/mini2/libraries/AVCLanNavi/changelog.txt new file mode 100644 index 0000000..e69de29 diff --git a/arduino/mini2/libraries/BuffSerial/BuffSerial.cpp b/arduino/mini2/libraries/BuffSerial/BuffSerial.cpp new file mode 100644 index 0000000..8351a02 --- /dev/null +++ b/arduino/mini2/libraries/BuffSerial/BuffSerial.cpp @@ -0,0 +1,176 @@ +/* + BuffSerial.cpp - serial with transmit buffer library for Wiring + Created by Kochetkov Aleksey, 28.11.2009 + Version 0.1.2 +*/ +#include + +#include "BuffSerial.h" + +// serial init +void BuffSerial::begin(long speed){ +#if defined(__AVR_ATmega8__) + UCSRB = _BV(RXCIE) | _BV(RXEN) | _BV(TXCIE) | _BV(TXEN); // enable rx, tx inerrputs + UBRRH = ((F_CPU / 16 + speed / 2) / speed - 1) >> 8; // usart speed + UBRRL = ((F_CPU / 16 + speed / 2) / speed - 1); +#else + UCSR0B = (_BV(RXCIE0) | _BV(RXEN0) | _BV(TXCIE0) | _BV(TXEN0)); // enable rx, tx inerrputs + UBRR0H = ((F_CPU / 16 + speed / 2) / speed - 1) >> 8; // usart speed + UBRR0L = ((F_CPU / 16 + speed / 2) / speed - 1); +#endif + rxBegin = rxEnd = 0; + txBegin = txEnd = txOverflow = 0; + txFull = 0; +} + +//USART Rx Complete +#if defined(__AVR_ATmega8__) +SIGNAL(SIG_UART_RECV) +#else +SIGNAL(USART_RX_vect) +#endif +{ +#if defined(__AVR_ATmega8__) + bSerial.rxBuffer[bSerial.rxEnd] = UDR; +#else + bSerial.rxBuffer[bSerial.rxEnd] = UDR0; +#endif + if (bSerial.rxEnd < RX_BUFF_SIZE) bSerial.rxEnd++; +} + +//USART Tx Complete +#if defined(__AVR_ATmega8__) +SIGNAL(SIG_UART_TRANS) +#else +SIGNAL(USART_TX_vect) +#endif +{ + if (bSerial.txEnd != bSerial.txBegin || bSerial.txFull != 0){ +#if defined(__AVR_ATmega8__) + UDR = bSerial.txBuffer[bSerial.txBegin]; // Send buffer +#else + UDR0 = bSerial.txBuffer[bSerial.txBegin]; // Send buffer +#endif + bSerial.txFull = 0; + bSerial.txBegin++; + if (bSerial.txBegin == TX_BUFF_SIZE) bSerial.txBegin = 0; + } + +} + +// send byte to serial or buffer if bisy +void BuffSerial::sendByte(uint8_t data){ + if (txFull){ + txOverflow++; + }else{ + uint8_t oldSREG = SREG; + cli(); +#if defined(__AVR_ATmega8__) + if (txEnd != txBegin || (UCSRA & _BV(UDRE)) == 0){ +#else + if (txEnd != txBegin || (UCSR0A & _BV(UDRE0)) == 0){ +#endif + txBuffer[txEnd] = data; + txEnd++; + if (txEnd == TX_BUFF_SIZE) txEnd = 0; + if (txEnd == txBegin) txFull = 1; // buffer overflow + }else{ +#if defined(__AVR_ATmega8__) + UDR = data; +#else + UDR0 = data; +#endif + } + SREG = oldSREG; + } +} + +// print string +void BuffSerial::print(const char *pBuf){ + while (*pBuf) { + sendByte(*pBuf++); + } +} + +void BuffSerial::print(const char pBuf){ + sendByte(pBuf); +} + +// print string from flash +void BuffSerial::print_p(const char *pBuf){ + char c; + while ((c = pgm_read_byte_near( pBuf++ ))) { + sendByte(c); + } +} + +void BuffSerial::println(const char *pBuf){ + print(pBuf); + println(); +} + +void BuffSerial::println(const char pBuf){ + print(pBuf); + println(); +} + +void BuffSerial::println(void){ + print("\r\n"); +} + +void BuffSerial::println_p(const char *pBuf){ + print_p(pBuf); + println(); +} + +void BuffSerial::printHex4(uint8_t data){ + uint8_t c = data & 0x0f; + c += c < 10 ? '0' : 'A' - 10 ; + sendByte(c); +} + +void BuffSerial::printHex8(uint8_t data){ + printHex4(data >> 4); + printHex4(data); +} + +void BuffSerial::printDec(uint8_t data){ + uint8_t buf[3]; + uint8_t i = 0; + if (data == 0){ + sendByte('0'); + return; + } + + while (data > 0){ + buf[i++] = data % 10; + data /= 10; + } + for (; i > 0; i--) + sendByte((buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10)); +} + +// check rx buffer not empty +bool BuffSerial::rxEnabled(void){ + return rxEnd; +} + +uint8_t BuffSerial::rxRead(void){ +#if defined(__AVR_ATmega8__) + cbi(UCSRB, RXCIE); // disable RX complete interrupt +#else + cbi(UCSR0B, RXCIE0); // disable RX complete interrupt +#endif + uint8_t readkey = rxBuffer[rxBegin]; // read begin of received Buffer + rxBegin++; + if (rxBegin == rxEnd) rxBegin = rxEnd = 0; // if Buffer is empty reset Buffer +#if defined(__AVR_ATmega8__) + sbi(UCSRB, RXCIE); // enable RX complete interrupt +#else + sbi(UCSR0B, RXCIE0); // enable RX complete interrupt +#endif + + return readkey; +} + +BuffSerial bSerial; diff --git a/arduino/mini2/libraries/BuffSerial/BuffSerial.h b/arduino/mini2/libraries/BuffSerial/BuffSerial.h new file mode 100644 index 0000000..efde980 --- /dev/null +++ b/arduino/mini2/libraries/BuffSerial/BuffSerial.h @@ -0,0 +1,54 @@ +/* + BuffSerial.h - serial with transmit buffer library for Wiring + Created by Kochetkov Aleksey, 28.11.2009 + Version 0.1.2 +*/ + +#ifndef BuffSerial_h +#define BuffSerial_h + +#include +#include "Arduino.h" + +#define TX_BUFF_SIZE 240 // max 65535 +#define RX_BUFF_SIZE 25 // max 255 +#define TX_BUFF_MAX_LEN TX_BUFF_SIZE - 1 +#define BUFFSERIAL_VERSION "0.1.2" + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +class BuffSerial{ + public: + uint8_t rxBuffer[RX_BUFF_SIZE]; + uint8_t rxBegin; + uint8_t rxEnd; + uint8_t txBuffer[TX_BUFF_SIZE]; + uint16_t txBegin; + uint16_t txEnd; + uint8_t txFull; + uint16_t txOverflow; + void begin(long); + void sendByte(uint8_t); + void print(const char*); + void print(const char); + void print_p(const char*); + void println(const char*); + void println(const char); + void println(void); + void println_p(const char*); + void printHex4(uint8_t); + void printHex8(uint8_t); + void printDec(uint8_t); + bool rxEnabled(void); + uint8_t rxRead(void); +}; + +extern BuffSerial bSerial; + +#endif + diff --git a/arduino/mini2/libraries/BuffSerial/changelog.txt b/arduino/mini2/libraries/BuffSerial/changelog.txt new file mode 100644 index 0000000..28fa686 --- /dev/null +++ b/arduino/mini2/libraries/BuffSerial/changelog.txt @@ -0,0 +1,2 @@ +2009-11-31 0.1.2 + + PSTR (println_p, print_p) \ No newline at end of file diff --git a/arduino/mini2/libraries/readme.txt b/arduino/mini2/libraries/readme.txt new file mode 100644 index 0000000..96ce674 --- /dev/null +++ b/arduino/mini2/libraries/readme.txt @@ -0,0 +1 @@ +For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries