QO100Tx_Rx/kmlib/rotary.cpp

394 lines
8.4 KiB
C++
Raw Permalink Normal View History

2025-10-20 20:11:21 +02:00
/*
this is an extract from kmclib (see github, dj0abr repos)
it works on raspberry pi only
* Raspberry PI / Zero AddOn Board specially for Ham Radio Applications
* ====================================================================
* Author: DJ0ABR
*
* (c) DJ0ABR
* www.dj0abr.de
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
encoder.cpp
===========
function to handle rotary encoder
Usage:
======
initialize and assign ports to the encoders
-------------------------------------------
up to 3 encoders are supported, If not used, then assign port nunmber -1
init_rotencoder(int portA1, int portB1, int portA2, int portB2, int portA3, int portB3)
see gpio.h _INPUTS_ for valid port numbers
read encoder:
-------------
int getEncSteps(int idx)
idx ... encoder number 0,1 or 2
returns the number of steps since last read
*
*/
#include "../qo100trx.h"
int init_gpio();
int getPort(char *port);
#define NUM_OF_ENCODERS 2
pthread_mutex_t rotenc_crit_sec;
#define LOCK pthread_mutex_lock(&(rotenc_crit_sec))
#define UNLOCK pthread_mutex_unlock(&(rotenc_crit_sec))
void *rotencproc(void *);
char portA[NUM_OF_ENCODERS][3] = {"fa","va"};
char portB[NUM_OF_ENCODERS][3] = {"fb","vb"};
int encsteps[NUM_OF_ENCODERS];
pthread_t rotenc_tid;
// port numbers see gpio.h _INPORTS_
// -1 if not used
void init_rotencoder()
{
// use the rotary encoder on a raspberry board only
// RASPI is passed to the Makefile as: make RASPI='-DRASPI'
#ifndef RASPI
return;
#endif
if(init_gpio() == -1) return;
memset(&encsteps, 0, sizeof(int)*NUM_OF_ENCODERS);
int pret = pthread_create(&rotenc_tid,NULL,rotencproc, NULL);
if(pret)
{
printf("rotenc process NOT started\n");
exit(0);
}
}
int getEncSteps(int idx)
{
int v;
LOCK;
v = encsteps[idx];
encsteps[idx] = 0;
UNLOCK;
return v;
}
void *rotencproc(void *pdata)
{
pthread_detach(pthread_self());
printf("rotenc process started\n");
int aval[NUM_OF_ENCODERS];
int bval[NUM_OF_ENCODERS];
int oldaval[NUM_OF_ENCODERS]={0,0};
while(keeprunning)
{
for(int i=0; i<NUM_OF_ENCODERS; i++)
{
aval[i] = getPort(portA[i]);
bval[i] = getPort(portB[i]);
if(aval[i]==1 && oldaval[i]==0)
{
// falling edge of port A
int dir = -1;
if(bval[i] == 1) dir = 1;
LOCK;
encsteps[i] += dir;
UNLOCK;
}
oldaval[i] = aval[i];
}
usleep(100);
}
printf("exit rotenc thread\n");
pthread_exit(NULL);
}
// 0=RX, 1=TX, 2=just released, 3=just pressed
int test_ptt_gpio()
{
#ifndef RASPI
return -1;
#endif
static int gold = -1;
int ret = 0;
int ptt = getPort("p");
if(gold != -1)
{
if(ptt == 0)
{
// PTT is pressed
if(gold == 0) ret = 1;
else ret = 3;
}
else
{
// PTT is released
if(gold == 0) ret = 2;
else ret = 0;
}
}
gold = ptt;
return ret;
}
// 0=unmuted, 1=muted, 2=just unmuted, 3=just muted
int test_mute_gpio()
{
#ifndef RASPI
return -1;
#endif
static int gold = -1;
int ret = 0;
int mute = getPort("m");
if(gold != -1)
{
if(mute == 0)
{
// mute is pressed
if(gold == 0) ret = 1;
else ret = 3;
}
else
{
// mute is released
if(gold == 0) ret = 2;
else ret = 0;
}
}
gold = mute;
return ret;
}
/* ============= Linux GPIO interface =============
requires packages: gpiod libgpiod-dev
command line interface see:
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/README
C-Functions see: /usr/include/gpiod.h
connect rotary encoders to these pins:
frequency-encoder A ... GPIO17 (Pin11)
frequency-encoder B ... GPIO27 (Pin13)
volume -encoder A ... GPIO4 (Pin 7)
volume -encoder B ... GPIO22 (Pin15)
PTT input ... GPIO18 (Pin12)
Mute ... GPIO23 (Pin16)
PTT output ... GPIO24 (Pin18)
*/
#include <gpiod.h>
struct gpiod_chip *chip = NULL;
struct gpiod_line *fa = NULL;
struct gpiod_line *fb = NULL, *va = NULL, *vb = NULL, *gptt = NULL, *gmute = NULL, *pttout = NULL;
int init_gpio()
{
int ret;
chip= gpiod_chip_open("/dev/gpiochip0");
if(!chip)
{
printf("cannot open GPIO chip\n");
return -1;
}
//fa= gpiod_chip_get_info(chip,17);
if (!fa) {
printf("cannot access GPIO17\n");
gpiod_chip_close(chip);
return -1;
}
//fb= gpiod_chip_get_line(chip,27);
if (!fb) {
printf("cannot access GPIO27\n");
gpiod_chip_close(chip);
return -1;
}
//va= gpiod_chip_get_line(chip,4);
if (!va) {
printf("cannot access GPIO4\n");
gpiod_chip_close(chip);
return -1;
}
//vb= gpiod_chip_get_line(chip,22);
if (!vb) {
printf("cannot access GPIO22\n");
gpiod_chip_close(chip);
return -1;
}
//gptt = gpiod_chip_get_line(chip,18);
if (!gptt) {
printf("cannot access GPIO18\n");
gpiod_chip_close(chip);
return -1;
}
//gmute = gpiod_chip_get_line(chip,23);
if (!gmute) {
printf("cannot access GPIO23\n");
gpiod_chip_close(chip);
return -1;
}
//pttout = gpiod_chip_get_line(chip,24);
if (!pttout) {
printf("cannot access GPIO24\n");
gpiod_chip_close(chip);
return -1;
}
//ret = gpiod_line_request_get_fd(fa, "huhu");
if (ret) {
printf("cannot init GPIO17 for input\n");
gpiod_chip_close(chip);
return -1;
}
//ret = gpiod_line_request_input(fb, "huhu");
if (ret) {
printf("cannot init GPIO27 for input\n");
gpiod_chip_close(chip);
return -1;
}
//ret = gpiod_line_request_input(va, "huhu");
if (ret) {
printf("cannot init GPIO4 for input\n");
gpiod_chip_close(chip);
return -1;
}
//ret = gpiod_line_request_input(vb, "huhu");
if (ret) {
printf("cannot init GPIO22 for input\n");
gpiod_chip_close(chip);
return -1;
}
//ret = gpiod_line_request_input(gptt, "huhu");
if (ret) {
printf("cannot init GPIO18 for input\n");
gpiod_chip_close(chip);
return -1;
}
//ret = gpiod_line_request_input(gmute, "huhu");
if (ret) {
printf("cannot init GPIO23 for input\n");
gpiod_chip_close(chip);
return -1;
}
//ret = gpiod_line_request_get_fd(pttout, "huhu", 0);
if (ret) {
printf("cannot init GPIO24 for output\n");
gpiod_chip_close(chip);
return -1;
}
printf("GPIOs initialized\n");
return 0;
}
void close_gpio()
{
/* if(fa) gpiod_line_request(fa);
if(fb) gpiod_line_request(fb);
if(va) gpiod_line_request(va);
if(vb) gpiod_line_request(vb);
if(gptt) gpiod_line_request(gptt);
if(gmute) gpiod_line_request(gmute);
*/
if(chip) gpiod_chip_close(chip);
}
// get status of physical port
int getPort(char *port)
{
#ifndef RASPI
return 0;
#endif
if(port[0] == 'f')
{
//if(port[1] == 'a') return gpiod_line_value(fa);
//return gpiod_line_value(fb);
}
if(port[0] == 'v')
{
//if(port[1] == 'a') return gpiod_line_value(va);
//return gpiod_line_value(vb);
}
//if(port[0] == 'p')
//return gpiod_line_value(gptt);
//if(port[0] == 'm')
//return gpiod_line_value(gmute);
return 0;
}
void setPort(char *port, int value)
{
#ifndef RASPI
return;
#endif
if(port[0] == 'p')
{
//gpiod_line_value(pttout,value);
}
}