This commit is contained in:
wu58430 2023-12-10 10:32:39 +08:00
parent 4a17d3a43e
commit 4fbc992f45
18 changed files with 566 additions and 497 deletions

View file

@ -1,2 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />
<module classpath="CMake" type="CPP_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.5 (uv-k5-firmware-chinese)" />
</facet>
</component>
</module>

View file

@ -20,8 +20,25 @@
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="cea36e80-e289-4d69-9030-7186d540ac0e" name="更改" comment="MDC联系人">
<list default="true" id="cea36e80-e289-4d69-9030-7186d540ac0e" name="更改" comment="MDC PY">
<change beforePath="$PROJECT_DIR$/.idea/uv-k5-firmware-chinese.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/uv-k5-firmware-chinese.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MDC_WRITE/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/MDC_WRITE/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/aircopy.c" beforeDir="false" afterPath="$PROJECT_DIR$/app/aircopy.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/aircopy.h" beforeDir="false" afterPath="$PROJECT_DIR$/app/aircopy.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/app.c" beforeDir="false" afterPath="$PROJECT_DIR$/app/app.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/generic.c" beforeDir="false" afterPath="$PROJECT_DIR$/app/generic.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/spectrum.c" beforeDir="false" afterPath="$PROJECT_DIR$/app/spectrum.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/frequencies.c" beforeDir="false" afterPath="$PROJECT_DIR$/frequencies.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/frequencies.h" beforeDir="false" afterPath="$PROJECT_DIR$/frequencies.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/functions.c" beforeDir="false" afterPath="$PROJECT_DIR$/functions.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/misc.c" beforeDir="false" afterPath="$PROJECT_DIR$/misc.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/misc.h" beforeDir="false" afterPath="$PROJECT_DIR$/misc.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/radio.c" beforeDir="false" afterPath="$PROJECT_DIR$/radio.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ui/helper.c" beforeDir="false" afterPath="$PROJECT_DIR$/ui/helper.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ui/ui.c" beforeDir="false" afterPath="$PROJECT_DIR$/ui/ui.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ui/ui.h" beforeDir="false" afterPath="$PROJECT_DIR$/ui/ui.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/win_make.bat" beforeDir="false" afterPath="$PROJECT_DIR$/win_make.bat" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -76,30 +93,53 @@
&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/win_make.bat&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/RUPC/Desktop/UV-K6/uv-k5-firmware-chinese/MDC_WRITE/main.py&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;settings.editor.selected.configurable&quot;: &quot;com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable&quot;,
&quot;structure.view.defaults.are.configured&quot;: &quot;true&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\RUPC\Desktop\UV-K6\uv-k5-firmware-chinese\MDC_WRITE" />
<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" selected="Shell Script.win docker">
<component name="RunManager" selected="Python.main">
<configuration name="clean" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile" temporary="true">
<makefile filename="$PROJECT_DIR$/Makefile" target="clean" workingDirectory="" arguments="">
<envs />
</makefile>
<method v="2" />
</configuration>
<configuration name="main" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
<module name="uv-k5-firmware-chinese" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="C:\Users\RUPC\py32\python.exe" />
<option name="SDK_NAME" value="Python 3.5 (uv-k5-firmware-chinese)" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/MDC_WRITE" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/MDC_WRITE/main.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="linux docker" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
@ -147,6 +187,7 @@
</configuration>
<list>
<item itemvalue="Makefile 目标.clean" />
<item itemvalue="Python.main" />
<item itemvalue="Shell Script.win docker" />
<item itemvalue="Shell Script.linux docker" />
<item itemvalue="Shell Script.win" />
@ -187,14 +228,11 @@
<workItem from="1702024305901" duration="2385000" />
<workItem from="1702049513969" duration="28027000" />
<workItem from="1702119088204" duration="12764000" />
<workItem from="1702141572484" duration="2000" />
</task>
<task id="LOCAL-00036" summary="MDC RX">
<created>1701687970236</created>
<option name="number" value="00036" />
<option name="presentableId" value="LOCAL-00036" />
<option name="project" value="LOCAL" />
<updated>1701687970236</updated>
<workItem from="1702141572484" duration="2405000" />
<workItem from="1702171975719" duration="1521000" />
<workItem from="1702173556660" duration="287000" />
<workItem from="1702173911297" duration="1180000" />
<workItem from="1702175521208" duration="2000" />
</task>
<task id="LOCAL-00037" summary="MDC RX">
<created>1701689801897</created>
@ -532,12 +570,22 @@
<option name="project" value="LOCAL" />
<updated>1702140061106</updated>
</task>
<option name="localTasksCounter" value="85" />
<task id="LOCAL-00085" summary="MDC PY">
<created>1702141605728</created>
<option name="number" value="00085" />
<option name="presentableId" value="LOCAL-00085" />
<option name="project" value="LOCAL" />
<updated>1702141605728</updated>
</task>
<option name="localTasksCounter" value="86" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnknownFeatures">
<option featureType="com.intellij.fileTypeFactory" implementationName="*.bat" />
</component>
<component name="VCPKGProject">
<isAutomaticEditVcpkgJson value="false" />
<isAutomaticCheckingOnLaunch value="false" />
@ -556,7 +604,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="fix bug" />
<MESSAGE value="掃描下翻譯" />
<MESSAGE value="fix https://github.com/losehu/uv-k5-firmware-chinese/issues/4" />
<MESSAGE value="修复切换调制模式时亚音消失问题" />
@ -581,6 +628,7 @@
<MESSAGE value="clion" />
<MESSAGE value="开机音修复" />
<MESSAGE value="MDC联系人" />
<option name="LAST_COMMIT_MESSAGE" value="MDC联系人" />
<MESSAGE value="MDC PY" />
<option name="LAST_COMMIT_MESSAGE" value="MDC PY" />
</component>
</project>

View file

@ -1,4 +1,5 @@
import sys
import serial.tools.list_ports
import re
import serial
max_contact=15
@ -6,6 +7,9 @@ line_count=0
MDC_ADD= [ 0x1D48, 0x1D88, 0x1DC8,0x1F08]
MDC_NUM_ADD=0X1D00
file_out="MDC.txt"
com_open=""
def payload_xor(payload):
XOR_ARRAY = bytes.fromhex('166c14e62e910d402135d5401303e980')
XOR_LEN = len(XOR_ARRAY)
@ -81,7 +85,8 @@ def check_duplicates(file_path):
else:
lines_seen.add(first_four)
def time_set():
with serial.Serial('COM4', 38400, timeout=1) as ser:
global com_open
with serial.Serial( com_open, 38400, timeout=1) as ser:
settime = b'\xAB\xCD\x08\x00\x02\x69\x10\xE6\xAC\xD1\x79\x25\x9D\xAD\xDC\xBA'
ser.write(settime)
@ -92,7 +97,8 @@ def time_set():
sys.exit()
def read_eeprom_byte(add):
with serial.Serial('COM4', 38400, timeout=1) as ser:
global com_open
with serial.Serial(com_open, 38400, timeout=1) as ser:
payload = b'\x1B\x05' + b'\x08\x00' + add.to_bytes(2, byteorder='little') + b'\x11\x00' + b'\x82\x40\x74\x65'
# 将 payload 中的最后四个字节替换为当前时间戳
hex_string = ' '.join(['{:02X}'.format(byte) for byte in payload])
@ -123,47 +129,49 @@ def read_eeprom():
sys.exit()
print("开始读取MDC联系人")
with open(file_out, 'w+') as file:
with serial.Serial('COM4', 38400, timeout=1) as ser:
a=0
while a<num_contact:
add=MDC_ADD[a//4]+(a%4)*16
a=a+1
print(a*100/num_contact,end='%\n')
payload = b'\x1B\x05' + b'\x08\x00' +add.to_bytes(2, byteorder='little')+b'\x10\x00'+b'\x82\x40\x74\x65'
global com_open
with serial.Serial(com_open, 38400, timeout=1) as ser:
a=0
while a<num_contact:
add=MDC_ADD[a//4]+(a%4)*16
a=a+1
print(a*100/num_contact,end='%\n')
payload = b'\x1B\x05' + b'\x08\x00' +add.to_bytes(2, byteorder='little')+b'\x10\x00'+b'\x82\x40\x74\x65'
# 将 payload 中的最后四个字节替换为当前时间戳
hex_string = ' '.join(['{:02X}'.format(byte) for byte in payload])
crc = crc16_ccitt(payload)
payload = payload + bytes([crc & 0xFF,]) + bytes([crc>>8,]) #swap bytes of crc to get little endian
message = b'\xAB\xCD' + b'\x0C\x00' + payload_xor(payload) + b'\xDC\xBA'
ser.write(message)
full_response = ser.read(128)
if len(full_response) == 0:
print("读取失败!")
input("按 Enter 键退出程序")
hex_string = ' '.join(['{:02X}'.format(byte) for byte in payload])
crc = crc16_ccitt(payload)
payload = payload + bytes([crc & 0xFF,]) + bytes([crc>>8,]) #swap bytes of crc to get little endian
message = b'\xAB\xCD' + b'\x0C\x00' + payload_xor(payload) + b'\xDC\xBA'
ser.write(message)
full_response = ser.read(128)
if len(full_response) == 0:
print("读取失败!")
input("按 Enter 键退出程序")
sys.exit()
sys.exit()
full_response_hex = full_response.hex()
# 将16进制字符串转换为字节串
full_response = bytes.fromhex(full_response_hex)
# 对payload部分进行解码然后以两位十六进制输出
full_response_hex = full_response.hex()
# 将16进制字符串转换为字节串
full_response = bytes.fromhex(full_response_hex)
# 对payload部分进行解码然后以两位十六进制输出
payload_decoded = convert_payload_to_hex(full_response)
i=0
# 将print的输出定向到文件中
for element in payload_decoded.split(' ')[8:]:
i = i + 1
if i == 3:
file.write(' ')
if i >= 3:
file.write(chr(int(element, 16)))
else:
file.write(element.upper())
file.write('\n')
print("读取成功,联系人保存至 MDC联系人.txt")
payload_decoded = convert_payload_to_hex(full_response)
i=0
# 将print的输出定向到文件中
for element in payload_decoded.split(' ')[8:]:
i = i + 1
if i == 3:
file.write(' ')
if i >= 3:
file.write(chr(int(element, 16)))
else:
file.write(element.upper())
file.write('\n')
print("读取成功,联系人保存至 MDC.txt")
return True
def write_eeprom_byte(add,num):
with serial.Serial('COM4', 38400, timeout=1) as ser:
global com_open
with serial.Serial(com_open, 38400, timeout=1) as ser:
payload = b'\x1D\x05' + b'\x09\x00' + add.to_bytes(2,
byteorder='little') + b'\x0F\x00' + b'\x82\x40\x74\x65' + num.to_bytes(1, byteorder='big')
# 将 payload 中的最后四个字节替换为当前时间戳
@ -179,7 +187,8 @@ def write_eeprom_byte(add,num):
sys.exit()
def write_eeprom_select(a,my_str):
with serial.Serial('COM4', 38400, timeout=1) as ser:
global com_open
with serial.Serial(com_open, 38400, timeout=1) as ser:
add = MDC_ADD[a // 4] + (a % 4) * 16
payload_data = ''.join(my_str).encode('utf-8')
hex1 = int(payload_data[0:2], 16)
@ -219,7 +228,7 @@ def deal_blank_line():
def write_eeprom():
print("正在将MDC联系人.txt写入到手台中")
print("正在将MDC.txt写入到手台中")
global line_count # 声明 line_count 是全局变量
a=0
deal_blank_line()
@ -244,6 +253,15 @@ def write_eeprom():
if __name__ == "__main__":
available_ports = list(serial.tools.list_ports.comports())
if available_ports:
print("可用串口:")
for port in available_ports:
print(port.device)
else:
print("没有发现可用串口。")
com_open=input("输入串口(例:COM4):")
value=-1
print("第一次使用MDC联系人请先写入联系人!!")
while value!=0 and value!=1:
@ -263,9 +281,9 @@ if __name__ == "__main__":
# code =[0xAB,0xCD,0x6C,0x00,0x0B,0x69,0x7C,0xE6,0x5E,0x9F,0x6D,0x41,0xBF,0x61,0xA1,0x25,0x13,0x02,0xE8,0x80,0x16,0x93,0x15,0xE2,0xD1,0x91,0x0D,0x44,0x20,0x36,0xD5,0x41,0x13,0x03,0x24,0x80,0x16,0xA1,0xDB,0x29,0xD1,0x6E,0x0D,0x40,0xDE,0xCA,0x2A,0xBF,0x13,0x00,0xE1,0x80,0x16,0x6D,0x14,0xE6,0xD1,0x6E,0xF2,0xBF,0xDE,0xCA,0x2A,0xBF,0x12,0x03,0x16,0x7F,0xE9,0x93,0xEB,0x19,0x2E,0x91,0x0D,0x40,0xDE,0xCA,0x2A,0xBF,0x42,0x56,0xA8,0xCE,0x45,0x24,0x51,0xA8,0x69,0x91,0x0D,0x40,0x21,0x35,0xD5,0x40,0x46,0x55,0xC4,0xCB,0x23,0x6C,0x14,0xE6,0x2E,0x91,0x0D,0x40,0x21,0x35,0xD5,0x40,0x79,0x5A,0xDC,0xBA]
# # code=[0xAB, 0xCD, 0x1C, 0x00, 0x0B, 0x69, 0x0C, 0xE6, 0xCE, 0x80, 0x1D, 0x40, 0xBF, 0x61, 0xA1, 0x25, 0xEC, 0xFC, 0x16, 0x7F, 0xE9, 0x93, 0xEB, 0x19, 0xD1, 0x6E, 0xF2, 0xBF, 0xDE, 0xCA, 0x2A, 0xBF, 0xCF, 0x04, 0xDC, 0xBA]
# payload_decoded = convert_payload_to_hex(code) # 跳过头部和尾部的校验信息
# hex_payload = ' '.join(['{:02X}'.format(byte) for byte in payload_decoded])
# print(hex_payload)
# code =[0xAB,0xCD,0x6C,0x00,0x0B,0x69,0x7C,0xE6,0x5E,0x9F,0x6D,0x41,0xBF,0x61,0xA1,0x25,0x13,0x02,0xE8,0x80,0x16,0x93,0x15,0xE2,0xD1,0x91,0x0D,0x44,0x20,0x36,0xD5,0x41,0x13,0x03,0x24,0x80,0x16,0xA1,0xDB,0x29,0xD1,0x6E,0x0D,0x40,0xDE,0xCA,0x2A,0xBF,0x13,0x00,0xE1,0x80,0x16,0x6D,0x14,0xE6,0xD1,0x6E,0xF2,0xBF,0xDE,0xCA,0x2A,0xBF,0x12,0x03,0x16,0x7F,0xE9,0x93,0xEB,0x19,0x2E,0x91,0x0D,0x40,0xDE,0xCA,0x2A,0xBF,0x42,0x56,0xA8,0xCE,0x45,0x24,0x51,0xA8,0x69,0x91,0x0D,0x40,0x21,0x35,0xD5,0x40,0x46,0x55,0xC4,0xCB,0x23,0x6C,0x14,0xE6,0x2E,0x91,0x0D,0x40,0x21,0x35,0xD5,0x40,0x79,0x5A,0xDC,0xBA]
# # code=[0xAB, 0xCD, 0x1C, 0x00, 0x0B, 0x69, 0x0C, 0xE6, 0xCE, 0x80, 0x1D, 0x40, 0xBF, 0x61, 0xA1, 0x25, 0xEC, 0xFC, 0x16, 0x7F, 0xE9, 0x93, 0xEB, 0x19, 0xD1, 0x6E, 0xF2, 0xBF, 0xDE, 0xCA, 0x2A, 0xBF, 0xCF, 0x04, 0xDC, 0xBA]
# payload_decoded = convert_payload_to_hex(code) # 跳过头部和尾部的校验信息
# hex_payload = ' '.join(['{:02X}'.format(byte) for byte in payload_decoded])
# print(hex_payload)

View file

@ -28,18 +28,26 @@
#include "ui/inputbox.h"
#include "ui/ui.h"
static const uint16_t Obfuscation[8] = {0x6C16, 0xE614, 0x912E, 0x400D, 0x3521, 0x40D5, 0x0313, 0x80E9};
static const uint16_t Obfuscation[8] = { 0x6C16, 0xE614, 0x912E, 0x400D, 0x3521, 0x40D5, 0x0313, 0x80E9 };
AIRCOPY_State_t gAircopyState;
uint16_t gAirCopyBlockNumber;
uint16_t gErrorsDuringAirCopy;
uint8_t gAirCopyIsSendMode;
uint16_t gAirCopyBlockNumber;
uint16_t gErrorsDuringAirCopy;
uint8_t gAirCopyIsSendMode;
uint16_t g_FSK_Buffer[36];
uint16_t g_FSK_Buffer[36];
void AIRCOPY_SendMessage(void)
bool AIRCOPY_SendMessage(void)
{
unsigned int i;
static uint8_t gAircopySendCountdown = 1;
if (gAircopyState != AIRCOPY_TRANSFER) {
return 1;
}
if (--gAircopySendCountdown) {
return 1;
}
g_FSK_Buffer[1] = (gAirCopyBlockNumber & 0x3FF) << 6;
@ -47,11 +55,13 @@ void AIRCOPY_SendMessage(void)
g_FSK_Buffer[34] = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64);
for (i = 0; i < 34; i++)
for (unsigned int i = 0; i < 34; i++) {
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
}
if (++gAirCopyBlockNumber >= 0x78)
if (++gAirCopyBlockNumber >= 0x78) {
gAircopyState = AIRCOPY_COMPLETE;
}
RADIO_SetTxParameters();
@ -60,172 +70,172 @@ void AIRCOPY_SendMessage(void)
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
gAircopySendCountdown = 30;
return 0;
}
void AIRCOPY_StorePacket(void)
{
uint16_t Status;
if (gFSKWriteIndex < 36)
if (gFSKWriteIndex < 36) {
return;
}
gFSKWriteIndex = 0;
gUpdateDisplay = true;
Status = BK4819_ReadRegister(BK4819_REG_0B);
uint16_t Status = BK4819_ReadRegister(BK4819_REG_0B);
BK4819_PrepareFSKReceive();
// Doc says bit 4 should be 1 = CRC OK, 0 = CRC FAIL, but original firmware checks for FAIL.
if ((Status & 0x0010U) == 0 && g_FSK_Buffer[0] == 0xABCD && g_FSK_Buffer[35] == 0xDCBA)
{
uint16_t CRC;
unsigned int i;
for (i = 0; i < 34; i++)
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
CRC = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64);
CRC_Init();
if (g_FSK_Buffer[34] == CRC)
{
const uint16_t *pData;
uint16_t Offset;
Offset = g_FSK_Buffer[1];
if (Offset < 0x1E00)
{
pData = &g_FSK_Buffer[2];
for (i = 0; i < 8; i++)
{
EEPROM_WriteBuffer(Offset, pData);
pData += 4;
Offset += 8;
}
if (Offset == 0x1E00)
gAircopyState = AIRCOPY_COMPLETE;
gAirCopyBlockNumber++;
return;
}
}
if ((Status & 0x0010U) != 0 || g_FSK_Buffer[0] != 0xABCD || g_FSK_Buffer[35] != 0xDCBA) {
gErrorsDuringAirCopy++;
return;
}
gErrorsDuringAirCopy++;
for (unsigned int i = 0; i < 34; i++) {
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
}
uint16_t CRC = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64);
if (g_FSK_Buffer[34] != CRC) {
gErrorsDuringAirCopy++;
return;
}
uint16_t Offset = g_FSK_Buffer[1];
if (Offset >= 0x1E00) {
gErrorsDuringAirCopy++;
return;
}
const uint16_t *pData = &g_FSK_Buffer[2];
for (unsigned int i = 0; i < 8; i++) {
EEPROM_WriteBuffer(Offset, pData);
pData += 4;
Offset += 8;
}
if (Offset == 0x1E00) {
gAircopyState = AIRCOPY_COMPLETE;
}
gAirCopyBlockNumber++;
}
static void AIRCOPY_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
uint32_t Frequency;
unsigned int i;
INPUTBOX_Append(Key);
gRequestDisplayScreen = DISPLAY_AIRCOPY;
if (gInputBoxIndex < 6)
{
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
return;
}
gInputBoxIndex = 0;
Frequency = StrToUL(INPUTBOX_GetAscii()) * 100;
for (i = 0; i < BAND_N_ELEM; i++)
{
if (Frequency >= frequencyBandTable[i].lower && Frequency < frequencyBandTable[i].upper)
{
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
gRxVfo->Band = i;
Frequency = FREQUENCY_RoundToStep(Frequency, gRxVfo->StepFrequency);
gRxVfo->freq_config_RX.Frequency = Frequency;
gRxVfo->freq_config_TX.Frequency = Frequency;
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
gCurrentVfo = gRxVfo;
RADIO_SetupRegisters(true);
BK4819_SetupAircopy();
BK4819_ResetFSK();
return;
}
}
gRequestDisplayScreen = DISPLAY_AIRCOPY;
if (bKeyHeld || !bKeyPressed) {
return;
}
INPUTBOX_Append(Key);
gRequestDisplayScreen = DISPLAY_AIRCOPY;
if (gInputBoxIndex < 6) {
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
return;
}
gInputBoxIndex = 0;
uint32_t Frequency = StrToUL(INPUTBOX_GetAscii()) * 100;
for (unsigned int i = 0; i < BAND_N_ELEM; i++) {
if (Frequency < frequencyBandTable[i].lower || Frequency >= frequencyBandTable[i].upper) {
continue;
}
if (TX_freq_check(Frequency)) {
continue;
}
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
Frequency = FREQUENCY_RoundToStep(Frequency, gRxVfo->StepFrequency);
gRxVfo->Band = i;
gRxVfo->freq_config_RX.Frequency = Frequency;
gRxVfo->freq_config_TX.Frequency = Frequency;
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
gCurrentVfo = gRxVfo;
RADIO_SetupRegisters(true);
BK4819_SetupAircopy();
BK4819_ResetFSK();
return;
}
gRequestDisplayScreen = DISPLAY_AIRCOPY;
}
static void AIRCOPY_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
if (gInputBoxIndex == 0)
{
gFSKWriteIndex = 0;
gAirCopyBlockNumber = 0;
gErrorsDuringAirCopy = 0;
gInputBoxIndex = 0;
gAirCopyIsSendMode = 0;
BK4819_PrepareFSKReceive();
gAircopyState = AIRCOPY_TRANSFER;
}
else
gInputBox[--gInputBoxIndex] = 10;
gRequestDisplayScreen = DISPLAY_AIRCOPY;
if (bKeyHeld || !bKeyPressed) {
return;
}
if (gInputBoxIndex == 0) {
gFSKWriteIndex = 0;
gAirCopyBlockNumber = 0;
gInputBoxIndex = 0;
gErrorsDuringAirCopy = 0;
gAirCopyIsSendMode = 0;
BK4819_PrepareFSKReceive();
gAircopyState = AIRCOPY_TRANSFER;
} else {
gInputBox[--gInputBoxIndex] = 10;
}
gRequestDisplayScreen = DISPLAY_AIRCOPY;
}
static void AIRCOPY_Key_MENU(bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
gFSKWriteIndex = 0;
gAirCopyBlockNumber = 0;
gInputBoxIndex = 0;
gAirCopyIsSendMode = 1;
g_FSK_Buffer[0] = 0xABCD;
g_FSK_Buffer[1] = 0;
g_FSK_Buffer[35] = 0xDCBA;
AIRCOPY_SendMessage();
GUI_DisplayScreen();
gAircopyState = AIRCOPY_TRANSFER;
if (bKeyHeld || !bKeyPressed) {
return;
}
gFSKWriteIndex = 0;
gAirCopyBlockNumber = 0;
gInputBoxIndex = 0;
gAirCopyIsSendMode = 1;
g_FSK_Buffer[0] = 0xABCD;
g_FSK_Buffer[1] = 0;
g_FSK_Buffer[35] = 0xDCBA;
GUI_DisplayScreen();
gAircopyState = AIRCOPY_TRANSFER;
}
void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
switch (Key)
{
case KEY_0:
case KEY_1:
case KEY_2:
case KEY_3:
case KEY_4:
case KEY_5:
case KEY_6:
case KEY_7:
case KEY_8:
case KEY_9:
AIRCOPY_Key_DIGITS(Key, bKeyPressed, bKeyHeld);
break;
case KEY_MENU:
AIRCOPY_Key_MENU(bKeyPressed, bKeyHeld);
break;
case KEY_EXIT:
AIRCOPY_Key_EXIT(bKeyPressed, bKeyHeld);
break;
default:
break;
switch (Key) {
case KEY_0:
case KEY_1:
case KEY_2:
case KEY_3:
case KEY_4:
case KEY_5:
case KEY_6:
case KEY_7:
case KEY_8:
case KEY_9:
AIRCOPY_Key_DIGITS(Key, bKeyPressed, bKeyHeld);
break;
case KEY_MENU:
AIRCOPY_Key_MENU(bKeyPressed, bKeyHeld);
break;
case KEY_EXIT:
AIRCOPY_Key_EXIT(bKeyPressed, bKeyHeld);
break;
default:
break;
}
}

View file

@ -37,7 +37,7 @@ extern uint8_t gAirCopyIsSendMode;
extern uint16_t g_FSK_Buffer[36];
void AIRCOPY_SendMessage(void);
bool AIRCOPY_SendMessage(void);
void AIRCOPY_StorePacket(void);
void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);

View file

@ -16,6 +16,8 @@
#ifdef ENABLE_FLASHLIGHT
#include "app/flashlight.h"
#endif
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "mdc1200.h"
#include "app/action.h"
@ -68,8 +70,21 @@
#include "ui/ui.h"
static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
void (*ProcessKeysFunctions[])(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) = {
[DISPLAY_MAIN] = &MAIN_ProcessKeys,
[DISPLAY_MENU] = &MENU_ProcessKeys,
[DISPLAY_SCANNER] = &SCANNER_ProcessKeys,
#ifdef ENABLE_FMRADIO
[DISPLAY_FM] = &FM_ProcessKeys,
#endif
#ifdef ENABLE_AIRCOPY
[DISPLAY_AIRCOPY] = &AIRCOPY_ProcessKeys,
#endif
};
static_assert(ARRAY_SIZE(ProcessKeysFunctions) == DISPLAY_N_ELEM);
static void CheckForIncoming(void)
{
if (!g_SquelchLost)
@ -698,15 +713,16 @@ static void CheckRadioInterrupts(void)
#ifdef ENABLE_AIRCOPY
if (interrupt_status_bits & BK4819_REG_02_FSK_FIFO_ALMOST_FULL &&
gScreenToDisplay == DISPLAY_AIRCOPY &&
gAircopyState == AIRCOPY_TRANSFER &&
gAirCopyIsSendMode == 0)
{
unsigned int i;
for (i = 0; i < 4; i++)
g_FSK_Buffer[gFSKWriteIndex++] = BK4819_ReadRegister(BK4819_REG_5F);
AIRCOPY_StorePacket();
gScreenToDisplay == DISPLAY_AIRCOPY &&
gAircopyState == AIRCOPY_TRANSFER &&
gAirCopyIsSendMode == 0)
{
for (unsigned int i = 0; i < 4; i++) {
g_FSK_Buffer[gFSKWriteIndex++] = BK4819_ReadRegister(BK4819_REG_5F);
}
AIRCOPY_StorePacket();
}
#endif
#ifdef ENABLE_MDC1200
MDC1200_process_rx( interrupt_status_bits);
@ -795,8 +811,7 @@ static void HandleVox(void)
if (gCurrentFunction == FUNCTION_POWER_SAVE)
FUNCTION_Select(FUNCTION_FOREGROUND);
if (gCurrentFunction != FUNCTION_TRANSMIT && gSerialConfigCountDown_500ms == 0)
if (gCurrentFunction != FUNCTION_TRANSMIT && !SerialConfigInProgress())
{
#ifdef ENABLE_DTMF_CALLING
gDTMF_ReplyState = DTMF_REPLY_NONE;
@ -816,7 +831,7 @@ void APP_Update(void)
}
#endif
if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReached || gSerialConfigCountDown_500ms > 0))
if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReached || SerialConfigInProgress()))
{ // transmitter timed out or must de-key
gTxTimeoutReached = false;
@ -1022,9 +1037,9 @@ static void CheckKeys(void)
// -------------------- PTT ------------------------
if (gPttIsPressed)
{
if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || gSerialConfigCountDown_500ms > 0)
if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress())
{ // PTT released or serial comms config in progress
if (++gPttDebounceCounter >= 3 || gSerialConfigCountDown_500ms > 0) // 30ms
if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms
{ // stop transmitting
ProcessKey(KEY_PTT, false, false);
gPttIsPressed = false;
@ -1035,7 +1050,7 @@ static void CheckKeys(void)
else
gPttDebounceCounter = 0;
}
else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && gSerialConfigCountDown_500ms == 0)
else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress())
{ // PTT pressed
if (++gPttDebounceCounter >= 3) // 30ms
{ // start transmitting
@ -1264,13 +1279,8 @@ gAlarmState = ALARM_STATE_SITE_ALARM;
#ifdef ENABLE_AIRCOPY
if (gScreenToDisplay == DISPLAY_AIRCOPY && gAircopyState == AIRCOPY_TRANSFER && gAirCopyIsSendMode == 1)
{
if (gAircopySendCountdown > 0)
{
if (--gAircopySendCountdown == 0)
{
AIRCOPY_SendMessage();
GUI_DisplayScreen();
}
if (!AIRCOPY_SendMessage()) {
GUI_DisplayScreen();
}
}
#endif
@ -1386,9 +1396,7 @@ void APP_TimeSlice500ms(void)
}
}
if (gSerialConfigCountDown_500ms > 0)
{
}
if (gReducedService)
{
@ -1870,33 +1878,9 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
#endif
}
else if (Key != KEY_SIDE1 && Key != KEY_SIDE2) {
switch (gScreenToDisplay) {
case DISPLAY_MAIN:
MAIN_ProcessKeys(Key, bKeyPressed, bKeyHeld);
break;
#ifdef ENABLE_FMRADIO
case DISPLAY_FM:
FM_ProcessKeys(Key, bKeyPressed, bKeyHeld);
break;
#endif
case DISPLAY_MENU:
MENU_ProcessKeys(Key, bKeyPressed, bKeyHeld);
break;
case DISPLAY_SCANNER:
SCANNER_ProcessKeys(Key, bKeyPressed, bKeyHeld);
break;
#ifdef ENABLE_AIRCOPY
case DISPLAY_AIRCOPY:
AIRCOPY_ProcessKeys(Key, bKeyPressed, bKeyHeld);
break;
#endif
case DISPLAY_INVALID:
default:
break;
}
else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && gScreenToDisplay != DISPLAY_INVALID) {
ProcessKeysFunctions[gScreenToDisplay](Key, bKeyPressed, bKeyHeld);
}
else
#ifdef ENABLE_AIRCOPY

View file

@ -106,8 +106,7 @@ void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld)
void GENERIC_Key_PTT(bool bKeyPressed)
{
gInputBoxIndex = 0;
if (!bKeyPressed || gSerialConfigCountDown_500ms > 0)
if (!bKeyPressed || SerialConfigInProgress())
{ // PTT released
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // we are transmitting .. stop

View file

@ -943,16 +943,15 @@ static void RenderStill() {
const uint8_t METER_PAD_LEFT = 3;
for (int i = 0; i < 121; i++) {
if (i % 10 == 0) {
gFrameBuffer[2][i + METER_PAD_LEFT] = 0b01110000;
} else if (i % 5 == 0) {
gFrameBuffer[2][i + METER_PAD_LEFT] = 0b00110000;
} else {
gFrameBuffer[2][i + METER_PAD_LEFT] = 0b00010000;
}
memset(&gFrameBuffer[2][METER_PAD_LEFT], 0b00010000, 121);
for (int i = 0; i < 121; i+=5) {
gFrameBuffer[2][i + METER_PAD_LEFT] = 0b00110000;
}
for (int i = 0; i < 121; i+=10) {
gFrameBuffer[2][i + METER_PAD_LEFT] = 0b01110000;
}
uint8_t x = Rssi2PX(scanInfo.rssi, 0, 121);
for (int i = 0; i < x; ++i) {
if (i % 5) {
@ -1182,9 +1181,7 @@ void APP_RunSpectrum() {
RelaunchScan();
for (int i = 0; i < 128; ++i) {
rssiHistory[i] = 0;
}
memset(rssiHistory, 0, sizeof(rssiHistory));
isInitialized = true;

View file

@ -217,7 +217,7 @@ int32_t TX_freq_check(const uint32_t Frequency)
break;
case F_LOCK_NONE:
for (uint8_t i = 0; i < ARRAY_SIZE(frequencyBandTable); i++)
for (uint32_t i = 0; i < ARRAY_SIZE(frequencyBandTable); i++)
if (Frequency >= frequencyBandTable[i].lower && Frequency < frequencyBandTable[i].upper)
return 0;
break;

View file

@ -80,7 +80,7 @@ uint32_t FREQUENCY_RoundToStep(uint32_t freq, uint16_t step);
STEP_Setting_t FREQUENCY_GetStepIdxFromSortedIdx(uint8_t sortedIdx);
uint32_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t step);
int32_t TX_freq_check(const uint32_t Frequency);
int32_t RX_freq_check(const uint32_t Frequency);
int32_t TX_freq_check( uint32_t Frequency);
int32_t RX_freq_check( uint32_t Frequency);
#endif

View file

@ -17,16 +17,20 @@
#include <string.h>
#include "app/mdc1200.h"
#include "app/dtmf.h"
#if defined(ENABLE_FMRADIO)
#include "app/fm.h"
#endif
#include "audio.h"
#include "bsp/dp32g030/gpio.h"
#include "dcs.h"
#include "driver/backlight.h"
#if defined(ENABLE_FMRADIO)
#include "driver/bk1080.h"
#endif
#include "driver/bk4819.h"
#include "driver/gpio.h"
#include "driver/system.h"
@ -41,14 +45,14 @@
#include "ui/ui.h"
FUNCTION_Type_t gCurrentFunction;
inline bool FUNCTION_IsRx()
{
inline bool FUNCTION_IsRx() {
return gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING ||
gCurrentFunction == FUNCTION_RECEIVE;
}
void FUNCTION_Init(void)
{
void FUNCTION_Init(void) {
#ifdef ENABLE_NOAA
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
#endif
@ -57,7 +61,7 @@ void FUNCTION_Init(void)
}
#ifdef ENABLE_NOAA
else
gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE;
gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE;
#endif
#ifdef ENABLE_DTMF_CALLING
@ -65,22 +69,22 @@ void FUNCTION_Init(void)
#endif
g_CxCSS_TAIL_Found = false;
g_CDCSS_Lost = false;
g_CTCSS_Lost = false;
g_CDCSS_Lost = false;
g_CTCSS_Lost = false;
#ifdef ENABLE_VOX
g_VOX_Lost = false;
#endif
g_SquelchLost = false;
g_SquelchLost = false;
gFlagTailNoteEliminationComplete = false;
gFlagTailNoteEliminationComplete = false;
gTailNoteEliminationCountdown_10ms = 0;
gFoundCTCSS = false;
gFoundCDCSS = false;
gFoundCTCSSCountdown_10ms = 0;
gFoundCDCSSCountdown_10ms = 0;
gEndOfRxDetectedMaybe = false;
gFoundCTCSS = false;
gFoundCDCSS = false;
gFoundCTCSSCountdown_10ms = 0;
gFoundCDCSSCountdown_10ms = 0;
gEndOfRxDetectedMaybe = false;
#ifdef ENABLE_NOAA
gNOAACountdown_10ms = 0;
@ -89,196 +93,192 @@ void FUNCTION_Init(void)
gUpdateStatus = true;
}
void FUNCTION_Select(FUNCTION_Type_t Function)
{
void FUNCTION_Foreground(const FUNCTION_Type_t PreviousFunction) {
#ifdef ENABLE_DTMF_CALLING
if (gDTMF_ReplyState != DTMF_REPLY_NONE)
RADIO_PrepareCssTX();
#endif
if (PreviousFunction == FUNCTION_TRANSMIT) {
ST7565_FixInterfGlitch();
gVFO_RSSI_bar_level[0] = 0;
gVFO_RSSI_bar_level[1] = 0;
} else if (PreviousFunction != FUNCTION_RECEIVE) {
return;
}
#if defined(ENABLE_FMRADIO)
if (gFmRadioMode)
gFM_RestoreCountdown_10ms = fm_restore_countdown_10ms;
#endif
#ifdef ENABLE_DTMF_CALLING
if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT ||
gDTMF_CallState == DTMF_CALL_STATE_RECEIVED ||
gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY)
{
gDTMF_auto_reset_time_500ms = gEeprom.DTMF_auto_reset_time * 2;
}
#endif
gUpdateStatus = true;
}
void FUNCTION_PowerSave() {
gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10;
gPowerSaveCountdownExpired = false;
gRxIdleMode = true;
gMonitor = false;
BK4819_DisableVox();
BK4819_Sleep();
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false);
gUpdateStatus = true;
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
GUI_SelectNextDisplay(DISPLAY_MAIN);
}
void FUNCTION_Transmit() {
// if DTMF is enabled when TX'ing, it changes the TX audio filtering !! .. 1of11
BK4819_DisableDTMF();
#ifdef ENABLE_DTMF_CALLING
// clear the DTMF RX buffer
DTMF_clear_RX();
#endif
// clear the DTMF RX live decoder buffer
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
#if defined(ENABLE_FMRADIO)
if (gFmRadioMode)
BK1080_Init(0, false);
#endif
#ifdef ENABLE_ALARM
if (gAlarmState == ALARM_STATE_SITE_ALARM)
{
GUI_DisplayScreen();
AUDIO_AudioPathOff();
SYSTEM_DelayMs(20);
BK4819_PlayTone(500, 0);
SYSTEM_DelayMs(2);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
SYSTEM_DelayMs(60);
BK4819_ExitTxMute();
gAlarmToneCounter = 0;
return;
}
#endif
gUpdateStatus = true;
GUI_DisplayScreen();
RADIO_SetTxParameters();
// turn the RED LED on
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true);
DTMF_Reply();
#ifdef ENABLE_MDC1200
if (gEeprom.ROGER == ROGER_MODE_MDC_HEAD || gEeprom.ROGER == ROGER_MODE_MDC_BOTH ||
gEeprom.ROGER == ROGER_MODE_MDC_HEAD_ROGER) {
BK4819_send_MDC1200(1, 0x80, gEeprom.MDC1200_ID, true);
#ifdef ENABLE_MDC1200_SIDE_BEEP
BK4819_start_tone(880, 10, true, true);
SYSTEM_DelayMs(120);
BK4819_stop_tones(true);
#endif
} else
#endif
if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO)
BK4819_PlaySingleTone(2525, 250, 0, gEeprom.DTMF_SIDE_TONE);
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState != ALARM_STATE_OFF) {
#ifdef ENABLE_TX1750
if (gAlarmState == ALARM_STATE_TX1750)
BK4819_TransmitTone(true, 1750);
#endif
#ifdef ENABLE_ALARM
if (gAlarmState == ALARM_STATE_TXALARM)
BK4819_TransmitTone(true, 500);
gAlarmToneCounter = 0;
#endif
SYSTEM_DelayMs(2);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
return;
}
#endif
if (gCurrentVfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable)
BK4819_EnableScramble(gCurrentVfo->SCRAMBLING_TYPE - 1);
else
BK4819_DisableScramble();
// if (gSetting_backlight_on_tx_rx & BACKLIGHT_ON_TR_TX) {
BACKLIGHT_TurnOn();
// }
}
void FUNCTION_Select(FUNCTION_Type_t Function) {
const FUNCTION_Type_t PreviousFunction = gCurrentFunction;
const bool bWasPowerSave = (PreviousFunction == FUNCTION_POWER_SAVE);
const bool bWasPowerSave = PreviousFunction == FUNCTION_POWER_SAVE;
gCurrentFunction = Function;
if (bWasPowerSave && Function != FUNCTION_POWER_SAVE)
{
if (bWasPowerSave && Function != FUNCTION_POWER_SAVE) {
BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable();
gRxIdleMode = false;
UI_DisplayStatus();
}
switch (Function)
{
switch (Function) {
case FUNCTION_FOREGROUND:
#ifdef ENABLE_DTMF_CALLING
if (gDTMF_ReplyState != DTMF_REPLY_NONE)
RADIO_PrepareCssTX();
#endif
if (PreviousFunction == FUNCTION_TRANSMIT)
{
ST7565_FixInterfGlitch();
gVFO_RSSI_bar_level[0] = 0;
gVFO_RSSI_bar_level[1] = 0;
}
else
if (PreviousFunction != FUNCTION_RECEIVE)
break;
#if defined(ENABLE_FMRADIO)
if (gFmRadioMode)
gFM_RestoreCountdown_10ms = fm_restore_countdown_10ms;
#endif
#ifdef ENABLE_DTMF_CALLING
if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT ||
gDTMF_CallState == DTMF_CALL_STATE_RECEIVED ||
gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY)
{
gDTMF_auto_reset_time_500ms = gEeprom.DTMF_auto_reset_time * 2;
}
#endif
gUpdateStatus = true;
FUNCTION_Foreground(PreviousFunction);
return;
case FUNCTION_POWER_SAVE:
FUNCTION_PowerSave();
return;
case FUNCTION_TRANSMIT:
FUNCTION_Transmit();
break;
case FUNCTION_MONITOR:
gMonitor = true;
break;
case FUNCTION_INCOMING:
case FUNCTION_RECEIVE:
break;
case FUNCTION_POWER_SAVE:
gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10;
gPowerSaveCountdownExpired = false;
gRxIdleMode = true;
gMonitor = false;
BK4819_DisableVox();
BK4819_Sleep();
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false);
gUpdateStatus = true;
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
GUI_SelectNextDisplay(DISPLAY_MAIN);
return;
case FUNCTION_TRANSMIT:
#ifdef ENABLE_MDC1200
BK4819_enable_mdc1200_rx(false);
#endif
// if DTMF is enabled when TX'ing, it changes the TX audio filtering !! .. 1of11
BK4819_DisableDTMF();
#ifdef ENABLE_DTMF_CALLING
// clear the DTMF RX buffer
DTMF_clear_RX();
#endif
// clear the DTMF RX live decoder buffer
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
#if defined(ENABLE_FMRADIO)
if (gFmRadioMode)
BK1080_Init(0, false);
#endif
#ifdef ENABLE_ALARM
if (gAlarmState == ALARM_STATE_SITE_ALARM)
{
GUI_DisplayScreen();
AUDIO_AudioPathOff();
SYSTEM_DelayMs(20);
BK4819_PlayTone(500, 0);
SYSTEM_DelayMs(2);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
SYSTEM_DelayMs(60);
BK4819_ExitTxMute();
gAlarmToneCounter = 0;
break;
}
#endif
gUpdateStatus = true;
GUI_DisplayScreen();
RADIO_SetTxParameters();
// turn the RED LED on
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true);
if(!DTMF_Reply()) {
#ifdef ENABLE_MDC1200
// if (g_current_vfo->channel.mdc1200_mode == MDC1200_MODE_BOT || g_current_vfo->channel.mdc1200_mode == MDC1200_MODE_BOTH)
if(gEeprom.ROGER == ROGER_MODE_MDC_HEAD||gEeprom.ROGER==ROGER_MODE_MDC_BOTH||gEeprom.ROGER==ROGER_MODE_MDC_HEAD_ROGER)
{
// SYSTEM_DelayMs(30);
BK4819_send_MDC1200(1, 0x80, gEeprom.MDC1200_ID, true);
#ifdef ENABLE_MDC1200_SIDE_BEEP
BK4819_start_tone(880, 10, true, true);
SYSTEM_DelayMs(120);
BK4819_stop_tones(true);
#endif
}
else
#endif
if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO)
BK4819_PlaySingleTone(2525, 250, 0, gEeprom.DTMF_SIDE_TONE);
}
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState != ALARM_STATE_OFF) {
#ifdef ENABLE_TX1750
if (gAlarmState == ALARM_STATE_TX1750)
BK4819_TransmitTone(true, 1750);
#endif
#ifdef ENABLE_ALARM
if (gAlarmState == ALARM_STATE_TXALARM)
BK4819_TransmitTone(true, 500);
gAlarmToneCounter = 0;
#endif
SYSTEM_DelayMs(2);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
break;
}
#endif
if (gCurrentVfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable)
BK4819_EnableScramble(gCurrentVfo->SCRAMBLING_TYPE - 1);
else
BK4819_DisableScramble();
// if (gSetting_backlight_on_tx_rx == BACKLIGHT_ON_TR_TX ||
// gSetting_backlight_on_tx_rx == BACKLIGHT_ON_TR_TXRX)
BACKLIGHT_TurnOn();
break;
case FUNCTION_BAND_SCOPE:
break;
}
gBatterySaveCountdown_10ms = battery_save_count_10ms;
gSchedulePowerSave = false;
gSchedulePowerSave = false;
#if defined(ENABLE_FMRADIO)
gFM_RestoreCountdown_10ms = 0;

4
misc.c
View file

@ -87,7 +87,9 @@ bool gSetting_KILLED;
//bool gSetting_350EN;
uint8_t gSetting_F_LOCK;
bool gSetting_ScrambleEnable;
#ifdef ENABLE_AIRCOPY
uint8_t gAircopySendCountdown;
#endif
#ifdef ENABLE_AM_FIX
bool gSetting_AM_fix;

7
misc.h
View file

@ -163,7 +163,9 @@ extern uint32_t gCustomAesKey[4];
extern bool bHasCustomAesKey;
extern uint32_t gChallenge[4];
extern uint8_t gTryCount;
#ifdef ENABLE_AIRCOPY
extern uint8_t gAircopySendCountdown;
#endif
extern uint16_t gEEPROM_RSSI_CALIB[7][4];
extern uint16_t gEEPROM_1F8A;
@ -327,4 +329,7 @@ extern volatile uint8_t boot_counter_10ms;
int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit, int32_t UpperLimit);
unsigned long StrToUL(const char * str);
void FUNCTION_NOP();
inline bool SerialConfigInProgress() { return gSerialConfigCountDown_500ms != 0; }
#endif

View file

@ -1016,7 +1016,7 @@ void RADIO_PrepareTX(void)
) {
// TX frequency not allowed
State = VFO_STATE_TX_DISABLE;
} else if (gSerialConfigCountDown_500ms > 0) {
} else if ( SerialConfigInProgress()) {
// TX is disabled or config upload/download in progress
State = VFO_STATE_TX_DISABLE;
} else if (gCurrentVfo->BUSY_CHANNEL_LOCK && gCurrentFunction == FUNCTION_RECEIVE) {

View file

@ -239,10 +239,11 @@ void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center)
void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black)
{
const uint8_t pattern = 1 << (y % 8);
if(black)
buffer[y/8][x] |= 1 << (y%8);
buffer[y/8][x] |= pattern;
else
buffer[y/8][x] &= ~(1 << (y%8));
buffer[y/8][x] &= ~pattern;
}

52
ui/ui.c
View file

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../misc.h"
#include <assert.h>
#include <string.h>
#include "app/chFrScanner.h"
@ -42,37 +43,28 @@ uint8_t gAskForConfirmation;
bool gAskToSave;
bool gAskToDelete;
void (*UI_DisplayFunctions[])(void) = {
[DISPLAY_MAIN] = &UI_DisplayMain,
[DISPLAY_MENU] = &UI_DisplayMenu,
[DISPLAY_SCANNER] = &UI_DisplayScanner,
#ifdef ENABLE_FMRADIO
[DISPLAY_FM] = &UI_DisplayFM,
#endif
#ifdef ENABLE_AIRCOPY
[DISPLAY_AIRCOPY] = &UI_DisplayAircopy,
#endif
};
static_assert(ARRAY_SIZE(UI_DisplayFunctions) == DISPLAY_N_ELEM);
void GUI_DisplayScreen(void)
{
switch (gScreenToDisplay)
{
case DISPLAY_MAIN:
UI_DisplayMain();
break;
#ifdef ENABLE_FMRADIO
case DISPLAY_FM:
UI_DisplayFM();
break;
#endif
case DISPLAY_MENU:
UI_DisplayMenu();
break;
case DISPLAY_SCANNER:
UI_DisplayScanner();
break;
#ifdef ENABLE_AIRCOPY
case DISPLAY_AIRCOPY:
UI_DisplayAircopy();
break;
#endif
default:
break;
}
if (gScreenToDisplay != DISPLAY_INVALID) {
UI_DisplayFunctions[gScreenToDisplay]();
}
}
void GUI_SelectNextDisplay(GUI_DisplayType_t Display)

22
ui/ui.h
View file

@ -19,17 +19,23 @@
#include <stdbool.h>
#include <stdint.h>
enum GUI_DisplayType_t
{
DISPLAY_MAIN = 0,
DISPLAY_FM,
DISPLAY_MENU,
DISPLAY_SCANNER,
DISPLAY_AIRCOPY,
DISPLAY_INVALID = 0xFFu
};
DISPLAY_MAIN = 0,
DISPLAY_MENU,
DISPLAY_SCANNER,
#ifdef ENABLE_FMRADIO
DISPLAY_FM,
#endif
#ifdef ENABLE_AIRCOPY
DISPLAY_AIRCOPY,
#endif
DISPLAY_N_ELEM,
DISPLAY_INVALID = 0xFFu
};
typedef enum GUI_DisplayType_t GUI_DisplayType_t;
extern GUI_DisplayType_t gScreenToDisplay;

View file

@ -28,8 +28,9 @@
:: Do the compile
::
::make clean
make clean
make
:: pyinstaller --onefile ./MDC_WRITE/main.py
:: If you have python installed, you can create a 'packed' .bin from the compiled firmware.bin file.
:: The Quansheng windows upload-to-radio program requires a 'packed' .bin file.
::