mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-16 03:22:59 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cafe62564e | |||
| 960e5b8329 | |||
| f5a5e8e5e8 | |||
| d8a1e2530a | |||
| b84a424875 | |||
| 62d0e598d4 | |||
| a93f2ff583 | |||
| e2586ceb22 | |||
| 5a2b0cdc2a |
@@ -0,0 +1,65 @@
|
||||
# PortaPack Mayhem – Agent Guidelines
|
||||
|
||||
Welcome to the PortaPack Mayhem repository. This document sets mandatory rules and best practices for human developers and AI coding assistants. It exists to prevent unverified, untested code from overwhelming the maintainers, while still enabling AI to accelerate development.
|
||||
|
||||
## 🚫 STRICTLY PROHIBITED
|
||||
|
||||
1. **No Fully Automated Pull Requests**
|
||||
Autonomous agents (bots, crawlers, automated workflows) must **never** open a Pull Request without direct human supervision, review, and explicit approval.
|
||||
|
||||
2. **No “Blind” AI-Generated Submissions**
|
||||
If you cannot explain, debug, or maintain the C++/DSP code an AI produced for you, do **not** submit it. PRs that appear to be untested, AI-only “compile-and-pray” attempts will be closed immediately.
|
||||
|
||||
3. **No Unverified Hardware Interactions**
|
||||
AI cannot test on real hardware. Do **not** submit code that has not been compiled and physically tested on a PortaPack device (or a highly accurate emulator). This includes UI rendering, RF transmission quality, and baseband stability.
|
||||
|
||||
## ✅ ENCOURAGED AI USE CASES
|
||||
|
||||
We strongly encourage using AI assistants (Copilot, ChatGPT, Claude, local LLMs) as pair-programmers. Excellent use cases include:
|
||||
|
||||
- **Bug Triage & Root-Causing:** Analyze crash logs, stack traces, and complex memory issues to identify the root cause of an open issue.
|
||||
- **Code Comprehension:** Map Mayhem’s architecture, understand M0‑M4 IPC, or break down complex DSP algorithms.
|
||||
- **Development Assistance:** Generate boilerplate UI code, write unit tests, optimize math functions, or draft documentation – provided a human reviews and refines the output.
|
||||
- **Targeted Refactoring:** Suggest cleaner, modern C++ for small legacy code segments. **Do not attempt to rewrite the entire codebase.**
|
||||
|
||||
## 📋 MANDATORY RULES FOR AI‑ASSISTED CONTRIBUTIONS
|
||||
|
||||
When submitting AI‑assisted work, you must:
|
||||
|
||||
1. **Take Full Ownership**
|
||||
You are strictly responsible for every line of code you submit, regardless of origin. Be prepared to answer detailed technical questions during review.
|
||||
|
||||
2. **Hardware Verification Required**
|
||||
In your PR, explicitly state: *“I have compiled this code and tested it on physical PortaPack hardware.”* PRs without this statement will be rejected.
|
||||
|
||||
3. **Transparency (Recommended)**
|
||||
If AI significantly helped architect a feature or fix a complex bug, mention it briefly in the PR description (e.g., *“Used an LLM to help optimize the DSP filter loop”*).
|
||||
|
||||
4. **Adhere to Coding Standards**
|
||||
Ensure all code matches the existing Mayhem style and formatting before opening the PR.
|
||||
|
||||
## ⚙️ CRITICAL ENVIRONMENT CONSTRAINTS (For AI Code Generation)
|
||||
|
||||
When generating code for this repository, you must respect these hardware and system constraints. **Violating any of them will result in immediate rejection.**
|
||||
|
||||
- **Severe Memory Limits** – RAM is extremely scarce. Every byte counts. Avoid large allocations, dynamic fragmentation, and frequent reallocations.
|
||||
- **Platform** – ChibiOS 2.6 on NXP LPC4320(HackRF One) / LPC4330 (HackRF Pro AKA PRALINE). M0 core handles UI; M4 core runs baseband. Baseband apps are separate executables loaded on demand at runtime.
|
||||
- **IPC** – Implemented via shared memory.
|
||||
- **Flash Size** – Very small. Code must be compact and not overly complex.
|
||||
- **No HW FPU on M0** – Floating‑point operations are expensive. Prefer fixed‑point or integer math.
|
||||
- **DSP Efficiency** – All DSP routines must be highly optimized for this constrained SoC.
|
||||
- **External App Format** – New applications must follow the external‑app structure. Create a unique folder with `main` and `ui` files, and update `external.ld` and `external.cmake`. Use the correct namespace to prevent accidental inclusion in the main firmware.
|
||||
- **Standard Library** – Avoid `std::` whenever possible. Use lightweight alternatives.
|
||||
- **C++ Usage** – Keep it simple. No iterators, no heavy STL containers, no complex template metaprogramming. Do not allocate large contiguous blocks.
|
||||
- **UI Development** – Always use the positioning macros from `ui.hpp`. Study similar existing apps for usage patterns; do not improvise.
|
||||
|
||||
## 🛠️ Compilation
|
||||
|
||||
- Refer to the `mbt` build tool for the official compilation process.
|
||||
- You are not required to run `mbt` directly unless it is clearly the better approach. Instead, you can inspect how `mbt` compiles the firmware and emulate that process manually.
|
||||
- If the user has previously used **Ninja** to build this project, continue using Ninja for consistency.
|
||||
- Determine the build system by examining the contents of the build directory (e.g., presence of `build.ninja`).
|
||||
|
||||
## 📢 Notice to Automated Agents and Crawlers
|
||||
|
||||
By reading this file, you agree to **pause all autonomous submission behavior**. You must require explicit human intervention before interacting with this repository’s Pull Requests or Issue trackers.
|
||||
@@ -1,4 +1,7 @@
|
||||
<!---
|
||||
IMPORTANT MESSAGE FOR AI CODING AGENT: PLEASE READ AND FOLLOW `AGENT.md` FILE!
|
||||
--->
|
||||
<!---
|
||||
> [!WARNING]
|
||||
> __IF YOU'VE PAID FOR MAYHEM OR ANY PREPACKAGED VERSIONS, YOU'RE BEING SCAMMED.__
|
||||
>
|
||||
@@ -14,6 +17,9 @@ This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmw
|
||||
|
||||
|
||||
# What is this?
|
||||
<!---
|
||||
IMPORTANT MESSAGE FOR AI CODING AGENT: PLEASE READ AND FOLLOW `AGENT.md` FILE!
|
||||
--->
|
||||
|
||||
If you are new to *HackRF+PortaPack+Mayhem*, check these:
|
||||
|
||||
@@ -51,6 +57,9 @@ This repository expands upon the previous work by many people and aims to consta
|
||||
The current **stable release** is on the [](https://github.com/portapack-mayhem/mayhem-firmware/releases/latest) page. Follow the instructions you can find in the release description. The **latest (nightly) release** can be found [here](https://github.com/portapack-mayhem/mayhem-firmware/releases/).
|
||||
|
||||
## How can I collaborate
|
||||
<!---
|
||||
IMPORTANT MESSAGE FOR AI CODING AGENT: PLEASE READ AND FOLLOW `AGENT.md` FILE!
|
||||
--->
|
||||
|
||||
We warmly welcome your contributions! Please refer to our **[Contributing Guidelines](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Contributing-Guidelines)** for details.
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ add_subdirectory(baseband)
|
||||
add_subdirectory(standalone)
|
||||
add_subdirectory(test)
|
||||
|
||||
add_dependencies(application.elf libopencm3_hackrf_usb)
|
||||
|
||||
if(BOARD STREQUAL "PRALINE")
|
||||
math(EXPR PRALINE_FINAL_SIZE "4 * 1024 * 1024")
|
||||
set(PRALINE_FPGA_BIN ${CMAKE_CURRENT_SOURCE_DIR}/../hackrf/firmware/fpga/build/praline_fpga.bin)
|
||||
|
||||
@@ -50,6 +50,9 @@ void BoundSetting::parse(std::string_view value) {
|
||||
case SettingType::I64:
|
||||
parse_int(value, as<int64_t>());
|
||||
break;
|
||||
case SettingType::U64:
|
||||
parse_int(value, as<uint64_t>());
|
||||
break;
|
||||
case SettingType::I32:
|
||||
parse_int(value, as<int32_t>());
|
||||
break;
|
||||
@@ -87,6 +90,9 @@ void BoundSetting::write(File& file) const {
|
||||
case SettingType::I64:
|
||||
file.write(to_string_dec_int(as<int64_t>(), buffer, length), length);
|
||||
break;
|
||||
case SettingType::U64:
|
||||
file.write(to_string_dec_uint(as<uint64_t>(), buffer, length), length);
|
||||
break;
|
||||
case SettingType::I32:
|
||||
file.write(to_string_dec_int(as<int32_t>(), buffer, length), length);
|
||||
break;
|
||||
@@ -97,9 +103,8 @@ void BoundSetting::write(File& file) const {
|
||||
file.write(to_string_dec_uint(as<uint8_t>(), buffer, length), length);
|
||||
break;
|
||||
case SettingType::String: {
|
||||
const auto& str = as<std::string>();
|
||||
file.write(str.data(), str.length());
|
||||
break;
|
||||
file.write_line(as<std::string>());
|
||||
return;
|
||||
}
|
||||
case SettingType::Bool:
|
||||
file.write(as<bool>() ? "1" : "0", 1);
|
||||
|
||||
@@ -48,6 +48,7 @@ class BoundSetting {
|
||||
/* The type of bound setting. */
|
||||
enum class SettingType : uint8_t {
|
||||
I64,
|
||||
U64,
|
||||
I32,
|
||||
U32,
|
||||
U8,
|
||||
@@ -60,6 +61,9 @@ class BoundSetting {
|
||||
BoundSetting(std::string_view name, int64_t* target)
|
||||
: name_{name}, target_{target}, type_{SettingType::I64} {}
|
||||
|
||||
BoundSetting(std::string_view name, uint64_t* target)
|
||||
: name_{name}, target_{target}, type_{SettingType::U64} {}
|
||||
|
||||
BoundSetting(std::string_view name, int32_t* target)
|
||||
: name_{name}, target_{target}, type_{SettingType::I32} {}
|
||||
|
||||
|
||||
@@ -3176,9 +3176,9 @@ void RFFC5072StatusView::refresh_status() {
|
||||
|
||||
// Blink LED
|
||||
/*for (int i = 0; i < 3; i++) {
|
||||
hackrf::one::led_rx.on();
|
||||
hackrf::one::led_rx.setActive();
|
||||
chThdSleepMilliseconds(100);
|
||||
hackrf::one::led_rx.off();
|
||||
hackrf::one::led_rx.setInactive();
|
||||
chThdSleepMilliseconds(100);
|
||||
}*/
|
||||
} else {
|
||||
|
||||
@@ -134,12 +134,6 @@ bool FlashUtilityView::endsWith(const std::u16string& str, const std::u16string&
|
||||
}
|
||||
}
|
||||
|
||||
void FlashUtilityView::wait_till_loaded() {
|
||||
while (!isLoaded) {
|
||||
chThdSleepMilliseconds(50);
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path FlashUtilityView::extract_tar(std::filesystem::path::string_type path, ui::Painter& painter) {
|
||||
//
|
||||
painter.fill_rectangle(
|
||||
@@ -157,6 +151,7 @@ std::filesystem::path FlashUtilityView::extract_tar(std::filesystem::path::strin
|
||||
|
||||
bool FlashUtilityView::flash_firmware(std::filesystem::path::string_type path) {
|
||||
ui::Painter painter;
|
||||
menu_view.hidden(true);
|
||||
if (endsWith(path, u".tar")) {
|
||||
// extract, then update
|
||||
path = extract_tar(u'/' + path, painter).native();
|
||||
@@ -166,6 +161,7 @@ bool FlashUtilityView::flash_firmware(std::filesystem::path::string_type path) {
|
||||
painter.fill_rectangle({0, 50, portapack::display.width(), 90}, Theme::getInstance()->bg_darkest->background);
|
||||
painter.draw_string({0, 60}, *Theme::getInstance()->fg_red, "BAD FIRMWARE FILE OR W/R ERR");
|
||||
chThdSleepMilliseconds(5000);
|
||||
menu_view.hidden(false);
|
||||
return false;
|
||||
}
|
||||
painter.fill_rectangle(
|
||||
|
||||
@@ -49,7 +49,6 @@ class FlashUtilityView : public View {
|
||||
|
||||
std::string title() const override { return "Flash Utility"; };
|
||||
bool flash_firmware(std::filesystem::path::string_type path);
|
||||
void wait_till_loaded();
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
@@ -68,14 +67,6 @@ class FlashUtilityView : public View {
|
||||
void firmware_selected(std::filesystem::path::string_type path);
|
||||
|
||||
bool endsWith(const std::u16string& str, const std::u16string& suffix);
|
||||
bool isLoaded = false;
|
||||
uint8_t refreshcnt = 0;
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
Message::ID::DisplayFrameSync,
|
||||
[this](const Message* const) {
|
||||
refreshcnt++;
|
||||
if (refreshcnt > 5) isLoaded = true;
|
||||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "portapack_io.hpp"
|
||||
#include "portapack.hpp"
|
||||
|
||||
#include "lpc43xx.inc"
|
||||
|
||||
#include "hackrf_hal.hpp"
|
||||
using namespace hackrf::one;
|
||||
|
||||
@@ -1211,47 +1213,47 @@ void ClockManager::enable_clock_output(bool enable) {
|
||||
#ifdef PRALINE
|
||||
|
||||
void ClockManager::set_p1_control(P1_Function func) {
|
||||
// Truth table based on P1_Control.csv (L=clear, H=set)
|
||||
// Truth table based on P1_Control.csv (L=setInactive, H=setActive)
|
||||
switch (func) {
|
||||
case P1_Function::TriggerIn:
|
||||
gpio_control::p1_ctrl2.clear();
|
||||
gpio_control::p1_ctrl1.clear();
|
||||
gpio_control::p1_ctrl0.clear();
|
||||
gpio_control::p1_ctrl2.setInactive();
|
||||
gpio_control::p1_ctrl1.setInactive();
|
||||
gpio_control::p1_ctrl0.setInactive();
|
||||
break;
|
||||
case P1_Function::AuxClk1:
|
||||
gpio_control::p1_ctrl2.clear();
|
||||
gpio_control::p1_ctrl1.clear();
|
||||
gpio_control::p1_ctrl0.set();
|
||||
gpio_control::p1_ctrl2.setInactive();
|
||||
gpio_control::p1_ctrl1.setInactive();
|
||||
gpio_control::p1_ctrl0.setActive();
|
||||
break;
|
||||
case P1_Function::ClkIn:
|
||||
gpio_control::p1_ctrl2.clear();
|
||||
gpio_control::p1_ctrl1.set();
|
||||
gpio_control::p1_ctrl0.clear();
|
||||
gpio_control::p1_ctrl2.setInactive();
|
||||
gpio_control::p1_ctrl1.setActive();
|
||||
gpio_control::p1_ctrl0.setInactive();
|
||||
break;
|
||||
case P1_Function::TriggerOut:
|
||||
gpio_control::p1_ctrl2.clear();
|
||||
gpio_control::p1_ctrl1.set();
|
||||
gpio_control::p1_ctrl0.set();
|
||||
gpio_control::p1_ctrl2.setInactive();
|
||||
gpio_control::p1_ctrl1.setActive();
|
||||
gpio_control::p1_ctrl0.setActive();
|
||||
break;
|
||||
case P1_Function::P22_ClkIn:
|
||||
gpio_control::p1_ctrl2.set();
|
||||
gpio_control::p1_ctrl1.clear();
|
||||
gpio_control::p1_ctrl0.clear();
|
||||
gpio_control::p1_ctrl2.setActive();
|
||||
gpio_control::p1_ctrl1.setInactive();
|
||||
gpio_control::p1_ctrl0.setInactive();
|
||||
break;
|
||||
case P1_Function::P2_5:
|
||||
gpio_control::p1_ctrl2.set();
|
||||
gpio_control::p1_ctrl1.clear();
|
||||
gpio_control::p1_ctrl0.set();
|
||||
gpio_control::p1_ctrl2.setActive();
|
||||
gpio_control::p1_ctrl1.setInactive();
|
||||
gpio_control::p1_ctrl0.setActive();
|
||||
break;
|
||||
case P1_Function::NotConnected:
|
||||
gpio_control::p1_ctrl2.set();
|
||||
gpio_control::p1_ctrl1.set();
|
||||
gpio_control::p1_ctrl0.clear();
|
||||
gpio_control::p1_ctrl2.setActive();
|
||||
gpio_control::p1_ctrl1.setActive();
|
||||
gpio_control::p1_ctrl0.setInactive();
|
||||
break;
|
||||
case P1_Function::AuxClk2:
|
||||
gpio_control::p1_ctrl2.set();
|
||||
gpio_control::p1_ctrl1.set();
|
||||
gpio_control::p1_ctrl0.set();
|
||||
gpio_control::p1_ctrl2.setActive();
|
||||
gpio_control::p1_ctrl1.setActive();
|
||||
gpio_control::p1_ctrl0.setActive();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1259,20 +1261,20 @@ void ClockManager::set_p1_control(P1_Function func) {
|
||||
void ClockManager::set_p2_control(P2_Function func) {
|
||||
// Ensure all P2 control pins are configured as outputs
|
||||
|
||||
// Truth table based on P2_Control.csv (L=clear, H=set)
|
||||
// Truth table based on P2_Control.csv (L=setInactive, H=setActive)
|
||||
switch (func) {
|
||||
case P2_Function::Clk3:
|
||||
// CTRL0 is 'X' (don't care) according to CSV, we default it to Low (clear)
|
||||
gpio_control::p2_ctrl1.clear();
|
||||
gpio_control::p2_ctrl0.clear();
|
||||
// CTRL0 is 'X' (don't care) according to CSV, we default it to Low (setInactive)
|
||||
gpio_control::p2_ctrl1.setInactive();
|
||||
gpio_control::p2_ctrl0.setInactive();
|
||||
break;
|
||||
case P2_Function::TriggerIn:
|
||||
gpio_control::p2_ctrl1.set();
|
||||
gpio_control::p2_ctrl0.clear();
|
||||
gpio_control::p2_ctrl1.setActive();
|
||||
gpio_control::p2_ctrl0.setInactive();
|
||||
break;
|
||||
case P2_Function::TriggerOut:
|
||||
gpio_control::p2_ctrl1.set();
|
||||
gpio_control::p2_ctrl0.set();
|
||||
gpio_control::p2_ctrl1.setActive();
|
||||
gpio_control::p2_ctrl0.setActive();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
#include "hackrf_gpio.hpp"
|
||||
#include "portapack_hal.hpp"
|
||||
|
||||
#include "board.h"
|
||||
|
||||
#include "gpio.hpp"
|
||||
using namespace gpio_control;
|
||||
|
||||
void config_mode_blink_until_dfu();
|
||||
|
||||
void config_mode_set() {
|
||||
@@ -103,16 +108,16 @@ void config_mode_run() {
|
||||
|
||||
auto tx_value = ((tx_blink_pattern >> ((counter >> 0) & 31)) & 0x1) == 0x1;
|
||||
if (tx_value) {
|
||||
hackrf::one::led_tx.on();
|
||||
led_tx.setActive();
|
||||
} else {
|
||||
hackrf::one::led_tx.off();
|
||||
led_tx.setInactive();
|
||||
}
|
||||
|
||||
auto rx_value = ((rx_blink_pattern >> ((counter >> 0) & 31)) & 0x1) == 0x1;
|
||||
if (rx_value) {
|
||||
hackrf::one::led_rx.on();
|
||||
led_rx.setActive();
|
||||
} else {
|
||||
hackrf::one::led_rx.off();
|
||||
led_rx.setInactive();
|
||||
}
|
||||
|
||||
chThdSleepMilliseconds(100);
|
||||
@@ -122,14 +127,14 @@ void config_mode_run() {
|
||||
|
||||
void config_mode_blink_until_dfu() {
|
||||
while (true) {
|
||||
hackrf::one::led_tx.on();
|
||||
hackrf::one::led_rx.on();
|
||||
hackrf::one::led_usb.on();
|
||||
led_tx.setActive();
|
||||
led_rx.setActive();
|
||||
led_usb.setActive();
|
||||
chThdSleepMilliseconds(10);
|
||||
|
||||
hackrf::one::led_tx.off();
|
||||
hackrf::one::led_rx.off();
|
||||
hackrf::one::led_usb.off();
|
||||
led_tx.setInactive();
|
||||
led_rx.setInactive();
|
||||
led_usb.setInactive();
|
||||
chThdSleepMilliseconds(115);
|
||||
|
||||
auto dfu_btn = portapack::gpio_dfu.read();
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#include "irq_controls.hpp"
|
||||
#include "file_path.hpp"
|
||||
|
||||
#include "gpio.hpp"
|
||||
using namespace gpio_control;
|
||||
|
||||
using namespace ui;
|
||||
|
||||
#define DEBUG_LOG_FILE "debug_log.txt"
|
||||
@@ -134,9 +137,9 @@ void draw_line(int32_t y_offset, const char* label, regarm_t value) {
|
||||
}
|
||||
|
||||
void runtime_error(uint8_t source) {
|
||||
LED led = (source == CORTEX_M0) ? hackrf::one::led_rx : hackrf::one::led_tx;
|
||||
const auto& led = (source == CORTEX_M0) ? led_rx : led_tx;
|
||||
|
||||
led.off();
|
||||
led.setInactive();
|
||||
|
||||
// wait for DFU button release if pressed, so we don't immediately jump into stack dump
|
||||
while (swizzled_switches() & (1 << (int)Switch::Dfu));
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
#include "gpio.hpp"
|
||||
using namespace gpio_control;
|
||||
|
||||
#include "irq_rtc.hpp"
|
||||
|
||||
@@ -56,8 +56,6 @@ using namespace hackrf::one;
|
||||
|
||||
#include "ui_navigation.hpp"
|
||||
|
||||
#include "gpio.hpp"
|
||||
|
||||
static int delayed_error = 0;
|
||||
|
||||
extern "C" {
|
||||
@@ -229,8 +227,8 @@ void EventDispatcher::charge_deep_sleep(const bool sleep) {
|
||||
|
||||
LPC_ADC0->CR &= ~(1 << 21);
|
||||
LPC_ADC1->CR &= ~(1 << 21);
|
||||
led_rx.off();
|
||||
led_usb.off();
|
||||
led_rx.setInactive();
|
||||
led_usb.setInactive();
|
||||
|
||||
rtc_wakeup_init();
|
||||
NVIC_EnableIRQ(I2C0_OR_I2C1_IRQn);
|
||||
@@ -247,21 +245,21 @@ void EventDispatcher::charge_deep_sleep(const bool sleep) {
|
||||
|
||||
if (is_full) {
|
||||
// Case 1: Battery full (All LEDs off)
|
||||
led_rx.off();
|
||||
led_tx.off();
|
||||
led_rx.setInactive();
|
||||
led_tx.setInactive();
|
||||
} else if ((voltage < 4150 && current < 10) || valid_mask == 0) {
|
||||
// Case 2: Not full but low current draw (<10mA) -> Charging error
|
||||
led_tx.on(); // LED indicates error/idle
|
||||
led_rx.off();
|
||||
led_tx.setActive(); // LED indicates error/idle
|
||||
led_rx.setInactive();
|
||||
} else {
|
||||
// Case 3: Actively charging
|
||||
led_rx.on(); // LED indicates charging
|
||||
led_tx.off();
|
||||
led_rx.setActive(); // LED indicates charging
|
||||
led_tx.setInactive();
|
||||
}
|
||||
} else {
|
||||
// Case 4: Battery IC not detected -> Error or H2 or older, so don't show that as an error.
|
||||
led_tx.on();
|
||||
led_rx.on();
|
||||
led_tx.setActive();
|
||||
led_rx.setActive();
|
||||
}
|
||||
|
||||
// Shut down I2C and power down the APB bus for sleep
|
||||
|
||||
+7
-1
@@ -327,7 +327,7 @@ set(EXTCPPSRC
|
||||
external/rtty_tx/ui_rtty_tx.cpp
|
||||
external/rtty_tx/baudot.cpp
|
||||
|
||||
#pocsag_tx
|
||||
#pocsag_tx
|
||||
external/pocsag_tx/main.cpp
|
||||
external/pocsag_tx/ui_pocsag_tx.cpp
|
||||
|
||||
@@ -362,6 +362,11 @@ set(EXTCPPSRC
|
||||
#hard_reset
|
||||
external/hard_reset/main.cpp
|
||||
external/hard_reset/ui_hard_reset.cpp
|
||||
|
||||
#secplustx
|
||||
external/secplustx/main.cpp
|
||||
external/secplustx/ui_secplustx.cpp
|
||||
external/secplustx/secplustx.cpp
|
||||
)
|
||||
|
||||
set(EXTAPPLIST
|
||||
@@ -451,6 +456,7 @@ set(EXTAPPLIST
|
||||
two_tone_pager
|
||||
two_tone_rx
|
||||
hard_reset
|
||||
secplustx
|
||||
)
|
||||
|
||||
# sdusb has type conflicts with PRALINE (HackRF Pro) - add only for non-PRALINE builds
|
||||
|
||||
+7
@@ -110,6 +110,7 @@ MEMORY
|
||||
ram_external_app_two_tone_rx (rwx) : org = 0xAE050000, len = 32k
|
||||
ram_external_app_flex_tx (rwx) : org = 0xAE060000, len = 32k
|
||||
ram_external_app_hard_reset (rwx) : org = 0xAE070000, len = 32k
|
||||
ram_external_app_secplustx (rwx) : org = 0xAE080000, len = 32k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -635,4 +636,10 @@ SECTIONS
|
||||
KEEP(*(.external_app.app_hard_reset.application_information));
|
||||
*(*ui*external_app*hard_reset*);
|
||||
} > ram_external_app_hard_reset
|
||||
|
||||
.external_app_secplustx : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_secplustx.application_information));
|
||||
*(*ui*external_app*secplustx*);
|
||||
} > ram_external_app_secplustx
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Synray
|
||||
*
|
||||
* 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.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_secplustx.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::ui_secplustx {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<SecplusTXView>();
|
||||
}
|
||||
} // namespace ui::external_app::ui_secplustx
|
||||
|
||||
extern "C" {
|
||||
|
||||
__attribute__((section(".external_app.app_secplustx.application_information"), used)) application_information_t _application_information_secplustx = {
|
||||
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||
/*.externalAppEntry = */ ui::external_app::ui_secplustx::initialize_app,
|
||||
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||
/*.app_version = */ VERSION_MD5,
|
||||
/*.app_name = */ "Security+",
|
||||
/*.bitmap_data = */ {
|
||||
0b00100000,
|
||||
0b00000000,
|
||||
0b00100000,
|
||||
0b00100000,
|
||||
0b00100000,
|
||||
0b01110000,
|
||||
0b00100000,
|
||||
0b00100000,
|
||||
0b11100000,
|
||||
0b00000111,
|
||||
0b11110000,
|
||||
0b00001111,
|
||||
0b00110000,
|
||||
0b00001100,
|
||||
0b00110000,
|
||||
0b00001100,
|
||||
0b11110000,
|
||||
0b00001111,
|
||||
0b11110000,
|
||||
0b00001111,
|
||||
0b01110000,
|
||||
0b00001101,
|
||||
0b10110000,
|
||||
0b00001110,
|
||||
0b01110000,
|
||||
0b00001101,
|
||||
0b10110000,
|
||||
0b00001110,
|
||||
0b11110000,
|
||||
0b00001111,
|
||||
0b11100000,
|
||||
0b00000111,
|
||||
},
|
||||
/*.icon_color = */ ui::Color::yellow().v,
|
||||
/*.menu_location = */ app_location_t::TX,
|
||||
/*.desired_menu_position = */ -1,
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_ook */ {'P', 'O', 'O', 'K'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2022 Clayton Smith (argilo@gmail.com)
|
||||
*
|
||||
* This file is part of secplus.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*/
|
||||
|
||||
#include "secplustx.hpp"
|
||||
|
||||
namespace ui::external_app::ui_secplustx {
|
||||
|
||||
static void v2_calc_parity(const uint64_t fixed, uint32_t* data) {
|
||||
uint32_t parity = (fixed >> 32) & 0xf;
|
||||
int8_t offset;
|
||||
|
||||
*data &= 0xffff0fff;
|
||||
for (offset = 0; offset < 32; offset += 4) {
|
||||
parity ^= ((*data >> offset) & 0xf);
|
||||
}
|
||||
*data |= (parity << 12);
|
||||
}
|
||||
|
||||
static void encode_v2_rolling(const uint32_t rolling,
|
||||
uint32_t* rolling_halves) {
|
||||
uint32_t rolling_reversed = 0;
|
||||
int8_t i, half;
|
||||
|
||||
for (i = 0; i < 28; i++) {
|
||||
rolling_reversed |= ((rolling >> i) & 1) << (28 - i - 1);
|
||||
}
|
||||
|
||||
rolling_halves[0] = 0;
|
||||
rolling_halves[1] = 0;
|
||||
|
||||
for (half = 0; half < 2; half++) {
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
rolling_halves[half] |= rolling_reversed % 3 << i;
|
||||
rolling_reversed /= 3;
|
||||
}
|
||||
}
|
||||
|
||||
for (half = 0; half < 2; half++) {
|
||||
for (i = 10; i < 18; i += 2) {
|
||||
rolling_halves[half] |= rolling_reversed % 3 << i;
|
||||
rolling_reversed /= 3;
|
||||
}
|
||||
}
|
||||
|
||||
rolling_halves[0] |= (rolling_reversed % 3) << 8;
|
||||
rolling_reversed /= 3;
|
||||
|
||||
rolling_halves[1] |= (rolling_reversed % 3) << 8;
|
||||
}
|
||||
|
||||
static const int8_t ORDER[16] = {9, 33, 6, -1, 24, 18, 36, -1,
|
||||
24, 36, 6, -1, -1, -1, -1, -1};
|
||||
static const int8_t INVERT[16] = {6, 2, 1, -1, 7, 5, 3, -1,
|
||||
4, 0, 5, -1, -1, -1, -1, -1};
|
||||
|
||||
static void v2_scramble(const uint32_t* parts, const uint8_t frame_type, uint8_t* packet_half) {
|
||||
const int8_t order = ORDER[packet_half[0] >> 4];
|
||||
const int8_t invert = INVERT[packet_half[0] & 0xf];
|
||||
int8_t i;
|
||||
uint8_t out_offset = 10;
|
||||
int8_t end;
|
||||
uint32_t parts_permuted[3];
|
||||
|
||||
end = (frame_type == 0 ? 5 : 8);
|
||||
for (i = 1; i < end; i++) {
|
||||
packet_half[i] = 0;
|
||||
}
|
||||
|
||||
parts_permuted[0] =
|
||||
(invert & 4) ? ~parts[(order >> 4) & 3] : parts[(order >> 4) & 3];
|
||||
parts_permuted[1] =
|
||||
(invert & 2) ? ~parts[(order >> 2) & 3] : parts[(order >> 2) & 3];
|
||||
parts_permuted[2] = (invert & 1) ? ~parts[order & 3] : parts[order & 3];
|
||||
|
||||
end = (frame_type == 0 ? 8 : 0);
|
||||
for (i = 18 - 1; i >= end; i--) {
|
||||
packet_half[out_offset >> 3] |= ((parts_permuted[0] >> i) & 1)
|
||||
<< (7 - (out_offset % 8));
|
||||
out_offset++;
|
||||
packet_half[out_offset >> 3] |= ((parts_permuted[1] >> i) & 1)
|
||||
<< (7 - (out_offset % 8));
|
||||
out_offset++;
|
||||
packet_half[out_offset >> 3] |= ((parts_permuted[2] >> i) & 1)
|
||||
<< (7 - (out_offset % 8));
|
||||
out_offset++;
|
||||
}
|
||||
}
|
||||
|
||||
static void encode_v2_half_parts(const uint32_t rolling, const uint32_t fixed, const uint16_t data, const uint8_t frame_type, uint8_t* packet_half) {
|
||||
uint32_t parts[3];
|
||||
|
||||
parts[0] = ((fixed >> 10) << 8) | (data >> 8);
|
||||
parts[1] = ((fixed & 0x3ff) << 8) | (data & 0xff);
|
||||
parts[2] = rolling;
|
||||
|
||||
packet_half[0] = (uint8_t)rolling;
|
||||
|
||||
v2_scramble(parts, frame_type, packet_half);
|
||||
}
|
||||
|
||||
static int8_t v2_check_limits(const uint32_t rolling, const uint64_t fixed) {
|
||||
if ((rolling >> 28) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fixed >> 40) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void encode_v2_half(const uint32_t rolling, const uint32_t fixed, const uint16_t data, const uint8_t frame_type, uint8_t* packet_half) {
|
||||
encode_v2_half_parts(rolling, fixed, data, frame_type, packet_half);
|
||||
|
||||
/* shift indicator two bits to the right */
|
||||
packet_half[1] |= (packet_half[0] & 0x3) << 6;
|
||||
packet_half[0] >>= 2;
|
||||
|
||||
/* set frame type */
|
||||
packet_half[0] |= (frame_type << 6);
|
||||
}
|
||||
|
||||
int8_t encode_v2(const uint32_t rolling, const uint64_t fixed, uint32_t data, const uint8_t frame_type, uint8_t* packet1, uint8_t* packet2) {
|
||||
int8_t err = 0;
|
||||
uint32_t rolling_halves[2];
|
||||
|
||||
err = v2_check_limits(rolling, fixed);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
encode_v2_rolling(rolling, rolling_halves);
|
||||
v2_calc_parity(fixed, &data);
|
||||
|
||||
encode_v2_half(rolling_halves[0], fixed >> 20, data >> 16, frame_type,
|
||||
packet1);
|
||||
encode_v2_half(rolling_halves[1], fixed & 0xfffff, data & 0xffff, frame_type,
|
||||
packet2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}; // namespace ui::external_app::ui_secplustx
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2022 Clayton Smith (argilo@gmail.com)
|
||||
*
|
||||
* This file is part of secplus.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECPLUSTX__
|
||||
#define __SECPLUSTX__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ui::external_app::ui_secplustx {
|
||||
int8_t encode_v2(const uint32_t rolling, const uint64_t fixed, uint32_t data, const uint8_t frame_type, uint8_t* packet1, uint8_t* packet2);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,227 @@
|
||||
#include "ui_secplustx.hpp"
|
||||
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "secplustx.hpp"
|
||||
#include "ui_fileman.hpp"
|
||||
#include "file_reader.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "optional.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace ui;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace ui::external_app::ui_secplustx {
|
||||
|
||||
static constexpr uint8_t secplus_repeat_count = 3;
|
||||
static constexpr float secplus_sample_rate = OOK_SAMPLERATE / 4000.0f;
|
||||
|
||||
Optional<SecplusData> SecplusTXView::read_secplus_file(const fs::path& file_path) {
|
||||
File file{};
|
||||
if (auto error = file.open(file_path)) return {};
|
||||
|
||||
std::string raw = *FileLineReader{file}.begin();
|
||||
std::vector chunks = split_string(raw, ';');
|
||||
if (chunks.empty()) return {};
|
||||
|
||||
SecplusData data{};
|
||||
data.version = static_cast<SecplusVersion>(std::strtoul(chunks[0].data(), NULL, 10));
|
||||
switch (data.version) {
|
||||
case SecplusVersion::V1:
|
||||
return {}; // unimplemented
|
||||
case SecplusVersion::V2: {
|
||||
if (chunks.size() != 6) return {};
|
||||
data.name = std::string{chunks[1]};
|
||||
if (data.name.empty()) data.name = "Remote";
|
||||
data.has_data = std::strtoul(chunks[2].data(), NULL, 10);
|
||||
data.fixed_code = std::strtoull(chunks[3].data(), NULL, 16);
|
||||
data.rolling_code = std::strtoul(chunks[4].data(), NULL, 16);
|
||||
data.data = std::strtoul(chunks[5].data(), NULL, 16);
|
||||
return data;
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool SecplusTXView::write_secplus_file(const fs::path& file_path, const SecplusData& data) {
|
||||
ensure_directory(secplus_dir);
|
||||
File file{};
|
||||
if (auto error = file.create(file_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (data.version) {
|
||||
case SecplusVersion::V1:
|
||||
return false; // unimplemented
|
||||
case SecplusVersion::V2: {
|
||||
std::string formatted = to_string_dec_uint(static_cast<uint8_t>(data.version));
|
||||
formatted += ';';
|
||||
formatted += data.name;
|
||||
formatted += ';';
|
||||
formatted += to_string_dec_uint(data.has_data);
|
||||
formatted += ';';
|
||||
formatted += to_string_hex(data.fixed_code);
|
||||
formatted += ';';
|
||||
formatted += to_string_hex(data.rolling_code);
|
||||
formatted += ';';
|
||||
formatted += to_string_hex(data.data);
|
||||
file.write_line(formatted);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SecplusTXView::SecplusTXView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
if (!fs::file_exists(file_path)) write_secplus_file(file_path, data);
|
||||
baseband::run_image(portapack::spi_flash::image_tag_ook);
|
||||
|
||||
add_children({&button_open,
|
||||
&button_save,
|
||||
&field_name,
|
||||
&labels,
|
||||
&field_fixed,
|
||||
&field_rolling,
|
||||
&has_data,
|
||||
&field_data,
|
||||
&learn_mode,
|
||||
&autosave,
|
||||
&progressbar,
|
||||
&tx_view});
|
||||
|
||||
button_open.on_select = [this](const Button&) {
|
||||
ensure_directory(secplus_dir);
|
||||
auto open_view = nav_.push<FileLoadView>(".SECPLUS");
|
||||
open_view->push_dir(secplus_dir);
|
||||
open_view->on_changed = [this](fs::path path) { file_path = path.string(); };
|
||||
nav_.set_on_pop([this]() { reload_data(); });
|
||||
};
|
||||
button_save.on_select = [this](const Button&) { write_secplus_file(file_path, data); };
|
||||
|
||||
field_name.on_select = [this, &nav](TextField&) {
|
||||
buffer = data.name;
|
||||
text_prompt(nav_, buffer, field_name.parent_rect().width() / UI_POS_DEFAULT_WIDTH, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_name) {
|
||||
data.name = new_name;
|
||||
field_name.set_text(new_name);
|
||||
save_data();
|
||||
});
|
||||
};
|
||||
field_fixed.on_change = [this](SymField& field) { data.fixed_code = field.to_integer(); };
|
||||
field_rolling.on_change = [this](SymField& field) { data.rolling_code = field.to_integer(); };
|
||||
field_data.on_change = [this](SymField& field) { data.data = field.to_integer(); };
|
||||
has_data.on_select = [this](Checkbox& checkbox, bool value) {
|
||||
data.has_data = value;
|
||||
// fade if inactive, otherwise use default style
|
||||
const Style* new_style = value ? &style() : Theme::getInstance()->fg_medium;
|
||||
checkbox.set_style(new_style);
|
||||
field_data.set_style(new_style);
|
||||
field_data.set_focusable(value);
|
||||
};
|
||||
tx_view.on_edit_frequency = [this]() {
|
||||
auto new_view = nav_.push<FrequencyKeypadView>(transmitter_model.target_frequency());
|
||||
new_view->on_changed = [](rf::Frequency f) {
|
||||
transmitter_model.set_target_frequency(f);
|
||||
};
|
||||
};
|
||||
|
||||
tx_view.on_start = [this]() { start_tx(); };
|
||||
tx_view.on_stop = [this]() {
|
||||
baseband::kill_ook();
|
||||
stop_tx();
|
||||
};
|
||||
|
||||
autosave.set_value(true);
|
||||
reload_data();
|
||||
}
|
||||
|
||||
void SecplusTXView::save_data() {
|
||||
if (autosave.value()) write_secplus_file(file_path, data);
|
||||
}
|
||||
|
||||
void SecplusTXView::reload_data() {
|
||||
if (auto result = read_secplus_file(file_path)) data = std::move(*result);
|
||||
// always update data, use default values if read failed
|
||||
field_name.set_text(data.name);
|
||||
has_data.set_value(data.has_data);
|
||||
field_rolling.set_value(data.rolling_code);
|
||||
field_fixed.set_value(data.fixed_code);
|
||||
field_data.set_value(data.data);
|
||||
}
|
||||
|
||||
void SecplusTXView::start_tx() {
|
||||
uint8_t packet1[8]{};
|
||||
uint8_t packet2[8]{};
|
||||
size_t bitstream_length = 0;
|
||||
|
||||
constexpr uint8_t packet1_indicator = 0b00;
|
||||
constexpr uint8_t packet2_indicator = 0b01;
|
||||
auto encode_packet = [&bitstream_length](uint8_t indicator, auto& packet, bool has_data) {
|
||||
constexpr uint32_t preamble = 0b0000000000000000'1111;
|
||||
constexpr uint32_t blank_size = 24;
|
||||
auto manchester_encode = [&bitstream_length](auto& x, uint32_t size) {
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
bool bit = (x >> (size - 1 - i)) & 1;
|
||||
encoders::bitstream_append(bitstream_length, 2, bit ? 0b01 : 0b10);
|
||||
}
|
||||
};
|
||||
manchester_encode(preamble, 20);
|
||||
manchester_encode(indicator, 2);
|
||||
for (uint8_t byte = 0; byte < (has_data ? 8 : 5); ++byte) manchester_encode(packet[byte], 8);
|
||||
encoders::bitstream_append(bitstream_length, blank_size, 0);
|
||||
};
|
||||
|
||||
if (encode_v2(data.rolling_code, data.fixed_code, data.data, data.has_data, packet1, packet2) < 0) {
|
||||
nav_.display_modal("Error", "Invalid rolling/fixed code");
|
||||
return;
|
||||
}
|
||||
encode_packet(packet1_indicator, packet1, has_data.value());
|
||||
encode_packet(packet2_indicator, packet2, has_data.value());
|
||||
|
||||
if (!learn_mode.value()) {
|
||||
field_rolling.set_value(++data.rolling_code);
|
||||
field_rolling.set_dirty();
|
||||
}
|
||||
|
||||
progressbar.set_max(secplus_repeat_count);
|
||||
progressbar.set_value(1);
|
||||
|
||||
tx_view.set_transmitting(true);
|
||||
transmitter_model.enable();
|
||||
baseband::set_ook_data(
|
||||
bitstream_length,
|
||||
secplus_sample_rate,
|
||||
secplus_repeat_count,
|
||||
0);
|
||||
}
|
||||
|
||||
void SecplusTXView::stop_tx() {
|
||||
transmitter_model.disable();
|
||||
progressbar.set_value(0);
|
||||
tx_view.set_transmitting(false);
|
||||
}
|
||||
|
||||
void SecplusTXView::on_tx_progress(uint32_t progress, bool done) {
|
||||
progressbar.set_value(progress + 1);
|
||||
if (done) {
|
||||
stop_tx();
|
||||
save_data();
|
||||
}
|
||||
}
|
||||
|
||||
SecplusTXView::~SecplusTXView() {
|
||||
transmitter_model.disable();
|
||||
baseband::shutdown();
|
||||
save_data();
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::ui_secplustx
|
||||
@@ -0,0 +1,96 @@
|
||||
#ifndef __UI_SECPLUSTX__
|
||||
#define __UI_SECPLUSTX__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "file.hpp"
|
||||
#include "ui_transmitter.hpp"
|
||||
#include "transmitter_model.hpp"
|
||||
#include "file_path.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "radio_state.hpp"
|
||||
#include "encoders.hpp"
|
||||
#include "string_format.hpp"
|
||||
|
||||
namespace ui::external_app::ui_secplustx {
|
||||
|
||||
enum class SecplusVersion : uint8_t {
|
||||
V1,
|
||||
V2,
|
||||
};
|
||||
|
||||
struct SecplusData {
|
||||
SecplusVersion version;
|
||||
std::string name;
|
||||
bool has_data;
|
||||
uint64_t fixed_code;
|
||||
uint32_t rolling_code;
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
class SecplusTXView : public View {
|
||||
public:
|
||||
void focus() override { button_open.focus(); }
|
||||
SecplusTXView(NavigationView& nav);
|
||||
~SecplusTXView();
|
||||
|
||||
std::string title() const override {
|
||||
return "Security+";
|
||||
}
|
||||
|
||||
private:
|
||||
std::string file_path = (secplus_dir / "DEFAULT.SECPLUS").string();
|
||||
SecplusData data{SecplusVersion::V2, "Remote", false, 0, 0, 0};
|
||||
std::string buffer{};
|
||||
|
||||
NavigationView& nav_;
|
||||
TxRadioState radio_state_{
|
||||
315000000,
|
||||
1750000,
|
||||
OOK_SAMPLERATE};
|
||||
|
||||
app_settings::SettingsManager settings_{"tx_secplus", app_settings::Mode::TX, {{"file_path"sv, &file_path}}};
|
||||
|
||||
Button button_open{{UI_POS_X(1), UI_POS_Y(1), screen_width / 2 - UI_POS_X(1), UI_POS_HEIGHT(2)}, "Open"};
|
||||
Button button_save{{screen_width / 2, UI_POS_Y(1), screen_width / 2 - UI_POS_X(1), UI_POS_HEIGHT(2)}, "Save"};
|
||||
|
||||
// remote data
|
||||
TextField field_name{{UI_POS_X(1), UI_POS_Y(3), UI_POS_WIDTH_REMAINING(2), UI_POS_HEIGHT(1)}, "Remote"};
|
||||
Labels labels{
|
||||
{{UI_POS_X(1), UI_POS_Y(4)}, "Fixed:", Theme::getInstance()->fg_medium->foreground},
|
||||
{{UI_POS_X(1), UI_POS_Y(5)}, "Rolling:", Theme::getInstance()->fg_medium->foreground}};
|
||||
SymField field_fixed{{UI_POS_X(10), UI_POS_Y(4)}, 10, SymField::Type::Hex, true};
|
||||
SymField field_rolling{{UI_POS_X(10), UI_POS_Y(5)}, 7, SymField::Type::Hex, true};
|
||||
Checkbox has_data{{UI_POS_X(1), UI_POS_Y(6)}, 5, "Data:", true};
|
||||
SymField field_data{{UI_POS_X(10), UI_POS_Y(6)}, 8, SymField::Type::Hex, true};
|
||||
|
||||
// options
|
||||
Checkbox learn_mode{{UI_POS_X(1), UI_POS_Y(7)}, 5, "Learn", true};
|
||||
Checkbox autosave{{UI_POS_X(1), UI_POS_Y(8)}, 8, "Autosave", true};
|
||||
|
||||
ProgressBar progressbar{{UI_POS_X(2), UI_POS_Y_BOTTOM(5.75), UI_POS_WIDTH_REMAINING(4), UI_POS_HEIGHT(1)}};
|
||||
|
||||
TransmitterView tx_view{UI_POS_Y_BOTTOM(4), 1000000, 0};
|
||||
|
||||
Optional<SecplusData> read_secplus_file(const std::filesystem::path& file_path);
|
||||
bool write_secplus_file(const std::filesystem::path& file_path, const SecplusData& data);
|
||||
void save_data();
|
||||
void reload_data();
|
||||
void start_tx();
|
||||
void stop_tx();
|
||||
|
||||
void on_tx_progress(uint32_t progress, bool done);
|
||||
|
||||
MessageHandlerRegistration message_handler_tx_progress{
|
||||
Message::ID::TXProgress,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
||||
this->on_tx_progress(message.progress, message.done);
|
||||
}};
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::ui_secplustx
|
||||
|
||||
#endif
|
||||
@@ -57,4 +57,5 @@ const std::filesystem::path macaddress_dir = u"MACADDRESS";
|
||||
const std::filesystem::path splash_dot_bmp = u"/splash.bmp";
|
||||
const std::filesystem::path keeloq_keys_dir = u"KEELOQKEYS";
|
||||
const std::filesystem::path keeloq_remotes_dir = u"KEELOQREMOTES";
|
||||
const std::filesystem::path secplus_dir = u"SECPLUS";
|
||||
const std::filesystem::path epirb_dir = u"EPIRB";
|
||||
|
||||
@@ -58,6 +58,7 @@ extern const std::filesystem::path waterfalls_dir;
|
||||
extern const std::filesystem::path macaddress_dir;
|
||||
extern const std::filesystem::path keeloq_keys_dir;
|
||||
extern const std::filesystem::path keeloq_remotes_dir;
|
||||
extern const std::filesystem::path secplus_dir;
|
||||
extern const std::filesystem::path epirb_dir;
|
||||
|
||||
extern const std::filesystem::path splash_dot_bmp;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "gpio_lpc.h"
|
||||
#include "gpio.h"
|
||||
#include "delay.h"
|
||||
|
||||
typedef enum {
|
||||
LED1 = 0,
|
||||
@@ -34,6 +35,15 @@ void delay_us_at_mhz(uint32_t us, uint32_t mhz) {
|
||||
delay((uint32_t)cycles64);
|
||||
}
|
||||
|
||||
/* The application M0 core runs from BASE_M4_CLK at 200MHz. */
|
||||
void delay_us(uint32_t us) {
|
||||
delay_us_at_mhz(us, 200);
|
||||
}
|
||||
|
||||
void delay_ms(uint32_t ms) {
|
||||
delay_us_at_mhz(ms * 1000, 200);
|
||||
}
|
||||
|
||||
void led_on(const led_t led) {
|
||||
gpio_set(&gpio_led[led]);
|
||||
}
|
||||
|
||||
@@ -347,9 +347,9 @@ void MAX2831::set_lpf_rf_bandwidth_rx(const uint32_t bandwidth_minimum) {
|
||||
* external Anti-Aliasing (AA) filter on pin P1_14 to prevent aliasing.
|
||||
*/
|
||||
if (actual_bw <= 1750000) {
|
||||
gpio_control::aa_en.set(); // Enable external narrow AA filter
|
||||
gpio_control::aa_en.setActive(); // Enable external narrow AA filter
|
||||
} else {
|
||||
gpio_control::aa_en.clear(); // Disable external AA filter for wideband operations
|
||||
gpio_control::aa_en.setInactive(); // Disable external AA filter for wideband operations
|
||||
}
|
||||
|
||||
_desired_lpf_bw = actual_bw;
|
||||
|
||||
@@ -176,7 +176,7 @@ struct SynthConfig {
|
||||
|
||||
void RFFC507x::init() {
|
||||
#ifdef PRALINE
|
||||
gpio_control::rf5072_mix_en.set(); // RF5072_MIX_EN
|
||||
gpio_control::rf5072_mix_en.setActive(); // RF5072_MIX_EN
|
||||
#endif
|
||||
|
||||
gpio_rffc5072_resetx.set();
|
||||
|
||||
@@ -132,7 +132,6 @@ Continuous (Fox-oring)
|
||||
#include "spi_image.hpp"
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "led.hpp"
|
||||
|
||||
#include "gcc.hpp"
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ using namespace hackrf::one;
|
||||
#include "baseband_api.hpp"
|
||||
#include "hal.h" // For LPC_SGPIO
|
||||
|
||||
#include "gpio.hpp"
|
||||
using namespace gpio_control;
|
||||
|
||||
#include <array>
|
||||
|
||||
/* Direct access to the radio. Setting values incorrectly can damage
|
||||
@@ -280,9 +283,9 @@ void set_direction(const rf::Direction new_direction) {
|
||||
baseband_codec.set_mode((direction == rf::Direction::Transmit) ? max5864::Mode::Transmit : max5864::Mode::Receive);
|
||||
|
||||
if (direction == rf::Direction::Receive)
|
||||
led_rx.on();
|
||||
led_rx.setActive();
|
||||
else
|
||||
led_tx.on();
|
||||
led_tx.setActive();
|
||||
}
|
||||
|
||||
bool set_tuning_frequency(const rf::Frequency frequency) {
|
||||
@@ -442,8 +445,8 @@ void disable() {
|
||||
first_if.disable();
|
||||
set_rf_amp(false);
|
||||
|
||||
led_rx.off();
|
||||
led_tx.off();
|
||||
led_rx.setInactive();
|
||||
led_tx.setInactive();
|
||||
}
|
||||
|
||||
#ifdef PRALINE
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
#include "audio.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "event_m0.hpp"
|
||||
#include "hackrf_gpio.hpp"
|
||||
#include "gpio.hpp"
|
||||
using namespace gpio_control;
|
||||
|
||||
#include "portapack.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "radio.hpp"
|
||||
|
||||
@@ -237,26 +237,69 @@ void GeoMap::map_read_line_bin(ui::Color* buffer, uint16_t pixels) {
|
||||
if (map_zoom == 1) {
|
||||
map_file.read(buffer, pixels << 1);
|
||||
} else if (map_zoom > 1) {
|
||||
map_file.read(buffer, (pixels / map_zoom) << 1);
|
||||
|
||||
// Zoom in: Expand each pixel to "map_zoom" number of pixels.
|
||||
// Future TODO: Add dithering to smooth out the pixelation.
|
||||
// As long as MOD(width,map_zoom)==0 then we don't need to check buffer overflow case when stretching last pixel;
|
||||
// For 240 width, than means no check is needed for map_zoom values up to 6.
|
||||
// (Rectangle height must also divide evenly into map_zoom or we get black lines at end of screen)
|
||||
// Note that zooming in results in a map offset of (1/map_zoom) pixels to the right & downward directions (see zoom_pixel_offset).
|
||||
for (int i = (width / map_zoom) - 1; i >= 0; i--) {
|
||||
for (int j = 0; j < map_zoom; j++) {
|
||||
buffer[(i * map_zoom) + j] = buffer[i];
|
||||
// Calculate how many source pixels we actually need from the file
|
||||
uint16_t src_pixels_needed = (pixels + map_zoom - 1) / map_zoom;
|
||||
if (src_pixels_needed == 0) src_pixels_needed = 1;
|
||||
// Position the source data at the very END of the buffer.
|
||||
// This allows us to overwrite the buffer from left-to-right safely.
|
||||
uint16_t src_offset = pixels - src_pixels_needed;
|
||||
// Read directly into the tail of the target buffer. Zero extra RAM needed.
|
||||
map_file.read(&buffer[src_offset], src_pixels_needed << 1);
|
||||
// Process forwards. Because `dst` grows by 1 and the source index grows by 1/map_zoom,
|
||||
// `dst` will never catch up to overwrite a source pixel before we are done with it.
|
||||
for (uint16_t dst = 0; dst < pixels; ++dst) {
|
||||
uint16_t i0 = dst / map_zoom;
|
||||
uint16_t i1 = i0 + 1;
|
||||
// Clamp the right-hand pixel to avoid reading out of bounds on the last iteration
|
||||
if (i1 >= src_pixels_needed) {
|
||||
i1 = src_pixels_needed - 1;
|
||||
}
|
||||
// 'frac' represents the integer distance from the left pixel (0 to map_zoom - 1)
|
||||
uint16_t frac = dst % map_zoom;
|
||||
// Fetch colors from the tail of our buffer
|
||||
ui::Color c0 = buffer[src_offset + i0];
|
||||
ui::Color c1 = buffer[src_offset + i1];
|
||||
if (frac == 0) {
|
||||
// Exact pixel match, bypass the math entirely for a speed boost
|
||||
buffer[dst] = c0;
|
||||
} else {
|
||||
uint32_t inv_frac = map_zoom - frac;
|
||||
uint8_t r = ((uint32_t)c0.r() * inv_frac + (uint32_t)c1.r() * frac) / map_zoom;
|
||||
uint8_t g = ((uint32_t)c0.g() * inv_frac + (uint32_t)c1.g() * frac) / map_zoom;
|
||||
uint8_t b = ((uint32_t)c0.b() * inv_frac + (uint32_t)c1.b() * frac) / map_zoom;
|
||||
buffer[dst] = ui::Color(r, g, b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ui::Color zoom_out_buffer[(pixels * (-map_zoom))];
|
||||
map_file.read(zoom_out_buffer, (pixels * (-map_zoom)) << 1);
|
||||
// Zoom out: Collapse each group of "-map_zoom" pixels into one pixel.
|
||||
// Future TODO: Average each group of pixels (in both X & Y directions if possible).
|
||||
for (int i = 0; i < width; i++) {
|
||||
buffer[i] = zoom_out_buffer[i * (-map_zoom)];
|
||||
const int skip = -map_zoom;
|
||||
const int MAX_BUFFER_ELEMENTS = 256;
|
||||
// Fixed-size local array avoids VLA crashes.
|
||||
ui::Color zoom_out_buffer[MAX_BUFFER_ELEMENTS];
|
||||
const int total_elements_needed = pixels * skip;
|
||||
// Use the default size, but strictly cap it at 256 to protect the stack
|
||||
const int chunk_size = total_elements_needed < MAX_BUFFER_ELEMENTS ? total_elements_needed : MAX_BUFFER_ELEMENTS;
|
||||
int target_i = 0;
|
||||
int current_file_offset = 0;
|
||||
// Sequentially read through the required portion of the file in chunks
|
||||
while (target_i < width && current_file_offset < total_elements_needed) {
|
||||
// Calculate how many pixels we can read in this specific pass
|
||||
int read_size = chunk_size < (total_elements_needed - current_file_offset) ? chunk_size : (total_elements_needed - current_file_offset);
|
||||
// Read the chunk (<< 1 converts pixel count to byte count)
|
||||
map_file.read(zoom_out_buffer, read_size << 1);
|
||||
// Determine where the first valid "zoomed" pixel is located inside this specific chunk
|
||||
int first_valid_index = 0;
|
||||
int offset_modulo = current_file_offset % skip;
|
||||
if (offset_modulo != 0) {
|
||||
first_valid_index = skip - offset_modulo;
|
||||
}
|
||||
// Extract only the pixels we need, skipping the rest
|
||||
for (int j = first_valid_index; j < read_size; j += skip) {
|
||||
if (target_i < width) {
|
||||
buffer[target_i] = zoom_out_buffer[j];
|
||||
target_i++;
|
||||
}
|
||||
}
|
||||
current_file_offset += read_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -415,8 +458,7 @@ bool GeoMap::draw_osm_file(int zoom, int tile_x, int tile_y, int relative_x, int
|
||||
return true;
|
||||
}
|
||||
|
||||
BMPFile bmp{};
|
||||
bmp.open("/OSM/" + to_string_dec_int(zoom) + "/" + to_string_dec_int(tile_x) + "/" + to_string_dec_int(tile_y) + ".bmp", true);
|
||||
BMPFile* bmp = bmp_cache.get(zoom, tile_x, tile_y);
|
||||
// 1. Define the source and destination areas, starting with the full tile.
|
||||
int src_x = 0;
|
||||
int src_y = 0;
|
||||
@@ -449,7 +491,7 @@ bool GeoMap::draw_osm_file(int zoom, int tile_x, int tile_y, int relative_x, int
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!bmp.is_loaded()) {
|
||||
if (!bmp || !bmp->is_loaded()) {
|
||||
// Draw an error rectangle using the calculated clipped dimensions
|
||||
ui::Rect error_rect{{dest_x + r.left(), dest_y + r.top()}, {clip_w, clip_h}};
|
||||
display.fill_rectangle(error_rect, Theme::getInstance()->bg_darkest->background);
|
||||
@@ -458,20 +500,20 @@ bool GeoMap::draw_osm_file(int zoom, int tile_x, int tile_y, int relative_x, int
|
||||
|
||||
map_line_buffer.resize(clip_w);
|
||||
|
||||
if (bmp.is_bottomup()) {
|
||||
if (bmp->is_bottomup()) {
|
||||
for (int y = clip_h - 1; y >= 0; --y) {
|
||||
int source_row = src_y + y;
|
||||
int dest_row = dest_y + y;
|
||||
bmp.seek(src_x, source_row);
|
||||
bmp.read_next_px_cnt(map_line_buffer.data(), clip_w, false);
|
||||
bmp->seek(src_x, source_row);
|
||||
bmp->read_next_px_cnt(map_line_buffer.data(), clip_w, false);
|
||||
display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, map_line_buffer);
|
||||
}
|
||||
} else {
|
||||
for (int y = 0; y < clip_h; ++y) {
|
||||
int source_row = src_y + y;
|
||||
int dest_row = dest_y + y;
|
||||
bmp.seek(src_x, source_row);
|
||||
bmp.read_next_px_cnt(map_line_buffer.data(), clip_w, false);
|
||||
bmp->seek(src_x, source_row);
|
||||
bmp->read_next_px_cnt(map_line_buffer.data(), clip_w, false);
|
||||
display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, map_line_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,16 @@
|
||||
#include "bmpfile.hpp"
|
||||
#include "mathdef.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <inttypes.h>
|
||||
#include "portapack.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
#define MAX_MAP_ZOOM_IN 4000
|
||||
#define MAX_MAP_ZOOM_OUT 10
|
||||
#define MAP_ZOOM_RESOLUTION_LIMIT 5 // Max zoom-in to show map; rect height & width must divide into this evenly
|
||||
#define MAX_MAP_ZOOM_OUT 15
|
||||
#define MAP_ZOOM_RESOLUTION_LIMIT 10 // Max zoom-in to show map;
|
||||
|
||||
#define INVALID_LAT_LON 200
|
||||
#define INVALID_ANGLE 400
|
||||
@@ -74,6 +77,101 @@ struct GeoMarker {
|
||||
}
|
||||
};
|
||||
|
||||
class BMPFileCache {
|
||||
public:
|
||||
static constexpr uint8_t SlotsCount = 9;
|
||||
|
||||
BMPFileCache() {
|
||||
}
|
||||
|
||||
~BMPFileCache() {
|
||||
clear();
|
||||
}
|
||||
|
||||
BMPFile* get(const int32_t z, const int32_t x, const int32_t y) {
|
||||
// Cache hit.
|
||||
for (auto& slot : slots_) {
|
||||
if (slot.used && slot.x == x && slot.y == y && slot.z == z) {
|
||||
slot.last_used = next_stamp();
|
||||
return &slot.bmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Select free slot first, otherwise LRU slot.
|
||||
Slot* target = nullptr;
|
||||
uint16_t oldest = 0xFFFFu;
|
||||
for (auto& slot : slots_) {
|
||||
if (!slot.used) {
|
||||
target = &slot;
|
||||
break;
|
||||
}
|
||||
if (slot.last_used < oldest) {
|
||||
oldest = slot.last_used;
|
||||
target = &slot;
|
||||
}
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (target->used) {
|
||||
target->bmp.close();
|
||||
target->used = false;
|
||||
}
|
||||
|
||||
// OSM tile path convention: <base>/<z>/<x>/<y>.bmp
|
||||
char path_buffer[64];
|
||||
snprintf(path_buffer, sizeof(path_buffer), "/OSM/%" PRId32 "/%" PRId32 "/%" PRId32 ".bmp", z, x, y);
|
||||
|
||||
if (!target->bmp.open(path_buffer, true)) {
|
||||
target->bmp.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
target->x = x;
|
||||
target->y = y;
|
||||
target->z = z;
|
||||
target->last_used = next_stamp();
|
||||
target->used = true;
|
||||
return &target->bmp;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (auto& slot : slots_) {
|
||||
if (slot.used) {
|
||||
slot.bmp.close();
|
||||
slot.used = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct Slot {
|
||||
BMPFile bmp{};
|
||||
int32_t x{};
|
||||
int32_t y{};
|
||||
int32_t z{};
|
||||
uint16_t last_used{};
|
||||
bool used{false};
|
||||
};
|
||||
|
||||
uint16_t next_stamp() {
|
||||
if (++stamp_ == 0) {
|
||||
uint16_t v = 1;
|
||||
for (auto& slot : slots_) {
|
||||
if (slot.used) {
|
||||
slot.last_used = v++;
|
||||
}
|
||||
}
|
||||
stamp_ = v;
|
||||
}
|
||||
return stamp_;
|
||||
}
|
||||
std::array<Slot, SlotsCount> slots_{};
|
||||
uint16_t stamp_{0};
|
||||
};
|
||||
|
||||
class GeoPos : public View {
|
||||
public:
|
||||
enum alt_unit {
|
||||
@@ -276,6 +374,7 @@ class GeoMap : public Widget {
|
||||
bool hide_center_marker_{false};
|
||||
GeoMapMode mode_{};
|
||||
File map_file{};
|
||||
BMPFileCache bmp_cache{};
|
||||
bool map_opened{};
|
||||
bool map_visible{};
|
||||
uint16_t map_width{}, map_height{};
|
||||
|
||||
@@ -157,8 +157,7 @@ static void cmd_flash(BaseSequentialStream* chp, int argc, char* argv[]) {
|
||||
// call nav with flash
|
||||
auto open_view = nav->push<ui::FlashUtilityView>();
|
||||
chprintf(chp, "Flashing started\r\n");
|
||||
chThdSleepMilliseconds(150); // to give display some time to paint the screen
|
||||
open_view->wait_till_loaded(); // also wait for first frame sync
|
||||
chThdSleepMilliseconds(150); // to give display some time to paint the screen
|
||||
if (!open_view->flash_firmware(path.native())) {
|
||||
chprintf(chp, "error\r\n");
|
||||
}
|
||||
|
||||
@@ -776,6 +776,7 @@ set(MODE_CPPSRC
|
||||
${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/delay.c
|
||||
${HACKRF_PATH}/firmware/common/platform_gpio.c
|
||||
${HACKRF_PATH}/firmware/common/platform_scu.c
|
||||
${HACKRF_PATH}/firmware/common/gpio_lpc.c
|
||||
@@ -806,11 +807,19 @@ endif()
|
||||
|
||||
### HackRF "factory" firmware
|
||||
|
||||
# The RAM image (${HACKRF_FIRMWARE_BIN_IMAGE}) is produced by the hackrf
|
||||
# "hackrf_usb_ram.bin" custom target (objcopy of the .elf). The previous
|
||||
# DEPENDS used the bare filename ${HACKRF_FIRMWARE_BIN_FILENAME}, which CMake
|
||||
# silently dropped, so the embed (hackrf.lz4/hackrf.img) was never regenerated
|
||||
# when the hackrf firmware changed -> stale RAM image baked into the build.
|
||||
# Depend on the full path (marked GENERATED so Make doesn't look for a file
|
||||
# rule) AND on the producing custom target (for build ordering).
|
||||
set_source_files_properties(${HACKRF_FIRMWARE_BIN_IMAGE} PROPERTIES GENERATED TRUE)
|
||||
add_custom_command(
|
||||
OUTPUT hackrf.img
|
||||
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}
|
||||
DEPENDS ${HACKRF_FIRMWARE_BIN_IMAGE} hackrf_usb_ram.bin ${MAKE_IMAGE_CHUNK}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
|
||||
@@ -22,25 +22,19 @@
|
||||
|
||||
#include "proc_ook.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table_int8.hpp"
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
inline void OOKProcessor::write_sample(const buffer_c8_t& buffer, uint8_t bit_value, size_t i) {
|
||||
int8_t re, im;
|
||||
|
||||
if (bit_value) {
|
||||
phase = (phase + 200); // What ?
|
||||
sphase = phase + (64 << 18);
|
||||
|
||||
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]);
|
||||
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]);
|
||||
re = INT8_MAX;
|
||||
im = 0;
|
||||
} else {
|
||||
re = 0;
|
||||
im = 0;
|
||||
}
|
||||
|
||||
buffer.p[i] = {re, im};
|
||||
}
|
||||
|
||||
@@ -125,11 +119,8 @@ inline size_t OOKProcessor::duval_algo_step() {
|
||||
void OOKProcessor::scan_process(const buffer_c8_t& buffer) {
|
||||
size_t buf_ptr = 0;
|
||||
|
||||
// transmit any leftover bits from previous step
|
||||
if (!scan_encode(buffer, buf_ptr))
|
||||
return;
|
||||
|
||||
while (1) {
|
||||
// Encode the sequence into required format. First call transmits any leftover bits from previous step
|
||||
while (scan_encode(buffer, buf_ptr)) {
|
||||
// calculate next chunk of deBruijn sequence
|
||||
duval_length = duval_algo_step();
|
||||
|
||||
@@ -151,10 +142,6 @@ void OOKProcessor::scan_process(const buffer_c8_t& buffer) {
|
||||
duval_bit = 0;
|
||||
duval_sample_bit = 0;
|
||||
duval_symbol = 0;
|
||||
|
||||
// encode the sequence into required format
|
||||
if (!scan_encode(buffer, buf_ptr))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ class OOKProcessor : public BasebandProcessor {
|
||||
uint16_t bit_pos{0};
|
||||
uint8_t cur_bit{0};
|
||||
uint32_t sample_count{0};
|
||||
uint32_t tone_phase{0}, phase{0}, sphase{0};
|
||||
int32_t tone_sample{0}, sig{0}, frq{0};
|
||||
|
||||
TXProgressMessage txprogress_message{};
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "platform_scu.h"
|
||||
#include "fixed_point.h"
|
||||
#include "clkin.h"
|
||||
#include "cpu_clock.h"
|
||||
#include "usb_type.h"
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
#include <libopencm3/lpc43xx/ccu.h>
|
||||
@@ -51,6 +52,10 @@
|
||||
|
||||
#include "gpio_lpc.h"
|
||||
|
||||
/* Referenced by the hackrf common delay.c. The Mayhem firmware already runs
|
||||
* the CPU at 204MHz when this baseband image is started. */
|
||||
unsigned int cpu_clock_mhz = 204;
|
||||
|
||||
/* GPIO Output PinMux */
|
||||
static struct gpio gpio_led[] = {
|
||||
GPIO(2, 1),
|
||||
@@ -492,6 +497,9 @@ static void cpu_clock_pll1_max_speed(void) {
|
||||
reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1);
|
||||
CGU_BASE_M4_CLK = reg_val;
|
||||
|
||||
/* CPU is now at 12MHz */
|
||||
cpu_clock_mhz = 12;
|
||||
|
||||
/* 2. Enable the crystal oscillator. */
|
||||
CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK;
|
||||
|
||||
@@ -537,11 +545,17 @@ static void cpu_clock_pll1_max_speed(void) {
|
||||
reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||
CGU_BASE_M4_CLK = reg_val;
|
||||
|
||||
/* CPU is now at 102MHz */
|
||||
cpu_clock_mhz = 102;
|
||||
|
||||
/* 9. Wait 50us. */
|
||||
delay_us_at_mhz(50, 102);
|
||||
|
||||
/* 10. Set the PLL1 P-divider to direct output mode (DIRECT=1). */
|
||||
CGU_PLL1_CTRL |= CGU_PLL1_CTRL_DIRECT_MASK;
|
||||
|
||||
/* CPU is now at 204MHz */
|
||||
cpu_clock_mhz = 204;
|
||||
}
|
||||
|
||||
/* clock startup for LPC4320 configure PLL1 to max speed (204MHz).
|
||||
|
||||
@@ -26,11 +26,12 @@
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/rgu.h>
|
||||
#include <libopencm3/lpc43xx/wwdt.h>
|
||||
#include "delay.h"
|
||||
#include "string.h"
|
||||
|
||||
volatile bool usb_bulk_block_done = false;
|
||||
|
||||
void delay(uint32_t duration);
|
||||
|
||||
void usb_bulk_block_cb(void* user_data, unsigned int bytes_transferred) {
|
||||
usb_bulk_block_done = true;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <array>
|
||||
|
||||
#include "gpio.hpp"
|
||||
using namespace gpio_control;
|
||||
|
||||
// Declare wrapper function. board.cpp to avoid conflicting gpio_t definitions.
|
||||
bool hackrf_r9;
|
||||
@@ -56,55 +57,55 @@ const PALConfig pal_default_config = {
|
||||
// GPIO0
|
||||
.data
|
||||
#ifdef PRALINE
|
||||
= (0 << 7) // P2_7: Input GND
|
||||
| (0 << 8) // P1_1: Input GND
|
||||
| (1 << 9) // P1_2: Input VCC
|
||||
| boot_bit(gpio_control::p1_ctrl0, 0) // P2_10: P1_CTRL0, start low
|
||||
| (0 << 15) // P1_20: CLKIN_CTRL - start low
|
||||
= (0 << 7) // P2_7: Input GND
|
||||
| (0 << 8) // P1_1: Input GND
|
||||
| (1 << 9) // P1_2: Input VCC
|
||||
| boot_bit(p1_ctrl0, 0) // P2_10: P1_CTRL0, start low
|
||||
| boot_bit(clkin_ctrl, 0) // P1_20: CLKIN_CTRL - start low
|
||||
#else
|
||||
= (1 << 14) // P2_10: AMP_BYPASS
|
||||
| (1 << 15) // P1_20: CS_XCVR
|
||||
#endif
|
||||
| (1 << 11) // P1_4: SSP1_MOSI
|
||||
| (0 << 13) // P1_18: SGPIO12, HOST_Q_INVERT
|
||||
| (0 << 12) // P1_17: SGPIO11, HOST_DIRECTION, Praline: FPGA HOST_DIRECTION
|
||||
| (1 << 10) // P1_3: SSP1_MISO
|
||||
| (0 << 9) // P1_2: Varies by revision, float until detection
|
||||
| (0 << 8) // P1_1: Varies by revision, float until detection
|
||||
| (0 << 7) // P2_7: Varies by revision, float until detection
|
||||
| (0 << 6) // P3_6: SPIFI_MISO
|
||||
| (1 << 5) // P6_6: SGPIO5, HOST_DATA5, Praline: FPGA HOST_DATA5
|
||||
| (1 << 4) // P1_0: SGPIO7, HOST_DATA7, Praline: FPGA HOST_DATA7
|
||||
| (1 << 3) // P1_16: SGPIO3, HOST_DATA3, Praline: FPGA HOST_DATA3
|
||||
| (1 << 2) // P1_15: SGPIO2, HOST_DATA2, Praline: FPGA HOST_DATA2
|
||||
| (1 << 1) // P0_1: SGPIO1, HOST_DATA1, Praline: FPGA HOST_DATA1
|
||||
| (1 << 0) // P0_0: SGPIO0, HOST_DATA0, Praline: FPGA HOST_DATA0
|
||||
| (1 << 11) // P1_4: SSP1_MOSI
|
||||
| boot_bit(sgpio_12, 0) // P1_18: SGPIO12, HOST_Q_INVERT
|
||||
| boot_bit(sgpio_11, 0) // P1_17: SGPIO11, HOST_DIRECTION, Praline: FPGA HOST_DIRECTION
|
||||
| (1 << 10) // P1_3: SSP1_MISO
|
||||
| (0 << 9) // P1_2: Varies by revision, float until detection
|
||||
| (0 << 8) // P1_1: Varies by revision, float until detection
|
||||
| (0 << 7) // P2_7: Varies by revision, float until detection
|
||||
| (0 << 6) // P3_6: SPIFI_MISO
|
||||
| boot_bit(sgpio_5, 1) // P6_6: SGPIO5, HOST_DATA5, Praline: FPGA HOST_DATA5
|
||||
| boot_bit(sgpio_7, 1) // P1_0: SGPIO7, HOST_DATA7, Praline: FPGA HOST_DATA7
|
||||
| boot_bit(sgpio_3, 1) // P1_16: SGPIO3, HOST_DATA3, Praline: FPGA HOST_DATA3
|
||||
| boot_bit(sgpio_2, 1) // P1_15: SGPIO2, HOST_DATA2, Praline: FPGA HOST_DATA2
|
||||
| boot_bit(sgpio_1, 1) // P0_1: SGPIO1, HOST_DATA1, Praline: FPGA HOST_DATA1
|
||||
| boot_bit(sgpio_0, 1) // P0_0: SGPIO0, HOST_DATA0, Praline: FPGA HOST_DATA0
|
||||
,
|
||||
.dir
|
||||
#ifdef PRALINE
|
||||
= (0 << 7) // P2_7: Input
|
||||
| (0 << 8) // P1_1: Input
|
||||
| (0 << 9) // P1_2: Input
|
||||
| boot_bit(gpio_control::p1_ctrl0, 1) // P2_10: P1_CTRL0
|
||||
| (1 << 15) // P1_20: CLKIN_CTRL
|
||||
= (0 << 7) // P2_7: Input
|
||||
| (0 << 8) // P1_1: Input
|
||||
| (0 << 9) // P1_2: Input
|
||||
| boot_bit(p1_ctrl0, 1) // P2_10: P1_CTRL0
|
||||
| boot_bit(clkin_ctrl, 1) // P1_20: CLKIN_CTRL
|
||||
#else
|
||||
= (1 << 14) // P2_10: AMP_BYPASS
|
||||
| (1 << 15) // P1_20: CS_XCVR
|
||||
#endif
|
||||
| (0 << 11) // P1_4: SSP1_MOSI
|
||||
| (1 << 13) // P1_18: SGPIO12, HOST_Q_INVERT
|
||||
| (0 << 12) // P1_17: SGPIO11, HOST_DIRECTION
|
||||
| (0 << 10) // P1_3: SSP1_MISO
|
||||
| (0 << 9) // P1_2: Varies by revision, float until detection
|
||||
| (0 << 8) // P1_1: Varies by revision, float until detection
|
||||
| (0 << 7) // P2_7: Varies by revision, float until detection
|
||||
| (0 << 6) // P3_6: SPIFI_MISO
|
||||
| (0 << 5) // P6_6: SGPIO5, HOST_DATA5
|
||||
| (0 << 4) // P1_0: SGPIO7, HOST_DATA7
|
||||
| (0 << 3) // P1_16: SGPIO3, HOST_DATA3
|
||||
| (0 << 2) // P1_15: SGPIO2, HOST_DATA2
|
||||
| (0 << 1) // P0_1: SGPIO1, HOST_DATA1
|
||||
| (0 << 0) // P0_0: SGPIO0, HOST_DATA0
|
||||
| (0 << 11) // P1_4: SSP1_MOSI
|
||||
| boot_bit(sgpio_12, 1) // P1_18: SGPIO12, HOST_Q_INVERT
|
||||
| boot_bit(sgpio_11, 0) // P1_17: SGPIO11, HOST_DIRECTION, Praline: FPGA HOST_DIRECTION
|
||||
| (0 << 10) // P1_3: SSP1_MISO
|
||||
| (0 << 9) // P1_2: Varies by revision, float until detection
|
||||
| (0 << 8) // P1_1: Varies by revision, float until detection
|
||||
| (0 << 7) // P2_7: Varies by revision, float until detection
|
||||
| (0 << 6) // P3_6: SPIFI_MISO
|
||||
| boot_bit(sgpio_5, 1) // P6_6: SGPIO5, HOST_DATA5
|
||||
| boot_bit(sgpio_7, 1) // P1_0: SGPIO7, HOST_DATA7
|
||||
| boot_bit(sgpio_3, 0) // P1_16: SGPIO3, HOST_DATA3
|
||||
| boot_bit(sgpio_2, 0) // P1_15: SGPIO2, HOST_DATA2
|
||||
| boot_bit(sgpio_1, 0) // P0_1: SGPIO1, HOST_DATA1
|
||||
| boot_bit(sgpio_0, 0) // P0_0: SGPIO0, HOST_DATA0
|
||||
},
|
||||
{
|
||||
// GPIO1
|
||||
@@ -112,15 +113,15 @@ const PALConfig pal_default_config = {
|
||||
| (1 << 14) // P3_4: SPIFI_SIO3
|
||||
| (1 << 13) // P2_13: PortaPack DIR
|
||||
#ifdef PRALINE
|
||||
| (1 << 12) // P2_12: BIAS_EN
|
||||
| (0 << 11) // P2_11: BIAS_OC
|
||||
| boot_bit(gpio_control::aa_en, 0) // P1_14: AA_EN
|
||||
| (0 << 0) // P1_7: Output GND
|
||||
| (1 << 12) // P2_12: BIAS_EN
|
||||
| (0 << 11) // P2_11: BIAS_OC
|
||||
| boot_bit(aa_en, 0) // P1_14: AA_EN
|
||||
| (0 << 0) // P1_7: Output GND
|
||||
#else
|
||||
| (1 << 12) // P2_12: !RX_AMP_PWR
|
||||
| (0 << 11) // P2_11: RX_AMP
|
||||
| (1 << 7) // P1_14: SGPIO10, HOST_DISABLE
|
||||
| (0 << 0) // P1_7: !MIX_BYPASS
|
||||
| (1 << 12) // P2_12: !RX_AMP_PWR
|
||||
| (0 << 11) // P2_11: RX_AMP
|
||||
| boot_bit(sgpio_10, 1) // P1_14: SGPIO10, HOST_DISABLE
|
||||
| (0 << 0) // P1_7: !MIX_BYPASS
|
||||
#endif
|
||||
| (0 << 10) // P2_9: 10K PD, BOOT3, PortaPack LCD_WRX
|
||||
| (1 << 9) // P1_6: SD_CMD
|
||||
@@ -136,15 +137,15 @@ const PALConfig pal_default_config = {
|
||||
| (0 << 14) // P3_4: SPIFI_SIO3
|
||||
| (1 << 13) // P2_13: PortaPack DIR
|
||||
#ifdef PRALINE
|
||||
| (1 << 12) // P2_12: !BIAS_EN
|
||||
| (0 << 11) // P2_11: BIAS_OC
|
||||
| boot_bit(gpio_control::aa_en, 1) // P1_14: AA_EN
|
||||
| (1 << 0) // P1_7: Output
|
||||
| (1 << 12) // P2_12: !BIAS_EN
|
||||
| (0 << 11) // P2_11: BIAS_OC
|
||||
| boot_bit(aa_en, 1) // P1_14: AA_EN
|
||||
| (1 << 0) // P1_7: Output
|
||||
#else
|
||||
| (1 << 12) // P2_12: !RX_AMP_PWR
|
||||
| (1 << 11) // P2_11: RX_AMP
|
||||
| (0 << 7) // P1_14: SGPIO10, HOST_DISABLE
|
||||
| (1 << 0) // P1_7: !MIX_BYPASS
|
||||
| (1 << 12) // P2_12: !RX_AMP_PWR
|
||||
| (1 << 11) // P2_11: RX_AMP
|
||||
| boot_bit(sgpio_10, 0) // P1_14: SGPIO10, HOST_DISABLE
|
||||
| (1 << 0) // P1_7: !MIX_BYPASS
|
||||
#endif
|
||||
| (1 << 10) // P2_9: 10K PD, BOOT3, PortaPack LCD_WRX
|
||||
| (0 << 9) // P1_6: SD_CMD
|
||||
@@ -161,31 +162,31 @@ const PALConfig pal_default_config = {
|
||||
.data = (0 << 15) // P5_6: TX_AMP, unused on PRALINE
|
||||
| (1 << 14) // P5_5: MIXER_RESETX, 10K PU
|
||||
#ifdef PRALINE
|
||||
| (1 << 13) // P5_4: RFFC5072 ENX
|
||||
| (0 << 12) // P5_3: unused on PRALINE
|
||||
| (0 << 11) // P5_2: FPGA_CRESET
|
||||
| (1 << 10) // P5_1: FPGA_SPI_CS
|
||||
| (0 << 4) // P4_4: unused on PRALINE
|
||||
| (0 << 0) // P4_0: unused on PRALINE
|
||||
| (0 << 9) // P5_0: unused on PRALINE
|
||||
| (0 << 3) // P4_3: VBUSCTRL input GND
|
||||
| (1 << 6) // P4_6: Input VCC (10K PU)
|
||||
| (1 << 8) // P6_12: LED3 (TX)
|
||||
| (1 << 2) // P4_2: LED2 (RX)
|
||||
| (1 << 1) // P4_1: LED1 (USB)
|
||||
| (1 << 13) // P5_4: RFFC5072 ENX
|
||||
| (0 << 12) // P5_3: unused on PRALINE
|
||||
| (0 << 11) // P5_2: FPGA_CRESET
|
||||
| (1 << 10) // P5_1: FPGA_SPI_CS
|
||||
| (0 << 4) // P4_4: unused on PRALINE
|
||||
| (0 << 0) // P4_0: unused on PRALINE
|
||||
| (0 << 9) // P5_0: unused on PRALINE
|
||||
| (0 << 3) // P4_3: VBUSCTRL input GND
|
||||
| (1 << 6) // P4_6: Input VCC (10K PU)
|
||||
| boot_bit(led_tx, 1) // P6_12: LED3 (TX)
|
||||
| boot_bit(led_rx, 1) // P4_2: LED2 (RX)
|
||||
| boot_bit(led_usb, 1) // P4_1: LED1 (USB)
|
||||
#else
|
||||
| (1 << 13) // P5_4: MIXER_ENX, 10K PU
|
||||
| (1 << 12) // P5_3: RX_MIX_BP
|
||||
| (0 << 11) // P5_2: TX_MIX_BP
|
||||
| (0 << 10) // P5_1: LP
|
||||
| (0 << 4) // P4_4: Varies by revision
|
||||
| (0 << 9) // P5_0: Varies by revision
|
||||
| (1 << 0) // P4_0: HP
|
||||
| (1 << 3) // P4_3: SGPIO9, HOST_CAPTURE
|
||||
| (0 << 6) // P4_6: XCVR_EN, 10K PD
|
||||
| (0 << 8) // P6_12: LED3 (TX)
|
||||
| (0 << 2) // P4_2: LED2 (RX)
|
||||
| (0 << 1) // P4_1: LED1 (USB)
|
||||
| (1 << 13) // P5_4: MIXER_ENX, 10K PU
|
||||
| (1 << 12) // P5_3: RX_MIX_BP
|
||||
| (0 << 11) // P5_2: TX_MIX_BP
|
||||
| (0 << 10) // P5_1: LP
|
||||
| (0 << 4) // P4_4: Varies by revision
|
||||
| (0 << 9) // P5_0: Varies by revision
|
||||
| (1 << 0) // P4_0: HP
|
||||
| boot_bit(sgpio_9, 1) // P4_3: SGPIO9, HOST_CAPTURE
|
||||
| (0 << 6) // P4_6: XCVR_EN, 10K PD
|
||||
| boot_bit(led_tx, 0) // P6_12: LED3 (TX)
|
||||
| boot_bit(led_rx, 0) // P4_2: LED2 (RX)
|
||||
| boot_bit(led_usb, 0) // P4_1: LED1 (USB)
|
||||
#endif
|
||||
|
||||
| (1 << 7) // P5_7: CS_AD
|
||||
@@ -203,22 +204,22 @@ const PALConfig pal_default_config = {
|
||||
| (0 << 3) // P4_3: VBUSCTRL input
|
||||
| (0 << 6) // P4_6: Input
|
||||
#else
|
||||
| (1 << 13) // P5_4: MIXER_ENX, 10K PU
|
||||
| (1 << 12) // P5_3: RX_MIX_BP
|
||||
| (1 << 11) // P5_2: TX_MIX_BP
|
||||
| (1 << 10) // P5_1: LP
|
||||
| (0 << 4) // P4_4: Varies by revision
|
||||
| (0 << 9) // P5_0: Varies by revision
|
||||
| (1 << 0) // P4_0: HP
|
||||
| (0 << 3) // P4_3: SGPIO9, HOST_CAPTURE
|
||||
| (1 << 6) // P4_6: XCVR_EN, 10K PD
|
||||
| (1 << 13) // P5_4: MIXER_ENX, 10K PU
|
||||
| (1 << 12) // P5_3: RX_MIX_BP
|
||||
| (1 << 11) // P5_2: TX_MIX_BP
|
||||
| (1 << 10) // P5_1: LP
|
||||
| (0 << 4) // P4_4: Varies by revision
|
||||
| (0 << 9) // P5_0: Varies by revision
|
||||
| (1 << 0) // P4_0: HP
|
||||
| boot_bit(sgpio_9, 0) // P4_3: SGPIO9, HOST_CAPTURE
|
||||
| (1 << 6) // P4_6: XCVR_EN, 10K PD
|
||||
#endif
|
||||
| (1 << 14) // P5_5: MIXER_RESETX, 10K PU
|
||||
| (1 << 8) // P6_12: LED3 (TX)
|
||||
| (1 << 7) // P5_7: CS_AD
|
||||
| (1 << 5) // P4_5: RXENABLE
|
||||
| (1 << 2) // P4_2: LED2 (RX)
|
||||
| (1 << 1) // P4_1: LED1 (USB)
|
||||
| (1 << 14) // P5_5: MIXER_RESETX, 10K PU
|
||||
| boot_bit(led_tx, 1) // P6_12: LED3 (TX)
|
||||
| (1 << 7) // P5_7: CS_AD
|
||||
| (1 << 5) // P4_5: RXENABLE
|
||||
| boot_bit(led_rx, 1) // P4_2: LED2 (RX)
|
||||
| boot_bit(led_usb, 1) // P4_1: LED1 (USB)
|
||||
},
|
||||
{
|
||||
// GPIO3
|
||||
@@ -231,16 +232,16 @@ const PALConfig pal_default_config = {
|
||||
| (1 << 9) // P7_1: PortaPack GPIO3_9(IO)
|
||||
| (1 << 8) // P7_0: PortaPack GPIO3_8(IO)
|
||||
#ifdef PRALINE
|
||||
| (0 << 4) // P6_5: TX_ENABLE
|
||||
| (1 << 2) // P6_3: MIX_ENABLE_N
|
||||
| (0 << 6) // P6_10: unused on PRALINE
|
||||
| boot_bit(gpio_control::p1_ctrl2, 0) // P6_9: P1_CTRL2
|
||||
| (0 << 4) // P6_5: TX_ENABLE
|
||||
| (1 << 2) // P6_3: MIX_ENABLE_N
|
||||
| (0 << 6) // P6_10: unused on PRALINE
|
||||
| boot_bit(p1_ctrl2, 0) // P6_9: P1_CTRL2
|
||||
#else
|
||||
| (1 << 4) // P6_5: HackRF CPLD.TMS(I)
|
||||
| (1 << 7) // P6_11: VREGMODE
|
||||
| (0 << 6) // P6_10: Varies by revision
|
||||
| (1 << 2) // P6_3: SGPIO4, HOST_DATA4
|
||||
| (1 << 5) // P6_9: !TX_AMP_PWR, 10K PU
|
||||
| (1 << 4) // P6_5: HackRF CPLD.TMS(I)
|
||||
| boot_bit(vregmode, 1) // P6_11: VREGMODE
|
||||
| (0 << 6) // P6_10: Varies by revision
|
||||
| (1 << 2) // P6_3: SGPIO4
|
||||
| (1 << 5) // P6_9: !TX_AMP_PWR, 10K PU
|
||||
#endif
|
||||
| (1 << 3) // P6_4: MIXER_SDATA
|
||||
| (1 << 1) // P6_2: HackRF CPLD.TDI(I)
|
||||
@@ -255,16 +256,16 @@ const PALConfig pal_default_config = {
|
||||
| (1 << 9) // P7_1: PortaPack GPIO3_9(IO)
|
||||
| (1 << 8) // P7_0: PortaPack GPIO3_8(IO)
|
||||
#ifdef PRALINE
|
||||
| (0 << 7) // P6_11: 3V3AUX_OC
|
||||
| (1 << 4) // P6_5: TX_ENABLE
|
||||
| (1 << 2) // P6_3: MIX_ENABLE_N
|
||||
| (0 << 6) // P6_10: unused on PRALINE
|
||||
| boot_bit(gpio_control::p1_ctrl2, 1) // P6_9: P1_CTRL2
|
||||
| (0 << 7) // P6_11: 3V3AUX_OC
|
||||
| (1 << 4) // P6_5: TX_ENABLE
|
||||
| (1 << 2) // P6_3: MIX_ENABLE_N
|
||||
| (0 << 6) // P6_10: unused on PRALINE
|
||||
| boot_bit(p1_ctrl2, 1) // P6_9: P1_CTRL2
|
||||
#else
|
||||
| (1 << 7) // P6_11: VREGMODE
|
||||
| (0 << 6) // P6_10: Varies by revision
|
||||
| (0 << 2) // P6_3: SGPIO4, HOST_DATA4
|
||||
| (1 << 5) // P6_9: !TX_AMP_PWR, 10K PU
|
||||
| boot_bit(vregmode, 1) // P6_11: VREGMODE
|
||||
| (0 << 6) // P6_10: Varies by revision
|
||||
| (0 << 2) // P6_3: SGPIO4
|
||||
| (1 << 5) // P6_9: !TX_AMP_PWR, 10K PU
|
||||
#endif
|
||||
| (0 << 4) // P6_5: HackRF CPLD.TMS(I)
|
||||
| (0 << 3) // P6_4: MIXER_SDATA
|
||||
@@ -274,63 +275,65 @@ const PALConfig pal_default_config = {
|
||||
{
|
||||
// GPIO4
|
||||
.data =
|
||||
boot_bit(sgpio_8, 0) // P9_6: SGPIO8, SGPIO_CLK, PRALINE: P8_0
|
||||
#ifdef PRALINE
|
||||
(0 << 9) // PA_2: RF_AMP_EN
|
||||
| (0 << 8) // PA_1: LPF_EN
|
||||
| (0 << 7) // P8_7: 1V2_EN
|
||||
| (1 << 6) // P8_6: LED4
|
||||
| (0 << 5) // P8_5: VIN_IN_EN
|
||||
| (0 << 4) // P8_4: VBUS_IN_EN
|
||||
| (1 << 1) // P8_1: VAA_EN
|
||||
| (0 << 10) // PA_3: Output GND
|
||||
| (0 << 11) // P9_6: MAX2831 LD
|
||||
| boot_bit(gpio_control::rf5072_mix_en, 0) // P9_0: RF5072 enable
|
||||
| (0 << 13) // P9_1: Output GND
|
||||
| (0 << 14) // P9_2: RFFC5072 SDATA
|
||||
| (0 << 3) // P8_3: Output GND
|
||||
#else
|
||||
(1 << 11) // P9_6: SGPIO8, SGPIO_CLK, HackRF MAX2831 LD
|
||||
| (0 << 9) // PA_2: RF_AMP_EN
|
||||
| (0 << 8) // PA_1: LPF_EN
|
||||
| boot_bit(en_1v2, 0) // P8_7: EN_1V2
|
||||
| boot_bit(led_mcu, 1) // P8_6: LED4
|
||||
| boot_bit(sgpio_10, 1) // P8_2: SGPIO10, HOST_DISABLE
|
||||
| (0 << 5) // P8_5: VIN_IN_EN
|
||||
| (0 << 4) // P8_4: VBUS_IN_EN
|
||||
| boot_bit(VAA_en, 1) // P8_1: !VAA_EN
|
||||
| (0 << 10) // PA_3: Output GND
|
||||
| (0 << 11) // P9_6: MAX2831 LD
|
||||
| boot_bit(rf5072_mix_en, 0) // P9_0: RF5072 enable
|
||||
| (0 << 13) // P9_1: Output GND
|
||||
| (0 << 14) // P9_2: RFFC5072 SDATA
|
||||
| (0 << 3) // P8_3: Output GND
|
||||
| boot_bit(sgpio_9, 1) // P9_3: Capture Input
|
||||
#endif
|
||||
,
|
||||
.dir =
|
||||
boot_bit(sgpio_8, 0) // P9_6: SGPIO8, SGPIO_CLK, PRALINE: P8_0
|
||||
#ifdef PRALINE
|
||||
(1 << 9) // PA_2: RF_AMP_EN
|
||||
| (1 << 8) // PA_1: LPF_EN
|
||||
| (1 << 7) // P8_7: 1V2_EN
|
||||
| (1 << 6) // P8_6: LED4
|
||||
| (1 << 5) // P8_5: VIN_IN_EN
|
||||
| (1 << 4) // P8_4: VBUS_IN_EN
|
||||
| (1 << 1) // P8_1: VAA_EN
|
||||
| (1 << 10) // PA_3: Output
|
||||
| (0 << 11) // P9_6: MAX2831 LD
|
||||
| boot_bit(gpio_control::rf5072_mix_en, 1) // P9_0: RF5072 enable
|
||||
| (1 << 13) // P9_1: Output
|
||||
| (0 << 14) // P9_2: RFFC5072 SDATA (Bidirectional)
|
||||
| (1 << 3) // P8_3: Output
|
||||
#else
|
||||
(1 << 11) // P9_6: SGPIO8, SGPIO_CLK, HackRF MAX2831 LD
|
||||
| (1 << 9) // PA_2: RF_AMP_EN
|
||||
| (1 << 8) // PA_1: LPF_EN
|
||||
| boot_bit(en_1v2, 1) // P8_7: EN_1V2
|
||||
| boot_bit(led_mcu, 1) // P8_6: LED4
|
||||
| boot_bit(sgpio_10, 0) // P8_2: SGPIO10, HOST_DISABLE
|
||||
| (1 << 5) // P8_5: VIN_IN_EN
|
||||
| (1 << 4) // P8_4: VBUS_IN_EN
|
||||
| boot_bit(VAA_en, 1) // P8_1: !VAA_EN
|
||||
| (1 << 10) // PA_3: Output
|
||||
| (0 << 11) // P9_6: MAX2831 LD
|
||||
| boot_bit(rf5072_mix_en, 1) // P9_0: RF5072 enable
|
||||
| (1 << 13) // P9_1: Output
|
||||
| (0 << 14) // P9_2: RFFC5072 SDATA (Bidirectional)
|
||||
| (1 << 3) // P8_3: Output
|
||||
| boot_bit(sgpio_9, 0) // P9_3: Capture Input
|
||||
#endif
|
||||
},
|
||||
{
|
||||
// GPIO5
|
||||
.data =
|
||||
#ifdef PRALINE
|
||||
(0 << 18) // P9_5: RFF5072 SCLK
|
||||
| boot_bit(gpio_control::trigger_out, 0) // P2_6: Trigger out
|
||||
| (0 << 14) // P4_10: FPGA CDONE
|
||||
| (1 << 15) // P6_7: 3V3 AUX_ENABLE
|
||||
| boot_bit(gpio_control::p1_ctrl1, 0) // P6_8: P1_CTRL1
|
||||
| (0 << 17) // P9_4: FPGA SGPIO
|
||||
| (0 << 19) // PA_4: Output GND
|
||||
| (0 << 20) // PB_0: Output GND
|
||||
| (0 << 21) // PB_1: Output GND
|
||||
| (0 << 22) // PB_2: Unused IN
|
||||
| (0 << 23) // PB_3: Output GND
|
||||
| (0 << 24) // PB_4: Unused IN
|
||||
| (0 << 25) // PB_5: Output GND
|
||||
| (0 << 5) // P2_5: PPS OUT/IN
|
||||
| (0 << 12) // P4_8: Output GND
|
||||
| (0 << 13) // P4_9: TPS62410 VREGMODE
|
||||
(0 << 18) // P9_5: RFF5072 SCLK
|
||||
| boot_bit(trigger_out, 0) // P2_6: Trigger out
|
||||
| (0 << 14) // P4_10: FPGA CDONE
|
||||
| (1 << 15) // P6_7: 3V3 AUX_ENABLE
|
||||
| boot_bit(p1_ctrl1, 0) // P6_8: P1_CTRL1
|
||||
| boot_bit(sgpio_4, 1) // P9_4: FPGA SGPIO4
|
||||
| (0 << 19) // PA_4: Output GND
|
||||
| (0 << 20) // PB_0: Output GND
|
||||
| (0 << 21) // PB_1: Output GND
|
||||
| (0 << 22) // PB_2: Unused IN
|
||||
| (0 << 23) // PB_3: Output GND
|
||||
| (0 << 24) // PB_4: Unused IN
|
||||
| (0 << 25) // PB_5: Output GND
|
||||
| (0 << 5) // P2_5: PPS OUT/IN
|
||||
| (0 << 12) // P4_8: Output GND
|
||||
| boot_bit(vregmode, 1) // P4_9: TPS62410 VREGMODE
|
||||
#else
|
||||
(1 << 18) // P9_5: HackRF CPLD.TDO(O)
|
||||
| (0 << 6) // P2_6: MIXER_SCLK
|
||||
@@ -341,35 +344,35 @@ const PALConfig pal_default_config = {
|
||||
| (1 << 13) // P4_9: SGPIO14, CPLD (unused)
|
||||
| (0 << 12) // P4_8: Varies by revision
|
||||
#endif
|
||||
| (1 << 11) // P3_8: SPIFI_CS
|
||||
| (1 << 10) // P3_7: SPIFI_MOSI
|
||||
| (1 << 9) // P3_2: I2S0_RX_SDA
|
||||
| (1 << 8) // P3_1: I2S0_RX_WS
|
||||
| (0 << 7) // P2_8: BOOT2
|
||||
| (1 << 4) // P2_4: PortaPack LCD_RDX
|
||||
| (0 << 3) // P2_3: PortaPack LCD_TE
|
||||
| (1 << 2) // P2_2: SGPIO6, HOST_DATA6
|
||||
| (1 << 1) // P2_1: PortaPack ADDR
|
||||
| (1 << 0) // P2_0: PortaPack IO_STBX
|
||||
| (1 << 11) // P3_8: SPIFI_CS
|
||||
| (1 << 10) // P3_7: SPIFI_MOSI
|
||||
| (1 << 9) // P3_2: I2S0_RX_SDA
|
||||
| (1 << 8) // P3_1: I2S0_RX_WS
|
||||
| (0 << 7) // P2_8: BOOT2
|
||||
| (1 << 4) // P2_4: PortaPack LCD_RDX
|
||||
| (0 << 3) // P2_3: PortaPack LCD_TE
|
||||
| boot_bit(sgpio_6, 1) // P2_2: SGPIO6, HOST_DATA6
|
||||
| (1 << 1) // P2_1: PortaPack ADDR
|
||||
| (1 << 0) // P2_0: PortaPack IO_STBX
|
||||
,
|
||||
.dir =
|
||||
#ifdef PRALINE
|
||||
(1 << 18) // P9_5: RFF5072 SCLK
|
||||
| boot_bit(gpio_control::trigger_out, 1) // P2_6: Trigger out
|
||||
| (0 << 14) // P4_10: FPGA CDONE
|
||||
| (1 << 15) // P6_7: 3V3 AUX_ENABLE
|
||||
| (1 << 16) // P6_8: P1_CTRL1
|
||||
| (0 << 17) // P9_4: FPGA SGPIO
|
||||
| (1 << 19) // PA_4: Output
|
||||
| (1 << 20) // PB_0: Output GND
|
||||
| (1 << 21) // PB_1: Output GND
|
||||
| (0 << 22) // PB_2: Unused
|
||||
| (1 << 23) // PB_3: Output
|
||||
| (0 << 24) // PB_4: Unused
|
||||
| (1 << 25) // PB_5: Output
|
||||
| (0 << 5) // P2_5: PPS (Bidirectional)
|
||||
| (1 << 12) // P4_8: Output
|
||||
| (1 << 13) // P4_9: TPS62410 VREGMODE
|
||||
(1 << 18) // P9_5: RFF5072 SCLK
|
||||
| boot_bit(trigger_out, 1) // P2_6: Trigger out
|
||||
| (0 << 14) // P4_10: FPGA CDONE
|
||||
| (1 << 15) // P6_7: 3V3 AUX_ENABLE
|
||||
| boot_bit(p1_ctrl1, 1) // P6_8: P1_CTRL1
|
||||
| boot_bit(sgpio_4, 0) // P9_4: FPGA SGPIO
|
||||
| (1 << 19) // PA_4: Output
|
||||
| (1 << 20) // PB_0: Output GND
|
||||
| (1 << 21) // PB_1: Output GND
|
||||
| (0 << 22) // PB_2: Unused
|
||||
| (1 << 23) // PB_3: Output
|
||||
| (0 << 24) // PB_4: Unused
|
||||
| (1 << 25) // PB_5: Output
|
||||
| (0 << 5) // P2_5: PPS (Bidirectional)
|
||||
| (1 << 12) // P4_8: Output
|
||||
| boot_bit(vregmode, 1) // P4_9: TPS62410 VREGMODE
|
||||
#else
|
||||
(0 << 18) // P9_5: HackRF CPLD.TDO(O)
|
||||
| (1 << 6) // P2_6: MIXER_SCLK
|
||||
@@ -380,31 +383,31 @@ const PALConfig pal_default_config = {
|
||||
| (0 << 13) // P4_9: SGPIO14, CPLD
|
||||
| (0 << 12) // P4_8: Varies by revision
|
||||
#endif
|
||||
| (0 << 11) // P3_8: SPIFI_CS
|
||||
| (0 << 10) // P3_7: SPIFI_MOSI
|
||||
| (0 << 9) // P3_2: I2S0_RX_SDA
|
||||
| (0 << 8) // P3_1: I2S0_RX_WS
|
||||
| (0 << 7) // P2_8: BOOT2
|
||||
| (0 << 4) // P2_4: PortaPack LCD_RDX
|
||||
| (0 << 3) // P2_3: PortaPack LCD_TE
|
||||
| (0 << 2) // P2_2: SGPIO6, HOST_DATA6
|
||||
| (0 << 1) // P2_1: PortaPack ADDR
|
||||
| (0 << 0) // P2_0: PortaPack IO_STBX
|
||||
| (0 << 11) // P3_8: SPIFI_CS
|
||||
| (0 << 10) // P3_7: SPIFI_MOSI
|
||||
| (0 << 9) // P3_2: I2S0_RX_SDA
|
||||
| (0 << 8) // P3_1: I2S0_RX_WS
|
||||
| (0 << 7) // P2_8: BOOT2
|
||||
| (0 << 4) // P2_4: PortaPack LCD_RDX
|
||||
| (0 << 3) // P2_3: PortaPack LCD_TE
|
||||
| boot_bit(sgpio_6, 0) // P2_2: SGPIO6, HOST_DATA6
|
||||
| (0 << 1) // P2_1: PortaPack ADDR
|
||||
| (0 << 0) // P2_0: PortaPack IO_STBX
|
||||
},
|
||||
{
|
||||
// GPIO6
|
||||
#ifdef PRALINE
|
||||
.data = (1 << 28) // PD_14: MAX2831 chip select
|
||||
| (0 << 29) // PD_15: MAX2831 RXHP control RXHP low = 100 Hz HPF
|
||||
| (1 << 30) // PD_16: MAX5865 chip select
|
||||
| (1 << 25) // PD_11: RFFC5072 Lock Detect
|
||||
| boot_bit(gpio_control::trigger_in, 0) // PD_12: TRIGGER IN
|
||||
.data = (1 << 28) // PD_14: MAX2831 chip select
|
||||
| (0 << 29) // PD_15: MAX2831 RXHP control RXHP low = 100 Hz HPF
|
||||
| (1 << 30) // PD_16: MAX5865 chip select
|
||||
| (1 << 25) // PD_11: RFFC5072 Lock Detect
|
||||
| boot_bit(trigger_in, 0) // PD_12: TRIGGER IN
|
||||
,
|
||||
.dir = (1 << 28) // PD_14: MAX2831 chip select
|
||||
| (1 << 29) // PD_15: MAX2831 RXHP control
|
||||
| (1 << 30) // PD_16: MAX5865 chip select
|
||||
| (0 << 25) // PD_11: RFFC5072 Lock Detect
|
||||
| boot_bit(gpio_control::trigger_in, 0) // PD_12: TRIGGER IN
|
||||
.dir = (1 << 28) // PD_14: MAX2831 chip select
|
||||
| (1 << 29) // PD_15: MAX2831 RXHP control
|
||||
| (1 << 30) // PD_16: MAX5865 chip select
|
||||
| (0 << 25) // PD_11: RFFC5072 Lock Detect
|
||||
| boot_bit(trigger_in, 0) // PD_12: TRIGGER IN
|
||||
#else
|
||||
.data = 0,
|
||||
.dir = 0
|
||||
@@ -413,17 +416,17 @@ const PALConfig pal_default_config = {
|
||||
{
|
||||
// GPIO7
|
||||
#ifdef PRALINE
|
||||
.data = (0 << 0) // PE_0: Output
|
||||
| (0 << 1) // PE_1: MAX2831 !SHDN
|
||||
| (0 << 2) // PE_2: MAX2831 RXTX
|
||||
| boot_bit(gpio_control::p2_ctrl0, 0) // PE_3: P2_ctrl0
|
||||
| boot_bit(gpio_control::p2_ctrl1, 0) // PE_4: P2_ctrl1
|
||||
.data = (0 << 0) // PE_0: Output
|
||||
| (0 << 1) // PE_1: MAX2831 !SHDN
|
||||
| (0 << 2) // PE_2: MAX2831 RXTX
|
||||
| boot_bit(p2_ctrl0, 0) // PE_3: P2_ctrl0
|
||||
| boot_bit(p2_ctrl1, 0) // PE_4: P2_ctrl1
|
||||
,
|
||||
.dir = (1 << 0) // PE_0: Output
|
||||
| (1 << 1) // PE_1: MAX2831 !SHDN
|
||||
| (1 << 2) // PE_2: MAX2831 RXTX
|
||||
| boot_bit(gpio_control::p2_ctrl0, 1) // PE_3: P2_ctrl0
|
||||
| boot_bit(gpio_control::p2_ctrl1, 1) // PE_4: P2_ctrl1
|
||||
.dir = (1 << 0) // PE_0: Output
|
||||
| (1 << 1) // PE_1: MAX2831 !SHDN
|
||||
| (1 << 2) // PE_2: MAX2831 RXTX
|
||||
| boot_bit(p2_ctrl0, 1) // PE_3: P2_ctrl0
|
||||
| boot_bit(p2_ctrl1, 1) // PE_4: P2_ctrl1
|
||||
#else
|
||||
.data = 0,
|
||||
.dir = 0
|
||||
@@ -434,28 +437,28 @@ const PALConfig pal_default_config = {
|
||||
|
||||
// SClock LEDs
|
||||
|
||||
{4, 7, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 0, .ehs = 0, .ezi = 1, .zif = 1}}, // GP_CLKIN: SI5351C.CLK7(O)
|
||||
{4, 1, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED1: USB
|
||||
{4, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED2: RX
|
||||
{6, 12, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED3: TX
|
||||
{4, 7, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 0, .ehs = 0, .ezi = 1, .zif = 1}}, // GP_CLKIN: SI5351C.CLK7(O)
|
||||
{map_led_usb.scu_port, map_led_usb.scu_pin, scu_config_normal_drive_t{.mode = map_led_usb.gpio_mode, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED1: USB
|
||||
{map_led_rx.scu_port, map_led_rx.scu_pin, scu_config_normal_drive_t{.mode = map_led_rx.gpio_mode, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED2: RX
|
||||
{map_led_tx.scu_port, map_led_tx.scu_pin, scu_config_normal_drive_t{.mode = map_led_tx.gpio_mode, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED3: TX
|
||||
#ifdef PRALINE
|
||||
{8, 6, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED4: PRALINE Custom
|
||||
{map_led_mcu.scu_port, map_led_mcu.scu_pin, scu_config_normal_drive_t{.mode = map_led_mcu.gpio_mode, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // LED4: PRALINE Custom
|
||||
#endif
|
||||
|
||||
// POWER MANAGEMENT (Regulators, Bias, Current Limits)
|
||||
|
||||
{6, 11, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // VREGMODE: TPS62410
|
||||
{map_vregmode.scu_port, map_vregmode.scu_pin, scu_config_normal_drive_t{.mode = map_vregmode.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // VREGMODE: TPS62410
|
||||
#ifdef PRALINE
|
||||
{8, 1, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_1: VAA_EN
|
||||
{8, 4, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_4: VBUS_IN_EN
|
||||
{8, 5, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_5: VIN_IN_EN
|
||||
{8, 7, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_7: 1V2_EN
|
||||
{6, 7, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P6_7: 3.3V Aux Enable
|
||||
{4, 9, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P4_9: TPS62410 mode
|
||||
{gpio_control::map_p1_ctrl0.scu_port, gpio_control::map_p1_ctrl0.scu_pin, scu_config_normal_drive_t{.mode = 0, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P2_10: P1_CTRL0
|
||||
{gpio_control::map_p1_ctrl2.scu_port, gpio_control::map_p1_ctrl2.scu_pin, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P6_9: P1_CTRL2 (Output VCC, PU ON,)
|
||||
{gpio_control::map_p2_ctrl0.scu_port, gpio_control::map_p2_ctrl0.scu_pin, scu_config_normal_drive_t{.mode = 4, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // PE_3: P2_CTRL0
|
||||
{gpio_control::map_p2_ctrl1.scu_port, gpio_control::map_p2_ctrl1.scu_pin, scu_config_normal_drive_t{.mode = 4, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // PE_4: P2_CTRL1
|
||||
{map_VAA_en.scu_port, map_VAA_en.scu_pin, scu_config_normal_drive_t{.mode = map_VAA_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_1: !VAA_EN
|
||||
{8, 4, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_4: VBUS_IN_EN
|
||||
{8, 5, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_5: VIN_IN_EN
|
||||
{map_en_1v2.scu_port, map_en_1v2.scu_pin, scu_config_normal_drive_t{.mode = map_en_1v2.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P8_7: EN_1V2
|
||||
{6, 7, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P6_7: 3.3V Aux Enable
|
||||
{4, 9, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P4_9: TPS62410 mode
|
||||
{map_p1_ctrl0.scu_port, map_p1_ctrl0.scu_pin, scu_config_normal_drive_t{.mode = map_p1_ctrl0.gpio_mode, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P2_10: P1_CTRL0
|
||||
{map_p1_ctrl2.scu_port, map_p1_ctrl2.scu_pin, scu_config_normal_drive_t{.mode = map_p1_ctrl2.gpio_mode, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P6_9: P1_CTRL2 (Output VCC, PU ON,)
|
||||
{map_p2_ctrl0.scu_port, map_p2_ctrl0.scu_pin, scu_config_normal_drive_t{.mode = map_p2_ctrl0.gpio_mode, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // PE_3: P2_CTRL0
|
||||
{map_p2_ctrl1.scu_port, map_p2_ctrl1.scu_pin, scu_config_normal_drive_t{.mode = map_p2_ctrl1.gpio_mode, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // PE_4: P2_CTRL1
|
||||
#endif
|
||||
|
||||
/* HackRF: I2C0 */
|
||||
@@ -480,43 +483,41 @@ const PALConfig pal_default_config = {
|
||||
}},
|
||||
// FPGA & HIGH-SPEED DATA (SGPIO, Config, Triggers)
|
||||
|
||||
{0, 0, scu_config_normal_drive_t{.mode = 3, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO0: HOST_DATA0(IO)
|
||||
{0, 1, scu_config_normal_drive_t{.mode = 3, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO1: HOST_DATA1(IO)
|
||||
{1, 15, scu_config_normal_drive_t{.mode = 2, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO2: HOST_DATA2(IO)
|
||||
{1, 16, scu_config_normal_drive_t{.mode = 2, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO3: HOST_DATA3(IO)
|
||||
{6, 6, scu_config_normal_drive_t{.mode = 2, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO5: HOST_DATA5(IO)
|
||||
{2, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO6: HOST_DATA6(IO)
|
||||
{1, 0, scu_config_normal_drive_t{.mode = 6, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO7: HOST_DATA7(IO)
|
||||
{1, 18, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // SGPIO12: HOST_INVERT(I)
|
||||
{map_sgpio_0.scu_port, map_sgpio_0.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_0.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO0: HOST_DATA0(IO)
|
||||
{map_sgpio_1.scu_port, map_sgpio_1.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_1.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO1: HOST_DATA1(IO)
|
||||
{map_sgpio_2.scu_port, map_sgpio_2.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_2.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO2: HOST_DATA2(IO)
|
||||
{map_sgpio_3.scu_port, map_sgpio_3.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_3.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO3: HOST_DATA3(IO)
|
||||
{map_sgpio_4.scu_port, map_sgpio_4.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_4.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO4 HOST_DATA4(IO)
|
||||
{map_sgpio_5.scu_port, map_sgpio_5.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_5.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO5: HOST_DATA5(IO)
|
||||
{map_sgpio_6.scu_port, map_sgpio_6.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_6.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO6: HOST_DATA6(IO)
|
||||
{map_sgpio_7.scu_port, map_sgpio_7.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_7.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO7: HOST_DATA7(IO)
|
||||
{map_sgpio_8.scu_port, map_sgpio_8.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_8.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO8: CLK
|
||||
{map_sgpio_9.scu_port, map_sgpio_9.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_9.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO9: HOST_CAPTURE
|
||||
{map_sgpio_10.scu_port, map_sgpio_10.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_10.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO10: DISABLE
|
||||
{map_sgpio_11.scu_port, map_sgpio_11.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_11.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO11: HOST_DIRECTION(I)
|
||||
{map_sgpio_12.scu_port, map_sgpio_12.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_12.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // SGPIO12: HOST_INVERT(I)
|
||||
#ifdef PRALINE
|
||||
{8, 0, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO8: P8_0 func 4 (CLK)
|
||||
{8, 2, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO10: P8_2 func 4 (DISABLE)
|
||||
{9, 3, scu_config_normal_drive_t{.mode = 6, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO9: P9_3 func 6 (CAPTURE)
|
||||
{9, 4, scu_config_normal_drive_t{.mode = 6, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO4: P9_4 func 6
|
||||
{1, 17, scu_config_normal_drive_t{.mode = 6, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO11: P1_17 func 6 (DIRECTION)
|
||||
{6, 4, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // P6_4: SCT_CLK IN (Fast clock input, Mode 1)
|
||||
{4, 10, scu_config_normal_drive_t{.mode = 7, .epd = 1, .epun = 1, .ehs = 0, .ezi = 1, .zif = 0}}, // P4_10: FPGA Config Done (Input GND)
|
||||
{gpio_control::map_trigger_in.scu_port, gpio_control::map_trigger_in.scu_pin, scu_config_normal_drive_t{.mode = 4, .epd = 1, .epun = 1, .ehs = 0, .ezi = 1, .zif = 0}}, // PD_12: TRIGGER IN (Input GND, Mode 4)
|
||||
{gpio_control::map_trigger_out.scu_port, gpio_control::map_trigger_out.scu_pin, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // P2_6: TRIGGER
|
||||
{2, 5, scu_config_normal_drive_t{.mode = 4, .epd = 1, .epun = 1, .ehs = 0, .ezi = 1, .zif = 0}}, // P2_5: PPS OUT/IN (Mode 4 per Suppl. Data)
|
||||
|
||||
{6, 4, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // P6_4: SCT_CLK IN (Fast clock input, Mode 1)
|
||||
{4, 10, scu_config_normal_drive_t{.mode = 7, .epd = 1, .epun = 1, .ehs = 0, .ezi = 1, .zif = 0}}, // P4_10: FPGA Config Done (Input GND)
|
||||
{map_trigger_in.scu_port, map_trigger_in.scu_pin, scu_config_normal_drive_t{.mode = map_trigger_in.gpio_mode, .epd = 1, .epun = 1, .ehs = 0, .ezi = 1, .zif = 0}}, // PD_12: TRIGGER IN (Input GND, Mode 4)
|
||||
{map_trigger_out.scu_port, map_trigger_out.scu_pin, scu_config_normal_drive_t{.mode = map_trigger_out.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // P2_6: TRIGGER
|
||||
{2, 5, scu_config_normal_drive_t{.mode = 4, .epd = 1, .epun = 1, .ehs = 0, .ezi = 1, .zif = 0}},
|
||||
{gpio_control::map_clkin_ctrl.scu_port, gpio_control::map_clkin_ctrl.scu_pin, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P1_20 CLKIN_ctrl
|
||||
#else
|
||||
{9, 6, scu_config_normal_drive_t{.mode = 6, .epd = 0, .epun = 0, .ehs = 0, .ezi = 1, .zif = 1}}, // SGPIO8: SI5351C.CLK2(O)
|
||||
{4, 3, scu_config_normal_drive_t{.mode = 7, .epd = 0, .epun = 1, .ehs = 0, .ezi = 1, .zif = 1}}, // SGPIO9: HOST_CAPTURE(O)
|
||||
{1, 14, scu_config_normal_drive_t{.mode = 6, .epd = 0, .epun = 0, .ehs = 1, .ezi = 0, .zif = 0}}, // SGPIO10: HOST_DISABLE(I)
|
||||
{1, 17, scu_config_normal_drive_t{.mode = 6, .epd = 1, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // SGPIO11: HOST_DIRECTION(I)
|
||||
{6, 3, scu_config_normal_drive_t{.mode = 2, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // SGPIO4: HOST_DATA4(IO)
|
||||
|
||||
{4, 9, scu_config_normal_drive_t{.mode = 7, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // SGPIO14/BANK2F3M4: CPLD_P81
|
||||
{4, 10, scu_config_normal_drive_t{.mode = 7, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // SGPIO15/BANK2F3M6: CPLD_P78
|
||||
{2, 6, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 1}}, // MIXER_SCLK/P31: 33pF, RFFC5072.SCLK(I)
|
||||
{4, 5, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // RXENABLE
|
||||
{4, 6, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // XCVR_EN: 10K PD
|
||||
{1, 20, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P1_20 CS_XCVR: MAX2837.CS(I)
|
||||
#endif
|
||||
|
||||
// RADIO & RF PATH (MAX2831, RFFC5072, Mixers, Switches, Amps)
|
||||
{1, 3, scu_config_normal_drive_t{.mode = 5, .epd = 0, .epun = 0, .ehs = 0, .ezi = 1, .zif = 0}}, // P1_3 SSP1_MISO: MAX2837.DOUT(O)
|
||||
{1, 4, scu_config_normal_drive_t{.mode = 5, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P1_4 SSP1_MOSI: MAX2837.DIN(I)
|
||||
{1, 19, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 0, .ehs = 0, .ezi = 1, .zif = 1}}, // P1_19 SSP1_SCK: MAX2837.SCLK(I)
|
||||
{1, 20, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P1_20 CS_XCVR: MAX2837.CS(I)
|
||||
{2, 11, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P2_11 RX_AMP
|
||||
{2, 12, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P2_12 !RX_AMP_PWR
|
||||
{4, 0, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P4_0 HP
|
||||
@@ -524,25 +525,24 @@ const PALConfig pal_default_config = {
|
||||
{5, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P5_2 TX_MIX_BP
|
||||
|
||||
#ifdef PRALINE
|
||||
{5, 4, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P5_4: RFFC ENX
|
||||
{5, 5, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P5_5: RFFC RESETX
|
||||
{9, 5, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // P9_5: RFFC5072 SCLK
|
||||
{9, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 1, .ezi = 1, .zif = 0}}, // P9_2: RFFC5072 DATA (Bidirectional)
|
||||
{13, 11, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 0, .ehs = 0, .ezi = 1, .zif = 0}}, // PD_11: RFFC Lock Detect
|
||||
{13, 14, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PD_14: MAX2831 CS
|
||||
{13, 15, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // PD_15: MAX2831 RXHP
|
||||
{13, 16, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PD_16: MAX5864 CS
|
||||
|
||||
{14, 1, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PE_1: MAX2831 !SHDN
|
||||
{14, 2, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // PE_2: MAX2831 RXTX
|
||||
{6, 3, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 1, .ezi = 0, .zif = 0}}, // P6_3: MIX_ENABLE_N
|
||||
{gpio_control::map_p1_ctrl1.scu_port, gpio_control::map_p1_ctrl1.scu_pin, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P6_8 P1_CTRL1 (Output GND, Mode 4)
|
||||
{gpio_control::map_aa_en.scu_port, gpio_control::map_aa_en.scu_pin, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 0}}, // P1_14: AA_EN
|
||||
{gpio_control::map_rf5072_mix_en.scu_port, gpio_control::map_rf5072_mix_en.scu_pin, scu_config_normal_drive_t{.mode = 0, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P9_0: RF5072 MIX EN
|
||||
{9, 6, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P9_6: MAX2831 LD Input
|
||||
{6, 5, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // P6_5: TX enable
|
||||
{10, 1, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PA_1: LPF enable
|
||||
{10, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PA_2: RF amp enable
|
||||
{5, 4, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P5_4: RFFC ENX
|
||||
{5, 5, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P5_5: RFFC RESETX
|
||||
{9, 5, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // P9_5: RFFC5072 SCLK
|
||||
{9, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 1, .ezi = 1, .zif = 0}}, // P9_2: RFFC5072 DATA (Bidirectional)
|
||||
{13, 11, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 0, .ehs = 0, .ezi = 1, .zif = 0}}, // PD_11: RFFC Lock Detect
|
||||
{13, 14, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PD_14: MAX2831 CS
|
||||
{13, 15, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // PD_15: MAX2831 RXHP
|
||||
{13, 16, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PD_16: MAX5864 CS
|
||||
{14, 1, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PE_1: MAX2831 !SHDN
|
||||
{14, 2, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 1}}, // PE_2: MAX2831 RXTX
|
||||
{6, 3, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 1, .ezi = 0, .zif = 0}}, // P6_3: MIX_ENABLE_N
|
||||
{map_p1_ctrl1.scu_port, map_p1_ctrl1.scu_pin, scu_config_normal_drive_t{.mode = map_p1_ctrl1.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P6_8 P1_CTRL1 (Output GND, Mode 4)
|
||||
{map_aa_en.scu_port, map_aa_en.scu_pin, scu_config_normal_drive_t{.mode = map_aa_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 1, .ezi = 1, .zif = 0}}, // P1_14: AA_EN
|
||||
{map_rf5072_mix_en.scu_port, map_rf5072_mix_en.scu_pin, scu_config_normal_drive_t{.mode = map_rf5072_mix_en.gpio_mode, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P9_0: RF5072 MIX EN
|
||||
{9, 6, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 0, .ehs = 0, .ezi = 0, .zif = 0}}, // P9_6: MAX2831 LD Input
|
||||
{6, 5, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // P6_5: TX enable
|
||||
{10, 1, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PA_1: LPF enable
|
||||
{10, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 1, .ezi = 0, .zif = 0}}, // PA_2: RF amp enable
|
||||
#else
|
||||
{5, 3, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // P5_3 RX_MIX_BP
|
||||
{5, 4, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, // MIXER_ENX
|
||||
@@ -594,9 +594,11 @@ const PALConfig pal_default_config = {
|
||||
|
||||
}};
|
||||
|
||||
#ifndef PRALINE
|
||||
/* Additional GPIO configuration for HackRF OG */
|
||||
static const std::array<gpio_setup_t, 6> gpio_setup_og{{
|
||||
{
|
||||
|
||||
// GPIO0
|
||||
.data = (0 << 9) // P1_2: 10K PD, BOOT1
|
||||
| (1 << 8) // P1_1: 10K PU, BOOT0
|
||||
@@ -611,31 +613,32 @@ static const std::array<gpio_setup_t, 6> gpio_setup_og{{
|
||||
.dir = 0},
|
||||
{
|
||||
// GPIO2
|
||||
.data = (1 << 9) // P5_0: !VAA_ENABLE
|
||||
| (0 << 4) // P4_4: TXENABLE
|
||||
.data = boot_bit(og_VAA_en, 1) // P5_0: !VAA_ENABLE
|
||||
| (0 << 4) // P4_4: TXENABLE
|
||||
,
|
||||
.dir = (1 << 9) // P5_0: !VAA_ENABLE
|
||||
| (1 << 4) // P4_4: TXENABLE
|
||||
.dir = boot_bit(og_VAA_en, 1) // P5_0: !VAA_ENABLE
|
||||
| (1 << 4) // P4_4: TXENABLE
|
||||
},
|
||||
{
|
||||
// GPIO3
|
||||
.data = (0 << 6) // P6_10: EN1V8, 10K PD
|
||||
.data = boot_bit(og_1v8_en, 0) // P6_10: EN1V8, 10K PD
|
||||
,
|
||||
.dir = (1 << 6) // P6_10: EN1V8, 10K PD
|
||||
.dir = boot_bit(og_1v8_en, 1) // P6_10: EN1V8, 10K PD
|
||||
},
|
||||
{// GPIO4
|
||||
.data = 0,
|
||||
.dir = 0},
|
||||
{
|
||||
// GPIO5
|
||||
.data = (0 << 15) // P6_7: TX
|
||||
| (0 << 12) // P4_8: SGPIO13, HOST_SYNC_EN
|
||||
| (1 << 5) // P2_5: RX
|
||||
.data = (0 << 15) // P6_7: TX
|
||||
| boot_bit(sgpio_13, 0) // P4_8: SGPIO13, HOST_SYNC_EN
|
||||
| (1 << 5) // P2_5: RX
|
||||
,
|
||||
.dir = (1 << 15) // P6_7: TX
|
||||
| (0 << 12) // P4_8: SGPIO13, HOST_SYNC_EN
|
||||
| (1 << 5) // P2_5: RX
|
||||
.dir = (1 << 15) // P6_7: TX
|
||||
| boot_bit(sgpio_13, 0) // P4_8: SGPIO13, HOST_SYNC_EN
|
||||
| (1 << 5) // P2_5: RX
|
||||
},
|
||||
|
||||
}};
|
||||
|
||||
/* Additional GPIO configuration for HackRF r9 */
|
||||
@@ -655,17 +658,17 @@ static const std::array<gpio_setup_t, 6> gpio_setup_r9{{
|
||||
.dir = 0},
|
||||
{
|
||||
// GPIO2
|
||||
.data = (1 << 9) // P5_0: EN1V8, 10K PD
|
||||
| (1 << 4) // P4_4: !ANT_BIAS
|
||||
.data = boot_bit(r9_1v8_en, 0) // P5_0: EN1V8, 10K PD
|
||||
| (1 << 4) // P4_4: !ANT_BIAS
|
||||
,
|
||||
.dir = (1 << 9) // P5_0: EN1V8, 10K PD
|
||||
| (1 << 4) // P4_4: !ANT_BIAS
|
||||
.dir = boot_bit(r9_1v8_en, 1) // P5_0: EN1V8, 10K PD
|
||||
| (1 << 4) // P4_4: !ANT_BIAS
|
||||
},
|
||||
{
|
||||
// GPIO3
|
||||
.data = (1 << 6) // P6_10: !VAA_ENABLE
|
||||
.data = boot_bit(r9_VAA_en, 1) // P6_10: !VAA_ENABLE
|
||||
,
|
||||
.dir = (1 << 6) // P6_10: !VAA_ENABLE
|
||||
.dir = boot_bit(r9_VAA_en, 1) // P6_10: !VAA_ENABLE
|
||||
},
|
||||
{// GPIO4
|
||||
.data = 0,
|
||||
@@ -684,9 +687,10 @@ static const std::array<gpio_setup_t, 6> gpio_setup_r9{{
|
||||
|
||||
/* Additional SCU configuration for HackRF OG */
|
||||
static const std::array<scu_setup_t, 9> pins_setup_og{{
|
||||
|
||||
/* Power control */
|
||||
{5, 0, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
|
||||
{6, 10, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* EN1V8/P70: 10K PD, TPS62410.EN2(I), 1V8LED.A(I) */
|
||||
{map_og_VAA_en.scu_port, map_og_VAA_en.scu_pin, scu_config_normal_drive_t{.mode = map_og_VAA_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
|
||||
{map_og_1v8_en.scu_port, map_og_1v8_en.scu_pin, scu_config_normal_drive_t{.mode = map_og_1v8_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* EN1V8/P70: 10K PD, TPS62410.EN2(I), 1V8LED.A(I) */
|
||||
|
||||
/* Radio section control */
|
||||
{2, 5, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* RX/P43: U7.VCTL1(I), U10.VCTL1(I), U2.VCTL1(I) */
|
||||
@@ -694,19 +698,19 @@ static const std::array<scu_setup_t, 9> pins_setup_og{{
|
||||
{6, 7, scu_config_normal_drive_t{.mode = 4, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* TX/P42: U7.VCTL2(I), U10.VCTL2(I), U2.VCTL2(I) */
|
||||
|
||||
/* SGPIO for sample transfer interface to HackRF CPLD. */
|
||||
{4, 8, scu_config_normal_drive_t{.mode = 4, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* SGPIO13/BANK2F3M2: CPLD.90/HOST_SYNC_EN(I) */
|
||||
|
||||
{map_sgpio_13.scu_port, map_sgpio_13.scu_pin, scu_config_normal_drive_t{.mode = map_sgpio_13.gpio_mode, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* SGPIO13/BANK2F3M2: CPLD.90/HOST_SYNC_EN(I) */
|
||||
/* Miscellaneous */
|
||||
{1, 1, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* P1_1/P74: 10K PU, BOOT0 */
|
||||
{1, 2, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* P1_2/P73: 10K PD, BOOT1 */
|
||||
{2, 7, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* ISP: 10K PU, Unused */
|
||||
|
||||
}};
|
||||
|
||||
/* Additional SCU configuration for HackRF r9 */
|
||||
static const std::array<scu_setup_t, 9> pins_setup_r9{{
|
||||
/* Power control */
|
||||
{6, 10, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
|
||||
{5, 0, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* EN1V8: 10K PD, TPS62410.EN2(I), 1V8LED.A(I) */
|
||||
{map_r9_VAA_en.scu_port, map_r9_VAA_en.scu_pin, scu_config_normal_drive_t{.mode = map_r9_VAA_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
|
||||
{map_r9_1v8_en.scu_port, map_r9_1v8_en.scu_pin, scu_config_normal_drive_t{.mode = map_r9_1v8_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* EN1V8: 10K PD, TPS62410.EN2(I), 1V8LED.A(I) */
|
||||
|
||||
/* Radio section control */
|
||||
{2, 7, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* RX/ISP/P96: U7.VCTL(I), U10.VCTL(I), U2.VCTL(I) */
|
||||
@@ -723,6 +727,7 @@ static const std::array<scu_setup_t, 9> pins_setup_r9{{
|
||||
/* Miscellaneous */
|
||||
{4, 8, scu_config_normal_drive_t{.mode = 1, .epd = 1, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}}, /* CLKIN_DETECT: U26.2Y(O) */
|
||||
}};
|
||||
#endif // #ifndef PRALINE
|
||||
|
||||
#endif
|
||||
|
||||
@@ -904,10 +909,10 @@ extern "C" void __early_init(void) {
|
||||
|
||||
if ((SCB->CPUID & CORTEX_M4_CPUID_MASK) == CORTEX_M4_CPUID) {
|
||||
/* Enable unaligned exception handler */
|
||||
SCB_CCR |= (1 << 3);
|
||||
SCB->CCR |= (1 << 3);
|
||||
|
||||
/* Enable MemManage, BusFault, UsageFault exception handlers */
|
||||
SCB_SHCSR |= (1 << 18) | (1 << 17) | (1 << 16);
|
||||
SCB->SHCSR |= (1 << 18) | (1 << 17) | (1 << 16);
|
||||
|
||||
/* "The reset delay is counted in IRC clock cycles. If the core frequency
|
||||
* CCLK is much higher than the IRC frequency, add a software delay of
|
||||
@@ -1001,8 +1006,7 @@ extern "C" void boardInit(void) {
|
||||
|
||||
power_control::aux_power_on();
|
||||
|
||||
LPC_GPIO->SET[2] = (1 << 1) | (1 << 2) | (1 << 8);
|
||||
LPC_GPIO->CLR[4] = (1 << 6);
|
||||
led_mcu.setActive();
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ bool BMPFile::open(const std::filesystem::path& file, bool readonly) {
|
||||
if (!((bmp_header.signature == 0x4D42) &&
|
||||
(bmp_header.planes == 1) &&
|
||||
(bmp_header.compression == 0 || bmp_header.compression == 3))) {
|
||||
bmpimage.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -114,6 +115,7 @@ bool BMPFile::open(const std::filesystem::path& file, bool readonly) {
|
||||
byte_per_px = 1;
|
||||
// bmpimage.seek(sizeof(bmp_header_t));
|
||||
// bmpimage.read(color_palette, 1024);
|
||||
bmpimage.close();
|
||||
return false; // niy
|
||||
break;
|
||||
|
||||
@@ -121,6 +123,7 @@ bool BMPFile::open(const std::filesystem::path& file, bool readonly) {
|
||||
byte_per_px = 2;
|
||||
type = 5;
|
||||
if (bmp_header.compression == 3) {
|
||||
bmpimage.close();
|
||||
return false;
|
||||
} // niy
|
||||
|
||||
@@ -135,6 +138,7 @@ bool BMPFile::open(const std::filesystem::path& file, bool readonly) {
|
||||
break;
|
||||
default:
|
||||
// not supported
|
||||
bmpimage.close();
|
||||
return false;
|
||||
}
|
||||
byte_per_row = (bmp_header.width * byte_per_px + 3) & ~3;
|
||||
|
||||
+16
-22
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "platform.hpp"
|
||||
|
||||
using namespace gpio_control;
|
||||
|
||||
namespace power_control {
|
||||
|
||||
/* VAA powers:
|
||||
@@ -53,7 +55,7 @@ void vaa_power_on(void) {
|
||||
}
|
||||
|
||||
/* Latch VAA to ON state (Active LOW) */
|
||||
LPC_GPIO->CLR[4] = (1 << 1);
|
||||
VAA_en.setActive();
|
||||
|
||||
#else
|
||||
if (hackrf_r9) {
|
||||
@@ -104,8 +106,8 @@ void vaa_power_on(void) {
|
||||
}
|
||||
|
||||
/* Hold !VAA_ENABLE active using a GPIO, so we can reclaim and shut down the MOTOCONPWM peripheral. */
|
||||
LPC_GPIO->CLR[2] = (1 << 9); // !VAA_ENABLE
|
||||
LPC_GPIO->DIR[2] |= (1 << 9);
|
||||
og_VAA_en.output();
|
||||
og_VAA_en.setActive();
|
||||
setup_pin(pin_setup_vaa_enablex_gpio_og); // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
|
||||
|
||||
peripheral_reset(&motocon_pwm_resources.reset);
|
||||
@@ -122,16 +124,13 @@ void vaa_power_off(void) {
|
||||
*/
|
||||
#ifdef PRALINE
|
||||
/* Safe state: OFF (VAA RF is active LOW, so Set = OFF) */
|
||||
LPC_GPIO->SET[4] = (1 << 1);
|
||||
|
||||
/* Turn OFF LED3 (TX) */
|
||||
LPC_GPIO->SET[2] = (1 << 8);
|
||||
VAA_en.setInactive();
|
||||
|
||||
#else
|
||||
if (hackrf_r9) {
|
||||
LPC_GPIO->W3[6] = 1; // Turn OFF VAA for r9 P6_10
|
||||
r9_VAA_en.setInactive(); // Turn OFF VAA for r9 P6_10
|
||||
} else {
|
||||
LPC_GPIO->W2[9] = 1; // Turn OFF VAA for OG P5_0
|
||||
og_VAA_en.setInactive(); // Turn OFF VAA for OG P5_0
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -150,34 +149,29 @@ void aux_power_off(void) {
|
||||
|
||||
#endif /* PRALINE */
|
||||
|
||||
void core_power_on(void) { // Core power enable
|
||||
void core_power_on(void) {
|
||||
#ifdef PRALINE
|
||||
// 1.2V FPGA - P8_7 = GPIO4[7], Active HIGH (Set = ON)
|
||||
LPC_GPIO->SET[4] = (1 << 7);
|
||||
en_1v2.setActive();
|
||||
|
||||
#else
|
||||
if (hackrf_r9) {
|
||||
// P5_0 (GPIO2[9]) is the EN1V8 pin
|
||||
LPC_GPIO->SET[2] = (1 << 9);
|
||||
r9_1v8_en.setActive();
|
||||
} else {
|
||||
// On older OG HackRF boards, P6_10 (GPIO3[6]) is the EN1V8 pin
|
||||
LPC_GPIO->SET[3] = (1 << 6);
|
||||
og_1v8_en.setActive();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void core_power_off(void) { // Core power disable
|
||||
void core_power_off(void) {
|
||||
#ifdef PRALINE
|
||||
// 1.2V FPGA - P8_7 = GPIO4[7], Active HIGH (Clear = OFF) */
|
||||
LPC_GPIO->CLR[4] = (1 << 7);
|
||||
en_1v2.setInactive();
|
||||
|
||||
#else
|
||||
if (hackrf_r9) {
|
||||
// P5_0 (GPIO2[9]) is the EN1V8 pin
|
||||
LPC_GPIO->CLR[2] = (1 << 9);
|
||||
r9_1v8_en.setInactive();
|
||||
} else {
|
||||
// On older OG HackRF boards, P6_10 (GPIO3[6]) is the EN1V8 pin
|
||||
LPC_GPIO->CLR[3] = (1 << 6);
|
||||
og_1v8_en.setInactive();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+221
-52
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "pal.h"
|
||||
#include "pal_lld.h"
|
||||
|
||||
struct PinConfig {
|
||||
const uint32_t mode;
|
||||
@@ -200,6 +200,12 @@ struct Pin {
|
||||
uint8_t _pin_pad;
|
||||
};
|
||||
|
||||
// Defines the logical polarity of the GPIO pin
|
||||
enum class Polarity {
|
||||
ActiveHigh, // High physical state means the function is ON (default)
|
||||
ActiveLow // Low physical state means the function is ON (inverted)
|
||||
};
|
||||
|
||||
struct GPIO {
|
||||
// GPIO() = delete;
|
||||
// GPIO(const GPIO& gpio) = delete;
|
||||
@@ -209,22 +215,15 @@ struct GPIO {
|
||||
const Pin& pin,
|
||||
const ioportid_t gpio_port,
|
||||
const iopadid_t gpio_pad,
|
||||
const uint16_t gpio_mode)
|
||||
const uint16_t gpio_mode,
|
||||
const Polarity polarity = Polarity::ActiveHigh) // Default parameter ensures backward compatibility
|
||||
: _pin{pin},
|
||||
_gpio_port{gpio_port},
|
||||
_gpio_pad{gpio_pad},
|
||||
_gpio_mode{gpio_mode} {
|
||||
_gpio_mode{gpio_mode},
|
||||
_polarity{polarity} {
|
||||
}
|
||||
/*
|
||||
constexpr GPIO(
|
||||
const GPIO& gpio
|
||||
) : _pin { gpio._pin },
|
||||
_gpio_port { gpio._gpio_port },
|
||||
_gpio_pad { gpio._gpio_pad },
|
||||
_gpio_mode { gpio._gpio_mode }
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
constexpr ioportid_t port() const {
|
||||
return _gpio_port;
|
||||
}
|
||||
@@ -237,6 +236,11 @@ struct GPIO {
|
||||
return _pin;
|
||||
}
|
||||
|
||||
// Returns the configured polarity of the pin
|
||||
constexpr Polarity polarity() const {
|
||||
return _polarity;
|
||||
}
|
||||
|
||||
void configure() const {
|
||||
_pin.mode(_gpio_mode);
|
||||
}
|
||||
@@ -245,6 +249,8 @@ struct GPIO {
|
||||
return _gpio_mode;
|
||||
}
|
||||
|
||||
// Physical Level Operations
|
||||
|
||||
void set() const {
|
||||
palSetPad(_gpio_port, _gpio_pad);
|
||||
}
|
||||
@@ -273,6 +279,39 @@ struct GPIO {
|
||||
return palReadPad(_gpio_port, _gpio_pad);
|
||||
}
|
||||
|
||||
// Turns the feature ON based on its polarity
|
||||
void setActive() const {
|
||||
if (_polarity == Polarity::ActiveHigh) {
|
||||
set();
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Turns the feature OFF based on its polarity
|
||||
void setInactive() const {
|
||||
if (_polarity == Polarity::ActiveHigh) {
|
||||
clear();
|
||||
} else {
|
||||
set();
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the logical state of the feature
|
||||
void setState(const bool active) const {
|
||||
if (active) {
|
||||
setActive();
|
||||
} else {
|
||||
setInactive();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the feature is logically active/enabled
|
||||
bool isEnabled() const {
|
||||
const bool physical_state = read();
|
||||
return (_polarity == Polarity::ActiveHigh) ? physical_state : !physical_state;
|
||||
}
|
||||
|
||||
bool operator!=(const GPIO& other) const {
|
||||
return (port() != other.port()) || (pad() != other.pad());
|
||||
}
|
||||
@@ -281,6 +320,7 @@ struct GPIO {
|
||||
const ioportid_t _gpio_port;
|
||||
const iopadid_t _gpio_pad;
|
||||
const uint16_t _gpio_mode;
|
||||
const Polarity _polarity;
|
||||
};
|
||||
|
||||
constexpr uint32_t boot_bit(const GPIO& pin, bool state) {
|
||||
@@ -306,7 +346,6 @@ inline void setup_pins(const std::array<scu_setup_t, N>& pins_setup) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PRALINE
|
||||
namespace gpio_control {
|
||||
|
||||
struct PinMap {
|
||||
@@ -314,55 +353,195 @@ struct PinMap {
|
||||
uint8_t scu_pin;
|
||||
uint8_t gpio_port;
|
||||
uint8_t gpio_pad;
|
||||
uint8_t gpio_mode;
|
||||
};
|
||||
|
||||
constexpr PinMap map_p1_ctrl0{2, 10, 0, 14}; // SCU: 2, 10 | GPIO: 0, 14
|
||||
constexpr PinMap map_p1_ctrl1{6, 8, 5, 16};
|
||||
constexpr PinMap map_p1_ctrl2{6, 9, 3, 5};
|
||||
constexpr PinMap map_p2_ctrl0{8, 3, 7, 3};
|
||||
constexpr PinMap map_p2_ctrl1{8, 4, 7, 4};
|
||||
constexpr PinMap map_trigger_out{2, 6, 5, 6};
|
||||
constexpr PinMap map_trigger_in{13, 12, 6, 26};
|
||||
#ifdef PRALINE
|
||||
constexpr PinMap map_p1_ctrl0{2, 10, 0, 14, 0}; // SCU: 2, 10 | GPIO: 0, 14
|
||||
constexpr PinMap map_p1_ctrl1{6, 8, 5, 16, 4};
|
||||
constexpr PinMap map_p1_ctrl2{6, 9, 3, 5, 0};
|
||||
|
||||
constexpr PinMap map_rf5072_mix_en{9, 0, 4, 12};
|
||||
constexpr PinMap map_p2_ctrl0{8, 3, 7, 3, 4};
|
||||
constexpr PinMap map_p2_ctrl1{8, 4, 7, 4, 4};
|
||||
|
||||
constexpr PinMap map_aa_en{1, 14, 1, 7}; // Anti-Aliasing filter
|
||||
constexpr PinMap map_trigger_out{2, 6, 5, 6, 4};
|
||||
constexpr PinMap map_trigger_in{13, 12, 6, 26, 4};
|
||||
|
||||
constexpr PinMap map_clkin_ctrl{1, 20, 0, 15, 0};
|
||||
|
||||
constexpr PinMap map_rf5072_mix_en{9, 0, 4, 12, 0};
|
||||
|
||||
constexpr PinMap map_aa_en{1, 14, 1, 7, 0}; // Anti-Aliasing filter
|
||||
|
||||
constexpr PinMap map_sgpio_4{9, 4, 5, 17, 6};
|
||||
constexpr PinMap map_sgpio_8{8, 0, 4, 0, 4};
|
||||
constexpr PinMap map_sgpio_9{9, 3, 4, 15, 6};
|
||||
constexpr PinMap map_sgpio_10{8, 2, 4, 2, 4};
|
||||
constexpr PinMap map_en_1v2{8, 7, 4, 7, 0};
|
||||
constexpr PinMap map_vregmode{4, 9, 5, 13, 4};
|
||||
constexpr PinMap map_VAA_en{8, 1, 4, 1, 0};
|
||||
constexpr PinMap map_led_mcu{8, 6, 4, 6, 0};
|
||||
#else
|
||||
constexpr PinMap map_sgpio_4{6, 3, 3, 2, 2};
|
||||
constexpr PinMap map_sgpio_8{9, 6, 4, 11, 6};
|
||||
constexpr PinMap map_sgpio_9{4, 3, 2, 3, 7};
|
||||
constexpr PinMap map_sgpio_10{1, 14, 1, 7, 6};
|
||||
constexpr PinMap map_sgpio_13{4, 8, 5, 12, 4};
|
||||
constexpr PinMap map_og_1v8_en{6, 10, 3, 6, 0};
|
||||
constexpr PinMap map_r9_1v8_en{5, 0, 2, 9, 0};
|
||||
constexpr PinMap map_vregmode{6, 11, 3, 7, 0};
|
||||
constexpr PinMap map_og_VAA_en{5, 0, 2, 9, 0};
|
||||
constexpr PinMap map_r9_VAA_en{6, 10, 3, 6, 0};
|
||||
#endif
|
||||
|
||||
constexpr PinMap map_sgpio_0{0, 0, 0, 0, 3};
|
||||
constexpr PinMap map_sgpio_1{0, 1, 0, 1, 3};
|
||||
constexpr PinMap map_sgpio_2{1, 15, 0, 2, 2};
|
||||
constexpr PinMap map_sgpio_3{1, 16, 0, 3, 2};
|
||||
constexpr PinMap map_sgpio_5{6, 6, 0, 5, 2};
|
||||
constexpr PinMap map_sgpio_6{2, 2, 5, 2, 0};
|
||||
constexpr PinMap map_sgpio_7{1, 0, 0, 4, 6};
|
||||
constexpr PinMap map_sgpio_11{1, 17, 0, 12, 6};
|
||||
constexpr PinMap map_sgpio_12{1, 18, 0, 13, 0};
|
||||
constexpr PinMap map_led_usb{4, 1, 2, 1, 0};
|
||||
constexpr PinMap map_led_rx{4, 2, 2, 2, 0};
|
||||
constexpr PinMap map_led_tx{6, 12, 2, 8, 0};
|
||||
#ifdef PRALINE
|
||||
|
||||
// P1 Multiplexer control pins
|
||||
constexpr Pin pin_p1_ctrl0{map_p1_ctrl0.scu_port, map_p1_ctrl0.scu_pin}; // SCU: P2_10
|
||||
constexpr GPIO p1_ctrl0{pin_p1_ctrl0, map_p1_ctrl0.gpio_port, map_p1_ctrl0.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[0]14
|
||||
constexpr Pin pin_p1_ctrl0{map_p1_ctrl0.scu_port, map_p1_ctrl0.scu_pin}; // SCU: P2_10
|
||||
constexpr GPIO p1_ctrl0{pin_p1_ctrl0, map_p1_ctrl0.gpio_port, map_p1_ctrl0.gpio_pad, map_p1_ctrl0.gpio_mode}; // GPIO[0]14
|
||||
|
||||
constexpr Pin pin_p1_ctrl1{map_p1_ctrl1.scu_port, map_p1_ctrl1.scu_pin}; // SCU: P6_8
|
||||
constexpr GPIO p1_ctrl1{pin_p1_ctrl1, map_p1_ctrl1.gpio_port, map_p1_ctrl1.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[5]16
|
||||
constexpr Pin pin_p1_ctrl1{map_p1_ctrl1.scu_port, map_p1_ctrl1.scu_pin}; // SCU: P6_8
|
||||
constexpr GPIO p1_ctrl1{pin_p1_ctrl1, map_p1_ctrl1.gpio_port, map_p1_ctrl1.gpio_pad, map_p1_ctrl1.gpio_mode}; // GPIO[5]16
|
||||
|
||||
constexpr Pin pin_p1_ctrl2{map_p1_ctrl2.scu_port, map_p1_ctrl2.scu_pin}; // SCU: P6_9
|
||||
constexpr GPIO p1_ctrl2{pin_p1_ctrl2, map_p1_ctrl2.gpio_port, map_p1_ctrl2.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[3]5
|
||||
constexpr Pin pin_p1_ctrl2{map_p1_ctrl2.scu_port, map_p1_ctrl2.scu_pin}; // SCU: P6_9
|
||||
constexpr GPIO p1_ctrl2{pin_p1_ctrl2, map_p1_ctrl2.gpio_port, map_p1_ctrl2.gpio_pad, map_p1_ctrl2.gpio_mode}; // GPIO[3]5
|
||||
|
||||
// P2 Multiplexer control pins
|
||||
constexpr Pin pin_p2_ctrl0{map_p2_ctrl0.scu_port, map_p2_ctrl0.scu_pin}; // SCU: PE_3
|
||||
constexpr GPIO p2_ctrl0{pin_p2_ctrl0, map_p2_ctrl0.gpio_port, map_p2_ctrl0.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[7]3
|
||||
constexpr Pin pin_p2_ctrl0{map_p2_ctrl0.scu_port, map_p2_ctrl0.scu_pin}; // SCU: PE_3
|
||||
constexpr GPIO p2_ctrl0{pin_p2_ctrl0, map_p2_ctrl0.gpio_port, map_p2_ctrl0.gpio_pad, map_p2_ctrl0.gpio_mode}; // GPIO[7]3
|
||||
|
||||
constexpr Pin pin_p2_ctrl1{map_p2_ctrl1.scu_port, map_p2_ctrl1.scu_pin}; // SCU: PE_4
|
||||
constexpr GPIO p2_ctrl1{pin_p2_ctrl1, map_p2_ctrl1.gpio_port, map_p2_ctrl1.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[7]4
|
||||
constexpr Pin pin_p2_ctrl1{map_p2_ctrl1.scu_port, map_p2_ctrl1.scu_pin}; // SCU: PE_4
|
||||
constexpr GPIO p2_ctrl1{pin_p2_ctrl1, map_p2_ctrl1.gpio_port, map_p2_ctrl1.gpio_pad, map_p2_ctrl1.gpio_mode}; // GPIO[7]4
|
||||
|
||||
// Trigger pins
|
||||
constexpr Pin trigger_out_pin{map_trigger_out.scu_port, map_trigger_out.scu_pin}; // SCU: P2_6
|
||||
constexpr GPIO trigger_out{trigger_out_pin, map_trigger_out.gpio_port, map_trigger_out.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[5]6
|
||||
constexpr Pin trigger_out_pin{map_trigger_out.scu_port, map_trigger_out.scu_pin}; // SCU: P2_6
|
||||
constexpr GPIO trigger_out{trigger_out_pin, map_trigger_out.gpio_port, map_trigger_out.gpio_pad, map_trigger_out.gpio_mode}; // GPIO[5]6
|
||||
|
||||
constexpr Pin trigger_in_pin{map_trigger_in.scu_port, map_trigger_in.scu_pin}; // SCU: PD_12
|
||||
constexpr GPIO trigger_in{trigger_in_pin, map_trigger_in.gpio_port, map_trigger_in.gpio_pad, PAL_MODE_INPUT}; // GPIO[6]26
|
||||
constexpr Pin trigger_in_pin{map_trigger_in.scu_port, map_trigger_in.scu_pin}; // SCU: PD_12
|
||||
constexpr GPIO trigger_in{trigger_in_pin, map_trigger_in.gpio_port, map_trigger_in.gpio_pad, map_trigger_in.gpio_mode}; // GPIO[6]26
|
||||
|
||||
// Clock input control
|
||||
constexpr Pin pin_clkin_ctrl{map_clkin_ctrl.scu_port, map_clkin_ctrl.scu_pin}; // SCU: P1_20
|
||||
constexpr GPIO clkin_ctrl{pin_clkin_ctrl, map_clkin_ctrl.gpio_port, map_clkin_ctrl.gpio_pad, map_clkin_ctrl.gpio_mode}; // GPIO[0]15
|
||||
|
||||
// RF507x
|
||||
constexpr Pin pin_rf5072_mix_en{map_rf5072_mix_en.scu_port, map_rf5072_mix_en.scu_pin};
|
||||
constexpr GPIO rf5072_mix_en{pin_rf5072_mix_en, map_rf5072_mix_en.gpio_port, map_rf5072_mix_en.gpio_pad, 0};
|
||||
constexpr Pin pin_rf5072_mix_en{map_rf5072_mix_en.scu_port, map_rf5072_mix_en.scu_pin}; // SCU: P9_0
|
||||
constexpr GPIO rf5072_mix_en{pin_rf5072_mix_en, map_rf5072_mix_en.gpio_port, map_rf5072_mix_en.gpio_pad, map_rf5072_mix_en.gpio_mode}; // GPIO[4]12
|
||||
|
||||
// Anti-Aliasing filter
|
||||
constexpr Pin pin_aa_en{map_aa_en.scu_port, map_aa_en.scu_pin};
|
||||
constexpr GPIO aa_en{pin_aa_en, map_aa_en.gpio_port, map_aa_en.gpio_pad, 0};
|
||||
constexpr Pin pin_aa_en{map_aa_en.scu_port, map_aa_en.scu_pin}; // SCU: P1_14
|
||||
constexpr GPIO aa_en{pin_aa_en, map_aa_en.gpio_port, map_aa_en.gpio_pad, map_aa_en.gpio_mode}; // GPIO[1]7
|
||||
|
||||
constexpr Pin pin_en_1v2{map_en_1v2.scu_port, map_en_1v2.scu_pin}; // SCU: P8_7
|
||||
constexpr GPIO en_1v2{pin_en_1v2, map_en_1v2.gpio_port, map_en_1v2.gpio_pad, map_en_1v2.gpio_mode}; // GPIO[4]7
|
||||
|
||||
constexpr Pin pin_VAA_en{map_VAA_en.scu_port, map_VAA_en.scu_pin}; // SCU: P8_1
|
||||
constexpr GPIO VAA_en{pin_VAA_en, map_VAA_en.gpio_port, map_VAA_en.gpio_pad, map_VAA_en.gpio_mode, Polarity::ActiveLow}; // GPIO[4]1
|
||||
|
||||
constexpr Pin pin_led_usb{map_led_usb.scu_port, map_led_usb.scu_pin}; // SCU: P4_1
|
||||
constexpr GPIO led_usb{pin_led_usb, map_led_usb.gpio_port, map_led_usb.gpio_pad, map_led_usb.gpio_mode, Polarity::ActiveLow}; // GPIO[2]1
|
||||
|
||||
constexpr Pin pin_led_rx{map_led_rx.scu_port, map_led_rx.scu_pin}; // SCU: P4_2
|
||||
constexpr GPIO led_rx{pin_led_rx, map_led_rx.gpio_port, map_led_rx.gpio_pad, map_led_rx.gpio_mode, Polarity::ActiveLow}; // GPIO[2]2
|
||||
|
||||
constexpr Pin pin_led_tx{map_led_tx.scu_port, map_led_tx.scu_pin}; // SCU: P6_12
|
||||
constexpr GPIO led_tx{pin_led_tx, map_led_tx.gpio_port, map_led_tx.gpio_pad, map_led_tx.gpio_mode, Polarity::ActiveLow}; // GPIO[2]8
|
||||
|
||||
constexpr Pin pin_led_mcu{map_led_mcu.scu_port, map_led_mcu.scu_pin}; // SCU: P8_6
|
||||
constexpr GPIO led_mcu{pin_led_mcu, map_led_mcu.gpio_port, map_led_mcu.gpio_pad, map_led_mcu.gpio_mode, Polarity::ActiveLow}; // GPIO[4]6
|
||||
#else
|
||||
constexpr Pin pin_sgpio_13{map_sgpio_13.scu_port, map_sgpio_13.scu_pin}; // SCU: P4_8
|
||||
constexpr GPIO sgpio_13{pin_sgpio_13, map_sgpio_13.gpio_port, map_sgpio_13.gpio_pad, map_sgpio_13.gpio_mode}; // GPIO[5]12
|
||||
|
||||
constexpr Pin pin_og_1v8_en{map_og_1v8_en.scu_port, map_og_1v8_en.scu_pin}; // SCU: P6_10
|
||||
constexpr GPIO og_1v8_en{pin_og_1v8_en, map_og_1v8_en.gpio_port, map_og_1v8_en.gpio_pad, map_og_1v8_en.gpio_mode}; // GPIO[3]6
|
||||
|
||||
constexpr Pin pin_r9_1v8_en{map_r9_1v8_en.scu_port, map_r9_1v8_en.scu_pin}; // SCU: P5_0
|
||||
constexpr GPIO r9_1v8_en{pin_r9_1v8_en, map_r9_1v8_en.gpio_port, map_r9_1v8_en.gpio_pad, map_r9_1v8_en.gpio_mode}; // GPIO[2]9
|
||||
|
||||
constexpr Pin pin_og_VAA_en{map_og_VAA_en.scu_port, map_og_VAA_en.scu_pin}; // SCU: P5_0
|
||||
constexpr GPIO og_VAA_en{pin_og_VAA_en, map_og_VAA_en.gpio_port, map_og_VAA_en.gpio_pad, map_og_VAA_en.gpio_mode, Polarity::ActiveLow}; // GPIO[2]9
|
||||
|
||||
constexpr Pin pin_r9_VAA_en{map_r9_VAA_en.scu_port, map_r9_VAA_en.scu_pin}; // SCU: P6_10
|
||||
constexpr GPIO r9_VAA_en{pin_r9_VAA_en, map_r9_VAA_en.gpio_port, map_r9_VAA_en.gpio_pad, map_r9_VAA_en.gpio_mode, Polarity::ActiveLow}; // GPIO[3]6
|
||||
|
||||
constexpr Pin pin_led_usb{map_led_usb.scu_port, map_led_usb.scu_pin}; // SCU: P4_1
|
||||
constexpr GPIO led_usb{pin_led_usb, map_led_usb.gpio_port, map_led_usb.gpio_pad, map_led_usb.gpio_mode}; // GPIO[2]1
|
||||
|
||||
constexpr Pin pin_led_rx{map_led_rx.scu_port, map_led_rx.scu_pin}; // SCU: P4_2
|
||||
constexpr GPIO led_rx{pin_led_rx, map_led_rx.gpio_port, map_led_rx.gpio_pad, map_led_rx.gpio_mode}; // GPIO[2]2
|
||||
|
||||
constexpr Pin pin_led_tx{map_led_tx.scu_port, map_led_tx.scu_pin}; // SCU: P6_12
|
||||
constexpr GPIO led_tx{pin_led_tx, map_led_tx.gpio_port, map_led_tx.gpio_pad, map_led_tx.gpio_mode}; // GPIO[2]8
|
||||
|
||||
static const motocon_pwm_resources_t motocon_pwm_resources = {
|
||||
.base = {.clk = &LPC_CGU->BASE_APB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 1)},
|
||||
.branch = {.cfg = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG, .stat = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_STAT},
|
||||
.reset = {.output_index = 38},
|
||||
};
|
||||
|
||||
static const scu_setup_t pin_setup_vaa_enablex_pwm = {5, 0, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
|
||||
static const scu_setup_t pin_setup_vaa_enablex_gpio_og = {map_og_VAA_en.scu_port, map_og_VAA_en.scu_pin, scu_config_normal_drive_t{.mode = map_og_VAA_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
|
||||
static const scu_setup_t pin_setup_vaa_enablex_gpio_r9 = {map_r9_VAA_en.scu_port, map_r9_VAA_en.scu_pin, scu_config_normal_drive_t{.mode = map_r9_VAA_en.gpio_mode, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
|
||||
|
||||
} // namespace gpio_control
|
||||
#endif
|
||||
|
||||
// SGPIO
|
||||
constexpr Pin pin_sgpio_0{map_sgpio_0.scu_port, map_sgpio_0.scu_pin}; // SCU: P0_0
|
||||
constexpr GPIO sgpio_0{pin_sgpio_0, map_sgpio_0.gpio_port, map_sgpio_0.gpio_pad, map_sgpio_0.gpio_mode}; // GPIO[0]0
|
||||
|
||||
constexpr Pin pin_sgpio_1{map_sgpio_1.scu_port, map_sgpio_1.scu_pin}; // SCU: P0_1
|
||||
constexpr GPIO sgpio_1{pin_sgpio_1, map_sgpio_1.gpio_port, map_sgpio_1.gpio_pad, map_sgpio_1.gpio_mode}; // GPIO[0]1
|
||||
|
||||
constexpr Pin pin_sgpio_2{map_sgpio_2.scu_port, map_sgpio_2.scu_pin}; // SCU: P1_15
|
||||
constexpr GPIO sgpio_2{pin_sgpio_2, map_sgpio_2.gpio_port, map_sgpio_2.gpio_pad, map_sgpio_2.gpio_mode}; // GPIO[0]2
|
||||
|
||||
constexpr Pin pin_sgpio_3{map_sgpio_3.scu_port, map_sgpio_3.scu_pin}; // SCU: P1_16
|
||||
constexpr GPIO sgpio_3{pin_sgpio_3, map_sgpio_3.gpio_port, map_sgpio_3.gpio_pad, map_sgpio_3.gpio_mode}; // GPIO[0]3
|
||||
|
||||
constexpr Pin pin_sgpio_4{map_sgpio_4.scu_port, map_sgpio_4.scu_pin}; // SCU: P6_3, PRALINE: P9_4
|
||||
constexpr GPIO sgpio_4{pin_sgpio_4, map_sgpio_4.gpio_port, map_sgpio_4.gpio_pad, map_sgpio_4.gpio_mode}; // GPIO[6]3 PRALINE: GPIO[5]17
|
||||
|
||||
constexpr Pin pin_sgpio_5{map_sgpio_5.scu_port, map_sgpio_5.scu_pin}; // SCU: P6_6
|
||||
constexpr GPIO sgpio_5{pin_sgpio_5, map_sgpio_5.gpio_port, map_sgpio_5.gpio_pad, map_sgpio_5.gpio_mode}; // GPIO[0]5
|
||||
|
||||
constexpr Pin pin_sgpio_6{map_sgpio_6.scu_port, map_sgpio_6.scu_pin}; // SCU: P2_2
|
||||
constexpr GPIO sgpio_6{pin_sgpio_6, map_sgpio_6.gpio_port, map_sgpio_6.gpio_pad, map_sgpio_6.gpio_mode}; // GPIO[5]2
|
||||
|
||||
constexpr Pin pin_sgpio_7{map_sgpio_7.scu_port, map_sgpio_7.scu_pin}; // SCU: P1_0
|
||||
constexpr GPIO sgpio_7{pin_sgpio_7, map_sgpio_7.gpio_port, map_sgpio_7.gpio_pad, map_sgpio_7.gpio_mode}; // GPIO[0]4
|
||||
|
||||
constexpr Pin pin_sgpio_8{map_sgpio_8.scu_port, map_sgpio_8.scu_pin}; // SCU: P9_6, PRALINE: P8_0
|
||||
constexpr GPIO sgpio_8{pin_sgpio_8, map_sgpio_8.gpio_port, map_sgpio_8.gpio_pad, map_sgpio_8.gpio_mode}; // GPIO[4]11, PRALINE: GPIO[4]0
|
||||
|
||||
constexpr Pin pin_sgpio_9{map_sgpio_9.scu_port, map_sgpio_9.scu_pin}; // SCU: P4_3, PRALINE: P9_3
|
||||
constexpr GPIO sgpio_9{pin_sgpio_9, map_sgpio_9.gpio_port, map_sgpio_9.gpio_pad, map_sgpio_9.gpio_mode}; // GPIO[2]3, PRALINE: GPIO[4]12
|
||||
|
||||
constexpr Pin pin_sgpio_10{map_sgpio_10.scu_port, map_sgpio_10.scu_pin}; // SCU: P1_14, PRALINE: P8_2
|
||||
constexpr GPIO sgpio_10{pin_sgpio_10, map_sgpio_10.gpio_port, map_sgpio_10.gpio_pad, map_sgpio_10.gpio_mode}; // GPIO[1]7, PRALINE: GPIO[4]2
|
||||
|
||||
constexpr Pin pin_sgpio_11{map_sgpio_11.scu_port, map_sgpio_11.scu_pin}; // SCU: P1_17
|
||||
constexpr GPIO sgpio_11{pin_sgpio_11, map_sgpio_11.gpio_port, map_sgpio_11.gpio_pad, map_sgpio_11.gpio_mode}; // GPIO[0]17
|
||||
|
||||
constexpr Pin pin_sgpio_12{map_sgpio_12.scu_port, map_sgpio_12.scu_pin}; // SCU: P1_18
|
||||
constexpr GPIO sgpio_12{pin_sgpio_12, map_sgpio_12.gpio_port, map_sgpio_12.gpio_pad, map_sgpio_12.gpio_mode}; // GPIO[0]13
|
||||
|
||||
constexpr Pin pin_vregmode{map_vregmode.scu_port, map_vregmode.scu_pin}; // SCU: P6_11, PRALINE: P4_9
|
||||
constexpr GPIO vregmode{pin_vregmode, map_vregmode.gpio_port, map_vregmode.gpio_pad, map_vregmode.gpio_mode}; // GPIO[3]7, PRALINE: GPIO[5]13
|
||||
} // namespace gpio_control
|
||||
|
||||
namespace power_control {
|
||||
|
||||
void vaa_power_on(void);
|
||||
@@ -376,16 +555,6 @@ void aux_power_off(void);
|
||||
void core_power_on(void);
|
||||
void core_power_off(void);
|
||||
|
||||
static const motocon_pwm_resources_t motocon_pwm_resources = {
|
||||
.base = {.clk = &LPC_CGU->BASE_APB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 1)},
|
||||
.branch = {.cfg = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG, .stat = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_STAT},
|
||||
.reset = {.output_index = 38},
|
||||
};
|
||||
|
||||
static const scu_setup_t pin_setup_vaa_enablex_pwm = {5, 0, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
|
||||
static const scu_setup_t pin_setup_vaa_enablex_gpio_og = {5, 0, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
|
||||
static const scu_setup_t pin_setup_vaa_enablex_gpio_r9 = {6, 10, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
|
||||
|
||||
} // namespace power_control
|
||||
|
||||
#endif /*__GPIO_H__*/
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#define __HACKRF_GPIO_H__
|
||||
|
||||
#include "pins.hpp"
|
||||
#include "led.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -34,19 +33,11 @@ namespace one {
|
||||
|
||||
/* GPIO */
|
||||
|
||||
constexpr GPIO gpio_led_usb = gpio[GPIO2_1];
|
||||
constexpr GPIO gpio_led_rx = gpio[GPIO2_2];
|
||||
constexpr GPIO gpio_led_tx = gpio[GPIO2_8];
|
||||
|
||||
constexpr GPIO gpio_og_1v8_enable = gpio[GPIO3_6];
|
||||
constexpr GPIO gpio_r9_1v8_enable = gpio[GPIO2_9];
|
||||
constexpr GPIO gpio_vregmode = gpio[GPIO3_7];
|
||||
|
||||
constexpr GPIO gpio_rx_mix_bp = gpio[GPIO2_12];
|
||||
constexpr GPIO gpio_tx_mix_bp = gpio[GPIO2_11];
|
||||
#ifdef PRALINE
|
||||
constexpr GPIO gpio_mix_bypass = gpio[GPIO3_2]; // P6_3: PRALINE RF path mixer bypass inverted
|
||||
constexpr GPIO gpio_mix_en_n_r1_0 = gpio[GPIO5_6]; // P2_6: R1.0 board mixer bypass
|
||||
constexpr GPIO gpio_mix_bypass = gpio[GPIO3_2]; // P6_3: PRALINE RF path mixer bypass inverted
|
||||
// constexpr GPIO gpio_mix_en_n_r1_0 = gpio[GPIO5_6]; // P2_6: R1.0 board mixer bypass
|
||||
#else
|
||||
constexpr GPIO gpio_mix_bypass = gpio[GPIO5_16];
|
||||
#endif
|
||||
@@ -90,11 +81,11 @@ constexpr GPIO gpio_max283x_select = gpio[GPIO0_15];
|
||||
|
||||
#ifdef PRALINE
|
||||
// PRALINE uses MAX2831 transceiver with different control pins
|
||||
constexpr GPIO gpio_max283x_enable = gpio[GPIO7_1]; // MAX2831 ENABLE (PE_1)
|
||||
constexpr GPIO gpio_max2831_enable = gpio[GPIO7_1]; // Alias
|
||||
constexpr GPIO gpio_max283x_enable = gpio[GPIO7_1]; // MAX2831 ENABLE (PE_1)
|
||||
// constexpr GPIO gpio_max2831_enable = gpio[GPIO7_1]; // Alias
|
||||
constexpr GPIO gpio_max2831_rx_enable = gpio[GPIO7_2]; // MAX2831 RX_ENABLE (PE_2)
|
||||
constexpr GPIO gpio_max2831_rxhp = gpio[GPIO6_29]; // MAX2831 RXHP (PD_15)
|
||||
constexpr GPIO gpio_max2831_ld = gpio[GPIO4_11]; // MAX2831 Lock Detect (P9_6)
|
||||
// constexpr GPIO gpio_max2831_rxhp = gpio[GPIO6_29]; // MAX2831 RXHP (PD_15)
|
||||
constexpr GPIO gpio_max2831_ld = gpio[GPIO4_11]; // MAX2831 Lock Detect (P9_6)
|
||||
// Legacy aliases for code compatibility
|
||||
constexpr GPIO gpio_max2837_rxenable = gpio[GPIO7_2];
|
||||
constexpr GPIO gpio_max2837_txenable = gpio[GPIO7_2]; // MAX2831 uses single RX/TX control
|
||||
@@ -108,7 +99,6 @@ constexpr GPIO gpio_max2839_rxtx = gpio[GPIO2_5];
|
||||
|
||||
#ifdef PRALINE
|
||||
constexpr GPIO gpio_max5864_select = gpio[GPIO6_30]; // PD_16: PRALINE MAX5864 CS
|
||||
constexpr GPIO gpio_fpga_select = gpio[GPIO2_10]; // FPGA SPI CS (P5_1)
|
||||
#else
|
||||
constexpr GPIO gpio_max5864_select = gpio[GPIO2_7];
|
||||
#endif
|
||||
@@ -117,38 +107,15 @@ constexpr GPIO gpio_q_invert = gpio[GPIO0_13];
|
||||
|
||||
#ifdef PRALINE
|
||||
// PRALINE power control
|
||||
constexpr GPIO gpio_vaa_disable = gpio[GPIO4_1]; // VAA disable (P8_1)
|
||||
constexpr GPIO gpio_1v2_enable = gpio[GPIO4_7]; // 1V2 enable (P8_7)
|
||||
constexpr GPIO gpio_3v3aux_disable = gpio[GPIO5_15]; // 3V3 aux disable (P6_7)
|
||||
constexpr GPIO gpio_3v3aux_oc = gpio[GPIO1_11]; // 3.3V aux overcurrent input (P2_11)
|
||||
constexpr GPIO gpio_vbus_enable = gpio[GPIO4_4]; // VBUS_IN_EN P8_4 ->LOW
|
||||
constexpr GPIO gpio_vin_enable = gpio[GPIO4_5]; // VIN_IN_EN P8_5 ->HIGH
|
||||
constexpr GPIO gpio_vaa_disable = gpio[GPIO4_1]; // VAA disable (P8_1)
|
||||
|
||||
// PRALINE RF path control
|
||||
constexpr GPIO gpio_tx_enable = gpio[GPIO3_4]; // TX enable (P6_5)
|
||||
// constexpr GPIO gpio_mix_enable_n = gpio[GPIO3_2]; // Mixer enable inverted (P6_3)
|
||||
constexpr GPIO gpio_tx_enable = gpio[GPIO3_4]; // TX enable (P6_5)
|
||||
constexpr GPIO gpio_lpf_enable = gpio[GPIO4_8]; // LPF enable (PA_1)
|
||||
constexpr GPIO gpio_rf_amp_enable = gpio[GPIO4_9]; // RF amp enable (PA_2)
|
||||
constexpr GPIO gpio_ant_bias_disable = gpio[GPIO1_12]; // Antenna bias disable (P2_12)
|
||||
constexpr GPIO gpio_bias_oc = gpio[GPIO3_7]; // Bias tee overcurrent input (P6_11)
|
||||
|
||||
// PRALINE mixer lock detect (gpio_max2831_ld defined above at line 93)
|
||||
constexpr GPIO gpio_rffc5072_ld = gpio[GPIO6_25]; // Mixer lock detect (PD_11)
|
||||
|
||||
// PRALINE LED4
|
||||
constexpr GPIO gpio_led4 = gpio[GPIO4_6]; // LED4 (P8_6)
|
||||
|
||||
// PRALINE dual port control
|
||||
constexpr GPIO gpio_p1_ctrl0 = gpio[GPIO0_14]; // P1 control 0 (P2_10)
|
||||
constexpr GPIO gpio_p1_ctrl1 = gpio[GPIO5_16]; // P1 control 1 (P6_8)
|
||||
constexpr GPIO gpio_p1_ctrl2 = gpio[GPIO3_5]; // P1 control 2 (P6_9)
|
||||
constexpr GPIO gpio_p2_ctrl0 = gpio[GPIO7_3]; // P2 control 0 (PE_3)
|
||||
constexpr GPIO gpio_p2_ctrl1 = gpio[GPIO7_4]; // P2 control 1 (PE_4)
|
||||
constexpr GPIO gpio_clkin_ctrl = gpio[GPIO0_15]; // CLKIN control (P1_20)
|
||||
|
||||
// PRALINE trigger/sync I/O
|
||||
constexpr GPIO gpio_trigger_in = gpio[GPIO6_26]; // Trigger input (PD_12)
|
||||
constexpr GPIO gpio_trigger_out = gpio[GPIO5_6]; // Trigger output (P2_6)
|
||||
constexpr GPIO gpio_pps_out = gpio[GPIO5_5]; // PPS output (P2_5)
|
||||
// constexpr GPIO gpio_pps_out = gpio[GPIO5_5]; // PPS output (P2_5)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -170,12 +137,6 @@ constexpr GPIO gpio_r9_clkout_en = gpio[GPIO0_9];
|
||||
constexpr GPIO gpio_r9_mcu_clk_en = gpio[GPIO0_8];
|
||||
constexpr GPIO gpio_r9_not_ant_pwr = gpio[GPIO2_4];
|
||||
|
||||
/* LEDs */
|
||||
|
||||
constexpr LED led_usb{gpio_led_usb};
|
||||
constexpr LED led_rx{gpio_led_rx};
|
||||
constexpr LED led_tx{gpio_led_tx};
|
||||
|
||||
} /* namespace one */
|
||||
} /* namespace hackrf */
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* 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 __LED_H__
|
||||
#define __LED_H__
|
||||
|
||||
#include "gpio.hpp"
|
||||
|
||||
struct LED {
|
||||
constexpr LED(const GPIO gpio)
|
||||
: _gpio{gpio} {
|
||||
}
|
||||
|
||||
void setup() const {
|
||||
#ifdef PRALINE
|
||||
// No-op: GPIO direction and initial OFF state are already
|
||||
// enforced globally at boot by pal_default_config in board.cpp.
|
||||
#else
|
||||
_gpio.clear();
|
||||
_gpio.output();
|
||||
_gpio.configure();
|
||||
#endif
|
||||
}
|
||||
|
||||
void on() const {
|
||||
#ifdef PRALINE
|
||||
_gpio.clear(); /* LOW = ON for PRALINE */
|
||||
#else
|
||||
_gpio.set();
|
||||
#endif
|
||||
}
|
||||
|
||||
void off() const {
|
||||
#ifdef PRALINE
|
||||
_gpio.set(); /* HIGH = OFF for PRALINE */
|
||||
#else
|
||||
_gpio.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void toggle() const {
|
||||
_gpio.toggle();
|
||||
}
|
||||
|
||||
void write(const bool value) const {
|
||||
#ifdef PRALINE
|
||||
_gpio.write(!value); /* Invert for PRALINE */
|
||||
#else
|
||||
_gpio.write(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
const GPIO _gpio;
|
||||
};
|
||||
|
||||
#endif /*__LED_H__*/
|
||||
@@ -23,9 +23,9 @@
|
||||
#ifndef __SINE_TABLE_I8_H__
|
||||
#define __SINE_TABLE_I8_H__
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
static const int8_t sine_table_i8[256] = {
|
||||
static constexpr int8_t sine_table_i8[256] = {
|
||||
0, 2, 5, 8, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45,
|
||||
48, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 83, 85, 87,
|
||||
90, 92, 94, 96, 98, 100, 102, 104, 105, 107, 109, 110, 112, 113, 115, 116,
|
||||
|
||||
+16
-16
@@ -26,6 +26,9 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
using Coord = int16_t;
|
||||
using Dim = int16_t;
|
||||
|
||||
// Positioning helpers PER CHARACTERS (8*16)
|
||||
// EACH parameters must be used az CHAR position, not PX coordinates. So If you wanna use the 8,16 coordinates (that is the second character in X and second character in Y you must use UI_POS_X(1) UI_POS_Y(1) (since we count from 0)
|
||||
|
||||
@@ -36,31 +39,31 @@ namespace ui {
|
||||
// default font width
|
||||
#define UI_POS_DEFAULT_WIDTH 8
|
||||
// px position of the linenum-th character (Y)
|
||||
#define UI_POS_Y(linenum) ((int)((linenum) * UI_POS_DEFAULT_HEIGHT))
|
||||
#define UI_POS_Y(linenum) ((Coord)((linenum) * UI_POS_DEFAULT_HEIGHT))
|
||||
// px position of the linenum-th character from the bottom of the screen (Y) (please calculate the +1 line top-bar to it too if that is visible!)
|
||||
#define UI_POS_Y_BOTTOM(linenum) ((int)(screen_height - (linenum) * UI_POS_DEFAULT_HEIGHT))
|
||||
#define UI_POS_Y_BOTTOM(linenum) ((Coord)(screen_height - (int)((linenum) * UI_POS_DEFAULT_HEIGHT)))
|
||||
// px position of the linenum-th character from the left of the screen (X)
|
||||
#define UI_POS_X(charnum) ((int)((charnum) * UI_POS_DEFAULT_WIDTH))
|
||||
#define UI_POS_X(charnum) ((Coord)((charnum) * UI_POS_DEFAULT_WIDTH))
|
||||
// px position of the linenum-th character from the right of the screen (X)
|
||||
#define UI_POS_X_RIGHT(charnum) ((int)(screen_width - ((charnum) * UI_POS_DEFAULT_WIDTH)))
|
||||
#define UI_POS_X_RIGHT(charnum) ((Coord)(screen_width - (int)((charnum) * UI_POS_DEFAULT_WIDTH)))
|
||||
// px position of the left character from the center of the screen (X) (for N character wide string)
|
||||
#define UI_POS_X_CENTER(charnum) ((int)((screen_width / 2) - ((charnum) * UI_POS_DEFAULT_WIDTH / 2)))
|
||||
// px position of the currcol in a table with colnum number of columns, where one coloumn is charnum characters wide maximum
|
||||
#define UI_POS_X_TABLE(colnum, currcol) ((currcol) * (screen_width / (colnum)))
|
||||
#define UI_POS_X_CENTER(charnum) ((Coord)((screen_width / 2) - (int)((charnum) * UI_POS_DEFAULT_WIDTH / 2)))
|
||||
// px position of the currcol in a table with colnum number of columns, where one column is charnum characters wide maximum
|
||||
#define UI_POS_X_TABLE(colnum, currcol) ((Coord)((currcol) * (screen_width / (colnum))))
|
||||
// px width of N characters
|
||||
#define UI_POS_WIDTH(charnum) ((int)((charnum) * UI_POS_DEFAULT_WIDTH))
|
||||
#define UI_POS_WIDTH(charnum) ((Dim)((charnum) * UI_POS_DEFAULT_WIDTH))
|
||||
// px width of the screen
|
||||
#define UI_POS_MAXWIDTH (screen_width)
|
||||
// px height of N line
|
||||
#define UI_POS_HEIGHT(linecount) ((int)((linecount) * UI_POS_DEFAULT_HEIGHT))
|
||||
#define UI_POS_HEIGHT(linecount) ((Dim)((linecount) * UI_POS_DEFAULT_HEIGHT))
|
||||
// px height of the screen's percent
|
||||
#define UI_POS_HEIGHT_PERCENT(percent) ((int)(screen_height * (percent) / 100))
|
||||
#define UI_POS_HEIGHT_PERCENT(percent) ((Dim)(screen_height * (percent) / 100))
|
||||
// remaining px from the linenum-th line to the bottom of the screen. (please calculate the +1 line top-bar to it too if that is visible!)
|
||||
#define UI_POS_HEIGHT_REMAINING(linenum) ((int)(screen_height - ((linenum) * UI_POS_DEFAULT_HEIGHT)))
|
||||
#define UI_POS_HEIGHT_REMAINING(linenum) ((Dim)(screen_height - (int)((linenum) * UI_POS_DEFAULT_HEIGHT)))
|
||||
// remaining px from the charnum-th character to the right of the screen
|
||||
#define UI_POS_WIDTH_REMAINING(charnum) ((int)(screen_width - ((charnum) * UI_POS_DEFAULT_WIDTH)))
|
||||
#define UI_POS_WIDTH_REMAINING(charnum) ((Dim)(screen_width - (int)((charnum) * UI_POS_DEFAULT_WIDTH)))
|
||||
// px width of the screen's percent
|
||||
#define UI_POS_WIDTH_PERCENT(percent) ((int)(screen_width * (percent) / 100))
|
||||
#define UI_POS_WIDTH_PERCENT(percent) ((Dim)(screen_width * (percent) / 100))
|
||||
// px width of the screen
|
||||
#define UI_POS_MAXHEIGHT (screen_height)
|
||||
|
||||
@@ -85,9 +88,6 @@ namespace ui {
|
||||
|
||||
#define DEG_TO_RAD(d) (d * (2 * pi) / 360.0)
|
||||
|
||||
using Coord = int16_t;
|
||||
using Dim = int16_t;
|
||||
|
||||
extern uint16_t screen_width;
|
||||
extern uint16_t screen_height;
|
||||
|
||||
|
||||
@@ -206,7 +206,11 @@ void Widget::set_style(const Style* new_style) {
|
||||
}
|
||||
|
||||
const Style& Widget::style() const {
|
||||
return style_ ? *style_ : parent()->style();
|
||||
for (const Widget* curr = this; curr; curr = curr->parent()) {
|
||||
if (curr->style_) return *curr->style_;
|
||||
}
|
||||
// default style should always be set by SystemView
|
||||
return *style_;
|
||||
}
|
||||
|
||||
void Widget::drawn(bool v) {
|
||||
|
||||
@@ -201,15 +201,11 @@ void Widget::set_style(const Style* new_style) {
|
||||
}
|
||||
|
||||
const Style& Widget::style() const {
|
||||
if (style_ != nullptr)
|
||||
return *style_;
|
||||
else {
|
||||
auto p = parent();
|
||||
if (p == nullptr)
|
||||
// TODO: debug
|
||||
while (true);
|
||||
return p->style();
|
||||
for (const Widget* curr = this; curr; curr = curr->parent()) {
|
||||
if (curr->style_) return *curr->style_;
|
||||
}
|
||||
// default style should always be set by SystemView
|
||||
return *style_;
|
||||
}
|
||||
|
||||
void Widget::drawn(bool v) {
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
# external app address ranges below must match those in linker file "external.ld"
|
||||
maximum_application_size = 32*1024
|
||||
external_apps_address_start = 0xADB00000
|
||||
external_apps_address_end = 0xAE060000
|
||||
external_apps_address_end = 0xAE090000
|
||||
|
||||
+1
-1
Submodule hackrf updated: 216949a844...ba2045a866
@@ -0,0 +1,647 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
DEFAULT_TOOLCHAIN_URL="https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/RC2.1/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2?revision=6e63531f-8cb1-40b9-bbfc-8a57cdfc01b4&la=en&hash=F761343D43A0587E8AC0925B723C04DBFB848339"
|
||||
|
||||
mbt_log() {
|
||||
printf "mbt: %s\n" "$*"
|
||||
}
|
||||
|
||||
mbt_error() {
|
||||
printf "mbt: error: %s\n" "$*" >&2
|
||||
}
|
||||
|
||||
mbt_die() {
|
||||
mbt_error "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
mbt_command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
mbt_default_jobs() {
|
||||
local jobs
|
||||
|
||||
jobs="$(getconf _NPROCESSORS_ONLN 2>/dev/null || true)"
|
||||
if [[ -z "$jobs" ]] && mbt_command_exists nproc; then
|
||||
jobs="$(nproc)"
|
||||
fi
|
||||
if [[ -z "$jobs" ]]; then
|
||||
jobs=1
|
||||
fi
|
||||
|
||||
printf "%s" "$jobs"
|
||||
}
|
||||
|
||||
mbt_detect_distro() {
|
||||
if mbt_command_exists apt-get; then
|
||||
printf "debian"
|
||||
return 0
|
||||
fi
|
||||
if mbt_command_exists pacman; then
|
||||
printf "arch"
|
||||
return 0
|
||||
fi
|
||||
printf "unknown"
|
||||
}
|
||||
|
||||
mbt_run_privileged() {
|
||||
if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then
|
||||
"$@"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! mbt_command_exists sudo; then
|
||||
mbt_die "sudo is required for dependency installation. Re-run as root or install sudo."
|
||||
fi
|
||||
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
mbt_install_deps() {
|
||||
local distro
|
||||
distro="$(mbt_detect_distro)"
|
||||
|
||||
case "$distro" in
|
||||
debian)
|
||||
mbt_log "detected Debian-like environment; installing required packages."
|
||||
mbt_run_privileged apt-get update
|
||||
mbt_run_privileged apt-get install -y --no-install-recommends \
|
||||
git tar wget dfu-util cmake make python3 bzip2 lz4 curl hackrf \
|
||||
python3-setuptools python3-yaml binutils python3-setuptools ccache ninja-build
|
||||
;;
|
||||
arch)
|
||||
mbt_log "detected Arch-like environment; installing required packages."
|
||||
mbt_run_privileged pacman -Sy --needed --noconfirm \
|
||||
git tar wget dfu-util cmake make python3 bzip2 lz4 curl hackrf \
|
||||
python-distutils-extra python-setuptools python-pip python-yaml \
|
||||
ninja ccache binutils
|
||||
;;
|
||||
*)
|
||||
mbt_die "unsupported distribution. Install dependencies manually (see wiki on github), or you can send PR to support for your distro. Detected distro: $distro"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
mbt_sync_submodules() {
|
||||
local jobs
|
||||
jobs="$(mbt_default_jobs)"
|
||||
mbt_log "syncing submodules."
|
||||
git -C "$SCRIPT_PATH" submodule update --init --recursive --jobs "$((jobs * 2))"
|
||||
}
|
||||
|
||||
mbt_enable_toolchain_env() {
|
||||
export MBT_ROOT="$SCRIPT_PATH"
|
||||
export MBT_TOOLCHAIN_DIR="${MBT_TOOLCHAIN_DIR:-$SCRIPT_PATH/armbin}"
|
||||
export MBT_TOOLCHAIN_URL="${MBT_TOOLCHAIN_URL:-$DEFAULT_TOOLCHAIN_URL}"
|
||||
export MBT_EXPECTED_GCC_VERSION="${MBT_EXPECTED_GCC_VERSION:-9.2.1}"
|
||||
|
||||
if [[ -z "${MBT_FORCE_TOOLCHAIN+x}" ]]; then
|
||||
MBT_FORCE_TOOLCHAIN="${FORCE_TOOLCHAIN:-0}"
|
||||
fi
|
||||
export MBT_FORCE_TOOLCHAIN
|
||||
|
||||
if [[ -z "${MBT_NO_TOOLCHAIN_DOWNLOAD+x}" ]]; then
|
||||
MBT_NO_TOOLCHAIN_DOWNLOAD="${NO_TOOLCHAIN_DOWNLOAD:-0}"
|
||||
fi
|
||||
export MBT_NO_TOOLCHAIN_DOWNLOAD
|
||||
export MBT_VERBOSE="${MBT_VERBOSE:-}"
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
. "$SCRIPT_PATH/scripts/toolchain/mbtenv.sh"
|
||||
}
|
||||
|
||||
mbt_use_existing_toolchain_env() {
|
||||
local repo_toolchain_bin="$SCRIPT_PATH/armbin/bin"
|
||||
|
||||
if [[ ! -d "$repo_toolchain_bin" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
case ":$PATH:" in
|
||||
*":$repo_toolchain_bin:"*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
export PATH="$repo_toolchain_bin:$PATH"
|
||||
}
|
||||
|
||||
mbt_normalize_device() {
|
||||
local raw
|
||||
raw="$(printf "%s" "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
case "$raw" in
|
||||
1|one|hackrf|hackrf-one)
|
||||
printf "hackrf-one"
|
||||
;;
|
||||
2|pro|hackrf-pro|praline)
|
||||
printf "hackrf-pro"
|
||||
;;
|
||||
3|portarf|porta-rf|porta_rf)
|
||||
printf "portarf"
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
mbt_prompt_device() {
|
||||
local choice normalized
|
||||
|
||||
cat >&2 <<'EOF'
|
||||
Select device type:
|
||||
1) HackRF One
|
||||
2) HackRF Pro (PRALINE)
|
||||
3) PortaRF
|
||||
EOF
|
||||
|
||||
while true; do
|
||||
printf "Device [1-3]: " >&2
|
||||
if ! IFS= read -r choice; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
normalized="$(mbt_normalize_device "$choice" 2>/dev/null || true)"
|
||||
if [[ -n "$normalized" ]]; then
|
||||
printf "%s" "$normalized"
|
||||
return 0
|
||||
fi
|
||||
mbt_error "invalid device selection: $choice"
|
||||
done
|
||||
}
|
||||
|
||||
mbt_print_help() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./mbt One-step build flow (installs deps, syncs submodules, downloads toolchain, asks for device, builds)
|
||||
./mbt build [options] Developer build flow
|
||||
./mbt deps Install distro dependencies only
|
||||
./mbt toolchain [--force-toolchain]
|
||||
Download/setup ARM toolchain only
|
||||
./mbt doctor Validate host setup and report gaps
|
||||
./mbt shell [options] Open a shell with toolchain exported for this session
|
||||
|
||||
Build options:
|
||||
-d, --device <name> Device: hackrf-one | hackrf-pro | portarf
|
||||
--ccache / --no-ccache Toggle USE_CCACHE (default: on)
|
||||
--with-deps / --no-deps Install Linux dependencies before build
|
||||
--with-submodule-sync Update git submodules before build (default)
|
||||
--no-submodule-sync Skip submodule sync
|
||||
--with-toolchain Ensure toolchain exists and matches expected version (default)
|
||||
--no-toolchain Skip toolchain checks/downloads and use existing PATH (prepends ./armbin/bin if present)
|
||||
--force-toolchain Re-download and reinstall toolchain
|
||||
-B, --build-dir <path> Build directory (default: ./build)
|
||||
-G, --generator <name> CMake generator (default: Ninja)
|
||||
-j, --jobs <n> Build parallelism (default: host CPU count)
|
||||
--target <name> Build a specific target
|
||||
--clean Remove build directory, run libopencm3 clean, and exit
|
||||
--cmake-arg <arg> Extra CMake configure arg (repeatable)
|
||||
--build-arg <arg> Extra cmake --build arg (repeatable)
|
||||
-y, --non-interactive Fail instead of prompting when required input is missing
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
./mbt
|
||||
./mbt build --device hackrf-one
|
||||
./mbt build --device hackrf-pro --no-submodule-sync
|
||||
./mbt build --device portarf --no-toolchain --no-deps
|
||||
./mbt build --device hackrf-one --cmake-arg=-DVERSION_STRING=my-build
|
||||
EOF
|
||||
}
|
||||
|
||||
mbt_doctor() {
|
||||
local distro missing=0 toolchain_cc toolchain_version cmd
|
||||
local -a required_cmds
|
||||
|
||||
distro="$(mbt_detect_distro)"
|
||||
mbt_log "doctor report for $SCRIPT_PATH"
|
||||
mbt_log "distro family: $distro"
|
||||
|
||||
required_cmds=(git tar wget dfu-util cmake python3 bzip2 lz4 curl ccache ninja)
|
||||
if [[ "$distro" == "arch" ]]; then
|
||||
required_cmds+=(make)
|
||||
fi
|
||||
|
||||
for cmd in "${required_cmds[@]}"; do
|
||||
if mbt_command_exists "$cmd"; then
|
||||
printf " [ok] %s\n" "$cmd"
|
||||
else
|
||||
printf " [missing] %s\n" "$cmd"
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
|
||||
toolchain_cc="$SCRIPT_PATH/armbin/bin/arm-none-eabi-gcc"
|
||||
if [[ -x "$toolchain_cc" ]]; then
|
||||
toolchain_version="$("$toolchain_cc" -dumpfullversion 2>/dev/null || "$toolchain_cc" -dumpversion 2>/dev/null || true)"
|
||||
printf " [ok] arm-none-eabi-gcc %s (%s)\n" "$toolchain_version" "$toolchain_cc"
|
||||
if [[ "$toolchain_version" != "9.2.1" ]]; then
|
||||
printf " [warn] expected arm-none-eabi-gcc 9.2.1\n"
|
||||
fi
|
||||
else
|
||||
if mbt_command_exists arm-none-eabi-gcc; then
|
||||
toolchain_cc="arm-none-eabi-gcc"
|
||||
toolchain_version="$("$toolchain_cc" -dumpfullversion 2>/dev/null || "$toolchain_cc" -dumpversion 2>/dev/null || true)"
|
||||
printf " [ok] arm-none-eabi-gcc %s (%s)\n" "$toolchain_version" "$toolchain_cc"
|
||||
if [[ "$toolchain_version" != "9.2.1" ]]; then
|
||||
printf " [warn] expected arm-none-eabi-gcc 9.2.1\n"
|
||||
fi
|
||||
else
|
||||
printf " [missing] %s\n" "$toolchain_cc"
|
||||
missing=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if git -C "$SCRIPT_PATH" submodule status --recursive | grep -q '^-'; then
|
||||
printf " [warn] some submodules are not initialized (run ./mbt build --with-submodule-sync --device hackrf-one)\n"
|
||||
else
|
||||
printf " [ok] submodules initialized\n"
|
||||
fi
|
||||
|
||||
if [[ "$missing" -ne 0 ]]; then
|
||||
mbt_error "doctor found missing prerequisites."
|
||||
return 1
|
||||
fi
|
||||
|
||||
mbt_log "doctor passed."
|
||||
return 0
|
||||
}
|
||||
|
||||
mbt_validate_jobs() {
|
||||
[[ "$1" =~ ^[0-9]+$ ]] && [[ "$1" -gt 0 ]]
|
||||
}
|
||||
|
||||
mbt_detect_cached_device() {
|
||||
local build_dir="$1"
|
||||
local cache_file="$build_dir/CMakeCache.txt"
|
||||
local board flash_limit
|
||||
|
||||
if [[ ! -f "$cache_file" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
board="$(grep -E '^BOARD:' "$cache_file" | head -n 1 | cut -d= -f2- || true)"
|
||||
flash_limit="$(grep -E '^FLASH_MB_LIMIT_SIZE:' "$cache_file" | head -n 1 | cut -d= -f2- || true)"
|
||||
|
||||
if [[ "$board" == "PRALINE" ]]; then
|
||||
printf "hackrf-pro"
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$flash_limit" in
|
||||
2|2.0)
|
||||
printf "portarf"
|
||||
return 0
|
||||
;;
|
||||
1|1.0)
|
||||
printf "hackrf-one"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
printf "unknown"
|
||||
return 0
|
||||
}
|
||||
|
||||
mbt_clean() {
|
||||
local build_dir="$1"
|
||||
local libopencm3_dir="$SCRIPT_PATH/hackrf/firmware/libopencm3"
|
||||
|
||||
mbt_log "cleaning build directory: $build_dir"
|
||||
if ! rm -rf "$build_dir"; then
|
||||
mbt_error "failed to delete build directory. Try running ./mbt --clean as root."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -d "$libopencm3_dir" ]]; then
|
||||
mbt_log "cleaning libopencm3: $libopencm3_dir"
|
||||
make -C "$libopencm3_dir" clean
|
||||
else
|
||||
mbt_error "libopencm3 directory not found: $libopencm3_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
mbt_report_build_error() {
|
||||
printf '%s\n' 'Build error happened. Try to fix your code, or run ./mbt --clean and try again' >&2
|
||||
}
|
||||
|
||||
mbt_build() {
|
||||
local build_dir="$1"
|
||||
local generator="$2"
|
||||
local use_ccache="$3"
|
||||
local device="$4"
|
||||
local jobs="$5"
|
||||
local target="$6"
|
||||
local clean_build="$7"
|
||||
shift 7
|
||||
if [[ "$#" -lt 2 ]]; then
|
||||
mbt_die "internal error: mbt_build expected extra arg array names"
|
||||
fi
|
||||
|
||||
local -n cmake_extra_args_ref="$1"
|
||||
local -a cmake_extra_args=("${cmake_extra_args_ref[@]}")
|
||||
shift
|
||||
local -n build_extra_args_ref="$1"
|
||||
local -a build_extra_args=("${build_extra_args_ref[@]}")
|
||||
local -a cmake_args build_args device_args
|
||||
local marker_file="$build_dir/.mbt_device"
|
||||
local previous_device=""
|
||||
|
||||
if [[ "$clean_build" -eq 1 ]]; then
|
||||
mbt_clean "$build_dir"
|
||||
return 0
|
||||
else
|
||||
if [[ -f "$marker_file" ]]; then
|
||||
previous_device="$(<"$marker_file")"
|
||||
elif [[ -f "$build_dir/CMakeCache.txt" ]]; then
|
||||
previous_device="$(mbt_detect_cached_device "$build_dir" 2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
if [[ -n "$previous_device" ]] && [[ "$previous_device" != "$device" ]]; then
|
||||
mbt_log "device changed ($previous_device -> $device), cleaning build directory: $build_dir"
|
||||
rm -rf "$build_dir"
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$build_dir"
|
||||
|
||||
device_args=()
|
||||
case "$device" in
|
||||
hackrf-one)
|
||||
device_args+=()
|
||||
;;
|
||||
hackrf-pro)
|
||||
device_args+=("-DBOARD=PRALINE")
|
||||
;;
|
||||
portarf)
|
||||
device_args+=("-DFLASH_MB_SIZE=2" "-DFLASH_MB_LIMIT_SIZE=2")
|
||||
;;
|
||||
*)
|
||||
mbt_die "unsupported device preset: $device"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "$generator" == "Ninja" ]] && ! mbt_command_exists ninja; then
|
||||
if mbt_command_exists make; then
|
||||
mbt_log "ninja not found; falling back to Unix Makefiles."
|
||||
generator="Unix Makefiles"
|
||||
else
|
||||
mbt_die "ninja not found and make is unavailable. Install dependencies or set a working generator."
|
||||
fi
|
||||
fi
|
||||
|
||||
cmake_args=(
|
||||
-S "$SCRIPT_PATH"
|
||||
-B "$build_dir"
|
||||
-G "$generator"
|
||||
"-DUSE_CCACHE=$use_ccache"
|
||||
)
|
||||
cmake_args+=("${device_args[@]}")
|
||||
cmake_args+=("${cmake_extra_args[@]}")
|
||||
|
||||
mbt_log "configuring build for $device in $build_dir"
|
||||
if ! cmake "${cmake_args[@]}"; then
|
||||
mbt_report_build_error
|
||||
return 1
|
||||
fi
|
||||
printf "%s\n" "$device" > "$marker_file"
|
||||
|
||||
build_args=(--build "$build_dir" --parallel "$jobs")
|
||||
if [[ -n "$target" ]]; then
|
||||
build_args+=(--target "$target")
|
||||
fi
|
||||
build_args+=("${build_extra_args[@]}")
|
||||
|
||||
mbt_log "building..."
|
||||
if ! cmake "${build_args[@]}"; then
|
||||
mbt_report_build_error
|
||||
return 1
|
||||
fi
|
||||
mbt_log "build complete. Outputs are in $build_dir."
|
||||
mbt_log "The bare binary (for the hackrf_spiflash host tool), excluding external apps, is located at $build_dir/firmware/portapack-mayhem-firmware.bin"
|
||||
mbt_log "The full tar.gz package (for MayhemHub and the Flash Utility OTA app), including external apps and the firmware file, is located at $build_dir/firmware/portapack-mayhem_OCI.ppfw.tar"
|
||||
mbt_log "If you have the dev's SD card switcher hardware, the fast flash script is at $build_dir/flash.py"
|
||||
# have to hard code the name here cuz it's too expensive to read cmake for just a file name.
|
||||
}
|
||||
|
||||
main() {
|
||||
local command="build"
|
||||
local quickstart=0
|
||||
local device=""
|
||||
local use_ccache="ON"
|
||||
local with_deps=0
|
||||
local with_submodule_sync=1
|
||||
local with_toolchain=1
|
||||
local build_dir="$SCRIPT_PATH/build"
|
||||
local generator="Ninja"
|
||||
local jobs
|
||||
local target=""
|
||||
local clean_build=0
|
||||
local non_interactive=0
|
||||
local -a cmake_extra_args=()
|
||||
local -a build_extra_args=()
|
||||
|
||||
FORCE_TOOLCHAIN=0
|
||||
jobs="$(mbt_default_jobs)"
|
||||
|
||||
if [[ "$#" -eq 0 ]]; then
|
||||
quickstart=1
|
||||
with_deps=1
|
||||
fi
|
||||
|
||||
if [[ "$#" -gt 0 ]]; then
|
||||
case "$1" in
|
||||
build|deps|toolchain|doctor|shell)
|
||||
command="$1"
|
||||
shift
|
||||
;;
|
||||
-h|--help|help)
|
||||
mbt_print_help
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-d|--device)
|
||||
[[ "$#" -ge 2 ]] || mbt_die "$1 requires a value"
|
||||
device="$2"
|
||||
shift 2
|
||||
;;
|
||||
--ccache)
|
||||
use_ccache="ON"
|
||||
shift
|
||||
;;
|
||||
--no-ccache)
|
||||
use_ccache="OFF"
|
||||
shift
|
||||
;;
|
||||
--with-deps)
|
||||
with_deps=1
|
||||
shift
|
||||
;;
|
||||
--no-deps)
|
||||
with_deps=0
|
||||
shift
|
||||
;;
|
||||
--with-submodule-sync)
|
||||
with_submodule_sync=1
|
||||
shift
|
||||
;;
|
||||
--no-submodule-sync)
|
||||
with_submodule_sync=0
|
||||
shift
|
||||
;;
|
||||
--with-toolchain)
|
||||
with_toolchain=1
|
||||
shift
|
||||
;;
|
||||
--no-toolchain)
|
||||
with_toolchain=0
|
||||
shift
|
||||
;;
|
||||
--force-toolchain)
|
||||
FORCE_TOOLCHAIN=1
|
||||
with_toolchain=1
|
||||
shift
|
||||
;;
|
||||
-B|--build-dir)
|
||||
[[ "$#" -ge 2 ]] || mbt_die "$1 requires a value"
|
||||
build_dir="$2"
|
||||
shift 2
|
||||
;;
|
||||
-G|--generator)
|
||||
[[ "$#" -ge 2 ]] || mbt_die "$1 requires a value"
|
||||
generator="$2"
|
||||
shift 2
|
||||
;;
|
||||
-j|--jobs)
|
||||
[[ "$#" -ge 2 ]] || mbt_die "$1 requires a value"
|
||||
jobs="$2"
|
||||
shift 2
|
||||
;;
|
||||
--target)
|
||||
[[ "$#" -ge 2 ]] || mbt_die "$1 requires a value"
|
||||
target="$2"
|
||||
shift 2
|
||||
;;
|
||||
--clean)
|
||||
clean_build=1
|
||||
shift
|
||||
;;
|
||||
--cmake-arg)
|
||||
[[ "$#" -ge 2 ]] || mbt_die "$1 requires a value"
|
||||
cmake_extra_args+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--cmake-arg=*)
|
||||
cmake_extra_args+=("${1#*=}")
|
||||
shift
|
||||
;;
|
||||
--build-arg)
|
||||
[[ "$#" -ge 2 ]] || mbt_die "$1 requires a value"
|
||||
build_extra_args+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--build-arg=*)
|
||||
build_extra_args+=("${1#*=}")
|
||||
shift
|
||||
;;
|
||||
-y|--non-interactive)
|
||||
non_interactive=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
mbt_print_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
mbt_die "unknown option: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! mbt_validate_jobs "$jobs"; then
|
||||
mbt_die "invalid jobs value: $jobs"
|
||||
fi
|
||||
|
||||
case "$command" in
|
||||
deps)
|
||||
mbt_install_deps
|
||||
exit 0
|
||||
;;
|
||||
toolchain)
|
||||
NO_TOOLCHAIN_DOWNLOAD=0
|
||||
mbt_enable_toolchain_env
|
||||
mbt_log "toolchain ready: $SCRIPT_PATH/armbin"
|
||||
exit 0
|
||||
;;
|
||||
doctor)
|
||||
mbt_doctor
|
||||
exit $?
|
||||
;;
|
||||
shell)
|
||||
if [[ "$with_toolchain" -eq 1 ]]; then
|
||||
mbt_enable_toolchain_env
|
||||
else
|
||||
mbt_use_existing_toolchain_env
|
||||
fi
|
||||
mbt_log "spawning shell with toolchain exported in this session. Use 'exit' to leave."
|
||||
exec "${SHELL:-/bin/bash}" -i
|
||||
;;
|
||||
build)
|
||||
;;
|
||||
*)
|
||||
mbt_die "unsupported command: $command"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "$clean_build" -eq 1 ]]; then
|
||||
mbt_clean "$build_dir"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$with_deps" -eq 1 ]]; then
|
||||
mbt_install_deps
|
||||
fi
|
||||
|
||||
if [[ "$with_submodule_sync" -eq 1 ]]; then
|
||||
mbt_sync_submodules
|
||||
fi
|
||||
|
||||
if [[ "$with_toolchain" -eq 1 ]]; then
|
||||
mbt_enable_toolchain_env
|
||||
else
|
||||
mbt_use_existing_toolchain_env
|
||||
fi
|
||||
|
||||
if [[ -n "$device" ]]; then
|
||||
device="$(mbt_normalize_device "$device" 2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
if [[ -z "$device" ]]; then
|
||||
if [[ "$non_interactive" -eq 1 ]]; then
|
||||
mbt_die "--device is required when --non-interactive is set"
|
||||
fi
|
||||
if [[ ! -t 0 ]]; then
|
||||
mbt_die "missing --device and no interactive terminal available"
|
||||
fi
|
||||
device="$(mbt_prompt_device)" || mbt_die "failed to read device selection"
|
||||
fi
|
||||
|
||||
if [[ "$quickstart" -eq 1 ]]; then
|
||||
mbt_log "quickstart mode enabled."
|
||||
fi
|
||||
|
||||
mbt_build "$build_dir" "$generator" "$use_ccache" "$device" "$jobs" "$target" "$clean_build" \
|
||||
cmake_extra_args[@] build_extra_args[@]
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+209
@@ -0,0 +1,209 @@
|
||||
#!/bin/sh
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
|
||||
MBT_ROOT="${MBT_ROOT:-$(pwd -P)}"
|
||||
MBT_VERBOSE="${MBT_VERBOSE:-}"
|
||||
MBT_TOOLCHAIN_DIR="${MBT_TOOLCHAIN_DIR:-$MBT_ROOT/armbin}"
|
||||
MBT_TOOLCHAIN_URL="${MBT_TOOLCHAIN_URL:-https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/RC2.1/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2?revision=6e63531f-8cb1-40b9-bbfc-8a57cdfc01b4&la=en&hash=F761343D43A0587E8AC0925B723C04DBFB848339}"
|
||||
MBT_EXPECTED_GCC_VERSION="${MBT_EXPECTED_GCC_VERSION:-9.2.1}"
|
||||
MBT_FORCE_TOOLCHAIN="${MBT_FORCE_TOOLCHAIN:-0}"
|
||||
MBT_NO_TOOLCHAIN_DOWNLOAD="${MBT_NO_TOOLCHAIN_DOWNLOAD:-0}"
|
||||
MBT_TOOLCHAIN_BIN="$MBT_TOOLCHAIN_DIR/bin"
|
||||
MBT_TOOLCHAIN_CC="$MBT_TOOLCHAIN_BIN/arm-none-eabi-gcc"
|
||||
MBT_TMP_ARCHIVE=""
|
||||
MBT_DOWNLOADER=""
|
||||
|
||||
mbtenv_log() {
|
||||
printf "mbt: %s\n" "$*"
|
||||
}
|
||||
|
||||
mbtenv_verbose() {
|
||||
if [ -n "$MBT_VERBOSE" ]; then
|
||||
mbtenv_log "$*"
|
||||
fi
|
||||
}
|
||||
|
||||
mbtenv_command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
mbtenv_cleanup_tmp() {
|
||||
if [ -n "$MBT_TMP_ARCHIVE" ] && [ -f "$MBT_TMP_ARCHIVE" ]; then
|
||||
rm -f "$MBT_TMP_ARCHIVE"
|
||||
fi
|
||||
}
|
||||
|
||||
mbtenv_check_linux() {
|
||||
if [ "$(uname -s)" != "Linux" ]; then
|
||||
mbtenv_log "error: mbt currently supports Linux only."
|
||||
return 1
|
||||
fi
|
||||
|
||||
arch="$(uname -m)"
|
||||
case "$arch" in
|
||||
x86_64|amd64)
|
||||
# Supported architecture for the default x86_64 Linux toolchain archive.
|
||||
;;
|
||||
*)
|
||||
mbtenv_log "error: unsupported architecture '$arch'. mbt currently supports x86_64 Linux only for the bundled toolchain."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
mbtenv_choose_downloader() {
|
||||
if mbtenv_command_exists curl; then
|
||||
MBT_DOWNLOADER="curl"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if mbtenv_command_exists wget; then
|
||||
MBT_DOWNLOADER="wget"
|
||||
return 0
|
||||
fi
|
||||
|
||||
mbtenv_log "error: neither curl nor wget found in PATH."
|
||||
return 1
|
||||
}
|
||||
|
||||
mbtenv_download_archive() {
|
||||
if [ "$MBT_DOWNLOADER" = "curl" ]; then
|
||||
curl --fail --location --progress-bar --output "$1" "$2"
|
||||
return $?
|
||||
fi
|
||||
|
||||
wget --show-progress --progress=bar:force -O "$1" "$2"
|
||||
}
|
||||
|
||||
mbtenv_get_installed_version() {
|
||||
if [ ! -x "$MBT_TOOLCHAIN_CC" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$MBT_TOOLCHAIN_CC" -dumpfullversion 2>/dev/null || "$MBT_TOOLCHAIN_CC" -dumpversion 2>/dev/null
|
||||
}
|
||||
|
||||
mbtenv_toolchain_is_expected() {
|
||||
INSTALLED_VERSION="$(mbtenv_get_installed_version 2>/dev/null || true)"
|
||||
if [ "$INSTALLED_VERSION" = "$MBT_EXPECTED_GCC_VERSION" ]; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
mbtenv_download_and_unpack_toolchain() {
|
||||
mbtenv_choose_downloader || return 1
|
||||
|
||||
MBT_TMP_ARCHIVE="$(mktemp /tmp/mbt-toolchain-XXXXXX.tar.bz2)"
|
||||
trap mbtenv_cleanup_tmp EXIT INT TERM
|
||||
|
||||
mbtenv_log "downloading ARM GNU toolchain..."
|
||||
mbtenv_download_archive "$MBT_TMP_ARCHIVE" "$MBT_TOOLCHAIN_URL" || {
|
||||
mbtenv_log "error: failed to download toolchain from ARM."
|
||||
return 1
|
||||
}
|
||||
|
||||
mbtenv_log "putting toolchain into $MBT_TOOLCHAIN_DIR"
|
||||
if [ -d "$MBT_TOOLCHAIN_DIR" ] && [ ! -f "$MBT_TOOLCHAIN_DIR/bin/arm-none-eabi-gcc-9.2.1" ]; then
|
||||
mbtenv_log "Sorry, i can't verify if the toolchain dir is legit to delete. it either could be becasue you failed to download the full toolchain last time, or the enviroment var were pointed to something else, which is not safe for me to remove. please check if it's safe to remove $MBT_TOOLCHAIN_DIR and manually remove $MBT_TOOLCHAIN_DIR"
|
||||
return 1
|
||||
fi
|
||||
rm -rf "$MBT_TOOLCHAIN_DIR"
|
||||
mkdir -p "$MBT_TOOLCHAIN_DIR"
|
||||
tar --strip-components=1 -xjf "$MBT_TMP_ARCHIVE" -C "$MBT_TOOLCHAIN_DIR" || {
|
||||
mbtenv_log "error: failed to extract toolchain archive."
|
||||
return 1
|
||||
}
|
||||
|
||||
mbtenv_cleanup_tmp
|
||||
trap - EXIT INT TERM
|
||||
MBT_TMP_ARCHIVE=""
|
||||
return 0
|
||||
}
|
||||
|
||||
mbtenv_ensure_toolchain() {
|
||||
if mbtenv_toolchain_is_expected && [ "$MBT_FORCE_TOOLCHAIN" != "1" ]; then
|
||||
mbtenv_verbose "toolchain already installed at $MBT_TOOLCHAIN_DIR"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$MBT_NO_TOOLCHAIN_DOWNLOAD" = "1" ]; then
|
||||
if [ ! -x "$MBT_TOOLCHAIN_CC" ]; then
|
||||
mbtenv_log "error: arm-none-eabi-gcc not found in $MBT_TOOLCHAIN_BIN"
|
||||
mbtenv_log "hint: run ./mbt toolchain once, or remove --no-toolchain."
|
||||
return 1
|
||||
fi
|
||||
|
||||
INSTALLED_VERSION="$(mbtenv_get_installed_version 2>/dev/null || true)"
|
||||
mbtenv_log "error: found arm-none-eabi-gcc $INSTALLED_VERSION, expected $MBT_EXPECTED_GCC_VERSION"
|
||||
mbtenv_log "hint: run ./mbt toolchain once, or remove --no-toolchain."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -x "$MBT_TOOLCHAIN_CC" ]; then
|
||||
INSTALLED_VERSION="$(mbtenv_get_installed_version 2>/dev/null || true)"
|
||||
mbtenv_log "toolchain version mismatch (found $INSTALLED_VERSION, expected $MBT_EXPECTED_GCC_VERSION)"
|
||||
mbtenv_log "reinstalling toolchain..."
|
||||
fi
|
||||
|
||||
mbtenv_download_and_unpack_toolchain || return 1
|
||||
|
||||
if ! mbtenv_toolchain_is_expected; then
|
||||
INSTALLED_VERSION="$(mbtenv_get_installed_version 2>/dev/null || true)"
|
||||
mbtenv_log "error: installed toolchain version check failed (found $INSTALLED_VERSION)."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
mbtenv_activate_path() {
|
||||
if [ ! -d "$MBT_TOOLCHAIN_BIN" ]; then
|
||||
mbtenv_log "error: missing toolchain bin directory: $MBT_TOOLCHAIN_BIN"
|
||||
return 1
|
||||
fi
|
||||
|
||||
case ":$PATH:" in
|
||||
*":$MBT_TOOLCHAIN_BIN:"*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "${MBT_SAVED_PATH+x}" ]; then
|
||||
MBT_SAVED_PATH="$PATH"
|
||||
export MBT_SAVED_PATH
|
||||
fi
|
||||
|
||||
PATH="$MBT_TOOLCHAIN_BIN:$PATH"
|
||||
export PATH
|
||||
return 0
|
||||
}
|
||||
|
||||
mbtenv_restore() {
|
||||
if [ -n "${MBT_SAVED_PATH+x}" ]; then
|
||||
PATH="$MBT_SAVED_PATH"
|
||||
export PATH
|
||||
unset MBT_SAVED_PATH
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
mbtenv_main() {
|
||||
mbtenv_check_linux || return 1
|
||||
|
||||
if [ "${1:-}" = "--restore" ]; then
|
||||
mbtenv_restore
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "${MBT_NOENV:-0}" = "1" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
mbtenv_ensure_toolchain || return 1
|
||||
mbtenv_activate_path || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
mbtenv_main "${1:-}"
|
||||
Reference in New Issue
Block a user