From f4e3140743a1b10828e603739477974a2113c3b7 Mon Sep 17 00:00:00 2001 From: wu58430 Date: Fri, 1 Dec 2023 16:03:09 +0800 Subject: [PATCH] F Lock change --- .idea/workspace.xml | 115 +- Dockerfile | 4 +- Makefile | 65 +- app/app.c | 26 +- app/common.c | 2 + compile-with-docker.bat | 2 +- compile-with-docker.sh | 2 +- debugging.h | 9 +- driver/bk4819.c | 2900 +++++++++++++++++++-------------------- driver/bk4819.h | 4 +- payment/sponsors.md | 12 +- ui/status.c | 4 + uv-k5font/ee | 2 + uv-k5font/font.xlsx | Bin 32952 -> 48494 bytes version.c | 2 +- 15 files changed, 1575 insertions(+), 1574 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d511425..19c678f 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -20,51 +20,19 @@ - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - + - { + "lastFilter": { + "state": "OPEN" } -}]]> +} - { + "keyToString": { + "ASKED_ADD_EXTERNAL_FILES": "true", + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.cidr.known.project.marker": "true", + "SHARE_PROJECT_CONFIGURATION_FILES": "true", + "WebServerToolWindowFactoryState": "false", + "cf.first.check.clang-format": "false", + "cidr.known.project.marker": "true", + "last_opened_file_path": "C:/Users/RUPC/Desktop/UV-K6/uv-k5-firmware-chinese", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "File.Encoding", + "vue.rearranger.settings.migration": "true" } -}]]> +} - + - @@ -170,7 +138,8 @@ - + + 1701136012311 @@ -270,7 +239,14 @@ - @@ -289,6 +265,7 @@ - \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 4b6c3f9..ddb2c4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM archlinux:latest +FROM --platform=amd64 archlinux:latest RUN pacman -Syyu base-devel --noconfirm RUN pacman -Syyu arm-none-eabi-gcc --noconfirm RUN pacman -Syyu arm-none-eabi-newlib --noconfirm @@ -9,4 +9,4 @@ WORKDIR /app COPY . . RUN git submodule update --init --recursive -#RUN make && cp firmware* compiled-firmware/ +#RUN make && cp firmware* compiled-firmware/ \ No newline at end of file diff --git a/Makefile b/Makefile index 6c2a001..6381f47 100644 --- a/Makefile +++ b/Makefile @@ -2,11 +2,14 @@ # compile options (see README.md for descriptions) # 0 = disable # 1 = enable -# + +# ---- COMPILER/LINKER OPTIONS ---- ENABLE_CLANG := 0 ENABLE_SWD := 0 ENABLE_OVERLAY := 0 ENABLE_LTO := 1 + +# ---- STOCK QUANSHENG FERATURES ---- ENABLE_UART := 1 ENABLE_AIRCOPY := 0 ENABLE_FMRADIO := 1 @@ -16,6 +19,9 @@ ENABLE_VOX := 1 ENABLE_ALARM := 0 ENABLE_TX1750 := 0 ENABLE_PWRON_PASSWORD := 0 +ENABLE_DTMF_CALLING := 1 + +# ---- CUSTOM MODS ---- ENABLE_BIG_FREQ := 1 ENABLE_SMALL_BOLD := 1 ENABLE_KEEP_MEM_NAME := 1 @@ -39,11 +45,11 @@ ENABLE_REDUCE_LOW_MID_TX_POWER:= 0 ENABLE_BYP_RAW_DEMODULATORS := 0 ENABLE_BLMIN_TMP_OFF := 0 ENABLE_SCAN_RANGES := 1 -ENABLE_DTMF_CALLING := 1 + ############################################################# + TARGET = firmware -GIT_HASH := 111 -$(info GIT_HASH = $(GIT_HASH)) + ifeq ($(ENABLE_CLANG),1) # GCC's linker, ld, doesn't understand LLVM's generated bytecode ENABLE_LTO := 0 @@ -60,7 +66,6 @@ BSP_HEADERS := $(patsubst %.def,%.h,$(BSP_HEADERS)) OBJS = # Startup files - OBJS += start.o OBJS += init.o ifeq ($(ENABLE_OVERLAY),1) @@ -161,6 +166,20 @@ else TOP := $(shell pwd) endif +ifdef OS # windows + RM = del /Q + FixPath = $(subst /,\,$1) + WHERE = where + NULL_OUTPUT = nul +else # unix + ifeq ($(shell uname), Linux) + RM = rm -f + FixPath = $1 + WHERE = which + NULL_OUTPUT = /dev/null + endif +endif + AS = arm-none-eabi-gcc CC = @@ -180,9 +199,16 @@ endif OBJCOPY = arm-none-eabi-objcopy SIZE = arm-none-eabi-size +AUTHOR_STRING := LOSEHU # the user might not have/want git installed # can set own version string here (max 7 chars) -#GIT_HASH := cn_all +ifneq (, $(shell $(WHERE) git)) + VERSION_STRING := $(shell git describe --tags --exact-match 2>$(NULL_OUTPUT)) + ifeq (, $(VERSION_STRING)) + VERSION_STRING := $(shell git rev-parse --short HEAD) + endif +endif +#VERSION_STRING := 230930b ASFLAGS = -c -mcpu=cortex-m0 @@ -192,8 +218,7 @@ endif CFLAGS = ifeq ($(ENABLE_CLANG),0) - CFLAGS += -Os -Wall -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD - #CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD + CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD #CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c99 -MMD #CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu99 -MMD #CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu11 -MMD @@ -217,7 +242,7 @@ CFLAGS += -Wextra #CFLAGS += -Wpedantic CFLAGS += -DPRINTF_INCLUDE_CONFIG_H -CFLAGS += -DGIT_HASH=\"$(GIT_HASH)\" +CFLAGS += -DAUTHOR_STRING=\"$(AUTHOR_STRING)\" -DVERSION_STRING=\"$(VERSION_STRING)\" ifeq ($(ENABLE_SPECTRUM),1) CFLAGS += -DENABLE_SPECTRUM @@ -294,9 +319,6 @@ endif ifeq ($(ENABLE_AM_FIX_SHOW_DATA),1) CFLAGS += -DENABLE_AM_FIX_SHOW_DATA endif -ifeq ($(ENABLE_AM_FIX_TEST1),1) - CFLAGS += -DENABLE_AM_FIX_TEST1 -endif ifeq ($(ENABLE_SQUELCH_MORE_SENSITIVE),1) CFLAGS += -DENABLE_SQUELCH_MORE_SENSITIVE endif @@ -336,16 +358,17 @@ endif ifeq ($(ENABLE_DTMF_CALLING),1) CFLAGS += -DENABLE_DTMF_CALLING endif + LDFLAGS = ifeq ($(ENABLE_CLANG),0) - LDFLAGS += -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld + LDFLAGS += -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld else # Fix warning about implied executable stack LDFLAGS += -z noexecstack -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld endif # Use newlib-nano instead of newlib -LDFLAGS += --specs=nano.specs +LDFLAGS += --specs=nano.specs ifeq ($(ENABLE_LTO),0) # Throw away unneeded func/data sections like LTO does @@ -367,17 +390,7 @@ LIBS = DEPS = $(OBJS:.o=.d) -ifdef OS - RM = del /Q - FixPath = $(subst /,\,$1) - WHERE = where -else - ifeq ($(shell uname), Linux) - RM = rm -f - FixPath = $1 - WHERE = which - endif -endif + ifneq (, $(shell $(WHERE) python)) MY_PYTHON := python @@ -402,7 +415,7 @@ else ifneq (,$(HAS_CRCMOD)) $(info !!!!!!!! run: pip install crcmod) $(info ) else - -$(MY_PYTHON) fw-pack.py $<.bin $(GIT_HASH) $<.packed.bin + -$(MY_PYTHON) fw-pack.py $<.bin $(AUTHOR_STRING) $(VERSION_STRING) $<.packed.bin endif $(SIZE) $< diff --git a/app/app.c b/app/app.c index e35e5d9..90f3ada 100644 --- a/app/app.c +++ b/app/app.c @@ -507,6 +507,9 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix) const uint8_t orig_pga = 6; // -3dB #ifdef ENABLE_AM_FIX + BK4819_SetAGC(gRxVfo->Modulation != MODULATION_AM || !gSetting_AM_fix); + + if (gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix) { // AM RX mode if (reset_am_fix) AM_fix_reset(chan); // TODO: only reset it when moving channel/frequency @@ -1781,11 +1784,18 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) // KEY_MENU has a special treatment here, because we want to pass hold event to ACTION_Handle // but we don't want it to complain when initial press happens // we want to react on realese instead - else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && // pass side buttons - !(Key == KEY_MENU && bKeyHeld)) // pass KEY_MENU held + // KEY_MENU has a special treatment here, because we want to pass hold event to ACTION_Handle + // but we don't want it to complain when initial press happens + // we want to react on realese instead + else if ( // pass side buttons + !(Key == KEY_SIDE1 && !bKeyHeld)) // pass KEY_MENU held { - if ((!bKeyPressed || bKeyHeld || (Key == KEY_MENU && bKeyPressed)) && // prevent released or held, prevent KEY_MENU pressed - !(Key == KEY_MENU && !bKeyPressed)) // pass KEY_MENU released +// if (!(Key == KEY_SIDE1&&bKeyHeld)&&(!bKeyPressed || (Key == KEY_SIDE1 && bKeyPressed)) && // prevent released or held, prevent KEY_MENU pressed +// !(Key == KEY_SIDE1 && !bKeyPressed)) // pass KEY_MENU released +// return; + if (!(Key == KEY_SIDE1) && !(bKeyPressed != 0)) + + // if (Key == KEY_SIDE1 == 0 && !bKeyPressed != 0) // pass KEY_MENU released return; // keypad is locked, tell the user @@ -1809,6 +1819,11 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) bool bFlag = false; if (Key == KEY_PTT) { +// if(gEeprom.KEY_LOCK) +// { +// gKeypadLocked = 4; // 2 seconds +// return; +// } if (gPttWasPressed) { bFlag = bKeyHeld; @@ -1816,6 +1831,9 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { bFlag = true; gPttWasPressed = false; + + + } } } diff --git a/app/common.c b/app/common.c index d62cbf1..22e9a07 100644 --- a/app/common.c +++ b/app/common.c @@ -17,6 +17,8 @@ void COMMON_KeypadLockToggle() #endif gEeprom.KEY_LOCK = !gEeprom.KEY_LOCK; + //按键锁定禁止发射 取消 + // RADIO_SetVfoState(VFO_STATE_NORMAL); gRequestSaveSettings = true; } diff --git a/compile-with-docker.bat b/compile-with-docker.bat index 42adad1..e1c888b 100644 --- a/compile-with-docker.bat +++ b/compile-with-docker.bat @@ -1,4 +1,4 @@ @echo off docker build -t uvk5 . -docker run -v %CD%\compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make clean && make && cp firmware* compiled-firmware/" +docker run --rm -v %CD%\compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make clean && make && cp firmware* compiled-firmware/" pause \ No newline at end of file diff --git a/compile-with-docker.sh b/compile-with-docker.sh index 7fd9433..6e19518 100644 --- a/compile-with-docker.sh +++ b/compile-with-docker.sh @@ -1,3 +1,3 @@ #!/bin/sh docker build -t uvk5 . -docker run -v ${PWD}/compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/" +docker run --rm -v ${PWD}/compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/" \ No newline at end of file diff --git a/debugging.h b/debugging.h index 58b85a4..262e42e 100644 --- a/debugging.h +++ b/debugging.h @@ -11,7 +11,14 @@ static inline void LogUart(char * str) UART_Send(str, strlen(str)); } - +static inline void LogPrint() +{ + uint16_t rssi = BK4819_GetRSSI(); + uint16_t reg7e = BK4819_ReadRegister(0x7E); + char buf[32]; + sprintf(buf, "reg7E: %d %2d %6d %2d %d rssi: %d\n", (reg7e >> 15), (reg7e >> 12) & 0b111, (reg7e >> 5) & 0b1111111, (reg7e >> 2) & 0b111, (reg7e >> 0) & 0b11, rssi); + LogUart(buf); +} diff --git a/driver/bk4819.c b/driver/bk4819.c index c2c050b..3559d72 100644 --- a/driver/bk4819.c +++ b/driver/bk4819.c @@ -25,12 +25,14 @@ #include "driver/systick.h" #ifndef ARRAY_SIZE - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif static const uint16_t FSK_RogerTable[7] = {0xF1A2, 0x7446, 0x61A4, 0x6544, 0x4E8A, 0xE044, 0xEA84}; + static const uint8_t DTMF_TONE1_GAIN = 65; static const uint8_t DTMF_TONE2_GAIN = 93; + static uint16_t gBK4819_GpioOutState; bool gRxIdleMode; @@ -38,58 +40,58 @@ bool gRxIdleMode; __inline uint16_t scale_freq(const uint16_t freq) { // return (((uint32_t)freq * 1032444u) + 50000u) / 100000u; // with rounding - return (((uint32_t)freq * 1353245u) + (1u << 16)) >> 17; // with rounding + return (((uint32_t)freq * 1353245u) + (1u << 16)) >> 17; // with rounding } 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); + 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_00, 0x8000); + BK4819_WriteRegister(BK4819_REG_00, 0x0000); - BK4819_WriteRegister(BK4819_REG_37, 0x1D0F); - BK4819_WriteRegister(BK4819_REG_36, 0x0022); + BK4819_WriteRegister(BK4819_REG_37, 0x1D0F); + BK4819_WriteRegister(BK4819_REG_36, 0x0022); - BK4819_DisableAGC(); -// BK4819_EnableAGC(); + BK4819_InitAGC(); + BK4819_SetAGC(true); - BK4819_WriteRegister(BK4819_REG_19, 0b0001000001000001); // <15> MIC AGC 1 = disable 0 = enable + BK4819_WriteRegister(BK4819_REG_19, 0b0001000001000001); // <15> MIC AGC 1 = disable 0 = enable - BK4819_WriteRegister(BK4819_REG_7D, 0xE940); + BK4819_WriteRegister(BK4819_REG_7D, 0xE940); - // REG_48 .. RX AF level - // - // <15:12> 11 ??? 0 to 15 - // - // <11:10> 0 AF Rx Gain-1 - // 0 = 0dB - // 1 = -6dB - // 2 = -12dB - // 3 = -18dB - // - // <9:4> 60 AF Rx Gain-2 -26dB ~ 5.5dB 0.5dB/step - // 63 = max - // 0 = mute - // - // <3:0> 15 AF DAC Gain (after Gain-1 and Gain-2) approx 2dB/step - // 15 = max - // 0 = min - // - BK4819_WriteRegister(BK4819_REG_48, // 0xB3A8); // 1011 00 111010 1000 - (11u << 12) | // ??? 0..15 - ( 0u << 10) | // AF Rx Gain-1 - (58u << 4) | // AF Rx Gain-2 - ( 8u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) + // REG_48 .. RX AF level + // + // <15:12> 11 ??? 0 to 15 + // + // <11:10> 0 AF Rx Gain-1 + // 0 = 0dB + // 1 = -6dB + // 2 = -12dB + // 3 = -18dB + // + // <9:4> 60 AF Rx Gain-2 -26dB ~ 5.5dB 0.5dB/step + // 63 = max + // 0 = mute + // + // <3:0> 15 AF DAC Gain (after Gain-1 and Gain-2) approx 2dB/step + // 15 = max + // 0 = min + // + BK4819_WriteRegister(BK4819_REG_48, // 0xB3A8); // 1011 00 111010 1000 + (11u << 12) | // ??? 0..15 + ( 0u << 10) | // AF Rx Gain-1 + (58u << 4) | // AF Rx Gain-2 + ( 8u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) #if 1 - const uint8_t dtmf_coeffs[] = {111, 107, 103, 98, 80, 71, 58, 44, 65, 55, 37, 23, 228, 203, 181, 159}; - for (unsigned int i = 0; i < ARRAY_SIZE(dtmf_coeffs); i++) - BK4819_WriteRegister(BK4819_REG_09, (i << 12) | dtmf_coeffs[i]); + const uint8_t dtmf_coeffs[] = {111, 107, 103, 98, 80, 71, 58, 44, 65, 55, 37, 23, 228, 203, 181, 159}; + for (unsigned int i = 0; i < ARRAY_SIZE(dtmf_coeffs); i++) + BK4819_WriteRegister(BK4819_REG_09, (i << 12) | dtmf_coeffs[i]); #else - // original code + // original code BK4819_WriteRegister(BK4819_REG_09, 0x006F); // 6F BK4819_WriteRegister(BK4819_REG_09, 0x106B); // 6B BK4819_WriteRegister(BK4819_REG_09, 0x2067); // 67 @@ -108,886 +110,859 @@ void BK4819_Init(void) BK4819_WriteRegister(BK4819_REG_09, 0xF09F); // 9F #endif - BK4819_WriteRegister(BK4819_REG_1F, 0x5454); - BK4819_WriteRegister(BK4819_REG_3E, 0xA037); + BK4819_WriteRegister(BK4819_REG_1F, 0x5454); + BK4819_WriteRegister(BK4819_REG_3E, 0xA037); - gBK4819_GpioOutState = 0x9000; + gBK4819_GpioOutState = 0x9000; - BK4819_WriteRegister(BK4819_REG_33, 0x9000); - BK4819_WriteRegister(BK4819_REG_3F, 0); + BK4819_WriteRegister(BK4819_REG_33, 0x9000); + BK4819_WriteRegister(BK4819_REG_3F, 0); } static uint16_t BK4819_ReadU16(void) { - unsigned int i; - uint16_t Value; + unsigned int 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); + 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; + 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; + return Value; } uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register) { - uint16_t Value; + uint16_t Value; - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); + 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); + 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); + SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - return Value; + 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); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - BK4819_WriteU8(Register); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + BK4819_WriteU8(Register); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - BK4819_WriteU16(Data); + BK4819_WriteU16(Data); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); } void BK4819_WriteU8(uint8_t Data) { - unsigned int i; + unsigned int i; - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - for (i = 0; i < 8; i++) - { - if ((Data & 0x80) == 0) - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - else - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + for (i = 0; i < 8; i++) + { + if ((Data & 0x80) == 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); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); - Data <<= 1; + Data <<= 1; - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); - } + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); + } } void BK4819_WriteU16(uint16_t Data) { - unsigned int i; + unsigned int i; - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - for (i = 0; i < 16; i++) - { - if ((Data & 0x8000) == 0) - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - else - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + for (i = 0; i < 16; i++) + { + if ((Data & 0x8000) == 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); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - Data <<= 1; + Data <<= 1; - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); - } + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); + } } -void BK4819_DisableAGC() +void BK4819_SetAGC(bool enable) { - // REG_10 - // - // 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1) - // - // <15:10> ??? - // - // <9:8> LNA Gain Short - // 3 = 0dB <<< - // 2 = -24dB // was -11 - // 1 = -30dB // was -16 - // 0 = -33dB // was -19 - // - // <7:5> LNA Gain - // 7 = 0dB - // 6 = -2dB - // 5 = -4dB - // 4 = -6dB - // 3 = -9dB - // 2 = -14dB <<< - // 1 = -19dB - // 0 = -24dB - // - // <4:3> MIXER Gain - // 3 = 0dB <<< - // 2 = -3dB - // 1 = -6dB - // 0 = -8dB - // - // <2:0> PGA Gain - // 7 = 0dB - // 6 = -3dB <<< - // 5 = -6dB - // 4 = -9dB - // 3 = -15dB - // 2 = -21dB - // 1 = -27dB - // 0 = -33dB - // - BK4819_WriteRegister(BK4819_REG_13, (3u << 8) | (5u << 5) | (3u << 3) | (6u << 0)); // 000000 11 101 11 110 + uint16_t regVal = BK4819_ReadRegister(BK4819_REG_7E); + if(!(regVal & (1 << 15)) == enable) + return; - BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 000000 11 011 11 011 - BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 000000 10 011 11 011 - BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 000000 00 011 11 010 - BK4819_WriteRegister(BK4819_REG_14, 0x0019); // 000000 00 000 11 001 + BK4819_WriteRegister(BK4819_REG_7E, (regVal & ~(1 << 15) & ~(0b111 << 12)) + | (!enable << 15) // 0 AGC fix mode + | (3u << 12) // 3 AGC fix index + ); - BK4819_WriteRegister(BK4819_REG_49, 0x2A38); - BK4819_WriteRegister(BK4819_REG_7B, 0x8420); + // if(enable) { + // BK4819_WriteRegister(BK4819_REG_7B, 0x8420); + // } + // else { + // BK4819_WriteRegister(BK4819_REG_7B, 0x318C); + + // BK4819_WriteRegister(BK4819_REG_7C, 0x595E); + // BK4819_WriteRegister(BK4819_REG_20, 0x8DEF); + + // for (uint8_t i = 0; i < 8; i++) { + // //BK4819_WriteRegister(BK4819_REG_06, ((i << 13) | 0x2500u) + 0x036u); + // BK4819_WriteRegister(BK4819_REG_06, (i & 7) << 13 | 0x4A << 7 | 0x36); + // } + // } } -void BK4819_EnableAGC() -{ - // REG_10 - // - // 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1) - // - // (15:10> ??? - // - // <9:8> LNA Gain Short - // 3 = 0dB << original - // 2 = -24dB // was -11 - // 1 = -30dB // was -16 - // 0 = -33dB // was -19 - // - // <7:5> LNA Gain - // 7 = 0dB - // 6 = -2dB - // 5 = -4dB - // 4 = -6dB - // 3 = -9dB - // 2 = -14dB << original - // 1 = -19dB - // 0 = -24dB - // - // <4:3> MIXER Gain - // 3 = 0dB << original - // 2 = -3dB - // 1 = -6dB - // 0 = -8dB - // - // <2:0> PGA Gain - // 7 = 0dB - // 6 = -3dB << original - // 5 = -6dB - // 4 = -9dB - // 3 = -15dB - // 2 = -21dB - // 1 = -27dB - // 0 = -33dB - // - BK4819_WriteRegister(BK4819_REG_13, (3u << 8) | (5u << 5) | (3u << 3) | (6u << 0)); +void BK4819_InitAGC() +{ + // REG_10, REG_11, REG_12 REG_13, REG_14 + // + // Rx AGC Gain Table[]. (Index Max->Min is 3,2,1,0,-1) + // + // <15:10> ??? + // + // <9:8> LNA Gain Short + // 3 = 0dB <<< 1o11 read from spectrum reference manual + // 2 = -24dB -19 -11 + // 1 = -30dB -24 -16 + // 0 = -33dB -28 -19 + // + // <7:5> LNA Gain + // 7 = 0dB + // 6 = -2dB + // 5 = -4dB + // 4 = -6dB + // 3 = -9dB + // 2 = -14dB <<< + // 1 = -19dB + // 0 = -24dB + // + // <4:3> MIXER Gain + // 3 = 0dB <<< + // 2 = -3dB + // 1 = -6dB + // 0 = -8dB + // + // <2:0> PGA Gain + // 7 = 0dB + // 6 = -3dB <<< + // 5 = -6dB + // 4 = -9dB + // 3 = -15dB + // 2 = -21dB + // 1 = -27dB + // 0 = -33dB + // - BK4819_WriteRegister(BK4819_REG_12, 0x037C); // 000000 11 011 11 100 - BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 000000 10 011 11 011 - BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 000000 00 011 11 010 - BK4819_WriteRegister(BK4819_REG_14, 0x0018); // 000000 00 000 11 000 + BK4819_WriteRegister(BK4819_REG_13, 0x03BE); // 0x03BE / 000000 11 101 11 110 / -7dB + BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 0x037B / 000000 11 011 11 011 / -24dB + BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 0x027B / 000000 10 011 11 011 / -43dB + BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 0x007A / 000000 00 011 11 010 / -58dB + BK4819_WriteRegister(BK4819_REG_14, 0x0019); // 0x0019 / 000000 00 000 11 001 / -79dB + BK4819_WriteRegister(BK4819_REG_49, (0 << 14) | (84 << 7) | (56 << 0)); //0x2A38 / 00 1010100 0111000 / 84, 56 + BK4819_WriteRegister(BK4819_REG_7B, 0x8420); - 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 (uint8_t i = 0; i < 8; i++) { - //BK4819_WriteRegister(BK4819_REG_06, ((i << 13) | 0x2500u) + 0x036u); - BK4819_WriteRegister(BK4819_REG_06, (i & 7) << 13 | 0x4A << 7 | 0x36); - } } + + void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet) { - if (bSet) - gBK4819_GpioOutState |= (0x40u >> Pin); - else - gBK4819_GpioOutState &= ~(0x40u >> Pin); + if (bSet) + gBK4819_GpioOutState |= (0x40u >> Pin); + else + gBK4819_GpioOutState &= ~(0x40u >> Pin); - BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState); + BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState); } void BK4819_SetCDCSSCodeWord(uint32_t CodeWord) { - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max - // 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, - 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)); + // 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, + 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)); - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | 2775u); + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | 2775u); - // REG_08 <15:0> <15> = 1 for CDCSS high 12bit - // <15> = 0 for CDCSS low 12bit - // <11:0> = CDCSShigh/low 12bit code - // - BK4819_WriteRegister(BK4819_REG_08, (0u << 15) | ((CodeWord >> 0) & 0x0FFF)); // LS 12-bits - BK4819_WriteRegister(BK4819_REG_08, (1u << 15) | ((CodeWord >> 12) & 0x0FFF)); // MS 12-bits + // REG_08 <15:0> <15> = 1 for CDCSS high 12bit + // <15> = 0 for CDCSS low 12bit + // <11:0> = CDCSShigh/low 12bit code + // + BK4819_WriteRegister(BK4819_REG_08, (0u << 15) | ((CodeWord >> 0) & 0x0FFF)); // LS 12-bits + BK4819_WriteRegister(BK4819_REG_08, (1u << 15) | ((CodeWord >> 12) & 0x0FFF)); // MS 12-bits } void BK4819_SetCTCSSFrequency(uint32_t FreqControlWord) { - // REG_51 <15> 0 1 = Enable TxCTCSS/CDCSS 0 = Disable - // REG_51 <14> 0 1 = GPIO0Input for CDCSS 0 = Normal Mode.(for BK4819v3) - // REG_51 <13> 0 1 = Transmit negative CDCSS code 0 = Transmit positive CDCSScode - // REG_51 <12> 0 CTCSS/CDCSS mode selection 1 = CTCSS 0 = CDCSS - // REG_51 <11> 0 CDCSS 24/23bit selection 1 = 24bit 0 = 23bit - // REG_51 <10> 0 1050HzDetectionMode 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // REG_51 <9> 0 Auto CDCSS Bw Mode 1 = Disable 0 = Enable. - // REG_51 <8> 0 Auto CTCSS Bw Mode 0 = Enable 1 = Disable - // REG_51 <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning 0 = min 127 = max + // REG_51 <15> 0 1 = Enable TxCTCSS/CDCSS 0 = Disable + // REG_51 <14> 0 1 = GPIO0Input for CDCSS 0 = Normal Mode.(for BK4819v3) + // REG_51 <13> 0 1 = Transmit negative CDCSS code 0 = Transmit positive CDCSScode + // REG_51 <12> 0 CTCSS/CDCSS mode selection 1 = CTCSS 0 = CDCSS + // REG_51 <11> 0 CDCSS 24/23bit selection 1 = 24bit 0 = 23bit + // REG_51 <10> 0 1050HzDetectionMode 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // REG_51 <9> 0 Auto CDCSS Bw Mode 1 = Disable 0 = Enable. + // REG_51 <8> 0 Auto CTCSS Bw Mode 0 = Enable 1 = Disable + // REG_51 <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning 0 = min 127 = max - uint16_t Config; - if (FreqControlWord == 2625) - { // Enables 1050Hz detection mode - // 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; // 1 0 0 1 0 1 0 0 0 1001010 - } - else - { // Enable TxCTCSS - // CTCSS Mode - // Enable Auto CDCSS Bw Mode - // Enable Auto CTCSS Bw Mode - // CTCSS/CDCSS Tx Gain1 Tuning = 74 - // - Config = 0x904A; // 1 0 0 1 0 0 0 0 0 1001010 - } - BK4819_WriteRegister(BK4819_REG_51, Config); + uint16_t Config; + if (FreqControlWord == 2625) + { // Enables 1050Hz detection mode + // 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; // 1 0 0 1 0 1 0 0 0 1001010 + } + else + { // Enable TxCTCSS + // CTCSS Mode + // Enable Auto CDCSS Bw Mode + // Enable Auto CTCSS Bw Mode + // CTCSS/CDCSS Tx Gain1 Tuning = 74 + // + Config = 0x904A; // 1 0 0 1 0 0 0 0 0 1001010 + } + BK4819_WriteRegister(BK4819_REG_51, Config); - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail RX detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | (((FreqControlWord * 206488u) + 50000u) / 100000u)); // with rounding + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail RX detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | (((FreqControlWord * 206488u) + 50000u) / 100000u)); // with rounding } // freq_10Hz is CTCSS Hz * 10 void BK4819_SetTailDetection(const uint32_t freq_10Hz) { - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail RX detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC2 | ((253910 + (freq_10Hz / 2)) / freq_10Hz)); // with rounding + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail RX detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC2 | ((253910 + (freq_10Hz / 2)) / freq_10Hz)); // with rounding } void BK4819_EnableVox(uint16_t VoxEnableThreshold, uint16_t VoxDisableThreshold) { - //VOX Algorithm - //if (voxamp>VoxEnableThreshold) VOX = 1; - //else - //if (voxampVoxEnableThreshold) VOX = 1; + //else + //if (voxamp 0 ??? - // - // <14:12> 4 RF filter bandwidth - // 0 = 1.7 kHz - // 1 = 2.0 kHz - // 2 = 2.5 kHz - // 3 = 3.0 kHz - // 4 = 3.75 kHz - // 5 = 4.0 kHz - // 6 = 4.25 kHz - // 7 = 4.5 kHz - // if <5> == 1, RF filter bandwidth * 2 - // - // <11:9> 0 RF filter bandwidth when signal is weak - // 0 = 1.7 kHz - // 1 = 2.0 kHz - // 2 = 2.5 kHz - // 3 = 3.0 kHz - // 4 = 3.75 kHz - // 5 = 4.0 kHz - // 6 = 4.25 kHz - // 7 = 4.5 kHz - // if <5> == 1, RF filter bandwidth * 2 - // - // <8:6> 1 AFTxLPF2 filter Band Width - // 1 = 2.5 kHz (for 12.5k channel space) - // 2 = 2.75 kHz - // 0 = 3.0 kHz (for 25k channel space) - // 3 = 3.5 kHz - // 4 = 4.5 kHz - // 5 = 4.25 kHz - // 6 = 4.0 kHz - // 7 = 3.75 kHz - // - // <5:4> 0 BW Mode Selection - // 0 = 12.5k - // 1 = 6.25k - // 2 = 25k/20k - // - // <3> 1 ??? - // - // <2> 0 Gain after FM Demodulation - // 0 = 0dB - // 1 = 6dB - // - // <1:0> 0 ??? + // REG_43 + // <15> 0 ??? + // + // <14:12> 4 RF filter bandwidth + // 0 = 1.7 kHz + // 1 = 2.0 kHz + // 2 = 2.5 kHz + // 3 = 3.0 kHz + // 4 = 3.75 kHz + // 5 = 4.0 kHz + // 6 = 4.25 kHz + // 7 = 4.5 kHz + // if <5> == 1, RF filter bandwidth * 2 + // + // <11:9> 0 RF filter bandwidth when signal is weak + // 0 = 1.7 kHz + // 1 = 2.0 kHz + // 2 = 2.5 kHz + // 3 = 3.0 kHz + // 4 = 3.75 kHz + // 5 = 4.0 kHz + // 6 = 4.25 kHz + // 7 = 4.5 kHz + // if <5> == 1, RF filter bandwidth * 2 + // + // <8:6> 1 AFTxLPF2 filter Band Width + // 1 = 2.5 kHz (for 12.5k channel space) + // 2 = 2.75 kHz + // 0 = 3.0 kHz (for 25k channel space) + // 3 = 3.5 kHz + // 4 = 4.5 kHz + // 5 = 4.25 kHz + // 6 = 4.0 kHz + // 7 = 3.75 kHz + // + // <5:4> 0 BW Mode Selection + // 0 = 12.5k + // 1 = 6.25k + // 2 = 25k/20k + // + // <3> 1 ??? + // + // <2> 0 Gain after FM Demodulation + // 0 = 0dB + // 1 = 6dB + // + // <1:0> 0 ??? - uint16_t val; + uint16_t val; - switch (Bandwidth) - { - default: - case BK4819_FILTER_BW_WIDE: // 25kHz - if (weak_no_different) - { // make the RX bandwidth the same with weak signals - val = - (0u << 15) | // 0 - (4u << 12) | // *3 RF filter bandwidth - (4u << 9) | // *0 RF filter bandwidth when signal is weak - (6u << 6) | // *0 AFTxLPF2 filter Band Width - (2u << 4) | // 2 BW Mode Selection - (1u << 3) | // 1 - (0u << 2) | // 0 Gain after FM Demodulation - (0u << 0); // 0 - } - else - { // with weak RX signals the RX bandwidth is reduced - val = // 0x3028); // 0 011 000 000 10 1 0 00 - (0u << 15) | // 0 - (4u << 12) | // *3 RF filter bandwidth - (2u << 9) | // *0 RF filter bandwidth when signal is weak - (6u << 6) | // *0 AFTxLPF2 filter Band Width - (2u << 4) | // 2 BW Mode Selection - (1u << 3) | // 1 - (0u << 2) | // 0 Gain after FM Demodulation - (0u << 0); // 0 - } - break; + switch (Bandwidth) + { + default: + case BK4819_FILTER_BW_WIDE: // 25kHz + if (weak_no_different) + { // make the RX bandwidth the same with weak signals + val = + (0u << 15) | // 0 + (4u << 12) | // *3 RF filter bandwidth + (4u << 9) | // *0 RF filter bandwidth when signal is weak + (6u << 6) | // *0 AFTxLPF2 filter Band Width + (2u << 4) | // 2 BW Mode Selection + (1u << 3) | // 1 + (0u << 2) | // 0 Gain after FM Demodulation + (0u << 0); // 0 + } + else + { // with weak RX signals the RX bandwidth is reduced + val = // 0x3028); // 0 011 000 000 10 1 0 00 + (0u << 15) | // 0 + (4u << 12) | // *3 RF filter bandwidth + (2u << 9) | // *0 RF filter bandwidth when signal is weak + (6u << 6) | // *0 AFTxLPF2 filter Band Width + (2u << 4) | // 2 BW Mode Selection + (1u << 3) | // 1 + (0u << 2) | // 0 Gain after FM Demodulation + (0u << 0); // 0 + } + break; - case BK4819_FILTER_BW_NARROW: // 12.5kHz - if (weak_no_different) - { - val = - (0u << 15) | // 0 - (4u << 12) | // *4 RF filter bandwidth - (4u << 9) | // *0 RF filter bandwidth when signal is weak - (0u << 6) | // *1 AFTxLPF2 filter Band Width - (0u << 4) | // 0 BW Mode Selection - (1u << 3) | // 1 - (0u << 2) | // 0 Gain after FM Demodulation - (0u << 0); // 0 - } - else - { - val = // 0x4048); // 0 100 000 001 00 1 0 00 - (0u << 15) | // 0 - (4u << 12) | // *4 RF filter bandwidth - (2u << 9) | // *0 RF filter bandwidth when signal is weak - (0u << 6) | // *1 AFTxLPF2 filter Band Width - (0u << 4) | // 0 BW Mode Selection - (1u << 3) | // 1 - (0u << 2) | // 0 Gain after FM Demodulation - (0u << 0); // 0 - } - break; + case BK4819_FILTER_BW_NARROW: // 12.5kHz + if (weak_no_different) + { + val = + (0u << 15) | // 0 + (4u << 12) | // *4 RF filter bandwidth + (4u << 9) | // *0 RF filter bandwidth when signal is weak + (0u << 6) | // *1 AFTxLPF2 filter Band Width + (0u << 4) | // 0 BW Mode Selection + (1u << 3) | // 1 + (0u << 2) | // 0 Gain after FM Demodulation + (0u << 0); // 0 + } + else + { + val = // 0x4048); // 0 100 000 001 00 1 0 00 + (0u << 15) | // 0 + (4u << 12) | // *4 RF filter bandwidth + (2u << 9) | // *0 RF filter bandwidth when signal is weak + (0u << 6) | // *1 AFTxLPF2 filter Band Width + (0u << 4) | // 0 BW Mode Selection + (1u << 3) | // 1 + (0u << 2) | // 0 Gain after FM Demodulation + (0u << 0); // 0 + } + break; - case BK4819_FILTER_BW_NARROWER: // 6.25kHz - if (weak_no_different) - { - val = - (0u << 15) | // 0 - (3u << 12) | // 3 RF filter bandwidth - (3u << 9) | // *0 RF filter bandwidth when signal is weak - (1u << 6) | // 1 AFTxLPF2 filter Band Width - (1u << 4) | // 1 BW Mode Selection - (1u << 3) | // 1 - (0u << 2) | // 0 Gain after FM Demodulation - (0u << 0); // 0 - } - else - { - val = - (0u << 15) | // 0 - (3u << 12) | // 3 RF filter bandwidth - (0u << 9) | // 0 RF filter bandwidth when signal is weak - (1u << 6) | // 1 AFTxLPF2 filter Band Width - (1u << 4) | // 1 BW Mode Selection - (1u << 3) | // 1 - (0u << 2) | // 1 Gain after FM Demodulation - (0u << 0); // 0 - } - break; - } + case BK4819_FILTER_BW_NARROWER: // 6.25kHz + if (weak_no_different) + { + val = + (0u << 15) | // 0 + (3u << 12) | // 3 RF filter bandwidth + (3u << 9) | // *0 RF filter bandwidth when signal is weak + (1u << 6) | // 1 AFTxLPF2 filter Band Width + (1u << 4) | // 1 BW Mode Selection + (1u << 3) | // 1 + (0u << 2) | // 0 Gain after FM Demodulation + (0u << 0); // 0 + } + else + { + val = + (0u << 15) | // 0 + (3u << 12) | // 3 RF filter bandwidth + (0u << 9) | // 0 RF filter bandwidth when signal is weak + (1u << 6) | // 1 AFTxLPF2 filter Band Width + (1u << 4) | // 1 BW Mode Selection + (1u << 3) | // 1 + (0u << 2) | // 1 Gain after FM Demodulation + (0u << 0); // 0 + } + break; + } - BK4819_WriteRegister(BK4819_REG_43, val); + BK4819_WriteRegister(BK4819_REG_43, val); } void BK4819_SetupPowerAmplifier(const uint8_t bias, const uint32_t frequency) { - // REG_36 <15:8> 0 PA Bias output 0 ~ 3.2V - // 255 = 3.2V - // 0 = 0V - // - // REG_36 <7> 0 - // 1 = Enable PA-CTL output - // 0 = Disable (Output 0 V) - // - // REG_36 <5:3> 7 PA gain 1 tuning - // 7 = max - // 0 = min - // - // REG_36 <2:0> 7 PA gain 2 tuning - // 7 = max - // 0 = min - // - // 280MHz gain 1 = 1 gain 2 = 0 gain 1 = 4 gain 2 = 2 - const uint8_t gain = (frequency < 28000000) ? (1u << 3) | (0u << 0) : (4u << 3) | (2u << 0); - const uint8_t enable = 1; - BK4819_WriteRegister(BK4819_REG_36, (bias << 8) | (enable << 7) | (gain << 0)); + // REG_36 <15:8> 0 PA Bias output 0 ~ 3.2V + // 255 = 3.2V + // 0 = 0V + // + // REG_36 <7> 0 + // 1 = Enable PA-CTL output + // 0 = Disable (Output 0 V) + // + // REG_36 <5:3> 7 PA gain 1 tuning + // 7 = max + // 0 = min + // + // REG_36 <2:0> 7 PA gain 2 tuning + // 7 = max + // 0 = min + // + // 280MHz gain 1 = 1 gain 2 = 0 gain 1 = 4 gain 2 = 2 + const uint8_t gain = (frequency < 28000000) ? (1u << 3) | (0u << 0) : (4u << 3) | (2u << 0); + const uint8_t enable = 1; + BK4819_WriteRegister(BK4819_REG_36, (bias << 8) | (enable << 7) | (gain << 0)); } void BK4819_SetFrequency(uint32_t Frequency) { - BK4819_WriteRegister(BK4819_REG_38, (Frequency >> 0) & 0xFFFF); - BK4819_WriteRegister(BK4819_REG_39, (Frequency >> 16) & 0xFFFF); + 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) + uint8_t SquelchOpenRSSIThresh, + uint8_t SquelchCloseRSSIThresh, + uint8_t SquelchOpenNoiseThresh, + uint8_t SquelchCloseNoiseThresh, + uint8_t SquelchCloseGlitchThresh, + uint8_t SquelchOpenGlitchThresh) { - // REG_70 - // - // <15> 0 Enable TONE1 - // 1 = Enable - // 0 = Disable - // - // <14:8> 0 TONE1 tuning gain - // 0 ~ 127 - // - // <7> 0 Enable TONE2 - // 1 = Enable - // 0 = Disable - // - // <6:0> 0 TONE2/FSK tuning gain - // 0 ~ 127 - // - BK4819_WriteRegister(BK4819_REG_70, 0); + // REG_70 + // + // <15> 0 Enable TONE1 + // 1 = Enable + // 0 = Disable + // + // <14:8> 0 TONE1 tuning gain + // 0 ~ 127 + // + // <7> 0 Enable TONE2 + // 1 = Enable + // 0 = Disable + // + // <6:0> 0 TONE2/FSK tuning gain + // 0 ~ 127 + // + BK4819_WriteRegister(BK4819_REG_70, 0); - // Glitch threshold for Squelch = close - // - // 0 ~ 255 - // - BK4819_WriteRegister(BK4819_REG_4D, 0xA000 | SquelchCloseGlitchThresh); + // Glitch threshold for Squelch = close + // + // 0 ~ 255 + // + BK4819_WriteRegister(BK4819_REG_4D, 0xA000 | SquelchCloseGlitchThresh); - // REG_4E - // - // <15:14> 1 ??? - // - // <13:11> 5 Squelch = open Delay Setting - // 0 ~ 7 - // - // <10:9> 7 Squelch = close Delay Setting - // 0 ~ 3 - // - // <8> 0 ??? - // - // <7:0> 8 Glitch threshold for Squelch = open - // 0 ~ 255 - // - BK4819_WriteRegister(BK4819_REG_4E, // 01 101 11 1 00000000 + // REG_4E + // + // <15:14> 1 ??? + // + // <13:11> 5 Squelch = open Delay Setting + // 0 ~ 7 + // + // <10:9> 7 Squelch = close Delay Setting + // 0 ~ 3 + // + // <8> 0 ??? + // + // <7:0> 8 Glitch threshold for Squelch = open + // 0 ~ 255 + // + BK4819_WriteRegister(BK4819_REG_4E, // 01 101 11 1 00000000 - // original (*) - (1u << 14) | // 1 ??? - (5u << 11) | // *5 squelch = open delay .. 0 ~ 7 - (6u << 9) | // *3 squelch = close delay .. 0 ~ 3 - SquelchOpenGlitchThresh); // 0 ~ 255 + // original (*) + (1u << 14) | // 1 ??? + (5u << 11) | // *5 squelch = open delay .. 0 ~ 7 + (6u << 9) | // *3 squelch = close delay .. 0 ~ 3 + SquelchOpenGlitchThresh); // 0 ~ 255 - // REG_4F - // - // <14:8> 47 Ex-noise threshold for Squelch = close - // 0 ~ 127 - // - // <7> ??? - // - // <6:0> 46 Ex-noise threshold for Squelch = open - // 0 ~ 127 - // - BK4819_WriteRegister(BK4819_REG_4F, ((uint16_t)SquelchCloseNoiseThresh << 8) | SquelchOpenNoiseThresh); + // REG_4F + // + // <14:8> 47 Ex-noise threshold for Squelch = close + // 0 ~ 127 + // + // <7> ??? + // + // <6:0> 46 Ex-noise threshold for Squelch = open + // 0 ~ 127 + // + BK4819_WriteRegister(BK4819_REG_4F, ((uint16_t)SquelchCloseNoiseThresh << 8) | SquelchOpenNoiseThresh); - // REG_78 - // - // <15:8> 72 RSSI threshold for Squelch = open 0.5dB/step - // - // <7:0> 70 RSSI threshold for Squelch = close 0.5dB/step - // - BK4819_WriteRegister(BK4819_REG_78, ((uint16_t)SquelchOpenRSSIThresh << 8) | SquelchCloseRSSIThresh); + // REG_78 + // + // <15:8> 72 RSSI threshold for Squelch = open 0.5dB/step + // + // <7:0> 70 RSSI threshold for Squelch = close 0.5dB/step + // + BK4819_WriteRegister(BK4819_REG_78, ((uint16_t)SquelchOpenRSSIThresh << 8) | SquelchCloseRSSIThresh); - BK4819_SetAF(BK4819_AF_MUTE); + BK4819_SetAF(BK4819_AF_MUTE); - BK4819_RX_TurnOn(); + BK4819_RX_TurnOn(); } void BK4819_SetAF(BK4819_AF_Type_t AF) { - // AF Output Inverse Mode = Inverse - // Undocumented bits 0x2040 - // + // AF Output Inverse Mode = Inverse + // Undocumented bits 0x2040 + // // BK4819_WriteRegister(BK4819_REG_47, 0x6040 | (AF << 8)); - BK4819_WriteRegister(BK4819_REG_47, (6u << 12) | (AF << 8) | (1u << 6)); + BK4819_WriteRegister(BK4819_REG_47, (6u << 12) | (AF << 8) | (1u << 6)); } void BK4819_SetRegValue(RegisterSpec s, uint16_t v) { - uint16_t reg = BK4819_ReadRegister(s.num); - reg &= ~(s.mask << s.offset); - BK4819_WriteRegister(s.num, reg | (v << s.offset)); + uint16_t reg = BK4819_ReadRegister(s.num); + reg &= ~(s.mask << s.offset); + BK4819_WriteRegister(s.num, reg | (v << s.offset)); } 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); // 0001111100001111 + // 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); // 0001111100001111 - // Turn off everything - BK4819_WriteRegister(BK4819_REG_30, 0); + // 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, 0b1011111111110001); // 1 0 1111 1 1 1111 0 0 0 1 + + BK4819_WriteRegister(BK4819_REG_30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_DISABLE_UNKNOWN | + 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_DISABLE_PA_GAIN | + BK4819_REG_30_DISABLE_MIC_ADC | + BK4819_REG_30_DISABLE_TX_DSP | + BK4819_REG_30_ENABLE_RX_DSP ); } void BK4819_PickRXFilterPathBasedOnFrequency(uint32_t Frequency) { - if (Frequency < 28000000) - { // VHF - BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, true); - BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); - } - else - if (Frequency == 0xFFFFFFFF) - { // OFF - BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); - BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); - } - else - { // UHF - BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); - BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, true); - } + if (Frequency < 28000000) + { // VHF + BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, true); + BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); + } + else + if (Frequency == 0xFFFFFFFF) + { // OFF + BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); + BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); + } + else + { // UHF + BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); + BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, true); + } } void BK4819_DisableScramble(void) { - const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); - BK4819_WriteRegister(BK4819_REG_31, Value & ~(1u << 1)); + const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); + BK4819_WriteRegister(BK4819_REG_31, Value & ~(1u << 1)); } void BK4819_EnableScramble(uint8_t Type) { - const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); - BK4819_WriteRegister(BK4819_REG_31, Value | (1u << 1)); + const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); + BK4819_WriteRegister(BK4819_REG_31, Value | (1u << 1)); - BK4819_WriteRegister(BK4819_REG_71, 0x68DC + (Type * 1032)); // 0110 1000 1101 1100 + BK4819_WriteRegister(BK4819_REG_71, 0x68DC + (Type * 1032)); // 0110 1000 1101 1100 } bool BK4819_CompanderEnabled(void) { - return (BK4819_ReadRegister(BK4819_REG_31) & (1u << 3)) ? true : false; + return (BK4819_ReadRegister(BK4819_REG_31) & (1u << 3)) ? true : false; } void BK4819_SetCompander(const unsigned int mode) { - // mode 0 .. OFF - // mode 1 .. TX - // mode 2 .. RX - // mode 3 .. TX and RX + // mode 0 .. OFF + // mode 1 .. TX + // mode 2 .. RX + // mode 3 .. TX and RX - const uint16_t r31 = BK4819_ReadRegister(BK4819_REG_31); + const uint16_t r31 = BK4819_ReadRegister(BK4819_REG_31); - if (mode == 0) - { // disable - BK4819_WriteRegister(BK4819_REG_31, r31 & ~(1u << 3)); - return; - } + if (mode == 0) + { // disable + BK4819_WriteRegister(BK4819_REG_31, r31 & ~(1u << 3)); + return; + } - // REG_29 - // - // <15:14> 10 Compress (AF Tx) Ratio - // 00 = Disable - // 01 = 1.333:1 - // 10 = 2:1 - // 11 = 4:1 - // - // <13:7> 86 Compress (AF Tx) 0 dB point (dB) - // - // <6:0> 64 Compress (AF Tx) noise point (dB) - // - const uint16_t compress_ratio = (mode == 1 || mode >= 3) ? 2 : 0; // 2:1 - const uint16_t compress_0dB = 86; - const uint16_t compress_noise_dB = 64; + // REG_29 + // + // <15:14> 10 Compress (AF Tx) Ratio + // 00 = Disable + // 01 = 1.333:1 + // 10 = 2:1 + // 11 = 4:1 + // + // <13:7> 86 Compress (AF Tx) 0 dB point (dB) + // + // <6:0> 64 Compress (AF Tx) noise point (dB) + // + const uint16_t compress_ratio = (mode == 1 || mode >= 3) ? 2 : 0; // 2:1 + const uint16_t compress_0dB = 86; + const uint16_t compress_noise_dB = 64; // AB40 10 1010110 1000000 - BK4819_WriteRegister(BK4819_REG_29, // (BK4819_ReadRegister(BK4819_REG_29) & ~(3u << 14)) | (compress_ratio << 14)); - (compress_ratio << 14) | - (compress_0dB << 7) | - (compress_noise_dB << 0)); + BK4819_WriteRegister(BK4819_REG_29, // (BK4819_ReadRegister(BK4819_REG_29) & ~(3u << 14)) | (compress_ratio << 14)); + (compress_ratio << 14) | + (compress_0dB << 7) | + (compress_noise_dB << 0)); - // REG_28 - // - // <15:14> 01 Expander (AF Rx) Ratio - // 00 = Disable - // 01 = 1:2 - // 10 = 1:3 - // 11 = 1:4 - // - // <13:7> 86 Expander (AF Rx) 0 dB point (dB) - // - // <6:0> 56 Expander (AF Rx) noise point (dB) - // - const uint16_t expand_ratio = (mode >= 2) ? 1 : 0; // 1:2 - const uint16_t expand_0dB = 86; - const uint16_t expand_noise_dB = 56; + // REG_28 + // + // <15:14> 01 Expander (AF Rx) Ratio + // 00 = Disable + // 01 = 1:2 + // 10 = 1:3 + // 11 = 1:4 + // + // <13:7> 86 Expander (AF Rx) 0 dB point (dB) + // + // <6:0> 56 Expander (AF Rx) noise point (dB) + // + const uint16_t expand_ratio = (mode >= 2) ? 1 : 0; // 1:2 + const uint16_t expand_0dB = 86; + const uint16_t expand_noise_dB = 56; // 6B38 01 1010110 0111000 - BK4819_WriteRegister(BK4819_REG_28, // (BK4819_ReadRegister(BK4819_REG_28) & ~(3u << 14)) | (expand_ratio << 14)); - (expand_ratio << 14) | - (expand_0dB << 7) | - (expand_noise_dB << 0)); + BK4819_WriteRegister(BK4819_REG_28, // (BK4819_ReadRegister(BK4819_REG_28) & ~(3u << 14)) | (expand_ratio << 14)); + (expand_ratio << 14) | + (expand_0dB << 7) | + (expand_noise_dB << 0)); - // enable - BK4819_WriteRegister(BK4819_REG_31, r31 | (1u << 3)); + // enable + BK4819_WriteRegister(BK4819_REG_31, r31 | (1u << 3)); } void BK4819_DisableVox(void) { - const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); - BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFB); + const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); + BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFB); } void BK4819_DisableDTMF(void) { - BK4819_WriteRegister(BK4819_REG_24, 0); + BK4819_WriteRegister(BK4819_REG_24, 0); } void BK4819_EnableDTMF(void) { - // no idea what this does - BK4819_WriteRegister(BK4819_REG_21, 0x06D8); // 0000 0110 1101 1000 + // no idea what this does + BK4819_WriteRegister(BK4819_REG_21, 0x06D8); // 0000 0110 1101 1000 - // REG_24 - // - // <15> 1 ??? - // - // <14:7> 24 Threshold - // - // <6> 1 ??? - // - // <5> 0 DTMF/SelCall enable - // 1 = Enable - // 0 = Disable - // - // <4> 1 DTMF or SelCall detection mode - // 1 = for DTMF - // 0 = for SelCall - // - // <3:0> 14 Max symbol number for SelCall detection - // + // REG_24 + // + // <15> 1 ??? + // + // <14:7> 24 Threshold + // + // <6> 1 ??? + // + // <5> 0 DTMF/SelCall enable + // 1 = Enable + // 0 = Disable + // + // <4> 1 DTMF or SelCall detection mode + // 1 = for DTMF + // 0 = for SelCall + // + // <3:0> 14 Max symbol number for SelCall detection + // // const uint16_t threshold = 24; // default, but doesn't decode non-QS radios - const uint16_t threshold = 130; // but 128 ~ 247 does - BK4819_WriteRegister(BK4819_REG_24, // 1 00011000 1 1 1 1110 - (1u << BK4819_REG_24_SHIFT_UNKNOWN_15) | - (threshold << BK4819_REG_24_SHIFT_THRESHOLD) | // 0 ~ 255 - (1u << BK4819_REG_24_SHIFT_UNKNOWN_6) | - BK4819_REG_24_ENABLE | - BK4819_REG_24_SELECT_DTMF | - (15u << BK4819_REG_24_SHIFT_MAX_SYMBOLS)); // 0 ~ 15 + const uint16_t threshold = 130; // but 128 ~ 247 does + BK4819_WriteRegister(BK4819_REG_24, // 1 00011000 1 1 1 1110 + (1u << BK4819_REG_24_SHIFT_UNKNOWN_15) | + (threshold << BK4819_REG_24_SHIFT_THRESHOLD) | // 0 ~ 255 + (1u << BK4819_REG_24_SHIFT_UNKNOWN_6) | + BK4819_REG_24_ENABLE | + BK4819_REG_24_SELECT_DTMF | + (15u << BK4819_REG_24_SHIFT_MAX_SYMBOLS)); // 0 ~ 15 } void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch) { uint16_t ToneConfig = BK4819_REG_70_ENABLE_TONE1; - BK4819_EnterTxMute(); - BK4819_SetAF(BK4819_AF_BEEP); + + BK4819_EnterTxMute(); + BK4819_SetAF(BK4819_AF_BEEP); if (bTuningGainSwitch == 0) ToneConfig |= 96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN; @@ -996,83 +971,82 @@ void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch) BK4819_WriteRegister(BK4819_REG_70, ToneConfig); BK4819_WriteRegister(BK4819_REG_30, 0); - BK4819_WriteRegister(BK4819_REG_30, BK4819_REG_30_ENABLE_AF_DAC | BK4819_REG_30_ENABLE_DISC_MODE | BK4819_REG_30_ENABLE_TX_DSP); + BK4819_WriteRegister(BK4819_REG_30, BK4819_REG_30_ENABLE_AF_DAC | BK4819_REG_30_ENABLE_DISC_MODE | BK4819_REG_30_ENABLE_TX_DSP); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); } +// level 0 ~ 127 void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay, const unsigned int level, const bool play_speaker) { - BK4819_EnterTxMute(); - - if (play_speaker) - { - AUDIO_AudioPathOn(); - BK4819_SetAF(BK4819_AF_BEEP); - } - else - BK4819_SetAF(BK4819_AF_MUTE); + BK4819_EnterTxMute(); - // level 0 ~ 127 -// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); -// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | ((level & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + if (play_speaker) + { + AUDIO_AudioPathOn(); + BK4819_SetAF(BK4819_AF_BEEP); + } + else + BK4819_SetAF(BK4819_AF_MUTE); - BK4819_EnableTXLink(); - SYSTEM_DelayMs(50); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone_Hz)); + BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | ((level & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_ExitTxMute(); - SYSTEM_DelayMs(delay); - BK4819_EnterTxMute(); + BK4819_EnableTXLink(); + SYSTEM_DelayMs(50); - if (play_speaker) - { - AUDIO_AudioPathOff(); - BK4819_SetAF(BK4819_AF_MUTE); - } - - BK4819_WriteRegister(BK4819_REG_70, 0x0000); - BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); - BK4819_ExitTxMute(); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone_Hz)); + + BK4819_ExitTxMute(); + SYSTEM_DelayMs(delay); + BK4819_EnterTxMute(); + + if (play_speaker) + { + AUDIO_AudioPathOff(); + BK4819_SetAF(BK4819_AF_MUTE); + } + + BK4819_WriteRegister(BK4819_REG_70, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); + BK4819_ExitTxMute(); } void BK4819_EnterTxMute(void) { - BK4819_WriteRegister(BK4819_REG_50, 0xBB20); + BK4819_WriteRegister(BK4819_REG_50, 0xBB20); } void BK4819_ExitTxMute(void) { - BK4819_WriteRegister(BK4819_REG_50, 0x3B20); + BK4819_WriteRegister(BK4819_REG_50, 0x3B20); } void BK4819_Sleep(void) { - BK4819_WriteRegister(BK4819_REG_30, 0); - BK4819_WriteRegister(BK4819_REG_37, 0x1D00); + 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_WriteRegister(BK4819_REG_70, 0); + BK4819_SetAF(BK4819_AF_MUTE); - BK4819_ExitTxMute(); + BK4819_ExitTxMute(); - BK4819_WriteRegister(BK4819_REG_30, 0); - BK4819_WriteRegister(BK4819_REG_30, - 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); + BK4819_WriteRegister(BK4819_REG_30, 0); + BK4819_WriteRegister(BK4819_REG_30, + 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); } #ifdef ENABLE_AIRCOPY - void BK4819_SetupAircopy(void) +void BK4819_SetupAircopy(void) { BK4819_WriteRegister(BK4819_REG_70, 0x00E0); // Enable Tone2, tuning gain 48 BK4819_WriteRegister(BK4819_REG_72, 0x3065); // Tone2 baudrate 1200 @@ -1085,717 +1059,717 @@ void BK4819_TurnsOffTones_TurnsOnRX(void) void BK4819_ResetFSK(void) { - BK4819_WriteRegister(BK4819_REG_3F, 0x0000); // Disable interrupts - BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Sync length 4 bytes, 7 byte preamble + BK4819_WriteRegister(BK4819_REG_3F, 0x0000); // Disable interrupts + BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Sync length 4 bytes, 7 byte preamble - SYSTEM_DelayMs(30); + SYSTEM_DelayMs(30); - BK4819_Idle(); + BK4819_Idle(); } void BK4819_Idle(void) { - BK4819_WriteRegister(BK4819_REG_30, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0x0000); } void BK4819_ExitBypass(void) { - BK4819_SetAF(BK4819_AF_MUTE); + BK4819_SetAF(BK4819_AF_MUTE); - // REG_7E - // - // <15> 0 AGC fix mode - // 1 = fix - // 0 = auto - // - // <14:12> 3 AGC fix index - // 3 ( 3) = max - // 2 ( 2) - // 1 ( 1) - // 0 ( 0) - // 7 (-1) - // 6 (-2) - // 5 (-3) - // 4 (-4) = min - // - // <11:6> 0 ??? - // - // <5:3> 5 DC filter band width for Tx (MIC In) - // 0 ~ 7 - // 0 = bypass DC filter - // - // <2:0> 6 DC filter band width for Rx (I.F In) - // 0 ~ 7 - // 0 = bypass DC filter - // - BK4819_WriteRegister(BK4819_REG_7E, // 0x302E); // 0 011 000000 101 110 - (0u << 15) | // 0 AGC fix mode - (3u << 12) | // 3 AGC fix index - (5u << 3) | // 5 DC Filter band width for Tx (MIC In) - (6u << 0)); // 6 DC Filter band width for Rx (I.F In) + // REG_7E + // + // <15> 0 AGC fix mode + // 1 = fix + // 0 = auto + // + // <14:12> 3 AGC fix index + // 3 ( 3) = max + // 2 ( 2) + // 1 ( 1) + // 0 ( 0) + // 7 (-1) + // 6 (-2) + // 5 (-3) + // 4 (-4) = min + // + // <11:6> 0 ??? + // + // <5:3> 5 DC filter band width for Tx (MIC In) + // 0 ~ 7 + // 0 = bypass DC filter + // + // <2:0> 6 DC filter band width for Rx (I.F In) + // 0 ~ 7 + // 0 = bypass DC filter + // + + uint16_t regVal = BK4819_ReadRegister(BK4819_REG_7E); + + // 0x302E / 0 011 000000 101 110 + BK4819_WriteRegister(BK4819_REG_7E, (regVal & ~(0b111 << 3)) + + | (5u << 3) // 5 DC Filter band width for Tx (MIC In) + + ); } void BK4819_PrepareTransmit(void) { - BK4819_ExitBypass(); - BK4819_ExitTxMute(); - BK4819_TxOn_Beep(); + 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); + 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) { - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max - // - BK4819_WriteRegister(BK4819_REG_51, 0x0000); + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max + // + BK4819_WriteRegister(BK4819_REG_51, 0x0000); } void BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(void) { - if (gRxIdleMode) - { - BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true); - BK4819_RX_TurnOn(); - } + if (gRxIdleMode) + { + BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true); + BK4819_RX_TurnOn(); + } } void BK4819_EnterDTMF_TX(bool bLocalLoopback) { - BK4819_EnableDTMF(); - BK4819_EnterTxMute(); - BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); + BK4819_EnableDTMF(); + BK4819_EnterTxMute(); + BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); - BK4819_WriteRegister(BK4819_REG_70, - BK4819_REG_70_MASK_ENABLE_TONE1 | -// (83u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | - (DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | - BK4819_REG_70_MASK_ENABLE_TONE2 | -// (83u << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)); -(DTMF_TONE2_GAIN << 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, - 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) -{ - uint16_t tone1 = 0; - uint16_t tone2 = 0; - - switch (Code) - { - case '0': tone1 = 941; tone2 = 1336; break; -// case '1': tone1 = 679; tone2 = 1209; break; - case '1': tone1 = 697; tone2 = 1209; break; - case '2': tone1 = 697; tone2 = 1336; break; -// case '3': tone1 = 679; tone2 = 1477; break; - case '3': tone1 = 697; tone2 = 1477; break; - case '4': tone1 = 770; tone2 = 1209; break; - case '5': tone1 = 770; tone2 = 1336; break; - case '6': tone1 = 770; tone2 = 1477; break; - case '7': tone1 = 852; tone2 = 1209; break; - case '8': tone1 = 852; tone2 = 1336; break; - case '9': tone1 = 852; tone2 = 1477; break; -// case 'A': tone1 = 679; tone2 = 1633; break; - case 'A': tone1 = 697; tone2 = 1633; break; - case 'B': tone1 = 770; tone2 = 1633; break; - case 'C': tone1 = 852; tone2 = 1633; break; - case 'D': tone1 = 941; tone2 = 1633; break; - case '*': tone1 = 941; tone2 = 1209; break; - case '#': tone1 = 941; tone2 = 1477; break; - } - - if (tone1 > 0) - BK4819_WriteRegister(BK4819_REG_71, (((uint32_t)tone1 * 103244) + 5000) / 10000); // with rounding - if (tone2 > 0) - BK4819_WriteRegister(BK4819_REG_72, (((uint32_t)tone2 * 103244) + 5000) / 10000); // with rounding -} - -void BK4819_PlayDTMFString(const char *pString, bool bDelayFirst, uint16_t FirstCodePersistTime, uint16_t HashCodePersistTime, uint16_t CodePersistTime, uint16_t CodeInternalTime) -{ - unsigned int i; - - if (pString == NULL) - return; - - for (i = 0; pString[i]; i++) - { - uint16_t Delay; - 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(); - - // REG_70 - // - // <15> 0 Enable TONE1 - // 1 = Enable - // 0 = Disable - // - // <14:8> 0 TONE1 tuning gain - // 0 ~ 127 - // - // <7> 0 Enable TONE2 - // 1 = Enable - // 0 = Disable - // - // <6:0> 0 TONE2/FSK amplitude - // 0 ~ 127 - // - // set the tone amplitude - // -// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); - - BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); - - BK4819_EnableTXLink(); - - SYSTEM_DelayMs(50); - - BK4819_ExitTxMute(); -} - -void BK4819_GenTail(uint8_t Tail) -{ - // REG_52 - // - // <15> 0 Enable 120/180/240 degree shift CTCSS or 134.4Hz Tail when CDCSS mode - // 0 = Normal - // 1 = Enable - // - // <14:13> 0 CTCSS tail mode selection (only valid when REG_52 <15> = 1) - // 00 = for 134.4Hz CTCSS Tail when CDCSS mode - // 01 = CTCSS0 120° phase shift - // 10 = CTCSS0 180° phase shift - // 11 = CTCSS0 240° phase shift - // - // <12> 0 CTCSSDetectionThreshold Mode - // 1 = ~0.1% - // 0 = 0.1 Hz - // - // <11:6> 0x0A CTCSS found detect threshold - // - // <5:0> 0x0F CTCSS lost detect threshold - - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz)*20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - - switch (Tail) - { - case 0: // 134.4Hz CTCSS Tail - BK4819_WriteRegister(BK4819_REG_52, 0x828F); // 1 00 0 001010 001111 - break; - case 1: // 120° phase shift - BK4819_WriteRegister(BK4819_REG_52, 0xA28F); // 1 01 0 001010 001111 - break; - case 2: // 180° phase shift - BK4819_WriteRegister(BK4819_REG_52, 0xC28F); // 1 10 0 001010 001111 - break; - case 3: // 240° phase shift - BK4819_WriteRegister(BK4819_REG_52, 0xE28F); // 1 11 0 001010 001111 - break; - case 4: // 55Hz tone freq - BK4819_WriteRegister(BK4819_REG_07, 0x046f); // 0 00 0 010001 101111 - break; - } -} - -void BK4819_EnableCDCSS(void) -{ - BK4819_GenTail(0); // CTC134 - BK4819_WriteRegister(BK4819_REG_51, 0x804A); -} - -void BK4819_EnableCTCSS(void) -{ - #ifdef ENABLE_CTCSS_TAIL_PHASE_SHIFT - //BK4819_GenTail(1); // 120° phase shift - BK4819_GenTail(2); // 180° phase shift - //BK4819_GenTail(3); // 240° phase shift - #else - BK4819_GenTail(4); // 55Hz tone freq - #endif - - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max - - BK4819_WriteRegister(BK4819_REG_51, 0x904A); // 1 0 0 1 0 0 0 0 0 1001010 -} - -uint16_t BK4819_GetRSSI(void) -{ - return BK4819_ReadRegister(BK4819_REG_67) & 0x01FF; -} - -uint8_t BK4819_GetGlitchIndicator(void) -{ - return BK4819_ReadRegister(BK4819_REG_63) & 0x00FF; -} - -uint8_t BK4819_GetExNoiceIndicator(void) -{ - return BK4819_ReadRegister(BK4819_REG_65) & 0x007F; -} - -uint16_t BK4819_GetVoiceAmplitudeOut(void) -{ - return BK4819_ReadRegister(BK4819_REG_64); -} - -uint8_t BK4819_GetAfTxRx(void) -{ - return BK4819_ReadRegister(BK4819_REG_6F) & 0x003F; -} - -bool BK4819_GetFrequencyScanResult(uint32_t *pFrequency) -{ - const uint16_t High = BK4819_ReadRegister(BK4819_REG_0D); - const bool Finished = (High & 0x8000) == 0; - if (Finished) - { - const uint16_t Low = BK4819_ReadRegister(BK4819_REG_0E); - *pFrequency = (uint32_t)((High & 0x7FF) << 16) | Low; - } - return Finished; -} - -BK4819_CssScanResult_t BK4819_GetCxCSSScanResult(uint32_t *pCdcssFreq, uint16_t *pCtcssFreq) -{ - uint16_t Low; - uint16_t High = BK4819_ReadRegister(BK4819_REG_69); - - if ((High & 0x8000) == 0) - { - Low = BK4819_ReadRegister(BK4819_REG_6A); - *pCdcssFreq = ((High & 0xFFF) << 12) | (Low & 0xFFF); - return BK4819_CSS_RESULT_CDCSS; - } - - Low = BK4819_ReadRegister(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) -{ - // REG_32 - // - // <15:14> 0 frequency scan time - // 0 = 0.2 sec - // 1 = 0.4 sec - // 2 = 0.8 sec - // 3 = 1.6 sec - // - // <13:1> ??? - // - // <0> 0 frequency scan enable - // 1 = enable - // 0 = disable - // - BK4819_WriteRegister(BK4819_REG_32, // 0x0244); // 00 0000100100010 0 - ( 0u << 14) | // 0 frequency scan Time - (290u << 1) | // ??? - ( 0u << 0)); // 0 frequency scan enable -} - -void BK4819_EnableFrequencyScan(void) -{ - // REG_32 - // - // <15:14> 0 frequency scan time - // 0 = 0.2 sec - // 1 = 0.4 sec - // 2 = 0.8 sec - // 3 = 1.6 sec - // - // <13:1> ??? - // - // <0> 0 frequency scan enable - // 1 = enable - // 0 = disable - // - BK4819_WriteRegister(BK4819_REG_32, // 0x0245); // 00 0000100100010 1 - ( 0u << 14) | // 0 frequency scan time - (290u << 1) | // ??? - ( 1u << 0)); // 1 frequency scan enable -} - -void BK4819_SetScanFrequency(uint32_t Frequency) -{ - BK4819_SetFrequency(Frequency); - - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max - // - BK4819_WriteRegister(BK4819_REG_51, - 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_ReadRegister(BK4819_REG_0B) >> 8) & 0x0F; -} - -uint8_t BK4819_GetCDCSSCodeType(void) -{ - return (BK4819_ReadRegister(BK4819_REG_0C) >> 14) & 3u; -} - -uint8_t BK4819_GetCTCShift(void) -{ - return (BK4819_ReadRegister(BK4819_REG_0C) >> 12) & 3u; -} - -uint8_t BK4819_GetCTCType(void) -{ - return (BK4819_ReadRegister(BK4819_REG_0C) >> 10) & 3u; -} - -void BK4819_SendFSKData(uint16_t *pData) -{ - unsigned int i; - uint8_t Timeout = 200; - - SYSTEM_DelayMs(20); - - BK4819_WriteRegister(BK4819_REG_3F, BK4819_REG_3F_FSK_TX_FINISHED); - BK4819_WriteRegister(BK4819_REG_59, 0x8068); - BK4819_WriteRegister(BK4819_REG_59, 0x0068); - - for (i = 0; i < 36; i++) - BK4819_WriteRegister(BK4819_REG_5F, pData[i]); - - SYSTEM_DelayMs(20); - - BK4819_WriteRegister(BK4819_REG_59, 0x2868); - - while (Timeout-- && (BK4819_ReadRegister(BK4819_REG_0C) & 1u) == 0) - SYSTEM_DelayMs(5); - - BK4819_WriteRegister(BK4819_REG_02, 0); - - SYSTEM_DelayMs(20); - - BK4819_ResetFSK(); -} - -void BK4819_PrepareFSKReceive(void) -{ - BK4819_ResetFSK(); - BK4819_WriteRegister(BK4819_REG_02, 0); - BK4819_WriteRegister(BK4819_REG_3F, 0); - BK4819_RX_TurnOn(); - BK4819_WriteRegister(BK4819_REG_3F, 0 | BK4819_REG_3F_FSK_RX_FINISHED | BK4819_REG_3F_FSK_FIFO_ALMOST_FULL); - - // Clear RX FIFO - // FSK Preamble Length 7 bytes - // FSK SyncLength Selection - BK4819_WriteRegister(BK4819_REG_59, 0x4068); - - // Enable FSK Scramble - // Enable FSK RX - // FSK Preamble Length 7 bytes - // FSK SyncLength Selection - BK4819_WriteRegister(BK4819_REG_59, 0x3068); -} - -void BK4819_PlayRoger(void) -{ - #if 0 - const uint32_t tone1_Hz = 500; - const uint32_t tone2_Hz = 700; - #else - // motorola type - const uint32_t tone1_Hz = 1540; - const uint32_t tone2_Hz = 1310; - #endif - - BK4819_EnterTxMute(); - BK4819_SetAF(BK4819_AF_MUTE); - -// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - - BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_EnableTXLink(); - SYSTEM_DelayMs(50); - - BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone1_Hz)); - - BK4819_ExitTxMute(); - SYSTEM_DelayMs(80); - BK4819_EnterTxMute(); - - BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone2_Hz)); - - BK4819_ExitTxMute(); - SYSTEM_DelayMs(80); - BK4819_EnterTxMute(); - - BK4819_WriteRegister(BK4819_REG_70, 0x0000); - BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); // 1 1 0000 0 1 1111 1 1 1 0 -} - -void BK4819_PlayRogerMDC(void) -{ - unsigned int i; - - BK4819_SetAF(BK4819_AF_MUTE); - - BK4819_WriteRegister(BK4819_REG_58, 0x37C3); // FSK Enable, - // RX Bandwidth FFSK 1200/1800 - // 0xAA or 0x55 Preamble - // 11 RX Gain, - // 101 RX Mode - // TX FFSK 1200/1800 - BK4819_WriteRegister(BK4819_REG_72, 0x3065); // Set Tone-2 to 1200Hz - BK4819_WriteRegister(BK4819_REG_70, 0x00E0); // Enable Tone-2 and Set Tone2 Gain - BK4819_WriteRegister(BK4819_REG_5D, 0x0D00); // Set FSK data length to 13 bytes - BK4819_WriteRegister(BK4819_REG_59, 0x8068); // 4 byte sync length, 6 byte preamble, clear TX FIFO - BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Same, but clear TX FIFO is now unset (clearing done) - BK4819_WriteRegister(BK4819_REG_5A, 0x5555); // First two sync bytes - BK4819_WriteRegister(BK4819_REG_5B, 0x55AA); // End of sync bytes. Total 4 bytes: 555555aa - BK4819_WriteRegister(BK4819_REG_5C, 0xAA30); // Disable CRC - - // Send the data from the roger table - for (i = 0; i < 7; i++) - BK4819_WriteRegister(BK4819_REG_5F, FSK_RogerTable[i]); - - SYSTEM_DelayMs(20); - - // 4 sync bytes, 6 byte preamble, Enable FSK TX - BK4819_WriteRegister(BK4819_REG_59, 0x0868); - - SYSTEM_DelayMs(180); - - // Stop FSK TX, reset Tone-2, disable FSK - BK4819_WriteRegister(BK4819_REG_59, 0x0068); - BK4819_WriteRegister(BK4819_REG_70, 0x0000); - BK4819_WriteRegister(BK4819_REG_58, 0x0000); -} - -void BK4819_Enable_AfDac_DiscMode_TxDsp(void) -{ - BK4819_WriteRegister(BK4819_REG_30, 0x0000); - BK4819_WriteRegister(BK4819_REG_30, 0x0302); -} - -void BK4819_GetVoxAmp(uint16_t *pResult) -{ - *pResult = BK4819_ReadRegister(BK4819_REG_64) & 0x7FFF; -} - -void BK4819_SetScrambleFrequencyControlWord(uint32_t Frequency) -{ - BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); -} - -void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code) -{ - BK4819_EnableDTMF(); - BK4819_EnterTxMute(); - - BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); -// BK4819_WriteRegister(BK4819_REG_70, 0xD3D3); BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | BK4819_REG_70_MASK_ENABLE_TONE2 | (DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)); - BK4819_EnableTXLink(); - SYSTEM_DelayMs(50); - - BK4819_PlayDTMF(Code); - - BK4819_ExitTxMute(); + 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, + 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) +{ + uint16_t tone1 = 0; + uint16_t tone2 = 0; + + switch (Code) + { + case '0': tone1 = 941; tone2 = 1336; break; + case '1': tone1 = 697; tone2 = 1209; break; + case '2': tone1 = 697; tone2 = 1336; break; + case '3': tone1 = 697; tone2 = 1477; break; + case '4': tone1 = 770; tone2 = 1209; break; + case '5': tone1 = 770; tone2 = 1336; break; + case '6': tone1 = 770; tone2 = 1477; break; + case '7': tone1 = 852; tone2 = 1209; break; + case '8': tone1 = 852; tone2 = 1336; break; + case '9': tone1 = 852; tone2 = 1477; break; + case 'A': tone1 = 697; tone2 = 1633; break; + case 'B': tone1 = 770; tone2 = 1633; break; + case 'C': tone1 = 852; tone2 = 1633; break; + case 'D': tone1 = 941; tone2 = 1633; break; + case '*': tone1 = 941; tone2 = 1209; break; + case '#': tone1 = 941; tone2 = 1477; break; + } + + if (tone1 > 0) + BK4819_WriteRegister(BK4819_REG_71, (((uint32_t)tone1 * 103244) + 5000) / 10000); // with rounding + if (tone2 > 0) + BK4819_WriteRegister(BK4819_REG_72, (((uint32_t)tone2 * 103244) + 5000) / 10000); // with rounding +} + +void BK4819_PlayDTMFString(const char *pString, bool bDelayFirst, uint16_t FirstCodePersistTime, uint16_t HashCodePersistTime, uint16_t CodePersistTime, uint16_t CodeInternalTime) +{ + unsigned int i; + + if (pString == NULL) + return; + + for (i = 0; pString[i]; i++) + { + uint16_t Delay; + 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(); + + // REG_70 + // + // <15> 0 Enable TONE1 + // 1 = Enable + // 0 = Disable + // + // <14:8> 0 TONE1 tuning gain + // 0 ~ 127 + // + // <7> 0 Enable TONE2 + // 1 = Enable + // 0 = Disable + // + // <6:0> 0 TONE2/FSK amplitude + // 0 ~ 127 + // + // set the tone amplitude + // + BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + + BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); + + BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); + + BK4819_EnableTXLink(); + + SYSTEM_DelayMs(50); + + BK4819_ExitTxMute(); +} + +void BK4819_GenTail(uint8_t Tail) +{ + // REG_52 + // + // <15> 0 Enable 120/180/240 degree shift CTCSS or 134.4Hz Tail when CDCSS mode + // 0 = Normal + // 1 = Enable + // + // <14:13> 0 CTCSS tail mode selection (only valid when REG_52 <15> = 1) + // 00 = for 134.4Hz CTCSS Tail when CDCSS mode + // 01 = CTCSS0 120° phase shift + // 10 = CTCSS0 180° phase shift + // 11 = CTCSS0 240° phase shift + // + // <12> 0 CTCSSDetectionThreshold Mode + // 1 = ~0.1% + // 0 = 0.1 Hz + // + // <11:6> 0x0A CTCSS found detect threshold + // + // <5:0> 0x0F CTCSS lost detect threshold + + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz)*20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + + switch (Tail) + { + case 0: // 134.4Hz CTCSS Tail + BK4819_WriteRegister(BK4819_REG_52, 0x828F); // 1 00 0 001010 001111 + break; + case 1: // 120° phase shift + BK4819_WriteRegister(BK4819_REG_52, 0xA28F); // 1 01 0 001010 001111 + break; + case 2: // 180° phase shift + BK4819_WriteRegister(BK4819_REG_52, 0xC28F); // 1 10 0 001010 001111 + break; + case 3: // 240° phase shift + BK4819_WriteRegister(BK4819_REG_52, 0xE28F); // 1 11 0 001010 001111 + break; + case 4: // 55Hz tone freq + BK4819_WriteRegister(BK4819_REG_07, 0x046f); // 0 00 0 010001 101111 + break; + } +} + +void BK4819_EnableCDCSS(void) +{ + BK4819_GenTail(0); // CTC134 + BK4819_WriteRegister(BK4819_REG_51, 0x804A); +} + +void BK4819_EnableCTCSS(void) +{ +#ifdef ENABLE_CTCSS_TAIL_PHASE_SHIFT + //BK4819_GenTail(1); // 120° phase shift + BK4819_GenTail(2); // 180° phase shift + //BK4819_GenTail(3); // 240° phase shift +#else + BK4819_GenTail(4); // 55Hz tone freq +#endif + + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max + + BK4819_WriteRegister(BK4819_REG_51, 0x904A); // 1 0 0 1 0 0 0 0 0 1001010 +} + +uint16_t BK4819_GetRSSI(void) +{ + return BK4819_ReadRegister(BK4819_REG_67) & 0x01FF; +} + +uint8_t BK4819_GetGlitchIndicator(void) +{ + return BK4819_ReadRegister(BK4819_REG_63) & 0x00FF; +} + +uint8_t BK4819_GetExNoiceIndicator(void) +{ + return BK4819_ReadRegister(BK4819_REG_65) & 0x007F; +} + +uint16_t BK4819_GetVoiceAmplitudeOut(void) +{ + return BK4819_ReadRegister(BK4819_REG_64); +} + +uint8_t BK4819_GetAfTxRx(void) +{ + return BK4819_ReadRegister(BK4819_REG_6F) & 0x003F; +} + +bool BK4819_GetFrequencyScanResult(uint32_t *pFrequency) +{ + const uint16_t High = BK4819_ReadRegister(BK4819_REG_0D); + const bool Finished = (High & 0x8000) == 0; + if (Finished) + { + const uint16_t Low = BK4819_ReadRegister(BK4819_REG_0E); + *pFrequency = (uint32_t)((High & 0x7FF) << 16) | Low; + } + return Finished; +} + +BK4819_CssScanResult_t BK4819_GetCxCSSScanResult(uint32_t *pCdcssFreq, uint16_t *pCtcssFreq) +{ + uint16_t Low; + uint16_t High = BK4819_ReadRegister(BK4819_REG_69); + + if ((High & 0x8000) == 0) + { + Low = BK4819_ReadRegister(BK4819_REG_6A); + *pCdcssFreq = ((High & 0xFFF) << 12) | (Low & 0xFFF); + return BK4819_CSS_RESULT_CDCSS; + } + + Low = BK4819_ReadRegister(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) +{ + // REG_32 + // + // <15:14> 0 frequency scan time + // 0 = 0.2 sec + // 1 = 0.4 sec + // 2 = 0.8 sec + // 3 = 1.6 sec + // + // <13:1> ??? + // + // <0> 0 frequency scan enable + // 1 = enable + // 0 = disable + // + BK4819_WriteRegister(BK4819_REG_32, // 0x0244); // 00 0000100100010 0 + ( 0u << 14) | // 0 frequency scan Time + (290u << 1) | // ??? + ( 0u << 0)); // 0 frequency scan enable +} + +void BK4819_EnableFrequencyScan(void) +{ + // REG_32 + // + // <15:14> 0 frequency scan time + // 0 = 0.2 sec + // 1 = 0.4 sec + // 2 = 0.8 sec + // 3 = 1.6 sec + // + // <13:1> ??? + // + // <0> 0 frequency scan enable + // 1 = enable + // 0 = disable + // + BK4819_WriteRegister(BK4819_REG_32, // 0x0245); // 00 0000100100010 1 + ( 0u << 14) | // 0 frequency scan time + (290u << 1) | // ??? + ( 1u << 0)); // 1 frequency scan enable +} + +void BK4819_SetScanFrequency(uint32_t Frequency) +{ + BK4819_SetFrequency(Frequency); + + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max + // + BK4819_WriteRegister(BK4819_REG_51, + 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_ReadRegister(BK4819_REG_0B) >> 8) & 0x0F; +} + +uint8_t BK4819_GetCDCSSCodeType(void) +{ + return (BK4819_ReadRegister(BK4819_REG_0C) >> 14) & 3u; +} + +uint8_t BK4819_GetCTCShift(void) +{ + return (BK4819_ReadRegister(BK4819_REG_0C) >> 12) & 3u; +} + +uint8_t BK4819_GetCTCType(void) +{ + return (BK4819_ReadRegister(BK4819_REG_0C) >> 10) & 3u; +} + +void BK4819_SendFSKData(uint16_t *pData) +{ + unsigned int i; + uint8_t Timeout = 200; + + SYSTEM_DelayMs(20); + + BK4819_WriteRegister(BK4819_REG_3F, BK4819_REG_3F_FSK_TX_FINISHED); + BK4819_WriteRegister(BK4819_REG_59, 0x8068); + BK4819_WriteRegister(BK4819_REG_59, 0x0068); + + for (i = 0; i < 36; i++) + BK4819_WriteRegister(BK4819_REG_5F, pData[i]); + + SYSTEM_DelayMs(20); + + BK4819_WriteRegister(BK4819_REG_59, 0x2868); + + while (Timeout-- && (BK4819_ReadRegister(BK4819_REG_0C) & 1u) == 0) + SYSTEM_DelayMs(5); + + BK4819_WriteRegister(BK4819_REG_02, 0); + + SYSTEM_DelayMs(20); + + BK4819_ResetFSK(); +} + +void BK4819_PrepareFSKReceive(void) +{ + BK4819_ResetFSK(); + BK4819_WriteRegister(BK4819_REG_02, 0); + BK4819_WriteRegister(BK4819_REG_3F, 0); + BK4819_RX_TurnOn(); + BK4819_WriteRegister(BK4819_REG_3F, 0 | BK4819_REG_3F_FSK_RX_FINISHED | BK4819_REG_3F_FSK_FIFO_ALMOST_FULL); + + // Clear RX FIFO + // FSK Preamble Length 7 bytes + // FSK SyncLength Selection + BK4819_WriteRegister(BK4819_REG_59, 0x4068); + + // Enable FSK Scramble + // Enable FSK RX + // FSK Preamble Length 7 bytes + // FSK SyncLength Selection + BK4819_WriteRegister(BK4819_REG_59, 0x3068); +} + +void BK4819_PlayRoger(void) +{ +#if 0 + const uint32_t tone1_Hz = 500; + const uint32_t tone2_Hz = 700; +#else + // motorola type + const uint32_t tone1_Hz = 1540; + const uint32_t tone2_Hz = 1310; +#endif + + BK4819_EnterTxMute(); + BK4819_SetAF(BK4819_AF_MUTE); + + BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + + BK4819_EnableTXLink(); + SYSTEM_DelayMs(50); + + BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone1_Hz)); + + BK4819_ExitTxMute(); + SYSTEM_DelayMs(80); + BK4819_EnterTxMute(); + + BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone2_Hz)); + + BK4819_ExitTxMute(); + SYSTEM_DelayMs(80); + BK4819_EnterTxMute(); + + BK4819_WriteRegister(BK4819_REG_70, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); // 1 1 0000 0 1 1111 1 1 1 0 +} + +void BK4819_PlayRogerMDC(void) +{ + unsigned int i; + + BK4819_SetAF(BK4819_AF_MUTE); + + BK4819_WriteRegister(BK4819_REG_58, 0x37C3); // FSK Enable, + // RX Bandwidth FFSK 1200/1800 + // 0xAA or 0x55 Preamble + // 11 RX Gain, + // 101 RX Mode + // TX FFSK 1200/1800 + BK4819_WriteRegister(BK4819_REG_72, 0x3065); // Set Tone-2 to 1200Hz + BK4819_WriteRegister(BK4819_REG_70, 0x00E0); // Enable Tone-2 and Set Tone2 Gain + BK4819_WriteRegister(BK4819_REG_5D, 0x0D00); // Set FSK data length to 13 bytes + BK4819_WriteRegister(BK4819_REG_59, 0x8068); // 4 byte sync length, 6 byte preamble, clear TX FIFO + BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Same, but clear TX FIFO is now unset (clearing done) + BK4819_WriteRegister(BK4819_REG_5A, 0x5555); // First two sync bytes + BK4819_WriteRegister(BK4819_REG_5B, 0x55AA); // End of sync bytes. Total 4 bytes: 555555aa + BK4819_WriteRegister(BK4819_REG_5C, 0xAA30); // Disable CRC + + // Send the data from the roger table + for (i = 0; i < 7; i++) + BK4819_WriteRegister(BK4819_REG_5F, FSK_RogerTable[i]); + + SYSTEM_DelayMs(20); + + // 4 sync bytes, 6 byte preamble, Enable FSK TX + BK4819_WriteRegister(BK4819_REG_59, 0x0868); + + SYSTEM_DelayMs(180); + + // Stop FSK TX, reset Tone-2, disable FSK + BK4819_WriteRegister(BK4819_REG_59, 0x0068); + BK4819_WriteRegister(BK4819_REG_70, 0x0000); + BK4819_WriteRegister(BK4819_REG_58, 0x0000); +} + +void BK4819_Enable_AfDac_DiscMode_TxDsp(void) +{ + BK4819_WriteRegister(BK4819_REG_30, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0x0302); +} + +void BK4819_GetVoxAmp(uint16_t *pResult) +{ + *pResult = BK4819_ReadRegister(BK4819_REG_64) & 0x7FFF; +} + +void BK4819_SetScrambleFrequencyControlWord(uint32_t Frequency) +{ + BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); +} + +void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code) +{ + BK4819_EnableDTMF(); + BK4819_EnterTxMute(); + + BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); + + BK4819_WriteRegister(BK4819_REG_70, + BK4819_REG_70_MASK_ENABLE_TONE1 | + (DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | + BK4819_REG_70_MASK_ENABLE_TONE2 | + (DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)); + + BK4819_EnableTXLink(); + + SYSTEM_DelayMs(50); + + BK4819_PlayDTMF(Code); + + BK4819_ExitTxMute(); +} \ No newline at end of file diff --git a/driver/bk4819.h b/driver/bk4819.h index c5dcdb4..3248c17 100644 --- a/driver/bk4819.h +++ b/driver/bk4819.h @@ -72,8 +72,8 @@ void BK4819_SetRegValue(RegisterSpec s, uint16_t v); void BK4819_WriteU8(uint8_t Data); void BK4819_WriteU16(uint16_t Data); -void BK4819_EnableAGC(); -void BK4819_DisableAGC(); +void BK4819_SetAGC(bool enable); +void BK4819_InitAGC(); void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet); diff --git a/payment/sponsors.md b/payment/sponsors.md index ddec26e..bf56beb 100644 --- a/payment/sponsors.md +++ b/payment/sponsors.md @@ -20,10 +20,14 @@ |-----------|-------|-------:|------------| | 忠 | 微信打赏 | ¥20.00 | 2023-11-19 | | BG6SNG | 支付宝打赏 | ¥10.00 | 2023-11-20 | -| 江璐璐 | 支付宝打赏 | ¥10.00 | 2023-11-21 -| 济南黄河业余无线电 | 微信打赏 | ¥25.00 | 2023-11-22 -| DE.BG9JAQ | 微信打赏 | ¥9.99 | 2023-11-22 -| 姜先生 | 微信打赏 | ¥66.6 | 2023-11-28 +| 江璐璐 | 支付宝打赏 | ¥10.00 | 2023-11-21 | +| 济南黄河业余无线电 | 微信打赏 | ¥25.00 | 2023-11-22 | +| DE.BG9JAQ | 微信打赏 | ¥9.99 | 2023-11-22 | +| 姜先生 | 微信打赏 | ¥66.6 | 2023-11-28 | +| Hui-Shao | 支付宝打赏 | ¥10.0 | 2023-11-29| +| BI1OWT | 支付宝打赏 | ¥10.0 | 2023-12-01| +| 蛋 | 微信打赏 | ¥6.66 | 2023-12-01| + diff --git a/ui/status.c b/ui/status.c index 01e18da..3923f82 100644 --- a/ui/status.c +++ b/ui/status.c @@ -154,9 +154,13 @@ void UI_DisplayStatus() // KEY-LOCK indicator if (gEeprom.KEY_LOCK) { + memmove(line + x, BITMAP_KeyLock, sizeof(BITMAP_KeyLock)); x += sizeof(BITMAP_KeyLock); x1 = x; + //按键锁定禁止发射 + // RADIO_SetVfoState(VFO_STATE_TX_DISABLE); + } else if (gWasFKeyPressed) diff --git a/uv-k5font/ee b/uv-k5font/ee index e69de29..e46a89e 100644 --- a/uv-k5font/ee +++ b/uv-k5font/ee @@ -0,0 +1,2 @@ +!(A&&B)&&(!C || (A && C)) && !(A && !C) + diff --git a/uv-k5font/font.xlsx b/uv-k5font/font.xlsx index febb32754d5fdb5f6f124e84987dfa8cb1c32f1d..bc58f64ce33ea1abc0602ec2e0c2f39ee60107dd 100644 GIT binary patch delta 45402 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 LZ*5%9H@g1^Bk|$w diff --git a/version.c b/version.c index b2bc0a8..a536d6e 100644 --- a/version.c +++ b/version.c @@ -4,7 +4,7 @@ #ifdef GIT_HASH #define VER GIT_HASH #else - #define VER "231004" + #define VER "102" #endif #ifndef ONE_OF_ELEVEN_VER