mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-22 07:29:03 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1733cbd2a | |||
| 4ec2d64cb7 | |||
| d370dae170 | |||
| 72f0a1be54 | |||
| a2e5e03f07 | |||
| 47eda54d6a | |||
| db81b9b1e1 | |||
| b9de1918b4 | |||
| b87d26f271 |
@@ -0,0 +1,41 @@
|
||||
FROM ubuntu:xenial
|
||||
|
||||
# Set location to download ARM toolkit from.
|
||||
# This will need to be changed over time or replaced with a static link to the latest release.
|
||||
ENV ARMBINURL=https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/gcc-arm-none-eabi-9-2019-q4-major-aarch64-linux.tar.bz2?revision=4583ce78-e7e7-459a-ad9f-bff8e94839f1&rev=4583ce78e7e7459aad9fbff8e94839f1&hash=C9B942D74CEA05FF9DE28380F267BB7D3F3B17A6 \
|
||||
PATH=$HOME/bin:$PATH:/opt/build/armbin/bin
|
||||
|
||||
#Create volume /havoc/bin for compiled firmware binaries
|
||||
VOLUME /havoc
|
||||
WORKDIR /havoc/firmware
|
||||
|
||||
# Fetch dependencies from APT
|
||||
RUN apt-get update && \
|
||||
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
|
||||
RUN curl https://bootstrap.pypa.io/pip/3.4/get-pip.py -o get-pip.py && \
|
||||
python3 get-pip.py
|
||||
|
||||
#Fetch additional dependencies from Python 3.x pip
|
||||
RUN pip install pyyaml
|
||||
RUN ln -s /usr/bin/python3 /usr/bin/python && \
|
||||
ln -s /usr/bin/pip3 /usr/bin/pip
|
||||
|
||||
ENV LANG C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
# Grab the GNU ARM toolchain from arm.com
|
||||
# Then extract contents to /opt/build/armbin/
|
||||
RUN mkdir /opt/build && cd /opt/build && \
|
||||
wget -O gcc-arm-none-eabi $ARMBINURL && \
|
||||
mkdir armbin && \
|
||||
tar --strip=1 -xjvf gcc-arm-none-eabi -C armbin
|
||||
|
||||
# Configure CCACHE
|
||||
RUN mkdir ~/bin && cd ~/bin && \
|
||||
for tool in gcc g++ cpp c++;do ln -s $(which ccache) arm-none-eabi-$tool;done
|
||||
|
||||
CMD cd .. && cd build && \
|
||||
cmake .. && make firmware
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
enable_language(C CXX ASM)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
project(application)
|
||||
|
||||
# Compiler options here.
|
||||
@@ -36,7 +38,13 @@ set(USE_OPT "-Os -g --specs=nano.specs")
|
||||
set(USE_COPT "-std=gnu99")
|
||||
|
||||
# C++ specific options here (added to USE_OPT).
|
||||
set(USE_CPPOPT "-std=c++17 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
|
||||
check_cxx_compiler_flag("-std=c++20" cpp20_supported)
|
||||
if(cpp20_supported)
|
||||
set(USE_CPPOPT "-std=c++20")
|
||||
else()
|
||||
set(USE_CPPOPT "-std=c++17")
|
||||
endif()
|
||||
set(USE_CPPOPT "${USE_CPPOPT} -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized -Wno-volatile")
|
||||
|
||||
# Enable this if you want the linker to remove unused code and data
|
||||
set(USE_LINK_GC yes)
|
||||
|
||||
@@ -38,10 +38,6 @@
|
||||
|
||||
namespace std {
|
||||
|
||||
constexpr bool operator==(const tpms::TransponderID& lhs, const tpms::TransponderID& rhs) {
|
||||
return (lhs.value() == rhs.value());
|
||||
}
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
struct TPMSRecentEntry {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "radio.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "crc.hpp"
|
||||
|
||||
#include "audio.hpp"
|
||||
|
||||
@@ -381,22 +382,35 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
|
||||
{"Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav]() { nav.push<DebugPeripheralsMenuView>(); }},
|
||||
{"Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav]() { nav.push<TemperatureView>(); }},
|
||||
{"Buttons Test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav]() { nav.push<DebugControlsView>(); }},
|
||||
{"Pmem", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugPmemView>(); }},
|
||||
{"P.Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugPmemView>(); }},
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
/* DebugPmemView *********************************************************/
|
||||
|
||||
uint32_t pmem_checksum(volatile const uint32_t data[63]) {
|
||||
CRC<32> crc{0x04c11db7, 0xffffffff, 0xffffffff};
|
||||
for (size_t i = 0; i < 63; i++) {
|
||||
const auto word = data[i];
|
||||
crc.process_byte((word >> 0) & 0xff);
|
||||
crc.process_byte((word >> 8) & 0xff);
|
||||
crc.process_byte((word >> 16) & 0xff);
|
||||
crc.process_byte((word >> 24) & 0xff);
|
||||
}
|
||||
return crc.checksum();
|
||||
}
|
||||
|
||||
DebugPmemView::DebugPmemView(NavigationView& nav)
|
||||
: data{*reinterpret_cast<pmem_data*>(memory::map::backup_ram.base())}, registers_widget(RegistersWidgetConfig{page_size, 8}, std::bind(&DebugPmemView::registers_widget_feed, this, std::placeholders::_1)) {
|
||||
static_assert(sizeof(pmem_data) == memory::map::backup_ram.size());
|
||||
|
||||
add_children({&text_page, ®isters_widget, &text_checksum, &button_ok});
|
||||
add_children({&text_page, ®isters_widget, &text_checksum, &text_checksum2, &button_ok});
|
||||
|
||||
registers_widget.set_parent_rect({0, 32, 240, 192});
|
||||
|
||||
text_checksum.set("Size: " + to_string_dec_uint(portapack::persistent_memory::data_size()) + " CRC: " + to_string_hex(data.check_value, 8));
|
||||
text_checksum.set("Size: " + to_string_dec_uint(portapack::persistent_memory::data_size(), 3) + " CRC: " + to_string_hex(data.check_value, 8));
|
||||
text_checksum2.set("Calculated CRC: " + to_string_hex(pmem_checksum(data.regfile), 8));
|
||||
|
||||
button_ok.on_select = [&nav](Button&) {
|
||||
nav.pop();
|
||||
|
||||
@@ -269,7 +269,7 @@ class DebugPmemView : public View {
|
||||
DebugPmemView(NavigationView& nav);
|
||||
void focus() override;
|
||||
bool on_encoder(const EncoderEvent delta) override;
|
||||
std::string title() const override { return "Pmem"; }
|
||||
std::string title() const override { return "P.Mem Debug"; }
|
||||
|
||||
private:
|
||||
struct pmem_data {
|
||||
@@ -282,13 +282,14 @@ class DebugPmemView : public View {
|
||||
|
||||
int32_t page{0};
|
||||
|
||||
const pmem_data& data;
|
||||
volatile const pmem_data& data;
|
||||
|
||||
Text text_page{{16, 16, 208, 16}};
|
||||
|
||||
RegistersWidget registers_widget;
|
||||
|
||||
Text text_checksum{{16, 240, 208, 16}};
|
||||
Text text_checksum{{16, 232, 208, 16}};
|
||||
Text text_checksum2{{16, 248, 208, 16}};
|
||||
|
||||
Button button_ok{
|
||||
{240 / 3, 270, 240 / 3, 24},
|
||||
|
||||
@@ -66,7 +66,7 @@ rf::Frequency GlassView::get_freq_from_bin_pos(uint8_t pos) {
|
||||
// starting from the middle, minus 8 ignored bin on each side. Since pos is [-120,120] after the (pos - 120), it's divided by SCREEN_W(240)/2 => 120
|
||||
freq_at_pos = f_center_ini + ((pos - 120) * ((looking_glass_range - ((16 * looking_glass_range) / SPEC_NB_BINS)) / 2)) / (SCREEN_W / 2);
|
||||
} else
|
||||
freq_at_pos = f_min - (offset * each_bin_size) + (pos * looking_glass_range) / SCREEN_W;
|
||||
freq_at_pos = f_min + (pos * looking_glass_range) / SCREEN_W;
|
||||
|
||||
return freq_at_pos;
|
||||
}
|
||||
@@ -77,23 +77,6 @@ void GlassView::on_marker_change() {
|
||||
PlotMarker(marker_pixel_index); // Refresh marker on screen
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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::retune() {
|
||||
// Start a new sweep.
|
||||
// Tune rx for this new slice directly because the model
|
||||
@@ -166,6 +149,31 @@ void GlassView::add_spectrum_pixel(uint8_t power) {
|
||||
}
|
||||
}
|
||||
|
||||
bool GlassView::process_bins(uint8_t* powerlevel) {
|
||||
bins_Hz_size += each_bin_size; // add the ignored DC spike to "pixel fulfilled bag of Hz"
|
||||
if (bins_Hz_size >= marker_pixel_step) // new pixel fullfilled
|
||||
{
|
||||
if (*powerlevel > min_color_power)
|
||||
add_spectrum_pixel(*powerlevel); // Pixel will represent max_power
|
||||
else
|
||||
add_spectrum_pixel(0); // Filtered out, show black
|
||||
*powerlevel = 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"
|
||||
if (mode != LOOKING_GLASS_SINGLEPASS) {
|
||||
f_center = f_center_ini;
|
||||
retune();
|
||||
} else
|
||||
baseband::spectrum_streaming_start();
|
||||
return true; // signal a new line
|
||||
}
|
||||
bins_Hz_size -= marker_pixel_step; // reset bins size, but carrying the eventual excess Hz into next pixel
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apparently, the spectrum object returns an array of SPEC_NB_BINS (256) bins
|
||||
// Each having the radio signal power for it's corresponding frequency slot
|
||||
void GlassView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
||||
@@ -174,31 +182,19 @@ void GlassView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
||||
// we actually need SCREEN_W (240) of those bins
|
||||
for (bin = 0; bin < bin_length; bin++) {
|
||||
get_max_power(spectrum, bin, max_power);
|
||||
if (ignore_dc && bin == 119) {
|
||||
bins_Hz_size += 12 * each_bin_size; // add the ignored DC spike to "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(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"
|
||||
if (mode != LOOKING_GLASS_SINGLEPASS) {
|
||||
f_center = f_center_ini;
|
||||
retune();
|
||||
} else
|
||||
baseband::spectrum_streaming_start();
|
||||
return; // signal a new line
|
||||
// process dc spike if enable
|
||||
if (bin == 119) {
|
||||
uint8_t next_max_power = 0;
|
||||
get_max_power(spectrum, bin + 1, next_max_power);
|
||||
for (uint8_t it = 0; it < ignore_dc; it++) {
|
||||
uint8_t med_max_power = (max_power + next_max_power) / 2; // due to the way process_bins works we have to keep resetting the color
|
||||
if (process_bins(&med_max_power) == true)
|
||||
return; // new line signaled, return
|
||||
}
|
||||
bins_Hz_size -= marker_pixel_step; // reset bins size, but carrying the eventual excess Hz into next pixel
|
||||
}
|
||||
// process actual bin
|
||||
if (process_bins(&max_power) == true)
|
||||
return; // new line signaled, return
|
||||
}
|
||||
if (mode != LOOKING_GLASS_SINGLEPASS) {
|
||||
f_center += looking_glass_step;
|
||||
@@ -225,8 +221,6 @@ void GlassView::on_range_changed() {
|
||||
f_max = f_max * MHZ_DIV;
|
||||
looking_glass_range = f_max - f_min;
|
||||
if (looking_glass_range <= LOOKING_GLASS_SLICE_WIDTH_MAX) {
|
||||
adjust_range(&f_min, &f_max, SCREEN_W);
|
||||
looking_glass_range = f_max - f_min;
|
||||
// if the view is done in one pass, show it like in analog_audio_app
|
||||
mode = LOOKING_GLASS_SINGLEPASS;
|
||||
offset = 0;
|
||||
@@ -237,24 +231,22 @@ void GlassView::on_range_changed() {
|
||||
each_bin_size = looking_glass_bandwidth / SCREEN_W;
|
||||
looking_glass_step = looking_glass_bandwidth;
|
||||
f_center_ini = f_min + (looking_glass_bandwidth / 2); // Initial center frequency for sweep
|
||||
} else { // if ( mode == LOOKING_GLASS_SLOWSCAN || mode == LOOKING_GLASS_FASTSCAN )
|
||||
} else {
|
||||
// view is made in multiple pass, use original bin picking
|
||||
mode = scan_type.selected_index_value();
|
||||
if (mode == LOOKING_GLASS_FASTSCAN) {
|
||||
offset = 2;
|
||||
offset = 8;
|
||||
ignore_dc = SPEC_NB_BINS - SCREEN_W - offset;
|
||||
bin_length = SCREEN_W;
|
||||
ignore_dc = 1;
|
||||
} else { // if( mode == LOOKING_GLASS_SLOWSCAN )
|
||||
offset = 16;
|
||||
offset = 132;
|
||||
bin_length = 80;
|
||||
ignore_dc = 0;
|
||||
}
|
||||
adjust_range(&f_min, &f_max, SCREEN_W);
|
||||
looking_glass_range = f_max - f_min;
|
||||
looking_glass_bandwidth = LOOKING_GLASS_SLICE_WIDTH_MAX;
|
||||
looking_glass_sampling_rate = LOOKING_GLASS_SLICE_WIDTH_MAX;
|
||||
each_bin_size = LOOKING_GLASS_SLICE_WIDTH_MAX / SPEC_NB_BINS;
|
||||
looking_glass_step = (bin_length + (ignore_dc * 12)) * each_bin_size;
|
||||
looking_glass_step = (bin_length + ignore_dc) * each_bin_size;
|
||||
f_center_ini = f_min - (offset * each_bin_size) + (looking_glass_bandwidth / 2); // Initial center frequency for sweep
|
||||
}
|
||||
search_span = looking_glass_range / MHZ_DIV;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "spectrum_color_lut.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
#define LOOKING_GLASS_SLICE_WIDTH_MAX 20000000
|
||||
#define MHZ_DIV 1000000
|
||||
|
||||
@@ -81,10 +82,8 @@ class GlassView : public View {
|
||||
void get_max_power(const ChannelSpectrum& spectrum, uint8_t bin, uint8_t& max_power);
|
||||
rf::Frequency get_freq_from_bin_pos(uint8_t pos);
|
||||
void on_marker_change();
|
||||
int64_t next_mult_of(int64_t num, int64_t multiplier);
|
||||
void adjust_range(int64_t* f_min, int64_t* f_max, int64_t width);
|
||||
void retune();
|
||||
bool move_to_next_position();
|
||||
bool process_bins(uint8_t* powerlevel);
|
||||
void on_channel_spectrum(const ChannelSpectrum& spectrum);
|
||||
void do_timers();
|
||||
void on_range_changed();
|
||||
|
||||
@@ -470,7 +470,7 @@ class SetPersistentMemoryView : public View {
|
||||
private:
|
||||
Text text_pmem_about{
|
||||
{0, 1 * 16, 240, 16},
|
||||
"PersistentMemory from/to SD"};
|
||||
"Persistent Memory from/to SD"};
|
||||
|
||||
Text text_pmem_informations{
|
||||
{0, 2 * 16, 240, 16},
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#ifndef __MAX283X_H__
|
||||
#define __MAX283X_H__
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "rf_path.hpp"
|
||||
|
||||
namespace max283x {
|
||||
|
||||
@@ -162,8 +162,8 @@ constexpr ConfigAmp config_amp(
|
||||
const Direction direction,
|
||||
const Band band) {
|
||||
return {{
|
||||
{.direction = direction, .band = band, .amplify = false},
|
||||
{.direction = direction, .band = band, .amplify = true},
|
||||
Config(direction, band, false),
|
||||
Config(direction, band, true),
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,11 @@ using sample_t = uint16_t;
|
||||
|
||||
constexpr sample_t sample_max = 1023;
|
||||
|
||||
constexpr sample_t touch_threshold = sample_max / 16;
|
||||
// If you have a dead bottom-left corner try to increase the sensitivity,
|
||||
// but look for flickering touch indicator in the Buttons test screen
|
||||
// in which case decrease sensitivity to avoid killing backlight timeout
|
||||
constexpr sample_t touch_sensitivity = 32;
|
||||
constexpr sample_t touch_threshold = sample_max / touch_sensitivity;
|
||||
|
||||
struct Samples {
|
||||
sample_t xp;
|
||||
|
||||
@@ -136,7 +136,7 @@ GeoMap::GeoMap(
|
||||
}
|
||||
|
||||
void GeoMap::paint(Painter& painter) {
|
||||
u_int16_t line;
|
||||
uint16_t line;
|
||||
std::array<ui::Color, 240> map_line_buffer;
|
||||
const auto r = screen_rect();
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
enable_language(C CXX ASM)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
project(baseband_shared)
|
||||
|
||||
# Compiler options here.
|
||||
@@ -36,7 +38,13 @@ set(USE_OPT "-O3 -g -falign-functions=16 -fno-math-errno --specs=nano.specs")
|
||||
set(USE_COPT "-std=gnu99")
|
||||
|
||||
# C++ specific options here (added to USE_OPT).
|
||||
set(USE_CPPOPT "-std=c++17 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
|
||||
check_cxx_compiler_flag("-std=c++20" cpp20_supported)
|
||||
if(cpp20_supported)
|
||||
set(USE_CPPOPT "-std=c++20")
|
||||
else()
|
||||
set(USE_CPPOPT "-std=c++17")
|
||||
endif()
|
||||
set(USE_CPPOPT "${USE_CPPOPT} -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized -Wno-volatile")
|
||||
|
||||
# Enable this if you want the linker to remove unused code and data
|
||||
set(USE_LINK_GC yes)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
|
||||
namespace jtag {
|
||||
namespace tap {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
#include "baseband.hpp"
|
||||
|
||||
|
||||
@@ -354,8 +354,8 @@ struct data_t {
|
||||
|
||||
struct backup_ram_t {
|
||||
private:
|
||||
uint32_t regfile[63];
|
||||
uint32_t check_value;
|
||||
volatile uint32_t regfile[63];
|
||||
volatile uint32_t check_value;
|
||||
|
||||
static void copy(const backup_ram_t& src, backup_ram_t& dst) {
|
||||
for (size_t i = 0; i < 63; i++) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define __TONESETS_H__
|
||||
|
||||
#include <memory>
|
||||
#include <array>
|
||||
|
||||
#define TONES_SAMPLERATE 1536000
|
||||
#define TONES_DELTA_COEF(sr) ((1ULL << 32) / sr)
|
||||
|
||||
@@ -60,6 +60,10 @@ class TransponderID {
|
||||
return id_;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const TransponderID& other) const {
|
||||
return id_ == other.id_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t id_;
|
||||
};
|
||||
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
find firmware/common firmware/baseband firmware/application firmware/test/application firmware/test/baseband -iname '*.h' -o -iname '*.hpp' -o -iname '*.cpp' -o -iname '*.c' | xargs clang-format-13 -style=file -i
|
||||
@@ -1,2 +1,2 @@
|
||||
a=441000000,b=450000000,m=NFM,bw=11k,s=25kHz,d=HAM 70cm
|
||||
a=420000000,b=450000000,m=NFM,bw=11k,s=25kHz,d=HAM 70cm
|
||||
|
||||
|
||||
Reference in New Issue
Block a user