mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-14 18:43:01 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 175e5e2e8c | |||
| 7bc27038be | |||
| 609bf3219f | |||
| bdbd616a84 |
@@ -167,6 +167,9 @@ void BLETxView::toggle() {
|
||||
}
|
||||
|
||||
void BLETxView::start() {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_btle_tx);
|
||||
transmitter_model.enable();
|
||||
|
||||
int randomChannel = channel_number;
|
||||
|
||||
if (auto_channel) {
|
||||
@@ -192,27 +195,19 @@ void BLETxView::start() {
|
||||
return;
|
||||
}
|
||||
|
||||
transmitter_model.enable();
|
||||
button_play.set_bitmap(&bitmap_stop);
|
||||
is_running = true;
|
||||
}
|
||||
|
||||
// Send next packet.
|
||||
// Setup next packet configuration.
|
||||
progressbar.set_max(packets[current_packet].packet_count);
|
||||
baseband::set_btletx(randomChannel, random_mac ? randomMac : packets[current_packet].macAddress, packets[current_packet].advertisementData, pduType);
|
||||
|
||||
is_sending = true;
|
||||
|
||||
if ((packet_counter % 10) == 0) {
|
||||
text_packets_sent.set(to_string_dec_uint(packet_counter));
|
||||
}
|
||||
|
||||
packet_counter--;
|
||||
progressbar.set_value(packets[current_packet].packet_count - packet_counter);
|
||||
}
|
||||
|
||||
void BLETxView::stop() {
|
||||
transmitter_model.disable();
|
||||
baseband::shutdown();
|
||||
|
||||
progressbar.set_value(0);
|
||||
button_play.set_bitmap(&bitmap_play);
|
||||
check_loop.set_value(false);
|
||||
@@ -222,30 +217,39 @@ void BLETxView::stop() {
|
||||
is_running = false;
|
||||
}
|
||||
|
||||
void BLETxView::reset() {
|
||||
transmitter_model.disable();
|
||||
baseband::shutdown();
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
// called each 1/60th of second, so 6 = 100ms
|
||||
void BLETxView::on_timer() {
|
||||
if (++mscounter == timer_period) {
|
||||
mscounter = 0;
|
||||
|
||||
if (is_active() && !is_sending) {
|
||||
if (is_active()) {
|
||||
// Reached end of current packet repeats.
|
||||
if (packet_counter == 0) {
|
||||
// Done sending all packets.
|
||||
if (current_packet == (num_packets - 1)) {
|
||||
current_packet = 0;
|
||||
|
||||
// If looping, restart from beginning.
|
||||
if (check_loop.value()) {
|
||||
update_current_packet(packets[current_packet], 0);
|
||||
start();
|
||||
update_current_packet(packets[current_packet], current_packet);
|
||||
reset();
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
} else {
|
||||
current_packet++;
|
||||
update_current_packet(packets[current_packet], current_packet);
|
||||
start();
|
||||
reset();
|
||||
}
|
||||
} else {
|
||||
start();
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,15 +258,18 @@ void BLETxView::on_timer() {
|
||||
void BLETxView::on_tx_progress(const bool done) {
|
||||
if (done) {
|
||||
if (is_active()) {
|
||||
is_sending = false;
|
||||
if ((packet_counter % 10) == 0) {
|
||||
text_packets_sent.set(to_string_dec_uint(packet_counter));
|
||||
}
|
||||
|
||||
packet_counter--;
|
||||
progressbar.set_value(packets[current_packet].packet_count - packet_counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLETxView::BLETxView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_btle_tx);
|
||||
|
||||
add_children({&button_open,
|
||||
&text_filename,
|
||||
&progressbar,
|
||||
|
||||
@@ -108,6 +108,7 @@ class BLETxView : public View {
|
||||
void toggle();
|
||||
void start();
|
||||
void stop();
|
||||
void reset();
|
||||
void handle_replay_thread_done(const uint32_t return_code);
|
||||
void file_error();
|
||||
bool saveFile(const std::filesystem::path& path);
|
||||
@@ -142,7 +143,6 @@ class BLETxView : public View {
|
||||
char randomMac[13] = "010203040506";
|
||||
|
||||
bool is_running = false;
|
||||
bool is_sending = false;
|
||||
uint64_t timer_count{0};
|
||||
int16_t timer_period{1};
|
||||
bool repeatLoop = false;
|
||||
|
||||
@@ -65,9 +65,13 @@ std::string commodity_type(CommodityType value) {
|
||||
|
||||
} /* namespace ert */
|
||||
|
||||
void ERTLogger::on_packet(const ert::Packet& packet) {
|
||||
void ERTLogger::on_packet(const ert::Packet& packet, const uint32_t target_frequency) {
|
||||
const auto formatted = packet.symbols_formatted();
|
||||
std::string entry = ert::format::type(packet.type()) + " " + formatted.data + "/" + formatted.errors;
|
||||
|
||||
// TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue!
|
||||
const auto target_frequency_str = to_string_dec_uint(target_frequency, 10);
|
||||
|
||||
std::string entry = target_frequency_str + " " + ert::format::type(packet.type()) + " " + formatted.data + "/" + formatted.errors;
|
||||
log_file.write_entry(packet.received_at(), entry);
|
||||
}
|
||||
|
||||
@@ -99,10 +103,12 @@ void RecentEntriesTable<ERTRecentEntries>::draw(
|
||||
painter.draw_string(target_rect.location(), style, line);
|
||||
}
|
||||
|
||||
ERTAppView::ERTAppView(NavigationView&) {
|
||||
ERTAppView::ERTAppView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_ert);
|
||||
|
||||
add_children({
|
||||
&field_frequency,
|
||||
&field_rf_amp,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
@@ -110,6 +116,8 @@ ERTAppView::ERTAppView(NavigationView&) {
|
||||
&recent_entries_view,
|
||||
});
|
||||
|
||||
field_frequency.set_step(1000000);
|
||||
|
||||
receiver_model.enable();
|
||||
|
||||
logger = std::make_unique<ERTLogger>();
|
||||
@@ -134,7 +142,7 @@ void ERTAppView::set_parent_rect(const Rect new_parent_rect) {
|
||||
|
||||
void ERTAppView::on_packet(const ert::Packet& packet) {
|
||||
if (logger) {
|
||||
logger->on_packet(packet);
|
||||
logger->on_packet(packet, receiver_model.target_frequency());
|
||||
}
|
||||
|
||||
if (packet.crc_ok()) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_freq_field.hpp"
|
||||
#include "ui_rssi.hpp"
|
||||
#include "ui_channel.hpp"
|
||||
|
||||
@@ -95,7 +96,7 @@ class ERTLogger {
|
||||
return log_file.append(filename);
|
||||
}
|
||||
|
||||
void on_packet(const ert::Packet& packet);
|
||||
void on_packet(const ert::Packet& packet, const uint32_t target_frequency);
|
||||
|
||||
private:
|
||||
LogFile log_file{};
|
||||
@@ -126,6 +127,7 @@ class ERTAppView : public View {
|
||||
ERTRecentEntries recent{};
|
||||
std::unique_ptr<ERTLogger> logger{};
|
||||
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{
|
||||
911600000 /* frequency */,
|
||||
2500000 /* bandwidth */,
|
||||
@@ -143,6 +145,10 @@ class ERTAppView : public View {
|
||||
|
||||
static constexpr auto header_height = 1 * 16;
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{5 * 8, 0 * 16},
|
||||
nav_};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
|
||||
|
||||
@@ -56,13 +56,23 @@ static msg_t ookthread_fn(void* arg) {
|
||||
v = (symbol < 2) ? 1 : 0; // TX on for dot or dash, off for pause
|
||||
delay = morse_symbols[symbol];
|
||||
|
||||
gpio_og_tx.write(v);
|
||||
if (hackrf_r9) { // r9 has a common PIN 54 for MODE CONTROL TX / RX, <=r6 has two independent MODE CONTROL pins (TX and RX)
|
||||
gpio_r9_rx.write(!v); // in hackrf r9 opposite logic "0" means tx , "1" rx = no tx)
|
||||
} else {
|
||||
gpio_og_tx.write(v); // in hackrf <=r6, "1" means tx , "0" no tx.
|
||||
}
|
||||
|
||||
arg_c->on_tx_progress(i, false);
|
||||
|
||||
chThdSleepMilliseconds(delay * arg_c->time_unit_ms);
|
||||
}
|
||||
|
||||
gpio_og_tx.write(0); // Ensure TX is off
|
||||
if (hackrf_r9) { // r9 has a common PIN 54 for MODE CONTROL TX / RX, <=r6 has two independent MODE CONTROL pins (TX and RX)
|
||||
gpio_r9_rx.write(1); // Hackrf_r9 , common pin, rx="1" (we ensure TX is off) / tx="0"
|
||||
} else {
|
||||
gpio_og_tx.write(0); // Hackrf <=r6 independent TX / RX pins ,now touching the tx pin ==> Ensure TX is off
|
||||
}
|
||||
|
||||
arg_c->on_tx_progress(0, true);
|
||||
chThdExit(0);
|
||||
|
||||
@@ -121,9 +131,9 @@ bool MorseView::start_tx() {
|
||||
transmitter_model.set_baseband_bandwidth(1'750'000); // Min TX LPF .already tested in FM morse max tone 9,999k , max dev 150khz
|
||||
transmitter_model.enable();
|
||||
|
||||
if (modulation == CW) {
|
||||
if (mode_cw) {
|
||||
ookthread = chThdCreateStatic(ookthread_wa, sizeof(ookthread_wa), NORMALPRIO + 10, ookthread_fn, this);
|
||||
} else if (modulation == FM) {
|
||||
} else {
|
||||
baseband::set_tones_config(transmitter_model.channel_bandwidth(), 0, symbol_count, false, false);
|
||||
}
|
||||
|
||||
@@ -133,8 +143,8 @@ bool MorseView::start_tx() {
|
||||
void MorseView::update_tx_duration() {
|
||||
uint32_t duration_ms;
|
||||
|
||||
time_unit_ms = 1200 / field_speed.value();
|
||||
symbol_count = morse_encode(message, time_unit_ms, field_tone.value(), &time_units);
|
||||
time_unit_ms = 1200 / speed;
|
||||
symbol_count = morse_encode(message, time_unit_ms, tone, &time_units);
|
||||
|
||||
if (symbol_count) {
|
||||
duration_ms = time_units * time_unit_ms;
|
||||
@@ -175,7 +185,7 @@ void MorseView::on_loop_progress(const uint32_t progress, const bool done) {
|
||||
}
|
||||
|
||||
void MorseView::set_foxhunt(size_t i) {
|
||||
message = foxhunt_codes[i];
|
||||
message = foxhunt_codes[i - 1];
|
||||
buffer = message.c_str();
|
||||
text_message.set(message);
|
||||
update_tx_duration();
|
||||
@@ -188,7 +198,7 @@ MorseView::MorseView(
|
||||
|
||||
add_children({&labels,
|
||||
&checkbox_foxhunt,
|
||||
&options_foxhunt,
|
||||
&field_foxhunt,
|
||||
&field_speed,
|
||||
&field_tone,
|
||||
&options_modulation,
|
||||
@@ -200,36 +210,46 @@ MorseView::MorseView(
|
||||
&tx_view});
|
||||
|
||||
// Default settings
|
||||
field_speed.set_value(15); // 15wps
|
||||
field_tone.set_value(700); // 700Hz FM tone
|
||||
options_modulation.set_selected_index(0); // CW mode
|
||||
options_loop.set_selected_index(0); // Off
|
||||
field_speed.set_value(speed);
|
||||
field_tone.set_value(tone);
|
||||
options_modulation.set_by_value(mode_cw);
|
||||
options_loop.set_by_value(loop);
|
||||
checkbox_foxhunt.set_value(foxhunt_mode);
|
||||
field_foxhunt.set_value(foxhunt_code);
|
||||
|
||||
checkbox_foxhunt.on_select = [this](Checkbox&, bool value) {
|
||||
foxhunt_mode = value;
|
||||
|
||||
if (foxhunt_mode)
|
||||
set_foxhunt(options_foxhunt.selected_index_value());
|
||||
set_foxhunt(foxhunt_code);
|
||||
};
|
||||
|
||||
options_foxhunt.on_change = [this](size_t i, int32_t) {
|
||||
field_foxhunt.on_change = [this](int32_t value) {
|
||||
foxhunt_code = value;
|
||||
|
||||
if (foxhunt_mode)
|
||||
set_foxhunt(i);
|
||||
set_foxhunt(foxhunt_code);
|
||||
};
|
||||
|
||||
options_modulation.on_change = [this](size_t i, int32_t) {
|
||||
modulation = (modulation_t)i;
|
||||
};
|
||||
|
||||
options_loop.on_change = [this](size_t i, uint32_t n) {
|
||||
options_modulation.on_change = [this](size_t i, int32_t value) {
|
||||
(void)i; // avoid unused warning
|
||||
loop = n;
|
||||
mode_cw = (bool)value;
|
||||
};
|
||||
|
||||
field_speed.on_change = [this](int32_t) {
|
||||
options_loop.on_change = [this](size_t i, uint32_t value) {
|
||||
(void)i; // avoid unused warning
|
||||
loop = value;
|
||||
};
|
||||
|
||||
field_speed.on_change = [this](int32_t value) {
|
||||
speed = value;
|
||||
update_tx_duration();
|
||||
};
|
||||
|
||||
field_tone.on_change = [this](int32_t value) {
|
||||
tone = value;
|
||||
};
|
||||
|
||||
button_message.on_select = [this, &nav](Button&) {
|
||||
this->on_set_text(nav);
|
||||
};
|
||||
|
||||
@@ -65,7 +65,6 @@ class MorseView : public View {
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
std::string buffer{"PORTAPACK"};
|
||||
std::string message{};
|
||||
uint32_t time_units{0};
|
||||
|
||||
@@ -74,14 +73,25 @@ class MorseView : public View {
|
||||
1750000 /* bandwidth */,
|
||||
1536000 /* sampling rate */
|
||||
};
|
||||
app_settings::SettingsManager settings_{
|
||||
"tx_morse", app_settings::Mode::TX};
|
||||
|
||||
enum modulation_t {
|
||||
CW = 0,
|
||||
FM = 1
|
||||
};
|
||||
modulation_t modulation{CW};
|
||||
std::string buffer{"PORTAPACK"};
|
||||
bool mode_cw{true};
|
||||
bool foxhunt_mode{false};
|
||||
uint32_t foxhunt_code{1};
|
||||
uint32_t speed{15};
|
||||
uint32_t tone{700};
|
||||
app_settings::SettingsManager settings_{
|
||||
"tx_morse",
|
||||
app_settings::Mode::TX,
|
||||
{
|
||||
{"message"sv, &buffer},
|
||||
{"foxhunt"sv, &foxhunt_mode},
|
||||
{"foxhunt_code"sv, &foxhunt_code},
|
||||
{"speed"sv, &speed},
|
||||
{"tone"sv, &tone},
|
||||
{"mode_cw"sv, &mode_cw},
|
||||
{"loop"sv, &loop},
|
||||
}};
|
||||
|
||||
bool start_tx();
|
||||
void update_tx_duration();
|
||||
@@ -90,7 +100,6 @@ class MorseView : public View {
|
||||
|
||||
Thread* ookthread{nullptr};
|
||||
Thread* loopthread{nullptr};
|
||||
bool foxhunt_mode{false};
|
||||
bool run{false};
|
||||
|
||||
Labels labels{
|
||||
@@ -104,20 +113,12 @@ class MorseView : public View {
|
||||
{4 * 8, 16},
|
||||
8,
|
||||
"Foxhunt:"};
|
||||
OptionsField options_foxhunt{
|
||||
NumberField field_foxhunt{
|
||||
{17 * 8, 16 + 4},
|
||||
7,
|
||||
{{"1 (MOE)", 0},
|
||||
{"2 (MOI)", 1},
|
||||
{"3 (MOS)", 2},
|
||||
{"4 (MOH)", 3},
|
||||
{"5 (MO5)", 4},
|
||||
{"6 (MON)", 5},
|
||||
{"7 (MOD)", 6},
|
||||
{"8 (MOB)", 7},
|
||||
{"9 (MO6)", 8},
|
||||
{"X (MO) ", 9},
|
||||
{"T (S) ", 10}}};
|
||||
2,
|
||||
{1, 11},
|
||||
1,
|
||||
' '};
|
||||
|
||||
NumberField field_speed{
|
||||
{10 * 8, 6 * 8},
|
||||
@@ -136,8 +137,8 @@ class MorseView : public View {
|
||||
OptionsField options_modulation{
|
||||
{15 * 8, 10 * 8},
|
||||
2,
|
||||
{{"CW", 0},
|
||||
{"FM", 1}}};
|
||||
{{"CW", true},
|
||||
{"FM", false}}};
|
||||
|
||||
OptionsField options_loop{
|
||||
{9 * 8, 12 * 8},
|
||||
|
||||
Reference in New Issue
Block a user