diff --git a/Makefile b/Makefile index a2dd96d..39e260b 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ COMPILER_PATH = g++ OUTPUT = main CFLAGS = -std=c++14 -O3 LDFLAGS = -OBJECTS = main.o drv/b15f.o drv/plottyfile.o drv/dot.o +OBJECTS = main.o drv/usart.o drv/b15f.o drv/plottyfile.o drv/dot.o COMPILE = $(COMPILER_PATH) $(CFLAGS) diff --git a/drv/b15f.cpp b/drv/b15f.cpp index ebcef9f..c58b4eb 100644 --- a/drv/b15f.cpp +++ b/drv/b15f.cpp @@ -31,7 +31,7 @@ void B15F::init() std::cout << "OK" << std::endl; - delay(1); + delay_ms(1); std::cout << PRE << "Teste Verbindung... " << std::flush; uint8_t tries = 3; @@ -65,7 +65,7 @@ void B15F::reconnect() uint8_t tries = RECONNECT_TRIES; while(tries--) { - delay(RECONNECT_TIMEOUT); + delay_ms(RECONNECT_TIMEOUT); discard(); @@ -86,7 +86,7 @@ void B15F::discard(void) for(uint8_t i = 0; i < 8; i++) { writeByte(RQ_DISC); // sende discard Befehl (verwerfe input) - delay((16000 / BAUDRATE) + 1); // warte mindestens eine Millisekunde, gegebenenfalls mehr + delay_ms((16000 / BAUDRATE) + 1); // warte mindestens eine Millisekunde, gegebenenfalls mehr } tcflush(usart, TCIFLUSH); // leere Eingangspuffer } @@ -219,7 +219,9 @@ bool B15F::analogWrite0(uint16_t value) try { writeByte(RQ_AA0); + delay_ms(1); writeInt(value); + delay_ms(1); uint8_t aw = readByte(); return aw == MSG_OK; @@ -253,6 +255,7 @@ uint16_t B15F::analogRead(uint8_t channel) try { writeByte(RQ_ADC); + delay_ms(1); writeByte(channel); return readInt(); } @@ -316,13 +319,13 @@ bool B15F::analogSequence(uint8_t channel_a, uint16_t* buffer_a, uint32_t offset void B15F::writeByte(uint8_t b) -{ +{ if(write(usart, &b, 1) != 1) throw DriverException("Fehler beim Senden. (byte)"); } void B15F::writeInt(uint16_t v) -{ +{ if(write(usart, reinterpret_cast(&v), 2) != 2) throw DriverException("Fehler beim Senden. (int)"); } @@ -434,10 +437,15 @@ bool B15F::readBlock(uint8_t* buffer, uint16_t offset) } } -void B15F::delay(uint16_t ms) +void B15F::delay_ms(uint16_t ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } + +void B15F::delay_us(uint16_t us) +{ + std::this_thread::sleep_for(std::chrono::microseconds(us)); +} B15F& B15F::getInstance(void) { diff --git a/drv/b15f.h b/drv/b15f.h index c5a8790..4d48b21 100644 --- a/drv/b15f.h +++ b/drv/b15f.h @@ -15,6 +15,7 @@ #include #include #include "driverexception.h" +#include "timeoutexception.h" class B15F { @@ -39,25 +40,55 @@ public: uint16_t analogRead(uint8_t); bool analogSequence(uint8_t channel_a, uint16_t* buffer_a, uint32_t offset_a, uint8_t channel_b, uint16_t* buffer_b, uint32_t offset_b, uint16_t start, int16_t delta, uint16_t count); - // Serielle Verbindung - inline void writeByte(uint8_t); - inline void writeInt(uint16_t); - inline uint8_t readByte(void); - inline uint16_t readInt(void); - inline bool readBlock(uint8_t* buffer, uint16_t offset); + /** + * Lässt den Treiber für eine angegebene Zeit pausieren + * \param ms Verzögerung in Millisekunden + */ + void delay_ms(uint16_t ms); + /** + * Lässt den Treiber für eine angegebene Zeit pausieren + * \param us Verzögerung in Microsekunden + */ + void delay_us(uint16_t us); - void delay(uint16_t); - + /** + * Liefert eine Referenz zur aktuellen Treiber-Instanz + * @throws DriverException + */ static B15F& getInstance(void); private: int usart = -1; - uint16_t timeout = 100; // ms + uint16_t timeout = 1000; // ms uint16_t block_timeout = 1; // ms int TEST = 0; static B15F* instance; + + + /*********************************************** + * Grundfunktionen für die serielle Verbindung * + ***********************************************/ + + /** + * Übergibt ein Byte an die USART Schnittstelle + */ + void writeByte(uint8_t); + + /** + * Übergibt ein Integer an die USART Schnittstelle + */ + void writeInt(uint16_t); + + /** + * Übergibt ein Integer an die USART Schnittstelle + * \throws TimeoutException + */ + uint8_t readByte(void); + uint16_t readInt(void); + bool readBlock(uint8_t* buffer, uint16_t offset); + // CONSTANTS const std::string PRE = "[B15F] "; @@ -66,7 +97,7 @@ private: constexpr static uint8_t MSG_FAIL = 0xFE; constexpr static uint16_t RECONNECT_TIMEOUT = 64; // ms constexpr static uint8_t RECONNECT_TRIES = 3; - constexpr static uint32_t BAUDRATE = 38400; + constexpr static uint32_t BAUDRATE = 115200; constexpr static uint8_t CRC7_POLY = 0x91; // REQUESTS diff --git a/drv/b15f.o b/drv/b15f.o index f95b112..47f3a9c 100644 Binary files a/drv/b15f.o and b/drv/b15f.o differ diff --git a/drv/driverexception.h b/drv/driverexception.h index 8352fd4..05f8e3e 100644 --- a/drv/driverexception.h +++ b/drv/driverexception.h @@ -29,4 +29,4 @@ protected: std::string msg_; }; -#endif +#endif // DRIVEREXCEPTION_H diff --git a/drv/timeoutexception.h b/drv/timeoutexception.h new file mode 100644 index 0000000..dea32b3 --- /dev/null +++ b/drv/timeoutexception.h @@ -0,0 +1,35 @@ +#ifndef TIMEOUTEXCEPTION_H +#define TIMEOUTEXCEPTION_H + +#include + +// SOURCE: https://stackoverflow.com/a/8152888 + +class TimeoutException: public std::exception +{ +public: + explicit TimeoutException(const char* message, int timeout) : TimeoutException(std::string(message), timeout) + { + } + + explicit TimeoutException(const std::string& message, int timeout) : msg(message), timeout(timeout) + { + if(!msg.length()) + msg = "Timeout reached (" + std::to_string(timeout) + ")"; + } + + virtual ~TimeoutException() throw () + { + } + + virtual const char* what() const throw () + { + return msg.c_str(); + } + +protected: + std::string msg; + int timeout; +}; + +#endif // TIMEOUTEXCEPTION_H diff --git a/drv/usart.cpp b/drv/usart.cpp new file mode 100644 index 0000000..554c598 --- /dev/null +++ b/drv/usart.cpp @@ -0,0 +1,74 @@ +#include "usart.h" + +USART::USART(std::string device) : device(device) +{ +} + +void USART::openDevice() +{ + file_desc = open(device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); + if(file_desc <= 0) + throw USARTException("Fehler beim Öffnen des Gerätes"); + + struct termios options; + int code = tcgetattr(file_desc, &options); + if(code) + throw USARTException("Fehler beim Lesen der Geräteparameter"); + + options.c_cflag = CS8 | CLOCAL | CREAD; + options.c_iflag = IGNPAR; + options.c_oflag = 0; + options.c_lflag = 0; + options.c_cc[VTIME] = timeout; + code = cfsetspeed(&options, baudrate); + if(code) + throw USARTException("Fehler beim Setzen der Baudrate"); + + code = tcsetattr(file_desc, TCSANOW, &options); + if(code) + throw USARTException("Fehler beim Setzen der Geräteparameter"); + + clearOutputBuffer(); + clearInputBuffer(); +} + +void USART::closeDevice() +{ + int code = close(file_desc); + if(code) + throw USARTException("Fehler beim Schließen des Gerätes"); +} + +void USART::clearInputBuffer() +{ + int code = tcflush(file_desc, TCIFLUSH); + if(code) + throw USARTException("Fehler beim Leeren des Eingangspuffers"); +} + +void USART::clearOutputBuffer() +{ + int code = tcflush(file_desc, TCOFLUSH); + if(code) + throw USARTException("Fehler beim Leeren des Ausgangspuffers"); +} + +uint32_t USART::getBaudrate() +{ + return baudrate; +} + +uint8_t USART::getTimeout() +{ + return timeout; +} + +void USART::setBaudrate(uint32_t baudrate) +{ + this->baudrate = baudrate; +} + +void USART::setTimeout(uint8_t timeout) +{ + this->timeout = timeout; +} diff --git a/drv/usart.h b/drv/usart.h new file mode 100644 index 0000000..7d17d20 --- /dev/null +++ b/drv/usart.h @@ -0,0 +1,102 @@ +#ifndef USART_H +#define USART_H + +#include +#include +#include +#include +#include +#include "usartexception.h" + +class USART +{ +public: + USART(std::string device); + + /************************************************* + * Methoden für die Verwaltung der Schnittstelle * + *************************************************/ + + /** + * Öffnet die USART Schnittstelle + * \throws USARTException + */ + void openDevice(void); + + /** + * Schließt die USART Schnittstelle + * \throws USARTException + */ + void closeDevice(void); + + /** + * Verwirft Daten, die bereits im Puffer liegen, aber noch nicht gelesen wurden + * \throws USARTException + */ + void clearInputBuffer(void); + + /** + * Verwirft Daten, die bereits im Puffer liegen, aber noch nicht gesendet wurden + * \throws USARTException + */ + void clearOutputBuffer(void); + + /*************************************************/ + + + + /************************************* + * Methoden für die Datenübertragung * + *************************************/ + + /** + * Sendet ein Byte über die USART Schnittstelle + * \param b das zu sendende Byte + * \throws USARTException + */ + void writeByte(uint8_t b); + + /*************************************/ + + + + /*************************************** + * Methoden für einstellbare Parameter * + ***************************************/ + + /** + * Liefert die eingestellte Baudrate + * Änderungen werden erst nach einem open() wirksam + */ + uint32_t getBaudrate(void); + + /** + * Liefert den eingestellten Timeout (in Dezisekunden) + * Änderungen werden erst nach einem open() wirksam + */ + uint8_t getTimeout(void); + + /** + * Setzt die Baudrate + * Änderungen werden erst nach einem open() wirksam + */ + void setBaudrate(uint32_t baudrate); + + /** + * Setzt den Timeout (in Dezisekunden) + * Änderungen werden erst nach einem open() wirksam + */ + void setTimeout(uint8_t timeout); + + /***************************************/ + +private: + + std::string device; // Gerätepfad + int file_desc = -1; // Linux Dateideskriptor + uint32_t baudrate = 9600; + uint8_t timeout = 10; // in Dezisekunden +}; + + +#endif // USART_H diff --git a/drv/usart.o b/drv/usart.o new file mode 100644 index 0000000..3039e27 Binary files /dev/null and b/drv/usart.o differ diff --git a/drv/usartexception.h b/drv/usartexception.h new file mode 100644 index 0000000..840ce6c --- /dev/null +++ b/drv/usartexception.h @@ -0,0 +1,33 @@ +#ifndef USARTEXCEPTION_H +#define USARTEXCEPTION_H + +#include +#include + +// SOURCE: https://stackoverflow.com/a/8152888 + +class USARTException: public std::exception +{ +public: + explicit USARTException(const char* message) : msg(message) + { + } + + explicit USARTException(const std::string& message) : msg(message) + { + } + + virtual ~USARTException() throw () + { + } + + virtual const char* what() const throw () + { + return msg.c_str(); + } + +protected: + std::string msg; +}; + +#endif // USARTEXCEPTION_H diff --git a/main b/main index c5917cc..da5b077 100755 Binary files a/main and b/main differ diff --git a/main.cpp b/main.cpp index b208336..6f27b98 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,6 @@ #include +#include +#include "drv/usart.h" #include "drv/b15f.h" #include "drv/plottyfile.h" @@ -35,9 +37,9 @@ void kennlinieErsterQuadrant() drv.analogWrite1(u_gs); drv.analogSequence(0, &ba[0], 0, 1, &bb[0], 0, 0, delta, sample_count); - drv.delay(10); + drv.delay_ms(10); drv.discard(); - drv.delay(10); + drv.delay_ms(10); for(uint16_t k = 0; k < sample_count+1; k++) { @@ -110,18 +112,34 @@ void beispielFunktionen() { B15F& drv = B15F::getInstance(); - /* + for(uint16_t i = 0; i < 256; i++) { drv.digitalWrite0(i); - drv.delay(50); - }*/ + drv.delay_ms(100); + } + + + + + while(1) + { + for(double d = 0; d < M_PI*2; d += .1) + { + uint16_t v = (sin(d) * 511 + 511); + drv.analogWrite0(v); + } + + } + + + uint16_t schwelle_unten = 1023; for(uint16_t i = 0; i < 1024; i++) { drv.analogWrite0(i); - drv.delay(1); + drv.delay_ms(1); if(drv.digitalRead0() & 0x01) { drv.discard(); @@ -142,7 +160,6 @@ void beispielFunktionen() for(uint16_t i = 1023; i > 0; i--) { drv.analogWrite0(i); - drv.delay(1); if(!(drv.digitalRead0() & 0x01)) { drv.discard(); @@ -165,7 +182,8 @@ void beispielFunktionen() int main() { - beispielFunktionen(); + USART usart("/dev/ttyUSB0"); + usart.openDevice(); diff --git a/main.o b/main.o index d3c8707..551fea6 100644 Binary files a/main.o and b/main.o differ