mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-29 09:16:30 -05:00
836 lines
18 KiB
C++
836 lines
18 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.
|
||
|
*/
|
||
|
|
||
|
#ifndef __RFFC507X_H__
|
||
|
#define __RFFC507X_H__
|
||
|
|
||
|
#include "rffc507x_spi.hpp"
|
||
|
|
||
|
#include <cstdint>
|
||
|
#include <array>
|
||
|
|
||
|
#include "dirty_registers.hpp"
|
||
|
#include "rf_path.hpp"
|
||
|
|
||
|
namespace rffc507x {
|
||
|
|
||
|
using reg_t = spi::reg_t;
|
||
|
using address_t = spi::address_t;
|
||
|
|
||
|
constexpr size_t reg_count = 31;
|
||
|
|
||
|
enum class Register : address_t {
|
||
|
LF = 0x00,
|
||
|
XO = 0x01,
|
||
|
CAL_TIME = 0x02,
|
||
|
VCO_CTRL = 0x03,
|
||
|
CT_CAL1 = 0x04,
|
||
|
CT_CAL2 = 0x05,
|
||
|
PLL_CAL1 = 0x06,
|
||
|
PLL_CAL2 = 0x07,
|
||
|
VCO_AUTO = 0x08,
|
||
|
PLL_CTRL = 0x09,
|
||
|
PLL_BIAS = 0x0a,
|
||
|
MIX_CONT = 0x0b,
|
||
|
P1_FREQ1 = 0x0c,
|
||
|
P1_FREQ2 = 0x0d,
|
||
|
P1_FREQ3 = 0x0e,
|
||
|
P2_FREQ1 = 0x0f,
|
||
|
P2_FREQ2 = 0x10,
|
||
|
P2_FREQ3 = 0x11,
|
||
|
FN_CTRL = 0x12,
|
||
|
EXT_MOD = 0x13,
|
||
|
FMOD = 0x14,
|
||
|
SDI_CTRL = 0x15,
|
||
|
GPO = 0x16,
|
||
|
T_VCO = 0x17,
|
||
|
IQMOD1 = 0x18,
|
||
|
IQMOD2 = 0x19,
|
||
|
IQMOD3 = 0x1a,
|
||
|
IQMOD4 = 0x1b,
|
||
|
T_CTRL = 0x1c,
|
||
|
DEV_CTRL = 0x1d,
|
||
|
TEST = 0x1e,
|
||
|
READBACK = 0x1f,
|
||
|
};
|
||
|
|
||
|
enum class Readback : uint8_t {
|
||
|
DeviceID = 0b0000,
|
||
|
TuningCalibration = 0b0001,
|
||
|
TuningVoltage = 0b0010,
|
||
|
StateMachine = 0b0011,
|
||
|
VCOCountL = 0b0100,
|
||
|
VCOCountH = 0b0101,
|
||
|
DCOffsetCal = 0b0110,
|
||
|
VCOMode = 0b0111,
|
||
|
};
|
||
|
|
||
|
struct LF_Type {
|
||
|
reg_t pllcpl : 3;
|
||
|
reg_t p1cpdef : 6;
|
||
|
reg_t p2cpdef : 6;
|
||
|
reg_t lfact : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(LF_Type) == sizeof(reg_t), "LF_Type type wrong size");
|
||
|
|
||
|
struct XO_Type {
|
||
|
reg_t suwait : 10;
|
||
|
reg_t xocf : 1;
|
||
|
reg_t xoc : 4;
|
||
|
reg_t xoch : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(XO_Type) == sizeof(reg_t), "XO_Type type wrong size");
|
||
|
|
||
|
struct CAL_TIME_Type {
|
||
|
reg_t tkv2 : 4;
|
||
|
reg_t tkv1 : 4;
|
||
|
reg_t reserved0 : 2;
|
||
|
reg_t tct : 5;
|
||
|
reg_t wait : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(CAL_TIME_Type) == sizeof(reg_t), "CAL_TIME_Type type wrong size");
|
||
|
|
||
|
struct VCO_CTRL_Type {
|
||
|
reg_t reserved0 : 1;
|
||
|
reg_t icpup : 2;
|
||
|
reg_t refst : 1;
|
||
|
reg_t xoi3 : 1;
|
||
|
reg_t xoi2 : 1;
|
||
|
reg_t xoi1 : 1;
|
||
|
reg_t kvpol : 1;
|
||
|
reg_t kvrng : 1;
|
||
|
reg_t kvavg : 2;
|
||
|
reg_t clkpl : 1;
|
||
|
reg_t ctpol : 1;
|
||
|
reg_t ctavg : 2;
|
||
|
reg_t xtvco : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(VCO_CTRL_Type) == sizeof(reg_t), "VCO_CTRL_Type type wrong size");
|
||
|
|
||
|
struct CT_CAL1_Type {
|
||
|
reg_t p1ctdef : 7;
|
||
|
reg_t p1ct : 1;
|
||
|
reg_t p1ctv : 5;
|
||
|
reg_t p1ctgain : 3;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(CT_CAL1_Type) == sizeof(reg_t), "CT_CAL1_Type type wrong size");
|
||
|
|
||
|
struct CT_CAL2_Type {
|
||
|
reg_t p2ctdef : 7;
|
||
|
reg_t p2ct : 1;
|
||
|
reg_t p2ctv : 5;
|
||
|
reg_t p2ctgain : 3;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(CT_CAL2_Type) == sizeof(reg_t), "CT_CAL2_Type type wrong size");
|
||
|
|
||
|
struct PLL_CAL1_Type {
|
||
|
reg_t reserved0 : 2;
|
||
|
reg_t p1sgn : 1;
|
||
|
reg_t p1kvgain : 3;
|
||
|
reg_t p1dn : 9;
|
||
|
reg_t p1kv : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(PLL_CAL1_Type) == sizeof(reg_t), "PLL_CAL1_Type type wrong size");
|
||
|
|
||
|
struct PLL_CAL2_Type {
|
||
|
reg_t reserved0 : 2;
|
||
|
reg_t p2sgn : 1;
|
||
|
reg_t p2kvgain : 3;
|
||
|
reg_t p2dn : 9;
|
||
|
reg_t p2kv : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(PLL_CAL2_Type) == sizeof(reg_t), "PLL_CAL2_Type type wrong size");
|
||
|
|
||
|
struct VCO_AUTO_Type {
|
||
|
reg_t reserved0 : 1;
|
||
|
reg_t ctmin : 7;
|
||
|
reg_t ctmax : 7;
|
||
|
reg_t auto_ : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(VCO_AUTO_Type) == sizeof(reg_t), "VCO_AUTO_Type type wrong size");
|
||
|
|
||
|
struct PLL_CTRL_Type {
|
||
|
reg_t plldy : 2;
|
||
|
reg_t aloi : 1;
|
||
|
reg_t relok : 1;
|
||
|
reg_t ldlev : 1;
|
||
|
reg_t lden : 1;
|
||
|
reg_t tvco : 5;
|
||
|
reg_t pllst : 1;
|
||
|
reg_t clkdiv : 3;
|
||
|
reg_t divby : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(PLL_CTRL_Type) == sizeof(reg_t), "PLL_CTRL_Type type wrong size");
|
||
|
|
||
|
struct PLL_BIAS_Type {
|
||
|
reg_t p2vcoi : 3;
|
||
|
reg_t p2loi : 4;
|
||
|
reg_t reserved0 : 1;
|
||
|
reg_t p1vcoi : 3;
|
||
|
reg_t p1loi : 4;
|
||
|
reg_t reserved1 : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(PLL_BIAS_Type) == sizeof(reg_t), "PLL_BIAS_Type type wrong size");
|
||
|
|
||
|
struct MIX_CONT_Type {
|
||
|
reg_t reserved0 : 9;
|
||
|
reg_t p2mixidd : 3;
|
||
|
reg_t p1mixidd : 3;
|
||
|
reg_t fulld : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(MIX_CONT_Type) == sizeof(reg_t), "MIX_CONT_Type type wrong size");
|
||
|
|
||
|
struct P1_FREQ1_Type {
|
||
|
reg_t p1vcosel : 2;
|
||
|
reg_t p1presc : 2;
|
||
|
reg_t p1lodiv : 3;
|
||
|
reg_t p1n : 9;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(P1_FREQ1_Type) == sizeof(reg_t), "P1_FREQ1_Type type wrong size");
|
||
|
|
||
|
struct P1_FREQ2_Type {
|
||
|
reg_t p1nmsb : 16;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(P1_FREQ2_Type) == sizeof(reg_t), "P1_FREQ2_Type type wrong size");
|
||
|
|
||
|
struct P1_FREQ3_Type {
|
||
|
reg_t reserved0 : 8;
|
||
|
reg_t p1nlsb : 8;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(P1_FREQ3_Type) == sizeof(reg_t), "P1_FREQ3_Type type wrong size");
|
||
|
|
||
|
struct P2_FREQ1_Type {
|
||
|
reg_t p2vcosel : 2;
|
||
|
reg_t p2presc : 2;
|
||
|
reg_t p2lodiv : 3;
|
||
|
reg_t p2n : 9;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(P2_FREQ1_Type) == sizeof(reg_t), "P2_FREQ1_Type type wrong size");
|
||
|
|
||
|
struct P2_FREQ2_Type {
|
||
|
reg_t p2nmsb : 16;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(P2_FREQ2_Type) == sizeof(reg_t), "P2_FREQ2_Type type wrong size");
|
||
|
|
||
|
struct P2_FREQ3_Type {
|
||
|
reg_t reserved0 : 8;
|
||
|
reg_t p2nlsb : 8;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(P2_FREQ3_Type) == sizeof(reg_t), "P2_FREQ3_Type type wrong size");
|
||
|
|
||
|
struct FN_CTRL_Type {
|
||
|
reg_t reserved0 : 1;
|
||
|
reg_t tzps : 1;
|
||
|
reg_t dmode : 1;
|
||
|
reg_t fm : 1;
|
||
|
reg_t dith : 1;
|
||
|
reg_t mode : 1;
|
||
|
reg_t phsalndly : 2;
|
||
|
reg_t phsalngain : 3;
|
||
|
reg_t phaln : 1;
|
||
|
reg_t sdm : 2;
|
||
|
reg_t dithr : 1;
|
||
|
reg_t fnz : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(FN_CTRL_Type) == sizeof(reg_t), "FN_CTRL_Type type wrong size");
|
||
|
|
||
|
struct EXT_MOD_Type {
|
||
|
reg_t reserved0 : 10;
|
||
|
reg_t modstep : 4;
|
||
|
reg_t modsetup : 2;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(EXT_MOD_Type) == sizeof(reg_t), "EXT_MOD_Type type wrong size");
|
||
|
|
||
|
struct FMOD_Type {
|
||
|
reg_t modulation : 16;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(FMOD_Type) == sizeof(reg_t), "FMOD_Type type wrong size");
|
||
|
|
||
|
struct SDI_CTRL_Type {
|
||
|
reg_t reserved0 : 1;
|
||
|
reg_t reset : 1;
|
||
|
reg_t reserved1 : 9;
|
||
|
reg_t addr : 1;
|
||
|
reg_t fourwire : 1;
|
||
|
reg_t mode : 1;
|
||
|
reg_t enbl : 1;
|
||
|
reg_t sipin : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(SDI_CTRL_Type) == sizeof(reg_t), "SDI_CTRL_Type type wrong size");
|
||
|
|
||
|
struct GPO_Type {
|
||
|
reg_t lock : 1;
|
||
|
reg_t gate : 1;
|
||
|
reg_t p1gpo : 7;
|
||
|
reg_t p2gpo : 7;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(GPO_Type) == sizeof(reg_t), "GPO_Type type wrong size");
|
||
|
|
||
|
struct T_VCO_Type {
|
||
|
reg_t reserved0 : 7;
|
||
|
reg_t curve_vco3 : 3;
|
||
|
reg_t curve_vco2 : 3;
|
||
|
reg_t curve_vco1 : 3;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(T_VCO_Type) == sizeof(reg_t), "T_VCO_Type type wrong size");
|
||
|
|
||
|
struct IQMOD1_Type {
|
||
|
reg_t bufdc : 2;
|
||
|
reg_t divbias : 1;
|
||
|
reg_t calblk : 1;
|
||
|
reg_t calnul : 1;
|
||
|
reg_t calon : 1;
|
||
|
reg_t lobias : 2;
|
||
|
reg_t modbias : 3;
|
||
|
/* Also defined as ctrl : 5 */
|
||
|
reg_t modiv : 1;
|
||
|
reg_t mod : 1;
|
||
|
reg_t txlo : 1;
|
||
|
reg_t bbgm : 1;
|
||
|
reg_t ctrl : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(IQMOD1_Type) == sizeof(reg_t), "IQMOD1_Type type wrong size");
|
||
|
|
||
|
struct IQMOD2_Type {
|
||
|
reg_t modbuf : 2;
|
||
|
reg_t mod : 2;
|
||
|
reg_t calatten : 2;
|
||
|
reg_t rctune : 6;
|
||
|
reg_t bbatten : 4;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(IQMOD2_Type) == sizeof(reg_t), "IQMOD2_Type type wrong size");
|
||
|
|
||
|
struct IQMOD3_Type {
|
||
|
/* Documentation error */
|
||
|
reg_t reserved0 : 3;
|
||
|
reg_t dacen : 1;
|
||
|
reg_t bufdacq : 6;
|
||
|
reg_t bufdaci : 6;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(IQMOD3_Type) == sizeof(reg_t), "IQMOD3_Type type wrong size");
|
||
|
|
||
|
struct IQMOD4_Type {
|
||
|
/* Documentation error */
|
||
|
reg_t bufbias2 : 2;
|
||
|
reg_t bufbias1 : 2;
|
||
|
reg_t moddacq : 6;
|
||
|
reg_t moddaci : 6;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(IQMOD4_Type) == sizeof(reg_t), "IQMOD4_Type type wrong size");
|
||
|
|
||
|
struct T_CTRL_Type {
|
||
|
reg_t reserved0 : 5;
|
||
|
reg_t v_test : 1;
|
||
|
reg_t ldo_by : 1;
|
||
|
reg_t ext_filt : 1;
|
||
|
reg_t ref_sel : 1;
|
||
|
reg_t filt_ctrl : 2;
|
||
|
reg_t fc_en : 1;
|
||
|
reg_t tbl_sel : 2;
|
||
|
reg_t tc_en : 2;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(T_CTRL_Type) == sizeof(reg_t), "T_CTRL_Type type wrong size");
|
||
|
|
||
|
struct DEV_CTRL_Type {
|
||
|
reg_t reserved0 : 1;
|
||
|
reg_t bypas : 1;
|
||
|
reg_t ctclk : 1;
|
||
|
reg_t dac : 1;
|
||
|
reg_t cpd : 1;
|
||
|
reg_t cpu : 1;
|
||
|
reg_t rsmstopst : 5;
|
||
|
reg_t rsmst : 1;
|
||
|
reg_t readsel : 4;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(DEV_CTRL_Type) == sizeof(reg_t), "DEV_CTRL_Type type wrong size");
|
||
|
|
||
|
struct TEST_Type {
|
||
|
reg_t lfsrd : 1;
|
||
|
reg_t rcbyp : 1;
|
||
|
reg_t rgbyp : 1;
|
||
|
reg_t lfsrt : 1;
|
||
|
reg_t lfsrgatetime : 4;
|
||
|
reg_t lfsrp : 1;
|
||
|
reg_t lfsr : 1;
|
||
|
reg_t tsel : 2;
|
||
|
reg_t tmux : 3;
|
||
|
reg_t ten : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(TEST_Type) == sizeof(reg_t), "TEST_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0000_Type {
|
||
|
reg_t mrev_id : 3;
|
||
|
reg_t dev_id : 13;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0000_Type) == sizeof(reg_t), "READBACK_0000_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0001_Type {
|
||
|
reg_t reserved0 : 1;
|
||
|
reg_t ctfail : 1;
|
||
|
reg_t cp_cal : 6;
|
||
|
reg_t ct_cal : 7;
|
||
|
reg_t lock : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0001_Type) == sizeof(reg_t), "READBACK_0001_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0010_Type {
|
||
|
reg_t v1_cal : 8;
|
||
|
reg_t v0_cal : 8;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0010_Type) == sizeof(reg_t), "READBACK_0010_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0011_Type {
|
||
|
reg_t reserved0 : 9;
|
||
|
reg_t f_errflag : 2;
|
||
|
reg_t rsm_state : 5;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0011_Type) == sizeof(reg_t), "READBACK_0011_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0100_Type {
|
||
|
reg_t vco_count_l : 16;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0100_Type) == sizeof(reg_t), "READBACK_0100_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0101_Type {
|
||
|
reg_t vco_count_h : 16;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0101_Type) == sizeof(reg_t), "READBACK_0101_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0110_Type {
|
||
|
reg_t reserved0 : 14;
|
||
|
reg_t cal_fbq : 1;
|
||
|
reg_t cal_fbi : 1;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0110_Type) == sizeof(reg_t), "READBACK_0110_Type type wrong size");
|
||
|
|
||
|
struct READBACK_0111_Type {
|
||
|
reg_t reserved0 : 11;
|
||
|
reg_t vco_tc_curve : 3;
|
||
|
reg_t vco_sel : 2;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(READBACK_0111_Type) == sizeof(reg_t), "READBACK_0111_Type type wrong size");
|
||
|
|
||
|
struct Register_Type {
|
||
|
LF_Type lf;
|
||
|
XO_Type xo;
|
||
|
CAL_TIME_Type cal_time;
|
||
|
VCO_CTRL_Type vco_ctrl;
|
||
|
CT_CAL1_Type ct_cal1;
|
||
|
CT_CAL2_Type ct_cal2;
|
||
|
PLL_CAL1_Type pll_cal1;
|
||
|
PLL_CAL2_Type pll_cal2;
|
||
|
VCO_AUTO_Type vco_auto;
|
||
|
PLL_CTRL_Type pll_ctrl;
|
||
|
PLL_BIAS_Type pll_bias;
|
||
|
MIX_CONT_Type mix_cont;
|
||
|
P1_FREQ1_Type p1_freq1;
|
||
|
P1_FREQ2_Type p1_freq2;
|
||
|
P1_FREQ3_Type p1_freq3;
|
||
|
P2_FREQ1_Type p2_freq1;
|
||
|
P2_FREQ2_Type p2_freq2;
|
||
|
P2_FREQ3_Type p2_freq3;
|
||
|
FN_CTRL_Type fn_ctrl;
|
||
|
EXT_MOD_Type ext_mod;
|
||
|
FMOD_Type fmod;
|
||
|
SDI_CTRL_Type sdi_ctrl;
|
||
|
GPO_Type gpo;
|
||
|
T_VCO_Type t_vco;
|
||
|
IQMOD1_Type iqmod1;
|
||
|
IQMOD2_Type iqmod2;
|
||
|
IQMOD3_Type iqmod3;
|
||
|
IQMOD4_Type iqmod4;
|
||
|
T_CTRL_Type t_ctrl;
|
||
|
DEV_CTRL_Type dev_ctrl;
|
||
|
TEST_Type test;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(Register_Type) == reg_count * sizeof(reg_t), "Register_Type wrong size");
|
||
|
|
||
|
struct RegisterMap {
|
||
|
constexpr RegisterMap(
|
||
|
Register_Type values
|
||
|
) : r(values)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
union {
|
||
|
Register_Type r;
|
||
|
std::array<reg_t, reg_count> w;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(RegisterMap) == reg_count * sizeof(reg_t), "RegisterMap type wrong size");
|
||
|
#if 0
|
||
|
struct ReadbackType {
|
||
|
union {
|
||
|
READBACK_0000_Type readback_0000;
|
||
|
READBACK_0001_Type readback_0001;
|
||
|
READBACK_0010_Type readback_0010;
|
||
|
READBACK_0011_Type readback_0011;
|
||
|
READBACK_0100_Type readback_0100;
|
||
|
READBACK_0101_Type readback_0101;
|
||
|
READBACK_0110_Type readback_0110;
|
||
|
READBACK_0111_Type readback_0111;
|
||
|
reg_t w;
|
||
|
};
|
||
|
};
|
||
|
#endif
|
||
|
#if 0
|
||
|
/* Revision 1 devices (mrev_id = 001):
|
||
|
* RFFC2071/2072/5071/5072, RFMD2080/2081
|
||
|
*/
|
||
|
constexpr RegisterMap default_revision_1 { std::array<reg_t, reg_count> {
|
||
|
0xbefa, 0x4064, 0x9055, 0x2d02,
|
||
|
0xb0bf, 0xb0bf, 0x0028, 0x0028,
|
||
|
0xfc06, 0x8220, 0x0202, 0x4800,
|
||
|
0x2324, 0x6276, 0x2700, 0x2f16,
|
||
|
0x3b13, 0xb100, 0x2a80, 0x0000,
|
||
|
0x0000, 0x0000, 0x0000, 0x0000,
|
||
|
0x0283, 0xf00f, 0x0000, 0x000f,
|
||
|
0x0000, 0x1000, 0x0001,
|
||
|
} };
|
||
|
|
||
|
/* Revision 2 devices (mrev_id = 010):
|
||
|
* RFFC2071A/2072A/5071A/5072A
|
||
|
*/
|
||
|
constexpr RegisterMap default_revision_2 { std::array<reg_t, reg_count> {
|
||
|
0xbefa, 0x4064, 0x9055, 0x2d02,
|
||
|
0xacbf, 0xacbf, 0x0028, 0x0028,
|
||
|
0xff00, 0x8220, 0x0202, 0x4800,
|
||
|
0x1a94, 0xd89d, 0x8900, 0x1e84,
|
||
|
0x89d8, 0x9d00, 0x2a80, 0x0000,
|
||
|
0x0000, 0x0000, 0x0000, 0x4900,
|
||
|
0x0281, 0xf00f, 0x0000, 0x0005,
|
||
|
0xc840, 0x1000, 0x0005,
|
||
|
} };
|
||
|
#endif
|
||
|
constexpr RegisterMap default_hackrf_one { Register_Type {
|
||
|
/* Started with recommended defaults for revision 1 devices
|
||
|
* (mrev_id = 001), RFFC2071/2072/5071/5072, RFMD2080/2081.
|
||
|
* Modified according to mixer programming guide.
|
||
|
*/
|
||
|
.lf = { /* 0 */
|
||
|
.pllcpl = 0b010,
|
||
|
.p1cpdef = 0b011111,
|
||
|
.p2cpdef = 0b011111,
|
||
|
.lfact = 1,
|
||
|
},
|
||
|
.xo = { /* 1 */
|
||
|
.suwait = 0b0001100100,
|
||
|
.xocf = 0b0,
|
||
|
.xoc = 0b1000,
|
||
|
.xoch = 0b0,
|
||
|
},
|
||
|
.cal_time = { /* 2 */
|
||
|
.tkv2 = 0b0101,
|
||
|
.tkv1 = 0b0101,
|
||
|
.reserved0 = 0b00,
|
||
|
.tct = 0b00100,
|
||
|
.wait = 0b1,
|
||
|
},
|
||
|
.vco_ctrl = { /* 3 */
|
||
|
.reserved0 = 0b0,
|
||
|
.icpup = 0b01,
|
||
|
.refst = 0b0,
|
||
|
.xoi3 = 0b0,
|
||
|
.xoi2 = 0b0,
|
||
|
.xoi1 = 0b0,
|
||
|
.kvpol = 0b0,
|
||
|
.kvrng = 0b1,
|
||
|
.kvavg = 0b10,
|
||
|
.clkpl = 0b1,
|
||
|
.ctpol = 0b0,
|
||
|
.ctavg = 0b01,
|
||
|
.xtvco = 0b0,
|
||
|
},
|
||
|
.ct_cal1 = { /* 4 */
|
||
|
.p1ctdef = 0b0111111,
|
||
|
.p1ct = 0b1,
|
||
|
.p1ctv = 12, /* RFMD recommneded change: 16 -> 12 */
|
||
|
.p1ctgain = 0b101,
|
||
|
},
|
||
|
.ct_cal2 = { /* 5 */
|
||
|
.p2ctdef = 0b0111111,
|
||
|
.p2ct = 0b1,
|
||
|
.p2ctv = 12, /* RFMD recommneded change: 16 -> 12 */
|
||
|
.p2ctgain = 0b101,
|
||
|
},
|
||
|
.pll_cal1 = { /* 6 */
|
||
|
.reserved0 = 0b00,
|
||
|
.p1sgn = 0b0,
|
||
|
.p1kvgain = 0b101,
|
||
|
.p1dn = 0b000000000,
|
||
|
.p1kv = 0b0,
|
||
|
},
|
||
|
.pll_cal2 = { /* 7 */
|
||
|
.reserved0 = 0b00,
|
||
|
.p2sgn = 0b0,
|
||
|
.p2kvgain = 0b101,
|
||
|
.p2dn = 0b000000000,
|
||
|
.p2kv = 0b0,
|
||
|
},
|
||
|
.vco_auto = { /* 8 */
|
||
|
.reserved0 = 0b0,
|
||
|
.ctmin = 0, /* RFMD recommended change: 3 -> 0 */
|
||
|
.ctmax = 127, /* RFMD recommended change: 124 -> 127 */
|
||
|
.auto_ = 0b1,
|
||
|
},
|
||
|
.pll_ctrl = { /* 9 */
|
||
|
.plldy = 0b00,
|
||
|
.aloi = 0b0,
|
||
|
.relok = 0b0,
|
||
|
.ldlev = 0b0,
|
||
|
.lden = 0b1,
|
||
|
.tvco = 0b01000,
|
||
|
.pllst = 0b0,
|
||
|
.clkdiv = 0b000,
|
||
|
.divby = 0b1,
|
||
|
},
|
||
|
.pll_bias = { /* 10 */
|
||
|
.p2vcoi = 0b010,
|
||
|
.p2loi = 0b0000,
|
||
|
.reserved0 = 0b0,
|
||
|
.p1vcoi = 0b010,
|
||
|
.p1loi = 0b0000,
|
||
|
.reserved1 = 0b0,
|
||
|
},
|
||
|
.mix_cont = { /* 11 */
|
||
|
.reserved0 = 0b000000000,
|
||
|
.p2mixidd = 4,
|
||
|
.p1mixidd = 4,
|
||
|
.fulld = 0b0, /* Part on HackRF is half-duplex (single mixer) */
|
||
|
},
|
||
|
.p1_freq1 = { /* 12 */
|
||
|
.p1vcosel = 0b00, /* RFMD VCO bank 1 configuration from A series part */
|
||
|
.p1presc = 0b01,
|
||
|
.p1lodiv = 0b001,
|
||
|
.p1n = 0b000110101,
|
||
|
},
|
||
|
.p1_freq2 = { /* 13 */
|
||
|
.p1nmsb = 0xd89d, /* RFMD VCO bank 1 configuration from A series part */
|
||
|
},
|
||
|
.p1_freq3 = { /* 14 */
|
||
|
.reserved0 = 0b00000000, /* RFMD VCO bank 1 configuration from A series part */
|
||
|
.p1nlsb = 0x89,
|
||
|
},
|
||
|
.p2_freq1 = { /* 15 */
|
||
|
.p2vcosel = 0b00, /* RFMD VCO bank 2 configuration from A series part */
|
||
|
.p2presc = 0b01,
|
||
|
.p2lodiv = 0b000,
|
||
|
.p2n = 0b000111101,
|
||
|
},
|
||
|
.p2_freq2 = { /* 16 */
|
||
|
.p2nmsb = 0x89d8, /* RFMD VCO bank 2 configuration from A series part */
|
||
|
},
|
||
|
.p2_freq3 = { /* 17 */
|
||
|
.reserved0 = 0b00000000, /* RFMD VCO bank 2 configuration from A series part */
|
||
|
.p2nlsb = 0x9d,
|
||
|
},
|
||
|
.fn_ctrl = { /* 18 */
|
||
|
.reserved0 = 0b0,
|
||
|
.tzps = 0b0,
|
||
|
.dmode = 0b0,
|
||
|
.fm = 0b0,
|
||
|
.dith = 0b0,
|
||
|
.mode = 0b0,
|
||
|
.phsalndly = 0b10,
|
||
|
.phsalngain = 0b010,
|
||
|
.phaln = 0b1,
|
||
|
.sdm = 0b10,
|
||
|
.dithr = 0b0,
|
||
|
.fnz = 0b0,
|
||
|
},
|
||
|
.ext_mod = { /* 19 */
|
||
|
.reserved0 = 0b0000000000,
|
||
|
.modstep = 0b0000,
|
||
|
.modsetup = 0b00,
|
||
|
},
|
||
|
.fmod = { /* 20 */
|
||
|
.modulation = 0x0000,
|
||
|
},
|
||
|
.sdi_ctrl = { /* 21 */
|
||
|
.reserved0 = 0b0,
|
||
|
.reset = 0b0,
|
||
|
.reserved1 = 0b000000000,
|
||
|
.addr = 0b0,
|
||
|
.fourwire = 0b0, /* Use three pin SPI mode */
|
||
|
.mode = 0b1, /* Active PLL register bank 2, active mixer 2 */
|
||
|
.enbl = 0b0, /* Part is initially disabled */
|
||
|
.sipin = 0b1, /* Control MODE, ENBL from SPI bus */
|
||
|
},
|
||
|
.gpo = { /* 22 */
|
||
|
.lock = 0b1, /* Present LOCK signal on GPIO4/LD/DO, HackRF One test point P6 */
|
||
|
.gate = 0b1, /* GPOs active even when part is disabled (ENBL=0) */
|
||
|
.p1gpo = 0b0000001, /* Turn on GPO1 to turn *off* !ANT_BIAS (GPO numbering is one-based) */
|
||
|
.p2gpo = 0b0000001, /* Turn on GPO1 to turn *off* !ANT_BIAS (GPO numbering is one-based) */
|
||
|
},
|
||
|
.t_vco = { /* 23 */
|
||
|
.reserved0 = 0b0000000,
|
||
|
.curve_vco3 = 0b000,
|
||
|
.curve_vco2 = 0b000,
|
||
|
.curve_vco1 = 0b000,
|
||
|
},
|
||
|
.iqmod1 = { /* 24 */
|
||
|
.bufdc = 0b11,
|
||
|
.divbias = 0b0,
|
||
|
.calblk = 0b0,
|
||
|
.calnul = 0b0,
|
||
|
.calon = 0b0,
|
||
|
.lobias = 0b10,
|
||
|
.modbias = 0b010,
|
||
|
.modiv = 0b0,
|
||
|
.mod = 0b0,
|
||
|
.txlo = 0b0,
|
||
|
.bbgm = 0b0,
|
||
|
.ctrl = 0b0,
|
||
|
},
|
||
|
.iqmod2 = { /* 25 */
|
||
|
.modbuf = 0b11,
|
||
|
.mod = 0b11,
|
||
|
.calatten = 0b00,
|
||
|
.rctune = 0b000000,
|
||
|
.bbatten = 0b1111,
|
||
|
},
|
||
|
.iqmod3 = { /* 26 */
|
||
|
.reserved0 = 0b000,
|
||
|
.dacen = 0b0,
|
||
|
.bufdacq = 0b000000,
|
||
|
.bufdaci = 0b000000,
|
||
|
},
|
||
|
.iqmod4 = { /* 27 */
|
||
|
.bufbias2 = 0b11,
|
||
|
.bufbias1 = 0b11,
|
||
|
.moddacq = 0b000000,
|
||
|
.moddaci = 0b000000,
|
||
|
},
|
||
|
.t_ctrl = { /* 28 */
|
||
|
.reserved0 = 0b00000,
|
||
|
.v_test = 0b0,
|
||
|
.ldo_by = 0b0,
|
||
|
.ext_filt = 0b0,
|
||
|
.ref_sel = 0b0,
|
||
|
.filt_ctrl = 0b00,
|
||
|
.fc_en = 0b0,
|
||
|
.tbl_sel = 0b00,
|
||
|
.tc_en = 0b00,
|
||
|
},
|
||
|
.dev_ctrl = { /* 29 */
|
||
|
.reserved0 = 0b0,
|
||
|
.bypas = 0b0,
|
||
|
.ctclk = 0b0,
|
||
|
.dac = 0b0,
|
||
|
.cpd = 0b0,
|
||
|
.cpu = 0b0,
|
||
|
.rsmstopst = 0b00000,
|
||
|
.rsmst = 0b0,
|
||
|
.readsel = 0b0001,
|
||
|
},
|
||
|
.test = { /* 30 */
|
||
|
.lfsrd = 0b1,
|
||
|
.rcbyp = 0b0,
|
||
|
.rgbyp = 0b1, /* RFMD recommended change: 0 -> 1 */
|
||
|
.lfsrt = 0b0,
|
||
|
.lfsrgatetime = 0b0000,
|
||
|
.lfsrp = 0b0,
|
||
|
.lfsr = 0b0,
|
||
|
.tsel = 0b00,
|
||
|
.tmux = 0b000,
|
||
|
.ten = 0b0,
|
||
|
},
|
||
|
} };
|
||
|
|
||
|
class RFFC507x {
|
||
|
public:
|
||
|
void init();
|
||
|
void reset();
|
||
|
|
||
|
void flush();
|
||
|
|
||
|
void enable();
|
||
|
void disable();
|
||
|
|
||
|
void set_mixer_current(const uint8_t value);
|
||
|
void set_frequency(const rf::Frequency lo_frequency);
|
||
|
|
||
|
RegisterMap registers();
|
||
|
|
||
|
private:
|
||
|
spi::SPI _bus;
|
||
|
|
||
|
RegisterMap _map { default_hackrf_one };
|
||
|
DirtyRegisters<Register, reg_count> _dirty;
|
||
|
|
||
|
void write(const address_t reg_num, const reg_t value);
|
||
|
reg_t read(const address_t reg_num);
|
||
|
|
||
|
void write(const Register reg, const reg_t value);
|
||
|
reg_t read(const Register reg);
|
||
|
|
||
|
void flush_one(const Register reg);
|
||
|
|
||
|
reg_t readback(const Readback readback);
|
||
|
|
||
|
void init_for_best_performance();
|
||
|
};
|
||
|
|
||
|
} /* rffc507x */
|
||
|
|
||
|
#endif/*__RFFC507X_H__*/
|