Skip to content

Add libgpiod support #283

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add libgpiod support
  • Loading branch information
ew1abz committed Jun 14, 2020
commit 81d11c5e93a86f472c460be0be9b7a2c94551aec
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,5 @@ $RECYCLE.BIN/
*.dSYM

# cmake
build/
build*/
tmp/
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ elseif(APPLE)
message(STATUS "RPATH support: ${CMAKE_MACOSX_RPATH}")

elseif (WIN32)
if(NOT VS2015 AND NOT VS2017)
message(FATAL_ERROR "You must use Microsoft Visual Studio 2015 or 2017 as compiler")
if(NOT VS2015 AND NOT VS2017 AND NOT VS2019)
message(FATAL_ERROR "You must use Microsoft Visual Studio 2015 | 2017 | 2019 as compiler")
endif()

# compile with full multicore
Expand Down Expand Up @@ -251,6 +251,14 @@ else()
set(HAMLIB_LIBRARIES "")
endif()

find_package(gpiod)
if(GPIOD_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_GPIOD")
else()
set(GPIOD_INCLUDE_DIRS "")
set(GPIOD_LIBRARIES "")
endif()

if(LINUX)
find_package(ALSA REQUIRED)
if(ALSA_FOUND)
Expand Down
4 changes: 3 additions & 1 deletion cmake/modules/FindCompiler.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ elseif(NOT DEFINED C_GCC AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(C_GCC 1)
elseif(NOT DEFINED C_MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(C_MSVC 1)
if(MSVC_VERSION GREATER 1910 AND MSVC_VERSION LESS 1919)
if(MSVC_VERSION GREATER 1919 AND MSVC_VERSION LESS 1926)
set(VS2019 ON)
elseif(MSVC_VERSION GREATER 1910 AND MSVC_VERSION LESS 1919)
set(VS2017 ON)
elseif(MSVC_VERSION GREATER 1899 AND MSVC_VERSION LESS 1910)
set(VS2015 ON)
Expand Down
23 changes: 23 additions & 0 deletions cmake/modules/Findgpiod.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# - Try to find libgpiod
# Once done this will define
# GPIOD_FOUND - System has libgpiod
# GPIOD_INCLUDE_DIRS - The libgpiod include directories
# GPIOD_LIBRARIES - The libraries needed to use libgpiod
# GPIOD_DEFINITIONS - Compiler switches required for using libgpiod

find_package(PkgConfig)
pkg_check_modules(PC_GPIOD QUIET gpiod)

find_path(GPIOD_INCLUDE_DIR gpiod.h)
find_library(GPIOD_LIBRARY NAMES gpiod)

include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set GPIOD_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(gpiod DEFAULT_MSG
GPIOD_LIBRARY GPIOD_INCLUDE_DIR)

mark_as_advanced(GPIOD_INCLUDE_DIR GPIOD_LIBRARY)

set(GPIOD_LIBRARIES ${GPIOD_LIBRARY})
set(GPIOD_INCLUDE_DIRS ${GPIOD_INCLUDE_DIR})
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include_directories(
${UDEV_INCLUDE_DIRS}
${PORTAUDIO_INCLUDE_DIRS}
${CUSTOM_GEOTRANZ_DIR}
${GPIOD_INCLUDE_DIRS}
)

if(WIN32 OR CYGWIN)
Expand Down Expand Up @@ -127,6 +128,7 @@ target_link_libraries(direwolf
${ALSA_LIBRARIES}
${UDEV_LIBRARIES}
${PORTAUDIO_LIBRARIES}
${GPIOD_LIBRARIES}
)

if(WIN32 OR CYGWIN)
Expand Down
4 changes: 3 additions & 1 deletion src/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
enum ptt_method_e {
PTT_METHOD_NONE, /* VOX or no transmit. */
PTT_METHOD_SERIAL, /* Serial port RTS or DTR. */
PTT_METHOD_GPIO, /* General purpose I/O, Linux only. */
PTT_METHOD_GPIO, /* General purpose I/O using sysfs, deprecated after 2020, Linux only. */
PTT_METHOD_GPIOD, /* General purpose I/O, using libgpiod, Linux only. */
PTT_METHOD_LPT, /* Parallel printer port, Linux only. */
PTT_METHOD_HAMLIB, /* HAMLib, Linux only. */
PTT_METHOD_CM108 }; /* GPIO pin of CM108/CM119/etc. Linux only. */
Expand Down Expand Up @@ -266,6 +267,7 @@ struct audio_s {
/* the case for CubieBoard where it was longer. */
/* This is filled in by ptt_init so we don't have to */
/* recalculate it each time we access it. */
/* Also GPIO chip name for GPIOD method. Looks like 'gpiochip4' */

/* This could probably be collapsed into ptt_device instead of being separate. */

Expand Down
37 changes: 37 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,43 @@ void config_init (char *fname, struct audio_s *p_audio_config,
}
p_audio_config->achan[channel].octrl[ot].ptt_method = PTT_METHOD_GPIO;
#endif
}
else if (strcasecmp(t, "GPIOD") == 0) {
#if __WIN32__
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file line %d: %s with GPIOD is only available on Linux.\n", line, otname);
#else
#if defined(USE_GPIOD)
t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file line %d: Missing GPIO chip for %s.\n", line, otname);
continue;
}
strlcpy(p_audio_config->achan[channel].octrl[ot].out_gpio_name, t,
sizeof(p_audio_config->achan[channel].octrl[ot].out_gpio_name));

t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf("Config file line %d: Missing GPIO number for %s.\n", line, otname);
continue;
}

if (*t == '-') {
p_audio_config->achan[channel].octrl[ot].out_gpio_num = atoi(t+1);
p_audio_config->achan[channel].octrl[ot].ptt_invert = 1;
}
else {
p_audio_config->achan[channel].octrl[ot].out_gpio_num = atoi(t);
p_audio_config->achan[channel].octrl[ot].ptt_invert = 0;
}
p_audio_config->achan[channel].octrl[ot].ptt_method = PTT_METHOD_GPIOD;
#else
text_color_set(DW_COLOR_ERROR);
dw_printf ("GPIOD is not supported.\n");
#endif /* USE_GPIOD*/
#endif /* __WIN32__ */
}
else if (strcasecmp(t, "LPT") == 0) {

Expand Down
3 changes: 3 additions & 0 deletions src/direwolf.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ int main (int argc, char *argv[])
#endif
#if defined(USE_CM108)
dw_printf (" cm108-ptt");
#endif
#if defined(USE_GPIOD)
dw_printf (" libgpiod");
#endif
dw_printf ("\n");
#endif
Expand Down
70 changes: 67 additions & 3 deletions src/ptt.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@
#include "cm108.h"
#endif

#ifdef USE_GPIOD
#include <gpiod.h>
#endif

/* So we can have more common code for fd. */
typedef int HANDLE;
#define INVALID_HANDLE_VALUE (-1)
Expand Down Expand Up @@ -623,6 +627,31 @@ void export_gpio(int ch, int ot, int invert, int direction)
get_access_to_gpio (gpio_value_path);
}

#if defined(USE_GPIOD)
int gpiod_probe(const char *chip_name, int line_number)
{
struct gpiod_chip *chip;
chip = gpiod_chip_open_by_name(chip_name);
if (chip == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Can't open GPIOD chip %s.\n", chip_name);
return -1;
}

struct gpiod_line *line;
line = gpiod_chip_get_line(chip, line_number);
if (line == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Can't get GPIOD line %d.\n", line_number);
return -1;
}
if (ptt_debug_level >= 2) {
text_color_set(DW_COLOR_DEBUG);
dw_printf("GPIOD probe OK. Chip: %s line: %d\n", chip_name, line_number);
}
return 0;
}
#endif /* USE_GPIOD */
#endif /* not __WIN32__ */


Expand All @@ -639,7 +668,8 @@ void export_gpio(int ch, int ot, int invert, int direction)
* ptt_method Method for PTT signal.
* PTT_METHOD_NONE - not configured. Could be using VOX.
* PTT_METHOD_SERIAL - serial (com) port.
* PTT_METHOD_GPIO - general purpose I/O.
* PTT_METHOD_GPIO - general purpose I/O (sysfs).
* PTT_METHOD_GPIOD - general purpose I/O (libgpiod).
* PTT_METHOD_LPT - Parallel printer port.
* PTT_METHOD_HAMLIB - HAMLib rig control.
* PTT_METHOD_CM108 - GPIO pins of CM108 etc. USB Audio.
Expand Down Expand Up @@ -718,12 +748,13 @@ void ptt_init (struct audio_s *audio_config_p)
if (ptt_debug_level >= 2) {

text_color_set(DW_COLOR_DEBUG);
dw_printf ("ch=%d, %s method=%d, device=%s, line=%d, gpio=%d, lpt_bit=%d, invert=%d\n",
dw_printf ("ch=%d, %s method=%d, device=%s, line=%d, name=%s, gpio=%d, lpt_bit=%d, invert=%d\n",
ch,
otnames[ot],
audio_config_p->achan[ch].octrl[ot].ptt_method,
audio_config_p->achan[ch].octrl[ot].ptt_device,
audio_config_p->achan[ch].octrl[ot].ptt_line,
audio_config_p->achan[ch].octrl[ot].out_gpio_name,
audio_config_p->achan[ch].octrl[ot].out_gpio_num,
audio_config_p->achan[ch].octrl[ot].ptt_lpt_bit,
audio_config_p->achan[ch].octrl[ot].ptt_invert);
Expand Down Expand Up @@ -869,7 +900,28 @@ void ptt_init (struct audio_s *audio_config_p)
if (using_gpio) {
get_access_to_gpio ("/sys/class/gpio/export");
}

#if defined(USE_GPIOD)
// GPIOD
for (ch = 0; ch < MAX_CHANS; ch++) {
if (save_audio_config_p->achan[ch].medium == MEDIUM_RADIO) {
for (int ot = 0; ot < NUM_OCTYPES; ot++) {
if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIOD) {
const char *chip_name = audio_config_p->achan[ch].octrl[ot].out_gpio_name;
int line_number = audio_config_p->achan[ch].octrl[ot].out_gpio_num;
int rc = gpiod_probe(chip_name, line_number);
if (rc < 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Disable PTT for channel %d\n", ch);
audio_config_p->achan[ch].octrl[ot].ptt_method = PTT_METHOD_NONE;
} else {
// Set initial state off ptt_set will invert output signal if appropriate.
ptt_set (ot, ch, 0);
}
}
}
}
}
#endif /* USE_GPIOD */
/*
* We should now be able to create the device nodes for
* the pins we want to use.
Expand Down Expand Up @@ -1226,6 +1278,18 @@ void ptt_set (int ot, int chan, int ptt_signal)
close (fd);

}

#if defined(USE_GPIOD)
if (save_audio_config_p->achan[chan].octrl[ot].ptt_method == PTT_METHOD_GPIOD) {
const char *chip = save_audio_config_p->achan[chan].octrl[ot].out_gpio_name;
int line = save_audio_config_p->achan[chan].octrl[ot].out_gpio_num;
int rc = gpiod_ctxless_set_value(chip, line, ptt, false, "direwolf", NULL, NULL);
if (ptt_debug_level >= 1) {
text_color_set(DW_COLOR_DEBUG);
dw_printf("PTT_METHOD_GPIOD chip: %s line: %d ptt: %d rc: %d\n", chip, line, ptt, rc);
}
}
#endif /* USE_GPIOD */
#endif

/*
Expand Down