New Antenna length Calculator

It reads the antennas definition from a txt file:

WHIPCALC/ANTENNAS.TXT

Inside the textfile you place each antenna you own with the following sintaxis:

<antenna label> <elements length in mm, separated by a space>

For example:

ANT500 185 315 450 586 724 862

Input the required frequency, adjust the wave type (full / half / quarter, etc.) and the calculator will return the antenna length (metric and imperial) while also calculating how much you need to expand the fitting antennas you got defined on the txt.

It may return up to 8 matching antennas, which is more than enough (normally you will have 2, perhaps 3 telescopic antennas around for your portapack)

If by any chance your antennas txt got more than 8 antennas, and more than 8 matches the length of the freq / wave you want, it will only show the first 8 matching antennas and will warn you at the bottom that there are even more results (hidden).

All calculations now are rounded into the best integer, considering first decimal, so precision is double than the original antenna calculator app.
This commit is contained in:
euquiq 2020-06-27 23:59:11 -03:00
parent 85664c27f8
commit 8443008dfa
4 changed files with 138 additions and 34 deletions

View File

@ -64,22 +64,48 @@ void WhipCalcView::update_result() {
text_result_metric.set(m + "m " + cm + "." + mm + "cm");
// ANT500 elements for crude adjustment
length /= 0.14;
if (int(length) <= 4) {
auto elements = to_string_dec_int((int)length, 1);
text_result_ant500.set(elements + " " + frac_str[((int(length * 10.0) % 10) + 1) / 3] + "ANT500 elements");
} else {
text_result_ant500.set("-");
}
uint8_t ant_count = 8; //Shown antennas counter
console.write("\f"); //Equivalent to clear console and string buffer.
length *= 1000; //Get length in mm needed to extend the antenna
for (antenna_entry antenna : antenna_db) { //go thru all antennas available
if (length >= antenna.elements.front() && length <= antenna.elements.back()) //This antenna is OK
{
uint16_t element,refined_quarter=0;
for(element=0; element < antenna.elements.size();element++) {
if (length == antenna.elements[element]) //Exact element in length
{
element++; //Real element is +1 (zero based vector)
break; //Done with this ant
}
else if (length < antenna.elements[element])
{
double remain, this_element, quarter = 0;
remain = length - antenna.elements[element-1]; //mm needed from this element to reach length
this_element=antenna.elements[element] - antenna.elements[element -1]; //total mm on this element
quarter = (remain * 4) / this_element; //havoc & portack ended on this int(quarter) resolution.
if (quarter - int(quarter) > 0.5) { //rounding gave a measure closer to next quarter
refined_quarter=int(quarter) + 1;
if(refined_quarter == 4) { //rounding gave a measure closer to next element
refined_quarter = 0;
element++;
}
} else {
refined_quarter=int(quarter);
}
break; //Done with this ant
}
}
if (!ant_count) {
console.write(" and more ...");
break;
}
console.write(antenna.label + " " + to_string_dec_int(element,1) + frac_str[refined_quarter] + " elements\n");
ant_count--;
}
}
// Imperial
calclength = (speed_of_light_fps / (double)field_frequency.value()) * divider;
/* auto feet = to_string_dec_int((int)length, 3);
auto inch = to_string_dec_int(int(length * 10.0) % 12, 2);
auto inch_c = to_string_dec_int(int(length * 100.0) % 10, 1); */
auto feet = to_string_dec_int(int(calclength), 3);
calclength = get_decimals(calclength,12); //inches
auto inch = to_string_dec_int(int(calclength), 2);
@ -94,13 +120,38 @@ WhipCalcView::WhipCalcView(
add_children({
&labels,
&antennas_on_memory,
&field_frequency,
&options_type,
&text_result_metric,
&text_result_imperial,
&text_result_ant500,
&console,
&button_exit
});
File antennas_file; //LOAD /WHIPCALC/ANTENNAS.TXT from microSD
auto result = antennas_file.open("WHIPCALC/ANTENNAS.TXT");
antenna_db.clear(); //Start with fresh db
if (result.is_valid()) {
antenna_Default(); //There is no txt, store a default ant500
} else {
std::string line; //There is a txt file
char one_char[1]; //Read it char by char
for (size_t pointer=0; pointer < antennas_file.size();pointer++) {
antennas_file.seek(pointer);
antennas_file.read(one_char, 1);
if ((int)one_char[0] > 31) { //ascii space upwards
line += one_char[0]; //Add it to the textline
}
else if (one_char[0] == '\n') { //New Line
txtline_process(line); //make sense of this textline
line.clear(); //Ready for next textline
}
}
if (line.length() > 0) txtline_process(line); //Last line had no newline at end ?
if (!antenna_db.size()) antenna_Default(); //no antenna found on txt, use default
}
antennas_on_memory.set(to_string_dec_int(antenna_db.size(),2) + " antennas"); //tell user
options_type.on_change = [this](size_t, OptionsField::value_t) {
this->update_result();
@ -128,4 +179,32 @@ WhipCalcView::WhipCalcView(
update_result();
}
void ui::WhipCalcView::txtline_process(std::string& line) {
if (line.find("#") != std::string::npos) return; //Line is just a comment
size_t previous = 0;
uint16_t value = 0;
antenna_entry new_antenna;
size_t current = line.find(" ");
while (current != std::string::npos) {
if (!previous) { //first space found
new_antenna.label.assign(line,0,current); //antenna label
} else {
value = std::stoi(line.substr(previous,current - previous));
if (!value) return; //No element length? abort antenna
new_antenna.elements.push_back(value); //Store this new element
}
previous = current + 1;
current = line.find(" ",previous); //Search for next space delimiter
}
if (!previous) return; //Not even a label ? drop this antenna!
value = std::stoi(line.substr(previous,current - previous)); //Last element
if (!value) return;
new_antenna.elements.push_back(value);
antenna_db.push_back(new_antenna); //Add this antenna
}
void ui::WhipCalcView::antenna_Default() {
antenna_db.push_back({"ANT500",{ 185, 315, 450, 586, 724, 862} }); //store a default ant500
}
}

View File

@ -28,6 +28,7 @@
#include "ui_receiver.hpp"
#include "ui_navigation.hpp"
#include "string_format.hpp"
#include <vector>
namespace ui {
@ -43,50 +44,67 @@ private:
const double speed_of_light_mps = 299792458.0; // m/s
const double speed_of_light_fps = 983571087.90472; // feet/s
const std::string frac_str[4] = { "", "1/4 ", "1/2 ", "3/4 " };
const std::string frac_str[4] = { "", " 1/4", " 1/2", " 3/4" };
struct antenna_entry {
std::string label { };
std::vector <uint16_t> elements { };
};
std::vector<antenna_entry> antenna_db { };
double get_decimals(double num, int16_t mult, bool round = false);
void update_result();
uint16_t string_to_number(std::string);
void txtline_process(std::string&);
void antenna_Default();
Labels labels {
{ { 5 * 8, 1 * 16 }, "Loaded:", Color::light_grey() },
{ { 2 * 8, 2 * 16 }, "Frequency:", Color::light_grey() },
{ { 2 * 8, 3 * 16 }, "Type:", Color::light_grey() }
{ { 7 * 8, 3 * 16 }, "Wave:", Color::light_grey() },
{ { 5 * 8, 4 * 16 }, "Metric:", Color::light_grey() },
{ { 3 * 8, 5 * 16 }, "Imperial:", Color::light_grey() }
};
Text antennas_on_memory {
{ 13 * 8, 1 * 16, 2 * 16, 16 },
};
FrequencyField field_frequency {
{ 13 * 8, 2 * 16 },
};
OptionsField options_type {
{ 8 * 8, 3 * 16 },
12,
{ 13 * 8, 3 * 16 },
7,
{
{ "Full wave", 8 },
{ "Half wave", 4 },
{ "Quarter wave", 2 },
{ "3/4 wave", 6 },
{ "1/8 wave", 1 },
{ "3/8 wave", 3 },
{ "5/8 wave", 5 },
{ "7/8 wave", 7 }
{ "Full", 8 },
{ "Half", 4 },
{ "Quarter", 2 },
{ "3/4", 6 },
{ "1/8", 1 },
{ "3/8", 3 },
{ "5/8", 5 },
{ "7/8", 7 }
}
};
Text text_result_metric {
{ 3 * 8, 5 * 16, 10 * 16, 16 },
{ 13 * 8, 4 * 16, 10 * 16, 16 },
"-"
};
Text text_result_imperial {
{ 2 * 8, 6 * 16, 10 * 16, 16 },
"-"
};
Text text_result_ant500 {
{ 2 * 8, 8 * 16, 26 * 16, 16 },
{ 13 * 8, 5 * 16, 10 * 16, 16 },
"-"
};
Console console {
{ 0, 7 * 16, 240, 144 } //Allows to show up to 8 antennas
};
Button button_exit {
{ 72, 264, 96, 32 },
{ 72, 17 * 16, 96, 32 },
"Exit"
};
};

View File

@ -595,7 +595,10 @@ void Console::write(std::string message) {
pen_color = s.foreground;
escape = false;
} else {
if (c == '\n') {
if (c=='\f') { //Add FORM FEED (clear screen)
clear();
buffer.clear();
} else if (c == '\n') {
crlf();
} else if (c == '\x1B') {
escape = true;

View File

@ -0,0 +1,4 @@
#<antenna label> <elements length in mm, separated by a space>
ANT700 95 134 175 206 230 245
ANT500 185 315 450 586 724 862
CHEAPO 118 183 253 326 399 476