mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
80c769b97d
* Generate CTCSS messages at fixed rate regardless of tone freq * Generate CTCSS messages at fixed rate regardless of tone freq * Function for generating CTCSS description strings * Function for generating CTCSS description strings * Increase width of CTCSS text to include tone freq * Increase width of CTCSS text field to include frequency * Use CTCSS tone freq when saving HAM freqs to freq file * Use function in tone_key.cpp for displaying CTCSS string * Use function in tone_key.cpp for CTCSS descr strings * Use function in tone_key.cpp for CTCSS descr strings * Clang test * Clang * Clang * Support for reading CTCSS tones from FreqMan file * Clang * Clean up and eliminate floating point * Clean up and eliminate floating point * Corrected CTCSS field length * Corrected CTCSS field length * Clang
206 lines
6.4 KiB
C++
206 lines
6.4 KiB
C++
/*
|
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
|
* Copyright (C) 2017 Furrtek
|
|
*
|
|
* This file is part of PortaPack.
|
|
*
|
|
* 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, 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; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "string_format.hpp"
|
|
#include "tone_key.hpp"
|
|
|
|
namespace tonekey {
|
|
|
|
// Keep list in ascending order by tone frequency
|
|
const tone_key_t tone_keys = {
|
|
{"None", F2Ix100(0.0)},
|
|
{"1 XZ", F2Ix100(67.0)},
|
|
{"39 WZ", F2Ix100(69.3)},
|
|
{"2 XA", F2Ix100(71.9)},
|
|
{"3 WA", F2Ix100(74.4)},
|
|
{"4 XB", F2Ix100(77.0)},
|
|
{"5 WB", F2Ix100(79.7)},
|
|
{"6 YZ", F2Ix100(82.5)},
|
|
{"7 YA", F2Ix100(85.4)},
|
|
{"8 YB", F2Ix100(88.5)},
|
|
{"9 ZZ", F2Ix100(91.5)},
|
|
{"10 ZA", F2Ix100(94.8)},
|
|
{"11 ZB", F2Ix100(97.4)},
|
|
{"12 1Z", F2Ix100(100.0)},
|
|
{"13 1A", F2Ix100(103.5)},
|
|
{"14 1B", F2Ix100(107.2)},
|
|
{"15 2Z", F2Ix100(110.9)},
|
|
{"16 2A", F2Ix100(114.8)},
|
|
{"17 2B", F2Ix100(118.8)},
|
|
{"18 3Z", F2Ix100(123.0)},
|
|
{"19 3A", F2Ix100(127.3)},
|
|
{"20 3B", F2Ix100(131.8)},
|
|
{"21 4Z", F2Ix100(136.5)},
|
|
{"22 4A", F2Ix100(141.3)},
|
|
{"23 4B", F2Ix100(146.2)},
|
|
{"24 5Z", F2Ix100(151.4)},
|
|
{"25 5A", F2Ix100(156.7)},
|
|
{"40 --", F2Ix100(159.8)},
|
|
{"26 5B", F2Ix100(162.2)},
|
|
{"41 --", F2Ix100(165.5)},
|
|
{"27 6Z", F2Ix100(167.9)},
|
|
{"42 --", F2Ix100(171.3)},
|
|
{"28 6A", F2Ix100(173.8)},
|
|
{"43 --", F2Ix100(177.3)},
|
|
{"29 6B", F2Ix100(179.9)},
|
|
{"44 --", F2Ix100(183.5)},
|
|
{"30 7Z", F2Ix100(186.2)},
|
|
{"45 --", F2Ix100(189.9)},
|
|
{"31 7A", F2Ix100(192.8)},
|
|
{"46 --", F2Ix100(196.6)},
|
|
{"47 --", F2Ix100(199.5)},
|
|
{"32 M1", F2Ix100(203.5)},
|
|
{"48 8Z", F2Ix100(206.5)},
|
|
{"33 M2", F2Ix100(210.7)},
|
|
{"34 M3", F2Ix100(218.1)},
|
|
{"35 M4", F2Ix100(225.7)},
|
|
{"49 9Z", F2Ix100(229.1)},
|
|
{"36 M5", F2Ix100(233.6)},
|
|
{"37 M6", F2Ix100(241.8)},
|
|
{"38 M7", F2Ix100(250.3)},
|
|
{"50 0Z", F2Ix100(254.1)},
|
|
{"Shure 19kHz", F2Ix100(19000.0)},
|
|
{"Axient 28kHz", F2Ix100(28000.0)},
|
|
{"Senn. 32.000k", F2Ix100(32000.0)},
|
|
{"Sony 32.382k", F2Ix100(32382.0)},
|
|
{"Senn. 32.768k", F2Ix100(32768.0)}};
|
|
|
|
std::string fx100_string(uint32_t f) {
|
|
return to_string_dec_uint(f / 100) + "." + to_string_dec_uint((f / 10) % 10);
|
|
}
|
|
|
|
void tone_keys_populate(OptionsField& field) {
|
|
using option_t = std::pair<std::string, int32_t>;
|
|
using options_t = std::vector<option_t>;
|
|
options_t tone_key_options;
|
|
std::string tone_name;
|
|
|
|
for (size_t c = 0; c < tone_keys.size(); c++) {
|
|
auto f = tone_keys[c].second;
|
|
if ((c != 0) && (f < 1000 * 100))
|
|
tone_name = "CTCSS " + fx100_string(f) + " #" + tone_keys[c].first;
|
|
else
|
|
tone_name = tone_keys[c].first;
|
|
|
|
tone_key_options.emplace_back(tone_name, c);
|
|
}
|
|
|
|
field.set_options(tone_key_options);
|
|
}
|
|
|
|
float tone_key_frequency(tone_index index) {
|
|
return float(tone_keys[index].second) / 100.0;
|
|
}
|
|
|
|
std::string tone_key_string(tone_index index) {
|
|
if (index < 0 || (unsigned)index >= tone_keys.size())
|
|
return std::string("");
|
|
return tone_keys[index].first;
|
|
}
|
|
|
|
// Return string showing frequency only from specific table index
|
|
std::string tone_key_value_string(tone_index index) {
|
|
if (index < 0 || (unsigned)index >= tone_keys.size())
|
|
return std::string("");
|
|
return fx100_string(tone_keys[index].second);
|
|
}
|
|
|
|
// Return variable-length string showing CTCSS tone from tone frequency
|
|
// Value is in 0.01 Hz units
|
|
std::string tone_key_string_by_value(uint32_t value, size_t max_length) {
|
|
static uint8_t tone_display_toggle{0};
|
|
static uint32_t last_value;
|
|
tone_index idx;
|
|
std::string freq_str;
|
|
|
|
// If >10Hz difference between consecutive samples, it's probably noise, so ignore
|
|
if (abs(value - last_value) > 10 * 100) {
|
|
last_value = value;
|
|
tone_display_toggle = 0;
|
|
return " ";
|
|
}
|
|
last_value = value;
|
|
|
|
// Only display 1/10 Hz accuracy if <1000 Hz; max 5 characters
|
|
if (value < 1000 * 100)
|
|
freq_str = "T:" + fx100_string(value);
|
|
else
|
|
freq_str = "T:" + to_string_dec_uint(value / 100);
|
|
|
|
// Check field length is enough for character counts in the string below
|
|
if (max_length >= 7 + 2 + 5) {
|
|
idx = tone_key_index_by_value(value);
|
|
if (idx != -1)
|
|
return freq_str + " #" + tone_key_string(idx);
|
|
} else {
|
|
// Not enough space; toggle between display of tone received and tone code #
|
|
if (tone_display_toggle++ >= TONE_DISPLAY_TOGGLE_COUNTER) {
|
|
if (tone_display_toggle >= TONE_DISPLAY_TOGGLE_COUNTER * 2) tone_display_toggle = 0;
|
|
|
|
// Look for a match in the table (otherwise just display frequency)
|
|
idx = tone_key_index_by_value(value);
|
|
if (idx != -1)
|
|
return "T:" + tone_key_string(idx);
|
|
}
|
|
}
|
|
return freq_str;
|
|
}
|
|
|
|
// Search tone_key table for tone frequency value
|
|
// Value is in 0.01 Hz units
|
|
tone_index tone_key_index_by_value(uint32_t value) {
|
|
uint32_t diff;
|
|
uint32_t min_diff{value * 2};
|
|
tone_index min_idx{-1};
|
|
tone_index idx;
|
|
|
|
// Find nearest match
|
|
for (idx = 0; idx < (tone_index)tone_keys.size(); idx++) {
|
|
diff = abs(value - tone_keys[idx].second);
|
|
if (diff < min_diff) {
|
|
min_idx = idx;
|
|
min_diff = diff;
|
|
} else {
|
|
// list is sorted in frequency order; if diff is getting larger than we've passed it
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Arbitrary confidence threshold
|
|
if (min_diff < TONE_FREQ_TOLERANCE_CENTIHZ)
|
|
return min_idx;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
tone_index tone_key_index_by_string(char* str) {
|
|
if (!str)
|
|
return -1;
|
|
for (tone_index index = 0; (unsigned)index < tone_keys.size(); index++) {
|
|
if (tone_keys[index].first.compare(str) >= 0)
|
|
return index;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
} // namespace tonekey
|