mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-12 17:49:31 +00:00
8443008dfa
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.
211 lines
7.2 KiB
C++
211 lines
7.2 KiB
C++
/*
|
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
|
* Copyright (C) 2016 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 "ui_whipcalc.hpp"
|
|
|
|
#include "ch.h"
|
|
#include "portapack.hpp"
|
|
#include "event_m0.hpp"
|
|
|
|
#include <cstring>
|
|
|
|
using namespace portapack;
|
|
|
|
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;
|
|
|
|
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, 2);
|
|
/* 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);
|
|
|
|
text_result_metric.set(m + "m " + cm + "." + mm + "cm");
|
|
|
|
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(calclength), 3);
|
|
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);
|
|
|
|
text_result_imperial.set(feet + "ft " + inch + "." + inch_c + "in");
|
|
}
|
|
|
|
WhipCalcView::WhipCalcView(
|
|
NavigationView& nav
|
|
) {
|
|
|
|
add_children({
|
|
&labels,
|
|
&antennas_on_memory,
|
|
&field_frequency,
|
|
&options_type,
|
|
&text_result_metric,
|
|
&text_result_imperial,
|
|
&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();
|
|
};
|
|
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.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<FrequencyKeypadView>(transmitter_model.tuning_frequency());
|
|
new_view->on_changed = [this](rf::Frequency f) {
|
|
this->update_result();
|
|
this->field_frequency.set_value(f);
|
|
};
|
|
};
|
|
|
|
button_exit.on_select = [this, &nav](Button&) {
|
|
nav.pop();
|
|
};
|
|
|
|
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
|
|
}
|
|
|
|
}
|