diff --git a/arduino/AVCLan_mini/AVCLan_mini.ino b/arduino/AVCLan_mini/AVCLan_mini.ino new file mode 100644 index 0000000..678b033 --- /dev/null +++ b/arduino/AVCLan_mini/AVCLan_mini.ino @@ -0,0 +1,141 @@ + +#include +#include +#include + + +int ledPin = 13; // LED connected to digital pin 13 +AVCLanDrv avclan; +bool first; +byte t; +byte count; + +void setup(){ + pinMode(ledPin, OUTPUT); // sets the digital pin as output + bSerial.begin(250000); + avclan.begin(); + bSerial.println("AVCLan"); + first = true; +} + +void loop(){ + + + if (INPUT_IS_SET){ +// LedOn(); + byte res = avclan.readMessage(); + if (!res){ + avclan.printMessage(true); + }else{ + bSerial.print("R"); + bSerial.printHex4(res); + bSerial.println(); + while (!avclan.isAvcBusFree()); + } +// LedOff(); + }else{ + if (first){ + first = false; + avclan.deviceAddress = 0x240; + avclan.broadcast = AVC_MSG_BROADCAST; + avclan.masterAddress = 0x0360; + avclan.slaveAddress = 0x01FF; + avclan.dataSize = 0x04; + avclan.message[0] = 0x01; + avclan.message[1] = 0x11; + avclan.message[2] = 0x13; + avclan.message[3] = 0x63; +// byte res = avclan.sendMessage(); +// if (!res){ +// avclan.printMessage(false); +// }else{ +// bSerial.print("W"); +// bSerial.printHex4(res); +// bSerial.println(); +// } + } + } + if (bSerial.rxEnabled()) { + cbi(UCSR0B, RXCIE0); // disable RX complete interrupt + uint8_t readkey = bSerial.rxRead(); + + switch (readkey){ + case 'P': // print config + bSerial.print("Overflow: "); + bSerial.printHex8(bSerial.txOverflow >> 8); + bSerial.printHex8(bSerial.txOverflow); + bSerial.println(); + break; + case 'M': + count = 0; + while(1){ + while (INPUT_IS_SET); + uint8_t oldSREG = SREG; + cli(); // disable interrupts + while (INPUT_IS_CLEAR); + TCNT2 = 0; + while (INPUT_IS_SET){ + t = TCNT2; + if (t > 0xF0) break; + }; + t = t / 2; + SREG = oldSREG; + bSerial.printDec(t); + bSerial.println(); + count++; + if (count > 30){ + delay(300); + count = 0; + } + } + break; + case 'S': + bSerial.println("S"); + sendMess(); + break; + case 'H': + bSerial.println("H set"); + AVC_OUT_EN; + OUTPUT_SET_1; + break; + case 'L': + bSerial.println("L set"); + AVC_OUT_EN; + OUTPUT_SET_0; + break; + case 'D': + bSerial.println("Out dis"); + AVC_OUT_DIS; + break; + } + } +} + +void sendMess(){ + avclan.deviceAddress = 0x360; + avclan.broadcast = AVC_MSG_NORMAL; + 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(); + if (!res){ + avclan.printMessage(false); + }else{ + bSerial.print("W"); + bSerial.printHex4(res); + bSerial.println(); + } +} + +void LedOn(){ + digitalWrite(ledPin, HIGH); +} + +void LedOff(){ + digitalWrite(ledPin, LOW); +} diff --git a/arduino/README.md b/arduino/README.md new file mode 100644 index 0000000..8fe3c72 --- /dev/null +++ b/arduino/README.md @@ -0,0 +1,2 @@ +Sources from http://compcar.ru/forum/showthread.php?t=3959 + diff --git a/arduino/libraries/AVCLanDrv/AVCLanDrv.cpp b/arduino/libraries/AVCLanDrv/AVCLanDrv.cpp new file mode 100644 index 0000000..3899711 --- /dev/null +++ b/arduino/libraries/AVCLanDrv/AVCLanDrv.cpp @@ -0,0 +1,447 @@ +/* + AVCLanDrv.cpp v.01 - AVCLan Library for 'duino / Wiring + Created by Kochetkov Aleksey, 30.06.2009 +*/ + +#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 + sbi(DATAOUT_DDR, DATAOUT); + sbi(OUTEN_DDR, OUTEN); + AVC_OUT_DIS; + OUTPUT_SET_0; +#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 + deviceAddress = 0x0000; +} + +// 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; + } + } + 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) { + 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. + send1BitWord(0); + }else{ + readBits(1); + } + + // Control + readBits(4); + p = _parityBit; + if (p != readBits(1)){ + SREG = oldSREG; + return 5; + } + + if (forMe){ + // Send ACK. + send1BitWord(0); + }else{ + readBits(1); + } + + dataSize = readBits(8); + p = _parityBit; + if (p != readBits(1)){ + SREG = oldSREG; + return 6; + } + + if (forMe){ + // Send ACK. + send1BitWord(0); + }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. + send1BitWord(0); + }else{ + readBits(1); + } + } + SREG = oldSREG; + return 0; +} + +// 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 TRUE if successful else FALSE. +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; +} + +// print message to serial +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(); + +} diff --git a/arduino/libraries/AVCLanDrv/AVCLanDrv.h b/arduino/libraries/AVCLanDrv/AVCLanDrv.h new file mode 100644 index 0000000..3cd5a49 --- /dev/null +++ b/arduino/libraries/AVCLanDrv/AVCLanDrv.h @@ -0,0 +1,108 @@ +/* + AVCLanDrv.h v.01 - AVCLan Library for 'duino / Wiring + Created by Kochetkov Aleksey, 30.06.2009 +*/ + +#ifndef AVCLanDrv_h +#define AVCLanDrv_h + +#include "WProgram.h" +#include "config.h" + +#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 OUT_SET_1 (cbi(DATAOUT_PORT, DATAOUT)); +#define OUT_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_NORMAL = 1, + AVC_MSG_BROADCAST = 0 +} AvcTransmissionMode; + +typedef enum +{ + ACT_NONE, + + // ACT_AUX_IN_USE, + // ACT_TUNER_IN_USE, + // ACT_TAPE_IN_USE, + // ACT_CD_IN_USE, + + // ACT_EJECT_CD, + // ACT_NO_CD, + + // ACT_STATUS, + // ACT_REGISTER, + // ACT_INIT, + // ACT_CHECK +} AvcActionID; + +#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; + byte dataSize; + byte message[AVC_MAXMSGLEN]; + void begin (); + byte readMessage (); + byte sendMessage (void); + void printMessage(bool incoming); + bool isAvcBusFree (void); + private: + bool _parityBit; + word readBits (byte nbBits); + 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); +}; +#endif diff --git a/arduino/libraries/AVCLanDrv/WProgram.h b/arduino/libraries/AVCLanDrv/WProgram.h new file mode 100644 index 0000000..c45168e --- /dev/null +++ b/arduino/libraries/AVCLanDrv/WProgram.h @@ -0,0 +1,31 @@ +#ifndef WProgram_h +#define WProgram_h + +#include +#include +#include + +#include + +#include "Arduino.h" + +#ifdef __cplusplus +#ifndef BuffSerial_h +#include "HardwareSerial.h" +#endif + +uint16_t makeWord(uint16_t w); +uint16_t makeWord(byte h, byte l); + +#define word(...) makeWord(__VA_ARGS__) + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); + +// WMath prototypes +long random(long); +long random(long, long); +void randomSeed(unsigned int); +long map(long, long, long, long, long); +#endif + +#endif diff --git a/arduino/libraries/AVCLanDrv/config.h b/arduino/libraries/AVCLanDrv/config.h new file mode 100644 index 0000000..92d8d7a --- /dev/null +++ b/arduino/libraries/AVCLanDrv/config.h @@ -0,0 +1,43 @@ +/* + config.h - AVCLan driver config + Created by Kochetkov Aleksey, 30.06.2009 +*/ + +// type of AVCLan hardwire driver +#define AVCLAN_ST485 +//#define AVCLAN_PCA82C250 +//#define AVCLAN_RESISTOR + +#ifdef AVCLAN_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 +#endif + +// 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 + + diff --git a/arduino/libraries/BuffSerial/BuffSerial.cpp b/arduino/libraries/BuffSerial/BuffSerial.cpp new file mode 100644 index 0000000..fb2e1cf --- /dev/null +++ b/arduino/libraries/BuffSerial/BuffSerial.cpp @@ -0,0 +1,163 @@ +/* + BuffSerial.cpp v.01 - serial with transmit buffer library for Wiring + Created by Kochetkov Aleksey, 03.07.2009 +*/ +#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); +} + + +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::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/libraries/BuffSerial/BuffSerial.h b/arduino/libraries/BuffSerial/BuffSerial.h new file mode 100644 index 0000000..bc98022 --- /dev/null +++ b/arduino/libraries/BuffSerial/BuffSerial.h @@ -0,0 +1,49 @@ +/* + BuffSerial.h v.01 - serial with transmit buffer library for Wiring + Created by Kochetkov Aleksey, 03.07.2009 +*/ + +#ifndef BuffSerial_h +#define BuffSerial_h + +#include "WProgram.h" + +#define TX_BUFF_SIZE 240 // max 65535 +#define RX_BUFF_SIZE 25 // max 255 +#define TX_BUFF_MAX_LEN TX_BUFF_SIZE - 1 + +#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 println(const char*); + void println(const char); + void println(void); + void printHex4(uint8_t); + void printHex8(uint8_t); + void printDec(uint8_t); + bool rxEnabled(void); + uint8_t rxRead(void); +}; + +extern BuffSerial bSerial; + +#endif +