mirror of
https://github.com/KostyaSha/arduino-iebus.git
synced 2025-06-20 22:06:09 +00:00
Move one variant, create other for sniffing
This commit is contained in:
parent
c4aee10f3d
commit
94d0e5d3fe
212
arduino/mini2/AVCLan_mini/AVCLan_mini.ino
Normal file
212
arduino/mini2/AVCLan_mini/AVCLan_mini.ino
Normal file
@ -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 <EEPROM.h>
|
||||||
|
#include <AVCLanDrv.h>
|
||||||
|
#include <AVCLanCDch.h>
|
||||||
|
#include <BuffSerial.h>
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
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<s_len; i++)
|
||||||
|
avclan.message[i]=data_tmp[i];
|
||||||
|
avclan.sendMessage();
|
||||||
|
break;
|
||||||
|
case 'Q' : // end of broadcast command
|
||||||
|
readSeq=0;
|
||||||
|
avclan.dataSize = s_len;
|
||||||
|
avclan.broadcast = AVC_MSG_BROADCAST;
|
||||||
|
avclan.masterAddress = avclan.deviceAddress;
|
||||||
|
avclan.slaveAddress = 0x01FF;
|
||||||
|
for (i=0; i<s_len; i++)
|
||||||
|
avclan.message[i]=data_tmp[i];
|
||||||
|
avclan.sendMessage();
|
||||||
|
break;
|
||||||
|
case 'H' : // end of set Head Unid ID
|
||||||
|
readSeq=0;
|
||||||
|
avclan.headAddress = (data_tmp[0] << 8) + data_tmp[1];
|
||||||
|
EEPROM.write(E_MASTER1, data_tmp[0]);
|
||||||
|
EEPROM.write(E_MASTER2, data_tmp[1]);
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
if (readSeq==1) {
|
||||||
|
if (readkey!=' ') {
|
||||||
|
s_c[s_dig]=readkey;
|
||||||
|
s_dig++;
|
||||||
|
if (s_dig==2) {
|
||||||
|
if (s_c[0]<':'){
|
||||||
|
s_c[0] -= 48;
|
||||||
|
}else{
|
||||||
|
s_c[0] -= 55;
|
||||||
|
}
|
||||||
|
data_tmp[s_len] = 16 * s_c[0];
|
||||||
|
if (s_c[1]<':'){
|
||||||
|
s_c[1] -= 48;
|
||||||
|
}else{
|
||||||
|
s_c[1] -= 55;
|
||||||
|
}
|
||||||
|
data_tmp[s_len] += s_c[1];
|
||||||
|
s_len++;
|
||||||
|
s_dig=0;
|
||||||
|
s_c[0]=s_c[1]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMess(){
|
||||||
|
avclan.broadcast = AVC_MSG_DIRECT;
|
||||||
|
avclan.masterAddress = 0x0360;
|
||||||
|
avclan.slaveAddress = 0x0140;
|
||||||
|
avclan.dataSize = 0x05;
|
||||||
|
avclan.message[0] = 0x00;
|
||||||
|
avclan.message[1] = 0x01;
|
||||||
|
avclan.message[2] = 0x12;
|
||||||
|
avclan.message[2] = 0x10;
|
||||||
|
avclan.message[3] = 0x63;
|
||||||
|
byte res = avclan.sendMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Чтение конфигурации из EEPROM
|
||||||
|
void EERPOM_read_config(){
|
||||||
|
if (EEPROM.read(E_INIT) != 'T'){
|
||||||
|
EEPROM.write(E_MASTER1, 0x01);
|
||||||
|
EEPROM.write(E_MASTER2, 0x40);
|
||||||
|
EEPROM.write(E_READONLY, 0);
|
||||||
|
EEPROM.write(E_INIT, 'T');
|
||||||
|
}else{
|
||||||
|
avclan.headAddress = (EEPROM.read(E_MASTER1) << 8) + EEPROM.read(E_MASTER2);
|
||||||
|
avclan.readonly = EEPROM.read(E_READONLY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
arduino/mini2/AVCLan_mini/changelog.txt
Normal file
20
arduino/mini2/AVCLan_mini/changelog.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
2010-07-22 0.1.6
|
||||||
|
+ во время приема сообщения из шины, загорается светодиод. Настройки порта для подключения светодиода в AVCLanDrv\config.h
|
||||||
|
+ добавлен вывод типа драйвера при печати версий компонентов по кнопке "V"
|
||||||
|
+ добавлен режим только чтение, плата не будет слать никаких сообщений в шину. Включение выключение по кнопке "M". Текущее значение сохраняется в EEPROM
|
||||||
|
|
||||||
|
2010-04-26 0.1.5
|
||||||
|
+ Вывод помощи по кнопке "?"
|
||||||
|
+ Установка адреса головы по команде вида S[адрес головы]H (0000 - автоматическое определение адреса). Сохранение адреса головы в EERPOM
|
||||||
|
* изменено назначение кнопок
|
||||||
|
h - Output mode On. Set Hi level
|
||||||
|
l - Output mode On. Set Low level
|
||||||
|
i - Input mode On. Read AVC-Lan
|
||||||
|
+ добавлена обработка событий avclan.event
|
||||||
|
+ после чтения сообщения запускается функция определения его ID (avclanDevice.getActionID), если ID найдено, запускается обработка сообщений (avclanDevice.processAction)
|
||||||
|
|
||||||
|
2009-11-31 0.1.4
|
||||||
|
+ При включении выводится номер текущей версии
|
||||||
|
+ Вывод версий компонентов по кнопке "V"
|
||||||
|
+ При печати конфигурации выводятся адрес головы и устройства
|
||||||
|
|
293
arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.cpp
Normal file
293
arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.cpp
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
AVCLanDrv.cpp - AVCLan CD changer library for 'duino / Wiring
|
||||||
|
Created by Kochetkov Aleksey, 04.08.2010
|
||||||
|
Version 0.2.2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AVCLanDrv.h"
|
||||||
|
#include "AVCLanCDch.h"
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
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;
|
102
arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.h
Normal file
102
arduino/mini2/libraries/AVCLanCDch/AVCLanCDch.h
Normal file
@ -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 <avr/pgmspace.h>
|
||||||
|
#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;
|
11
arduino/mini2/libraries/AVCLanCDch/changelog.txt
Normal file
11
arduino/mini2/libraries/AVCLanCDch/changelog.txt
Normal file
@ -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'а
|
||||||
|
+ автоматическое определение адреса головы
|
||||||
|
|
579
arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.cpp
Normal file
579
arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.cpp
Normal file
@ -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;
|
131
arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.h
Normal file
131
arduino/mini2/libraries/AVCLanDrv/AVCLanDrv.h
Normal file
@ -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
|
15
arduino/mini2/libraries/AVCLanDrv/changelog.txt
Normal file
15
arduino/mini2/libraries/AVCLanDrv/changelog.txt
Normal file
@ -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)
|
||||||
|
|
137
arduino/mini2/libraries/AVCLanDrv/config.h
Normal file
137
arduino/mini2/libraries/AVCLanDrv/config.h
Normal file
@ -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
|
||||||
|
|
||||||
|
|
64
arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.cpp
Normal file
64
arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.cpp
Normal file
@ -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 <avr/pgmspace.h>
|
||||||
|
|
||||||
|
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;
|
41
arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.h
Normal file
41
arduino/mini2/libraries/AVCLanNavi/AVCLanNavi.h
Normal file
@ -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 <avr/pgmspace.h>
|
||||||
|
#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;
|
0
arduino/mini2/libraries/AVCLanNavi/changelog.txt
Normal file
0
arduino/mini2/libraries/AVCLanNavi/changelog.txt
Normal file
176
arduino/mini2/libraries/BuffSerial/BuffSerial.cpp
Normal file
176
arduino/mini2/libraries/BuffSerial/BuffSerial.cpp
Normal file
@ -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 <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
54
arduino/mini2/libraries/BuffSerial/BuffSerial.h
Normal file
54
arduino/mini2/libraries/BuffSerial/BuffSerial.h
Normal file
@ -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 <avr/pgmspace.h>
|
||||||
|
#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
|
||||||
|
|
2
arduino/mini2/libraries/BuffSerial/changelog.txt
Normal file
2
arduino/mini2/libraries/BuffSerial/changelog.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
2009-11-31 0.1.2
|
||||||
|
+ добавлены фунции печати строк PSTR (println_p, print_p)
|
1
arduino/mini2/libraries/readme.txt
Normal file
1
arduino/mini2/libraries/readme.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries
|
Loading…
x
Reference in New Issue
Block a user