Compare commits

...

88 Commits

Author SHA1 Message Date
summermorningdream e99fd4787a
Merge 9f0a0c55e5 into a3b71d0e3d 2024-05-07 11:21:38 +00:00
summermorningdream 9f0a0c55e5
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-05-07 19:21:35 +08:00
zxkmm 6c37d883a0 merge new changes 2024-04-30 23:05:53 +08:00
zxkmm 5d7cfda97b merge new changes 2024-04-28 15:33:50 +08:00
zxkmm 9fc45b32c9 merge new changes:wq 2024-04-18 18:17:03 +08:00
sommermorgentraum b27a313118
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-04-16 21:52:52 +08:00
zxkmm f2c86862c0 merge new changes 2024-04-11 22:53:52 +08:00
sommermorgentraum 8c0715408d
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-04-08 13:47:37 +08:00
sommermorgentraum 3eb6cf47ae
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-04-07 14:08:33 +08:00
sommermorgentraum c288f703da
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-04-07 10:08:03 +08:00
zxkmm 208a89090a Merge new changes 2024-04-06 11:37:35 +08:00
zxkmm 6b3ea87d86 Merge branch 'next' into sdcard_refactor_firmware_part 2024-04-06 00:48:13 +08:00
zxkmm 17b9231601 merge new changes 2024-04-04 10:00:27 +08:00
zxkmm cc89e2af9e log for automove 2024-04-04 09:45:40 +08:00
zxkmm 77ba7bde98 remove debug things 2024-04-04 09:30:55 +08:00
zxkmm e2940a52f2 comment 2024-04-04 00:26:47 +08:00
zxkmm 348ef17131 merge new changes 2024-04-04 00:10:12 +08:00
zxkmm c00dfeed3f worker tune per Nother request 2024-04-04 00:04:41 +08:00
zxkmm 7cbba2d2e7 merge new changes 2024-04-03 16:01:13 +08:00
zxkmm c36c9c9389 format 2024-04-03 15:49:59 +08:00
zxkmm a00543b4f8 format sstv 2024-04-03 15:46:20 +08:00
zxkmm 75a930c1fa format 2024-04-03 15:36:12 +08:00
zxkmm d3f618fa5b format 2024-04-03 15:27:51 +08:00
zxkmm 6d2b290daa gitignore 2024-04-03 14:48:07 +08:00
zxkmm 9e67e250b2 path change per requests 2024-04-03 14:47:03 +08:00
zxkmm 6b4abbc5f7 textual change for review requrest 2024-04-03 13:51:55 +08:00
zxkmm 1b410675f6 format 2024-04-03 12:42:30 +08:00
zxkmm 24ff586155 clean up 2024-04-03 12:37:36 +08:00
zxkmm 6cdcb16a3a fix bad path decleration 2024-04-03 11:43:28 +08:00
zxkmm 7a3b4966b4 modal layout tune 2024-04-03 08:29:57 +08:00
zxkmm 50af3c605f rename AUTO_REMOVE to AUTO_MOVE typo 2024-04-03 08:13:57 +08:00
zxkmm 6a56d743fc worker add a flag 2024-04-03 08:08:21 +08:00
zxkmm 2a903bf9e4 merge new changes, fix worker 2024-04-03 07:47:17 +08:00
zxkmm d150e39852 merge latest change 2024-04-02 23:28:57 +08:00
zxkmm d3e8260318 fix lambda logic 2024-04-02 22:56:19 +08:00
zxkmm fa596227ef textual 2024-04-02 20:39:51 +08:00
zxkmm d4296ed434 sstv 2024-04-02 19:55:17 +08:00
zxkmm 923324e931 remove debug things 2024-04-02 17:34:43 +08:00
zxkmm 98c1b05e81 textual 2024-04-02 16:52:10 +08:00
zxkmm 4ab6a38507 add auto mover 2024-04-02 16:03:12 +08:00
zxkmm 7d48624a78 move user profile into root 2024-04-02 14:48:44 +08:00
zxkmm 6c36d45005 rename RES into SYS, sorry for the typo above 2024-04-02 13:52:24 +08:00
zxkmm 940c2d7682 rename RES into USR 2024-04-02 13:47:34 +08:00
sommermorgentraum a08ccf4f2e
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-31 14:56:51 +08:00
zxkmm 5e10a41331 format 2024-03-30 20:45:19 +08:00
zxkmm a0a2ff9724 format 2024-03-30 20:41:34 +08:00
zxkmm 04966f2e0f format 2024-03-30 20:36:07 +08:00
zxkmm 5b5b5333e9 textual 2024-03-30 20:29:46 +08:00
sommermorgentraum 8d032438bd
Merge branch 'next' into sdcard_refactor_firmware_part 2024-03-30 20:24:45 +08:00
zxkmm 9460177fc9 fix recon and scanner casued by new changes 2024-03-30 20:23:53 +08:00
zxkmm 675925269c clean 2024-03-30 18:41:22 +08:00
zxkmm 119ebfe90e analog audio 2024-03-30 18:07:55 +08:00
zxkmm 457eb71014 fix for merged 2024-03-30 17:09:58 +08:00
sommermorgentraum 6fb09f6d59
Merge branch 'next' into sdcard_refactor_firmware_part 2024-03-30 16:06:00 +08:00
not tre mann e38c370d7d
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-15 21:57:26 +08:00
not tre mann b04bd4c0d9
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-15 12:01:35 +08:00
zxkmm c5039f2eb0 fix for comment 2024-03-15 00:49:54 +08:00
zxkmm 93825234f3 fix for comment 2024-03-15 00:43:16 +08:00
zxkmm 5181923fc6 fixed bug caused by 3a3c79a8ab 2024-03-14 11:37:31 +08:00
zxkmm 1451d49f8a revert 3a3c79a8ab because it cause a bug 2024-03-14 10:44:20 +08:00
not tre mann 3cd9faa24d
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-14 10:06:41 +08:00
not tre mann 6d638698d2
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-14 01:27:11 +08:00
zxkmm 3a3c79a8ab decided to let user can pop dir even in file picking view 2024-03-14 01:24:06 +08:00
zxkmm fa8ed6e9dd remove unneeded code in push and pop dir 2024-03-14 00:28:31 +08:00
not tre mann 7b4a79ee38
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-14 00:01:02 +08:00
not tre mann 7307703692
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-13 23:26:12 +08:00
zxkmm 7a52068de8 fix sdcard detect logic 2024-03-13 16:35:07 +08:00
zxkmm 30965ef083 fix shitty path connect 2024-03-13 16:32:37 +08:00
zxkmm 75eeab2368 remove short link 2024-03-13 15:59:36 +08:00
zxkmm 5f5aeb96f3 sstv remove duplict code 2024-03-13 15:57:34 +08:00
zxkmm bb774d362d sdcard_status_guard 2024-03-13 12:36:56 +08:00
zxkmm 4573a78ce0 format and textual 2024-03-13 12:03:51 +08:00
zxkmm 62b8e86381 format 2024-03-13 11:59:00 +08:00
zxkmm 77145d0514 add warning per Nother's request 2024-03-13 11:53:23 +08:00
zxkmm 8bd2f5bc1f splash redirect 2024-03-13 00:01:30 +08:00
zxkmm 7c61e65c0b textual 2024-03-12 21:19:58 +08:00
zxkmm 38c001bd1d textual 2024-03-12 20:59:59 +08:00
zxkmm 19f5d3db93 fix recon logic 2024-03-12 19:05:29 +08:00
zxkmm dc7f5ae35a implement user file cover res file if same name per request by @gullradriel - FREQMAN 2024-03-12 16:16:35 +08:00
zxkmm a95871162d implement user file cover res file if same name per request by @gullradriel - SSTV 2024-03-12 15:50:40 +08:00
zxkmm 30b4cc4e60 implement user file cover res file if same name per request by @gullradriel - SSTV 2024-03-12 15:49:57 +08:00
not tre mann 94ca23fc01
Merge branch 'portapack-mayhem:next' into sdcard_refactor_firmware_part 2024-03-12 12:01:25 +08:00
zxkmm 3167b584de git ignore 2024-03-11 16:52:54 +08:00
zxkmm e7543d102c rename SYS into RES 2024-03-11 16:36:39 +08:00
not tre mann 53b667abca
Merge branch 'next' into sdcard_refactor_firmware_part 2024-03-11 08:49:38 +08:00
zxkmm 8c9e64e61f fix sstv read file logic logic 2024-03-11 00:43:12 +08:00
zxkmm 1f26de2f4a merge #1965 into this branch 2024-03-10 21:31:37 +08:00
zxkmm 78e6ba9f70 seperate firmware change and sdcard change - firmware part 2024-03-10 21:07:48 +08:00
44 changed files with 717 additions and 213 deletions

6
.gitignore vendored
View File

@ -9,10 +9,16 @@
/firmware/application/portapack_cpld_data.cpp
/firmware/application/hackrf_cpld_data.cpp
/firmware/application/hackrf_cpld_data.hpp
/sdcard/SYS/ADSB/world_map.bin
/sdcard/SYS/FREQMAN/BHT*
/sdcard/SYS/FREQMAN/R.TXT
/sdcard/SYS/FREQMAN/XXX.TXT
/sdcard/ADSB/world_map.bin
/sdcard/FREQMAN/BHT*
/sdcard/FREQMAN/R.TXT
/sdcard/FREQMAN/XXX.TXT
# Toolchain binaries
/armbin
# Compiled Object files

View File

@ -33,6 +33,7 @@
#include "app_settings.hpp"
#include "radio_state.hpp"
#include "tone_key.hpp"
#include "file_path.hpp"
namespace ui {
@ -226,7 +227,7 @@ class AnalogAudioView : public View {
RecordView record_view{
{0 * 8, 2 * 16, 30 * 8, 1 * 16},
u"AUD",
u"AUDIO",
audio_dir_user,
RecordView::FileType::WAV,
4096,
4};

View File

@ -470,7 +470,7 @@ BLERxView::BLERxView(NavigationView& nav)
logging = v;
if (logger && logging)
logger->append(blerx_dir.string() + "/Logs/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
logger->append(blerx_dir_user.string() + "/Logs/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
};
check_log.set_value(logging);

View File

@ -134,7 +134,7 @@ class BleRecentEntryDetailView : public View {
void on_save_file(const std::string value, BLETxPacket packetToSave);
bool saveFile(const std::filesystem::path& path, BLETxPacket packetToSave);
std::string packetFileBuffer{};
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
std::filesystem::path packet_save_path{blerx_dir_user / u"Lists/????.csv"};
static constexpr uint8_t total_data_lines{5};
@ -251,9 +251,9 @@ class BLERxView : public View {
uint64_t total_count = 0;
std::vector<std::string> searchList{};
std::filesystem::path find_packet_path{blerx_dir / u"Find/????.TXT"};
std::filesystem::path log_packets_path{blerx_dir / u"Logs/????.TXT"};
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
std::filesystem::path find_packet_path{blerx_dir_user / u"Find/????.TXT"};
std::filesystem::path log_packets_path{blerx_dir_user / u"Logs/????.TXT"};
std::filesystem::path packet_save_path{blerx_dir_user / u"Lists/????.csv"};
static constexpr auto header_height = 4 * 16;
static constexpr auto switch_button_height = 3 * 16;

View File

@ -139,7 +139,7 @@ class BLETxView : public View {
uint32_t prev_value{0};
std::filesystem::path file_path{};
std::filesystem::path packet_save_path{bletx_dir / u"BLETX_????.TXT"};
std::filesystem::path packet_save_path{bletx_dir_user / u"BLETX_????.TXT"};
uint8_t channel_number = 37;
bool auto_channel = false;
@ -166,7 +166,7 @@ class BLETxView : public View {
std::unique_ptr<FileWrapper> dataFileWrapper{};
File dataFile{};
std::filesystem::path dataTempFilePath{bletx_dir / u"dataFileTemp.TXT"};
std::filesystem::path dataTempFilePath{bletx_dir_resources / u"dataFileTemp.TXT"};
std::vector<uint16_t> markedBytes{};
CursorPos cursor_pos{};
uint8_t marked_counter = 0;

View File

@ -102,7 +102,7 @@ class CaptureAppView : public View {
RecordView record_view{
{0 * 8, 2 * 16, 30 * 8, 1 * 16},
u"BBD_????.*",
captures_dir,
captures_dir_user,
RecordView::FileType::RawS16,
16384,
3};

View File

@ -95,9 +95,11 @@ void SoundBoardView::start_tx(const uint32_t id) {
stop();
if (!reader->open(u"/WAV/" + file_list[id].native())) {
file_error();
return;
if (!reader->open(wav_dir_resources + u"/" + file_list[id].native())) {
if (!reader->open(wav_dir_user + u"/" + file_list[id].native())) {
file_error();
return;
}
}
playing_id = id;
@ -164,28 +166,34 @@ void SoundBoardView::refresh_list() {
c_page = page;
// List directories and files, put directories up top
std::filesystem::path file_list_index[2];
file_list_index[0] = wav_dir_user;
file_list_index[1] = wav_dir_resources;
uint32_t count = 0;
for (const auto& entry : std::filesystem::directory_iterator(wav_dir, u"*")) {
if (std::filesystem::is_regular_file(entry.status())) {
if (entry.path().string().length()) {
auto entry_extension = entry.path().extension().string();
// tempnewnote: need test
for (const auto& now_path : file_list_index) {
for (const auto& entry : std::filesystem::directory_iterator(now_path, u"*")) {
if (std::filesystem::is_regular_file(entry.status())) {
if (entry.path().string().length()) {
auto entry_extension = entry.path().extension().string();
for (auto& c : entry_extension)
c = toupper(c);
for (auto& c : entry_extension)
c = toupper(c);
if (entry_extension == ".WAV") {
if (reader->open(wav_dir / entry.path())) {
if ((reader->channels() == 1) && ((reader->bits_per_sample() == 8) || (reader->bits_per_sample() == 16))) {
// sounds[c].ms_duration = reader->ms_duration();
// sounds[c].path = u"WAV/" + entry.path().native();
if (count >= (page - 1) * 100 && count < page * 100) {
file_list.push_back(entry.path());
if (file_list.size() == 100) {
page++;
break;
if (entry_extension == ".WAV") {
if (reader->open(now_path / entry.path().native())) {
if ((reader->channels() == 1) && ((reader->bits_per_sample() == 8) || (reader->bits_per_sample() == 16))) {
// sounds[c].ms_duration = reader->ms_duration();
// sounds[c].path = u"/SYS/WAV/" + entry.path().native();
if (count >= (page - 1) * 100 && count < page * 100) {
file_list.push_back(entry.path());
if (file_list.size() == 100) {
page++;
break;
}
}
count++;
}
count++;
}
}
}

View File

@ -233,7 +233,7 @@ class APRSRxView : public View {
RecordView record_view{
{0 * 8, 1 * 16, 30 * 8, 1 * 16},
u"AFS_????.WAV",
aprs_dir,
aprs_dir_user,
RecordView::FileType::WAV,
4096,
4};

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 Furrtek
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -49,6 +50,7 @@ static const fs::path cxx_ext{u".C*"};
static const fs::path png_ext{u".PNG"};
static const fs::path bmp_ext{u".BMP"};
static const fs::path rem_ext{u".REM"};
} // namespace ui
namespace {
@ -227,7 +229,7 @@ void FileManBaseView::load_directory_contents(const fs::path& dir_path) {
auto filtering = !extension_filter.empty();
bool cxx_file = path_iequal(cxx_ext, extension_filter);
text_current.set(dir_path.empty() ? "(sd root)" : truncate(dir_path, 24));
text_current.set(current_path.empty() ? "/" : truncate(dir_path, 24));
for (const auto& entry : fs::directory_iterator(dir_path, u"*")) {
// Hide files starting with '.' (hidden / tmp).
@ -237,6 +239,7 @@ void FileManBaseView::load_directory_contents(const fs::path& dir_path) {
if (fs::is_regular_file(entry.status())) {
if (!filtering || path_iequal(entry.path().extension(), extension_filter) || (cxx_file && is_cxx_capture_file(entry.path())))
insert_sorted(entry_list, {entry.path().string(), (uint32_t)entry.size(), false});
} else if (fs::is_directory(entry.status())) {
insert_sorted(entry_list, {entry.path().string(), 0, true});
}
@ -291,6 +294,8 @@ FileManBaseView::FileManBaseView(
extension_filter{filter} {
add_children({&labels,
&text_current,
&option_profile_switch,
&label_profile,
&button_exit});
button_exit.on_select = [this](Button&) {
@ -313,6 +318,24 @@ FileManBaseView::FileManBaseView(
pop_dir();
};
}
option_profile_switch.on_change = [this](size_t, uint8_t profiles) {
switch (static_cast<DirProfiles>(profiles)) {
case DirProfiles::User:
jumping_between_profiles(current_path, DirProfiles::User);
option_profile_switch.set_style(nullptr);
break;
case DirProfiles::System:
jumping_between_profiles(current_path, DirProfiles::System);
option_profile_switch.set_style(&Styles::red);
break;
}
reload_current();
};
}
void FileManBaseView::focus() {
@ -324,8 +347,29 @@ void FileManBaseView::focus() {
}
void FileManBaseView::push_dir(const fs::path& path) {
// if you want it freely jump between profiles when picking files in your app, don't use this
// , you should use push_fake_dir, which handle and call back the dir automatically
if (path == parent_dir_path) {
pop_dir();
} else if (path == system_dir || path == apps_dir || path == firmware_dir) {
nav_.push<ModalMessageView>(
"Warning",
"It is not recommended to\n"
"modify system files,\n"
"so you can easily\n"
"update sdcard content.\n"
"You can add all the custom\n"
"files in root folders.\n"
"Continue anyway?",
YESNO,
[this, path](bool choice) {
if (choice) {
current_path /= path;
saved_index_stack.push_back(menu_view.highlighted_index());
menu_view.set_highlighted(0);
reload_current();
}
});
} else {
current_path /= path;
saved_index_stack.push_back(menu_view.highlighted_index());
@ -334,14 +378,33 @@ void FileManBaseView::push_dir(const fs::path& path) {
}
}
void FileManBaseView::pop_dir() {
if (saved_index_stack.empty())
return;
void FileManBaseView::push_fake_dir(const fs::path& path) {
// the one this accepted is just a flag (e.g. CAPTURE, instead of /SYS/CAPTURE nor /CAPTURE), not real dir
// after passing the flag here, this func will handle it automatically and make callback automatically
fs::path first_level = path.extract_first_level();
const fs::path default_mother_dir = user_dir;
current_path = current_path.parent_path();
reload_current(true);
menu_view.set_highlighted(saved_index_stack.back());
saved_index_stack.pop_back();
if (first_level != user_dir && first_level != system_dir) {
current_path = default_mother_dir / path;
saved_index_stack.push_back(
menu_view.highlighted_index()); // TODO: do we really want to allow user to redirect to other dir tho?
menu_view.set_highlighted(0);
reload_current();
}
}
void FileManBaseView::pop_dir() {
if (saved_index_stack.empty() && current_path == u"/") {
return;
} else if (saved_index_stack.empty()) {
current_path = u"";
reload_current();
} else {
current_path = current_path.parent_path();
reload_current();
menu_view.set_highlighted(saved_index_stack.back());
saved_index_stack.pop_back();
}
}
std::string get_extension(std::string t) {
@ -388,8 +451,10 @@ void FileManBaseView::refresh_list() {
}
menu_view.add_item(
{entry_name.substr(0, max_filename_length) + std::string(21 - entry_name.length(), ' ') + size_str,
ui::Color::yellow(),
{entry_name + std::string(21 - entry_name.length(), ' ') + size_str,
(entry.path == system_dir || entry.path == apps_dir || entry.path == firmware_dir) ? Color::red() : Color::yellow(),
&bitmap_icon_dir,
[this](KeyEvent key) {
if (on_select_entry)
@ -420,6 +485,31 @@ void FileManBaseView::reload_current(bool reset_pagination) {
refresh_list();
}
fs::path FileManBaseView::jumping_between_profiles(fs::path& path, DirProfiles profile) {
fs::path first_level = path.extract_first_level();
const fs::path null_path = u"";
if (profile == DirProfiles::User) {
if (first_level == system_dir) { // /SYS/abcdef
path = path.remove_first_level();
} else if (first_level == null_path) { // /abcdef
// this is for: after user redirected to other dir and then switch to user profile
path = user_dir;
}
} else if (profile == DirProfiles::System) {
if (first_level == null_path && path != system_dir) { // /abcdef
// the second argument is for preventing circuling enter system dir
path = system_dir / path;
} else if (first_level == system_dir) { // /SYS/abcdef
// this is for: after user redirected to other dir and then switch to system profile
path = system_dir;
}
}
return path;
}
const FileManBaseView::file_assoc_t& FileManBaseView::get_assoc(
const fs::path& ext) const {
size_t index = 0;
@ -547,7 +637,8 @@ void FileManagerView::refresh_widgets(const bool v) {
button_paste.hidden(v);
button_new_dir.hidden(v);
button_new_file.hidden(v);
option_profile_switch.hidden(!v);
label_profile.hidden(!v);
set_dirty();
}
@ -752,7 +843,8 @@ FileManagerView::FileManagerView(
} else {
text_date.set_style(&Styles::grey);
if (selected_is_valid())
text_date.set((is_directory(get_selected_full_path()) ? "Created " : "Modified ") + to_string_FAT_timestamp(file_created_date(get_selected_full_path())));
text_date.set((is_directory(get_selected_full_path()) ? "Created " : "Modified ") +
to_string_FAT_timestamp(file_created_date(get_selected_full_path())));
else
text_date.set("");
}
@ -862,5 +954,4 @@ FileManagerView::FileManagerView(
reload_current();
};
}
} // namespace ui

View File

@ -48,6 +48,11 @@ enum class ClipboardMode : uint8_t {
Copy
};
enum class DirProfiles : uint8_t {
User = 1,
System = 2
};
class FileManBaseView : public View {
public:
FileManBaseView(
@ -59,6 +64,7 @@ class FileManBaseView : public View {
void focus() override;
std::string title() const override { return "Fileman"; };
void push_dir(const std::filesystem::path& path);
void push_fake_dir(const std::filesystem::path& path);
protected:
uint32_t prev_highlight = 0;
@ -95,6 +101,9 @@ class FileManBaseView : public View {
void reload_current(bool reset_pagination = false);
void load_directory_contents(const std::filesystem::path& dir_path);
void load_directory_contents_unordered(const std::filesystem::path& dir_path, size_t file_cnt);
std::filesystem::path jumping_between_profiles(std::filesystem::path& path, DirProfiles profile);
const file_assoc_t& get_assoc(const std::filesystem::path& ext) const;
NavigationView& nav_;
@ -106,6 +115,7 @@ class FileManBaseView : public View {
const std::string str_back{"<--"};
const std::string str_next{"-->"};
const std::string str_full{"Can't load more.."};
const std::filesystem::path parent_dir_path{u".."};
std::filesystem::path current_path{u""};
std::filesystem::path extension_filter{u""};
@ -116,10 +126,10 @@ class FileManBaseView : public View {
bool show_hidden_files{false};
Labels labels{
{{0, 0}, "Path:", Color::light_grey()}};
{{0, 0}, "\u007F", Color::white()}};
Text text_current{
{6 * 8, 0 * 8, 24 * 8, 16},
{1 * 8, 0 * 8, 20 * 8, 16},
"",
};
@ -127,6 +137,16 @@ class FileManBaseView : public View {
{0, 2 * 8, 240, 26 * 8},
true};
OptionsField option_profile_switch{
{11 * 8, 32 * 8},
16,
{{"User Directory ", 1},
{"System Directory", 2}}};
Labels label_profile{
{{0 * 8, 32 * 8}, "Profile: ", Color::light_grey()},
{{9 * 8, 32 * 8}, "\u007F/", Color::white()}};
Button button_exit{
{22 * 8, 34 * 8, 8 * 8, 32},
"Exit"};

View File

@ -2,6 +2,7 @@
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2023 Kyle Reed
* copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -96,7 +97,11 @@ void FreqManBaseView::focus() {
if (error_ == ERROR_ACCESS) {
nav_.display_modal("Error", "File access error", ABORT);
} else if (error_ == ERROR_NOFILES) {
nav_.display_modal("Error", "No database files\nin /FREQMAN", ABORT);
nav_.display_modal("Error",
"No database files\nin either" +
freqman_dir_user.string() +
"\nor" + freqman_dir_resources.string(),
ABORT);
} else {
options_category.focus();
}
@ -107,7 +112,15 @@ void FreqManBaseView::change_category(size_t new_index) {
return;
current_category_index = new_index;
if (!db_.open(get_freqman_path(current_category()))) {
current_is_system_item = false;
if (!db_.open(get_freqman_path(current_category(), dir_profile::ProfileUser))) {
current_is_system_item = true;
}
if (current_is_system_item && // <<< this means that entered previus condition, it's a work around to save 1 byte of ram
(!db_.open(
get_freqman_path(current_category(), dir_profile::ProfileSystem)))) {
error_ = ERROR_ACCESS;
}
@ -117,15 +130,20 @@ void FreqManBaseView::change_category(size_t new_index) {
void FreqManBaseView::refresh_categories() {
OptionsField::options_t new_categories;
scan_root_files(
freqman_dir, u"*.TXT", [&new_categories](const fs::path& path) {
// Skip temp/hidden files.
if (path.empty() || path.native()[0] == u'.')
return;
auto load_files = [&new_categories](const fs::path& dir) {
scan_root_files(
dir, u"*.TXT", [&new_categories](const fs::path& path) {
// Skip temp/hidden files.
if (path.empty() || path.native()[0] == u'.')
return;
// The UI layer will truncate long file names when displaying.
new_categories.emplace_back(path.stem().string(), new_categories.size());
});
// The UI layer will truncate long file names when displaying.
new_categories.emplace_back(path.stem().string(), new_categories.size());
});
};
load_files(freqman_dir_resources);
load_files(freqman_dir_user);
// Alphabetically sort the categories.
std::sort(new_categories.begin(), new_categories.end(), [](auto& left, auto& right) {
@ -163,9 +181,17 @@ FrequencySaveView::FrequencySaveView(
bind(field_description, entry_.description, nav);
button_save.on_select = [this, &nav](Button&) {
db_.insert_entry(db_.entry_count(), entry_);
nav_.pop();
button_save.on_select = [this, &nav](Button&) { // TODO: don't list system category here
if (current_is_system_item) {
nav.display_modal("Forbid",
"Can't save to\n"
"system category.\n"
"Please save to \n"
"a user category.");
} else {
db_.insert_entry(db_.entry_count(), entry_);
nav_.pop();
}
};
}
@ -238,6 +264,7 @@ void FrequencyManagerView::on_edit_desc() {
}
void FrequencyManagerView::on_add_category() {
ensure_directory(freqman_dir_user);
temp_buffer_.clear();
text_prompt(nav_, temp_buffer_, 20, [this](std::string& new_name) {
if (!new_name.empty()) {
@ -252,8 +279,8 @@ void FrequencyManagerView::on_del_category() {
"Delete", "Delete " + current_category() + "\nAre you sure?", YESNO,
[this](bool choice) {
if (choice) {
db_.close(); // Ensure file is closed.
auto path = get_freqman_path(current_category());
db_.close(); // Ensure file is closed.
auto path = get_freqman_path(current_category(), dir_profile::ProfileUser); // only allow del user's
delete_file(path);
refresh_categories();
}
@ -285,6 +312,19 @@ void FrequencyManagerView::on_del_entry() {
}
});
}
bool FrequencyManagerView::forbid_delete_system_item_helper(NavigationView& nav) {
// this is just a modal, however, it's been forbidden in those handler.
if (current_is_system_item) {
nav.display_modal("Forbid",
"Can't do that to \n"
"system item.\n"
"If you have to,\n"
"do it with File Manager");
}
return current_is_system_item;
}
FrequencyManagerView::FrequencyManagerView(
NavigationView& nav)
@ -309,31 +349,44 @@ FrequencyManagerView::FrequencyManagerView(
};
button_add_category.on_select = [this]() {
// this one will only directly add to /FREQMAN
on_add_category();
};
button_del_category.on_select = [this]() {
on_del_category();
button_del_category.on_select = [this, &nav]() {
if (!forbid_delete_system_item_helper(nav)) {
on_del_category();
}
};
button_edit_entry.on_select = [this](Button&) {
on_edit_entry();
button_edit_entry.on_select = [this, &nav](Button&) {
if (!forbid_delete_system_item_helper(nav)) {
on_edit_entry();
}
};
button_edit_freq.on_select = [this](Button&) {
on_edit_freq();
button_edit_freq.on_select = [this, &nav](Button&) {
if (!forbid_delete_system_item_helper(nav)) {
on_edit_freq();
}
};
button_edit_desc.on_select = [this](Button&) {
on_edit_desc();
button_edit_desc.on_select = [this, &nav](Button&) {
if (!forbid_delete_system_item_helper(nav)) {
on_edit_desc();
}
};
button_add_entry.on_select = [this]() {
on_add_entry();
button_add_entry.on_select = [this, &nav]() {
if (!forbid_delete_system_item_helper(nav)) {
on_add_entry();
}
};
button_del_entry.on_select = [this]() {
on_del_entry();
button_del_entry.on_select = [this, &nav]() {
if (!forbid_delete_system_item_helper(nav)) {
on_del_entry();
}
};
}

View File

@ -2,6 +2,7 @@
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2023 Kyle Reed
* copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -123,6 +124,7 @@ class FrequencyManagerView : public FreqManBaseView {
std::string title() const override { return "Freqman"; }
private:
bool forbid_delete_system_item_helper(NavigationView& nav);
std::string temp_buffer_{};
void on_edit_entry();

View File

@ -38,6 +38,8 @@
#include "radio_state.hpp"
#include "pocsag_app.hpp"
#include "file_path.hpp"
#include <functional>
class FskRxLogger {
@ -160,7 +162,7 @@ class FskxRxMainView : public View {
RecordView record_view{
{0 * 8, 4 * 16, 30 * 8, 1 * 16},
u"FSKRX_????.C16",
u"FSKRX",
fskrx_dir_user,
RecordView::FileType::RawS16,
16384,
3};

View File

@ -48,7 +48,7 @@ IQTrimView::IQTrimView(NavigationView& nav)
field_path.on_select = [this](TextField&) {
auto open_view = nav_.push<FileLoadView>(".C*");
open_view->push_dir(captures_dir);
open_view->push_fake_dir(captures_dir);
open_view->on_changed = [this](fs::path path) {
open_file(path);
};

View File

@ -573,6 +573,8 @@ void GlassView::set_spec_iq_phase_calibration_value(uint8_t cal_value) { // def
void GlassView::load_presets() {
File presets_file;
auto error = presets_file.open(looking_glass_dir / u"PRESETS.TXT");
// TODO: this app originally ain't support user load list.
// should support, but ain't have funtionality loss in sdcard refactor PR.
presets_db.clear();
// Add the "Manual" entry.

View File

@ -131,7 +131,7 @@ void PlaylistView::open_file(bool prompt_save) {
}
auto open_view = nav_.push<FileLoadView>(".PPL");
open_view->push_dir(playlist_dir);
open_view->push_fake_dir(playlist_dir);
open_view->on_changed = [this](fs::path new_file_path) {
on_file_changed(new_file_path);
};
@ -170,7 +170,7 @@ void PlaylistView::save_file(bool show_dialogs) {
void PlaylistView::add_entry(fs::path&& path) {
if (playlist_path_.empty()) {
playlist_path_ = next_filename_matching_pattern(playlist_dir / u"PLAY_????.PPL");
playlist_path_ = next_filename_matching_pattern(playlist_dir_user / u"PLAY_????.PPL");
// Hack around focus getting called by ctor before parent is set.
if (parent())
@ -388,7 +388,7 @@ PlaylistView::PlaylistView(
&waterfall,
});
ensure_directory(playlist_dir);
ensure_fake_directories(playlist_dir);
waterfall.show_audio_spectrum_view(false);
field_frequency.set_value(transmitter_model.target_frequency());
@ -411,7 +411,7 @@ PlaylistView::PlaylistView(
if (is_active())
return;
auto open_view = nav_.push<FileLoadView>(".C*");
open_view->push_dir(captures_dir);
open_view->push_fake_dir(captures_dir);
open_view->on_changed = [this](fs::path path) {
add_entry(std::move(path));
};

View File

@ -337,7 +337,7 @@ ReconView::ReconView(NavigationView& nav)
// set record View
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"AUTO_AUDIO", audio_dir,
u"AUTO_AUDIO", audio_dir_user,
RecordView::FileType::WAV, 4096, 4);
record_view->set_filename_date_frequency(true);
record_view->set_auto_trim(false);
@ -680,7 +680,7 @@ ReconView::ReconView(NavigationView& nav)
open_view->on_changed = [this](std::vector<std::string> result) {
input_file = result[0];
output_file = result[1];
freq_file_path = get_freqman_path(output_file).string();
freq_file_path = get_freqman_path(output_file, dir_profile::ProfileUser).string();
load_persisted_settings();
ui_settings.save();
@ -731,7 +731,7 @@ ReconView::ReconView(NavigationView& nav)
file_name.set("=>");
// Loading input and output file from settings
freq_file_path = get_freqman_path(output_file).string();
freq_file_path = get_freqman_path(output_file, dir_profile::ProfileUser).string();
field_recon_match_mode.set_selected_index(recon_match_mode);
field_squelch.set_value(squelch);
@ -790,7 +790,10 @@ void ReconView::frequency_file_load() {
.load_ranges = load_ranges,
.load_hamradios = load_hamradios,
.load_repeaters = load_repeaters};
if (!load_freqman_file(file_input, frequency_list, options) || frequency_list.empty()) {
if (
(!load_freqman_file(file_input, frequency_list, options, dir_profile::ProfileSystem) &&
!load_freqman_file(file_input, frequency_list, options, dir_profile::ProfileUser)) ||
frequency_list.empty()) {
file_name.set_style(&Styles::red);
desc_cycle.set("...empty file...");
frequency_list.clear();
@ -1170,18 +1173,18 @@ size_t ReconView::change_mode(freqman_index_t new_mod) {
if (new_mod == SPEC_MODULATION) {
if (persistent_memory::recon_repeat_recorded()) {
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"RECON_REPEAT.C16", captures_dir,
u"RECON_REPEAT.C16", captures_dir_user,
RecordView::FileType::RawS16, 16384, 3);
record_view->set_filename_as_is(true);
} else {
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"AUTO_RAW", captures_dir,
u"AUTO_RAW", captures_dir_user,
RecordView::FileType::RawS16, 16384, 3);
record_view->set_filename_date_frequency(true);
}
} else {
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"AUTO_AUDIO", audio_dir,
u"AUTO_AUDIO", audio_dir_user,
RecordView::FileType::WAV, 4096, 4);
record_view->set_filename_date_frequency(true);
}

View File

@ -182,6 +182,7 @@ class ReconView : public View {
const std::filesystem::path repeat_rec_file = u"RECON_REPEAT.C16";
const std::filesystem::path repeat_rec_meta = u"RECON_REPEAT.TXT";
// tempnote: path const var removed
const size_t repeat_read_size{16384};
const size_t repeat_buffer_count{3};
int8_t repeat_cur_rep = 0;

View File

@ -2,6 +2,7 @@
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -57,26 +58,30 @@ ReconSetupViewMain::ReconSetupViewMain(NavigationView& nav, Rect parent_rect, st
button_input_file.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->push_dir(freqman_dir);
open_view->push_fake_dir(freqman_dir); // the argu that push fake dir accepted is just a flag, so can safely hard coded
open_view->on_changed = [this, &nav](std::filesystem::path new_file_path) {
if (new_file_path.native().find((u"/" / freqman_dir).native()) == 0) {
if ((new_file_path.native().find((u"/" / freqman_dir_resources).native()) == 0) || new_file_path.native().find((freqman_dir_user).native()) == 0) {
_input_file = new_file_path.stem().string();
text_input_file.set(_input_file);
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
nav.display_modal("LOAD ERROR", "A valid file from\n" +
freqman_dir_user.string() +
"\nor\n" +
freqman_dir_resources.string() +
"\ndirectories is\nrequired.");
}
};
};
button_choose_output_file.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->push_dir(freqman_dir);
open_view->push_fake_dir(freqman_dir); // the argu that push fake dir accepted is just a flag, so can safely hard coded
open_view->on_changed = [this, &nav](std::filesystem::path new_file_path) {
if (new_file_path.native().find((u"/" / freqman_dir).native()) == 0) {
if (new_file_path.native().find((freqman_dir_user).native()) == 0) {
_output_file = new_file_path.stem().string();
button_choose_output_name.set_text(_output_file);
} else {
nav.display_modal("SAVE ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
nav.display_modal("SAVE ERROR", "A valid file from\n" + freqman_dir_user.string() + "\ndirectories is\nrequired.");
}
};
};

View File

@ -60,7 +60,7 @@
// screen size helper
#define SCREEN_W 240
//#define SCREEN_H 320
// #define SCREEN_H 320
// recon settings nb params
#define RECON_SETTINGS_NB_PARAMS 7

View File

@ -247,7 +247,7 @@ RemoteEntryEditView::RemoteEntryEditView(
field_path.on_select = [this, &nav](TextField&) {
auto open_view = nav.push<FileLoadView>(".C*");
open_view->push_dir(captures_dir);
open_view->push_fake_dir(captures_dir);
open_view->on_changed = [this](fs::path path) {
load_path(std::move(path));
refresh_ui();
@ -356,7 +356,7 @@ RemoteView::RemoteView(
Dim waterfall_height = waterfall_bottom - waterfall_top;
waterfall.set_parent_rect({0, waterfall_top, screen_width, waterfall_height});
ensure_directory(remotes_dir);
ensure_fake_directories(remotes_dir);
// Load the previously loaded remote if exists.
if (!load_remote(settings_.remote_path))
@ -528,7 +528,7 @@ void RemoteView::new_remote() {
void RemoteView::open_remote() {
auto open_view = nav_.push<FileLoadView>(".REM");
open_view->push_dir(remotes_dir);
open_view->push_fake_dir(remotes_dir);
open_view->on_changed = [this](fs::path path) {
save_remote();
load_remote(std::move(path));
@ -539,7 +539,7 @@ void RemoteView::open_remote() {
void RemoteView::init_remote() {
model_ = {"<Unnamed Remote>", {}};
reset_buttons();
set_remote_path(next_filename_matching_pattern(remotes_dir / u"REMOTE_????.REM"));
set_remote_path(next_filename_matching_pattern(remotes_dir_user / u"REMOTE_????.REM"));
set_needs_save(false);
if (remote_path_.empty())

View File

@ -2,6 +2,7 @@
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2018 Furrtek
* Copyright (C) 2023 Mark Thompson
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -336,13 +337,13 @@ ScannerView::ScannerView(
// Button to load a Freqman file.
button_load.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->push_dir(freqman_dir);
open_view->push_fake_dir(freqman_dir); // the argu that push fake dir accepted is just a flag, so can safely hard coded
open_view->on_changed = [this, &nav](std::filesystem::path new_file_path) {
if (new_file_path.native().find((u"/" / freqman_dir).native()) == 0) {
if ((new_file_path.native().find((u"/" / freqman_dir_resources).native()) == 0) || new_file_path.native().find((freqman_dir_user).native()) == 0) {
scan_pause();
frequency_file_load(new_file_path);
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directories is\nrequired.");
}
};
};
@ -491,7 +492,7 @@ ScannerView::ScannerView(
// Button to add current frequency (found during Search) to the Scan Frequency List
button_add.on_select = [this](Button&) {
FreqmanDB db;
if (db.open(get_freqman_path(freqman_file), /*create*/ true)) {
if (db.open(get_freqman_path(freqman_file, dir_profile::ProfileUser), /*create*/ true)) {
freqman_entry entry{
.frequency_a = current_frequency,
.type = freqman_type::Single,
@ -537,7 +538,7 @@ ScannerView::ScannerView(
receiver_model.set_squelch_level(0);
// LOAD FREQUENCIES
frequency_file_load(get_freqman_path(freqman_file));
frequency_file_load(get_freqman_path(freqman_file, dir_profile::ProfileUser));
}
void ScannerView::frequency_file_load(const fs::path& path) {

View File

@ -38,7 +38,7 @@
#define SCANNER_SLEEP_MS 50 // ms that Scanner Thread sleeps per loop
#define STATISTICS_UPDATES_PER_SEC 10
#define MAX_FREQ_LOCK 10 //# of 50ms cycles scanner locks into freq when signal detected, to verify signal is not spurious
#define MAX_FREQ_LOCK 10 // # of 50ms cycles scanner locks into freq when signal detected, to verify signal is not spurious
namespace ui {

View File

@ -5,7 +5,7 @@
* Copyright (C) 2023 Kyle Reed
* Copyright (C) 2024 Mark Thompson
* Copyright (C) 2024 u-foka
* Copyleft (ɔ) 2024 zxkmm under GPL license
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*

View File

@ -5,7 +5,7 @@
* Copyright (C) 2023 Kyle Reed
* Copyright (C) 2024 Mark Thompson
* Copyright (C) 2024 u-foka
* Copyleft (ɔ) 2024 zxkmm under GPL license
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*

View File

@ -27,7 +27,7 @@ namespace fs = std::filesystem;
namespace ui {
const std::filesystem::path splash_dot_bmp{u"/splash.bmp"};
const std::filesystem::path current_using_splash_image{u"/splash.bmp"};
ScreenshotViewer::ScreenshotViewer(
NavigationView& nav,
@ -108,8 +108,8 @@ SplashViewer::SplashViewer(
bool SplashViewer::on_key(const KeyEvent key) {
if (valid_image && key == KeyEvent::Right) {
delete_file(splash_dot_bmp);
copy_file(path_, splash_dot_bmp);
delete_file(current_using_splash_image);
copy_file(path_, current_using_splash_image);
}
nav_.pop();
@ -125,7 +125,7 @@ void SplashViewer::paint(Painter& painter) {
}
// Show option to set splash screen if it's not already the splash screen
if (!path_iequal(path_, splash_dot_bmp)) {
if (!path_iequal(path_, current_using_splash_image)) {
painter.draw_string({0, 0}, Styles::white, "*RIGHT BUTTON UPDATES SPLASH*");
valid_image = true;
}

View File

@ -32,7 +32,7 @@
namespace ui {
extern const std::filesystem::path splash_dot_bmp;
extern const std::filesystem::path current_using_splash_image;
class ScreenshotViewer : public View {
public:

View File

@ -25,6 +25,7 @@
#include "portapack.hpp"
#include "hackrf_hal.hpp"
#include "file_path.hpp"
#include <cstring>
#include <stdio.h>
@ -35,7 +36,13 @@ namespace ui {
void SSTVTXView::focus() {
if (file_error)
nav_.display_modal("No files", "No valid bitmaps\nin /sstv directory.", ABORT);
nav_.display_modal("No files",
"No valid bitmaps\nin either" +
sstv_dir.string() +
"\nor\n" +
sstv_dir_resources.string() +
"directory.",
ABORT);
else
options_bitmaps.focus();
}
@ -172,7 +179,10 @@ void SSTVTXView::start_tx() {
}
void SSTVTXView::on_bitmap_changed(const size_t index) {
bmp_file.open("/sstv/" + bitmaps[index].string());
auto open_system_dir = bmp_file.open(sstv_dir_user + u"/" + bitmaps[index].string());
if (!open_system_dir->ok()) {
bmp_file.open(sstv_dir_resources + u"/" + bitmaps[index].string());
}
bmp_file.read(&bmp_header, sizeof(bmp_header));
set_dirty();
}
@ -200,31 +210,47 @@ SSTVTXView::SSTVTXView(
NavigationView& nav)
: nav_(nav) {
std::vector<std::filesystem::path> file_list;
std::filesystem::path file_list_index[2];
using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>;
options_t bitmap_options;
options_t mode_options;
uint32_t c;
// Search for valid bitmaps
file_list = scan_root_files(u"/sstv", u"*.bmp");
if (!file_list.size()) {
file_error = true;
return;
}
for (const auto& file_name : file_list) {
if (!bmp_file.open("/sstv/" + file_name.string()).is_valid()) {
bmp_file.read(&bmp_header, sizeof(bmp_header));
if ((bmp_header.signature == 0x4D42) && // "BM"
(bmp_header.width == 320) && // Must be exactly 320x256 pixels for now
(bmp_header.height == 256) &&
(bmp_header.planes == 1) &&
(bmp_header.bpp == 24) && // 24 bpp only
(bmp_header.compression == 0)) { // No compression
bitmaps.push_back(file_name);
file_list_index[0] = sstv_dir_user;
file_list_index[1] = u"/" + sstv_dir_resources;
bool found_files = false;
for (const auto& now_path : file_list_index) {
file_list = scan_root_files(now_path, u"*.bmp");
if (!file_list.size()) {
continue; // Skip to the next path if no files found
}
found_files = true; // Mark that we found some files
for (const auto& file_name : file_list) {
if (!bmp_file.open(now_path / file_name).is_valid()) {
bmp_file.read(&bmp_header, sizeof(bmp_header));
if ((bmp_header.signature == 0x4D42) && // "BM"
(bmp_header.width == 320) && // Must be exactly 320x256 pixels for now
(bmp_header.height == 256) &&
(bmp_header.planes == 1) &&
(bmp_header.bpp == 24) && // 24 bpp only
(bmp_header.compression == 0)) { // No compression
bitmaps.push_back(file_name);
}
}
}
}
if (!found_files) {
file_error = true;
return;
}
if (!bitmaps.size()) {
file_error = true;
return;

View File

@ -80,8 +80,14 @@ class SSTVTXView : public View {
void prepare_scanline();
Labels labels{
{{1 * 8, 1 * 8}, "File:", Color::light_grey()},
{{1 * 8, 3 * 8}, "Mode:", Color::light_grey()}};
{{1 * 8, 1 * 8}, "Profile:", Color::light_grey()},
{{1 * 8, 3 * 8}, "File:", Color::light_grey()},
{{1 * 8, 5 * 8}, "Mode:", Color::light_grey()}};
OptionsField options_profile{
{6 * 8, 1 * 8},
16,
{}};
OptionsField options_bitmaps{
{6 * 8, 1 * 8},

View File

@ -144,7 +144,6 @@ WhipCalcView::WhipCalcView(NavigationView& nav)
void WhipCalcView::load_antenna_db() {
File antennas_file;
auto error = antennas_file.open(whipcalc_dir / u"ANTENNAS.TXT");
if (error)
return;

View File

@ -42,6 +42,7 @@ SpectrumInputImageView::SpectrumInputImageView(NavigationView& nav) {
ensure_directory(spectrum_dir);
open_view->push_dir(spectrum_dir);
// tempnewnote: const var removed
open_view->on_changed = [this](std::filesystem::path new_file_path) {
this->file = new_file_path.string();

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -22,6 +23,7 @@
#include "file.hpp"
#include "complex.hpp"
#include "file_path.hpp"
#include <algorithm>
#include <codecvt>
@ -368,6 +370,15 @@ std::filesystem::filesystem_error ensure_directory(
return make_new_directory(dir_path);
}
void ensure_fake_directories(
const std::filesystem::path& dir_path) {
std::filesystem::path combined_user_dir = user_dir / dir_path;
std::filesystem::path combimed_system_dir = system_dir / dir_path;
ensure_directory(combimed_system_dir);
ensure_directory(combined_user_dir);
}
namespace std {
namespace filesystem {
@ -454,6 +465,49 @@ path path::filename() const {
}
}
path path::remove_first_level() const { // /abc/def/ghi/hjk.q to /def/ghi/hjk.q
std::size_t start_index = _s.find(preferred_separator);
if (start_index == _s.npos) {
return _s;
} else {
start_index += 1; // To move past the first slash
std::size_t end_index = _s.find(preferred_separator, start_index);
if (end_index == _s.npos) {
end_index = _s.length(); // If there's no more slashes, end at the end of the string
}
return _s.substr(end_index);
}
}
path path::extract_first_level() const { // /abc/def/ghi/hjk.q to /abc
const auto first_separator = _s.find_first_of(preferred_separator);
if (first_separator == _s.npos) {
return _s;
} else {
const auto second_separator = _s.find_first_of(preferred_separator, first_separator + 1);
if (second_separator == _s.npos) {
return _s.substr(0, first_separator);
} else {
return _s.substr(0, second_separator);
}
}
}
path path::absolute_trimmed_path() const {
basic_string<char16_t> path_str = _s.substr();
if (path_str.front() == '/') {
path_str.erase(0, 1);
}
if (path_str.back() == '/') {
path_str.pop_back();
}
return path{path_str};
}
path path::stem() const {
const auto t = filename().native();
const auto index = t.find_last_of(u'.');

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -116,6 +117,9 @@ struct path {
path parent_path() const;
path extension() const;
path filename() const;
path remove_first_level() const;
path extract_first_level() const;
path absolute_trimmed_path() const;
path stem() const;
bool empty() const {
@ -276,6 +280,7 @@ std::filesystem::filesystem_error file_update_date(const std::filesystem::path&
std::filesystem::filesystem_error make_new_file(const std::filesystem::path& file_path);
std::filesystem::filesystem_error make_new_directory(const std::filesystem::path& dir_path);
std::filesystem::filesystem_error ensure_directory(const std::filesystem::path& dir_path);
void ensure_fake_directories(const std::filesystem::path& dir_path);
template <typename TCallback>
void scan_root_files(const std::filesystem::path& directory, const std::filesystem::path& extension, const TCallback& fn) {

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2024 Mark Thompson
* copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -22,28 +23,104 @@
#include "file_path.hpp"
#include "file.hpp"
const std::filesystem::path adsb_dir = u"ADSB";
const std::filesystem::path ais_dir = u"AIS";
const std::filesystem::path apps_dir = u"APPS";
const std::filesystem::path aprs_dir = u"APRS";
const std::filesystem::path audio_dir = u"AUDIO";
const std::filesystem::path blerx_dir = u"BLERX";
const std::filesystem::path bletx_dir = u"BLETX";
const std::filesystem::path captures_dir = u"CAPTURES";
const std::filesystem::path debug_dir = u"DEBUG";
const std::filesystem::path firmware_dir = u"FIRMWARE";
const std::filesystem::path freqman_dir = u"FREQMAN";
const std::filesystem::path gps_dir = u"GPS";
const std::filesystem::path logs_dir = u"LOGS";
const std::filesystem::path looking_glass_dir = u"LOOKINGGLASS";
const std::filesystem::path playlist_dir = u"PLAYLIST";
const std::filesystem::path remotes_dir = u"REMOTES";
const std::filesystem::path repeat_rec_path = u"CAPTURES";
const std::filesystem::path samples_dir = u"SAMPLES";
const std::filesystem::path screenshots_dir = u"SCREENSHOTS";
const std::filesystem::path settings_dir = u"SETTINGS";
const std::filesystem::path spectrum_dir = u"SPECTRUM";
const std::filesystem::path splash_dir = u"SPLASH";
const std::filesystem::path sstv_dir = u"SSTV";
const std::filesystem::path wav_dir = u"WAV";
const std::filesystem::path whipcalc_dir = u"WHIPCALC";
const std::filesystem::path adsb_dir = u"SYS/ADSB"; // this dir no need to seperate profiles since all are resources
const std::filesystem::path ais_dir = u"SYS/AIS"; // this dir no need to seperate profiles since all are resources
const std::filesystem::path apps_dir = u"APPS"; // currently in root
// APRS
const std::filesystem::path aprs_dir = u"APRS"; // fake path
const std::filesystem::path aprs_dir_user = u"/APRS";
const std::filesystem::path aprs_dir_resources = u"SYS/APRS";
// AUDIO
const std::filesystem::path audio_dir = u"AUDIO"; // fake path
const std::filesystem::path audio_dir_user = u"/AUDIO";
const std::filesystem::path audio_dir_resources = u"SYS/AUDIO";
// BLERX
const std::filesystem::path blerx_dir = u"BLERX"; // fake path
const std::filesystem::path blerx_dir_user = u"/BLERX";
const std::filesystem::path blerx_dir_resources = u"SYS/BLERX";
// BLETX
const std::filesystem::path bletx_dir = u"BLETX"; // fake path
const std::filesystem::path bletx_dir_user = u"/BLETX";
const std::filesystem::path bletx_dir_resources = u"SYS/BLETX";
// CAPTURES
const std::filesystem::path captures_dir = u"CAPTURES"; // fake path
const std::filesystem::path captures_dir_user = u"/CAPTURES"; // used by recon and capture apps to save capture C16 into USR
const std::filesystem::path captures_dir_resources = u"SYS/CAPTURES";
const std::filesystem::path debug_dir = u"DEBUG"; // in root
const std::filesystem::path firmware_dir = u"FIRMWARE"; // in root
// FREQMAN
const std::filesystem::path freqman_dir = u"FREQMAN"; // fake path
const std::filesystem::path freqman_dir_user = u"/FREQMAN";
const std::filesystem::path freqman_dir_resources = u"SYS/FREQMAN";
const std::filesystem::path fskrx_dir_user = u"/FSKRX";
const std::filesystem::path gps_dir = u"/GPS";
const std::filesystem::path logs_dir = u"/LOGS";
const std::filesystem::path looking_glass_dir = u"SYS/LOOKINGGLASS";
// PLAYLIST
const std::filesystem::path playlist_dir = u"PLAYLIST"; // fake dir
const std::filesystem::path playlist_dir_user = u"/PLAYLIST"; // used by playlist aka replay app, to save nre created PPL files into USR
const std::filesystem::path playlist_dir_resources = u"SYS/PLAYLIST"; //
// REMOTE
const std::filesystem::path remotes_dir = u"REMOTES"; // fake dir
const std::filesystem::path remotes_dir_user = u"/REMOTES";
const std::filesystem::path remotes_dir_resources = u"SYS/REMOTES";
// recon app
const std::filesystem::path repeat_rec_path = u"/CAPTURES"; // this is for recon captures files
const std::filesystem::path samples_dir = u"SYS/CAPTURES"; // TODO: rename var name
const std::filesystem::path screenshots_dir = u"/SCREENSHOTS"; // TODO: rename var name to screenshots_dir
const std::filesystem::path settings_dir = u"/SETTINGS";
const std::filesystem::path spectrum_dir = u"SPECTRUM"; // fake dir
const std::filesystem::path splash_dir = u"/SPLASH";
const std::filesystem::path sstv_dir = u"SSTV"; // fake path
const std::filesystem::path sstv_dir_user = u"/SSTV";
const std::filesystem::path sstv_dir_resources = u"SYS/SSTV";
const std::filesystem::path system_dir = u"/SYS"; // in root
const std::filesystem::path user_dir = u"/"; // root
// WAV
const std::filesystem::path wav_dir = u"WAV"; // fake path
const std::filesystem::path wav_dir_user = u"/WAV";
const std::filesystem::path wav_dir_resources = u"SYS/WAV";
const std::filesystem::path whipcalc_dir = u"SYS/WHIPCALC";
// vector
const std::vector<std::string> allow_dirs = {
"ADSB",
"AIS",
"BLETX",
"GPS",
"LOOKINGGLASS",
"PLAYLIST",
"REMOTES",
"SPLASH",
"SSTV",
"WAV",
"WHIPCALC",
"SAMPLES",
};

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2024 Mark Thompson
* copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -25,29 +26,83 @@
#include "file.hpp"
extern const std::filesystem::path adsb_dir;
extern const std::filesystem::path ais_dir;
extern const std::filesystem::path apps_dir;
extern const std::filesystem::path aprs_dir;
extern const std::filesystem::path aprs_dir_user;
extern const std::filesystem::path aprs_dir_resources;
extern const std::filesystem::path audio_dir;
extern const std::filesystem::path audio_dir_user;
extern const std::filesystem::path audio_dir_resources;
extern const std::filesystem::path blerx_dir;
extern const std::filesystem::path blerx_dir_user;
extern const std::filesystem::path blerx_dir_resources;
extern const std::filesystem::path bletx_dir;
extern const std::filesystem::path bletx_dir_user;
extern const std::filesystem::path bletx_dir_resources;
extern const std::filesystem::path captures_dir;
extern const std::filesystem::path captures_dir_user;
extern const std::filesystem::path captures_dir_resources;
extern const std::filesystem::path debug_dir;
extern const std::filesystem::path firmware_dir;
extern const std::filesystem::path freqman_dir;
extern const std::filesystem::path freqman_dir_user;
extern const std::filesystem::path freqman_dir_resources;
extern const std::filesystem::path fskrx_dir_user;
extern const std::filesystem::path gps_dir;
extern const std::filesystem::path logs_dir;
extern const std::filesystem::path looking_glass_dir;
extern const std::filesystem::path playlist_dir;
extern const std::filesystem::path playlist_dir_user;
extern const std::filesystem::path playlist_dir_resources;
extern const std::filesystem::path remotes_dir;
extern const std::filesystem::path remotes_dir_user;
extern const std::filesystem::path remotes_dir_resources;
extern const std::filesystem::path repeat_rec_path;
extern const std::filesystem::path samples_dir;
extern const std::filesystem::path screenshots_dir;
extern const std::filesystem::path settings_dir;
extern const std::filesystem::path spectrum_dir;
extern const std::filesystem::path splash_dir;
extern const std::filesystem::path sstv_dir;
extern const std::filesystem::path sstv_dir_user;
extern const std::filesystem::path sstv_dir_resources;
extern const std::filesystem::path system_dir;
extern const std::filesystem::path user_dir;
extern const std::filesystem::path wav_dir;
extern const std::filesystem::path wav_dir_user;
extern const std::filesystem::path wav_dir_resources;
extern const std::filesystem::path whipcalc_dir;
extern const std::vector<std::string> allow_dirs;
#endif /* __FILE_PATH_H__ */

View File

@ -3,6 +3,8 @@
* Copyright (C) 2016 Furrtek
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
* Copyright (C) 2023 Kyle Reed
* copyleft (ɔ) 2024 zxkmm with the GPL license
*
*
* This file is part of PortaPack.
*
@ -39,6 +41,7 @@
namespace fs = std::filesystem;
const std::filesystem::path freqman_extension{u".TXT"};
bool current_is_system_item{true};
// NB: Don't include UI headers to keep this code unit testable.
using option_t = std::pair<std::string, int32_t>;
@ -218,21 +221,32 @@ std::string freqman_entry_get_step_string_short(freqman_index_t step) {
return {};
}
const std::filesystem::path get_freqman_path(const std::string& stem) {
return freqman_dir / stem + freqman_extension;
const std::filesystem::path get_freqman_path(const std::string& stem, dir_profile profile) {
switch (profile) {
case dir_profile::ProfileSystem:
return freqman_dir_resources / stem + freqman_extension;
break;
case dir_profile::ProfileUser:
return freqman_dir_user / stem + freqman_extension;
break;
default:
// throw ?
return freqman_dir_user / stem + freqman_extension;
}
}
bool create_freqman_file(const std::string& file_stem) {
auto fs_error = make_new_file(get_freqman_path(file_stem));
// always create in user dir, so no judgement here
auto fs_error = make_new_file(get_freqman_path(file_stem, dir_profile::ProfileUser)); // only allow create on usr dir
return fs_error.ok();
}
bool load_freqman_file(const std::string& file_stem, freqman_db& db, freqman_load_options options) {
return parse_freqman_file(get_freqman_path(file_stem), db, options);
bool load_freqman_file(const std::string& file_stem, freqman_db& db, freqman_load_options options, dir_profile profile) {
return parse_freqman_file(get_freqman_path(file_stem, profile), db, options);
}
void delete_freqman_file(const std::string& file_stem) {
delete_file(get_freqman_path(file_stem));
delete_file(get_freqman_path(file_stem, dir_profile::ProfileUser)); // don't allow to delete sys files
}
std::string pretty_string(const freqman_entry& entry, size_t max_length) {

View File

@ -3,6 +3,7 @@
* Copyright (C) 2016 Furrtek
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
* Copyright (C) 2023 Kyle Reed
* copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -37,6 +38,7 @@
/* Defined in freqman_db.cpp */
extern const std::filesystem::path freqman_extension;
extern bool current_is_system_item;
using freqman_index_t = uint8_t;
constexpr freqman_index_t freqman_invalid_index = static_cast<freqman_index_t>(-1);
@ -60,6 +62,11 @@ enum class freqman_type : uint8_t {
Unknown,
};
enum class dir_profile : uint8_t {
ProfileUser = 1,
ProfileSystem = 2
};
/* Tables for next round of changes.
* // TODO: attempt to consolidate all of these values
* // and settings into a single location.
@ -177,9 +184,9 @@ using freqman_entry_ptr = std::unique_ptr<freqman_entry>;
using freqman_db = std::vector<freqman_entry_ptr>;
/* Gets the full path for a given file stem (no extension). */
const std::filesystem::path get_freqman_path(const std::string& stem);
const std::filesystem::path get_freqman_path(const std::string& stem, dir_profile profile);
bool create_freqman_file(const std::string& file_stem);
bool load_freqman_file(const std::string& file_stem, freqman_db& db, freqman_load_options options);
bool load_freqman_file(const std::string& file_stem, freqman_db& db, freqman_load_options options, dir_profile profile);
void delete_freqman_file(const std::string& file_stem);
/* Gets a pretty string representation for an entry. */

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* copyleft (ɔ) 2023 zxkmm under GPL license
* copyleft (ɔ) 2023 zxkmm with the GPL license
* Copyright (C) 2023 u-foka
*
* This file is part of PortaPack.

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* copyleft (ɔ) 2023 zxkmm under GPL license
* copyleft (ɔ) 2023 zxkmm with the GPL license
* Copyright (C) 2023 u-foka
*
* This file is part of PortaPack.

View File

@ -2,7 +2,7 @@
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2024 u-foka
* Copyleft (ɔ) 2024 zxkmm under GPL license
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -465,6 +465,11 @@ void SystemStatusView::set_back_hidden(bool new_value) {
void SystemStatusView::set_title_image_enabled(bool new_value) {
if (new_value) {
add_child(&button_title);
if (!already_shown_sdcard_warning_in_this_boot) {
// the modal warning can't be called from constructor since the nav isn't valid at that time, so putting here as a work around
new_sdcard_structure_checker();
already_shown_sdcard_warning_in_this_boot = true;
}
} else {
remove_child(&button_title);
}
@ -599,6 +604,93 @@ void SystemStatusView::rtc_battery_workaround() {
}
}
void SystemStatusView::new_sdcard_structure_checker() {
const std::filesystem::path root_dir = u"/";
const std::filesystem::path resources_dir = u"SYS";
std::vector<std::filesystem::path> directories = scan_root_directories(root_dir);
auto scan_result = std::find(directories.begin(), directories.end(), resources_dir);
auto sd_status = sd_card::status();
if (
nav_.is_valid() &&
(scan_result == directories.end()) &&
(sd_status == sd_card::Status::Mounted)) {
nav_.display_modal(
"Warning",
" WARNING!!!\n"
"SD Card content changed\n"
"in this update,\n"
"Press YES to auto move.\n"
"After finished,\n"
"you should move your own\n"
"files back into\n"
"original folders,\n"
"which are now only for users.\n"
"You can also choose NO,\n"
"and then manually merge\n"
"following the Wiki.\n"
"Details:\n"
"Mayhem wiki - Updating",
YESNO,
[this](bool choice) {
if (choice) {
new_sdcard_structure_worker();
}
},
true);
}
}
void SystemStatusView::new_sdcard_structure_worker() {
const std::filesystem::path root_dir = u"/";
const std::filesystem::path system_dir = u"SYS";
/// worker log
std::filesystem::path filename{};
File automove_dump_file{};
ensure_directory(logs_dir);
filename = next_filename_matching_pattern(logs_dir + "/AUTOMOVE_LOG_????.TXT");
automove_dump_file.create(filename);
std::vector<std::filesystem::path> root_dirs = scan_root_directories(root_dir);
std::vector<std::string> scan_result_string_vec;
for (const auto& e : root_dirs) {
scan_result_string_vec.push_back(e.string());
}
std::string scan_result_string = "";
for (const auto& e : scan_result_string_vec) {
scan_result_string += e + "\n";
}
automove_dump_file.write_line(scan_result_string + "\n\n");
/// worker moving folders
ensure_directory(system_dir);
auto directories = scan_root_directories(root_dir);
for (const auto& e : root_dirs) {
for (const auto& d : allow_dirs) {
if (e.absolute_trimmed_path().string() == d) {
std::filesystem::path new_path = system_dir / d;
rename_file(e, new_path);
automove_dump_file.write_line("Moved: " + e.string() + " to " + new_path.string() + "\n");
break;
}
}
}
/// worker renaming
rename_file(u"/SYS/SAMPLES", u"/SYS/CAPTURES"); // it's because, make it easier to use the sample folder.
/// worker check adding flag
make_new_file(U"/AUTO_MOVED"); // add a flag to check in case if need something as flag to check in the future
}
/* Information View *****************************************************/
InformationView::InformationView(
@ -1006,7 +1098,7 @@ BMPView::BMPView(NavigationView& nav) {
}
void BMPView::paint(Painter&) {
if (!portapack::display.drawBMP2({0, 0}, splash_dot_bmp))
if (!portapack::display.drawBMP2({0, 0}, current_using_splash_image))
portapack::display.drawBMP({(240 - 230) / 2, (320 - 50) / 2 - 10}, splash_bmp, false);
}
@ -1079,15 +1171,17 @@ void ModalMessageView::paint(Painter& painter) {
auto lines = split_string(message_, '\n');
for (size_t i = 0; i < lines.size(); ++i) {
painter.draw_string(
{1 * 8, (Coord)(((compact) ? 8 * 3 : 120) + (i * 16))},
style(),
lines[i]);
}
}
void ModalMessageView::focus() {
if ((type_ == YESNO)) {
button_yes.focus();
if (type_ == YESNO) {
button_no.focus(); // it should default to NO like all the operating system
} else {
button_ok.focus();
}

View File

@ -2,7 +2,7 @@
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2024 u-foka
* Copyleft (ɔ) 2024 zxkmm under GPL license
* Copyleft (ɔ) 2024 zxkmm with the GPL license
*
* This file is part of PortaPack.
*
@ -191,6 +191,7 @@ class SystemStatusView : public View {
void set_title(const std::string new_value);
private:
bool already_shown_sdcard_warning_in_this_boot{false};
static constexpr auto default_title = "";
bool batt_info_up = false; // to prevent show multiple batt info dialog
NavigationView& nav_;
@ -289,6 +290,10 @@ class SystemStatusView : public View {
void refresh();
void on_clk();
void rtc_battery_workaround();
void new_sdcard_structure_checker();
void new_sdcard_structure_worker();
void on_battery_data(const BatteryStateMessage* msg);
void on_battery_details();
@ -447,17 +452,17 @@ class ModalMessageView : public View {
const bool compact;
Button button_ok{
{10 * 8, 14 * 16, 10 * 8, 48},
{0, screen_height - 8 * 8, screen_width, 48},
"OK",
};
Button button_yes{
{5 * 8, 14 * 16, 8 * 8, 48},
{0, screen_height - 8 * 8, screen_width / 2, 48},
"YES",
};
Button button_no{
{17 * 8, 14 * 16, 8 * 8, 48},
{screen_width / 2, screen_height - 8 * 8, screen_width / 2, 48},
"NO",
};
};

View File

@ -1,6 +1,8 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
* Copyleft (ɔ) 2024 zxkmm under GPL license
* Copyleft (ɔ) 2024 zxkmm with the GPL license
* Copyright (C) 2024 u-foka
* Copyright (C) 2024 Mark Thompson
*
* This file is part of PortaPack.
*

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
* Copyleft (ɔ) 2024 zxkmm under GPL license
* Copyleft (ɔ) 2024 zxkmm with the GPL license
* Copyright (C) 2024 u-foka
* Copyright (C) 2024 Mark Thompson
*
@ -347,42 +347,6 @@ class IO {
addr(1); /* Set up for data phase (most likely after a command) */
}
// void high_contrast(ui::Color& pixel, size_t contrast_level_shift) { // TODO
// uint16_t r = (pixel.v >> 11) & 0x1F;
// uint16_t g = (pixel.v >> 5) & 0x3F;
// uint16_t b = pixel.v & 0x1F;
//
// if ((r << contrast_level_shift) > 0x1F) { // should be slightly smaller, need more obverse...
// r = 0x1F;
// } else {
// r = r << contrast_level_shift;
// }
//
// if ((g << contrast_level_shift) > 0x3F) { // same as above
// g = 0x3F;
// } else {
// g = g << contrast_level_shift;
// }
//
// if ((b << contrast_level_shift) > 0x1F) { // same as above
// b = 0x1F;
// } else {
// b = b << contrast_level_shift;
// }
//
// pixel.v = (r << 11) | (g << 5) | b;
// }
//
// void gray_scale(ui::Color& pixel) { // TODO: the blackwhite not looks right....
// uint16_t r = (pixel.v >> 11) & 0x1F;
// uint16_t g = (pixel.v >> 5) & 0x3F;
// uint16_t b = pixel.v & 0x1F;
//
// uint16_t average = (r + g + b) / 3;
//
// pixel.v = (average << 11) | (average << 5) | average;
// }
void lcd_write_data(const uint32_t value) __attribute__((always_inline)) {
// NOTE: Assumes and DIR=0 and ADDR=1 from command phase.
data_write_high(value); /* Drive high byte */

View File

@ -23,11 +23,11 @@ import sys
import struct
from PIL import Image
outfile = open('../../sdcard/ADSB/world_map.bin', 'wb')
outfile = open('../../sdcard/SYS/ADSB/world_map.bin', 'wb')
# Allow for bigger images
Image.MAX_IMAGE_PIXELS = None
im = Image.open("../../sdcard/ADSB/world_map.jpg")
im = Image.open("../../sdcard/SYS/ADSB/world_map.jpg")
pix = im.load()
# Write as unsigned short (2 bytes) as little endian
outfile.write(struct.pack('<H', im.size[0]))