You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dvmfirmware-hs/ADF7021.cpp

1440 lines
48 KiB

/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017,2018,2019,2020 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* Some of the code is based on work of Guus Van Dooren PE1PLM:
* https://github.com/ki6zum/gmsk-dstar/blob/master/firmware/dvmega/dvmega.ino
*
* 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 of the License, 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; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <math.h>
#include "Globals.h"
#include "ADF7021.h"
#if defined(ENABLE_ADF7021)
// ---------------------------------------------------------------------------
// Globals
// ---------------------------------------------------------------------------
volatile bool toTxRequest = false;
volatile bool toRxRequest = false;
volatile bool even = true;
static uint32_t lastClk = 2U;
volatile uint32_t AD7021_CONTROL;
uint32_t ADF7021_RX_REG0;
uint32_t ADF7021_TX_REG0;
uint32_t ADF7021_REG1;
uint32_t ADF7021_REG2;
uint32_t ADF7021_REG3;
uint32_t ADF7021_REG4;
uint32_t ADF7021_REG10;
uint32_t ADF7021_REG13;
uint32_t div2;
uint32_t f_div;
uint8_t RX_N_Divider; // Rx - 8-bit Integer_N
uint16_t RX_F_Divider; // Rx - 15-bit Frational_N
uint8_t TX_N_Divider; // Tx - 8-bit Integer_N
uint16_t TX_F_Divider; // Tx - 15-bit Frational_N
uint16_t dmrDev;
uint16_t p25Dev;
uint16_t nxdnDev;
int8_t m_dmrDiscBWAdj;
int8_t m_p25DiscBWAdj;
int8_t m_nxdnDiscBWAdj;
int8_t m_dmrPostBWAdj;
int8_t m_p25PostBWAdj;
int8_t m_nxdnPostBWAdj;
bool m_afcEnable;
uint8_t m_afcKI;
uint8_t m_afcKP;
uint8_t m_afcRange;
// ---------------------------------------------------------------------------
// Global Functions
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
static void AD7021_IOCTL_Shift()
{
for (int i = 31; i >= 0; i--) {
if (ADF_BIT_READ(AD7021_CONTROL, i) == HIGH)
io.SDATA(HIGH);
else
io.SDATA(LOW);
io.delayBit();
io.SCLK(HIGH);
io.delayBit();
io.SCLK(LOW);
}
// to keep SDATA signal at defined level when idle (not required)
io.SDATA(LOW);
}
/// <summary>
///
/// </summary>
static void AD7021_IOCTL_SLEPulse()
{
io.SLE1(HIGH);
io.delayBit();
io.SLE1(LOW);
}
/// <summary>
///
/// </summary>
/// <param name="doSle"></param>
static void AD7021_1_IOCTL(bool doSle = true)
{
AD7021_IOCTL_Shift();
if (doSle)
AD7021_IOCTL_SLEPulse();
}
#if defined(DUPLEX)
/// <summary>
///
/// </summary>
static void AD7021_2_IOCTL_SLEPulse()
{
io.SLE2(HIGH);
io.delayBit();
io.SLE2(LOW);
}
/// <summary>
///
/// </summary>
/// <param name="doSle"></param>
static void AD7021_2_IOCTL(bool doSle = true)
{
AD7021_IOCTL_Shift();
if (doSle)
AD7021_2_IOCTL_SLEPulse();
}
#endif
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Hardware interrupt handler.
/// </summary>
void IO::interrupt1()
{
uint8_t bit = 0U;
if (!m_started)
return;
uint8_t clk = CLK();
// this is to prevent activation by spurious interrupts
// which seem to happen if you send out an control word
// needs investigation
// this workaround will fail if only rising or falling edge
// is used to trigger the interrupt !!!!
// TODO: figure out why sending the control word seems to issue interrupts
// possibly this is a design problem of the RF7021 board or too long wires
// on the breadboard build
// but normally this will not hurt too much
if (clk == lastClk)
return;
else
lastClk = clk;
// we set the TX bit at TXD low, sampling of ADF7021 happens at rising clock
if (m_tx && clk == 0U) {
m_txBuffer.get(bit, m_control);
even = !even;
#if defined(BIDIR_DATA_PIN)
if (bit)
setRXDInt(HIGH);
else
setRXDInt(LOW);
#else
if (bit)
setTXDInt(HIGH);
else
setTXDInt(LOW);
#endif
// wait a brief period before raising SLE
if (toTxRequest == true) {
asm volatile(
"nop \n\t"
"nop \n\t"
"nop \n\t"
);
// SLE Pulse, should be moved out of here into class method
// according to datasheet in 4FSK we have to deliver this before 1/4 tbit == 26uS
SLE1(HIGH);
asm volatile(
"nop \n\t"
"nop \n\t"
"nop \n\t"
);
SLE1(LOW);
SDATA(LOW);
// now do housekeeping
toTxRequest = false;
// first tranmittted bit is always the odd bit
even = ADF7021_EVEN_BIT;
}
}
// we sample the RX bit at rising TXD clock edge, so TXD must be 1 and we are not in tx mode
if (!m_tx && clk == 1U && !m_duplex) {
if (RXD1())
bit = 1U;
else
bit = 0U;
m_rxBuffer.put(bit, m_control);
}
if (toRxRequest && even == ADF7021_EVEN_BIT && m_tx && clk == 0U) {
// that is absolutely crucial in 4FSK, see datasheet:
// enable sle after 1/4 tBit == 26uS when sending MSB (even == false) and clock is low
delayUS(26U);
// SLE Pulse, should be moved out of here into class method
SLE1(HIGH);
asm volatile(
"nop \n\t"
"nop \n\t"
"nop \n\t"
);
SLE1(LOW);
SDATA(LOW);
// now do housekeeping
m_tx = false;
toRxRequest = false;
// last tranmittted bit is always the even bit
// since the current bit is a transitional "don't care" bit, never transmitted
even = !ADF7021_EVEN_BIT;
}
m_watchdog++;
m_int1Counter++;
}
#if defined(DUPLEX)
/// <summary>
/// Hardware interrupt handler.
/// </summary>
void IO::interrupt2()
{
uint8_t bit = 0U;
if (m_duplex) {
if (RXD2())
bit = 1U;
else
bit = 0U;
m_rxBuffer.put(bit, m_control);
}
m_int2Counter++;
}
#endif
/// <summary>
/// Sets the ADF7021 RF configuration.
/// </summary>
/// <param name="modemState"></param>
/// <param name="reset"></param>
void IO::rf1Conf(DVM_STATE modemState, bool reset)
{
uint32_t txFrequencyTmp, rxFrequencyTmp;
DEBUG4("IO::rf1Conf(): ADF1 (Tx/Rx); modemState/reset/rxGain", modemState, reset, m_gainMode);
#if defined (ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS)
io.checkBand(m_rxFrequency, m_txFrequency);
#endif
// Toggle CE pin for ADF7021 reset
if (reset) {
CE(LOW);
delayReset();
CE(HIGH);
delayReset();
}
/*
** VCO/Oscillator (Register 1)
*/
configureBand();
/*
** Fractional-N Synthesizer (Register 0)
*/
float divider = 0.0f;
if (div2 == 1U)
divider = (m_rxFrequency - 100000) / (ADF7021_PFD / 2U);
else
divider = (m_rxFrequency - 100000) / ADF7021_PFD;
// calculate Integer_N and Fractional_N divider values for Rx
RX_N_Divider = floor(divider);
divider = (divider - RX_N_Divider) * 32768;
RX_F_Divider = floor(divider + 0.5);
// setup rx register 0
ADF7021_RX_REG0 = (uint32_t)ADF7021_REG0_ADDR; // Register Address 0
#if defined(BIDIR_DATA_PIN)
ADF7021_RX_REG0 |= (uint32_t)0b01001 << 27; // Mux regulator/receive
#else
ADF7021_RX_REG0 |= (uint32_t)0b01011 << 27; // Mux regulator/uart-spi enabled/receive
#endif
ADF7021_RX_REG0 |= (uint32_t)RX_N_Divider << 19; // Frequency - 8-bit Int_N
ADF7021_RX_REG0 |= (uint32_t)RX_F_Divider << 4; // Frequency - 15-bit Frac_N
if (div2 == 1U)
divider = m_txFrequency / (ADF7021_PFD / 2U);
else
divider = m_txFrequency / ADF7021_PFD;
// calculate Integer_N and Fractional_N divider values for Tx
TX_N_Divider = floor(divider);
divider = (divider - TX_N_Divider) * 32768;
TX_F_Divider = floor(divider + 0.5);
// setup tx register 0
ADF7021_TX_REG0 = (uint32_t)ADF7021_REG0_ADDR; // Register Address 0
#if defined(BIDIR_DATA_PIN)
ADF7021_TX_REG0 |= (uint32_t)0b01000 << 27; // Mux regulator/transmit
#else
ADF7021_TX_REG0 |= (uint32_t)0b01010 << 27; // Mux regulator/uart-spi enabled/transmit
#endif
ADF7021_TX_REG0 |= (uint32_t)TX_N_Divider << 19; // Frequency - 8-bit Int_N
ADF7021_TX_REG0 |= (uint32_t)TX_F_Divider << 4; // Frequency - 15-bit Frac_N
// configure ADF Tx/RX
configureTxRx(modemState);
// write registers
/*
** VCO/Oscillator (Register 1)
*/
AD7021_CONTROL = ADF7021_REG1;
AD7021_1_IOCTL();
/*
** Tx/Rx Clock (Register 3)
*/
AD7021_CONTROL = ADF7021_REG3;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf(): ADF1 REG3 =", (ADF7021_REG3 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Demodulator Setup (Register 4)
*/
AD7021_CONTROL = ADF7021_REG4;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf(): ADF1 REG4 =", (ADF7021_REG4 >> 16 & 0xFFFFU), (ADF7021_REG4 & 0xFFFFU));
/*
** IF Fine Cal Setup (Register 6)
*/
AD7021_CONTROL = ADF7021_REG6;
AD7021_1_IOCTL();
/*
** IF Coarse Cal Setup (Register 5)
*/
AD7021_CONTROL = ADF7021_REG5;
AD7021_1_IOCTL();
// delay for filter calibration
delayIfCal();
/*
** N Register (Frequency) (Register 0)
*/
setRX();
/*
** Transmit Modulation (Register 2)
*/
AD7021_CONTROL = ADF7021_REG2;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf(): ADF1 REG2 =", (ADF7021_REG2 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Test DAC (Register 14)
*/
#if defined(TEST_DAC)
AD7021_CONTROL = 0x0000001E;
#else
AD7021_CONTROL = 0x0000000E;
#endif
AD7021_1_IOCTL();
/*
** AGC (Register 9)
*/
switch (m_gainMode) {
case ADF_GAIN_AUTO_LIN:
AD7021_CONTROL = 0x100231E9; // AGC ON, LNA high linearity
break;
case ADF_GAIN_LOW:
AD7021_CONTROL = 0x120631E9; // AGC OFF, low gain, LNA high linearity
break;
case ADF_GAIN_HIGH:
AD7021_CONTROL = 0x00A631E9; // AGC OFF, high gain
break;
case ADF_GAIN_AUTO:
default:
AD7021_CONTROL = 0x000231E9; // AGC ON, normal operation
break;
}
AD7021_1_IOCTL();
/*
** AFC (Register 10)
*/
AD7021_CONTROL = ADF7021_REG10;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf(): ADF1 REG10 =", (ADF7021_REG10 >> 16 & 0xFFFFU), (ADF7021_REG10 & 0xFFFFU));
/*
** Sync Word Detect (Register 11)
*/
AD7021_CONTROL = 0x0000003B;
AD7021_1_IOCTL();
/*
** SWD/Threshold Setup (Register 12)
*/
AD7021_CONTROL = 0x0000010C;
AD7021_1_IOCTL();
/*
** 3FSK/4FSK Demod (Register 13)
*/
AD7021_CONTROL = ADF7021_REG13;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf(): ADF1 REG13 =", (ADF7021_REG13 >> 16 & 0xFFFFU), (ADF7021_REG13 & 0xFFFFU));
/*
** Test Mode (Register 15)
*/
#if defined(TEST_TX)
PTT(HIGH);
AD7021_CONTROL = ADF7021_TX_REG0;
AD7021_1_IOCTL();
AD7021_CONTROL = 0x000E010F;
#else
AD7021_CONTROL = 0x000E000F;
#endif
AD7021_1_IOCTL();
#if defined(DUPLEX)
// if duplex -- auto setup the second ADF7021
if (m_duplex && (modemState != STATE_CW))
rf2Conf(modemState);
#endif
}
#if defined(DUPLEX)
/// <summary>
/// Sets the ADF7021 RF configuration.
/// </summary>
/// <param name="modemState"></param>
/// <param name="reset"></param>
void IO::rf2Conf(DVM_STATE modemState)
{
DEBUG3("IO::rf2Conf(): ADF2 (Rx); modemState/rxGain", modemState, m_gainMode);
// configure ADF Tx/RX
configureTxRx(modemState);
// write registers
/*
** VCO/Oscillator (Register 1)
*/
AD7021_CONTROL = ADF7021_REG1;
AD7021_2_IOCTL();
/*
** Tx/Rx Clock (Register 3)
*/
AD7021_CONTROL = ADF7021_REG3;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf(): ADF2 REG3 =", (ADF7021_REG3 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Demodulator Setup (Register 4)
*/
AD7021_CONTROL = ADF7021_REG4;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf(): ADF2 REG4 =", (ADF7021_REG4 >> 16 & 0xFFFFU), (ADF7021_REG4 & 0xFFFFU));
/*
** IF Fine Cal Setup (Register 6)
*/
AD7021_CONTROL = ADF7021_REG6;
AD7021_2_IOCTL();
/*
** IF Coarse Cal Setup (Register 5)
*/
AD7021_CONTROL = ADF7021_REG5;
AD7021_2_IOCTL();
// delay for filter calibration
delayIfCal();
/*
** N Register (Frequency) (Register 0)
*/
// set to RX only
AD7021_CONTROL = ADF7021_RX_REG0;
AD7021_2_IOCTL();
/*
** Transmit Modulation (Register 2)
*/
AD7021_CONTROL = ADF7021_REG2;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf(): ADF2 REG2 =", (ADF7021_REG2 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Test DAC (Register 14)
*/
AD7021_CONTROL = 0x0000000E;
AD7021_2_IOCTL();
/*
** AGC (Register 9)
*/
switch (m_gainMode) {
case ADF_GAIN_AUTO_LIN:
AD7021_CONTROL = 0x100231E9; // AGC ON, LNA high linearity
break;
case ADF_GAIN_LOW:
AD7021_CONTROL = 0x120631E9; // AGC OFF, low gain, LNA high linearity
break;
case ADF_GAIN_HIGH:
AD7021_CONTROL = 0x00A631E9; // AGC OFF, high gain
break;
case ADF_GAIN_AUTO:
default:
AD7021_CONTROL = 0x000231E9; // AGC ON, normal operation
break;
}
AD7021_2_IOCTL();
/*
** AFC (Register 10)
*/
AD7021_CONTROL = ADF7021_REG10;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf(): ADF2 REG10 =", (ADF7021_REG10 >> 16 & 0xFFFFU), (ADF7021_REG10 & 0xFFFFU));
/*
** Sync Word Detect (Register 11)
*/
AD7021_CONTROL = 0x0000003B;
AD7021_2_IOCTL();
/*
** SWD/Threshold Setup (Register 12)
*/
AD7021_CONTROL = 0x0000010C;
AD7021_2_IOCTL();
/*
** 3FSK/4FSK Demod (Register 13)
*/
AD7021_CONTROL = ADF7021_REG13;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf(): ADF2 REG13 =", (ADF7021_REG13 >> 16 & 0xFFFFU), (ADF7021_REG13 & 0xFFFFU));
/*
** Test Mode (Register 15)
*/
AD7021_CONTROL = 0x000E000F;
AD7021_2_IOCTL();
}
#endif // DUPLEX
/// <summary>
///
/// </summary>
/// <param name="dmrTXLevel"></param>
/// <param name="p25TXLevel"></param>
/// <param name="nxdnTXLevel"></param>
void IO::setDeviations(uint8_t dmrTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel)
{
dmrDev = uint16_t((ADF7021_DEV_DMR * uint16_t(dmrTXLevel)) / 128U);
p25Dev = uint16_t((ADF7021_DEV_P25 * uint16_t(p25TXLevel)) / 128U);
nxdnDev = uint16_t((ADF7021_DEV_NXDN * uint16_t(nxdnTXLevel)) / 128U);
}
/// <summary>
/// Sets the RF adjustment parameters.
/// </summary>
/// <param name="dmrDevAdj"></param>
/// <param name="p25DevAdj"></param>
/// <param name="dmrDiscBWAdj"></param>
/// <param name="p25DiscBWAdj"></param>
/// <param name="nxdnDiscBWAdj"></param>
/// <param name="dmrPostBWAdj"></param>
/// <param name="p25PostBWAdj"></param>
/// <param name="nxdnPostBWAdj"></param>
void IO::setRFAdjust(int8_t dmrDiscBWAdj, int8_t p25DiscBWAdj, int8_t nxdnDiscBWAdj, int8_t dmrPostBWAdj, int8_t p25PostBWAdj, int8_t nxdnPostBWADJ)
{
m_dmrDiscBWAdj = dmrDiscBWAdj;
m_p25DiscBWAdj = p25DiscBWAdj;
m_nxdnDiscBWAdj = nxdnDiscBWAdj;
m_dmrPostBWAdj = dmrPostBWAdj;
m_p25PostBWAdj = p25PostBWAdj;
m_nxdnPostBWAdj = nxdnPostBWADJ;
DEBUG4("IO::setRFAdjust(): RF adjustment, discBW", dmrDiscBWAdj, p25DiscBWAdj, nxdnDiscBWAdj);
DEBUG4("IO::setRFAdjust(): RF adjustment, postBW", dmrPostBWAdj, p25PostBWAdj, nxdnPostBWADJ);
}
/// <summary>
/// Sets the RF AFC parameters.
/// </summary>
/// <param name="afcEnable"></param>
/// <param name="afcKI"></param>
/// <param name="afcKP"></param>
/// <param name="afcRange"></param>
void IO::setAFCParams(bool afcEnable, uint8_t afcKI, uint8_t afcKP, uint8_t afcRange)
{
m_afcEnable = afcEnable;
m_afcKI = afcKI;
m_afcKP = afcKP;
m_afcRange = afcRange;
DEBUG5("IO::setAFCParams(): AFC params", afcEnable, afcKI, afcKP, afcRange);
}
/// <summary>
///
/// </summary>
void IO::updateCal(DVM_STATE modemState)
{
uint32_t ADF7021_REG2;
float divider;
/*
** VCO/Oscillator (Register 1)
*/
configureBand();
AD7021_CONTROL = ADF7021_REG1;
AD7021_1_IOCTL();
// configure ADF Tx/Rx
configureTxRx(modemState);
/*
** Demodulator Setup (Register 4)
*/
AD7021_CONTROL = ADF7021_REG4;
AD7021_1_IOCTL();
/*
** Fractional-N Synthesizer (Register 0)
*/
if (div2 == 1U)
divider = m_txFrequency / (ADF7021_PFD / 2U);
else
divider = m_txFrequency / ADF7021_PFD;
// calculate Integer_N and Fractional_N divider values for Rx
TX_N_Divider = floor(divider);
divider = (divider - TX_N_Divider) * 32768;
TX_F_Divider = floor(divider + 0.5);
// setup tx register 0
ADF7021_TX_REG0 = (uint32_t)0b0000; // register 0
#if defined(BIDIR_DATA_PIN)
ADF7021_TX_REG0 |= (uint32_t)0b01000 << 27; // mux regulator/transmit
#else
ADF7021_TX_REG0 |= (uint32_t)0b01010 << 27; // mux regulator/uart-spi enabled/transmit
#endif
ADF7021_TX_REG0 |= (uint32_t)TX_N_Divider << 19; // frequency - 15-bit Frac_N
ADF7021_TX_REG0 |= (uint32_t)TX_F_Divider << 4; // frequency - 8-bit Int_N
/*
** Transmit Modulation (Register 2)
*/
AD7021_CONTROL = ADF7021_REG2;
AD7021_1_IOCTL();
DEBUG2("IO::updateCal(): ADF calibration; modemState", modemState);
if (m_tx)
setTX();
else
setRX();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
uint16_t IO::readRSSI()
{
uint32_t AD7021_RB;
uint16_t RB_word = 0U;
uint8_t RB_code, gainCode, gainCorr;
// Register 7, readback enable, ADC RSSI mode
AD7021_RB = 0x0147;
// Send control register
for (int i = 8; i >= 0; i--) {
if (ADF_BIT_READ(AD7021_RB, i) == HIGH)
SDATA(HIGH);
else
SDATA(LOW);
delayBit();
SCLK(HIGH);
delayBit();
SCLK(LOW);
}
SDATA(LOW);
#if defined(DUPLEX)
if (m_duplex || m_modemState == STATE_RSSI_CAL)
SLE2(HIGH);
else
SLE1(HIGH);
#else
SLE1(HIGH);
#endif
delayBit();
// Read SREAD pin
for (int i = 17; i >= 0; i--) {
SCLK(HIGH);
delayBit();
if ((i != 17) && (i != 0))
RB_word |= ((SREAD() & 0x01) << (i - 1));
SCLK(LOW);
delayBit();
}
#if defined(DUPLEX)
if (m_duplex || m_modemState == STATE_RSSI_CAL)
SLE2(LOW);
else
SLE1(LOW);
#else
SLE1(LOW);
#endif
// Process RSSI code
RB_code = RB_word & 0x7f;
gainCode = (RB_word >> 7) & 0x0f;
switch (gainCode) {
case 0b1010:
gainCorr = 0U;
break;
case 0b0110:
gainCorr = 24U;
break;
case 0b0101:
gainCorr = 38U;
break;
case 0b0100:
gainCorr = 58U;
break;
case 0b0000:
gainCorr = 86U;
break;
default:
gainCorr = 0U;
break;
}
return (130 - (RB_code + gainCorr) / 2);
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
void IO::configureBand()
{
/*
** VCO/Oscillator (Register 1)
*/
/** 136 - 174mhz */
if ((m_txFrequency >= VHF_MIN) && (m_txFrequency < VHF_MAX)) {
ADF7021_REG1 = ADF7021_REG1_VHF; // VHF (80 - 200), external VCO
div2 = 1U;
}
/** 216 - 225mhz */
if ((m_txFrequency >= VHF_220_MIN) && (m_txFrequency < VHF_220_MAX)) {
ADF7021_REG1 = ADF7021_REG1_VHF_220; // VHF (200 - 450), external VCO
div2 = 1U; // should be 2U?
}
/** 380 - 431mhz */
if ((m_txFrequency >= UHF_380_MIN) && (m_txFrequency < UHF_380_MAX)) {
// NOTE: I've included support for this band, but, this could be problematic due to
// the external VCO control on most (if not all) hotspots
ADF7021_REG1 = ADF7021_REG1_UHF_380; // UHF (200 - 450), external VCO
div2 = 1U;
}
/** 431 - 450mhz */
if ((m_txFrequency >= UHF_1_MIN) && (m_txFrequency < UHF_1_MAX)) {
ADF7021_REG1 = ADF7021_REG1_UHF_1; // UHF (431 - 450), internal VCO
div2 = 1U;
}
/** 450 - 470mhz */
if ((m_txFrequency >= UHF_2_MIN) && (m_txFrequency < UHF_2_MAX)) {
ADF7021_REG1 = ADF7021_REG1_UHF_2; // UHF (450 - 470), internal VCO
div2 = 1U;
}
/** 470 - 520mhz */
if ((m_txFrequency >= UHF_T_MIN) && (m_txFrequency < UHF_T_MAX)) {
// NOTE: I've included support for this band, but, this could be problematic due to
// the external VCO control on most (if not all) hotspots
ADF7021_REG1 = ADF7021_REG1_UHF_T; // UHF (470 - 520), external VCO
#if defined(FORCE_UHF_INTERAL_L)
div2 = 2U;
#else
div2 = 1U;
#endif
}
/** 842 - 900mhz */
if ((m_txFrequency >= UHF_800_MIN) && (m_txFrequency < UHF_800_MAX)) {
ADF7021_REG1 = ADF7021_REG1_800; // UHF (862 - 900), internal VCO
div2 = 2U;
}
/** 900 - 950mhz */
if ((m_txFrequency >= UHF_900_MIN) && (m_txFrequency < UHF_900_MAX)) {
ADF7021_REG1 = ADF7021_REG1_900; // UHF (900 - 950), internal VCO
div2 = 2U;
}
if (div2 == 1U)
f_div = 2U;
else
f_div = 1U;
DEBUG3("IO::configureBand(): ADF freq band; reg1/f_div", ADF7021_REG1, f_div);
}
/// <summary>
///
/// </summary>
/// <param name="modemState"></param>
void IO::configureTxRx(DVM_STATE modemState)
{
uint16_t dmrDiscBW = ADF7021_DISC_BW_DMR, dmrPostBW = ADF7021_POST_BW_DMR;
uint16_t p25DiscBW = ADF7021_DISC_BW_P25, p25PostBW = ADF7021_POST_BW_P25;
uint16_t nxdnDiscBW = ADF7021_DISC_BW_NXDN, nxdnPostBW = ADF7021_POST_BW_NXDN;
// configure DMR discriminator and post demodulator BW
if (m_dmrDiscBWAdj != 0) {
if (dmrDiscBW + m_dmrDiscBWAdj < 0)
dmrDiscBW = 0U;
else
dmrDiscBW = ADF7021_DISC_BW_DMR + m_dmrDiscBWAdj;
if (dmrDiscBW > ADF7021_DISC_BW_MAX)
dmrDiscBW = ADF7021_DISC_BW_MAX;
}
if (m_dmrPostBWAdj != 0) {
if (dmrPostBW + m_dmrPostBWAdj < 0)
dmrPostBW = 0U;
else
dmrPostBW = ADF7021_POST_BW_DMR + m_dmrPostBWAdj;
if (dmrPostBW > ADF7021_POST_BW_MAX)
dmrPostBW = ADF7021_POST_BW_MAX;
}
// configure P25 discriminator and post demodulator BW
if (m_p25DiscBWAdj != 0) {
if (p25DiscBW + m_p25DiscBWAdj < 0)
p25DiscBW = 0U;
else
p25DiscBW = ADF7021_DISC_BW_P25 + m_p25DiscBWAdj;
if (p25DiscBW > ADF7021_DISC_BW_MAX)
p25DiscBW = ADF7021_DISC_BW_MAX;
}
if (m_p25PostBWAdj != 0) {
if (p25PostBW + m_p25PostBWAdj < 0)
p25PostBW = 0U;
else
p25PostBW = ADF7021_POST_BW_P25 + m_p25PostBWAdj;
if (p25PostBW > ADF7021_POST_BW_MAX)
p25PostBW = ADF7021_POST_BW_MAX;
}
// configure NXDN discriminator and post demodulator BW
if (m_nxdnDiscBWAdj != 0) {
if (nxdnDiscBW + m_nxdnDiscBWAdj < 0)
nxdnDiscBW = 0U;
else
nxdnDiscBW = ADF7021_DISC_BW_NXDN + m_nxdnDiscBWAdj;
if (nxdnDiscBW > ADF7021_DISC_BW_MAX)
nxdnDiscBW = ADF7021_DISC_BW_MAX;
}
if (m_nxdnPostBWAdj != 0) {
if (nxdnPostBW + m_nxdnPostBWAdj < 0)
nxdnPostBW = 0U;
else
nxdnPostBW = ADF7021_POST_BW_NXDN + m_nxdnPostBWAdj;
if (nxdnPostBW > ADF7021_POST_BW_MAX)
nxdnPostBW = ADF7021_POST_BW_MAX;
}
/*
** Configure the remaining registers based on modem state.
*/
switch (modemState) {
case STATE_CW: // 4FSK
{
// Dev: +1 symb (variable), symb rate = 4800
/*
** Tx/Rx Clock (Register 3)
*/
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(3 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(32 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(147 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(2 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(40 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(123 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
#endif
/*
** AFC (Register 10)
*/
ADF7021_REG10 = (uint32_t)ADF7021_REG10_ADDR; // Register Address 10
if (m_afcEnable) {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_ENABLE << 4; // AFC Enable/Disable
} else {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_DISABLE << 4; // AFC Enable/Disable
}
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG10 |= (uint32_t)(569 & 0xFFFU) << 5; // AFC Scaling Factor
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG10 |= (uint32_t)(683 & 0xFFFU) << 5; // AFC Scaling Factor
#endif
ADF7021_REG10 |= (uint32_t)(m_afcKI & 0xFU) << 17; // KI
ADF7021_REG10 |= (uint32_t)(m_afcKP & 0x7U) << 21; // KP
ADF7021_REG10 |= (uint32_t)(m_afcRange & 0xFFU) << 24; // Maximum AFC Range
/*
** Demodulator Setup (Register 4)
*/
// K=32
ADF7021_REG4 = (uint32_t)ADF7021_REG4_ADDR; // Register Address 4
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_MODE_4FSK << 4; // Demodulation Scheme
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_CROSS_PROD << 7; // Dot Product
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_INV_CLKDAT << 8; // Clock/Data Inversion
ADF7021_REG4 |= (uint32_t)(dmrDiscBW & 0x3FFU) << 10; // Discriminator BW
ADF7021_REG4 |= (uint32_t)(dmrPostBW & 0xFFFU) << 20; // Post Demod BW
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_25K << 30; // IF Filter
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_DMR << 4; // Slicer Threshold
/*
** Transmit Modulation (Register 2)
*/
ADF7021_REG2 = (uint32_t)ADF7021_REG2_ADDR; // Register Address 2
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_MOD_4FSKRC << 4; // Modulation Scheme
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_PA_DEF << 7; // PA Enable & PA Bias
ADF7021_REG2 |= (uint32_t)(m_rfPower & 0x3FU) << 13; // PA Level (0 - Off, 63 - 13 dBm)
ADF7021_REG2 |= (uint32_t)(m_cwIdTXLevel / div2) << 19; // Freq. Deviation
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_INV_CLKDAT << 28; // Clock/Data Inversion
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_RC_5 << 30; // R-Cosine Alpha
}
break;
case STATE_DMR: // 4FSK
{
// Dev: +1 symb 648 Hz, symb rate = 4800
/*
** Tx/Rx Clock (Register 3)
*/
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(3 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(32 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(147 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(2 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(40 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(123 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
#endif
/*
** AFC (Register 10)
*/
ADF7021_REG10 = (uint32_t)ADF7021_REG10_ADDR; // Register Address 10
if (m_afcEnable) {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_ENABLE << 4; // AFC Enable/Disable
} else {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_DISABLE << 4; // AFC Enable/Disable
}
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG10 |= (uint32_t)(569 & 0xFFFU) << 5; // AFC Scaling Factor
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG10 |= (uint32_t)(683 & 0xFFFU) << 5; // AFC Scaling Factor
#endif
ADF7021_REG10 |= (uint32_t)(m_afcKI & 0xFU) << 17; // KI
ADF7021_REG10 |= (uint32_t)(m_afcKP & 0x7U) << 21; // KP
ADF7021_REG10 |= (uint32_t)(m_afcRange & 0xFFU) << 24; // Maximum AFC Range
/*
** Demodulator Setup (Register 4)
*/
// K=32
ADF7021_REG4 = (uint32_t)ADF7021_REG4_ADDR; // Register Address 4
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_MODE_4FSK << 4; // Demodulation Scheme
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_CROSS_PROD << 7; // Dot Product
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_INV_CLKDAT << 8; // Clock/Data Inversion
ADF7021_REG4 |= (uint32_t)(dmrDiscBW & 0x3FFU) << 10; // Discriminator BW
ADF7021_REG4 |= (uint32_t)(dmrPostBW & 0xFFFU) << 20; // Post Demod BW
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_25K << 30; // IF Filter
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_DMR << 4; // Slicer Threshold
/*
** Transmit Modulation (Register 2)
*/
ADF7021_REG2 = (uint32_t)ADF7021_REG2_ADDR; // Register Address 2
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_MOD_4FSKRC << 4; // Modulation Scheme
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_PA_DEF << 7; // PA Enable & PA Bias
ADF7021_REG2 |= (uint32_t)(m_rfPower & 0x3FU) << 13; // PA Level (0 - Off, 63 - 13 dBm)
ADF7021_REG2 |= (uint32_t)(dmrDev / div2) << 19; // Freq. Deviation
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_INV_DATA << 28; // Data Inversion
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_RC_5 << 30; // R-Cosine Alpha
}
break;
case STATE_P25: // 4FSK
{
// Dev: +1 symb 600 Hz, symb rate = 4800
/*
** Tx/Rx Clock (Register 3)
*/
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(3 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(32 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(147 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(2 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(40 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(123 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
#endif
/*
** AFC (Register 10)
*/
ADF7021_REG10 = (uint32_t)ADF7021_REG10_ADDR; // Register Address 10
if (m_afcEnable) {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_ENABLE << 4; // AFC Enable/Disable
} else {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_DISABLE << 4; // AFC Enable/Disable
}
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG10 |= (uint32_t)(569 & 0xFFFU) << 5; // AFC Scaling Factor
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG10 |= (uint32_t)(683 & 0xFFFU) << 5; // AFC Scaling Factor
#endif
ADF7021_REG10 |= (uint32_t)(m_afcKI & 0xFU) << 17; // KI
ADF7021_REG10 |= (uint32_t)(m_afcKP & 0x7U) << 21; // KP
ADF7021_REG10 |= (uint32_t)(m_afcRange & 0xFFU) << 24; // Maximum AFC Range
/*
** Demodulator Setup (Register 4)
*/
// K=32
ADF7021_REG4 = (uint32_t)ADF7021_REG4_ADDR; // Register Address 4
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_MODE_4FSK << 4; // Demodulation Scheme
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_CROSS_PROD << 7; // Dot Product
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_INV_CLKDAT << 8; // Clock/Data Inversion
ADF7021_REG4 |= (uint32_t)(p25DiscBW & 0x3FFU) << 10; // Discriminator BW
ADF7021_REG4 |= (uint32_t)(p25PostBW & 0xFFFU) << 20; // Post Demod BW
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_25K << 30; // IF Filter
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_P25 << 4; // Slicer Threshold
/*
** Transmit Modulation (Register 2)
*/
ADF7021_REG2 = (uint32_t)ADF7021_REG2_ADDR; // Register Address 2
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_MOD_4FSKRC << 4; // Modulation Scheme
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_PA_DEF << 7; // PA Enable & PA Bias
ADF7021_REG2 |= (uint32_t)(m_rfPower & 0x3FU) << 13; // PA Level (0 - Off, 63 - 13 dBm)
ADF7021_REG2 |= (uint32_t)(p25Dev / div2) << 19; // Freq. Deviation
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_INV_CLKDAT << 28; // Clock/Data Inversion
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_RC_5 << 30; // R-Cosine Alpha
}
break;
case STATE_NXDN: // 4FSK
{
// Dev: +1 symb 350 Hz, symb rate = 2400
// Dev: +1 symb 800 Hz, symb rate = 4800
/*
** Tx/Rx Clock (Register 3)
*/
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
#if defined(NXDN_9600_BAUD)
ADF7021_REG3 |= (uint32_t)(3 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(32 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
#else
ADF7021_REG3 |= (uint32_t)(4 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(48 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
#endif
ADF7021_REG3 |= (uint32_t)(147 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
#if defined(NXDN_9600_BAUD)
ADF7021_REG3 |= (uint32_t)(2 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(40 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
#else
ADF7021_REG3 |= (uint32_t)(4 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(40 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
#endif
ADF7021_REG3 |= (uint32_t)(123 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
#endif
/*
** AFC (Register 10)
*/
ADF7021_REG10 = (uint32_t)ADF7021_REG10_ADDR; // Register Address 10
/*
if (m_afcEnable) {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_ENABLE << 4; // AFC Enable/Disable
} else {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_DISABLE << 4; // AFC Enable/Disable
}
*/
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_DISABLE << 4; // AFC Enable/Disable
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG10 |= (uint32_t)(569 & 0xFFFU) << 5; // AFC Scaling Factor
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG10 |= (uint32_t)(683 & 0xFFFU) << 5; // AFC Scaling Factor
#endif
ADF7021_REG10 |= (uint32_t)(m_afcKI & 0xFU) << 17; // KI
ADF7021_REG10 |= (uint32_t)(m_afcKP & 0x7U) << 21; // KP
ADF7021_REG10 |= (uint32_t)(m_afcRange & 0xFFU) << 24; // Maximum AFC Range
/*
** Demodulator Setup (Register 4)
*/
// K=32
ADF7021_REG4 = (uint32_t)ADF7021_REG4_ADDR; // Register Address 4
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_MODE_4FSK << 4; // Demodulation Scheme
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_CROSS_PROD << 7; // Dot Product
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_INV_CLKDAT << 8; // Clock/Data Inversion
ADF7021_REG4 |= (uint32_t)(nxdnDiscBW & 0x3FFU) << 10; // Discriminator BW
ADF7021_REG4 |= (uint32_t)(nxdnPostBW & 0xFFFU) << 20; // Post Demod BW
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_125K << 30; // IF Filter
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_NXDN << 4; // Slicer Threshold
/*
** Transmit Modulation (Register 2)
*/
ADF7021_REG2 = (uint32_t)ADF7021_REG2_ADDR; // Register Address 2
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_MOD_4FSKRC << 4; // Modulation Scheme
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_PA_DEF << 7; // PA Enable & PA Bias
ADF7021_REG2 |= (uint32_t)(m_rfPower & 0x3FU) << 13; // PA Level (0 - Off, 63 - 13 dBm)
ADF7021_REG2 |= (uint32_t)(nxdnDev / div2) << 19; // Freq. Deviation
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_INV_CLKDAT << 28; // Clock/Data Inversion
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_RC_5 << 30; // R-Cosine Alpha
}
break;
default: // GMSK
{
// Dev: 1200 Hz, symb rate = 4800
/*
** Tx/Rx Clock (Register 3)
*/
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(6 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(8 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(147 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG3 = (uint32_t)ADF7021_REG3_ADDR; // Register Address 3
ADF7021_REG3 |= (uint32_t)ADF7021_REG3_BBOS_DIV_8 << 4; // Base Band Clock Divider
ADF7021_REG3 |= (uint32_t)(5 & 0xFU) << 6; // Demodulator Clock Divider
ADF7021_REG3 |= (uint32_t)(16 & 0xFFU) << 10; // Data/Clock Recovery Divider (CDR)
ADF7021_REG3 |= (uint32_t)(123 & 0xFFU) << 18; // Sequencer Clock Divider
ADF7021_REG3 |= (uint32_t)(10 & 0x3FU) << 26; // AGC Clock Divider
#endif
/*
** AFC (Register 10)
*/
ADF7021_REG10 = (uint32_t)ADF7021_REG10_ADDR; // Register Address 10
if (m_afcEnable) {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_ENABLE << 4; // AFC Enable/Disable
} else {
ADF7021_REG10 |= (uint32_t)ADF7021_REG10_AFC_DISABLE << 4; // AFC Enable/Disable
}
/** Support for 14.7456 MHz TCXO (modified RF7021SE boards) */
#if defined(ADF7021_14_7456)
ADF7021_REG10 |= (uint32_t)(569 & 0xFFFU) << 5; // AFC Scaling Factor
/** Support for 12.2880 MHz TCXO */
#elif defined(ADF7021_12_2880)
ADF7021_REG10 |= (uint32_t)(683 & 0xFFFU) << 5; // AFC Scaling Factor
#endif
ADF7021_REG10 |= (uint32_t)(m_afcKI & 0xFU) << 17; // KI
ADF7021_REG10 |= (uint32_t)(m_afcKP & 0x7U) << 21; // KP
ADF7021_REG10 |= (uint32_t)(m_afcRange & 0xFFU) << 24; // Maximum AFC Range
/*
** Demodulator Setup (Register 4)
*/
// K=32
ADF7021_REG4 = (uint32_t)ADF7021_REG4_ADDR; // Register Address 4
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_MODE_GMSK << 4; // Demodulation Scheme
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_DOT_PROD << 7; // Dot Product
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_INV_DATA << 8; // Clock/Data Inversion
ADF7021_REG4 |= (uint32_t)ADF7021_DISC_BW_DEFAULT << 10; // Discriminator BW
ADF7021_REG4 |= (uint32_t)ADF7021_POST_BW_DEFAULT << 20; // Post Demod BW
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_125K << 30; // IF Filter
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_DEFAULT << 4; // Slicer Threshold
/*
** Transmit Modulation (Register 2)
*/
ADF7021_REG2 = (uint32_t)ADF7021_REG2_ADDR; // Register Address 2
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_MOD_GMSK << 4; // Modulation Scheme
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_PA_DEF << 7; // PA Enable & PA Bias
ADF7021_REG2 |= (uint32_t)(m_rfPower & 0x3FU) << 13; // PA Level (0 - Off, 63 - 13 dBm)
ADF7021_REG2 |= (uint32_t)(ADF7021_DEV_DEFAULT / div2) << 19; // Freq. Deviation
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_INV_NORM << 28; // Clock/Data Inversion
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_RC_5 << 30; // R-Cosine Alpha
}
break;
}
DEBUG5("IO::configureTxRx(): ADF Tx/Rx values; dmrDiscBW/dmrPostBW/p25DiscBW/p25PostBW", dmrDiscBW, dmrPostBW, p25DiscBW, p25PostBW);
DEBUG3("IO::configureTxRx(): ADF Tx/Rx values; nxdnDiscBW/nxdnPostBW", nxdnDiscBW, nxdnPostBW);
DEBUG5("IO::configureTxRx(): ADF Tx/Rx values; dmrSymDev/p25SymDev/nxdnSymDev/rfPower", (uint16_t)((ADF7021_PFD * dmrDev) / (f_div * 65536)),
(uint16_t)((ADF7021_PFD * p25Dev) / (f_div * 65536)), (uint16_t)((ADF7021_PFD * nxdnDev) / (f_div * 65536)), m_rfPower);
}
/// <summary>
///
/// </summary>
void IO::setTX()
{
// PTT pin on (doing it earlier helps to measure timing impact)
setPTTInt(HIGH);
// Send register 0 for TX operation, but do not activate yet.
// This is done in the interrupt at the correct time
AD7021_CONTROL = ADF7021_TX_REG0;
AD7021_1_IOCTL(false);
#if defined(BIDIR_DATA_PIN)
setDataDirOut(true); // data pin output mode
#endif
toTxRequest = true;
while(CLK());
}
/// <summary>
///
/// </summary>
/// <param name="doSle"></param>
void IO::setRX(bool doSle)
{
// PTT pin off (doing it earlier helps to measure timing impact)
setPTTInt(LOW);
// Send register 0 for RX operation, but do not activate yet.
// This is done in the interrupt at the correct time
AD7021_CONTROL = ADF7021_RX_REG0;
AD7021_1_IOCTL(doSle);
#if defined(BIDIR_DATA_PIN)
setDataDirOut(false); // data pin output mode
#endif
if (!doSle) {
toRxRequest = true;
while(toRxRequest) {
asm volatile ("nop");
}
}
}
#endif // ENABLE_ADF7021

Powered by TurnKey Linux.