Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for HackRF One R9 #805

Merged
merged 1 commit into from Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions firmware/application/CMakeLists.txt
Expand Up @@ -103,6 +103,7 @@ set(CSRC
${PLATFORMSRC}
${BOARDSRC}
${FATFSSRC}
firmware_info.c
)

# C++ sources that can be compiled in ARM or THUMB mode depending on the global
Expand Down Expand Up @@ -193,6 +194,7 @@ set(CPPSRC
hw/debounce.cpp
hw/encoder.cpp
hw/max2837.cpp
hw/max2839.cpp
hw/max5864.cpp
hw/rffc507x.cpp
hw/rffc507x_spi.cpp
Expand Down
10 changes: 6 additions & 4 deletions firmware/application/apps/ui_debug.cpp
Expand Up @@ -322,17 +322,19 @@ void DebugControlsView::focus() {
/* DebugPeripheralsMenuView **********************************************/

DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
const char * max283x = hackrf_r9 ? "MAX2839" : "MAX2837";
const char * si5351x = hackrf_r9 ? "Si5351A" : "Si5351C";
add_items({
{ "RFFC5072", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
"RFFC5072", RegistersWidgetConfig { 31, 16 },
[](const size_t register_number) { return radio::debug::first_if::register_read(register_number); }
); } },
{ "MAX2837", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
"MAX2837", RegistersWidgetConfig { 32, 10 },
{ max283x, ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav, max283x](){ nav.push<RegistersView>(
max283x, RegistersWidgetConfig { 32, 10 },
[](const size_t register_number) { return radio::debug::second_if::register_read(register_number); }
); } },
{ "Si5351C", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
"Si5351C", RegistersWidgetConfig { 96, 8 },
{ si5351x, ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav, si5351x](){ nav.push<RegistersView>(
si5351x, RegistersWidgetConfig { 96, 8 },
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
); } },
{ audio::debug::codec_name(), ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
Expand Down
1 change: 0 additions & 1 deletion firmware/application/apps/ui_debug.hpp
Expand Up @@ -29,7 +29,6 @@
#include "ui_navigation.hpp"

#include "rffc507x.hpp"
#include "max2837.hpp"
#include "portapack.hpp"

#include <functional>
Expand Down
4 changes: 2 additions & 2 deletions firmware/application/apps/ui_morse.cpp
Expand Up @@ -57,13 +57,13 @@ static msg_t ookthread_fn(void * arg) {
v = (symbol < 2) ? 1 : 0; // TX on for dot or dash, off for pause
delay = morse_symbols[symbol];

gpio_tx.write(v);
gpio_og_tx.write(v);
arg_c->on_tx_progress(i, false);

chThdSleepMilliseconds(delay * arg_c->time_unit_ms);
}

gpio_tx.write(0); // Ensure TX is off
gpio_og_tx.write(0); // Ensure TX is off
arg_c->on_tx_progress(0, true);
chThdExit(0);

Expand Down
2 changes: 1 addition & 1 deletion firmware/application/baseband_api.cpp
Expand Up @@ -307,7 +307,7 @@ void run_image(const portapack::spi_flash::image_tag_t image_tag) {

creg::m4txevent::clear();

m4_init(image_tag, portapack::memory::map::m4_code);
m4_init(image_tag, portapack::memory::map::m4_code, false);
baseband_image_running = true;

creg::m4txevent::enable();
Expand Down
291 changes: 202 additions & 89 deletions firmware/application/clock_manager.cpp

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions firmware/application/clock_manager.hpp
Expand Up @@ -65,11 +65,8 @@ class ClockManager {
void enable_codec_clocks();
void disable_codec_clocks();

void enable_first_if_clock();
void disable_first_if_clock();

void enable_second_if_clock();
void disable_second_if_clock();
void enable_if_clocks();
void disable_if_clocks();

void set_sampling_frequency(const uint32_t frequency);

Expand Down Expand Up @@ -99,6 +96,7 @@ class ClockManager {

ReferenceSource detect_reference_source();
Reference choose_reference();
bool loss_of_signal();
};

#endif/*__CLOCK_MANAGER_H__*/
9 changes: 6 additions & 3 deletions firmware/application/core_control.cpp
Expand Up @@ -38,7 +38,7 @@ using namespace lpc43xx;
* I suppose I could force M4MEMMAP to an invalid memory reason which would
* cause an exception and effectively halt the M4. But that feels gross.
*/
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to) {
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to, const bool full_reset) {
const portapack::spi_flash::chunk_t* chunk = reinterpret_cast<const portapack::spi_flash::chunk_t*>(portapack::spi_flash::images.base());
while(chunk->tag) {
if( chunk->tag == image_tag ) {
Expand All @@ -50,8 +50,11 @@ void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack:
*/
LPC_CREG->M4MEMMAP = to.base();

/* Reset M4 core */
LPC_RGU->RESET_CTRL[0] = (1 << 13);
/* Reset M4 core and optionally all peripherals */
LPC_RGU->RESET_CTRL[0] = (full_reset) ?
(1 << 1) // PERIPH_RST
: (1 << 13) // M4_RST
;

return;
}
Expand Down
2 changes: 1 addition & 1 deletion firmware/application/core_control.hpp
Expand Up @@ -27,7 +27,7 @@
#include "memory_map.hpp"
#include "spi_image.hpp"

void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to);
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to, const bool full_reset);
void m4_request_shutdown();

void m0_halt();
Expand Down
13 changes: 13 additions & 0 deletions firmware/application/firmware_info.c
@@ -0,0 +1,13 @@
#include "../../hackrf/firmware/common/firmware_info.h"
#include "../../hackrf/firmware/common/platform_detect.h"

#define SUPPORTED_PLATFORM (PLATFORM_HACKRF1_OG | PLATFORM_HACKRF1_R9)
#define DFU_MODE_VALUE 0

__attribute__((section(".firmware_info"))) const struct firmware_info_t firmware_info = {
.magic = "HACKRFFW",
.struct_version = 1,
.dfu_mode = DFU_MODE_VALUE,
.supported_platform = SUPPORTED_PLATFORM,
.version_string = VERSION_STRING,
};
40 changes: 35 additions & 5 deletions firmware/application/hw/max2837.cpp
Expand Up @@ -32,8 +32,12 @@ using namespace hackrf::one;

namespace max2837 {

using namespace max283x;

namespace lna {

using namespace max283x::lna;

constexpr std::array<uint8_t, 8> lookup_8db_steps {
0b111, 0b011, 0b110, 0b010,
0b100, 0b000, 0b000, 0b000
Expand All @@ -48,6 +52,8 @@ static uint_fast8_t gain_ordinal(const int8_t db) {

namespace vga {

using namespace max283x::vga;

static uint_fast8_t gain_ordinal(const int8_t db) {
const auto db_sat = gain_db_range.clip(db);
return ((db_sat >> 1) & 0b11111) ^ 0b11111;
Expand All @@ -57,6 +63,8 @@ static uint_fast8_t gain_ordinal(const int8_t db) {

namespace tx {

using namespace max283x::tx;

static uint_fast8_t gain_ordinal(const int8_t db) {
const auto db_sat = gain_db_range.clip(db);
uint8_t value = db_sat & 0x0f;
Expand All @@ -69,6 +77,8 @@ static uint_fast8_t gain_ordinal(const int8_t db) {

namespace filter {

using namespace max283x::filter;

static uint_fast8_t bandwidth_ordinal(const uint32_t bandwidth) {
/* Determine filter setting that will provide bandwidth greater than or
* equal to requested bandwidth.
Expand All @@ -84,13 +94,13 @@ static uint_fast8_t bandwidth_ordinal(const uint32_t bandwidth) {
constexpr float seconds_for_temperature_sense_adc_conversion = 30.0e-6;
constexpr halrtcnt_t ticks_for_temperature_sense_adc_conversion = (base_m4_clk_f * seconds_for_temperature_sense_adc_conversion + 1);

constexpr uint32_t reference_frequency = max2837_reference_f;
constexpr uint32_t reference_frequency = max283x_reference_f;
constexpr uint32_t pll_factor = 1.0 / (4.0 / 3.0 / reference_frequency) + 0.5;

void MAX2837::init() {
set_mode(Mode::Shutdown);

gpio_max2837_enable.output();
gpio_max283x_enable.output();
gpio_max2837_rxenable.output();
gpio_max2837_txenable.output();

Expand Down Expand Up @@ -140,10 +150,30 @@ void MAX2837::init() {
set_mode(Mode::Standby);
}

enum class Mask {
Enable = 0b001,
RxEnable = 0b010,
TxEnable = 0b100,
Shutdown = 0b000,
Standby = Enable,
Receive = Enable | RxEnable,
Transmit = Enable | TxEnable,
};

Mask mode_mask(const Mode mode) {
switch (mode) {
case Mode::Standby: return Mask::Standby;
case Mode::Receive: return Mask::Receive;
case Mode::Transmit: return Mask::Transmit;
default: return Mask::Shutdown;
}
}

void MAX2837::set_mode(const Mode mode) {
gpio_max2837_enable.write(toUType(mode) & toUType(Mode::Mask_Enable));
gpio_max2837_rxenable.write(toUType(mode) & toUType(Mode::Mask_RxEnable));
gpio_max2837_txenable.write(toUType(mode) & toUType(Mode::Mask_TxEnable));
Mask mask = mode_mask(mode);
gpio_max283x_enable.write(toUType(mask) & toUType(Mask::Enable));
gpio_max2837_rxenable.write(toUType(mask) & toUType(Mask::RxEnable));
gpio_max2837_txenable.write(toUType(mask) & toUType(Mask::TxEnable));
}

void MAX2837::flush() {
Expand Down
115 changes: 14 additions & 101 deletions firmware/application/hw/max2837.hpp
Expand Up @@ -22,106 +22,19 @@
#ifndef __MAX2837_H__
#define __MAX2837_H__

#include "max283x.hpp"
#include "gpio.hpp"
#include "spi_arbiter.hpp"

#include <cstdint>
#include <array>

#include "dirty_registers.hpp"
#include "rf_path.hpp"
#include "utility.hpp"

namespace max2837 {

enum class Mode {
Mask_Enable = 0b001,
Mask_RxEnable = 0b010,
Mask_TxEnable = 0b100,

Shutdown = 0b000,
Standby = Mask_Enable,
Receive = Mask_Enable | Mask_RxEnable,
Transmit = Mask_Enable | Mask_TxEnable,
};

/*************************************************************************/

namespace lo {

constexpr std::array<rf::FrequencyRange, 4> band { {
{ 2300000000, 2400000000 },
{ 2400000000, 2500000000 },
{ 2500000000, 2600000000 },
{ 2600000000, 2700000000 },
} };

} /* namespace lo */

/*************************************************************************/

namespace lna {

constexpr range_t<int8_t> gain_db_range { 0, 40 };
constexpr int8_t gain_db_step = 8;

constexpr std::array<rf::FrequencyRange, 2> band { {
{ 2300000000, 2500000000 },
{ 2500000000, 2700000000 },
} };

} /* namespace lna */

/*************************************************************************/

namespace vga {

constexpr range_t<int8_t> gain_db_range { 0, 62 };
constexpr int8_t gain_db_step = 2;

} /* namespace vga */

/*************************************************************************/

namespace tx {

constexpr range_t<int8_t> gain_db_range { 0, 47 };
constexpr int8_t gain_db_step = 1;
}

/*************************************************************************/

namespace filter {

constexpr std::array<uint32_t, 16> bandwidths {
/* Assumption: these values are in ascending order */
1750000,
2500000, /* Some documentation says 2.25MHz */
3500000,
5000000,
5500000,
6000000,
7000000,
8000000,
9000000,
10000000,
12000000,
14000000,
15000000,
20000000,
24000000,
28000000,
};

constexpr auto bandwidth_minimum = bandwidths[0];
constexpr auto bandwidth_maximum = bandwidths[bandwidths.size() - 1];

} /* namespace filter */

/*************************************************************************/

using reg_t = uint16_t;
using address_t = uint8_t;
using namespace max283x;

constexpr size_t reg_count = 32;

Expand Down Expand Up @@ -826,21 +739,21 @@ constexpr RegisterMap initial_register_values { Register_Type {
},
} };

class MAX2837 {
class MAX2837 : public MAX283x {
public:
constexpr MAX2837(
spi::arbiter::Target& target
) : _target(target)
{
}

void init();
void set_mode(const Mode mode);
void init() override;
void set_mode(const Mode mode) override;

void set_tx_vga_gain(const int_fast8_t db);
void set_lna_gain(const int_fast8_t db);
void set_vga_gain(const int_fast8_t db);
void set_lpf_rf_bandwidth(const uint32_t bandwidth_minimum);
void set_tx_vga_gain(const int_fast8_t db) override;
void set_lna_gain(const int_fast8_t db) override;
void set_vga_gain(const int_fast8_t db) override;
void set_lpf_rf_bandwidth(const uint32_t bandwidth_minimum) override;
#if 0
void rx_cal() {
_map.r.spi_en.EN_SPI = 1;
Expand Down Expand Up @@ -882,16 +795,16 @@ class MAX2837 {
}
#endif

bool set_frequency(const rf::Frequency lo_frequency);
bool set_frequency(const rf::Frequency lo_frequency) override;

void set_rx_lo_iq_calibration(const size_t v);
void set_rx_lo_iq_calibration(const size_t v) override;
void set_rx_bias_trim(const size_t v);
void set_vco_bias(const size_t v);
void set_rx_buff_vcm(const size_t v);
void set_rx_buff_vcm(const size_t v) override;

reg_t temp_sense();
reg_t temp_sense() override;

reg_t read(const address_t reg_num);
reg_t read(const address_t reg_num) override;

private:
spi::arbiter::Target& _target;
Expand Down