From 48f4405e1aa77f36512cb82296b1be651c413d9e Mon Sep 17 00:00:00 2001 From: Charles Jones Date: Thu, 13 Jun 2013 21:52:23 -0700 Subject: [PATCH 1/2] I2C class changes Bug? Changed the type of the value parameter of the send method from 'int' to 'unsigned char'. Given only 8 bit's is ever transmitted over the wire 'int' could cause confusion. Added conditional value checks to several functions to validate params. Efficieny enhancement By moving the fileopen processes to the setAddress and setDevice methods we can negate the need to repetively open and close the file during read and write operations. setAddress and setDeviceFile now return 1 or -1 --- drivers/i2c.cpp | 352 +++++++++++++++++++++++++++++------------------- drivers/i2c.h | 14 +- 2 files changed, 226 insertions(+), 140 deletions(-) diff --git a/drivers/i2c.cpp b/drivers/i2c.cpp index 867e105..fb43181 100644 --- a/drivers/i2c.cpp +++ b/drivers/i2c.cpp @@ -4,18 +4,157 @@ //Class for accessing GNUBLIN i2c Bus //******************************************************************* -//------------------Konstruktor------------------ +//------------------local defines----------------- /** @~english -* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* @brief creates macro reference for default device "/dev/i2c-1" * * @~german +* @brief schafft Makro Referenz für Standard-Gerät "/ dev/i2c-1" +* +*/ +#define DEFAULTDEVICE "/dev/i2c-1" + +//------------------Konstruktor------------------ +/** @~english +* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* +* @~german +* @brief Setzt das error_flag auf "false" und das devicefile auf standardmäßig "/dev/i2c-1" +* +*/ +gnublin_i2c::gnublin_i2c() +{ + init(DEFAULTDEVICE, -1); +} + +//------------------Konstruktor------------------ +/** @~english +* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* +* @~german +* @brief Setzt das error_flag auf "false" und das devicefile auf standardmäßig "/dev/i2c-1" +* +*/ +gnublin_i2c::gnublin_i2c(int Address) +{ + init(DEFAULTDEVICE, Address); +} + +//------------------Konstruktor------------------ +/** @~english +* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* +* @~german * @brief Setzt das error_flag auf "false" und das devicefile auf standardmäßig "/dev/i2c-1" * */ -gnublin_i2c::gnublin_i2c() +gnublin_i2c::gnublin_i2c(std::string Devicefile, int Address) +{ + init(Devicefile, Address); +} + +//------------------destructor------------------ +/** @~english +* @brief Closes the file handle +* +* @~german +* @brief Schließt die Datei Griff +* +*/ +gnublin_i2c::~gnublin_i2c() { - devicefile="/dev/i2c-1"; + close_fd(); +} + +//------------------init------------------ +/** @~english +* @brief Called by the constructors to initialize class variables. +* +* @~german +* @brief Wird von den Konstruktoren der Klasse Variablen zu initialisieren. +* +*/ +void gnublin_i2c::init(std::string Devicefile, int Address) +{ + devicefile=Devicefile; + slave_address = Address; error_flag=false; + fd = 0; +} + +//------------------error messaging------------------ +/** @~english +* @brief Called by the constructors to initialize class variables. +* +* @param message String contents that describe the error. +* @return failure: -1 +* +* @~german +* @brief Wird von den Konstruktoren der Klasse Variablen zu initialisieren. +* +* @param message String Inhalte, die den Fehler beschreiben. +* @return failure: -1 +* +*/ +int gnublin_i2c::errorMsg(std::string message) +{ + ErrorMessage=message; + error_flag=true; + close_fd(); + return -1; +} + +//------------------close file descriptor------------------ +/** @~english +* @brief Closes the file if open and resets the variable. +* +* @~german +* @brief Schließt die Datei, wenn offen und setzt die Variable. +* +*/ +void gnublin_i2c::close_fd() +{ + if (fd) { + close(fd); + fd = 0; + } +} + +//------------------open file descriptor------------------ +/** @~english +* @brief if a file is already open it is closed first. A new file is opened +* and io operations defined based on the class values for devicefile +* and slave_address. +* +* @return failure: -1 +* +* @~german +* @brief wenn eine Datei bereits geöffnet ist, wird es zunächst geschlossen. +* Eine neue Datei wird geöffnet und IO-Operationen werden auf Basis der Klasse +* Werte für Device-Datei und Slave_Address definiert. +* +* @return failure: -1 +* +*/ +int gnublin_i2c::open_fd() +{ + error_flag = false; + + if (fd) { + close_fd(); + fd = 0; + } + + if (slave_address == -1) + return errorMsg("ERROR slave address is not set\n"); + + if ((fd = open(devicefile.c_str(), O_RDWR)) < 0) + return errorMsg("ERROR opening: " + devicefile + "\n"); + + if (ioctl(fd, I2C_SLAVE, slave_address) < 0) + return errorMsg("ERROR address: " + numberToString(slave_address) + "\n"); + + return 0; } //-------------------------------Fail------------------------------- @@ -39,15 +178,18 @@ bool gnublin_i2c::fail(){ * * With this function you can set the individual I2C Slave-Address. * @param Address new I2C slave Address +* @return failure: -1 * * @~german * @brief Setzt die i2c slave Adresse * * Mit dieser Funktion kann die individuelle I2C Slave-Adresse gesetzt werden. * @param Address neue I2C slave Adresse +* @return failure: -1 */ -void gnublin_i2c::setAddress(int Address){ +int gnublin_i2c::setAddress(int Address){ slave_address = Address; + return open_fd(); } //-------------get Address------------- @@ -90,15 +232,18 @@ const char *gnublin_i2c::getErrorMessage(){ * * This function sets the devicefile you want to access. by default "/dev/i2c-1" is set. * @param filename path to the devicefile e.g. "/dev/i2c-0" +* @return failure: -1 * * @~german * @brief setzt die I2C Device Datei. Standard ist die "/dev/i2c-1" * * Diese Funktion setzt die Geräte Datei, auf die man zugreifen möchte. Standardmäßig ist bereits "/dev/i2c-1" gesetzt. * @param filename Dateipfad zur Geräte Datei, z.B. "/dev/i2c-0" +* @return failure: -1 */ -void gnublin_i2c::setDevicefile(std::string filename){ +int gnublin_i2c::setDevicefile(std::string filename){ devicefile = filename; + return open_fd(); } @@ -126,32 +271,21 @@ void gnublin_i2c::setDevicefile(std::string filename){ * @return Erfolg: 1, Misserfolg: -1 */ int gnublin_i2c::receive(unsigned char *RxBuf, int length){ - error_flag=false; - int fd; + if (RxBuf == 0) + return errorMsg("Receive method received a null TxBuf pointer.\n"); + if (length < 1) + return errorMsg("Receive method received an invalid buffer length.\n"); - if ((fd = open(devicefile.c_str(), O_RDWR)) < 0) { - ErrorMessage="ERROR opening: " + devicefile + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if (ioctl(fd, I2C_SLAVE, slave_address) < 0) { - ErrorMessage="ERROR address: " + numberToString(slave_address) + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if (read(fd, RxBuf, length) != length){ - ErrorMessage="i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"; - error_flag=true; - close(fd); - return -1; - } + if (!fd) + if (open_fd() == -1) + return -1; + + error_flag=false; + + if (read(fd, RxBuf, length) != length) + return errorMsg("i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"); - close(fd); return 1; } @@ -187,39 +321,24 @@ int gnublin_i2c::receive(unsigned char *RxBuf, int length){ * @return Erfolg: 1, Misserfolg: -1 */ int gnublin_i2c::receive(unsigned char RegisterAddress, unsigned char *RxBuf, int length){ - error_flag=false; - int fd; - - if ((fd = open(devicefile.c_str(), O_RDWR)) < 0) { - ErrorMessage="ERROR opening: " + devicefile + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if (ioctl(fd, I2C_SLAVE, slave_address) < 0) { - ErrorMessage="ERROR address: " + numberToString(slave_address) + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if (write(fd, &RegisterAddress, 1) != 1){ - ErrorMessage="i2c write error!\n"; - error_flag=true; - close(fd); - return -1; - } + if (RxBuf == 0) + return errorMsg("Receive method received a null TxBuf pointer.\n"); + if (length < 1) + return errorMsg("Receive method received an invalid buffer length.\n"); - if (read(fd, RxBuf, length) != length){ - ErrorMessage="i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"; - error_flag=true; - close(fd); - return -1; - } + if (!fd) + if (open_fd() == -1) + return -1; + + error_flag=false; + + if (write(fd, &RegisterAddress, 1) != 1) + return errorMsg("i2c write error!\n"); + + if (read(fd, RxBuf, length) != length) + return errorMsg("i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"); - close(fd); return 1; } @@ -247,31 +366,21 @@ int gnublin_i2c::receive(unsigned char RegisterAddress, unsigned char *RxBuf, in * @return Erfolg: 1, Misserfolg: -1 */ int gnublin_i2c::send(unsigned char *TxBuf, int length){ + + if (TxBuf == 0) + return errorMsg("Send method received a null TxBuf pointer.\n"); + if (length < 1) + return errorMsg("Send method received an invalid buffer length.\n"); + + if (!fd) + if (open_fd() == -1) + return -1; + error_flag=false; - int fd; - - if ((fd = open(devicefile.c_str(), O_RDWR)) < 0) { - ErrorMessage="ERROR opening: " + devicefile + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if (ioctl(fd, I2C_SLAVE, slave_address) < 0) { - ErrorMessage="ERROR address: " + numberToString(slave_address) + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if(write(fd, TxBuf, length) != length){ - ErrorMessage="i2c write error!\n"; - error_flag=true; - close(fd); - return -1; - } - close(fd); + if(write(fd, TxBuf, length) != length) + return errorMsg("i2c write error!\n"); + return 1; } @@ -307,38 +416,24 @@ int gnublin_i2c::send(unsigned char *TxBuf, int length){ * @return Erfolg: 1, Misserfolg: -1 */ int gnublin_i2c::send(unsigned char RegisterAddress, unsigned char *TxBuf, int length){ + + if (TxBuf == 0) + return errorMsg("Send method received a null TxBuf pointer.\n"); + if (length < 1) + return errorMsg("Send method received an invalid buffer length.\n"); + + if (!fd) + if (open_fd() == -1) + return -1; + error_flag=false; - int fd, i; - unsigned char data[length+1]; - data[0]=RegisterAddress; - - for ( i = 0; i < length ; i++ ) { - data[ i + 1 ] = (char)TxBuf[ i ]; - } - - if ((fd = open(devicefile.c_str(), O_RDWR)) < 0) { - ErrorMessage="ERROR opening: " + devicefile + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if (ioctl(fd, I2C_SLAVE, slave_address) < 0) { - ErrorMessage="ERROR address: " + numberToString(slave_address) + "\n"; - error_flag=true; - close(fd); - return -1; - } - - - if(write(fd, data, length+1) != length+1){ - ErrorMessage="i2c write error!\n"; - error_flag=true; - close(fd); + + if (send(RegisterAddress) == -1) return -1; - } - close(fd); + if(write(fd, TxBuf, length) != length) + return errorMsg("i2c write error!\n"); + return 1; } @@ -363,33 +458,16 @@ int gnublin_i2c::send(unsigned char RegisterAddress, unsigned char *TxBuf, int l * @param value Byte das gesendet wird. * @return Erfolg: 1, Misserfolg: -1 */ -int gnublin_i2c::send(int value){ +int gnublin_i2c::send(unsigned char value){ + + if (!fd) + if (open_fd() == -1) + return -1; + error_flag=false; - int buffer[1]; - buffer[0]=value; - int fd; - - if ((fd = open(devicefile.c_str(), O_RDWR)) < 0) { - ErrorMessage="ERROR opening: " + devicefile + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if (ioctl(fd, I2C_SLAVE, slave_address) < 0) { - ErrorMessage="ERROR address: " + numberToString(slave_address) + "\n"; - error_flag=true; - close(fd); - return -1; - } - - if(write(fd, buffer, 1) != 1){ - ErrorMessage="i2c write error!\n"; - error_flag=true; - close(fd); - return -1; - } - close(fd); + if(write(fd, &value, 1) != 1) + return errorMsg("i2c write error!\n"); + return 1; } diff --git a/drivers/i2c.h b/drivers/i2c.h index 107a73b..0920c17 100644 --- a/drivers/i2c.h +++ b/drivers/i2c.h @@ -19,16 +19,24 @@ class gnublin_i2c { int slave_address; std::string devicefile; std::string ErrorMessage; + int fd; + int errorMsg(std::string message); + int open_fd(); + void close_fd(); + void init(std::string DeviceFile, int Address); public: gnublin_i2c(); + gnublin_i2c(int Address); + gnublin_i2c(std::string DeviceFile, int Address); + ~gnublin_i2c(); bool fail(); - void setAddress(int Address); + int setAddress(int Address); int getAddress(); const char *getErrorMessage(); - void setDevicefile(std::string filename); + int setDevicefile(std::string filename); int receive(unsigned char *RxBuf, int length); int receive(unsigned char RegisterAddress, unsigned char *RxBuf, int length); int send(unsigned char *TxBuf, int length); int send(unsigned char RegisterAddress, unsigned char *TxBuf, int length); - int send(int value); + int send(unsigned char value); }; From 8eccee11ca2634424fc944fb93a6996506972103 Mon Sep 17 00:00:00 2001 From: Charles Jones Date: Sun, 16 Jun 2013 21:51:50 -0700 Subject: [PATCH 2/2] Created abstract driver. Error handling moved to gnublin_driver --- build-API.sh | 2 + drivers/adc.cpp | 48 ++-------------- drivers/adc.h | 7 +-- drivers/driver.cpp | 87 ++++++++++++++++++++++++++++ drivers/driver.h | 28 +++++++++ drivers/gpio.cpp | 93 ++++++++---------------------- drivers/gpio.h | 9 +-- drivers/i2c.cpp | 116 +++++++++++++------------------------ drivers/i2c.h | 9 +-- drivers/spi.cpp | 138 +++++++++++++-------------------------------- drivers/spi.h | 10 +--- 11 files changed, 233 insertions(+), 314 deletions(-) create mode 100644 drivers/driver.cpp create mode 100644 drivers/driver.h diff --git a/build-API.sh b/build-API.sh index 3efa949..07c175b 100644 --- a/build-API.sh +++ b/build-API.sh @@ -22,6 +22,7 @@ rm include_tmp.h cat include/functions.h >> gnublin.h +cat drivers/driver.h >> gnublin.h cat drivers/gpio.h >> gnublin.h cat drivers/i2c.h >> gnublin.h cat drivers/spi.h >> gnublin.h @@ -52,6 +53,7 @@ echo "//******************************************** cat include/functions.cpp >> gnublin.cpp +cat drivers/driver.cpp >> gnublin.cpp cat drivers/gpio.cpp >> gnublin.cpp cat drivers/i2c.cpp >> gnublin.cpp cat drivers/spi.cpp >> gnublin.cpp diff --git a/drivers/adc.cpp b/drivers/adc.cpp index 0e43ec2..a0252c6 100644 --- a/drivers/adc.cpp +++ b/drivers/adc.cpp @@ -18,45 +18,9 @@ gnublin_adc::gnublin_adc(){ sleep(1); } file.close(); - error_flag = false; + clearError(); } -//-------------fail------------- -/** @~english -* @brief Returns the error flag. -* -* If something went wrong, the flag is true. -* @return bool error_flag -* -* @~german -* @brief Gibt das Error Flag zurück. -* -* Falls das Error Flag in der Klasse gesetzt wurde, wird true zurück gegeben, anderenfalls false. -* @return bool error_flag -*/ -bool gnublin_adc::fail(){ - return error_flag; -} - - -//-------------getErrorMessage------------- -/** @~english -* @brief Get the last Error Message. -* -* This Funktion returns the last Error Message, which occurred in that Class. -* @return ErrorMessage as c-string -* -* @~german -* @brief Gibt die letzte Error Nachricht zurück. -* -* Diese Funktion gibt die Letzte Error Nachricht zurück, welche in dieser Klasse gespeichert wurde. -* @return ErrorMessage als c-string -*/ -const char *gnublin_adc::getErrorMessage(){ - return ErrorMessage.c_str(); -} - - //-------------getValue------------- /** @~english * @brief Get Value. @@ -78,16 +42,14 @@ int gnublin_adc::getValue(int pin){ std::string pin_str = numberToString(pin); std::string device = "/dev/lpc313x_adc"; std::ofstream file(device.c_str()); - if (file < 0) { - error_flag = true; - return -1; - } + if (file < 0) + return setErrorMessage("Unable to open "+device); file << pin_str; file.close(); std::ifstream dev_file(device.c_str()); dev_file >> value; dev_file.close(); - error_flag = false; + clearError(); return hexstringToNumber(value); } @@ -126,7 +88,7 @@ int gnublin_adc::getVoltage(int pin){ * @return Erfolg: 1, Fehler: -1 */ int gnublin_adc::setReference(int ref){ - error_flag = false; + clearError(); return 1; } diff --git a/drivers/adc.h b/drivers/adc.h index f744c37..1cc8663 100644 --- a/drivers/adc.h +++ b/drivers/adc.h @@ -15,17 +15,14 @@ * * Mit der gnublin_adc API lassen sich die GPAs auf dem GNUBLIN einfach aus dem eigenem Programm heraus auslesen. */ -class gnublin_adc { +class gnublin_adc : public gnublin_driver { public: gnublin_adc(); int getValue(int pin); int getVoltage(int pin); int setReference(int ref); - bool fail(); - const char *getErrorMessage(); private: - bool error_flag; - std::string ErrorMessage; + void onError() {}; }; #endif diff --git a/drivers/driver.cpp b/drivers/driver.cpp new file mode 100644 index 0000000..93e5988 --- /dev/null +++ b/drivers/driver.cpp @@ -0,0 +1,87 @@ +#include "driver.h" + +//******************************************************************* +//Class for accessing GNUBLIN i2c Bus +//******************************************************************* + +//------------------Konstruktor------------------ +/** @~english +* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* +* @~german +* @brief Setzt das error_flag auf "false" und das devicefile auf standardmäßig "/dev/i2c-1" +* +*/ +gnublin_driver::gnublin_driver() +{ + error_flag=false; + ErrorMessage=""; +} + +//------------------error messaging------------------ +/** @~english +* @brief Called by the constructors to initialize class variables. +* +* @param message String contents that describe the error. +* @return failure: -1 +* +* @~german +* @brief Wird von den Konstruktoren der Klasse Variablen zu initialisieren. +* +* @param message String Inhalte, die den Fehler beschreiben. +* @return failure: -1 +* +*/ +int gnublin_driver::setErrorMessage(std::string message) +{ + ErrorMessage=message; + error_flag=true; + return -1; +} + +//------------------error messaging------------------ +/** @~english +* @brief Resets the error_flag and other associated details. +* +* @~german +* @brief Setzt die error_flag und anderen damit verbundenen Informationen. +* +*/ +void gnublin_driver::clearError() +{ + ErrorMessage=""; + error_flag=false; +} + +//-------------------------------Fail------------------------------- +/** @~english +* @brief returns the error flag to check if the last operation went wrong +* +* @return error_flag as boolean +* +* @~german +* @brief Gibt das error_flag zurück um zu überprüfen ob die vorangegangene Operation einen Fehler auweist +* +* @return error_flag als bool +*/ +bool gnublin_driver::fail(){ + return error_flag; +} + +//-------------get Error Message------------- +/** @~english +* @brief Get the last Error Message. +* +* This function returns the last Error Message, which occurred in that Class. +* @return ErrorMessage as c-string +* +* @~german +* @brief Gibt die letzte Error Nachricht zurück. +* +* Diese Funktion gibt die Letzte Error Nachricht zurück, welche in dieser Klasse gespeichert wurde. +* @return ErrorMessage als c-string +*/ +const char *gnublin_driver::getErrorMessage(){ + return ErrorMessage.c_str(); +} + diff --git a/drivers/driver.h b/drivers/driver.h new file mode 100644 index 0000000..2d682a1 --- /dev/null +++ b/drivers/driver.h @@ -0,0 +1,28 @@ +#include "../include/includes.h" +//******************************************************************* +//Class for accessing GNUBLIN i2c Bus +//******************************************************************* +/** +* @class gnublin_i2c +* @~english +* @brief Class for accessing GNUBLIN i2c bus +* +* The GNUBLIN I2C bus can easily accessed with this class +* @~german +* @brief Klasse für den zugriff auf den GNUBLIN I2C Bus +* +* Die GNUBLIN I2C Klasse gewährt einfachen Zugriff auf den I2C Bus +*/ + +class gnublin_driver { + bool error_flag; + std::string ErrorMessage; + virtual void onError() = 0; +protected: + gnublin_driver(); +public: + bool fail(); + int setErrorMessage(std::string message); + const char *getErrorMessage(); + void clearError(); +}; diff --git a/drivers/gpio.cpp b/drivers/gpio.cpp index b639134..36619c8 100644 --- a/drivers/gpio.cpp +++ b/drivers/gpio.cpp @@ -1,4 +1,5 @@ #include "gpio.h" +#include "driver.h" /** @~english * @brief Reset the ErrorFlag. @@ -7,8 +8,7 @@ * @brief Setzt das ErrorFlag zurück. * */ -gnublin_gpio::gnublin_gpio(){ - error_flag = false; +gnublin_gpio::gnublin_gpio() : gnublin_driver() { } @@ -29,49 +29,15 @@ int gnublin_gpio::unexport(int pin){ std::string pin_str = numberToString(pin); std::string dir = "/sys/class/gpio/unexport"; std::ofstream file (dir.c_str()); - if (file < 0) { - error_flag = true; - return -1; - } + if (file < 0) + return setErrorMessage("Unable to open " + dir +"\n"); file << pin_str; file.close(); - error_flag = false; + clearError(); return 1; } -/** @~english -* @brief Returns the error flag. -* -* If something went wrong, the flag is true. -* @return bool error_flag -* -* @~german -* @brief Gibt das Error Flag zurück. -* -* Falls das Error Flag in der Klasse gesetzt wurde, wird true zurück gegeben, anderenfalls false. -* @return bool error_flag -*/ -bool gnublin_gpio::fail(){ - return error_flag; -} - -/** @~english -* @brief Get the last Error Message. -* -* This Funktion returns the last Error Message, which occurred in that Class. -* @return ErrorMessage as c-string -* -* @~german -* @brief Gibt die letzte Error Nachricht zurück. -* -* Diese Funktion gibt die Letzte Error Nachricht zurück, welche in dieser Klasse gespeichert wurde. -* @return ErrorMessage als c-string -*/ -const char *gnublin_gpio::getErrorMessage(){ - return ErrorMessage.c_str(); -} - /** @~english * @brief Change the PinMode. * @@ -94,31 +60,26 @@ const char *gnublin_gpio::getErrorMessage(){ */ int gnublin_gpio::pinMode(int pin, std::string direction){ #if (BOARD != RASPBERRY_PI) - if (pin == 4 && direction == "out"){ - error_flag = true; - return -1; - } + if (pin == 4 && direction == "out") + return setErrorMessage("Pin 4 can not be set to 'out'\n"); #endif std::string pin_str = numberToString(pin); std::string dir = "/sys/class/gpio/export"; std::ofstream file (dir.c_str()); - if (file < 0) { - error_flag = true; - return -1; - } + if (file < 0) + return setErrorMessage("Unable to open " + dir + "\n"); file << pin; file.close(); dir = "/sys/class/gpio/gpio" + pin_str + "/direction"; file.open(dir.c_str()); - if (file < 0) { - error_flag = true; - return -1; - } + if (file < 0) + return setErrorMessage("Unable to open " + dir + "\n"); file << direction; file.close(); - error_flag = false; + + clearError(); return 1; } @@ -141,27 +102,21 @@ int gnublin_gpio::pinMode(int pin, std::string direction){ */ int gnublin_gpio::digitalWrite(int pin, int value){ #if (BOARD != RASPBERRY_PI) - if (pin == 4){ - error_flag = true; - return -1; - } + if (pin == 4) + return setErrorMessage("Pin 4 is not available for usage\n"); #endif - if (value != 0 && value != 1){ - error_flag = true; - return -1; - } + if (value != 0 && value != 1) + return setErrorMessage("Value ["+numberToString(value)+"] must be 0 or 1\n"); std::string value_str = numberToString(value); std::string pin_str = numberToString(pin); std::string dir = "/sys/class/gpio/gpio" + pin_str + "/value"; std::ofstream file (dir.c_str()); - if (file < 0) { - error_flag = true; - return -1; - } + if (file < 0) + return setErrorMessage("Unable to open " + dir + "\n"); file << value_str; file.close(); - error_flag = false; + clearError(); return 1; } @@ -185,13 +140,11 @@ int gnublin_gpio::digitalRead(int pin) { std::string pin_str = numberToString(pin); std::string device = "/sys/class/gpio/gpio" + pin_str + "/value"; std::ifstream file(device.c_str()); - if (file < 0){ - error_flag = true; - return -1; - } + if (file < 0) + return setErrorMessage("Unable to open " + device + "\n"); file >> value; file.close(); - error_flag = false; + clearError(); return stringToNumber(value); } diff --git a/drivers/gpio.h b/drivers/gpio.h index 4fbbbe0..0fb7a9e 100644 --- a/drivers/gpio.h +++ b/drivers/gpio.h @@ -1,5 +1,4 @@ #include "../include/includes.h" - /** * @class gnublin_gpio * @~english @@ -11,16 +10,12 @@ * * Mit der gnublin_gpio API lassen sich die GPIO-Ports auf dem GNUBLIN einfach aus dem eigenem Programm heraus ansteuern. */ -class gnublin_gpio { +class gnublin_gpio : public gnublin_driver { public: gnublin_gpio(); - bool fail(); int pinMode(int pin, std::string direction); //Defines GPIO as INPUT or OUTPUT int digitalWrite(int pin, int value); //Writes value on GPIO int digitalRead(int pin); //Reads value from GPIO int unexport(int pin); - const char *getErrorMessage(); - private: - bool error_flag; - std::string ErrorMessage; + void onError() {}; }; diff --git a/drivers/i2c.cpp b/drivers/i2c.cpp index fb43181..dc7a698 100644 --- a/drivers/i2c.cpp +++ b/drivers/i2c.cpp @@ -16,39 +16,39 @@ //------------------Konstruktor------------------ /** @~english -* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* @brief Sets the devicefile to "/dev/i2c-1" * * @~german -* @brief Setzt das error_flag auf "false" und das devicefile auf standardmäßig "/dev/i2c-1" +* @brief Setzt das devicefile auf standardmäßig "/dev/i2c-1" * */ -gnublin_i2c::gnublin_i2c() +gnublin_i2c::gnublin_i2c() : gnublin_driver() { init(DEFAULTDEVICE, -1); } //------------------Konstruktor------------------ /** @~english -* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* @brief Sets the devicefile to "/dev/i2c-1" * * @~german -* @brief Setzt das error_flag auf "false" und das devicefile auf standardmäßig "/dev/i2c-1" +* @brief Setzt das devicefile auf standardmäßig "/dev/i2c-1" * */ -gnublin_i2c::gnublin_i2c(int Address) +gnublin_i2c::gnublin_i2c(int Address) : gnublin_driver() { init(DEFAULTDEVICE, Address); } //------------------Konstruktor------------------ /** @~english -* @brief Sets the error_flag to "false" and the devicefile to "/dev/i2c-1" +* @brief Sets the devicefile to "/dev/i2c-1" * * @~german -* @brief Setzt das error_flag auf "false" und das devicefile auf standardmäßig "/dev/i2c-1" +* @brief Setzt das devicefile auf standardmäßig "/dev/i2c-1" * */ -gnublin_i2c::gnublin_i2c(std::string Devicefile, int Address) +gnublin_i2c::gnublin_i2c(std::string Devicefile, int Address) : gnublin_driver() { init(Devicefile, Address); } @@ -78,30 +78,22 @@ void gnublin_i2c::init(std::string Devicefile, int Address) { devicefile=Devicefile; slave_address = Address; - error_flag=false; fd = 0; } -//------------------error messaging------------------ +//------------------Error message------------------ /** @~english -* @brief Called by the constructors to initialize class variables. -* -* @param message String contents that describe the error. -* @return failure: -1 +* @brief Closes the file if open and resets the variable. +* called from base class when error message is set * * @~german -* @brief Wird von den Konstruktoren der Klasse Variablen zu initialisieren. -* -* @param message String Inhalte, die den Fehler beschreiben. -* @return failure: -1 +* @brief Schließt die Datei, wenn offen und setzt die Variable. +* Wird aufgerufen, wenn Fehlermeldung Basisklasse eingestellt ist. * */ -int gnublin_i2c::errorMsg(std::string message) +void gnublin_i2c::onError() { - ErrorMessage=message; - error_flag=true; close_fd(); - return -1; } //------------------close file descriptor------------------ @@ -138,7 +130,7 @@ void gnublin_i2c::close_fd() */ int gnublin_i2c::open_fd() { - error_flag = false; + clearError(); if (fd) { close_fd(); @@ -146,32 +138,17 @@ int gnublin_i2c::open_fd() } if (slave_address == -1) - return errorMsg("ERROR slave address is not set\n"); + return setErrorMessage("ERROR slave address is not set\n"); if ((fd = open(devicefile.c_str(), O_RDWR)) < 0) - return errorMsg("ERROR opening: " + devicefile + "\n"); + return setErrorMessage("ERROR opening: " + devicefile + "\n"); if (ioctl(fd, I2C_SLAVE, slave_address) < 0) - return errorMsg("ERROR address: " + numberToString(slave_address) + "\n"); + return setErrorMessage("ERROR address: " + numberToString(slave_address) + "\n"); return 0; } -//-------------------------------Fail------------------------------- -/** @~english -* @brief returns the error flag to check if the last operation went wrong -* -* @return error_flag as boolean -* -* @~german -* @brief Gibt das error_flag zurück um zu überprüfen ob die vorangegangene Operation einen Fehler auweist -* -* @return error_flag als bool -*/ -bool gnublin_i2c::fail(){ - return error_flag; -} - //-------------set Address------------- /** @~english * @brief Set the i2c slave address @@ -209,23 +186,6 @@ int gnublin_i2c::getAddress(){ return slave_address; } -//-------------get Error Message------------- -/** @~english -* @brief Get the last Error Message. -* -* This function returns the last Error Message, which occurred in that Class. -* @return ErrorMessage as c-string -* -* @~german -* @brief Gibt die letzte Error Nachricht zurück. -* -* Diese Funktion gibt die Letzte Error Nachricht zurück, welche in dieser Klasse gespeichert wurde. -* @return ErrorMessage als c-string -*/ -const char *gnublin_i2c::getErrorMessage(){ - return ErrorMessage.c_str(); -} - //-------------------set devicefile---------------- /** @~english * @brief set i2c the device file. default is "/dev/i2c-1" @@ -273,18 +233,18 @@ int gnublin_i2c::setDevicefile(std::string filename){ int gnublin_i2c::receive(unsigned char *RxBuf, int length){ if (RxBuf == 0) - return errorMsg("Receive method received a null TxBuf pointer.\n"); + return setErrorMessage("Receive method received a null TxBuf pointer.\n"); if (length < 1) - return errorMsg("Receive method received an invalid buffer length.\n"); + return setErrorMessage("Receive method received an invalid buffer length.\n"); if (!fd) if (open_fd() == -1) return -1; - error_flag=false; + clearError(); if (read(fd, RxBuf, length) != length) - return errorMsg("i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"); + return setErrorMessage("i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"); return 1; } @@ -323,21 +283,21 @@ int gnublin_i2c::receive(unsigned char *RxBuf, int length){ int gnublin_i2c::receive(unsigned char RegisterAddress, unsigned char *RxBuf, int length){ if (RxBuf == 0) - return errorMsg("Receive method received a null TxBuf pointer.\n"); + return setErrorMessage("Receive method received a null TxBuf pointer.\n"); if (length < 1) - return errorMsg("Receive method received an invalid buffer length.\n"); + return setErrorMessage("Receive method received an invalid buffer length.\n"); if (!fd) if (open_fd() == -1) return -1; - error_flag=false; + clearError(); if (write(fd, &RegisterAddress, 1) != 1) - return errorMsg("i2c write error!\n"); + return setErrorMessage("i2c write error!\n"); if (read(fd, RxBuf, length) != length) - return errorMsg("i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"); + return setErrorMessage("i2c read error! Address: " + numberToString(slave_address) + " dev file: " + devicefile + "\n"); return 1; } @@ -368,18 +328,18 @@ int gnublin_i2c::receive(unsigned char RegisterAddress, unsigned char *RxBuf, in int gnublin_i2c::send(unsigned char *TxBuf, int length){ if (TxBuf == 0) - return errorMsg("Send method received a null TxBuf pointer.\n"); + return setErrorMessage("Send method received a null TxBuf pointer.\n"); if (length < 1) - return errorMsg("Send method received an invalid buffer length.\n"); + return setErrorMessage("Send method received an invalid buffer length.\n"); if (!fd) if (open_fd() == -1) return -1; - error_flag=false; + clearError(); if(write(fd, TxBuf, length) != length) - return errorMsg("i2c write error!\n"); + return setErrorMessage("i2c write error!\n"); return 1; } @@ -418,21 +378,21 @@ int gnublin_i2c::send(unsigned char *TxBuf, int length){ int gnublin_i2c::send(unsigned char RegisterAddress, unsigned char *TxBuf, int length){ if (TxBuf == 0) - return errorMsg("Send method received a null TxBuf pointer.\n"); + return setErrorMessage("Send method received a null TxBuf pointer.\n"); if (length < 1) - return errorMsg("Send method received an invalid buffer length.\n"); + return setErrorMessage("Send method received an invalid buffer length.\n"); if (!fd) if (open_fd() == -1) return -1; - error_flag=false; + clearError(); if (send(RegisterAddress) == -1) return -1; if(write(fd, TxBuf, length) != length) - return errorMsg("i2c write error!\n"); + return setErrorMessage("i2c write error!\n"); return 1; } @@ -464,10 +424,10 @@ int gnublin_i2c::send(unsigned char value){ if (open_fd() == -1) return -1; - error_flag=false; + clearError(); if(write(fd, &value, 1) != 1) - return errorMsg("i2c write error!\n"); + return setErrorMessage("i2c write error!\n"); return 1; } diff --git a/drivers/i2c.h b/drivers/i2c.h index 0920c17..eb2abfe 100644 --- a/drivers/i2c.h +++ b/drivers/i2c.h @@ -1,4 +1,5 @@ #include "../include/includes.h" +#include "driver.h" //******************************************************************* //Class for accessing GNUBLIN i2c Bus //******************************************************************* @@ -14,25 +15,21 @@ * Die GNUBLIN I2C Klasse gewährt einfachen Zugriff auf den I2C Bus */ -class gnublin_i2c { - bool error_flag; +class gnublin_i2c : public gnublin_driver { int slave_address; std::string devicefile; - std::string ErrorMessage; int fd; - int errorMsg(std::string message); int open_fd(); void close_fd(); void init(std::string DeviceFile, int Address); + void onError(); public: gnublin_i2c(); gnublin_i2c(int Address); gnublin_i2c(std::string DeviceFile, int Address); ~gnublin_i2c(); - bool fail(); int setAddress(int Address); int getAddress(); - const char *getErrorMessage(); int setDevicefile(std::string filename); int receive(unsigned char *RxBuf, int length); int receive(unsigned char RegisterAddress, unsigned char *RxBuf, int length); diff --git a/drivers/spi.cpp b/drivers/spi.cpp index a608709..8f61d12 100644 --- a/drivers/spi.cpp +++ b/drivers/spi.cpp @@ -1,6 +1,5 @@ #include "spi.h" - //*************************************************************************** // Class for accessing the SPI-Bus //*************************************************************************** @@ -19,8 +18,8 @@ * GNUBLIN: CS = 11 * RASPBERRY PI: CS = 0 */ -gnublin_spi::gnublin_spi(){ - error_flag = false; +gnublin_spi::gnublin_spi() : gnublin_driver() +{ #if BOARD == RASPBERRY_PI std::string device = "/dev/spidev0.0"; #else @@ -35,6 +34,8 @@ gnublin_spi::gnublin_spi(){ #endif sleep(1); fd = open(device.c_str(), O_RDWR); + if (fd < 0) + setErrorMessage("Unable to open file "+device+"\n"); } } @@ -45,41 +46,6 @@ gnublin_spi::~gnublin_spi(){ close(fd); } - -//******************** fail() *********************************************** -/** -* @~english -* @brief Returns the errorflag to detect error in the previous called method. -* -* @return error_flag -* -* @~german -* @brief Gibt das errorflag zurück, um Fehler in der zuvor aufgerugfenen Methode zu erkennen. -* -* @return error_flag -*/ -bool gnublin_spi::fail(){ - return error_flag; -} - - -//-------------get Error Message------------- -/** -* @~english -* @brief Returns the ErrorMessage of the previous error if one exist. -* -* @return ErrorMessage as C-String -* -* @~german -* @brief Gibt die Fehlernachricht des zuvor aufgetretenen Fehlers zurück, wenn weine exisitert. -* -* @return ErrorMessage als C-String -*/ -const char *gnublin_spi::getErrorMessage(){ - return ErrorMessage.c_str(); -} - - //*********************** setCS ********************************************* /** @@ -108,12 +74,10 @@ int gnublin_spi::setCS(int cs){ system(command.c_str()); sleep(1); fd = open(device.c_str(), O_RDWR); - if (fd < 0){ - error_flag = true; - return -1; - } + if (fd < 0) + return setErrorMessage("Unable to open file "+device+"\n"); } - error_flag = false; + clearError(); return 1; } @@ -134,11 +98,9 @@ int gnublin_spi::setCS(int cs){ * @return 1 bei Erfolg, -1 im Fehlerfall */ int gnublin_spi::setMode(unsigned char mode){ - if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return 1; } @@ -158,11 +120,9 @@ int gnublin_spi::setMode(unsigned char mode){ */ int gnublin_spi::getMode(){ __u8 mode; - if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return mode; } @@ -183,11 +143,9 @@ int gnublin_spi::getMode(){ * @return 1 bei Erfolg, -1 im Fehlerfall */ int gnublin_spi::setLSB(unsigned char lsb){ - if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb) < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return 1; } @@ -207,11 +165,9 @@ int gnublin_spi::setLSB(unsigned char lsb){ */ int gnublin_spi::getLSB(){ __u8 lsb; - if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) { - error_flag = true; - return -1; - } - error_flag = false; + if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return lsb; } @@ -232,11 +188,9 @@ int gnublin_spi::getLSB(){ * @return 1 bei Erfolg, -1 im Fehlerfall */ int gnublin_spi::setLength(unsigned char bits){ - if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return 1; } @@ -256,11 +210,9 @@ int gnublin_spi::setLength(unsigned char bits){ */ int gnublin_spi::getLength(){ __u8 bits; - if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return bits; } @@ -281,11 +233,9 @@ int gnublin_spi::getLength(){ * @return 1 bei Erfolg, -1 im Fehlerfall */ int gnublin_spi::setSpeed(unsigned int speed){ - if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0){ - error_flag = true; - return -1; - } - error_flag = true; + if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return 1; } @@ -305,11 +255,9 @@ int gnublin_spi::setSpeed(unsigned int speed){ */ int gnublin_spi::getSpeed(){ __u32 speed; - if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) + return setErrorMessage("ioctl failed."); + clearError(); return speed; } @@ -331,11 +279,9 @@ int gnublin_spi::getSpeed(){ * @return 1 bei Erfolg, -1 im Fehlerfall */ int gnublin_spi::receive(char* buffer, int len){ - if (read(fd, buffer, len) < 0) { - error_flag = true; - return -1; - } - error_flag = false; + if (read(fd, buffer, len) < 0) + return setErrorMessage("read failed."); + clearError(); return 1; } @@ -366,11 +312,9 @@ int gnublin_spi::send(unsigned char* tx, int length){ xfer.speed_hz = 0; xfer.bits_per_word = 0; status = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer); - if ( status < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if ( status < 0) + return setErrorMessage("ioctl status shows failure."); + clearError(); return 1; } @@ -414,11 +358,9 @@ int gnublin_spi::message(unsigned char* tx, int tx_length, unsigned char* rx, in xfer[1].bits_per_word = 0; status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer); - if (status < 0){ - error_flag = true; - return -1; - } - error_flag = false; + if (status < 0) + return setErrorMessage("ioctl status shows failure."); + clearError(); return 1; } diff --git a/drivers/spi.h b/drivers/spi.h index 81d521e..3e80fff 100644 --- a/drivers/spi.h +++ b/drivers/spi.h @@ -1,5 +1,5 @@ #include "../include/includes.h" - +#include "driver.h" //*************************************************************************** // Class for accessing the SPI-Bus //*************************************************************************** @@ -15,7 +15,7 @@ * * Diese Klasse ermöglicht das Senden und Empfangen von Daten über den SPI-Bus. */ -class gnublin_spi{ +class gnublin_spi : gnublin_driver { public: gnublin_spi(); ~gnublin_spi(); @@ -31,11 +31,7 @@ class gnublin_spi{ int send(unsigned char* tx, int length); int setCS(int cs); int message(unsigned char* tx, int tx_length, unsigned char* rx, int rx_length); - const char *getErrorMessage(); - bool fail(); private: int fd; - bool error_flag; - std::string ErrorMessage; - + void onError() {}; };