mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-14 02:29:29 +00:00
radio.cpp: program FPGA quarter-rate shift together with tuning offset
This commit is contained in:
@@ -144,6 +144,10 @@ static rf::Direction cached_direction = rf::Direction::Receive;
|
|||||||
static bool cached_rf_amp = false;
|
static bool cached_rf_amp = false;
|
||||||
static int_fast8_t cached_lna_gain = 0;
|
static int_fast8_t cached_lna_gain = 0;
|
||||||
static int_fast8_t cached_vga_gain = 0;
|
static int_fast8_t cached_vga_gain = 0;
|
||||||
|
/* FPGA quarter-rate shift mode currently programmed, in gateware encoding
|
||||||
|
* (0b00 none / 0b11 up / 0b01 down). The baseband filter width depends on it,
|
||||||
|
* so ReceiverModel reads it back through get_quarter_shift(). */
|
||||||
|
static uint8_t cached_quarter_shift = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
@@ -182,18 +186,15 @@ void init() {
|
|||||||
|
|
||||||
fpga_set_mode(FPGA_MODE_RX);
|
fpga_set_mode(FPGA_MODE_RX);
|
||||||
|
|
||||||
// These FPGA registers control DC_BLOCK, Q-Inv, QUARTER SHIFT, and Decimation.
|
/* Boot register state, matching fpga_init() in hackrf/firmware/common/fpga.c:
|
||||||
fpga_debug_register_write(FPGA_REG_CTRL, FPGA_CTRL_DC_BLOCK_EN); // DC_BLOCK=1, QUARTER_SHIFT=0, Q_INVERT=0
|
* DC block on, no PRBS, no external trigger, no quarter shift, TX NCO off.
|
||||||
fpga_debug_register_write(FPGA_REG_DECIM, 0x00); // RX_DECIM=No Decim
|
* The decimation ratio and the quarter shift are programmed later by
|
||||||
|
* ClockManager::set_sampling_frequency() and set_tuning_frequency(). */
|
||||||
// RX Mode: Register 3 is RX Digital Gain. Start with 0dB (no shift).
|
fpga_debug_register_write(FPGA_REG_CTRL, FPGA_CTRL_DC_BLOCK_EN);
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DIGITAL_GAIN, FPGA_RX_DEFAULT_DIGITAL_GAIN);
|
fpga_debug_register_write(FPGA_REG_DECIM, 0x00); // RX_DECIM = no decimation
|
||||||
|
fpga_debug_register_write(FPGA_REG_RX_PSTEP, 0x00); // quarter shift off
|
||||||
/* RX Mode: Initialize DC Block parameters to standard Praline values.
|
fpga_debug_register_write(FPGA_REG_TX_CONTROL, 0x00);
|
||||||
* 0x04 Width and 0x08 Adapt Rate are typical for 40MHz stability.
|
cached_quarter_shift = 0;
|
||||||
*/
|
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DC_BLOCK_WIDTH, FPGA_RX_DEFAULT_DC_WIDTH);
|
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DC_ADAPT_RATE, FPGA_RX_DEFAULT_ADAPT_RATE);
|
|
||||||
|
|
||||||
ssp1_arbiter.invalidate();
|
ssp1_arbiter.invalidate();
|
||||||
chThdSleepMilliseconds(10); // Let FPGA registers settle
|
chThdSleepMilliseconds(10); // Let FPGA registers settle
|
||||||
@@ -224,13 +225,13 @@ void set_direction(const rf::Direction new_direction) {
|
|||||||
fpga_debug_register_write(FPGA_REG_TX_PHASE_STEP, 0x00);
|
fpga_debug_register_write(FPGA_REG_TX_PHASE_STEP, 0x00);
|
||||||
} else {
|
} else {
|
||||||
fpga_set_mode(FPGA_MODE_RX);
|
fpga_set_mode(FPGA_MODE_RX);
|
||||||
// RX Mode: Ensure NCO is disabled and reset digital gain
|
/* RX Mode: DC block on, TX NCO off. The quarter shift is re-applied by
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DIGITAL_GAIN, FPGA_RX_DEFAULT_DIGITAL_GAIN);
|
* set_tuning_frequency(); clear it here so a stale TX/RX transition
|
||||||
/* RX Mode: Initialize DC Block parameters to standard Praline values.
|
* cannot leave a rotation programmed with no matching LO offset. */
|
||||||
* 0x04 Width and 0x08 Adapt Rate are typical for 40MHz stability.
|
fpga_debug_register_write(FPGA_REG_CTRL, FPGA_CTRL_DC_BLOCK_EN);
|
||||||
*/
|
fpga_debug_register_write(FPGA_REG_TX_CONTROL, 0x00);
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DC_BLOCK_WIDTH, FPGA_RX_DEFAULT_DC_WIDTH);
|
fpga_debug_register_write(FPGA_REG_RX_PSTEP, 0x00);
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DC_ADAPT_RATE, FPGA_RX_DEFAULT_ADAPT_RATE);
|
cached_quarter_shift = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -309,7 +310,19 @@ bool set_tuning_frequency(const rf::Frequency frequency) {
|
|||||||
final_frequency = final_frequency + portapack::persistent_memory::config_freq_rx_correction();
|
final_frequency = final_frequency + portapack::persistent_memory::config_freq_rx_correction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRALINE
|
||||||
|
/* The PRALINE tuning tables offset the analogue passband by a quarter of
|
||||||
|
* the ADC sample rate and have the FPGA rotate it back to DC, so the
|
||||||
|
* planner needs to know the AFE rate. See tuning.cpp. */
|
||||||
|
const uint32_t afe_rate = portapack::clock_manager.get_sampling_frequency()
|
||||||
|
<< portapack::clock_manager.get_resampling_n();
|
||||||
|
const auto tuning_config = tuning::config::create(
|
||||||
|
final_frequency,
|
||||||
|
afe_rate,
|
||||||
|
direction == rf::Direction::Transmit);
|
||||||
|
#else
|
||||||
const auto tuning_config = tuning::config::create(final_frequency);
|
const auto tuning_config = tuning::config::create(final_frequency);
|
||||||
|
#endif
|
||||||
if (tuning_config.is_valid()) {
|
if (tuning_config.is_valid()) {
|
||||||
first_if.disable();
|
first_if.disable();
|
||||||
|
|
||||||
@@ -339,6 +352,22 @@ bool set_tuning_frequency(const rf::Frequency frequency) {
|
|||||||
LPC_GPIO->CLR[0] = (1 << 13); // SGPIO12 = 0 (Q normal)
|
LPC_GPIO->CLR[0] = (1 << 13); // SGPIO12 = 0 (Q normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Program the FPGA's quarter-rate shift to match the offset the tuning
|
||||||
|
* table just applied to the analogue centre frequency. The gateware
|
||||||
|
* (hackrf/firmware/fpga/top/standard.py) takes both bits from the top
|
||||||
|
* of register 0x03 (rx_pstep):
|
||||||
|
* rx_pstep[6] -> quarter_shift.enable
|
||||||
|
* rx_pstep[7] -> quarter_shift.up
|
||||||
|
* which is exactly fpga_set_rx_quarter_shift_mode() in
|
||||||
|
* hackrf/firmware/common/fpga.c: write (mode & 0b11) << 6.
|
||||||
|
*
|
||||||
|
* These two settings MUST be programmed together. Tuning off-centre
|
||||||
|
* without the rotation puts the signal outside the decimation filter's
|
||||||
|
* passband and it disappears entirely; rotating without the offset
|
||||||
|
* moves the wanted signal off DC by the same amount. */
|
||||||
|
cached_quarter_shift = tuning_config.quarter_shift;
|
||||||
|
fpga_debug_register_write(FPGA_REG_RX_PSTEP, (cached_quarter_shift & 0b11) << 6);
|
||||||
|
|
||||||
ssp1_arbiter.invalidate();
|
ssp1_arbiter.invalidate();
|
||||||
#else
|
#else
|
||||||
baseband_cpld.set_invert(mixer_invert ^ baseband_invert);
|
baseband_cpld.set_invert(mixer_invert ^ baseband_invert);
|
||||||
@@ -469,6 +498,10 @@ int_fast8_t get_cached_lna_gain() {
|
|||||||
int_fast8_t get_cached_vga_gain() {
|
int_fast8_t get_cached_vga_gain() {
|
||||||
return cached_vga_gain;
|
return cached_vga_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t get_cached_quarter_shift() {
|
||||||
|
return cached_quarter_shift;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace first_if {
|
namespace first_if {
|
||||||
@@ -570,18 +603,11 @@ void register_write(const size_t register_number, uint32_t value) {
|
|||||||
void init() {
|
void init() {
|
||||||
fpga_set_mode(FPGA_MODE_RX);
|
fpga_set_mode(FPGA_MODE_RX);
|
||||||
|
|
||||||
// These FPGA registers control DC_BLOCK, Q-Inv, QUARTER SHIFT, and Decimation.
|
/* Same boot state as fpga_init() in hackrf/firmware/common/fpga.c. */
|
||||||
fpga_debug_register_write(FPGA_REG_CTRL, FPGA_CTRL_DC_BLOCK_EN); // DC_BLOCK=1, QUARTER_SHIFT=0, Q_INVERT=0
|
fpga_debug_register_write(FPGA_REG_CTRL, FPGA_CTRL_DC_BLOCK_EN);
|
||||||
fpga_debug_register_write(FPGA_REG_DECIM, 0x00); // RX_DECIM=No Decim
|
fpga_debug_register_write(FPGA_REG_DECIM, 0x00); // RX_DECIM = no decimation
|
||||||
|
fpga_debug_register_write(FPGA_REG_RX_PSTEP, 0x00); // quarter shift off
|
||||||
// RX Mode: Register 3 is RX Digital Gain. Start with 0dB (no shift).
|
fpga_debug_register_write(FPGA_REG_TX_CONTROL, 0x00);
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DIGITAL_GAIN, FPGA_RX_DEFAULT_DIGITAL_GAIN);
|
|
||||||
|
|
||||||
/* RX Mode: Initialize DC Block parameters to standard Praline values.
|
|
||||||
* 0x04 Width and 0x08 Adapt Rate are typical for 40MHz stability.
|
|
||||||
*/
|
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DC_BLOCK_WIDTH, FPGA_RX_DEFAULT_DC_WIDTH);
|
|
||||||
fpga_debug_register_write(FPGA_REG_RX_DC_ADAPT_RATE, FPGA_RX_DEFAULT_ADAPT_RATE);
|
|
||||||
|
|
||||||
ssp1_arbiter.invalidate(); // Force arbiter to reconfigure on next transfer
|
ssp1_arbiter.invalidate(); // Force arbiter to reconfigure on next transfer
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user