mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-15 11:02:58 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ecbb232d9c | |||
| 0e59e61461 | |||
| 7da322f926 | |||
| 04392752d1 | |||
| db5fcaba44 | |||
| a8f0c8eac9 | |||
| 6fadd70c1d | |||
| 8d8d457da2 | |||
| 893df7272f | |||
| bb90fdc5fc | |||
| 50859171f4 | |||
| fc1b676ce6 | |||
| 776ac652a8 | |||
| c9c438824d | |||
| 95eb1e6d59 | |||
| 1f32367495 | |||
| 0ed5e6542e | |||
| 7240d45a4f | |||
| 17250304e0 | |||
| 835bc49999 | |||
| a6eb430830 | |||
| 8dd68a0811 | |||
| 9540776afd | |||
| f5d4fce945 | |||
| 8840a6e894 | |||
| 7ef98f7741 | |||
| b41be47c9d | |||
| 1e2bc703b8 | |||
| 9115eadd17 | |||
| 05429d3d15 | |||
| 30c1f9f594 | |||
| f994f8d697 | |||
| e045628dab | |||
| 17cdb34fea | |||
| 9df0f6e9df | |||
| 54e4b535cc | |||
| d6555a7af0 | |||
| 30004a1c3c | |||
| 8d60da0a5a | |||
| 17f30b6f26 | |||
| 3d13ee828e | |||
| 7b4662fe4a | |||
| 8fcedb017c | |||
| 7b3ab64930 | |||
| b856b047cc |
+1
-1
@@ -14,7 +14,7 @@ COPY ./ /havocsrc
|
||||
|
||||
#Fetch dependencies from APT
|
||||
RUN apt-get update && \
|
||||
apt-get install -y tar wget dfu-util cmake python bzip2 curl python3 python3-yaml && \
|
||||
apt-get install -y tar wget dfu-util cmake python bzip2 lz4 curl python3 python3-yaml && \
|
||||
apt-get -qy autoremove
|
||||
|
||||
#Install current pip from PyPa
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ COPY ./ /havocsrc
|
||||
# Fetch dependencies from APK
|
||||
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
|
||||
RUN apk update -U
|
||||
RUN apk add --no-cache git tar wget cmake curl bzip2 make
|
||||
RUN apk add --no-cache git tar wget cmake curl bzip2 lz4 make
|
||||
RUN apk add --no-cache dfu-util ccache icu-data-full
|
||||
RUN apk add --no-cache python3 py3-pip py3-yaml
|
||||
RUN apk add --no-cache py3-pyyaml-env-tag
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ WORKDIR /havoc/firmware
|
||||
|
||||
# Fetch dependencies from APT
|
||||
RUN apt-get update && \
|
||||
apt-get install -y git tar wget dfu-util cmake python3 ccache bzip2 curl && \
|
||||
apt-get install -y git tar wget dfu-util cmake python3 ccache bzip2 liblz4-tool curl && \
|
||||
apt-get -qy autoremove
|
||||
|
||||
#Install current pip from PyPa
|
||||
|
||||
@@ -10,7 +10,7 @@ WORKDIR /havoc/firmware
|
||||
# Fetch dependencies from APK
|
||||
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
|
||||
RUN apk update -U
|
||||
RUN apk add --no-cache git tar wget cmake curl bzip2 make
|
||||
RUN apk add --no-cache git tar wget cmake curl bzip2 lz4 make
|
||||
RUN apk add --no-cache dfu-util ccache icu-data-full
|
||||
RUN apk add --no-cache python3 py3-pip py3-yaml
|
||||
RUN apk add --no-cache py3-pyyaml-env-tag
|
||||
|
||||
@@ -28,6 +28,7 @@ set(CHIBIOS_PORTAPACK ${PROJECT_SOURCE_DIR}/chibios-portapack)
|
||||
set(EXTRACT_CPLD_DATA ${PROJECT_SOURCE_DIR}/tools/extract_cpld_data.py)
|
||||
set(MAKE_SPI_IMAGE ${PROJECT_SOURCE_DIR}/tools/make_spi_image.py)
|
||||
set(MAKE_IMAGE_CHUNK ${PROJECT_SOURCE_DIR}/tools/make_image_chunk.py)
|
||||
set(LZ4 lz4)
|
||||
|
||||
set(FIRMWARE_NAME portapack-h1_h2-mayhem)
|
||||
set(FIRMWARE_FILENAME ${FIRMWARE_NAME}.bin)
|
||||
|
||||
@@ -234,6 +234,8 @@ set(CPPSRC
|
||||
apps/ui_debug.cpp
|
||||
apps/ui_encoders.cpp
|
||||
apps/ui_fileman.cpp
|
||||
apps/ui_flash_utility.cpp
|
||||
apps/ui_sd_over_usb.cpp
|
||||
apps/ui_freqman.cpp
|
||||
apps/ui_jammer.cpp
|
||||
apps/ui_keyfob.cpp
|
||||
@@ -317,7 +319,10 @@ set(TCSRC)
|
||||
set(TCPPSRC)
|
||||
|
||||
# List ASM source files here
|
||||
set(ASMSRC ${PORTASM})
|
||||
set(ASMSRC
|
||||
${PORTASM}
|
||||
lz4.S
|
||||
)
|
||||
|
||||
set(INCDIR ${CMAKE_CURRENT_BINARY_DIR} ${COMMON} ${PORTINC} ${KERNINC} ${TESTINC}
|
||||
${HALINC} ${PLATFORMINC} ${BOARDINC}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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_flash_utility.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
Thread* FlashUtilityView::thread { nullptr };
|
||||
static constexpr size_t max_filename_length = 26;
|
||||
|
||||
FlashUtilityView::FlashUtilityView(NavigationView& nav) : nav_ (nav) {
|
||||
add_children({
|
||||
&labels,
|
||||
&menu_view
|
||||
});
|
||||
|
||||
menu_view.set_parent_rect({ 0, 3 * 8, 240, 33 * 8 });
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(u"FIRMWARE", u"*.bin")) {
|
||||
auto filename = entry.path().filename();
|
||||
auto path = entry.path().native();
|
||||
|
||||
menu_view.add_item({
|
||||
filename.string().substr(0, max_filename_length),
|
||||
ui::Color::red(),
|
||||
&bitmap_icon_temperature,
|
||||
[this, path]() {
|
||||
this->firmware_selected(path);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void FlashUtilityView::firmware_selected(std::filesystem::path::string_type path) {
|
||||
nav_.push<ModalMessageView>(
|
||||
"Warning!",
|
||||
"This will replace your\ncurrent firmware.\n\nIf things go wrong you are\nrequired to flash manually\nwith dfu.",
|
||||
YESNO,
|
||||
[this, path](bool choice) {
|
||||
if (choice) {
|
||||
std::u16string full_path = std::u16string(u"FIRMWARE/") + path;
|
||||
this->flash_firmware(full_path);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void FlashUtilityView::flash_firmware(std::filesystem::path::string_type path) {
|
||||
ui::Painter painter;
|
||||
painter.fill_rectangle(
|
||||
{ 0, 0, portapack::display.width(), portapack::display.height() },
|
||||
ui::Color::black()
|
||||
);
|
||||
|
||||
painter.draw_string({ 12, 24 }, this->nav_.style(), "This will take 15 seconds.");
|
||||
painter.draw_string({ 12, 64 }, this->nav_.style(), "Please wait while LEDs RX");
|
||||
painter.draw_string({ 12, 84 }, this->nav_.style(), "and TX are flashing.");
|
||||
painter.draw_string({ 12, 124 }, this->nav_.style(), "Then restart the device.");
|
||||
|
||||
std::memcpy(&shared_memory.bb_data.data[0], path.c_str(), (path.length() + 1) * 2);
|
||||
m4_init(portapack::spi_flash::image_tag_flash_utility, portapack::memory::map::m4_code, false);
|
||||
m0_halt();
|
||||
}
|
||||
|
||||
void FlashUtilityView::focus() {
|
||||
menu_view.focus();
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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_FLSH_UITILTY_H__
|
||||
#define __UI_FLSH_UITILTY_H__
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "ff.h"
|
||||
#include "baseband_api.hpp"
|
||||
#include "core_control.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ui {
|
||||
|
||||
class FlashUtilityView : public View {
|
||||
public:
|
||||
FlashUtilityView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Flash Utility"; };
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
bool confirmed = false;
|
||||
static Thread* thread;
|
||||
|
||||
Labels labels {
|
||||
{ { 4, 4 }, "Select firmware to flash:", Color::white() }
|
||||
};
|
||||
|
||||
MenuView menu_view {
|
||||
{ 0, 2 * 8, 240, 26 * 8 },
|
||||
true
|
||||
};
|
||||
|
||||
void firmware_selected(std::filesystem::path::string_type path);
|
||||
void flash_firmware(std::filesystem::path::string_type path);
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_FLSH_UITILTY_H__*/
|
||||
+1816
-1700
File diff suppressed because it is too large
Load Diff
@@ -42,367 +42,388 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ReconThread {
|
||||
public:
|
||||
ReconThread(freqman_db *database );
|
||||
~ReconThread();
|
||||
class ReconThread {
|
||||
public:
|
||||
ReconThread(freqman_db *database );
|
||||
~ReconThread();
|
||||
|
||||
void set_recon(const bool v);
|
||||
void set_freq_delete(const bool v);
|
||||
bool is_recon();
|
||||
void set_recon(const bool v);
|
||||
void set_freq_delete(const bool v);
|
||||
bool is_recon();
|
||||
|
||||
void set_lock_duration( const uint32_t v );
|
||||
uint32_t get_lock_duration();
|
||||
void set_lock_nb_match( const uint32_t v );
|
||||
void set_match_mode( const uint32_t v );
|
||||
uint32_t get_lock_nb_match();
|
||||
void set_lock_duration( const uint32_t v );
|
||||
uint32_t get_lock_duration();
|
||||
void set_lock_nb_match( const uint32_t v );
|
||||
void set_match_mode( const uint32_t v );
|
||||
uint32_t get_lock_nb_match();
|
||||
|
||||
void set_freq_lock(const uint32_t v);
|
||||
uint32_t is_freq_lock();
|
||||
int64_t get_current_freq();
|
||||
void set_freq_lock(const uint32_t v);
|
||||
uint32_t is_freq_lock();
|
||||
int64_t get_current_freq();
|
||||
|
||||
void set_stepper(const int64_t v);
|
||||
void set_stepper(const int64_t v);
|
||||
void set_index_stepper(const int64_t v);
|
||||
|
||||
void change_recon_direction();
|
||||
bool get_recon_direction();
|
||||
void set_recon_direction( const bool v);
|
||||
void change_recon_direction();
|
||||
bool get_recon_direction();
|
||||
void set_recon_direction( const bool v);
|
||||
|
||||
void set_continuous(const bool v);
|
||||
void set_continuous(const bool v);
|
||||
|
||||
void set_default_modulation( freqman_index_t index );
|
||||
freqman_index_t get_current_modulation();
|
||||
void set_default_bandwidth( freqman_index_t index );
|
||||
freqman_index_t get_current_bandwidth();
|
||||
void set_default_step( freqman_index_t index );
|
||||
void set_freq_index( int16_t index );
|
||||
int16_t get_freq_index();
|
||||
void set_default_modulation( freqman_index_t index );
|
||||
freqman_index_t get_current_modulation();
|
||||
void set_default_bandwidth( freqman_index_t index );
|
||||
freqman_index_t get_current_bandwidth();
|
||||
void set_default_step( freqman_index_t index );
|
||||
void set_freq_index( int16_t index );
|
||||
int16_t get_freq_index();
|
||||
|
||||
void run();
|
||||
void stop();
|
||||
void run();
|
||||
void stop();
|
||||
|
||||
ReconThread(const ReconThread&) = delete;
|
||||
ReconThread(ReconThread&&) = delete;
|
||||
ReconThread& operator=(const ReconThread&) = delete;
|
||||
ReconThread& operator=(ReconThread&&) = delete;
|
||||
ReconThread(const ReconThread&) = delete;
|
||||
ReconThread(ReconThread&&) = delete;
|
||||
ReconThread& operator=(const ReconThread&) = delete;
|
||||
ReconThread& operator=(ReconThread&&) = delete;
|
||||
|
||||
private:
|
||||
freqman_db &frequency_list_ ;
|
||||
Thread* thread { nullptr };
|
||||
int64_t freq = 0 ;
|
||||
uint32_t step = 0 ;
|
||||
freqman_index_t def_modulation = 0 ;
|
||||
freqman_index_t def_bandwidth = 0 ;
|
||||
freqman_index_t def_step = 0 ;
|
||||
tone_index tone = 0 ;
|
||||
freqman_entry last_entry = { } ;
|
||||
int16_t frequency_index = 0 ;
|
||||
private:
|
||||
freqman_db &frequency_list_ ;
|
||||
Thread* thread { nullptr };
|
||||
int64_t freq = 0 ;
|
||||
uint32_t step = 0 ;
|
||||
freqman_index_t def_modulation = 0 ;
|
||||
freqman_index_t def_bandwidth = 0 ;
|
||||
freqman_index_t def_step = 0 ;
|
||||
tone_index tone = 0 ;
|
||||
freqman_entry last_entry = { } ;
|
||||
int16_t frequency_index = 0 ;
|
||||
|
||||
bool _recon { true };
|
||||
bool _freq_delete { false };
|
||||
bool _fwd { true };
|
||||
bool _continuous { true };
|
||||
int64_t _stepper { 0 };
|
||||
int32_t _freq_lock { 0 };
|
||||
uint32_t _lock_duration { 50 };
|
||||
uint32_t _lock_nb_match { 10 };
|
||||
static msg_t static_fn(void* arg);
|
||||
};
|
||||
bool _recon { true };
|
||||
bool _freq_delete { false };
|
||||
bool _fwd { true };
|
||||
bool _continuous { true };
|
||||
bool entry_has_changed = false ;
|
||||
int64_t _stepper { 0 };
|
||||
int64_t _index_stepper { 0 };
|
||||
int32_t _freq_lock { 0 };
|
||||
uint32_t _lock_duration { 50 };
|
||||
uint32_t _lock_nb_match { 10 };
|
||||
static msg_t static_fn(void* arg);
|
||||
};
|
||||
|
||||
class ReconView : public View {
|
||||
public:
|
||||
ReconView(NavigationView& nav);
|
||||
~ReconView();
|
||||
class ReconView : public View {
|
||||
public:
|
||||
ReconView(NavigationView& nav);
|
||||
~ReconView();
|
||||
|
||||
void focus() override;
|
||||
void focus() override;
|
||||
|
||||
void big_display_freq( int64_t f );
|
||||
void big_display_freq( int64_t f );
|
||||
|
||||
const Style style_grey { // recon
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::grey(),
|
||||
};
|
||||
const Style style_grey { // recon
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::grey(),
|
||||
};
|
||||
|
||||
const Style style_white { // recon
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::white(),
|
||||
};
|
||||
const Style style_white { // recon
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::white(),
|
||||
};
|
||||
|
||||
const Style style_yellow { //Found signal
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::yellow(),
|
||||
};
|
||||
const Style style_yellow { //Found signal
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::yellow(),
|
||||
};
|
||||
|
||||
const Style style_green { //Found signal
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::green(),
|
||||
};
|
||||
const Style style_green { //Found signal
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::green(),
|
||||
};
|
||||
|
||||
const Style style_red { //erasing freq
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::red(),
|
||||
};
|
||||
const Style style_red { //erasing freq
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::red(),
|
||||
};
|
||||
|
||||
const Style style_blue { // quick recon, wait == 0
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::blue(),
|
||||
};
|
||||
const Style style_blue { // quick recon, wait == 0
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::blue(),
|
||||
};
|
||||
|
||||
std::string title() const override { return "Recon"; };
|
||||
std::string title() const override { return "Recon"; };
|
||||
|
||||
//void set_parent_rect(const Rect new_parent_rect) override;
|
||||
//void set_parent_rect(const Rect new_parent_rect) override;
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
void start_recon_thread();
|
||||
size_t change_mode( freqman_index_t mod_type);
|
||||
void show_max( bool refresh_display = false );
|
||||
void recon_pause();
|
||||
void recon_resume();
|
||||
void user_pause();
|
||||
void user_resume();
|
||||
void frequency_file_load( bool stop_all_before = false);
|
||||
void on_statistics_update(const ChannelStatistics& statistics);
|
||||
void on_headphone_volume_changed(int32_t v);
|
||||
void set_display_freq( int64_t freq );
|
||||
void handle_retune( int64_t freq , uint32_t index );
|
||||
bool check_sd_card();
|
||||
void start_recon_thread();
|
||||
size_t change_mode( freqman_index_t mod_type);
|
||||
void show_max( bool refresh_display = false );
|
||||
void recon_pause();
|
||||
void recon_resume();
|
||||
void user_pause();
|
||||
void user_resume();
|
||||
void frequency_file_load( bool stop_all_before = false);
|
||||
void on_statistics_update(const ChannelStatistics& statistics);
|
||||
void on_headphone_volume_changed(int32_t v);
|
||||
void set_display_freq( int64_t freq );
|
||||
void handle_retune( int64_t freq , uint32_t index );
|
||||
bool check_sd_card();
|
||||
void handle_coded_squelch(const uint32_t value);
|
||||
|
||||
jammer::jammer_range_t frequency_range { false, 0, 0 }; //perfect for manual recon task too...
|
||||
int32_t squelch { 0 };
|
||||
int32_t db { 0 };
|
||||
int32_t timer { 0 };
|
||||
int32_t wait { 5000 }; // in msec. if > 0 wait duration after a lock, if < 0 duration is set to 'wait' unless there is no more activity
|
||||
uint32_t lock_wait { 500 }; // in msec. Represent the maximum amount of time we will wait for a lock to complete before switching to next
|
||||
int32_t def_step { 0 };
|
||||
freqman_db frequency_list = { };
|
||||
uint32_t current_index { 0 };
|
||||
bool userpause { false };
|
||||
bool continuous_lock { false };
|
||||
std::string input_file = { "RECON" };
|
||||
std::string output_file = { "RECON_RESULTS" };
|
||||
bool autosave = { true };
|
||||
bool autostart = { true };
|
||||
bool continuous = { true };
|
||||
bool filedelete = { true };
|
||||
bool load_freqs = { true };
|
||||
bool load_ranges = { true };
|
||||
bool load_hamradios = { true };
|
||||
bool update_ranges = { true };
|
||||
bool fwd = { true };
|
||||
// maximum usable freq
|
||||
long long int MAX_UFREQ = { 7200000000 };
|
||||
uint32_t recon_lock_nb_match = { 10 };
|
||||
uint32_t recon_lock_duration = { 50 };
|
||||
uint32_t recon_match_mode = { 0 };
|
||||
bool scanner_mode { false };
|
||||
bool manual_mode { false };
|
||||
bool sd_card_mounted = false ;
|
||||
int32_t volume = 40 ;
|
||||
jammer::jammer_range_t frequency_range { false, 0, 0 }; //perfect for manual recon task too...
|
||||
int32_t squelch { 0 };
|
||||
int32_t db { 0 };
|
||||
int32_t timer { 0 };
|
||||
int32_t wait { 5000 }; // in msec. if > 0 wait duration after a lock, if < 0 duration is set to 'wait' unless there is no more activity
|
||||
uint32_t lock_wait { 500 }; // in msec. Represent the maximum amount of time we will wait for a lock to complete before switching to next
|
||||
int32_t def_step { 0 };
|
||||
freqman_db frequency_list = { };
|
||||
uint32_t current_index { 0 };
|
||||
bool userpause { false };
|
||||
bool continuous_lock { false };
|
||||
std::string input_file = { "RECON" };
|
||||
std::string output_file = { "RECON_RESULTS" };
|
||||
bool autosave = { true };
|
||||
bool autostart = { true };
|
||||
bool continuous = { true };
|
||||
bool filedelete = { true };
|
||||
bool load_freqs = { true };
|
||||
bool load_ranges = { true };
|
||||
bool load_hamradios = { true };
|
||||
bool update_ranges = { true };
|
||||
bool fwd = { true };
|
||||
// maximum usable freq
|
||||
long long int MAX_UFREQ = { 7200000000 };
|
||||
uint32_t recon_lock_nb_match = { 10 };
|
||||
uint32_t recon_lock_duration = { 50 };
|
||||
uint32_t recon_match_mode = { 0 };
|
||||
bool scanner_mode { false };
|
||||
bool manual_mode { false };
|
||||
bool sd_card_mounted = false ;
|
||||
int32_t volume = 40 ;
|
||||
|
||||
Labels labels
|
||||
{
|
||||
{ { 0 * 8 , 0 * 16 }, "LNA: VGA: AMP: VOL: ", Color::light_grey() },
|
||||
{ { 0 * 8 , 1 * 16 }, "BW: SQ: W,L: , ", Color::light_grey() },
|
||||
{ { 3 * 8 , 10 * 16 }, "START END MANUAL", Color::light_grey() },
|
||||
{ { 0 * 8 , (26 * 8) + 4 }, "MODE:", Color::light_grey() },
|
||||
{ { 11 * 8 , (26 * 8) + 4 }, "STEP:", Color::light_grey() },
|
||||
};
|
||||
Labels labels
|
||||
{
|
||||
{ { 0 * 8 , 0 * 16 }, "LNA: VGA: AMP: VOL: ", Color::light_grey() },
|
||||
{ { 0 * 8 , 1 * 16 }, "BW: SQ: W,L: , ", Color::light_grey() },
|
||||
{ { 3 * 8 , 10 * 16 }, "START END MANUAL", Color::light_grey() },
|
||||
{ { 0 * 8 , (26 * 8) + 4 }, "MODE:", Color::light_grey() },
|
||||
{ { 11 * 8 , (26 * 8) + 4 }, "STEP:", Color::light_grey() },
|
||||
};
|
||||
|
||||
LNAGainField field_lna {
|
||||
{ 4 * 8, 0 * 16 }
|
||||
};
|
||||
LNAGainField field_lna {
|
||||
{ 4 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
VGAGainField field_vga {
|
||||
{ 11 * 8, 0 * 16 }
|
||||
};
|
||||
VGAGainField field_vga {
|
||||
{ 11 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 18 * 8, 0 * 16 }
|
||||
};
|
||||
RFAmpField field_rf_amp {
|
||||
{ 18 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
NumberField field_volume {
|
||||
{ 24 * 8, 0 * 16 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
' ',
|
||||
};
|
||||
NumberField field_volume {
|
||||
{ 24 * 8, 0 * 16 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
' ',
|
||||
};
|
||||
|
||||
OptionsField field_bw {
|
||||
{ 3 * 8, 1 * 16 },
|
||||
6,
|
||||
{ }
|
||||
};
|
||||
OptionsField field_bw {
|
||||
{ 3 * 8, 1 * 16 },
|
||||
6,
|
||||
{ }
|
||||
};
|
||||
|
||||
NumberField field_squelch {
|
||||
{ 12 * 8, 1 * 16 },
|
||||
3,
|
||||
{ -90, 20 },
|
||||
1,
|
||||
' ',
|
||||
};
|
||||
NumberField field_squelch {
|
||||
{ 12 * 8, 1 * 16 },
|
||||
3,
|
||||
{ -90, 20 },
|
||||
1,
|
||||
' ',
|
||||
};
|
||||
|
||||
NumberField field_wait {
|
||||
{ 20 * 8, 1 * 16 },
|
||||
5,
|
||||
{ -9000, 9000 },
|
||||
100,
|
||||
' ',
|
||||
};
|
||||
NumberField field_wait {
|
||||
{ 20 * 8, 1 * 16 },
|
||||
5,
|
||||
{ -9000, 9000 },
|
||||
100,
|
||||
' ',
|
||||
};
|
||||
|
||||
NumberField field_lock_wait {
|
||||
{ 26 * 8, 1 * 16 },
|
||||
4,
|
||||
{ 100 , 9000 },
|
||||
100,
|
||||
' ',
|
||||
};
|
||||
NumberField field_lock_wait {
|
||||
{ 26 * 8, 1 * 16 },
|
||||
4,
|
||||
{ 100 , 9000 },
|
||||
100,
|
||||
' ',
|
||||
};
|
||||
|
||||
RSSI rssi {
|
||||
{ 0 * 16, 2 * 16, 240 - 4 * 8 , 16 },
|
||||
};
|
||||
RSSI rssi {
|
||||
{ 0 * 16, 2 * 16, 240 - 5 * 8 - 1 , 16 },
|
||||
};
|
||||
|
||||
Text text_cycle {
|
||||
{ 0, 3 * 16, 3 * 8, 16 },
|
||||
};
|
||||
ButtonWithEncoder text_cycle {
|
||||
{ 0, 3 * 16, 3 * 8, 16 },
|
||||
""
|
||||
};
|
||||
|
||||
Text text_max {
|
||||
{ 3 * 8, 3 * 16, 20 * 8 , 16 },
|
||||
};
|
||||
Text text_max {
|
||||
{ 3 * 8, 3 * 16, 20 * 8 , 16 },
|
||||
};
|
||||
|
||||
Text desc_cycle {
|
||||
{0, 4 * 16, 240 , 16 },
|
||||
};
|
||||
Text desc_cycle {
|
||||
{0, 4 * 16, 240 , 16 },
|
||||
};
|
||||
|
||||
/* BigFrequency big_display { //Show frequency in glamour
|
||||
{ 4, 7 * 16 - 8 , 28 * 8, 52 },
|
||||
0
|
||||
}; */
|
||||
/* BigFrequency big_display { //Show frequency in glamour
|
||||
{ 4, 7 * 16 - 8 , 28 * 8, 52 },
|
||||
0
|
||||
}; */
|
||||
|
||||
Text big_display { //Show frequency in text mode
|
||||
{ 0, 5 * 16 , 21 * 8, 16 },
|
||||
};
|
||||
Text big_display { //Show frequency in text mode
|
||||
{ 0, 5 * 16 , 21 * 8, 16 },
|
||||
};
|
||||
|
||||
Text freq_stats { //Show frequency stats in text mode
|
||||
{ 0, 6 * 16 , 21 * 8, 16 },
|
||||
};
|
||||
Text freq_stats { //Show frequency stats in text mode
|
||||
{ 0, 6 * 16 , 21 * 8, 16 },
|
||||
};
|
||||
|
||||
Text text_timer { //Show frequency stats in text mode
|
||||
{ 0, 7 * 16 , 21 * 8, 16 },
|
||||
};
|
||||
// TIMER: 9999
|
||||
Text text_timer { //Show frequency stats in text mode
|
||||
{ 0, 7 * 16 , 11 * 8, 16 },
|
||||
};
|
||||
|
||||
Button button_recon_setup {
|
||||
{ 240 - 4 * 8 , 2 * 16 , 4 * 8, 28 },
|
||||
"OPT"
|
||||
};
|
||||
// T: Senn. 32.000k
|
||||
Text text_ctcss {
|
||||
{ 12 * 8 + 4, 7 * 16 , 14 * 8, 1 * 8 },
|
||||
""
|
||||
};
|
||||
|
||||
Button button_looking_glass {
|
||||
{ 240 - 5 * 8 , 6 * 16 - 4 , 5 * 8, 28 },
|
||||
"GLASS"
|
||||
};
|
||||
Button button_recon_setup {
|
||||
{ 240 - 5 * 8 , 2 * 16 , 5 * 8, 28 },
|
||||
"OPT"
|
||||
};
|
||||
|
||||
Button button_scanner_mode {
|
||||
{ 240 - 8 * 8 , 8 * 16 , 8 * 8, 28 },
|
||||
"RECON"
|
||||
};
|
||||
Button button_looking_glass {
|
||||
{ 240 - 5 * 8 , 5 * 16 , 5 * 8, 28 },
|
||||
"GLASS"
|
||||
};
|
||||
|
||||
Text file_name { //Show file used
|
||||
{ 0 , 8 * 16 + 6 , 21 * 8, 16 },
|
||||
};
|
||||
// Button can be RECON or SCANNER
|
||||
Button button_scanner_mode {
|
||||
{ 240 - 7 * 8 , 8 * 16 , 7 * 8, 28 },
|
||||
"RECON"
|
||||
};
|
||||
|
||||
ButtonWithEncoder button_manual_start {
|
||||
{ 0 * 8, 11 * 16, 11 * 8, 28 },
|
||||
""
|
||||
};
|
||||
Text file_name { //Show file used
|
||||
{ 0 , 8 * 16 + 6 , 240 - 7 * 8, 16 },
|
||||
};
|
||||
|
||||
ButtonWithEncoder button_manual_end {
|
||||
{ 12 * 8 - 6, 11 * 16, 11 * 8, 28 },
|
||||
""
|
||||
};
|
||||
ButtonWithEncoder button_manual_start {
|
||||
{ 0 * 8, 11 * 16, 11 * 8, 28 },
|
||||
""
|
||||
};
|
||||
|
||||
Button button_manual_recon {
|
||||
{ 23 * 8 - 3, 11 * 16, 7 * 8 , 28 },
|
||||
"SEARCH"
|
||||
};
|
||||
ButtonWithEncoder button_manual_end {
|
||||
{ 12 * 8 - 6, 11 * 16, 11 * 8, 28 },
|
||||
""
|
||||
};
|
||||
|
||||
OptionsField field_mode {
|
||||
{ 5 * 8, (26 * 8) + 4 },
|
||||
6,
|
||||
{
|
||||
}
|
||||
};
|
||||
Button button_manual_recon {
|
||||
{ 23 * 8 - 3, 11 * 16, 7 * 8 , 28 },
|
||||
"SEARCH"
|
||||
};
|
||||
|
||||
OptionsField step_mode {
|
||||
{ 17 * 8, (26 * 8) + 4 },
|
||||
12,
|
||||
{
|
||||
}
|
||||
};
|
||||
OptionsField field_mode {
|
||||
{ 5 * 8, (26 * 8) + 4 },
|
||||
6,
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
ButtonWithEncoder button_pause {
|
||||
{ 0, (15 * 16) - 4, 72, 28 },
|
||||
"PAUSE"
|
||||
};
|
||||
OptionsField step_mode {
|
||||
{ 17 * 8, (26 * 8) + 4 },
|
||||
12,
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
ButtonWithEncoder button_pause {
|
||||
{ 0, (15 * 16) - 4, 72, 28 },
|
||||
"PAUSE"
|
||||
};
|
||||
|
||||
|
||||
Button button_audio_app {
|
||||
{ 84, (15 * 16) - 4, 72, 28 },
|
||||
"AUDIO"
|
||||
};
|
||||
Button button_audio_app {
|
||||
{ 84, (15 * 16) - 4, 72, 28 },
|
||||
"AUDIO"
|
||||
};
|
||||
|
||||
ButtonWithEncoder button_add {
|
||||
{ 168, (15 * 16) - 4, 72, 28 },
|
||||
"<STORE>"
|
||||
};
|
||||
ButtonWithEncoder button_add {
|
||||
{ 168, (15 * 16) - 4, 72, 28 },
|
||||
"<STORE>"
|
||||
};
|
||||
|
||||
Button button_dir {
|
||||
{ 0, (35 * 8) - 4, 34, 28 },
|
||||
"FW>"
|
||||
};
|
||||
Button button_dir {
|
||||
{ 0, (35 * 8) - 4, 34, 28 },
|
||||
"FW>"
|
||||
};
|
||||
|
||||
Button button_restart {
|
||||
{ 38, (35 * 8) - 4, 34, 28 },
|
||||
"RST"
|
||||
};
|
||||
Button button_restart {
|
||||
{ 38, (35 * 8) - 4, 34, 28 },
|
||||
"RST"
|
||||
};
|
||||
|
||||
|
||||
Button button_mic_app {
|
||||
{ 84, (35 * 8) - 4, 72, 28 },
|
||||
"MIC TX"
|
||||
};
|
||||
Button button_mic_app {
|
||||
{ 84, (35 * 8) - 4, 72, 28 },
|
||||
"MIC TX"
|
||||
};
|
||||
|
||||
ButtonWithEncoder button_remove {
|
||||
{ 168, (35 * 8) - 4, 72, 28 },
|
||||
"<REMOVE>"
|
||||
};
|
||||
ButtonWithEncoder button_remove {
|
||||
{ 168, (35 * 8) - 4, 72, 28 },
|
||||
"<REMOVE>"
|
||||
};
|
||||
|
||||
std::unique_ptr<ReconThread> recon_thread { };
|
||||
std::unique_ptr<ReconThread> recon_thread { };
|
||||
|
||||
MessageHandlerRegistration message_handler_retune {
|
||||
Message::ID::Retune,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const RetuneMessage*>(p);
|
||||
this->handle_retune(message.freq,message.range);
|
||||
}
|
||||
};
|
||||
MessageHandlerRegistration message_handler_coded_squelch {
|
||||
Message::ID::CodedSquelch,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const CodedSquelchMessage*>(p);
|
||||
this->handle_coded_squelch(message.value);
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_stats {
|
||||
Message::ID::ChannelStatistics,
|
||||
[this](const Message* const p) {
|
||||
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
|
||||
}
|
||||
};
|
||||
// app save settings
|
||||
std::app_settings settings { };
|
||||
std::app_settings::AppSettings app_settings { };
|
||||
};
|
||||
MessageHandlerRegistration message_handler_retune {
|
||||
Message::ID::Retune,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const RetuneMessage*>(p);
|
||||
this->handle_retune(message.freq,message.range);
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_stats {
|
||||
Message::ID::ChannelStatistics,
|
||||
[this](const Message* const p) {
|
||||
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
|
||||
}
|
||||
};
|
||||
// app save settings
|
||||
std::app_settings settings { };
|
||||
std::app_settings::AppSettings app_settings { };
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
|
||||
@@ -34,268 +34,268 @@ using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume )
|
||||
{
|
||||
File settings_file;
|
||||
size_t length, file_position = 0;
|
||||
char * pos;
|
||||
char * line_start;
|
||||
char * line_end;
|
||||
char file_data[257];
|
||||
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume )
|
||||
{
|
||||
File settings_file;
|
||||
size_t length, file_position = 0;
|
||||
char * pos;
|
||||
char * line_start;
|
||||
char * line_end;
|
||||
char file_data[257];
|
||||
|
||||
uint32_t it = 0 ;
|
||||
uint32_t nb_params = 9 ;
|
||||
std::string params[ 9 ];
|
||||
uint32_t it = 0 ;
|
||||
uint32_t nb_params = 9 ;
|
||||
std::string params[ 9 ];
|
||||
|
||||
bool check_sd_card = (sd_card::status() == sd_card::Status::Mounted) ? true : false ;
|
||||
bool check_sd_card = (sd_card::status() == sd_card::Status::Mounted) ? true : false ;
|
||||
|
||||
if( check_sd_card )
|
||||
{
|
||||
auto result = settings_file.open( source );
|
||||
if( !result.is_valid() )
|
||||
{
|
||||
while( it < nb_params )
|
||||
{
|
||||
// Read a 256 bytes block from file
|
||||
settings_file.seek(file_position);
|
||||
memset(file_data, 0, 257);
|
||||
auto read_size = settings_file.read(file_data, 256);
|
||||
if (read_size.is_error())
|
||||
break ;
|
||||
file_position += 256;
|
||||
// Reset line_start to beginning of buffer
|
||||
line_start = file_data;
|
||||
pos=line_start;
|
||||
while ((line_end = strstr(line_start, "\x0A"))) {
|
||||
length = line_end - line_start - 1 ;
|
||||
params[ it ] = string( pos , length );
|
||||
it ++ ;
|
||||
line_start = line_end + 1;
|
||||
pos=line_start ;
|
||||
if (line_start - file_data >= 256)
|
||||
break;
|
||||
if( it >= nb_params )
|
||||
break ;
|
||||
}
|
||||
if (read_size.value() != 256)
|
||||
break; // End of file
|
||||
if( check_sd_card )
|
||||
{
|
||||
auto result = settings_file.open( source );
|
||||
if( !result.is_valid() )
|
||||
{
|
||||
while( it < nb_params )
|
||||
{
|
||||
// Read a 256 bytes block from file
|
||||
settings_file.seek(file_position);
|
||||
memset(file_data, 0, 257);
|
||||
auto read_size = settings_file.read(file_data, 256);
|
||||
if (read_size.is_error())
|
||||
break ;
|
||||
file_position += 256;
|
||||
// Reset line_start to beginning of buffer
|
||||
line_start = file_data;
|
||||
pos=line_start;
|
||||
while ((line_end = strstr(line_start, "\x0A"))) {
|
||||
length = line_end - line_start - 1 ;
|
||||
params[ it ] = string( pos , length );
|
||||
it ++ ;
|
||||
line_start = line_end + 1;
|
||||
pos=line_start ;
|
||||
if (line_start - file_data >= 256)
|
||||
break;
|
||||
if( it >= nb_params )
|
||||
break ;
|
||||
}
|
||||
if (read_size.value() != 256)
|
||||
break; // End of file
|
||||
|
||||
// Restart at beginning of last incomplete line
|
||||
file_position -= (file_data + 256 - line_start);
|
||||
}
|
||||
}
|
||||
// Restart at beginning of last incomplete line
|
||||
file_position -= (file_data + 256 - line_start);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if( it > 0 )
|
||||
input_file = params[ 0 ];
|
||||
else
|
||||
input_file = "RECON" ;
|
||||
if( it > 0 )
|
||||
input_file = params[ 0 ];
|
||||
else
|
||||
input_file = "RECON" ;
|
||||
|
||||
if( it > 1 )
|
||||
output_file= params[ 1 ];
|
||||
else
|
||||
output_file = "RECON_RESULTS" ;
|
||||
if( it > 1 )
|
||||
output_file= params[ 1 ];
|
||||
else
|
||||
output_file = "RECON_RESULTS" ;
|
||||
|
||||
if( it > 2 )
|
||||
recon_lock_duration = strtoll( params[ 2 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_lock_duration = 50 ;
|
||||
if( it > 2 )
|
||||
recon_lock_duration = strtoll( params[ 2 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_lock_duration = 50 ;
|
||||
|
||||
if( it > 3 )
|
||||
recon_lock_nb_match = strtoll( params[ 3 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_lock_nb_match = 10 ;
|
||||
if( it > 3 )
|
||||
recon_lock_nb_match = strtoll( params[ 3 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_lock_nb_match = 10 ;
|
||||
|
||||
if( it > 4 )
|
||||
recon_squelch_level = strtoll( params[ 4 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_squelch_level = -14 ;
|
||||
if( it > 4 )
|
||||
recon_squelch_level = strtoll( params[ 4 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_squelch_level = -14 ;
|
||||
|
||||
if( it > 5 )
|
||||
recon_match_mode = strtoll( params[ 5 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_match_mode = 0 ;
|
||||
if( it > 5 )
|
||||
recon_match_mode = strtoll( params[ 5 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
recon_match_mode = 0 ;
|
||||
|
||||
if( it > 6 )
|
||||
wait = strtoll( params[ 6 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
wait = 5000 ;
|
||||
if( it > 6 )
|
||||
wait = strtoll( params[ 6 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
wait = 5000 ;
|
||||
|
||||
if( it > 7 )
|
||||
lock_wait = strtoll( params[ 7 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
lock_wait = 1000 ;
|
||||
if( it > 7 )
|
||||
lock_wait = strtoll( params[ 7 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
lock_wait = 1000 ;
|
||||
|
||||
if( it > 8 )
|
||||
volume = strtoll( params[ 8 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
volume = 40 ;
|
||||
if( it > 8 )
|
||||
volume = strtoll( params[ 8 ].c_str() , nullptr , 10 );
|
||||
else
|
||||
volume = 40 ;
|
||||
|
||||
if( it < nb_params )
|
||||
{
|
||||
/* bad number of params, signal defaults */
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
if( it < nb_params )
|
||||
{
|
||||
/* bad number of params, signal defaults */
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool ReconSetupSaveStrings( std::string dest, std::string input_file , std::string output_file , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume )
|
||||
{
|
||||
File settings_file;
|
||||
bool ReconSetupSaveStrings( std::string dest, std::string input_file , std::string output_file , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume )
|
||||
{
|
||||
File settings_file;
|
||||
|
||||
auto result = settings_file.create( dest );
|
||||
if( result.is_valid() )
|
||||
return false ;
|
||||
settings_file.write_line( input_file );
|
||||
settings_file.write_line( output_file );
|
||||
settings_file.write_line( to_string_dec_uint( recon_lock_duration ) );
|
||||
settings_file.write_line( to_string_dec_uint( recon_lock_nb_match ) );
|
||||
settings_file.write_line( to_string_dec_int( recon_squelch_level ) );
|
||||
settings_file.write_line( to_string_dec_uint( recon_match_mode ) );
|
||||
settings_file.write_line( to_string_dec_int( wait ) );
|
||||
settings_file.write_line( to_string_dec_uint( lock_wait ) );
|
||||
settings_file.write_line( to_string_dec_int( volume ) );
|
||||
return true ;
|
||||
}
|
||||
auto result = settings_file.create( dest );
|
||||
if( result.is_valid() )
|
||||
return false ;
|
||||
settings_file.write_line( input_file );
|
||||
settings_file.write_line( output_file );
|
||||
settings_file.write_line( to_string_dec_uint( recon_lock_duration ) );
|
||||
settings_file.write_line( to_string_dec_uint( recon_lock_nb_match ) );
|
||||
settings_file.write_line( to_string_dec_int( recon_squelch_level ) );
|
||||
settings_file.write_line( to_string_dec_uint( recon_match_mode ) );
|
||||
settings_file.write_line( to_string_dec_int( wait ) );
|
||||
settings_file.write_line( to_string_dec_uint( lock_wait ) );
|
||||
settings_file.write_line( to_string_dec_int( volume ) );
|
||||
return true ;
|
||||
}
|
||||
|
||||
ReconSetupViewMain::ReconSetupViewMain( NavigationView &nav , Rect parent_rect , std::string input_file , std::string output_file ) : View( parent_rect ) , _input_file { input_file } , _output_file { output_file }
|
||||
{
|
||||
hidden(true);
|
||||
add_children({
|
||||
&button_load_freqs,
|
||||
&text_input_file,
|
||||
&button_save_freqs,
|
||||
&button_output_file,
|
||||
&checkbox_autosave_freqs,
|
||||
&checkbox_autostart_recon,
|
||||
&checkbox_continuous,
|
||||
&checkbox_clear_output
|
||||
});
|
||||
ReconSetupViewMain::ReconSetupViewMain( NavigationView &nav , Rect parent_rect , std::string input_file , std::string output_file ) : View( parent_rect ) , _input_file { input_file } , _output_file { output_file }
|
||||
{
|
||||
hidden(true);
|
||||
add_children({
|
||||
&button_load_freqs,
|
||||
&text_input_file,
|
||||
&button_save_freqs,
|
||||
&button_output_file,
|
||||
&checkbox_autosave_freqs,
|
||||
&checkbox_autostart_recon,
|
||||
&checkbox_continuous,
|
||||
&checkbox_clear_output
|
||||
});
|
||||
|
||||
checkbox_autosave_freqs.set_value( persistent_memory::recon_autosave_freqs() );
|
||||
checkbox_autostart_recon.set_value( persistent_memory::recon_autostart_recon() );
|
||||
checkbox_continuous.set_value( persistent_memory::recon_continuous() );
|
||||
checkbox_clear_output.set_value( persistent_memory::recon_clear_output() );
|
||||
checkbox_autosave_freqs.set_value( persistent_memory::recon_autosave_freqs() );
|
||||
checkbox_autostart_recon.set_value( persistent_memory::recon_autostart_recon() );
|
||||
checkbox_continuous.set_value( persistent_memory::recon_continuous() );
|
||||
checkbox_clear_output.set_value( persistent_memory::recon_clear_output() );
|
||||
|
||||
text_input_file.set( _input_file );
|
||||
button_output_file.set_text( _output_file );
|
||||
text_input_file.set( _input_file );
|
||||
button_output_file.set_text( _output_file );
|
||||
|
||||
button_load_freqs.on_select = [this, &nav](Button&) {
|
||||
auto open_view = nav.push<FileLoadView>(".TXT");
|
||||
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
|
||||
std::string dir_filter = "FREQMAN/";
|
||||
std::string str_file_path = new_file_path.string();
|
||||
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
|
||||
// get the filename without txt extension so we can use load_freqman_file fcn
|
||||
_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.");
|
||||
}
|
||||
};
|
||||
};
|
||||
button_load_freqs.on_select = [this, &nav](Button&) {
|
||||
auto open_view = nav.push<FileLoadView>(".TXT");
|
||||
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
|
||||
std::string dir_filter = "FREQMAN/";
|
||||
std::string str_file_path = new_file_path.string();
|
||||
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
|
||||
// get the filename without txt extension so we can use load_freqman_file fcn
|
||||
_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.");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
button_save_freqs.on_select = [this, &nav](Button&) {
|
||||
auto open_view = nav.push<FileLoadView>(".TXT");
|
||||
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
|
||||
std::string dir_filter = "FREQMAN/";
|
||||
std::string str_file_path = new_file_path.string();
|
||||
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
|
||||
_output_file = new_file_path.stem().string();
|
||||
button_output_file.set_text( _output_file );
|
||||
} else {
|
||||
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
|
||||
}
|
||||
};
|
||||
};
|
||||
button_save_freqs.on_select = [this, &nav](Button&) {
|
||||
auto open_view = nav.push<FileLoadView>(".TXT");
|
||||
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
|
||||
std::string dir_filter = "FREQMAN/";
|
||||
std::string str_file_path = new_file_path.string();
|
||||
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
|
||||
_output_file = new_file_path.stem().string();
|
||||
button_output_file.set_text( _output_file );
|
||||
} else {
|
||||
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
button_output_file.on_select =[this, &nav](Button&) {
|
||||
text_prompt( nav, _output_file , 28 ,
|
||||
[this](std::string& buffer) {
|
||||
_output_file = buffer ;
|
||||
button_output_file.set_text( _output_file );
|
||||
} );
|
||||
};
|
||||
};
|
||||
button_output_file.on_select =[this, &nav](Button&) {
|
||||
text_prompt( nav, _output_file , 28 ,
|
||||
[this](std::string& buffer) {
|
||||
_output_file = buffer ;
|
||||
button_output_file.set_text( _output_file );
|
||||
} );
|
||||
};
|
||||
};
|
||||
|
||||
void ReconSetupViewMain::Save( std::string &input_file , std::string &output_file ) {
|
||||
persistent_memory::set_recon_autosave_freqs(checkbox_autosave_freqs.value());
|
||||
persistent_memory::set_recon_autostart_recon(checkbox_autostart_recon.value());
|
||||
persistent_memory::set_recon_continuous(checkbox_continuous.value());
|
||||
persistent_memory::set_recon_clear_output(checkbox_clear_output.value());
|
||||
input_file=_input_file ;
|
||||
output_file=_output_file ;
|
||||
};
|
||||
void ReconSetupViewMore::Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode ) {
|
||||
persistent_memory::set_recon_load_freqs(checkbox_load_freqs.value());
|
||||
persistent_memory::set_recon_load_ranges(checkbox_load_ranges.value());
|
||||
persistent_memory::set_recon_load_hamradios(checkbox_load_hamradios.value());
|
||||
persistent_memory::set_recon_update_ranges_when_recon(checkbox_update_ranges_when_recon.value());
|
||||
recon_lock_duration = field_recon_lock_duration.value();
|
||||
recon_lock_nb_match = field_recon_lock_nb_match.value();
|
||||
recon_match_mode = field_recon_match_mode . selected_index_value() ;
|
||||
};
|
||||
void ReconSetupViewMain::Save( std::string &input_file , std::string &output_file ) {
|
||||
persistent_memory::set_recon_autosave_freqs(checkbox_autosave_freqs.value());
|
||||
persistent_memory::set_recon_autostart_recon(checkbox_autostart_recon.value());
|
||||
persistent_memory::set_recon_continuous(checkbox_continuous.value());
|
||||
persistent_memory::set_recon_clear_output(checkbox_clear_output.value());
|
||||
input_file=_input_file ;
|
||||
output_file=_output_file ;
|
||||
};
|
||||
void ReconSetupViewMore::Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode ) {
|
||||
persistent_memory::set_recon_load_freqs(checkbox_load_freqs.value());
|
||||
persistent_memory::set_recon_load_ranges(checkbox_load_ranges.value());
|
||||
persistent_memory::set_recon_load_hamradios(checkbox_load_hamradios.value());
|
||||
persistent_memory::set_recon_update_ranges_when_recon(checkbox_update_ranges_when_recon.value());
|
||||
recon_lock_duration = field_recon_lock_duration.value();
|
||||
recon_lock_nb_match = field_recon_lock_nb_match.value();
|
||||
recon_match_mode = field_recon_match_mode . selected_index_value() ;
|
||||
};
|
||||
|
||||
void ReconSetupViewMain::focus() {
|
||||
button_load_freqs.focus();
|
||||
}
|
||||
void ReconSetupViewMain::focus() {
|
||||
button_load_freqs.focus();
|
||||
}
|
||||
|
||||
ReconSetupViewMore::ReconSetupViewMore( NavigationView &nav , Rect parent_rect , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , uint32_t recon_match_mode ) : View( parent_rect ), _recon_lock_duration { recon_lock_duration } , _recon_lock_nb_match { recon_lock_nb_match } , _recon_match_mode { recon_match_mode }
|
||||
{
|
||||
(void)nav;
|
||||
hidden(true);
|
||||
ReconSetupViewMore::ReconSetupViewMore( NavigationView &nav , Rect parent_rect , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , uint32_t recon_match_mode ) : View( parent_rect ), _recon_lock_duration { recon_lock_duration } , _recon_lock_nb_match { recon_lock_nb_match } , _recon_match_mode { recon_match_mode }
|
||||
{
|
||||
(void)nav;
|
||||
hidden(true);
|
||||
|
||||
add_children({
|
||||
&checkbox_load_freqs,
|
||||
&checkbox_load_ranges,
|
||||
&checkbox_load_hamradios,
|
||||
&checkbox_update_ranges_when_recon,
|
||||
&text_recon_lock_duration,
|
||||
&field_recon_lock_duration,
|
||||
&text_recon_lock_nb,
|
||||
&field_recon_lock_nb_match,
|
||||
&field_recon_match_mode,
|
||||
});
|
||||
add_children({
|
||||
&checkbox_load_freqs,
|
||||
&checkbox_load_ranges,
|
||||
&checkbox_load_hamradios,
|
||||
&checkbox_update_ranges_when_recon,
|
||||
&text_recon_lock_duration,
|
||||
&field_recon_lock_duration,
|
||||
&text_recon_lock_nb,
|
||||
&field_recon_lock_nb_match,
|
||||
&field_recon_match_mode,
|
||||
});
|
||||
|
||||
checkbox_load_freqs.set_value( persistent_memory::recon_load_freqs() );
|
||||
checkbox_load_ranges.set_value( persistent_memory::recon_load_ranges() );
|
||||
checkbox_load_hamradios.set_value( persistent_memory::recon_load_hamradios() );
|
||||
checkbox_update_ranges_when_recon.set_value( persistent_memory::recon_update_ranges_when_recon() );
|
||||
field_recon_lock_duration.set_value( _recon_lock_duration );
|
||||
field_recon_lock_nb_match.set_value( _recon_lock_nb_match );
|
||||
field_recon_match_mode.set_by_value( _recon_match_mode );
|
||||
};
|
||||
checkbox_load_freqs.set_value( persistent_memory::recon_load_freqs() );
|
||||
checkbox_load_ranges.set_value( persistent_memory::recon_load_ranges() );
|
||||
checkbox_load_hamradios.set_value( persistent_memory::recon_load_hamradios() );
|
||||
checkbox_update_ranges_when_recon.set_value( persistent_memory::recon_update_ranges_when_recon() );
|
||||
field_recon_lock_duration.set_value( _recon_lock_duration );
|
||||
field_recon_lock_nb_match.set_value( _recon_lock_nb_match );
|
||||
field_recon_match_mode.set_by_value( _recon_match_mode );
|
||||
};
|
||||
|
||||
void ReconSetupViewMore::focus() {
|
||||
checkbox_load_freqs.focus();
|
||||
}
|
||||
void ReconSetupViewMore::focus() {
|
||||
checkbox_load_freqs.focus();
|
||||
}
|
||||
|
||||
void ReconSetupView::focus() {
|
||||
viewMain.focus();
|
||||
}
|
||||
void ReconSetupView::focus() {
|
||||
viewMain.focus();
|
||||
}
|
||||
|
||||
ReconSetupView::ReconSetupView(
|
||||
NavigationView& nav , std::string _input_file , std::string _output_file , uint32_t _recon_lock_duration , uint32_t _recon_lock_nb_match , uint32_t _recon_match_mode ) : nav_ { nav } , input_file { _input_file } , output_file { _output_file } , recon_lock_duration { _recon_lock_duration } , recon_lock_nb_match { _recon_lock_nb_match } , recon_match_mode { _recon_match_mode }
|
||||
{
|
||||
add_children({
|
||||
&tab_view,
|
||||
&viewMain,
|
||||
&viewMore,
|
||||
&button_save
|
||||
});
|
||||
ReconSetupView::ReconSetupView(
|
||||
NavigationView& nav , std::string _input_file , std::string _output_file , uint32_t _recon_lock_duration , uint32_t _recon_lock_nb_match , uint32_t _recon_match_mode ) : nav_ { nav } , input_file { _input_file } , output_file { _output_file } , recon_lock_duration { _recon_lock_duration } , recon_lock_nb_match { _recon_lock_nb_match } , recon_match_mode { _recon_match_mode }
|
||||
{
|
||||
add_children({
|
||||
&tab_view,
|
||||
&viewMain,
|
||||
&viewMore,
|
||||
&button_save
|
||||
});
|
||||
|
||||
button_save.on_select = [this,&nav](Button&) {
|
||||
viewMain.Save( input_file , output_file );
|
||||
viewMore.Save( recon_lock_duration , recon_lock_nb_match , recon_match_mode );
|
||||
std::vector<std::string> messages ;
|
||||
messages.push_back( input_file );
|
||||
messages.push_back( output_file );
|
||||
messages.push_back( to_string_dec_uint( recon_lock_duration ) );
|
||||
messages.push_back( to_string_dec_uint( recon_lock_nb_match ) );
|
||||
messages.push_back( to_string_dec_uint( recon_match_mode ) );
|
||||
on_changed( messages );
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
button_save.on_select = [this,&nav](Button&) {
|
||||
viewMain.Save( input_file , output_file );
|
||||
viewMore.Save( recon_lock_duration , recon_lock_nb_match , recon_match_mode );
|
||||
std::vector<std::string> messages ;
|
||||
messages.push_back( input_file );
|
||||
messages.push_back( output_file );
|
||||
messages.push_back( to_string_dec_uint( recon_lock_duration ) );
|
||||
messages.push_back( to_string_dec_uint( recon_lock_nb_match ) );
|
||||
messages.push_back( to_string_dec_uint( recon_match_mode ) );
|
||||
on_changed( messages );
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -29,166 +29,166 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume );
|
||||
bool ReconSetupSaveStrings( std::string dest, const std::string input_file , const std::string output_file , const uint32_t recon_lock_duration , const uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume );
|
||||
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume );
|
||||
bool ReconSetupSaveStrings( std::string dest, const std::string input_file , const std::string output_file , const uint32_t recon_lock_duration , const uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume );
|
||||
|
||||
class ReconSetupViewMain : public View {
|
||||
public:
|
||||
ReconSetupViewMain( NavigationView& nav, Rect parent_rect , std::string input_file , std::string output_file );
|
||||
void Save( std::string &input_file , std::string &output_file );
|
||||
void focus() override;
|
||||
class ReconSetupViewMain : public View {
|
||||
public:
|
||||
ReconSetupViewMain( NavigationView& nav, Rect parent_rect , std::string input_file , std::string output_file );
|
||||
void Save( std::string &input_file , std::string &output_file );
|
||||
void focus() override;
|
||||
|
||||
private:
|
||||
std::string _input_file = { "RECON" };
|
||||
std::string _output_file = { "RECON_RESULTS" };
|
||||
private:
|
||||
std::string _input_file = { "RECON" };
|
||||
std::string _output_file = { "RECON_RESULTS" };
|
||||
|
||||
Button button_load_freqs {
|
||||
{ 1 * 8 , 12 , 18 * 8 , 22 },
|
||||
"select input file"
|
||||
};
|
||||
Text text_input_file {
|
||||
{ 1 * 8 , 4 + 2 * 16, 18 * 8, 22 },
|
||||
"RECON"
|
||||
};
|
||||
Button button_load_freqs {
|
||||
{ 1 * 8 , 12 , 18 * 8 , 22 },
|
||||
"select input file"
|
||||
};
|
||||
Text text_input_file {
|
||||
{ 1 * 8 , 4 + 2 * 16, 18 * 8, 22 },
|
||||
"RECON"
|
||||
};
|
||||
|
||||
Button button_save_freqs {
|
||||
{ 1 * 8 , 4 * 16 - 8 , 18 * 8 , 22 },
|
||||
"select output file"
|
||||
};
|
||||
Button button_output_file {
|
||||
{ 1 * 8 , 5 * 16 - 2, 18 * 8, 22 },
|
||||
"RECON_RESULTS"
|
||||
};
|
||||
Button button_save_freqs {
|
||||
{ 1 * 8 , 4 * 16 - 8 , 18 * 8 , 22 },
|
||||
"select output file"
|
||||
};
|
||||
Button button_output_file {
|
||||
{ 1 * 8 , 5 * 16 - 2, 18 * 8, 22 },
|
||||
"RECON_RESULTS"
|
||||
};
|
||||
|
||||
Checkbox checkbox_autosave_freqs {
|
||||
{ 1 * 8, 7 * 16 - 4 },
|
||||
3,
|
||||
"autosave freqs"
|
||||
};
|
||||
Checkbox checkbox_autosave_freqs {
|
||||
{ 1 * 8, 7 * 16 - 4 },
|
||||
3,
|
||||
"autosave freqs"
|
||||
};
|
||||
|
||||
Checkbox checkbox_autostart_recon {
|
||||
{ 1 * 8, 9 * 16 - 4 },
|
||||
3,
|
||||
"autostart recon"
|
||||
};
|
||||
Checkbox checkbox_autostart_recon {
|
||||
{ 1 * 8, 9 * 16 - 4 },
|
||||
3,
|
||||
"autostart recon"
|
||||
};
|
||||
|
||||
Checkbox checkbox_continuous {
|
||||
{ 1 * 8, 11 * 16 - 4 },
|
||||
3,
|
||||
"continuous"
|
||||
};
|
||||
Checkbox checkbox_clear_output {
|
||||
{ 1 * 8, 13 * 16 - 4 },
|
||||
3,
|
||||
"clear output at start"
|
||||
};
|
||||
};
|
||||
Checkbox checkbox_continuous {
|
||||
{ 1 * 8, 11 * 16 - 4 },
|
||||
3,
|
||||
"continuous"
|
||||
};
|
||||
Checkbox checkbox_clear_output {
|
||||
{ 1 * 8, 13 * 16 - 4 },
|
||||
3,
|
||||
"clear output at start"
|
||||
};
|
||||
};
|
||||
|
||||
class ReconSetupViewMore : public View {
|
||||
public:
|
||||
ReconSetupViewMore( NavigationView& nav, Rect parent_rect , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
|
||||
class ReconSetupViewMore : public View {
|
||||
public:
|
||||
ReconSetupViewMore( NavigationView& nav, Rect parent_rect , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
|
||||
|
||||
void Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode );
|
||||
void Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode );
|
||||
|
||||
void focus() override;
|
||||
void focus() override;
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
const uint32_t _recon_lock_duration = 50 ;
|
||||
const uint32_t _recon_lock_nb_match = 10 ;
|
||||
const uint32_t _recon_match_mode = 0 ;
|
||||
const uint32_t _recon_lock_duration = 50 ;
|
||||
const uint32_t _recon_lock_nb_match = 10 ;
|
||||
const uint32_t _recon_match_mode = 0 ;
|
||||
|
||||
Checkbox checkbox_load_freqs {
|
||||
{ 1 * 8, 12 },
|
||||
3,
|
||||
"input: load freqs"
|
||||
};
|
||||
Checkbox checkbox_load_freqs {
|
||||
{ 1 * 8, 12 },
|
||||
3,
|
||||
"input: load freqs"
|
||||
};
|
||||
|
||||
Checkbox checkbox_load_ranges {
|
||||
{ 1 * 8, 42 },
|
||||
3,
|
||||
"input: load ranges"
|
||||
};
|
||||
Checkbox checkbox_load_ranges {
|
||||
{ 1 * 8, 42 },
|
||||
3,
|
||||
"input: load ranges"
|
||||
};
|
||||
|
||||
Checkbox checkbox_load_hamradios {
|
||||
{ 1 * 8, 72 },
|
||||
3,
|
||||
"input: load hamradios"
|
||||
};
|
||||
Checkbox checkbox_load_hamradios {
|
||||
{ 1 * 8, 72 },
|
||||
3,
|
||||
"input: load hamradios"
|
||||
};
|
||||
|
||||
Checkbox checkbox_update_ranges_when_recon {
|
||||
{ 1 * 8, 102 },
|
||||
3,
|
||||
"auto update m-ranges"
|
||||
};
|
||||
Text text_recon_lock_duration {
|
||||
{ 1 * 8 , 132 , 22 * 8 , 22 },
|
||||
" ms (lock duration)"
|
||||
};
|
||||
NumberField field_recon_lock_duration {
|
||||
{ 1 * 8, 132 }, // position X , Y
|
||||
4, // number of displayed digits (even empty)
|
||||
{ 50 , 990 }, // range of number
|
||||
10, // rotary encoder increment
|
||||
' ', // filling character
|
||||
false // can loop
|
||||
};
|
||||
Text text_recon_lock_nb {
|
||||
{ 1 * 8 , 162 , 25 * 8 , 22 },
|
||||
" x (nb lock to match freq)"
|
||||
};
|
||||
NumberField field_recon_lock_nb_match {
|
||||
{ 1 * 8, 162 },
|
||||
4,
|
||||
{ 1, 99 },
|
||||
1,
|
||||
' ',
|
||||
false
|
||||
};
|
||||
OptionsField field_recon_match_mode {
|
||||
{ 1 * 8, 192 },
|
||||
20, // CONTINUOUS MATCH MODE / SPARSE TIMED MATCH MODE
|
||||
{
|
||||
{ "SQL MATCH: CONTINOUS" , 0 },
|
||||
{ "SQL MATCH: SPARSE" , 1 }
|
||||
}
|
||||
};
|
||||
};
|
||||
Checkbox checkbox_update_ranges_when_recon {
|
||||
{ 1 * 8, 102 },
|
||||
3,
|
||||
"auto update m-ranges"
|
||||
};
|
||||
Text text_recon_lock_duration {
|
||||
{ 1 * 8 , 132 , 22 * 8 , 22 },
|
||||
" ms (lock duration)"
|
||||
};
|
||||
NumberField field_recon_lock_duration {
|
||||
{ 1 * 8, 132 }, // position X , Y
|
||||
4, // number of displayed digits (even empty)
|
||||
{ 50 , 990 }, // range of number
|
||||
10, // rotary encoder increment
|
||||
' ', // filling character
|
||||
false // can loop
|
||||
};
|
||||
Text text_recon_lock_nb {
|
||||
{ 1 * 8 , 162 , 25 * 8 , 22 },
|
||||
" x (nb lock to match freq)"
|
||||
};
|
||||
NumberField field_recon_lock_nb_match {
|
||||
{ 1 * 8, 162 },
|
||||
4,
|
||||
{ 1, 99 },
|
||||
1,
|
||||
' ',
|
||||
false
|
||||
};
|
||||
OptionsField field_recon_match_mode {
|
||||
{ 1 * 8, 192 },
|
||||
20, // CONTINUOUS MATCH MODE / SPARSE TIMED MATCH MODE
|
||||
{
|
||||
{ "SQL MATCH: CONTINOUS" , 0 },
|
||||
{ "SQL MATCH: SPARSE" , 1 }
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class ReconSetupView : public View {
|
||||
public:
|
||||
ReconSetupView( NavigationView& nav , std::string _input_file , std::string _output_file , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
|
||||
class ReconSetupView : public View {
|
||||
public:
|
||||
ReconSetupView( NavigationView& nav , std::string _input_file , std::string _output_file , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
|
||||
|
||||
std::function<void( std::vector<std::string> messages )> on_changed { };
|
||||
std::function<void( std::vector<std::string> messages )> on_changed { };
|
||||
|
||||
void focus() override;
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Recon setup"; };
|
||||
std::string title() const override { return "Recon setup"; };
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
NavigationView& nav_ ;
|
||||
NavigationView& nav_ ;
|
||||
|
||||
std::string input_file = { "RECON" };
|
||||
std::string output_file = { "RECON_RESULTS" };
|
||||
uint32_t recon_lock_duration = 50 ;
|
||||
uint32_t recon_lock_nb_match = 10 ;
|
||||
uint32_t recon_match_mode = 0 ;
|
||||
std::string input_file = { "RECON" };
|
||||
std::string output_file = { "RECON_RESULTS" };
|
||||
uint32_t recon_lock_duration = 50 ;
|
||||
uint32_t recon_lock_nb_match = 10 ;
|
||||
uint32_t recon_match_mode = 0 ;
|
||||
|
||||
Rect view_rect = { 0, 3 * 8, 240, 230 };
|
||||
Rect view_rect = { 0, 3 * 8, 240, 230 };
|
||||
|
||||
ReconSetupViewMain viewMain{ nav_ , view_rect , input_file , output_file };
|
||||
ReconSetupViewMore viewMore{ nav_ , view_rect , recon_lock_duration , recon_lock_nb_match , recon_match_mode };
|
||||
ReconSetupViewMain viewMain{ nav_ , view_rect , input_file , output_file };
|
||||
ReconSetupViewMore viewMore{ nav_ , view_rect , recon_lock_duration , recon_lock_nb_match , recon_match_mode };
|
||||
|
||||
TabView tab_view {
|
||||
{ "Main", Color::cyan() , &viewMain },
|
||||
{ "More", Color::green(), &viewMore }
|
||||
};
|
||||
Button button_save {
|
||||
{ 9 * 8, 255, 14 * 8 , 40 },
|
||||
"SAVE"
|
||||
};
|
||||
};
|
||||
TabView tab_view {
|
||||
{ "Main", Color::cyan() , &viewMain },
|
||||
{ "More", Color::green(), &viewMore }
|
||||
};
|
||||
Button button_save {
|
||||
{ 9 * 8, 255, 14 * 8 , 40 },
|
||||
"SAVE"
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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_sd_over_usb.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
SdOverUsbView::SdOverUsbView(NavigationView& nav) : nav_ (nav) {
|
||||
add_children({
|
||||
&labels,
|
||||
&button_run
|
||||
});
|
||||
|
||||
button_run.on_select = [this](Button&) {
|
||||
ui::Painter painter;
|
||||
painter.fill_rectangle(
|
||||
{ 0, 0, portapack::display.width(), portapack::display.height() },
|
||||
ui::Color::black()
|
||||
);
|
||||
|
||||
painter.draw_bitmap(
|
||||
{ portapack::display.width()/2-8, portapack::display.height()/2-8 },
|
||||
bitmap_icon_hackrf,
|
||||
ui::Color::yellow(),
|
||||
ui::Color::black()
|
||||
);
|
||||
|
||||
sdcDisconnect(&SDCD1);
|
||||
sdcStop(&SDCD1);
|
||||
|
||||
portapack::shutdown(true);
|
||||
m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, false);
|
||||
m0_halt();
|
||||
/* will not return*/
|
||||
};
|
||||
}
|
||||
|
||||
void SdOverUsbView::focus() {
|
||||
button_run.focus();
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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_SD_OVER_USB_H__
|
||||
#define __UI_SD_OVER_USB_H__
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "ff.h"
|
||||
#include "baseband_api.hpp"
|
||||
#include "core_control.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ui {
|
||||
|
||||
class SdOverUsbView : public View {
|
||||
public:
|
||||
SdOverUsbView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Flash Utility"; };
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
Labels labels {
|
||||
{ { 3 * 8, 2 * 16 }, "Click Run to start the", Color::white() },
|
||||
{ { 3 * 8, 3 * 16 }, "USB Mass Storage Mode.", Color::white() },
|
||||
{ { 3 * 8, 5 * 16 }, "It can take up to 20s", Color::white() },
|
||||
{ { 3 * 8, 6 * 16 }, "for the drive to be", Color::white() },
|
||||
{ { 3 * 8, 7 * 16 }, "available.", Color::white() },
|
||||
};
|
||||
|
||||
Button button_run {
|
||||
{ 9 * 8, 15 * 16, 12 * 8, 3 * 16 },
|
||||
"Run"
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif /*__UI_SD_OVER_USB_H__*/
|
||||
@@ -42,375 +42,524 @@ using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
SetDateTimeView::SetDateTimeView(
|
||||
NavigationView& nav
|
||||
) {
|
||||
button_save.on_select = [&nav, this](Button&){
|
||||
const auto model = this->form_collect();
|
||||
const rtc::RTC new_datetime {
|
||||
model.year, model.month, model.day,
|
||||
model.hour, model.minute, model.second
|
||||
SetDateTimeView::SetDateTimeView(
|
||||
NavigationView& nav
|
||||
) {
|
||||
button_save.on_select = [&nav, this](Button&){
|
||||
const auto model = this->form_collect();
|
||||
const rtc::RTC new_datetime {
|
||||
model.year, model.month, model.day,
|
||||
model.hour, model.minute, model.second
|
||||
};
|
||||
rtcSetTime(&RTCD1, &new_datetime);
|
||||
nav.pop();
|
||||
},
|
||||
|
||||
button_cancel.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
},
|
||||
|
||||
add_children({
|
||||
&labels,
|
||||
&field_year,
|
||||
&field_month,
|
||||
&field_day,
|
||||
&field_hour,
|
||||
&field_minute,
|
||||
&field_second,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
});
|
||||
|
||||
rtc::RTC datetime;
|
||||
rtcGetTime(&RTCD1, &datetime);
|
||||
SetDateTimeModel model {
|
||||
datetime.year(),
|
||||
datetime.month(),
|
||||
datetime.day(),
|
||||
datetime.hour(),
|
||||
datetime.minute(),
|
||||
datetime.second()
|
||||
};
|
||||
rtcSetTime(&RTCD1, &new_datetime);
|
||||
nav.pop();
|
||||
},
|
||||
|
||||
button_cancel.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
},
|
||||
|
||||
add_children({
|
||||
&labels,
|
||||
&field_year,
|
||||
&field_month,
|
||||
&field_day,
|
||||
&field_hour,
|
||||
&field_minute,
|
||||
&field_second,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
});
|
||||
|
||||
rtc::RTC datetime;
|
||||
rtcGetTime(&RTCD1, &datetime);
|
||||
SetDateTimeModel model {
|
||||
datetime.year(),
|
||||
datetime.month(),
|
||||
datetime.day(),
|
||||
datetime.hour(),
|
||||
datetime.minute(),
|
||||
datetime.second()
|
||||
};
|
||||
|
||||
form_init(model);
|
||||
}
|
||||
|
||||
void SetDateTimeView::focus() {
|
||||
button_cancel.focus();
|
||||
}
|
||||
|
||||
void SetDateTimeView::form_init(const SetDateTimeModel& model) {
|
||||
field_year.set_value(model.year);
|
||||
field_month.set_value(model.month);
|
||||
field_day.set_value(model.day);
|
||||
field_hour.set_value(model.hour);
|
||||
field_minute.set_value(model.minute);
|
||||
field_second.set_value(model.second);
|
||||
}
|
||||
|
||||
SetDateTimeModel SetDateTimeView::form_collect() {
|
||||
return {
|
||||
.year = static_cast<uint16_t>(field_year.value()),
|
||||
.month = static_cast<uint8_t>(field_month.value()),
|
||||
.day = static_cast<uint8_t>(field_day.value()),
|
||||
.hour = static_cast<uint8_t>(field_hour.value()),
|
||||
.minute = static_cast<uint8_t>(field_minute.value()),
|
||||
.second = static_cast<uint8_t>(field_second.value())
|
||||
};
|
||||
}
|
||||
|
||||
SetRadioView::SetRadioView(
|
||||
NavigationView& nav
|
||||
) {
|
||||
button_cancel.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
const auto reference = portapack::clock_manager.get_reference();
|
||||
|
||||
std::string source_name("---");
|
||||
switch(reference.source) {
|
||||
case ClockManager::ReferenceSource::Xtal: source_name = "HackRF"; break;
|
||||
case ClockManager::ReferenceSource::PortaPack: source_name = "PortaPack"; break;
|
||||
case ClockManager::ReferenceSource::External: source_name = "External"; break;
|
||||
form_init(model);
|
||||
}
|
||||
|
||||
value_source.set(source_name);
|
||||
value_source_frequency.set(to_string_dec_uint(reference.frequency / 1000000, 2) + "." + to_string_dec_uint((reference.frequency % 1000000) / 100, 4, '0') + " MHz");
|
||||
void SetDateTimeView::focus() {
|
||||
button_cancel.focus();
|
||||
}
|
||||
|
||||
label_source.set_style(&style_text);
|
||||
value_source.set_style(&style_text);
|
||||
value_source_frequency.set_style(&style_text);
|
||||
void SetDateTimeView::form_init(const SetDateTimeModel& model) {
|
||||
field_year.set_value(model.year);
|
||||
field_month.set_value(model.month);
|
||||
field_day.set_value(model.day);
|
||||
field_hour.set_value(model.hour);
|
||||
field_minute.set_value(model.minute);
|
||||
field_second.set_value(model.second);
|
||||
}
|
||||
|
||||
add_children({
|
||||
&label_source,
|
||||
&value_source,
|
||||
&value_source_frequency,
|
||||
});
|
||||
SetDateTimeModel SetDateTimeView::form_collect() {
|
||||
return {
|
||||
.year = static_cast<uint16_t>(field_year.value()),
|
||||
.month = static_cast<uint8_t>(field_month.value()),
|
||||
.day = static_cast<uint8_t>(field_day.value()),
|
||||
.hour = static_cast<uint8_t>(field_hour.value()),
|
||||
.minute = static_cast<uint8_t>(field_minute.value()),
|
||||
.second = static_cast<uint8_t>(field_second.value())
|
||||
};
|
||||
}
|
||||
|
||||
SetRadioView::SetRadioView(
|
||||
NavigationView& nav
|
||||
) {
|
||||
button_cancel.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
const auto reference = portapack::clock_manager.get_reference();
|
||||
|
||||
std::string source_name("---");
|
||||
switch(reference.source) {
|
||||
case ClockManager::ReferenceSource::Xtal: source_name = "HackRF"; break;
|
||||
case ClockManager::ReferenceSource::PortaPack: source_name = "PortaPack"; break;
|
||||
case ClockManager::ReferenceSource::External: source_name = "External"; break;
|
||||
}
|
||||
|
||||
value_source.set(source_name);
|
||||
value_source_frequency.set(to_string_dec_uint(reference.frequency / 1000000, 2) + "." + to_string_dec_uint((reference.frequency % 1000000) / 100, 4, '0') + " MHz");
|
||||
|
||||
label_source.set_style(&style_text);
|
||||
value_source.set_style(&style_text);
|
||||
value_source_frequency.set_style(&style_text);
|
||||
|
||||
if( reference.source == ClockManager::ReferenceSource::Xtal ) {
|
||||
add_children({
|
||||
&labels_correction,
|
||||
&field_ppm,
|
||||
});
|
||||
&label_source,
|
||||
&value_source,
|
||||
&value_source_frequency,
|
||||
});
|
||||
|
||||
if( reference.source == ClockManager::ReferenceSource::Xtal ) {
|
||||
add_children({
|
||||
&labels_correction,
|
||||
&field_ppm,
|
||||
});
|
||||
}
|
||||
|
||||
add_children({
|
||||
&check_clkout,
|
||||
&field_clkout_freq,
|
||||
&labels_clkout_khz,
|
||||
&value_freq_step,
|
||||
&labels_bias,
|
||||
&check_bias,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
SetFrequencyCorrectionModel model {
|
||||
static_cast<int8_t>(portapack::persistent_memory::correction_ppb() / 1000) , 0
|
||||
};
|
||||
|
||||
form_init(model);
|
||||
|
||||
check_clkout.set_value(portapack::persistent_memory::clkout_enabled());
|
||||
check_clkout.on_select = [this](Checkbox&, bool v) {
|
||||
clock_manager.enable_clock_output(v);
|
||||
portapack::persistent_memory::set_clkout_enabled(v);
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
field_clkout_freq.set_value(portapack::persistent_memory::clkout_freq());
|
||||
value_freq_step.set_style(&style_text);
|
||||
|
||||
field_clkout_freq.on_select = [this](NumberField&) {
|
||||
freq_step_khz++;
|
||||
if(freq_step_khz > 3) {
|
||||
freq_step_khz = 0;
|
||||
}
|
||||
switch(freq_step_khz) {
|
||||
case 0:
|
||||
value_freq_step.set(" |");
|
||||
break;
|
||||
case 1:
|
||||
value_freq_step.set(" | ");
|
||||
break;
|
||||
case 2:
|
||||
value_freq_step.set(" | ");
|
||||
break;
|
||||
case 3:
|
||||
value_freq_step.set("| ");
|
||||
break;
|
||||
}
|
||||
field_clkout_freq.set_step(pow(10, freq_step_khz));
|
||||
};
|
||||
|
||||
check_bias.set_value(portapack::get_antenna_bias());
|
||||
check_bias.on_select = [this](Checkbox&, bool v) {
|
||||
portapack::set_antenna_bias(v);
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
button_save.on_select = [this, &nav](Button&){
|
||||
const auto model = this->form_collect();
|
||||
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
|
||||
portapack::persistent_memory::set_clkout_freq(model.freq);
|
||||
clock_manager.enable_clock_output(portapack::persistent_memory::clkout_enabled());
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
add_children({
|
||||
&check_hamitup,
|
||||
&button_hamitup_freq,
|
||||
&check_clkout,
|
||||
&field_clkout_freq,
|
||||
&labels_clkout_khz,
|
||||
&value_freq_step,
|
||||
&labels_bias,
|
||||
&check_bias,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
void SetRadioView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
SetFrequencyCorrectionModel model {
|
||||
static_cast<int8_t>(portapack::persistent_memory::correction_ppb() / 1000) , 0
|
||||
};
|
||||
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
|
||||
field_ppm.set_value(model.ppm);
|
||||
}
|
||||
|
||||
form_init(model);
|
||||
|
||||
check_clkout.set_value(portapack::persistent_memory::clkout_enabled());
|
||||
check_clkout.on_select = [this](Checkbox&, bool v) {
|
||||
clock_manager.enable_clock_output(v);
|
||||
portapack::persistent_memory::set_clkout_enabled(v);
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
check_hamitup.set_value(portapack::persistent_memory::config_hamitup());
|
||||
check_hamitup.on_select = [this](Checkbox&, bool v) {
|
||||
portapack::persistent_memory::set_config_hamitup(v);
|
||||
// Retune to take hamitup change in account
|
||||
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
|
||||
//Refresh status bar with/out UP!
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
button_hamitup_freq.set_text( to_string_short_freq( portapack::persistent_memory::config_hamitup_freq() ) + "MHz");
|
||||
|
||||
button_hamitup_freq.on_select = [this, &nav](Button& button) {
|
||||
auto new_view = nav.push<FrequencyKeypadView>(portapack::persistent_memory::config_hamitup_freq() );
|
||||
new_view->on_changed = [this, &button](rf::Frequency f) {
|
||||
portapack::persistent_memory::set_config_hamitup_freq( f );
|
||||
// Retune to take hamitup change in account
|
||||
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
|
||||
button_hamitup_freq.set_text( "<" + to_string_short_freq( f ) + " MHz>" );
|
||||
};
|
||||
};
|
||||
|
||||
field_clkout_freq.set_value(portapack::persistent_memory::clkout_freq());
|
||||
value_freq_step.set_style(&style_text);
|
||||
|
||||
field_clkout_freq.on_select = [this](NumberField&) {
|
||||
freq_step_khz++;
|
||||
if(freq_step_khz > 3) {
|
||||
freq_step_khz = 0;
|
||||
}
|
||||
switch(freq_step_khz) {
|
||||
case 0:
|
||||
value_freq_step.set(" |");
|
||||
break;
|
||||
case 1:
|
||||
value_freq_step.set(" | ");
|
||||
break;
|
||||
case 2:
|
||||
value_freq_step.set(" | ");
|
||||
break;
|
||||
case 3:
|
||||
value_freq_step.set("| ");
|
||||
break;
|
||||
}
|
||||
field_clkout_freq.set_step(pow(10, freq_step_khz));
|
||||
};
|
||||
|
||||
check_bias.set_value(portapack::get_antenna_bias());
|
||||
check_bias.on_select = [this](Checkbox&, bool v) {
|
||||
portapack::set_antenna_bias(v);
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
button_save.on_select = [this, &nav](Button&){
|
||||
const auto model = this->form_collect();
|
||||
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
|
||||
portapack::persistent_memory::set_clkout_freq(model.freq);
|
||||
clock_manager.enable_clock_output(portapack::persistent_memory::clkout_enabled());
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetRadioView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
|
||||
field_ppm.set_value(model.ppm);
|
||||
}
|
||||
|
||||
SetFrequencyCorrectionModel SetRadioView::form_collect() {
|
||||
return {
|
||||
.ppm = static_cast<int8_t>(field_ppm.value()),
|
||||
.freq = static_cast<uint32_t>(field_clkout_freq.value()),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
SetUIView::SetUIView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_disable_touchscreen,
|
||||
&checkbox_speaker,
|
||||
&checkbox_bloff,
|
||||
&options_bloff,
|
||||
&checkbox_showsplash,
|
||||
&checkbox_showclock,
|
||||
&options_clockformat,
|
||||
&checkbox_guireturnflag,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen());
|
||||
checkbox_speaker.set_value(persistent_memory::config_speaker());
|
||||
checkbox_showsplash.set_value(persistent_memory::config_splash());
|
||||
checkbox_showclock.set_value(!persistent_memory::hide_clock());
|
||||
checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon());
|
||||
|
||||
const auto backlight_config = persistent_memory::config_backlight_timer();
|
||||
checkbox_bloff.set_value(backlight_config.timeout_enabled());
|
||||
options_bloff.set_by_value(backlight_config.timeout_enum());
|
||||
|
||||
if (persistent_memory::clock_with_date()) {
|
||||
options_clockformat.set_selected_index(1);
|
||||
} else {
|
||||
options_clockformat.set_selected_index(0);
|
||||
SetFrequencyCorrectionModel SetRadioView::form_collect() {
|
||||
return {
|
||||
.ppm = static_cast<int8_t>(field_ppm.value()),
|
||||
.freq = static_cast<uint32_t>(field_clkout_freq.value()),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_config_backlight_timer({
|
||||
(persistent_memory::backlight_timeout_t)options_bloff.selected_index_value(),
|
||||
checkbox_bloff.value()
|
||||
});
|
||||
|
||||
if (checkbox_showclock.value()){
|
||||
if (options_clockformat.selected_index() == 1)
|
||||
persistent_memory::set_clock_with_date(true);
|
||||
else
|
||||
persistent_memory::set_clock_with_date(false);
|
||||
SetUIView::SetUIView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_disable_touchscreen,
|
||||
&checkbox_speaker,
|
||||
&checkbox_bloff,
|
||||
&options_bloff,
|
||||
&checkbox_showsplash,
|
||||
&checkbox_showclock,
|
||||
&options_clockformat,
|
||||
&checkbox_guireturnflag,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen());
|
||||
checkbox_speaker.set_value(persistent_memory::config_speaker());
|
||||
checkbox_showsplash.set_value(persistent_memory::config_splash());
|
||||
checkbox_showclock.set_value(!persistent_memory::hide_clock());
|
||||
checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon());
|
||||
|
||||
const auto backlight_config = persistent_memory::config_backlight_timer();
|
||||
checkbox_bloff.set_value(backlight_config.timeout_enabled());
|
||||
options_bloff.set_by_value(backlight_config.timeout_enum());
|
||||
|
||||
if (persistent_memory::clock_with_date()) {
|
||||
options_clockformat.set_selected_index(1);
|
||||
} else {
|
||||
options_clockformat.set_selected_index(0);
|
||||
}
|
||||
|
||||
if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
||||
persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status
|
||||
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
||||
EventDispatcher::send_message(message);
|
||||
|
||||
persistent_memory::set_config_splash(checkbox_showsplash.value());
|
||||
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
|
||||
persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value());
|
||||
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetUIView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_config_backlight_timer({
|
||||
(persistent_memory::backlight_timeout_t)options_bloff.selected_index_value(),
|
||||
checkbox_bloff.value()
|
||||
});
|
||||
|
||||
if (checkbox_showclock.value()){
|
||||
if (options_clockformat.selected_index() == 1)
|
||||
persistent_memory::set_clock_with_date(true);
|
||||
else
|
||||
persistent_memory::set_clock_with_date(false);
|
||||
}
|
||||
|
||||
if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
||||
persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status
|
||||
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
||||
EventDispatcher::send_message(message);
|
||||
|
||||
persistent_memory::set_config_splash(checkbox_showsplash.value());
|
||||
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
|
||||
persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value());
|
||||
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetUIView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Appl. Settings
|
||||
// ---------------------------------------------------------
|
||||
SetAppSettingsView::SetAppSettingsView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_load_app_settings,
|
||||
&checkbox_save_app_settings,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
checkbox_load_app_settings.set_value(persistent_memory::load_app_settings());
|
||||
checkbox_save_app_settings.set_value(persistent_memory::save_app_settings());
|
||||
// ---------------------------------------------------------
|
||||
// Appl. Settings
|
||||
// ---------------------------------------------------------
|
||||
SetAppSettingsView::SetAppSettingsView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_load_app_settings,
|
||||
&checkbox_save_app_settings,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
checkbox_load_app_settings.set_value(persistent_memory::load_app_settings());
|
||||
checkbox_save_app_settings.set_value(persistent_memory::save_app_settings());
|
||||
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_load_app_settings(checkbox_load_app_settings.value());
|
||||
persistent_memory::set_save_app_settings(checkbox_save_app_settings.value());
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_load_app_settings(checkbox_load_app_settings.value());
|
||||
persistent_memory::set_save_app_settings(checkbox_save_app_settings.value());
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetAppSettingsView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
void SetAppSettingsView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
SetAudioView::SetAudioView(NavigationView& nav) {
|
||||
add_children({
|
||||
&labels,
|
||||
&field_tone_mix,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
// ---------------------------------------------------------
|
||||
// Converter Settings
|
||||
// ---------------------------------------------------------
|
||||
SetConverterSettingsView::SetConverterSettingsView(NavigationView& nav) {
|
||||
add_children({
|
||||
&check_show_converter,
|
||||
&check_converter,
|
||||
&converter_mode,
|
||||
&button_converter_freq,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
field_tone_mix.set_value(persistent_memory::tone_mix());
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_tone_mix(field_tone_mix.value());
|
||||
nav.pop();
|
||||
};
|
||||
check_show_converter.set_value(!portapack::persistent_memory::config_hide_converter());
|
||||
check_show_converter.on_select = [this](Checkbox&, bool v) {
|
||||
portapack::persistent_memory::set_config_hide_converter(!v);
|
||||
if( !v )
|
||||
{
|
||||
check_converter.set_value(false);
|
||||
}
|
||||
// Retune to take converter change in account
|
||||
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
|
||||
//Refresh status bar with/out converter
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
check_converter.set_value(portapack::persistent_memory::config_converter());
|
||||
check_converter.on_select = [this](Checkbox&, bool v) {
|
||||
if( v )
|
||||
{
|
||||
check_show_converter.set_value(true);
|
||||
portapack::persistent_memory::set_config_hide_converter(false);
|
||||
}
|
||||
portapack::persistent_memory::set_config_converter(v);
|
||||
// Retune to take converter change in account
|
||||
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
|
||||
//Refresh status bar with/out converter
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
void SetAudioView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
converter_mode.set_by_value( portapack::persistent_memory::config_updown_converter() );
|
||||
converter_mode.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
portapack::persistent_memory::set_config_updown_converter( v );
|
||||
//Refresh status bar with icon up or down
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_bigger_qr,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
button_converter_freq.set_text( to_string_short_freq( portapack::persistent_memory::config_converter_freq() ) + "MHz");
|
||||
button_converter_freq.on_select = [this, &nav](Button& button) {
|
||||
auto new_view = nav.push<FrequencyKeypadView>(portapack::persistent_memory::config_converter_freq() );
|
||||
new_view->on_changed = [this, &button](rf::Frequency f) {
|
||||
portapack::persistent_memory::set_config_converter_freq( f );
|
||||
// Retune to take converter change in account
|
||||
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
|
||||
button_converter_freq.set_text( "<" + to_string_short_freq( f ) + " MHz>" );
|
||||
};
|
||||
};
|
||||
|
||||
checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code());
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value());
|
||||
nav.pop();
|
||||
};
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
void SetConverterSettingsView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
}
|
||||
// ---------------------------------------------------------
|
||||
// Persistent Memory Settings
|
||||
// ---------------------------------------------------------
|
||||
SetPersistentMemoryView::SetPersistentMemoryView(NavigationView& nav) {
|
||||
add_children({
|
||||
&text_pmem_about,
|
||||
&text_pmem_informations,
|
||||
&text_pmem_status,
|
||||
&check_load_mem_at_startup,
|
||||
&button_save_mem_to_file,
|
||||
&button_load_mem_from_file,
|
||||
&button_return
|
||||
});
|
||||
|
||||
void SetQRCodeView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
bool load_mem_at_startup = false ;
|
||||
File pmem_flag_file_handle ;
|
||||
std::string pmem_flag_file = "/SETTINGS/PMEM_FILEFLAG" ;
|
||||
auto result = pmem_flag_file_handle.open(pmem_flag_file);
|
||||
if(!result.is_valid())
|
||||
{
|
||||
load_mem_at_startup = true ;
|
||||
}
|
||||
check_load_mem_at_startup.set_value(load_mem_at_startup);
|
||||
check_load_mem_at_startup.on_select = [this](Checkbox&, bool v) {
|
||||
File pmem_flag_file_handle ;
|
||||
std::string pmem_flag_file = "/SETTINGS/PMEM_FILEFLAG" ;
|
||||
if( v )
|
||||
{
|
||||
auto result = pmem_flag_file_handle.open(pmem_flag_file);
|
||||
if(result.is_valid())
|
||||
{
|
||||
auto result = pmem_flag_file_handle.create(pmem_flag_file); //third: create if it is not there
|
||||
if( !result.is_valid() )
|
||||
{
|
||||
text_pmem_status.set("pmem flag file created");
|
||||
}
|
||||
else
|
||||
{
|
||||
text_pmem_status.set("!err. creating pmem flagfile!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text_pmem_status.set("pmem flag already present");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = delete_file( pmem_flag_file );
|
||||
if( result != 0 )
|
||||
{
|
||||
text_pmem_status.set("!err. deleting pmem flagfile!");
|
||||
}
|
||||
else
|
||||
{
|
||||
text_pmem_status.set("pmem flag file deleted");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Settings main menu
|
||||
// ---------------------------------------------------------
|
||||
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
||||
if( portapack::persistent_memory::show_gui_return_icon() )
|
||||
{
|
||||
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
|
||||
}
|
||||
add_items({
|
||||
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
||||
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
|
||||
{ "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
|
||||
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||
{ "Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
|
||||
{ "App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SetAppSettingsView>(); } },
|
||||
{ "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } }
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
button_save_mem_to_file.on_select = [&nav, this](Button&) {
|
||||
if( !portapack::persistent_memory::save_persistent_settings_to_file("SETTINGS/pmem_settings") )
|
||||
{
|
||||
text_pmem_status.set("!problem saving settings!");
|
||||
}
|
||||
else
|
||||
{
|
||||
text_pmem_status.set("settings saved");
|
||||
}
|
||||
};
|
||||
|
||||
button_load_mem_from_file.on_select = [&nav, this](Button&) {
|
||||
if( !portapack::persistent_memory::load_persistent_settings_from_file("SETTINGS/pmem_settings") )
|
||||
{
|
||||
text_pmem_status.set("!problem loading settings!");
|
||||
}
|
||||
else
|
||||
{
|
||||
text_pmem_status.set("settings loaded");
|
||||
//Refresh status bar with icon up or down
|
||||
StatusRefreshMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
button_return.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetPersistentMemoryView::focus() {
|
||||
button_return.focus();
|
||||
}
|
||||
|
||||
//
|
||||
// Audio settings
|
||||
//
|
||||
SetAudioView::SetAudioView(NavigationView& nav) {
|
||||
add_children({
|
||||
&labels,
|
||||
&field_tone_mix,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
field_tone_mix.set_value(persistent_memory::tone_mix());
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_tone_mix(field_tone_mix.value());
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetAudioView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_bigger_qr,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code());
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value());
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void SetQRCodeView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Settings main menu
|
||||
// ---------------------------------------------------------
|
||||
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
||||
if( portapack::persistent_memory::show_gui_return_icon() )
|
||||
{
|
||||
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
|
||||
}
|
||||
add_items({
|
||||
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
||||
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
|
||||
{ "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
|
||||
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||
{ "Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
|
||||
{ "App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SetAppSettingsView>(); } },
|
||||
{ "Converter", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetConverterSettingsView>(); } },
|
||||
{ "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } },
|
||||
{ "P.Memory Mgmt", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav](){ nav.push<SetPersistentMemoryView>(); } },
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -198,16 +198,6 @@ private:
|
||||
"Turn on bias voltage"
|
||||
};
|
||||
|
||||
Checkbox check_hamitup {
|
||||
{ 18, 14 * 16},
|
||||
7,
|
||||
"HamItUp"
|
||||
};
|
||||
Button button_hamitup_freq {
|
||||
{ 240 - 15 * 8 , 14 * 16 , 15 * 8 , 24 },
|
||||
"",
|
||||
};
|
||||
|
||||
Button button_save {
|
||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Save"
|
||||
@@ -336,6 +326,53 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
class SetConverterSettingsView : public View {
|
||||
public:
|
||||
SetConverterSettingsView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Converter"; };
|
||||
|
||||
private:
|
||||
|
||||
Checkbox check_show_converter {
|
||||
{ 18, 4 * 16},
|
||||
19,
|
||||
"show/hide converter"
|
||||
};
|
||||
|
||||
Checkbox check_converter {
|
||||
{ 18, 6 * 16},
|
||||
7,
|
||||
"enable/disable converter"
|
||||
};
|
||||
|
||||
OptionsField converter_mode {
|
||||
{ 18 , 8 * 16 + 4 },
|
||||
0,
|
||||
{
|
||||
{" + ",0}, // up converter
|
||||
{" - ",1} // down converter
|
||||
}
|
||||
};
|
||||
|
||||
Button button_converter_freq {
|
||||
{ 18 + 4 * 8 , 8 * 16 , 16 * 8 , 24 },
|
||||
"",
|
||||
};
|
||||
|
||||
Button button_save {
|
||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Save"
|
||||
};
|
||||
|
||||
Button button_cancel {
|
||||
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
||||
class SetAudioView : public View {
|
||||
public:
|
||||
SetAudioView(NavigationView& nav);
|
||||
@@ -395,6 +432,54 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
class SetPersistentMemoryView : public View {
|
||||
public:
|
||||
SetPersistentMemoryView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "P.Mem Mgmt"; };
|
||||
|
||||
private:
|
||||
|
||||
Text text_pmem_about {
|
||||
{ 0, 1 * 16, 240 , 16 },
|
||||
"PersistentMemory from/to SD"
|
||||
};
|
||||
|
||||
Text text_pmem_informations {
|
||||
{ 0, 2 * 16, 240 , 16 },
|
||||
"use: when no/dead coin bat."
|
||||
};
|
||||
|
||||
Text text_pmem_status {
|
||||
{ 0, 3 * 16, 240 , 16 },
|
||||
""
|
||||
};
|
||||
|
||||
Checkbox check_load_mem_at_startup {
|
||||
{ 18, 6 * 16},
|
||||
19,
|
||||
"load from sd at startup"
|
||||
};
|
||||
|
||||
Button button_save_mem_to_file {
|
||||
{ 0, 9 * 16, 240, 32 },
|
||||
"save p.mem to sdcard"
|
||||
};
|
||||
|
||||
Button button_load_mem_from_file {
|
||||
{ 0, 12 * 16, 240, 32 },
|
||||
"load p.mem from sdcard"
|
||||
};
|
||||
|
||||
Button button_return {
|
||||
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Return",
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class SettingsMenuView : public BtnGridView {
|
||||
public:
|
||||
SettingsMenuView(NavigationView& nav);
|
||||
|
||||
@@ -197,6 +197,28 @@ static constexpr Bitmap bitmap_icon_debug {
|
||||
{ 16, 16 }, bitmap_icon_debug_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_downconvert_data[] = {
|
||||
0x00, 0x00,
|
||||
0x77, 0x77,
|
||||
0x51, 0x51,
|
||||
0x33, 0x53,
|
||||
0x51, 0x51,
|
||||
0x51, 0x77,
|
||||
0x00, 0x80,
|
||||
0x80, 0x01,
|
||||
0x80, 0x01,
|
||||
0x80, 0x01,
|
||||
0x80, 0x01,
|
||||
0xF8, 0x1F,
|
||||
0xF0, 0x0F,
|
||||
0xE0, 0x07,
|
||||
0xC0, 0x03,
|
||||
0x80, 0x01,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_downconvert {
|
||||
{ 16, 16 }, bitmap_icon_downconvert_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_more_data[] = {
|
||||
0x10,
|
||||
0x10,
|
||||
@@ -825,28 +847,6 @@ static constexpr Bitmap bitmap_icon_rename {
|
||||
{ 16, 16 }, bitmap_icon_rename_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_hamitup_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x22, 0x47,
|
||||
0x22, 0x49,
|
||||
0x22, 0x49,
|
||||
0x22, 0x47,
|
||||
0x22, 0x01,
|
||||
0x22, 0x01,
|
||||
0x1C, 0x41,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_hamitup {
|
||||
{ 16, 16 }, bitmap_icon_hamitup_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_lora_data[] = {
|
||||
0xC0, 0x03,
|
||||
0x30, 0x0C,
|
||||
@@ -1023,6 +1023,28 @@ static constexpr Bitmap bitmap_icon_dmr {
|
||||
{ 16, 16 }, bitmap_icon_dmr_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_upconvert_data[] = {
|
||||
0x80, 0x01,
|
||||
0xC0, 0x03,
|
||||
0xE0, 0x07,
|
||||
0xF0, 0x0F,
|
||||
0xF8, 0x1F,
|
||||
0x80, 0x01,
|
||||
0x80, 0x01,
|
||||
0x80, 0x01,
|
||||
0x80, 0x01,
|
||||
0x00, 0x00,
|
||||
0x77, 0x77,
|
||||
0x51, 0x51,
|
||||
0x33, 0x53,
|
||||
0x51, 0x51,
|
||||
0x51, 0x77,
|
||||
0x00, 0x80,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_upconvert {
|
||||
{ 16, 16 }, bitmap_icon_upconvert_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_clk_int_data[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -28,22 +29,20 @@ using namespace lpc43xx;
|
||||
|
||||
#include "message.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "lz4.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
/* TODO: OK, this is cool, but how do I put the M4 to sleep so I can switch to
|
||||
* a different image? Other than asking the old image to sleep while the M0
|
||||
* makes changes?
|
||||
*
|
||||
* I suppose I could force M4MEMMAP to an invalid memory reason which would
|
||||
* cause an exception and effectively halt the M4. But that feels gross.
|
||||
*/
|
||||
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to, const bool full_reset) {
|
||||
const portapack::spi_flash::chunk_t* chunk = reinterpret_cast<const portapack::spi_flash::chunk_t*>(portapack::spi_flash::images.base());
|
||||
while(chunk->tag) {
|
||||
if( chunk->tag == image_tag ) {
|
||||
/* Initialize M4 code RAM */
|
||||
std::memcpy(reinterpret_cast<void*>(to.base()), &chunk->data[0], chunk->length);
|
||||
if(chunk->tag == image_tag) {
|
||||
|
||||
const void *src = &chunk->data[0];
|
||||
void *dst = reinterpret_cast<void*>(to.base());
|
||||
|
||||
/* extract and initialize M4 code RAM */
|
||||
unlz4_len(src, dst, chunk->compressed_data_size);
|
||||
|
||||
/* M4 core is assumed to be sleeping with interrupts off, so we can mess
|
||||
* with its address space and RAM without concern.
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/* source: https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/lz4-decompression-routine-for-cortex-m0-and-later */
|
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m0
|
||||
.thumb
|
||||
|
||||
/* License: Public Domain - I cannot be held responsible for what it does or does not do if you use it, whether it's modified or not. */
|
||||
/* Entry point = unlz4. On entry: r0 = source, r1 = destination. The first two bytes of the source must contain the length of the compressed data. */
|
||||
|
||||
.func unlz4
|
||||
.global unlz4,unlz4_len
|
||||
.type unlz4,%function
|
||||
.type unlz4_len,%function
|
||||
|
||||
.thumb_func
|
||||
unlz4: ldrh r2,[r0] /* get length of compressed data */
|
||||
adds r0,r0,#2 /* advance source pointer */
|
||||
|
||||
.thumb_func
|
||||
unlz4_len: push {r4-r6,lr} /* save r4, r5, r6 and return-address */
|
||||
adds r5,r2,r0 /* point r5 to end of compressed data */
|
||||
|
||||
getToken: ldrb r6,[r0] /* get token */
|
||||
adds r0,r0,#1 /* advance source pointer */
|
||||
lsrs r4,r6,#4 /* get literal length, keep token in r6 */
|
||||
beq getOffset /* jump forward if there are no literals */
|
||||
bl getLength /* get length of literals */
|
||||
movs r2,r0 /* point r2 to literals */
|
||||
bl copyData /* copy literals (r2=src, r1=dst, r4=len) */
|
||||
movs r0,r2 /* update source pointer */
|
||||
|
||||
getOffset: ldrb r3,[r0,#0] /* get match offset's low byte */
|
||||
subs r2,r1,r3 /* subtract from destination; this will become the match position */
|
||||
ldrb r3,[r0,#1] /* get match offset's high byte */
|
||||
lsls r3,r3,#8 /* shift to high byte */
|
||||
subs r2,r2,r3 /* subtract from match position */
|
||||
adds r0,r0,#2 /* advance source pointer */
|
||||
lsls r4,r6,#28 /* get rid of token's high 28 bits */
|
||||
lsrs r4,r4,#28 /* move the 4 low bits back where they were */
|
||||
bl getLength /* get length of match data */
|
||||
adds r4,r4,#4 /* minimum match length is 4 bytes */
|
||||
bl copyData /* copy match data (r2=src, r1=dst, r4=len) */
|
||||
cmp r0,r5 /* check if we've reached the end of the compressed data */
|
||||
blt getToken /* if not, go get the next token */
|
||||
pop {r4-r6,pc} /* restore r4, r5 and r6, then return */
|
||||
|
||||
.thumb_func
|
||||
getLength: cmp r4,#0x0f /* if length is 15, then more length info follows */
|
||||
bne gotLength /* jump forward if we have the complete length */
|
||||
|
||||
getLengthLoop: ldrb r3,[r0] /* read another byte */
|
||||
adds r0,r0,#1 /* advance source pointer */
|
||||
adds r4,r4,r3 /* add byte to length */
|
||||
cmp r3,#0xff /* check if end reached */
|
||||
beq getLengthLoop /* if not, go round loop */
|
||||
gotLength: bx lr /* return */
|
||||
|
||||
.thumb_func
|
||||
copyData: rsbs r4,r4,#0 /* index = -length */
|
||||
subs r2,r2,r4 /* point to end of source */
|
||||
subs r1,r1,r4 /* point to end of destination */
|
||||
|
||||
copyDataLoop: ldrb r3,[r2,r4] /* read byte from source_end[-index] */
|
||||
strb r3,[r1,r4] /* store byte in destination_end[-index] */
|
||||
adds r4,r4,#1 /* increment index */
|
||||
bne copyDataLoop /* keep going until index wraps to 0 */
|
||||
bx lr /* return */
|
||||
.size unlz4,.-unlz4
|
||||
.endfunc
|
||||
/* 42 narrow instructions = 84 bytes */
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 __LZ4_H__
|
||||
#define __LZ4_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern void unlz4_len(const void *aSource, void *aDestination, uint32_t aLength);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__LZ4_H__*/
|
||||
@@ -515,11 +515,13 @@ bool init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
void shutdown(const bool leave_screen_on) {
|
||||
gpdma::controller.disable();
|
||||
|
||||
backlight()->off();
|
||||
display.shutdown();
|
||||
if (!leave_screen_on) {
|
||||
backlight()->off();
|
||||
display.shutdown();
|
||||
}
|
||||
|
||||
radio::disable();
|
||||
audio::shutdown();
|
||||
|
||||
@@ -63,7 +63,7 @@ void set_antenna_bias(const bool v);
|
||||
bool get_antenna_bias();
|
||||
|
||||
bool init();
|
||||
void shutdown();
|
||||
void shutdown(const bool leave_screen_on = false);
|
||||
|
||||
Backlight* backlight();
|
||||
|
||||
|
||||
@@ -170,8 +170,17 @@ void set_direction(const rf::Direction new_direction) {
|
||||
|
||||
bool set_tuning_frequency(const rf::Frequency frequency) {
|
||||
rf::Frequency final_frequency = frequency ;
|
||||
if( portapack::persistent_memory::config_hamitup() ) {
|
||||
final_frequency = frequency + portapack::persistent_memory::config_hamitup_freq();
|
||||
// if feature is enabled
|
||||
if( portapack::persistent_memory::config_converter() ) {
|
||||
//downconvert
|
||||
if( portapack::persistent_memory::config_updown_converter() )
|
||||
{
|
||||
final_frequency = frequency - portapack::persistent_memory::config_converter_freq();
|
||||
}
|
||||
else //upconvert
|
||||
{
|
||||
final_frequency = frequency + portapack::persistent_memory::config_converter_freq();
|
||||
}
|
||||
}
|
||||
const auto tuning_config = tuning::config::create(final_frequency);
|
||||
if( tuning_config.is_valid() ) {
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
#include "ui_playlist.hpp"
|
||||
#include "ui_view_wav.hpp"
|
||||
#include "ui_whipcalc.hpp"
|
||||
#include "ui_flash_utility.hpp"
|
||||
#include "ui_sd_over_usb.hpp"
|
||||
|
||||
//#include "acars_app.hpp"
|
||||
#include "ais_app.hpp"
|
||||
@@ -111,7 +113,7 @@ SystemStatusView::SystemStatusView(
|
||||
&button_back,
|
||||
&title,
|
||||
&button_title,
|
||||
&button_hamitup,
|
||||
&button_converter,
|
||||
&button_speaker,
|
||||
&button_stealth,
|
||||
//&button_textentry,
|
||||
@@ -127,6 +129,24 @@ SystemStatusView::SystemStatusView(
|
||||
else
|
||||
button_speaker.hidden(true);
|
||||
|
||||
|
||||
if( portapack::persistent_memory::config_hide_converter() )
|
||||
{
|
||||
button_converter.hidden(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
button_converter.hidden(false);
|
||||
if( portapack::persistent_memory::config_converter() )
|
||||
{
|
||||
button_converter.set_foreground(Color::red());
|
||||
}
|
||||
else
|
||||
{
|
||||
button_converter.set_foreground(Color::light_grey());
|
||||
}
|
||||
}
|
||||
|
||||
button_back.id = -1; // Special ID used by FocusManager
|
||||
title.set_style(&style_systemstatus);
|
||||
|
||||
@@ -149,8 +169,8 @@ SystemStatusView::SystemStatusView(
|
||||
this->on_title();
|
||||
};
|
||||
|
||||
button_hamitup.on_select = [this](ImageButton&) {
|
||||
this->on_hamitup();
|
||||
button_converter.on_select = [this](ImageButton&) {
|
||||
this->on_converter();
|
||||
};
|
||||
|
||||
button_speaker.on_select = [this](ImageButton&) {
|
||||
@@ -184,16 +204,33 @@ SystemStatusView::SystemStatusView(
|
||||
}
|
||||
|
||||
void SystemStatusView::refresh() {
|
||||
if( portapack::persistent_memory::config_hamitup() )
|
||||
if( portapack::persistent_memory::config_hide_converter() )
|
||||
{
|
||||
button_hamitup.set_foreground(Color::red());
|
||||
button_converter.hidden(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
button_hamitup.set_foreground(Color::light_grey());
|
||||
if( portapack::persistent_memory::config_updown_converter() )
|
||||
{
|
||||
button_converter.set_bitmap(&bitmap_icon_downconvert);
|
||||
}
|
||||
else
|
||||
{
|
||||
button_converter.set_bitmap(&bitmap_icon_upconvert);
|
||||
}
|
||||
button_converter.hidden(false);
|
||||
if( portapack::persistent_memory::config_converter() )
|
||||
{
|
||||
button_converter.set_foreground(Color::red());
|
||||
}
|
||||
else
|
||||
{
|
||||
button_converter.set_foreground(Color::light_grey());
|
||||
}
|
||||
}
|
||||
// Retune to take hamitup change in account
|
||||
// Retune to take converter change in account
|
||||
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
|
||||
transmitter_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
|
||||
|
||||
if (!portapack::persistent_memory::config_speaker()) {
|
||||
button_speaker.set_foreground(Color::light_grey());
|
||||
@@ -257,16 +294,16 @@ void SystemStatusView::set_title(const std::string new_value) {
|
||||
}
|
||||
}
|
||||
|
||||
void SystemStatusView::on_hamitup() {
|
||||
if(!portapack::persistent_memory::config_hamitup())
|
||||
void SystemStatusView::on_converter() {
|
||||
if(!portapack::persistent_memory::config_converter())
|
||||
{
|
||||
portapack::persistent_memory::set_config_hamitup( true );
|
||||
button_hamitup.set_foreground(Color::red());
|
||||
portapack::persistent_memory::set_config_converter( true );
|
||||
button_converter.set_foreground(Color::red());
|
||||
}
|
||||
else
|
||||
{
|
||||
portapack::persistent_memory::set_config_hamitup( false );
|
||||
button_hamitup.set_foreground(Color::light_grey());
|
||||
portapack::persistent_memory::set_config_converter( false );
|
||||
button_converter.set_foreground(Color::light_grey());
|
||||
}
|
||||
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() ); // Retune
|
||||
}
|
||||
@@ -578,6 +615,8 @@ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
|
||||
{ "Antenna length", ui::Color::green(), &bitmap_icon_tools_antenna, [&nav](){ nav.push<WhipCalcView>(); } },
|
||||
|
||||
{ "Wipe SD card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push<WipeSDView>(); } },
|
||||
{ "Flash Utility", ui::Color::red(), &bitmap_icon_temperature, [&nav](){ nav.push<FlashUtilityView>(); } },
|
||||
{ "SD over USB", ui::Color::yellow(), &bitmap_icon_hackrf, [&nav](){ nav.push<SdOverUsbView>(); } },
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
@@ -684,6 +723,14 @@ SystemView::SystemView(
|
||||
|
||||
navigation_view.push<SystemMenuView>();
|
||||
|
||||
File pmem_flag_file_handle ;
|
||||
std::string pmem_flag_file = "/SETTINGS/PMEM_FILEFLAG" ;
|
||||
auto result = pmem_flag_file_handle.open(pmem_flag_file);
|
||||
if(!result.is_valid())
|
||||
{
|
||||
portapack::persistent_memory::load_persistent_settings_from_file("SETTINGS/pmem_settings");
|
||||
}
|
||||
|
||||
if (portapack::persistent_memory::config_splash())
|
||||
{
|
||||
navigation_view.push<BMPView>();
|
||||
|
||||
@@ -147,9 +147,9 @@ namespace ui
|
||||
Color::light_grey(),
|
||||
Color::dark_grey()};
|
||||
|
||||
ImageButton button_hamitup{
|
||||
ImageButton button_converter{
|
||||
{17 * 8, 0, 2 * 8, 1 * 16},
|
||||
&bitmap_icon_hamitup,
|
||||
&bitmap_icon_upconvert,
|
||||
Color::light_grey(),
|
||||
Color::dark_grey()
|
||||
};
|
||||
@@ -194,7 +194,7 @@ namespace ui
|
||||
SDCardStatusView sd_card_status_view{
|
||||
{28 * 8, 0 * 16, 2 * 8, 1 * 16}};
|
||||
|
||||
void on_hamitup();
|
||||
void on_converter();
|
||||
void on_speaker();
|
||||
void on_stealth();
|
||||
void on_bias_tee();
|
||||
|
||||
@@ -90,8 +90,6 @@ set(CSRC
|
||||
${PORTSRC}
|
||||
${KERNSRC}
|
||||
${TESTSRC}
|
||||
${HALSRC}
|
||||
${PLATFORMSRC}
|
||||
${BOARDSRC}
|
||||
)
|
||||
|
||||
@@ -189,7 +187,7 @@ set(AOPT)
|
||||
set(TOPT "-mthumb -DTHUMB")
|
||||
|
||||
# Define C warning options here
|
||||
set(CWARN "-Wall -Wextra -Wstrict-prototypes")
|
||||
set(CWARN "-Wall -Wextra")
|
||||
|
||||
# Define C++ warning options here
|
||||
set(CPPWARN "-Wall -Wextra")
|
||||
@@ -262,10 +260,11 @@ macro(DeclareTargets chunk_tag name)
|
||||
project("baseband_${name}")
|
||||
|
||||
include(${RULESPATH}/rules.cmake)
|
||||
add_executable(${PROJECT_NAME}.elf $<TARGET_OBJECTS:baseband_shared> ${MODE_CPPSRC})
|
||||
add_executable(${PROJECT_NAME}.elf $<TARGET_OBJECTS:baseband_shared> ${MODE_CPPSRC} ${HALSRC} ${PLATFORMSRC})
|
||||
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_DEPENDS ${LDSCRIPT})
|
||||
add_definitions(${DEFS})
|
||||
include_directories(. ${INCDIR})
|
||||
target_compile_definitions(${PROJECT_NAME}.elf PUBLIC "-DBASEBAND_${name}")
|
||||
include_directories(. ${INCDIR} ${MODE_INCDIR})
|
||||
link_directories(${LLIBDIR})
|
||||
target_link_libraries(${PROJECT_NAME}.elf ${LIBS})
|
||||
target_link_libraries(${PROJECT_NAME}.elf -Wl,-Map=${PROJECT_NAME}.map)
|
||||
@@ -273,7 +272,8 @@ macro(DeclareTargets chunk_tag name)
|
||||
add_custom_command(
|
||||
OUTPUT ${PROJECT_NAME}.bin ${PROJECT_NAME}.img
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
|
||||
COMMAND ${MAKE_IMAGE_CHUNK} ${PROJECT_NAME}.bin ${chunk_tag} ${PROJECT_NAME}.img
|
||||
COMMAND ${LZ4} -f -9 ${PROJECT_NAME}.bin ${PROJECT_NAME}.lz4
|
||||
COMMAND ${MAKE_IMAGE_CHUNK} ${PROJECT_NAME}.lz4 ${chunk_tag} ${PROJECT_NAME}.img
|
||||
DEPENDS ${PROJECT_NAME}.elf ${MAKE_IMAGE_CHUNK}
|
||||
VERBATIM
|
||||
)
|
||||
@@ -504,11 +504,70 @@ set(MODE_CPPSRC
|
||||
)
|
||||
DeclareTargets(PWFM wfm_audio)
|
||||
|
||||
### Flash Utility
|
||||
|
||||
include(${CHIBIOS_PORTAPACK}/os/various/fatfs_bindings/fatfs.cmake)
|
||||
set(MODE_INCDIR ${FATFSINC})
|
||||
set(MODE_CPPSRC
|
||||
proc_flash_utility.cpp
|
||||
w25q80bv.cpp
|
||||
${FATFSSRC}
|
||||
)
|
||||
DeclareTargets(PFUT flash_utility)
|
||||
|
||||
### SD over USB
|
||||
|
||||
set(MODE_INCDIR
|
||||
${HACKRF_PATH}/firmware
|
||||
${HACKRF_PATH}/firmware/common
|
||||
${HACKRF_PATH}/firmware/libopencm3/include
|
||||
)
|
||||
set(MODE_CPPSRC
|
||||
sd_over_usb/proc_sd_over_usb.cpp
|
||||
|
||||
sd_over_usb/scsi.c
|
||||
sd_over_usb/diskio.c
|
||||
sd_over_usb/sd_over_usb.c
|
||||
sd_over_usb/usb_descriptor.c
|
||||
sd_over_usb/hackrf_core.c
|
||||
|
||||
${HACKRF_PATH}/firmware/common/usb.c
|
||||
${HACKRF_PATH}/firmware/common/usb_queue.c
|
||||
${HACKRF_PATH}/firmware/hackrf_usb/usb_device.c
|
||||
${HACKRF_PATH}/firmware/hackrf_usb/usb_endpoint.c
|
||||
${HACKRF_PATH}/firmware/common/usb_request.c
|
||||
${HACKRF_PATH}/firmware/common/usb_standard_request.c
|
||||
${HACKRF_PATH}/firmware/common/platform_detect.c
|
||||
${HACKRF_PATH}/firmware/common/gpio_lpc.c
|
||||
${HACKRF_PATH}/firmware/common/firmware_info.c
|
||||
${HACKRF_PATH}/firmware/common/si5351c.c
|
||||
${HACKRF_PATH}/firmware/common/i2c_bus.c
|
||||
${HACKRF_PATH}/firmware/common/mixer.c
|
||||
${HACKRF_PATH}/firmware/common/clkin.c
|
||||
${HACKRF_PATH}/firmware/common/spi_bus.c
|
||||
${HACKRF_PATH}/firmware/common/sgpio.c
|
||||
${HACKRF_PATH}/firmware/common/rf_path.c
|
||||
${HACKRF_PATH}/firmware/common/i2c_lpc.c
|
||||
${HACKRF_PATH}/firmware/common/spi_ssp.c
|
||||
${HACKRF_PATH}/firmware/common/rffc5071_spi.c
|
||||
${HACKRF_PATH}/firmware/common/rffc5071.c
|
||||
${HACKRF_PATH}/firmware/common/clkin.c
|
||||
${HACKRF_PATH}/firmware/common/gpdma.c
|
||||
|
||||
${HACKRF_PATH}/firmware/libopencm3/lib/cm3/nvic.c
|
||||
${HACKRF_PATH}/firmware/libopencm3/lib/cm3/sync.c
|
||||
${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/scu.c
|
||||
${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/timer.c
|
||||
${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/i2c.c
|
||||
)
|
||||
DeclareTargets(PUSB sd_over_usb)
|
||||
|
||||
### HackRF "factory" firmware
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT hackrf.img
|
||||
COMMAND ${MAKE_IMAGE_CHUNK} ${HACKRF_FIRMWARE_BIN_IMAGE} HRF1 hackrf.img 98304
|
||||
COMMAND ${LZ4} -f -9 ${HACKRF_FIRMWARE_BIN_IMAGE} hackrf.lz4
|
||||
COMMAND ${MAKE_IMAGE_CHUNK} hackrf.lz4 HRF1 hackrf.img
|
||||
DEPENDS ${HACKRF_FIRMWARE_BIN_FILENAME} ${MAKE_IMAGE_CHUNK}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
@@ -36,6 +36,7 @@ inline uint32_t get_free_stack_space(){
|
||||
return stack_space_left;
|
||||
}
|
||||
|
||||
/* Executes a breakpoint only when a debugger is attached. */
|
||||
#define HALT_IF_DEBUGGING() \
|
||||
do { \
|
||||
if ((*(volatile uint32_t *)0xE000EDF0) & (1 << 0)) { \
|
||||
@@ -43,4 +44,9 @@ inline uint32_t get_free_stack_space(){
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Stops execution until a debugger is attached. */
|
||||
#define HALT_UNTIL_DEBUGGING() \
|
||||
while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \
|
||||
__asm__ __volatile__("bkpt 1")
|
||||
|
||||
#endif/*__DEBUG_H__*/
|
||||
|
||||
@@ -119,7 +119,11 @@
|
||||
* @brief Enables the SDC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
|
||||
#if defined(BASEBAND_flash_utility) || defined(BASEBAND_sd_over_usb)
|
||||
#define HAL_USE_SDC TRUE
|
||||
#else
|
||||
#define HAL_USE_SDC FALSE
|
||||
#endif /* BASEBAND_flash_utility */
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 "ch.h"
|
||||
#include "hal.h"
|
||||
#include "ff.h"
|
||||
|
||||
#include "w25q80bv.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#define PAGE_LEN 256U
|
||||
#define NUM_PAGES 4096U
|
||||
|
||||
void initialize_flash();
|
||||
void erase_flash();
|
||||
void initialize_sdcard();
|
||||
void write_firmware(FIL *);
|
||||
void write_page(size_t, uint8_t *, size_t);
|
||||
|
||||
int main() {
|
||||
const TCHAR *filename = reinterpret_cast<const TCHAR *>(&shared_memory.bb_data.data[0]);
|
||||
|
||||
initialize_flash();
|
||||
palSetPad(LED_PORT, LEDRX_PAD);
|
||||
erase_flash();
|
||||
|
||||
initialize_sdcard();
|
||||
|
||||
FIL firmware_file;
|
||||
if (f_open(&firmware_file, filename, FA_READ) != FR_OK) chDbgPanic("no file");
|
||||
|
||||
palSetPad(LED_PORT, LEDTX_PAD);
|
||||
|
||||
write_firmware(&firmware_file);
|
||||
|
||||
palClearPad(LED_PORT, LEDTX_PAD);
|
||||
palClearPad(LED_PORT, LEDRX_PAD);
|
||||
|
||||
f_close(&firmware_file);
|
||||
|
||||
while(1)
|
||||
__WFE();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initialize_flash() {
|
||||
w25q80bv::disable_spifi();
|
||||
w25q80bv::initialite_spi();
|
||||
w25q80bv::setup();
|
||||
|
||||
w25q80bv::wait_for_device();
|
||||
w25q80bv::wait_not_busy();
|
||||
}
|
||||
|
||||
void erase_flash() {
|
||||
w25q80bv::remove_write_protection();
|
||||
w25q80bv::wait_not_busy();
|
||||
|
||||
w25q80bv::erase_chip();
|
||||
w25q80bv::wait_not_busy();
|
||||
}
|
||||
|
||||
void initialize_sdcard() {
|
||||
static FATFS fs;
|
||||
|
||||
sdcStart(&SDCD1, nullptr);
|
||||
if (sdcConnect(&SDCD1) == CH_FAILED) chDbgPanic("no sd card #1");
|
||||
if (f_mount(&fs, reinterpret_cast<const TCHAR*>(_T("")), 1) != FR_OK) chDbgPanic("no sd card #2");
|
||||
}
|
||||
|
||||
void write_firmware(FIL *firmware_file) {
|
||||
uint8_t *data_buffer = &shared_memory.bb_data.data[0];
|
||||
|
||||
for (size_t page_index = 0; page_index < NUM_PAGES; page_index++) {
|
||||
if (page_index % 32 == 0)
|
||||
palTogglePad(LED_PORT, LEDTX_PAD);
|
||||
|
||||
size_t bytes_read;
|
||||
if (f_read(firmware_file, data_buffer, PAGE_LEN, &bytes_read) != FR_OK) chDbgPanic("no data");
|
||||
|
||||
if (bytes_read > 0)
|
||||
write_page(page_index, data_buffer, bytes_read);
|
||||
|
||||
if (bytes_read < PAGE_LEN)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void write_page(size_t page_index, uint8_t *data_buffer, size_t data_length) {
|
||||
w25q80bv::wait_not_busy();
|
||||
w25q80bv::remove_write_protection();
|
||||
w25q80bv::wait_not_busy();
|
||||
w25q80bv::write(page_index, data_buffer, data_length);
|
||||
w25q80bv::wait_not_busy();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 "diskio.h"
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
uint32_t get_capacity(void) {
|
||||
return mmcsdGetCardCapacity(&SDCD1);
|
||||
}
|
||||
|
||||
bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n) {
|
||||
return sdcRead(&SDCD1, startblk, buf, n);
|
||||
}
|
||||
|
||||
bool_t write_block(uint32_t startblk, uint8_t *buf, uint32_t n) {
|
||||
return sdcWrite(&SDCD1, startblk, buf, n);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 __DISKIO_H__
|
||||
#define __DISKIO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <chtypes.h>
|
||||
|
||||
uint32_t get_capacity(void);
|
||||
bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n);
|
||||
bool_t write_block(uint32_t startblk, uint8_t *buf, uint32_t n);
|
||||
|
||||
#endif /* __DISKIO_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
extern "C" {
|
||||
void start_usb(void);
|
||||
void irq_usb(void);
|
||||
void usb_transfer(void);
|
||||
|
||||
CH_IRQ_HANDLER(Vector60) {
|
||||
irq_usb();
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
sdcStart(&SDCD1, nullptr);
|
||||
if (sdcConnect(&SDCD1) == CH_FAILED) chDbgPanic("no sd card #1");
|
||||
|
||||
start_usb();
|
||||
|
||||
while (true) {
|
||||
usb_transfer();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 "scsi.h"
|
||||
#include "diskio.h"
|
||||
|
||||
volatile bool usb_bulk_block_done = false;
|
||||
|
||||
void usb_bulk_block_cb(void* user_data, unsigned int bytes_transferred) {
|
||||
usb_bulk_block_done = true;
|
||||
|
||||
(void)user_data;
|
||||
(void)bytes_transferred;
|
||||
}
|
||||
|
||||
void usb_send_bulk(void* const data, const uint32_t maximum_length) {
|
||||
usb_bulk_block_done = false;
|
||||
|
||||
usb_transfer_schedule_block(
|
||||
&usb_endpoint_bulk_in,
|
||||
data,
|
||||
maximum_length,
|
||||
usb_bulk_block_cb,
|
||||
NULL);
|
||||
|
||||
while (!usb_bulk_block_done);
|
||||
}
|
||||
|
||||
void usb_receive_bulk(void* const data, const uint32_t maximum_length) {
|
||||
usb_bulk_block_done = false;
|
||||
|
||||
usb_transfer_schedule_block(
|
||||
&usb_endpoint_bulk_out,
|
||||
data,
|
||||
maximum_length,
|
||||
usb_bulk_block_cb,
|
||||
NULL);
|
||||
|
||||
while (!usb_bulk_block_done);
|
||||
}
|
||||
|
||||
void usb_send_csw(msd_cbw_t *msd_cbw_data, uint8_t status) {
|
||||
msd_csw_t csw = {
|
||||
.signature = MSD_CSW_SIGNATURE,
|
||||
.tag = msd_cbw_data->tag,
|
||||
.data_residue = 0,
|
||||
.status = status
|
||||
};
|
||||
|
||||
memcpy(&usb_bulk_buffer[0], &csw, sizeof(msd_csw_t));
|
||||
usb_send_bulk(&usb_bulk_buffer[0], sizeof(msd_csw_t));
|
||||
}
|
||||
|
||||
uint8_t handle_inquiry(msd_cbw_t *msd_cbw_data) {
|
||||
(void)msd_cbw_data;
|
||||
|
||||
scsi_inquiry_response_t ret = {
|
||||
0x00, /* direct access block device */
|
||||
0x80, /* removable */
|
||||
0x00, //0x04, /* SPC-2 */
|
||||
0x00, //0x02, /* response data format */
|
||||
0x20, /* response has 0x20 + 4 bytes */
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
"Mayhem",
|
||||
"Portapack MSD",
|
||||
{'v','1','.','6'}
|
||||
};
|
||||
|
||||
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_inquiry_response_t));
|
||||
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_inquiry_response_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t handle_inquiry_serial_number(msd_cbw_t *msd_cbw_data) {
|
||||
(void)msd_cbw_data;
|
||||
|
||||
scsi_unit_serial_number_inquiry_response_t ret = {
|
||||
.peripheral = 0x00,
|
||||
.page_code = 0x80,
|
||||
.reserved = 0,
|
||||
.page_length = 0x08,
|
||||
.serialNumber = "Mayhem"
|
||||
};
|
||||
|
||||
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_unit_serial_number_inquiry_response_t));
|
||||
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_unit_serial_number_inquiry_response_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t read_format_capacities(msd_cbw_t *msd_cbw_data) {
|
||||
uint16_t len = msd_cbw_data->cmd_data[7] << 8 | msd_cbw_data->cmd_data[8];
|
||||
|
||||
if (len != 0) {
|
||||
size_t num_blocks = get_capacity();
|
||||
|
||||
scsi_read_format_capacities_response_t ret = {
|
||||
.header = {0, 0, 0, 1 * 8 /* num_entries * 8 */},
|
||||
.blocknum = {((num_blocks) >> 24)& 0xff, ((num_blocks) >> 16)& 0xff, ((num_blocks) >> 8)& 0xff, num_blocks & 0xff},
|
||||
.blocklen = {0b10 /* formated */, 0, (512) >> 8, 0},
|
||||
};
|
||||
|
||||
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_format_capacities_response_t));
|
||||
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_read_format_capacities_response_t));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t read_capacity10(msd_cbw_t *msd_cbw_data) {
|
||||
(void)msd_cbw_data;
|
||||
|
||||
size_t num_blocks = get_capacity();
|
||||
|
||||
scsi_read_capacity10_response_t ret = {
|
||||
.last_block_addr = cpu_to_be32(num_blocks - 1),
|
||||
.block_size = cpu_to_be32(512)
|
||||
};
|
||||
|
||||
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_capacity10_response_t));
|
||||
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_read_capacity10_response_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t request_sense(msd_cbw_t *msd_cbw_data) {
|
||||
(void)msd_cbw_data;
|
||||
|
||||
scsi_sense_response_t ret = {
|
||||
.byte = { 0x70, 0, SCSI_SENSE_KEY_GOOD, 0,
|
||||
0, 0, 0, 8,
|
||||
0, 0 ,0 ,0,
|
||||
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER, 0, 0,
|
||||
0, 0 }
|
||||
};
|
||||
|
||||
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_sense_response_t));
|
||||
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_sense_response_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t mode_sense6(msd_cbw_t *msd_cbw_data) {
|
||||
(void)msd_cbw_data;
|
||||
|
||||
scsi_mode_sense6_response_t ret = {
|
||||
.byte = {
|
||||
sizeof(scsi_mode_sense6_response_t) - 1,
|
||||
0,
|
||||
0,
|
||||
0 }
|
||||
};
|
||||
|
||||
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_mode_sense6_response_t));
|
||||
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_mode_sense6_response_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static data_request_t decode_data_request(const uint8_t *cmd) {
|
||||
data_request_t req;
|
||||
uint32_t lba;
|
||||
uint16_t blk;
|
||||
|
||||
memcpy(&lba, &cmd[2], sizeof(lba));
|
||||
memcpy(&blk, &cmd[7], sizeof(blk));
|
||||
|
||||
req.first_lba = be32_to_cpu(lba);
|
||||
req.blk_cnt = be16_to_cpu(blk);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
uint8_t data_read10(msd_cbw_t *msd_cbw_data) {
|
||||
data_request_t req = decode_data_request(msd_cbw_data->cmd_data);
|
||||
|
||||
for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) {
|
||||
read_block(req.first_lba + block_index, &usb_bulk_buffer[0], 1 /* n blocks */);
|
||||
usb_send_bulk(&usb_bulk_buffer[0], 512);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t data_write10(msd_cbw_t *msd_cbw_data) {
|
||||
data_request_t req = decode_data_request(msd_cbw_data->cmd_data);
|
||||
|
||||
for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) {
|
||||
usb_receive_bulk(&usb_bulk_buffer[0], 512);
|
||||
write_block(req.first_lba + block_index, &usb_bulk_buffer[0], 1 /* n blocks */);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scsi_command(msd_cbw_t *msd_cbw_data) {
|
||||
uint8_t status = 1;
|
||||
|
||||
switch (msd_cbw_data->cmd_data[0]) {
|
||||
case SCSI_CMD_INQUIRY:
|
||||
if ((msd_cbw_data->cmd_data[1] & 0b1) && msd_cbw_data->cmd_data[2] == 0x80) {
|
||||
status = handle_inquiry_serial_number(msd_cbw_data);
|
||||
}
|
||||
else if ((msd_cbw_data->cmd_data[1] & 0b11) || msd_cbw_data->cmd_data[2] != 0) {
|
||||
status = 1;
|
||||
}
|
||||
else {
|
||||
status = handle_inquiry(msd_cbw_data);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SCSI_CMD_REQUEST_SENSE:
|
||||
status = request_sense(msd_cbw_data);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_READ_CAPACITY_10:
|
||||
status = read_capacity10(msd_cbw_data);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_READ_10:
|
||||
status = data_read10(msd_cbw_data);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_WRITE_10:
|
||||
status = data_write10(msd_cbw_data);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_TEST_UNIT_READY:
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
case SCSI_CMD_MODE_SENSE_6:
|
||||
status = mode_sense6(msd_cbw_data);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_READ_FORMAT_CAPACITIES:
|
||||
status = read_format_capacities(msd_cbw_data);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_VERIFY_10:
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
usb_send_csw(msd_cbw_data, status);
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 __SCSI_H__
|
||||
#define __SCSI_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <common/usb.h>
|
||||
#include <common/usb_request.h>
|
||||
#include <common/usb_standard_request.h>
|
||||
#include <hackrf_usb/usb_device.h>
|
||||
#include <hackrf_usb/usb_endpoint.h>
|
||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
#include "platform_detect.h"
|
||||
#include "hackrf_core.h"
|
||||
#include "usb_bulk_buffer.h"
|
||||
|
||||
#define MSD_CBW_SIGNATURE 0x43425355
|
||||
#define MSD_CSW_SIGNATURE 0x53425355
|
||||
|
||||
#define SCSI_CMD_TEST_UNIT_READY 0x00
|
||||
#define SCSI_CMD_REQUEST_SENSE 0x03
|
||||
#define SCSI_CMD_INQUIRY 0x12
|
||||
#define SCSI_CMD_MODE_SENSE_6 0x1A
|
||||
#define SCSI_CMD_START_STOP_UNIT 0x1B
|
||||
#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
|
||||
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
|
||||
#define SCSI_CMD_READ_CAPACITY_10 0x25
|
||||
#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
|
||||
#define SCSI_CMD_READ_10 0x28
|
||||
#define SCSI_CMD_WRITE_10 0x2A
|
||||
#define SCSI_CMD_VERIFY_10 0x2F
|
||||
|
||||
#define SCSI_SENSE_KEY_GOOD 0x00
|
||||
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
|
||||
#define SCSI_SENSE_KEY_NOT_READY 0x02
|
||||
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
|
||||
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
|
||||
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
|
||||
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
|
||||
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
|
||||
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
|
||||
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
|
||||
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
|
||||
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
|
||||
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
|
||||
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
|
||||
|
||||
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
|
||||
#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
|
||||
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
|
||||
#define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28
|
||||
#define SCSI_ASENSE_WRITE_PROTECTED 0x27
|
||||
#define SCSI_ASENSE_FORMAT_ERROR 0x31
|
||||
#define SCSI_ASENSE_INVALID_COMMAND 0x20
|
||||
#define SCSI_ASENSE_LBA_OUT_OF_RANGE 0x21
|
||||
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
|
||||
|
||||
#define SCSI_ASENSEQ_NO_QUALIFIER 0x00
|
||||
#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
|
||||
#define SCSI_ASENSEQ_INIT_COMMAND_REQUIRED 0x02
|
||||
#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
|
||||
|
||||
#define MSD_CBW_SIGNATURE 0x43425355
|
||||
#define MSD_CSW_SIGNATURE 0x53425355
|
||||
|
||||
#define USB_TRANSFER_SIZE 0x2000
|
||||
|
||||
typedef struct {
|
||||
uint32_t signature;
|
||||
uint32_t tag;
|
||||
uint32_t data_len;
|
||||
uint8_t flags;
|
||||
uint8_t lun;
|
||||
uint8_t cmd_len;
|
||||
uint8_t cmd_data[16];
|
||||
} __attribute__((packed)) msd_cbw_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t peripheral;
|
||||
uint8_t removable;
|
||||
uint8_t version;
|
||||
uint8_t response_data_format;
|
||||
uint8_t additional_length;
|
||||
uint8_t sccstp;
|
||||
uint8_t bqueetc;
|
||||
uint8_t cmdque;
|
||||
uint8_t vendorID[8];
|
||||
uint8_t productID[16];
|
||||
uint8_t productRev[4];
|
||||
} scsi_inquiry_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t signature;
|
||||
uint32_t tag;
|
||||
uint32_t data_residue;
|
||||
uint8_t status;
|
||||
} __attribute__((packed)) msd_csw_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t header[4];
|
||||
uint8_t blocknum[4];
|
||||
uint8_t blocklen[4];
|
||||
} scsi_read_format_capacities_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t last_block_addr;
|
||||
uint32_t block_size;
|
||||
} scsi_read_capacity10_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t byte[18];
|
||||
} scsi_sense_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t byte[4];
|
||||
} scsi_mode_sense6_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t first_lba;
|
||||
uint16_t blk_cnt;
|
||||
} data_request_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t peripheral;
|
||||
uint8_t page_code;
|
||||
uint8_t reserved;
|
||||
uint8_t page_length;
|
||||
uint8_t serialNumber[8];
|
||||
} scsi_unit_serial_number_inquiry_response_t;
|
||||
|
||||
static inline uint16_t bswap_16(const uint16_t x)
|
||||
__attribute__ ((warn_unused_result))
|
||||
__attribute__ ((const))
|
||||
__attribute__ ((always_inline));
|
||||
|
||||
static inline uint16_t bswap_16(const uint16_t x) {
|
||||
uint8_t tmp;
|
||||
union { uint16_t x; uint8_t b[2]; } data;
|
||||
|
||||
data.x = x;
|
||||
tmp = data.b[0];
|
||||
data.b[0] = data.b[1];
|
||||
data.b[1] = tmp;
|
||||
|
||||
return data.x;
|
||||
}
|
||||
|
||||
static inline uint32_t bswap_32(const uint32_t x)
|
||||
__attribute__ ((warn_unused_result))
|
||||
__attribute__ ((const))
|
||||
__attribute__ ((always_inline));
|
||||
|
||||
static inline uint32_t bswap_32(const uint32_t x) {
|
||||
uint8_t tmp;
|
||||
union { uint32_t x; uint8_t b[4]; } data;
|
||||
|
||||
data.x = x;
|
||||
tmp = data.b[0];
|
||||
data.b[0] = data.b[3];
|
||||
data.b[3] = tmp;
|
||||
tmp = data.b[1];
|
||||
data.b[1] = data.b[2];
|
||||
data.b[2] = tmp;
|
||||
|
||||
return data.x;
|
||||
}
|
||||
|
||||
#define be16_to_cpu(x) bswap_16(x)
|
||||
#define be32_to_cpu(x) bswap_32(x)
|
||||
|
||||
#define cpu_to_be16(x) bswap_16(x)
|
||||
#define cpu_to_be32(x) bswap_32(x)
|
||||
|
||||
void scsi_command(msd_cbw_t *msd_cbw_data);
|
||||
|
||||
#endif /* __SCSI_H__ */
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 "sd_over_usb.h"
|
||||
#include "scsi.h"
|
||||
|
||||
bool scsi_running = false;
|
||||
|
||||
usb_request_status_t report_max_lun(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
endpoint->buffer[0] = 0;
|
||||
usb_transfer_schedule_block(
|
||||
endpoint->in,
|
||||
&endpoint->buffer,
|
||||
1,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
|
||||
scsi_running = true;
|
||||
}
|
||||
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_class_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) {
|
||||
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
|
||||
|
||||
volatile uint8_t request = endpoint->setup.request;
|
||||
|
||||
if (request == 0xFE)
|
||||
return report_max_lun(endpoint, stage);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const usb_request_handlers_t usb_request_handlers = {
|
||||
.standard = usb_standard_request,
|
||||
.class = usb_class_request,
|
||||
.vendor = 0,
|
||||
.reserved = 0
|
||||
};
|
||||
|
||||
void usb_configuration_changed(usb_device_t* const device) {
|
||||
(void)device;
|
||||
|
||||
usb_endpoint_init(&usb_endpoint_bulk_in);
|
||||
usb_endpoint_init(&usb_endpoint_bulk_out);
|
||||
}
|
||||
|
||||
void start_usb(void) {
|
||||
detect_hardware_platform();
|
||||
pin_setup();
|
||||
cpu_clock_init();
|
||||
|
||||
usb_set_configuration_changed_cb(usb_configuration_changed);
|
||||
usb_peripheral_reset();
|
||||
|
||||
usb_device_init(0, &usb_device);
|
||||
|
||||
usb_queue_init(&usb_endpoint_control_out_queue);
|
||||
usb_queue_init(&usb_endpoint_control_in_queue);
|
||||
usb_queue_init(&usb_endpoint_bulk_out_queue);
|
||||
usb_queue_init(&usb_endpoint_bulk_in_queue);
|
||||
|
||||
usb_endpoint_init(&usb_endpoint_control_out);
|
||||
usb_endpoint_init(&usb_endpoint_control_in);
|
||||
|
||||
nvic_set_priority(NVIC_USB0_IRQ, 255);
|
||||
|
||||
usb_run(&usb_device);
|
||||
}
|
||||
|
||||
void stop_usb(void) {
|
||||
usb_peripheral_reset();
|
||||
}
|
||||
|
||||
void irq_usb(void) {
|
||||
usb0_isr();
|
||||
}
|
||||
|
||||
volatile bool transfer_complete = false;
|
||||
void scsi_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred)
|
||||
{
|
||||
(void)user_data;
|
||||
(void)bytes_transferred;
|
||||
|
||||
transfer_complete = true;
|
||||
}
|
||||
|
||||
void usb_transfer(void) {
|
||||
if (scsi_running) {
|
||||
transfer_complete = false;
|
||||
usb_transfer_schedule_block(
|
||||
&usb_endpoint_bulk_out,
|
||||
&usb_bulk_buffer[0x4000],
|
||||
USB_TRANSFER_SIZE,
|
||||
scsi_bulk_transfer_complete,
|
||||
NULL);
|
||||
|
||||
while (!transfer_complete);
|
||||
|
||||
msd_cbw_t *msd_cbw_data = (msd_cbw_t *) &usb_bulk_buffer[0x4000];
|
||||
|
||||
if (msd_cbw_data->signature == MSD_CBW_SIGNATURE){
|
||||
scsi_command(msd_cbw_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 __USB_SD_OVER_USB_H__
|
||||
#define __USB_SD_OVER_USB_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <common/usb.h>
|
||||
#include <common/usb_request.h>
|
||||
#include <common/usb_standard_request.h>
|
||||
#include <hackrf_usb/usb_device.h>
|
||||
#include <hackrf_usb/usb_endpoint.h>
|
||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
#include "platform_detect.h"
|
||||
#include "hackrf_core.h"
|
||||
#include "usb_bulk_buffer.h"
|
||||
|
||||
void start_usb(void);
|
||||
void stop_usb(void);
|
||||
void irq_usb(void);
|
||||
void usb_transfer(void);
|
||||
|
||||
#endif /* __USB_SD_OVER_USB_H__ */
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* 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 __USB_BULK_BUFFER_H__
|
||||
#define __USB_BULK_BUFFER_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define USB_BULK_BUFFER_SIZE 0x8000
|
||||
#define USB_BULK_BUFFER_MASK 0x7FFF
|
||||
|
||||
/* Address of usb_bulk_buffer is set in ldscripts. If you change the name of this
|
||||
* variable, it won't be where it needs to be in the processor's address space,
|
||||
* unless you also adjust the ldscripts.
|
||||
*/
|
||||
extern uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE];
|
||||
|
||||
#endif /*__USB_BULK_BUFFER_H__*/
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2012 Jared Boone
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include "usb_type.h"
|
||||
#include "usb_descriptor.h"
|
||||
|
||||
#define USB_VENDOR_ID (0x1D50)
|
||||
|
||||
#ifdef HACKRF_ONE
|
||||
#define USB_PRODUCT_ID (0x6089)
|
||||
#elif JAWBREAKER
|
||||
#define USB_PRODUCT_ID (0x604B)
|
||||
#elif RAD1O
|
||||
#define USB_PRODUCT_ID (0xCC15)
|
||||
#else
|
||||
#define USB_PRODUCT_ID (0xFFFF)
|
||||
#endif
|
||||
|
||||
#define USB_API_VERSION (0x0107)
|
||||
|
||||
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
|
||||
|
||||
#define USB_MAX_PACKET0 (64)
|
||||
#define USB_MAX_PACKET_BULK_FS (64)
|
||||
#define USB_MAX_PACKET_BULK_HS (512)
|
||||
|
||||
#define USB_BULK_IN_EP_ADDR (0x81)
|
||||
#define USB_BULK_OUT_EP_ADDR (0x02)
|
||||
|
||||
#define USB_STRING_LANGID (0x0409)
|
||||
|
||||
uint8_t usb_descriptor_device[] = {
|
||||
18, // bLength
|
||||
USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType
|
||||
USB_WORD(0x0200), // bcdUSB
|
||||
0x00, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
USB_MAX_PACKET0, // bMaxPacketSize0
|
||||
USB_WORD(USB_VENDOR_ID), // idVendor
|
||||
USB_WORD(USB_PRODUCT_ID), // idProduct
|
||||
USB_WORD(USB_API_VERSION), // bcdDevice
|
||||
0x01, // iManufacturer
|
||||
0x02, // iProduct
|
||||
0x04, // iSerialNumber
|
||||
0x01 // bNumConfigurations
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_device_qualifier[] = {
|
||||
10, // bLength
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType
|
||||
USB_WORD(0x0200), // bcdUSB
|
||||
0x00, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
64, // bMaxPacketSize0
|
||||
0x01, // bNumOtherSpeedConfigurations
|
||||
0x00 // bReserved
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_configuration_full_speed[] = {
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0x08, // bInterfaceClass: vendor-specific
|
||||
0x06, // bInterfaceSubClass
|
||||
0x50, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_configuration_high_speed[] = {
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0x08, // bInterfaceClass: vendor-specific
|
||||
0x06, // bInterfaceSubClass
|
||||
0x50, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_languages[] = {
|
||||
0x04, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
USB_WORD(USB_STRING_LANGID), // wLANGID
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
uint8_t usb_descriptor_string_manufacturer[] = {
|
||||
40, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'G', 0x00,
|
||||
'r', 0x00,
|
||||
'e', 0x00,
|
||||
'a', 0x00,
|
||||
't', 0x00,
|
||||
' ', 0x00,
|
||||
'S', 0x00,
|
||||
'c', 0x00,
|
||||
'o', 0x00,
|
||||
't', 0x00,
|
||||
't', 0x00,
|
||||
' ', 0x00,
|
||||
'G', 0x00,
|
||||
'a', 0x00,
|
||||
'd', 0x00,
|
||||
'g', 0x00,
|
||||
'e', 0x00,
|
||||
't', 0x00,
|
||||
's', 0x00,
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_product[] = {
|
||||
#ifdef HACKRF_ONE
|
||||
43, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'P', 0x00,
|
||||
'o', 0x00,
|
||||
'r', 0x00,
|
||||
't', 0x00,
|
||||
'a', 0x00,
|
||||
'P', 0x00,
|
||||
'a', 0x00,
|
||||
'c', 0x00,
|
||||
'k', 0x00,
|
||||
' ', 0x00,
|
||||
|
||||
'M', 0x00,
|
||||
'a', 0x00,
|
||||
'y', 0x00,
|
||||
'h', 0x00,
|
||||
'e', 0x00,
|
||||
'm', 0x00,
|
||||
|
||||
#elif JAWBREAKER
|
||||
36, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'H', 0x00,
|
||||
'a', 0x00,
|
||||
'c', 0x00,
|
||||
'k', 0x00,
|
||||
'R', 0x00,
|
||||
'F', 0x00,
|
||||
' ', 0x00,
|
||||
'J', 0x00,
|
||||
'a', 0x00,
|
||||
'w', 0x00,
|
||||
'b', 0x00,
|
||||
'r', 0x00,
|
||||
'e', 0x00,
|
||||
'a', 0x00,
|
||||
'k', 0x00,
|
||||
'e', 0x00,
|
||||
'r', 0x00,
|
||||
#elif RAD1O
|
||||
12, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'r', 0x00,
|
||||
'a', 0x00,
|
||||
'd', 0x00,
|
||||
'1', 0x00,
|
||||
'o', 0x00,
|
||||
#else
|
||||
14, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'H', 0x00,
|
||||
'a', 0x00,
|
||||
'c', 0x00,
|
||||
'k', 0x00,
|
||||
'R', 0x00,
|
||||
'F', 0x00,
|
||||
#endif
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_config_description[] = {
|
||||
24, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'T', 0x00,
|
||||
'r', 0x00,
|
||||
'a', 0x00,
|
||||
'n', 0x00,
|
||||
's', 0x00,
|
||||
'c', 0x00,
|
||||
'e', 0x00,
|
||||
'i', 0x00,
|
||||
'v', 0x00,
|
||||
'e', 0x00,
|
||||
'r', 0x00,
|
||||
};
|
||||
|
||||
#ifdef DFU_MODE
|
||||
uint8_t usb_descriptor_string_serial_number[] = {
|
||||
30, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'R', 0x00,
|
||||
'u', 0x00,
|
||||
'n', 0x00,
|
||||
'n', 0x00,
|
||||
'i', 0x00,
|
||||
'n', 0x00,
|
||||
'g', 0x00,
|
||||
'F', 0x00,
|
||||
'r', 0x00,
|
||||
'o', 0x00,
|
||||
'm', 0x00,
|
||||
'R', 0x00,
|
||||
'A', 0x00,
|
||||
'M', 0x00,
|
||||
};
|
||||
#else
|
||||
uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN];
|
||||
#endif
|
||||
|
||||
uint8_t* usb_descriptor_strings[] = {
|
||||
usb_descriptor_string_languages,
|
||||
usb_descriptor_string_manufacturer,
|
||||
usb_descriptor_string_product,
|
||||
usb_descriptor_string_config_description,
|
||||
usb_descriptor_string_serial_number,
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
||||
uint8_t wcid_string_descriptor[] = {
|
||||
18, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'M', 0x00,
|
||||
'S', 0x00,
|
||||
'F', 0x00,
|
||||
'T', 0x00,
|
||||
'1', 0x00,
|
||||
'0', 0x00,
|
||||
'0', 0x00,
|
||||
USB_WCID_VENDOR_REQ, // vendor request code for further descriptor
|
||||
0x00
|
||||
};
|
||||
|
||||
uint8_t wcid_feature_descriptor[] = {
|
||||
0x28, 0x00, 0x00, 0x00, // bLength
|
||||
USB_WORD(0x0100), // WCID version
|
||||
USB_WORD(0x0004), // WICD descriptor index
|
||||
0x01, // bNumSections
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Reserved
|
||||
0x00, // bInterfaceNumber
|
||||
0x01, // Reserved
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0x00,0x00, // Compatible ID, padded with zeros
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Sub-compatible ID
|
||||
0x00,0x00,0x00,0x00,0x00,0x00 // Reserved
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2012 Jared Boone
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
extern uint8_t usb_descriptor_device[];
|
||||
extern uint8_t usb_descriptor_device_qualifier[];
|
||||
extern uint8_t usb_descriptor_configuration_full_speed[];
|
||||
extern uint8_t usb_descriptor_configuration_high_speed[];
|
||||
extern uint8_t usb_descriptor_string_languages[];
|
||||
extern uint8_t usb_descriptor_string_manufacturer[];
|
||||
extern uint8_t usb_descriptor_string_product[];
|
||||
|
||||
#define USB_DESCRIPTOR_STRING_SERIAL_LEN 32
|
||||
#define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN \
|
||||
(USB_DESCRIPTOR_STRING_SERIAL_LEN * 2 + 2) /* UTF-16LE */
|
||||
extern uint8_t usb_descriptor_string_serial_number[];
|
||||
|
||||
extern uint8_t* usb_descriptor_strings[];
|
||||
|
||||
#define USB_WCID_VENDOR_REQ 0x19
|
||||
extern uint8_t wcid_string_descriptor[];
|
||||
extern uint8_t wcid_feature_descriptor[];
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 "w25q80bv.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
namespace w25q80bv {
|
||||
|
||||
void disable_spifi(){
|
||||
RESET_CTRL1 = RESET_CTRL1_SPIFI_RST;
|
||||
}
|
||||
|
||||
void initialite_spi(){
|
||||
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
palOutputPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
const uint32_t clock_prescale_rate = 2;
|
||||
const uint32_t serial_clock_rate = 2;
|
||||
|
||||
SSP_CR1(SSP0_BASE) = 0;
|
||||
SSP_CPSR(SSP0_BASE) = clock_prescale_rate;
|
||||
SSP_CR0(SSP0_BASE) = (serial_clock_rate << 8) | SSP_DATA_8BITS;
|
||||
SSP_CR1(SSP0_BASE) = SSP_ENABLE;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
/* Init SPIFI GPIO to Normal GPIO */
|
||||
|
||||
MMIO32(PIN_GROUP3 + PIN3) = (SCU_SSP_IO | SCU_CONF_FUNCTION2);
|
||||
MMIO32(PIN_GROUP3 + PIN4) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
MMIO32(PIN_GROUP3 + PIN5) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
MMIO32(PIN_GROUP3 + PIN6) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
MMIO32(PIN_GROUP3 + PIN7) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
MMIO32(PIN_GROUP3 + PIN8) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
|
||||
/* configure SSP pins */
|
||||
MMIO32(SCU_SSP0_CIPO) = (SCU_SSP_IO | SCU_CONF_FUNCTION5);
|
||||
MMIO32(SCU_SSP0_COPI) = (SCU_SSP_IO | SCU_CONF_FUNCTION5);
|
||||
MMIO32(SCU_SSP0_SCK) = (SCU_SSP_IO | SCU_CONF_FUNCTION2);
|
||||
|
||||
/* configure GPIO pins */
|
||||
MMIO32(SCU_FLASH_HOLD) = SCU_GPIO_FAST;
|
||||
MMIO32(SCU_FLASH_WP) = SCU_GPIO_FAST;
|
||||
MMIO32(SCU_SSP0_CS) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
|
||||
//remove hardware write protection
|
||||
/* drive CS, HOLD, and WP pins high */
|
||||
palSetPad(W25Q80BV_HOLD_PORT, W25Q80BV_HOLD_PAD);
|
||||
palSetPad(W25Q80BV_WP_PORT, W25Q80BV_WP_PAD);
|
||||
|
||||
/* Set GPIO pins as outputs. */
|
||||
palOutputPad(W25Q80BV_HOLD_PORT, W25Q80BV_HOLD_PAD);
|
||||
palOutputPad(W25Q80BV_WP_PORT, W25Q80BV_WP_PAD);
|
||||
}
|
||||
|
||||
void wait_for_device() {
|
||||
uint8_t device_id;
|
||||
do {
|
||||
device_id = get_device_id();
|
||||
} while (device_id != W25Q80BV_DEVICE_ID_RES &&
|
||||
device_id != W25Q16DV_DEVICE_ID_RES);
|
||||
}
|
||||
|
||||
void wait_not_busy() {
|
||||
while (get_status() & W25Q80BV_STATUS_BUSY) {HALT_IF_DEBUGGING();}
|
||||
}
|
||||
|
||||
void remove_write_protection() {
|
||||
uint8_t data[] = {W25Q80BV_WRITE_ENABLE};
|
||||
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
for (size_t j = 0; j < 1; j++) {
|
||||
data[j] = spi_ssp_transfer_word(data[j]);
|
||||
}
|
||||
|
||||
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
while (!(get_status() & W25Q80BV_STATUS_WEL)) {HALT_IF_DEBUGGING();}
|
||||
}
|
||||
|
||||
uint32_t spi_ssp_transfer_word(const uint32_t data) {
|
||||
while ((SSP_SR(SSP0_BASE) & SSP_SR_TNF) == 0) {HALT_IF_DEBUGGING();}
|
||||
SSP_DR(SSP0_BASE) = data;
|
||||
while (SSP_SR(SSP0_BASE) & SSP_SR_BSY) {HALT_IF_DEBUGGING();}
|
||||
while ((SSP_SR(SSP0_BASE) & SSP_SR_RNE) == 0) {HALT_IF_DEBUGGING();}
|
||||
return SSP_DR(SSP0_BASE);
|
||||
}
|
||||
|
||||
uint8_t get_status() {
|
||||
uint8_t data[] = {W25Q80BV_READ_STATUS1, 0xFF};
|
||||
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
for (size_t j = 0; j < 2; j++) {
|
||||
data[j] = spi_ssp_transfer_word(data[j]);
|
||||
}
|
||||
|
||||
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
return data[1];
|
||||
}
|
||||
|
||||
uint8_t get_device_id() {
|
||||
uint8_t data[] = {W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
for (size_t j = 0; j < 5; j++) {
|
||||
data[j] = spi_ssp_transfer_word(data[j]);
|
||||
}
|
||||
|
||||
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
return data[4];
|
||||
}
|
||||
|
||||
void erase_chip() {
|
||||
uint8_t data[] = {W25Q80BV_CHIP_ERASE};
|
||||
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
|
||||
for (size_t j = 0; j < 1; j++) {
|
||||
data[j] = spi_ssp_transfer_word(data[j]);
|
||||
}
|
||||
|
||||
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
}
|
||||
|
||||
void write(size_t page_index, uint8_t *data_buffer, size_t length) {
|
||||
size_t page_len = 256U;
|
||||
size_t addr = page_index * page_len;
|
||||
uint8_t header[] = {
|
||||
W25Q80BV_PAGE_PROGRAM,
|
||||
(uint8_t)((addr & 0xFF0000) >> 16),
|
||||
(uint8_t)((addr & 0xFF00) >> 8),
|
||||
(uint8_t)(addr & 0xFF)
|
||||
};
|
||||
|
||||
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
header[j] = spi_ssp_transfer_word(header[j]);
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < length; j++) {
|
||||
data_buffer[j] = spi_ssp_transfer_word(data_buffer[j]);
|
||||
}
|
||||
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Bernd Herzog
|
||||
*
|
||||
* 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 __W25Q80BV_H__
|
||||
#define __W25Q80BV_H__
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#define RGU_BASE 0x40053000
|
||||
#define RESET_CTRL1 MMIO32(RGU_BASE + 0x104)
|
||||
#define RESET_CTRL1_SPIFI_RST_SHIFT (21)
|
||||
#define RESET_CTRL1_SPIFI_RST (1 << RESET_CTRL1_SPIFI_RST_SHIFT)
|
||||
|
||||
#define W25Q80BV_WRITE_ENABLE 0x06
|
||||
#define W25Q80BV_CHIP_ERASE 0xC7
|
||||
#define W25Q80BV_DEVICE_ID 0xAB
|
||||
#define W25Q80BV_PAGE_PROGRAM 0x02
|
||||
|
||||
#define PERIPH_BASE_APB0 0x40080000
|
||||
#define SCU_BASE (PERIPH_BASE_APB0 + 0x06000)
|
||||
#define MMIO32(addr) (*(volatile uint32_t *)(addr))
|
||||
|
||||
#define PIN_GROUP3 (SCU_BASE + 0x180)
|
||||
#define PIN3 0x00C
|
||||
#define PIN4 0x010
|
||||
#define PIN5 0x014
|
||||
#define PIN6 0x018
|
||||
#define PIN7 0x01C
|
||||
#define PIN8 0x020
|
||||
|
||||
#define BIT0 (1<<0)
|
||||
#define BIT1 (1<<1)
|
||||
#define BIT2 (1<<2)
|
||||
#define BIT3 (1<<3)
|
||||
#define BIT4 (1<<4)
|
||||
#define BIT5 (1<<5)
|
||||
#define BIT6 (1<<6)
|
||||
#define BIT7 (1<<7)
|
||||
#define BIT8 (1<<8)
|
||||
|
||||
#define SCU_CONF_EPUN_DIS_PULLUP (BIT4)
|
||||
#define SCU_CONF_EHS_FAST (BIT5)
|
||||
#define SCU_CONF_EZI_EN_IN_BUFFER (BIT6)
|
||||
#define SCU_CONF_ZIF_DIS_IN_GLITCH_FILT (BIT7)
|
||||
|
||||
#define SCU_GPIO_FAST (SCU_CONF_EPUN_DIS_PULLUP | \
|
||||
SCU_CONF_EHS_FAST | \
|
||||
SCU_CONF_EZI_EN_IN_BUFFER | \
|
||||
SCU_CONF_ZIF_DIS_IN_GLITCH_FILT)
|
||||
#define SCU_SSP_IO SCU_GPIO_FAST
|
||||
|
||||
#define SCU_CONF_FUNCTION0 (0x0)
|
||||
#define SCU_CONF_FUNCTION2 (0x2)
|
||||
#define SCU_CONF_FUNCTION4 (0x4)
|
||||
#define SCU_CONF_FUNCTION5 (0x5)
|
||||
|
||||
#define SCU_SSP0_CIPO (PIN_GROUP3 + PIN6)
|
||||
#define SCU_SSP0_COPI (PIN_GROUP3 + PIN7)
|
||||
#define SCU_SSP0_SCK (PIN_GROUP3 + PIN3)
|
||||
#define SCU_SSP0_CS (PIN_GROUP3 + PIN8)
|
||||
#define SCU_FLASH_HOLD (PIN_GROUP3 + PIN4)
|
||||
#define SCU_FLASH_WP (PIN_GROUP3 + PIN5)
|
||||
|
||||
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
|
||||
#define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */
|
||||
|
||||
#define SSP_CR1(port) MMIO32(port + 0x004)
|
||||
#define PERIPH_BASE_APB0 0x40080000
|
||||
#define SSP0_BASE (PERIPH_BASE_APB0 + 0x03000)
|
||||
#define SSP_CPSR(port) MMIO32(port + 0x010)
|
||||
#define SSP_CR0(port) MMIO32(port + 0x000)
|
||||
#define SSP_ENABLE BIT1
|
||||
#define SSP_DATA_8BITS 0x7
|
||||
|
||||
#define palSetPad(port, pad) (LPC_GPIO->SET[(port)] = 1 << (pad))
|
||||
#define palClearPad(port, pad) (LPC_GPIO->CLR[(port)] = 1 << (pad))
|
||||
#define palOutputPad(port, pad) (LPC_GPIO->DIR[(port)] |= 1 << (pad))
|
||||
#define palTogglePad(port, pad) (LPC_GPIO->NOT[(port)] |= 1 << (pad))
|
||||
|
||||
#define W25Q80BV_SELECT_PORT 5
|
||||
#define W25Q80BV_SELECT_PAD 11
|
||||
#define W25Q80BV_WP_PORT 1
|
||||
#define W25Q80BV_WP_PAD 15
|
||||
#define W25Q80BV_HOLD_PORT 1
|
||||
#define W25Q80BV_HOLD_PAD 14
|
||||
|
||||
#define LED_PORT 2
|
||||
#define LEDRX_PAD 2
|
||||
#define LEDTX_PAD 8
|
||||
|
||||
|
||||
#define W25Q80BV_STATUS_BUSY 0x01
|
||||
#define W25Q80BV_STATUS_WEL 0x02
|
||||
#define W25Q80BV_READ_STATUS1 0x05
|
||||
#define W25Q80BV_READ_STATUS2 0x35
|
||||
|
||||
#define PERIPH_BASE_APB0 0x40080000
|
||||
#define SSP0_BASE (PERIPH_BASE_APB0 + 0x03000)
|
||||
#define SSP_DR(port) MMIO32(port + 0x008)
|
||||
#define SSP_SR(port) MMIO32(port + 0x00C)
|
||||
|
||||
#define SSP_SR_TNF BIT1
|
||||
#define SSP_SR_RNE BIT2
|
||||
#define SSP_SR_BSY BIT4
|
||||
|
||||
namespace w25q80bv {
|
||||
void disable_spifi();
|
||||
uint8_t get_status();
|
||||
void wait_for_device();
|
||||
void wait_not_busy();
|
||||
uint32_t spi_ssp_transfer_word(const uint32_t data);
|
||||
void initialite_spi();
|
||||
void setup();
|
||||
void remove_write_protection();
|
||||
uint8_t get_device_id();
|
||||
void erase_chip();
|
||||
void write(size_t page_index, uint8_t *data_buffer, size_t length);
|
||||
}
|
||||
|
||||
#endif/*__W25Q80BV_H__*/
|
||||
@@ -25,8 +25,10 @@ MEMORY
|
||||
{
|
||||
flash (rx) : org = 0x00000000, len = 32752 /* Local SRAM @ 0x10080000 */
|
||||
ram (rwx) : org = 0x10000000, len = 96k /* Local SRAM @ 0x10000000 */
|
||||
ram_usb (rwx) : org = 0x20008000, len = 32K
|
||||
}
|
||||
|
||||
usb_bulk_buffer = ORIGIN(ram_usb);
|
||||
__ram_start__ = ORIGIN(ram);
|
||||
__ram_size__ = LENGTH(ram);
|
||||
__ram_end__ = __ram_start__ + __ram_size__;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,183 +36,193 @@ using namespace modems;
|
||||
using namespace serializer;
|
||||
|
||||
namespace portapack {
|
||||
namespace persistent_memory {
|
||||
|
||||
enum backlight_timeout_t {
|
||||
Timeout5Sec = 0,
|
||||
Timeout15Sec = 1,
|
||||
Timeout30Sec = 2,
|
||||
Timeout60Sec = 3,
|
||||
Timeout180Sec = 4,
|
||||
Timeout300Sec = 5,
|
||||
Timeout600Sec = 6,
|
||||
Timeout3600Sec = 7,
|
||||
};
|
||||
namespace persistent_memory {
|
||||
|
||||
struct backlight_config_t {
|
||||
public:
|
||||
backlight_config_t() :
|
||||
_timeout_enum(backlight_timeout_t::Timeout600Sec),
|
||||
_timeout_enabled(false)
|
||||
{
|
||||
}
|
||||
enum backlight_timeout_t {
|
||||
Timeout5Sec = 0,
|
||||
Timeout15Sec = 1,
|
||||
Timeout30Sec = 2,
|
||||
Timeout60Sec = 3,
|
||||
Timeout180Sec = 4,
|
||||
Timeout300Sec = 5,
|
||||
Timeout600Sec = 6,
|
||||
Timeout3600Sec = 7,
|
||||
};
|
||||
|
||||
backlight_config_t(
|
||||
backlight_timeout_t timeout_enum,
|
||||
bool timeout_enabled
|
||||
) :
|
||||
_timeout_enum(timeout_enum),
|
||||
_timeout_enabled(timeout_enabled)
|
||||
{
|
||||
}
|
||||
struct backlight_config_t {
|
||||
public:
|
||||
backlight_config_t() :
|
||||
_timeout_enum(backlight_timeout_t::Timeout600Sec),
|
||||
_timeout_enabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool timeout_enabled() const {
|
||||
return _timeout_enabled;
|
||||
}
|
||||
backlight_config_t(
|
||||
backlight_timeout_t timeout_enum,
|
||||
bool timeout_enabled
|
||||
) :
|
||||
_timeout_enum(timeout_enum),
|
||||
_timeout_enabled(timeout_enabled)
|
||||
{
|
||||
}
|
||||
|
||||
backlight_timeout_t timeout_enum() const {
|
||||
return _timeout_enum;
|
||||
}
|
||||
bool timeout_enabled() const {
|
||||
return _timeout_enabled;
|
||||
}
|
||||
|
||||
uint32_t timeout_seconds() const {
|
||||
switch(timeout_enum()) {
|
||||
case Timeout5Sec: return 5;
|
||||
case Timeout15Sec: return 15;
|
||||
case Timeout30Sec: return 30;
|
||||
case Timeout60Sec: return 60;
|
||||
case Timeout180Sec: return 180;
|
||||
case Timeout300Sec: return 300;
|
||||
default:
|
||||
case Timeout600Sec: return 600;
|
||||
case Timeout3600Sec: return 3600;
|
||||
}
|
||||
}
|
||||
backlight_timeout_t timeout_enum() const {
|
||||
return _timeout_enum;
|
||||
}
|
||||
|
||||
private:
|
||||
backlight_timeout_t _timeout_enum;
|
||||
bool _timeout_enabled;
|
||||
};
|
||||
uint32_t timeout_seconds() const {
|
||||
switch(timeout_enum()) {
|
||||
case Timeout5Sec: return 5;
|
||||
case Timeout15Sec: return 15;
|
||||
case Timeout30Sec: return 30;
|
||||
case Timeout60Sec: return 60;
|
||||
case Timeout180Sec: return 180;
|
||||
case Timeout300Sec: return 300;
|
||||
default:
|
||||
case Timeout600Sec: return 600;
|
||||
case Timeout3600Sec: return 3600;
|
||||
}
|
||||
}
|
||||
|
||||
namespace cache {
|
||||
private:
|
||||
backlight_timeout_t _timeout_enum;
|
||||
bool _timeout_enabled;
|
||||
};
|
||||
|
||||
/* Set values in cache to sensible defaults. */
|
||||
void defaults();
|
||||
namespace cache {
|
||||
|
||||
/* Load cached settings from values in persistent RAM, replacing with defaults
|
||||
* if persistent RAM contents appear to be invalid. */
|
||||
void init();
|
||||
/* Set values in cache to sensible defaults. */
|
||||
void defaults();
|
||||
|
||||
/* Calculate a check value for cached settings, and copy the check value and
|
||||
* settings into persistent RAM. Intended to be called periodically to update
|
||||
* persistent settings with current settings. */
|
||||
void persist();
|
||||
/* Load cached settings from values in persistent RAM, replacing with defaults
|
||||
* if persistent RAM contents appear to be invalid. */
|
||||
void init();
|
||||
|
||||
} /* namespace cache */
|
||||
/* Calculate a check value for cached settings, and copy the check value and
|
||||
* settings into persistent RAM. Intended to be called periodically to update
|
||||
* persistent settings with current settings. */
|
||||
void persist();
|
||||
|
||||
using ppb_t = int32_t;
|
||||
} /* namespace cache */
|
||||
|
||||
rf::Frequency tuned_frequency();
|
||||
void set_tuned_frequency(const rf::Frequency new_value);
|
||||
using ppb_t = int32_t;
|
||||
|
||||
ppb_t correction_ppb();
|
||||
void set_correction_ppb(const ppb_t new_value);
|
||||
rf::Frequency tuned_frequency();
|
||||
void set_tuned_frequency(const rf::Frequency new_value);
|
||||
|
||||
void set_touch_calibration(const touch::Calibration& new_value);
|
||||
const touch::Calibration& touch_calibration();
|
||||
ppb_t correction_ppb();
|
||||
void set_correction_ppb(const ppb_t new_value);
|
||||
|
||||
serial_format_t serial_format();
|
||||
void set_serial_format(const serial_format_t new_value);
|
||||
void set_touch_calibration(const touch::Calibration& new_value);
|
||||
const touch::Calibration& touch_calibration();
|
||||
|
||||
int32_t tone_mix();
|
||||
void set_tone_mix(const int32_t new_value);
|
||||
serial_format_t serial_format();
|
||||
void set_serial_format(const serial_format_t new_value);
|
||||
|
||||
int32_t afsk_mark_freq();
|
||||
void set_afsk_mark(const int32_t new_value);
|
||||
int32_t tone_mix();
|
||||
void set_tone_mix(const int32_t new_value);
|
||||
|
||||
int32_t afsk_space_freq();
|
||||
void set_afsk_space(const int32_t new_value);
|
||||
int32_t afsk_mark_freq();
|
||||
void set_afsk_mark(const int32_t new_value);
|
||||
|
||||
int32_t modem_baudrate();
|
||||
void set_modem_baudrate(const int32_t new_value);
|
||||
int32_t afsk_space_freq();
|
||||
void set_afsk_space(const int32_t new_value);
|
||||
|
||||
uint8_t modem_repeat();
|
||||
void set_modem_repeat(const uint32_t new_value);
|
||||
int32_t modem_baudrate();
|
||||
void set_modem_baudrate(const int32_t new_value);
|
||||
|
||||
uint32_t playing_dead();
|
||||
void set_playing_dead(const uint32_t new_value);
|
||||
uint8_t modem_repeat();
|
||||
void set_modem_repeat(const uint32_t new_value);
|
||||
|
||||
uint32_t playdead_sequence();
|
||||
void set_playdead_sequence(const uint32_t new_value);
|
||||
uint32_t playing_dead();
|
||||
void set_playing_dead(const uint32_t new_value);
|
||||
|
||||
bool stealth_mode();
|
||||
void set_stealth_mode(const bool v);
|
||||
uint32_t playdead_sequence();
|
||||
void set_playdead_sequence(const uint32_t new_value);
|
||||
|
||||
uint8_t config_cpld();
|
||||
void set_config_cpld(uint8_t i);
|
||||
bool stealth_mode();
|
||||
void set_stealth_mode(const bool v);
|
||||
|
||||
bool config_splash();
|
||||
bool config_hamitup();
|
||||
int64_t config_hamitup_freq();
|
||||
bool show_gui_return_icon();
|
||||
bool load_app_settings();
|
||||
bool save_app_settings();
|
||||
bool show_bigger_qr_code();
|
||||
bool hide_clock();
|
||||
bool clock_with_date();
|
||||
bool config_login();
|
||||
bool config_speaker();
|
||||
backlight_config_t config_backlight_timer();
|
||||
bool disable_touchscreen();
|
||||
uint8_t config_cpld();
|
||||
void set_config_cpld(uint8_t i);
|
||||
|
||||
void set_gui_return_icon(bool v);
|
||||
void set_load_app_settings(bool v);
|
||||
void set_save_app_settings(bool v);
|
||||
void set_show_bigger_qr_code(bool v);
|
||||
void set_config_splash(bool v);
|
||||
void set_config_hamitup(bool v);
|
||||
void set_config_hamitup_freq(const int64_t v );
|
||||
void set_clock_hidden(bool v);
|
||||
void set_clock_with_date(bool v);
|
||||
void set_config_login(bool v);
|
||||
void set_config_speaker(bool v);
|
||||
void set_config_backlight_timer(const backlight_config_t& new_value);
|
||||
void set_disable_touchscreen(bool v);
|
||||
bool config_splash();
|
||||
bool config_hide_converter();
|
||||
bool config_converter();
|
||||
bool config_updown_converter();
|
||||
int64_t config_converter_freq();
|
||||
bool show_gui_return_icon();
|
||||
bool load_app_settings();
|
||||
bool save_app_settings();
|
||||
bool show_bigger_qr_code();
|
||||
bool hide_clock();
|
||||
bool clock_with_date();
|
||||
bool config_login();
|
||||
bool config_speaker();
|
||||
backlight_config_t config_backlight_timer();
|
||||
bool disable_touchscreen();
|
||||
|
||||
//uint8_t ui_config_textentry();
|
||||
//void set_config_textentry(uint8_t new_value);
|
||||
void set_gui_return_icon(bool v);
|
||||
void set_load_app_settings(bool v);
|
||||
void set_save_app_settings(bool v);
|
||||
void set_show_bigger_qr_code(bool v);
|
||||
void set_config_splash(bool v);
|
||||
void set_config_hide_converter(bool v);
|
||||
void set_config_converter(bool v);
|
||||
void set_config_updown_converter(const bool v);
|
||||
void set_config_converter_freq(const int64_t v );
|
||||
void set_clock_hidden(bool v);
|
||||
void set_clock_with_date(bool v);
|
||||
void set_config_login(bool v);
|
||||
void set_config_speaker(bool v);
|
||||
void set_config_backlight_timer(const backlight_config_t& new_value);
|
||||
void set_disable_touchscreen(bool v);
|
||||
|
||||
uint32_t pocsag_last_address();
|
||||
void set_pocsag_last_address(uint32_t address);
|
||||
//uint8_t ui_config_textentry();
|
||||
//void set_config_textentry(uint8_t new_value);
|
||||
|
||||
uint32_t pocsag_ignore_address();
|
||||
void set_pocsag_ignore_address(uint32_t address);
|
||||
uint32_t pocsag_last_address();
|
||||
void set_pocsag_last_address(uint32_t address);
|
||||
|
||||
bool clkout_enabled();
|
||||
void set_clkout_enabled(bool v);
|
||||
uint32_t clkout_freq();
|
||||
void set_clkout_freq(uint32_t freq);
|
||||
uint32_t pocsag_ignore_address();
|
||||
void set_pocsag_ignore_address(uint32_t address);
|
||||
|
||||
/* Recon app */
|
||||
bool recon_autosave_freqs();
|
||||
bool recon_autostart_recon();
|
||||
bool recon_continuous();
|
||||
bool recon_clear_output();
|
||||
bool recon_load_freqs();
|
||||
bool recon_load_ranges();
|
||||
bool recon_update_ranges_when_recon();
|
||||
bool recon_load_hamradios();
|
||||
bool recon_match_mode();
|
||||
void set_recon_autosave_freqs(const bool v);
|
||||
void set_recon_autostart_recon(const bool v);
|
||||
void set_recon_continuous(const bool v);
|
||||
void set_recon_clear_output(const bool v);
|
||||
void set_recon_load_freqs(const bool v);
|
||||
void set_recon_load_ranges(const bool v);
|
||||
void set_recon_update_ranges_when_recon(const bool v);
|
||||
void set_recon_load_hamradios(const bool v );
|
||||
void set_recon_match_mode( const bool v );
|
||||
bool clkout_enabled();
|
||||
void set_clkout_enabled(bool v);
|
||||
uint32_t clkout_freq();
|
||||
void set_clkout_freq(uint32_t freq);
|
||||
|
||||
/* Recon app */
|
||||
bool recon_autosave_freqs();
|
||||
bool recon_autostart_recon();
|
||||
bool recon_continuous();
|
||||
bool recon_clear_output();
|
||||
bool recon_load_freqs();
|
||||
bool recon_load_ranges();
|
||||
bool recon_update_ranges_when_recon();
|
||||
bool recon_load_hamradios();
|
||||
bool recon_match_mode();
|
||||
void set_recon_autosave_freqs(const bool v);
|
||||
void set_recon_autostart_recon(const bool v);
|
||||
void set_recon_continuous(const bool v);
|
||||
void set_recon_clear_output(const bool v);
|
||||
void set_recon_load_freqs(const bool v);
|
||||
void set_recon_load_ranges(const bool v);
|
||||
void set_recon_update_ranges_when_recon(const bool v);
|
||||
void set_recon_load_hamradios(const bool v );
|
||||
void set_recon_match_mode( const bool v );
|
||||
|
||||
// sd persisting settings
|
||||
int save_persistent_settings_to_file( std::string filename );
|
||||
int load_persistent_settings_from_file( std::string filename );
|
||||
|
||||
} /* namespace persistent_memory */
|
||||
|
||||
} /* namespace persistent_memory */
|
||||
} /* namespace portapack */
|
||||
|
||||
#endif/*__PORTAPACK_PERSISTENT_MEMORY_H__*/
|
||||
|
||||
@@ -106,6 +106,8 @@ constexpr image_tag_t image_tag_gps { 'P', 'G', 'P', 'S' };
|
||||
constexpr image_tag_t image_tag_siggen { 'P', 'S', 'I', 'G' };
|
||||
constexpr image_tag_t image_tag_sstv_tx { 'P', 'S', 'T', 'X' };
|
||||
constexpr image_tag_t image_tag_tones { 'P', 'T', 'O', 'N' };
|
||||
constexpr image_tag_t image_tag_flash_utility { 'P', 'F', 'U', 'T' };
|
||||
constexpr image_tag_t image_tag_usb_sd { 'P', 'U', 'S', 'B' };
|
||||
|
||||
constexpr image_tag_t image_tag_noop { 'P', 'N', 'O', 'P' };
|
||||
|
||||
@@ -114,6 +116,7 @@ constexpr image_tag_t image_tag_hackrf { 'H', 'R', 'F', '1' };
|
||||
struct chunk_t {
|
||||
const image_tag_t tag;
|
||||
const uint32_t length;
|
||||
const uint32_t compressed_data_size;
|
||||
const uint8_t data[];
|
||||
|
||||
const chunk_t* next() const {
|
||||
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 307 B |
Binary file not shown.
|
Before Width: | Height: | Size: 189 B |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 251 B |
@@ -27,7 +27,7 @@ import struct
|
||||
usage_message = """
|
||||
PortaPack image chunk writer
|
||||
|
||||
Usage: <command> <input_binary> <four-characer tag> <output_tagged_binary> [<chunk max size>]
|
||||
Usage: <command> <input_binary> <four-characer tag> <output_tagged_binary>
|
||||
"""
|
||||
|
||||
def read_image(path):
|
||||
@@ -41,17 +41,33 @@ def write_image(data, path):
|
||||
f.write(data)
|
||||
f.close()
|
||||
|
||||
input_image_max_length = 32768
|
||||
if len(sys.argv) in (4, 5):
|
||||
if len(sys.argv) == 4:
|
||||
input_image = read_image(sys.argv[1])
|
||||
input_image = bytearray(input_image)
|
||||
tag = tuple(map(ord, sys.argv[2]))
|
||||
output_path = sys.argv[3]
|
||||
if len(sys.argv) == 5:
|
||||
input_image_max_length = int(sys.argv[4])
|
||||
|
||||
if input_image[4] & 8 == 8:
|
||||
input_image = input_image[15:]
|
||||
else:
|
||||
input_image = input_image[7:]
|
||||
|
||||
if (len(input_image) & 3) != 0:
|
||||
for i in range(4 - (len(input_image) & 3)):
|
||||
input_image.append(0)
|
||||
|
||||
output_image = bytearray()
|
||||
output_image += struct.pack('<4BI', tag[0], tag[1], tag[2], tag[3], len(input_image) - 4)
|
||||
output_image += input_image
|
||||
write_image(output_image, output_path)
|
||||
|
||||
elif len(sys.argv) == 2:
|
||||
input_image = bytearray()
|
||||
null_image = bytearray()
|
||||
tag = (0, 0, 0, 0)
|
||||
output_path = sys.argv[1]
|
||||
null_image += struct.pack('<4BI', tag[0], tag[1], tag[2], tag[3], 0)
|
||||
write_image(null_image, output_path)
|
||||
|
||||
else:
|
||||
print(usage_message)
|
||||
sys.exit(-1)
|
||||
@@ -59,14 +75,3 @@ else:
|
||||
if len(tag) != 4:
|
||||
print(usage_message)
|
||||
sys.exit(-2)
|
||||
|
||||
if len(input_image) > input_image_max_length:
|
||||
raise RuntimeError('image size of %d exceeds device size of %d bytes' % (len(input_image), input_image_max_length))
|
||||
if (len(input_image) & 3) != 0:
|
||||
raise RuntimeError('image size of %d is not multiple of four' % (len(input_image,)))
|
||||
|
||||
output_image = bytearray()
|
||||
output_image += struct.pack('<4BI', tag[0], tag[1], tag[2], tag[3], len(input_image))
|
||||
output_image += input_image
|
||||
|
||||
write_image(output_image, output_path)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user