portapack-mayhem/firmware/application/radio.cpp
Jared Boone 0647f26707 Move SGPIO configuration and control to baseband firmware.
Addresses long-standing and annoying bug where SGPIO DMA channel would not disable -- and not configure cleanly next time it was needed. My theory is that the DMA channel couldn't disable until it got a request from the peripheral, and sometimes the peripheral was disabled before that last request.

Anyway, the baseband firmware should control the SGPIO, methinks, despite the impact on baseband code size.
2016-01-10 10:23:39 -08:00

163 lines
4.1 KiB
C++

/*
* 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.
*/
#include "radio.hpp"
#include "rf_path.hpp"
#include "max5864.hpp"
#include "baseband_cpld.hpp"
#include "portapack_shared_memory.hpp"
#include "tuning.hpp"
#include "spi_arbiter.hpp"
#include "hackrf_hal.hpp"
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
#include "portapack.hpp"
namespace radio {
static constexpr uint32_t ssp1_cpsr = 2;
static constexpr uint32_t ssp_scr(
const float pclk_f,
const uint32_t cpsr,
const float spi_f
) {
return static_cast<uint8_t>(pclk_f / cpsr / spi_f - 1);
}
static constexpr SPIConfig ssp_config_max2837 = {
.end_cb = NULL,
.ssport = gpio_max2837_select.port(),
.sspad = gpio_max2837_select.pad(),
.cr0 =
CR0_CLOCKRATE(ssp_scr(ssp1_pclk_f, ssp1_cpsr, max2837_spi_f))
| CR0_FRFSPI
| CR0_DSS16BIT
,
.cpsr = ssp1_cpsr,
};
static constexpr SPIConfig ssp_config_max5864 = {
.end_cb = NULL,
.ssport = gpio_max5864_select.port(),
.sspad = gpio_max5864_select.pad(),
.cr0 =
CR0_CLOCKRATE(ssp_scr(ssp1_pclk_f, ssp1_cpsr, max5864_spi_f))
| CR0_FRFSPI
| CR0_DSS8BIT
,
.cpsr = ssp1_cpsr,
};
static spi::arbiter::Arbiter ssp1_arbiter(portapack::ssp1);
static spi::arbiter::Target ssp1_target_max2837 {
ssp1_arbiter,
ssp_config_max2837
};
static spi::arbiter::Target ssp1_target_max5864 {
ssp1_arbiter,
ssp_config_max5864
};
static rf::path::Path rf_path;
rffc507x::RFFC507x first_if;
max2837::MAX2837 second_if { ssp1_target_max2837 };
static max5864::MAX5864 baseband_codec { ssp1_target_max5864 };
static baseband::CPLD baseband_cpld;
static rf::Direction direction { rf::Direction::Receive };
void init() {
rf_path.init();
first_if.init();
second_if.init();
baseband_codec.init();
baseband_cpld.init();
}
void set_direction(const rf::Direction new_direction) {
/* TODO: Refactor all the various "Direction" enumerations into one. */
/* TODO: Only make changes if direction changes, but beware of clock enabling. */
direction = new_direction;
second_if.set_mode((direction == rf::Direction::Transmit) ? max2837::Mode::Transmit : max2837::Mode::Receive);
rf_path.set_direction(direction);
baseband_codec.set_mode((direction == rf::Direction::Transmit) ? max5864::Mode::Transmit : max5864::Mode::Receive);
}
bool set_tuning_frequency(const rf::Frequency frequency) {
const auto tuning_config = tuning::config::create(frequency);
if( tuning_config.is_valid() ) {
first_if.disable();
if( tuning_config.first_lo_frequency ) {
first_if.set_frequency(tuning_config.first_lo_frequency);
first_if.enable();
}
const auto result_second_if = second_if.set_frequency(tuning_config.second_lo_frequency);
rf_path.set_band(tuning_config.rf_path_band);
baseband_cpld.set_q_invert(tuning_config.baseband_q_invert);
return result_second_if;
} else {
return false;
}
}
void set_rf_amp(const bool rf_amp) {
rf_path.set_rf_amp(rf_amp);
}
void set_lna_gain(const int_fast8_t db) {
second_if.set_lna_gain(db);
}
void set_vga_gain(const int_fast8_t db) {
second_if.set_vga_gain(db);
}
void set_baseband_filter_bandwidth(const uint32_t bandwidth_minimum) {
second_if.set_lpf_rf_bandwidth(bandwidth_minimum);
}
void set_baseband_decimation_by(const size_t n) {
baseband_cpld.set_decimation_by(n);
}
void disable() {
baseband_codec.set_mode(max5864::Mode::Shutdown);
second_if.set_mode(max2837::Mode::Standby);
first_if.disable();
set_rf_amp(false);
}
} /* namespace radio */