From 8443008dfa60fafb1000b44aff9ec2bccbfab63b Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Sat, 27 Jun 2020 23:59:11 -0300 Subject: [PATCH 1/9] 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: 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. --- firmware/application/apps/ui_whipcalc.cpp | 107 +++++++++++++++++++--- firmware/application/apps/ui_whipcalc.hpp | 56 +++++++---- firmware/common/ui_widget.cpp | 5 +- sdcard/WHIPCALC/ANTENNAS.TXT | 4 + 4 files changed, 138 insertions(+), 34 deletions(-) create mode 100644 sdcard/WHIPCALC/ANTENNAS.TXT diff --git a/firmware/application/apps/ui_whipcalc.cpp b/firmware/application/apps/ui_whipcalc.cpp index 64de95b42..4ed2100dd 100644 --- a/firmware/application/apps/ui_whipcalc.cpp +++ b/firmware/application/apps/ui_whipcalc.cpp @@ -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 +} + } diff --git a/firmware/application/apps/ui_whipcalc.hpp b/firmware/application/apps/ui_whipcalc.hpp index d9a663436..d8585925f 100644 --- a/firmware/application/apps/ui_whipcalc.hpp +++ b/firmware/application/apps/ui_whipcalc.hpp @@ -28,6 +28,7 @@ #include "ui_receiver.hpp" #include "ui_navigation.hpp" #include "string_format.hpp" +#include 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 elements { }; + }; + + std::vector 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" }; }; diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 5e2d7db87..c4c035a63 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -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; diff --git a/sdcard/WHIPCALC/ANTENNAS.TXT b/sdcard/WHIPCALC/ANTENNAS.TXT new file mode 100644 index 000000000..da821ef26 --- /dev/null +++ b/sdcard/WHIPCALC/ANTENNAS.TXT @@ -0,0 +1,4 @@ +# +ANT700 95 134 175 206 230 245 +ANT500 185 315 450 586 724 862 +CHEAPO 118 183 253 326 399 476 \ No newline at end of file From 65ab23fd3c3e0bf727bd0756eef10f3031d20753 Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 14:19:09 +0200 Subject: [PATCH 2/9] Comma as separator --- firmware/application/apps/ui_whipcalc.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/application/apps/ui_whipcalc.cpp b/firmware/application/apps/ui_whipcalc.cpp index 4ed2100dd..599f68865 100644 --- a/firmware/application/apps/ui_whipcalc.cpp +++ b/firmware/application/apps/ui_whipcalc.cpp @@ -140,7 +140,7 @@ WhipCalcView::WhipCalcView( 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 + if ((int)one_char[0] > ' ') { //ascii space upwards line += one_char[0]; //Add it to the textline } else if (one_char[0] == '\n') { //New Line @@ -181,10 +181,11 @@ WhipCalcView::WhipCalcView( void ui::WhipCalcView::txtline_process(std::string& line) { if (line.find("#") != std::string::npos) return; //Line is just a comment + char separator = ','; size_t previous = 0; uint16_t value = 0; antenna_entry new_antenna; - size_t current = line.find(" "); + size_t current = line.find(separator); while (current != std::string::npos) { if (!previous) { //first space found new_antenna.label.assign(line,0,current); //antenna label @@ -194,7 +195,7 @@ void ui::WhipCalcView::txtline_process(std::string& line) { new_antenna.elements.push_back(value); //Store this new element } previous = current + 1; - current = line.find(" ",previous); //Search for next space delimiter + current = line.find(separator,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 From 32b07d9f4d04370a1dae26abce60532c756d3719 Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 14:19:30 +0200 Subject: [PATCH 3/9] Update ANTENNAS.TXT --- sdcard/WHIPCALC/ANTENNAS.TXT | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdcard/WHIPCALC/ANTENNAS.TXT b/sdcard/WHIPCALC/ANTENNAS.TXT index da821ef26..3aa037cba 100644 --- a/sdcard/WHIPCALC/ANTENNAS.TXT +++ b/sdcard/WHIPCALC/ANTENNAS.TXT @@ -1,4 +1,4 @@ -# -ANT700 95 134 175 206 230 245 -ANT500 185 315 450 586 724 862 -CHEAPO 118 183 253 326 399 476 \ No newline at end of file +#antenna label,elements length in mm, separated by a commas +ANT700,95,134,175,206,230,245 +ANT500,185,315,450,586,724,862 +TELESCOPIC,118,183,253,326,399,476 \ No newline at end of file From a81ab669945b9e66200f3caf87014275ae9d5d29 Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 17:41:32 +0200 Subject: [PATCH 4/9] Show all antennas even if they are off range --- firmware/application/apps/ui_whipcalc.cpp | 94 ++++++++++++----------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/firmware/application/apps/ui_whipcalc.cpp b/firmware/application/apps/ui_whipcalc.cpp index 599f68865..9d9929348 100644 --- a/firmware/application/apps/ui_whipcalc.cpp +++ b/firmware/application/apps/ui_whipcalc.cpp @@ -54,62 +54,66 @@ void WhipCalcView::update_result() { // Metric length = (speed_of_light_mps / (double)field_frequency.value()) * divider; - auto m = to_string_dec_int((int)length, 2); + auto m = to_string_dec_int((int)length, 0); /* auto cm = to_string_dec_int(int(length * 100.0) % 100, 2); auto mm = to_string_dec_int(int(length * 1000.0) % 10, 1); */ calclength = get_decimals(length,100); //cm - auto cm = to_string_dec_int(int(calclength), 2); - auto mm = to_string_dec_int(int(get_decimals(calclength,10,true)), 1); + auto cm = to_string_dec_int(int(calclength), 0); + auto mm = to_string_dec_int(int(get_decimals(calclength,10,true)), 0); text_result_metric.set(m + "m " + cm + "." + mm + "cm"); - uint8_t ant_count = 8; //Shown antennas counter + uint8_t ant_count = 9; //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--; - } - } + length *= 1000; //Get length in mm needed to extend the antenna + for (antenna_entry antenna : antenna_db) + { //go thru all antennas available + 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--; // For now, just showing all. + } // Imperial calclength = (speed_of_light_fps / (double)field_frequency.value()) * divider; - auto feet = to_string_dec_int(int(calclength), 3); + auto feet = to_string_dec_int(int(calclength), 0); calclength = get_decimals(calclength,12); //inches - auto inch = to_string_dec_int(int(calclength), 2); - auto inch_c = to_string_dec_int(int(get_decimals(calclength,10,true)), 1); + auto inch = to_string_dec_int(int(calclength), 0); + auto inch_c = to_string_dec_int(int(get_decimals(calclength,10,true)), 0); text_result_imperial.set(feet + "ft " + inch + "." + inch_c + "in"); } @@ -151,7 +155,7 @@ WhipCalcView::WhipCalcView( 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 + antennas_on_memory.set(to_string_dec_int(antenna_db.size(),0) + " antennas"); //tell user options_type.on_change = [this](size_t, OptionsField::value_t) { this->update_result(); From dfa524eac0cf358f034b71938d7269a0dfc08abc Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 17:42:11 +0200 Subject: [PATCH 5/9] Slighty larger steps --- firmware/application/apps/ui_whipcalc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/apps/ui_whipcalc.cpp b/firmware/application/apps/ui_whipcalc.cpp index 9d9929348..d57dccc61 100644 --- a/firmware/application/apps/ui_whipcalc.cpp +++ b/firmware/application/apps/ui_whipcalc.cpp @@ -163,7 +163,7 @@ WhipCalcView::WhipCalcView( options_type.set_selected_index(2); // Quarter wave field_frequency.set_value(transmitter_model.tuning_frequency()); - field_frequency.set_step(500000); // 500kHz step + field_frequency.set_step(1000000); // 1MHz step field_frequency.on_change = [this](rf::Frequency) { this->update_result(); }; From d175e33990dad9e7f794b5a0be6fd4ba7b06b138 Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 20:05:31 +0200 Subject: [PATCH 6/9] Show infinite+ if freq is 0 and small tweaks --- firmware/application/apps/ui_whipcalc.cpp | 74 ++++++++++++----------- firmware/application/apps/ui_whipcalc.hpp | 26 ++++---- 2 files changed, 51 insertions(+), 49 deletions(-) diff --git a/firmware/application/apps/ui_whipcalc.cpp b/firmware/application/apps/ui_whipcalc.cpp index d57dccc61..ffc464748 100644 --- a/firmware/application/apps/ui_whipcalc.cpp +++ b/firmware/application/apps/ui_whipcalc.cpp @@ -48,25 +48,39 @@ double ui::WhipCalcView::get_decimals(double num, int16_t mult, bool round) { void WhipCalcView::update_result() { double length, calclength, divider; - + console.clear(true); divider = ((double)options_type.selected_index_value() / 8.0); - - // Metric - length = (speed_of_light_mps / (double)field_frequency.value()) * divider; - - auto m = to_string_dec_int((int)length, 0); -/* auto cm = to_string_dec_int(int(length * 100.0) % 100, 2); - auto mm = to_string_dec_int(int(length * 1000.0) % 10, 1); */ - calclength = get_decimals(length,100); //cm - auto cm = to_string_dec_int(int(calclength), 0); - auto mm = to_string_dec_int(int(get_decimals(calclength,10,true)), 0); - - text_result_metric.set(m + "m " + cm + "." + mm + "cm"); + // Antenna lengths fields + if (field_frequency.value() > 0) + { + // Metric + length = (speed_of_light_mps / (double)field_frequency.value()) * divider; + auto m = to_string_dec_int((int)length, 0); + //auto cm = to_string_dec_int(int(length * 100.0) % 100, 2); + //auto mm = to_string_dec_int(int(length * 1000.0) % 10, 1); + calclength = get_decimals(length, 100); //cm + auto cm = to_string_dec_int(int(calclength), 0); + auto mm = to_string_dec_int(int(get_decimals(calclength, 10, true)), 0); + text_result_metric.set(m + "m " + cm + "." + mm + "cm"); + + // Imperial + calclength = (speed_of_light_fps / (double)field_frequency.value()) * divider; + auto feet = to_string_dec_int(int(calclength), 0); + calclength = get_decimals(calclength, 12); //inches + auto inch = to_string_dec_int(int(calclength), 0); + auto inch_c = to_string_dec_int(int(get_decimals(calclength, 10, true)), 0); + text_result_imperial.set(feet + "ft " + inch + "." + inch_c + "in"); + } + else + { + text_result_metric.set("infinity+"); + text_result_imperial.set("infinity+"); + return; + } uint8_t ant_count = 9; //Shown antennas counter - console.write("\f"); //Equivalent to clear console and string buffer. - length *= 1000; //Get length in mm needed to extend the antenna + length *= 1000; //Get length in mm needed to extend the antenna for (antenna_entry antenna : antenna_db) { //go thru all antennas available uint16_t element, refined_quarter = 0; @@ -107,20 +121,9 @@ void WhipCalcView::update_result() { console.write(antenna.label + ": " + to_string_dec_int(element, 1) + frac_str[refined_quarter] + " elements\n"); ant_count--; // For now, just showing all. } - - // Imperial - calclength = (speed_of_light_fps / (double)field_frequency.value()) * divider; - auto feet = to_string_dec_int(int(calclength), 0); - calclength = get_decimals(calclength,12); //inches - auto inch = to_string_dec_int(int(calclength), 0); - auto inch_c = to_string_dec_int(int(get_decimals(calclength,10,true)), 0); - - text_result_imperial.set(feet + "ft " + inch + "." + inch_c + "in"); } -WhipCalcView::WhipCalcView( - NavigationView& nav -) { +WhipCalcView::WhipCalcView(NavigationView& nav) { add_children({ &labels, @@ -133,14 +136,14 @@ WhipCalcView::WhipCalcView( &button_exit }); - File antennas_file; //LOAD /WHIPCALC/ANTENNAS.TXT from microSD + File antennas_file; 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 + antenna_Default(); // default ant500 } else { - std::string line; //There is a txt file - char one_char[1]; //Read it char by char + std::string line; + char one_char[1]; for (size_t pointer=0; pointer < antennas_file.size();pointer++) { antennas_file.seek(pointer); antennas_file.read(one_char, 1); @@ -157,12 +160,11 @@ WhipCalcView::WhipCalcView( } antennas_on_memory.set(to_string_dec_int(antenna_db.size(),0) + " antennas"); //tell user + options_type.set_selected_index(2); // Quarter wave options_type.on_change = [this](size_t, OptionsField::value_t) { this->update_result(); }; - options_type.set_selected_index(2); // Quarter wave - field_frequency.set_value(transmitter_model.tuning_frequency()); field_frequency.set_step(1000000); // 1MHz step field_frequency.on_change = [this](rf::Frequency) { this->update_result(); @@ -171,8 +173,8 @@ WhipCalcView::WhipCalcView( // TODO: Provide separate modal method/scheme? auto new_view = nav.push(transmitter_model.tuning_frequency()); new_view->on_changed = [this](rf::Frequency f) { - this->update_result(); this->field_frequency.set_value(f); + this->update_result(); }; }; @@ -180,7 +182,7 @@ WhipCalcView::WhipCalcView( nav.pop(); }; - update_result(); + field_frequency.set_value(transmitter_model.tuning_frequency()); } void ui::WhipCalcView::txtline_process(std::string& line) { diff --git a/firmware/application/apps/ui_whipcalc.hpp b/firmware/application/apps/ui_whipcalc.hpp index d8585925f..9c463b7e3 100644 --- a/firmware/application/apps/ui_whipcalc.hpp +++ b/firmware/application/apps/ui_whipcalc.hpp @@ -61,23 +61,23 @@ private: void antenna_Default(); Labels labels { - { { 5 * 8, 1 * 16 }, "Loaded:", Color::light_grey() }, - { { 2 * 8, 2 * 16 }, "Frequency:", 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() } + //{ { 5 * 8, 1 * 16 }, "Loaded:", Color::light_grey() }, + { { 2 * 8, 1 * 16 }, "Frequency:", Color::light_grey() }, + { { 7 * 8, 2 * 16 }, "Wave:", Color::light_grey() }, + { { 5 * 8, 3 * 16 }, "Metric:", Color::light_grey() }, + { { 3 * 8, 4 * 16 }, "Imperial:", Color::light_grey() } }; - Text antennas_on_memory { + /*Text antennas_on_memory { { 13 * 8, 1 * 16, 2 * 16, 16 }, - }; + };*/ FrequencyField field_frequency { - { 13 * 8, 2 * 16 }, + { 13 * 8, 1 * 16 }, }; OptionsField options_type { - { 13 * 8, 3 * 16 }, + { 13 * 8, 2 * 16 }, 7, { { "Full", 8 }, @@ -92,20 +92,20 @@ private: }; Text text_result_metric { - { 13 * 8, 4 * 16, 10 * 16, 16 }, + { 13 * 8, 3 * 16, 10 * 16, 16 }, "-" }; Text text_result_imperial { - { 13 * 8, 5 * 16, 10 * 16, 16 }, + { 13 * 8, 4 * 16, 10 * 16, 16 }, "-" }; Console console { - { 0, 7 * 16, 240, 144 } //Allows to show up to 8 antennas + { 0, 6 * 16, 240, 160 } }; Button button_exit { { 72, 17 * 16, 96, 32 }, - "Exit" + "Back" }; }; From ddffc69937264be83031d7b916169d0180dab423 Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 20:06:00 +0200 Subject: [PATCH 7/9] Clear with buffer clear --- firmware/common/ui_widget.cpp | 10 +++++----- firmware/common/ui_widget.hpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index c4c035a63..01639e0c5 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -570,7 +570,10 @@ Console::Console( { } -void Console::clear() { +void Console::clear(bool clear_buffer = false) { + if(clear_buffer) + buffer.clear(); + display.fill_rectangle( screen_rect(), Color::black() @@ -595,10 +598,7 @@ void Console::write(std::string message) { pen_color = s.foreground; escape = false; } else { - if (c=='\f') { //Add FORM FEED (clear screen) - clear(); - buffer.clear(); - } else if (c == '\n') { + if (c == '\n') { crlf(); } else if (c == '\x1B') { escape = true; diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index e4b8533bf..61ffeb725 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -312,7 +312,7 @@ class Console : public Widget { public: Console(Rect parent_rect); - void clear(); + void clear(bool clear_buffer); void write(std::string message); void writeln(std::string message); From 9ee83c5dbb58cbd412ac542bc544501762630df6 Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 21:02:43 +0200 Subject: [PATCH 8/9] Update ANTENNAS.TXT --- sdcard/WHIPCALC/ANTENNAS.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdcard/WHIPCALC/ANTENNAS.TXT b/sdcard/WHIPCALC/ANTENNAS.TXT index 3aa037cba..6a509e894 100644 --- a/sdcard/WHIPCALC/ANTENNAS.TXT +++ b/sdcard/WHIPCALC/ANTENNAS.TXT @@ -1,4 +1,4 @@ #antenna label,elements length in mm, separated by a commas ANT700,95,134,175,206,230,245 ANT500,185,315,450,586,724,862 -TELESCOPIC,118,183,253,326,399,476 \ No newline at end of file +Cheap 11cm,118,183,253,326,399,476 \ No newline at end of file From 728426c5e75c94389bfdeac2373fab033ee3b020 Mon Sep 17 00:00:00 2001 From: eried <1091420+eried@users.noreply.github.com> Date: Sun, 28 Jun 2020 21:35:14 +0200 Subject: [PATCH 9/9] Just minor changes --- firmware/application/apps/ui_whipcalc.cpp | 345 +++++++++++----------- firmware/application/apps/ui_whipcalc.hpp | 134 ++++----- 2 files changed, 239 insertions(+), 240 deletions(-) diff --git a/firmware/application/apps/ui_whipcalc.cpp b/firmware/application/apps/ui_whipcalc.cpp index ffc464748..c99f21a79 100644 --- a/firmware/application/apps/ui_whipcalc.cpp +++ b/firmware/application/apps/ui_whipcalc.cpp @@ -30,188 +30,203 @@ using namespace portapack; -namespace ui { +namespace ui +{ -void WhipCalcView::focus() { - field_frequency.focus(); -} - -double ui::WhipCalcView::get_decimals(double num, int16_t mult, bool round) { - num -= int(num); //keep decimals only - num *= mult; //Shift decimals into integers - if (!round) return num; - int16_t intnum = int(num); //Round it up if necessary - num -= intnum; //Get decimal part - if (num > .5) intnum++; //Round up - return intnum; - } - -void WhipCalcView::update_result() { - double length, calclength, divider; - console.clear(true); - divider = ((double)options_type.selected_index_value() / 8.0); - - // Antenna lengths fields - if (field_frequency.value() > 0) + void WhipCalcView::focus() { - // Metric - length = (speed_of_light_mps / (double)field_frequency.value()) * divider; - auto m = to_string_dec_int((int)length, 0); - //auto cm = to_string_dec_int(int(length * 100.0) % 100, 2); - //auto mm = to_string_dec_int(int(length * 1000.0) % 10, 1); - calclength = get_decimals(length, 100); //cm - auto cm = to_string_dec_int(int(calclength), 0); - auto mm = to_string_dec_int(int(get_decimals(calclength, 10, true)), 0); - text_result_metric.set(m + "m " + cm + "." + mm + "cm"); - - // Imperial - calclength = (speed_of_light_fps / (double)field_frequency.value()) * divider; - auto feet = to_string_dec_int(int(calclength), 0); - calclength = get_decimals(calclength, 12); //inches - auto inch = to_string_dec_int(int(calclength), 0); - auto inch_c = to_string_dec_int(int(get_decimals(calclength, 10, true)), 0); - text_result_imperial.set(feet + "ft " + inch + "." + inch_c + "in"); - } - else - { - text_result_metric.set("infinity+"); - text_result_imperial.set("infinity+"); - return; + field_frequency.focus(); } - uint8_t ant_count = 9; //Shown antennas counter - length *= 1000; //Get length in mm needed to extend the antenna - for (antenna_entry antenna : antenna_db) - { //go thru all antennas available - uint16_t element, refined_quarter = 0; - for (element = 0; element < antenna.elements.size(); element++) + double ui::WhipCalcView::get_decimals(double num, int16_t mult, bool round) + { + num -= int(num); //keep decimals only + num *= mult; //Shift decimals into integers + if (!round) + return num; + int16_t intnum = int(num); //Round it up if necessary + num -= intnum; //Get decimal part + if (num > .5) + intnum++; //Round up + return intnum; + } + + void WhipCalcView::update_result() + { + double length, calclength, divider; + console.clear(true); + divider = ((double)options_type.selected_index_value() / 8.0); + + // Antenna lengths fields + if (field_frequency.value() > 0) { - 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 - } + // Metric + length = (speed_of_light_mps / (double)field_frequency.value()) * divider; + auto m = to_string_dec_int((int)length, 0); + //auto cm = to_string_dec_int(int(length * 100.0) % 100, 2); + //auto mm = to_string_dec_int(int(length * 1000.0) % 10, 1); + calclength = get_decimals(length, 100); //cm + auto cm = to_string_dec_int(int(calclength), 0); + auto mm = to_string_dec_int(int(get_decimals(calclength, 10, true)), 0); + text_result_metric.set(m + "m " + cm + "." + mm + "cm"); + + // Imperial + calclength = (speed_of_light_fps / (double)field_frequency.value()) * divider; + auto feet = to_string_dec_int(int(calclength), 0); + calclength = get_decimals(calclength, 12); //inches + auto inch = to_string_dec_int(int(calclength), 0); + auto inch_c = to_string_dec_int(int(get_decimals(calclength, 10, true)), 0); + text_result_imperial.set(feet + "ft " + inch + "." + inch_c + "in"); } - /*if (!ant_count) + else + { + text_result_metric.set("infinity+"); + text_result_imperial.set("infinity+"); + return; + } + + uint8_t ant_count = 9; //Shown antennas counter + length *= 1000; //Get length in mm needed to extend the antenna + for (antenna_entry antenna : antenna_db) + { //go thru all antennas available + 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--; // For now, just showing all. + console.write(antenna.label + ": " + to_string_dec_int(element, 1) + frac_str[refined_quarter] + " elements\n"); + ant_count--; // For now, just showing all. + } } -} -WhipCalcView::WhipCalcView(NavigationView& nav) { + WhipCalcView::WhipCalcView(NavigationView &nav) + { + add_children({&labels, + //&antennas_on_memory, + &field_frequency, + &options_type, + &text_result_metric, + &text_result_imperial, + &console, + &button_exit}); - add_children({ - &labels, - &antennas_on_memory, - &field_frequency, - &options_type, - &text_result_metric, - &text_result_imperial, - &console, - &button_exit - }); + File antennas_file; + auto error = antennas_file.open("WHIPCALC/ANTENNAS.TXT"); - File antennas_file; - auto result = antennas_file.open("WHIPCALC/ANTENNAS.TXT"); + if (!error.is_valid()) + { + std::string line; + char one_char[1]; + 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] >= ' ') + 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 (result.is_valid()) { - antenna_Default(); // default ant500 - } else { - std::string line; - char one_char[1]; - 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] > ' ') { //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(),0) + " antennas"); //tell user - - options_type.set_selected_index(2); // Quarter wave - options_type.on_change = [this](size_t, OptionsField::value_t) { - this->update_result(); - }; - - field_frequency.set_step(1000000); // 1MHz step - field_frequency.on_change = [this](rf::Frequency) { - this->update_result(); - }; - field_frequency.on_edit = [this, &nav]() { - // TODO: Provide separate modal method/scheme? - auto new_view = nav.push(transmitter_model.tuning_frequency()); - new_view->on_changed = [this](rf::Frequency f) { - this->field_frequency.set_value(f); + if (!antenna_db.size()) + add_default_antenna(); + //antennas_on_memory.set(to_string_dec_int(antenna_db.size(),0) + " antennas"); //tell user + + options_type.set_selected_index(2); // Quarter wave + options_type.on_change = [this](size_t, OptionsField::value_t) { this->update_result(); }; - }; - - button_exit.on_select = [this, &nav](Button&) { - nav.pop(); - }; - - field_frequency.set_value(transmitter_model.tuning_frequency()); -} -void ui::WhipCalcView::txtline_process(std::string& line) { - if (line.find("#") != std::string::npos) return; //Line is just a comment - char separator = ','; - size_t previous = 0; - uint16_t value = 0; - antenna_entry new_antenna; - size_t current = line.find(separator); - 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(separator,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 -} + field_frequency.set_step(1000000); // 1MHz step + field_frequency.on_change = [this](rf::Frequency) { + this->update_result(); + }; + field_frequency.on_edit = [this, &nav]() { + // TODO: Provide separate modal method/scheme? + auto new_view = nav.push(transmitter_model.tuning_frequency()); + new_view->on_changed = [this](rf::Frequency f) { + this->field_frequency.set_value(f); + this->update_result(); + }; + }; - void ui::WhipCalcView::antenna_Default() { - antenna_db.push_back({"ANT500",{ 185, 315, 450, 586, 724, 862} }); //store a default ant500 -} + button_exit.on_select = [this, &nav](Button &) { + nav.pop(); + }; -} + field_frequency.set_value(transmitter_model.tuning_frequency()); + } + + void ui::WhipCalcView::txtline_process(std::string &line) + { + if (line.find("#") != std::string::npos) + return; //Line is just a comment + + char separator = ','; + size_t previous = 0; + uint16_t value = 0; + antenna_entry new_antenna; + size_t current = line.find(separator); + + while (current != std::string::npos) + { + if (!previous) + 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(separator, 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::add_default_antenna() + { + antenna_db.push_back({"ANT500", {185, 315, 450, 586, 724, 862}}); //store a default ant500 + } +} // namespace ui diff --git a/firmware/application/apps/ui_whipcalc.hpp b/firmware/application/apps/ui_whipcalc.hpp index 9c463b7e3..7f1cefc08 100644 --- a/firmware/application/apps/ui_whipcalc.hpp +++ b/firmware/application/apps/ui_whipcalc.hpp @@ -30,85 +30,69 @@ #include "string_format.hpp" #include -namespace ui { +namespace ui +{ + class WhipCalcView : public View + { + public: + WhipCalcView(NavigationView &nav); + void focus() override; + std::string title() const override { return "Antenna length"; }; -class WhipCalcView : public View { -public: - WhipCalcView(NavigationView& nav); - - void focus() override; - - std::string title() const override { return "Antenna length"; }; + 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"}; -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" }; - - struct antenna_entry { - std::string label { }; - std::vector elements { }; - }; - - std::vector 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, 1 * 16 }, "Frequency:", Color::light_grey() }, - { { 7 * 8, 2 * 16 }, "Wave:", Color::light_grey() }, - { { 5 * 8, 3 * 16 }, "Metric:", Color::light_grey() }, - { { 3 * 8, 4 * 16 }, "Imperial:", Color::light_grey() } - }; - - /*Text antennas_on_memory { - { 13 * 8, 1 * 16, 2 * 16, 16 }, - };*/ - - FrequencyField field_frequency { - { 13 * 8, 1 * 16 }, - }; - - OptionsField options_type { - { 13 * 8, 2 * 16 }, - 7, + struct antenna_entry { - { "Full", 8 }, - { "Half", 4 }, - { "Quarter", 2 }, - { "3/4", 6 }, - { "1/8", 1 }, - { "3/8", 3 }, - { "5/8", 5 }, - { "7/8", 7 } - } + std::string label{}; + std::vector elements{}; + }; + + std::vector 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 add_default_antenna(); + + Labels labels{ + {{2 * 8, 1 * 16}, "Frequency:", Color::light_grey()}, + {{7 * 8, 2 * 16}, "Wave:", Color::light_grey()}, + {{5 * 8, 3 * 16}, "Metric:", Color::light_grey()}, + {{3 * 8, 4 * 16}, "Imperial:", Color::light_grey()}}; + + FrequencyField field_frequency{ + {13 * 8, 1 * 16}, + }; + + OptionsField options_type{ + {13 * 8, 2 * 16}, + 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{ + {13 * 8, 3 * 16, 10 * 16, 16}, + "-"}; + Text text_result_imperial{ + {13 * 8, 4 * 16, 10 * 16, 16}, + "-"}; + Console console{ + {0, 6 * 16, 240, 160}}; + + Button button_exit{ + {72, 17 * 16, 96, 32}, + "Back"}; }; - - Text text_result_metric { - { 13 * 8, 3 * 16, 10 * 16, 16 }, - "-" - }; - Text text_result_imperial { - { 13 * 8, 4 * 16, 10 * 16, 16 }, - "-" - }; - Console console { - { 0, 6 * 16, 240, 160 } - }; - - Button button_exit { - { 72, 17 * 16, 96, 32 }, - "Back" - }; -}; } /* namespace ui */ -#endif/*__UI_WHIPCALC__*/ +#endif /*__UI_WHIPCALC__*/