Cours:DevoirPOO2 classes
Révision datée du 6 octobre 2022 à 09:51 par Bjacquot (discussion | contributions)
Il s’agit d’une page protégée.
#ifndef ECLAIRAGEDIMMABLE_H
#define ECLAIRAGEDIMMABLE_H
#include <QObject>
class EclairageDimmable : public QObject
{
Q_OBJECT
public:
explicit EclairageDimmable(QObject *parent = nullptr);
bool isOn;
unsigned int puissance; // entre 1 et 4
public slots:
void allumer();
void eteindre();
void augmenterPuissance();
void diminuerPuissance();
protected:
virtual void appliquerConsigne();
signals:
};
#endif // ECLAIRAGEDIMMABLE_H
|
#include "eclairagedimmable.h"
#include <QDebug>
EclairageDimmable::EclairageDimmable(QObject *parent) : QObject(parent)
{
isOn=false;
puissance=1;
}
void EclairageDimmable::allumer()
{
isOn=true;
appliquerConsigne();
}
void EclairageDimmable::eteindre()
{
isOn=false;
appliquerConsigne();
}
void EclairageDimmable::augmenterPuissance()
{
if (puissance<4) puissance++;
appliquerConsigne();
}
void EclairageDimmable::diminuerPuissance()
{
if (puissance>2) puissance--;
appliquerConsigne();
}
void EclairageDimmable::appliquerConsigne()
{
qDebug() << "je suis "<< (isOn==true?"allumée":"éteinte")<< " à la puissance "<<puissance;
}
|
#ifndef BARREGRAPHE_H
#define BARREGRAPHE_H
#include "eclairagedimmable.h"
#include "gpio.h"
using namespace exploringRPi;
class Barregraphe : public EclairageDimmable
{
public:
Barregraphe(int pinLed1, int pinLed2, int pinLed3, int pinLed4);
protected:
GPIO led1;
GPIO led2;
GPIO led3;
GPIO led4;
void appliquerConsigne() override;
};
#endif // BARREGRAPHE_H
|
#include "barregraphe.h"
Barregraphe::Barregraphe(int pinLed1, int pinLed2, int pinLed3, int pinLed4)
:led1(pinLed1),led2(pinLed2),led3(pinLed3),led4(pinLed4)
{
led1.setDirection(OUTPUT);
led2.setDirection(OUTPUT);
led3.setDirection(OUTPUT);
led4.setDirection(OUTPUT);
}
void Barregraphe::appliquerConsigne()
{
EclairageDimmable::appliquerConsigne();
v if (isOn==false)
{
led1.setValue(LOW);
led2.setValue(LOW);
led3.setValue(LOW);
led4.setValue(LOW);
}
else
{
if (puissance==1)
{
led1.setValue(HIGH);
led2.setValue(LOW);
led3.setValue(LOW);
led4.setValue(LOW);
}
else if (puissance==2)
{
led1.setValue(HIGH);
led2.setValue(HIGH);
led3.setValue(LOW);
led4.setValue(LOW);
}
else if (puissance==3)
{
led1.setValue(HIGH);
led2.setValue(HIGH);
led3.setValue(HIGH);
led4.setValue(LOW);
}
else
{
led1.setValue(HIGH);
led2.setValue(HIGH);
led3.setValue(HIGH);
led4.setValue(HIGH);
}
}
}
|
#ifndef LEDDIMMABLE_H
#define LEDDIMMABLE_H
#include "eclairagedimmable.h"
#include "pwm.h"
class LedDimmable : public EclairageDimmable
{
public:
LedDimmable(unsigned int numPwm);
protected:
Pwm mli;
void appliquerConsigne() override;
};
#endif // LEDDIMMABLE_H
|
#include "leddimmable.h"
LedDimmable::LedDimmable(unsigned int numPwm)
: mli(numPwm)
{
mli.setRange(23);
mli.setRapportCyclique(0);
}
void LedDimmable::appliquerConsigne()
{
EclairageDimmable::appliquerConsigne();
if (isOn==false)
{
mli.setRapportCyclique(0);
}
else
{
mli.setRapportCyclique(puissance*3+10);
}
}
|
#ifndef PWM_H
#define PWM_H
#include "rpiperipherique.h"
class Pwm : public RpiPeripherique
{
private:
unsigned int mRange=0;
unsigned int regPWM_RNG; // Clock controller
unsigned int regPWM_DAT; // Clock controller
public:
Pwm(unsigned int pwmNumber);
void setRange(unsigned int rng);
void setRapportCyclique(unsigned int rapport);
};
#endif // PWM_H
|
#include "pwm.h"
#include <iostream>
#include <unistd.h>
using namespace std;
#define PWM_CTL_PWM0 0
#define PWM_CTL_PWM1 8
#define GPIO_FSEL12 6
#define GPIO_FSEL13 9
#define PWM_MODE_NORMAL 0x1
const unsigned int regGPIO_FSEL = 0x200004; // Clock controller
const unsigned int regPWM_CTL = 0x20C000; // Clock controller
const unsigned int regPWM_RNG0 = 0x20C010; // Clock controller
const unsigned int regPWM_DAT0 = 0x20C014; // Clock controller
const unsigned int regPWM_RNG1 = 0x20C020; // Clock controller
const unsigned int regPWM_DAT1 = 0x20C024; // Clock controller
Pwm::Pwm(unsigned int pwmNumber):RpiPeripherique()
{
int offset,offsetGPIO;
if (pwmNumber>1)
{
cout << "le numéro de PWM doit être 0 ou 1 !"<<endl;
exit(-1);
}
if (pwmNumber==0)
{
cout <<"pwm0"<<endl;
regPWM_RNG = regPWM_RNG0;
regPWM_DAT = regPWM_DAT0;
offset = PWM_CTL_PWM0;
offsetGPIO = GPIO_FSEL12;
}
else
{
cout <<"pwm1"<<endl;
regPWM_RNG = regPWM_RNG1;
regPWM_DAT = regPWM_DAT1;
offset = PWM_CTL_PWM1;
offsetGPIO = GPIO_FSEL13;
}
regClearBits(regPWM_CTL,0xff,offset);
regClearBits(regGPIO_FSEL,0x7,offsetGPIO);
regSetBits(regGPIO_FSEL,0x4,offsetGPIO);
usleep(110);
regSetBits(regPWM_CTL,PWM_MODE_NORMAL,offset);
}
void Pwm::setRange(unsigned int rng)
{
mRange = rng;
regWrite(regPWM_RNG,rng);
setRapportCyclique(0);
}
void Pwm::setRapportCyclique(unsigned int rapport)
{
if (rapport >= mRange)
{
cout << "rapport cyclique non adapté !"<<mRange<<" "<<rapport<<endl;
exit(-1);
}
regWrite(regPWM_DAT,rapport);
}
|
#ifndef PWMCLK_H
#define PWMCLK_H
#include "rpiperipherique.h"
/*
0 0 Hz Ground
1 19.2 MHz oscillator
2 0 Hz testdebug0
3 0 Hz testdebug1
4 0 Hz PLLA
5 1000 MHz PLLC (changes with overclock settings)
6 500 MHz PLLD
7 216 MHz HDMI auxiliary
8-15 0 Hz Ground
*/
class PwmClk : public RpiPeripherique
{
private:
void regSetBitsWithPassword(unsigned int reg, unsigned int val,unsigned int offset);
void regClearBitsWithPassword(unsigned int reg, unsigned int val,unsigned int offset);
public:
PwmClk();
void setPwmClkDiv(unsigned int prediv);
};
#endif // PWMCLK_H
|
#include "pwmclk.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <iostream>
using namespace std;
#define CM_PWMCTL_SRV 0
#define CM_PWMCTL_ENAB 4
#define CM_PWMCTL_KILL 5
#define CM_PWMCTL_BUSY 7
#define CM_PWMCTL_FLIP 8
#define CM_PWMCTL_MASH 9
#define CM_PWMCTL_PASSWORD 24
#define CM_PWMDIV_DIVF 0
#define CM_PWMDIV_DIVI 12
#define PWMCLK_PASSWORD 0x5a
const unsigned int regCM_PWMCTL = 0x1010a0; // Clock controller
const unsigned int regCM_PWMDIV = 0x1010a4; // Clock controller
PwmClk::PwmClk():RpiPeripherique()
{
cout << "Horloge par défaut : clk1 19.2M"<<endl;
cout << "MASH = 0 : % entiere"<<endl;
cout << "Arret de l'horloge PWM ..."<<endl;
regClearBitsWithPassword(regCM_PWMCTL,1,CM_PWMCTL_ENAB);
while (regRead(regCM_PWMCTL)&(1<<CM_PWMCTL_BUSY));
cout <<"ok"<<endl;
regSetBitsWithPassword(regCM_PWMCTL,1,CM_PWMCTL_SRV);
regClearBitsWithPassword(regCM_PWMCTL,3,CM_PWMCTL_MASH);
}
void PwmClk::regSetBitsWithPassword(unsigned int reg, unsigned int val, unsigned int offset)
{
unsigned int regVal = regRead(reg);
regVal |= (val<<offset)|(PWMCLK_PASSWORD<<CM_PWMCTL_PASSWORD);
regWrite(reg,regVal);
}
void PwmClk::regClearBitsWithPassword(unsigned int reg, unsigned int val, unsigned int offset)
{
unsigned int regVal = regRead(reg);
regVal &=~(val<<offset);
regVal |= PWMCLK_PASSWORD<<CM_PWMCTL_PASSWORD;
regWrite(reg,regVal);
}
void PwmClk::setPwmClkDiv(unsigned int prediv)
{
if (prediv > 0xfff)
{
cout <<"prediviseur trop grand !!"<<endl;
exit(-1);
}
cout << "Arret de l'horloge PWM ..."<<endl;
regClearBitsWithPassword(regCM_PWMCTL,1,CM_PWMCTL_ENAB);
while (regRead(regCM_PWMCTL)&(1<<CM_PWMCTL_BUSY));
cout <<"ok"<<endl;
regClearBitsWithPassword(regCM_PWMDIV,0xfff,CM_PWMDIV_DIVI);
regSetBitsWithPassword(regCM_PWMDIV,prediv,CM_PWMDIV_DIVI);
cout <<"Démarrage de l'horloge PWM ..."<<endl;
regSetBitsWithPassword(regCM_PWMCTL,1,CM_PWMCTL_ENAB);
while ( (regRead(regCM_PWMCTL)&(1<<CM_PWMCTL_BUSY)) == 0);
cout << "ok !"<<endl;
}
|
#ifndef RPIPERIPHERIQUE_H
#define RPIPERIPHERIQUE_H
#include <cstdint>
class RpiPeripherique
{
private:
int mBaseAdress = 0;
unsigned int *memMap;
public:
RpiPeripherique();
protected :
void regWrite(unsigned int reg, unsigned int val);
void regSetBits(unsigned int reg, unsigned int val,unsigned int offset);
void regClearBits(unsigned int reg, unsigned int val,unsigned int offset);
unsigned int regRead(unsigned int reg);
};
#endif // RPIPERIPHERIQUE_H
|
#include "rpiperipherique.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
using namespace std;
RpiPeripherique::RpiPeripherique()
{
uint8_t buf[4];
int memSize = 0;
int fd = open("/sys/firmware/devicetree/base/soc/ranges", O_RDONLY);
if (fd<=0)
{
cout << "Pb de configuration de sysfs !!"<<endl;
exit(-1);
}
lseek(fd, 4, SEEK_SET);
if (read(fd, buf, sizeof(buf)) == sizeof(buf)) {
mBaseAdress = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] );
cout << "Adresse de base des périphs : 0x"<< hex << mBaseAdress <<endl;
}
lseek(fd, 8, SEEK_SET);
if (read(fd, buf, sizeof(buf)) == sizeof(buf)) {
memSize = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] );
cout << "Taille de la mémoire : 0x"<< hex << memSize <<endl;
}
close(fd);
if ( (memSize==0) || (mBaseAdress==0) )
{
cout << "Pb de lecture des paramètres mémoire !!"<<endl;
exit(-1);
}
fd = open("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC);
if (fd<=0)
{
cout << "Pb d'accès à /dev/mem !!"<<endl;
exit(-1);
}
memMap = (unsigned int *)mmap(NULL, memSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, mBaseAdress);
if (memMap == MAP_FAILED)
{
cout << "Pb de mappage mémoire !!"<<endl;
exit(-1);
}
close(fd);
}
void RpiPeripherique::regWrite(unsigned int reg, unsigned int val)
{
*(memMap+reg/4) = val;
}
void RpiPeripherique::regSetBits(unsigned int reg, unsigned int val, unsigned int offset)
{
unsigned int regVal = *(memMap+reg/4);
regVal |= val<<offset;
*(memMap+reg/4) = regVal;
}
void RpiPeripherique::regClearBits(unsigned int reg, unsigned int val, unsigned int offset)
{
unsigned int regVal = *(memMap+reg/4);
regVal &=~ (val<<offset);
*(memMap+reg/4) = regVal;
}
unsigned int RpiPeripherique::regRead(unsigned int reg)
{
return *(memMap+reg/4);
}
|
#ifndef GPIO_H
#define GPIO_H
#include<string>
#include<fstream>
using std::string;
using std::ofstream;
#define GPIO_PATH "/sys/class/gpio/"
namespace exploringRPi {
typedef int (*CallbackType)(int);
enum GPIO_DIRECTION{ INPUT, OUTPUT };
enum GPIO_VALUE{ LOW=0, HIGH=1 };
enum GPIO_EDGE{ NONE, RISING, FALLING, BOTH };
class GPIO {
private:
int number, debounceTime;
string name, path;
public:
GPIO(int number); // constructor exports pin
virtual int getNumber() { return number; }
// General Input and Output Settings
virtual int setDirection(GPIO_DIRECTION);
virtual GPIO_DIRECTION getDirection();
virtual int setValue(GPIO_VALUE);
virtual int toggleOutput();
virtual GPIO_VALUE getValue();
virtual int setActiveLow(bool isLow=true); // low=1, high=0
virtual int setActiveHigh(); // default state
virtual void setDebounceTime(int time) { this->debounceTime = time; }
// Advanced output: faster by keeping the stream open (~20x)
virtual int streamOpen();
virtual int streamWrite(GPIO_VALUE);
virtual int streamClose();
virtual int toggleOutput(int time); // thread invert output every X ms
virtual int toggleOutput(int numberOfTimes, int time);
virtual void changeToggleTime(int time) { this->togglePeriod = time; }
virtual void toggleCancel() { this->threadRunning = false; }
// Advanced input: detect input edges -- threaded and non-threaded
virtual int setEdgeType(GPIO_EDGE);
virtual GPIO_EDGE getEdgeType();
virtual int waitForEdge(); // waits until button is pressed
virtual int waitForEdge(CallbackType callback); // threaded callback
virtual void waitForEdgeCancel() { this->threadRunning = false; }
virtual ~GPIO(); // destructor unexports the pin
private:
int write(string path, string filename, string value);
int write(string path, string filename, int value);
string read(string path, string filename);
int exportGPIO();
int unexportGPIO();
ofstream stream;
pthread_t thread;
CallbackType callbackFunction;
bool threadRunning;
int togglePeriod; // default 100ms
int toggleNumber; // default -1 (infinite)
friend void* threadedPoll(void *value);
friend void* threadedToggle(void *value);
};
void* threadedPoll(void *value); // callback functions for threads
void* threadedToggle(void *value); // callback functions for threads
} /* namespace exploringRPi */
#endif // GPIO_H
|
#include "gpio.h"
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include<cstdlib>
#include<cstdio>
#include<fcntl.h>
#include<unistd.h>
#include<sys/epoll.h>
#include<pthread.h>
using namespace std;
namespace exploringRPi {
/**
*
* @param number The GPIO number for the RPi
*/
GPIO::GPIO(int number) {
this->number = number;
this->debounceTime = 0;
this->togglePeriod=100;
this->toggleNumber=-1; //infinite number
this->callbackFunction = NULL;
this->threadRunning = false;
ostringstream s;
s << "gpio" << number;
this->name = string(s.str());
this->path = GPIO_PATH + this->name + "/";
this->exportGPIO();
// need to give Linux time to set up the sysfs structure
usleep(250000); // 250ms delay
}
int GPIO::write(string path, string filename, string value){
ofstream fs;
fs.open((path + filename).c_str());
if (!fs.is_open()){
perror("GPIO: write failed to open file ");
return -1;
}
fs << value;
fs.close();
return 0;
}
string GPIO::read(string path, string filename){
ifstream fs;
fs.open((path + filename).c_str());
if (!fs.is_open()){
perror("GPIO: read failed to open file ");
}
string input;
getline(fs,input);
fs.close();
return input;
}
int GPIO::write(string path, string filename, int value){
stringstream s;
s << value;
return this->write(path,filename,s.str());
}
int GPIO::exportGPIO(){
return this->write(GPIO_PATH, "export", this->number);
}
int GPIO::unexportGPIO(){
return this->write(GPIO_PATH, "unexport", this->number);
}
int GPIO::setDirection(GPIO_DIRECTION dir){
switch(dir){
case INPUT: return this->write(this->path, "direction", "in");
break;
case OUTPUT:return this->write(this->path, "direction", "out");
break;
}
return -1;
}
int GPIO::setValue(GPIO_VALUE value){
switch(value){
case HIGH: return this->write(this->path, "value", "1");
break;
case LOW: return this->write(this->path, "value", "0");
break;
}
return -1;
}
int GPIO::setEdgeType(GPIO_EDGE value){
switch(value){
case NONE: return this->write(this->path, "edge", "none");
break;
case RISING: return this->write(this->path, "edge", "rising");
break;
case FALLING: return this->write(this->path, "edge", "falling");
break;
case BOTH: return this->write(this->path, "edge", "both");
break;
}
return -1;
}
int GPIO::setActiveLow(bool isLow){
if(isLow) return this->write(this->path, "active_low", "1");
else return this->write(this->path, "active_low", "0");
}
int GPIO::setActiveHigh(){
return this->setActiveLow(false);
}
GPIO_VALUE GPIO::getValue(){
string input = this->read(this->path, "value");
if (input == "0") return LOW;
else return HIGH;
}
GPIO_DIRECTION GPIO::getDirection(){
string input = this->read(this->path, "direction");
if (input == "in") return INPUT;
else return OUTPUT;
}
GPIO_EDGE GPIO::getEdgeType(){
string input = this->read(this->path, "edge");
if (input == "rising") return RISING;
else if (input == "falling") return FALLING;
else if (input == "both") return BOTH;
else return NONE;
}
int GPIO::streamOpen(){
stream.open((path + "value").c_str());
return 0;
}
int GPIO::streamWrite(GPIO_VALUE value){
stream << value << std::flush;
return 0;
}
int GPIO::streamClose(){
stream.close();
return 0;
}
int GPIO::toggleOutput(){
this->setDirection(OUTPUT);
if ((bool) this->getValue()) this->setValue(LOW);
else this->setValue(HIGH);
return 0;
}
int GPIO::toggleOutput(int time){ return this->toggleOutput(-1, time); }
int GPIO::toggleOutput(int numberOfTimes, int time){
this->setDirection(OUTPUT);
this->toggleNumber = numberOfTimes;
this->togglePeriod = time;
this->threadRunning = true;
if(pthread_create(&this->thread, NULL, &threadedToggle, static_cast<void*>(this))){
perror("GPIO: Failed to create the toggle thread");
this->threadRunning = false;
return -1;
}
return 0;
}
// This thread function is a friend function of the class
void* threadedToggle(void *value){
GPIO *gpio = static_cast<GPIO*>(value);
bool isHigh = (bool) gpio->getValue(); //find current value
while(gpio->threadRunning){
if (isHigh) gpio->setValue(HIGH);
else gpio->setValue(LOW);
usleep(gpio->togglePeriod * 500);
isHigh=!isHigh;
if(gpio->toggleNumber>0) gpio->toggleNumber--;
if(gpio->toggleNumber==0) gpio->threadRunning=false;
}
return 0;
}
// Blocking Poll - based on the epoll socket code in the epoll man page
int GPIO::waitForEdge(){
this->setDirection(INPUT); // must be an input pin to poll its value
int fd, i, epollfd, count=0;
struct epoll_event ev;
epollfd = epoll_create(1);
if (epollfd == -1) {
perror("GPIO: Failed to create epollfd");
return -1;
}
if ((fd = open((this->path + "value").c_str(), O_RDONLY | O_NONBLOCK)) == -1) {
perror("GPIO: Failed to open file");
return -1;
}
//ev.events = read operation | edge triggered | urgent data
ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
ev.data.fd = fd; // attach the file file descriptor
//Register the file descriptor on the epoll instance, see: man epoll_ctl
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
perror("GPIO: Failed to add control interface");
return -1;
}
while(count<=1){ // ignore the first trigger
i = epoll_wait(epollfd, &ev, 1, -1);
if (i==-1){
perror("GPIO: Poll Wait fail");
count=5; // terminate loop
}
else {
count++; // count the triggers up
}
}
close(fd);
if (count==5) return -1;
return 0;
}
// This thread function is a friend function of the class
void* threadedPoll(void *value){
GPIO *gpio = static_cast<GPIO*>(value);
while(gpio->threadRunning){
gpio->callbackFunction(gpio->waitForEdge());
usleep(gpio->debounceTime * 1000);
}
return 0;
}
int GPIO::waitForEdge(CallbackType callback){
this->threadRunning = true;
this->callbackFunction = callback;
// create the thread, pass the reference, address of the function and data
if(pthread_create(&this->thread, NULL, &threadedPoll, static_cast<void*>(this))){
perror("GPIO: Failed to create the poll thread");
this->threadRunning = false;
return -1;
}
return 0;
}
GPIO::~GPIO() {
this->unexportGPIO();
}
} /* namespace exploringRPi */
|
#ifndef BOUTON_H
#define BOUTON_H
#include <QObject>
#include <QFileSystemWatcher>
#include "gpio.h"
using namespace exploringRPi;
class Bouton : public QObject
{
Q_OBJECT
public:
explicit Bouton(int nbBroche,GPIO_EDGE typeFront);
bool getValue();
private:
GPIO broche;
QFileSystemWatcher fileScanner;
signals:
void change();
public slots:
void evenementBroche();
};
#endif // BOUTON_H
|
#include "bouton.h"
Bouton::Bouton(int nbBroche, GPIO_EDGE typeFront) : QObject(), broche(nbBroche)
{
broche.setDirection(INPUT);
broche.setEdgeType(typeFront);
fileScanner.addPath(QString("/sys/class/gpio/gpio%1/value").arg(nbBroche));
connect(&fileScanner,SIGNAL(fileChanged(QString)),this,SLOT(evenementBroche()));
}
bool Bouton::getValue()
{
return broche.getValue();
}
void Bouton::evenementBroche()
{
emit change();
}
|