mdc tx end test

This commit is contained in:
wu58430 2023-12-03 12:27:34 +08:00
parent 8d67ff068c
commit 9366901ccb
19 changed files with 1533 additions and 84 deletions

View file

@ -20,8 +20,26 @@
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="cea36e80-e289-4d69-9030-7186d540ac0e" name="更改" comment="修复切换调制模式时亚音消失问题">
<list default="true" id="cea36e80-e289-4d69-9030-7186d540ac0e" name="更改" comment="按键锁定改回以前逻辑">
<change afterPath="$PROJECT_DIR$/app/mdc1200.c" afterDir="false" />
<change afterPath="$PROJECT_DIR$/app/mdc1200.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMakeLists.txt" beforeDir="false" afterPath="$PROJECT_DIR$/CMakeLists.txt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Makefile" beforeDir="false" afterPath="$PROJECT_DIR$/Makefile" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/app.c" beforeDir="false" afterPath="$PROJECT_DIR$/app/app.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/spectrum.c" beforeDir="false" afterPath="$PROJECT_DIR$/app/spectrum.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/audio.c" beforeDir="false" afterPath="$PROJECT_DIR$/audio.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cmake-build-debug/CMakeFiles/clion-Debug-log.txt" beforeDir="false" afterPath="$PROJECT_DIR$/cmake-build-debug/CMakeFiles/clion-Debug-log.txt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/driver/bk4819.c" beforeDir="false" afterPath="$PROJECT_DIR$/driver/bk4819.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/driver/bk4819.h" beforeDir="false" afterPath="$PROJECT_DIR$/driver/bk4819.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/driver/crc.c" beforeDir="false" afterPath="$PROJECT_DIR$/driver/crc.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/driver/crc.h" beforeDir="false" afterPath="$PROJECT_DIR$/driver/crc.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/driver/systick.c" beforeDir="false" afterPath="$PROJECT_DIR$/driver/systick.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/driver/systick.h" beforeDir="false" afterPath="$PROJECT_DIR$/driver/systick.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/radio.c" beforeDir="false" afterPath="$PROJECT_DIR$/radio.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ui/main.c" beforeDir="false" afterPath="$PROJECT_DIR$/ui/main.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ui/main.h" beforeDir="false" afterPath="$PROJECT_DIR$/ui/main.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/版本说明.txt" beforeDir="false" afterPath="$PROJECT_DIR$/版本说明.txt" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -65,32 +83,38 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;ASKED_ADD_EXTERNAL_FILES&quot;: &quot;true&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
&quot;cf.first.check.clang-format&quot;: &quot;false&quot;,
&quot;cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/RUPC/Desktop/UV-K6/uv-k5-firmware-chinese&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;File.Encoding&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
<component name="PropertiesComponent"><![CDATA[{
"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/app",
"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"
}
}</component>
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\RUPC\Desktop\UV-K6\uv-k5-firmware-chinese\app" />
<recent name="C:\Users\RUPC\Desktop\UV-K6\uv-k5-firmware-chinese" />
</key>
</component>
<component name="RunManager">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="未命名" type="ShConfigurationType" nameIsGenerated="true">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="false" />
@ -125,7 +149,7 @@
<workItem from="1701325367312" duration="22657000" />
<workItem from="1701413653518" duration="3544000" />
<workItem from="1701430185864" duration="10115000" />
<workItem from="1701559895523" duration="3042000" />
<workItem from="1701559895523" duration="12283000" />
</task>
<task id="LOCAL-00001" summary="bug fix">
<created>1701136012311</created>
@ -267,7 +291,14 @@
<option name="project" value="LOCAL" />
<updated>1701562094909</updated>
</task>
<option name="localTasksCounter" value="21" />
<task id="LOCAL-00021" summary="按键锁定改回以前逻辑">
<created>1701563372624</created>
<option name="number" value="00021" />
<option name="presentableId" value="LOCAL-00021" />
<option name="project" value="LOCAL" />
<updated>1701563372624</updated>
</task>
<option name="localTasksCounter" value="22" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -291,6 +322,7 @@
<MESSAGE value="掃描下翻譯" />
<MESSAGE value="fix https://github.com/losehu/uv-k5-firmware-chinese/issues/4" />
<MESSAGE value="修复切换调制模式时亚音消失问题" />
<option name="LAST_COMMIT_MESSAGE" value="修复切换调制模式时亚音消失问题" />
<MESSAGE value="按键锁定改回以前逻辑" />
<option name="LAST_COMMIT_MESSAGE" value="按键锁定改回以前逻辑" />
</component>
</project>

View file

@ -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)

View file

@ -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

View file

@ -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){

562
app/mdc1200.c Normal file
View file

@ -0,0 +1,562 @@
#include "driver/bk4819.h"
#include "driver/crc.h"
#include "mdc1200.h"
#include "misc.h"
#include <string.h>
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();
}

106
app/mdc1200.h Normal file
View file

@ -0,0 +1,106 @@
#ifndef MDC1200H
#define MDC1200H
#include <stdint.h>
#include <stdbool.h>
#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

View file

@ -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();

View file

@ -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);

View file

@ -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.

View file

@ -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();
}
}
//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

View file

@ -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

View file

@ -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;

View file

@ -21,6 +21,7 @@
void CRC_Init(void);
uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size);
void CRC_InitReverse(void);
#endif

View file

@ -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);
}

View file

@ -21,6 +21,7 @@
void SYSTICK_Init(void);
void SYSTICK_DelayUs(uint32_t Delay);
void SYSTICK_Delay250ns(const uint32_t Delay);
#endif

29
radio.c
View file

@ -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 <string.h>
#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 &&

View file

@ -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];

View file

@ -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

View file

@ -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