mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-28 00:39:44 -05:00
Replay of IQ files ! :D
Added icons and colors for commonly used files in Fileman Fileman can filter by file extension Bugfix: Fileman doesn't crash anymore on renaming long file names Updated binary
This commit is contained in:
parent
3221992ad1
commit
b38adf3769
@ -195,7 +195,7 @@ set(CPPSRC
|
||||
ui_rds.cpp
|
||||
ui_receiver.cpp
|
||||
ui_record_view.cpp
|
||||
ui_replay_view.cpp
|
||||
# ui_replay_view.cpp
|
||||
ui_rssi.cpp
|
||||
ui_scanner.cpp
|
||||
# ui_script.cpp
|
||||
|
@ -367,6 +367,28 @@ static constexpr Bitmap bitmap_record {
|
||||
{ 16, 16 }, bitmap_record_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_file_text_data[] = {
|
||||
0x00, 0x20,
|
||||
0x00, 0x30,
|
||||
0x00, 0x38,
|
||||
0x00, 0x38,
|
||||
0x00, 0x34,
|
||||
0x00, 0x32,
|
||||
0x00, 0x31,
|
||||
0x80, 0x30,
|
||||
0xC0, 0x30,
|
||||
0xE0, 0x3F,
|
||||
0x30, 0x30,
|
||||
0x18, 0x30,
|
||||
0x0C, 0x30,
|
||||
0x0E, 0x78,
|
||||
0x1F, 0xFC,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_file_text {
|
||||
{ 16, 16 }, bitmap_icon_file_text_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_ais_data[] = {
|
||||
0x00, 0x01,
|
||||
0x80, 0x01,
|
||||
@ -449,6 +471,28 @@ static constexpr Bitmap bitmap_icon_nuoptix {
|
||||
{ 16, 16 }, bitmap_icon_nuoptix_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_file_iq_data[] = {
|
||||
0x98, 0x00,
|
||||
0x24, 0x06,
|
||||
0xA4, 0x08,
|
||||
0x34, 0x10,
|
||||
0xB8, 0x20,
|
||||
0x20, 0x20,
|
||||
0x80, 0x00,
|
||||
0xD5, 0x55,
|
||||
0x80, 0x00,
|
||||
0x02, 0x70,
|
||||
0x82, 0x20,
|
||||
0x04, 0x20,
|
||||
0x88, 0x20,
|
||||
0x30, 0x70,
|
||||
0x80, 0x00,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_file_iq {
|
||||
{ 16, 16 }, bitmap_icon_file_iq_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_closecall_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x10,
|
||||
@ -1751,6 +1795,28 @@ static constexpr Bitmap bitmap_bulb_off {
|
||||
{ 24, 24 }, bitmap_bulb_off_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_file_image_data[] = {
|
||||
0x00, 0x00,
|
||||
0xFF, 0xFF,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x89, 0x80,
|
||||
0xC1, 0x81,
|
||||
0xE1, 0xA3,
|
||||
0xB1, 0xB3,
|
||||
0x89, 0xDC,
|
||||
0x07, 0x8C,
|
||||
0x01, 0x90,
|
||||
0x01, 0x80,
|
||||
0xAB, 0x82,
|
||||
0xFF, 0xD5,
|
||||
0xFF, 0xFF,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_file_image {
|
||||
{ 16, 16 }, bitmap_icon_file_image_data
|
||||
};
|
||||
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
|
@ -233,13 +233,14 @@ space_info space(const path& p);
|
||||
} /* namespace filesystem */
|
||||
} /* namespace std */
|
||||
|
||||
std::vector<std::filesystem::path> scan_root_files(const std::filesystem::path& directory, const std::filesystem::path& extension);
|
||||
std::vector<std::filesystem::path> scan_root_directories(const std::filesystem::path& directory);
|
||||
std::filesystem::path next_filename_stem_matching_pattern(std::filesystem::path filename_stem_pattern);
|
||||
void delete_file(const std::filesystem::path& file_path);
|
||||
void rename_file(const std::filesystem::path& file_path, const std::filesystem::path& new_name);
|
||||
uint32_t make_new_directory(const std::filesystem::path& dir_path);
|
||||
|
||||
std::vector<std::filesystem::path> scan_root_files(const std::filesystem::path& directory, const std::filesystem::path& extension);
|
||||
std::vector<std::filesystem::path> scan_root_directories(const std::filesystem::path& directory);
|
||||
std::filesystem::path next_filename_stem_matching_pattern(std::filesystem::path filename_stem_pattern);
|
||||
|
||||
/* Values added to FatFs FRESULT enum, values outside the FRESULT data type */
|
||||
static_assert(sizeof(FIL::err) == 1, "FatFs FIL::err size not expected.");
|
||||
|
||||
|
@ -27,13 +27,14 @@
|
||||
//TEST: Check AFSK transmit end, skips last bits ?
|
||||
//TEST: Imperial in whipcalc
|
||||
|
||||
//BUG: Crash on rename file with long filename
|
||||
//BUG: Auto backlight off doesn't work anymore
|
||||
//BUG: CPLD-related rx ok, tx bad, see portapack.cpp lines 214+ to disable CPLD overlay
|
||||
//BUG: REPLAY See what's wrong with quality (format, or need for interpolation filter ?)
|
||||
//BUG: (Workaround ok) CPLD-related rx ok, tx bad, see portapack.cpp lines 214+ to disable CPLD overlay
|
||||
//BUG: SCANNER Lock on frequency, if frequency jump, still locked on first one
|
||||
//BUG: SCANNER Multiple slices
|
||||
|
||||
//TODO: Display file creation/modification date in FileLoadView
|
||||
//TODO: Display recording frequency in Replay (from associated .txt file, if present)
|
||||
//TODO: Clean up ReplayThread
|
||||
//TODO: Cap Wav viewer position
|
||||
//TODO: Adapt wav viewer position step
|
||||
//TODO: Use unit_auto_scale
|
||||
@ -80,10 +81,7 @@ Continuous (Fox-oring)
|
||||
// Old or low-priority stuff:
|
||||
//TODO: Bodet :)
|
||||
//TODO: Analog TV tx with camcorder font character generator
|
||||
//TODO: Show address/data bit fields in OOK TX
|
||||
//TODO: Scan for OOK TX
|
||||
//TODO: Script engine ?
|
||||
//TODO: AFSK receiver
|
||||
//TODO: Check more OOK encoders
|
||||
//BUG (fixed ?): No audio in about when shown second time
|
||||
//TODO: Show MD5 mismatches for modules not found, etc...
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include "replay_app.hpp"
|
||||
#include "string_format.hpp"
|
||||
|
||||
#include "ui_fileman.hpp"
|
||||
#include "io_file.hpp"
|
||||
|
||||
#include "baseband_api.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
@ -31,31 +34,132 @@ using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
void ReplayAppView::set_ready() {
|
||||
ready_signal = true;
|
||||
}
|
||||
|
||||
void ReplayAppView::on_file_changed(std::filesystem::path new_file_path) {
|
||||
File bbd_file;
|
||||
std::string str_duration = "";
|
||||
|
||||
file_path = new_file_path;
|
||||
|
||||
text_filename.set(new_file_path.string().substr(0, 18));
|
||||
|
||||
bbd_file.open("/" + new_file_path.string());
|
||||
auto file_size = bbd_file.size();
|
||||
auto duration = file_size / (2 * 2 * sampling_rate / 8);
|
||||
|
||||
progressbar.set_max(file_size);
|
||||
|
||||
if (duration >= 60)
|
||||
str_duration = to_string_dec_uint(duration / 60) + "m";
|
||||
|
||||
text_duration.set(str_duration + to_string_dec_uint(duration % 60) + "s");
|
||||
|
||||
button_play.focus();
|
||||
}
|
||||
|
||||
void ReplayAppView::on_tx_progress(const uint32_t progress) {
|
||||
progressbar.set_value(progress);
|
||||
}
|
||||
|
||||
void ReplayAppView::focus() {
|
||||
button_open.focus();
|
||||
}
|
||||
|
||||
bool ReplayAppView::is_active() const {
|
||||
return (bool)replay_thread;
|
||||
}
|
||||
|
||||
void ReplayAppView::toggle() {
|
||||
if( is_active() ) {
|
||||
stop();
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayAppView::start() {
|
||||
stop();
|
||||
|
||||
std::unique_ptr<stream::Reader> reader;
|
||||
|
||||
auto p = std::make_unique<FileReader>();
|
||||
auto open_error = p->open(file_path);
|
||||
if( open_error.is_valid() ) {
|
||||
handle_error(open_error.value());
|
||||
} else {
|
||||
reader = std::move(p);
|
||||
}
|
||||
|
||||
if( reader ) {
|
||||
button_play.set_bitmap(&bitmap_stop);
|
||||
replay_thread = std::make_unique<ReplayThread>(
|
||||
std::move(reader),
|
||||
read_size, buffer_count,
|
||||
&ready_signal,
|
||||
[]() {
|
||||
ReplayThreadDoneMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
},
|
||||
[](File::Error error) {
|
||||
ReplayThreadDoneMessage message { error.code() };
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
radio::enable({
|
||||
receiver_model.tuning_frequency(),
|
||||
sampling_rate,
|
||||
baseband_bandwidth,
|
||||
rf::Direction::Transmit,
|
||||
receiver_model.rf_amp(),
|
||||
static_cast<int8_t>(receiver_model.lna()),
|
||||
static_cast<int8_t>(receiver_model.vga())
|
||||
});
|
||||
}
|
||||
|
||||
void ReplayAppView::stop() {
|
||||
if( is_active() )
|
||||
replay_thread.reset();
|
||||
|
||||
progressbar.set_value(0);
|
||||
|
||||
radio::disable();
|
||||
button_play.set_bitmap(&bitmap_play);
|
||||
}
|
||||
|
||||
void ReplayAppView::handle_replay_thread_done(const File::Error error) {
|
||||
stop();
|
||||
if( error.code() ) {
|
||||
handle_error(error);
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayAppView::handle_error(const File::Error error) {
|
||||
nav_.display_modal("Error", error.what());
|
||||
}
|
||||
|
||||
ReplayAppView::ReplayAppView(
|
||||
NavigationView& nav
|
||||
) : nav_ (nav)
|
||||
{
|
||||
std::vector<std::filesystem::path> file_list;
|
||||
|
||||
// Search for files with the right extension
|
||||
file_list = scan_root_files(u"/", u"*.C16");
|
||||
if (!file_list.size()) {
|
||||
file_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
baseband::run_image(portapack::spi_flash::image_tag_replay);
|
||||
|
||||
add_children({
|
||||
&field_frequency,
|
||||
&field_frequency_step,
|
||||
&field_rf_amp,
|
||||
&replay_view,
|
||||
&button_play,
|
||||
&text_filename,
|
||||
&text_duration,
|
||||
&progressbar,
|
||||
&button_open,
|
||||
&waterfall,
|
||||
});
|
||||
|
||||
replay_view.set_file_list(file_list);
|
||||
|
||||
field_frequency.set_value(target_frequency());
|
||||
field_frequency.set_step(receiver_model.frequency_step());
|
||||
field_frequency.on_change = [this](rf::Frequency f) {
|
||||
@ -75,9 +179,16 @@ ReplayAppView::ReplayAppView(
|
||||
receiver_model.set_frequency_step(v);
|
||||
this->field_frequency.set_step(v);
|
||||
};
|
||||
|
||||
replay_view.on_error = [&nav](std::string message) {
|
||||
nav.display_modal("Error", message);
|
||||
|
||||
button_play.on_select = [this](ImageButton&) {
|
||||
this->toggle();
|
||||
};
|
||||
|
||||
button_open.on_select = [this, &nav](Button&) {
|
||||
auto new_view = nav.push<FileLoadView>(".C16");
|
||||
new_view->on_changed = [this](std::filesystem::path new_file_path) {
|
||||
on_file_changed(new_file_path);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@ -100,13 +211,6 @@ void ReplayAppView::set_parent_rect(const Rect new_parent_rect) {
|
||||
waterfall.set_parent_rect(waterfall_rect);
|
||||
}
|
||||
|
||||
void ReplayAppView::focus() {
|
||||
if (!file_error) {
|
||||
field_frequency.focus();
|
||||
} else
|
||||
nav_.display_modal("No files", "No .C16 files in\nSD card root", ABORT, nullptr);
|
||||
}
|
||||
|
||||
void ReplayAppView::on_target_frequency_changed(rf::Frequency f) {
|
||||
set_target_frequency(f);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_replay_view.hpp"
|
||||
#include "replay_thread.hpp"
|
||||
#include "ui_spectrum.hpp"
|
||||
|
||||
#include <string>
|
||||
@ -40,24 +40,40 @@ public:
|
||||
~ReplayAppView();
|
||||
|
||||
void on_hide() override;
|
||||
|
||||
void set_parent_rect(const Rect new_parent_rect) override;
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Replay (BETA)"; };
|
||||
std::string title() const override { return "Replay"; };
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
bool is_active() const;
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
bool file_error { false };
|
||||
static constexpr ui::Dim header_height = 3 * 16;
|
||||
|
||||
static constexpr ui::Dim header_height = 2 * 16;
|
||||
static constexpr uint32_t sampling_rate = 4000000;
|
||||
static constexpr uint32_t baseband_bandwidth = 2500000;
|
||||
const size_t read_size { 16384 };
|
||||
const size_t buffer_count { 3 };
|
||||
|
||||
void on_file_changed(std::filesystem::path new_file_path);
|
||||
void on_target_frequency_changed(rf::Frequency f);
|
||||
|
||||
rf::Frequency target_frequency() const;
|
||||
void on_tx_progress(const uint32_t progress);
|
||||
|
||||
void set_target_frequency(const rf::Frequency new_value);
|
||||
rf::Frequency target_frequency() const;
|
||||
|
||||
void toggle();
|
||||
void set_ready();
|
||||
void handle_replay_thread_done(const File::Error error);
|
||||
void handle_error(const File::Error error);
|
||||
|
||||
std::filesystem::path file_path { };
|
||||
std::unique_ptr<ReplayThread> replay_thread { };
|
||||
bool ready_signal { false };
|
||||
|
||||
FrequencyField field_frequency {
|
||||
{ 0 * 8, 0 * 16 },
|
||||
@ -71,12 +87,57 @@ private:
|
||||
{ 16 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
ReplayView replay_view {
|
||||
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
|
||||
16384, 3
|
||||
ImageButton button_play {
|
||||
{ 0 * 8, 1 * 16 + 8, 2 * 8, 1 * 16 },
|
||||
&bitmap_play,
|
||||
Color::green(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Text text_filename {
|
||||
{ 2 * 8, 1 * 16, 18 * 8, 16 },
|
||||
"-"
|
||||
};
|
||||
Text text_duration {
|
||||
{ 2 * 8, 2 * 16, 6 * 8, 16 },
|
||||
"-"
|
||||
};
|
||||
ProgressBar progressbar {
|
||||
{ 9 * 8, 2 * 16, 10 * 8, 16 }
|
||||
};
|
||||
|
||||
Button button_open {
|
||||
{ 20 * 8, 1 * 16, 10 * 8, 2 * 16 },
|
||||
"Open file"
|
||||
};
|
||||
|
||||
spectrum::WaterfallWidget waterfall { };
|
||||
|
||||
MessageHandlerRegistration message_handler_replay_thread_error {
|
||||
Message::ID::ReplayThreadDone,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
|
||||
this->handle_replay_thread_done(message.error);
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_fifo_signal {
|
||||
Message::ID::RequestSignal,
|
||||
[this](const Message* const p) {
|
||||
const auto message = static_cast<const RequestSignalMessage*>(p);
|
||||
if (message->signal == RequestSignalMessage::Signal::FillRequest) {
|
||||
this->set_ready();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_tx_progress {
|
||||
Message::ID::TXProgress,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
||||
this->on_tx_progress(message.progress);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
@ -41,10 +41,12 @@ ReplayThread::ReplayThread(
|
||||
std::unique_ptr<stream::Reader> reader,
|
||||
size_t read_size,
|
||||
size_t buffer_count,
|
||||
bool* ready_signal,
|
||||
std::function<void()> success_callback,
|
||||
std::function<void(File::Error)> error_callback
|
||||
) : config { read_size, buffer_count },
|
||||
reader { std::move(reader) },
|
||||
ready_sig { ready_signal },
|
||||
success_callback { std::move(success_callback) },
|
||||
error_callback { std::move(error_callback) }
|
||||
{
|
||||
@ -79,7 +81,12 @@ Optional<File::Error> ReplayThread::run() {
|
||||
|
||||
StreamBuffer* prefill_buffer { nullptr };
|
||||
|
||||
// TESTING: Prefill
|
||||
// Wait for FIFOs to be allocated in baseband
|
||||
// Wait for ui_replay_view to tell us that the buffers are ready (awful :( )
|
||||
while (!(*ready_sig)) {
|
||||
chThdSleep(100);
|
||||
};
|
||||
|
||||
// While empty buffers fifo is not empty...
|
||||
while (!buffers.empty()) {
|
||||
prefill_buffer = buffers.get_prefill();
|
||||
@ -87,7 +94,7 @@ Optional<File::Error> ReplayThread::run() {
|
||||
if (prefill_buffer == nullptr) {
|
||||
buffers.put_app(prefill_buffer);
|
||||
} else {
|
||||
size_t blocks = prefill_buffer->capacity() / 512;
|
||||
size_t blocks = 16384 / 512;
|
||||
|
||||
for (size_t c = 0; c < blocks; c++) {
|
||||
auto read_result = reader->read(&((uint8_t*)prefill_buffer->data())[c * 512], 512);
|
||||
@ -96,23 +103,23 @@ Optional<File::Error> ReplayThread::run() {
|
||||
}
|
||||
}
|
||||
|
||||
prefill_buffer->set_size(prefill_buffer->capacity());
|
||||
prefill_buffer->set_size(16384);
|
||||
|
||||
buffers.put(prefill_buffer);
|
||||
//if (!buffers.put(prefill_buffer)) for(;;) {};
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
baseband::set_fifo_data(nullptr);
|
||||
|
||||
while( !chThdShouldTerminate() ) {
|
||||
auto buffer = buffers.get();
|
||||
|
||||
size_t blocks = buffer->capacity() / 512;
|
||||
|
||||
for (size_t c = 0; c < blocks; c++) {
|
||||
auto read_result = reader->read(&((uint8_t*)buffer->data())[c * 512], 512);
|
||||
if( read_result.is_error() ) {
|
||||
return read_result.error();
|
||||
auto read_result = reader->read(buffer->data(), buffer->capacity());
|
||||
if( read_result.is_error() ) {
|
||||
return read_result.error();
|
||||
} else {
|
||||
if (read_result.value() == 0) {
|
||||
return { };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
std::unique_ptr<stream::Reader> reader,
|
||||
size_t read_size,
|
||||
size_t buffer_count,
|
||||
bool* ready_signal,
|
||||
std::function<void()> success_callback,
|
||||
std::function<void(File::Error)> error_callback
|
||||
);
|
||||
@ -57,6 +58,7 @@ public:
|
||||
private:
|
||||
ReplayConfig config;
|
||||
std::unique_ptr<stream::Reader> reader;
|
||||
bool* ready_sig;
|
||||
std::function<void()> success_callback;
|
||||
std::function<void(File::Error)> error_callback;
|
||||
Thread* thread { nullptr };
|
||||
|
@ -32,14 +32,24 @@ namespace ui {
|
||||
void FileManBaseView::load_directory_contents(const std::filesystem::path& dir_path) {
|
||||
current_path = dir_path;
|
||||
|
||||
text_current.set(dir_path.string());
|
||||
text_current.set(dir_path.string().substr(0, 30 - 8));
|
||||
|
||||
entry_list.clear();
|
||||
|
||||
// List all directories and files, put directories up top
|
||||
auto filtering = (bool)extension_filter.size();
|
||||
|
||||
// List directories and files, put directories up top
|
||||
for (const auto& entry : std::filesystem::directory_iterator(dir_path, u"*")) {
|
||||
if (std::filesystem::is_regular_file(entry.status())) {
|
||||
entry_list.push_back({ entry.path(), (uint32_t)entry.size(), false });
|
||||
if (entry.path().string().length()) {
|
||||
auto entry_extension = entry.path().extension().string();
|
||||
|
||||
for (auto &c: entry_extension)
|
||||
c = toupper(c);
|
||||
|
||||
if ((entry_extension == extension_filter) || !filtering)
|
||||
entry_list.push_back({ entry.path(), (uint32_t)entry.size(), false });
|
||||
}
|
||||
} else if (std::filesystem::is_directory(entry.status())) {
|
||||
entry_list.insert(entry_list.begin(), { entry.path(), 0, true });
|
||||
}
|
||||
@ -57,8 +67,10 @@ std::filesystem::path FileManBaseView::get_selected_path() {
|
||||
}
|
||||
|
||||
FileManBaseView::FileManBaseView(
|
||||
NavigationView& nav
|
||||
) : nav_ (nav)
|
||||
NavigationView& nav,
|
||||
std::string filter
|
||||
) : nav_ (nav),
|
||||
extension_filter { filter }
|
||||
{
|
||||
load_directory_contents(current_path);
|
||||
|
||||
@ -95,10 +107,6 @@ void FileManBaseView::focus() {
|
||||
}
|
||||
|
||||
void FileManBaseView::refresh_list() {
|
||||
std::string size_str { };
|
||||
uint32_t suffix_index;
|
||||
size_t file_size;
|
||||
|
||||
if (!entry_list.size()) {
|
||||
// Hide widgets, show warning
|
||||
if (on_refresh_widgets)
|
||||
@ -111,9 +119,10 @@ void FileManBaseView::refresh_list() {
|
||||
menu_view.clear();
|
||||
|
||||
for (size_t n = 0; n < entry_list.size(); n++) {
|
||||
auto entry_name = entry_list[n].entry_path.filename().string().substr(0, 20);
|
||||
auto entry = &entry_list[n];
|
||||
auto entry_name = entry->entry_path.filename().string().substr(0, 20);
|
||||
|
||||
if (entry_list[n].is_directory) {
|
||||
if (entry->is_directory) {
|
||||
|
||||
menu_view.add_item({
|
||||
entry_name,
|
||||
@ -127,8 +136,8 @@ void FileManBaseView::refresh_list() {
|
||||
|
||||
} else {
|
||||
|
||||
file_size = entry_list[n].size;
|
||||
suffix_index = 0;
|
||||
auto file_size = entry->size;
|
||||
size_t suffix_index = 0;
|
||||
|
||||
while (file_size >= 1024) {
|
||||
file_size /= 1024;
|
||||
@ -137,12 +146,23 @@ void FileManBaseView::refresh_list() {
|
||||
if (suffix_index > 4)
|
||||
suffix_index = 4;
|
||||
|
||||
size_str = to_string_dec_uint(file_size) + suffix[suffix_index];
|
||||
std::string size_str = to_string_dec_uint(file_size) + suffix[suffix_index];
|
||||
|
||||
auto entry_extension = entry->entry_path.extension().string();
|
||||
for (auto &c: entry_extension)
|
||||
c = toupper(c);
|
||||
|
||||
// Associate extension to icon and color
|
||||
size_t c;
|
||||
for (c = 0; c < file_types.size() - 1; c++) {
|
||||
if (entry_extension == file_types[c].extension)
|
||||
break;
|
||||
}
|
||||
|
||||
menu_view.add_item({
|
||||
entry_name + std::string(21 - entry_name.length(), ' ') + size_str,
|
||||
ui::Color::white(),
|
||||
&bitmap_icon_file,
|
||||
file_types[c].color,
|
||||
file_types[c].icon,
|
||||
[this](){
|
||||
if (on_select_entry)
|
||||
on_select_entry();
|
||||
@ -186,8 +206,9 @@ void FileLoadView::refresh_widgets(const bool v) {
|
||||
}
|
||||
|
||||
FileLoadView::FileLoadView(
|
||||
NavigationView& nav
|
||||
) : FileManBaseView(nav)
|
||||
NavigationView& nav,
|
||||
std::string filter
|
||||
) : FileManBaseView(nav, filter)
|
||||
{
|
||||
on_refresh_widgets = [this](bool v) {
|
||||
refresh_widgets(v);
|
||||
@ -216,7 +237,7 @@ FileLoadView::FileLoadView(
|
||||
}
|
||||
|
||||
void FileManagerView::on_rename(NavigationView& nav) {
|
||||
text_prompt(nav, &name_buffer, 12, [this](std::string * buffer) {
|
||||
text_prompt(nav, &name_buffer, max_filename_length, [this](std::string * buffer) {
|
||||
rename_file(get_selected_path(), *buffer);
|
||||
load_directory_contents(current_path);
|
||||
refresh_list();
|
||||
@ -244,7 +265,7 @@ FileManagerView::~FileManagerView() {
|
||||
|
||||
FileManagerView::FileManagerView(
|
||||
NavigationView& nav
|
||||
) : FileManBaseView(nav)
|
||||
) : FileManBaseView(nav, "")
|
||||
{
|
||||
on_refresh_widgets = [this](bool v) {
|
||||
refresh_widgets(v);
|
||||
@ -271,7 +292,7 @@ FileManagerView::FileManagerView(
|
||||
button_new_dir.on_select = [this, &nav](Button&) {
|
||||
name_buffer.clear();
|
||||
|
||||
text_prompt(nav, &name_buffer, 12, [this](std::string * buffer) {
|
||||
text_prompt(nav, &name_buffer, max_filename_length, [this](std::string * buffer) {
|
||||
std::string path_str = *buffer;
|
||||
|
||||
make_new_directory(current_path.string() + '/' + path_str);
|
||||
@ -281,10 +302,8 @@ FileManagerView::FileManagerView(
|
||||
};
|
||||
|
||||
button_rename.on_select = [this, &nav](Button&) {
|
||||
if (!entry_list[menu_view.highlighted()].is_directory) {
|
||||
name_buffer = entry_list[menu_view.highlighted()].entry_path.filename().string();
|
||||
on_rename(nav);
|
||||
}
|
||||
name_buffer = entry_list[menu_view.highlighted()].entry_path.filename().string().substr(0, max_filename_length);
|
||||
on_rename(nav);
|
||||
};
|
||||
|
||||
button_delete.on_select = [this, &nav](Button&) {
|
||||
|
@ -39,7 +39,8 @@ struct fileman_entry {
|
||||
class FileManBaseView : public View {
|
||||
public:
|
||||
FileManBaseView(
|
||||
NavigationView& nav
|
||||
NavigationView& nav,
|
||||
std::string filter
|
||||
);
|
||||
|
||||
void focus() override;
|
||||
@ -52,13 +53,31 @@ public:
|
||||
protected:
|
||||
NavigationView& nav_;
|
||||
|
||||
static constexpr size_t max_filename_length = 30 - 2;
|
||||
|
||||
const std::string suffix[5] = { "B", "kB", "MB", "GB", "??" };
|
||||
|
||||
struct file_assoc_t {
|
||||
std::string extension;
|
||||
const Bitmap* icon;
|
||||
ui::Color color;
|
||||
};
|
||||
|
||||
const std::vector<file_assoc_t> file_types = {
|
||||
{ ".TXT", &bitmap_icon_file_text, ui::Color::white() },
|
||||
{ ".PNG", &bitmap_icon_file_image, ui::Color::green() },
|
||||
{ ".BMP", &bitmap_icon_file_image, ui::Color::green() },
|
||||
{ ".C16", &bitmap_icon_file_iq, ui::Color::blue() },
|
||||
{ ".WAV", &bitmap_icon_speaker, ui::Color::dark_magenta() },
|
||||
{ "", &bitmap_icon_file, ui::Color::light_grey() }
|
||||
};
|
||||
|
||||
bool empty_root { false };
|
||||
std::function<void(void)> on_select_entry { nullptr };
|
||||
std::function<void(bool)> on_refresh_widgets { nullptr };
|
||||
std::vector<fileman_entry> entry_list { };
|
||||
std::filesystem::path current_path { u"" };
|
||||
std::string extension_filter { "" };
|
||||
|
||||
void change_category(int32_t category_id);
|
||||
void refresh_list();
|
||||
@ -113,7 +132,7 @@ class FileLoadView : public FileManBaseView {
|
||||
public:
|
||||
std::function<void(std::filesystem::path)> on_changed { };
|
||||
|
||||
FileLoadView(NavigationView& nav);
|
||||
FileLoadView(NavigationView& nav, std::string filter);
|
||||
|
||||
private:
|
||||
void refresh_widgets(const bool v);
|
||||
|
@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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_replay_view.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
#include "message.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "rtc_time.hpp"
|
||||
#include "io_file.hpp"
|
||||
|
||||
#include "string_format.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ui {
|
||||
|
||||
void ReplayView::on_file_changed(const uint32_t duration) {
|
||||
std::string str_duration = "";
|
||||
|
||||
if (duration >= 60)
|
||||
str_duration = to_string_dec_uint(duration / 60) + "m";
|
||||
|
||||
text_duration.set(str_duration + to_string_dec_uint(duration % 60) + "s");
|
||||
}
|
||||
|
||||
ReplayView::ReplayView(
|
||||
const Rect parent_rect,
|
||||
const size_t read_size,
|
||||
const size_t buffer_count
|
||||
) : View { parent_rect },
|
||||
read_size { read_size },
|
||||
buffer_count { buffer_count }
|
||||
{
|
||||
add_children({
|
||||
&rect_background,
|
||||
&button_play,
|
||||
&options_files,
|
||||
&text_duration,
|
||||
//&text_time_seek,
|
||||
});
|
||||
|
||||
rect_background.set_parent_rect({ { 0, 0 }, size() });
|
||||
|
||||
options_files.on_change = [this](size_t, int32_t duration) {
|
||||
this->on_file_changed(duration);
|
||||
};
|
||||
|
||||
button_play.on_select = [this](ImageButton&) {
|
||||
this->toggle();
|
||||
};
|
||||
|
||||
/*signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
|
||||
this->on_tick_second();
|
||||
};*/
|
||||
}
|
||||
|
||||
ReplayView::~ReplayView() {
|
||||
//rtc_time::signal_tick_second -= signal_token_tick_second;
|
||||
}
|
||||
|
||||
void ReplayView::focus() {
|
||||
options_files.focus();
|
||||
}
|
||||
|
||||
void ReplayView::set_file_list(const std::vector<std::filesystem::path>& file_list) {
|
||||
File bbd_file;
|
||||
uint32_t duration;
|
||||
|
||||
for (const auto& file : file_list) {
|
||||
bbd_file.open("/" + file.string());
|
||||
duration = bbd_file.size() / (2 * 2 * sampling_rate / 8);
|
||||
file_options.emplace_back(file.string().substr(0, 8), duration);
|
||||
}
|
||||
options_files.set_options(file_options);
|
||||
options_files.set_selected_index(0); // First file
|
||||
on_file_changed(file_options[0].second);
|
||||
}
|
||||
|
||||
bool ReplayView::is_active() const {
|
||||
return (bool)replay_thread;
|
||||
}
|
||||
|
||||
void ReplayView::toggle() {
|
||||
if( is_active() ) {
|
||||
stop();
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayView::start() {
|
||||
stop();
|
||||
|
||||
std::unique_ptr<stream::Reader> reader;
|
||||
|
||||
auto p = std::make_unique<FileReader>();
|
||||
auto create_error = p->open(file_options[options_files.selected_index()].first + ".C16");
|
||||
if( create_error.is_valid() ) {
|
||||
handle_error(create_error.value());
|
||||
} else {
|
||||
reader = std::move(p);
|
||||
}
|
||||
|
||||
if( reader ) {
|
||||
button_play.set_bitmap(&bitmap_stop);
|
||||
replay_thread = std::make_unique<ReplayThread>(
|
||||
std::move(reader),
|
||||
read_size, buffer_count,
|
||||
[]() {
|
||||
ReplayThreadDoneMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
},
|
||||
[](File::Error error) {
|
||||
ReplayThreadDoneMessage message { error.code() };
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
update_status_display();
|
||||
|
||||
radio::enable({
|
||||
receiver_model.tuning_frequency(),
|
||||
sampling_rate,
|
||||
2500000, //baseband_bandwidth,
|
||||
rf::Direction::Transmit,
|
||||
receiver_model.rf_amp(),
|
||||
static_cast<int8_t>(receiver_model.lna()),
|
||||
static_cast<int8_t>(receiver_model.vga())
|
||||
});
|
||||
}
|
||||
|
||||
void ReplayView::stop() {
|
||||
if( is_active() ) {
|
||||
replay_thread.reset();
|
||||
radio::disable();
|
||||
button_play.set_bitmap(&bitmap_play);
|
||||
}
|
||||
|
||||
update_status_display();
|
||||
}
|
||||
|
||||
void ReplayView::on_tick_second() {
|
||||
update_status_display();
|
||||
}
|
||||
|
||||
void ReplayView::update_status_display() {
|
||||
/*if( sampling_rate ) {
|
||||
const auto space_info = std::filesystem::space("");
|
||||
const uint32_t bytes_per_second = file_type == FileType::WAV ? (sampling_rate * 2) : (sampling_rate * 4);
|
||||
const uint32_t available_seconds = space_info.free / bytes_per_second;
|
||||
const uint32_t seconds = available_seconds % 60;
|
||||
const uint32_t available_minutes = available_seconds / 60;
|
||||
const uint32_t minutes = available_minutes % 60;
|
||||
const uint32_t hours = available_minutes / 60;
|
||||
const std::string available_time =
|
||||
to_string_dec_uint(hours, 3, ' ') + ":" +
|
||||
to_string_dec_uint(minutes, 2, '0') + ":" +
|
||||
to_string_dec_uint(seconds, 2, '0');
|
||||
text_time_available.set(available_time);
|
||||
}*/
|
||||
}
|
||||
|
||||
void ReplayView::handle_replay_thread_done(const File::Error error) {
|
||||
stop();
|
||||
if( error.code() ) {
|
||||
handle_error(error);
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayView::handle_error(const File::Error error) {
|
||||
if( on_error ) {
|
||||
on_error(error.what());
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef __UI_REPLAY_VIEW_H__
|
||||
#define __UI_REPLAY_VIEW_H__
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
|
||||
#include "replay_thread.hpp"
|
||||
#include "signal.hpp"
|
||||
#include "bitmap.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ReplayView : public View {
|
||||
public:
|
||||
std::function<void(std::string)> on_error { };
|
||||
|
||||
ReplayView(
|
||||
const Rect parent_rect,
|
||||
const size_t read_size,
|
||||
const size_t buffer_count
|
||||
);
|
||||
~ReplayView();
|
||||
|
||||
void focus() override;
|
||||
|
||||
void set_file_list(const std::vector<std::filesystem::path>& file_list);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
bool is_active() const;
|
||||
|
||||
private:
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
|
||||
static constexpr uint32_t sampling_rate = 4000000;
|
||||
|
||||
void toggle();
|
||||
|
||||
void on_file_changed(const uint32_t duration);
|
||||
void on_tick_second();
|
||||
void update_status_display();
|
||||
|
||||
void handle_replay_thread_done(const File::Error error);
|
||||
void handle_error(const File::Error error);
|
||||
|
||||
const size_t read_size;
|
||||
const size_t buffer_count;
|
||||
//SignalToken signal_token_tick_second { };
|
||||
options_t file_options { };
|
||||
//std::filesystem:path file_path { };
|
||||
|
||||
Rectangle rect_background {
|
||||
Color::black()
|
||||
};
|
||||
|
||||
ImageButton button_play {
|
||||
{ 0 * 8, 0 * 16, 2 * 8, 1 * 16 },
|
||||
&bitmap_play,
|
||||
Color::green(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
OptionsField options_files {
|
||||
{ 2 * 8, 0 * 8 },
|
||||
8,
|
||||
{ }
|
||||
};
|
||||
|
||||
Text text_duration {
|
||||
{ 11 * 8, 0 * 8, 12 * 8, 16 },
|
||||
"-"
|
||||
};
|
||||
|
||||
/*Text text_time_seek {
|
||||
{ 18 * 8, 0 * 16, 9 * 8, 16 },
|
||||
"",
|
||||
};*/
|
||||
|
||||
std::unique_ptr<ReplayThread> replay_thread { };
|
||||
|
||||
MessageHandlerRegistration message_handler_replay_thread_error {
|
||||
Message::ID::CaptureThreadDone,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
|
||||
this->handle_replay_thread_done(message.error);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_REPLAY_VIEW_H__*/
|
@ -150,7 +150,7 @@ ViewWavView::ViewWavView(
|
||||
});
|
||||
|
||||
button_open.on_select = [this, &nav](Button&) {
|
||||
auto open_view = nav.push<FileLoadView>();
|
||||
auto open_view = nav.push<FileLoadView>(".WAV");
|
||||
open_view->on_changed = [this](std::filesystem::path file_path) {
|
||||
load_wav(file_path);
|
||||
field_pos_seconds.focus();
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "proc_replay.hpp"
|
||||
#include "sine_table_int8.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "event_m4.hpp"
|
||||
|
||||
@ -31,16 +32,18 @@ ReplayProcessor::ReplayProcessor() {
|
||||
channel_filter_pass_f = taps_200k_decim_1.pass_frequency_normalized * 1000000; // 162760.416666667
|
||||
channel_filter_stop_f = taps_200k_decim_1.stop_frequency_normalized * 1000000; // 337239.583333333
|
||||
|
||||
spectrum_interval_samples = (baseband_fs / 8) / spectrum_rate_hz;
|
||||
spectrum_interval_samples = baseband_fs / spectrum_rate_hz;
|
||||
spectrum_samples = 0;
|
||||
|
||||
channel_spectrum.set_decimation_factor(1);
|
||||
|
||||
configured = false;
|
||||
}
|
||||
|
||||
void ReplayProcessor::execute(const buffer_c8_t& buffer) {
|
||||
/* 4MHz, 2048 samples */
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
if (!configured) return;
|
||||
|
||||
// File data is in C16 format, we need C8
|
||||
// File samplerate is 500kHz, we're at 4MHz
|
||||
@ -51,37 +54,28 @@ void ReplayProcessor::execute(const buffer_c8_t& buffer) {
|
||||
// So 256 * 4 bytes per sample (C16) = 1024 bytes from the file
|
||||
if( stream ) {
|
||||
const size_t bytes_to_read = sizeof(*buffer.p) * 2 * (buffer.count / 8); // *2 (C16), /8 (oversampling) should be == 1024
|
||||
const auto result = stream->read(iq_buffer.p, bytes_to_read);
|
||||
bytes_read += stream->read(iq_buffer.p, bytes_to_read);
|
||||
}
|
||||
|
||||
//feed_channel_stats(channel);
|
||||
|
||||
// Zero-stuff
|
||||
// Fill and "stretch"
|
||||
for (size_t i = 0; i < buffer.count; i++) {
|
||||
|
||||
// DEBUG: This works. Transmits a 1kHz tone
|
||||
/*sample = (sine_table_i8[(tone_phase & 0xFF000000) >> 24]);
|
||||
tone_phase += (1000 * ((1ULL << 32) / baseband_fs));
|
||||
// Do FM
|
||||
delta = sample * 30000 * (0xFFFFFFULL / baseband_fs);
|
||||
phase += delta;
|
||||
sphase = phase + (64 << 24);
|
||||
iq_buffer.p[i >> 3] = { (int16_t)(sine_table_i8[(sphase & 0xFF000000) >> 24]) << 8, (int16_t)(sine_table_i8[(phase & 0xFF000000) >> 24]) << 8 };
|
||||
*/
|
||||
|
||||
/*if (i & 3)
|
||||
if (i & 3) {
|
||||
buffer.p[i] = buffer.p[i - 1];
|
||||
else {*/
|
||||
} else {
|
||||
auto re_out = iq_buffer.p[i >> 3].real() >> 8;
|
||||
auto im_out = iq_buffer.p[i >> 3].imag() >> 8;
|
||||
buffer.p[i] = { re_out, im_out };
|
||||
//}
|
||||
buffer.p[i] = { (int8_t)re_out, (int8_t)im_out };
|
||||
}
|
||||
}
|
||||
|
||||
spectrum_samples += buffer.count;
|
||||
if( spectrum_samples >= spectrum_interval_samples ) {
|
||||
spectrum_samples -= spectrum_interval_samples;
|
||||
channel_spectrum.feed(iq_buffer, channel_filter_pass_f, channel_filter_stop_f);
|
||||
|
||||
txprogress_message.progress = bytes_read; // Inform UI about progress
|
||||
txprogress_message.done = false;
|
||||
shared_memory.application_queue.push(txprogress_message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,8 +87,15 @@ void ReplayProcessor::on_message(const Message* const message) {
|
||||
break;
|
||||
|
||||
case Message::ID::ReplayConfig:
|
||||
configured = false;
|
||||
bytes_read = 0;
|
||||
replay_config(*reinterpret_cast<const ReplayConfigMessage*>(message));
|
||||
break;
|
||||
|
||||
// App has prefilled the buffers, we're ready to go now
|
||||
case Message::ID::FIFOData:
|
||||
configured = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -104,6 +105,9 @@ void ReplayProcessor::on_message(const Message* const message) {
|
||||
void ReplayProcessor::replay_config(const ReplayConfigMessage& message) {
|
||||
if( message.config ) {
|
||||
stream = std::make_unique<StreamOutput>(message.config);
|
||||
|
||||
// Tell application that the buffers and FIFO pointers are ready, prefill
|
||||
shared_memory.application_queue.push(sig_message);
|
||||
} else {
|
||||
stream.reset();
|
||||
}
|
||||
|
@ -47,26 +47,29 @@ private:
|
||||
|
||||
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit };
|
||||
|
||||
std::array<complex16_t, 256> iq { }; // This fits in just right in allocated RAM - Too big ?
|
||||
std::array<complex16_t, 256> iq { };
|
||||
const buffer_c16_t iq_buffer {
|
||||
iq.data(),
|
||||
iq.size()
|
||||
iq.size(),
|
||||
baseband_fs / 8
|
||||
};
|
||||
|
||||
uint32_t channel_filter_pass_f = 0;
|
||||
uint32_t channel_filter_stop_f = 0;
|
||||
|
||||
// DEBUG
|
||||
//uint32_t tone_phase { 0 }, phase { 0 }, delta { 0 }, sphase { 0 };
|
||||
//int8_t sample { 0 };
|
||||
|
||||
std::unique_ptr<StreamOutput> stream { };
|
||||
|
||||
SpectrumCollector channel_spectrum { };
|
||||
size_t spectrum_interval_samples = 0;
|
||||
size_t spectrum_samples = 0;
|
||||
|
||||
bool configured { false };
|
||||
uint32_t bytes_read { 0 };
|
||||
|
||||
void replay_config(const ReplayConfigMessage& message);
|
||||
|
||||
TXProgressMessage txprogress_message { };
|
||||
RequestSignalMessage sig_message { RequestSignalMessage::Signal::FillRequest };
|
||||
};
|
||||
|
||||
#endif/*__PROC_REPLAY_HPP__*/
|
||||
|
@ -51,8 +51,6 @@ size_t StreamOutput::read(void* const data, const size_t length) {
|
||||
// We need a full buffer...
|
||||
if( !fifo_buffers_full.out(active_buffer) ) {
|
||||
// ...but none are available. Hole in transmission (inform app and stop ?)
|
||||
//active_buffer = nullptr;
|
||||
//creg::m4txevent::assert();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -21,10 +21,6 @@
|
||||
|
||||
#include "buffer_exchange.hpp"
|
||||
|
||||
// DEBUG:
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
|
||||
BufferExchange* BufferExchange::obj { nullptr };
|
||||
|
||||
BufferExchange::BufferExchange(
|
||||
|
@ -55,7 +55,6 @@ public:
|
||||
return fifo_buffers_for_baseband->in(p);
|
||||
}
|
||||
|
||||
// TESTING...
|
||||
bool put_app(StreamBuffer* const p) {
|
||||
return fifo_buffers_for_application->in(p);
|
||||
}
|
||||
|
@ -70,49 +70,49 @@ struct Color {
|
||||
return { 255, 0, 0 };
|
||||
}
|
||||
static constexpr Color dark_red() {
|
||||
return { 127, 0, 0 };
|
||||
return { 191, 0, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color orange() {
|
||||
return { 255, 175, 0 };
|
||||
}
|
||||
static constexpr Color dark_orange() {
|
||||
return { 127, 88, 0 };
|
||||
return { 191, 88, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color yellow() {
|
||||
return { 255, 255, 0 };
|
||||
}
|
||||
static constexpr Color dark_yellow() {
|
||||
return { 127, 127, 0 };
|
||||
return { 191, 191, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color green() {
|
||||
return { 0, 255, 0 };
|
||||
}
|
||||
static constexpr Color dark_green() {
|
||||
return { 0, 127, 0 };
|
||||
return { 0, 191, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color blue() {
|
||||
return { 0, 0, 255 };
|
||||
}
|
||||
static constexpr Color dark_blue() {
|
||||
return { 0, 0, 127 };
|
||||
return { 0, 0, 191 };
|
||||
}
|
||||
|
||||
static constexpr Color cyan() {
|
||||
return { 0, 255, 255 };
|
||||
}
|
||||
static constexpr Color dark_cyan() {
|
||||
return { 0, 127, 127 };
|
||||
return { 0, 191, 191 };
|
||||
}
|
||||
|
||||
static constexpr Color magenta() {
|
||||
return { 255, 0, 255 };
|
||||
}
|
||||
static constexpr Color dark_magenta() {
|
||||
return { 127, 0, 127 };
|
||||
return { 191, 0, 191 };
|
||||
}
|
||||
|
||||
static constexpr Color white() {
|
||||
@ -120,10 +120,10 @@ struct Color {
|
||||
}
|
||||
|
||||
static constexpr Color light_grey() {
|
||||
return { 127, 127, 127 };
|
||||
return { 191, 191, 191 };
|
||||
}
|
||||
static constexpr Color grey() {
|
||||
return { 91, 91, 91 };
|
||||
return { 127, 127, 127 };
|
||||
}
|
||||
static constexpr Color dark_grey() {
|
||||
return { 63, 63, 63 };
|
||||
|
BIN
firmware/graphics/icon_file_image.png
Normal file
BIN
firmware/graphics/icon_file_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 146 B |
BIN
firmware/graphics/icon_file_iq.png
Normal file
BIN
firmware/graphics/icon_file_iq.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 B |
BIN
firmware/graphics/icon_file_text.png
Normal file
BIN
firmware/graphics/icon_file_text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 143 B |
Binary file not shown.
Loading…
Reference in New Issue
Block a user