From 9366901ccbdb996e945a7a2461914803b2e58f2f Mon Sep 17 00:00:00 2001 From: wu58430 Date: Sun, 3 Dec 2023 12:27:34 +0800 Subject: [PATCH] mdc tx end test --- .idea/workspace.xml | 78 ++- CMakeLists.txt | 2 +- Makefile | 18 +- app/app.c | 19 +- app/mdc1200.c | 562 +++++++++++++++ app/mdc1200.h | 106 +++ app/spectrum.c | 37 +- audio.c | 4 +- .../CMakeFiles/clion-Debug-log.txt | 13 +- driver/bk4819.c | 647 +++++++++++++++++- driver/bk4819.h | 5 + driver/crc.c | 36 +- driver/crc.h | 1 + driver/systick.c | 20 + driver/systick.h | 1 + radio.c | 29 +- ui/main.c | 20 +- ui/main.h | 2 +- 版本说明.txt | 17 + 19 files changed, 1533 insertions(+), 84 deletions(-) create mode 100644 app/mdc1200.c create mode 100644 app/mdc1200.h diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d2caabd..4c75cb3 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -20,8 +20,26 @@ - + + + + + + + + + + + + + + + + + + + - { - "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" + +}]]> + + + + + @@ -291,6 +322,7 @@ - \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 912475f..717986f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -816,4 +816,4 @@ add_executable(uv_k5_firmware_custom_0_17 sram-overlay.c sram-overlay.h version.c - version.h chinese.h) + version.h chinese.h app/mdc1200.c app/mdc1200.c) diff --git a/Makefile b/Makefile index 6381f47..1a761df 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,10 @@ ENABLE_REDUCE_LOW_MID_TX_POWER:= 0 ENABLE_BYP_RAW_DEMODULATORS := 0 ENABLE_BLMIN_TMP_OFF := 0 ENABLE_SCAN_RANGES := 1 +ENABLE_MDC1200 := 1 +ENABLE_MDC1200_SHOW_OP_ARG := 1 +ENABLE_MDC1200_SIDE_BEEP := 1 + ############################################################# @@ -72,7 +76,9 @@ ifeq ($(ENABLE_OVERLAY),1) OBJS += sram-overlay.o endif OBJS += external/printf/printf.o - +ifeq ($(ENABLE_MDC1200),1) + OBJS += app/mdc1200.o +endif # Drivers OBJS += driver/adc.o ifeq ($(ENABLE_UART),1) @@ -233,7 +239,15 @@ else # We get most of the space savings if LTO creates problems CFLAGS += -ffunction-sections -fdata-sections endif - +ifeq ($(ENABLE_MDC1200),1) + CFLAGS += -DENABLE_MDC1200 +endif +ifeq ($(ENABLE_MDC1200_SHOW_OP_ARG),1) + CFLAGS += -DENABLE_MDC1200_SHOW_OP_ARG +endif +ifeq ($(ENABLE_MDC1200_SIDE_BEEP),1) + CFLAGS += -DENABLE_MDC1200_SIDE_BEEP +endif # May cause unhelpful build failures #CFLAGS += -Wpadded diff --git a/app/app.c b/app/app.c index 93f9c52..2797584 100644 --- a/app/app.c +++ b/app/app.c @@ -446,6 +446,7 @@ static void HandleFunction(void) void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix) { + (void)reset_am_fix; const unsigned int chan = gEeprom.RX_VFO; // const unsigned int chan = gRxVfo->CHANNEL_SAVE; @@ -498,31 +499,13 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix) gUpdateStatus = true; } - { // RF RX front end gain - // original QS front end register settings - // 0x03BE 00000 011 101 11 110 - const uint8_t orig_lna_short = 3; // 0dB - const uint8_t orig_lna = 5; // -4dB - const uint8_t orig_mixer = 3; // 0dB - 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 AM_fix_10ms(chan); } - else { // FM RX mode - BK4819_WriteRegister(BK4819_REG_13, (orig_lna_short << 8) | (orig_lna << 5) | (orig_mixer << 3) | (orig_pga << 0)); - } -#else - (void)reset_am_fix; - BK4819_WriteRegister(BK4819_REG_13, (orig_lna_short << 8) | (orig_lna << 5) | (orig_mixer << 3) | (orig_pga << 0)); #endif - } // AF gain - original QS values // if (gRxVfo->Modulation != MODULATION_FM){ diff --git a/app/mdc1200.c b/app/mdc1200.c new file mode 100644 index 0000000..e76754a --- /dev/null +++ b/app/mdc1200.c @@ -0,0 +1,562 @@ + +#include "driver/bk4819.h" +#include "driver/crc.h" + +#include "mdc1200.h" +#include "misc.h" +#include + + +const uint8_t mdc1200_pre_amble[] = {0x00, 0x00, 0x00}; +const uint8_t mdc1200_sync[5] = {0x07, 0x09, 0x2a, 0x44, 0x6f}; + +uint8_t mdc1200_sync_suc_xor[sizeof(mdc1200_sync)]; + + +#if 1 + +uint16_t compute_crc(const void *data, const unsigned int data_len) +{ // let the CPU's hardware do some work :) + uint16_t crc; + CRC_InitReverse(); + crc = CRC_Calculate(data, data_len); + CRC_Init(); + return crc; +} + +#elif 1 + +uint16_t compute_crc(const void *data, const unsigned int data_len) + { // using the reverse computation and polynominal avoids having to reverse the bit order during and after + unsigned int i; + const uint8_t *data8 = (const uint8_t *)data; + uint16_t crc = 0; + for (i = 0; i < data_len; i++) + { + unsigned int k; + crc ^= data8[i]; + for (k = 8; k > 0; k--) + crc = (crc & 1u) ? (crc >> 1) ^ 0x8408 : crc >> 1; + } + return crc ^ 0xffff; + } + +#else + + uint16_t compute_crc(const void *data, const unsigned int data_len) + { + unsigned int i; + const uint8_t *data8 = (const uint8_t *)data; + uint16_t crc = 0; + + for (i = 0; i < data_len; i++) + { + uint8_t mask; + + // bit reverse each data byte + const uint8_t bits = bit_reverse_8(*data8++); + + for (mask = 0x0080; mask != 0; mask >>= 1) + { + uint16_t msb = crc & 0x8000; + if (bits & mask) + msb ^= 0x8000; + crc <<= 1; + if (msb) + crc ^= 0x1021; + } + } + + // bit reverse and invert the final CRC + return bit_reverse_16(crc) ^ 0xffff; + } + +#endif + +void error_correction(void *data) +{ // can correct up to 3 or 4 corrupted bits (I think) + + int i; + uint8_t shift_reg; + uint8_t syn; + uint8_t *data8 = (uint8_t *)data; + + for (i = 0, shift_reg = 0, syn = 0; i < MDC1200_FEC_K; i++) + { + const uint8_t bi = data8[i]; + int bit_num; + for (bit_num = 0; bit_num < 8; bit_num++) + { + uint8_t b; + unsigned int k = 0; + + shift_reg = (shift_reg << 1) | ((bi >> bit_num) & 1u); + b = ((shift_reg >> 6) ^ (shift_reg >> 5) ^ (shift_reg >> 2) ^ (shift_reg >> 0)) & 1u; + syn = (syn << 1) | (((b ^ (data8[i + MDC1200_FEC_K] >> bit_num)) & 1u) ? 1u : 0u); + + if (syn & 0x80) k++; + if (syn & 0x20) k++; + if (syn & 0x04) k++; + if (syn & 0x02) k++; + + if (k >= 3) + { // correct a bit error + int ii = i; + int bn = bit_num - 7; + if (bn < 0) + { + bn += 8; + ii--; + } + if (ii >= 0) + data8[ii] ^= 1u << bn; // fix a bit + syn ^= 0xA6; // 10100110 + } + } + } +} + +bool decode_data(void *data) +{ + uint16_t crc1; + uint16_t crc2; + uint8_t *data8 = (uint8_t *)data; + + { // de-interleave + + unsigned int i; + unsigned int k; + unsigned int m; + uint8_t deinterleaved[(MDC1200_FEC_K * 2) * 8]; // temp individual bit storage + + // interleave order + // 0, 16, 32, 48, 64, 80, 96, + // 1, 17, 33, 49, 65, 81, 97, + // 2, 18, 34, 50, 66, 82, 98, + // 3, 19, 35, 51, 67, 83, 99, + // 4, 20, 36, 52, 68, 84, 100, + // 5, 21, 37, 53, 69, 85, 101, + // 6, 22, 38, 54, 70, 86, 102, + // 7, 23, 39, 55, 71, 87, 103, + // 8, 24, 40, 56, 72, 88, 104, + // 9, 25, 41, 57, 73, 89, 105, + // 10, 26, 42, 58, 74, 90, 106, + // 11, 27, 43, 59, 75, 91, 107, + // 12, 28, 44, 60, 76, 92, 108, + // 13, 29, 45, 61, 77, 93, 109, + // 14, 30, 46, 62, 78, 94, 110, + // 15, 31, 47, 63, 79, 95, 111 + + // de-interleave the received bits + for (i = 0, k = 0; i < 16; i++) + { + for (m = 0; m < MDC1200_FEC_K; m++) + { + const unsigned int n = (m * 16) + i; + deinterleaved[k++] = (data8[n >> 3] >> ((7 - n) & 7u)) & 1u; + } + } + + // copy the de-interleaved bits back into the data buffer + for (i = 0, m = 0; i < (MDC1200_FEC_K * 2); i++) + { + unsigned int k; + uint8_t b = 0; + for (k = 0; k < 8; k++) + if (deinterleaved[m++]) + b |= 1u << k; + data8[i] = b; + } + } + + // try to correct the odd corrupted bit + error_correction(data); + + // rx'ed de-interleaved data (min 14 bytes) looks like this .. + // + // OP ARG ID CRC STATUS FEC bits + // 01 80 1234 2E3E 00 6580A862DD8808 + + crc1 = compute_crc(data, 4); + crc2 = ((uint16_t)data8[5] << 8) | (data8[4] << 0); + + return (crc1 == crc2) ? true : false; +} + +// ********************************************************** +// TX + +void xor_modulation(void *data, const unsigned int size) +{ // exclusive-or succesive bits - the entire packet + unsigned int i; + uint8_t *data8 = (uint8_t *)data; + uint8_t prev_bit = 0; + for (i = 0; i < size; i++) + { + int bit_num; + uint8_t in = data8[i]; + uint8_t out = 0; + for (bit_num = 7; bit_num >= 0; bit_num--) + { + const uint8_t new_bit = (in >> bit_num) & 1u; + if (new_bit != prev_bit) + out |= 1u << bit_num; // previous bit and new bit are different - send a '1' + prev_bit = new_bit; + } + data8[i] = out ^ 0xff; + } +} + +uint8_t * encode_data(void *data) +{ + // R=1/2 K=7 convolutional coder + // + // OP ARG ID CRC STATUS FEC bits + // 01 80 1234 2E3E 00 6580A862DD8808 + // + // 1. reverse the bit order for each byte of the first 7 bytes (to undo the reversal performed for display, above) + // 2. feed those bits into a shift register which is preloaded with all zeros + // 3. for each bit, calculate the modulo-2 sum: bit(n-0) + bit(n-2) + bit(n-5) + bit(n-6) + // 4. then for each byte of resulting output, again reverse those bits to generate the values shown above + + uint8_t *data8 = (uint8_t *)data; + + { // add the FEC bits to the end of the data + unsigned int i; + uint8_t shift_reg = 0; + for (i = 0; i < MDC1200_FEC_K; i++) + { + unsigned int bit_num; + const uint8_t bi = data8[i]; + uint8_t bo = 0; + for (bit_num = 0; bit_num < 8; bit_num++) + { + shift_reg = (shift_reg << 1) | ((bi >> bit_num) & 1u); + bo |= (((shift_reg >> 6) ^ (shift_reg >> 5) ^ (shift_reg >> 2) ^ (shift_reg >> 0)) & 1u) << bit_num; + } + data8[MDC1200_FEC_K + i] = bo; + } + } + + + { // interleave the bits + + unsigned int i; + unsigned int k; + uint8_t interleaved[(MDC1200_FEC_K * 2) * 8]; // temp individual bit storage + + // interleave order + // 0, 16, 32, 48, 64, 80, 96, + // 1, 17, 33, 49, 65, 81, 97, + // 2, 18, 34, 50, 66, 82, 98, + // 3, 19, 35, 51, 67, 83, 99, + // 4, 20, 36, 52, 68, 84, 100, + // 5, 21, 37, 53, 69, 85, 101, + // 6, 22, 38, 54, 70, 86, 102, + // 7, 23, 39, 55, 71, 87, 103, + // 8, 24, 40, 56, 72, 88, 104, + // 9, 25, 41, 57, 73, 89, 105, + // 10, 26, 42, 58, 74, 90, 106, + // 11, 27, 43, 59, 75, 91, 107, + // 12, 28, 44, 60, 76, 92, 108, + // 13, 29, 45, 61, 77, 93, 109, + // 14, 30, 46, 62, 78, 94, 110, + // 15, 31, 47, 63, 79, 95, 111 + + // bit interleaver + for (i = 0, k = 0; i < (MDC1200_FEC_K * 2); i++) + { + unsigned int bit_num; + const uint8_t b = data8[i]; + for (bit_num = 0; bit_num < 8; bit_num++) + { + interleaved[k] = (b >> bit_num) & 1u; + k += 16; + if (k >= sizeof(interleaved)) + k -= sizeof(interleaved) - 1; + } + } + + // copy the interleaved bits back to the data buffer + for (i = 0, k = 0; i < (MDC1200_FEC_K * 2); i++) + { + int bit_num; + uint8_t b = 0; + for (bit_num = 7; bit_num >= 0; bit_num--) + if (interleaved[k++]) + b |= 1u << bit_num; + data8[i] = b; + } + } + + return data8 + (MDC1200_FEC_K * 2); +} + +unsigned int MDC1200_encode_single_packet(void *data, const uint8_t op, const uint8_t arg, const uint16_t unit_id) +{ + unsigned int size; + uint16_t crc; + uint8_t *p = (uint8_t *)data; + + memcpy(p, mdc1200_pre_amble, sizeof(mdc1200_pre_amble)); + p += sizeof(mdc1200_pre_amble); + memcpy(p, mdc1200_sync, sizeof(mdc1200_sync)); + p += sizeof(mdc1200_sync); + + p[0] = op; + p[1] = arg; + p[2] = (unit_id >> 8) & 0x00ff; + p[3] = (unit_id >> 0) & 0x00ff; + crc = compute_crc(p, 4); + p[4] = (crc >> 0) & 0x00ff; + p[5] = (crc >> 8) & 0x00ff; + p[6] = 0; // unknown field (00 for PTTIDs, 76 for STS and MSG) + + p = encode_data(p); + + size = (unsigned int)(p - (uint8_t *)data); + + xor_modulation(data, size); + + return size; +} + + +struct { + uint8_t bit; + uint8_t prev_bit; + uint8_t xor_bit; + uint64_t shift_reg; + unsigned int bit_count; + unsigned int stage; + bool inverted_sync; + unsigned int data_index; + uint8_t data[40]; +} rx; + +void MDC1200_reset_rx(void) +{ + memset(&rx, 0, sizeof(rx)); +} + +bool MDC1200_process_rx_data( + const void *buffer, + const unsigned int size, + //const bool inverted, + uint8_t *op, + uint8_t *arg, + uint16_t *unit_id) +{ + const uint8_t *buffer8 = (const uint8_t *)buffer; + unsigned int index; + + // 04 8D BF 66 58 sync + // FB 72 40 99 A7 inverted sync + // + // 04 8D BF 66 58 40 C4 B0 32 BA F9 33 18 35 08 83 F6 0C 36 .. 80 87 20 23 2C AE 22 10 26 0F 02 A4 08 24 + // 04 8D BF 66 58 45 DB 03 07 BC FA 35 2E 33 0E 83 0E 83 69 .. 86 92 02 05 28 AC 26 34 22 0B 02 0B 02 4E + + memset(&rx, 0, sizeof(rx)); + + for (index = 0; index < size; index++) + { + int bit; + const uint8_t rx_byte = buffer8[index]; + + for (bit = 7; bit >= 0; bit--) + { + unsigned int i; + + rx.prev_bit = rx.bit; + + rx.bit = (rx_byte >> bit) & 1u; + + rx.xor_bit = (rx.xor_bit ^ rx.bit) & 1u; // toggle our bit if the rx bit is high + + rx.shift_reg = (rx.shift_reg << 1) | rx.xor_bit; + rx.bit_count++; + + // ********* + + if (rx.stage == 0) + { // looking for the 40-bit sync pattern + + const unsigned int sync_bit_ok_threshold = 32; + + if (rx.bit_count >= 40) + { + // 40-bit sync pattern + uint64_t sync_nor = 0x07092a446fu; // normal + uint64_t sync_inv = 0xffffffffffu ^ sync_nor; // bit inverted + + sync_nor ^= rx.shift_reg; + sync_inv ^= rx.shift_reg; + + unsigned int nor_count = 0; + unsigned int inv_count = 0; + for (i = 40; i > 0; i--, sync_nor >>= 1, sync_inv >>= 1) + { + nor_count += sync_nor & 1u; + inv_count += sync_inv & 1u; + } + nor_count = 40 - nor_count; + inv_count = 40 - inv_count; + + + + if (nor_count >= sync_bit_ok_threshold || inv_count >= sync_bit_ok_threshold) + { // good enough + + rx.inverted_sync = (inv_count > nor_count) ? true : false; + rx.data_index = 0; + rx.bit_count = 0; + rx.stage = 1; + + + } + } + + continue; + } + + if (rx.bit_count < 8) + continue; + + rx.bit_count = 0; + + rx.data[rx.data_index++] = rx.shift_reg & 0xff; // save the last 8 bits + + if (rx.data_index < (MDC1200_FEC_K * 2)) + continue; + + + + if (!decode_data(rx.data)) + { + MDC1200_reset_rx(); + + + + continue; + } + + // extract the info from the packet + *op = rx.data[0]; + *arg = rx.data[1]; + *unit_id = ((uint16_t)rx.data[2] << 8) | (rx.data[3] << 0); + + + // reset the detector + MDC1200_reset_rx(); + + return true; + } + } + + MDC1200_reset_rx(); + + return false; +} + +uint8_t mdc1200_rx_buffer[sizeof(mdc1200_sync_suc_xor) + (MDC1200_FEC_K * 2)]; +unsigned int mdc1200_rx_buffer_index = 0; + +uint8_t mdc1200_op; +uint8_t mdc1200_arg; +uint16_t mdc1200_unit_id; +uint8_t mdc1200_rx_ready_tick_500ms; + +void MDC1200_process_rx(const uint16_t interrupt_bits) +{ + const uint16_t rx_sync_flags = BK4819_ReadRegister(0x0B); + const uint16_t fsk_reg59 = BK4819_ReadRegister(0x59) & ~((1u << 15) | (1u << 14) | (1u << 12) | (1u << 11)); + + const bool rx_sync = (interrupt_bits & BK4819_REG_02_FSK_RX_SYNC) ? true : false; + const bool rx_sync_neg = (rx_sync_flags & (1u << 7)) ? true : false; + const bool rx_fifo_almost_full = (interrupt_bits & BK4819_REG_02_FSK_FIFO_ALMOST_FULL) ? true : false; + const bool rx_finished = (interrupt_bits & BK4819_REG_02_FSK_RX_FINISHED) ? true : false; + + + if (rx_sync) + { + + mdc1200_rx_buffer_index = 0; + + { + unsigned int i; + memset(mdc1200_rx_buffer, 0, sizeof(mdc1200_rx_buffer)); + for (i = 0; i < sizeof(mdc1200_sync_suc_xor); i++) + mdc1200_rx_buffer[mdc1200_rx_buffer_index++] = mdc1200_sync_suc_xor[i] ^ (rx_sync_neg ? 0xFF : 0x00); + } + + + + + + + } + + if (rx_fifo_almost_full) + { + unsigned int i; + const unsigned int count = BK4819_ReadRegister(0x5E) & (7u << 0); // almost full threshold + + + // fetch received packet data + for (i = 0; i < count; i++) + { + const uint16_t word = BK4819_ReadRegister(0x5F) ^ (rx_sync_neg ? 0xFFFF : 0x0000); + + + + if (mdc1200_rx_buffer_index < sizeof(mdc1200_rx_buffer)) + mdc1200_rx_buffer[mdc1200_rx_buffer_index++] = (word >> 0) & 0xff; + + if (mdc1200_rx_buffer_index < sizeof(mdc1200_rx_buffer)) + mdc1200_rx_buffer[mdc1200_rx_buffer_index++] = (word >> 8) & 0xff; + } + + + if (mdc1200_rx_buffer_index >= sizeof(mdc1200_rx_buffer)) + { + BK4819_WriteRegister(0x59, (1u << 15) | (1u << 14) | fsk_reg59); + BK4819_WriteRegister(0x59, (1u << 12) | fsk_reg59); + + + if (MDC1200_process_rx_data( + mdc1200_rx_buffer, + mdc1200_rx_buffer_index, + &mdc1200_op, + &mdc1200_arg, + &mdc1200_unit_id)) { + mdc1200_rx_ready_tick_500ms = 2 * 6; // 6 second MDC display time + + gUpdateDisplay = true; + + } + + mdc1200_rx_buffer_index = 0; + } + } + + if (rx_finished) + { + mdc1200_rx_buffer_index = 0; + + + BK4819_WriteRegister(0x59, (1u << 15) | (1u << 14) | fsk_reg59); + BK4819_WriteRegister(0x59, (1u << 12) | fsk_reg59); + + + } +} + + + +void MDC1200_init(void) +{ + memcpy(mdc1200_sync_suc_xor, mdc1200_sync, sizeof(mdc1200_sync)); + xor_modulation(mdc1200_sync_suc_xor, sizeof(mdc1200_sync_suc_xor)); + + MDC1200_reset_rx(); +} diff --git a/app/mdc1200.h b/app/mdc1200.h new file mode 100644 index 0000000..3f9d5e8 --- /dev/null +++ b/app/mdc1200.h @@ -0,0 +1,106 @@ + +#ifndef MDC1200H +#define MDC1200H + +#include +#include + +#define MDC1200_FEC_K 7 // R=1/2 K=7 convolutional coder + +// 0x00 (0x81) emergency alarm +// 0x20 (0x00) emergency alarm ack +// +// 0x01 (0x80) is PTT ID +// 0x01 (0x00) is POST ID +// 0x11 (0x8A) is REMOTE MONITOR +// 0x22 (0x06) is STATUS REQ +// 0x2B (0x0C) is RADIO ENABLE +// 0x2B (0x00) is RADIO DISABLE +// 0x35 (0x89) is CALL ALERT +// 0x46 (0xXX) is STS XX +// 0x47 (0xXX) is MSG XX +// +// 0x63 (0x85) is RADIO CHECK +// 0x30 (0x00) is RADIO CHECK ack +// +// * CALL ALERT [Double packet - 2 codewords, 1234 places call to 5678] +// 3589 5678 830D 1234 [Spectra, Astro Saber "PAGE", Maxtrac "CA" w/Ack Expected=Y] +// 3589 5678 810D 1234 [Maxtrac "CA" w/Ack Expected=N] +// +// * VOICE SELECTIVE CALL [Double packet - 2 codewords, 1234 places call to 5678] +// 3589 5678 8205 1234 [Spectra "CALL"] +// 3589 5678 8015 1234 [Maxtrac "SC", Astro Saber "CALL"] +// +// * CALL ALERT ACKNOWLEDGE [Double packet - 2 codewords, 5678 acks the call from 1234] +// 3589 1234 A000 5678 +// +// * SIMPLE STATUS [unit 1234 transmits status number X] +// 460X 1234 +// +// * STATUS ACKNOWLEDGE +// 2300 1234 +// +// * STATUS REQUEST [i.e. unit 5678 report your last status] +// 2206 5678 +// +// * STATUS RESPONSE [from target 5678 when interrogated] +// 060X 5678 +// +// * INBOUND MESSAGE +// 470X 1234 [ack expected] +// 070X 1234 [ack not expected CDM1550] +// +// * INBOUND MESSAGE ACKNOWLEDGE +// 2300 1234 +// +// * REMOTE MONITOR [No MDC response from target unless it has PTT ID] +// 118A 5678 [118A per KA6SQG] +// +// * SELECTIVE RADIO INHIBIT [Fixed end inhibits target 5678] +// 2B00 5678 +// +// * SELECTIVE RADIO INHIBIT ACKNOWLEDGE [5678 acks the inhibit] +// 0B00 5678 +// +// * SELECTIVE RADIO INHIBIT CANCEL [Fixed end enables target 5678] +// 2B0C 5678 +// +// * SELECTIVE RADIO INHIBIT CANCEL [5678 acks the enable] +// 0B0C 5678 +// +// * REQUEST TO TALK [Unit 1234 asks fixed end for permission to PTT] +// 4001 1234 [CDM1550 dedicated button] +// 4101 1234 [CDM1550 slaved to mic PTT] +// +// * REQUEST TO TALK ACKNOWLEDGE +// 2300 1234 [general ack - not same as permission to PTT] + +enum mdc1200_op_code_e { + MDC1200_OP_CODE_PTT_ID = 0x01, + MDC1200_OP_CODE_POST_ID = 0x01, + MDC1200_OP_CODE_REMOTE_MONITOR = 0x11, + MDC1200_OP_CODE_STATUS_REQ = 0x22, + MDC1200_OP_CODE_RADIO_ENABLE = 0x2B, + MDC1200_OP_CODE_RADIO_DISABLE = 0x2B, + MDC1200_OP_CODE_CALL_ALERT = 0x35, + MDC1200_OP_CODE_STS_XX = 0x46, + MDC1200_OP_CODE_MSG_XX = 0x47, + MDC1200_OP_CODE_RADIO_CHECK = 0x63 +}; +typedef enum mdc1200_op_code_e mdc1200_op_code_t; + +extern const uint8_t mdc1200_sync[5]; +extern uint8_t mdc1200_sync_suc_xor[sizeof(mdc1200_sync)]; + +extern uint8_t mdc1200_op; +extern uint8_t mdc1200_arg; +extern uint16_t mdc1200_unit_id; +extern uint8_t mdc1200_rx_ready_tick_500ms; + +unsigned int MDC1200_encode_single_packet(void *data, const uint8_t op, const uint8_t arg, const uint16_t unit_id); +//unsigned int MDC1200_encode_double_packet(void *data, const uint8_t op, const uint8_t arg, const uint16_t unit_id, const uint8_t b0, const uint8_t b1, const uint8_t b2, const uint8_t b3); +void MDC1200_reset_rx(void); +void MDC1200_process_rx(const uint16_t interrupt_bits); +void MDC1200_init(void); + +#endif diff --git a/app/spectrum.c b/app/spectrum.c index eaeb848..d8ac734 100644 --- a/app/spectrum.c +++ b/app/spectrum.c @@ -18,6 +18,8 @@ #include "driver/backlight.h" #include "audio.h" #include "ui/helper.h" +#include "am_fix.h" +#include "ui/main.h" struct FrequencyBandInfo { uint32_t lower; @@ -30,6 +32,7 @@ struct FrequencyBandInfo { const uint16_t RSSI_MAX_VALUE = 65535; + static uint16_t R30, R37, R3D, R43, R47, R48, R7E; static uint32_t initialFreq; static char String[32]; @@ -68,7 +71,7 @@ SpectrumSettings settings = {stepsCount: STEPS_64, uint32_t fMeasure = 0; uint32_t currentFreq, tempFreq; uint16_t rssiHistory[128]; - +int vfo; uint8_t freqInputIndex = 0; uint8_t freqInputDotIndex = 0; KEY_Code_t freqInputArr[10]; @@ -99,7 +102,10 @@ static uint8_t DBm2S(int dbm) { return i; } -static int Rssi2DBm(uint16_t rssi) { return (rssi >> 1) - 160; } +static int Rssi2DBm(uint16_t rssi) +{ + return (rssi / 2) - 160 + dBmCorrTable[gRxVfo->Band]; +} static uint16_t GetRegMenuValue(uint8_t st) { RegisterSpec s = registerSpecs[st]; @@ -276,7 +282,15 @@ uint16_t GetRssi() { while ((BK4819_ReadRegister(0x63) & 0b11111111) >= 255) { SYSTICK_DelayUs(100); } - return BK4819_GetRSSI(); + if(settings.modulationType == MODULATION_AM) + { + return BK4819_GetRSSI() - rssi_gain_diff[vfo]; //return the corrected RSSI to allow for AM_Fixs AGC action. + } + else + { + return BK4819_GetRSSI(); + } + } static void ToggleAudio(bool on) { @@ -383,7 +397,7 @@ static void Measure() { rssiHistory[scanInfo.i] = scanInfo.rssi = GetRssi(); } static uint16_t dbm2rssi(int dBm) { - return (dBm + 160)*2; + return (dBm + 160 - dBmCorrTable[gRxVfo->Band])*2; } static void ClampRssiTriggerLevel() @@ -475,6 +489,7 @@ static void ToggleModulation() { settings.modulationType = MODULATION_FM; } RADIO_SetModulation(settings.modulationType); + RelaunchScan(); redrawScreen = true; } @@ -588,7 +603,7 @@ uint8_t Rssi2PX(uint16_t rssi, uint8_t pxMin, uint8_t pxMax) { const uint8_t PX_RANGE = pxMax - pxMin; - int dbm = clamp(rssi - (160 << 1), DB_MIN, DB_MAX); + int dbm = clamp(Rssi2DBm(rssi) << 1, DB_MIN, DB_MAX); return ((dbm - DB_MIN) * PX_RANGE + DB_RANGE / 2) / DB_RANGE + pxMin; } @@ -1104,6 +1119,11 @@ static void UpdateListening() { } static void Tick() { + + if(settings.modulationType == MODULATION_AM) + { + AM_fix_10ms(vfo); //allow AM_Fix to apply its AGC action + } if (!preventKeypress) { HandleUserInput(); } @@ -1133,8 +1153,9 @@ static void Tick() { void APP_RunSpectrum() { // TX here coz it always? set to active VFO - currentFreq = initialFreq = - gEeprom.VfoInfo[gEeprom.TX_VFO].pRX->Frequency; + vfo = gEeprom.TX_VFO; + //set the current frequency in the middle of the display + currentFreq = initialFreq = gEeprom.VfoInfo[vfo].pRX->Frequency - ((GetStepsCount()/2) * GetScanStep()); BackupRegisters(); @@ -1144,7 +1165,7 @@ void APP_RunSpectrum() { newScanStart = true; ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off - RADIO_SetModulation(settings.modulationType = MODULATION_FM); + RADIO_SetModulation(settings.modulationType = gRxVfo->Modulation); BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false); RelaunchScan(); diff --git a/audio.c b/audio.c index e865fdc..66a48f8 100644 --- a/audio.c +++ b/audio.c @@ -192,7 +192,9 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep) #endif SYSTEM_DelayMs(5); - BK4819_TurnsOffTones_TurnsOnRX(); + //stop tone + //BK4819_TurnsOffTones_TurnsOnRX(); + BK4819_stop_tones(false); SYSTEM_DelayMs(5); BK4819_WriteRegister(BK4819_REG_71, ToneConfig); diff --git a/cmake-build-debug/CMakeFiles/clion-Debug-log.txt b/cmake-build-debug/CMakeFiles/clion-Debug-log.txt index c48853a..2594228 100644 --- a/cmake-build-debug/CMakeFiles/clion-Debug-log.txt +++ b/cmake-build-debug/CMakeFiles/clion-Debug-log.txt @@ -1,4 +1,13 @@ "C:\Program Files\JetBrains\CLion 2023.1.1\bin\cmake\win\x64\bin\cmake.exe" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=C:/Qt/Qt5.13.1/Tools/mingw730_64/bin/mingw32-make.exe -DCMAKE_C_COMPILER=C:/Qt/Qt5.13.1/Tools/mingw730_64/bin/gcc.exe -DCMAKE_CXX_COMPILER=C:/Qt/Qt5.13.1/Tools/mingw730_64/bin/g++.exe -G "CodeBlocks - MinGW Makefiles" -S C:\Users\RUPC\Desktop\UV-K6\uv-k5-firmware-chinese -B C:\Users\RUPC\Desktop\UV-K6\uv-k5-firmware-chinese\cmake-build-debug -- Configuring done --- Generating done --- Build files have been written to: C:/Users/RUPC/Desktop/UV-K6/uv-k5-firmware-chinese/cmake-build-debug +CMake Error at CMakeLists.txt:122 (add_executable): + Cannot find source file: + + external/CMSIS_5/CMSIS/DAP/Firmware/Config/DAP_config.h + + +CMake Error at CMakeLists.txt:122 (add_executable): + No SOURCES given to target: uv_k5_firmware_custom_0_17 + + +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/driver/bk4819.c b/driver/bk4819.c index 3559d72..d52ec01 100644 --- a/driver/bk4819.c +++ b/driver/bk4819.c @@ -23,10 +23,13 @@ #include "driver/gpio.h" #include "driver/system.h" #include "driver/systick.h" - +#ifdef ENABLE_MDC1200 +#include "app/mdc1200.h" +#endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif +BK4819_FilterBandwidth_t m_bandwidth = BK4819_FILTER_BW_NARROW; static const uint16_t FSK_RogerTable[7] = {0xF1A2, 0x7446, 0x61A4, 0x6544, 0x4E8A, 0xE044, 0xEA84}; @@ -164,6 +167,7 @@ uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register) GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); return Value; + } void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data) @@ -562,6 +566,7 @@ void BK4819_SetFilterBandwidth(const BK4819_FilterBandwidth_t Bandwidth, const b // <1:0> 0 ??? uint16_t val; + m_bandwidth = Bandwidth; switch (Bandwidth) { @@ -1772,4 +1777,642 @@ void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code) BK4819_PlayDTMF(Code); BK4819_ExitTxMute(); -} \ No newline at end of file +} +//ENABLE_MDC1200 +#define h +#ifdef h +void BK4819_start_tone(const uint16_t frequency, const unsigned int level, const bool tx, const bool tx_mute) +{ + SYSTEM_DelayMs(1); + + GPIO_ClearBit(&GPIOC->DATA, 4); + + SYSTEM_DelayMs(1); + + // mute TX + BK4819_WriteRegister(0x50, (1u << 15) | 0x3B20); + + BK4819_WriteRegister(0x70, BK4819_REG_70_ENABLE_TONE1 | ((level & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + + BK4819_WriteRegister(0x30, 0); + + if (!tx) + { + BK4819_WriteRegister(0x30, +// BK4819_REG_30_ENABLE_VCO_CALIB | +// BK4819_REG_30_ENABLE_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_ENABLE_PA_GAIN | +// BK4819_REG_30_ENABLE_MIC_ADC | + BK4819_REG_30_ENABLE_TX_DSP | +// BK4819_REG_30_ENABLE_RX_DSP | + 0); + } + else + { + BK4819_WriteRegister(0x30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_ENABLE_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_ENABLE_PA_GAIN | +// BK4819_REG_30_ENABLE_MIC_ADC | + BK4819_REG_30_ENABLE_TX_DSP | +// BK4819_REG_30_ENABLE_RX_DSP | + 0); + } + + BK4819_WriteRegister(0x71, scale_freq(frequency)); + + SYSTEM_DelayMs(1); + +// BK4819_SetAF(tx ? BK4819_AF_BEEP : 2); + BK4819_SetAF(2); // RX +// BK4819_SetAF(BK4819_AF_BEEP); // TX + + if (!tx_mute) + BK4819_WriteRegister(0x50, 0x3B20); // 0011 1011 0010 0000 + + GPIO_SetBit(&GPIOC->DATA, 4); + + SYSTEM_DelayMs(1); +} + +void BK4819_stop_tones(const bool tx) +{ + SYSTEM_DelayMs(1); + + GPIO_ClearBit(&GPIOC->DATA, 4); + + SYSTEM_DelayMs(1); + + BK4819_SetAF(BK4819_AF_MUTE); + +// BK4819_EnterTxMute(); + + SYSTEM_DelayMs(1); + + BK4819_WriteRegister(0x70, 0); + + BK4819_WriteRegister(0x30, 0); + if (!tx) + { + BK4819_WriteRegister(0x30, + BK4819_REG_30_ENABLE_VCO_CALIB | +// BK4819_REG_30_ENABLE_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_ENABLE_PA_GAIN | +// BK4819_REG_30_ENABLE_MIC_ADC | +// BK4819_REG_30_ENABLE_TX_DSP | + BK4819_REG_30_ENABLE_RX_DSP | + 0); + } + else + { + BK4819_WriteRegister(0x30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_ENABLE_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_ENABLE_PA_GAIN | + BK4819_REG_30_ENABLE_MIC_ADC | + BK4819_REG_30_ENABLE_TX_DSP | +// BK4819_REG_30_ENABLE_RX_DSP | + 0); + } + + SYSTEM_DelayMs(1); + + BK4819_ExitTxMute(); + + SYSTEM_DelayMs(1); +} + +void BK4819_enable_mdc1200_rx(const bool enable) + { + // REG_70 + // + // <15> 0 TONE-1 + // 1 = enable + // 0 = disable + // + // <14:8> 0 TONE-1 gain + // + // <7> 0 TONE-2 + // 1 = enable + // 0 = disable + // + // <6:0> 0 TONE-2 / FSK gain + // 0 ~ 127 + // + // enable tone-2, set gain + + // REG_72 + // + // <15:0> 0x2854 TONE-2 / FSK frequency control word + // = freq(Hz) * 10.32444 for XTAL 13M / 26M or + // = freq(Hz) * 10.48576 for XTAL 12.8M / 19.2M / 25.6M / 38.4M + // + // tone-2 = 1200Hz + + // REG_58 + // + // <15:13> 1 FSK TX mode selection + // 0 = FSK 1.2K and FSK 2.4K TX .. no tones, direct FM + // 1 = FFSK 1200 / 1800 TX + // 2 = ??? + // 3 = FFSK 1200 / 2400 TX + // 4 = ??? + // 5 = NOAA SAME TX + // 6 = ??? + // 7 = ??? + // + // <12:10> 0 FSK RX mode selection + // 0 = FSK 1.2K, FSK 2.4K RX and NOAA SAME RX .. no tones, direct FM + // 1 = ??? + // 2 = ??? + // 3 = ??? + // 4 = FFSK 1200 / 2400 RX + // 5 = ??? + // 6 = ??? + // 7 = FFSK 1200 / 1800 RX + // + // <9:8> 0 FSK RX gain + // 0 ~ 3 + // + // <7:6> 0 ??? + // 0 ~ 3 + // + // <5:4> 0 FSK preamble type selection + // 0 = 0xAA or 0x55 due to the MSB of FSK sync byte 0 + // 1 = ??? + // 2 = 0x55 + // 3 = 0xAA + // + // <3:1> 1 FSK RX bandwidth setting + // 0 = FSK 1.2K .. no tones, direct FM + // 1 = FFSK 1200 / 1800 + // 2 = NOAA SAME RX + // 3 = ??? + // 4 = FSK 2.4K and FFSK 1200 / 2400 + // 5 = ??? + // 6 = ??? + // 7 = ??? + // + // <0> 1 FSK enable + // 0 = disable + // 1 = enable + + // REG_5C + // + // <15:7> ??? + // + // <6> 1 CRC option enable + // 0 = disable + // 1 = enable + // + // <5:0> ??? + // + // disable CRC + + // REG_5D + // + // set the packet size + + if (enable) + { + const uint16_t fsk_reg59 = + (0u << 15) | // 1 = clear TX FIFO + (0u << 14) | // 1 = clear RX FIFO + (0u << 13) | // 1 = scramble + (0u << 12) | // 1 = enable RX + (0u << 11) | // 1 = enable TX + (0u << 10) | // 1 = invert data when RX + (0u << 9) | // 1 = invert data when TX + (0u << 8) | // ??? + (0u << 4) | // 0 ~ 15 preamble length selection .. mdc1200 does not send bit reversals :( + (1u << 3) | // 0/1 sync length selection + (0u << 0); // 0 ~ 7 ??? + + BK4819_WriteRegister(0x70, + ( 0u << 15) | // 0 + ( 0u << 8) | // 0 + ( 1u << 7) | // 1 + (96u << 0)); // 96 + + BK4819_WriteRegister(0x72, scale_freq(1200)); + + BK4819_WriteRegister(0x58, + (1u << 13) | // 1 FSK TX mode selection + // 0 = FSK 1.2K and FSK 2.4K TX .. no tones, direct FM + // 1 = FFSK 1200 / 1800 TX + // 2 = ??? + // 3 = FFSK 1200 / 2400 TX + // 4 = ??? + // 5 = NOAA SAME TX + // 6 = ??? + // 7 = ??? + // + (7u << 10) | // 0 FSK RX mode selection + // 0 = FSK 1.2K, FSK 2.4K RX and NOAA SAME RX .. no tones, direct FM + // 1 = ??? + // 2 = ??? + // 3 = ??? + // 4 = FFSK 1200 / 2400 RX + // 5 = ??? + // 6 = ??? + // 7 = FFSK 1200 / 1800 RX + // + (3u << 8) | // 0 FSK RX gain + // 0 ~ 3 + // + (0u << 6) | // 0 ??? + // 0 ~ 3 + // + (0u << 4) | // 0 FSK preamble type selection + // 0 = 0xAA or 0x55 due to the MSB of FSK sync byte 0 + // 1 = ??? + // 2 = 0x55 + // 3 = 0xAA + // + (1u << 1) | // 1 FSK RX bandwidth setting + // 0 = FSK 1.2K .. no tones, direct FM + // 1 = FFSK 1200 / 1800 + // 2 = NOAA SAME RX + // 3 = ??? + // 4 = FSK 2.4K and FFSK 1200 / 2400 + // 5 = ??? + // 6 = ??? + // 7 = ??? + // + (1u << 0)); // 1 FSK enable + // 0 = disable + // 1 = enable + + // REG_5A .. bytes 0 & 1 sync pattern + // + // <15:8> sync byte 0 + // < 7:0> sync byte 1 +// BK4819_WriteRegister(0x5A, ((uint16_t)mdc1200_sync_suc_xor[0] << 8) | (mdc1200_sync_suc_xor[1] << 0)); + BK4819_WriteRegister(0x5A, ((uint16_t)mdc1200_sync_suc_xor[1] << 8) | (mdc1200_sync_suc_xor[2] << 0)); + + // REG_5B .. bytes 2 & 3 sync pattern + // + // <15:8> sync byte 2 + // < 7:0> sync byte 3 +// BK4819_WriteRegister(0x5B, ((uint16_t)mdc1200_sync_suc_xor[2] << 8) | (mdc1200_sync_suc_xor[3] << 0)); + BK4819_WriteRegister(0x5B, ((uint16_t)mdc1200_sync_suc_xor[3] << 8) | (mdc1200_sync_suc_xor[4] << 0)); + + // disable CRC + BK4819_WriteRegister(0x5C, 0x5625); // 01010110 0 0 100101 +// BK4819_WriteRegister(0x5C, 0xAA30); // 10101010 0 0 110000 + + // set the almost full threshold + BK4819_WriteRegister(0x5E, (64u << 3) | (1u << 0)); // 0 ~ 127, 0 ~ 7 + + { // packet size .. sync + 14 bytes - size of a single mdc1200 packet +// uint16_t size = 1 + (MDC1200_FEC_K * 2); + uint16_t size = 0 + (MDC1200_FEC_K * 2); +// size -= (fsk_reg59 & (1u << 3)) ? 4 : 2; + size = ((size + 1) / 2) * 2; // round up to even, else FSK RX doesn't work + BK4819_WriteRegister(0x5D, ((size - 1) << 8)); + } + + // clear FIFO's then enable RX + BK4819_WriteRegister(0x59, (1u << 15) | (1u << 14) | fsk_reg59); + BK4819_WriteRegister(0x59, (1u << 12) | fsk_reg59); + + // clear interrupt flags + BK4819_WriteRegister(0x02, 0); + +// BK4819_RX_TurnOn(); + + // enable interrupts +// BK4819_WriteRegister(0x3F, BK4819_ReadRegister(0x3F) | BK4819_REG_3F_FSK_RX_SYNC | BK4819_REG_3F_FSK_RX_FINISHED | BK4819_REG_3F_FSK_FIFO_ALMOST_FULL); + } + else + { + BK4819_WriteRegister(0x70, 0); + BK4819_WriteRegister(0x58, 0); + } + } + + void BK4819_send_MDC1200(const uint8_t op, const uint8_t arg, const uint16_t id, const bool long_preamble) + { + uint16_t fsk_reg59; + uint8_t packet[42]; + + // create the MDC1200 packet + const unsigned int size = MDC1200_encode_single_packet(packet, op, arg, id); + + //BK4819_ExitTxMute(); + BK4819_WriteRegister(0x50, 0x3B20); // 0011 1011 0010 0000 + + BK4819_WriteRegister(0x30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_ENABLE_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_ENABLE_PA_GAIN | +// BK4819_REG_30_ENABLE_MIC_ADC | + BK4819_REG_30_ENABLE_TX_DSP | +// BK4819_REG_30_ENABLE_RX_DSP | + 0); + + #if 1 + GPIO_ClearBit(&GPIOC->DATA, 4); + BK4819_SetAF(BK4819_AF_MUTE); + #else + // let the user hear the FSK being sent + BK4819_SetAF(BK4819_AF_BEEP); + GPIO_SetBit(&GPIOC->DATA, 4); + #endif +// SYSTEM_DelayMs(2); + + // REG_51 + // + // <15> TxCTCSS/CDCSS 0 = disable 1 = Enable + // + // turn off CTCSS/CDCSS during FFSK + const uint16_t css_val = BK4819_ReadRegister(0x51); + BK4819_WriteRegister(0x51, 0); + + // set the FM deviation level + const uint16_t dev_val = BK4819_ReadRegister(0x40); + #if defined(ENABLE_UART) && defined(ENABLE_UART_DEBUG) +// UART_printf("tx dev %04X\r\n", dev_val); + #endif + { + uint16_t deviation = 850; + switch (m_bandwidth) + { + case BK4819_FILTER_BW_WIDE: deviation = 1050; break; + case BK4819_FILTER_BW_NARROW: deviation = 850; break; + case BK4819_FILTER_BW_NARROWER: deviation = 750; break; + } + //BK4819_WriteRegister(0x40, (3u << 12) | (deviation & 0xfff)); + BK4819_WriteRegister(0x40, (dev_val & 0xf000) | (deviation & 0xfff)); + } + + // REG_2B 0 + // + // <15> 1 Enable CTCSS/CDCSS DC cancellation after FM Demodulation 1 = enable 0 = disable + // <14> 1 Enable AF DC cancellation after FM Demodulation 1 = enable 0 = disable + // <10> 0 AF RX HPF 300Hz filter 0 = enable 1 = disable + // <9> 0 AF RX LPF 3kHz filter 0 = enable 1 = disable + // <8> 0 AF RX de-emphasis filter 0 = enable 1 = disable + // <2> 0 AF TX HPF 300Hz filter 0 = enable 1 = disable + // <1> 0 AF TX LPF filter 0 = enable 1 = disable + // <0> 0 AF TX pre-emphasis filter 0 = enable 1 = disable + // + // disable the 300Hz HPF and FM pre-emphasis filter + // + const uint16_t filt_val = BK4819_ReadRegister(0x2B); + BK4819_WriteRegister(0x2B, (1u << 2) | (1u << 0)); + + // ******************************************* + // setup the FFSK modem as best we can for MDC1200 + + // MDC1200 uses 1200/1800 Hz FSK tone frequencies 1200 bits/s + // + BK4819_WriteRegister(0x58, // 0x37C3); // 001 101 11 11 00 001 1 + (1u << 13) | // 1 FSK TX mode selection + // 0 = FSK 1.2K and FSK 2.4K TX .. no tones, direct FM + // 1 = FFSK 1200/1800 TX + // 2 = ??? + // 3 = FFSK 1200/2400 TX + // 4 = ??? + // 5 = NOAA SAME TX + // 6 = ??? + // 7 = ??? + // + (7u << 10) | // 0 FSK RX mode selection + // 0 = FSK 1.2K, FSK 2.4K RX and NOAA SAME RX .. no tones, direct FM + // 1 = ??? + // 2 = ??? + // 3 = ??? + // 4 = FFSK 1200/2400 RX + // 5 = ??? + // 6 = ??? + // 7 = FFSK 1200/1800 RX + // + (0u << 8) | // 0 FSK RX gain + // 0 ~ 3 + // + (0u << 6) | // 0 ??? + // 0 ~ 3 + // + (0u << 4) | // 0 FSK preamble type selection + // 0 = 0xAA or 0x55 due to the MSB of FSK sync byte 0 + // 1 = ??? + // 2 = 0x55 + // 3 = 0xAA + // + (1u << 1) | // 1 FSK RX bandwidth setting + // 0 = FSK 1.2K .. no tones, direct FM + // 1 = FFSK 1200/1800 + // 2 = NOAA SAME RX + // 3 = ??? + // 4 = FSK 2.4K and FFSK 1200/2400 + // 5 = ??? + // 6 = ??? + // 7 = ??? + // + (1u << 0)); // 1 FSK enable + // 0 = disable + // 1 = enable + + // REG_72 + // + // <15:0> 0x2854 TONE-2 / FSK frequency control word + // = freq(Hz) * 10.32444 for XTAL 13M / 26M or + // = freq(Hz) * 10.48576 for XTAL 12.8M / 19.2M / 25.6M / 38.4M + // + // tone-2 = 1200Hz + // + BK4819_WriteRegister(0x72, scale_freq(1200)); + + // REG_70 + // + // <15> 0 TONE-1 + // 1 = enable + // 0 = disable + // + // <14:8> 0 TONE-1 tuning + // + // <7> 0 TONE-2 + // 1 = enable + // 0 = disable + // + // <6:0> 0 TONE-2 / FSK tuning + // 0 ~ 127 + // + // enable tone-2, set gain + // + BK4819_WriteRegister(0x70, // 0 0000000 1 1100000 + ( 0u << 15) | // 0 + ( 0u << 8) | // 0 + ( 1u << 7) | // 1 + (96u << 0)); // 96 +// (127u << 0)); + + // REG_59 + // + // <15> 0 TX FIFO 1 = clear + // <14> 0 RX FIFO 1 = clear + // <13> 0 FSK Scramble 1 = Enable + // <12> 0 FSK RX 1 = Enable + // <11> 0 FSK TX 1 = Enable + // <10> 0 FSK data when RX 1 = Invert + // <9> 0 FSK data when TX 1 = Invert + // <8> 0 ??? + // + // <7:4> 0 FSK preamble length selection + // 0 = 1 byte + // 1 = 2 bytes + // 2 = 3 bytes + // 15 = 16 bytes + // + // <3> 0 FSK sync length selection + // 0 = 2 bytes (FSK Sync Byte 0, 1) + // 1 = 4 bytes (FSK Sync Byte 0, 1, 2, 3) + // + // <2:0> 0 ??? + // + fsk_reg59 = (0u << 15) | // 0/1 1 = clear TX FIFO + (0u << 14) | // 0/1 1 = clear RX FIFO + (0u << 13) | // 0/1 1 = scramble + (0u << 12) | // 0/1 1 = enable RX + (0u << 11) | // 0/1 1 = enable TX + (0u << 10) | // 0/1 1 = invert data when RX + (0u << 9) | // 0/1 1 = invert data when TX + (0u << 8) | // 0/1 ??? + (0u << 4) | // 0 ~ 15 preamble length .. bit toggling + (1u << 3) | // 0/1 sync length + (0u << 0); // 0 ~ 7 ??? + fsk_reg59 |= long_preamble ? 15u << 4 : 3u << 4; + + // Set packet length (not including pre-amble and sync bytes that we can't seem to disable) + BK4819_WriteRegister(0x5D, ((size - 1) << 8)); + + // REG_5A + // + // <15:8> 0x55 FSK Sync Byte 0 (Sync Byte 0 first, then 1,2,3) + // <7:0> 0x55 FSK Sync Byte 1 + // + BK4819_WriteRegister(0x5A, 0x0000); // bytes 1 & 2 + + // REG_5B + // + // <15:8> 0x55 FSK Sync Byte 2 (Sync Byte 0 first, then 1,2,3) + // <7:0> 0xAA FSK Sync Byte 3 + // + BK4819_WriteRegister(0x5B, 0x0000); // bytes 2 & 3 + + // CRC setting (plus other stuff we don't know what) + // + // REG_5C + // + // <15:7> ??? + // + // <6> 1 CRC option enable 0 = disable 1 = enable + // + // <5:0> ??? + // + // disable CRC + // + // NB, this also affects TX pre-amble in some way + // + BK4819_WriteRegister(0x5C, 0x5625); // 010101100 0 100101 +// BK4819_WriteRegister(0x5C, 0xAA30); // 101010100 0 110000 +// BK4819_WriteRegister(0x5C, 0x0030); // 000000000 0 110000 + + BK4819_WriteRegister(0x59, (1u << 15) | (1u << 14) | fsk_reg59); // clear FIFO's + BK4819_WriteRegister(0x59, fsk_reg59); // release the FIFO reset + + { // load the entire packet data into the TX FIFO buffer + unsigned int i; + const uint16_t *p = (const uint16_t *)packet; + for (i = 0; i < (size / sizeof(p[0])); i++) + BK4819_WriteRegister(0x5F, p[i]); // load 16-bits at a time + } + + // enable tx interrupt + BK4819_WriteRegister(0x3F, BK4819_REG_3F_FSK_TX_FINISHED); + + // enable FSK TX + BK4819_WriteRegister(0x59, (1u << 11) | fsk_reg59); + + { // packet time is .. + // 173ms for PTT ID, acks, emergency + // 266ms for call alert and sel-calls + + // allow up to 310ms for the TX to complete + // if it takes any longer then somethings gone wrong, we shut the TX down + unsigned int timeout = 300 / 4; + + while (timeout-- > 0) + { + SYSTEM_DelayMs(4); + if (BK4819_ReadRegister(0x0C) & (1u << 0)) + { // we have interrupt flags + BK4819_WriteRegister(0x02, 0); + if (BK4819_ReadRegister(0x02) & BK4819_REG_02_FSK_TX_FINISHED) + timeout = 0; // TX is complete + } + } + } + + GPIO_ClearBit(&GPIOC->DATA, 4); + + // disable FSK + BK4819_WriteRegister(0x59, fsk_reg59); + + BK4819_WriteRegister(0x3F, 0); // disable interrupts + BK4819_WriteRegister(0x70, 0); + BK4819_WriteRegister(0x58, 0); + + // restore FM deviation level + BK4819_WriteRegister(0x40, dev_val); + + // restore TX/RX filtering + BK4819_WriteRegister(0x2B, filt_val); + + // restore the CTCSS/CDCSS setting + BK4819_WriteRegister(0x51, css_val); + + //BK4819_EnterTxMute(); + BK4819_WriteRegister(0x50, 0xBB20); // 1011 1011 0010 0000 + + //BK4819_SetAF(BK4819_AF_MUTE); + BK4819_WriteRegister(0x47, (1u << 14) | (1u << 13) | (BK4819_AF_MUTE << 8) | (1u << 6)); + + BK4819_WriteRegister(0x30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_ENABLE_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_ENABLE_PA_GAIN | + BK4819_REG_30_ENABLE_MIC_ADC | + BK4819_REG_30_ENABLE_TX_DSP | +// BK4819_REG_30_ENABLE_RX_DSP | + 0); + + //BK4819_ExitTxMute(); + BK4819_WriteRegister(0x50, 0x3B20); // 0011 1011 0010 0000 + } +#endif \ No newline at end of file diff --git a/driver/bk4819.h b/driver/bk4819.h index 3248c17..8787246 100644 --- a/driver/bk4819.h +++ b/driver/bk4819.h @@ -66,6 +66,7 @@ typedef enum BK4819_CssScanResult_t BK4819_CssScanResult_t; extern bool gRxIdleMode; void BK4819_Init(void); + uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register); void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data); void BK4819_SetRegValue(RegisterSpec s, uint16_t v); @@ -168,6 +169,10 @@ void BK4819_Enable_AfDac_DiscMode_TxDsp(void); void BK4819_GetVoxAmp(uint16_t *pResult); void BK4819_SetScrambleFrequencyControlWord(uint32_t Frequency); void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code); +void BK4819_send_MDC1200(const uint8_t op, const uint8_t arg, const uint16_t id, const bool long_preamble); + +void BK4819_stop_tones(const bool tx); +void BK4819_start_tone(const uint16_t frequency, const unsigned int level, const bool tx, const bool tx_mute); #endif diff --git a/driver/crc.c b/driver/crc.c index 7a1840d..e839d55 100644 --- a/driver/crc.c +++ b/driver/crc.c @@ -19,18 +19,34 @@ void CRC_Init(void) { - CRC_CR = 0 - | CRC_CR_CRC_EN_BITS_DISABLE - | CRC_CR_INPUT_REV_BITS_NORMAL - | CRC_CR_INPUT_INV_BITS_NORMAL - | CRC_CR_OUTPUT_REV_BITS_NORMAL - | CRC_CR_OUTPUT_INV_BITS_NORMAL - | CRC_CR_DATA_WIDTH_BITS_8 - | CRC_CR_CRC_SEL_BITS_CRC_16_CCITT - ; - CRC_IV = 0; + CRC_CR = + CRC_CR_CRC_EN_BITS_DISABLE | + CRC_CR_INPUT_REV_BITS_NORMAL | + CRC_CR_INPUT_INV_BITS_BIT_INVERTED | + CRC_CR_OUTPUT_REV_BITS_REVERSED | + CRC_CR_OUTPUT_INV_BITS_BIT_INVERTED | + CRC_CR_DATA_WIDTH_BITS_8 | + CRC_CR_CRC_SEL_BITS_CRC_16_CCITT; + + CRC_IV = 0; + } +#ifdef ENABLE_MDC1200 +void CRC_InitReverse(void) + { + CRC_CR = + CRC_CR_CRC_EN_BITS_DISABLE | + CRC_CR_INPUT_REV_BITS_NORMAL | + CRC_CR_INPUT_INV_BITS_BIT_INVERTED | + CRC_CR_OUTPUT_REV_BITS_REVERSED | + CRC_CR_OUTPUT_INV_BITS_BIT_INVERTED | + CRC_CR_DATA_WIDTH_BITS_8 | + CRC_CR_CRC_SEL_BITS_CRC_16_CCITT; + + CRC_IV = 0; + } +#endif uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size) { const uint8_t *pData = (const uint8_t *)pBuffer; diff --git a/driver/crc.h b/driver/crc.h index acc9b49..cf192ee 100644 --- a/driver/crc.h +++ b/driver/crc.h @@ -21,6 +21,7 @@ void CRC_Init(void); uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size); +void CRC_InitReverse(void); #endif diff --git a/driver/systick.c b/driver/systick.c index 5971d74..dd4e469 100644 --- a/driver/systick.c +++ b/driver/systick.c @@ -43,3 +43,23 @@ void SYSTICK_DelayUs(uint32_t Delay) } while (i < ticks); } +void SYSTICK_Delay250ns(const uint32_t Delay) +{ + const uint32_t ticks = (Delay * gTickMultiplier) >> 2; + uint32_t i = 0; + uint32_t Start = SysTick->LOAD; + uint32_t Previous = SysTick->VAL; + + do { + uint32_t Delta; + uint32_t Current; + + do Current = SysTick->VAL; + while (Current == Previous); + + Delta = (Current < Previous) ? -Current : Start - Current; + i += Delta + Previous; + Previous = Current; + + } while (i < ticks); +} diff --git a/driver/systick.h b/driver/systick.h index 95ba478..9d0d1f2 100644 --- a/driver/systick.h +++ b/driver/systick.h @@ -21,6 +21,7 @@ void SYSTICK_Init(void); void SYSTICK_DelayUs(uint32_t Delay); +void SYSTICK_Delay250ns(const uint32_t Delay); #endif diff --git a/radio.c b/radio.c index 826b030..7591dfb 100644 --- a/radio.c +++ b/radio.c @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "driver/bk4819.h" +#include "app/mdc1200.h" #include #include "app/dtmf.h" @@ -904,6 +906,7 @@ void RADIO_SetTxParameters(void) void RADIO_SetModulation(ModulationMode_t modulation) { + static ModulationMode_t m = MODULATION_UKNOWN; BK4819_AF_Type_t mod; switch(modulation) { default: @@ -928,9 +931,16 @@ void RADIO_SetModulation(ModulationMode_t modulation) } BK4819_SetAF(mod); - BK4819_SetRegValue(afDacGainRegSpec, 0xF); - BK4819_WriteRegister(BK4819_REG_3D, modulation == MODULATION_USB ? 0 : 0x2AAB); - BK4819_SetRegValue(afcDisableRegSpec, modulation != MODULATION_FM); + if(m != modulation) { + m = modulation; + BK4819_SetRegValue(afDacGainRegSpec, 0xF); + BK4819_WriteRegister(BK4819_REG_3D, modulation == MODULATION_USB ? 0 : 0x2AAB); + BK4819_SetRegValue(afcDisableRegSpec, modulation != MODULATION_FM); +#ifdef ENABLE_AM_FIX + BK4819_SetAGC(gRxVfo->Modulation != MODULATION_AM || !gSetting_AM_fix); + BK4819_InitAGC(); +#endif + } } void RADIO_SetVfoState(VfoState_t State) @@ -1113,12 +1123,19 @@ void RADIO_SendEndOfTransmission(void) if (gEeprom.ROGER == ROGER_MODE_ROGER) BK4819_PlayRoger(); else - if (gEeprom.ROGER == ROGER_MODE_MDC) - BK4819_PlayRogerMDC(); + if (gEeprom.ROGER == ROGER_MODE_MDC) { + BK4819_send_MDC1200(MDC1200_OP_CODE_POST_ID, 0x00, 12, false); +#ifdef ENABLE_MDC1200_SIDE_BEEP + BK4819_start_tone(880, 10, true, true); + SYSTEM_DelayMs(120); + BK4819_stop_tones(true); +#endif + } if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO) - BK4819_PlaySingleTone(2475, 250, 28, gEeprom.DTMF_SIDE_TONE); + { BK4819_PlaySingleTone(2475, 250, 28, gEeprom.DTMF_SIDE_TONE); + } if ( #ifdef ENABLE_DTMF_CALLING gDTMF_CallState == DTMF_CALL_STATE_NONE && diff --git a/ui/main.c b/ui/main.c index 24bdb49..89d4c04 100644 --- a/ui/main.c +++ b/ui/main.c @@ -38,7 +38,15 @@ #include "ui/ui.h" center_line_t center_line = CENTER_LINE_NONE; - +const int8_t dBmCorrTable[7] = { + -15, // band 1 + -25, // band 2 + -20, // band 3 + -4, // band 4 + -7, // band 5 + -6, // band 6 + -1 // band 7 +}; // *************************************************************************** static void DrawSmallAntennaAndBars(uint8_t *p, unsigned int level) @@ -175,15 +183,7 @@ static void DisplayRSSIBar(const int16_t rssi, const bool now) if (now) memset(p_line, 0, LCD_WIDTH); - const int8_t dBmCorrTable[7] = { - -15, // band 1 - -25, // band 2 - -20, // band 3 - -4, // band 4 - -7, // band 5 - -6, // band 6 - -1 // band 7 - }; + const int16_t s0_dBm = -130; // S0 .. base level // const int16_t rssi_dBm = (rssi / 2) - 160; const int16_t rssi_dBm = (rssi / 2) - 160 + dBmCorrTable[gRxVfo->Band]; diff --git a/ui/main.h b/ui/main.h index 80024f9..ba01acc 100644 --- a/ui/main.h +++ b/ui/main.h @@ -33,6 +33,6 @@ extern center_line_t center_line; void UI_DisplayAudioBar(void); void UI_UpdateRSSI(const int16_t rssi, const int vfo); void UI_DisplayMain(void); - +extern const int8_t dBmCorrTable[7]; #endif diff --git a/版本说明.txt b/版本说明.txt index ea0b268..5770a64 100644 --- a/版本说明.txt +++ b/版本说明.txt @@ -1,3 +1,20 @@ +#0.10.4 + 修复开机显示问题 + 修复宽窄带开机后失效问题 + 频谱图增加AM-FIX + 增加MDC1200信令 +#0.10.3 + 修复“长按菜单切换调制模式(AM/FM/USB)再切回FM亚音消失问题” + 锁定按键改成原来的逻辑,以后这种操作逻辑相关的都不来改了,众口难调 +#0.10.2 + 修复命名信道时频率会变化的bug + 锁定按键时只允许发射/接收按键,与官方中文版逻辑一致 +#0.10.1 + 重构代码,菜单名使用中文(是的,中文宏定义,感谢现代编译器,中文见/ui/menu.c) + 优化代码,节省了1.4KB + 修复扫描时“频差”翻译错误,纠正为“频率” + 修复开机显示菜单选项错误问题 + (哥们比较空,所以更新的快,其实不用天天升级,跟着大版本升级就好了) # 0.10 * 版本为egcn变种,旨在精简固件植入更多功能,如MDC1200信令 * egcn更新至191,结束:https://github.com/losehu/uv-k5-firmware-egcn/tree/main