Compare commits

...

22 Commits

Author SHA1 Message Date
Erwin Ried 4f9e8e9642 Update README.md 2023-01-25 15:34:09 +01:00
Erwin Ried de53626a46 Update README.md 2023-01-25 15:33:00 +01:00
Erwin Ried 2cf6849985 Update README.md 2023-01-25 15:16:03 +01:00
Erwin Ried 1cde3ab189 Update README.md 2023-01-25 15:12:21 +01:00
Erwin Ried bdb70a3231 Update README.md 2023-01-25 15:04:43 +01:00
Erwin Ried 49e63e2728 Update README.md 2023-01-25 14:36:18 +01:00
Erwin Ried 1beca57e56 Update README.md 2023-01-25 14:33:27 +01:00
Erwin Ried 27632825a3 Update contributors list 2023-01-25 14:14:12 +01:00
gullradriel e02e58b366 Merge pull request #789 from formtapez/settings
Save and recall all receiver settings of the Audio RX app
2023-01-21 13:04:52 +01:00
formtapez 37912df085 tabs vs spaces 2023-01-21 11:46:43 +01:00
formtapez a20a08c630 save/recall all receiver settings 2023-01-21 11:36:06 +01:00
formtapez a8885282cd save and recall stepsize 2023-01-20 22:21:59 +01:00
gullradriel 2d9090862b Merge pull request #782 from Brumi-2021/adding_Vertical_rate_field_ADSB_TX
Added Vertical rate field ADSB-TX
2023-01-05 09:59:00 +01:00
Brumi-2021 6e5bb7911c Added Vertical rate field ADSB-TX 2023-01-05 00:14:11 +01:00
Brumi-2021 46f98ddc8b Merge pull request #780 from Brumi-2021/Correcting_complementary_Bearing_Compas_Hdg_angle_ADSB-TX_App_final
Solving correct  Bearing Angle in ADSB TX app
2023-01-01 23:15:52 +01:00
Brumi-2021 2902365b80 Solving correct Bearing Angle in ADSB TX app 2023-01-01 23:23:06 +01:00
Brumi-2021 c0f368c978 Merge pull request #775 from Brumi-2021/Small_BW_Label_error_correction_Scanner_App
Scanner BW label corrections
2022-12-29 23:23:41 +01:00
Brumi-2021 75c2b69f19 Scanner BW label corrections 2022-12-30 00:38:54 +01:00
Brumi-2021 3291c7e2a0 Merge pull request #774 from Brumi-2021/Minor_ADSB_Compas_sinf32_array_value_correction_and_comments
Minor sin_f32_table correction and comments
2022-12-29 22:24:28 +01:00
Brumi-2021 64ca9f6a68 Minor sin_f32_table correction and comments 2022-12-29 23:27:15 +01:00
gullradriel 297063873f Merge pull request #767 from rusty-labs/scanner-manual-mode-unlimited-range
#765 Scanner app, unlimited range for manual mode
2022-12-29 17:41:00 +01:00
rusty.labs 1f7b800c2a #765 unlimited range for manual mode
* fix for #765, manual mode has unlimited range now
* speedup for button_add.on_select (roughly x70 times faster)
* fix for random freezes while switching to Audio
2022-12-26 17:18:30 -05:00
13 changed files with 227 additions and 94 deletions
+15 -22
View File
@@ -6,7 +6,7 @@ This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmw
[<img src="https://raw.githubusercontent.com/wiki/eried/portapack-mayhem/img/hw_overview_h2_front.png" height="400">](https://github.com/eried/portapack-mayhem/wiki/Hardware-overview) [<img src="https://raw.githubusercontent.com/wiki/eried/portapack-mayhem/img/hw_overview_h2_inside.png" height="400">](https://github.com/eried/portapack-mayhem/wiki/Hardware-overview#portapack-internals)
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_9zbXMk) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_DmU7GQX) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
# Quick overview
@@ -18,31 +18,23 @@ If you are new to *HackRF+PortaPack+Mayhem*, there is an awesome introductory vi
This repository expands upon the previous work by many people and aims to constantly add new features, bugfixes and generate documentation to make further development easier. [Collaboration](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate) is always welcomed and appreciated.
## Does it work on H1/H2 PortaPack?
## What to buy?
Yes, both devices are the [same](https://github.com/eried/portapack-mayhem/wiki/First-steps). The one I am using to test all changes is this [PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_9zbXMk), which is a kit that includes everything you need. Sadly, the people making the H2 never made the updated schematics available, which is not ideal (and goes against the terms of the license). Most members of the community are using a clone of the [PortaPack H1+HackRF+metal case](https://s.click.aliexpress.com/e/_dS6liw4), which does not include any battery functionality, but it is a cheaper alternative.
:heavy_check_mark: A recommended one is this [PortaPack H2](https://s.click.aliexpress.com/e/_DmU7GQX) pack, that includes everything you need. Sadly, the people making the H2 never made the updated schematics available (against the terms of the license).
To support the people behind the hardware, please buy a genuine [HackRF](https://greatscottgadgets.com/hackrf/) and [PortaPack](https://store.sharebrained.com/products/portapack-for-hackrf-one-kit).
:heavy_check_mark: Another popular option is the clone of the [PortaPack H1](https://s.click.aliexpress.com/e/_Dkbqs2X).
## Where is the latest firmware?
:warning: Be cautious , *ask* the seller about compatibility with the latest releases. Look out for the description of the item, if they provide the firmware files for an older version or they have custom setup instructions, this means it might be **NOT compatible**, for example:
The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
![image](https://user-images.githubusercontent.com/1091420/214579017-9ad970b9-0917-48f6-a550-588226d3f89b.png)
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
:warning: If it looks **too different**, this might mean that they are using their own recipe, check the [different models](https://github.com/eried/portapack-mayhem/wiki/PortaPack-Versions) in our wiki. For example all the H3 and clones of that version use their own version of the firmware. They do not contribute the changes back and eventually you will be left with a device that nobody maintains:
## Is this the newest firmware for my PortaPack?
Most probably: **YES**. *If you find new features somewhere else, please [suggest](https://github.com/eried/portapack-mayhem/issues/new/choose) them*.
![image](https://user-images.githubusercontent.com/1091420/214581333-424900ee-26f8-4e96-be2f-69d8dc995ba9.png)
## Which one is actually the newest?
There is a lot of confusion of which is the latest version because no old version used any actual "version number". Additionally, since the files were distributed on facebook groups, github issue links and similar temporal sources, then there was no central location for them.
## Where is the latest version?
This fork (**Mayhem**) uses *major.minor.release* [semantic versioning](https://en.wikipedia.org/wiki/Software_versioning), so you can always compare your current version with the latest from [Releases](https://github.com/eried/portapack-mayhem/releases/latest).
## What about Havoc/GridRF/jamesshao8/jboone's?
* jboone's PortaPack: the [vanilla](https://en.wikipedia.org/wiki/Vanilla_software) experience
* Havoc: It was the most popular fork of jboone's PortaPack, currrently, it is not being maintained nor updated
* jamesshao8: He keeps his own version of the fork, while not attached as a fork to anything. Latest functions do not follow the license and are not being published with source code, so keep this in mind
* GridRF: They sell PortaPack clones with their own firmware based on a old version, which has no sourcecode available
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description. The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
## How can I collaborate
You can write [documentation](https://github.com/eried/portapack-mayhem/wiki), fix bugs and [answer issues](https://github.com/eried/portapack-mayhem/issues) or add new functionality. Please check the following [guide](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate) with details.
@@ -51,11 +43,15 @@ Consider that the hardware and firmware has been created and maintain by a [lot]
[![Contributors](https://contrib.rocks/image?repo=eried/portapack-mayhem)](https://github.com/eried/portapack-mayhem/graphs/contributors)
To support the people behind the hardware, please buy a genuine [HackRF](https://greatscottgadgets.com/hackrf/) and [PortaPack](https://store.sharebrained.com/products/portapack-for-hackrf-one-kit).
As a last option, if you want to send money directly to me for getting more boards, antennas and such:
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CBPQA4HRRPJQ6&source=url)
## What if I really want to pay for something?
## What if I really want something specific?
If what you need can be relevant in general, you can [request a feature](https://github.com/eried/portapack-mayhem/issues/new?labels=enhancement&template=feature_request.md).
You can create a bounty and invite people to your own bounty. This will incentivize coders to work on a new feature, solving a bug or even writting documentation. Start a bounty by [creating](https://github.com/eried/portapack-mayhem/issues/new/choose) or [choosing](https://github.com/eried/portapack-mayhem/issues/) an existing issue. Then, go to [Bountysource](https://www.bountysource.com/) and post a bounty using the link to that specific [issue](https://www.bountysource.com/teams/portapack-mayhem/issues).
Promote your bounty over our Discord by clicking the chat badge on [top](#portapack-mayhem).
@@ -64,6 +60,3 @@ Promote your bounty over our Discord by clicking the chat badge on [top](#portap
First, check the [documentation](https://github.com/eried/portapack-mayhem/wiki). If you find a bug or you think the problem is related to the current repository, please open an [issue](https://github.com/eried/portapack-mayhem/issues/new/choose).
You can reach the [official community](https://www.facebook.com/groups/177623356165819) in Facebook, and our Discord by clicking the chat badge on [top](#portapack-mayhem).
## What if I find incongruencies, or grammatical errors in the text?
If is on the [Wiki](https://github.com/eried/portapack-mayhem/wiki), you can modify it directly. If is on files of the repository, you can send corrections as [pull requests](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate#coding-new-stuff-or-fixing-bugs). As a last resource, open an [issue](https://github.com/eried/portapack-mayhem/issues/new/choose).
+14 -1
View File
@@ -51,6 +51,13 @@ int app_settings::load(std::string application, AppSettings* settings) {
settings->tx_amp=std::app_settings::read_long_long(file_content, "tx_amp=");
settings->tx_frequency=std::app_settings::read_long_long(file_content, "tx_frequency=");
settings->tx_gain=std::app_settings::read_long_long(file_content, "tx_gain=");
settings->step=std::app_settings::read_long_long(file_content, "step=");
settings->modulation=std::app_settings::read_long_long(file_content, "modulation=");
settings->am_config_index=std::app_settings::read_long_long(file_content, "am_config_index=");
settings->nbfm_config_index=std::app_settings::read_long_long(file_content, "nbfm_config_index=");
settings->wfm_config_index=std::app_settings::read_long_long(file_content, "wfm_config_index=");
settings->squelch=std::app_settings::read_long_long(file_content, "squelch=");
rc = SETTINGS_OK;
}
else rc = SETTINGS_UNABLE_TO_LOAD;
@@ -61,7 +68,7 @@ int app_settings::load(std::string application, AppSettings* settings) {
int app_settings::save(std::string application, AppSettings* settings) {
if (portapack::persistent_memory::save_app_settings()) {
if (portapack::persistent_memory::save_app_settings()) {
file_path = folder+"/"+application+".ini";
make_new_directory(folder);
@@ -79,6 +86,12 @@ int app_settings::save(std::string application, AppSettings* settings) {
// Save other settings from struct
settings_file.write_line("rx_frequency="+to_string_dec_uint(settings->rx_frequency));
settings_file.write_line("tx_frequency="+to_string_dec_uint(settings->tx_frequency));
settings_file.write_line("step="+to_string_dec_uint(settings->step));
settings_file.write_line("modulation="+to_string_dec_uint(settings->modulation));
settings_file.write_line("am_config_index="+to_string_dec_uint(settings->am_config_index));
settings_file.write_line("nbfm_config_index="+to_string_dec_uint(settings->nbfm_config_index));
settings_file.write_line("wfm_config_index="+to_string_dec_uint(settings->wfm_config_index));
settings_file.write_line("squelch="+to_string_dec_uint(settings->squelch));
rc = SETTINGS_OK;
}
+5
View File
@@ -59,6 +59,11 @@ public:
uint32_t tx_frequency;
uint8_t tx_gain;
uint8_t vga;
uint32_t step;
uint8_t am_config_index;
uint8_t nbfm_config_index;
uint8_t wfm_config_index;
uint8_t squelch;
};
int load(std::string application, AppSettings* settings);
+20 -10
View File
@@ -136,6 +136,7 @@ AnalogAudioView::AnalogAudioView(
field_vga.set_value(app_settings.vga);
receiver_model.set_rf_amp(app_settings.rx_amp);
field_frequency.set_value(app_settings.rx_frequency);
receiver_model.set_configuration_without_init(static_cast<ReceiverModel::Mode>(app_settings.modulation), app_settings.step, app_settings.am_config_index, app_settings.nbfm_config_index, app_settings.wfm_config_index, app_settings.squelch);
}
else field_frequency.set_value(receiver_model.tuning_frequency());
@@ -193,36 +194,45 @@ AnalogAudioView::AnalogAudioView(
audio::output::start();
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
}
size_t AnalogAudioView::get_spec_bw_index() {
return spec_bw_index;
return spec_bw_index;
}
void AnalogAudioView::set_spec_bw(size_t index, uint32_t bw) {
spec_bw_index = index;
spec_bw = bw;
spec_bw_index = index;
spec_bw = bw;
baseband::set_spectrum(bw, spec_trigger);
receiver_model.set_sampling_rate(bw);
receiver_model.set_baseband_bandwidth(bw/2);
baseband::set_spectrum(bw, spec_trigger);
receiver_model.set_sampling_rate(bw);
receiver_model.set_baseband_bandwidth(bw/2);
}
uint16_t AnalogAudioView::get_spec_trigger() {
return spec_trigger;
return spec_trigger;
}
void AnalogAudioView::set_spec_trigger(uint16_t trigger) {
spec_trigger = trigger;
spec_trigger = trigger;
baseband::set_spectrum(spec_bw, spec_trigger);
baseband::set_spectrum(spec_bw, spec_trigger);
}
AnalogAudioView::~AnalogAudioView() {
// save app settings
app_settings.rx_frequency = field_frequency.value();
app_settings.lna = receiver_model.lna();
app_settings.vga = receiver_model.vga();
app_settings.rx_amp = receiver_model.rf_amp();
app_settings.step = receiver_model.frequency_step();
app_settings.modulation = (uint8_t)receiver_model.modulation();
app_settings.am_config_index = receiver_model.am_configuration();
app_settings.nbfm_config_index = receiver_model.nbfm_configuration();
app_settings.wfm_config_index = receiver_model.wfm_configuration();
app_settings.squelch = receiver_model.squelch_level();
settings.save("rx_audio", &app_settings);
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
@@ -38,7 +38,7 @@ namespace ui
console.writeln("Brumi-2021,texasyojimbo");
console.writeln("heurist1,intoxsick,ckuethe");
console.writeln("notpike,jLynx,zigad");
console.writeln("MichalLeonBorsuk");
console.writeln("MichalLeonBorsuk,jimilinuxguy");
console.writeln("");
break;
+5 -2
View File
@@ -162,13 +162,16 @@ ADSBSpeedView::ADSBSpeedView(
add_children({
&labels_speed,
&labels_vert_rate,
&compass,
&field_angle,
&field_speed
&field_speed,
&field_vert_rate
});
field_angle.set_value(0);
field_speed.set_value(400);
field_vert_rate.set_value(0);
field_angle.on_change = [this](int32_t v) {
compass.set_value(v);
@@ -181,7 +184,7 @@ void ADSBSpeedView::collect_frames(const uint32_t ICAO_address, std::vector<ADSB
ADSBFrame temp_frame;
encode_frame_velo(temp_frame, ICAO_address, field_speed.value(),
field_angle.value(), 0); // TODO: v_rate
field_angle.value(), field_vert_rate.value()); // Added v_rate , ft/min , (+) climb , (-) descend .
frame_list.emplace_back(temp_frame);
}
+8
View File
@@ -96,6 +96,10 @@ private:
{ { 1 * 8, 6 * 16 }, "Speed: kn Bearing: *", Color::light_grey() }
};
Labels labels_vert_rate {
{ { 1 * 8, 8 * 16 }, "Vert. rate: ft/min, (+/-)", Color::light_grey() }
};
Compass compass {
{ 21 * 8, 2 * 16 }
};
@@ -107,6 +111,10 @@ private:
NumberField field_speed {
{ 8 * 8, 6 * 16 }, 3, { 0, 999 }, 5, ' '
};
NumberField field_vert_rate {
{ 11 * 8, 8 * 16 }, 5, { -4096, 4096 }, 64, ' ' // Let's limit to +/-5k aprox , Ex. max safe descent vertical rate aprox -1000 ft/min on an instrument approach. , std step is 64
};
};
class ADSBSquawkView : public OptionTabView {
+118 -44
View File
@@ -31,13 +31,23 @@ ScannerThread::ScannerThread(
std::vector<rf::Frequency> frequency_list
) : frequency_list_ { std::move(frequency_list) }
{
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ScannerThread::static_fn, this);
create_thread();
}
ScannerThread::ScannerThread(const jammer::jammer_range_t& frequency_range, size_t def_step) : frequency_range_(frequency_range), def_step_(def_step)
{
create_thread();
}
ScannerThread::~ScannerThread() {
stop();
}
void ScannerThread::create_thread()
{
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ScannerThread::static_fn, this);
}
void ScannerThread::stop() {
if( thread ) {
chThdTerminate(thread);
@@ -102,12 +112,13 @@ void ScannerThread::run() {
else
restart_scan=false; //Effectively skipping first retuning, giving system time
}
message.freq = frequency_list_[frequency_index];
message.range = frequency_index; //Inform freq (for coloring purposes also!)
EventDispatcher::send_message(message);
}
else { //NOT scanning
if (_freq_del != 0) { //There is a frequency to delete
for (uint16_t i = 0; i < frequency_list_.size(); i++) { //Search for the freq to delete
for (uint32_t i = 0; i < frequency_list_.size(); i++) { //Search for the freq to delete
if (frequency_list_[i] == _freq_del)
{ //found: Erase it
frequency_list_.erase(frequency_list_.begin() + i);
@@ -126,16 +137,58 @@ void ScannerThread::run() {
}
chThdSleepMilliseconds(50); //Needed to (eventually) stabilize the receiver into new freq
}
}else if(def_step_ > 0) // manual mode
{
RetuneMessage message { };
int64_t frequency_index = 0;
int64_t size = (frequency_range_.max - frequency_range_.min) / def_step_;
bool restart_scan = false; //Flag whenever scanning is restarting after a pause
while( !chThdShouldTerminate() ) {
if (_scanning) { //Scanning
if (_freq_lock == 0) { //normal scanning (not performing freq_lock)
if (!restart_scan) { //looping at full speed
if (_fwd) { //forward
frequency_index++;
if (frequency_index >= size)
frequency_index = 0;
} else { //reverse
if (frequency_index < 1)
frequency_index = size;
frequency_index--;
}
receiver_model.set_tuning_frequency(frequency_range_.min + frequency_index * def_step_); // Retune
}
else
restart_scan=false; //Effectively skipping first retuning, giving system time
}
message.freq = frequency_range_.min + frequency_index * def_step_;
message.range = 0; //Inform freq (for coloring purposes also!)
EventDispatcher::send_message(message);
}
else { //NOT scanning
restart_scan=true; //Flag the need for skipping a cycle when restarting scan
}
chThdSleepMilliseconds(50); //Needed to (eventually) stabilize the receiver into new freq
}
}
}
void ScannerView::handle_retune(uint32_t i) {
void ScannerView::handle_retune(int64_t freq, uint32_t freq_idx) {
current_index = freq_idx; //since it is an ongoing scan, this is a new index
current_frequency = freq;
switch (scan_thread->is_freq_lock())
{
case 0: //NO FREQ LOCK, ONGOING STANDARD SCANNING
text_cycle.set( to_string_dec_uint(i + 1,3) );
current_index = i; //since it is an ongoing scan, this is a new index
if (description_list[current_index].size() > 0) desc_cycle.set( description_list[current_index] ); //Show new description
if (frequency_list.size() > 0) {
text_cycle.set( to_string_dec_uint(freq_idx + 1,3) );
}
if (freq_idx < description_list.size() && description_list[freq_idx].size() > 0) {
desc_cycle.set( description_list[freq_idx] ); //Show new description
}
break;
case 1: //STARTING LOCK FREQ
big_display.set_style(&style_yellow);
@@ -146,7 +199,7 @@ void ScannerView::handle_retune(uint32_t i) {
default: //freq lock is checking the signal, do not update display
return;
}
big_display.set(frequency_list[current_index]); //UPDATE the big Freq after 0, 1 or MAX_FREQ_LOCK (at least, for color synching)
big_display.set(freq); //UPDATE the big Freq after 0, 1 or MAX_FREQ_LOCK (at least, for color synching)
}
void ScannerView::focus() {
@@ -154,6 +207,8 @@ void ScannerView::focus() {
}
ScannerView::~ScannerView() {
// make sure to stop the thread before shutting down the receiver
scan_thread.reset();
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
@@ -297,23 +352,15 @@ ScannerView::ScannerView(
description_list.clear();
def_step = step_mode.selected_index_value(); //Use def_step from manual selector
description_list.push_back(
"M" + to_string_short_freq(frequency_range.min) + ">"
+ to_string_short_freq(frequency_range.max) + "S"
+ to_string_short_freq(def_step).erase(0,1) //euquiq: lame kludge to reduce spacing in step freq
);
rf::Frequency frequency = frequency_range.min;
while (frequency_list.size() < FREQMAN_MAX_PER_FILE && frequency <= frequency_range.max) { //add manual range
frequency_list.push_back(frequency);
description_list.push_back(""); //If empty, will keep showing the last description
frequency+=def_step;
}
show_max();
desc_cycle.set("");
text_max.set("");
text_cycle.set("");
if ( userpause ) //If user-paused, resume
user_resume();
big_display.set_style(&style_grey); //Back to grey color
start_scan_thread(); //RESTART SCANNER THREAD
start_scan_thread(frequency_range, def_step); //RESTART SCANNER THREAD
}
};
@@ -333,35 +380,56 @@ ScannerView::ScannerView(
big_display.set_style(&style_grey); //Back to grey color
};
button_add.on_select = [this](Button&) { //frequency_list[current_index]
button_add.on_select = [this](Button&) { // current_frequency
File scanner_file;
std::string freq_file_path = "FREQMAN/" + loaded_file_name + ".TXT";
const std::string freq_file_path = "FREQMAN/" + loaded_file_name + ".TXT";
auto result = scanner_file.open(freq_file_path); //First search if freq is already in txt
if (!result.is_valid()) {
std::string frequency_to_add = "f="
+ to_string_dec_uint(frequency_list[current_index] / 1000)
+ to_string_dec_uint(frequency_list[current_index] % 1000UL, 3, '0');
char one_char[1]; //Read it char by char
std::string line; //and put read line in here
const std::string frequency_to_add = "f="
+ to_string_dec_uint(current_frequency / 1000)
+ to_string_dec_uint(current_frequency % 1000UL, 3, '0');
bool found=false;
for (size_t pointer=0; pointer < scanner_file.size();pointer++) {
constexpr size_t buffer_size = 1024;
char buffer[buffer_size];
for (size_t pointer = 0, freq_str_idx = 0; pointer < scanner_file.size(); pointer += buffer_size) {
size_t adjusted_buffer_size;
if (pointer + buffer_size >= scanner_file.size()) {
memset(buffer, 0, sizeof(buffer));
adjusted_buffer_size = scanner_file.size() - pointer;
}
else {
adjusted_buffer_size = buffer_size;
}
scanner_file.seek(pointer);
scanner_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
if (line.compare(0, frequency_to_add.size(),frequency_to_add) == 0) {
found=true;
break;
scanner_file.read(buffer, adjusted_buffer_size);
for (size_t i = 0; i < adjusted_buffer_size; ++i) {
if (buffer[i] == frequency_to_add.data()[freq_str_idx]) {
++freq_str_idx;
if (freq_str_idx >= frequency_to_add.size()) {
found = true;
break;
}
}
else {
freq_str_idx = 0;
}
line.clear(); //Ready for next textline
}
}
if (found) {
break;
}
}
if (found) {
nav_.display_modal("Error", "Frequency already exists");
big_display.set(frequency_list[current_index]); //After showing an error
big_display.set(current_frequency); //After showing an error
}
else {
scanner_file.append(freq_file_path); //Second: append if it is not there
@@ -370,7 +438,7 @@ ScannerView::ScannerView(
} else
{
nav_.display_modal("Error", "Cannot open " + loaded_file_name + ".TXT\nfor appending freq.");
big_display.set(frequency_list[current_index]); //After showing an error
big_display.set(current_frequency); //After showing an error
}
};
@@ -516,9 +584,9 @@ size_t ScannerView::change_mode(uint8_t new_mod) { //Before this, do a scan_thre
switch (new_mod) {
case NFM: //bw 16k (2) default
bw.emplace_back("8k5", 0);
bw.emplace_back("11k", 0);
bw.emplace_back("16k", 0);
bw.emplace_back("8k5 ", 0);
bw.emplace_back("11k ", 0);
bw.emplace_back("16k ", 0);
field_bw.set_options(bw);
baseband::run_image(portapack::spi_flash::image_tag_nfm_audio);
@@ -545,7 +613,7 @@ size_t ScannerView::change_mode(uint8_t new_mod) { //Before this, do a scan_thre
receiver_model.set_sampling_rate(3072000); receiver_model.set_baseband_bandwidth(1750000);
break;
case WFM:
bw.emplace_back("200k", 0);
bw.emplace_back("200k ", 0);
field_bw.set_options(bw);
baseband::run_image(portapack::spi_flash::image_tag_wfm_audio);
@@ -566,4 +634,10 @@ void ScannerView::start_scan_thread() {
scan_thread = std::make_unique<ScannerThread>(frequency_list);
}
void ScannerView::start_scan_thread(const jammer::jammer_range_t& frequency_range, size_t def_step) {
receiver_model.enable();
receiver_model.set_squelch_level(0);
scan_thread = std::make_unique<ScannerThread>(frequency_range, def_step);
}
} /* namespace ui */
+8 -2
View File
@@ -46,6 +46,7 @@ size_t const mod_step[3] = {9000, 100000, 12500 };
class ScannerThread {
public:
ScannerThread(std::vector<rf::Frequency> frequency_list);
ScannerThread(const jammer::jammer_range_t& frequency_range, size_t def_step);
~ScannerThread();
void set_scanning(const bool v);
@@ -67,6 +68,8 @@ public:
private:
std::vector<rf::Frequency> frequency_list_ { };
jammer::jammer_range_t frequency_range_ {false, 0, 0};
size_t def_step_ { 0 };
Thread* thread { nullptr };
bool _scanning { true };
@@ -75,6 +78,7 @@ private:
uint32_t _freq_del { 0 };
static msg_t static_fn(void* arg);
void run();
void create_thread();
};
class ScannerView : public View {
@@ -120,6 +124,7 @@ private:
NavigationView& nav_;
void start_scan_thread();
void start_scan_thread(const jammer::jammer_range_t& frequency_range, size_t def_step);
size_t change_mode(uint8_t mod_type);
void show_max();
void scan_pause();
@@ -129,7 +134,7 @@ private:
void on_statistics_update(const ChannelStatistics& statistics);
void on_headphone_volume_changed(int32_t v);
void handle_retune(uint32_t i);
void handle_retune(int64_t freq, uint32_t freq_idx);
jammer::jammer_range_t frequency_range { false, 0, 0 }; //perfect for manual scan task too...
int32_t squelch { 0 };
@@ -139,6 +144,7 @@ private:
freqman_db database { };
std::string loaded_file_name;
uint32_t current_index { 0 };
rf::Frequency current_frequency { 0 };
bool userpause { false };
Labels labels {
@@ -295,7 +301,7 @@ private:
Message::ID::Retune,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const RetuneMessage*>(p);
this->handle_retune(message.range);
this->handle_retune(message.freq, message.range);
}
};
+9
View File
@@ -313,3 +313,12 @@ size_t ReceiverModel::wfm_configuration() const {
void ReceiverModel::update_wfm_configuration() {
wfm_configs[wfm_config_index].apply();
}
void ReceiverModel::set_configuration_without_init(const Mode new_mode, const rf::Frequency new_frequency_step, const size_t new_am_config_index, const size_t new_nbfm_config_index, const size_t new_wfm_config_index, uint8_t new_squelch_level) {
mode_ = new_mode;
frequency_step_ = new_frequency_step;
am_config_index = new_am_config_index;
nbfm_config_index = new_nbfm_config_index;
wfm_config_index = new_wfm_config_index;
squelch_level_ = new_squelch_level;
}
+2
View File
@@ -87,6 +87,8 @@ public:
size_t wfm_configuration() const;
void set_wfm_configuration(const size_t n);
void set_configuration_without_init(const Mode new_mode, const rf::Frequency new_frequency_step, const size_t new_am_config_index, const size_t new_nbfm_config_index, const size_t new_wfm_config_index, uint8_t new_squelch_level);
private:
rf::Frequency frequency_step_ { 25000 };
bool enabled_ { false };
+17 -10
View File
@@ -307,26 +307,33 @@ adsb_pos decode_frame_pos(ADSBFrame& frame_even, ADSBFrame& frame_odd) {
void encode_frame_velo(ADSBFrame& frame, const uint32_t ICAO_address, const uint32_t speed,
const float angle, const int32_t v_rate) {
int32_t velo_ew, velo_ns, v_rate_coded;
int32_t velo_ew, velo_ns;
uint32_t velo_ew_abs, velo_ns_abs, v_rate_coded_abs;
// To get NS and EW speeds from speed and bearing, a polar to cartesian conversion is enough
velo_ew = static_cast<int32_t>(sin_f32(DEG_TO_RAD(angle) + (pi / 2)) * speed);
velo_ns = static_cast<int32_t>(sin_f32(DEG_TO_RAD(angle)) * speed);
velo_ew = static_cast<int32_t>(sin_f32(DEG_TO_RAD(angle) ) * speed); // East direction, is the projection from West -> East is directly sin(angle=Compas Bearing) , (90º is the max +1, EAST) max velo_EW
velo_ns = static_cast<int32_t>(sin_f32( (pi/2 - DEG_TO_RAD(angle) ) ) * speed); // North direction,is the projection of North = cos(angle=Compas Bearing), cos(angle)= sen(90-angle) (0º is the max +1 NORTH) max velo_NS
v_rate_coded = (v_rate / 64) + 1;
velo_ew_abs = abs(velo_ew) + 1;
velo_ns_abs = abs(velo_ns) + 1;
v_rate_coded_abs = abs(v_rate_coded);
v_rate_coded_abs = (abs(v_rate) / 64) + 1; //encoding vertical rate source. (Decoding, VR ft/min = (Decimal v_rate_value - 1)* 64)
velo_ew_abs = abs(velo_ew) + 1; // encoding Velo speed EW , when sign Direction is 0 (+): West->East, (-) 1: East->West
velo_ns_abs = abs(velo_ns) + 1; // encoding Velo speed NS , when sign Direction is 0 (+): South->North , (-) 1: North->South
make_frame_adsb(frame, ICAO_address);
frame.push_byte((TC_AIRBORNE_VELO << 3) | 1); // Subtype: 1 (subsonic)
// Airborne velocities are all transmitted with Type Code 19 ( TC=19, using 5 bits ,TC=19 [Binary: 10011]), the following 3 bits are Subt-type Code ,SC= 1,2,3,4
// SC Subtypes code 1 and 2 are used to report ground speeds of aircraft. (SC 3,4 to used to report true airspeed. SC 2,4 are for supersonic aircraft (not used in commercial airline).
frame.push_byte((TC_AIRBORNE_VELO << 3) | 1); // 1st byte , top 5 bits Type Code TC=19, and lower 3 bits (38-40 bits), SC=001 Subtype Code SC: 1 (subsonic) ,
// Message A, (ME bits from 14-35) , 22 bits = Sign ew(1 bit) + V_ew (10 bits) + Sign_ns (1 bit) + V_ns (10 bits)
// Vertical rate source bit VrSrc (ME bit 36) indicates source of the altitude measurements. GNSS altitude(0) / , barometric altitude(1).
// Vertical rate source direction,(ME bit 37) movement can be read from Svr bit , with 0 and 1 referring to climb and descent, respectively (ft/min)
// The encoded vertical rate value VR can be computed using message (ME bits 38 to 46). If the 9-bit block contains all zeros, the vertical rate information is not available.
// + Sign VrSrc (vert rate src) (1 bit)+ VrSrc (9 bits).
frame.push_byte(((velo_ew < 0 ? 1 : 0) << 2) | (velo_ew_abs >> 8));
frame.push_byte(velo_ew_abs);
frame.push_byte(((velo_ns < 0 ? 1 : 0) << 7) | (velo_ns_abs >> 3));
frame.push_byte((velo_ns_abs << 5) | ((v_rate_coded < 0 ? 1 : 0) << 3) | (v_rate_coded_abs >> 6)); // VrSrc = 0
frame.push_byte((velo_ns_abs << 5) | ((v_rate < 0 ? 1 : 0) << 3) | (v_rate_coded_abs >> 6)); // VrSrc = 0
frame.push_byte(v_rate_coded_abs << 2);
frame.push_byte(0);
+5 -2
View File
@@ -35,7 +35,10 @@ w = numpy.arange(length, dtype=numpy.float64) * (2 * numpy.pi / length)
v = numpy.sin(w)
print(v)
*/
constexpr uint16_t sine_table_f32_period = 256;
constexpr uint16_t sine_table_f32_period = 256;
// periode is 256 . means sine_table_f32[0]= sine_table_f32[0+256], sine_table_f32[1]=sine_table_f32[1+256] (those two added manualy)
// Then table has 258 values ,256:[0,..255] + [256] and [257], those two are used when we interpolate[255] with [255+1], and [256] with [256+1]
// [256] index is needed in the function sin_f32() when we are inputing very small radian values , example , sin_f32((-1e-14) in radians)
static constexpr std::array<float, sine_table_f32_period + 2> sine_table_f32{
0.00000000e+00, 2.45412285e-02, 4.90676743e-02,
@@ -123,7 +126,7 @@ static constexpr std::array<float, sine_table_f32_period + 2> sine_table_f32{
-2.42980180e-01, -2.19101240e-01, -1.95090322e-01,
-1.70961889e-01, -1.46730474e-01, -1.22410675e-01,
-9.80171403e-02, -7.35645636e-02, -4.90676743e-02,
-2.45412285e-02, 0.00000000e+00, 0.00000000e+00
-2.45412285e-02, 0.00000000e+00, 2.45412285e-02
};
inline float sin_f32(const float w) {