custom-uv-k5-firmware/driver/bk4819.c
2023-08-26 12:41:55 +01:00

817 lines
21 KiB
C

/* Copyright 2023 Dual Tachyon
* https://github.com/DualTachyon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bk4819.h"
#include "bsp/dp32g030/gpio.h"
#include "bsp/dp32g030/portcon.h"
#include "driver/gpio.h"
#include "driver/system.h"
#include "driver/systick.h"
static uint16_t gBK4819_GpioOutState;
bool gThisCanEnable_BK4819_Rxon;
void BK4819_Init(void)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
BK4819_WriteRegister(BK4819_REG_00, 0x8000);
BK4819_WriteRegister(BK4819_REG_00, 0x0000);
BK4819_WriteRegister(BK4819_REG_37, 0x1D0F);
BK4819_WriteRegister(BK4819_REG_36, 0x0022);
BK4819_SetAGC(0);
BK4819_WriteRegister(BK4819_REG_19, 0x1041);
BK4819_WriteRegister(BK4819_REG_7D, 0xE940);
BK4819_WriteRegister(BK4819_REG_48, 0xB3A8);
BK4819_WriteRegister(BK4819_REG_09, 0x006F);
BK4819_WriteRegister(BK4819_REG_09, 0x106B);
BK4819_WriteRegister(BK4819_REG_09, 0x2067);
BK4819_WriteRegister(BK4819_REG_09, 0x3062);
BK4819_WriteRegister(BK4819_REG_09, 0x4050);
BK4819_WriteRegister(BK4819_REG_09, 0x5047);
BK4819_WriteRegister(BK4819_REG_09, 0x603A);
BK4819_WriteRegister(BK4819_REG_09, 0x702C);
BK4819_WriteRegister(BK4819_REG_09, 0x8041);
BK4819_WriteRegister(BK4819_REG_09, 0x9037);
BK4819_WriteRegister(BK4819_REG_09, 0xA025);
BK4819_WriteRegister(BK4819_REG_09, 0xB017);
BK4819_WriteRegister(BK4819_REG_09, 0xC0E4);
BK4819_WriteRegister(BK4819_REG_09, 0xD0CB);
BK4819_WriteRegister(BK4819_REG_09, 0xE0B5);
BK4819_WriteRegister(BK4819_REG_09, 0xF09F);
BK4819_WriteRegister(BK4819_REG_1F, 0x5454);
BK4819_WriteRegister(BK4819_REG_3E, 0xA037);
gBK4819_GpioOutState = 0x9000;
BK4819_WriteRegister(BK4819_REG_33, 0x9000);
BK4819_WriteRegister(BK4819_REG_3F, 0);
}
static uint16_t BK4819_ReadU16(void)
{
uint8_t i;
uint16_t Value;
PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_ENABLE;
GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_INPUT;
SYSTICK_DelayUs(1);
Value = 0;
for (i = 0; i < 16; i++) {
Value <<= 1;
Value |= GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
SYSTICK_DelayUs(1);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
SYSTICK_DelayUs(1);
}
PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_DISABLE;
GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_OUTPUT;
return Value;
}
uint16_t BK4819_GetRegister(BK4819_REGISTER_t Register)
{
uint16_t Value;
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
SYSTICK_DelayUs(1);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
BK4819_WriteU8(Register | 0x80);
Value = BK4819_ReadU16();
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
return Value;
}
void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
SYSTICK_DelayUs(1);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
BK4819_WriteU8(Register);
SYSTICK_DelayUs(1);
BK4819_WriteU16(Data);
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN);
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
}
void BK4819_WriteU8(uint8_t Data)
{
uint8_t i;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
for (i = 0; i < 8; i++) {
if ((Data & 0x80U) == 0) {
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
} else {
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
}
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
SYSTICK_DelayUs(1);
Data <<= 1;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
SYSTICK_DelayUs(1);
}
}
void BK4819_WriteU16(uint16_t Data)
{
uint8_t i;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
for (i = 0; i < 16; i++) {
if ((Data & 0x8000U) == 0U) {
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
} else {
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA);
}
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
Data <<= 1;
SYSTICK_DelayUs(1);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL);
SYSTICK_DelayUs(1);
}
}
void BK4819_SetAGC(uint8_t Value)
{
if (Value == 0) {
BK4819_WriteRegister(BK4819_REG_13, 0x03BE);
BK4819_WriteRegister(BK4819_REG_12, 0x037B);
BK4819_WriteRegister(BK4819_REG_11, 0x027B);
BK4819_WriteRegister(BK4819_REG_10, 0x007A);
BK4819_WriteRegister(BK4819_REG_14, 0x0019);
BK4819_WriteRegister(BK4819_REG_49, 0x2A38);
BK4819_WriteRegister(BK4819_REG_7B, 0x8420);
} else if (Value == 1) {
uint8_t i;
BK4819_WriteRegister(BK4819_REG_13, 0x03BE);
BK4819_WriteRegister(BK4819_REG_12, 0x037C);
BK4819_WriteRegister(BK4819_REG_11, 0x027B);
BK4819_WriteRegister(BK4819_REG_10, 0x007A);
BK4819_WriteRegister(BK4819_REG_14, 0x0018);
BK4819_WriteRegister(BK4819_REG_49, 0x2A38);
BK4819_WriteRegister(BK4819_REG_7B, 0x318C);
BK4819_WriteRegister(BK4819_REG_7C, 0x595E);
BK4819_WriteRegister(BK4819_REG_20, 0x8DEF);
for (i = 0; i < 8; i++) {
// Bug? The bit 0x2000 below overwrites the (i << 13)
BK4819_WriteRegister(BK4819_REG_06, ((i << 13) | 0x2500U) + 0x36U);
}
}
}
void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet)
{
if (bSet) {
gBK4819_GpioOutState |= (0x40U >> Pin);
} else {
gBK4819_GpioOutState &= ~(0x40U >> Pin);
}
BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState);
}
void BK4819_SetCDCSSCodeWord(uint32_t CodeWord)
{
// Enable CDCSS
// Transmit positive CDCSS code
// CDCSS Mode
// CDCSS 23bit
// Enable Auto CDCSS Bw Mode
// Enable Auto CTCSS Bw Mode
// CTCSS/CDCSS Tx Gain1 Tuning = 51
BK4819_WriteRegister(BK4819_REG_51, 0
| BK4819_REG_51_ENABLE_CxCSS
| BK4819_REG_51_GPIO6_PIN2_NORMAL
| BK4819_REG_51_TX_CDCSS_POSITIVE
| BK4819_REG_51_MODE_CDCSS
| BK4819_REG_51_CDCSS_23_BIT
| BK4819_REG_51_1050HZ_NO_DETECTION
| BK4819_REG_51_AUTO_CDCSS_BW_ENABLE
| BK4819_REG_51_AUTO_CTCSS_BW_ENABLE
| (51U << BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1));
// CTC1 Frequency Control Word = 2775
BK4819_WriteRegister(BK4819_REG_07, 0
| BK4819_REG_07_MODE_CTC1
| (2775U << BK4819_REG_07_SHIFT_FREQUENCY));
// Set the code word
BK4819_WriteRegister(BK4819_REG_08, 0x0000 | ((CodeWord >> 0) & 0xFFF));
BK4819_WriteRegister(BK4819_REG_08, 0x8000 | ((CodeWord >> 12) & 0xFFF));
}
void BK4819_SetCTCSSBaudRate(uint32_t BaudRate)
{
uint16_t Config;
if (BaudRate == 2625) {
// Enable TxCTCSS
// CTCSS Mode
// 1050/4 Detect Enable
// Enable Auto CDCSS Bw Mode
// Enable Auto CTCSS Bw Mode
// CTCSS/CDCSS Tx Gain1 Tuning = 74
Config = 0x944A;
} else {
// Enable TxCTCSS
// CTCSS Mode
// Enable Auto CDCSS Bw Mode
// Enable Auto CTCSS Bw Mode
// CTCSS/CDCSS Tx Gain1 Tuning = 74
Config = 0x904A;
}
BK4819_WriteRegister(BK4819_REG_51, Config);
// CTC1 Frequency Control Word
BK4819_WriteRegister(BK4819_REG_07, 0
| BK4819_REG_07_MODE_CTC1
| ((BaudRate * 2065) / 1000) << BK4819_REG_07_SHIFT_FREQUENCY);
}
void BK4819_Set55HzTailDetection(void)
{
// CTC2 Frequency Control Word = round_nearest(25391 / 55) = 462
BK4819_WriteRegister(BK4819_REG_07, (1U << 13) | 462);
}
void BK4819_EnableVox(uint16_t Vox1Threshold, uint16_t Vox0Threshold)
{
uint16_t Value;
Value = BK4819_GetRegister(BK4819_REG_31);
// 0xA000 is undocumented?
BK4819_WriteRegister(BK4819_REG_46, 0xA000 | (Vox1Threshold & 0x07FF));
// 0x1800 is undocumented?
BK4819_WriteRegister(BK4819_REG_79, 0x1800 | (Vox0Threshold & 0x07FF));
// Bottom 12 bits are undocumented?
BK4819_WriteRegister(BK4819_REG_7A, 0x289A);
// Enable VOX
BK4819_WriteRegister(BK4819_REG_31, Value | 4);
}
void BK4819_SetFilterBandwidth(BK4819_FilterBandwidth_t Bandwidth)
{
if (Bandwidth == BK4819_FILTER_BW_WIDE) {
BK4819_WriteRegister(BK4819_REG_43, 0x3028);
} else if (Bandwidth == BK4819_FILTER_BW_NARROW) {
BK4819_WriteRegister(BK4819_REG_43, 0x4048);
}
}
void BK4819_SetupPowerAmplifier(uint16_t Bias, uint32_t Frequency)
{
uint8_t Gain;
if (Bias > 255) {
Bias = 255;
}
if (Frequency < 28000000) {
// Gain 1 = 1
// Gain 2 = 0
Gain = 0x08U;
} else {
// Gain 1 = 4
// Gain 2 = 2
Gain = 0x22U;
}
// Enable PACTLoutput
BK4819_WriteRegister(BK4819_REG_36, (Bias << 8) | 0x80U | Gain);
}
void BK4819_SetFrequency(uint32_t Frequency)
{
BK4819_WriteRegister(BK4819_REG_38, (Frequency >> 0) & 0xFFFF);
BK4819_WriteRegister(BK4819_REG_39, (Frequency >> 16) & 0xFFFF);
}
void BK4819_SetupSquelch(uint8_t SquelchOpenRSSIThresh, uint8_t SquelchCloseRSSIThresh, uint8_t SquelchOpenNoiseThresh, uint8_t SquelchCloseNoiseThresh, uint8_t SquelchCloseGlitchThresh, uint8_t SquelchOpenGlitchThresh)
{
BK4819_WriteRegister(BK4819_REG_70, 0);
BK4819_WriteRegister(BK4819_REG_4D, 0xA000 | SquelchCloseGlitchThresh);
// 0x6f = 0110 1111 meaning the default sql delays from the datasheet are used (101 and 111)
BK4819_WriteRegister(BK4819_REG_4E, 0x6F00 | SquelchOpenGlitchThresh);
BK4819_WriteRegister(BK4819_REG_4F, (SquelchCloseNoiseThresh << 8) | SquelchOpenNoiseThresh);
BK4819_WriteRegister(BK4819_REG_78, (SquelchOpenRSSIThresh << 8) | SquelchCloseRSSIThresh);
BK4819_SetAF(BK4819_AF_MUTE);
BK4819_RX_TurnOn();
}
void BK4819_SetAF(BK4819_AF_Type_t AF)
{
// AF Output Inverse Mode = Inverse
// Undocumented bits 0x2040
BK4819_WriteRegister(BK4819_REG_47, 0x6040 | (AF << 8));
}
void BK4819_RX_TurnOn(void)
{
// DSP Voltage Setting = 1
// ANA LDO = 2.7v
// VCO LDO = 2.7v
// RF LDO = 2.7v
// PLL LDO = 2.7v
// ANA LDO bypass
// VCO LDO bypass
// RF LDO bypass
// PLL LDO bypass
// Reserved bit is 1 instead of 0
// Enable DSP
// Enable XTAL
// Enable Band Gap
BK4819_WriteRegister(BK4819_REG_37, 0x1F0F);
// Turn off everything
BK4819_WriteRegister(BK4819_REG_30, 0);
// Enable VCO Calibration
// Enable RX Link
// Enable AF DAC
// Enable PLL/VCO
// Disable PA Gain
// Disable MIC ADC
// Disable TX DSP
// Enable RX DSP
BK4819_WriteRegister(BK4819_REG_30, 0xBFF1);
}
void BK4819_PickRXFilterPathBasedOnFrequency(uint32_t Frequency)
{
if (Frequency < 28000000) {
BK4819_ToggleGpioOut(BK4819_GPIO2_PIN30, true);
BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31, false);
} else if (Frequency == 0xFFFFFFFF) {
BK4819_ToggleGpioOut(BK4819_GPIO2_PIN30, false);
BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31, false);
} else {
BK4819_ToggleGpioOut(BK4819_GPIO2_PIN30, false);
BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31, true);
}
}
void BK4819_DisableScramble(void)
{
uint16_t Value;
Value = BK4819_GetRegister(BK4819_REG_31);
BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFD);
}
void BK4819_EnableScramble(uint8_t Type)
{
uint16_t Value;
Value = BK4819_GetRegister(BK4819_REG_31);
BK4819_WriteRegister(BK4819_REG_31, Value | 2);
BK4819_WriteRegister(BK4819_REG_71, (Type * 0x0408) + 0x68DC);
}
void BK4819_DisableVox(void)
{
uint16_t Value;
Value = BK4819_GetRegister(BK4819_REG_31);
BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFB);
}
void BK4819_DisableDTMF(void)
{
BK4819_WriteRegister(BK4819_REG_24, 0);
}
void BK4819_EnableDTMF(void)
{
BK4819_WriteRegister(BK4819_REG_21, 0x06D8);
BK4819_WriteRegister(BK4819_REG_24, 0
| (1U << BK4819_REG_24_SHIFT_UNKNOWN_15)
| (24 << BK4819_REG_24_SHIFT_THRESHOLD)
| (1U << BK4819_REG_24_SHIFT_UNKNOWN_6)
| BK4819_REG_24_ENABLE
| BK4819_REG_24_SELECT_DTMF
| (14U << BK4819_REG_24_SHIFT_MAX_SYMBOLS)
);
}
void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch)
{
uint16_t ToneConfig;
BK4819_EnterTxMute();
BK4819_SetAF(BK4819_AF_BEEP);
if (bTuningGainSwitch == 0) {
ToneConfig = 0
| BK4819_REG_70_ENABLE_TONE1
| (96U << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN);
} else {
ToneConfig = 0
| BK4819_REG_70_ENABLE_TONE1
| (28U << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN);
}
BK4819_WriteRegister(BK4819_REG_70, ToneConfig);
BK4819_WriteRegister(BK4819_REG_30, 0);
BK4819_WriteRegister(BK4819_REG_30, 0
| BK4819_REG_30_ENABLE_AF_DAC
| BK4819_REG_30_ENABLE_DISC_MODE
| BK4819_REG_30_ENABLE_TX_DSP);
;
BK4819_WriteRegister(BK4819_REG_71, (uint16_t)(Frequency * 10.32444));
}
void BK4819_EnterTxMute(void)
{
BK4819_WriteRegister(BK4819_REG_50, 0xBB20);
}
void BK4819_ExitTxMute(void)
{
BK4819_WriteRegister(BK4819_REG_50, 0x3B20);
}
void BK4819_Sleep(void)
{
BK4819_WriteRegister(BK4819_REG_30, 0);
BK4819_WriteRegister(BK4819_REG_37, 0x1D00);
}
void BK4819_TurnsOffTones_TurnsOnRX(void)
{
BK4819_WriteRegister(BK4819_REG_70, 0);
BK4819_SetAF(BK4819_AF_MUTE);
BK4819_ExitTxMute();
BK4819_WriteRegister(BK4819_REG_30, 0);
BK4819_WriteRegister(BK4819_REG_30, 0
| BK4819_REG_30_ENABLE_VCO_CALIB
| BK4819_REG_30_ENABLE_RX_LINK
| BK4819_REG_30_ENABLE_AF_DAC
| BK4819_REG_30_ENABLE_DISC_MODE
| BK4819_REG_30_ENABLE_PLL_VCO
| BK4819_REG_30_ENABLE_RX_DSP
);
}
void BK4819_SetupAircopy(void)
{
BK4819_WriteRegister(BK4819_REG_70, 0x00E0);
BK4819_WriteRegister(BK4819_REG_72, 0x3065);
BK4819_WriteRegister(BK4819_REG_58, 0x00C1);
BK4819_WriteRegister(BK4819_REG_5C, 0x5665);
BK4819_WriteRegister(BK4819_REG_5D, 0x4700);
}
void BK4819_ResetFSK(void)
{
BK4819_WriteRegister(BK4819_REG_3F, 0x0000);
BK4819_WriteRegister(BK4819_REG_59, 0x0068);
SYSTEM_DelayMs(30);
BK4819_Idle();
}
void BK4819_Idle(void)
{
BK4819_WriteRegister(BK4819_REG_30, 0x0000);
}
void BK4819_ExitBypass(void)
{
BK4819_SetAF(BK4819_AF_MUTE);
BK4819_WriteRegister(BK4819_REG_7E, 0x302E);
}
void BK4819_PrepareTransmit(void)
{
BK4819_ExitBypass();
BK4819_ExitTxMute();
BK4819_TxOn_Beep();
}
void BK4819_TxOn_Beep(void)
{
BK4819_WriteRegister(BK4819_REG_37, 0x1D0F);
BK4819_WriteRegister(BK4819_REG_52, 0x028F);
BK4819_WriteRegister(BK4819_REG_30, 0x0000);
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE);
}
void BK4819_ExitSubAu(void)
{
BK4819_WriteRegister(BK4819_REG_51, 0x0000);
}
void BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(void)
{
if (gThisCanEnable_BK4819_Rxon) {
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2, true);
BK4819_RX_TurnOn();
}
}
void BK4819_EnterDTMF_TX(bool bLocalLoopback)
{
BK4819_EnableDTMF();
BK4819_EnterTxMute();
if (bLocalLoopback) {
BK4819_SetAF(BK4819_AF_BEEP);
} else {
BK4819_SetAF(BK4819_AF_MUTE);
}
BK4819_WriteRegister(BK4819_REG_70, 0
| BK4819_REG_70_MASK_ENABLE_TONE1
| (83 << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)
| BK4819_REG_70_MASK_ENABLE_TONE2
| (83 << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)
);
BK4819_EnableTXLink();
}
void BK4819_ExitDTMF_TX(bool bKeep)
{
BK4819_EnterTxMute();
BK4819_SetAF(BK4819_AF_MUTE);
BK4819_WriteRegister(BK4819_REG_70, 0x0000);
BK4819_DisableDTMF();
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE);
if (!bKeep) {
BK4819_ExitTxMute();
}
}
void BK4819_EnableTXLink(void)
{
BK4819_WriteRegister(BK4819_REG_30, 0
| BK4819_REG_30_ENABLE_VCO_CALIB
| BK4819_REG_30_ENABLE_UNKNOWN
| BK4819_REG_30_DISABLE_RX_LINK
| BK4819_REG_30_ENABLE_AF_DAC
| BK4819_REG_30_ENABLE_DISC_MODE
| BK4819_REG_30_ENABLE_PLL_VCO
| BK4819_REG_30_ENABLE_PA_GAIN
| BK4819_REG_30_DISABLE_MIC_ADC
| BK4819_REG_30_ENABLE_TX_DSP
| BK4819_REG_30_DISABLE_RX_DSP
);
}
void BK4819_PlayDTMF(char Code)
{
switch (Code) {
case '0':
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
break;
case '1':
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
break;
case '2':
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
break;
case '3':
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
break;
case '4':
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
break;
case '5':
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
break;
case '6':
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
break;
case '7':
BK4819_WriteRegister(BK4819_REG_71, 0x225C);
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
break;
case '8':
BK4819_WriteRegister(BK4819_REG_71, 0x225c);
BK4819_WriteRegister(BK4819_REG_72, 0x35E1);
break;
case '9':
BK4819_WriteRegister(BK4819_REG_71, 0x225C);
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
break;
case 'A':
BK4819_WriteRegister(BK4819_REG_71, 0x1C1C);
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
break;
case 'B':
BK4819_WriteRegister(BK4819_REG_71, 0x1F0E);
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
break;
case 'C':
BK4819_WriteRegister(BK4819_REG_71, 0x225C);
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
break;
case 'D':
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
BK4819_WriteRegister(BK4819_REG_72, 0x41DC);
break;
case '*':
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
BK4819_WriteRegister(BK4819_REG_72, 0x30C2);
break;
case '#':
BK4819_WriteRegister(BK4819_REG_71, 0x25F3);
BK4819_WriteRegister(BK4819_REG_72, 0x3B91);
break;
}
}
void BK4819_PlayDTMFString(char *pString, bool bDelayFirst, uint16_t FirstCodePersistTime, uint16_t HashCodePersistTime, uint16_t CodePersistTime, uint16_t CodeInternalTime)
{
uint8_t i;
uint16_t Delay;
for (i = 0; pString[i]; i++) {
BK4819_PlayDTMF(pString[i]);
BK4819_ExitTxMute();
if (bDelayFirst && i == 0) {
Delay = FirstCodePersistTime;
} else if (pString[i] == '*' || pString[i] == '#') {
Delay = HashCodePersistTime;
} else {
Delay = CodePersistTime;
}
SYSTEM_DelayMs(Delay);
BK4819_EnterTxMute();
SYSTEM_DelayMs(CodeInternalTime);
}
}
void BK4819_TransmitTone(bool bLocalLoopback, uint32_t Frequency)
{
BK4819_EnterTxMute();
BK4819_WriteRegister(BK4819_REG_70, 0
| BK4819_REG_70_MASK_ENABLE_TONE1
| (64U << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_WriteRegister(BK4819_REG_71, (uint16_t)(Frequency * 10.32444));
if (bLocalLoopback) {
BK4819_SetAF(BK4819_AF_BEEP);
} else {
BK4819_SetAF(BK4819_AF_MUTE);
}
BK4819_EnableTXLink();
SYSTEM_DelayMs(50);
BK4819_ExitTxMute();
}
void BK4819_GenTail(uint8_t Tail)
{
switch(Tail) {
case 0: // CTC134
BK4819_WriteRegister(BK4819_REG_52, 0x828F);
break;
case 1: // CTC120
BK4819_WriteRegister(BK4819_REG_52, 0xA28F);
break;
case 2: // CTC180
BK4819_WriteRegister(BK4819_REG_52, 0xC28F);
break;
case 3: // CTC240
BK4819_WriteRegister(BK4819_REG_52, 0xE28F);
break;
case 4: // CTC55
BK4819_WriteRegister(BK4819_REG_07, 0x046f);
break;
}
}
void BK4819_EnableCDCSS(void)
{
BK4819_GenTail(0); // CTC134
BK4819_WriteRegister(BK4819_REG_51, 0x804A);
}
void BK4819_EnableCTCSS(void)
{
BK4819_GenTail(4); // CTC55
BK4819_WriteRegister(BK4819_REG_51, 0x904A);
}
uint16_t BK4819_GetRSSI(void)
{
return BK4819_GetRegister(BK4819_REG_67) & 0x01FF;
}
bool BK4819_GetFrequencyScanResult(int32_t *pFrequency)
{
uint16_t High, Low;
bool Finished;
High = BK4819_GetRegister(BK4819_REG_0D);
Finished = (High & 0x8000) == 0;
if (Finished) {
Low = BK4819_GetRegister(BK4819_REG_0E);
*pFrequency = ((High & 0x7FF) << 16) | Low;
}
return Finished;
}
BK4819_CssScanResult_t BK4819_GetCxCSSScanResult(int32_t *pCdcssFreq, uint16_t *pCtcssFreq)
{
uint16_t High, Low;
High = BK4819_GetRegister(BK4819_REG_69);
if ((High & 0x8000) == 0) {
Low = BK4819_GetRegister(BK4819_REG_6A);
*pCdcssFreq = ((High & 0xFFF) << 12) | (Low & 0xFFF);
return BK4819_CSS_RESULT_CDCSS;
}
Low = BK4819_GetRegister(BK4819_REG_68);
if ((Low & 0x8000) == 0) {
*pCtcssFreq = (Low & 0x1FFF) * 4843 / 10000;
return BK4819_CSS_RESULT_CTCSS;
}
return BK4819_CSS_RESULT_NOT_FOUND;
}
void BK4819_DisableFrequencyScan(void)
{
BK4819_WriteRegister(BK4819_REG_32, 0x0244);
}
void BK4819_EnableFrequencyScan(void)
{
BK4819_WriteRegister(BK4819_REG_32, 0x0245);
}
void BK4819_SetScanFrequency(int32_t Frequency)
{
BK4819_SetFrequency(Frequency);
BK4819_WriteRegister(BK4819_REG_51, 0
| BK4819_REG_51_DISABLE_CxCSS
| BK4819_REG_51_GPIO6_PIN2_NORMAL
| BK4819_REG_51_TX_CDCSS_POSITIVE
| BK4819_REG_51_MODE_CDCSS
| BK4819_REG_51_CDCSS_23_BIT
| BK4819_REG_51_1050HZ_NO_DETECTION
| BK4819_REG_51_AUTO_CDCSS_BW_DISABLE
| BK4819_REG_51_AUTO_CTCSS_BW_DISABLE
);
BK4819_RX_TurnOn();
}
void BK4819_Disable(void)
{
BK4819_WriteRegister(BK4819_REG_30, 0);
}
void BK4819_StopScan(void)
{
BK4819_DisableFrequencyScan();
BK4819_Disable();
}
uint8_t BK4819_GetDTMF_5TONE_Code(void)
{
return (BK4819_GetRegister(BK4819_REG_0B) >> 8) & 0x0F;
}
uint8_t BK4819_CheckCDCSSCodeReceived(void)
{
return (BK4819_GetRegister(BK4819_REG_0C) >> 14) & 3;
}