Merge remote-tracking branch 'drv/master'
This commit is contained in:
commit
c278274ed0
31
driver/Makefile
Normal file
31
driver/Makefile
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Name: Makefile
|
||||
# Project: B15F (board15 Famulus Edition)
|
||||
# Author: Tristan Krause
|
||||
# Creation Date: 2019-03-22
|
||||
|
||||
# Umgebungseinstellungen
|
||||
COMPILER_PATH = g++
|
||||
|
||||
|
||||
OUTPUT = main
|
||||
CFLAGS = -std=c++14 -O3 -Wall -Wextra
|
||||
LDFLAGS =
|
||||
OBJECTS = main.o drv/usart.o drv/b15f.o drv/plottyfile.o drv/dot.o
|
||||
|
||||
COMPILE = $(COMPILER_PATH) $(CFLAGS)
|
||||
|
||||
B15F: $(OBJECTS)
|
||||
@echo "Linking..."
|
||||
$(COMPILE) $(OBJECTS) -o $(OUTPUT) $(LDFLAGS)
|
||||
|
||||
help:
|
||||
@echo "This Makefile has the following rules:"
|
||||
@echo "make B15F .... to compile (default)"
|
||||
@echo "make clean ... to delete objects, elf and hex file"
|
||||
|
||||
clean:
|
||||
@echo "Cleaning..."
|
||||
rm -f $(OBJECTS) $(OUTPUT)
|
||||
|
||||
.cpp.o:
|
||||
$(COMPILE) -c $< -o $@
|
270
driver/drv/b15f.cpp
Normal file
270
driver/drv/b15f.cpp
Normal file
|
@ -0,0 +1,270 @@
|
|||
#include "b15f.h"
|
||||
|
||||
B15F* B15F::instance = nullptr;
|
||||
|
||||
B15F::B15F()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void B15F::init()
|
||||
{
|
||||
|
||||
std::string device = exec("bash -c 'ls /dev/ttyUSB*'");
|
||||
while(device.find(' ') != std::string::npos || device.find('\n') != std::string::npos || device.find('\t') != std::string::npos)
|
||||
device.pop_back();
|
||||
|
||||
if(device.length() == 0)
|
||||
throw DriverException("Adapter nicht gefunden");
|
||||
|
||||
std::cout << PRE << "Verwende Adapter: " << device << std::endl;
|
||||
|
||||
|
||||
|
||||
std::cout << PRE << "Stelle Verbindung mit Adapter her... " << std::flush;
|
||||
usart.setBaudrate(BAUDRATE);
|
||||
usart.openDevice(device);
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
|
||||
// Temporärer Test
|
||||
uint8_t block[] = {0, 1, 2, 3};
|
||||
while(1)
|
||||
usart.writeBlock(&block[0], 0, sizeof(block));
|
||||
throw std::runtime_error("SCHLUSS");
|
||||
|
||||
|
||||
|
||||
std::cout << PRE << "Teste Verbindung... " << std::flush;
|
||||
uint8_t tries = 3;
|
||||
while(tries--)
|
||||
{
|
||||
// verwerfe Daten, die µC noch hat
|
||||
discard();
|
||||
|
||||
if(!testConnection())
|
||||
continue;
|
||||
|
||||
if(!testIntConv())
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
if(tries == 0)
|
||||
throw DriverException("Verbindungstest fehlgeschlagen. Neueste Version im Einsatz?");
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
// Gib board info aus
|
||||
std::vector<std::string> info = getBoardInfo();
|
||||
std::cout << PRE << "AVR Firmware Version: " << info[0] << " um " << info[1] << " Uhr (" << info[2] << ")" << std::endl;
|
||||
}
|
||||
|
||||
void B15F::reconnect()
|
||||
{
|
||||
std::cout << PRE << "Verbindung unterbrochen, stelle Verbindung neu her: " << std::flush;
|
||||
|
||||
uint8_t tries = RECONNECT_TRIES;
|
||||
while(tries--)
|
||||
{
|
||||
delay_ms(RECONNECT_TIMEOUT);
|
||||
|
||||
discard();
|
||||
|
||||
if(testConnection())
|
||||
{
|
||||
std::cout << "OK" << std::endl << std::flush;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw DriverException("Verbindung kann nicht repariert werden");
|
||||
}
|
||||
|
||||
void B15F::discard(void)
|
||||
{
|
||||
usart.flushOutputBuffer();
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
usart.writeByte(RQ_DISC); // sende discard Befehl (verwerfe input)
|
||||
delay_ms((16000 / BAUDRATE) + 1); // warte mindestens eine Millisekunde, gegebenenfalls mehr
|
||||
}
|
||||
usart.flushInputBuffer();
|
||||
}
|
||||
|
||||
bool B15F::testConnection()
|
||||
{
|
||||
// erzeuge zufälliges Byte
|
||||
srand(time(NULL));
|
||||
uint8_t dummy = rand() % 256;
|
||||
|
||||
usart.writeByte(RQ_TEST);
|
||||
usart.writeByte(dummy);
|
||||
|
||||
uint8_t aw = usart.readByte();
|
||||
uint8_t mirror = usart.readByte();
|
||||
|
||||
return aw == MSG_OK && mirror == dummy;
|
||||
}
|
||||
|
||||
bool B15F::testIntConv()
|
||||
{
|
||||
srand(time(NULL));
|
||||
uint16_t dummy = rand() % (0xFFFF / 3);
|
||||
|
||||
usart.writeByte(RQ_INT);
|
||||
usart.writeInt(dummy);
|
||||
|
||||
uint16_t aw = usart.readInt();
|
||||
return aw == dummy * 3;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> B15F::getBoardInfo(void)
|
||||
{
|
||||
std::vector<std::string> info;
|
||||
|
||||
usart.writeByte(RQ_INFO);
|
||||
|
||||
uint8_t n = usart.readByte();
|
||||
while(n--)
|
||||
{
|
||||
uint8_t len = usart.readByte();
|
||||
std::string str;
|
||||
|
||||
while(len--)
|
||||
str += static_cast<char>(usart.readByte());
|
||||
|
||||
info.push_back(str);
|
||||
}
|
||||
|
||||
uint8_t aw = usart.readByte();
|
||||
if(aw != MSG_OK)
|
||||
throw DriverException("Board Info fehlerhalft: code " + std::to_string((int) aw));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
bool B15F::digitalWrite0(uint8_t port)
|
||||
{
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_BA0);
|
||||
usart.writeByte(port);
|
||||
|
||||
uint8_t aw = usart.readByte();
|
||||
return aw == MSG_OK;
|
||||
}
|
||||
|
||||
bool B15F::digitalWrite1(uint8_t port)
|
||||
{
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_BA1);
|
||||
usart.writeByte(port);
|
||||
|
||||
uint8_t aw = usart.readByte();
|
||||
return aw == MSG_OK;
|
||||
}
|
||||
|
||||
uint8_t B15F::digitalRead0()
|
||||
{
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_BE0);
|
||||
return usart.readByte();
|
||||
}
|
||||
|
||||
uint8_t B15F::digitalRead1()
|
||||
{
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_BE1);
|
||||
return usart.readByte();
|
||||
}
|
||||
|
||||
bool B15F::analogWrite0(uint16_t value)
|
||||
{
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_AA0);
|
||||
usart.writeInt(value);
|
||||
|
||||
uint8_t aw = usart.readByte();
|
||||
return aw == MSG_OK;
|
||||
}
|
||||
|
||||
bool B15F::analogWrite1(uint16_t value)
|
||||
{
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_AA1);
|
||||
usart.writeInt(value);
|
||||
|
||||
uint8_t aw = usart.readByte();
|
||||
return aw == MSG_OK;
|
||||
}
|
||||
|
||||
uint16_t B15F::analogRead(uint8_t channel)
|
||||
{
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_ADC);
|
||||
usart.writeByte(channel);
|
||||
return usart.readInt();
|
||||
}
|
||||
|
||||
bool B15F::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)
|
||||
{
|
||||
buffer_a += offset_a;
|
||||
buffer_b += offset_b;
|
||||
|
||||
usart.flushInputBuffer();
|
||||
usart.writeByte(RQ_ADC_DAC_STROKE);
|
||||
usart.writeByte(channel_a);
|
||||
usart.writeByte(channel_b);
|
||||
usart.writeInt(start);
|
||||
usart.writeInt(static_cast<uint16_t>(delta));
|
||||
usart.writeInt(count);
|
||||
uint8_t aw = usart.readByte();
|
||||
|
||||
if(aw != MSG_OK)
|
||||
throw DriverException("Mikrocontroller nicht synchron");
|
||||
|
||||
for(uint16_t i = 0; i < count; i++)
|
||||
{
|
||||
buffer_a[i] = usart.readInt();
|
||||
buffer_b[i] = usart.readInt();
|
||||
}
|
||||
|
||||
aw = usart.readByte();
|
||||
if(aw == MSG_OK)
|
||||
return aw;
|
||||
|
||||
throw DriverException("Sequenz unterbrochen");
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/478960
|
||||
std::string B15F::exec(std::string cmd) {
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
B15F& B15F::getInstance(void)
|
||||
{
|
||||
if(!instance)
|
||||
instance = new B15F();
|
||||
|
||||
return *instance;
|
||||
}
|
199
driver/drv/b15f.h
Normal file
199
driver/drv/b15f.h
Normal file
|
@ -0,0 +1,199 @@
|
|||
#ifndef B15F_H
|
||||
#define B15F_H
|
||||
|
||||
#include <iostream>
|
||||
#include <bits/stdc++.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include "usart.h"
|
||||
#include "driverexception.h"
|
||||
#include "timeoutexception.h"
|
||||
|
||||
class B15F
|
||||
{
|
||||
private:
|
||||
// privater Konstruktor
|
||||
B15F(void);
|
||||
public:
|
||||
|
||||
/*************************************
|
||||
* Grundfunktionen des B15F Treibers *
|
||||
*************************************/
|
||||
|
||||
/**
|
||||
* Initialisiert und testet die Verbindung zum B15
|
||||
* \throws DriverException
|
||||
*/
|
||||
void init(void);
|
||||
|
||||
/**
|
||||
* Versucht die Verbindung zum B15 wiederherzustellen
|
||||
* \throws DriverException
|
||||
*/
|
||||
void reconnect(void);
|
||||
|
||||
/**
|
||||
* Verwirft Daten im USART Puffer auf dieser Maschine und B15
|
||||
* \throws DriverException
|
||||
*/
|
||||
void discard(void);
|
||||
|
||||
/**
|
||||
* Testet die USART Verbindung auf Funktion
|
||||
* \throws DriverException
|
||||
*/
|
||||
bool testConnection(void);
|
||||
|
||||
/**
|
||||
* Testet die Integer Konvertierung der USART Verbindung
|
||||
* \throws DriverException
|
||||
*/
|
||||
bool testIntConv(void);
|
||||
|
||||
/**
|
||||
* Liefert Informationen zur aktuellen Firmware des B15
|
||||
* \throws DriverException
|
||||
*/
|
||||
std::vector<std::string> getBoardInfo(void);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Liefert eine Referenz zur aktuellen Treiber-Instanz
|
||||
* @throws DriverException
|
||||
*/
|
||||
static B15F& getInstance(void);
|
||||
|
||||
/**
|
||||
* Führt ein Befehl auf dieser Maschine aus und liefert stdout zurück
|
||||
* \param cmd Der Befehl
|
||||
*/
|
||||
static std::string exec(std::string cmd);
|
||||
|
||||
/*************************************/
|
||||
|
||||
|
||||
|
||||
/*************************
|
||||
* Steuerbefehle für B15 *
|
||||
*************************/
|
||||
|
||||
/**
|
||||
* Setzt den Wert des digitalen Ausgabeports 0
|
||||
* \param port Wert für gesamten Port
|
||||
* \throws DriverException
|
||||
*/
|
||||
bool digitalWrite0(uint8_t);
|
||||
|
||||
/**
|
||||
* Setzt den Wert des digitalen Ausgabeports 1
|
||||
* \param port Wert für gesamten Port
|
||||
* \throws DriverException
|
||||
*/
|
||||
bool digitalWrite1(uint8_t);
|
||||
|
||||
/**
|
||||
* Liest den Wert des digitalen Eingabeports 0
|
||||
* \return Wert für gesamten Port
|
||||
* \throws DriverException
|
||||
*/
|
||||
uint8_t digitalRead0(void);
|
||||
|
||||
/**
|
||||
* Liest den Wert des digitalen Eingabeports 1
|
||||
* \return Wert für gesamten Port
|
||||
* \throws DriverException
|
||||
*/
|
||||
uint8_t digitalRead1(void);
|
||||
|
||||
/**
|
||||
* Setzt den Wert des Digital-Analog-Converters (DAC / DAU) 0
|
||||
* \param port 10-Bit Wert
|
||||
* \throws DriverException
|
||||
*/
|
||||
bool analogWrite0(uint16_t);
|
||||
|
||||
/**
|
||||
* Setzt den Wert des Digital-Analog-Converters (DAC / DAU) 1
|
||||
* \param port 10-Bit Wert
|
||||
* \throws DriverException
|
||||
*/
|
||||
bool analogWrite1(uint16_t);
|
||||
|
||||
/**
|
||||
* Liest den Wert des Analog-Digital-Converters (ADC / ADU)
|
||||
* \param channel Kanalwahl von 0 - 7
|
||||
* \throws DriverException
|
||||
*/
|
||||
uint16_t analogRead(uint8_t channel);
|
||||
|
||||
/**
|
||||
* \brief Komplexe Analoge Sequenz
|
||||
* DAC 0 wird auf den Startwert gesetzt und dann schrittweise um Delta inkrementiert.
|
||||
* Für jeden eingestelleten DAC-Wert werden zwei ADCs (channel_a und channel_b) angesprochen und die Werte übermittelt.
|
||||
* Die Werte werden in buffer_a für Kanal a und buffer_b für Kanal b gespeichert.
|
||||
* \param channel_a Auswahl des ADC a, von 0 - 7
|
||||
* \param buffer_a Speichertort für Werte des Kanals a
|
||||
* \param offset_a Anzahl an Werten des Kanals a, die im Speicher übersprungen werden sollen
|
||||
* \param channel_b Auswahl des ADC b, von 0 - 7
|
||||
* \param buffer_b Speichertort für Werte des Kanals b
|
||||
* \param offset_b Anzahl an Werten des Kanals b, die im Speicher übersprungen werden
|
||||
* \param start Startwert des DACs
|
||||
* \param delta Schrittweite, mit welcher der DAC inkrementiert wird
|
||||
* \param count Anzahl an Inkrementierungen
|
||||
* \throws DriverException
|
||||
*/
|
||||
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);
|
||||
|
||||
/*************************/
|
||||
|
||||
private:
|
||||
USART usart;
|
||||
|
||||
static B15F* instance;
|
||||
|
||||
|
||||
// CONSTANTS
|
||||
const std::string PRE = "[B15F] ";
|
||||
const std::string SERIAL_DEVICE = "/dev/ttyUSB0";
|
||||
constexpr static uint8_t MSG_OK = 0xFF;
|
||||
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 = 115200;
|
||||
|
||||
// REQUESTS
|
||||
constexpr static uint8_t RQ_DISC = 0;
|
||||
constexpr static uint8_t RQ_TEST = 1;
|
||||
constexpr static uint8_t RQ_INFO = 2;
|
||||
constexpr static uint8_t RQ_INT = 3;
|
||||
constexpr static uint8_t RQ_BA0 = 5;
|
||||
constexpr static uint8_t RQ_BA1 = 6;
|
||||
constexpr static uint8_t RQ_BE0 = 7;
|
||||
constexpr static uint8_t RQ_BE1 = 8;
|
||||
constexpr static uint8_t RQ_AA0 = 9;
|
||||
constexpr static uint8_t RQ_AA1 = 10;
|
||||
constexpr static uint8_t RQ_ADC = 11;
|
||||
constexpr static uint8_t RQ_ADC_DAC_STROKE = 12;
|
||||
};
|
||||
|
||||
#endif // B15F_H
|
BIN
driver/drv/b15f.o
Normal file
BIN
driver/drv/b15f.o
Normal file
Binary file not shown.
22
driver/drv/dot.cpp
Normal file
22
driver/drv/dot.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "dot.h"
|
||||
|
||||
Dot::Dot(uint16_t x, uint16_t y, uint8_t curve) : x(x), y(y), curve(curve)
|
||||
{
|
||||
if(curve >= 64)
|
||||
throw std::range_error("Kurvenindex muss im Bereich [0, 63] liegen");
|
||||
}
|
||||
|
||||
uint16_t Dot::getX() const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16_t Dot::getY() const
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
uint8_t Dot::getCurve(void) const
|
||||
{
|
||||
return curve;
|
||||
}
|
21
driver/drv/dot.h
Normal file
21
driver/drv/dot.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef DOT_H
|
||||
#define DOT_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
class Dot
|
||||
{
|
||||
public:
|
||||
Dot(uint16_t x, uint16_t y, uint8_t curve);
|
||||
uint16_t getX(void) const;
|
||||
uint16_t getY(void) const;
|
||||
uint8_t getCurve(void) const;
|
||||
|
||||
private:
|
||||
uint16_t x, y;
|
||||
uint8_t curve;
|
||||
};
|
||||
|
||||
|
||||
#endif // DOT_H
|
BIN
driver/drv/dot.h.gch
Normal file
BIN
driver/drv/dot.h.gch
Normal file
Binary file not shown.
BIN
driver/drv/dot.o
Normal file
BIN
driver/drv/dot.o
Normal file
Binary file not shown.
32
driver/drv/driverexception.h
Normal file
32
driver/drv/driverexception.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef DRIVEREXCEPTION_H
|
||||
#define DRIVEREXCEPTION_H
|
||||
|
||||
#include <exception>
|
||||
|
||||
// SOURCE: https://stackoverflow.com/a/8152888
|
||||
|
||||
class DriverException: public std::exception
|
||||
{
|
||||
public:
|
||||
explicit DriverException(const char* message) : msg_(message)
|
||||
{
|
||||
}
|
||||
|
||||
explicit DriverException(const std::string& message) : msg_(message)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DriverException() throw ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* what() const throw ()
|
||||
{
|
||||
return msg_.c_str();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string msg_;
|
||||
};
|
||||
|
||||
#endif // DRIVEREXCEPTION_H
|
198
driver/drv/plottyfile.cpp
Normal file
198
driver/drv/plottyfile.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
#include "plottyfile.h"
|
||||
|
||||
void PlottyFile::addDot(Dot& dot)
|
||||
{
|
||||
dots.push_back(dot);
|
||||
}
|
||||
|
||||
void PlottyFile::addDot(Dot dot)
|
||||
{
|
||||
dots.push_back(dot);
|
||||
}
|
||||
|
||||
void PlottyFile::setFunctionType(FunctionType function_type)
|
||||
{
|
||||
this->function_type = function_type;
|
||||
}
|
||||
|
||||
void PlottyFile::setQuadrant(uint8_t quadrant)
|
||||
{
|
||||
if(quadrant < 1 || quadrant > 4)
|
||||
throw std::range_error("Ungueltiger Quadrant");
|
||||
this->quadrant = quadrant;
|
||||
}
|
||||
|
||||
void PlottyFile::setRefX(uint16_t ref_x)
|
||||
{
|
||||
this->ref_x = ref_x;
|
||||
}
|
||||
|
||||
void PlottyFile::setRefY(uint16_t ref_y)
|
||||
{
|
||||
this->ref_y = ref_y;
|
||||
}
|
||||
|
||||
void PlottyFile::setParaFirstCurve(uint16_t para_first)
|
||||
{
|
||||
this->para_first = para_first;
|
||||
}
|
||||
|
||||
void PlottyFile::setParaStepWidth(uint16_t para_stepwidth)
|
||||
{
|
||||
this->para_stepwidth = para_stepwidth;
|
||||
}
|
||||
|
||||
void PlottyFile::setUnitX(std::string unit_x)
|
||||
{
|
||||
this->unit_x = unit_x;
|
||||
}
|
||||
|
||||
void PlottyFile::setDescX(std::string desc_x)
|
||||
{
|
||||
this->desc_x = desc_x;
|
||||
}
|
||||
|
||||
void PlottyFile::setUnitY(std::string unit_y)
|
||||
{
|
||||
this->unit_y = unit_y;
|
||||
}
|
||||
|
||||
void PlottyFile::setDescY(std::string desc_y)
|
||||
{
|
||||
this->desc_y = desc_y;
|
||||
}
|
||||
|
||||
void PlottyFile::setUnitPara(std::string unit_para)
|
||||
{
|
||||
this->unit_para = unit_para;
|
||||
}
|
||||
|
||||
void PlottyFile::setDescPara(std::string desc_para)
|
||||
{
|
||||
this->desc_para = desc_para;
|
||||
}
|
||||
|
||||
FunctionType PlottyFile::getFunctionType() const
|
||||
{
|
||||
return function_type;
|
||||
}
|
||||
|
||||
uint8_t PlottyFile::getQuadrant() const
|
||||
{
|
||||
return quadrant;
|
||||
}
|
||||
|
||||
uint16_t PlottyFile::getRefX() const
|
||||
{
|
||||
return ref_x;
|
||||
}
|
||||
|
||||
uint16_t PlottyFile::getRefY() const
|
||||
{
|
||||
return ref_y;
|
||||
}
|
||||
|
||||
uint16_t PlottyFile::getParaFirstCurve() const
|
||||
{
|
||||
return para_first;
|
||||
}
|
||||
|
||||
uint16_t PlottyFile::getParaStepWidth() const
|
||||
{
|
||||
return para_stepwidth;
|
||||
}
|
||||
|
||||
std::string PlottyFile::getUnitX() const
|
||||
{
|
||||
return unit_x;
|
||||
}
|
||||
|
||||
std::string PlottyFile::getDescX() const
|
||||
{
|
||||
return desc_x;
|
||||
}
|
||||
|
||||
std::string PlottyFile::getUnitY() const
|
||||
{
|
||||
return unit_y;
|
||||
}
|
||||
|
||||
std::string PlottyFile::getDescY() const
|
||||
{
|
||||
return desc_y;
|
||||
}
|
||||
|
||||
std::string PlottyFile::getUnitPara() const
|
||||
{
|
||||
return unit_para;
|
||||
}
|
||||
|
||||
std::string PlottyFile::getDescPara() const
|
||||
{
|
||||
return desc_para;
|
||||
}
|
||||
|
||||
void PlottyFile::prepStr(std::string& str, uint8_t len)
|
||||
{
|
||||
if(str.length() > len)
|
||||
throw std::runtime_error("Zu grosser String.");
|
||||
|
||||
if(str.length() != len)
|
||||
str += '\n';
|
||||
|
||||
while(str.length() < len)
|
||||
str += '\0';
|
||||
}
|
||||
|
||||
void PlottyFile::writeToFile(std::string filename)
|
||||
{
|
||||
prepStr(unit_x, STR_LEN_SHORT);
|
||||
prepStr(desc_x, STR_LEN_LARGE);
|
||||
prepStr(unit_y, STR_LEN_SHORT);
|
||||
prepStr(desc_y, STR_LEN_LARGE);
|
||||
prepStr(unit_para, STR_LEN_SHORT);
|
||||
prepStr(desc_para, STR_LEN_LARGE);
|
||||
|
||||
std::ofstream file(filename);
|
||||
|
||||
// write file header
|
||||
file.write(reinterpret_cast<char*>(&command), 1);
|
||||
file.write(head.c_str(), head.length());
|
||||
file.write(filetype.c_str(), filetype.length());
|
||||
file.write(reinterpret_cast<char*>(&version), 2);
|
||||
file.write(reinterpret_cast<char*>(&subversion), 2);
|
||||
file.put(static_cast<uint8_t>(function_type));
|
||||
file.write(reinterpret_cast<char*>(&quadrant), 1);
|
||||
file.write(reinterpret_cast<char*>(&ref_x), 2);
|
||||
file.write(reinterpret_cast<char*>(&ref_y), 2);
|
||||
file.write(reinterpret_cast<char*>(¶_first), 2);
|
||||
file.write(reinterpret_cast<char*>(¶_stepwidth), 2);
|
||||
file.write(unit_x.c_str(), unit_x.length());
|
||||
file.write(desc_x.c_str(), desc_x.length());
|
||||
file.write(unit_y.c_str(), unit_y.length());
|
||||
file.write(desc_y.c_str(), desc_y.length());
|
||||
file.write(unit_para.c_str(), unit_para.length());
|
||||
file.write(desc_para.c_str(), desc_para.length());
|
||||
file.write(reinterpret_cast<const char*>(&eof), 1);
|
||||
|
||||
// make sure header size is 256 Byte
|
||||
while(file.tellp() < 256)
|
||||
file.put(0);
|
||||
|
||||
for(Dot& dot : dots)
|
||||
{
|
||||
file.put((dot.getX() >> 8) | (static_cast<uint8_t>(dot.getCurve()) << 2));
|
||||
file.put(dot.getX() & 0xFF);
|
||||
file.put(dot.getY() >> 8);
|
||||
file.put(dot.getY() & 0xFF);
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void PlottyFile::startPlotty(std::string filename)
|
||||
{
|
||||
int code = system(("./plotty --in " + filename).c_str());
|
||||
if(code)
|
||||
throw std::runtime_error("Fehler beim Aufruf von plotty");
|
||||
}
|
79
driver/drv/plottyfile.h
Normal file
79
driver/drv/plottyfile.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef PLOTTYFILE_H
|
||||
#define PLOTTYFILE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
#include "dot.h"
|
||||
|
||||
enum FunctionType
|
||||
{
|
||||
CurveFamily = 'S',
|
||||
Curve = 'C',
|
||||
Level = 'P'
|
||||
};
|
||||
|
||||
class PlottyFile
|
||||
{
|
||||
public:
|
||||
void addDot(Dot& dot);
|
||||
void addDot(Dot dot);
|
||||
|
||||
void setFunctionType(FunctionType);
|
||||
void setQuadrant(uint8_t);
|
||||
void setRefX(uint16_t);
|
||||
void setRefY(uint16_t);
|
||||
void setParaFirstCurve(uint16_t);
|
||||
void setParaStepWidth(uint16_t);
|
||||
void setUnitX(std::string);
|
||||
void setDescX(std::string);
|
||||
void setUnitY(std::string);
|
||||
void setDescY(std::string);
|
||||
void setUnitPara(std::string);
|
||||
void setDescPara(std::string);
|
||||
|
||||
FunctionType getFunctionType(void) const;
|
||||
uint8_t getQuadrant(void) const;
|
||||
uint16_t getRefX(void) const;
|
||||
uint16_t getRefY(void) const;
|
||||
uint16_t getParaFirstCurve(void) const;
|
||||
uint16_t getParaStepWidth(void) const;
|
||||
std::string getUnitX(void) const;
|
||||
std::string getDescX(void) const;
|
||||
std::string getUnitY(void) const;
|
||||
std::string getDescY(void) const;
|
||||
std::string getUnitPara(void) const;
|
||||
std::string getDescPara(void) const;
|
||||
|
||||
void writeToFile(std::string filename);
|
||||
void startPlotty(std::string filename);
|
||||
private:
|
||||
void prepStr(std::string& str, uint8_t len);
|
||||
|
||||
std::vector<Dot> dots;
|
||||
|
||||
int8_t command = 0x1D;
|
||||
const std::string head = "HTWK-HWLab";
|
||||
const std::string filetype = "MD";
|
||||
int16_t version = 1;
|
||||
int16_t subversion = 0;
|
||||
FunctionType function_type = FunctionType::Curve;
|
||||
uint8_t quadrant = 1;
|
||||
uint16_t ref_x = 1023;
|
||||
uint16_t ref_y = 1023;
|
||||
uint16_t para_first = 1;
|
||||
uint16_t para_stepwidth = 1;
|
||||
std::string unit_x;
|
||||
std::string desc_x;
|
||||
std::string unit_y;
|
||||
std::string desc_y;
|
||||
std::string unit_para;
|
||||
std::string desc_para;
|
||||
const uint8_t eof = 0xD;
|
||||
|
||||
constexpr static uint8_t STR_LEN_SHORT = 10;
|
||||
constexpr static uint8_t STR_LEN_LARGE = 20;
|
||||
};
|
||||
|
||||
#endif // PLOTTYFILE_H
|
BIN
driver/drv/plottyfile.o
Normal file
BIN
driver/drv/plottyfile.o
Normal file
Binary file not shown.
35
driver/drv/timeoutexception.h
Normal file
35
driver/drv/timeoutexception.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef TIMEOUTEXCEPTION_H
|
||||
#define TIMEOUTEXCEPTION_H
|
||||
|
||||
#include <exception>
|
||||
|
||||
// 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
|
296
driver/drv/usart.cpp
Normal file
296
driver/drv/usart.cpp
Normal file
|
@ -0,0 +1,296 @@
|
|||
#include "usart.h"
|
||||
|
||||
void USART::openDevice(std::string device)
|
||||
{
|
||||
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");
|
||||
|
||||
flushOutputBuffer();
|
||||
flushInputBuffer();
|
||||
}
|
||||
|
||||
void USART::closeDevice()
|
||||
{
|
||||
int code = close(file_desc);
|
||||
if(code)
|
||||
throw USARTException("Fehler beim Schließen des Gerätes");
|
||||
}
|
||||
|
||||
void USART::flushInputBuffer()
|
||||
{
|
||||
int code = tcflush(file_desc, TCIFLUSH);
|
||||
if(code)
|
||||
throw USARTException("Fehler beim Leeren des Eingangspuffers");
|
||||
}
|
||||
|
||||
void USART::flushOutputBuffer()
|
||||
{
|
||||
int code = tcflush(file_desc, TCOFLUSH);
|
||||
if(code)
|
||||
throw USARTException("Fehler beim Leeren des Ausgangspuffers");
|
||||
}
|
||||
|
||||
void USART::writeByte(uint8_t b)
|
||||
{
|
||||
int sent = write(file_desc, &b, 1);
|
||||
if(sent != 1)
|
||||
{
|
||||
std::cout << "WARNUNG: Fehler beim Senden (" << sent << "): writeByte(), wiederhole..." << std::endl;
|
||||
usleep(100000);
|
||||
sent = write(file_desc, &b, 1);
|
||||
if(sent != 1)
|
||||
throw USARTException("Fehler beim Senden: writeByte()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void USART::writeInt(uint16_t d)
|
||||
{
|
||||
int sent = write(file_desc, reinterpret_cast<char*>(&d), 2);
|
||||
if(sent != 2)
|
||||
throw USARTException("Fehler beim Senden: writeInt()");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int USART::read_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout)
|
||||
{
|
||||
uint32_t elapsed = 0;
|
||||
int n_read = -1;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
auto end = start;
|
||||
while(elapsed < timeout)
|
||||
{
|
||||
n_read = read(file_desc, buffer + offset, len);
|
||||
if (n_read == len)
|
||||
return n_read;
|
||||
|
||||
end = std::chrono::steady_clock::now();
|
||||
elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
|
||||
}
|
||||
|
||||
return n_read;
|
||||
}
|
||||
|
||||
int USART::write_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout)
|
||||
{
|
||||
uint32_t elapsed = 0;
|
||||
int n_sent = -1;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
auto end = start;
|
||||
while(elapsed < timeout)
|
||||
{
|
||||
n_sent = write(file_desc, buffer + offset, len);
|
||||
if (n_sent == len)
|
||||
return n_sent;
|
||||
|
||||
end = std::chrono::steady_clock::now();
|
||||
elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
|
||||
}
|
||||
|
||||
return n_sent;
|
||||
}
|
||||
|
||||
void USART::writeBlock(uint8_t* buffer, uint16_t offset, uint8_t len)
|
||||
{
|
||||
uint8_t crc;
|
||||
uint8_t aw;
|
||||
const uint16_t us_per_bit = (1000000 / baudrate) * 16;
|
||||
const uint16_t n_total = len + 3;
|
||||
|
||||
do
|
||||
{
|
||||
// calc crc
|
||||
crc = 0;
|
||||
for(uint8_t i = 0; i < len; i++)
|
||||
{
|
||||
crc ^= buffer[i];
|
||||
for (uint8_t k = 0; k < 8; k++)
|
||||
{
|
||||
if (crc & 1)
|
||||
crc ^= CRC7_POLY;
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// construct block
|
||||
block_buffer[0] = len;
|
||||
std::memcpy(&block_buffer[1], buffer + offset, len);
|
||||
block_buffer[len + 1] = crc;
|
||||
block_buffer[len + 2] = BLOCK_END;
|
||||
|
||||
// send block
|
||||
int n_sent = write_timeout(&block_buffer[0], 0, len + 3, us_per_bit * n_total);
|
||||
if(n_sent != n_total)
|
||||
throw std::runtime_error("fatal (send): " + std::to_string(n_sent));
|
||||
flushOutputBuffer();
|
||||
|
||||
usleep(1000);
|
||||
|
||||
// check response
|
||||
int n_read = read_timeout(&aw, 0, 1, us_per_bit);
|
||||
for(uint8_t i = 0; i < 10 && n_read != 1; i++)
|
||||
{
|
||||
flushOutputBuffer();
|
||||
flushInputBuffer();
|
||||
std::cout << "WARNING: read error (" << n_read << "), retry #" << (int) i << std::endl;
|
||||
usleep(1000000);
|
||||
n_read = read_timeout(&aw, 0, 1, us_per_bit * 2);
|
||||
}
|
||||
|
||||
if(n_read == 0)
|
||||
{
|
||||
std::cout << "timeout info" << std::endl;
|
||||
for(uint8_t i = 0; i < MAX_BLOCK_SIZE; i++)
|
||||
{
|
||||
writeByte(0x80); // Stoppzeichen für Block
|
||||
|
||||
n_read = read_timeout(&aw, 0, 1, us_per_bit * 2);
|
||||
if(n_read == 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(n_read != 1)
|
||||
throw std::runtime_error("fatal: " + std::to_string(n_read));
|
||||
|
||||
flushInputBuffer();
|
||||
}
|
||||
while(aw != 0xFF);
|
||||
|
||||
//std::cout << "OK" << std::endl;
|
||||
}
|
||||
|
||||
uint8_t USART::readByte(void)
|
||||
{
|
||||
char b;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
auto end = start;
|
||||
uint16_t elapsed = 0;
|
||||
while(elapsed < timeout * 100)
|
||||
{
|
||||
int code = read(file_desc, &b, 1);
|
||||
if (code > 0)
|
||||
return static_cast<uint8_t>(b);
|
||||
|
||||
end = std::chrono::steady_clock::now();
|
||||
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
}
|
||||
|
||||
throw TimeoutException("Verbindung unterbrochen.", timeout);
|
||||
}
|
||||
|
||||
uint16_t USART::readInt(void)
|
||||
{
|
||||
return readByte() | readByte() << 8;
|
||||
}
|
||||
|
||||
bool USART::readBlock(uint8_t* buffer, uint16_t offset)
|
||||
{
|
||||
uint8_t len = readByte();
|
||||
uint8_t crc = 0;
|
||||
buffer += offset;
|
||||
|
||||
uint32_t block_timeout = timeout / 10;
|
||||
|
||||
// wait for block
|
||||
int n_ready;
|
||||
uint16_t elapsed = 0;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
auto end = start;
|
||||
while(elapsed < block_timeout)
|
||||
{
|
||||
int code = ioctl(file_desc, FIONREAD, &n_ready);
|
||||
if(code != 0)
|
||||
{
|
||||
std::cout << "n_ready code: " << code << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(n_ready >= len + 1)
|
||||
break;
|
||||
|
||||
end = std::chrono::steady_clock::now();
|
||||
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
}
|
||||
if(elapsed >= timeout)
|
||||
{
|
||||
std::cout << "block timeout: " << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
while(len--)
|
||||
{
|
||||
*buffer = readByte();
|
||||
|
||||
crc ^= *buffer++;
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (crc & 1)
|
||||
crc ^= CRC7_POLY;
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
crc ^= readByte();
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (crc & 1)
|
||||
crc ^= CRC7_POLY;
|
||||
crc >>= 1;
|
||||
}
|
||||
|
||||
if(TEST == 1)
|
||||
crc = 1;
|
||||
if(TEST > 100)
|
||||
TEST = 0;
|
||||
|
||||
if (crc == 0)
|
||||
{
|
||||
writeByte(0xFF);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeByte(0xFE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
134
driver/drv/usart.h
Normal file
134
driver/drv/usart.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
#ifndef USART_H
|
||||
#define USART_H
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include "usartexception.h"
|
||||
#include "timeoutexception.h"
|
||||
|
||||
class USART
|
||||
{
|
||||
public:
|
||||
|
||||
/*************************************************
|
||||
* Methoden für die Verwaltung der Schnittstelle *
|
||||
*************************************************/
|
||||
|
||||
/**
|
||||
* Öffnet die USART Schnittstelle
|
||||
* \param device Linux-Gerätepfad
|
||||
* \throws USARTException
|
||||
*/
|
||||
void openDevice(std::string device);
|
||||
|
||||
/**
|
||||
* 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 flushInputBuffer(void);
|
||||
|
||||
/**
|
||||
* Verwirft Daten, die bereits im Puffer liegen, aber noch nicht gesendet wurden
|
||||
* \throws USARTException
|
||||
*/
|
||||
void flushOutputBuffer(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);
|
||||
|
||||
/**
|
||||
* Sendet ein Integer über die USART Schnittstelle
|
||||
* \param b das zu sendende Byte
|
||||
* \throws USARTException
|
||||
*/
|
||||
void writeInt(uint16_t d);
|
||||
|
||||
/**
|
||||
* Empfängt ein Byte über die USART Schnittstelle
|
||||
* \throws USARTException
|
||||
*/
|
||||
uint8_t readByte(void);
|
||||
|
||||
/**
|
||||
* Empfängt ein Integer über die USART Schnittstelle
|
||||
* \throws USARTException
|
||||
*/
|
||||
uint16_t readInt(void);
|
||||
|
||||
int read_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout);
|
||||
int write_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout);
|
||||
void writeBlock(uint8_t* buffer, uint16_t offset, uint8_t len);
|
||||
bool readBlock(uint8_t* buffer, uint16_t offset);
|
||||
|
||||
/*************************************/
|
||||
|
||||
|
||||
|
||||
/***************************************
|
||||
* Methoden für einstellbare Parameter *
|
||||
***************************************/
|
||||
|
||||
/**
|
||||
* Liefert die eingestellte Baudrate
|
||||
* <b>Änderungen werden erst nach einem open() wirksam</b>
|
||||
*/
|
||||
uint32_t getBaudrate(void);
|
||||
|
||||
/**
|
||||
* Liefert den eingestellten Timeout (in Dezisekunden)
|
||||
* <b>Änderungen werden erst nach einem open() wirksam</b>
|
||||
*/
|
||||
uint8_t getTimeout(void);
|
||||
|
||||
/**
|
||||
* Setzt die Baudrate
|
||||
* <b>Änderungen werden erst nach einem open() wirksam</b>
|
||||
*/
|
||||
void setBaudrate(uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* Setzt den Timeout (in Dezisekunden)
|
||||
* <b>Änderungen werden erst nach einem open() wirksam</b>
|
||||
*/
|
||||
void setTimeout(uint8_t timeout);
|
||||
|
||||
/***************************************/
|
||||
|
||||
constexpr static uint8_t CRC7_POLY = 0x91;
|
||||
constexpr static uint8_t MAX_BLOCK_SIZE = 16;
|
||||
constexpr static uint8_t BLOCK_END = 0x80;
|
||||
private:
|
||||
|
||||
int file_desc = -1; // Linux Dateideskriptor
|
||||
uint32_t baudrate = 9600;
|
||||
int TEST = 0;
|
||||
uint8_t timeout = 10; // in Dezisekunden
|
||||
uint8_t block_buffer[MAX_BLOCK_SIZE + 3];
|
||||
};
|
||||
|
||||
|
||||
#endif // USART_H
|
BIN
driver/drv/usart.o
Normal file
BIN
driver/drv/usart.o
Normal file
Binary file not shown.
33
driver/drv/usartexception.h
Normal file
33
driver/drv/usartexception.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef USARTEXCEPTION_H
|
||||
#define USARTEXCEPTION_H
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
// 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
|
36
driver/gnuplotscript.gp
Normal file
36
driver/gnuplotscript.gp
Normal file
|
@ -0,0 +1,36 @@
|
|||
set margin 10,10
|
||||
unset key
|
||||
set grid
|
||||
set title ''
|
||||
set xlabel 'U_{GS} [V]'
|
||||
set ylabel 'I_D [mA]'
|
||||
set xrange [5:0]
|
||||
set x2range [5:0]
|
||||
set y2range [0:50]
|
||||
set yrange [0:50]
|
||||
set label at 2,36 'U_{DS} [V] = 300' right
|
||||
set label at 2,33 'U_{DS} [V] = 325' right
|
||||
set label at 2,21 'U_{DS} [V] = 350' right
|
||||
set label at 2,38 'U_{DS} [V] = 375' right
|
||||
set label at 2,23 'U_{DS} [V] = 400' right
|
||||
set label at 2,23 'U_{DS} [V] = 425' right
|
||||
set label at 2,24 'U_{DS} [V] = 450' right
|
||||
set label at 2,24 'U_{DS} [V] = 475' right
|
||||
set label at 2,25 'U_{DS} [V] = 500' right
|
||||
set label at 2,5 'U_{DS} [V] = 525' right
|
||||
set label at 2,6 'U_{DS} [V] = 550' right
|
||||
set label at 2,13 'U_{DS} [V] = 575' right
|
||||
set label at 2,13 'U_{DS} [V] = 600' right
|
||||
set label at 2,13 'U_{DS} [V] = 625' right
|
||||
set label at 2,2 'U_{DS} [V] = 650' right
|
||||
set label at 2,2 'U_{DS} [V] = 675' right
|
||||
set label at 2,6 'U_{DS} [V] = 700' right
|
||||
set label at 2,2 'U_{DS} [V] = 725' right
|
||||
set label at 2,2 'U_{DS} [V] = 725' right
|
||||
set y2tics
|
||||
unset ytics
|
||||
set ytics format ''
|
||||
unset output
|
||||
set terminal qt
|
||||
unset output
|
||||
plot "/tmp/tempfile1" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 300' w l,"/tmp/tempfile2" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 325' w l,"/tmp/tempfile3" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 350' w l,"/tmp/tempfile4" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 375' w l,"/tmp/tempfile5" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 400' w l,"/tmp/tempfile6" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 425' w l,"/tmp/tempfile7" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 450' w l,"/tmp/tempfile8" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 475' w l,"/tmp/tempfile9" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 500' w l,"/tmp/tempfile10" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 525' w l,"/tmp/tempfile11" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 550' w l,"/tmp/tempfile12" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 575' w l,"/tmp/tempfile13" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 600' w l,"/tmp/tempfile14" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 625' w l,"/tmp/tempfile15" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 650' w l,"/tmp/tempfile16" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 675' w l,"/tmp/tempfile17" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 700' w l,"/tmp/tempfile18" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 725' w l,"/tmp/tempfile19" using ($1*0.004888):($2*0.048876) binary format="%int16%int16" endian=big title 'U_{DS} [V] = 750' w l
|
BIN
driver/graph
Executable file
BIN
driver/graph
Executable file
Binary file not shown.
BIN
driver/main
Executable file
BIN
driver/main
Executable file
Binary file not shown.
145
driver/main.cpp
Normal file
145
driver/main.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include "drv/usart.h"
|
||||
#include "drv/b15f.h"
|
||||
#include "drv/plottyfile.h"
|
||||
|
||||
|
||||
void kennlinieErsterQuadrant()
|
||||
{
|
||||
B15F& drv = B15F::getInstance();
|
||||
PlottyFile pf;
|
||||
|
||||
uint16_t ba[1024];
|
||||
uint16_t bb[1024];
|
||||
|
||||
const uint16_t sample_count = 100;
|
||||
const uint16_t delta = 10;
|
||||
|
||||
const uint16_t u_gs_start = 440;
|
||||
const uint16_t u_gs_delta = 20;
|
||||
const uint16_t u_gs_end = 600;
|
||||
|
||||
pf.setUnitX("V");
|
||||
pf.setUnitY("mA");
|
||||
pf.setUnitPara("V");
|
||||
pf.setDescX("U_{DS}");
|
||||
pf.setDescY("I_D");
|
||||
pf.setDescPara("U_{GS}");
|
||||
pf.setRefX(5);
|
||||
pf.setRefY(50);
|
||||
pf.setParaFirstCurve(u_gs_start);
|
||||
pf.setParaStepWidth(u_gs_delta);
|
||||
|
||||
uint8_t curve = 0;
|
||||
for(uint16_t u_gs = u_gs_start; u_gs <= u_gs_end; u_gs += u_gs_delta)
|
||||
{
|
||||
drv.analogWrite1(u_gs);
|
||||
|
||||
drv.analogSequence(0, &ba[0], 0, 1, &bb[0], 0, 0, delta, sample_count);
|
||||
drv.delay_ms(10);
|
||||
drv.discard();
|
||||
drv.delay_ms(10);
|
||||
|
||||
for(uint16_t k = 0; k < sample_count+1; k++)
|
||||
{
|
||||
uint16_t i_d = ba[k] - bb[k];
|
||||
uint16_t u_ds = bb[k];
|
||||
pf.addDot(Dot(u_ds, i_d, curve));
|
||||
}
|
||||
|
||||
curve++;
|
||||
}
|
||||
|
||||
// speichern und plotty starten
|
||||
pf.writeToFile("test_plot");
|
||||
pf.startPlotty("test_plot");
|
||||
}
|
||||
|
||||
void kennlinieZweiterQuadrant()
|
||||
{
|
||||
B15F& drv = B15F::getInstance();
|
||||
PlottyFile pf;
|
||||
|
||||
uint16_t ba[1024];
|
||||
uint16_t bb[1024];
|
||||
|
||||
const uint16_t sample_count = 1000;
|
||||
const uint16_t delta = 1;
|
||||
|
||||
const uint16_t u_gs_start = 300;
|
||||
const uint16_t u_gs_delta = 25;
|
||||
const uint16_t u_gs_end = 700;
|
||||
|
||||
pf.setQuadrant(2);
|
||||
pf.setUnitX("V");
|
||||
pf.setUnitY("mA");
|
||||
pf.setUnitPara("V");
|
||||
pf.setDescX("U_{GS}");
|
||||
pf.setDescY("I_D");
|
||||
pf.setDescPara("U_{DS}");
|
||||
pf.setRefX(5);
|
||||
pf.setRefY(50);
|
||||
pf.setParaFirstCurve(u_gs_start);
|
||||
pf.setParaStepWidth(u_gs_delta);
|
||||
|
||||
uint8_t curve = 0;
|
||||
for(uint16_t u_gs = u_gs_start; u_gs <= u_gs_end; u_gs += u_gs_delta)
|
||||
{
|
||||
drv.analogWrite1(u_gs);
|
||||
|
||||
drv.analogSequence(0, &ba[0], 0, 1, &bb[0], 0, 0, delta, sample_count);
|
||||
|
||||
curve = 0;
|
||||
for(uint16_t k = 0; k < sample_count + 1; k++)
|
||||
{
|
||||
if(ba[k] > bb[k] && bb[k] % 50 == 0 && bb[k] > 0)
|
||||
{
|
||||
uint16_t i_d = ba[k] - bb[k];
|
||||
pf.addDot(Dot(u_gs, i_d, bb[k] / 50));
|
||||
}
|
||||
curve++;
|
||||
}
|
||||
std::cout << "u_gs: " << u_gs << std::endl;
|
||||
}
|
||||
|
||||
// speichern und plotty starten
|
||||
pf.writeToFile("test_plot");
|
||||
pf.startPlotty("test_plot");
|
||||
}
|
||||
|
||||
void testFunktionen()
|
||||
{
|
||||
B15F& drv = B15F::getInstance();
|
||||
|
||||
|
||||
drv.digitalWrite0(0xFF);
|
||||
drv.analogWrite0(128);
|
||||
std::cout << (int) drv.digitalRead0() << std::endl;;
|
||||
std::cout << "adc: " << (int) drv.analogRead(4) << std::endl;
|
||||
|
||||
drv.digitalWrite0(0x00);
|
||||
drv.analogWrite0(0);
|
||||
std::cout << (int) drv.digitalRead0() << std::endl;;
|
||||
std::cout << "adc: " << (int) drv.analogRead(4) << std::endl;
|
||||
|
||||
drv.digitalWrite0(0xFF);
|
||||
drv.analogWrite0(255);
|
||||
std::cout << (int) drv.digitalRead0() << std::endl;
|
||||
std::cout << "adc: " << (int) drv.analogRead(4) << std::endl;
|
||||
|
||||
|
||||
uint16_t a[1024];
|
||||
uint16_t b[1024];
|
||||
drv.analogSequence(0, &a[0], 0, 1, &b[0], 0, 0, 1, 1024);
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
kennlinieZweiterQuadrant();
|
||||
|
||||
std::cout << "Schluss." << std::endl;
|
||||
}
|
BIN
driver/main.o
Normal file
BIN
driver/main.o
Normal file
Binary file not shown.
BIN
driver/plotty
Executable file
BIN
driver/plotty
Executable file
Binary file not shown.
BIN
driver/test_plot
Normal file
BIN
driver/test_plot
Normal file
Binary file not shown.
Loading…
Reference in a new issue