first commit

This commit is contained in:
2025-10-20 20:11:21 +02:00
commit cbf3c258e0
318 changed files with 41712 additions and 0 deletions
+428
View File
@@ -0,0 +1,428 @@
/*
* 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.
*
kmhelper.cpp
===========
useful functions
*
*/
#include "../qo100trx.h"
#include <pwd.h>
int keeprunning = 1; // set to 0 at program end to exit all processes
char configfile[512] = {0};
// check if it is already running
int isRunning(char *prgname)
{
int num = 0;
char s[256];
sprintf(s,"ps -e | grep %s",prgname);
FILE *fp = popen(s,"r");
if(fp)
{
// gets the output of the system command
while (fgets(s, sizeof(s)-1, fp) != NULL)
{
if(strstr(s,prgname) && !strstr(s,"grep"))
{
if(++num == 2)
{
printf("%s is already running, do not start twice !\n",prgname);
pclose(fp);
return 1;
}
}
}
pclose(fp);
}
return 0;
}
void (*sigfunc)();
// signal handler
void sighandler(int signum)
{
//printf("\n\nprogram stopped by signal\n");
(*sigfunc)();
}
void install_signal_handler(void (*signalfunction)())
{
sigfunc = signalfunction;
// signal handler, mainly used if the user presses Ctrl-C
struct sigaction sigact;
sigact.sa_handler = sighandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
sigaction(SIGABRT, &sigact, NULL); // assert() error
//sigaction(SIGSEGV, &sigact, NULL);
// switch off signal 13 (broken pipe)
// instead handle the return value of the write or send function
signal(SIGPIPE, SIG_IGN);
}
void getParameters(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "c:")) != -1)
{
switch (opt)
{
case 'c':
// specify config file name
if(optarg && strlen(optarg) > 2 && strlen(optarg) < (sizeof(configfile)-1))
{
strcpy(configfile,optarg);
}
else
{
printf("invalid Config File Parameter [-c Configfilename]: %s\n", optarg);
exit(0);
}
break;
}
}
}
// run external program and return it's output
char *runProgram(char *parameter, int maxlen)
{
//printf("run:<%s>\n",parameter);
FILE *fp = popen(parameter,"r");
if(fp)
{
*parameter = 0;
while (fgets(parameter+strlen(parameter), maxlen-1-strlen(parameter), fp) != NULL)
{
//printf("returns:<%s>\n", parameter);
}
pclose(fp);
return parameter;
}
else
printf("ERROR: cannot run: %s\n",parameter);
return NULL;
}
void showbitstring(char* title, uint8_t* data, int totallen, int anz)
{
printf("%s. len %d: ", title, totallen);
for (int i = 0; i < anz; i++)
printf("%01X ", data[i]);
printf("\n");
}
void showbytestring(char *title, uint8_t *data, int totallen, int anz)
{
printf("%s. len % 4d: ",title, totallen);
for(int i=0; i<anz; i++)
printf("%02X ",data[i]);
printf("\n");
}
void showbytestring16(char *title, uint16_t *data, int anz)
{
printf("%s. len %d: ",title,anz);
for(int i=0; i<anz; i++)
printf("%04X ",data[i]);
printf("\n");
}
void showbytestring32(char* title, uint32_t* data, int anz)
{
printf("%s. len %d: ", title, anz);
for (int i = 0; i < anz; i++)
printf("%08X ", data[i]);
printf("\n");
}
void showbytestringf(char* title, float* data, int totallen, int anz)
{
printf("%s. len %d: ", title, totallen);
for (int i = 0; i < anz; i++)
printf("%7.4f ", data[i]);
printf("\n");
}
// get own IP adress
char* ownIP()
{
static char ip[20] = { 0 };
struct ifaddrs* ifaddr, * ifa;
int s;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1)
{
printf("cannot read own IP address, getifaddrs faield. Check Networking\n");
return ip;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;
s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (ifa->ifa_addr->sa_family == AF_INET)
{
if (s != 0)
{
printf("getnameinfo() failed: %s\n", gai_strerror(s));
printf("cannot read own IP address, getnameinfo failed: %s. Check Networking\n", gai_strerror(s));
break;
}
if (strncmp(host, "127", 3) != 0)
{
strcpy(ip, host);
break;
}
}
}
freeifaddrs(ifaddr);
return ip;
}
char* cleanStr(char *s)
{
if(s[0] > ' ')
{
// remove trailing crlf
for(size_t j=0; j<strlen(s); j++)
if(s[j] == '\n' || s[j] == '\r') s[j] = 0;
return s; // nothing to do
}
for(size_t i=0; i<strlen(s); i++)
{
if(s[i] >= '0')
{
// i is on first character
memmove(s,s+i,strlen(s)-i);
s[strlen(s)-i] = 0;
// remove trailing crlf
for(size_t j=0; j<strlen(s); j++)
if(s[j] == 'n' || s[j] == '\r') s[j] = 0;
return s;
}
}
return NULL; // no text found in string
}
char *getword(char *s, int idx)
{
if(idx == 0)
{
for(size_t i=0; i<strlen(s); i++)
{
if(s[i] < '0')
{
s[i] = 0;
return s;
}
}
return NULL;
}
for(size_t j=0; j<strlen(s); j++)
{
if(s[j] > ' ')
{
char *start = s+j;
for(size_t k=0; k<strlen(start); k++)
{
if(start[k] == ' ' || start[k] == '\r' || start[k] == '\n')
{
start[k] = 0;
return start;
}
}
return start;
}
}
return NULL;
}
// read the value of an element from the config file
// Format:
// # ... comment
// ElementName-space-ElementValue
// the returned value is a static string and must be copied somewhere else
// before this function can be called again
char *getConfigElement(char *elemname)
{
if(strlen(configfile) < 2) return NULL;
static char s[501];
int found = 0;
char fn[1024];
if(strlen(configfile) > 512)
{
printf("config file path+name too long: %s\n",configfile);
exit(0);
}
strcpy(fn,configfile);
if(fn[0] == '~')
{
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
sprintf(fn,"%s%s",homedir,configfile+1);
}
//printf("read Configuration file %s\n",fn);
FILE *fr = fopen(fn,"rb");
if(!fr)
{
printf("!!! Configuration file %s not found !!!\n",fn);
exit(0);
}
while(1)
{
if(fgets(s,500,fr) == NULL) break;
// remove leading SPC or TAB
if(cleanStr(s) == 0) continue;
// check if its a comment
if(s[0] == '#') continue;
// get word on index
char *p = getword(s,0);
if(!p) break;
if(strcmp(p, elemname) == 0)
{
char val[500];
if(*(s+strlen(p)+1) == 0) continue;
p = getword(s+strlen(p)+1,1);
if(!p) break;
// replace , with .
char *pkomma = strchr(p,',');
if(pkomma) *pkomma = '.';
strcpy(val,p);
strcpy(s,val);
found = 1;
break;
}
}
fclose(fr);
if(found == 0) return NULL;
return s;
}
void getConfigElement_double(char *elemname, double *pv, double multiplier)
{
char *p = getConfigElement(elemname);
if(p) *pv = atof(p) * multiplier;
}
void getConfigElement_longlong(char *elemname, long long *pv, double multiplier)
{
char *p = getConfigElement(elemname);
if(p) *pv = (long long)(atof(p) * multiplier);
}
void getConfigElement_int(char *elemname, int *pv, double multiplier)
{
char *p = getConfigElement(elemname);
if(p) *pv = (int)(atof(p) * multiplier);
}
float measure_samplerate(int id, int samp, int prt)
{
static unsigned long lastus[10];
static unsigned long samples[10];
static int f[10];
static int cnt[10];
static int first=1;
if(first)
{
first = 0;
for(int i=0; i<10; i++)
{
f[i] = 1;
cnt[i] = 0;
}
}
// measure sample rate
struct timeval tv;
gettimeofday(&tv, NULL);
if(f[id])
{
f[id] = 0;
lastus[id] = tv.tv_sec * 1000000 + tv.tv_usec;
samples[id] = samp;
}
samples[id] += samp;
unsigned long tnow = tv.tv_sec * 1000000 + tv.tv_usec;
float sr = 0;
if(++(cnt[id]) >= prt)
{
cnt[id] = 0;
sr = (samples[id]*1e6)/(tnow - lastus[id]);
printf("%d: %.6f\n",id,sr/1e6);
}
return sr;
}
int measure_maxval(double v, int anz)
{
static double max = - 99999999;
static int cnt = 0;
v = fabs(v);
if(v > max)
{
max = v;
//printf("maxval: %f\n",max);
}
if(++cnt >= anz)
{
printf("maxval: %f\n",max);
max = - 99999999;
cnt = 0;
return 1;
}
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netdb.h>
int isRunning(char *prgname);
void install_signal_handler(void (*signalfunction)());
void showbitstring(char* title, uint8_t* data, int totallen, int anz);
void showbytestring(char *title, uint8_t *data, int totallen, int anz);
void showbytestring16(char *title, uint16_t *data, int anz);
void showbytestring32(char* title, uint32_t* data, int anz);
void showbytestringf(char* title, float* data, int totallen, int anz);
char* ownIP();
char *getConfigElement(char *elemname);
void getConfigElement_double(char *elemname, double *pv, double multiplier);
void getConfigElement_longlong(char *elemname, long long *pv, double multiplier);
void getConfigElement_int(char *elemname, int *pv, double multiplier);
float measure_samplerate(int id, int samp, int prt);
int measure_maxval(double v, int anz);
char *runProgram(char *parameter, int maxlen);
extern int keeprunning;
BIN
View File
Binary file not shown.
+173
View File
@@ -0,0 +1,173 @@
/*
* 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.
*
* universal thread safe fifo, used by many drivers and applications
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <pthread.h>
#include "kmfifo.h"
FIFOOBJ fifo[MAXFIFOS];
int fifonum = 0;
#define LOCK(id) pthread_mutex_lock(&fifo[id].crit_sec)
#define UNLOCK(id) pthread_mutex_unlock(&fifo[id].crit_sec)
// creates a new fifo
// maxelem_num ... max. number of elements in fifo
// maxelem_len ... max. length of one element (shorter elements are allowed)
// returns: ID of a fifo object, to be used for fifo functions
int create_fifo(int maxelem_num, int maxelem_len)
{
// create the fifo memory and init variables
fifo[fifonum].fifomem = malloc(maxelem_num * maxelem_len);
fifo[fifonum].plen = (int *)malloc(maxelem_num * sizeof(int));
fifo[fifonum].maxelemlen =maxelem_len;
fifo[fifonum].maxelem = maxelem_num;
fifo[fifonum].rdidx = 0;
fifo[fifonum].wridx = 0;
pthread_mutex_init(&fifo[fifonum].crit_sec, NULL);
int id = fifonum;
fifonum++;
return id;
}
void destroy_fifos()
{
for(int i=0; i<fifonum; i++)
{
free(fifo[fifonum].fifomem);
free(fifo[fifonum].plen);
if (&fifo[fifonum].crit_sec != NULL) pthread_mutex_destroy(&fifo[fifonum].crit_sec);
}
}
// write into the fifo
// ignore data if the fifo is full
void write_fifo(int id, uint8_t *pdata, int len)
{
FIFOOBJ *pfo = &fifo[id];
if(len > pfo->maxelemlen)
{
printf("element too long\n");
return;
}
LOCK(id);
if (((pfo->wridx + 1) % pfo->maxelem) == pfo->rdidx)
{
printf("cannot WRITE fifo %d full\n",id);
UNLOCK(id);
return;
}
// insert length of new data
*(pfo->plen) = len; // real length of the element
// insert new data
void *dst = (void *)((uint8_t *)pfo->fifomem + pfo->wridx * pfo->maxelemlen);
memcpy(dst, pdata, len);
if(++pfo->wridx >= pfo->maxelem) pfo->wridx = 0;
UNLOCK(id);
}
// read from the fifo
// return: number of bytes read
int read_fifo(int id, uint8_t* pdata, int maxlen)
{
FIFOOBJ *pfo = &fifo[id];
LOCK(id);
if(pfo->rdidx == pfo->wridx)
{
// Fifo empty, no data available
//printf("read: no data\n");
UNLOCK(id);
return 0;
}
// read length
int len = *pfo->plen; // length of an element
if (len > maxlen)
{
printf("read_fifo: %d, pdata too small. Need:%d has:%d\n", id, len, maxlen);
return 0; // pdata too small
}
// read data
void *src = (void *)((uint8_t *)pfo->fifomem + pfo->rdidx * pfo->maxelemlen);
memcpy(pdata, src, len);
if (++pfo->rdidx >= pfo->maxelem) pfo->rdidx = 0;
UNLOCK(id);
return len;
}
void fifo_clear(int id)
{
fifo[id].wridx = fifo[id].rdidx = 0;
}
int fifo_freespace(int id)
{
int freebuf = 0;
LOCK(id);
int elemInFifo = (fifo[id].wridx + fifo[id].maxelem - fifo[id].rdidx) % fifo[id].maxelem;
freebuf = fifo[id].maxelem - elemInFifo;
UNLOCK(id);
return freebuf;
}
int fifo_dataavail(int id)
{
LOCK(id);
if (fifo[id].rdidx == fifo[id].wridx)
{
// Fifo empty, no data available
UNLOCK(id);
return 0;
}
UNLOCK(id);
return 1;
}
int fifo_usedspace(int id)
{
int us = fifo[id].maxelem - fifo_freespace(id);
return us;
}
+21
View File
@@ -0,0 +1,21 @@
// max number of fifo, just a high number, never really used
#define MAXFIFOS 200
typedef struct _FIFOOBJ_ {
int maxelem;
int maxelemlen;
int rdidx;
int wridx;
void *fifomem;
int *plen; // real length of an element
pthread_mutex_t crit_sec;
} FIFOOBJ;
int create_fifo(int elem_num, int elem_len);
void destroy_fifos();
void write_fifo(int id, uint8_t *pdata, int len);
int read_fifo(int id, uint8_t* pdata, int maxlen);
void fifo_clear(int id);
int fifo_freespace(int id);
int fifo_dataavail(int id);
int fifo_usedspace(int id);
BIN
View File
Binary file not shown.
+114
View File
@@ -0,0 +1,114 @@
/*
* Linux multithreaded timer
* =========================
* 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 3 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, see <http://www.gnu.org/licenses/>
*
* Repeatable Timer for various needs
* ==================================
*
*/
#include "kmtimer.h"
/*
usage:
// this function is called every time_in_ms milliseconds
void timerhandler_function(void)
{
// called every time_in_ms
}
// start a new timer
int timernum = start_timer(time_in_ms, &timerhandler_function);
stop_timer(timernum);
*/
typedef struct _TIMERDEF_ {
int to_ms; // timeout value in ms
timer_t timerid;
void(*timer_func_handler_pntr)(void); // this user supplied function is called on timeout
struct itimerspec in, out;
} TIMERDEF;
#define MAXTIMERS 20
TIMERDEF timers[MAXTIMERS];
int timernum = 0;
// callback function. The timer number is in val.sival_int
void sighler (union sigval val)
{
int tnum = val.sival_int;
timers[tnum].timer_func_handler_pntr();
}
int start_timer(int mSec, void(*timer_func_handler)(void))
{
timers[timernum].timer_func_handler_pntr = timer_func_handler;
timers[timernum].to_ms = mSec;
pthread_attr_t attr;
pthread_attr_init( &attr );
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = sighler;
sig.sigev_value.sival_int = timernum;
sig.sigev_notify_attributes = &attr;
int ret = timer_create(CLOCK_REALTIME, &sig, &(timers[timernum].timerid));
if (ret == 0)
{
timers[timernum].in.it_value.tv_sec = mSec / 1000;
timers[timernum].in.it_value.tv_nsec = (mSec % 1000) * 1000000;
timers[timernum].in.it_interval.tv_sec = mSec / 1000;
timers[timernum].in.it_interval.tv_nsec = (mSec % 1000) * 1000000;
ret = timer_settime(timers[timernum].timerid, 0, &timers[timernum].in, &timers[timernum].out);
if(ret == -1)
{
printf("timer_settime() failed with %d\n", errno);
return -1;
}
}
else
{
printf("timer_create() failed with %d\n", errno);
return -1;
}
int r = timernum;
timernum++;
return r;
}
void stop_timer(int timer)
{
timer_delete(timers[timer].timerid);
}
+13
View File
@@ -0,0 +1,13 @@
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
int start_timer(int mSec, void(*timer_func_handler)(void));
void stop_timer(int timer);
void sleep_ms(int ms);
BIN
View File
Binary file not shown.
+393
View File
@@ -0,0 +1,393 @@
/*
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);
}
}
+7
View File
@@ -0,0 +1,7 @@
void init_rotencoder();
void close_gpio();
int getEncSteps(int idx);
int test_ptt_gpio();
int test_mute_gpio();
void setPort(char *port, int value);
int getPort(char *port);
BIN
View File
Binary file not shown.