mirror of
https://github.com/RFnexus/modem73.git
synced 2026-04-27 14:30:33 +00:00
Add option for TX blanking to suppress decoder when transmitting for half-duplex audio
This commit is contained in:
parent
e992322eb2
commit
be38e04153
3 changed files with 64 additions and 2 deletions
41
kiss_tnc.cc
41
kiss_tnc.cc
|
|
@ -252,6 +252,7 @@ public:
|
|||
}
|
||||
|
||||
std::cerr << "Fragmentation: " << (config_.fragmentation_enabled ? "enabled" : "disabled") << std::endl;
|
||||
std::cerr << "TX Blanking: " << (config_.tx_blanking_enabled ? "enabled" : "disabled") << std::endl;
|
||||
|
||||
// Show PTT status
|
||||
switch (config_.ptt_type) {
|
||||
|
|
@ -533,6 +534,10 @@ private:
|
|||
std::cerr << packet_visualize(data.data(), data.size(), true, config_.fragmentation_enabled) << std::endl;
|
||||
}
|
||||
|
||||
if (config_.tx_blanking_enabled) {
|
||||
tx_blanking_active_ = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_UI
|
||||
if (g_ui_state) {
|
||||
g_ui_state->transmitting = true;
|
||||
|
|
@ -554,6 +559,7 @@ private:
|
|||
|
||||
if (samples.empty()) {
|
||||
ui_log("TX: Encoding failed");
|
||||
tx_blanking_active_ = false;
|
||||
#ifdef WITH_UI
|
||||
if (g_ui_state) g_ui_state->transmitting = false;
|
||||
#endif
|
||||
|
|
@ -653,6 +659,8 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
tx_blanking_active_ = false;
|
||||
|
||||
#ifdef WITH_UI
|
||||
if (g_ui_state) {
|
||||
g_ui_state->transmitting = false;
|
||||
|
|
@ -748,10 +756,22 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
bool was_blanking = false;
|
||||
|
||||
while (rx_running_ && g_running) {
|
||||
int n = audio_->read(buffer.data(), buffer.size());
|
||||
if (n > 0) {
|
||||
decoder_->process(buffer.data(), n, frame_callback);
|
||||
bool blanking = tx_blanking_active_.load();
|
||||
|
||||
if (blanking) {
|
||||
was_blanking = true;
|
||||
} else {
|
||||
if (was_blanking) {
|
||||
decoder_->reset();
|
||||
was_blanking = false;
|
||||
}
|
||||
decoder_->process(buffer.data(), n, frame_callback);
|
||||
}
|
||||
|
||||
#ifdef WITH_UI
|
||||
if (g_ui_state && ++level_update_counter >= LEVEL_UPDATE_INTERVAL) {
|
||||
|
|
@ -859,6 +879,9 @@ private:
|
|||
std::chrono::steady_clock::time_point tx_lockout_until_;
|
||||
static constexpr float RX_LOCKOUT_SECONDS = 0.5f;
|
||||
|
||||
// TX blanking
|
||||
std::atomic<bool> tx_blanking_active_{false};
|
||||
|
||||
public:
|
||||
// Update config at runtime (called from UI)
|
||||
void update_config(const TNCConfig& new_config) {
|
||||
|
|
@ -867,6 +890,10 @@ public:
|
|||
config_.carrier_threshold_db = new_config.carrier_threshold_db;
|
||||
config_.p_persistence = new_config.p_persistence;
|
||||
config_.slot_time_ms = new_config.slot_time_ms;
|
||||
|
||||
|
||||
// TX blanking
|
||||
config_.tx_blanking_enabled = new_config.tx_blanking_enabled;
|
||||
|
||||
// Update callsign if changed
|
||||
if (config_.callsign != new_config.callsign) {
|
||||
|
|
@ -988,6 +1015,9 @@ void print_help(const char* prog) {
|
|||
<< "\nFragmentation:\n"
|
||||
<< " --frag Enable packet fragmentation/reassembly\n"
|
||||
<< " --no-frag Disable fragmentation (default)\n"
|
||||
<< "\nTX Blanking:\n"
|
||||
<< " --tx-blank Suppress decoder during TX\n"
|
||||
<< " --no-tx-blank Disable TX blanking (default)\n"
|
||||
<< "\n"
|
||||
#ifdef WITH_UI
|
||||
<< " -h, --headless Run without TUI\n"
|
||||
|
|
@ -1113,6 +1143,10 @@ int main(int argc, char** argv) {
|
|||
config.fragmentation_enabled = true;
|
||||
} else if (arg == "--no-frag") {
|
||||
config.fragmentation_enabled = false;
|
||||
} else if (arg == "--tx-blank") {
|
||||
config.tx_blanking_enabled = true;
|
||||
} else if (arg == "--no-tx-blank") {
|
||||
config.tx_blanking_enabled = false;
|
||||
} else {
|
||||
std::cerr << "Unknown option: " << arg << std::endl;
|
||||
print_help(argv[0]);
|
||||
|
|
@ -1171,6 +1205,7 @@ int main(int argc, char** argv) {
|
|||
config.slot_time_ms = ui_state.slot_time_ms;
|
||||
config.p_persistence = ui_state.p_persistence;
|
||||
config.fragmentation_enabled = ui_state.fragmentation_enabled;
|
||||
config.tx_blanking_enabled = ui_state.tx_blanking_enabled;
|
||||
// Audio devices
|
||||
config.audio_input_device = ui_state.audio_input_device;
|
||||
config.audio_output_device = ui_state.audio_output_device;
|
||||
|
|
@ -1215,6 +1250,7 @@ int main(int argc, char** argv) {
|
|||
ui_state.p_persistence = config.p_persistence;
|
||||
ui_state.short_frame = config.short_frame;
|
||||
ui_state.fragmentation_enabled = config.fragmentation_enabled;
|
||||
ui_state.tx_blanking_enabled = config.tx_blanking_enabled;
|
||||
// Audio devices
|
||||
ui_state.audio_input_device = config.audio_input_device;
|
||||
ui_state.audio_output_device = config.audio_output_device;
|
||||
|
|
@ -1268,6 +1304,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
// Sync fragmentation setting from command line to UI
|
||||
ui_state.fragmentation_enabled = config.fragmentation_enabled;
|
||||
ui_state.tx_blanking_enabled = config.tx_blanking_enabled;
|
||||
|
||||
ui_state.update_modem_info();
|
||||
|
||||
|
|
@ -1329,7 +1366,7 @@ int main(int argc, char** argv) {
|
|||
new_config.p_persistence = state.p_persistence;
|
||||
new_config.slot_time_ms = state.slot_time_ms;
|
||||
new_config.fragmentation_enabled = state.fragmentation_enabled;
|
||||
// Audio devices
|
||||
new_config.tx_blanking_enabled = state.tx_blanking_enabled;
|
||||
new_config.audio_input_device = state.audio_input_device;
|
||||
new_config.audio_output_device = state.audio_output_device;
|
||||
// PTT settings
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ struct TNCConfig {
|
|||
// Fragmentation settings
|
||||
bool fragmentation_enabled = false;
|
||||
|
||||
// TX blanking
|
||||
bool tx_blanking_enabled = false;
|
||||
|
||||
// Settings file path
|
||||
std::string config_file = "";
|
||||
};
|
||||
|
|
|
|||
22
tnc_ui.hh
22
tnc_ui.hh
|
|
@ -102,6 +102,7 @@ struct TNCUIState {
|
|||
float airtime_seconds = 0.0f;
|
||||
int random_data_size = 0;
|
||||
bool fragmentation_enabled = false;
|
||||
bool tx_blanking_enabled = false;
|
||||
|
||||
// stats
|
||||
std::atomic<float> total_tx_time{0.0f};
|
||||
|
|
@ -415,6 +416,7 @@ struct TNCUIState {
|
|||
fprintf(f, "slot_time_ms=%d\n", slot_time_ms);
|
||||
fprintf(f, "p_persistence=%d\n", p_persistence);
|
||||
fprintf(f, "fragmentation_enabled=%d\n", fragmentation_enabled ? 1 : 0);
|
||||
fprintf(f, "tx_blanking_enabled=%d\n", tx_blanking_enabled ? 1 : 0);
|
||||
fprintf(f, "# Audio/PTT\n");
|
||||
fprintf(f, "audio_input=%s\n", audio_input_device.c_str());
|
||||
fprintf(f, "audio_output=%s\n", audio_output_device.c_str());
|
||||
|
|
@ -463,6 +465,7 @@ struct TNCUIState {
|
|||
else if (strcmp(key, "slot_time_ms") == 0) slot_time_ms = atoi(value);
|
||||
else if (strcmp(key, "p_persistence") == 0) p_persistence = atoi(value);
|
||||
else if (strcmp(key, "fragmentation_enabled") == 0) fragmentation_enabled = atoi(value) != 0;
|
||||
else if (strcmp(key, "tx_blanking_enabled") == 0) tx_blanking_enabled = atoi(value) != 0;
|
||||
else if (strcmp(key, "audio_input") == 0) audio_input_device = value;
|
||||
else if (strcmp(key, "audio_output") == 0) audio_output_device = value;
|
||||
else if (strcmp(key, "audio_device") == 0) {
|
||||
|
|
@ -740,6 +743,7 @@ private:
|
|||
FIELD_THRESHOLD,
|
||||
FIELD_PERSISTENCE,
|
||||
FIELD_FRAGMENTATION,
|
||||
FIELD_TX_BLANKING,
|
||||
FIELD_AUDIO_INPUT,
|
||||
FIELD_AUDIO_OUTPUT,
|
||||
FIELD_PTT_TYPE,
|
||||
|
|
@ -1241,6 +1245,11 @@ private:
|
|||
state_.update_modem_info(); // Update random_data_size limits
|
||||
state_.add_log("(!) Fragmentation changed, restart required");
|
||||
break;
|
||||
case FIELD_TX_BLANKING:
|
||||
state_.tx_blanking_enabled = !state_.tx_blanking_enabled;
|
||||
apply_settings();
|
||||
state_.add_log(std::string("TX blanking ") + (state_.tx_blanking_enabled ? "enabled" : "disabled"));
|
||||
break;
|
||||
case FIELD_AUDIO_INPUT:
|
||||
break;
|
||||
case FIELD_AUDIO_OUTPUT:
|
||||
|
|
@ -2281,6 +2290,19 @@ private:
|
|||
if (dy >= 0) draw_toggle_field(dy, c1, c2, "Enabled", FIELD_FRAGMENTATION, state_.fragmentation_enabled);
|
||||
row += 2;
|
||||
|
||||
// TX Blanking section
|
||||
dy = visible_y(row);
|
||||
if (dy >= 0) {
|
||||
attron(A_DIM);
|
||||
mvaddstr(dy, c1, "TX BLANKING");
|
||||
attroff(A_DIM);
|
||||
}
|
||||
row++;
|
||||
|
||||
dy = visible_y(row);
|
||||
if (dy >= 0) draw_toggle_field(dy, c1, c2, "Enabled", FIELD_TX_BLANKING, state_.tx_blanking_enabled);
|
||||
row += 2;
|
||||
|
||||
// Audio / ptt
|
||||
|
||||
dy = visible_y(row);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue