mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-15 11:02:58 +00:00
Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c4e27ea29 | |||
| 54e4230191 | |||
| f069383c2a | |||
| d3a356d415 | |||
| f0e4fdcbcc | |||
| d5f6f42fae | |||
| 7a89858cc6 | |||
| 15c9a76536 | |||
| d7359a8cd5 | |||
| 50e5bc60ee | |||
| 9385be4f1e | |||
| 9cddab9a5e | |||
| 6e01a1d0dc | |||
| f73cd39d2d | |||
| 0303c658ea | |||
| 94ddb63b1d | |||
| b1aa607a7c | |||
| 509f86c1f7 | |||
| b45ca43e27 | |||
| 47482d1e58 | |||
| 59dfe5b50b | |||
| b1f5023fe1 | |||
| a54b94fe53 | |||
| 45bdabcef9 | |||
| 6cdada1118 | |||
| cffc72c516 | |||
| e53514aa12 | |||
| 775de5ce6f | |||
| 4ff92be23b | |||
| 948d8d947e | |||
| 55c300ac4b | |||
| 29b7a5ee56 | |||
| 2ef9ebd7bd | |||
| 850a79c9bb | |||
| 812f0f8211 | |||
| d00c21adb7 | |||
| 925c1548a8 | |||
| cd1f1bd388 | |||
| 474fe00146 | |||
| 44b2e5ea61 | |||
| 48ed7b1b1a | |||
| 6201be82ea | |||
| fe1d296b48 | |||
| 697876d86a | |||
| b72c765911 | |||
| 2a14888b80 | |||
| 99f1bded4d | |||
| d8e9fad205 | |||
| 0e8dc1567c | |||
| 4ff71dcfca | |||
| ed0f0eb15e | |||
| 193a80edea | |||
| df0c85db8f | |||
| c5738c46d5 | |||
| 0acf7ec2c2 | |||
| dc560ba01f | |||
| d74fd92451 | |||
| bcefa774cd | |||
| 8382eaf45f | |||
| 9f700a30c0 | |||
| d815e6c952 | |||
| e60ec953ab | |||
| 72d1e21fc6 | |||
| e4d42817ee | |||
| 5729bde214 | |||
| ec7a77896a | |||
| 99c26c3b7b | |||
| aa20bff2b9 | |||
| f5e949047d | |||
| afb75af5b1 | |||
| 7f99b1181e | |||
| cec0fe3288 | |||
| ba3114c0b6 | |||
| cc2bb772e5 | |||
| fbf9138410 | |||
| 0559aa2037 | |||
| 0d7072ec5d | |||
| c1f55c0dec | |||
| 464b7dd98d | |||
| 4d429437b5 | |||
| bc39292e72 | |||
| 27f70cb9fe | |||
| e5f80adeb7 | |||
| 5a6f6e8db0 | |||
| 21547e6c55 | |||
| 12cfbf70f0 | |||
| c3971cae32 | |||
| f7c2dde79f | |||
| cd2d810c31 | |||
| ba6202e651 | |||
| 40d64030c8 | |||
| 049a20b878 | |||
| 0e5ae7a6a4 | |||
| c867f98117 | |||
| 54eebedc1f | |||
| 35db368527 | |||
| be691fd278 | |||
| 3db3e78b44 | |||
| a48ecccd7d | |||
| 570775552c | |||
| 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 | |||
| 9115eadd17 | |||
| 7b4662fe4a | |||
| 8fcedb017c | |||
| 7b3ab64930 | |||
| b856b047cc |
+1
-1
@@ -45,7 +45,7 @@ endif()
|
||||
set(LICENSE_PATH ${CMAKE_CURRENT_LIST_DIR}/LICENSE)
|
||||
set(HARDWARE_PATH ${CMAKE_CURRENT_LIST_DIR}/hardware)
|
||||
|
||||
add_subdirectory(hackrf/firmware/hackrf_usb)
|
||||
add_subdirectory(hackrf-portapack)
|
||||
|
||||
set(HACKRF_FIRMWARE_DFU_FILENAME hackrf_usb.dfu)
|
||||
set(HACKRF_FIRMWARE_BIN_FILENAME hackrf_usb_ram.bin)
|
||||
|
||||
@@ -39,7 +39,7 @@ The current **stable release** is on the [, fix bugs and [answer issues](https://github.com/eried/portapack-mayhem/issues) or add new functionality. Please check the following [guide](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate) with details.
|
||||
|
||||
Consider that the hardware and firmware has been created and maintain by a [lot](https://github.com/mossmann/hackrf/graphs/contributors) of [people](https://github.com/eried/portapack-mayhem/graphs/contributors), so always try colaborating your time and effort first. For coding related questions, if something does not fit as an issue, please join our Discord by clicking the chat badge on [top](#portapack-mayhem).
|
||||
Consider that the hardware and firmware has been created and maintain by a [lot](https://github.com/mossmann/hackrf/graphs/contributors) of [people](https://github.com/eried/portapack-mayhem/graphs/contributors), so always try collaborating your time and effort first. For coding related questions, if something does not fit as an issue, please join our Discord by clicking the chat badge on [top](#portapack-mayhem).
|
||||
|
||||
[](https://github.com/eried/portapack-mayhem/graphs/contributors)
|
||||
|
||||
|
||||
+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)
|
||||
|
||||
@@ -155,6 +155,7 @@ set(CPPSRC
|
||||
${COMMON}/ui_widget.cpp
|
||||
${COMMON}/utility.cpp
|
||||
${COMMON}/wm8731.cpp
|
||||
${COMMON}/performance_counter.cpp
|
||||
app_settings.cpp
|
||||
audio.cpp
|
||||
baseband_api.cpp
|
||||
@@ -230,10 +231,13 @@ set(CPPSRC
|
||||
apps/ui_nrf_rx.cpp
|
||||
apps/ui_aprs_tx.cpp
|
||||
apps/ui_bht_tx.cpp
|
||||
apps/ui_dfu_menu.cpp
|
||||
apps/ui_coasterp.cpp
|
||||
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 +321,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}
|
||||
|
||||
@@ -117,6 +117,7 @@ private:
|
||||
{ " 2m ", 2000000 },
|
||||
{ " 1m ", 1000000 },
|
||||
{ "500k", 500000 },
|
||||
{ "100k", 100000 },
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ std::string type(Packet::Type value) {
|
||||
case Packet::Type::Unknown: return "???";
|
||||
case Packet::Type::IDM: return "IDM";
|
||||
case Packet::Type::SCM: return "SCM";
|
||||
case Packet::Type::SCMPLUS: return "SCM+";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +63,8 @@ std::string commodity_type(CommodityType value) {
|
||||
|
||||
void ERTLogger::on_packet(const ert::Packet& packet) {
|
||||
const auto formatted = packet.symbols_formatted();
|
||||
log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors);
|
||||
std::string entry = ert::format::type(packet.type()) + " " + formatted.data + "/" + formatted.errors;
|
||||
log_file.write_entry(packet.received_at(), entry);
|
||||
}
|
||||
|
||||
const ERTRecentEntry::Key ERTRecentEntry::invalid_key { };
|
||||
|
||||
@@ -161,10 +161,16 @@ void ReplayAppView::start() {
|
||||
sample_rate * 8,
|
||||
baseband_bandwidth,
|
||||
rf::Direction::Transmit,
|
||||
rf_amp, // previous code line : "receiver_model.rf_amp()," was passing the same rf_amp of all Receiver Apps
|
||||
rf_amp, // previous code line : "receiver_model.rf_amp()," was passing the same rf_amp of all Receiver Apps
|
||||
static_cast<int8_t>(receiver_model.lna()),
|
||||
static_cast<int8_t>(receiver_model.vga())
|
||||
});
|
||||
|
||||
if (portapack::persistent_memory::stealth_mode()){
|
||||
DisplaySleepMessage message;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ReplayAppView::stop(const bool do_loop) {
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace tpms {
|
||||
namespace format {
|
||||
|
||||
static bool use_kpa = true;
|
||||
static bool use_celsius = true;
|
||||
|
||||
std::string type(Reading::Type type) {
|
||||
return to_string_dec_uint(toUType(type), 2);
|
||||
@@ -45,15 +46,11 @@ std::string id(TransponderID id) {
|
||||
}
|
||||
|
||||
std::string pressure(Pressure pressure) {
|
||||
if(use_kpa){
|
||||
return to_string_dec_int(pressure.kilopascal(), 3);
|
||||
}
|
||||
return to_string_dec_int(pressure.psi(), 3);
|
||||
|
||||
return to_string_dec_int(use_kpa? pressure.kilopascal():pressure.psi(), 3);
|
||||
}
|
||||
|
||||
std::string temperature(Temperature temperature) {
|
||||
return to_string_dec_int(temperature.celsius(), 3);
|
||||
return to_string_dec_int(use_celsius? temperature.celsius():temperature.fahrenheit(), 3);
|
||||
}
|
||||
|
||||
std::string flags(Flags flags) {
|
||||
@@ -111,15 +108,15 @@ void RecentEntriesTable<TPMSRecentEntries>::draw(
|
||||
std::string line = tpms::format::type(entry.type) + " " + tpms::format::id(entry.id);
|
||||
|
||||
if( entry.last_pressure.is_valid() ) {
|
||||
line += " " + tpms::format::pressure(entry.last_pressure.value());
|
||||
line += " " + tpms::format::pressure(entry.last_pressure.value());
|
||||
} else {
|
||||
line += " " " ";
|
||||
line += " " " ";
|
||||
}
|
||||
|
||||
if( entry.last_temperature.is_valid() ) {
|
||||
line += " " + tpms::format::temperature(entry.last_temperature.value());
|
||||
line += " " + tpms::format::temperature(entry.last_temperature.value());
|
||||
} else {
|
||||
line += " " " ";
|
||||
line += " " " ";
|
||||
}
|
||||
|
||||
if( entry.received_count > 999 ) {
|
||||
@@ -145,10 +142,12 @@ TPMSAppView::TPMSAppView(NavigationView&) {
|
||||
&rssi,
|
||||
&channel,
|
||||
&options_band,
|
||||
&options_pressure,
|
||||
&options_temperature,
|
||||
&field_rf_amp,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
&options_type,
|
||||
&recent_entries_view
|
||||
});
|
||||
|
||||
// load app settings
|
||||
@@ -181,16 +180,19 @@ TPMSAppView::TPMSAppView(NavigationView&) {
|
||||
};
|
||||
options_band.set_by_value(target_frequency());
|
||||
|
||||
options_type.on_change = [this](size_t, int32_t i) {
|
||||
if (i == 0){
|
||||
tpms::format::use_kpa = true;
|
||||
} else if (i == 1){
|
||||
tpms::format::use_kpa = false;
|
||||
}
|
||||
update_type();
|
||||
options_pressure.on_change = [this](size_t, int32_t i) {
|
||||
tpms::format::use_kpa = !i;
|
||||
update_view();
|
||||
};
|
||||
|
||||
options_type.set_selected_index(0, true);
|
||||
options_pressure.set_selected_index(0, true);
|
||||
|
||||
options_temperature.on_change = [this](size_t, int32_t i) {
|
||||
tpms::format::use_celsius = !i;
|
||||
update_view();
|
||||
};
|
||||
|
||||
options_temperature.set_selected_index(0, true);
|
||||
|
||||
logger = std::make_unique<TPMSLogger>();
|
||||
if( logger ) {
|
||||
@@ -214,16 +216,8 @@ void TPMSAppView::focus() {
|
||||
options_band.focus();
|
||||
}
|
||||
|
||||
void TPMSAppView::update_type() {
|
||||
if (tpms::format::use_kpa){
|
||||
remove_child(&recent_entries_view_psi);
|
||||
add_child(&recent_entries_view_kpa);
|
||||
recent_entries_view_kpa.set_parent_rect(view_normal_rect);
|
||||
} else {
|
||||
remove_child(&recent_entries_view_kpa);
|
||||
add_child(&recent_entries_view_psi);
|
||||
recent_entries_view_psi.set_parent_rect(view_normal_rect);
|
||||
}
|
||||
void TPMSAppView::update_view() {
|
||||
recent_entries_view.set_parent_rect(view_normal_rect);
|
||||
}
|
||||
|
||||
void TPMSAppView::set_parent_rect(const Rect new_parent_rect) {
|
||||
@@ -231,7 +225,7 @@ void TPMSAppView::set_parent_rect(const Rect new_parent_rect) {
|
||||
|
||||
view_normal_rect = { 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height };
|
||||
|
||||
update_type();
|
||||
update_view();
|
||||
}
|
||||
|
||||
void TPMSAppView::on_packet(const tpms::Packet& packet) {
|
||||
@@ -244,23 +238,13 @@ void TPMSAppView::on_packet(const tpms::Packet& packet) {
|
||||
const auto reading = reading_opt.value();
|
||||
auto& entry = ::on_packet(recent, TPMSRecentEntry::Key { reading.type(), reading.id() });
|
||||
entry.update(reading);
|
||||
|
||||
if(tpms::format::use_kpa){
|
||||
recent_entries_view_kpa.set_dirty();
|
||||
} else {
|
||||
recent_entries_view_psi.set_dirty();
|
||||
}
|
||||
recent_entries_view.set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
void TPMSAppView::on_show_list() {
|
||||
if(tpms::format::use_kpa){
|
||||
recent_entries_view_kpa.hidden(false);
|
||||
recent_entries_view_kpa.focus();
|
||||
} else {
|
||||
recent_entries_view_psi.hidden(false);
|
||||
recent_entries_view_psi.focus();
|
||||
}
|
||||
recent_entries_view.hidden(false);
|
||||
recent_entries_view.focus();
|
||||
}
|
||||
|
||||
void TPMSAppView::on_band_changed(const uint32_t new_band_frequency) {
|
||||
|
||||
@@ -144,7 +144,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
OptionsField options_type {
|
||||
OptionsField options_pressure {
|
||||
{ 5 * 8, 0 * 16 },
|
||||
3,
|
||||
{
|
||||
@@ -153,6 +153,15 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
OptionsField options_temperature {
|
||||
{ 9 * 8, 0 * 16 },
|
||||
1,
|
||||
{
|
||||
{ "C", 0 },
|
||||
{ "F", 1 }
|
||||
}
|
||||
};
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 13 * 8, 0 * 16 }
|
||||
};
|
||||
@@ -168,31 +177,21 @@ private:
|
||||
TPMSRecentEntries recent { };
|
||||
std::unique_ptr<TPMSLogger> logger { };
|
||||
|
||||
const RecentEntriesColumns columns_kpa { {
|
||||
const RecentEntriesColumns columns { {
|
||||
{ "Tp", 2 },
|
||||
{ "ID", 8 },
|
||||
{ "kPa", 3 },
|
||||
{ "C", 3 },
|
||||
{ "Pres", 4 },
|
||||
{ "Temp", 4 },
|
||||
{ "Cnt", 3 },
|
||||
{ "Fl", 2 },
|
||||
} };
|
||||
TPMSRecentEntriesView recent_entries_view_kpa { columns_kpa, recent };
|
||||
|
||||
const RecentEntriesColumns columns_psi { {
|
||||
{ "Tp", 2 },
|
||||
{ "ID", 8 },
|
||||
{ "PSI", 3 },
|
||||
{ "C", 3 },
|
||||
{ "Cnt", 3 },
|
||||
{ "Fl", 2 },
|
||||
} };
|
||||
TPMSRecentEntriesView recent_entries_view_psi { columns_psi, recent };
|
||||
TPMSRecentEntriesView recent_entries_view { columns, recent };
|
||||
|
||||
uint32_t target_frequency_ = initial_target_frequency;
|
||||
|
||||
void on_packet(const tpms::Packet& packet);
|
||||
void on_show_list();
|
||||
void update_type();
|
||||
void update_view();
|
||||
|
||||
void on_band_changed(const uint32_t new_band_frequency);
|
||||
|
||||
|
||||
@@ -266,7 +266,9 @@ bool ControlsSwitchesWidget::on_key(const KeyEvent key) {
|
||||
}
|
||||
|
||||
void ControlsSwitchesWidget::paint(Painter& painter) {
|
||||
const std::array<Rect, 7> button_rects { {
|
||||
const auto pos = screen_pos();
|
||||
|
||||
const std::array<Rect, 8> button_rects { {
|
||||
{ 64, 32, 16, 16 }, // Right
|
||||
{ 0, 32, 16, 16 }, // Left
|
||||
{ 32, 64, 16, 16 }, // Down
|
||||
@@ -274,27 +276,63 @@ void ControlsSwitchesWidget::paint(Painter& painter) {
|
||||
{ 32, 32, 16, 16 }, // Select
|
||||
{ 16, 96, 16, 16 }, // Encoder phase 0
|
||||
{ 48, 96, 16, 16 }, // Encoder phase 1
|
||||
{ 96, 0, 16, 16 }, // Dfu
|
||||
} };
|
||||
const auto pos = screen_pos();
|
||||
auto switches_raw = control::debug::switches();
|
||||
auto switches_debounced = get_switches_state().to_ulong();
|
||||
auto switches_event = key_event_mask;
|
||||
|
||||
for(const auto r : button_rects) {
|
||||
const auto c =
|
||||
((switches_event & 1) ?
|
||||
Color::red() :
|
||||
((switches_debounced & 1) ?
|
||||
Color::green() :
|
||||
((switches_raw & 1) ?
|
||||
Color::yellow() :
|
||||
Color::blue()
|
||||
)
|
||||
)
|
||||
);
|
||||
painter.fill_rectangle(r + pos, c);
|
||||
painter.fill_rectangle(r + pos, Color::blue());
|
||||
}
|
||||
|
||||
const std::array<Rect, 8> raw_rects { {
|
||||
{ 64 + 1, 32 + 1, 16 - 2, 16 - 2 }, // Right
|
||||
{ 0 + 1, 32 + 1, 16 - 2, 16 - 2 }, // Left
|
||||
{ 32 + 1, 64 + 1, 16 - 2, 16 - 2 }, // Down
|
||||
{ 32 + 1, 0 + 1, 16 - 2, 16 - 2 }, // Up
|
||||
{ 32 + 1, 32 + 1, 16 - 2, 16 - 2 }, // Select
|
||||
{ 16 + 1, 96 + 1, 16 - 2, 16 - 2 }, // Encoder phase 0
|
||||
{ 48 + 1, 96 + 1, 16 - 2, 16 - 2 }, // Encoder phase 1
|
||||
{ 96 + 1, 0 + 1, 16 - 2, 16 - 2 }, // Dfu
|
||||
} };
|
||||
|
||||
auto switches_raw = control::debug::switches();
|
||||
for(const auto r : raw_rects) {
|
||||
if (switches_raw & 1)
|
||||
painter.fill_rectangle(r + pos, Color::yellow());
|
||||
|
||||
switches_raw >>= 1;
|
||||
}
|
||||
|
||||
const std::array<Rect, 6> debounced_rects { {
|
||||
{ 64 + 2, 32 + 2, 16 - 4, 16 - 4 }, // Right
|
||||
{ 0 + 2, 32 + 2, 16 - 4, 16 - 4 }, // Left
|
||||
{ 32 + 2, 64 + 2, 16 - 4, 16 - 4 }, // Down
|
||||
{ 32 + 2, 0 + 2, 16 - 4, 16 - 4 }, // Up
|
||||
{ 32 + 2, 32 + 2, 16 - 4, 16 - 4 }, // Select
|
||||
{ 96 + 2, 0 + 2, 16 - 4, 16 - 4 }, // Dfu
|
||||
} };
|
||||
|
||||
auto switches_debounced = get_switches_state().to_ulong();
|
||||
for(const auto r : debounced_rects) {
|
||||
if (switches_debounced & 1)
|
||||
painter.fill_rectangle(r + pos, Color::green());
|
||||
|
||||
switches_debounced >>= 1;
|
||||
}
|
||||
|
||||
const std::array<Rect, 6> events_rects { {
|
||||
{ 64 + 3, 32 + 3, 16 - 6, 16 - 6 }, // Right
|
||||
{ 0 + 3, 32 + 3, 16 - 6, 16 - 6 }, // Left
|
||||
{ 32 + 3, 64 + 3, 16 - 6, 16 - 6 }, // Down
|
||||
{ 32 + 3, 0 + 3, 16 - 6, 16 - 6 }, // Up
|
||||
{ 32 + 3, 32 + 3, 16 - 6, 16 - 6 }, // Select
|
||||
{ 96 + 3, 0 + 3, 16 - 6, 16 - 6 }, // Dfu
|
||||
} };
|
||||
|
||||
auto switches_event = key_event_mask;
|
||||
for(const auto r : events_rects) {
|
||||
if (switches_event & 1)
|
||||
painter.fill_rectangle(r + pos, Color::red());
|
||||
|
||||
switches_event >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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_dfu_menu.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "performance_counter.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
DfuMenu::DfuMenu(NavigationView& nav) : nav_ (nav) {
|
||||
add_children({
|
||||
&text_head,
|
||||
&labels,
|
||||
&text_info_line_1,
|
||||
&text_info_line_2,
|
||||
&text_info_line_3,
|
||||
&text_info_line_4,
|
||||
&text_info_line_5,
|
||||
&text_info_line_6,
|
||||
&text_info_line_7,
|
||||
&text_info_line_8
|
||||
});
|
||||
}
|
||||
|
||||
void DfuMenu::paint(Painter& painter) {
|
||||
auto utilisation = get_cpu_utilisation_in_percent();
|
||||
|
||||
text_info_line_1.set(to_string_dec_uint(chCoreStatus(), 6));
|
||||
text_info_line_2.set(to_string_dec_uint((uint32_t)get_free_stack_space(), 6));
|
||||
text_info_line_3.set(to_string_dec_uint(utilisation, 6));
|
||||
text_info_line_4.set(to_string_dec_uint(shared_memory.m4_heap_usage, 6));
|
||||
text_info_line_5.set(to_string_dec_uint(shared_memory.m4_stack_usage, 6));
|
||||
text_info_line_6.set(to_string_dec_uint(shared_memory.m4_cpu_usage, 6));
|
||||
text_info_line_7.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
|
||||
text_info_line_8.set(to_string_dec_uint(chTimeNow()/1000, 6));
|
||||
|
||||
constexpr auto margin = 5;
|
||||
constexpr auto lines = 8 + 2;
|
||||
|
||||
painter.fill_rectangle(
|
||||
{
|
||||
{6 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
||||
{15 * CHARACTER_WIDTH + margin * 2, lines * LINE_HEIGHT + margin * 2}
|
||||
},
|
||||
ui::Color::black()
|
||||
);
|
||||
|
||||
painter.fill_rectangle(
|
||||
{
|
||||
{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
||||
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}
|
||||
},
|
||||
ui::Color::dark_cyan()
|
||||
);
|
||||
|
||||
painter.fill_rectangle(
|
||||
{
|
||||
{21 * CHARACTER_WIDTH + margin, 3 * LINE_HEIGHT - margin},
|
||||
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}
|
||||
},
|
||||
ui::Color::dark_cyan()
|
||||
);
|
||||
|
||||
painter.fill_rectangle(
|
||||
{
|
||||
{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin - 8},
|
||||
{17 * CHARACTER_WIDTH + margin * 2, 8}
|
||||
},
|
||||
ui::Color::dark_cyan()
|
||||
);
|
||||
|
||||
painter.fill_rectangle(
|
||||
{
|
||||
{5 * CHARACTER_WIDTH - margin, (lines+3) * LINE_HEIGHT + margin},
|
||||
{17 * CHARACTER_WIDTH + margin * 2, 8}
|
||||
},
|
||||
ui::Color::dark_cyan()
|
||||
);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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_DFU_MENU_H__
|
||||
#define __UI_DFU_MENU_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
#include "event_m0.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "string_format.hpp"
|
||||
|
||||
#define LINE_HEIGHT 16
|
||||
#define CHARACTER_WIDTH 8
|
||||
|
||||
namespace ui {
|
||||
class NavigationView;
|
||||
|
||||
class DfuMenu : public View {
|
||||
public:
|
||||
DfuMenu(NavigationView& nav);
|
||||
~DfuMenu() = default;
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
Text text_head {{ 6 * CHARACTER_WIDTH, 3 * LINE_HEIGHT, 11 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, "Performance"};
|
||||
|
||||
Labels labels {
|
||||
{ { 6 * CHARACTER_WIDTH, 5 * LINE_HEIGHT }, "M0 heap:", Color::dark_cyan() },
|
||||
{ { 6 * CHARACTER_WIDTH, 6 * LINE_HEIGHT }, "M0 stack:", Color::dark_cyan() },
|
||||
{ { 6 * CHARACTER_WIDTH, 7 * LINE_HEIGHT }, "M0 cpu %:", Color::dark_cyan() },
|
||||
{ { 6 * CHARACTER_WIDTH, 8 * LINE_HEIGHT }, "M4 heap:", Color::dark_cyan() },
|
||||
{ { 6 * CHARACTER_WIDTH, 9 * LINE_HEIGHT }, "M4 stack:", Color::dark_cyan() },
|
||||
{ { 6 * CHARACTER_WIDTH,10 * LINE_HEIGHT }, "M4 cpu %:", Color::dark_cyan() },
|
||||
{ { 6 * CHARACTER_WIDTH,11 * LINE_HEIGHT }, "M4 miss:", Color::dark_cyan() },
|
||||
{ { 6 * CHARACTER_WIDTH,12 * LINE_HEIGHT }, "uptime:", Color::dark_cyan() }
|
||||
};
|
||||
|
||||
Text text_info_line_1 {{ 15 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
Text text_info_line_2 {{ 15 * CHARACTER_WIDTH, 6 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
Text text_info_line_3 {{ 15 * CHARACTER_WIDTH, 7 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
Text text_info_line_4 {{ 15 * CHARACTER_WIDTH, 8 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
Text text_info_line_5 {{ 15 * CHARACTER_WIDTH, 9 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
Text text_info_line_6 {{ 15 * CHARACTER_WIDTH,10 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
Text text_info_line_7 {{ 15 * CHARACTER_WIDTH,11 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
Text text_info_line_8 {{ 15 * CHARACTER_WIDTH,12 * LINE_HEIGHT, 5 * CHARACTER_WIDTH, 1 * LINE_HEIGHT }, ""};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_DFU_MENU_H__*/
|
||||
@@ -262,6 +262,44 @@ void FileManagerView::on_rename(NavigationView& nav) {
|
||||
});
|
||||
}
|
||||
|
||||
void FileManagerView::on_refactor(NavigationView& nav) {
|
||||
text_prompt(nav, name_buffer, max_filename_length, [this](std::string& buffer) {
|
||||
|
||||
std::string destination_path = current_path.string();
|
||||
if (destination_path.back() != '/')//if the path is not ended with '/', add '/'
|
||||
destination_path += '/';
|
||||
|
||||
auto selected_path = get_selected_path();
|
||||
auto extension = selected_path.extension().string();
|
||||
|
||||
if(extension.empty()){// Is Dir
|
||||
destination_path = destination_path + buffer;
|
||||
extension_buffer = "";
|
||||
}else{//is File
|
||||
destination_path = destination_path + buffer + extension_buffer;
|
||||
}
|
||||
|
||||
rename_file(get_selected_path(), destination_path); //rename the selected file
|
||||
|
||||
if (!extension.empty() && selected_path.string().back() != '/' && extension.substr(1) == "C16") { //substr(1) is for ignore the dot
|
||||
// Rename its partner ( C16 <-> TXT ) file.
|
||||
auto partner_file_path = selected_path.string().substr(0, selected_path.string().size() - 4) + ".TXT";
|
||||
destination_path = destination_path.substr(0, destination_path.size() - 4) + ".TXT";
|
||||
rename_file(partner_file_path, destination_path);
|
||||
} else if (!extension.empty() && selected_path.string().back() != '/' && extension.substr(1) == "TXT") {
|
||||
// If the file user choose is a TXT file.
|
||||
auto partner_file_path = selected_path.string().substr(0, selected_path.string().size() - 4) + ".C16";
|
||||
destination_path = destination_path.substr(0, destination_path.size() - 4) + ".C16";
|
||||
rename_file(partner_file_path, destination_path);
|
||||
}
|
||||
|
||||
load_directory_contents(current_path);
|
||||
refresh_list();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void FileManagerView::on_delete() {
|
||||
delete_file(get_selected_path());
|
||||
load_directory_contents(current_path);
|
||||
@@ -271,6 +309,7 @@ void FileManagerView::on_delete() {
|
||||
void FileManagerView::refresh_widgets(const bool v) {
|
||||
button_rename.hidden(v);
|
||||
button_new_dir.hidden(v);
|
||||
button_refactor.hidden(v);
|
||||
button_delete.hidden(v);
|
||||
set_dirty();
|
||||
}
|
||||
@@ -293,6 +332,7 @@ FileManagerView::FileManagerView(
|
||||
&labels,
|
||||
&text_date,
|
||||
&button_rename,
|
||||
&button_refactor,
|
||||
&button_new_dir,
|
||||
&button_delete
|
||||
});
|
||||
@@ -325,7 +365,19 @@ FileManagerView::FileManagerView(
|
||||
name_buffer = entry_list[menu_view.highlighted_index()].entry_path.filename().string().substr(0, max_filename_length);
|
||||
on_rename(nav);
|
||||
};
|
||||
|
||||
|
||||
button_refactor.on_select = [this, &nav](Button&) {
|
||||
name_buffer = entry_list[menu_view.highlighted_index()].entry_path.filename().string().substr(0, max_filename_length);
|
||||
size_t pos = name_buffer.find_last_of(".");
|
||||
|
||||
if (pos != std::string::npos) {
|
||||
extension_buffer = name_buffer.substr(pos);
|
||||
name_buffer = name_buffer.substr(0, pos);
|
||||
}
|
||||
|
||||
on_refactor(nav);
|
||||
};
|
||||
|
||||
button_delete.on_select = [this, &nav](Button&) {
|
||||
// Use display_modal ?
|
||||
nav.push<ModalMessageView>("Delete", "Delete " + entry_list[menu_view.highlighted_index()].entry_path.filename().string() + "\nAre you sure?", YESNO,
|
||||
|
||||
@@ -67,8 +67,8 @@ protected:
|
||||
{ ".TXT", &bitmap_icon_file_text, ui::Color::white() },
|
||||
{ ".PNG", &bitmap_icon_file_image, ui::Color::green() },
|
||||
{ ".BMP", &bitmap_icon_file_image, ui::Color::green() },
|
||||
{ ".C8", &bitmap_icon_file_iq, ui::Color::blue() },
|
||||
{ ".C16", &bitmap_icon_file_iq, ui::Color::blue() },
|
||||
{ ".C8", &bitmap_icon_file_iq, ui::Color::dark_cyan() },
|
||||
{ ".C16", &bitmap_icon_file_iq, ui::Color::dark_cyan() },
|
||||
{ ".WAV", &bitmap_icon_file_wav, ui::Color::dark_magenta() },
|
||||
{ "", &bitmap_icon_file, ui::Color::light_grey() }
|
||||
};
|
||||
@@ -143,9 +143,11 @@ public:
|
||||
|
||||
private:
|
||||
std::string name_buffer { };
|
||||
std::string extension_buffer { };
|
||||
|
||||
void refresh_widgets(const bool v);
|
||||
void on_rename(NavigationView& nav);
|
||||
void on_refactor(NavigationView& nav);
|
||||
void on_delete();
|
||||
|
||||
Labels labels {
|
||||
@@ -158,11 +160,17 @@ private:
|
||||
};
|
||||
|
||||
Button button_rename {
|
||||
{ 0 * 8, 29 * 8, 14 * 8, 32 },
|
||||
{ 0 * 8, 29 * 8, 9 * 8, 32 },
|
||||
"Rename"
|
||||
};
|
||||
|
||||
Button button_refactor{
|
||||
{ 10 * 8, 29 * 8, 10 * 8, 32 },
|
||||
"Refactor"
|
||||
};
|
||||
|
||||
Button button_delete {
|
||||
{ 16 * 8, 29 * 8, 14 * 8, 32 },
|
||||
{ 21 * 8, 29 * 8, 9 * 8, 32 },
|
||||
"Delete"
|
||||
};
|
||||
|
||||
|
||||
@@ -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__*/
|
||||
@@ -26,7 +26,6 @@ using namespace portapack;
|
||||
|
||||
namespace ui
|
||||
{
|
||||
|
||||
void GlassView::focus()
|
||||
{
|
||||
field_marker.focus();
|
||||
@@ -39,6 +38,29 @@ namespace ui
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
// Returns the next multiple of num that is a multiple of multiplier
|
||||
int64_t GlassView::next_mult_of(int64_t num, int64_t multiplier) {
|
||||
return ((num / multiplier) + 1) * multiplier;
|
||||
}
|
||||
|
||||
// Returns the previous multiple of num that is a multiple of multiplier
|
||||
//int64_t GlassView::prev_mult_of(int64_t num, int64_t multiplier) {
|
||||
// return (num / multiplier) * multiplier;
|
||||
//}
|
||||
|
||||
void GlassView::adjust_range(int64_t* f_min, int64_t* f_max, int64_t width) {
|
||||
int64_t span = *f_max - *f_min;
|
||||
int64_t num_intervals = span / width;
|
||||
if( span % width != 0 )
|
||||
{
|
||||
num_intervals++;
|
||||
}
|
||||
int64_t new_span = num_intervals * width;
|
||||
int64_t delta_span = (new_span - span) / 2;
|
||||
*f_min -= delta_span;
|
||||
*f_max += delta_span;
|
||||
}
|
||||
|
||||
void GlassView::on_lna_changed(int32_t v_db)
|
||||
{
|
||||
receiver_model.set_lna(v_db);
|
||||
@@ -49,12 +71,71 @@ namespace ui
|
||||
receiver_model.set_vga(v_db);
|
||||
}
|
||||
|
||||
void GlassView::add_spectrum_pixel(Color color)
|
||||
void GlassView::reset_live_view( bool clear_screen )
|
||||
{
|
||||
spectrum_row[pixel_index++] = color;
|
||||
max_freq_hold = 0 ;
|
||||
max_freq_power = -1000 ;
|
||||
if( clear_screen )
|
||||
{
|
||||
// only clear screen in peak mode
|
||||
if( live_frequency_view == 2 )
|
||||
{
|
||||
display.fill_rectangle( { { 0 , 108 + 16 } , { 240 , 320 - (108 + 16) } } , { 0 , 0 , 0 } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GlassView::add_spectrum_pixel( uint8_t power )
|
||||
{
|
||||
static int64_t last_max_freq = 0 ;
|
||||
|
||||
spectrum_row[pixel_index] = spectrum_rgb3_lut[power] ; // row of colors
|
||||
spectrum_data[pixel_index] = ( live_frequency_integrate * spectrum_data[pixel_index] + power ) / (live_frequency_integrate + 1); // smoothing
|
||||
pixel_index ++ ;
|
||||
|
||||
if (pixel_index == 240) // got an entire waterfall line
|
||||
{
|
||||
display.draw_pixels({{0, display.scroll(1)}, {240, 1}}, spectrum_row); // new line at top, one less var, speedier
|
||||
if( live_frequency_view > 0 )
|
||||
{
|
||||
constexpr int rssi_sample_range = 256;
|
||||
constexpr float rssi_voltage_min = 0.4;
|
||||
constexpr float rssi_voltage_max = 2.2;
|
||||
constexpr float adc_voltage_max = 3.3;
|
||||
constexpr int raw_min = rssi_sample_range * rssi_voltage_min / adc_voltage_max;
|
||||
constexpr int raw_max = rssi_sample_range * rssi_voltage_max / adc_voltage_max;
|
||||
constexpr int raw_delta = raw_max - raw_min;
|
||||
const range_t<int> y_max_range { 0 , 320 - ( 108 + 16 ) };
|
||||
|
||||
//drawing and keeping track of max freq
|
||||
for( uint16_t xpos = 0 ; xpos < 240 ; xpos ++ )
|
||||
{
|
||||
// save max powerwull freq
|
||||
if( spectrum_data[ xpos ] > max_freq_power )
|
||||
{
|
||||
max_freq_power = spectrum_data[ xpos ];
|
||||
max_freq_hold = f_min + ( (f_max - f_min) * xpos) / 240 ;
|
||||
}
|
||||
|
||||
int16_t point = y_max_range.clip( ( ( spectrum_data[ xpos ] - raw_min ) * ( 320 - ( 108 + 16 ) ) ) / raw_delta );
|
||||
uint8_t color_gradient = (point * 255) / 212 ;
|
||||
// clear if not in peak view
|
||||
if( live_frequency_view != 2 )
|
||||
{
|
||||
display.fill_rectangle( { { xpos , 108 + 16 } , { 1 , 320 - point } } , { 0 , 0 , 0 } );
|
||||
}
|
||||
display.fill_rectangle( { { xpos , 320 - point } , { 1 , point } } , { color_gradient , 0 , uint8_t( 255 - color_gradient ) } );
|
||||
}
|
||||
if( last_max_freq != max_freq_hold )
|
||||
{
|
||||
last_max_freq = max_freq_hold ;
|
||||
freq_stats.set( "MAX HOLD: "+to_string_short_freq( max_freq_hold ) );
|
||||
}
|
||||
PlotMarker(field_marker.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
display.draw_pixels({{0, display.scroll(1)}, {240, 1}}, spectrum_row); // new line at top, one less var, speedier
|
||||
}
|
||||
pixel_index = 0; // Start New cascade line
|
||||
}
|
||||
}
|
||||
@@ -64,52 +145,83 @@ namespace ui
|
||||
void GlassView::on_channel_spectrum(const ChannelSpectrum &spectrum)
|
||||
{
|
||||
baseband::spectrum_streaming_stop();
|
||||
|
||||
// Convert bins of this spectrum slice into a representative max_power and when enough, into pixels
|
||||
// Spectrum.db has 256 bins. Center 12 bins are ignored (DC spike is blanked) Leftmost and rightmost 2 bins are ignored
|
||||
// All things said and done, we actually need 240 of those bins:
|
||||
for (uint8_t bin = 0; bin < 240; bin++)
|
||||
if( fast_scan || ( LOOKING_GLASS_SLICE_WIDTH < LOOKING_GLASS_SLICE_WIDTH_MAX ) )
|
||||
{
|
||||
if (bin < 120)
|
||||
// Convert bins of this spectrum slice into a representative max_power and when enough, into pixels
|
||||
// Spectrum.db has 256 bins. Center 12 bins are ignored (DC spike is blanked) Leftmost and rightmost 2 bins are ignored
|
||||
// All things said and done, we actually need 240 of those bins:
|
||||
for (uint8_t bin = 0; bin < 240; bin++)
|
||||
{
|
||||
if (bin < 120)
|
||||
{
|
||||
if (spectrum.db[134 + bin] > max_power) // 134
|
||||
max_power = spectrum.db[134 + bin];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spectrum.db[bin - 118] > max_power) // 118
|
||||
max_power = spectrum.db[bin - 118];
|
||||
}
|
||||
|
||||
bins_Hz_size += each_bin_size; // add this bin Hz count into the "pixel fulfilled bag of Hz"
|
||||
|
||||
if (bins_Hz_size >= marker_pixel_step) // new pixel fullfilled
|
||||
{
|
||||
if (min_color_power < max_power)
|
||||
add_spectrum_pixel(max_power); // Pixel will represent max_power
|
||||
else
|
||||
add_spectrum_pixel(0); // Filtered out, show black
|
||||
|
||||
max_power = 0;
|
||||
|
||||
if (!pixel_index) // Received indication that a waterfall line has been completed
|
||||
{
|
||||
bins_Hz_size = 0; // Since this is an entire pixel line, we don't carry "Pixels into next bin"
|
||||
f_center = f_center_ini - 2 * each_bin_size ; // Start a new sweep
|
||||
radio::set_tuning_frequency(f_center); // tune rx for this new slice directly, faster than using persistent memory saving
|
||||
chThdSleepMilliseconds(10);
|
||||
baseband::spectrum_streaming_start(); // Do the RX
|
||||
return;
|
||||
}
|
||||
bins_Hz_size -= marker_pixel_step; // reset bins size, but carrying the eventual excess Hz into next pixel
|
||||
}
|
||||
}
|
||||
f_center += 240 * each_bin_size ; // Move into the next bandwidth slice NOTE: spectrum.sampling_rate = LOOKING_GLASS_SLICE_WIDTH
|
||||
}
|
||||
else //slow scan
|
||||
{
|
||||
for (uint8_t bin = 0; bin < 120 ; bin++)
|
||||
{
|
||||
if (spectrum.db[134 + bin] > max_power) // 134
|
||||
max_power = spectrum.db[134 + bin];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spectrum.db[bin - 118] > max_power) // 118
|
||||
max_power = spectrum.db[bin - 118];
|
||||
}
|
||||
|
||||
bins_Hz_size += each_bin_size; // add this bin Hz count into the "pixel fulfilled bag of Hz"
|
||||
bins_Hz_size += each_bin_size; // add this bin Hz count into the "pixel fulfilled bag of Hz"
|
||||
|
||||
if (bins_Hz_size >= marker_pixel_step) // new pixel fullfilled
|
||||
{
|
||||
if (min_color_power < max_power)
|
||||
add_spectrum_pixel(spectrum_rgb3_lut[max_power]); // Pixel will represent max_power
|
||||
else
|
||||
add_spectrum_pixel(0); // Filtered out, show black
|
||||
|
||||
max_power = 0;
|
||||
|
||||
if (!pixel_index) // Received indication that a waterfall line has been completed
|
||||
if (bins_Hz_size >= marker_pixel_step) // new pixel fullfilled
|
||||
{
|
||||
bins_Hz_size = 0; // Since this is an entire pixel line, we don't carry "Pixels into next bin"
|
||||
f_center = f_center_ini; // Start a new sweep
|
||||
radio::set_tuning_frequency(f_center); // tune rx for this new slice directly, faster than using persistent memory saving
|
||||
chThdSleepMilliseconds(10);
|
||||
baseband::spectrum_streaming_start(); // Do the RX
|
||||
return;
|
||||
}
|
||||
bins_Hz_size -= marker_pixel_step; // reset bins size, but carrying the eventual excess Hz into next pixel
|
||||
}
|
||||
}
|
||||
if (min_color_power < max_power)
|
||||
add_spectrum_pixel(max_power); // Pixel will represent max_power
|
||||
else
|
||||
add_spectrum_pixel(0); // Filtered out, show black
|
||||
|
||||
f_center += LOOKING_GLASS_SLICE_WIDTH; // Move into the next bandwidth slice NOTE: spectrum.sampling_rate = LOOKING_GLASS_SLICE_WIDTH
|
||||
max_power = 0;
|
||||
|
||||
if (!pixel_index) // Received indication that a waterfall line has been completed
|
||||
{
|
||||
bins_Hz_size = 0; // Since this is an entire pixel line, we don't carry "Pixels into next bin"
|
||||
f_center = f_center_ini - 2 * each_bin_size ; // Start a new sweep
|
||||
radio::set_tuning_frequency(f_center); // tune rx for this new slice directly, faster than using persistent memory saving
|
||||
chThdSleepMilliseconds(10);
|
||||
baseband::spectrum_streaming_start(); // Do the RX
|
||||
return;
|
||||
}
|
||||
bins_Hz_size -= marker_pixel_step; // reset bins size, but carrying the eventual excess Hz into next pixel
|
||||
}
|
||||
}
|
||||
f_center += 120 * each_bin_size ;
|
||||
}
|
||||
radio::set_tuning_frequency(f_center); // tune rx for this new slice directly, faster than using persistent memory saving
|
||||
chThdSleepMilliseconds(5);
|
||||
|
||||
// receiver_model.set_tuning_frequency(f_center); //tune rx for this slice
|
||||
baseband::spectrum_streaming_start(); // Do the RX
|
||||
}
|
||||
|
||||
@@ -127,19 +239,27 @@ namespace ui
|
||||
|
||||
void GlassView::on_range_changed()
|
||||
{
|
||||
reset_live_view( false );
|
||||
f_min = field_frequency_min.value();
|
||||
f_max = field_frequency_max.value();
|
||||
search_span = f_max - f_min;
|
||||
|
||||
field_marker.set_range(f_min, f_max); // Move the marker between range
|
||||
field_marker.set_value(f_min + (search_span / 2)); // Put MARKER AT MIDDLE RANGE
|
||||
text_range.set(to_string_dec_uint(search_span));
|
||||
if( locked_range )
|
||||
{
|
||||
button_range.set_text(">"+to_string_dec_uint(search_span)+"<");
|
||||
}
|
||||
else
|
||||
{
|
||||
button_range.set_text(" "+to_string_dec_uint(search_span)+" ");
|
||||
}
|
||||
|
||||
f_min = (f_min)*MHZ_DIV; // Transpose into full frequency realm
|
||||
f_max = (f_max)*MHZ_DIV;
|
||||
search_span = search_span * MHZ_DIV;
|
||||
adjust_range( &f_min , &f_max , 240 );
|
||||
|
||||
marker_pixel_step = search_span / 240; // Each pixel value in Hz
|
||||
marker_pixel_step = (f_max - f_min) / 240; // Each pixel value in Hz
|
||||
text_marker_pm.set(to_string_dec_uint((marker_pixel_step / X2_MHZ_DIV) + 1)); // Give idea of +/- marker precision
|
||||
|
||||
int32_t marker_step = marker_pixel_step / MHZ_DIV;
|
||||
@@ -156,7 +276,20 @@ namespace ui
|
||||
pixel_index = 0; // reset pixel counter
|
||||
max_power = 0;
|
||||
bins_Hz_size = 0; // reset amount of Hz filled up by pixels
|
||||
|
||||
if( next_mult_of( (f_max - f_min) , 240 ) <= LOOKING_GLASS_SLICE_WIDTH_MAX )
|
||||
{
|
||||
LOOKING_GLASS_SLICE_WIDTH = next_mult_of( (f_max - f_min) , 240 );
|
||||
receiver_model.set_sampling_rate(LOOKING_GLASS_SLICE_WIDTH);
|
||||
receiver_model.set_baseband_bandwidth(LOOKING_GLASS_SLICE_WIDTH/2);
|
||||
}
|
||||
else if( LOOKING_GLASS_SLICE_WIDTH != LOOKING_GLASS_SLICE_WIDTH_MAX )
|
||||
{
|
||||
LOOKING_GLASS_SLICE_WIDTH = LOOKING_GLASS_SLICE_WIDTH_MAX ;
|
||||
receiver_model.set_sampling_rate(LOOKING_GLASS_SLICE_WIDTH);
|
||||
receiver_model.set_baseband_bandwidth(LOOKING_GLASS_SLICE_WIDTH);
|
||||
}
|
||||
receiver_model.set_squelch_level(0);
|
||||
each_bin_size = LOOKING_GLASS_SLICE_WIDTH / 240 ;
|
||||
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, field_trigger.value());
|
||||
receiver_model.set_tuning_frequency(f_center_ini); // tune rx for this slice
|
||||
}
|
||||
@@ -166,11 +299,16 @@ namespace ui
|
||||
pos = pos * MHZ_DIV;
|
||||
pos -= f_min;
|
||||
pos = pos / marker_pixel_step; // Real pixel
|
||||
|
||||
portapack::display.fill_rectangle({0, 100, 240, 8}, Color::black()); // Clear old marker and whole marker rectangle btw
|
||||
portapack::display.fill_rectangle({(int)pos - 2, 100, 5, 3}, Color::red()); // Red marker top
|
||||
portapack::display.fill_rectangle({(int)pos - 1, 103, 3, 3}, Color::red()); // Red marker middle
|
||||
portapack::display.fill_rectangle({(int)pos, 106, 1, 2}, Color::red()); // Red marker bottom
|
||||
|
||||
uint8_t shift_y = 0 ;
|
||||
if( live_frequency_view > 0 )
|
||||
{
|
||||
shift_y = 16 ;
|
||||
}
|
||||
portapack::display.fill_rectangle({0, 100 + shift_y, 240, 8}, Color::black()); // Clear old marker and whole marker rectangle btw
|
||||
portapack::display.fill_rectangle({(int)pos - 2, 100 + shift_y, 5, 3}, Color::red()); // Red marker top
|
||||
portapack::display.fill_rectangle({(int)pos - 1, 103 + shift_y, 3, 3}, Color::red()); // Red marker middle
|
||||
portapack::display.fill_rectangle({(int)pos, 106 + shift_y, 1, 2}, Color::red()); // Red marker bottom
|
||||
}
|
||||
|
||||
GlassView::GlassView(
|
||||
@@ -183,96 +321,117 @@ namespace ui
|
||||
&field_frequency_max,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
&text_range,
|
||||
&button_range,
|
||||
&steps_config,
|
||||
&scan_type,
|
||||
&view_config,
|
||||
&level_integration,
|
||||
&filter_config,
|
||||
&field_rf_amp,
|
||||
&range_presets,
|
||||
&field_marker,
|
||||
&text_marker_pm,
|
||||
&field_trigger});
|
||||
&field_trigger,
|
||||
&button_jump,
|
||||
&button_rst,
|
||||
&freq_stats});
|
||||
|
||||
load_Presets(); // Load available presets from TXT files (or default)
|
||||
|
||||
field_frequency_min.set_value(presets_db[0].min); // Defaults to first preset
|
||||
field_frequency_min.set_step( steps );
|
||||
field_frequency_min.on_change = [this](int32_t v)
|
||||
{
|
||||
int32_t steps_ = steps ;
|
||||
if( steps_ < 24 )
|
||||
steps_ = 24 ;
|
||||
if( v > 7200 - steps_ )
|
||||
reset_live_view( true );
|
||||
int32_t min_size = steps ;
|
||||
if( locked_range )
|
||||
min_size = search_span ;
|
||||
if( min_size < 2 )
|
||||
min_size = 2 ;
|
||||
if( v > 7200 - min_size )
|
||||
{
|
||||
v = 7200 - steps_ ;
|
||||
v = 7200 - min_size ;
|
||||
field_frequency_min.set_value( v );
|
||||
}
|
||||
if (v >= (field_frequency_max.value() - steps_ ) )
|
||||
field_frequency_max.set_value( v + steps_ );
|
||||
if (v > (field_frequency_max.value() - min_size ) )
|
||||
field_frequency_max.set_value( v + min_size );
|
||||
if( locked_range )
|
||||
field_frequency_max.set_value( v + min_size );
|
||||
this->on_range_changed();
|
||||
};
|
||||
field_frequency_min.set_value(presets_db[0].min); // Defaults to first preset
|
||||
field_frequency_min.set_step( steps );
|
||||
|
||||
field_frequency_min.on_select = [this, &nav](NumberField& field) {
|
||||
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_min.value()*1000000);
|
||||
new_view->on_changed = [this, &field](rf::Frequency f) {
|
||||
int32_t freq = f / 1000000 ;
|
||||
int32_t steps_ = steps ;
|
||||
if( steps_ < 24 )
|
||||
steps_ = 24 ;
|
||||
if( freq > (7200 - steps_ ) )
|
||||
freq= 7200 - steps_ ;
|
||||
int32_t min_size = steps ;
|
||||
if( locked_range )
|
||||
min_size = search_span ;
|
||||
if( min_size < 2 )
|
||||
min_size = 2 ;
|
||||
if( freq > (7200 - min_size ) )
|
||||
freq = 7200 - min_size ;
|
||||
field_frequency_min.set_value( freq );
|
||||
if( field_frequency_max.value() < ( freq + steps_ ) )
|
||||
field_frequency_max.set_value( freq + steps_ );
|
||||
if( field_frequency_max.value() < ( freq + min_size ) )
|
||||
field_frequency_max.set_value( freq + min_size );
|
||||
this->on_range_changed();
|
||||
};
|
||||
};
|
||||
|
||||
field_frequency_max.set_value(presets_db[0].max); // Defaults to first preset
|
||||
field_frequency_max.set_step( steps );
|
||||
field_frequency_max.on_change = [this](int32_t v)
|
||||
{
|
||||
int32_t steps_ = steps ;
|
||||
if( steps_ < 24 )
|
||||
steps_ = 24 ;
|
||||
if( v < steps_ )
|
||||
reset_live_view( true );
|
||||
int32_t min_size = steps ;
|
||||
if( locked_range )
|
||||
min_size = search_span ;
|
||||
if( min_size < 2 )
|
||||
min_size = 2 ;
|
||||
if( v < min_size )
|
||||
{
|
||||
v = steps_ ;
|
||||
v = min_size ;
|
||||
field_frequency_max.set_value( v );
|
||||
}
|
||||
if (v < (field_frequency_min.value() + steps_) )
|
||||
field_frequency_min.set_value(v - steps_);
|
||||
if (v < (field_frequency_min.value() + min_size) )
|
||||
field_frequency_min.set_value(v - min_size);
|
||||
if( locked_range )
|
||||
field_frequency_min.set_value( v - min_size );
|
||||
this->on_range_changed();
|
||||
};
|
||||
field_frequency_max.set_value(presets_db[0].max); // Defaults to first preset
|
||||
field_frequency_max.set_step( steps );
|
||||
|
||||
field_frequency_max.on_select = [this, &nav](NumberField& field) {
|
||||
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_max.value()*1000000);
|
||||
new_view->on_changed = [this, &field](rf::Frequency f) {
|
||||
int32_t steps_ = steps ;
|
||||
if( steps_ < 24 )
|
||||
steps_ = 24 ;
|
||||
int32_t min_size = steps ;
|
||||
if( locked_range )
|
||||
min_size = search_span ;
|
||||
if( min_size < 2 )
|
||||
min_size = 2 ;
|
||||
int32_t freq = f / 1000000 ;
|
||||
if( freq < 24 )
|
||||
freq = 24 ;
|
||||
if( freq < min_size )
|
||||
freq = min_size ;
|
||||
field_frequency_max.set_value( freq );
|
||||
if( field_frequency_min.value() > ( freq - steps) )
|
||||
field_frequency_min.set_value( freq - steps );
|
||||
if( field_frequency_min.value() > ( freq - min_size) )
|
||||
field_frequency_min.set_value( freq - min_size );
|
||||
this->on_range_changed();
|
||||
};
|
||||
};
|
||||
|
||||
field_lna.set_value(receiver_model.lna());
|
||||
field_lna.on_change = [this](int32_t v)
|
||||
{
|
||||
reset_live_view( true );
|
||||
this->on_lna_changed(v);
|
||||
};
|
||||
field_lna.set_value(receiver_model.lna());
|
||||
|
||||
field_vga.set_value(receiver_model.vga());
|
||||
field_vga.on_change = [this](int32_t v_db)
|
||||
{
|
||||
reset_live_view( true );
|
||||
this->on_vga_changed(v_db);
|
||||
};
|
||||
field_vga.set_value(receiver_model.vga());
|
||||
|
||||
steps_config.set_selected_index(3); //default of 250 Mhz steps
|
||||
steps_config.on_change = [this](size_t n, OptionsField::value_t v)
|
||||
{
|
||||
(void)n;
|
||||
@@ -280,6 +439,67 @@ namespace ui
|
||||
field_frequency_max.set_step( v );
|
||||
steps = v ;
|
||||
};
|
||||
steps_config.set_selected_index(0); //default of 1 Mhz steps
|
||||
|
||||
scan_type.on_change = [this](size_t n, OptionsField::value_t v)
|
||||
{
|
||||
(void)n;
|
||||
fast_scan = v ;
|
||||
};
|
||||
scan_type.set_selected_index(0); // default legacy fast scan
|
||||
|
||||
view_config.on_change = [this](size_t n, OptionsField::value_t v)
|
||||
{
|
||||
(void)n;
|
||||
// clear between changes
|
||||
reset_live_view( true );
|
||||
if( v == 0 )
|
||||
{
|
||||
live_frequency_view = 0 ;
|
||||
level_integration.hidden( true );
|
||||
freq_stats.hidden( true );
|
||||
button_jump.hidden( true );
|
||||
button_rst.hidden( true );
|
||||
display.scroll_set_area(109, 319); // Restart scroll on the correct coordinates
|
||||
}
|
||||
else if( v == 1 )
|
||||
{
|
||||
display.fill_rectangle( { { 0 , 108 } , { 240 , 24 } } , { 0 , 0 , 0 } );
|
||||
live_frequency_view = 1 ;
|
||||
display.scroll_disable();
|
||||
level_integration.hidden( false );
|
||||
freq_stats.hidden( false );
|
||||
button_jump.hidden( false );
|
||||
button_rst.hidden( false );
|
||||
}
|
||||
else if( v == 2 )
|
||||
{
|
||||
display.fill_rectangle( { { 0 , 108 } , { 240 , 24 } } , { 0 , 0 , 0 } );
|
||||
live_frequency_view = 2 ;
|
||||
display.scroll_disable();
|
||||
level_integration.hidden( false );
|
||||
freq_stats.hidden( false );
|
||||
button_jump.hidden( false );
|
||||
button_rst.hidden( false );
|
||||
}
|
||||
set_dirty();
|
||||
};
|
||||
view_config.set_selected_index(0); //default spectrum
|
||||
|
||||
level_integration.on_change = [this](size_t n, OptionsField::value_t v)
|
||||
{
|
||||
(void)n;
|
||||
reset_live_view( true );
|
||||
live_frequency_integrate = v ;
|
||||
};
|
||||
level_integration.set_selected_index(3); //default integration of ( 3 * old value + new_value ) / 4
|
||||
|
||||
filter_config.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
reset_live_view( true );
|
||||
min_color_power = v;
|
||||
};
|
||||
filter_config.set_selected_index(0);
|
||||
|
||||
range_presets.on_change = [this](size_t n, OptionsField::value_t v)
|
||||
{
|
||||
@@ -304,11 +524,37 @@ namespace ui
|
||||
nav_.push<AnalogAudioView>(); // Jump into audio view
|
||||
};
|
||||
|
||||
field_trigger.set_value(32); // Defaults to 32, as normal triggering resolution
|
||||
field_trigger.on_change = [this](int32_t v)
|
||||
{
|
||||
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, v);
|
||||
};
|
||||
field_trigger.set_value(32); // Defaults to 32, as normal triggering resolution
|
||||
|
||||
button_range.on_select = [this](Button&) {
|
||||
if( locked_range )
|
||||
{
|
||||
locked_range = false ;
|
||||
button_range.set_style(&style_white);
|
||||
button_range.set_text(" "+to_string_dec_uint(search_span)+" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
locked_range = true ;
|
||||
button_range.set_style(&style_red);
|
||||
button_range.set_text(">"+to_string_dec_uint(search_span)+"<");
|
||||
}
|
||||
};
|
||||
|
||||
button_jump.on_select = [this](Button&) {
|
||||
receiver_model.set_tuning_frequency(max_freq_hold); // Center tune rx in marker freq.
|
||||
receiver_model.set_frequency_step(MHZ_DIV); // Preset a 1 MHz frequency step into RX -> AUDIO
|
||||
nav_.pop();
|
||||
nav_.push<AnalogAudioView>(); // Jump into audio view
|
||||
};
|
||||
|
||||
button_rst.on_select = [this](Button&) {
|
||||
reset_live_view( true );
|
||||
};
|
||||
|
||||
display.scroll_set_area(109, 319);
|
||||
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, field_trigger.value()); // trigger:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2020 euquiq
|
||||
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -36,13 +37,14 @@
|
||||
|
||||
namespace ui
|
||||
{
|
||||
#define LOOKING_GLASS_SLICE_WIDTH 20000000 // Each slice bandwidth 20 MHz
|
||||
#define LOOKING_GLASS_SLICE_WIDTH_MAX 19999920
|
||||
#define MHZ_DIV 1000000
|
||||
#define X2_MHZ_DIV 2000000
|
||||
|
||||
class GlassView : public View
|
||||
{
|
||||
public:
|
||||
|
||||
GlassView(NavigationView &nav);
|
||||
|
||||
GlassView( const GlassView &);
|
||||
@@ -64,15 +66,38 @@ namespace ui
|
||||
rf::Frequency max{};
|
||||
std::string label{};
|
||||
};
|
||||
|
||||
const Style style_white { // free range
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::white(),
|
||||
};
|
||||
|
||||
const Style style_red { // locked range
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::red(),
|
||||
};
|
||||
|
||||
std::vector<preset_entry> presets_db{};
|
||||
|
||||
// Each slice bandwidth 20 MHz and a multiple of 240
|
||||
// since we are using LOOKING_GLASS_SLICE_WIDTH/240 as the each_bin_size
|
||||
// it should also be a multiple of 2 since we are using LOOKING_GLASS_SLICE_WIDTH / 2 as centering freq
|
||||
int64_t LOOKING_GLASS_SLICE_WIDTH = 19999920;
|
||||
|
||||
// frequency rounding helpers
|
||||
int64_t next_mult_of(int64_t num, int64_t multiplier);
|
||||
//int64_t prev_mult_of(int64_t num, int64_t multiplier);
|
||||
void adjust_range(int64_t* f_min, int64_t* f_max, int64_t width);
|
||||
|
||||
void on_channel_spectrum(const ChannelSpectrum& spectrum);
|
||||
void do_timers();
|
||||
void on_range_changed();
|
||||
void on_lna_changed(int32_t v_db);
|
||||
void on_vga_changed(int32_t v_db);
|
||||
void add_spectrum_pixel(Color color);
|
||||
void reset_live_view( bool clear_screen );
|
||||
void add_spectrum_pixel(uint8_t power);
|
||||
void PlotMarker(rf::Frequency pos);
|
||||
void load_Presets();
|
||||
void txtline_process(std::string& line);
|
||||
@@ -89,16 +114,23 @@ namespace ui
|
||||
uint8_t min_color_power { 0 };
|
||||
uint32_t pixel_index { 0 };
|
||||
std::array<Color, 240> spectrum_row = { 0 };
|
||||
std::array<uint8_t, 240> spectrum_data = { 0 };
|
||||
ChannelSpectrumFIFO* fifo { nullptr };
|
||||
uint8_t max_power = 0;
|
||||
int32_t steps = 250 ; // default of 250 Mhz steps
|
||||
int32_t steps = 0 ;
|
||||
uint8_t live_frequency_view = 0 ;
|
||||
int16_t live_frequency_integrate = 3 ;
|
||||
int64_t max_freq_hold = 0 ;
|
||||
int16_t max_freq_power = -1000 ;
|
||||
bool fast_scan = true ; // default to legacy fast scan
|
||||
bool locked_range = false ;
|
||||
|
||||
Labels labels{
|
||||
{{0, 0}, "MIN: MAX: LNA VGA ", Color::light_grey()},
|
||||
{{0, 1 * 16}, " RANGE: FILTER: AMP:", Color::light_grey()},
|
||||
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Color::light_grey()},
|
||||
{{0, 2 * 16}, "PRESET:", Color::light_grey()},
|
||||
{{0, 3 * 16}, "MARKER: MHz +/- MHz", Color::light_grey()},
|
||||
{{0, 4 * 16}, "RESOLUTION: STEPS:", Color::light_grey()}
|
||||
{{0, 4 * 16}, "RES: STEP:", Color::light_grey()}
|
||||
};
|
||||
|
||||
NumberField field_frequency_min {
|
||||
@@ -125,24 +157,12 @@ namespace ui
|
||||
{ 27 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
Text text_range{
|
||||
Button button_range{
|
||||
{7 * 8, 1 * 16, 4 * 8, 16},
|
||||
""};
|
||||
|
||||
OptionsField steps_config{
|
||||
{ 22 * 8, 4 * 16},
|
||||
4,
|
||||
{
|
||||
{"1", 1},
|
||||
{"50", 50},
|
||||
{"100", 100},
|
||||
{"250", 250},
|
||||
{"500", 500},
|
||||
{"1000", 1000},
|
||||
}};
|
||||
|
||||
OptionsField filter_config{
|
||||
{19 * 8, 1 * 16},
|
||||
{20 * 8, 1 * 16},
|
||||
4,
|
||||
{
|
||||
{"OFF ", 0},
|
||||
@@ -172,12 +192,74 @@ namespace ui
|
||||
""};
|
||||
|
||||
NumberField field_trigger{
|
||||
{11 * 8, 4 * 16},
|
||||
{4 * 8, 4 * 16},
|
||||
3,
|
||||
{2, 128},
|
||||
2,
|
||||
' '};
|
||||
|
||||
OptionsField steps_config{
|
||||
{ 13 * 8, 4 * 16},
|
||||
3,
|
||||
{
|
||||
{"1", 1},
|
||||
{"25", 25},
|
||||
{"50", 50},
|
||||
{"100", 100},
|
||||
{"250", 250},
|
||||
{"500", 500},
|
||||
}
|
||||
};
|
||||
|
||||
OptionsField scan_type{
|
||||
{ 17 * 8, 4 * 16},
|
||||
2,
|
||||
{
|
||||
{"F-", true },
|
||||
{"S-", false },
|
||||
}
|
||||
};
|
||||
|
||||
OptionsField view_config{
|
||||
{ 19 * 8, 4 * 16},
|
||||
7,
|
||||
{
|
||||
{"SPCTR-V", 0 },
|
||||
{"LEVEL-V", 1 },
|
||||
{"PEAK-V" , 2 },
|
||||
}
|
||||
};
|
||||
|
||||
OptionsField level_integration{
|
||||
{ 27 * 8, 4 * 16},
|
||||
2,
|
||||
{
|
||||
{"x0", 0 },
|
||||
{"x1", 1 },
|
||||
{"x2", 2 },
|
||||
{"x3", 3 },
|
||||
{"x4", 4 },
|
||||
{"x5", 5 },
|
||||
{"x6", 6 },
|
||||
{"x7", 7 },
|
||||
{"x8", 8 },
|
||||
{"x9", 9 },
|
||||
}};
|
||||
|
||||
Button button_jump {
|
||||
{ 240 - 4 * 8 , 5 * 16 , 4 * 8, 16 },
|
||||
"JMP"
|
||||
};
|
||||
|
||||
Button button_rst {
|
||||
{ 240 - 9 * 8 , 5 * 16 , 4 * 8, 16 },
|
||||
"RST"
|
||||
};
|
||||
|
||||
Text freq_stats{
|
||||
{0 * 8, 5 * 16 , 240 - 10 * 8 , 8 },
|
||||
""
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_spectrum_config {
|
||||
Message::ID::ChannelSpectrumConfig,
|
||||
|
||||
@@ -180,7 +180,10 @@ void MicTXView::rxaudio(bool is_on) {
|
||||
receiver_model.set_sampling_rate(3072000);
|
||||
receiver_model.set_baseband_bandwidth(1750000);
|
||||
// receiver_model.set_tuning_frequency(field_frequency.value()); //probably this too can be commented out.
|
||||
receiver_model.set_tuning_frequency(rx_frequency); // Now with seperate controls!
|
||||
if (bool_same_F_tx_rx_enabled) // when stop TX ,define to which freq RX we return
|
||||
receiver_model.set_tuning_frequency(tx_frequency); // Update freq also for RX = TX
|
||||
else
|
||||
receiver_model.set_tuning_frequency(rx_frequency); // Now with seperate freq controls!
|
||||
receiver_model.set_lna(rx_lna);
|
||||
receiver_model.set_vga(rx_vga);
|
||||
receiver_model.set_rf_amp(rx_amp);
|
||||
@@ -237,6 +240,7 @@ MicTXView::MicTXView(
|
||||
&field_frequency,
|
||||
&options_tone_key,
|
||||
&check_rogerbeep,
|
||||
&check_common_freq_tx_rx, // added to handle common or separate freq- TX/RX
|
||||
&check_rxactive,
|
||||
&field_volume,
|
||||
&field_rxbw,
|
||||
@@ -266,6 +270,7 @@ MicTXView::MicTXView(
|
||||
&field_frequency,
|
||||
&options_tone_key,
|
||||
&check_rogerbeep,
|
||||
&check_common_freq_tx_rx, // added to handle common or separate freq- TX/RX
|
||||
&check_rxactive,
|
||||
&field_volume,
|
||||
&field_rxbw,
|
||||
@@ -332,8 +337,12 @@ MicTXView::MicTXView(
|
||||
field_frequency.set_step(receiver_model.frequency_step());
|
||||
field_frequency.on_change = [this](rf::Frequency f) {
|
||||
tx_frequency = f;
|
||||
if(!rx_enabled)
|
||||
if(!rx_enabled) { // not activated receiver. just update freq TX
|
||||
transmitter_model.set_tuning_frequency(f);
|
||||
} else { // activated receiver.
|
||||
if (bool_same_F_tx_rx_enabled) // user selected common freq- TX = RX
|
||||
receiver_model.set_tuning_frequency(f); //Update common freq also for RX
|
||||
}
|
||||
};
|
||||
field_frequency.on_edit = [this, &nav]() {
|
||||
focused_ui = 0;
|
||||
@@ -341,8 +350,12 @@ MicTXView::MicTXView(
|
||||
auto new_view = nav.push<FrequencyKeypadView>(tx_frequency);
|
||||
new_view->on_changed = [this](rf::Frequency f) {
|
||||
tx_frequency = f;
|
||||
if(!rx_enabled)
|
||||
if(!rx_enabled) {
|
||||
transmitter_model.set_tuning_frequency(f);
|
||||
} else {
|
||||
if (bool_same_F_tx_rx_enabled)
|
||||
receiver_model.set_tuning_frequency(f); //Update freq also for RX
|
||||
}
|
||||
this->field_frequency.set_value(f);
|
||||
set_dirty();
|
||||
};
|
||||
@@ -511,6 +524,13 @@ MicTXView::MicTXView(
|
||||
rogerbeep_enabled = v;
|
||||
};
|
||||
|
||||
check_common_freq_tx_rx.on_select = [this](Checkbox&, bool v) {
|
||||
bool_same_F_tx_rx_enabled = v;
|
||||
field_rxfrequency.hidden(v); //Hide or show separated freq RX field . (When no hide user can enter down indep. freq for RX)
|
||||
set_dirty(); //Refresh GUI interface
|
||||
receiver_model.set_tuning_frequency(v ? tx_frequency : rx_frequency); // To go to the proper tuned freq. when toggling it
|
||||
};
|
||||
|
||||
field_va_level.on_change = [this](int32_t v) {
|
||||
va_level = v;
|
||||
vumeter.set_mark(v);
|
||||
@@ -563,12 +583,12 @@ MicTXView::MicTXView(
|
||||
rx_frequency = receiver_model.tuning_frequency();
|
||||
field_rxfrequency.set_value(rx_frequency);
|
||||
field_rxfrequency.set_step(receiver_model.frequency_step());
|
||||
field_rxfrequency.on_change = [this](rf::Frequency f) {
|
||||
field_rxfrequency.on_change = [this](rf::Frequency f) { // available when field rxfrequency not hidden => user selected separated freq RX/TX-
|
||||
rx_frequency = f;
|
||||
if(rx_enabled)
|
||||
receiver_model.set_tuning_frequency(f);
|
||||
};
|
||||
field_rxfrequency.on_edit = [this, &nav]() {
|
||||
field_rxfrequency.on_edit = [this, &nav]() { // available when field rxfrequency not hidden => user selected separated freq RX/TX-
|
||||
focused_ui = 1;
|
||||
// TODO: Provide separate modal method/scheme?
|
||||
auto new_view = nav.push<FrequencyKeypadView>(rx_frequency);
|
||||
|
||||
@@ -80,6 +80,7 @@ private:
|
||||
bool va_enabled { false };
|
||||
bool ptt_enabled { true };
|
||||
bool rogerbeep_enabled { false };
|
||||
bool bool_same_F_tx_rx_enabled { false };
|
||||
bool rx_enabled { false };
|
||||
uint32_t tone_key_index { };
|
||||
float mic_gain { 1.0 };
|
||||
@@ -123,9 +124,9 @@ private:
|
||||
{ {20 * 8, 10 * 8 }, "DEC:", Color::light_grey() },
|
||||
{ { 4 * 8, ( 13 * 8 ) - 2 }, "TONE KEY:", Color::light_grey() },
|
||||
{ { 7 * 8, 23 * 8 }, "VOL:", Color::light_grey() },
|
||||
{ {14 * 8, 23 * 8 }, "RXBW:", Color::light_grey() }, //we remove the label "FM" because we will display all MOD types RX_BW.
|
||||
{ {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
|
||||
{ { 5 * 8, 25 * 8 }, "F:", Color::light_grey() },
|
||||
{ {14 * 8, 23 * 8 }, "RXBW:", Color::light_grey() }, //we remove the label "FM" because we will display all MOD types RX_BW.
|
||||
{ {20 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
|
||||
{ { 5 * 8, 25 * 8 }, "F_RX:", Color::light_grey() },
|
||||
{ { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()},
|
||||
{ {12 * 8, 27 * 8 }, "VGA:", Color::light_grey()},
|
||||
{ {19 * 8, 27 * 8 }, "AMP:", Color::light_grey()}
|
||||
@@ -145,8 +146,8 @@ private:
|
||||
{ { 4 * 8, ( 13 * 8 ) - 2 }, "TONE KEY:", Color::light_grey() },
|
||||
{ { (6 * 8)+4, 23 * 8 }, "VOL:", Color::light_grey() },
|
||||
{ {14 * 8, 23 * 8 }, "RXBW:", Color::light_grey() }, //we remove the label "FM" because we will display all MOD types RX_BW.
|
||||
{ {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
|
||||
{ { 5 * 8, 25 * 8 }, "F:", Color::light_grey() },
|
||||
{ {20 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
|
||||
{ { 5 * 8, 25 * 8 }, "F_RX:", Color::light_grey() },
|
||||
{ { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()},
|
||||
{ {12 * 8, 27 * 8 }, "VGA:", Color::light_grey()},
|
||||
{ {19 * 8, 27 * 8 }, "AMP:", Color::light_grey()}
|
||||
@@ -287,7 +288,7 @@ OptionsField options_wm8731_boost_mode {
|
||||
};
|
||||
|
||||
Checkbox check_rogerbeep {
|
||||
{ 3 * 8, ( 16 * 8 ) + 4 },
|
||||
{ 3 * 8, ( 16 * 8 ) + 7 },
|
||||
10,
|
||||
"Roger beep",
|
||||
false
|
||||
@@ -295,11 +296,18 @@ OptionsField options_wm8731_boost_mode {
|
||||
|
||||
Checkbox check_rxactive {
|
||||
{ 3 * 8, ( 21 * 8 ) - 4 },
|
||||
8,
|
||||
18, // it was 8, but if it is string size should be 18
|
||||
"RX audio listening",
|
||||
false
|
||||
};
|
||||
|
||||
Checkbox check_common_freq_tx_rx {
|
||||
{ 18 * 8, ( 16* 8 ) + 7 },
|
||||
8,
|
||||
"F = F_RX",
|
||||
false
|
||||
};
|
||||
|
||||
NumberField field_volume {
|
||||
{ 11* 8, 23 * 8 },
|
||||
2,
|
||||
@@ -319,7 +327,7 @@ OptionsField options_wm8731_boost_mode {
|
||||
};
|
||||
|
||||
NumberField field_squelch {
|
||||
{ 20 * 8, 25 * 8 },
|
||||
{ 23 * 8, 25 * 8 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
@@ -327,7 +335,7 @@ OptionsField options_wm8731_boost_mode {
|
||||
};
|
||||
|
||||
FrequencyField field_rxfrequency {
|
||||
{ 7 * 8, 25 * 8 },
|
||||
{ 10 * 8, 25 * 8 },
|
||||
};
|
||||
|
||||
NumberField field_rxlna {
|
||||
@@ -347,7 +355,7 @@ OptionsField options_wm8731_boost_mode {
|
||||
};
|
||||
|
||||
NumberField field_rxamp {
|
||||
{ 23 * 8, 27 * 8 },
|
||||
{ 24 * 8, 27 * 8 },
|
||||
1,
|
||||
{ 0, 1 },
|
||||
1,
|
||||
|
||||
@@ -150,9 +150,11 @@ namespace ui {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ReconThread::run() {
|
||||
|
||||
if (frequency_list_.size() > 0 ) { //IF THERE IS A FREQUENCY LIST ...
|
||||
void ReconThread::run()
|
||||
{
|
||||
//IF THERE IS A FREQUENCY LIST ...
|
||||
if (frequency_list_.size() > 0 )
|
||||
{
|
||||
int64_t minfreq = 0 ;
|
||||
int64_t maxfreq = 0 ;
|
||||
bool has_looped = false ;
|
||||
@@ -200,121 +202,93 @@ namespace ui {
|
||||
last_entry . bandwidth = -1 ;
|
||||
last_entry . step = -1 ;
|
||||
bool restart_recon = false; //Flag whenever scanning is restarting after a pause
|
||||
int16_t last_index = -1 ;
|
||||
|
||||
while( !chThdShouldTerminate() && frequency_list_.size() > 0 ) {
|
||||
has_looped = false ;
|
||||
entry_has_changed = false ;
|
||||
while( !chThdShouldTerminate() && frequency_list_.size() > 0 )
|
||||
{
|
||||
if( !_freq_delete )
|
||||
{
|
||||
if( _recon || _stepper != 0 || _index_stepper != 0 || last_index !=frequency_index )
|
||||
has_looped = false ;
|
||||
if( last_entry . frequency_a != freq || entry_has_changed )
|
||||
{
|
||||
last_index = frequency_index ;
|
||||
if( last_entry . frequency_a != freq )
|
||||
last_entry . frequency_a = freq ;
|
||||
receiver_model.set_tuning_frequency( freq ); // Retune
|
||||
message.freq = freq ;
|
||||
message.range = frequency_index ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
entry_has_changed = false ;
|
||||
|
||||
// Set modulation if any
|
||||
if( last_entry . modulation != frequency_list_[ frequency_index ] . modulation && frequency_list_[ frequency_index ] . modulation >= 0 )
|
||||
{
|
||||
last_entry . modulation = frequency_list_[ frequency_index ]. modulation;
|
||||
message.freq = last_entry . modulation ;
|
||||
message.range = MSG_RECON_SET_MODULATION ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
// Set bandwidth if any
|
||||
if( last_entry . bandwidth != frequency_list_[ frequency_index ] . bandwidth && frequency_list_[ frequency_index ] . bandwidth >= 0 )
|
||||
{
|
||||
last_entry . bandwidth = frequency_list_[ frequency_index ]. bandwidth;
|
||||
message.freq = last_entry . bandwidth ;
|
||||
message.range = MSG_RECON_SET_BANDWIDTH ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
if( last_entry . step != frequency_list_[ frequency_index ] . step && frequency_list_[ frequency_index ] . step >= 0 )
|
||||
{
|
||||
last_entry . step = frequency_list_[ frequency_index ]. step ;
|
||||
message.freq = last_entry . step ;
|
||||
message.range = MSG_RECON_SET_STEP ;
|
||||
EventDispatcher::send_message(message);
|
||||
step = freqman_entry_get_step_value( last_entry . step );
|
||||
}
|
||||
|
||||
if( _recon || _stepper != 0 || _index_stepper != 0 )
|
||||
{
|
||||
if( _freq_lock == 0 || _stepper != 0 || _index_stepper != 0 ) //normal recon (not performing freq_lock)
|
||||
{
|
||||
last_entry . frequency_a = freq ;
|
||||
receiver_model.set_tuning_frequency( freq ); // Retune
|
||||
message.freq = freq ;
|
||||
message.range = frequency_index ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
// Set modulation if any
|
||||
if( last_entry . modulation != frequency_list_[ frequency_index ] . modulation && frequency_list_[ frequency_index ] . modulation >= 0 )
|
||||
{
|
||||
last_entry . modulation = frequency_list_[ frequency_index ]. modulation;
|
||||
message.freq = last_entry . modulation ;
|
||||
message.range = MSG_RECON_SET_MODULATION ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
// Set bandwidth if any
|
||||
if( last_entry . bandwidth != frequency_list_[ frequency_index ] . bandwidth && frequency_list_[ frequency_index ] . bandwidth >= 0 )
|
||||
{
|
||||
last_entry . bandwidth = frequency_list_[ frequency_index ]. bandwidth;
|
||||
message.freq = last_entry . bandwidth ;
|
||||
message.range = MSG_RECON_SET_BANDWIDTH ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
if( last_entry . step != frequency_list_[ frequency_index ] . step && frequency_list_[ frequency_index ] . step >= 0 )
|
||||
{
|
||||
last_entry . step = frequency_list_[ frequency_index ]. step ;
|
||||
message.freq = last_entry . step ;
|
||||
message.range = MSG_RECON_SET_STEP ;
|
||||
EventDispatcher::send_message(message);
|
||||
step = freqman_entry_get_step_value( last_entry . step );
|
||||
}
|
||||
if( _freq_lock == 0 || _stepper != 0 ) //normal recon (not performing freq_lock)
|
||||
{
|
||||
if( !restart_recon || _stepper != 0 )
|
||||
if( !restart_recon || _stepper != 0 || _index_stepper != 0 )
|
||||
{
|
||||
|
||||
/* we are doing a range */
|
||||
if( frequency_list_[ frequency_index ] . type == RANGE ) {
|
||||
|
||||
if ( ( _fwd && _stepper == 0 ) || _stepper > 0 ) {
|
||||
//forward
|
||||
freq += step ;
|
||||
// if bigger than range max
|
||||
if (freq > maxfreq ) {
|
||||
// when going forward we already know that we can skip a whole range => two values in the list
|
||||
frequency_index ++ ;
|
||||
entry_has_changed = true ;
|
||||
// looping
|
||||
if( (uint32_t)frequency_index >= frequency_list_.size() )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( (!_fwd && _stepper == 0 ) || _stepper < 0 ) {
|
||||
//reverse
|
||||
freq -= step ;
|
||||
// if lower than range min
|
||||
if (freq < minfreq ) {
|
||||
// when back we have to check one step at a time
|
||||
frequency_index -- ;
|
||||
entry_has_changed = true ;
|
||||
// looping
|
||||
if( frequency_index < 0 )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( frequency_list_[ frequency_index ] . type == SINGLE ) {
|
||||
if ( (_fwd && _stepper == 0 ) || _stepper > 0 ) { //forward
|
||||
frequency_index++;
|
||||
entry_has_changed = true ;
|
||||
// looping
|
||||
if( (uint32_t)frequency_index >= frequency_list_.size() )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = 0 ;
|
||||
}
|
||||
}
|
||||
else if( (!_fwd && _stepper == 0 ) || _stepper < 0 ) {
|
||||
//reverse
|
||||
frequency_index--;
|
||||
entry_has_changed = true ;
|
||||
// if previous if under the list => go back from end
|
||||
if( frequency_index < 0 )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( frequency_list_[ frequency_index ] . type == HAMRADIO )
|
||||
if( _index_stepper == 0 )
|
||||
{
|
||||
if ( (_fwd && _stepper == 0 ) || _stepper > 0 ) { //forward
|
||||
if( ( minfreq != maxfreq ) && freq == minfreq )
|
||||
{
|
||||
freq = maxfreq ;
|
||||
/* we are doing a range */
|
||||
if( frequency_list_[ frequency_index ] . type == RANGE ) {
|
||||
if ( ( _fwd && _stepper == 0 ) || _stepper > 0 ) {
|
||||
//forward
|
||||
freq += step ;
|
||||
// if bigger than range max
|
||||
if (freq > maxfreq ) {
|
||||
// when going forward we already know that we can skip a whole range => two values in the list
|
||||
frequency_index ++ ;
|
||||
entry_has_changed = true ;
|
||||
// looping
|
||||
if( (uint32_t)frequency_index >= frequency_list_.size() )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else if( (!_fwd && _stepper == 0 ) || _stepper < 0 ) {
|
||||
//reverse
|
||||
freq -= step ;
|
||||
// if lower than range min
|
||||
if (freq < minfreq ) {
|
||||
// when back we have to check one step at a time
|
||||
frequency_index -- ;
|
||||
entry_has_changed = true ;
|
||||
// looping
|
||||
if( frequency_index < 0 )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( frequency_list_[ frequency_index ] . type == SINGLE ) {
|
||||
if ( (_fwd && _stepper == 0 ) || _stepper > 0 ) { //forward
|
||||
frequency_index++;
|
||||
entry_has_changed = true ;
|
||||
// looping
|
||||
@@ -324,15 +298,8 @@ namespace ui {
|
||||
frequency_index = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( (!_fwd && _stepper == 0 ) || _stepper < 0 ) {
|
||||
//reverse
|
||||
if( ( minfreq != maxfreq ) && freq == maxfreq )
|
||||
{
|
||||
freq = minfreq ;
|
||||
}
|
||||
else
|
||||
{
|
||||
else if( (!_fwd && _stepper == 0 ) || _stepper < 0 ) {
|
||||
//reverse
|
||||
frequency_index--;
|
||||
entry_has_changed = true ;
|
||||
// if previous if under the list => go back from end
|
||||
@@ -343,98 +310,131 @@ namespace ui {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( frequency_list_[ frequency_index ] . type == HAMRADIO )
|
||||
{
|
||||
if ( (_fwd && _stepper == 0 ) || _stepper > 0 ) { //forward
|
||||
if( ( minfreq != maxfreq ) && freq == minfreq )
|
||||
{
|
||||
freq = maxfreq ;
|
||||
}
|
||||
else
|
||||
{
|
||||
frequency_index++;
|
||||
entry_has_changed = true ;
|
||||
// looping
|
||||
if( (uint32_t)frequency_index >= frequency_list_.size() )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( (!_fwd && _stepper == 0 ) || _stepper < 0 ) {
|
||||
//reverse
|
||||
if( ( minfreq != maxfreq ) && freq == maxfreq )
|
||||
{
|
||||
freq = minfreq ;
|
||||
}
|
||||
else
|
||||
{
|
||||
frequency_index--;
|
||||
entry_has_changed = true ;
|
||||
// if previous if under the list => go back from end
|
||||
if( frequency_index < 0 )
|
||||
{
|
||||
has_looped = true ;
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// set index to boundary if !continuous
|
||||
if( has_looped && !_continuous )
|
||||
{
|
||||
entry_has_changed = true ;
|
||||
/* prepare values for the next run, when user will resume */
|
||||
if( ( _fwd && _stepper == 0 ) || _stepper > 0 )
|
||||
{
|
||||
frequency_index = 0 ;
|
||||
}
|
||||
else if( ( !_fwd && _stepper == 0 ) || _stepper < 0 )
|
||||
{
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// set index to boundary if !continuous
|
||||
else
|
||||
{
|
||||
if( _index_stepper > 0 )
|
||||
frequency_index ++ ;
|
||||
if( _index_stepper < 0 )
|
||||
frequency_index -- ;
|
||||
if( frequency_index < 0 )
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
if( (unsigned)frequency_index >= frequency_list_.size() )
|
||||
frequency_index = 0 ;
|
||||
entry_has_changed = true ;
|
||||
}
|
||||
|
||||
// reload entry if changed
|
||||
if( entry_has_changed ){
|
||||
switch( frequency_list_[ frequency_index ] . type ){
|
||||
case SINGLE:
|
||||
freq = frequency_list_[ frequency_index ] . frequency_a ;
|
||||
break;
|
||||
case RANGE:
|
||||
minfreq = frequency_list_[ frequency_index ] . frequency_a ;
|
||||
maxfreq = frequency_list_[ frequency_index ] . frequency_b ;
|
||||
if( ( _fwd && _stepper == 0 ) || _stepper > 0 || _index_stepper > 0 )
|
||||
{
|
||||
freq = minfreq ;
|
||||
}
|
||||
else if( ( !_fwd && _stepper == 0 ) || _stepper < 0 || _index_stepper < 0 )
|
||||
{
|
||||
freq = maxfreq ;
|
||||
}
|
||||
break;
|
||||
case HAMRADIO:
|
||||
minfreq = frequency_list_[ frequency_index ] . frequency_a ;
|
||||
maxfreq = frequency_list_[ frequency_index ] . frequency_b ;
|
||||
if( ( _fwd && _stepper == 0 ) || _stepper > 0 || _index_stepper > 0 )
|
||||
{
|
||||
freq = minfreq ;
|
||||
}
|
||||
else if( ( !_fwd && _stepper == 0 ) || _stepper < 0 || _index_stepper < 0 )
|
||||
{
|
||||
freq = maxfreq ;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// send a pause message with the right freq
|
||||
if( has_looped && !_continuous )
|
||||
{
|
||||
entry_has_changed = true ;
|
||||
/* prepare values for the next run, when user will resume */
|
||||
if( ( _fwd && _stepper == 0 ) || _stepper > 0 )
|
||||
{
|
||||
frequency_index = 0 ;
|
||||
}
|
||||
else if( ( !_fwd && _stepper == 0 ) || _stepper < 0 )
|
||||
{
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
}
|
||||
// signal pause to handle_retune
|
||||
receiver_model.set_tuning_frequency( freq ); // Retune to actual freq
|
||||
message.freq = freq ;
|
||||
message.range = MSG_RECON_PAUSE ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
}
|
||||
if( _stepper < 0 ) _stepper ++ ;
|
||||
if( _stepper > 0 ) _stepper -- ;
|
||||
if( _index_stepper < 0 ) _index_stepper ++ ;
|
||||
if( _index_stepper > 0 ) _index_stepper -- ;
|
||||
} // if( !restart_recon || _stepper != 0 || _index_stepper != 0 )
|
||||
else
|
||||
{
|
||||
restart_recon = false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
restart_recon = true ;
|
||||
}
|
||||
if( _index_stepper != 0 )
|
||||
{
|
||||
if( _index_stepper > 0 )
|
||||
frequency_index ++ ;
|
||||
if( _index_stepper < 0 )
|
||||
frequency_index -- ;
|
||||
if( frequency_index < 0 )
|
||||
frequency_index = frequency_list_.size() - 1 ;
|
||||
if( (unsigned)frequency_index >= frequency_list_.size() )
|
||||
frequency_index = 0 ;
|
||||
entry_has_changed = true ;
|
||||
}
|
||||
// reload entry if changed
|
||||
if( entry_has_changed ){
|
||||
switch( frequency_list_[ frequency_index ] . type ){
|
||||
case SINGLE:
|
||||
freq = frequency_list_[ frequency_index ] . frequency_a ;
|
||||
break;
|
||||
case RANGE:
|
||||
minfreq = frequency_list_[ frequency_index ] . frequency_a ;
|
||||
maxfreq = frequency_list_[ frequency_index ] . frequency_b ;
|
||||
if( ( _fwd && _stepper == 0 ) || _stepper > 0 || _index_stepper > 0 )
|
||||
{
|
||||
freq = minfreq ;
|
||||
}
|
||||
else if( ( !_fwd && _stepper == 0 ) || _stepper < 0 || _index_stepper < 0 )
|
||||
{
|
||||
freq = maxfreq ;
|
||||
}
|
||||
break;
|
||||
case HAMRADIO:
|
||||
minfreq = frequency_list_[ frequency_index ] . frequency_a ;
|
||||
maxfreq = frequency_list_[ frequency_index ] . frequency_b ;
|
||||
if( ( _fwd && _stepper == 0 ) || _stepper > 0 || _index_stepper > 0 )
|
||||
{
|
||||
freq = minfreq ;
|
||||
}
|
||||
else if( ( !_fwd && _stepper == 0 ) || _stepper < 0 || _index_stepper < 0 )
|
||||
{
|
||||
freq = maxfreq ;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
// send a pause message with the right freq
|
||||
if( has_looped && !_continuous )
|
||||
{
|
||||
// signal pause to handle_retune
|
||||
receiver_model.set_tuning_frequency( freq ); // Retune to actual freq
|
||||
message.freq = freq ;
|
||||
message.range = MSG_RECON_PAUSE ;
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
if( _stepper < 0 ) _stepper ++ ;
|
||||
if( _stepper > 0 ) _stepper -- ;
|
||||
if( _index_stepper < 0 ) _index_stepper ++ ;
|
||||
if( _index_stepper > 0 ) _index_stepper -- ;
|
||||
|
||||
}
|
||||
} // if( _freq_lock == 0 || _stepper != 0 || _index_stepper != 0 )
|
||||
} // if( _recon || _stepper != 0 || _index_stepper != 0 )
|
||||
} // if( !freq_delete )
|
||||
chThdSleepMilliseconds( _lock_duration ); //Needed to (eventually) stabilize the receiver into new freq
|
||||
}
|
||||
}
|
||||
}
|
||||
} //while( !chThdShouldTerminate() && frequency_list_.size() > 0 )
|
||||
}//if (frequency_list_.size() > 0 )
|
||||
} //ReconThread::run
|
||||
|
||||
bool ReconView::check_sd_card()
|
||||
{
|
||||
@@ -528,32 +528,28 @@ namespace ui {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t freq_lock = recon_thread->is_freq_lock();
|
||||
|
||||
if( freq_lock == 0 ) {
|
||||
//NO FREQ LOCK, ONGOING STANDARD SCANNING
|
||||
if( index < 1000 && index < frequency_list.size() )
|
||||
text_cycle.set_text( to_string_dec_uint( index + 1 , 3 ) );
|
||||
if(frequency_list[index].description.size() > 0)
|
||||
{
|
||||
text_cycle.set_text( to_string_dec_uint( index + 1 , 3 ) );
|
||||
if(frequency_list[index].description.size() > 0)
|
||||
switch( frequency_list[current_index].type )
|
||||
{
|
||||
switch( frequency_list[current_index].type )
|
||||
{
|
||||
case RANGE:
|
||||
desc_cycle.set( "R: " + frequency_list[current_index].description ); //Show new description
|
||||
break ;
|
||||
case HAMRADIO:
|
||||
desc_cycle.set( "H: " + frequency_list[current_index].description ); //Show new description
|
||||
break ;
|
||||
default:
|
||||
case SINGLE:
|
||||
desc_cycle.set( "S: " + frequency_list[current_index].description ); //Show new description
|
||||
break ;
|
||||
}
|
||||
case RANGE:
|
||||
desc_cycle.set( "R: " + frequency_list[current_index].description ); //Show new description
|
||||
break ;
|
||||
case HAMRADIO:
|
||||
desc_cycle.set( "H: " + frequency_list[current_index].description ); //Show new description
|
||||
break ;
|
||||
default:
|
||||
case SINGLE:
|
||||
desc_cycle.set( "S: " + frequency_list[current_index].description ); //Show new description
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t freq_lock = recon_thread->is_freq_lock();
|
||||
if( freq_lock == 0 ) {
|
||||
//NO FREQ LOCK, ONGOING STANDARD SCANNING
|
||||
big_display.set_style(&style_white);
|
||||
if( !userpause )
|
||||
button_pause.set_text("<PAUSE>");
|
||||
@@ -766,7 +762,7 @@ namespace ui {
|
||||
}
|
||||
button_scanner_mode.set_style( &style_blue );
|
||||
button_scanner_mode.set_text( "RECON" );
|
||||
file_name.set( "USE:" );
|
||||
file_name.set( "=>" );
|
||||
|
||||
field_squelch.set_value( squelch );
|
||||
|
||||
@@ -1194,7 +1190,7 @@ namespace ui {
|
||||
button_scanner_mode.set_style( &style_white );
|
||||
button_scanner_mode.set_text( "MSEARCH" );
|
||||
file_name.set_style( &style_white );
|
||||
file_name.set( "USE: MANUAL RANGE" );
|
||||
file_name.set( "=> MANUAL RANGE" );
|
||||
|
||||
start_recon_thread();
|
||||
user_resume();
|
||||
@@ -1574,12 +1570,12 @@ namespace ui {
|
||||
{
|
||||
desc_cycle.set(" NO " + input_file + ".TXT FILE ..." );
|
||||
file_name.set_style( &style_white );
|
||||
file_name.set( "USE: NO DATA" );
|
||||
file_name.set( "=> NO DATA" );
|
||||
}
|
||||
else
|
||||
{
|
||||
file_name.set_style( &style_blue );
|
||||
file_name.set( "USE: "+input_file + ".TXT" );
|
||||
file_name.set( "=> "+input_file );
|
||||
}
|
||||
step_mode.set_selected_index(def_step); //Impose the default step into the manual step selector
|
||||
}
|
||||
@@ -1591,11 +1587,11 @@ namespace ui {
|
||||
{
|
||||
desc_cycle.set(" NO " + output_file + ".TXT FILE ..." );
|
||||
file_name.set_style( &style_white );
|
||||
file_name.set( "USE:" );
|
||||
file_name.set( "=> EMPTY" );
|
||||
}
|
||||
else
|
||||
{
|
||||
file_name.set( "USE: "+output_file + ".TXT" );
|
||||
file_name.set( "=> "+output_file );
|
||||
file_name.set_style( &style_red );
|
||||
}
|
||||
step_mode.set_selected_index(def_step); //Impose the default step into the manual step selector
|
||||
|
||||
@@ -270,16 +270,16 @@ namespace ui {
|
||||
};
|
||||
|
||||
RSSI rssi {
|
||||
{ 0 * 16, 2 * 16, 240 - 5 * 8 - 1 , 16 },
|
||||
{ 0 * 16, 2 * 16, 240 - 8 * 8 + 4 , 16 },
|
||||
};
|
||||
|
||||
ButtonWithEncoder text_cycle {
|
||||
{ 0, 3 * 16, 3 * 8, 16 },
|
||||
{ 0, 3 * 16, 4 * 8, 16 },
|
||||
""
|
||||
};
|
||||
|
||||
Text text_max {
|
||||
{ 3 * 8, 3 * 16, 20 * 8 , 16 },
|
||||
{ 4 * 8, 3 * 16, 240 - 7 * 8 - 4 * 8 , 16 },
|
||||
};
|
||||
|
||||
Text desc_cycle {
|
||||
@@ -292,11 +292,11 @@ namespace ui {
|
||||
}; */
|
||||
|
||||
Text big_display { //Show frequency in text mode
|
||||
{ 0, 5 * 16 , 21 * 8, 16 },
|
||||
{ 0, 5 * 16 , 23 * 8, 16 },
|
||||
};
|
||||
|
||||
Text freq_stats { //Show frequency stats in text mode
|
||||
{ 0, 6 * 16 , 21 * 8, 16 },
|
||||
{ 0, 6 * 16 , 23 * 8, 16 },
|
||||
};
|
||||
|
||||
// TIMER: 9999
|
||||
@@ -311,12 +311,12 @@ namespace ui {
|
||||
};
|
||||
|
||||
Button button_recon_setup {
|
||||
{ 240 - 5 * 8 , 2 * 16 , 5 * 8, 28 },
|
||||
"OPT"
|
||||
{ 240 - 7 * 8 , 2 * 16 , 7 * 8, 28 },
|
||||
"CONFIG"
|
||||
};
|
||||
|
||||
Button button_looking_glass {
|
||||
{ 240 - 5 * 8 , 5 * 16 , 5 * 8, 28 },
|
||||
{ 240 - 7 * 8 , 5 * 16 , 7 * 8, 28 },
|
||||
"GLASS"
|
||||
};
|
||||
|
||||
|
||||
@@ -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,425 +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_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);
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Converter Settings
|
||||
// ---------------------------------------------------------
|
||||
SetConverterSettingsView::SetConverterSettingsView(NavigationView& nav) {
|
||||
add_children({
|
||||
&check_show_converter,
|
||||
&check_converter,
|
||||
&converter_mode,
|
||||
&button_converter_freq,
|
||||
&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
|
||||
});
|
||||
|
||||
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);
|
||||
};
|
||||
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);
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
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);
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
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>" );
|
||||
};
|
||||
};
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
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);
|
||||
};
|
||||
|
||||
void SetConverterSettingsView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
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>" );
|
||||
};
|
||||
};
|
||||
|
||||
SetAudioView::SetAudioView(NavigationView& nav) {
|
||||
add_children({
|
||||
&labels,
|
||||
&field_tone_mix,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
};
|
||||
void SetConverterSettingsView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
// ---------------------------------------------------------
|
||||
// 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 SetAudioView::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");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_bigger_qr,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
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");
|
||||
}
|
||||
};
|
||||
|
||||
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_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_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
}
|
||||
button_return.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetQRCodeView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
void SetPersistentMemoryView::focus() {
|
||||
button_return.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>(); } }
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
//
|
||||
// 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 */
|
||||
|
||||
@@ -432,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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -43,6 +43,7 @@ using namespace lpc43xx;
|
||||
#include <array>
|
||||
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -262,6 +263,8 @@ void EventDispatcher::on_touch_event(ui::TouchEvent event) {
|
||||
void EventDispatcher::handle_lcd_frame_sync() {
|
||||
DisplayFrameSyncMessage message;
|
||||
message_map.send(&message);
|
||||
|
||||
static_cast<ui::SystemView *>(top_widget)->paint_overlay();
|
||||
painter.paint_widget_tree(top_widget);
|
||||
|
||||
portapack::backlight()->on();
|
||||
@@ -304,7 +307,12 @@ void EventDispatcher::handle_switches() {
|
||||
if( switches_state[i] ) {
|
||||
const auto event = static_cast<ui::KeyEvent>(i);
|
||||
if( !event_bubble_key(event) ) {
|
||||
context.focus_manager().update(top_widget, event);
|
||||
if (switches_state[(size_t)ui::KeyEvent::Dfu]) {
|
||||
static_cast<ui::SystemView *>(top_widget)->toggle_overlay();
|
||||
}
|
||||
else {
|
||||
context.focus_manager().update(top_widget, event);
|
||||
}
|
||||
}
|
||||
|
||||
in_key_event = true;
|
||||
|
||||
@@ -42,7 +42,7 @@ using namespace hackrf::one;
|
||||
|
||||
static Thread* thread_controls_event = NULL;
|
||||
|
||||
static std::array<Debounce, 7> switch_debounce;
|
||||
static std::array<Debounce, 8> switch_debounce;
|
||||
|
||||
static Encoder encoder;
|
||||
|
||||
@@ -193,11 +193,13 @@ void controls_init() {
|
||||
|
||||
SwitchesState get_switches_state() {
|
||||
SwitchesState result;
|
||||
for(size_t i=0; i<result.size(); i++) {
|
||||
for(size_t i=0; i<result.size()-1; i++) {
|
||||
// TODO: Ignore multiple keys at the same time?
|
||||
result[i] = switch_debounce[i].state();
|
||||
}
|
||||
|
||||
result[result.size()-1] = switch_debounce[switch_debounce.size()-1].state();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ enum class Switch {
|
||||
Down = 2,
|
||||
Up = 3,
|
||||
Sel = 4,
|
||||
Dfu = 5,
|
||||
};
|
||||
|
||||
using SwitchesState = std::bitset<5>;
|
||||
using SwitchesState = std::bitset<6>;
|
||||
|
||||
using EncoderPosition = uint32_t;
|
||||
|
||||
|
||||
@@ -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__*/
|
||||
@@ -145,14 +145,14 @@ Continuous (Fox-oring)
|
||||
rffc507x::RFFC507x first_if;
|
||||
|
||||
static void event_loop() {
|
||||
ui::Context context;
|
||||
ui::SystemView system_view {
|
||||
static ui::Context context;
|
||||
static ui::SystemView system_view {
|
||||
context,
|
||||
portapack::display.screen_rect()
|
||||
};
|
||||
|
||||
EventDispatcher event_dispatcher { &system_view, context };
|
||||
MessageHandlerRegistration message_handler_display_sleep {
|
||||
static MessageHandlerRegistration message_handler_display_sleep {
|
||||
Message::ID::DisplaySleep,
|
||||
[&event_dispatcher](const Message* const) {
|
||||
event_dispatcher.set_display_sleep(true);
|
||||
|
||||
@@ -61,7 +61,7 @@ portapack::IO io {
|
||||
portapack::gpio_io_stbx,
|
||||
portapack::gpio_addr,
|
||||
portapack::gpio_lcd_te,
|
||||
portapack::gpio_unused,
|
||||
portapack::gpio_dfu,
|
||||
};
|
||||
|
||||
portapack::BacklightCAT4004 backlight_cat4004;
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace ui {
|
||||
// show green peak value
|
||||
if( peak_enabled )
|
||||
{
|
||||
const Rect r5 { r.left() + peak - 1 , r.top() , 3 , r.height() };
|
||||
const Rect r5 { r.left() + peak - 3 , r.top() , 3 , r.height() };
|
||||
painter.fill_rectangle(
|
||||
r5,
|
||||
Color::green()
|
||||
@@ -160,7 +160,7 @@ namespace ui {
|
||||
// show green peak value if enabled
|
||||
if( peak_enabled )
|
||||
{
|
||||
const Rect r5 { r.left(), r.bottom() - peak - 1 , r.width() , 3 };
|
||||
const Rect r5 { r.left(), r.bottom() - peak - 3 , r.width() , 3 };
|
||||
painter.fill_rectangle(
|
||||
r5,
|
||||
Color::green()
|
||||
@@ -434,6 +434,23 @@ namespace ui {
|
||||
void RSSIGraph::set_nb_columns( int16_t nb )
|
||||
{
|
||||
nb_columns = nb ;
|
||||
while( graph_list.size() > nb_columns )
|
||||
{
|
||||
graph_list.erase( graph_list.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
void RSSIGraph::on_hide() {
|
||||
nb_columns_before_hide = nb_columns ;
|
||||
nb_columns = 1 ;
|
||||
while( graph_list.size() > nb_columns )
|
||||
{
|
||||
graph_list.erase( graph_list.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
void RSSIGraph::on_show() {
|
||||
nb_columns = nb_columns_before_hide ;
|
||||
}
|
||||
|
||||
void RSSI::on_focus() {
|
||||
|
||||
@@ -115,8 +115,12 @@ namespace ui {
|
||||
void paint(Painter& painter) override;
|
||||
void add_values(int16_t rssi_min, int16_t rssi_avg, int16_t rssi_max, int16_t db );
|
||||
void set_nb_columns( int16_t nb );
|
||||
|
||||
void on_hide() override ;
|
||||
void on_show() override ;
|
||||
|
||||
private:
|
||||
uint16_t nb_columns_before_hide = 16 ;
|
||||
uint16_t nb_columns = 16 ;
|
||||
RSSIGraphList graph_list { } ;
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "bmp_splash.hpp"
|
||||
#include "bmp_modal_warning.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "ui_about_simple.hpp"
|
||||
#include "ui_adsb_rx.hpp"
|
||||
@@ -70,6 +71,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"
|
||||
@@ -613,6 +616,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
|
||||
}
|
||||
@@ -719,6 +724,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>();
|
||||
@@ -736,6 +749,36 @@ Context& SystemView::context() const {
|
||||
return context_;
|
||||
}
|
||||
|
||||
void SystemView::toggle_overlay() {
|
||||
if (overlay_active){
|
||||
this->remove_child(&this->overlay);
|
||||
this->set_dirty();
|
||||
shared_memory.request_m4_performance_counter = 0;
|
||||
}
|
||||
else{
|
||||
this->add_child(&this->overlay);
|
||||
this->set_dirty();
|
||||
shared_memory.request_m4_performance_counter = 1;
|
||||
shared_memory.m4_cpu_usage = 0;
|
||||
shared_memory.m4_heap_usage = 0;
|
||||
shared_memory.m4_stack_usage = 0;
|
||||
}
|
||||
|
||||
overlay_active = !overlay_active;
|
||||
}
|
||||
|
||||
void SystemView::paint_overlay() {
|
||||
static bool last_paint_state = false;
|
||||
if (overlay_active){
|
||||
// paint background only every other second
|
||||
if ((((chTimeNow()>>10) & 0x01) == 0x01) == last_paint_state)
|
||||
return;
|
||||
|
||||
last_paint_state = !last_paint_state;
|
||||
this->overlay.set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/* ***********************************************************************/
|
||||
|
||||
void BMPView::focus() {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "ui_channel.hpp"
|
||||
#include "ui_audio.hpp"
|
||||
#include "ui_sd_card_status_view.hpp"
|
||||
#include "ui_dfu_menu.hpp"
|
||||
|
||||
#include "bitmap.hpp"
|
||||
#include "ff.h"
|
||||
@@ -125,7 +126,7 @@ namespace ui
|
||||
Color::dark_grey()};
|
||||
|
||||
ImageButton button_back{
|
||||
{2, 0 * 16, 16, 16},
|
||||
{0, 0 * 16, 12 * 8, 16},//back button is long enough to cover the title area to make it easier to touch
|
||||
&bitmap_icon_previous,
|
||||
Color::white(),
|
||||
Color::dark_grey()};
|
||||
@@ -290,10 +291,15 @@ namespace ui
|
||||
const Rect parent_rect);
|
||||
|
||||
Context &context() const override;
|
||||
void toggle_overlay();
|
||||
void paint_overlay();
|
||||
|
||||
private:
|
||||
bool overlay_active {false};
|
||||
|
||||
SystemStatusView status_view{navigation_view};
|
||||
InformationView info_view{navigation_view};
|
||||
DfuMenu overlay{navigation_view};
|
||||
NavigationView navigation_view{};
|
||||
Context &context_;
|
||||
};
|
||||
|
||||
@@ -90,8 +90,6 @@ set(CSRC
|
||||
${PORTSRC}
|
||||
${KERNSRC}
|
||||
${TESTSRC}
|
||||
${HALSRC}
|
||||
${PLATFORMSRC}
|
||||
${BOARDSRC}
|
||||
)
|
||||
|
||||
@@ -141,6 +139,7 @@ set(CPPSRC
|
||||
${COMMON}/chibios_cpp.cpp
|
||||
debug.cpp
|
||||
${COMMON}/gcc.cpp
|
||||
${COMMON}/performance_counter.cpp
|
||||
tone_gen.cpp
|
||||
)
|
||||
|
||||
@@ -189,7 +188,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 +261,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 +273,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 +505,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
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "baseband_dma.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
@@ -103,8 +104,12 @@ static constexpr auto& gpdma_channel_sgpio = gpdma::channels[portapack::sgpio_gp
|
||||
|
||||
static ThreadWait thread_wait;
|
||||
|
||||
volatile uint32_t buffer_transfered = 0;
|
||||
volatile uint32_t buffer_handled = 0;
|
||||
|
||||
static void transfer_complete() {
|
||||
const auto next_lli_index = gpdma_channel_sgpio.next_lli() - &lli_loop[0];
|
||||
buffer_transfered++;
|
||||
thread_wait.wake_from_interrupt(next_lli_index);
|
||||
}
|
||||
|
||||
@@ -158,6 +163,10 @@ void disable() {
|
||||
|
||||
baseband::buffer_t wait_for_buffer() {
|
||||
const auto next_index = thread_wait.sleep();
|
||||
buffer_handled++;
|
||||
|
||||
auto buffer_missed = buffer_transfered - buffer_handled;
|
||||
shared_memory.m4_buffer_missed = buffer_missed;
|
||||
|
||||
if( next_index >= 0 ) {
|
||||
const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask;
|
||||
|
||||
@@ -508,6 +508,8 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief System tick event hook.
|
||||
* @details This hook is invoked in the system tick handler immediately
|
||||
@@ -516,6 +518,8 @@
|
||||
#if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__)
|
||||
#define SYSTEM_TICK_EVENT_HOOK() { \
|
||||
/* System tick event code here.*/ \
|
||||
extern void update_performance_counters(); \
|
||||
update_performance_counters(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <hal.h>
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "performance_counter.hpp"
|
||||
|
||||
void write_m4_panic_msg(const char *panic_message, struct extctx *ctxp) {
|
||||
if (ctxp == nullptr) {
|
||||
@@ -116,5 +117,28 @@ CH_IRQ_HANDLER(HardFaultVector) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void update_performance_counters() {
|
||||
auto performance_counter_active = shared_memory.request_m4_performance_counter;
|
||||
if (performance_counter_active == 0x00)
|
||||
return;
|
||||
|
||||
static bool last_paint_state = false;
|
||||
if ((((chTimeNow()>>10) & 0x01) == 0x01) == last_paint_state)
|
||||
return;
|
||||
|
||||
// Idle thread state is sometimes unuseable
|
||||
if (chThdGetTicks(chSysGetIdleThread()) > 0x10000000)
|
||||
return;
|
||||
|
||||
last_paint_state = !last_paint_state;
|
||||
|
||||
auto utilisation = get_cpu_utilisation_in_percent();
|
||||
auto free_stack = (uint32_t)get_free_stack_space();
|
||||
auto free_heap = chCoreStatus();
|
||||
|
||||
shared_memory.m4_cpu_usage = utilisation;
|
||||
shared_memory.m4_stack_usage = free_stack;
|
||||
shared_memory.m4_heap_usage = free_heap;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -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__*/
|
||||
|
||||
@@ -83,6 +83,12 @@ SSB::SSB() : hilbert() {
|
||||
}
|
||||
|
||||
void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer,TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
|
||||
//unused
|
||||
(void)configured_in ;
|
||||
(void)new_beep_index ;
|
||||
(void)new_beep_timer ;
|
||||
(void)new_txprogress_message ;
|
||||
|
||||
// No way to activate correctly the roger beep in this option, Maybe not enough M4 CPU power , Let's block roger beep in SSB selection by now .
|
||||
int32_t sample = 0;
|
||||
int8_t re = 0, im = 0;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "event_m4.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
@@ -120,3 +121,4 @@ void EventDispatcher::handle_spectrum() {
|
||||
const UpdateSpectrumMessage message;
|
||||
baseband_processor->on_message(&message);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,6 +87,7 @@ void ERTProcessor::consume_symbol(
|
||||
) {
|
||||
const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
||||
scm_builder.execute(sliced_symbol);
|
||||
scmplus_builder.execute(sliced_symbol);
|
||||
idm_builder.execute(sliced_symbol);
|
||||
}
|
||||
|
||||
@@ -97,6 +98,13 @@ void ERTProcessor::scm_handler(
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
|
||||
void ERTProcessor::scmplus_handler(
|
||||
const baseband::Packet& packet
|
||||
) {
|
||||
const ERTPacketMessage message { ert::Packet::Type::SCMPLUS, packet };
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
|
||||
void ERTProcessor::idm_handler(
|
||||
const baseband::Packet& packet
|
||||
) {
|
||||
|
||||
@@ -44,10 +44,14 @@ constexpr uint64_t scm_preamble_and_sync_manchester { 0b101010101001011001100110
|
||||
constexpr size_t scm_preamble_and_sync_length { 42 - 10 };
|
||||
constexpr size_t scm_payload_length_max { 150 };
|
||||
|
||||
// ''.join(['%d%d' % (c, 1-c) for c in map(int, bin(0x16a3)[2:].zfill(16))])
|
||||
constexpr uint64_t scmplus_preamble_and_sync_manchester { 0b01010110011010011001100101011010 };
|
||||
constexpr size_t scmplus_preamble_and_sync_length { 32 - 0 };
|
||||
constexpr size_t scmplus_payload_length_max { 224 };
|
||||
|
||||
// ''.join(['%d%d' % (c, 1-c) for c in map(int, bin(0x555516a3)[2:].zfill(32))])
|
||||
constexpr uint64_t idm_preamble_and_sync_manchester { 0b0110011001100110011001100110011001010110011010011001100101011010 };
|
||||
constexpr size_t idm_preamble_and_sync_length { 64 - 16 };
|
||||
|
||||
constexpr size_t idm_payload_length_max { 1408 };
|
||||
|
||||
class ERTProcessor : public BasebandProcessor {
|
||||
@@ -80,6 +84,15 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
PacketBuilder<BitPattern, NeverMatch, FixedLength> scmplus_builder {
|
||||
{ scmplus_preamble_and_sync_manchester, scmplus_preamble_and_sync_length, 1 },
|
||||
{ },
|
||||
{ scmplus_payload_length_max },
|
||||
[this](const baseband::Packet& packet) {
|
||||
this->scmplus_handler(packet);
|
||||
}
|
||||
};
|
||||
|
||||
PacketBuilder<BitPattern, NeverMatch, FixedLength> idm_builder {
|
||||
{ idm_preamble_and_sync_manchester, idm_preamble_and_sync_length, 1 },
|
||||
{ },
|
||||
@@ -91,6 +104,7 @@ private:
|
||||
|
||||
void consume_symbol(const float symbol);
|
||||
void scm_handler(const baseband::Packet& packet);
|
||||
void scmplus_handler(const baseband::Packet& packet);
|
||||
void idm_handler(const baseband::Packet& packet);
|
||||
|
||||
float sum_half_period[2];
|
||||
|
||||
@@ -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,49 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
void update_performance_counters() {}
|
||||
@@ -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__*/
|
||||
@@ -508,7 +508,7 @@ static const std::array<scu_setup_t, 26> pins_setup_portapack { {
|
||||
{ 2, 1, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* U0_RXD: PortaPack P2_1/ADDR */
|
||||
{ 2, 3, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* I2C1_SDA: PortaPack P2_3/LCD_TE */
|
||||
{ 2, 4, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* I2C1_SCL: PortaPack P2_4/LCD_RDX */
|
||||
{ 2, 8, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* P2_8: 10K PD, BOOT2, DFU switch, PortaPack P2_8/<unused> */
|
||||
{ 2, 8, scu_config_normal_drive_t { .mode=1, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=1 } }, /* P2_8: 10K PD, BOOT2, DFU switch, PortaPack P2_8/<unused> */
|
||||
{ 2, 9, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* P2_9: 10K PD, BOOT3, PortaPack P2_9/LCD_WRX */
|
||||
{ 2, 13, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* P2_13: PortaPack P2_13/DIR */
|
||||
{ 7, 0, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_8: PortaPack GPIO3_8(IO) */
|
||||
|
||||
@@ -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__;
|
||||
|
||||
@@ -47,6 +47,9 @@ ID Packet::id() const {
|
||||
const auto lsb = reader_.read(35, 24);
|
||||
return (msb << 24) | lsb;
|
||||
}
|
||||
if( type() == Type::SCMPLUS ) {
|
||||
return reader_.read(2 * 8, 32);
|
||||
}
|
||||
if( type() == Type::IDM ) {
|
||||
return reader_.read(5 * 8, 32);
|
||||
}
|
||||
@@ -57,6 +60,9 @@ Consumption Packet::consumption() const {
|
||||
if( type() == Type::SCM ) {
|
||||
return reader_.read(11, 24);
|
||||
}
|
||||
if( type() == Type::SCMPLUS ) {
|
||||
return reader_.read(6 * 8, 32);
|
||||
}
|
||||
if( type() == Type::IDM ) {
|
||||
return reader_.read(25 * 8, 32);
|
||||
}
|
||||
@@ -67,6 +73,9 @@ CommodityType Packet::commodity_type() const {
|
||||
if( type() == Type::SCM ) {
|
||||
return reader_.read(5, 4);
|
||||
}
|
||||
if( type() == Type::SCMPLUS ) {
|
||||
return reader_.read(1 * 8 + 4, 4);
|
||||
}
|
||||
if( type() == Type::IDM ) {
|
||||
return reader_.read(4 * 8 + 4, 4);
|
||||
}
|
||||
@@ -80,7 +89,8 @@ FormattedSymbols Packet::symbols_formatted() const {
|
||||
bool Packet::crc_ok() const {
|
||||
switch(type()) {
|
||||
case Type::SCM: return crc_ok_scm();
|
||||
case Type::IDM: return crc_ok_idm();
|
||||
case Type::SCMPLUS:
|
||||
case Type::IDM: return crc_ok_ccitt();
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
@@ -95,7 +105,7 @@ bool Packet::crc_ok_scm() const {
|
||||
return ert_bch.checksum() == 0x0000;
|
||||
}
|
||||
|
||||
bool Packet::crc_ok_idm() const {
|
||||
bool Packet::crc_ok_ccitt() const {
|
||||
CRC<16> ert_crc_ccitt { 0x1021, 0xffff, 0x1d0f };
|
||||
for(size_t i=0; i<length(); i+=8) {
|
||||
ert_crc_ccitt.process_byte(reader_.read(i, 8));
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
Unknown = 0,
|
||||
IDM = 1,
|
||||
SCM = 2,
|
||||
SCMPLUS = 3,
|
||||
};
|
||||
|
||||
Packet(
|
||||
@@ -80,7 +81,7 @@ private:
|
||||
const Reader reader_;
|
||||
const Type type_;
|
||||
|
||||
bool crc_ok_idm() const;
|
||||
bool crc_ok_ccitt() const;
|
||||
bool crc_ok_scm() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 "performance_counter.hpp"
|
||||
#include "ch.h"
|
||||
|
||||
uint8_t get_cpu_utilisation_in_percent() {
|
||||
static systime_t last_time = 0;
|
||||
static systime_t last_idle_ticks = 0;
|
||||
|
||||
auto now = chTimeNow();
|
||||
auto idle_ticks = chThdGetTicks(chSysGetIdleThread());
|
||||
|
||||
if (last_time == 0) {
|
||||
last_time = now;
|
||||
last_idle_ticks = idle_ticks;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t time_elapsed = now - last_time;
|
||||
int32_t idle_elapsed = idle_ticks - last_idle_ticks;
|
||||
|
||||
int32_t working_ticks = time_elapsed - idle_elapsed;
|
||||
|
||||
if (working_ticks < 0)
|
||||
working_ticks = 0;
|
||||
|
||||
auto utilisation = working_ticks * 100 / time_elapsed;
|
||||
|
||||
last_time = now;
|
||||
last_idle_ticks = idle_ticks;
|
||||
|
||||
if (utilisation > 100) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
return (uint8_t) utilisation;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 __PERFORMANCE_COUNTER_H__
|
||||
#define __PERFORMANCE_COUNTER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t get_cpu_utilisation_in_percent();
|
||||
|
||||
#endif /* __PERFORMANCE_COUNTER_H__ */
|
||||
@@ -36,7 +36,7 @@ namespace portapack {
|
||||
constexpr GPIO gpio_io_stbx = gpio[GPIO5_0]; /* P2_0 */
|
||||
constexpr GPIO gpio_addr = gpio[GPIO5_1]; /* P2_1 */
|
||||
constexpr GPIO gpio_lcd_te = gpio[GPIO5_3]; /* P2_3 */
|
||||
constexpr GPIO gpio_unused = gpio[GPIO5_7]; /* P2_8 */
|
||||
constexpr GPIO gpio_dfu = gpio[GPIO5_7]; /* P2_8 */
|
||||
constexpr GPIO gpio_lcd_rdx = gpio[GPIO5_4]; /* P2_4 */
|
||||
constexpr GPIO gpio_lcd_wrx = gpio[GPIO1_10]; /* P2_9 */
|
||||
constexpr GPIO gpio_dir = gpio[GPIO1_13]; /* P2_13 */
|
||||
|
||||
@@ -110,7 +110,8 @@ uint32_t IO::io_update(const TouchPinsConfig write_value) {
|
||||
}
|
||||
gpio_addr.write(addr);
|
||||
|
||||
return switches_raw;
|
||||
auto dfu_btn = portapack::io.dfu_read() & 0x01;
|
||||
return (switches_raw & 0x7f) | (dfu_btn << 7);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -214,6 +214,10 @@ public:
|
||||
return gpio_rot_a.read();
|
||||
}
|
||||
|
||||
uint32_t dfu_read() {
|
||||
return gpio_rot_b.read();
|
||||
}
|
||||
|
||||
private:
|
||||
const GPIO gpio_dir;
|
||||
const GPIO gpio_lcd_rdx;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,187 +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_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 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_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);
|
||||
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__*/
|
||||
|
||||
@@ -64,6 +64,12 @@ struct SharedMemory {
|
||||
JammerChannel jammer_channels[24];
|
||||
uint8_t data[512];
|
||||
} bb_data { { { { 0, 0 } }, 0, { 0 } } };
|
||||
|
||||
uint8_t volatile request_m4_performance_counter{ 0 };
|
||||
uint8_t volatile m4_cpu_usage{ 0 };
|
||||
uint16_t volatile m4_stack_usage{ 0 };
|
||||
uint16_t volatile m4_heap_usage{ 0 };
|
||||
uint16_t volatile m4_buffer_missed{ 0 };
|
||||
};
|
||||
|
||||
extern SharedMemory& shared_memory;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -100,8 +100,8 @@ Optional<Reading> Packet::reading_ook_8k4_schrader() const {
|
||||
* Preamble: 01*40
|
||||
* System ID: 01100101, ??*20 (not really sure what this data is)
|
||||
* ID: 32 Manchester symbols
|
||||
* Value: 8 Manchester symbols (temperature?)
|
||||
* Value: 8 Manchester symbols (pressure?)
|
||||
* Value: 8 Manchester symbols (pressure)
|
||||
* Value: 8 Manchester symbols (temperature)
|
||||
* Checksum: 8 Manchester symbols (uint8_t sum of bytes starting with system ID)
|
||||
*/
|
||||
/* NOTE: First four bits of packet are consumed in preamble detection.
|
||||
@@ -123,8 +123,8 @@ Optional<Reading> Packet::reading_ook_8k4_schrader() const {
|
||||
return Reading {
|
||||
Reading::Type::GMC_96,
|
||||
(uint32_t)id,
|
||||
Pressure { static_cast<int>(value_1) * 4 / 3 },
|
||||
Temperature { static_cast<int>(value_0) - 56 }
|
||||
Pressure { static_cast<int>(value_0) * 11 / 4 },
|
||||
Temperature { static_cast<int>(value_1) - 61 }
|
||||
};
|
||||
} else {
|
||||
return { };
|
||||
|
||||
@@ -325,7 +325,8 @@ enum class KeyEvent {
|
||||
Down = 2,
|
||||
Up = 3,
|
||||
Select = 4,
|
||||
Back = 5, /* Left and Up together */
|
||||
Dfu = 5,
|
||||
Back = 6, /* Left and Up together */
|
||||
};
|
||||
|
||||
using EncoderEvent = int32_t;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -12,4 +12,6 @@ pause
|
||||
echo.
|
||||
hackrf_update.exe portapack-h1_h2-mayhem.bin
|
||||
echo.
|
||||
echo If your device never boot after flashing, please refer to https://github.com/eried/portapack-mayhem/wiki/Won't-boot
|
||||
echo.
|
||||
pause
|
||||
|
||||
+1
-1
Submodule hackrf updated: ae71cb5b7a...ebe1ca003a
@@ -0,0 +1,93 @@
|
||||
# Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.1.3)
|
||||
set(CMAKE_TOOLCHAIN_FILE ../toolchain-arm-cortex-m.cmake)
|
||||
|
||||
project(hackrf_usb C)
|
||||
|
||||
include(../hackrf/firmware/hackrf-common.cmake)
|
||||
|
||||
set(PATH_HACKRF_USB ../hackrf/firmware/hackrf_usb)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PATH_HACKRF_CPLD_DATA_C}
|
||||
COMMAND ${PATH_CPLD_BITSTREAM_TOOL} --xsvf ${PATH_HACKRF_CPLD_XSVF} --hackrf-data ${PATH_HACKRF_CPLD_DATA_C}
|
||||
DEPENDS ${PATH_CPLD_BITSTREAM_TOOL} ${PATH_HACKRF_CPLD_XSVF}
|
||||
)
|
||||
|
||||
set(SRC_M4
|
||||
${PATH_HACKRF_USB}/hackrf_usb.c
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/tuning.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/streaming.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/usb.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_request.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_standard_request.c"
|
||||
${PATH_HACKRF_USB}/usb_descriptor.c
|
||||
${PATH_HACKRF_USB}/usb_device.c
|
||||
${PATH_HACKRF_USB}/usb_endpoint.c
|
||||
${PATH_HACKRF_USB}/usb_api_board_info.c
|
||||
${PATH_HACKRF_USB}/usb_api_cpld.c
|
||||
${PATH_HACKRF_USB}/usb_api_m0_state.c
|
||||
${PATH_HACKRF_USB}/usb_api_register.c
|
||||
${PATH_HACKRF_USB}/usb_api_spiflash.c
|
||||
${PATH_HACKRF_USB}/usb_api_transceiver.c
|
||||
${PATH_HACKRF_USB}/usb_api_operacake.c
|
||||
${PATH_HACKRF_USB}/usb_api_sweep.c
|
||||
${PATH_HACKRF_USB}/usb_api_ui.c
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/cpld_xc2c.c"
|
||||
"${PATH_HACKRF_CPLD_DATA_C}"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/ports.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/crc.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rom_iap.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/operacake.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/operacake_sctimer.c"
|
||||
)
|
||||
|
||||
set(SRC_M0 ${PATH_HACKRF_USB}/sgpio_m0.s)
|
||||
|
||||
if(BOARD STREQUAL "HACKRF_ONE")
|
||||
SET(SRC_M4
|
||||
${SRC_M4}
|
||||
portapack.c
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/ui_portapack.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BOARD STREQUAL "RAD1O")
|
||||
SET(SRC_M4
|
||||
${SRC_M4}
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/display.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/print.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/render.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/decoder.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/smallfonts.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/draw.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/ubuntu18.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/ui_rad1o.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
DeclareTargets()
|
||||
@@ -0,0 +1,640 @@
|
||||
/*
|
||||
* Copyright 2018-2022 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2018 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 "portapack.h"
|
||||
|
||||
#include "hackrf_core.h"
|
||||
#include "gpio_lpc.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
|
||||
static void portapack_sleep_milliseconds(const uint32_t milliseconds)
|
||||
{
|
||||
/* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */
|
||||
delay(milliseconds * 40800);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static struct gpio_t gpio_io_stbx = GPIO(5, 0); /* P2_0 */
|
||||
static struct gpio_t gpio_addr = GPIO(5, 1); /* P2_1 */
|
||||
__attribute__((unused))
|
||||
static struct gpio_t gpio_lcd_te = GPIO(5, 3); /* P2_3 */
|
||||
__attribute__((unused))
|
||||
static struct gpio_t gpio_unused = GPIO(5, 7); /* P2_8 */
|
||||
static struct gpio_t gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */
|
||||
static struct gpio_t gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */
|
||||
static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */
|
||||
|
||||
// clang-format on
|
||||
|
||||
typedef struct portapack_if_t {
|
||||
gpio_t gpio_dir;
|
||||
gpio_t gpio_lcd_rdx;
|
||||
gpio_t gpio_lcd_wrx;
|
||||
gpio_t gpio_io_stbx;
|
||||
gpio_t gpio_addr;
|
||||
gpio_port_t* const gpio_port_data;
|
||||
uint8_t io_reg;
|
||||
} portapack_if_t;
|
||||
|
||||
static portapack_if_t portapack_if = {
|
||||
.gpio_dir = &gpio_dir,
|
||||
.gpio_lcd_rdx = &gpio_lcd_rdx,
|
||||
.gpio_lcd_wrx = &gpio_lcd_wrx,
|
||||
.gpio_io_stbx = &gpio_io_stbx,
|
||||
.gpio_addr = &gpio_addr,
|
||||
.gpio_port_data = GPIO_LPC_PORT(3),
|
||||
.io_reg = 0x03,
|
||||
};
|
||||
|
||||
/* NOTE: Code below assumes the shift value is "8". */
|
||||
#define GPIO_DATA_SHIFT (8)
|
||||
static const uint32_t gpio_data_mask = 0xFFU << GPIO_DATA_SHIFT;
|
||||
|
||||
static void portapack_data_mask_set()
|
||||
{
|
||||
portapack_if.gpio_port_data->mask = ~gpio_data_mask;
|
||||
}
|
||||
|
||||
static void portapack_data_write_low(const uint32_t value)
|
||||
{
|
||||
portapack_if.gpio_port_data->mpin = (value << GPIO_DATA_SHIFT);
|
||||
}
|
||||
|
||||
static void portapack_data_write_high(const uint32_t value)
|
||||
{
|
||||
/* NOTE: Assumes no other bits in the port are masked. */
|
||||
/* NOTE: Assumes that bits 15 through 8 are masked. */
|
||||
portapack_if.gpio_port_data->mpin = value;
|
||||
}
|
||||
|
||||
static void portapack_dir_read()
|
||||
{
|
||||
portapack_if.gpio_port_data->dir &= ~gpio_data_mask;
|
||||
gpio_set(portapack_if.gpio_dir);
|
||||
}
|
||||
|
||||
static void portapack_dir_write()
|
||||
{
|
||||
gpio_clear(portapack_if.gpio_dir);
|
||||
portapack_if.gpio_port_data->dir |= gpio_data_mask;
|
||||
/* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin
|
||||
* is also on port 3, and switches direction periodically...
|
||||
* Time to resort to bit-banding to enforce atomicity? But then, how
|
||||
* to change direction on eight bits efficiently? Or do I care, since
|
||||
* the PortaPack data bus shouldn't change direction too frequently?
|
||||
*/
|
||||
}
|
||||
|
||||
__attribute__((unused)) static void portapack_lcd_rd_assert()
|
||||
{
|
||||
gpio_clear(portapack_if.gpio_lcd_rdx);
|
||||
}
|
||||
|
||||
static void portapack_lcd_rd_deassert()
|
||||
{
|
||||
gpio_set(portapack_if.gpio_lcd_rdx);
|
||||
}
|
||||
|
||||
static void portapack_lcd_wr_assert()
|
||||
{
|
||||
gpio_clear(portapack_if.gpio_lcd_wrx);
|
||||
}
|
||||
|
||||
static void portapack_lcd_wr_deassert()
|
||||
{
|
||||
gpio_set(portapack_if.gpio_lcd_wrx);
|
||||
}
|
||||
|
||||
static void portapack_io_stb_assert()
|
||||
{
|
||||
gpio_clear(portapack_if.gpio_io_stbx);
|
||||
}
|
||||
|
||||
static void portapack_io_stb_deassert()
|
||||
{
|
||||
gpio_set(portapack_if.gpio_io_stbx);
|
||||
}
|
||||
|
||||
static void portapack_addr(const bool value)
|
||||
{
|
||||
gpio_write(portapack_if.gpio_addr, value);
|
||||
}
|
||||
|
||||
static void portapack_lcd_command(const uint32_t value)
|
||||
{
|
||||
portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */
|
||||
portapack_dir_write(); /* Turn around data bus, MCU->CPLD */
|
||||
portapack_addr(0); /* Indicate command */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
portapack_lcd_wr_assert(); /* Latch high byte */
|
||||
|
||||
portapack_data_write_low(value); /* Drive low byte (pass-through) */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
portapack_lcd_wr_deassert(); /* Complete write operation */
|
||||
|
||||
portapack_addr(1); /* Set up for data phase (most likely after a command) */
|
||||
}
|
||||
|
||||
static void portapack_lcd_write_data(const uint32_t value)
|
||||
{
|
||||
// NOTE: Assumes and DIR=0 and ADDR=1 from command phase.
|
||||
portapack_data_write_high(value); /* Drive high byte */
|
||||
__asm__("nop");
|
||||
portapack_lcd_wr_assert(); /* Latch high byte */
|
||||
|
||||
portapack_data_write_low(value); /* Drive low byte (pass-through) */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
portapack_lcd_wr_deassert(); /* Complete write operation */
|
||||
}
|
||||
|
||||
static void portapack_io_write(const bool address, const uint_fast16_t value)
|
||||
{
|
||||
portapack_data_write_low(value);
|
||||
portapack_dir_write();
|
||||
portapack_addr(address);
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
portapack_io_stb_assert();
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
portapack_io_stb_deassert();
|
||||
}
|
||||
|
||||
static void portapack_if_init()
|
||||
{
|
||||
portapack_data_mask_set();
|
||||
portapack_data_write_high(0);
|
||||
|
||||
portapack_dir_read();
|
||||
portapack_lcd_rd_deassert();
|
||||
portapack_lcd_wr_deassert();
|
||||
portapack_io_stb_deassert();
|
||||
portapack_addr(0);
|
||||
|
||||
gpio_output(portapack_if.gpio_dir);
|
||||
gpio_output(portapack_if.gpio_lcd_rdx);
|
||||
gpio_output(portapack_if.gpio_lcd_wrx);
|
||||
gpio_output(portapack_if.gpio_io_stbx);
|
||||
gpio_output(portapack_if.gpio_addr);
|
||||
/* gpio_input(portapack_if.gpio_rot_a); */
|
||||
/* gpio_input(portapack_if.gpio_rot_b); */
|
||||
|
||||
scu_pinmux(SCU_PINMUX_PP_D0, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
scu_pinmux(SCU_PINMUX_PP_D1, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
scu_pinmux(SCU_PINMUX_PP_D2, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
scu_pinmux(SCU_PINMUX_PP_D3, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
scu_pinmux(SCU_PINMUX_PP_D4, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
scu_pinmux(SCU_PINMUX_PP_D5, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
scu_pinmux(SCU_PINMUX_PP_D6, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
scu_pinmux(SCU_PINMUX_PP_D7, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
|
||||
|
||||
scu_pinmux(SCU_PINMUX_PP_DIR, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL);
|
||||
scu_pinmux(SCU_PINMUX_PP_LCD_RDX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL);
|
||||
scu_pinmux(SCU_PINMUX_PP_LCD_WRX, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL);
|
||||
scu_pinmux(SCU_PINMUX_PP_IO_STBX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL);
|
||||
scu_pinmux(SCU_PINMUX_PP_ADDR, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL);
|
||||
/* scu_pinmux(SCU_PINMUX_PP_LCD_TE, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */
|
||||
/* scu_pinmux(SCU_PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */
|
||||
}
|
||||
|
||||
static void portapack_lcd_reset_state(const bool active)
|
||||
{
|
||||
portapack_if.io_reg = (portapack_if.io_reg & 0xfe) | (active ? (1 << 0) : 0);
|
||||
portapack_io_write(1, portapack_if.io_reg);
|
||||
}
|
||||
|
||||
static void portapack_lcd_data_write_command_and_data(
|
||||
const uint_fast8_t command,
|
||||
const uint8_t* data,
|
||||
const size_t data_count)
|
||||
{
|
||||
portapack_lcd_command(command);
|
||||
for (size_t i = 0; i < data_count; i++) {
|
||||
portapack_lcd_write_data(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void portapack_lcd_sleep_out()
|
||||
{
|
||||
const uint8_t cmd_11[] = {};
|
||||
portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11));
|
||||
// "It will be necessary to wait 120msec after sending Sleep Out
|
||||
// command (when in Sleep In Mode) before Sleep In command can be
|
||||
// sent."
|
||||
portapack_sleep_milliseconds(120);
|
||||
}
|
||||
|
||||
static void portapack_lcd_display_on()
|
||||
{
|
||||
const uint8_t cmd_29[] = {};
|
||||
portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29));
|
||||
}
|
||||
|
||||
static void portapack_lcd_ramwr_start()
|
||||
{
|
||||
const uint8_t cmd_2c[] = {};
|
||||
portapack_lcd_data_write_command_and_data(0x2c, cmd_2c, ARRAY_SIZEOF(cmd_2c));
|
||||
}
|
||||
|
||||
static void portapack_lcd_set(
|
||||
const uint_fast8_t command,
|
||||
const uint_fast16_t start,
|
||||
const uint_fast16_t end)
|
||||
{
|
||||
const uint8_t data[] = {(start >> 8), (start & 0xff), (end >> 8), (end & 0xff)};
|
||||
portapack_lcd_data_write_command_and_data(command, data, ARRAY_SIZEOF(data));
|
||||
}
|
||||
|
||||
static void portapack_lcd_caset(
|
||||
const uint_fast16_t start_column,
|
||||
const uint_fast16_t end_column)
|
||||
{
|
||||
portapack_lcd_set(0x2a, start_column, end_column);
|
||||
}
|
||||
|
||||
static void portapack_lcd_paset(
|
||||
const uint_fast16_t start_page,
|
||||
const uint_fast16_t end_page)
|
||||
{
|
||||
portapack_lcd_set(0x2b, start_page, end_page);
|
||||
}
|
||||
|
||||
static void portapack_lcd_start_ram_write(const ui_rect_t rect)
|
||||
{
|
||||
portapack_lcd_caset(rect.point.x, rect.point.x + rect.size.width - 1);
|
||||
portapack_lcd_paset(rect.point.y, rect.point.y + rect.size.height - 1);
|
||||
portapack_lcd_ramwr_start();
|
||||
}
|
||||
|
||||
static void portapack_lcd_write_pixel(const ui_color_t pixel)
|
||||
{
|
||||
portapack_lcd_write_data(pixel.v);
|
||||
}
|
||||
|
||||
static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n)
|
||||
{
|
||||
while (n--) {
|
||||
portapack_lcd_write_data(c.v);
|
||||
}
|
||||
}
|
||||
|
||||
static void portapack_lcd_wake()
|
||||
{
|
||||
portapack_lcd_sleep_out();
|
||||
portapack_lcd_display_on();
|
||||
}
|
||||
|
||||
static void portapack_lcd_reset()
|
||||
{
|
||||
portapack_lcd_reset_state(false);
|
||||
portapack_sleep_milliseconds(1);
|
||||
portapack_lcd_reset_state(true);
|
||||
portapack_sleep_milliseconds(10);
|
||||
portapack_lcd_reset_state(false);
|
||||
portapack_sleep_milliseconds(120);
|
||||
}
|
||||
|
||||
static void portapack_lcd_init()
|
||||
{
|
||||
// LCDs are configured for IM[2:0] = 001
|
||||
// 8080-I system, 16-bit parallel bus
|
||||
|
||||
//
|
||||
// 0x3a: DBI[2:0] = 101
|
||||
// MDT[1:0] = XX (if not in 18-bit mode, right?)
|
||||
|
||||
// Power control B
|
||||
// 0
|
||||
// PCEQ=1, DRV_ena=0, Power control=3
|
||||
const uint8_t cmd_cf[] = {0x00, 0xD9, 0x30};
|
||||
portapack_lcd_data_write_command_and_data(0xCF, cmd_cf, ARRAY_SIZEOF(cmd_cf));
|
||||
|
||||
// Power on sequence control
|
||||
const uint8_t cmd_ed[] = {0x64, 0x03, 0x12, 0x81};
|
||||
portapack_lcd_data_write_command_and_data(0xED, cmd_ed, ARRAY_SIZEOF(cmd_ed));
|
||||
|
||||
// Driver timing control A
|
||||
const uint8_t cmd_e8[] = {0x85, 0x10, 0x78};
|
||||
portapack_lcd_data_write_command_and_data(0xE8, cmd_e8, ARRAY_SIZEOF(cmd_e8));
|
||||
|
||||
// Power control A
|
||||
const uint8_t cmd_cb[] = {0x39, 0x2C, 0x00, 0x34, 0x02};
|
||||
portapack_lcd_data_write_command_and_data(0xCB, cmd_cb, ARRAY_SIZEOF(cmd_cb));
|
||||
|
||||
// Pump ratio control
|
||||
const uint8_t cmd_f7[] = {0x20};
|
||||
portapack_lcd_data_write_command_and_data(0xF7, cmd_f7, ARRAY_SIZEOF(cmd_f7));
|
||||
|
||||
// Driver timing control B
|
||||
const uint8_t cmd_ea[] = {0x00, 0x00};
|
||||
portapack_lcd_data_write_command_and_data(0xEA, cmd_ea, ARRAY_SIZEOF(cmd_ea));
|
||||
|
||||
const uint8_t cmd_b1[] = {0x00, 0x1B};
|
||||
portapack_lcd_data_write_command_and_data(0xB1, cmd_b1, ARRAY_SIZEOF(cmd_b1));
|
||||
|
||||
// Blanking Porch Control
|
||||
// VFP = 0b0000010 = 2 (number of HSYNC of vertical front porch)
|
||||
// VBP = 0b0000010 = 2 (number of HSYNC of vertical back porch)
|
||||
// HFP = 0b0001010 = 10 (number of DOTCLOCK of horizontal front porch)
|
||||
// HBP = 0b0010100 = 20 (number of DOTCLOCK of horizontal back porch)
|
||||
const uint8_t cmd_b5[] = {0x02, 0x02, 0x0a, 0x14};
|
||||
portapack_lcd_data_write_command_and_data(0xB5, cmd_b5, ARRAY_SIZEOF(cmd_b5));
|
||||
|
||||
// Display Function Control
|
||||
// PT[1:0] = 0b10
|
||||
// PTG[1:0] = 0b10
|
||||
// ISC[3:0] = 0b0010 (scan cycle interval of gate driver: 5 frames)
|
||||
// SM = 0 (gate driver pin arrangement in combination with GS)
|
||||
// SS = 1 (source output scan direction S720 -> S1)
|
||||
// GS = 0 (gate output scan direction G1 -> G320)
|
||||
// REV = 1 (normally white)
|
||||
// NL = 0b100111 (default)
|
||||
// PCDIV = 0b000000 (default?)
|
||||
const uint8_t cmd_b6[] = {0x0A, 0xA2, 0x27, 0x00};
|
||||
portapack_lcd_data_write_command_and_data(0xB6, cmd_b6, ARRAY_SIZEOF(cmd_b6));
|
||||
|
||||
// Power Control 1
|
||||
//VRH[5:0]
|
||||
const uint8_t cmd_c0[] = {0x1B};
|
||||
portapack_lcd_data_write_command_and_data(0xC0, cmd_c0, ARRAY_SIZEOF(cmd_c0));
|
||||
|
||||
// Power Control 2
|
||||
//SAP[2:0];BT[3:0]
|
||||
const uint8_t cmd_c1[] = {0x12};
|
||||
portapack_lcd_data_write_command_and_data(0xC1, cmd_c1, ARRAY_SIZEOF(cmd_c1));
|
||||
|
||||
// VCOM Control 1
|
||||
const uint8_t cmd_c5[] = {0x32, 0x3C};
|
||||
portapack_lcd_data_write_command_and_data(0xC5, cmd_c5, ARRAY_SIZEOF(cmd_c5));
|
||||
|
||||
// VCOM Control 2
|
||||
const uint8_t cmd_c7[] = {0x9B};
|
||||
portapack_lcd_data_write_command_and_data(0xC7, cmd_c7, ARRAY_SIZEOF(cmd_c7));
|
||||
|
||||
// Memory Access Control
|
||||
// Invert X and Y memory access order, so upper-left of
|
||||
// screen is (0,0) when writing to display.
|
||||
const uint8_t cmd_36[] = {
|
||||
(1 << 7) | // MY=1
|
||||
(1 << 6) | // MX=1
|
||||
(0 << 5) | // MV=0
|
||||
(1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic
|
||||
(1 << 3) // BGR=1: For Kingtech LCD, BGR filter.
|
||||
};
|
||||
portapack_lcd_data_write_command_and_data(0x36, cmd_36, ARRAY_SIZEOF(cmd_36));
|
||||
|
||||
// COLMOD: Pixel Format Set
|
||||
// DPI=101 (16 bits/pixel), DBI=101 (16 bits/pixel)
|
||||
const uint8_t cmd_3a[] = {0x55};
|
||||
portapack_lcd_data_write_command_and_data(0x3A, cmd_3a, ARRAY_SIZEOF(cmd_3a));
|
||||
|
||||
//portapack_lcd_data_write_command_and_data(0xF6, { 0x01, 0x30 });
|
||||
// WEMODE=1 (reset column and page number on overflow)
|
||||
// MDT[1:0]
|
||||
// EPF[1:0]=00 (use channel MSB for LSB)
|
||||
// RIM=0 (If COLMOD[6:4]=101 (65k color), 16-bit RGB interface (1 transfer/pixel))
|
||||
// RM=0 (system interface/VSYNC interface)
|
||||
// DM[1:0]=00 (internal clock operation)
|
||||
// ENDIAN=0 (doesn't matter with 16-bit interface)
|
||||
const uint8_t cmd_f6[] = {0x01, 0x30, 0x00};
|
||||
portapack_lcd_data_write_command_and_data(0xF6, cmd_f6, ARRAY_SIZEOF(cmd_f6));
|
||||
|
||||
// 3Gamma Function Disable
|
||||
const uint8_t cmd_f2[] = {0x00};
|
||||
portapack_lcd_data_write_command_and_data(0xF2, cmd_f2, ARRAY_SIZEOF(cmd_f2));
|
||||
|
||||
// Gamma curve selected
|
||||
const uint8_t cmd_26[] = {0x01};
|
||||
portapack_lcd_data_write_command_and_data(0x26, cmd_26, ARRAY_SIZEOF(cmd_26));
|
||||
|
||||
// Set Gamma
|
||||
const uint8_t cmd_e0[] = {
|
||||
0x0F,
|
||||
0x1D,
|
||||
0x19,
|
||||
0x0E,
|
||||
0x10,
|
||||
0x07,
|
||||
0x4C,
|
||||
0x63,
|
||||
0x3F,
|
||||
0x03,
|
||||
0x0D,
|
||||
0x00,
|
||||
0x26,
|
||||
0x24,
|
||||
0x04};
|
||||
portapack_lcd_data_write_command_and_data(0xE0, cmd_e0, ARRAY_SIZEOF(cmd_e0));
|
||||
|
||||
// Set Gamma
|
||||
const uint8_t cmd_e1[] = {
|
||||
0x00,
|
||||
0x1C,
|
||||
0x1F,
|
||||
0x02,
|
||||
0x0F,
|
||||
0x03,
|
||||
0x35,
|
||||
0x25,
|
||||
0x47,
|
||||
0x04,
|
||||
0x0C,
|
||||
0x0B,
|
||||
0x29,
|
||||
0x2F,
|
||||
0x05};
|
||||
portapack_lcd_data_write_command_and_data(0xE1, cmd_e1, ARRAY_SIZEOF(cmd_e1));
|
||||
|
||||
portapack_lcd_wake();
|
||||
|
||||
// Turn on Tearing Effect Line (TE) output signal.
|
||||
const uint8_t cmd_35[] = {0b00000000};
|
||||
portapack_lcd_data_write_command_and_data(0x35, cmd_35, ARRAY_SIZEOF(cmd_35));
|
||||
}
|
||||
|
||||
void portapack_backlight(const bool on)
|
||||
{
|
||||
portapack_if.io_reg = (portapack_if.io_reg & 0x7f) | (on ? (1 << 7) : 0);
|
||||
portapack_io_write(1, portapack_if.io_reg);
|
||||
}
|
||||
|
||||
void portapack_reference_oscillator(const bool on)
|
||||
{
|
||||
const uint8_t mask = 1 << 6;
|
||||
portapack_if.io_reg = (portapack_if.io_reg & ~mask) | (on ? mask : 0);
|
||||
portapack_io_write(1, portapack_if.io_reg);
|
||||
}
|
||||
|
||||
void portapack_fill_rectangle(const ui_rect_t rect, const ui_color_t color)
|
||||
{
|
||||
portapack_lcd_start_ram_write(rect);
|
||||
portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height);
|
||||
}
|
||||
|
||||
void portapack_clear_display(const ui_color_t color)
|
||||
{
|
||||
const ui_rect_t rect_screen = {{0, 0}, {240, 320}};
|
||||
portapack_fill_rectangle(rect_screen, color);
|
||||
}
|
||||
|
||||
void portapack_draw_bitmap(
|
||||
const ui_point_t point,
|
||||
const ui_bitmap_t bitmap,
|
||||
const ui_color_t foreground,
|
||||
const ui_color_t background)
|
||||
{
|
||||
const ui_rect_t rect = {.point = point, .size = bitmap.size};
|
||||
|
||||
portapack_lcd_start_ram_write(rect);
|
||||
|
||||
const size_t count = bitmap.size.width * bitmap.size.height;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const uint8_t pixel = bitmap.data[i >> 3] & (1U << (i & 0x7));
|
||||
portapack_lcd_write_pixel(pixel ? foreground : background);
|
||||
}
|
||||
}
|
||||
|
||||
ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c)
|
||||
{
|
||||
if (c >= font->c_start) {
|
||||
const uint_fast8_t index = c - font->c_start;
|
||||
if (index < font->c_count) {
|
||||
const ui_bitmap_t bitmap = {
|
||||
.size = font->glyph_size,
|
||||
.data = &font->data[index * font->data_stride]};
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
const ui_bitmap_t bitmap = {
|
||||
.size = font->glyph_size,
|
||||
.data = font->data,
|
||||
};
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static bool jtag_pp_tck(const bool tms_value)
|
||||
{
|
||||
gpio_write(jtag_cpld.gpio->gpio_pp_tms, tms_value);
|
||||
|
||||
// 8 ns TMS/TDI to TCK setup
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
|
||||
gpio_set(jtag_cpld.gpio->gpio_tck);
|
||||
|
||||
// 15 ns TCK to TMS/TDI hold time
|
||||
// 20 ns TCK high time
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
|
||||
gpio_clear(jtag_cpld.gpio->gpio_tck);
|
||||
|
||||
// 20 ns TCK low time
|
||||
// 25 ns TCK falling edge to TDO valid
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
|
||||
return gpio_read(jtag_cpld.gpio->gpio_pp_tdo);
|
||||
}
|
||||
|
||||
static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
size_t bit_in_index = count - 1;
|
||||
size_t bit_out_index = 0;
|
||||
while (bit_out_index < count) {
|
||||
const uint32_t tdo = jtag_pp_tck((tms_bits >> bit_in_index) & 1) & 1;
|
||||
result |= (tdo << bit_out_index);
|
||||
|
||||
bit_in_index--;
|
||||
bit_out_index++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t jtag_pp_idcode(void)
|
||||
{
|
||||
cpld_jtag_take(&jtag_cpld);
|
||||
|
||||
/* TODO: Check if PortaPack TMS is floating or driven by an external device. */
|
||||
gpio_output(jtag_cpld.gpio->gpio_pp_tms);
|
||||
|
||||
/* Test-Logic/Reset -> Run-Test/Idle -> Select-DR/Scan -> Capture-DR */
|
||||
jtag_pp_shift(0b11111010, 8);
|
||||
|
||||
/* Shift-DR */
|
||||
const uint32_t idcode = jtag_pp_shift(0, 32);
|
||||
|
||||
/* Exit1-DR -> Update-DR -> Run-Test/Idle -> ... -> Test-Logic/Reset */
|
||||
jtag_pp_shift(0b11011111, 8);
|
||||
|
||||
cpld_jtag_release(&jtag_cpld);
|
||||
|
||||
return idcode;
|
||||
}
|
||||
|
||||
static bool portapack_detect(void)
|
||||
{
|
||||
const uint32_t idcode = jtag_pp_idcode();
|
||||
return idcode == 0x00025610 || idcode == 0x020A50DD;
|
||||
}
|
||||
|
||||
static const portapack_t portapack_instance = {};
|
||||
|
||||
static const portapack_t* portapack_pointer = NULL;
|
||||
|
||||
const portapack_t* portapack(void)
|
||||
{
|
||||
return portapack_pointer;
|
||||
}
|
||||
|
||||
void portapack_init(void)
|
||||
{
|
||||
if (portapack_detect()) {
|
||||
portapack_if_init();
|
||||
portapack_lcd_reset();
|
||||
portapack_lcd_init();
|
||||
portapack_pointer = &portapack_instance;
|
||||
} else {
|
||||
portapack_pointer = NULL;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,986 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
/* Generated by software containing ST-Developer
|
||||
* from STEP Tools, Inc. (www.steptools.com)
|
||||
*/
|
||||
|
||||
FILE_DESCRIPTION(
|
||||
/* description */ (''),
|
||||
/* implementation_level */ '2;1');
|
||||
|
||||
FILE_NAME(
|
||||
/* name */
|
||||
'D:\\OneDrive\\Projects\\RepRap\\HackRF\\REVISITED\\revisited_support.
|
||||
stp',
|
||||
/* time_stamp */ '2023-04-11T09:54:07+02:00',
|
||||
/* author */ ('erwin'),
|
||||
/* organization */ (''),
|
||||
/* preprocessor_version */ 'ST-DEVELOPER v18.1',
|
||||
/* originating_system */ 'Autodesk Inventor 2022',
|
||||
/* authorisation */ '');
|
||||
|
||||
FILE_SCHEMA (('AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }'));
|
||||
ENDSEC;
|
||||
|
||||
DATA;
|
||||
#10=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#13),#883);
|
||||
#11=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',#890,#12);
|
||||
#12=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#14),#882);
|
||||
#13=STYLED_ITEM('',(#899),#14);
|
||||
#14=MANIFOLD_SOLID_BREP('Solid1',#461);
|
||||
#15=FACE_BOUND('',#135,.T.);
|
||||
#16=FACE_BOUND('',#136,.T.);
|
||||
#17=FACE_BOUND('',#142,.T.);
|
||||
#18=FACE_BOUND('',#145,.T.);
|
||||
#19=CONICAL_SURFACE('',#515,1.50402,0.785398163397446);
|
||||
#20=CONICAL_SURFACE('',#525,1.50402,0.785398163397446);
|
||||
#21=CONICAL_SURFACE('',#530,1.50402,0.785398163397446);
|
||||
#22=CONICAL_SURFACE('',#533,1.50402,0.785398163397446);
|
||||
#23=PLANE('',#491);
|
||||
#24=PLANE('',#500);
|
||||
#25=PLANE('',#501);
|
||||
#26=PLANE('',#510);
|
||||
#27=PLANE('',#518);
|
||||
#28=PLANE('',#532);
|
||||
#29=PLANE('',#535);
|
||||
#30=LINE('',#735,#56);
|
||||
#31=LINE('',#738,#57);
|
||||
#32=LINE('',#740,#58);
|
||||
#33=LINE('',#787,#59);
|
||||
#34=LINE('',#792,#60);
|
||||
#35=LINE('',#796,#61);
|
||||
#36=LINE('',#799,#62);
|
||||
#37=LINE('',#802,#63);
|
||||
#38=LINE('',#806,#64);
|
||||
#39=LINE('',#807,#65);
|
||||
#40=LINE('',#810,#66);
|
||||
#41=LINE('',#812,#67);
|
||||
#42=LINE('',#813,#68);
|
||||
#43=LINE('',#818,#69);
|
||||
#44=LINE('',#821,#70);
|
||||
#45=LINE('',#826,#71);
|
||||
#46=LINE('',#829,#72);
|
||||
#47=LINE('',#833,#73);
|
||||
#48=LINE('',#834,#74);
|
||||
#49=LINE('',#843,#75);
|
||||
#50=LINE('',#855,#76);
|
||||
#51=LINE('',#859,#77);
|
||||
#52=LINE('',#865,#78);
|
||||
#53=LINE('',#870,#79);
|
||||
#54=LINE('',#875,#80);
|
||||
#55=LINE('',#878,#81);
|
||||
#56=VECTOR('',#550,3.00804);
|
||||
#57=VECTOR('',#553,10.);
|
||||
#58=VECTOR('',#554,10.);
|
||||
#59=VECTOR('',#567,10.);
|
||||
#60=VECTOR('',#572,10.);
|
||||
#61=VECTOR('',#577,8.02144);
|
||||
#62=VECTOR('',#580,10.);
|
||||
#63=VECTOR('',#583,10.0268);
|
||||
#64=VECTOR('',#588,7.01876);
|
||||
#65=VECTOR('',#589,10.0268);
|
||||
#66=VECTOR('',#592,10.);
|
||||
#67=VECTOR('',#593,10.0268);
|
||||
#68=VECTOR('',#594,10.);
|
||||
#69=VECTOR('',#599,3.00804);
|
||||
#70=VECTOR('',#602,10.);
|
||||
#71=VECTOR('',#609,10.);
|
||||
#72=VECTOR('',#612,10.);
|
||||
#73=VECTOR('',#617,10.);
|
||||
#74=VECTOR('',#618,10.0268);
|
||||
#75=VECTOR('',#631,1.50402);
|
||||
#76=VECTOR('',#646,1.25335);
|
||||
#77=VECTOR('',#651,1.50402);
|
||||
#78=VECTOR('',#658,1.25335);
|
||||
#79=VECTOR('',#665,1.50402);
|
||||
#80=VECTOR('',#672,1.50402);
|
||||
#81=VECTOR('',#677,10.);
|
||||
#82=CYLINDRICAL_SURFACE('',#484,3.00804);
|
||||
#83=CYLINDRICAL_SURFACE('',#496,8.02144);
|
||||
#84=CYLINDRICAL_SURFACE('',#498,7.01876);
|
||||
#85=CYLINDRICAL_SURFACE('',#502,3.00804);
|
||||
#86=CYLINDRICAL_SURFACE('',#506,8.02144);
|
||||
#87=CYLINDRICAL_SURFACE('',#508,8.02144);
|
||||
#88=CYLINDRICAL_SURFACE('',#511,7.01876);
|
||||
#89=CYLINDRICAL_SURFACE('',#513,7.01876);
|
||||
#90=CYLINDRICAL_SURFACE('',#522,1.15335);
|
||||
#91=CYLINDRICAL_SURFACE('',#527,1.15335);
|
||||
#92=CYLINDRICAL_SURFACE('',#536,7.01876);
|
||||
#93=CYLINDRICAL_SURFACE('',#537,8.02144);
|
||||
#94=FACE_OUTER_BOUND('',#119,.T.);
|
||||
#95=FACE_OUTER_BOUND('',#120,.T.);
|
||||
#96=FACE_OUTER_BOUND('',#121,.T.);
|
||||
#97=FACE_OUTER_BOUND('',#122,.T.);
|
||||
#98=FACE_OUTER_BOUND('',#123,.T.);
|
||||
#99=FACE_OUTER_BOUND('',#124,.T.);
|
||||
#100=FACE_OUTER_BOUND('',#125,.T.);
|
||||
#101=FACE_OUTER_BOUND('',#126,.T.);
|
||||
#102=FACE_OUTER_BOUND('',#127,.T.);
|
||||
#103=FACE_OUTER_BOUND('',#128,.T.);
|
||||
#104=FACE_OUTER_BOUND('',#129,.T.);
|
||||
#105=FACE_OUTER_BOUND('',#130,.T.);
|
||||
#106=FACE_OUTER_BOUND('',#131,.T.);
|
||||
#107=FACE_OUTER_BOUND('',#132,.T.);
|
||||
#108=FACE_OUTER_BOUND('',#133,.T.);
|
||||
#109=FACE_OUTER_BOUND('',#134,.T.);
|
||||
#110=FACE_OUTER_BOUND('',#137,.T.);
|
||||
#111=FACE_OUTER_BOUND('',#138,.T.);
|
||||
#112=FACE_OUTER_BOUND('',#139,.T.);
|
||||
#113=FACE_OUTER_BOUND('',#140,.T.);
|
||||
#114=FACE_OUTER_BOUND('',#141,.T.);
|
||||
#115=FACE_OUTER_BOUND('',#143,.T.);
|
||||
#116=FACE_OUTER_BOUND('',#144,.T.);
|
||||
#117=FACE_OUTER_BOUND('',#146,.T.);
|
||||
#118=FACE_OUTER_BOUND('',#147,.T.);
|
||||
#119=EDGE_LOOP('',(#300,#301,#302,#303,#304,#305,#306));
|
||||
#120=EDGE_LOOP('',(#307,#308,#309,#310,#311,#312,#313,#314));
|
||||
#121=EDGE_LOOP('',(#315,#316,#317,#318,#319,#320));
|
||||
#122=EDGE_LOOP('',(#321,#322,#323,#324,#325,#326,#327,#328));
|
||||
#123=EDGE_LOOP('',(#329,#330,#331,#332));
|
||||
#124=EDGE_LOOP('',(#333,#334,#335,#336,#337));
|
||||
#125=EDGE_LOOP('',(#338,#339,#340,#341));
|
||||
#126=EDGE_LOOP('',(#342,#343,#344,#345));
|
||||
#127=EDGE_LOOP('',(#346,#347,#348,#349,#350,#351,#352,#353));
|
||||
#128=EDGE_LOOP('',(#354,#355,#356,#357));
|
||||
#129=EDGE_LOOP('',(#358,#359,#360,#361));
|
||||
#130=EDGE_LOOP('',(#362,#363,#364,#365));
|
||||
#131=EDGE_LOOP('',(#366,#367,#368,#369,#370));
|
||||
#132=EDGE_LOOP('',(#371,#372,#373,#374,#375));
|
||||
#133=EDGE_LOOP('',(#376,#377,#378,#379));
|
||||
#134=EDGE_LOOP('',(#380,#381,#382,#383,#384,#385,#386,#387,#388,#389,#390,
|
||||
#391,#392,#393,#394));
|
||||
#135=EDGE_LOOP('',(#395));
|
||||
#136=EDGE_LOOP('',(#396));
|
||||
#137=EDGE_LOOP('',(#397,#398,#399,#400,#401));
|
||||
#138=EDGE_LOOP('',(#402,#403,#404,#405));
|
||||
#139=EDGE_LOOP('',(#406,#407,#408,#409,#410));
|
||||
#140=EDGE_LOOP('',(#411,#412,#413,#414,#415));
|
||||
#141=EDGE_LOOP('',(#416));
|
||||
#142=EDGE_LOOP('',(#417));
|
||||
#143=EDGE_LOOP('',(#418,#419,#420,#421,#422));
|
||||
#144=EDGE_LOOP('',(#423));
|
||||
#145=EDGE_LOOP('',(#424));
|
||||
#146=EDGE_LOOP('',(#425,#426,#427,#428,#429));
|
||||
#147=EDGE_LOOP('',(#430,#431,#432,#433));
|
||||
#148=CIRCLE('',#482,7.00804);
|
||||
#149=CIRCLE('',#483,3.00804);
|
||||
#150=CIRCLE('',#485,3.00804);
|
||||
#151=CIRCLE('',#486,3.00804);
|
||||
#152=CIRCLE('',#487,3.00804);
|
||||
#153=CIRCLE('',#489,3.00804);
|
||||
#154=CIRCLE('',#490,7.00804);
|
||||
#155=CIRCLE('',#492,7.01876);
|
||||
#156=CIRCLE('',#493,7.01876);
|
||||
#157=CIRCLE('',#494,7.01876);
|
||||
#158=CIRCLE('',#495,7.01876);
|
||||
#159=CIRCLE('',#497,8.02144);
|
||||
#160=CIRCLE('',#499,7.01876);
|
||||
#161=CIRCLE('',#503,3.00804);
|
||||
#162=CIRCLE('',#504,3.00804);
|
||||
#163=CIRCLE('',#505,3.00804);
|
||||
#164=CIRCLE('',#507,8.02144);
|
||||
#165=CIRCLE('',#509,8.02144);
|
||||
#166=CIRCLE('',#512,7.01876);
|
||||
#167=CIRCLE('',#514,7.01876);
|
||||
#168=CIRCLE('',#516,1.75469);
|
||||
#169=CIRCLE('',#517,1.15335);
|
||||
#170=CIRCLE('',#519,7.01876);
|
||||
#171=CIRCLE('',#520,8.02144);
|
||||
#172=CIRCLE('',#521,1.75469);
|
||||
#173=CIRCLE('',#523,1.15335);
|
||||
#174=CIRCLE('',#524,1.15335);
|
||||
#175=CIRCLE('',#526,1.15335);
|
||||
#176=CIRCLE('',#528,1.15335);
|
||||
#177=CIRCLE('',#529,1.15335);
|
||||
#178=CIRCLE('',#531,1.75469);
|
||||
#179=CIRCLE('',#534,1.75469);
|
||||
#180=B_SPLINE_CURVE_WITH_KNOTS('',3,(#684,#685,#686,#687,#688,#689),
|
||||
.UNSPECIFIED.,.F.,.F.,(4,2,4),(1.84958971453185,1.88077149669059,1.89236508906971),
|
||||
.UNSPECIFIED.);
|
||||
#181=B_SPLINE_CURVE_WITH_KNOTS('',3,(#693,#694,#695,#696,#697,#698),
|
||||
.UNSPECIFIED.,.F.,.F.,(4,2,4),(0.677497757408314,0.788403142650085,0.821392408392587),
|
||||
.UNSPECIFIED.);
|
||||
#182=B_SPLINE_CURVE_WITH_KNOTS('',3,(#700,#701,#702,#703,#704,#705),
|
||||
.UNSPECIFIED.,.F.,.F.,(4,2,4),(0.718120459763341,0.755157597858511,0.76176835105742),
|
||||
.UNSPECIFIED.);
|
||||
#183=B_SPLINE_CURVE_WITH_KNOTS('',3,(#707,#708,#709,#710,#711,#712,#713,
|
||||
#714,#715,#716),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(1.8094458082449,1.88790790479797,
|
||||
2.05305157993795,2.26943298100183,2.27022614805197),.UNSPECIFIED.);
|
||||
#184=B_SPLINE_CURVE_WITH_KNOTS('',3,(#719,#720,#721,#722,#723,#724,#725,
|
||||
#726,#727,#728,#729,#730),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,4),(-0.000793167050811743,
|
||||
0.,0.216381428611185,0.381525135470128,0.509883396641204,0.567800192420913),
|
||||
.UNSPECIFIED.);
|
||||
#185=B_SPLINE_CURVE_WITH_KNOTS('',3,(#745,#746,#747,#748,#749,#750,#751,
|
||||
#752,#753,#754,#755,#756),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,4),(1.71827230670034,
|
||||
1.75955118014646,1.88790953171987,2.05305335488903,2.26943488454831,2.27022805161283),
|
||||
.UNSPECIFIED.);
|
||||
#186=B_SPLINE_CURVE_WITH_KNOTS('',3,(#760,#761,#762,#763,#764,#765,#766,
|
||||
#767),.UNSPECIFIED.,.F.,.F.,(4,2,2,4),(-0.000793167053338841,0.,0.216381446124703,
|
||||
0.281282906842762),.UNSPECIFIED.);
|
||||
#187=B_SPLINE_CURVE_WITH_KNOTS('',3,(#769,#770,#771,#772,#773,#774,#775,
|
||||
#776),.UNSPECIFIED.,.F.,.F.,(4,2,2,4),(4.43658033669356,4.60723589928881,
|
||||
4.776503081225,4.8535852884345),.UNSPECIFIED.);
|
||||
#188=B_SPLINE_CURVE_WITH_KNOTS('',3,(#779,#780,#781,#782),.UNSPECIFIED.,
|
||||
.F.,.F.,(4,4),(0.661852334486626,0.723354146244754),.UNSPECIFIED.);
|
||||
#189=VERTEX_POINT('',#682);
|
||||
#190=VERTEX_POINT('',#683);
|
||||
#191=VERTEX_POINT('',#690);
|
||||
#192=VERTEX_POINT('',#692);
|
||||
#193=VERTEX_POINT('',#699);
|
||||
#194=VERTEX_POINT('',#706);
|
||||
#195=VERTEX_POINT('',#717);
|
||||
#196=VERTEX_POINT('',#732);
|
||||
#197=VERTEX_POINT('',#734);
|
||||
#198=VERTEX_POINT('',#736);
|
||||
#199=VERTEX_POINT('',#739);
|
||||
#200=VERTEX_POINT('',#743);
|
||||
#201=VERTEX_POINT('',#744);
|
||||
#202=VERTEX_POINT('',#757);
|
||||
#203=VERTEX_POINT('',#759);
|
||||
#204=VERTEX_POINT('',#768);
|
||||
#205=VERTEX_POINT('',#777);
|
||||
#206=VERTEX_POINT('',#784);
|
||||
#207=VERTEX_POINT('',#786);
|
||||
#208=VERTEX_POINT('',#789);
|
||||
#209=VERTEX_POINT('',#791);
|
||||
#210=VERTEX_POINT('',#795);
|
||||
#211=VERTEX_POINT('',#797);
|
||||
#212=VERTEX_POINT('',#801);
|
||||
#213=VERTEX_POINT('',#805);
|
||||
#214=VERTEX_POINT('',#809);
|
||||
#215=VERTEX_POINT('',#811);
|
||||
#216=VERTEX_POINT('',#815);
|
||||
#217=VERTEX_POINT('',#817);
|
||||
#218=VERTEX_POINT('',#819);
|
||||
#219=VERTEX_POINT('',#824);
|
||||
#220=VERTEX_POINT('',#828);
|
||||
#221=VERTEX_POINT('',#832);
|
||||
#222=VERTEX_POINT('',#840);
|
||||
#223=VERTEX_POINT('',#842);
|
||||
#224=VERTEX_POINT('',#846);
|
||||
#225=VERTEX_POINT('',#849);
|
||||
#226=VERTEX_POINT('',#852);
|
||||
#227=VERTEX_POINT('',#853);
|
||||
#228=VERTEX_POINT('',#858);
|
||||
#229=VERTEX_POINT('',#862);
|
||||
#230=VERTEX_POINT('',#863);
|
||||
#231=VERTEX_POINT('',#868);
|
||||
#232=VERTEX_POINT('',#873);
|
||||
#233=EDGE_CURVE('',#189,#190,#180,.T.);
|
||||
#234=EDGE_CURVE('',#190,#191,#148,.T.);
|
||||
#235=EDGE_CURVE('',#191,#192,#181,.T.);
|
||||
#236=EDGE_CURVE('',#193,#192,#182,.F.);
|
||||
#237=EDGE_CURVE('',#194,#193,#183,.F.);
|
||||
#238=EDGE_CURVE('',#194,#195,#149,.T.);
|
||||
#239=EDGE_CURVE('',#195,#189,#184,.T.);
|
||||
#240=EDGE_CURVE('',#196,#196,#150,.T.);
|
||||
#241=EDGE_CURVE('',#196,#197,#30,.T.);
|
||||
#242=EDGE_CURVE('',#198,#197,#151,.T.);
|
||||
#243=EDGE_CURVE('',#198,#195,#31,.T.);
|
||||
#244=EDGE_CURVE('',#194,#199,#32,.T.);
|
||||
#245=EDGE_CURVE('',#197,#199,#152,.T.);
|
||||
#246=EDGE_CURVE('',#200,#201,#185,.F.);
|
||||
#247=EDGE_CURVE('',#200,#202,#153,.T.);
|
||||
#248=EDGE_CURVE('',#202,#203,#186,.T.);
|
||||
#249=EDGE_CURVE('',#204,#203,#187,.F.);
|
||||
#250=EDGE_CURVE('',#204,#205,#154,.T.);
|
||||
#251=EDGE_CURVE('',#201,#205,#188,.F.);
|
||||
#252=EDGE_CURVE('',#206,#190,#155,.F.);
|
||||
#253=EDGE_CURVE('',#206,#207,#33,.T.);
|
||||
#254=EDGE_CURVE('',#207,#205,#156,.T.);
|
||||
#255=EDGE_CURVE('',#208,#204,#157,.F.);
|
||||
#256=EDGE_CURVE('',#208,#209,#34,.T.);
|
||||
#257=EDGE_CURVE('',#191,#209,#158,.F.);
|
||||
#258=EDGE_CURVE('',#201,#210,#35,.T.);
|
||||
#259=EDGE_CURVE('',#210,#211,#159,.T.);
|
||||
#260=EDGE_CURVE('',#211,#200,#36,.T.);
|
||||
#261=EDGE_CURVE('',#207,#212,#37,.T.);
|
||||
#262=EDGE_CURVE('',#212,#210,#160,.T.);
|
||||
#263=EDGE_CURVE('',#213,#206,#38,.T.);
|
||||
#264=EDGE_CURVE('',#213,#212,#39,.T.);
|
||||
#265=EDGE_CURVE('',#208,#214,#40,.T.);
|
||||
#266=EDGE_CURVE('',#214,#215,#41,.F.);
|
||||
#267=EDGE_CURVE('',#215,#209,#42,.F.);
|
||||
#268=EDGE_CURVE('',#216,#216,#161,.T.);
|
||||
#269=EDGE_CURVE('',#216,#217,#43,.T.);
|
||||
#270=EDGE_CURVE('',#217,#218,#162,.T.);
|
||||
#271=EDGE_CURVE('',#218,#202,#44,.T.);
|
||||
#272=EDGE_CURVE('',#211,#217,#163,.T.);
|
||||
#273=EDGE_CURVE('',#198,#219,#164,.T.);
|
||||
#274=EDGE_CURVE('',#189,#219,#45,.T.);
|
||||
#275=EDGE_CURVE('',#193,#220,#46,.F.);
|
||||
#276=EDGE_CURVE('',#220,#199,#165,.T.);
|
||||
#277=EDGE_CURVE('',#192,#221,#47,.T.);
|
||||
#278=EDGE_CURVE('',#221,#220,#48,.F.);
|
||||
#279=EDGE_CURVE('',#215,#221,#166,.T.);
|
||||
#280=EDGE_CURVE('',#219,#213,#167,.T.);
|
||||
#281=EDGE_CURVE('',#222,#222,#168,.T.);
|
||||
#282=EDGE_CURVE('',#222,#223,#49,.T.);
|
||||
#283=EDGE_CURVE('',#223,#223,#169,.F.);
|
||||
#284=EDGE_CURVE('',#214,#224,#170,.F.);
|
||||
#285=EDGE_CURVE('',#218,#224,#171,.T.);
|
||||
#286=EDGE_CURVE('',#225,#225,#172,.T.);
|
||||
#287=EDGE_CURVE('',#226,#227,#173,.F.);
|
||||
#288=EDGE_CURVE('',#226,#223,#50,.T.);
|
||||
#289=EDGE_CURVE('',#227,#226,#174,.F.);
|
||||
#290=EDGE_CURVE('',#225,#228,#51,.T.);
|
||||
#291=EDGE_CURVE('',#228,#228,#175,.F.);
|
||||
#292=EDGE_CURVE('',#229,#230,#176,.F.);
|
||||
#293=EDGE_CURVE('',#229,#228,#52,.T.);
|
||||
#294=EDGE_CURVE('',#230,#229,#177,.F.);
|
||||
#295=EDGE_CURVE('',#231,#231,#178,.T.);
|
||||
#296=EDGE_CURVE('',#231,#230,#53,.T.);
|
||||
#297=EDGE_CURVE('',#232,#232,#179,.T.);
|
||||
#298=EDGE_CURVE('',#232,#227,#54,.T.);
|
||||
#299=EDGE_CURVE('',#203,#224,#55,.F.);
|
||||
#300=ORIENTED_EDGE('',*,*,#233,.T.);
|
||||
#301=ORIENTED_EDGE('',*,*,#234,.T.);
|
||||
#302=ORIENTED_EDGE('',*,*,#235,.T.);
|
||||
#303=ORIENTED_EDGE('',*,*,#236,.F.);
|
||||
#304=ORIENTED_EDGE('',*,*,#237,.F.);
|
||||
#305=ORIENTED_EDGE('',*,*,#238,.T.);
|
||||
#306=ORIENTED_EDGE('',*,*,#239,.T.);
|
||||
#307=ORIENTED_EDGE('',*,*,#240,.T.);
|
||||
#308=ORIENTED_EDGE('',*,*,#241,.T.);
|
||||
#309=ORIENTED_EDGE('',*,*,#242,.F.);
|
||||
#310=ORIENTED_EDGE('',*,*,#243,.T.);
|
||||
#311=ORIENTED_EDGE('',*,*,#238,.F.);
|
||||
#312=ORIENTED_EDGE('',*,*,#244,.T.);
|
||||
#313=ORIENTED_EDGE('',*,*,#245,.F.);
|
||||
#314=ORIENTED_EDGE('',*,*,#241,.F.);
|
||||
#315=ORIENTED_EDGE('',*,*,#246,.F.);
|
||||
#316=ORIENTED_EDGE('',*,*,#247,.T.);
|
||||
#317=ORIENTED_EDGE('',*,*,#248,.T.);
|
||||
#318=ORIENTED_EDGE('',*,*,#249,.F.);
|
||||
#319=ORIENTED_EDGE('',*,*,#250,.T.);
|
||||
#320=ORIENTED_EDGE('',*,*,#251,.F.);
|
||||
#321=ORIENTED_EDGE('',*,*,#234,.F.);
|
||||
#322=ORIENTED_EDGE('',*,*,#252,.F.);
|
||||
#323=ORIENTED_EDGE('',*,*,#253,.T.);
|
||||
#324=ORIENTED_EDGE('',*,*,#254,.T.);
|
||||
#325=ORIENTED_EDGE('',*,*,#250,.F.);
|
||||
#326=ORIENTED_EDGE('',*,*,#255,.F.);
|
||||
#327=ORIENTED_EDGE('',*,*,#256,.T.);
|
||||
#328=ORIENTED_EDGE('',*,*,#257,.F.);
|
||||
#329=ORIENTED_EDGE('',*,*,#258,.T.);
|
||||
#330=ORIENTED_EDGE('',*,*,#259,.T.);
|
||||
#331=ORIENTED_EDGE('',*,*,#260,.T.);
|
||||
#332=ORIENTED_EDGE('',*,*,#246,.T.);
|
||||
#333=ORIENTED_EDGE('',*,*,#254,.F.);
|
||||
#334=ORIENTED_EDGE('',*,*,#261,.T.);
|
||||
#335=ORIENTED_EDGE('',*,*,#262,.T.);
|
||||
#336=ORIENTED_EDGE('',*,*,#258,.F.);
|
||||
#337=ORIENTED_EDGE('',*,*,#251,.T.);
|
||||
#338=ORIENTED_EDGE('',*,*,#253,.F.);
|
||||
#339=ORIENTED_EDGE('',*,*,#263,.F.);
|
||||
#340=ORIENTED_EDGE('',*,*,#264,.T.);
|
||||
#341=ORIENTED_EDGE('',*,*,#261,.F.);
|
||||
#342=ORIENTED_EDGE('',*,*,#256,.F.);
|
||||
#343=ORIENTED_EDGE('',*,*,#265,.T.);
|
||||
#344=ORIENTED_EDGE('',*,*,#266,.T.);
|
||||
#345=ORIENTED_EDGE('',*,*,#267,.T.);
|
||||
#346=ORIENTED_EDGE('',*,*,#268,.F.);
|
||||
#347=ORIENTED_EDGE('',*,*,#269,.T.);
|
||||
#348=ORIENTED_EDGE('',*,*,#270,.T.);
|
||||
#349=ORIENTED_EDGE('',*,*,#271,.T.);
|
||||
#350=ORIENTED_EDGE('',*,*,#247,.F.);
|
||||
#351=ORIENTED_EDGE('',*,*,#260,.F.);
|
||||
#352=ORIENTED_EDGE('',*,*,#272,.T.);
|
||||
#353=ORIENTED_EDGE('',*,*,#269,.F.);
|
||||
#354=ORIENTED_EDGE('',*,*,#243,.F.);
|
||||
#355=ORIENTED_EDGE('',*,*,#273,.T.);
|
||||
#356=ORIENTED_EDGE('',*,*,#274,.F.);
|
||||
#357=ORIENTED_EDGE('',*,*,#239,.F.);
|
||||
#358=ORIENTED_EDGE('',*,*,#275,.T.);
|
||||
#359=ORIENTED_EDGE('',*,*,#276,.T.);
|
||||
#360=ORIENTED_EDGE('',*,*,#244,.F.);
|
||||
#361=ORIENTED_EDGE('',*,*,#237,.T.);
|
||||
#362=ORIENTED_EDGE('',*,*,#277,.T.);
|
||||
#363=ORIENTED_EDGE('',*,*,#278,.T.);
|
||||
#364=ORIENTED_EDGE('',*,*,#275,.F.);
|
||||
#365=ORIENTED_EDGE('',*,*,#236,.T.);
|
||||
#366=ORIENTED_EDGE('',*,*,#257,.T.);
|
||||
#367=ORIENTED_EDGE('',*,*,#267,.F.);
|
||||
#368=ORIENTED_EDGE('',*,*,#279,.T.);
|
||||
#369=ORIENTED_EDGE('',*,*,#277,.F.);
|
||||
#370=ORIENTED_EDGE('',*,*,#235,.F.);
|
||||
#371=ORIENTED_EDGE('',*,*,#252,.T.);
|
||||
#372=ORIENTED_EDGE('',*,*,#233,.F.);
|
||||
#373=ORIENTED_EDGE('',*,*,#274,.T.);
|
||||
#374=ORIENTED_EDGE('',*,*,#280,.T.);
|
||||
#375=ORIENTED_EDGE('',*,*,#263,.T.);
|
||||
#376=ORIENTED_EDGE('',*,*,#281,.T.);
|
||||
#377=ORIENTED_EDGE('',*,*,#282,.T.);
|
||||
#378=ORIENTED_EDGE('',*,*,#283,.T.);
|
||||
#379=ORIENTED_EDGE('',*,*,#282,.F.);
|
||||
#380=ORIENTED_EDGE('',*,*,#259,.F.);
|
||||
#381=ORIENTED_EDGE('',*,*,#262,.F.);
|
||||
#382=ORIENTED_EDGE('',*,*,#264,.F.);
|
||||
#383=ORIENTED_EDGE('',*,*,#280,.F.);
|
||||
#384=ORIENTED_EDGE('',*,*,#273,.F.);
|
||||
#385=ORIENTED_EDGE('',*,*,#242,.T.);
|
||||
#386=ORIENTED_EDGE('',*,*,#245,.T.);
|
||||
#387=ORIENTED_EDGE('',*,*,#276,.F.);
|
||||
#388=ORIENTED_EDGE('',*,*,#278,.F.);
|
||||
#389=ORIENTED_EDGE('',*,*,#279,.F.);
|
||||
#390=ORIENTED_EDGE('',*,*,#266,.F.);
|
||||
#391=ORIENTED_EDGE('',*,*,#284,.T.);
|
||||
#392=ORIENTED_EDGE('',*,*,#285,.F.);
|
||||
#393=ORIENTED_EDGE('',*,*,#270,.F.);
|
||||
#394=ORIENTED_EDGE('',*,*,#272,.F.);
|
||||
#395=ORIENTED_EDGE('',*,*,#281,.F.);
|
||||
#396=ORIENTED_EDGE('',*,*,#286,.F.);
|
||||
#397=ORIENTED_EDGE('',*,*,#287,.F.);
|
||||
#398=ORIENTED_EDGE('',*,*,#288,.T.);
|
||||
#399=ORIENTED_EDGE('',*,*,#283,.F.);
|
||||
#400=ORIENTED_EDGE('',*,*,#288,.F.);
|
||||
#401=ORIENTED_EDGE('',*,*,#289,.F.);
|
||||
#402=ORIENTED_EDGE('',*,*,#286,.T.);
|
||||
#403=ORIENTED_EDGE('',*,*,#290,.T.);
|
||||
#404=ORIENTED_EDGE('',*,*,#291,.T.);
|
||||
#405=ORIENTED_EDGE('',*,*,#290,.F.);
|
||||
#406=ORIENTED_EDGE('',*,*,#292,.F.);
|
||||
#407=ORIENTED_EDGE('',*,*,#293,.T.);
|
||||
#408=ORIENTED_EDGE('',*,*,#291,.F.);
|
||||
#409=ORIENTED_EDGE('',*,*,#293,.F.);
|
||||
#410=ORIENTED_EDGE('',*,*,#294,.F.);
|
||||
#411=ORIENTED_EDGE('',*,*,#295,.T.);
|
||||
#412=ORIENTED_EDGE('',*,*,#296,.T.);
|
||||
#413=ORIENTED_EDGE('',*,*,#294,.T.);
|
||||
#414=ORIENTED_EDGE('',*,*,#292,.T.);
|
||||
#415=ORIENTED_EDGE('',*,*,#296,.F.);
|
||||
#416=ORIENTED_EDGE('',*,*,#240,.F.);
|
||||
#417=ORIENTED_EDGE('',*,*,#295,.F.);
|
||||
#418=ORIENTED_EDGE('',*,*,#297,.T.);
|
||||
#419=ORIENTED_EDGE('',*,*,#298,.T.);
|
||||
#420=ORIENTED_EDGE('',*,*,#289,.T.);
|
||||
#421=ORIENTED_EDGE('',*,*,#287,.T.);
|
||||
#422=ORIENTED_EDGE('',*,*,#298,.F.);
|
||||
#423=ORIENTED_EDGE('',*,*,#268,.T.);
|
||||
#424=ORIENTED_EDGE('',*,*,#297,.F.);
|
||||
#425=ORIENTED_EDGE('',*,*,#255,.T.);
|
||||
#426=ORIENTED_EDGE('',*,*,#249,.T.);
|
||||
#427=ORIENTED_EDGE('',*,*,#299,.T.);
|
||||
#428=ORIENTED_EDGE('',*,*,#284,.F.);
|
||||
#429=ORIENTED_EDGE('',*,*,#265,.F.);
|
||||
#430=ORIENTED_EDGE('',*,*,#271,.F.);
|
||||
#431=ORIENTED_EDGE('',*,*,#285,.T.);
|
||||
#432=ORIENTED_EDGE('',*,*,#299,.F.);
|
||||
#433=ORIENTED_EDGE('',*,*,#248,.F.);
|
||||
#434=TOROIDAL_SURFACE('',#481,7.00804000000001,4.);
|
||||
#435=TOROIDAL_SURFACE('',#488,7.00804,4.);
|
||||
#436=ADVANCED_FACE('',(#94),#434,.F.);
|
||||
#437=ADVANCED_FACE('',(#95),#82,.T.);
|
||||
#438=ADVANCED_FACE('',(#96),#435,.F.);
|
||||
#439=ADVANCED_FACE('',(#97),#23,.T.);
|
||||
#440=ADVANCED_FACE('',(#98),#83,.F.);
|
||||
#441=ADVANCED_FACE('',(#99),#84,.T.);
|
||||
#442=ADVANCED_FACE('',(#100),#24,.T.);
|
||||
#443=ADVANCED_FACE('',(#101),#25,.T.);
|
||||
#444=ADVANCED_FACE('',(#102),#85,.T.);
|
||||
#445=ADVANCED_FACE('',(#103),#86,.F.);
|
||||
#446=ADVANCED_FACE('',(#104),#87,.F.);
|
||||
#447=ADVANCED_FACE('',(#105),#26,.T.);
|
||||
#448=ADVANCED_FACE('',(#106),#88,.F.);
|
||||
#449=ADVANCED_FACE('',(#107),#89,.T.);
|
||||
#450=ADVANCED_FACE('',(#108),#19,.F.);
|
||||
#451=ADVANCED_FACE('',(#109,#15,#16),#27,.T.);
|
||||
#452=ADVANCED_FACE('',(#110),#90,.F.);
|
||||
#453=ADVANCED_FACE('',(#111),#20,.F.);
|
||||
#454=ADVANCED_FACE('',(#112),#91,.F.);
|
||||
#455=ADVANCED_FACE('',(#113),#21,.F.);
|
||||
#456=ADVANCED_FACE('',(#114,#17),#28,.T.);
|
||||
#457=ADVANCED_FACE('',(#115),#22,.F.);
|
||||
#458=ADVANCED_FACE('',(#116,#18),#29,.F.);
|
||||
#459=ADVANCED_FACE('',(#117),#92,.F.);
|
||||
#460=ADVANCED_FACE('',(#118),#93,.F.);
|
||||
#461=CLOSED_SHELL('',(#436,#437,#438,#439,#440,#441,#442,#443,#444,#445,
|
||||
#446,#447,#448,#449,#450,#451,#452,#453,#454,#455,#456,#457,#458,#459,#460));
|
||||
#462=DERIVED_UNIT_ELEMENT(#464,1.);
|
||||
#463=DERIVED_UNIT_ELEMENT(#885,-3.);
|
||||
#464=(
|
||||
MASS_UNIT()
|
||||
NAMED_UNIT(*)
|
||||
SI_UNIT($,.GRAM.)
|
||||
);
|
||||
#465=DERIVED_UNIT((#462,#463));
|
||||
#466=MEASURE_REPRESENTATION_ITEM('density measure',
|
||||
POSITIVE_RATIO_MEASURE(1.),#465);
|
||||
#467=PROPERTY_DEFINITION_REPRESENTATION(#472,#469);
|
||||
#468=PROPERTY_DEFINITION_REPRESENTATION(#473,#470);
|
||||
#469=REPRESENTATION('material name',(#471),#882);
|
||||
#470=REPRESENTATION('density',(#466),#882);
|
||||
#471=DESCRIPTIVE_REPRESENTATION_ITEM('Generic','Generic');
|
||||
#472=PROPERTY_DEFINITION('material property','material name',#892);
|
||||
#473=PROPERTY_DEFINITION('material property','density of part',#892);
|
||||
#474=DATE_TIME_ROLE('creation_date');
|
||||
#475=APPLIED_DATE_AND_TIME_ASSIGNMENT(#476,#474,(#892));
|
||||
#476=DATE_AND_TIME(#477,#478);
|
||||
#477=CALENDAR_DATE(2020,5,10);
|
||||
#478=LOCAL_TIME(0,0,0.,#479);
|
||||
#479=COORDINATED_UNIVERSAL_TIME_OFFSET(0,0,.BEHIND.);
|
||||
#480=AXIS2_PLACEMENT_3D('placement',#680,#538,#539);
|
||||
#481=AXIS2_PLACEMENT_3D('',#681,#540,#541);
|
||||
#482=AXIS2_PLACEMENT_3D('',#691,#542,#543);
|
||||
#483=AXIS2_PLACEMENT_3D('',#718,#544,#545);
|
||||
#484=AXIS2_PLACEMENT_3D('',#731,#546,#547);
|
||||
#485=AXIS2_PLACEMENT_3D('',#733,#548,#549);
|
||||
#486=AXIS2_PLACEMENT_3D('',#737,#551,#552);
|
||||
#487=AXIS2_PLACEMENT_3D('',#741,#555,#556);
|
||||
#488=AXIS2_PLACEMENT_3D('',#742,#557,#558);
|
||||
#489=AXIS2_PLACEMENT_3D('',#758,#559,#560);
|
||||
#490=AXIS2_PLACEMENT_3D('',#778,#561,#562);
|
||||
#491=AXIS2_PLACEMENT_3D('',#783,#563,#564);
|
||||
#492=AXIS2_PLACEMENT_3D('',#785,#565,#566);
|
||||
#493=AXIS2_PLACEMENT_3D('',#788,#568,#569);
|
||||
#494=AXIS2_PLACEMENT_3D('',#790,#570,#571);
|
||||
#495=AXIS2_PLACEMENT_3D('',#793,#573,#574);
|
||||
#496=AXIS2_PLACEMENT_3D('',#794,#575,#576);
|
||||
#497=AXIS2_PLACEMENT_3D('',#798,#578,#579);
|
||||
#498=AXIS2_PLACEMENT_3D('',#800,#581,#582);
|
||||
#499=AXIS2_PLACEMENT_3D('',#803,#584,#585);
|
||||
#500=AXIS2_PLACEMENT_3D('',#804,#586,#587);
|
||||
#501=AXIS2_PLACEMENT_3D('',#808,#590,#591);
|
||||
#502=AXIS2_PLACEMENT_3D('',#814,#595,#596);
|
||||
#503=AXIS2_PLACEMENT_3D('',#816,#597,#598);
|
||||
#504=AXIS2_PLACEMENT_3D('',#820,#600,#601);
|
||||
#505=AXIS2_PLACEMENT_3D('',#822,#603,#604);
|
||||
#506=AXIS2_PLACEMENT_3D('',#823,#605,#606);
|
||||
#507=AXIS2_PLACEMENT_3D('',#825,#607,#608);
|
||||
#508=AXIS2_PLACEMENT_3D('',#827,#610,#611);
|
||||
#509=AXIS2_PLACEMENT_3D('',#830,#613,#614);
|
||||
#510=AXIS2_PLACEMENT_3D('',#831,#615,#616);
|
||||
#511=AXIS2_PLACEMENT_3D('',#835,#619,#620);
|
||||
#512=AXIS2_PLACEMENT_3D('',#836,#621,#622);
|
||||
#513=AXIS2_PLACEMENT_3D('',#837,#623,#624);
|
||||
#514=AXIS2_PLACEMENT_3D('',#838,#625,#626);
|
||||
#515=AXIS2_PLACEMENT_3D('',#839,#627,#628);
|
||||
#516=AXIS2_PLACEMENT_3D('',#841,#629,#630);
|
||||
#517=AXIS2_PLACEMENT_3D('',#844,#632,#633);
|
||||
#518=AXIS2_PLACEMENT_3D('',#845,#634,#635);
|
||||
#519=AXIS2_PLACEMENT_3D('',#847,#636,#637);
|
||||
#520=AXIS2_PLACEMENT_3D('',#848,#638,#639);
|
||||
#521=AXIS2_PLACEMENT_3D('',#850,#640,#641);
|
||||
#522=AXIS2_PLACEMENT_3D('',#851,#642,#643);
|
||||
#523=AXIS2_PLACEMENT_3D('',#854,#644,#645);
|
||||
#524=AXIS2_PLACEMENT_3D('',#856,#647,#648);
|
||||
#525=AXIS2_PLACEMENT_3D('',#857,#649,#650);
|
||||
#526=AXIS2_PLACEMENT_3D('',#860,#652,#653);
|
||||
#527=AXIS2_PLACEMENT_3D('',#861,#654,#655);
|
||||
#528=AXIS2_PLACEMENT_3D('',#864,#656,#657);
|
||||
#529=AXIS2_PLACEMENT_3D('',#866,#659,#660);
|
||||
#530=AXIS2_PLACEMENT_3D('',#867,#661,#662);
|
||||
#531=AXIS2_PLACEMENT_3D('',#869,#663,#664);
|
||||
#532=AXIS2_PLACEMENT_3D('',#871,#666,#667);
|
||||
#533=AXIS2_PLACEMENT_3D('',#872,#668,#669);
|
||||
#534=AXIS2_PLACEMENT_3D('',#874,#670,#671);
|
||||
#535=AXIS2_PLACEMENT_3D('',#876,#673,#674);
|
||||
#536=AXIS2_PLACEMENT_3D('',#877,#675,#676);
|
||||
#537=AXIS2_PLACEMENT_3D('',#879,#678,#679);
|
||||
#538=DIRECTION('axis',(0.,0.,1.));
|
||||
#539=DIRECTION('refdir',(1.,0.,0.));
|
||||
#540=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#541=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#542=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#543=DIRECTION('ref_axis',(-0.914718354155798,0.404091985283683,0.));
|
||||
#544=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#545=DIRECTION('ref_axis',(-0.914718354155798,0.404091985283683,0.));
|
||||
#546=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#547=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#548=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#549=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#550=DIRECTION('',(0.,0.,-1.));
|
||||
#551=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#552=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#553=DIRECTION('',(0.,0.,1.));
|
||||
#554=DIRECTION('',(0.,0.,-1.));
|
||||
#555=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#556=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#557=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#558=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#559=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#560=DIRECTION('ref_axis',(0.902489931377324,0.430710951523817,0.));
|
||||
#561=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#562=DIRECTION('ref_axis',(0.902489931377324,0.430710951523817,0.));
|
||||
#563=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#564=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#565=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#566=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||
#567=DIRECTION('',(-1.,-1.98254111540207E-16,0.));
|
||||
#568=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#569=DIRECTION('ref_axis',(-0.227318181659297,0.973820540082777,0.));
|
||||
#570=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#571=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||
#572=DIRECTION('',(1.,0.,0.));
|
||||
#573=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#574=DIRECTION('ref_axis',(0.265195148400822,0.964194758990457,0.));
|
||||
#575=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#576=DIRECTION('ref_axis',(0.166497708562777,0.986041841426288,0.));
|
||||
#577=DIRECTION('',(0.,0.,-1.));
|
||||
#578=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#579=DIRECTION('ref_axis',(0.166497708562777,0.986041841426288,0.));
|
||||
#580=DIRECTION('',(0.,0.,1.));
|
||||
#581=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#582=DIRECTION('ref_axis',(-0.227318181659297,0.973820540082777,0.));
|
||||
#583=DIRECTION('',(0.,0.,-1.));
|
||||
#584=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#585=DIRECTION('ref_axis',(-0.227318181659297,0.973820540082777,0.));
|
||||
#586=DIRECTION('center_axis',(-1.98254111540207E-16,1.,0.));
|
||||
#587=DIRECTION('ref_axis',(-1.,-1.98254111540207E-16,0.));
|
||||
#588=DIRECTION('',(0.,0.,1.));
|
||||
#589=DIRECTION('',(-1.,-1.98254111540207E-16,0.));
|
||||
#590=DIRECTION('center_axis',(0.,-1.,0.));
|
||||
#591=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#592=DIRECTION('',(0.,0.,-1.));
|
||||
#593=DIRECTION('',(-1.,0.,0.));
|
||||
#594=DIRECTION('',(0.,0.,-1.));
|
||||
#595=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#596=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#597=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#598=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#599=DIRECTION('',(0.,0.,-1.));
|
||||
#600=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#601=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#602=DIRECTION('',(0.,0.,1.));
|
||||
#603=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#604=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#605=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#606=DIRECTION('ref_axis',(-0.17448917007188,-0.984659093050801,0.));
|
||||
#607=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#608=DIRECTION('ref_axis',(-0.17448917007188,-0.984659093050801,0.));
|
||||
#609=DIRECTION('',(0.,0.,-1.));
|
||||
#610=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#611=DIRECTION('ref_axis',(0.701436943476595,0.712731516299239,0.));
|
||||
#612=DIRECTION('',(0.,0.,1.));
|
||||
#613=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#614=DIRECTION('ref_axis',(0.701436943476595,0.712731516299239,0.));
|
||||
#615=DIRECTION('center_axis',(-0.511399544395539,-0.859343066529332,0.));
|
||||
#616=DIRECTION('ref_axis',(0.859343066529332,-0.511399544395539,0.));
|
||||
#617=DIRECTION('',(0.,0.,-1.));
|
||||
#618=DIRECTION('',(-0.859343066529332,0.511399544395539,0.));
|
||||
#619=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#620=DIRECTION('ref_axis',(0.265195148400822,0.964194758990457,0.));
|
||||
#621=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#622=DIRECTION('ref_axis',(0.265195148400822,0.964194758990457,0.));
|
||||
#623=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#624=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||
#625=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#626=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||
#627=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#628=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#629=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#630=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#631=DIRECTION('',(0.707106781186546,-8.65956056235492E-17,0.707106781186549));
|
||||
#632=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#633=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#634=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#635=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#636=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#637=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||
#638=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#639=DIRECTION('ref_axis',(-0.687645856987837,0.726046262553195,0.));
|
||||
#640=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#641=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#642=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#643=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#644=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#645=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#646=DIRECTION('',(0.,0.,-1.));
|
||||
#647=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#648=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#649=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#650=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#651=DIRECTION('',(-0.707106781186546,8.65956056235492E-17,0.707106781186549));
|
||||
#652=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#653=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#654=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#655=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#656=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#657=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#658=DIRECTION('',(0.,0.,-1.));
|
||||
#659=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#660=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#661=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#662=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#663=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#664=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#665=DIRECTION('',(0.707106781186546,8.65956056235491E-17,-0.707106781186549));
|
||||
#666=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#667=DIRECTION('ref_axis',(1.,0.,0.));
|
||||
#668=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#669=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#670=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#671=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#672=DIRECTION('',(-0.707106781186546,-8.65956056235491E-17,-0.707106781186549));
|
||||
#673=DIRECTION('center_axis',(0.,0.,-1.));
|
||||
#674=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||
#675=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#676=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||
#677=DIRECTION('',(0.,0.,1.));
|
||||
#678=DIRECTION('center_axis',(0.,0.,1.));
|
||||
#679=DIRECTION('ref_axis',(-0.687645856987837,0.726046262553195,0.));
|
||||
#680=CARTESIAN_POINT('',(0.,0.,0.));
|
||||
#681=CARTESIAN_POINT('Origin',(56.15008,33.58978,9.00804));
|
||||
#682=CARTESIAN_POINT('',(50.6247958150228,37.2041966558329,5.02865273728351));
|
||||
#683=CARTESIAN_POINT('',(50.2500667968349,37.371640500346,5.00804));
|
||||
#684=CARTESIAN_POINT('Ctrl Pts',(50.6247958150228,37.2041966558329,5.02865273728351));
|
||||
#685=CARTESIAN_POINT('Ctrl Pts',(50.5357227502342,37.2471651591677,5.01865867292698));
|
||||
#686=CARTESIAN_POINT('Ctrl Pts',(50.4451021174361,37.2885580963717,5.01227776512809));
|
||||
#687=CARTESIAN_POINT('Ctrl Pts',(50.3188228412002,37.3429786608689,5.00854341432407));
|
||||
#688=CARTESIAN_POINT('Ctrl Pts',(50.2844922321955,37.3574503025008,5.00804000000001));
|
||||
#689=CARTESIAN_POINT('Ctrl Pts',(50.2500667968359,37.3716405003456,5.00804));
|
||||
#690=CARTESIAN_POINT('',(49.3915707992385,35.4432033258548,5.00804));
|
||||
#691=CARTESIAN_POINT('Origin',(56.15008,33.58978,5.00804));
|
||||
#692=CARTESIAN_POINT('',(50.5009650642326,34.9087067416334,5.19449159161523));
|
||||
#693=CARTESIAN_POINT('Ctrl Pts',(49.3915707992386,35.4432033258547,5.00804));
|
||||
#694=CARTESIAN_POINT('Ctrl Pts',(49.6951751671788,35.328531451996,5.00804000000001));
|
||||
#695=CARTESIAN_POINT('Ctrl Pts',(49.9860105158439,35.1945427153753,5.04710404861977));
|
||||
#696=CARTESIAN_POINT('Ctrl Pts',(50.3432741314213,35.0005095939757,5.14244590473823));
|
||||
#697=CARTESIAN_POINT('Ctrl Pts',(50.4231029442769,34.9550428956352,5.16715902818914));
|
||||
#698=CARTESIAN_POINT('Ctrl Pts',(50.5009650642326,34.9087067416334,5.19449159161523));
|
||||
#699=CARTESIAN_POINT('',(50.865434714585,34.6918089502903,5.34623350576054));
|
||||
#700=CARTESIAN_POINT('Ctrl Pts',(50.5009650642326,34.9087067416334,5.19449159161523));
|
||||
#701=CARTESIAN_POINT('Ctrl Pts',(50.6092970149861,34.8442378322808,5.2325202237245));
|
||||
#702=CARTESIAN_POINT('Ctrl Pts',(50.713867355334,34.7820074769152,5.27543332367862));
|
||||
#703=CARTESIAN_POINT('Ctrl Pts',(50.8300172908763,34.7128860440073,5.32928148605159));
|
||||
#704=CARTESIAN_POINT('Ctrl Pts',(50.8476922638109,34.702367575356,5.33765072778525));
|
||||
#705=CARTESIAN_POINT('Ctrl Pts',(50.865434714585,34.6918089502903,5.34623350576053));
|
||||
#706=CARTESIAN_POINT('',(53.5900419872343,32.0103782098292,9.00804));
|
||||
#707=CARTESIAN_POINT('Ctrl Pts',(50.865434714585,34.6918089502903,5.34623350576054));
|
||||
#708=CARTESIAN_POINT('Ctrl Pts',(51.1121207963903,34.5450047753834,5.46556605438542));
|
||||
#709=CARTESIAN_POINT('Ctrl Pts',(51.3409384813757,34.3909239972629,5.61283853761381));
|
||||
#710=CARTESIAN_POINT('Ctrl Pts',(51.9985611380572,33.901436736254,6.14034807784202));
|
||||
#711=CARTESIAN_POINT('Ctrl Pts',(52.36002697223,33.5624215607093,6.59035964936713));
|
||||
#712=CARTESIAN_POINT('Ctrl Pts',(53.0622110060386,32.7998916705579,7.71732122046303));
|
||||
#713=CARTESIAN_POINT('Ctrl Pts',(53.3621670790386,32.3792556992102,8.42174702507106));
|
||||
#714=CARTESIAN_POINT('Ctrl Pts',(53.5883907362628,32.0130538273486,9.00378851990973));
|
||||
#715=CARTESIAN_POINT('Ctrl Pts',(53.5892165587142,32.0117161394183,9.00591426074358));
|
||||
#716=CARTESIAN_POINT('Ctrl Pts',(53.5900419872343,32.0103782098292,9.00804));
|
||||
#717=CARTESIAN_POINT('',(55.5936905952374,36.545915225572,9.00804));
|
||||
#718=CARTESIAN_POINT('Origin',(56.15008,33.58978,9.00804));
|
||||
#719=CARTESIAN_POINT('Ctrl Pts',(55.5936905952374,36.545915225572,9.00804));
|
||||
#720=CARTESIAN_POINT('Ctrl Pts',(55.592145656931,36.5456244447927,9.00591426074139));
|
||||
#721=CARTESIAN_POINT('Ctrl Pts',(55.5906006319998,36.5453341179705,9.003788519914));
|
||||
#722=CARTESIAN_POINT('Ctrl Pts',(55.1675385371182,36.4659649486835,8.42174695117465));
|
||||
#723=CARTESIAN_POINT('Ctrl Pts',(54.6545826862427,36.4044463028556,7.71732117907136));
|
||||
#724=CARTESIAN_POINT('Ctrl Pts',(53.6180100302521,36.4100409995902,6.59035964936721));
|
||||
#725=CARTESIAN_POINT('Ctrl Pts',(53.1239713487764,36.4489591152896,6.14034807784204));
|
||||
#726=CARTESIAN_POINT('Ctrl Pts',(52.1544325475448,36.6375433694353,5.50479228867297));
|
||||
#727=CARTESIAN_POINT('Ctrl Pts',(51.706839390841,36.7599974653572,5.28734773854807));
|
||||
#728=CARTESIAN_POINT('Ctrl Pts',(51.0368192247517,37.0161904928946,5.09359272486355));
|
||||
#729=CARTESIAN_POINT('Ctrl Pts',(50.8294613797647,37.1054667718539,5.05161636663702));
|
||||
#730=CARTESIAN_POINT('Ctrl Pts',(50.6247958150228,37.2041966558329,5.02865273728351));
|
||||
#731=CARTESIAN_POINT('Origin',(56.15008,33.58978,8.34898816748364E-16));
|
||||
#732=CARTESIAN_POINT('',(59.15812,33.58978,11.02948));
|
||||
#733=CARTESIAN_POINT('Origin',(56.15008,33.58978,11.02948));
|
||||
#734=CARTESIAN_POINT('',(59.15812,33.58978,8.34898816748364E-16));
|
||||
#735=CARTESIAN_POINT('',(59.15812,33.58978,8.34898816748364E-16));
|
||||
#736=CARTESIAN_POINT('',(55.5936905952374,36.545915225572,8.34898816748364E-16));
|
||||
#737=CARTESIAN_POINT('Origin',(56.15008,33.58978,8.34898816748364E-16));
|
||||
#738=CARTESIAN_POINT('',(55.5936905952374,36.545915225572,8.34898816748364E-16));
|
||||
#739=CARTESIAN_POINT('',(53.5900419872343,32.0103782098292,8.34898816748364E-16));
|
||||
#740=CARTESIAN_POINT('',(53.5900419872343,32.0103782098292,8.34898816748364E-16));
|
||||
#741=CARTESIAN_POINT('Origin',(56.15008,33.58978,8.34898816748364E-16));
|
||||
#742=CARTESIAN_POINT('Origin',(-56.15008,33.58978,9.00804));
|
||||
#743=CARTESIAN_POINT('',(-55.6492482327348,36.5558333006839,9.00804));
|
||||
#744=CARTESIAN_POINT('',(-50.8690026990792,37.2211675600968,5.05313309133144));
|
||||
#745=CARTESIAN_POINT('Ctrl Pts',(-50.8690026990792,37.2211675600968,5.05313309133144));
|
||||
#746=CARTESIAN_POINT('Ctrl Pts',(-51.0145997406747,37.1519340562777,5.07724190703958));
|
||||
#747=CARTESIAN_POINT('Ctrl Pts',(-51.1614075276573,37.0875150337691,5.11089878051668));
|
||||
#748=CARTESIAN_POINT('Ctrl Pts',(-51.7670974898426,36.8427986295485,5.28734773854807));
|
||||
#749=CARTESIAN_POINT('Ctrl Pts',(-52.2123145225646,36.7119688419987,5.50479228867298));
|
||||
#750=CARTESIAN_POINT('Ctrl Pts',(-53.1781446766363,36.5052283730743,6.14034807784203));
|
||||
#751=CARTESIAN_POINT('Ctrl Pts',(-53.6713662685796,36.4570485041999,6.59035964936717));
|
||||
#752=CARTESIAN_POINT('Ctrl Pts',(-54.7076513859303,36.4320077753044,7.71732102739605));
|
||||
#753=CARTESIAN_POINT('Ctrl Pts',(-55.2216710420583,36.4838920515183,8.42174668038323));
|
||||
#754=CARTESIAN_POINT('Ctrl Pts',(-55.6461479112677,36.5553102658067,9.00378851994531));
|
||||
#755=CARTESIAN_POINT('Ctrl Pts',(-55.6476981110072,36.5555715554873,9.00591426070426));
|
||||
#756=CARTESIAN_POINT('Ctrl Pts',(-55.6492482327348,36.5558333006839,9.00804));
|
||||
#757=CARTESIAN_POINT('',(-53.5291859784223,32.1135621403131,9.00804));
|
||||
#758=CARTESIAN_POINT('Origin',(-56.15008,33.58978,9.00804));
|
||||
#759=CARTESIAN_POINT('',(-52.2816789701062,33.7786037525209,6.52377627814055));
|
||||
#760=CARTESIAN_POINT('Ctrl Pts',(-53.5291859784223,32.1135621403131,9.00804));
|
||||
#761=CARTESIAN_POINT('Ctrl Pts',(-53.5284144759865,32.1149318745353,9.00591426073462));
|
||||
#762=CARTESIAN_POINT('Ctrl Pts',(-53.5276425703196,32.1163013829575,9.00378851991685));
|
||||
#763=CARTESIAN_POINT('Ctrl Pts',(-53.3161791000315,32.4912203499456,8.421746904257));
|
||||
#764=CARTESIAN_POINT('Ctrl Pts',(-53.0332091000439,32.923465901452,7.71732115279223));
|
||||
#765=CARTESIAN_POINT('Ctrl Pts',(-52.5383121465054,33.5058147781869,6.88645852589308));
|
||||
#766=CARTESIAN_POINT('Ctrl Pts',(-52.4152132167845,33.641733996463,6.70051126035222));
|
||||
#767=CARTESIAN_POINT('Ctrl Pts',(-52.2816789701062,33.7786037525209,6.52377627814055));
|
||||
#768=CARTESIAN_POINT('',(-49.4228448227586,35.5536872054672,5.00804));
|
||||
#769=CARTESIAN_POINT('Ctrl Pts',(-52.2816789701062,33.7786037525209,6.52377627814055));
|
||||
#770=CARTESIAN_POINT('Ctrl Pts',(-52.0283995813855,34.0382097260861,6.188556442245));
|
||||
#771=CARTESIAN_POINT('Ctrl Pts',(-51.7254354644008,34.3097161939923,5.87034180686871));
|
||||
#772=CARTESIAN_POINT('Ctrl Pts',(-50.9861359604753,34.8410968297498,5.35362337513694));
|
||||
#773=CARTESIAN_POINT('Ctrl Pts',(-50.5662347209846,35.0890773541913,5.16508026972491));
|
||||
#774=CARTESIAN_POINT('Ctrl Pts',(-49.8740938940358,35.3944054481485,5.02954756629323));
|
||||
#775=CARTESIAN_POINT('Ctrl Pts',(-49.6508407134816,35.4797540591315,5.00804));
|
||||
#776=CARTESIAN_POINT('Ctrl Pts',(-49.4228448227586,35.5536872054672,5.00804));
|
||||
#777=CARTESIAN_POINT('',(-50.3070040221276,37.4590289915242,5.00804));
|
||||
#778=CARTESIAN_POINT('Origin',(-56.15008,33.58978,5.00804));
|
||||
#779=CARTESIAN_POINT('Ctrl Pts',(-50.3070040221276,37.4590289915242,5.00804));
|
||||
#780=CARTESIAN_POINT('Ctrl Pts',(-50.4981604245898,37.3877544004905,5.00804));
|
||||
#781=CARTESIAN_POINT('Ctrl Pts',(-50.685995630357,37.3081900739412,5.02282970300183));
|
||||
#782=CARTESIAN_POINT('Ctrl Pts',(-50.8690026990792,37.2211675600968,5.05313309133144));
|
||||
#783=CARTESIAN_POINT('Origin',(-0.143365748922946,36.1667324932162,5.00804));
|
||||
#784=CARTESIAN_POINT('',(47.5752549255443,37.901304,5.00804));
|
||||
#785=CARTESIAN_POINT('Origin',(47.5752549255443,30.882544,5.00804));
|
||||
#786=CARTESIAN_POINT('',(-47.8548953186122,37.901304,5.00804));
|
||||
#787=CARTESIAN_POINT('',(24.625115448216,37.901304,5.00804));
|
||||
#788=CARTESIAN_POINT('Origin',(-47.8548953186122,30.882544,5.00804));
|
||||
#789=CARTESIAN_POINT('',(-47.2578282212087,35.895944,5.00804));
|
||||
#790=CARTESIAN_POINT('Origin',(-47.2578282212087,28.877184,5.00804));
|
||||
#791=CARTESIAN_POINT('',(46.911574398011,35.895944,5.00804));
|
||||
#792=CARTESIAN_POINT('',(-24.7012950035171,35.895944,5.00804));
|
||||
#793=CARTESIAN_POINT('Origin',(46.911574398011,28.877184,5.00804));
|
||||
#794=CARTESIAN_POINT('Origin',(-54.313696853361,44.4653087691744,8.34898816748364E-16));
|
||||
#795=CARTESIAN_POINT('',(-50.8690027014949,37.2211675589481,8.34898816748364E-16));
|
||||
#796=CARTESIAN_POINT('',(-50.8690027014949,37.2211675589481,8.34898816748364E-16));
|
||||
#797=CARTESIAN_POINT('',(-55.6492482327348,36.5558333006839,8.34898816748364E-16));
|
||||
#798=CARTESIAN_POINT('Origin',(-54.313696853361,44.4653087691744,8.34898816748364E-16));
|
||||
#799=CARTESIAN_POINT('',(-55.6492482327348,36.5558333006839,8.34898816748364E-16));
|
||||
#800=CARTESIAN_POINT('Origin',(-47.8548953186122,30.882544,8.34898816748364E-16));
|
||||
#801=CARTESIAN_POINT('',(-47.8548953186122,37.901304,8.34898816748364E-16));
|
||||
#802=CARTESIAN_POINT('',(-47.8548953186122,37.901304,8.34898816748364E-16));
|
||||
#803=CARTESIAN_POINT('Origin',(-47.8548953186122,30.882544,8.34898816748364E-16));
|
||||
#804=CARTESIAN_POINT('Origin',(49.393596645355,37.901304,8.34898816748364E-16));
|
||||
#805=CARTESIAN_POINT('',(47.5752549255443,37.901304,8.34898816748364E-16));
|
||||
#806=CARTESIAN_POINT('',(47.5752549255443,37.901304,8.34898816748364E-16));
|
||||
#807=CARTESIAN_POINT('',(56.15008,37.901304,8.34898816748364E-16));
|
||||
#808=CARTESIAN_POINT('Origin',(-49.2592242581112,35.895944,8.34898816748364E-16));
|
||||
#809=CARTESIAN_POINT('',(-47.2578282212087,35.895944,8.34898816748364E-16));
|
||||
#810=CARTESIAN_POINT('',(-47.2578282212087,35.895944,8.34898816748364E-16));
|
||||
#811=CARTESIAN_POINT('',(46.911574398011,35.895944,8.34898816748364E-16));
|
||||
#812=CARTESIAN_POINT('',(3.44542787094439,35.895944,8.34898816748364E-16));
|
||||
#813=CARTESIAN_POINT('',(46.911574398011,35.895944,8.34898816748364E-16));
|
||||
#814=CARTESIAN_POINT('Origin',(-56.15008,33.58978,8.34898816748364E-16));
|
||||
#815=CARTESIAN_POINT('',(-59.15812,33.58978,11.02948));
|
||||
#816=CARTESIAN_POINT('Origin',(-56.15008,33.58978,11.02948));
|
||||
#817=CARTESIAN_POINT('',(-59.15812,33.58978,8.34898816748364E-16));
|
||||
#818=CARTESIAN_POINT('',(-59.15812,33.58978,8.34898816748364E-16));
|
||||
#819=CARTESIAN_POINT('',(-53.5291859784223,32.1135621403131,8.34898816748364E-16));
|
||||
#820=CARTESIAN_POINT('Origin',(-56.15008,33.58978,8.34898816748364E-16));
|
||||
#821=CARTESIAN_POINT('',(-53.5291859784223,32.1135621403131,8.34898816748364E-16));
|
||||
#822=CARTESIAN_POINT('Origin',(-56.15008,33.58978,8.34898816748364E-16));
|
||||
#823=CARTESIAN_POINT('Origin',(54.1099855158704,44.4289424937642,8.34898816748364E-16));
|
||||
#824=CARTESIAN_POINT('',(50.6247958676965,37.2041966304233,8.34898816748364E-16));
|
||||
#825=CARTESIAN_POINT('Origin',(54.1099855158704,44.4289424937642,8.34898816748364E-16));
|
||||
#826=CARTESIAN_POINT('',(50.6247958676965,37.2041966304233,8.34898816748364E-16));
|
||||
#827=CARTESIAN_POINT('Origin',(46.7632739531924,27.7986401027071,8.34898816748364E-16));
|
||||
#828=CARTESIAN_POINT('',(50.8654347145886,34.6918089502882,8.34898816748364E-16));
|
||||
#829=CARTESIAN_POINT('',(50.8654347145886,34.6918089502882,8.34898816748364E-16));
|
||||
#830=CARTESIAN_POINT('Origin',(46.7632739531924,27.7986401027071,8.34898816748364E-16));
|
||||
#831=CARTESIAN_POINT('Origin',(48.6050463004756,36.0369778940524,8.34898816748364E-16));
|
||||
#832=CARTESIAN_POINT('',(50.5009650642326,34.9087067416334,8.34898816748364E-16));
|
||||
#833=CARTESIAN_POINT('',(50.5009650642326,34.9087067416334,8.34898816748364E-16));
|
||||
#834=CARTESIAN_POINT('',(51.9286708844819,34.0590715558221,8.34898816748364E-16));
|
||||
#835=CARTESIAN_POINT('Origin',(46.911574398011,28.877184,8.34898816748364E-16));
|
||||
#836=CARTESIAN_POINT('Origin',(46.911574398011,28.877184,8.34898816748364E-16));
|
||||
#837=CARTESIAN_POINT('Origin',(47.5752549255443,30.882544,8.34898816748364E-16));
|
||||
#838=CARTESIAN_POINT('Origin',(47.5752549255443,30.882544,8.34898816748364E-16));
|
||||
#839=CARTESIAN_POINT('Origin',(-56.15008,33.58978,0.250670000000001));
|
||||
#840=CARTESIAN_POINT('',(-57.90477,33.58978,8.34898816748364E-16));
|
||||
#841=CARTESIAN_POINT('Origin',(-56.15008,33.58978,8.34898816748364E-16));
|
||||
#842=CARTESIAN_POINT('',(-57.30343,33.58978,0.601340000000002));
|
||||
#843=CARTESIAN_POINT('',(-57.6541,33.58978,0.250670000000001));
|
||||
#844=CARTESIAN_POINT('Origin',(-56.15008,33.58978,0.601340000000002));
|
||||
#845=CARTESIAN_POINT('Origin',(56.15008,33.58978,8.34898816748364E-16));
|
||||
#846=CARTESIAN_POINT('',(-52.2816789901629,33.7786037319632,8.34898816748364E-16));
|
||||
#847=CARTESIAN_POINT('Origin',(-47.2578282212087,28.877184,8.34898816748364E-16));
|
||||
#848=CARTESIAN_POINT('Origin',(-46.5401352542153,28.1769811811481,8.34898816748364E-16));
|
||||
#849=CARTESIAN_POINT('',(57.90477,33.58978,8.34898816748364E-16));
|
||||
#850=CARTESIAN_POINT('Origin',(56.15008,33.58978,8.34898816748364E-16));
|
||||
#851=CARTESIAN_POINT('Origin',(-56.15008,33.58978,-2.83875875713276));
|
||||
#852=CARTESIAN_POINT('',(-57.30343,33.58978,10.42814));
|
||||
#853=CARTESIAN_POINT('',(-54.99673,33.58978,10.42814));
|
||||
#854=CARTESIAN_POINT('Origin',(-56.15008,33.58978,10.42814));
|
||||
#855=CARTESIAN_POINT('',(-57.30343,33.58978,-2.83875875713276));
|
||||
#856=CARTESIAN_POINT('Origin',(-56.15008,33.58978,10.42814));
|
||||
#857=CARTESIAN_POINT('Origin',(56.15008,33.58978,0.250670000000001));
|
||||
#858=CARTESIAN_POINT('',(57.30343,33.58978,0.601340000000002));
|
||||
#859=CARTESIAN_POINT('',(57.6541,33.58978,0.250670000000001));
|
||||
#860=CARTESIAN_POINT('Origin',(56.15008,33.58978,0.601340000000002));
|
||||
#861=CARTESIAN_POINT('Origin',(56.15008,33.58978,-2.83875875713276));
|
||||
#862=CARTESIAN_POINT('',(57.30343,33.58978,10.42814));
|
||||
#863=CARTESIAN_POINT('',(54.99673,33.58978,10.42814));
|
||||
#864=CARTESIAN_POINT('Origin',(56.15008,33.58978,10.42814));
|
||||
#865=CARTESIAN_POINT('',(57.30343,33.58978,-2.83875875713276));
|
||||
#866=CARTESIAN_POINT('Origin',(56.15008,33.58978,10.42814));
|
||||
#867=CARTESIAN_POINT('Origin',(56.15008,33.58978,10.77881));
|
||||
#868=CARTESIAN_POINT('',(54.39539,33.58978,11.02948));
|
||||
#869=CARTESIAN_POINT('Origin',(56.15008,33.58978,11.02948));
|
||||
#870=CARTESIAN_POINT('',(54.64606,33.58978,10.77881));
|
||||
#871=CARTESIAN_POINT('Origin',(56.15008,33.58978,11.02948));
|
||||
#872=CARTESIAN_POINT('Origin',(-56.15008,33.58978,10.77881));
|
||||
#873=CARTESIAN_POINT('',(-54.39539,33.58978,11.02948));
|
||||
#874=CARTESIAN_POINT('Origin',(-56.15008,33.58978,11.02948));
|
||||
#875=CARTESIAN_POINT('',(-54.64606,33.58978,10.77881));
|
||||
#876=CARTESIAN_POINT('Origin',(-56.15008,33.58978,11.02948));
|
||||
#877=CARTESIAN_POINT('Origin',(-47.2578282212087,28.877184,8.34898816748364E-16));
|
||||
#878=CARTESIAN_POINT('',(-52.2816789901629,33.7786037319632,8.34898816748364E-16));
|
||||
#879=CARTESIAN_POINT('Origin',(-46.5401352542153,28.1769811811481,8.34898816748364E-16));
|
||||
#880=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#884,
|
||||
'DISTANCE_ACCURACY_VALUE',
|
||||
'Maximum model space distance between geometric entities at asserted c
|
||||
onnectivities');
|
||||
#881=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#884,
|
||||
'DISTANCE_ACCURACY_VALUE',
|
||||
'Maximum model space distance between geometric entities at asserted c
|
||||
onnectivities');
|
||||
#882=(
|
||||
GEOMETRIC_REPRESENTATION_CONTEXT(3)
|
||||
GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#880))
|
||||
GLOBAL_UNIT_ASSIGNED_CONTEXT((#884,#886,#887))
|
||||
REPRESENTATION_CONTEXT('','3D')
|
||||
);
|
||||
#883=(
|
||||
GEOMETRIC_REPRESENTATION_CONTEXT(3)
|
||||
GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#881))
|
||||
GLOBAL_UNIT_ASSIGNED_CONTEXT((#884,#886,#887))
|
||||
REPRESENTATION_CONTEXT('','3D')
|
||||
);
|
||||
#884=(
|
||||
LENGTH_UNIT()
|
||||
NAMED_UNIT(*)
|
||||
SI_UNIT(.MILLI.,.METRE.)
|
||||
);
|
||||
#885=(
|
||||
LENGTH_UNIT()
|
||||
NAMED_UNIT(*)
|
||||
SI_UNIT(.CENTI.,.METRE.)
|
||||
);
|
||||
#886=(
|
||||
NAMED_UNIT(*)
|
||||
PLANE_ANGLE_UNIT()
|
||||
SI_UNIT($,.RADIAN.)
|
||||
);
|
||||
#887=(
|
||||
NAMED_UNIT(*)
|
||||
SI_UNIT($,.STERADIAN.)
|
||||
SOLID_ANGLE_UNIT()
|
||||
);
|
||||
#888=SHAPE_DEFINITION_REPRESENTATION(#889,#890);
|
||||
#889=PRODUCT_DEFINITION_SHAPE('',$,#892);
|
||||
#890=SHAPE_REPRESENTATION('',(#480),#882);
|
||||
#891=PRODUCT_DEFINITION_CONTEXT('part definition',#896,'design');
|
||||
#892=PRODUCT_DEFINITION('revisited_support','revisited_support',#893,#891);
|
||||
#893=PRODUCT_DEFINITION_FORMATION('',$,#898);
|
||||
#894=PRODUCT_RELATED_PRODUCT_CATEGORY('revisited_support',
|
||||
'revisited_support',(#898));
|
||||
#895=APPLICATION_PROTOCOL_DEFINITION('international standard',
|
||||
'automotive_design',2009,#896);
|
||||
#896=APPLICATION_CONTEXT(
|
||||
'Core Data for Automotive Mechanical Design Process');
|
||||
#897=PRODUCT_CONTEXT('part definition',#896,'mechanical');
|
||||
#898=PRODUCT('revisited_support','revisited_support',$,(#897));
|
||||
#899=PRESENTATION_STYLE_ASSIGNMENT((#900));
|
||||
#900=SURFACE_STYLE_USAGE(.BOTH.,#903);
|
||||
#901=SURFACE_STYLE_RENDERING_WITH_PROPERTIES($,#907,(#902));
|
||||
#902=SURFACE_STYLE_TRANSPARENT(0.);
|
||||
#903=SURFACE_SIDE_STYLE('',(#904,#901));
|
||||
#904=SURFACE_STYLE_FILL_AREA(#905);
|
||||
#905=FILL_AREA_STYLE('',(#906));
|
||||
#906=FILL_AREA_STYLE_COLOUR('',#907);
|
||||
#907=COLOUR_RGB('',0.749019607843137,0.749019607843137,0.749019607843137);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,62 @@
|
||||
f=88200000,m=WFM,bw=200k,d=RMF Polkowice
|
||||
f=88200000,m=WFM,bw=200k,d=RMF Kielce
|
||||
f=89200000,m=WFM,bw=200k,d=RMF Bielsko-Biala
|
||||
f=89300000,m=WFM,bw=200k,d=RMF Lublin
|
||||
f=89300000,m=WFM,bw=200k,d=RMF Koszalin
|
||||
f=90600000,m=WFM,bw=200k,d=RMF Warsaw
|
||||
f=91000000,m=WFM,bw=200k,d=RMF Warsaw
|
||||
f=91300000,m=WFM,bw=200k,d=RMF Łobez
|
||||
f=91500000,m=WFM,bw=200k,d=RMF Ostroleka
|
||||
f=91700000,m=WFM,bw=200k,d=RMF Wagrowiec
|
||||
f=91900000,m=WFM,bw=200k,d=RMF Siedlce
|
||||
f=92500000,m=WFM,bw=200k,d=NRK Oslo
|
||||
f=92600000,m=WFM,bw=200k,d=RMF Elbląg
|
||||
f=92900000,m=WFM,bw=200k,d=RMF Wroclaw
|
||||
f=93000000,m=WFM,bw=200k,d=RMF Katowice
|
||||
f=93300000,m=WFM,bw=200k,d=RMF Bydgoszcz
|
||||
f=93500000,m=WFM,bw=200k,d=RMF Lodz
|
||||
f=93600000,m=WFM,bw=200k,d=RMF Ryki
|
||||
f=93800000,m=WFM,bw=200k,d=RMF Luban
|
||||
f=94300000,m=WFM,bw=200k,d=RMF Płock
|
||||
f=94600000,m=WFM,bw=200k,d=RMF Poznan
|
||||
f=94800000,m=WFM,bw=200k,d=NRK Bergen
|
||||
f=94800000,m=WFM,bw=200k,d=RMF Zagan
|
||||
f=95100000,m=WFM,bw=200k,d=RMF Suwałki
|
||||
f=95300000,m=WFM,bw=200k,d=RMF Olsztyn
|
||||
f=95400000,m=WFM,bw=200k,d=RMF Tarnow
|
||||
f=96000000,m=WFM,bw=200k,d=RMF Krakow
|
||||
f=96100000,m=WFM,bw=200k,d=RMF Legnica
|
||||
f=96100000,m=WFM,bw=200k,d=RMF Gorzow Wielkopolski
|
||||
f=96400000,m=WFM,bw=200k,d=RMF Bialogard
|
||||
f=96600000,m=WFM,bw=200k,d=RMF Walcz
|
||||
f=97100000,m=WFM,bw=200k,d=RMF Włoszczowa
|
||||
f=97200000,m=WFM,bw=200k,d=NRK Melhus
|
||||
f=98000000,m=WFM,bw=200k,d=RMF Kalisz
|
||||
f=98400000,m=WFM,bw=200k,d=RMF Gdansk
|
||||
f=98600000,m=WFM,bw=200k,d=NRK Arendal
|
||||
f=98900000,m=WFM,bw=200k,d=RMF Konin
|
||||
f=99300000,m=WFM,bw=200k,d=RMF Opole
|
||||
f=99500000,m=WFM,bw=200k,d=RMF Kluczbork
|
||||
f=100100000,m=WFM,bw=200k,d=RMF Rzeszow
|
||||
f=100200000,m=WFM,bw=200k,d=RMF Bialystok
|
||||
f=100800000,m=WFM,bw=200k,d=RMF Jelenia Gora
|
||||
f=100900000,m=WFM,bw=200k,d=RMF Slupsk
|
||||
f=101100000,m=WFM,bw=200k,d=RMF Solina
|
||||
f=101200000,m=WFM,bw=200k,d=RMF Swinoujscie
|
||||
f=101600000,m=WFM,bw=200k,d=RMF Klodzko
|
||||
f=101800000,m=WFM,bw=200k,d=RMF Zakopane
|
||||
f=101800000,m=WFM,bw=200k,d=RMF Leżajsk
|
||||
f=102000000,m=WFM,bw=200k,d=RMF Gizycko
|
||||
f=102900000,m=WFM,bw=200k,d=RMF Walbrzych
|
||||
f=103200000,m=WFM,bw=200k,d=RMF Szczawnica
|
||||
f=103400000,m=WFM,bw=200k,d=RMF Przemyśl
|
||||
f=103400000,m=WFM,bw=200k,d=RMF Lebork
|
||||
f=104700000,m=WFM,bw=200k,d=RMF Rabka
|
||||
f=104900000,m=WFM,bw=200k,d=RMF Koszalin
|
||||
f=105900000,m=WFM,bw=200k,d=RMF Krynica
|
||||
f=105900000,m=WFM,bw=200k,d=RMF Czestochowa
|
||||
f=106400000,m=WFM,bw=200k,d=RMF Zielona Gora
|
||||
f=106500000,m=WFM,bw=200k,d=RMF Elk
|
||||
f=106700000,m=WFM,bw=200k,d=RMF Szczecin
|
||||
f=107400000,m=WFM,bw=200k,d=RMF Iława
|
||||
f=107700000,m=WFM,bw=200k,d=RMF Zamosc
|
||||
@@ -0,0 +1,5 @@
|
||||
f=863000000,d=WaterMeter
|
||||
f=868000000,d=WaterMeter: ETW-ECO, Zenner
|
||||
f=868600000,d=WaterMeter: Ecomess
|
||||
f=868950000,d=WaterMeter: Apator/Santech/Techem
|
||||
f=874400000,d=WaterMeter
|
||||
@@ -1,18 +1,22 @@
|
||||
# INI,END,DESCRIPTION
|
||||
# (Freq range in MHz, min separation 240MHz)
|
||||
# INI,END,DESCRIPTION
|
||||
# (Freq range in MHz, min separation 3MHz)
|
||||
# (Description up to 20 char)
|
||||
# (fields comma delimiter)
|
||||
260,500,315/433 MHz KEYFOBS
|
||||
2320,2560,BL / WIFI 2.4GHz
|
||||
5160,5900,WIFI 5GHz
|
||||
10,7250,FULL RANGE
|
||||
140,380,VHF MICS AND MARINE
|
||||
260,500,315/433 MHz KEYFOBS
|
||||
390,420,RADIOSONDES
|
||||
420,660,UHF MICS
|
||||
|
||||
# https://www.fcc.gov/wireless/bureau-divisions/mobility-division/paging
|
||||
35,36,USA PAGERS 35
|
||||
43,44,USA PAGERS 44
|
||||
152,159,USA PAGERS 152
|
||||
454,460,USA PAGERS 454
|
||||
929,932,USA PAGERS 930
|
||||
# WATER METERS
|
||||
850,900,Water meters
|
||||
902,928,ISM 900MHz
|
||||
# PAGERS https://www.fcc.gov/wireless/bureau-divisions/mobility-division/paging
|
||||
34,36,USA PAGERS 35
|
||||
43,45,USA PAGERS 44
|
||||
151,153,USA PAGERS 152
|
||||
453,454,USA PAGERS 454
|
||||
929,931,USA PAGERS 930
|
||||
# WIFI
|
||||
2320,2560,BL / WIFI 2.4GHz
|
||||
5160,5900,WIFI 5GHz
|
||||
# FULL
|
||||
10,7250,FULL RANGE
|
||||
|
||||
Reference in New Issue
Block a user