280 lines
6.2 KiB
C++
280 lines
6.2 KiB
C++
/***************************************************************************
|
|
|
|
source::worx PiGPIO
|
|
Copyright © 2022 c.holzheuer
|
|
chris@sourceworx.org
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
***************************************************************************/
|
|
|
|
#include <QtGlobal>
|
|
#include <QDebug>
|
|
|
|
#include <SWPiGPIO.h>
|
|
|
|
#ifdef Q_OS_LINUX
|
|
|
|
#include <cstdint>
|
|
//#include <pigpio.h>
|
|
//#include "/usr/include/pigpio.h"
|
|
|
|
#include <pigpiod_if2.h>
|
|
|
|
PiGPIO::PiGPIO()
|
|
{
|
|
//::gpioInitialise();
|
|
// Connect to Pi.
|
|
constexpr char* optHost = nullptr;
|
|
constexpr char* optPort = nullptr;
|
|
PI = ::pigpio_start( optHost, optPort );
|
|
qDebug() << " -- PiGPIO::PiGPIO(): " << PI;
|
|
if( PI < 0 )
|
|
qDebug() << "-- PiGPIO::PiGPIO() FAIL";
|
|
}
|
|
|
|
|
|
PiGPIO::~PiGPIO()
|
|
{
|
|
::pigpio_stop( PI );
|
|
}
|
|
|
|
|
|
//----------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
* @brief Implementierung für Linux
|
|
*/
|
|
|
|
PiGRotaryDial::PiGRotaryDial( unsigned dialA, unsigned dialB, unsigned button, QObject* parent )
|
|
: QObject( parent ),
|
|
_dialA( dialA ), _dialB( dialB ), _button( button )
|
|
|
|
{
|
|
|
|
_Pi = PiGPIO::Instance().PI;
|
|
|
|
//_mode = mode;
|
|
//_cb = cb_func;
|
|
_levA = 0;
|
|
_levB = 0;
|
|
_step = 0;
|
|
|
|
::set_mode( _Pi, _dialA, PI_INPUT );
|
|
::set_mode( _Pi, _dialB, PI_INPUT );
|
|
::set_mode( _Pi, _button, PI_INPUT );
|
|
|
|
// pull up is needed as encoder common is grounded
|
|
|
|
::set_pull_up_down( _Pi, _dialA, PI_PUD_UP );
|
|
::set_pull_up_down( _Pi, _dialB, PI_PUD_UP );
|
|
::set_pull_up_down( _Pi, _button, PI_PUD_UP );
|
|
|
|
_glitch = 1000;
|
|
|
|
::set_glitch_filter( _Pi, _dialA, _glitch );
|
|
::set_glitch_filter( _Pi, _dialB, _glitch );
|
|
::set_glitch_filter( _Pi, _button, _glitch );
|
|
|
|
_oldState = ( ::gpio_read( _Pi, _dialA ) << 1) | ::gpio_read( _Pi, _dialB );
|
|
|
|
// monitor encoder level changes
|
|
//int callback_ex(int pi, unsigned user_gpio, unsigned edge, CBFuncEx_t f, void *userdata)
|
|
// typedef void (*CBFuncEx_t)(int pi, unsigned user_gpio, unsigned level, uint32_t tick, void * userdata);
|
|
_callbackIdA = ::callback_ex( _Pi, _dialA, EITHER_EDGE, PiGPIOPulse, this );
|
|
_callbackIdB = ::callback_ex( _Pi, _dialB, EITHER_EDGE, PiGPIOPulse, this );
|
|
_callbackIdC = ::callback_ex( _Pi, _button, EITHER_EDGE, PiGPIOPulse, this );
|
|
}
|
|
|
|
|
|
PiGRotaryDial::~PiGRotaryDial()
|
|
{
|
|
|
|
if( _callbackIdA >= 0 )
|
|
{
|
|
::callback_cancel( _callbackIdA );
|
|
_callbackIdA = -1;
|
|
}
|
|
|
|
if( _callbackIdB >= 0 )
|
|
{
|
|
::callback_cancel( _callbackIdB );
|
|
_callbackIdB = -1;
|
|
}
|
|
|
|
if( _callbackIdC >= 0 )
|
|
{
|
|
::callback_cancel( _callbackIdC );
|
|
_callbackIdC = -1;
|
|
}
|
|
|
|
::set_glitch_filter( _Pi, _dialA, 0 );
|
|
::set_glitch_filter( _Pi, _dialB, 0 );
|
|
::set_glitch_filter( _Pi, _button, 0 );
|
|
|
|
}
|
|
|
|
|
|
void PiGRotaryDial::setGlitchFilter( int glitch )
|
|
{
|
|
if( _glitch == glitch )
|
|
return;
|
|
_glitch = glitch;
|
|
::set_glitch_filter( _Pi, _dialA, glitch );
|
|
::set_glitch_filter( _Pi, _dialB, glitch );
|
|
::set_glitch_filter( _Pi, _button, glitch );
|
|
}
|
|
|
|
|
|
void PiGRotaryDial::pulse( unsigned gpio, unsigned level )
|
|
{
|
|
|
|
|
|
if( level == PI_TIMEOUT )
|
|
return;
|
|
if( gpio == _button )
|
|
return handleClick( level );
|
|
|
|
if( gpio == _dialA )
|
|
_levA = level;
|
|
else
|
|
_levB = level;
|
|
|
|
// sourceworx proudly presents:
|
|
// den primitivstmöglichen Auslese-algorithmus
|
|
// für Rotary-Dials.
|
|
// Die klugen Varianten stehen hier:
|
|
// https://www.best-microcontroller-projects.com/rotary-encoder.html
|
|
// https://web.engr.oregonstate.edu/~traylor/ece473/student_projects/ReadingEncoderSwitches.pdf
|
|
|
|
// wenn sich was geändert hatte ...
|
|
if( gpio == _dialB && level == 1 )
|
|
{
|
|
// bestimmt der andere Kontakt die
|
|
// die Drehrichtung
|
|
|
|
int delta = _levA ? -1 : +1;
|
|
//qDebug() << "###### EMIT: " << delta;
|
|
emit deltaChanged( delta );
|
|
}
|
|
}
|
|
|
|
|
|
void PiGRotaryDial::handleClick( unsigned level )
|
|
{
|
|
if( !_pressed && level == 0 )
|
|
{
|
|
_pressed = true;
|
|
return;
|
|
}
|
|
if( _pressed && level == 1 )
|
|
{
|
|
_pressed = false;
|
|
emit clicked();
|
|
}
|
|
|
|
}
|
|
|
|
#endif // Q_OS_LINUX
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
source::worx PiGPIO
|
|
Copyright © 2022 c.holzheuer
|
|
chris@sourceworx.org
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
***************************************************************************/
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
|
|
PiGPIO::PiGPIO()
|
|
{
|
|
|
|
}
|
|
|
|
PiGPIO::~PiGPIO()
|
|
{
|
|
}
|
|
|
|
|
|
PiGRotaryDial::PiGRotaryDial( unsigned dialA, unsigned dialB, unsigned button, QObject* parent )
|
|
: QObject( parent ),
|
|
_dialA( dialA ), _dialB( dialB ), _button( button )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
PiGRotaryDial::~PiGRotaryDial()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void PiGRotaryDial::setGlitchFilter( int )
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void PiGRotaryDial::pulse( unsigned, unsigned )
|
|
{
|
|
|
|
}
|
|
|
|
#endif //Q_OS_WIN
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
source::worx PiGPIO
|
|
Copyright © 2022 c.holzheuer
|
|
chris@sourceworx.org
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
void PiGRotaryDial::PiGPIOPulse( int pi, unsigned gpio, unsigned level, uint32_t tick, void *user )
|
|
{
|
|
|
|
Q_UNUSED( pi );
|
|
Q_UNUSED( tick );
|
|
|
|
// Need a static callback to link with C.
|
|
PiGRotaryDial* mySelf = static_cast<PiGRotaryDial*>( user );
|
|
if( mySelf )
|
|
mySelf->pulse( gpio, level ); // Call the instance callback.
|
|
}
|
|
|
|
/*
|
|
void PiGRotaryDial::setPosition( int position )
|
|
{
|
|
_step = position * 4;
|
|
}
|
|
|
|
|
|
int PiGRotaryDial::position()
|
|
{
|
|
return _step / 4;
|
|
}
|
|
*/
|