/*************************************************************************** * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, * * Niccolò Izzo IU2KIN * * Frederik Saraci IU2NRO * * Silvano Seva IU2KWO * * * * 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 3 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, see * ***************************************************************************/ #include #include #include #include #include "HR_Cx000.h" #include "HR_C5000.h" #include "HR_C6000.h" bool Cx000_uSpiBusy() { return (gpio_readPin(DMR_CS) == 0) ? true : false; } template <> void HR_Cx000< C5000_SpiOpModes >::setDacGain(int8_t gain) { // TODO: "DALin" register for HR_C5000 is not documented. (void) gain; } template <> void HR_Cx000< C6000_SpiOpModes >::setDacGain(int8_t gain) { // If gain is at minimum, just turn off DAC output and return if(gain <= -31) { writeReg(C6000_SpiOpModes::CONFIG, 0xE2, 0x00); return; } uint8_t value = 0x80 | (((uint8_t) gain) & 0x1F); if(gain > 0) value |= 0x40; writeReg(C6000_SpiOpModes::CONFIG, 0x37, value); // DAC gain writeReg(C6000_SpiOpModes::CONFIG, 0xE2, 0x02); // Enable DAC } template <> void HR_Cx000< C5000_SpiOpModes >::setInputGain(int8_t value) { /* * On HR_C5000 the input gain value is controlled by bits 7:3 of of register * 0x0F (ADLinVol): these bits allow to set the gain in a range from +12dB * to -34.5dB in steps of 1.5dB each. * The equation relating the gain in dB with register value is: Gain = reg*1.5 - 34.5 * Its inverse is: reg = (gain + 34.5)/1.5 or, equivalently, reg = (gain/1.5) + 23 */ // Keep gain value in range +12dB ... -34.5dB if(value > 12) value = 12; if(value < -34.5) value = -34.5; // Apply the inverse equation to obtain gain register. Gain is multiplied // by ten and divided by 15 to keep using integer operations. int16_t result = (((int16_t) value) * 10)/15 + 23; uint8_t regVal = ((uint8_t) result); if(regVal > 31) regVal = 31; writeReg(C5000_SpiOpModes::CONFIG, 0x0F, regVal << 3); } template <> void HR_Cx000< C6000_SpiOpModes >::setInputGain(int8_t value) { /* * On HR_C6000 the input gain in two stages: the first one is a "coarse" * stage capable of doing only 0dB, -6dB and -12dB. The second stage is a * "fine" stage ranging from 0 to +36dB in steps of 3dB. * Both of them are controlled by register 0xE4: bits 5:4 control the first * stage, while bits 4:0 control the fine stage. * * Allowable gain ranges are: * - 0 ... +36dB when coarse stage bits are 00 * - -6 ... +30dB when coarse stage bits are 01 * - -12 ... +24dB when coarse stage bits are 10 or 11 * * General equation for gain is reg*3 + offset, where "offset" is the gain * of the coarse stage. * Inverse equation, given the coarse gain, is: reg = (gain - offset)/3 * * In this code we use -12dB and 0dB coarse gain values, leaving the fine * tuning to the second stage. */ uint8_t regValue = 0; if(value < 24) { int8_t fineGain = (value + 12)/3; // Compute fine gain, -12dB offset regValue = (2 << 4) // Select -12dB coarse gain | ((uint8_t) fineGain); // Set fine gain bits } else { // For values starting from +24dB set coarse gain to 0dB and use // only fine gain regValue = ((uint8_t) value/3); } writeReg(C6000_SpiOpModes::CONFIG, 0xE4, regValue); } ScopedChipSelect::ScopedChipSelect() { gpio_clearPin(DMR_CS); } ScopedChipSelect::~ScopedChipSelect() { delayUs(2); gpio_setPin(DMR_CS); delayUs(2); } FmConfig operator |(FmConfig lhs, FmConfig rhs) { return static_cast< FmConfig > ( static_cast< std::underlying_type< FmConfig >::type >(lhs) | static_cast< std::underlying_type< FmConfig >::type >(rhs) ); }