#include "gpio.hpp" #include "../../systems/systemCall.h" #include #include #define PIN_COUNT 26 class Gpio::gpioImpl { public: uint8_t pinCount = PIN_COUNT; char buffer[50]; uint8_t currentPin = 0; int ck = 0; std::ifstream bufFile; pinDefinition pins[PIN_COUNT + 1]; gpioImpl() { checkCurrentPins(); } void setFunction(uint8_t gpioNo, Gpio::pinFunction function) { pinInitiate(gpioNo); switch(pins[gpioNo].function) { case passive: pins[gpioNo].function = function; break; case gpio: pins[gpioNo].function = function; break; case i2c: pins[gpioNo].function = function; break; case spi: pins[gpioNo].function = function; break; case pwm: pins[gpioNo].function = function; break; case pcm: pins[gpioNo].function = function; break; case uart: pins[gpioNo].function = function; break; case eeprom: pins[gpioNo].function = function; break; case clk: pins[gpioNo].function = function; break; } } void setMode(uint8_t gpioNo, Gpio::pinMode mode) { switch(mode) { case input: sprintf(buffer, "echo \"in\" > /sys/class/gpio/gpio%d/direction",gpioNo); pins[gpioNo].mode = mode; system(buffer); break; case output: sprintf(buffer, "echo \"out\" > /sys/class/gpio/gpio%d/direction",gpioNo); pins[gpioNo].mode = mode; system(buffer); break; case analog: std::cout << "No analog pins are awailable for raspberry" << std::endl; break; case alternate: default : throwError(__LINE__,notValidMode); break; } } void setOutputState(uint8_t gpioNo, Gpio::pinState state) { std::cout << "This version of the code doesn't allow pin output Stage configuration for the raspberry" << std::endl; } void setPullUpDonw(uint8_t gpioNo, Gpio::pinPullUpDown resistance) { std::cout << "This version of the code doesn't allow Pull up or Pull donw configurations for the raspberry" << std::endl; } void setSpeed(uint8_t gpioNo, Gpio::pinSpeed speed) { std::cout << "This version of the code doesn't allow pin speed changes for the raspberry" << std::endl; } void config(uint8_t gpioNo,Gpio::pinFunction function, Gpio::pinMode mode, Gpio::pinState state, Gpio::pinPullUpDown resistance, Gpio::pinSpeed speed) { pinInitiate(gpioNo); setFunction(gpioNo, function); setMode(gpioNo, mode); } int8_t readPin(uint8_t gpioNo) { if(pins[gpioNo].mode == undefined) { throwError(__LINE__,pinNotDeclared); } else { if(pins[gpioNo].function == gpio) { sprintf(buffer,"/sys/class/gpio/gpio%d/value",gpioNo); bufFile.open(buffer,std::ios::in); if(bufFile.is_open()) { bufFile.read(buffer,3); bufFile.read(buffer,1); if(buffer[0] == '1') { bufFile.close(); return 1; } else if (buffer[0] == '0') { bufFile.close(); return 0; } } } else { throwError(__LINE__, pinNotGpio); } } return 2; } void writePin(uint8_t gpioNo, uint8_t value) { if(pins[gpioNo].mode == undefined) { throwError(__LINE__,pinNotDeclared); } else { if(pins[gpioNo].function == gpio) { if(value == 0) { sprintf(buffer, "echo \"%d\" > /sys/class/gpio/gpio%d/value",value,gpioNo); system(buffer); } else if (value == 1) { sprintf(buffer, "echo \"%d\" > /sys/class/gpio/gpio%d/value",value,gpioNo); system(buffer); } else { throwError(__LINE__,notValidOut); } } else { throwError(__LINE__, pinNotGpio); } } } uint16_t readRange(uint8_t start, uint8_t stop) { return 0; } void writeRange(uint8_t start, uint8_t stop, uint16_t value) { } void pinInitiate(uint8_t gpioNo) { if(gpioNo <= PIN_COUNT) { sprintf(buffer,"[ -d /sys/class/gpio/gpio%d ]",gpioNo); // retunrs null if directory exists ck = system(buffer); if( ck != 0) { sprintf(buffer, "echo \"%d\" > /sys/class/gpio/export",gpioNo); ck = system(buffer); } else { std::cout << "Pin already initiated"<< std::endl; std::cout << " - "; pinPrintInfo(gpioNo); } } else { throwError(__LINE__,pinOutOfRange); } } void pinUninitiate(uint8_t gpioNo) { if(gpioNo <= PIN_COUNT) { sprintf(buffer,"[ -d /sys/class/gpio/gpio%d ]",gpioNo); // retunrs null if directory exists ck = system(buffer); if( ck == 0) { sprintf(buffer, "echo \"%d\" > /sys/class/gpio/unexport",gpioNo); system(buffer); } else { throwError(__LINE__,pinNotDeclared); } } else { throwError(__LINE__,pinOutOfRange); } } void checkCurrentPins() { uint8_t i = 0; for( i = 0; i < PIN_COUNT; i++) { sprintf(buffer,"[ -d /sys/class/gpio/gpio%d ]",i); // retunrs null if directory exists ck = system(buffer); if( ck == 0) { std::cout << "Pin: "<< unsigned(i) << " Exists " << std::endl; sprintf(buffer,"/sys/class/gpio/gpio%d/direction",i); bufFile.open(buffer,std::ios::in); if(bufFile.is_open()) { bufFile.read(buffer,3); if(buffer[0] == 'i') { if (buffer[1] == 'n') { pins[i].mode = input; // init of the direction and the rest as a stanard gpio pin. pins[i].state = openDrain; pins[i].pud = none; pins[i].speed = normal; pins[i].interrupt = disabled; pins[i].function = gpio; } } else if (buffer[0] == 'o') { if(buffer[1] == 'u') { if(buffer[2] == 't') { pins[i].mode = output; pins[i].state = openDrain; pins[i].pud = none; pins[i].speed = normal; pins[i].interrupt = disabled; pins[i].function = gpio; } } } bufFile.close(); } } } } void pinList() // Lists allthe pins whom their mode in not set to undefined. { uint8_t i = 0; for(i = 0; i < PIN_COUNT; i++) { if(pins[i].mode != undefined) { std::cout << "|Pin "<< unsigned(i) <<" already exists and will be initialized as default GPIO|" << std::endl; pinPrintInfo(i); } } } void pinPrintInfo(uint8_t gpioNo) // a graphical arrangement to see the cunnrently acive pins { std::cout << "Pin No: " << unsigned(gpioNo); switch(pins[gpioNo].mode) { case undefined: std::cout << "| Mode: Undefined\t"; break; case input: std::cout << "| Mode: Input\t"; break; case output: std::cout << "| Mode: Output\t"; break; case analog: std::cout << "| Mode: Analog\t"; break; case alternate: std::cout << "| Mode: Alternate\t"; break; } switch(pins[gpioNo].state) { case floating: std::cout << "| State: Floating "; break; case pushPull: std::cout << "| State: Push-Pull "; break; case openDrain: std::cout << "| State: Open Drain "; break; } switch(pins[gpioNo].pud) { case none: std::cout << "| Pud: None "; break; case pullUp: std::cout << "| Pud: Pull-up "; break; case pullDown: std::cout << "| Pud: Pull-down "; break; } switch(pins[gpioNo].speed) { case slow: std::cout << "| Speed: Slow "; break; case normal: std::cout << "| Speed: Normal "; break; case fast: std::cout << "| Speed: Fast "; break; case veryFast: std::cout << "| Speed: Very Fast "; break; } switch(pins[gpioNo].interrupt) { case disabled: std::cout << "| Interrupt: No "; break; case enabled: std::cout << "| Interrupt: Yes "; break; } switch(pins[gpioNo].function) { case passive: std::cout << "| Function: NONE"; break; case gpio: std::cout << "| Function: GPIO"; break; case i2c: std::cout << "| Function: I2C"; break; case spi: std::cout << "| Function: SPI"; break; case pwm: std::cout << "| Function: PWM"; break; case pcm: std::cout << "| Function: PCM"; break; case uart: std::cout << "| Function: UART"; break; case eeprom: std::cout << "| Function: EEPROM"; break; case clk: std::cout << "| Function: CLK"; break; } std::cout << "|" << std::endl; } void throwError(uint16_t line, Gpio::errors errNo) { std::cout << "Error GPIO.C | Code Line: "<< unsigned(line) << " | Error No: "<< errNo << " | Description: "; switch(errNo) { case notValidMode: std::cout << "notValidMode"; break; case notValidOut: std::cout << "notValidOut"; break; case pinOutOfRange: std::cout << "pinOutOfRange"; break; case pinNotDeclared: std::cout << "pinNotDeclared"; break; case pinNotReachable: std::cout << "pinNotReachable"; break; case pinNoPullUpDown: std::cout << "pinNoPullUpDown"; break; case pinNotAnalog: std::cout << "pinNotAnalog"; break; case pinNotDigital: std::cout << "pinNotDigital"; break; case pinTooFast: std::cout << "pinTooFast"; break; case pinBocked: std::cout << "pinBocked"; break; case pinAlreadyUsed: std::cout << "pinAlreadyUsed"; break; case pinNotGpio: std::cout << "pinAlreadyUsed"; break; default: std::cout << "Unhandled Error"; break; } std::cout << " |" << std::endl; } }; Gpio::Gpio():gpioPimpl(new gpioImpl()){} Gpio::~Gpio(){} void Gpio::setFunction(uint8_t gpioNo, Gpio::pinFunction function) { return gpioPimpl->setFunction(gpioNo, function); } void Gpio::setMode(uint8_t gpioNo, Gpio::pinMode mode) { return gpioPimpl->setMode(gpioNo, mode); } void Gpio::setOutputState(uint8_t gpioNo, Gpio::pinState state) { return gpioPimpl->setOutputState(gpioNo,state); } void Gpio::setPullUpDonw(uint8_t gpioNo, Gpio::pinPullUpDown resistance) { return gpioPimpl->setPullUpDonw(gpioNo,resistance); } void Gpio::setSpeed(uint8_t gpioNo, Gpio::pinSpeed speed) { return gpioPimpl->setSpeed(gpioNo, speed); } void Gpio::config(uint8_t gpioNo,Gpio::pinFunction function, Gpio::pinMode mode, Gpio::pinState state, Gpio::pinPullUpDown resistance, Gpio::pinSpeed speed) { return gpioPimpl->config(gpioNo,function ,mode,state,resistance,speed); } uint8_t Gpio::readPin(uint8_t gpioNo) { return gpioPimpl->readPin(gpioNo); } void Gpio::writePin(uint8_t gpioNo, uint8_t value) { return gpioPimpl->writePin(gpioNo, value); } uint16_t Gpio::readRange(uint8_t start, uint8_t stop) { return gpioPimpl->readRange(start,stop); } void Gpio::writeRange(uint8_t start, uint8_t stop, uint16_t value) { return gpioPimpl->writeRange(start,stop,value); } void Gpio::pinInitiate(uint8_t gpioNo) { return gpioPimpl->pinInitiate(gpioNo); } void Gpio::pinUninitiate(uint8_t gpioNo) { return gpioPimpl->pinUninitiate(gpioNo); } void Gpio::checkCurrentPins() { return gpioPimpl->checkCurrentPins(); } void Gpio::pinList() { return gpioPimpl->pinList(); } void Gpio::pinPrintInfo(uint8_t gpioNo) { return gpioPimpl->pinPrintInfo(gpioNo); } void Gpio::throwError(uint16_t line, Gpio::errors error) { return gpioPimpl->throwError(line, error); }