kopia lustrzana https://github.com/OpenRTX/OpenRTX
234 wiersze
9.2 KiB
C++
234 wiersze
9.2 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2021 - 2022 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 <http://www.gnu.org/licenses/> *
|
|
**************************************************************************/
|
|
|
|
#include <interfaces/delays.h>
|
|
#include <I2C0.h>
|
|
#include "AT1846S.h"
|
|
|
|
void AT1846S::init()
|
|
{
|
|
i2c_writeReg16(0x30, 0x0001); // Soft reset
|
|
delayMs(50);
|
|
|
|
i2c_writeReg16(0x30, 0x0004); // Chip enable
|
|
i2c_writeReg16(0x04, 0x0FD0); // 26MHz crystal frequency
|
|
i2c_writeReg16(0x1F, 0x1000); // Gpio6 squelch output
|
|
i2c_writeReg16(0x09, 0x03AC);
|
|
i2c_writeReg16(0x24, 0x0001);
|
|
i2c_writeReg16(0x31, 0x0031);
|
|
i2c_writeReg16(0x33, 0x45F5); // AGC number
|
|
i2c_writeReg16(0x34, 0x2B89); // RX digital gain
|
|
i2c_writeReg16(0x3F, 0x3263); // RSSI 3 threshold
|
|
i2c_writeReg16(0x41, 0x470F); // Tx digital gain
|
|
i2c_writeReg16(0x42, 0x1036);
|
|
i2c_writeReg16(0x43, 0x00BB);
|
|
i2c_writeReg16(0x44, 0x06FF); // Tx digital gain
|
|
i2c_writeReg16(0x47, 0x7F2F); // Soft mute
|
|
i2c_writeReg16(0x4E, 0x0082);
|
|
i2c_writeReg16(0x4F, 0x2C62);
|
|
i2c_writeReg16(0x53, 0x0094);
|
|
i2c_writeReg16(0x54, 0x2A3C);
|
|
i2c_writeReg16(0x55, 0x0081);
|
|
i2c_writeReg16(0x56, 0x0B02);
|
|
i2c_writeReg16(0x57, 0x1C00); // Bypass RSSI low-pass
|
|
i2c_writeReg16(0x5A, 0x4935); // SQ detection time
|
|
i2c_writeReg16(0x58, 0xBCCD);
|
|
i2c_writeReg16(0x62, 0x3263); // Modulation detect tresh
|
|
i2c_writeReg16(0x4E, 0x2082);
|
|
i2c_writeReg16(0x63, 0x16AD);
|
|
i2c_writeReg16(0x30, 0x40A4);
|
|
delayMs(50);
|
|
|
|
i2c_writeReg16(0x30, 0x40A6); // Start calibration
|
|
delayMs(100);
|
|
i2c_writeReg16(0x30, 0x4006); // Stop calibration
|
|
|
|
delayMs(100);
|
|
|
|
i2c_writeReg16(0x58, 0xBCED);
|
|
i2c_writeReg16(0x0A, 0x7BA0); // PGA gain
|
|
i2c_writeReg16(0x41, 0x4731); // Tx digital gain
|
|
i2c_writeReg16(0x44, 0x05FF); // Tx digital gain
|
|
i2c_writeReg16(0x59, 0x09D2); // Mixer gain
|
|
i2c_writeReg16(0x44, 0x05CF); // Tx digital gain
|
|
i2c_writeReg16(0x44, 0x05CC); // Tx digital gain
|
|
i2c_writeReg16(0x48, 0x1A32); // Noise 1 threshold
|
|
i2c_writeReg16(0x60, 0x1A32); // Noise 2 threshold
|
|
i2c_writeReg16(0x3F, 0x29D1); // RSSI 3 threshold
|
|
i2c_writeReg16(0x0A, 0x7BA0); // PGA gain
|
|
i2c_writeReg16(0x49, 0x0C96); // RSSI SQL thresholds
|
|
i2c_writeReg16(0x33, 0x45F5); // AGC number
|
|
i2c_writeReg16(0x41, 0x470F); // Tx digital gain
|
|
i2c_writeReg16(0x42, 0x1036);
|
|
i2c_writeReg16(0x43, 0x00BB);
|
|
}
|
|
|
|
void AT1846S::setBandwidth(const AT1846S_BW band)
|
|
{
|
|
if(band == AT1846S_BW::_25)
|
|
{
|
|
// 25kHz bandwidth
|
|
i2c_writeReg16(0x15, 0x1F00); // Tuning bit
|
|
i2c_writeReg16(0x32, 0x7564); // AGC target power
|
|
i2c_writeReg16(0x3A, 0x44C3); // Modulation detect sel
|
|
i2c_writeReg16(0x3F, 0x29D2); // RSSI 3 threshold
|
|
i2c_writeReg16(0x3C, 0x0E1C); // Peak detect threshold
|
|
i2c_writeReg16(0x48, 0x1E38); // Noise 1 threshold
|
|
i2c_writeReg16(0x62, 0x3767); // Modulation detect tresh
|
|
i2c_writeReg16(0x65, 0x248A);
|
|
i2c_writeReg16(0x66, 0xFF2E); // RSSI comp and AFC range
|
|
i2c_writeReg16(0x7F, 0x0001); // Switch to page 1
|
|
i2c_writeReg16(0x06, 0x0024); // AGC gain table
|
|
i2c_writeReg16(0x07, 0x0214);
|
|
i2c_writeReg16(0x08, 0x0224);
|
|
i2c_writeReg16(0x09, 0x0314);
|
|
i2c_writeReg16(0x0A, 0x0324);
|
|
i2c_writeReg16(0x0B, 0x0344);
|
|
i2c_writeReg16(0x0D, 0x1384);
|
|
i2c_writeReg16(0x0E, 0x1B84);
|
|
i2c_writeReg16(0x0F, 0x3F84);
|
|
i2c_writeReg16(0x12, 0xE0EB);
|
|
i2c_writeReg16(0x7F, 0x0000); // Back to page 0
|
|
maskSetRegister(0x30, 0x3000, 0x3000);
|
|
}
|
|
else
|
|
{
|
|
// 12.5kHz bandwidth
|
|
i2c_writeReg16(0x15, 0x1100); // Tuning bit
|
|
i2c_writeReg16(0x32, 0x4495); // AGC target power
|
|
i2c_writeReg16(0x3A, 0x40C3); // Modulation detect sel
|
|
i2c_writeReg16(0x3F, 0x28D0); // RSSI 3 threshold
|
|
i2c_writeReg16(0x3C, 0x0F1E); // Peak detect threshold
|
|
i2c_writeReg16(0x48, 0x1DB6); // Noise 1 threshold
|
|
i2c_writeReg16(0x62, 0x1425); // Modulation detect tresh
|
|
i2c_writeReg16(0x65, 0x2494);
|
|
i2c_writeReg16(0x66, 0xEB2E); // RSSI comp and AFC range
|
|
i2c_writeReg16(0x7F, 0x0001); // Switch to page 1
|
|
i2c_writeReg16(0x06, 0x0014); // AGC gain table
|
|
i2c_writeReg16(0x07, 0x020C);
|
|
i2c_writeReg16(0x08, 0x0214);
|
|
i2c_writeReg16(0x09, 0x030C);
|
|
i2c_writeReg16(0x0A, 0x0314);
|
|
i2c_writeReg16(0x0B, 0x0324);
|
|
i2c_writeReg16(0x0C, 0x0344);
|
|
i2c_writeReg16(0x0D, 0x1344);
|
|
i2c_writeReg16(0x0E, 0x1B44);
|
|
i2c_writeReg16(0x0F, 0x3F44);
|
|
i2c_writeReg16(0x12, 0xE0EB); // Back to page 0
|
|
i2c_writeReg16(0x7F, 0x0000);
|
|
maskSetRegister(0x30, 0x3000, 0x0000);
|
|
}
|
|
|
|
reloadConfig();
|
|
}
|
|
|
|
void AT1846S::setOpMode(const AT1846S_OpMode mode)
|
|
{
|
|
if(mode == AT1846S_OpMode::DMR)
|
|
{
|
|
// DMR mode
|
|
i2c_writeReg16(0x3A, 0x00C2);
|
|
i2c_writeReg16(0x33, 0x45F5);
|
|
i2c_writeReg16(0x41, 0x4731);
|
|
i2c_writeReg16(0x42, 0x1036);
|
|
i2c_writeReg16(0x43, 0x00BB);
|
|
i2c_writeReg16(0x58, 0xBCFD); // Bit 0 = 1: CTCSS LPF bandwidth to 250Hz
|
|
// Bit 3 = 1: bypass CTCSS HPF
|
|
// Bit 4 = 1: bypass CTCSS LPF
|
|
// Bit 5 = 1: bypass voice LPF
|
|
// Bit 6 = 1: bypass voice HPF
|
|
// Bit 7 = 1: bypass pre/de-emphasis
|
|
// Bit 11 = 1: bypass VOX HPF
|
|
// Bit 12 = 1: bypass VOX LPF
|
|
// Bit 13 = 1: bypass RSSI LPF
|
|
i2c_writeReg16(0x44, 0x06CC);
|
|
i2c_writeReg16(0x40, 0x0031);
|
|
}
|
|
else
|
|
{
|
|
// FM mode
|
|
i2c_writeReg16(0x33, 0x44A5);
|
|
i2c_writeReg16(0x41, 0x4431);
|
|
i2c_writeReg16(0x42, 0x10F0);
|
|
i2c_writeReg16(0x43, 0x00A9);
|
|
i2c_writeReg16(0x58, 0xBC05); // Bit 0 = 1: CTCSS LPF badwidth to 250Hz
|
|
// Bit 3 = 0: enable CTCSS HPF
|
|
// Bit 4 = 0: enable CTCSS LPF
|
|
// Bit 5 = 0: enable voice LPF
|
|
// Bit 6 = 0: enable voice HPF
|
|
// Bit 7 = 0: enable pre/de-emphasis
|
|
// Bit 11 = 1: bypass VOX HPF
|
|
// Bit 12 = 1: bypass VOX LPF
|
|
// Bit 13 = 1: bypass RSSI LPF
|
|
i2c_writeReg16(0x44, 0x06FF);
|
|
i2c_writeReg16(0x40, 0x0030);
|
|
|
|
maskSetRegister(0x57, 0x0001, 0x00); // Audio feedback off
|
|
maskSetRegister(0x3A, 0x7000, 0x4000); // Select voice channel
|
|
}
|
|
|
|
reloadConfig();
|
|
}
|
|
|
|
/*
|
|
* Implementation of AT1846S I2C interface.
|
|
*
|
|
* NOTE: on GDx devices the I2C bus is shared between the EEPROM and the AT1846S,
|
|
* so we have to acquire exclusive ownership before exchanging data
|
|
*/
|
|
|
|
static constexpr uint8_t devAddr = 0xE2;
|
|
|
|
void AT1846S::i2c_init()
|
|
{
|
|
// I2C already init'd by platform support package
|
|
}
|
|
|
|
void AT1846S::i2c_writeReg16(uint8_t reg, uint16_t value)
|
|
{
|
|
/*
|
|
* Beware of endianness!
|
|
* When writing an AT1846S register, bits 15:8 must be sent first, followed
|
|
* by bits 7:0.
|
|
*/
|
|
|
|
uint8_t buf[3];
|
|
buf[0] = reg;
|
|
buf[1] = (value >> 8) & 0xFF;
|
|
buf[2] = value & 0xFF;
|
|
|
|
i2c0_lockDeviceBlocking();
|
|
i2c0_write(devAddr, buf, 3, true);
|
|
i2c0_releaseDevice();
|
|
}
|
|
|
|
uint16_t AT1846S::i2c_readReg16(uint8_t reg)
|
|
{
|
|
uint16_t value = 0;
|
|
|
|
i2c0_lockDeviceBlocking();
|
|
i2c0_write(devAddr, ®, 1, false);
|
|
i2c0_read(devAddr, &value, 2);
|
|
i2c0_releaseDevice();
|
|
|
|
// Correction for AT1846S sending register data in big endian format
|
|
return __builtin_bswap16(value);
|
|
}
|