mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
commit
6cf5990b0e
28
.github/workflows/changelog.py
vendored
Normal file
28
.github/workflows/changelog.py
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
raw_git = os.popen('git log next --since="24 hours" --pretty=format:"- %h - {USERNAME}*+%al-%an*: %s"').read()
|
||||
|
||||
|
||||
def compute_username(line):
|
||||
stripped = re.search(r'(?<=\*)(.*?)(?=\*)', line).group(0)
|
||||
|
||||
pattern = re.compile("[$@+&?].*[$@+&?]")
|
||||
if pattern.match(stripped):
|
||||
stripped = re.sub("[$@+&?].*[$@+&?]", "", stripped)
|
||||
stripped = re.match(r'.+?(?=-)', stripped).group(0)
|
||||
else:
|
||||
stripped = re.sub(r'^.*?-', "", stripped)
|
||||
return "@" + stripped
|
||||
|
||||
|
||||
def compile_line(line):
|
||||
username = compute_username(line)
|
||||
line = re.sub(r'[*].*[*]', "", line)
|
||||
line = line.replace("{USERNAME}", username)
|
||||
return line
|
||||
|
||||
|
||||
for row in raw_git.splitlines():
|
||||
print(compile_line(row))
|
99
.github/workflows/create_nightly_release.yml
vendored
Normal file
99
.github/workflows/create_nightly_release.yml
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
name: Nightly Release
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check_date:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check latest commit
|
||||
outputs:
|
||||
should_run: ${{ steps.should_run.outputs.should_run }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: print latest_commit
|
||||
run: echo ${{ github.sha }}
|
||||
|
||||
- name: check latest commit is less than a day
|
||||
id: should_run
|
||||
continue-on-error: true
|
||||
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false"
|
||||
build:
|
||||
needs: check_date
|
||||
if: ${{ needs.check_date.outputs.should_run != 'false' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
||||
- name: Get version date
|
||||
id: version_date
|
||||
run: echo "::set-output name=date::n_$(date +'%y%m%d')"
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: next
|
||||
submodules: true
|
||||
- name: Git Sumbodule Update
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
- name: Build the Docker image
|
||||
run: docker build -t portapack-dev -f dockerfile-nogit . --tag my-image-name:$(date +%s)
|
||||
- name: Make build folder
|
||||
run: mkdir ${{ github.workspace }}/build
|
||||
- name: Run the Docker image
|
||||
run: docker run -e VERSION_STRING=${{ steps.version_date.outputs.date }} -i -v ${{ github.workspace }}:/havoc portapack-dev
|
||||
- name: Create Firmware ZIP
|
||||
run: |
|
||||
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
|
||||
- name: Create SD Card ZIP
|
||||
run: |
|
||||
zip -r sdcard.zip sdcard
|
||||
- name: Create changelog
|
||||
run: |
|
||||
CHANGELOG=$(python3 .github/workflows/changelog.py)
|
||||
CHANGELOG="${CHANGELOG//'%'/'%25'}"
|
||||
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
|
||||
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||
echo "::set-output name=content::$CHANGELOG"
|
||||
id: changelog
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: nightly-tag-${{ steps.date.outputs.date }}
|
||||
release_name: Nightly Release - ${{ steps.date.outputs.date }}
|
||||
body: |
|
||||
**Nightly release - ${{ steps.date.outputs.date }}**
|
||||
This build is the latest and greatest, although may not be the most stable as this is a nightly release.
|
||||
## Release notes
|
||||
### Revision (${{ steps.version_date.outputs.date }}):
|
||||
${{ steps.changelog.outputs.content }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
- name: Upload Firmware Asset
|
||||
id: upload-firmware-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./firmware.zip
|
||||
asset_name: mayhem_nightly_${{ steps.version_date.outputs.date }}_FIRMWARE.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Upload SD Card Assets
|
||||
id: upload-sd-card-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./sdcard.zip
|
||||
asset_name: mayhem_nightly_${{ steps.version_date.outputs.date }}_COPY_TO_SDCARD.zip
|
||||
asset_content_type: application/zip
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -39,7 +39,6 @@
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
/firmware/baseband/*.bin
|
||||
|
@ -25,8 +25,8 @@ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/firmware/toolchain-arm-cortex
|
||||
|
||||
project(portapack-h1)
|
||||
|
||||
#set(VERSION "")
|
||||
if (NOT DEFINED VERSION)
|
||||
set(VERSION "$ENV{VERSION_STRING}")
|
||||
if ("$ENV{VERSION_STRING}" STREQUAL "")
|
||||
execute_process(
|
||||
COMMAND git log -n 1 --format=%h
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
@ -38,7 +38,7 @@ if (NOT DEFINED VERSION)
|
||||
if (GIT_VERSION_FOUND)
|
||||
set(VERSION "unknown")
|
||||
else (GIT_VERSION_FOUND)
|
||||
set(VERSION "local-${GIT_VERSION}")
|
||||
set(VERSION "${GIT_VERSION}")
|
||||
endif (GIT_VERSION_FOUND)
|
||||
endif()
|
||||
|
||||
|
@ -26,7 +26,9 @@ To support the people behind the hardware, please buy a genuine [HackRF](https:/
|
||||
|
||||
## Where is the latest firmware?
|
||||
|
||||
The current stable release is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
|
||||
The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
|
||||
|
||||
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
|
||||
|
||||
## Is this the newest firmware for my PortaPack?
|
||||
Most probably: **YES**. *If you find new features somewhere else, please [suggest](https://github.com/eried/portapack-mayhem/issues/new/choose) them*.
|
||||
|
@ -169,7 +169,7 @@ int main(void) {
|
||||
|
||||
sdcStart(&SDCD1, nullptr);
|
||||
|
||||
controls_init();
|
||||
// controls_init(); // Commented out as now happens in portapack.cpp
|
||||
lcd_frame_sync_configure();
|
||||
rtc_interrupt_enable();
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
|
||||
|
||||
#include "clock_manager.hpp"
|
||||
#include "event_m0.hpp"
|
||||
|
||||
@ -45,6 +46,7 @@ using asahi_kasei::ak4951::AK4951;
|
||||
#include "cpld_update.hpp"
|
||||
|
||||
#include "optional.hpp"
|
||||
#include "irq_controls.hpp"
|
||||
|
||||
namespace portapack {
|
||||
|
||||
@ -179,18 +181,19 @@ static PortaPackModel portapack_model() {
|
||||
static Optional<PortaPackModel> model;
|
||||
|
||||
if( !model.is_valid() ) {
|
||||
/*For the time being, it is impossible to distinguish the hardware of R1 and R2 from the software level*/
|
||||
/*At this point, I2c is not ready.*/
|
||||
//if( audio_codec_wm8731.detected() ) {
|
||||
// model = PortaPackModel::R1_20150901;
|
||||
//} else {
|
||||
model = PortaPackModel::R2_20170522;
|
||||
//}
|
||||
if( audio_codec_wm8731.detected() ) {
|
||||
model = PortaPackModel::R1_20150901; // H1R1
|
||||
} else {
|
||||
model = PortaPackModel::R2_20170522; // H1R2, H2+
|
||||
}
|
||||
}
|
||||
|
||||
return model.value();
|
||||
}
|
||||
|
||||
//audio_codec_wm8731 = H1R1 & H2+
|
||||
//audio_codec_ak4951 = H1R2
|
||||
|
||||
static audio::Codec* portapack_audio_codec() {
|
||||
/* I2C ready OK, Automatic recognition of audio chip */
|
||||
return (audio_codec_wm8731.detected())
|
||||
@ -200,16 +203,37 @@ static audio::Codec* portapack_audio_codec() {
|
||||
}
|
||||
|
||||
static const portapack::cpld::Config& portapack_cpld_config() {
|
||||
const auto switches_state = get_switches_state();
|
||||
if (switches_state[(size_t)ui::KeyEvent::Up]){
|
||||
persistent_memory::set_config_cpld(1);
|
||||
return portapack::cpld::rev_20170522::config;
|
||||
}
|
||||
if (switches_state[(size_t)ui::KeyEvent::Down]){
|
||||
persistent_memory::set_config_cpld(2);
|
||||
return portapack::cpld::rev_20150901::config;
|
||||
}
|
||||
if (switches_state[(size_t)ui::KeyEvent::Left]){
|
||||
persistent_memory::set_config_cpld(3);
|
||||
}
|
||||
if (switches_state[(size_t)ui::KeyEvent::Select]){
|
||||
persistent_memory::set_config_cpld(0);
|
||||
}
|
||||
|
||||
|
||||
if (portapack::persistent_memory::config_cpld() == 1) {
|
||||
return portapack::cpld::rev_20170522::config;
|
||||
} else if (portapack::persistent_memory::config_cpld() == 2) {
|
||||
return portapack::cpld::rev_20150901::config;
|
||||
}
|
||||
return (portapack_model() == PortaPackModel::R2_20170522)
|
||||
? portapack::cpld::rev_20170522::config
|
||||
: portapack::cpld::rev_20150901::config
|
||||
;
|
||||
? portapack::cpld::rev_20170522::config
|
||||
: portapack::cpld::rev_20150901::config;
|
||||
}
|
||||
|
||||
Backlight* backlight() {
|
||||
return (portapack_model() == PortaPackModel::R2_20170522)
|
||||
? static_cast<portapack::Backlight*>(&backlight_cat4004)
|
||||
: static_cast<portapack::Backlight*>(&backlight_on_off);
|
||||
? static_cast<portapack::Backlight*>(&backlight_cat4004) // R2_20170522
|
||||
: static_cast<portapack::Backlight*>(&backlight_on_off); // R1_20150901
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||
@ -318,14 +342,15 @@ bool init() {
|
||||
|
||||
i2c0.start(i2c_config_boot_clock);
|
||||
|
||||
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
||||
shutdown_base();
|
||||
return false;
|
||||
}
|
||||
// Keeping this here for now incase we need to revert
|
||||
// if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
||||
// shutdown_base();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if( !hackrf::cpld::load_sram() ) {
|
||||
chSysHalt();
|
||||
}
|
||||
// if( !hackrf::cpld::load_sram() ) {
|
||||
// chSysHalt();
|
||||
// }
|
||||
|
||||
configure_pins_portapack();
|
||||
|
||||
@ -336,7 +361,6 @@ bool init() {
|
||||
i2c0.stop();
|
||||
|
||||
set_clock_config(clock_config_irc);
|
||||
|
||||
cgu::pll1::disable();
|
||||
|
||||
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
|
||||
@ -377,20 +401,38 @@ bool init() {
|
||||
|
||||
i2c0.start(i2c_config_fast_clock);
|
||||
|
||||
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
|
||||
touch::adc::init();
|
||||
controls_init();
|
||||
|
||||
audio::init(portapack_audio_codec());
|
||||
|
||||
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
|
||||
clock_manager.enable_first_if_clock();
|
||||
clock_manager.enable_second_if_clock();
|
||||
clock_manager.enable_codec_clocks();
|
||||
radio::init();
|
||||
radio::init();
|
||||
|
||||
touch::adc::init();
|
||||
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
||||
// If using a "2021/12 QFP100", press and hold the left button while booting. Should only need to do once.
|
||||
const auto switches_state = get_switches_state();
|
||||
/*
|
||||
* The LEFT key held check seems redundant as its in the portapack_cpld_config().
|
||||
* But for some reason the persistent_memory check fails on some devices if we dont have the extra check in....
|
||||
* So dont ask me why that is, but we have to keep this redundant check in for the persistent_memory check to work.
|
||||
*/
|
||||
if (!switches_state[(size_t)ui::KeyEvent::Left] && portapack::persistent_memory::config_cpld() != 3){
|
||||
shutdown_base();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( !hackrf::cpld::load_sram() ) {
|
||||
chSysHalt();
|
||||
}
|
||||
|
||||
LPC_CREG->DMAMUX = portapack::gpdma_mux;
|
||||
gpdma::controller.enable();
|
||||
|
||||
audio::init(portapack_audio_codec());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ namespace ui
|
||||
void on_speaker();
|
||||
void on_stealth();
|
||||
void on_bias_tee();
|
||||
//void on_textentry();
|
||||
// void on_textentry();
|
||||
void on_camera();
|
||||
void on_title();
|
||||
void refresh();
|
||||
@ -212,7 +212,7 @@ namespace ui
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
static constexpr auto version_string = "v1.4.4";
|
||||
// static constexpr auto version_string = "v1.4.4"; // This is commented out as we are now setting the version via ENV (VERSION_STRING=v1.0.0)
|
||||
NavigationView &nav_;
|
||||
|
||||
Rectangle backdrop{
|
||||
@ -221,7 +221,7 @@ namespace ui
|
||||
|
||||
Text version{
|
||||
{2, 0, 11 * 8, 16},
|
||||
version_string};
|
||||
VERSION_STRING};
|
||||
|
||||
LiveDateTime ltime{
|
||||
{86, 0, 19 * 8, 16}};
|
||||
|
@ -115,6 +115,10 @@ void AK4951::init() {
|
||||
// update(Register::DigitalFilterMode);
|
||||
}
|
||||
|
||||
bool AK4951::detected() {
|
||||
return reset();
|
||||
}
|
||||
|
||||
bool AK4951::reset() {
|
||||
io.audio_reset_state(true);
|
||||
|
||||
|
@ -823,6 +823,8 @@ public:
|
||||
std::string name() const override {
|
||||
return "AK4951";
|
||||
}
|
||||
|
||||
bool detected();
|
||||
|
||||
void init() override;
|
||||
bool reset() override;
|
||||
|
@ -82,7 +82,7 @@ struct data_t {
|
||||
int32_t afsk_space_freq;
|
||||
int32_t modem_baudrate;
|
||||
int32_t modem_repeat;
|
||||
|
||||
|
||||
// Play dead unlock
|
||||
uint32_t playdead_magic;
|
||||
uint32_t playing_dead;
|
||||
@ -95,6 +95,9 @@ struct data_t {
|
||||
uint32_t pocsag_ignore_address;
|
||||
|
||||
int32_t tone_mix;
|
||||
|
||||
// Hardware
|
||||
uint32_t hardware_config;
|
||||
};
|
||||
|
||||
static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region");
|
||||
@ -254,6 +257,10 @@ bool config_splash() {
|
||||
return data->ui_config & (1 << 31);
|
||||
}
|
||||
|
||||
uint8_t config_cpld() {
|
||||
return data->hardware_config;
|
||||
}
|
||||
|
||||
uint32_t config_backlight_timer() {
|
||||
const uint32_t timer_seconds[8] = { 0, 5, 15, 30, 60, 180, 300, 600 };
|
||||
return timer_seconds[data->ui_config & 7]; //first three bits, 8 possible values
|
||||
@ -287,6 +294,10 @@ void set_config_splash(bool v) {
|
||||
data->ui_config = (data->ui_config & ~(1 << 31)) | (v << 31);
|
||||
}
|
||||
|
||||
void set_config_cpld(uint8_t i) {
|
||||
data->hardware_config = i;
|
||||
}
|
||||
|
||||
void set_config_backlight_timer(uint32_t i) {
|
||||
data->ui_config = (data->ui_config & ~7) | (i & 7);
|
||||
}
|
||||
|
@ -74,6 +74,9 @@ void set_playdead_sequence(const uint32_t new_value);
|
||||
bool stealth_mode();
|
||||
void set_stealth_mode(const bool v);
|
||||
|
||||
uint8_t config_cpld();
|
||||
void set_config_cpld(uint8_t i);
|
||||
|
||||
bool config_splash();
|
||||
bool hide_clock();
|
||||
bool clock_with_date();
|
||||
|
2
flashing/Check for firmware updates.url
Normal file
2
flashing/Check for firmware updates.url
Normal file
@ -0,0 +1,2 @@
|
||||
[InternetShortcut]
|
||||
URL=https://github.com/eried/portapack-mayhem/releases
|
2
flashing/How to update the firmware.url
Normal file
2
flashing/How to update the firmware.url
Normal file
@ -0,0 +1,2 @@
|
||||
[InternetShortcut]
|
||||
URL=https://github.com/eried/portapack-mayhem/wiki/Update-firmware
|
1
flashing/README.txt
Normal file
1
flashing/README.txt
Normal file
@ -0,0 +1 @@
|
||||
Plug HackRF+Portapack, set it in HackRF mode, launch flash_portapack_mayhem.bat
|
BIN
flashing/dfu-util-static.exe
Normal file
BIN
flashing/dfu-util-static.exe
Normal file
Binary file not shown.
19
flashing/dfu_hackrf_one.bat
Normal file
19
flashing/dfu_hackrf_one.bat
Normal file
@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
|
||||
echo *** Run HackRF firmware in RAM via LPC DFU ***
|
||||
echo.
|
||||
echo This is used to "unbrick" your HackRF, if you are no longer able to use
|
||||
echo HackRF tools to flash or operate your HackRF.
|
||||
echo.
|
||||
echo Connect your HackRF One to a USB port on your computer.
|
||||
echo.
|
||||
echo Hold down both the DFU and RESET buttons on the HackRF.
|
||||
echo Then release the RESET button (closest to the edge).
|
||||
echo Then release the DFU button.
|
||||
echo.
|
||||
pause
|
||||
|
||||
echo.
|
||||
dfu-util-static.exe --device 1fc9:000c --download hackrf_one_usb.dfu --reset
|
||||
echo.
|
||||
pause
|
BIN
flashing/driver/dpinst.exe
Normal file
BIN
flashing/driver/dpinst.exe
Normal file
Binary file not shown.
7
flashing/driver/dpinst.xml
Normal file
7
flashing/driver/dpinst.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" ?>
|
||||
<dpinst>
|
||||
<deleteBinaries/>
|
||||
<installAllOrNone/>
|
||||
<suppressAddRemovePrograms/>
|
||||
<suppressWizard/>
|
||||
</dpinst>
|
BIN
flashing/driver/hackrf_one.inf
Normal file
BIN
flashing/driver/hackrf_one.inf
Normal file
Binary file not shown.
BIN
flashing/driver/hackrf_one_amd64.cat
Normal file
BIN
flashing/driver/hackrf_one_amd64.cat
Normal file
Binary file not shown.
BIN
flashing/driver/lpc_dfu.inf
Normal file
BIN
flashing/driver/lpc_dfu.inf
Normal file
Binary file not shown.
BIN
flashing/driver/lpc_dfu_amd64.cat
Normal file
BIN
flashing/driver/lpc_dfu_amd64.cat
Normal file
Binary file not shown.
15
flashing/flash_hackrf_one.bat
Normal file
15
flashing/flash_hackrf_one.bat
Normal file
@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
|
||||
echo *** Re-flash the HackRF with HackRF firmware ***
|
||||
echo.
|
||||
echo Connect your HackRF One to a USB port on your computer.
|
||||
echo.
|
||||
echo If using a PortaPack, put the PortaPack in HackRF mode by selecting
|
||||
echo the "HackRF" option from the main menu.
|
||||
echo.
|
||||
pause
|
||||
|
||||
echo.
|
||||
hackrf_update.exe hackrf_one_usb.bin
|
||||
echo.
|
||||
pause
|
15
flashing/flash_portapack_mayhem.bat
Normal file
15
flashing/flash_portapack_mayhem.bat
Normal file
@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
|
||||
echo *** Re-flash the HackRF with PortaPack firmware ***
|
||||
echo.
|
||||
echo Connect your HackRF One to a USB port on your computer.
|
||||
echo.
|
||||
echo If using a PortaPack, put the PortaPack in HackRF mode by selecting
|
||||
echo the "HackRF" option from the main menu.
|
||||
echo.
|
||||
pause
|
||||
|
||||
echo.
|
||||
hackrf_update.exe portapack-h1_h2-mayhem.bin
|
||||
echo.
|
||||
pause
|
BIN
flashing/hackrf_one_usb.bin
Normal file
BIN
flashing/hackrf_one_usb.bin
Normal file
Binary file not shown.
BIN
flashing/hackrf_one_usb.dfu
Normal file
BIN
flashing/hackrf_one_usb.dfu
Normal file
Binary file not shown.
BIN
flashing/hackrf_update.exe
Normal file
BIN
flashing/hackrf_update.exe
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user