mirror of
https://github.com/RFnexus/modem73.git
synced 2026-04-27 14:30:33 +00:00
Make CM108 support conditional on hidapi availability, cleanup
This commit is contained in:
parent
13c102e7cd
commit
842f9391a4
6 changed files with 167 additions and 71 deletions
|
|
@ -1 +0,0 @@
|
||||||
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0d8c", MODE="0660", TAG+="uaccess"
|
|
||||||
34
Makefile
34
Makefile
|
|
@ -1,7 +1,7 @@
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXXFLAGS = -std=c++17 -O3 -march=native -Wall -Wextra
|
CXXFLAGS = -std=c++17 -O3 -march=native -Wall -Wextra
|
||||||
LDFLAGS = -lpthread -ltinfo -lncurses -ldl -lm -lhidapi-hidraw
|
LDFLAGS = -lpthread -ltinfo -lncurses -ldl -lm
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
AICODIX_DSP ?= ../dsp
|
AICODIX_DSP ?= ../dsp
|
||||||
|
|
@ -19,6 +19,20 @@ OBJS = miniaudio.o
|
||||||
# defualt to build with UI, headless operations through --headless
|
# defualt to build with UI, headless operations through --headless
|
||||||
UI_FLAGS = -DWITH_UI
|
UI_FLAGS = -DWITH_UI
|
||||||
|
|
||||||
|
# Optional CM108 PTT support requires libhidapi-dev
|
||||||
|
HIDAPI_CFLAGS := $(shell pkg-config --cflags hidapi-hidraw 2>/dev/null || pkg-config --cflags hidapi-libusb 2>/dev/null || pkg-config --cflags hidapi 2>/dev/null)
|
||||||
|
HIDAPI_LIBS := $(shell pkg-config --libs hidapi-hidraw 2>/dev/null || pkg-config --libs hidapi-libusb 2>/dev/null || pkg-config --libs hidapi 2>/dev/null)
|
||||||
|
|
||||||
|
ifneq ($(HIDAPI_LIBS),)
|
||||||
|
$(info CM108 PTT support: enabled (found hidapi))
|
||||||
|
CM108_FLAGS = -DWITH_CM108
|
||||||
|
CXXFLAGS += $(HIDAPI_CFLAGS)
|
||||||
|
LDFLAGS += $(HIDAPI_LIBS)
|
||||||
|
else
|
||||||
|
$(info CM108 PTT support: disabled (install libhidapi-dev to enable))
|
||||||
|
CM108_FLAGS =
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: all clean install debug help
|
.PHONY: all clean install debug help
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
@ -27,14 +41,25 @@ miniaudio.o: miniaudio.c miniaudio.h
|
||||||
$(CC) -c -O2 -o $@ miniaudio.c
|
$(CC) -c -O2 -o $@ miniaudio.c
|
||||||
|
|
||||||
$(TARGET): $(SRCS) $(HDRS) $(OBJS)
|
$(TARGET): $(SRCS) $(HDRS) $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(UI_FLAGS) $(INCLUDES) -o $@ $(SRCS) $(OBJS) $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(UI_FLAGS) $(CM108_FLAGS) $(INCLUDES) -o $@ $(SRCS) $(OBJS) $(LDFLAGS)
|
||||||
|
ifneq ($(HIDAPI_LIBS),)
|
||||||
|
@echo ""
|
||||||
|
@echo "CM108 PTT support enabled. To allow non-root access, install udev rules:"
|
||||||
|
@echo " sudo cp misc/50-cm108-ptt.rules /etc/udev/rules.d/"
|
||||||
|
@echo " sudo udevadm control --reload-rules"
|
||||||
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGET) $(OBJS)
|
rm -f $(TARGET) $(OBJS)
|
||||||
|
|
||||||
install: $(TARGET)
|
install: $(TARGET)
|
||||||
install -m 755 $(TARGET) /usr/local/bin/
|
install -m 755 $(TARGET) /usr/local/bin/
|
||||||
$(shell cp 50-cm108-ptt.rules /etc/udev/rules.d/)
|
ifneq ($(HIDAPI_LIBS),)
|
||||||
|
@if [ -f misc/50-cm108-ptt.rules ]; then \
|
||||||
|
cp misc/50-cm108-ptt.rules /etc/udev/rules.d/ 2>/dev/null || \
|
||||||
|
echo "Note: Run 'sudo cp misc/50-cm108-ptt.rules /etc/udev/rules.d/' for CM108 udev rules"; \
|
||||||
|
fi
|
||||||
|
endif
|
||||||
|
|
||||||
# Debug build
|
# Debug build
|
||||||
debug: CXXFLAGS = -std=c++17 -g -O0 -Wall -Wextra -DDEBUG
|
debug: CXXFLAGS = -std=c++17 -g -O0 -Wall -Wextra -DDEBUG
|
||||||
|
|
@ -55,6 +80,9 @@ help:
|
||||||
@echo " AICODIX_CODE - Path to aicodix/code (default: ../code)"
|
@echo " AICODIX_CODE - Path to aicodix/code (default: ../code)"
|
||||||
@echo " MODEM_SRC - Path to modem source (default: ../modem)"
|
@echo " MODEM_SRC - Path to modem source (default: ../modem)"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
@echo "Optional features:"
|
||||||
|
@echo " CM108 PTT - Requires libhidapi-dev (auto-detected)"
|
||||||
|
@echo ""
|
||||||
@echo "Example:"
|
@echo "Example:"
|
||||||
@echo " make AICODIX_DSP=~/aicodix/dsp AICODIX_CODE=~/aicodix/code"
|
@echo " make AICODIX_DSP=~/aicodix/dsp AICODIX_CODE=~/aicodix/code"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
|
||||||
15
cm108_ptt.hh
15
cm108_ptt.hh
|
|
@ -6,8 +6,9 @@
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "hidapi.h"
|
#include <hidapi/hidapi.h>
|
||||||
|
|
||||||
class CM108PTT {
|
class CM108PTT {
|
||||||
public:
|
public:
|
||||||
|
|
@ -30,8 +31,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(){
|
void close(){
|
||||||
|
if (handle_) {
|
||||||
hid_close(handle_);
|
hid_close(handle_);
|
||||||
res_ = hid_exit();
|
handle_ = nullptr;
|
||||||
|
}
|
||||||
|
hid_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_ptt(bool on){
|
void set_ptt(bool on){
|
||||||
|
|
@ -48,13 +52,14 @@ public:
|
||||||
buf[2] = 0x00;
|
buf[2] = 0x00;
|
||||||
buf[3] = 0x00;
|
buf[3] = 0x00;
|
||||||
}
|
}
|
||||||
|
buf[4] = 0x00;
|
||||||
|
|
||||||
res_ = hid_write(handle_, buf, 5);
|
res_ = hid_write(handle_, buf, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int res_;
|
int res_ = 0;
|
||||||
int gpio_; //#PTT control pin GPIOX , where X should be 1,2,3,4 - GPIO3 on most devices
|
int gpio_ = 3; // PTT control pin GPIOX, where X should be 1,2,3,4 - GPIO3 on most devices
|
||||||
const int cm108_on_[4] = {0x01, 0x02, 0x04, 0x08};
|
const int cm108_on_[4] = {0x01, 0x02, 0x04, 0x08};
|
||||||
hid_device *handle_;
|
hid_device *handle_ = nullptr;
|
||||||
};
|
};
|
||||||
69
kiss_tnc.cc
69
kiss_tnc.cc
|
|
@ -30,7 +30,9 @@
|
||||||
#include "miniaudio_audio.hh"
|
#include "miniaudio_audio.hh"
|
||||||
#include "rigctl_ptt.hh"
|
#include "rigctl_ptt.hh"
|
||||||
#include "serial_ptt.hh"
|
#include "serial_ptt.hh"
|
||||||
|
#ifdef WITH_CM108
|
||||||
#include "cm108_ptt.hh"
|
#include "cm108_ptt.hh"
|
||||||
|
#endif
|
||||||
#include "modem.hh"
|
#include "modem.hh"
|
||||||
|
|
||||||
#ifdef WITH_UI
|
#ifdef WITH_UI
|
||||||
|
|
@ -185,9 +187,11 @@ public:
|
||||||
config_.com_invert_rts)) {
|
config_.com_invert_rts)) {
|
||||||
std::cerr << "Could not open COM port: " << serial_ptt_->last_error() << std::endl;
|
std::cerr << "Could not open COM port: " << serial_ptt_->last_error() << std::endl;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_CM108
|
||||||
} else if (config_.ptt_type == PTTType::CM108) {
|
} else if (config_.ptt_type == PTTType::CM108) {
|
||||||
cm108_ptt_ = std::make_unique<CM108PTT>();
|
cm108_ptt_ = std::make_unique<CM108PTT>();
|
||||||
cm108_ptt_->open(config_.cm108_gpio);
|
cm108_ptt_->open(config_.cm108_gpio);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
dummy_ptt_ = std::make_unique<DummyPTT>();
|
dummy_ptt_ = std::make_unique<DummyPTT>();
|
||||||
dummy_ptt_->connect();
|
dummy_ptt_->connect();
|
||||||
|
|
@ -250,9 +254,11 @@ public:
|
||||||
std::cerr << "PTT: COM " << config_.com_port
|
std::cerr << "PTT: COM " << config_.com_port
|
||||||
<< " (" << PTT_LINE_OPTIONS[config_.com_ptt_line] << ")" << std::endl;
|
<< " (" << PTT_LINE_OPTIONS[config_.com_ptt_line] << ")" << std::endl;
|
||||||
break;
|
break;
|
||||||
|
#ifdef WITH_CM108
|
||||||
case PTTType::CM108:
|
case PTTType::CM108:
|
||||||
std::cerr << "PTT: CM108 (GPIO" << config_.cm108_gpio << ")";
|
std::cerr << "PTT: CM108 (GPIO" << config_.cm108_gpio << ")" << std::endl;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start threads
|
// Start threads
|
||||||
|
|
@ -592,14 +598,18 @@ private:
|
||||||
if (g_ui_state) g_ui_state->ptt_on = false;
|
if (g_ui_state) g_ui_state->ptt_on = false;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// RIGCTL, COM, CM108 or NONE mode
|
// RIGCTL, COM, or NONE mode
|
||||||
total_tx_duration += (config_.tx_delay_ms + config_.ptt_tail_ms) / 1000.0f;
|
total_tx_duration += (config_.tx_delay_ms + config_.ptt_tail_ms) / 1000.0f;
|
||||||
|
|
||||||
ui_log("TX: " + std::to_string(samples.size()) + " samples, " +
|
ui_log("TX: " + std::to_string(samples.size()) + " samples, " +
|
||||||
std::to_string(duration) + " seconds");
|
std::to_string(duration) + " seconds");
|
||||||
|
|
||||||
// PTT on (for RIGCTL, COM or CM108 mode)
|
// PTT on (for RIGCTL or COM mode)
|
||||||
if (config_.ptt_type == PTTType::RIGCTL || config_.ptt_type == PTTType::COM || config_.ptt_type == PTTType::CM108) {
|
if (config_.ptt_type == PTTType::RIGCTL || config_.ptt_type == PTTType::COM
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
|| config_.ptt_type == PTTType::CM108
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
set_ptt(true);
|
set_ptt(true);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(config_.ptt_delay_ms));
|
std::this_thread::sleep_for(std::chrono::milliseconds(config_.ptt_delay_ms));
|
||||||
}
|
}
|
||||||
|
|
@ -619,7 +629,11 @@ private:
|
||||||
audio_->drain_playback();
|
audio_->drain_playback();
|
||||||
|
|
||||||
// PTT off
|
// PTT off
|
||||||
if (config_.ptt_type == PTTType::RIGCTL || config_.ptt_type == PTTType::COM || config_.ptt_type == PTTType::CM108) {
|
if (config_.ptt_type == PTTType::RIGCTL || config_.ptt_type == PTTType::COM
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
|| config_.ptt_type == PTTType::CM108
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(config_.ptt_tail_ms));
|
std::this_thread::sleep_for(std::chrono::milliseconds(config_.ptt_tail_ms));
|
||||||
set_ptt(false);
|
set_ptt(false);
|
||||||
}
|
}
|
||||||
|
|
@ -753,8 +767,10 @@ private:
|
||||||
} else {
|
} else {
|
||||||
serial_ptt_->ptt_off();
|
serial_ptt_->ptt_off();
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_CM108
|
||||||
} else if (cm108_ptt_) {
|
} else if (cm108_ptt_) {
|
||||||
cm108_ptt_->set_ptt(on);
|
cm108_ptt_->set_ptt(on);
|
||||||
|
#endif
|
||||||
} else if (dummy_ptt_) {
|
} else if (dummy_ptt_) {
|
||||||
dummy_ptt_->set_ptt(on);
|
dummy_ptt_->set_ptt(on);
|
||||||
}
|
}
|
||||||
|
|
@ -808,7 +824,9 @@ private:
|
||||||
std::unique_ptr<MiniAudio> audio_;
|
std::unique_ptr<MiniAudio> audio_;
|
||||||
std::unique_ptr<RigctlPTT> rigctl_;
|
std::unique_ptr<RigctlPTT> rigctl_;
|
||||||
std::unique_ptr<SerialPTT> serial_ptt_;
|
std::unique_ptr<SerialPTT> serial_ptt_;
|
||||||
|
#ifdef WITH_CM108
|
||||||
std::unique_ptr<CM108PTT> cm108_ptt_;
|
std::unique_ptr<CM108PTT> cm108_ptt_;
|
||||||
|
#endif
|
||||||
std::unique_ptr<DummyPTT> dummy_ptt_;
|
std::unique_ptr<DummyPTT> dummy_ptt_;
|
||||||
|
|
||||||
int server_fd_ = -1;
|
int server_fd_ = -1;
|
||||||
|
|
@ -932,12 +950,20 @@ void print_help(const char* prog) {
|
||||||
<< " --short Use short frames\n"
|
<< " --short Use short frames\n"
|
||||||
<< " --normal Use normal frames (default)\n"
|
<< " --normal Use normal frames (default)\n"
|
||||||
<< "\nPTT options:\n"
|
<< "\nPTT options:\n"
|
||||||
<< " --ptt TYPE PTT type: none, rigctl, vox (default: rigctl)\n"
|
<< " --ptt TYPE PTT type: none, rigctl, vox, com"
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
<< ", cm108"
|
||||||
|
#endif
|
||||||
|
<< " (default: rigctl)\n"
|
||||||
<< " --rigctl HOST:PORT Rigctl address (default: localhost:4532)\n"
|
<< " --rigctl HOST:PORT Rigctl address (default: localhost:4532)\n"
|
||||||
|
<< " --com-port PORT Serial port for COM PTT (default: /dev/ttyUSB0)\n"
|
||||||
|
<< " --com-line LINE COM PTT line: dtr, rts, both (default: rts)\n"
|
||||||
<< " --vox-freq HZ VOX tone frequency (default: 1200)\n"
|
<< " --vox-freq HZ VOX tone frequency (default: 1200)\n"
|
||||||
<< " --vox-lead MS VOX lead time in ms (default: 150)\n"
|
<< " --vox-lead MS VOX lead time in ms (default: 150)\n"
|
||||||
<< " --vox-tail MS VOX tail time in ms (default: 100)\n"
|
<< " --vox-tail MS VOX tail time in ms (default: 100)\n"
|
||||||
<< " --cm108-gpio CM108 GPIO pin for PTT (default: 3)\n"
|
#ifdef WITH_CM108
|
||||||
|
<< " --cm108-gpio N CM108 GPIO pin for PTT (default: 3)\n"
|
||||||
|
#endif
|
||||||
<< " --ptt-delay MS PTT delay before TX (default: 50)\n"
|
<< " --ptt-delay MS PTT delay before TX (default: 50)\n"
|
||||||
<< " --ptt-tail MS PTT tail after TX (default: 50)\n"
|
<< " --ptt-tail MS PTT tail after TX (default: 50)\n"
|
||||||
<< "\nCSMA options:\n"
|
<< "\nCSMA options:\n"
|
||||||
|
|
@ -1017,14 +1043,32 @@ int main(int argc, char** argv) {
|
||||||
} else {
|
} else {
|
||||||
config.rigctl_host = hostport;
|
config.rigctl_host = hostport;
|
||||||
}
|
}
|
||||||
|
} else if (arg == "--com-port" && i + 1 < argc) {
|
||||||
|
config.com_port = argv[++i];
|
||||||
|
} else if (arg == "--com-line" && i + 1 < argc) {
|
||||||
|
std::string line = argv[++i];
|
||||||
|
if (line == "dtr") config.com_ptt_line = 0;
|
||||||
|
else if (line == "rts") config.com_ptt_line = 1;
|
||||||
|
else if (line == "both") config.com_ptt_line = 2;
|
||||||
|
else {
|
||||||
|
std::cerr << "Unknown COM PTT line: " << line << " (use dtr, rts, or both)\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else if (arg == "--ptt" && i + 1 < argc) {
|
} else if (arg == "--ptt" && i + 1 < argc) {
|
||||||
std::string ptt_type = argv[++i];
|
std::string ptt_type = argv[++i];
|
||||||
if (ptt_type == "none") config.ptt_type = PTTType::NONE;
|
if (ptt_type == "none") config.ptt_type = PTTType::NONE;
|
||||||
else if (ptt_type == "rigctl") config.ptt_type = PTTType::RIGCTL;
|
else if (ptt_type == "rigctl") config.ptt_type = PTTType::RIGCTL;
|
||||||
else if (ptt_type == "vox") config.ptt_type = PTTType::VOX;
|
else if (ptt_type == "vox") config.ptt_type = PTTType::VOX;
|
||||||
|
else if (ptt_type == "com") config.ptt_type = PTTType::COM;
|
||||||
|
#ifdef WITH_CM108
|
||||||
else if (ptt_type == "cm108") config.ptt_type = PTTType::CM108;
|
else if (ptt_type == "cm108") config.ptt_type = PTTType::CM108;
|
||||||
|
#endif
|
||||||
else {
|
else {
|
||||||
std::cerr << "Unknown PTT type: " << ptt_type << " (use none, rigctl, cm108 or vox)\n";
|
std::cerr << "Unknown PTT type: " << ptt_type << " (use none, rigctl, vox, com"
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
<< ", cm108"
|
||||||
|
#endif
|
||||||
|
<< ")\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (arg == "--vox-freq" && i + 1 < argc) {
|
} else if (arg == "--vox-freq" && i + 1 < argc) {
|
||||||
|
|
@ -1033,8 +1077,10 @@ int main(int argc, char** argv) {
|
||||||
config.vox_lead_ms = std::atoi(argv[++i]);
|
config.vox_lead_ms = std::atoi(argv[++i]);
|
||||||
} else if (arg == "--vox-tail" && i + 1 < argc) {
|
} else if (arg == "--vox-tail" && i + 1 < argc) {
|
||||||
config.vox_tail_ms = std::atoi(argv[++i]);
|
config.vox_tail_ms = std::atoi(argv[++i]);
|
||||||
|
#ifdef WITH_CM108
|
||||||
} else if (arg == "--cm108-gpio" && i + 1 < argc) {
|
} else if (arg == "--cm108-gpio" && i + 1 < argc) {
|
||||||
config.cm108_gpio = std::atoi(argv[++i]);
|
config.cm108_gpio = std::atoi(argv[++i]);
|
||||||
|
#endif
|
||||||
} else if (arg == "--ptt-delay" && i + 1 < argc) {
|
} else if (arg == "--ptt-delay" && i + 1 < argc) {
|
||||||
config.ptt_delay_ms = std::atoi(argv[++i]);
|
config.ptt_delay_ms = std::atoi(argv[++i]);
|
||||||
} else if (arg == "--ptt-tail" && i + 1 < argc) {
|
} else if (arg == "--ptt-tail" && i + 1 < argc) {
|
||||||
|
|
@ -1126,8 +1172,6 @@ int main(int argc, char** argv) {
|
||||||
config.com_invert_dtr = ui_state.com_invert_dtr;
|
config.com_invert_dtr = ui_state.com_invert_dtr;
|
||||||
config.com_invert_rts = ui_state.com_invert_rts;
|
config.com_invert_rts = ui_state.com_invert_rts;
|
||||||
|
|
||||||
// CM108 PTT settings
|
|
||||||
config.cm108_gpio = ui_state.cm108_gpio;
|
|
||||||
|
|
||||||
// Network settings
|
// Network settings
|
||||||
config.port = ui_state.port;
|
config.port = ui_state.port;
|
||||||
|
|
@ -1202,7 +1246,7 @@ int main(int argc, char** argv) {
|
||||||
ui_state.vox_tone_freq = config.vox_tone_freq;
|
ui_state.vox_tone_freq = config.vox_tone_freq;
|
||||||
ui_state.vox_lead_ms = config.vox_lead_ms;
|
ui_state.vox_lead_ms = config.vox_lead_ms;
|
||||||
ui_state.vox_tail_ms = config.vox_tail_ms;
|
ui_state.vox_tail_ms = config.vox_tail_ms;
|
||||||
ui_state.cm108_gpio = config.cm108_gpio;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1285,9 +1329,6 @@ int main(int argc, char** argv) {
|
||||||
new_config.com_invert_dtr = state.com_invert_dtr;
|
new_config.com_invert_dtr = state.com_invert_dtr;
|
||||||
new_config.com_invert_rts = state.com_invert_rts;
|
new_config.com_invert_rts = state.com_invert_rts;
|
||||||
|
|
||||||
//CM108 PTT setings
|
|
||||||
new_config.cm108_gpio = state.cm108_gpio;
|
|
||||||
|
|
||||||
tnc.update_config(new_config);
|
tnc.update_config(new_config);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
38
kiss_tnc.hh
38
kiss_tnc.hh
|
|
@ -37,7 +37,9 @@ enum class PTTType {
|
||||||
RIGCTL = 1,
|
RIGCTL = 1,
|
||||||
VOX = 2,
|
VOX = 2,
|
||||||
COM = 3,
|
COM = 3,
|
||||||
|
#ifdef WITH_CM108
|
||||||
CM108 = 4
|
CM108 = 4
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TNCConfig {
|
struct TNCConfig {
|
||||||
|
|
@ -75,8 +77,10 @@ struct TNCConfig {
|
||||||
bool com_invert_dtr = false;
|
bool com_invert_dtr = false;
|
||||||
bool com_invert_rts = false;
|
bool com_invert_rts = false;
|
||||||
|
|
||||||
|
#ifdef WITH_CM108
|
||||||
// CM108 PTT settings
|
// CM108 PTT settings
|
||||||
int cm108_gpio = 3;
|
int cm108_gpio = 3;
|
||||||
|
#endif
|
||||||
|
|
||||||
// PTT timing
|
// PTT timing
|
||||||
int ptt_delay_ms = 50; // Delay after PTT before TX
|
int ptt_delay_ms = 50; // Delay after PTT before TX
|
||||||
|
|
@ -254,44 +258,32 @@ inline std::string packet_visualize(const uint8_t* data, size_t len, bool is_tx,
|
||||||
uint8_t flags = data[4];
|
uint8_t flags = data[4];
|
||||||
|
|
||||||
oss << " │ FRAG HDR [5 bytes] Magic: 0xF3 │\n";
|
oss << " │ FRAG HDR [5 bytes] Magic: 0xF3 │\n";
|
||||||
oss << " │ Packet ID: " << std::setw(5) << pkt_id;
|
oss << " │ Packet ID: 0x" << std::hex << std::setfill('0') << std::setw(4) << pkt_id << std::dec;
|
||||||
oss << " Seq: " << std::setw(3) << (int)seq;
|
oss << " Seq: " << std::setw(3) << (int)seq;
|
||||||
oss << " Flags: ";
|
oss << " Flags: ";
|
||||||
|
if (flags & 0x02) oss << "FIRST ";
|
||||||
std::string flag_str;
|
if (flags & 0x01) oss << "MORE";
|
||||||
if (flags & 0x02) flag_str += "FIRST ";
|
if (!(flags & 0x03)) oss << "LAST";
|
||||||
if (flags & 0x01) flag_str += "MORE";
|
oss << std::string(20, ' ') << "│\n";
|
||||||
if (flag_str.empty()) flag_str = "LAST";
|
|
||||||
oss << std::left << std::setw(12) << flag_str << std::right << " │\n";
|
|
||||||
|
|
||||||
offset = 5;
|
offset = 5;
|
||||||
oss << " ├─────────────────────────────────────────────────────────────┤\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (offset < len) {
|
||||||
|
oss << " ├─────────────────────────────────────────────────────────────┤\n";
|
||||||
size_t payload_len = len - offset;
|
size_t payload_len = len - offset;
|
||||||
oss << " │ PAYLOAD [" << payload_len << " bytes]";
|
oss << " │ PAYLOAD [" << payload_len << " bytes]";
|
||||||
oss << std::string(49 - std::to_string(payload_len).length(), ' ') << "│\n";
|
oss << std::string(49 - std::to_string(payload_len).length(), ' ') << "│\n";
|
||||||
|
|
||||||
size_t preview_len = std::min(payload_len, (size_t)32);
|
size_t preview_len = std::min(payload_len, (size_t)24);
|
||||||
if (preview_len > 0) {
|
|
||||||
oss << " │ ";
|
oss << " │ ";
|
||||||
for (size_t i = 0; i < preview_len; i++) {
|
for (size_t i = 0; i < preview_len; i++) {
|
||||||
oss << std::hex << std::setfill('0') << std::setw(2) << (int)data[offset + i];
|
oss << std::hex << std::setfill('0') << std::setw(2) << (int)data[offset + i];
|
||||||
if (i < preview_len - 1) oss << " ";
|
if (i < preview_len - 1) oss << " ";
|
||||||
}
|
}
|
||||||
if (payload_len > 32) oss << "...";
|
if (payload_len > 24) oss << " ...";
|
||||||
size_t used = preview_len * 3 - 1 + (payload_len > 32 ? 3 : 0);
|
oss << std::dec;
|
||||||
|
size_t used = preview_len * 3 - 1 + (payload_len > 24 ? 4 : 0);
|
||||||
if (used < 57) oss << std::string(57 - used, ' ');
|
if (used < 57) oss << std::string(57 - used, ' ');
|
||||||
oss << std::dec << " │\n";
|
|
||||||
|
|
||||||
oss << " │ ";
|
|
||||||
for (size_t i = 0; i < preview_len; i++) {
|
|
||||||
char c = data[offset + i];
|
|
||||||
oss << (c >= 32 && c < 127 ? c : '.');
|
|
||||||
}
|
|
||||||
if (payload_len > 32) oss << "...";
|
|
||||||
size_t ascii_used = preview_len + (payload_len > 32 ? 3 : 0);
|
|
||||||
if (ascii_used < 57) oss << std::string(57 - ascii_used, ' ');
|
|
||||||
oss << " │\n";
|
oss << " │\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
63
tnc_ui.hh
63
tnc_ui.hh
|
|
@ -35,7 +35,10 @@ const std::vector<std::string> CODE_RATE_OPTIONS = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<std::string> PTT_TYPE_OPTIONS = {
|
const std::vector<std::string> PTT_TYPE_OPTIONS = {
|
||||||
"NONE", "RIGCTL", "VOX", "COM", "CM108"
|
"NONE", "RIGCTL", "VOX", "COM"
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
, "CM108"
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<std::string> PTT_LINE_OPTIONS = {
|
const std::vector<std::string> PTT_LINE_OPTIONS = {
|
||||||
|
|
@ -68,7 +71,7 @@ struct TNCUIState {
|
||||||
int port = 8001;
|
int port = 8001;
|
||||||
|
|
||||||
// PTT
|
// PTT
|
||||||
int ptt_type_index = 1; // 0=NONE, 1=RIGCTL, 2=VOX 3=SERIAL 4=CM108
|
int ptt_type_index = 1; // 0=NONE, 1=RIGCTL, 2=VOX
|
||||||
|
|
||||||
// Rigctl settings (PTT type 1)
|
// Rigctl settings (PTT type 1)
|
||||||
std::string rigctl_host = "localhost";
|
std::string rigctl_host = "localhost";
|
||||||
|
|
@ -87,8 +90,10 @@ struct TNCUIState {
|
||||||
bool com_invert_dtr = false;
|
bool com_invert_dtr = false;
|
||||||
bool com_invert_rts = false;
|
bool com_invert_rts = false;
|
||||||
|
|
||||||
|
#ifdef WITH_CM108
|
||||||
// CM108 PTT settings (PTT type 4)
|
// CM108 PTT settings (PTT type 4)
|
||||||
int cm108_gpio = 3; //GPIO pin to use for PTT, default 3
|
int cm108_gpio = 3; // GPIO pin to use for PTT, default 3
|
||||||
|
#endif
|
||||||
|
|
||||||
int mtu_bytes = 0;
|
int mtu_bytes = 0;
|
||||||
int bitrate_bps = 0;
|
int bitrate_bps = 0;
|
||||||
|
|
@ -370,6 +375,10 @@ struct TNCUIState {
|
||||||
fprintf(f, "com_ptt_line=%d\n", com_ptt_line);
|
fprintf(f, "com_ptt_line=%d\n", com_ptt_line);
|
||||||
fprintf(f, "com_invert_dtr=%d\n", com_invert_dtr ? 1 : 0);
|
fprintf(f, "com_invert_dtr=%d\n", com_invert_dtr ? 1 : 0);
|
||||||
fprintf(f, "com_invert_rts=%d\n", com_invert_rts ? 1 : 0);
|
fprintf(f, "com_invert_rts=%d\n", com_invert_rts ? 1 : 0);
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
fprintf(f, "# CM108 PTT\n");
|
||||||
|
fprintf(f, "cm108_gpio=%d\n", cm108_gpio);
|
||||||
|
#endif
|
||||||
fprintf(f, "# Network\n");
|
fprintf(f, "# Network\n");
|
||||||
fprintf(f, "port=%d\n", port);
|
fprintf(f, "port=%d\n", port);
|
||||||
fprintf(f, "# Utils\n");
|
fprintf(f, "# Utils\n");
|
||||||
|
|
@ -416,6 +425,9 @@ struct TNCUIState {
|
||||||
else if (strcmp(key, "com_ptt_line") == 0) com_ptt_line = atoi(value);
|
else if (strcmp(key, "com_ptt_line") == 0) com_ptt_line = atoi(value);
|
||||||
else if (strcmp(key, "com_invert_dtr") == 0) com_invert_dtr = atoi(value) != 0;
|
else if (strcmp(key, "com_invert_dtr") == 0) com_invert_dtr = atoi(value) != 0;
|
||||||
else if (strcmp(key, "com_invert_rts") == 0) com_invert_rts = atoi(value) != 0;
|
else if (strcmp(key, "com_invert_rts") == 0) com_invert_rts = atoi(value) != 0;
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
else if (strcmp(key, "cm108_gpio") == 0) cm108_gpio = atoi(value);
|
||||||
|
#endif
|
||||||
else if (strcmp(key, "port") == 0) port = atoi(value);
|
else if (strcmp(key, "port") == 0) port = atoi(value);
|
||||||
else if (strcmp(key, "random_data_size") == 0) random_data_size = atoi(value);
|
else if (strcmp(key, "random_data_size") == 0) random_data_size = atoi(value);
|
||||||
}
|
}
|
||||||
|
|
@ -685,7 +697,9 @@ private:
|
||||||
FIELD_COM_PORT,
|
FIELD_COM_PORT,
|
||||||
FIELD_COM_LINE,
|
FIELD_COM_LINE,
|
||||||
FIELD_COM_INVERT,
|
FIELD_COM_INVERT,
|
||||||
|
#ifdef WITH_CM108
|
||||||
FIELD_CM108_GPIO,
|
FIELD_CM108_GPIO,
|
||||||
|
#endif
|
||||||
FIELD_NET_PORT,
|
FIELD_NET_PORT,
|
||||||
FIELD_PRESET,
|
FIELD_PRESET,
|
||||||
FIELD_COUNT
|
FIELD_COUNT
|
||||||
|
|
@ -838,10 +852,10 @@ private:
|
||||||
|
|
||||||
edit_text_field(FIELD_COM_PORT);
|
edit_text_field(FIELD_COM_PORT);
|
||||||
|
|
||||||
|
#ifdef WITH_CM108
|
||||||
} else if (current_field_ == FIELD_CM108_GPIO) {
|
} else if (current_field_ == FIELD_CM108_GPIO) {
|
||||||
|
|
||||||
|
|
||||||
edit_text_field(FIELD_CM108_GPIO);
|
edit_text_field(FIELD_CM108_GPIO);
|
||||||
|
#endif
|
||||||
|
|
||||||
} else if (current_field_ == FIELD_AUDIO_INPUT) {
|
} else if (current_field_ == FIELD_AUDIO_INPUT) {
|
||||||
|
|
||||||
|
|
@ -1052,9 +1066,11 @@ private:
|
||||||
} else if (field == FIELD_COM_PORT) {
|
} else if (field == FIELD_COM_PORT) {
|
||||||
row = 20;
|
row = 20;
|
||||||
max_len = 20;
|
max_len = 20;
|
||||||
|
#ifdef WITH_CM108
|
||||||
} else if (field == FIELD_CM108_GPIO) {
|
} else if (field == FIELD_CM108_GPIO) {
|
||||||
row = 20;
|
row = 20;
|
||||||
max_len = 1;
|
max_len = 1;
|
||||||
|
#endif
|
||||||
} else if (field == FIELD_NET_PORT) {
|
} else if (field == FIELD_NET_PORT) {
|
||||||
if (state_.ptt_type_index == 2) { //2 extra rows
|
if (state_.ptt_type_index == 2) { //2 extra rows
|
||||||
row = 24;
|
row = 24;
|
||||||
|
|
@ -1096,6 +1112,16 @@ private:
|
||||||
state_.com_port = buf;
|
state_.com_port = buf;
|
||||||
state_.add_log("(!) COM port changed, restart required");
|
state_.add_log("(!) COM port changed, restart required");
|
||||||
apply_settings();
|
apply_settings();
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
} else if (field == FIELD_CM108_GPIO) {
|
||||||
|
try {
|
||||||
|
int gpio = std::stoi(buf);
|
||||||
|
if (gpio >= 1 && gpio <= 4) {
|
||||||
|
state_.cm108_gpio = gpio;
|
||||||
|
apply_settings();
|
||||||
|
}
|
||||||
|
} catch (...) {}
|
||||||
|
#endif
|
||||||
} else if (field == FIELD_NET_PORT) {
|
} else if (field == FIELD_NET_PORT) {
|
||||||
try {
|
try {
|
||||||
int port = std::stoi(buf);
|
int port = std::stoi(buf);
|
||||||
|
|
@ -1105,16 +1131,7 @@ private:
|
||||||
apply_settings();
|
apply_settings();
|
||||||
}
|
}
|
||||||
} catch (...) {}
|
} catch (...) {}
|
||||||
} else if (field == FIELD_CM108_GPIO) {
|
|
||||||
try {
|
|
||||||
int gpio = std::stoi(buf);
|
|
||||||
if (gpio >= 1 && gpio <= 4) {
|
|
||||||
state_.cm108_gpio = gpio;
|
|
||||||
apply_settings();
|
|
||||||
}
|
}
|
||||||
} catch (...) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodelay(stdscr, TRUE);
|
nodelay(stdscr, TRUE);
|
||||||
|
|
@ -1133,6 +1150,13 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_CM108
|
||||||
|
if (state_.ptt_type_index != 4) { // not CM108
|
||||||
|
if (field == FIELD_CM108_GPIO) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1168,7 +1192,11 @@ private:
|
||||||
case FIELD_AUDIO_OUTPUT:
|
case FIELD_AUDIO_OUTPUT:
|
||||||
break;
|
break;
|
||||||
case FIELD_PTT_TYPE:
|
case FIELD_PTT_TYPE:
|
||||||
|
#ifdef WITH_CM108
|
||||||
state_.ptt_type_index = (state_.ptt_type_index + delta + 5) % 5;
|
state_.ptt_type_index = (state_.ptt_type_index + delta + 5) % 5;
|
||||||
|
#else
|
||||||
|
state_.ptt_type_index = (state_.ptt_type_index + delta + 4) % 4;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case FIELD_VOX_FREQ:
|
case FIELD_VOX_FREQ:
|
||||||
state_.vox_tone_freq += delta * 100;
|
state_.vox_tone_freq += delta * 100;
|
||||||
|
|
@ -2041,11 +2069,13 @@ private:
|
||||||
if (field == FIELD_COM_INVERT) return row;
|
if (field == FIELD_COM_INVERT) return row;
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
// CM108 field, only when CM108 selected as ptt
|
#ifdef WITH_CM108
|
||||||
|
// CM108 field, only when CM108 selected as PTT
|
||||||
if (state_.ptt_type_index == 4) {
|
if (state_.ptt_type_index == 4) {
|
||||||
if (field == FIELD_CM108_GPIO) return row;
|
if (field == FIELD_CM108_GPIO) return row;
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
row++;
|
row++;
|
||||||
// NETWORK section
|
// NETWORK section
|
||||||
row++; // header
|
row++; // header
|
||||||
|
|
@ -2276,7 +2306,7 @@ private:
|
||||||
}
|
}
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_CM108
|
||||||
if (state_.ptt_type_index == 4) { // CM108
|
if (state_.ptt_type_index == 4) { // CM108
|
||||||
dy = visible_y(row);
|
dy = visible_y(row);
|
||||||
if (dy >= 0) {
|
if (dy >= 0) {
|
||||||
|
|
@ -2286,6 +2316,7 @@ private:
|
||||||
}
|
}
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
row++;
|
row++;
|
||||||
|
|
||||||
// Network section
|
// Network section
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue