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"?> <?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> </configurations>
</component> </component>
<component name="ChangeListManager"> <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$/.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> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -76,30 +93,53 @@
&quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;, &quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
&quot;cf.first.check.clang-format&quot;: &quot;false&quot;, &quot;cf.first.check.clang-format&quot;: &quot;false&quot;,
&quot;cidr.known.project.marker&quot;: &quot;true&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.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&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.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;, &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&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;structure.view.defaults.are.configured&quot;: &quot;true&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot; &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
} }
}</component> }</component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <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\app" />
<recent name="C:\Users\RUPC\Desktop\UV-K6\uv-k5-firmware-chinese" /> <recent name="C:\Users\RUPC\Desktop\UV-K6\uv-k5-firmware-chinese" />
</key> </key>
</component> </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"> <configuration name="clean" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile" temporary="true">
<makefile filename="$PROJECT_DIR$/Makefile" target="clean" workingDirectory="" arguments=""> <makefile filename="$PROJECT_DIR$/Makefile" target="clean" workingDirectory="" arguments="">
<envs /> <envs />
</makefile> </makefile>
<method v="2" /> <method v="2" />
</configuration> </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"> <configuration name="linux docker" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" /> <option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" /> <option name="INDEPENDENT_SCRIPT_PATH" value="true" />
@ -147,6 +187,7 @@
</configuration> </configuration>
<list> <list>
<item itemvalue="Makefile 目标.clean" /> <item itemvalue="Makefile 目标.clean" />
<item itemvalue="Python.main" />
<item itemvalue="Shell Script.win docker" /> <item itemvalue="Shell Script.win docker" />
<item itemvalue="Shell Script.linux docker" /> <item itemvalue="Shell Script.linux docker" />
<item itemvalue="Shell Script.win" /> <item itemvalue="Shell Script.win" />
@ -187,14 +228,11 @@
<workItem from="1702024305901" duration="2385000" /> <workItem from="1702024305901" duration="2385000" />
<workItem from="1702049513969" duration="28027000" /> <workItem from="1702049513969" duration="28027000" />
<workItem from="1702119088204" duration="12764000" /> <workItem from="1702119088204" duration="12764000" />
<workItem from="1702141572484" duration="2000" /> <workItem from="1702141572484" duration="2405000" />
</task> <workItem from="1702171975719" duration="1521000" />
<task id="LOCAL-00036" summary="MDC RX"> <workItem from="1702173556660" duration="287000" />
<created>1701687970236</created> <workItem from="1702173911297" duration="1180000" />
<option name="number" value="00036" /> <workItem from="1702175521208" duration="2000" />
<option name="presentableId" value="LOCAL-00036" />
<option name="project" value="LOCAL" />
<updated>1701687970236</updated>
</task> </task>
<task id="LOCAL-00037" summary="MDC RX"> <task id="LOCAL-00037" summary="MDC RX">
<created>1701689801897</created> <created>1701689801897</created>
@ -532,12 +570,22 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1702140061106</updated> <updated>1702140061106</updated>
</task> </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 /> <servers />
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" /> <option name="version" value="3" />
</component> </component>
<component name="UnknownFeatures">
<option featureType="com.intellij.fileTypeFactory" implementationName="*.bat" />
</component>
<component name="VCPKGProject"> <component name="VCPKGProject">
<isAutomaticEditVcpkgJson value="false" /> <isAutomaticEditVcpkgJson value="false" />
<isAutomaticCheckingOnLaunch value="false" /> <isAutomaticCheckingOnLaunch value="false" />
@ -556,7 +604,6 @@
</option> </option>
</component> </component>
<component name="VcsManagerConfiguration"> <component name="VcsManagerConfiguration">
<MESSAGE value="fix bug" />
<MESSAGE value="掃描下翻譯" /> <MESSAGE value="掃描下翻譯" />
<MESSAGE value="fix https://github.com/losehu/uv-k5-firmware-chinese/issues/4" /> <MESSAGE value="fix https://github.com/losehu/uv-k5-firmware-chinese/issues/4" />
<MESSAGE value="修复切换调制模式时亚音消失问题" /> <MESSAGE value="修复切换调制模式时亚音消失问题" />
@ -581,6 +628,7 @@
<MESSAGE value="clion" /> <MESSAGE value="clion" />
<MESSAGE value="开机音修复" /> <MESSAGE value="开机音修复" />
<MESSAGE value="MDC联系人" /> <MESSAGE value="MDC联系人" />
<option name="LAST_COMMIT_MESSAGE" value="MDC联系人" /> <MESSAGE value="MDC PY" />
<option name="LAST_COMMIT_MESSAGE" value="MDC PY" />
</component> </component>
</project> </project>

View file

@ -1,4 +1,5 @@
import sys import sys
import serial.tools.list_ports
import re import re
import serial import serial
max_contact=15 max_contact=15
@ -6,6 +7,9 @@ line_count=0
MDC_ADD= [ 0x1D48, 0x1D88, 0x1DC8,0x1F08] MDC_ADD= [ 0x1D48, 0x1D88, 0x1DC8,0x1F08]
MDC_NUM_ADD=0X1D00 MDC_NUM_ADD=0X1D00
file_out="MDC.txt" file_out="MDC.txt"
com_open=""
def payload_xor(payload): def payload_xor(payload):
XOR_ARRAY = bytes.fromhex('166c14e62e910d402135d5401303e980') XOR_ARRAY = bytes.fromhex('166c14e62e910d402135d5401303e980')
XOR_LEN = len(XOR_ARRAY) XOR_LEN = len(XOR_ARRAY)
@ -81,7 +85,8 @@ def check_duplicates(file_path):
else: else:
lines_seen.add(first_four) lines_seen.add(first_four)
def time_set(): 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' settime = b'\xAB\xCD\x08\x00\x02\x69\x10\xE6\xAC\xD1\x79\x25\x9D\xAD\xDC\xBA'
ser.write(settime) ser.write(settime)
@ -92,7 +97,8 @@ def time_set():
sys.exit() sys.exit()
def read_eeprom_byte(add): 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 = b'\x1B\x05' + b'\x08\x00' + add.to_bytes(2, byteorder='little') + b'\x11\x00' + b'\x82\x40\x74\x65'
# 将 payload 中的最后四个字节替换为当前时间戳 # 将 payload 中的最后四个字节替换为当前时间戳
hex_string = ' '.join(['{:02X}'.format(byte) for byte in payload]) hex_string = ' '.join(['{:02X}'.format(byte) for byte in payload])
@ -123,47 +129,49 @@ def read_eeprom():
sys.exit() sys.exit()
print("开始读取MDC联系人") print("开始读取MDC联系人")
with open(file_out, 'w+') as file: with open(file_out, 'w+') as file:
with serial.Serial('COM4', 38400, timeout=1) as ser: global com_open
a=0 with serial.Serial(com_open, 38400, timeout=1) as ser:
while a<num_contact: a=0
add=MDC_ADD[a//4]+(a%4)*16 while a<num_contact:
a=a+1 add=MDC_ADD[a//4]+(a%4)*16
print(a*100/num_contact,end='%\n') a=a+1
payload = b'\x1B\x05' + b'\x08\x00' +add.to_bytes(2, byteorder='little')+b'\x10\x00'+b'\x82\x40\x74\x65' 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 中的最后四个字节替换为当前时间戳 # 将 payload 中的最后四个字节替换为当前时间戳
hex_string = ' '.join(['{:02X}'.format(byte) for byte in payload]) hex_string = ' '.join(['{:02X}'.format(byte) for byte in payload])
crc = crc16_ccitt(payload) crc = crc16_ccitt(payload)
payload = payload + bytes([crc & 0xFF,]) + bytes([crc>>8,]) #swap bytes of crc to get little endian 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' message = b'\xAB\xCD' + b'\x0C\x00' + payload_xor(payload) + b'\xDC\xBA'
ser.write(message) ser.write(message)
full_response = ser.read(128) full_response = ser.read(128)
if len(full_response) == 0: if len(full_response) == 0:
print("读取失败!") print("读取失败!")
input("按 Enter 键退出程序") input("按 Enter 键退出程序")
sys.exit() sys.exit()
full_response_hex = full_response.hex() full_response_hex = full_response.hex()
# 将16进制字符串转换为字节串 # 将16进制字符串转换为字节串
full_response = bytes.fromhex(full_response_hex) full_response = bytes.fromhex(full_response_hex)
# 对payload部分进行解码然后以两位十六进制输出 # 对payload部分进行解码然后以两位十六进制输出
payload_decoded = convert_payload_to_hex(full_response) payload_decoded = convert_payload_to_hex(full_response)
i=0 i=0
# 将print的输出定向到文件中 # 将print的输出定向到文件中
for element in payload_decoded.split(' ')[8:]: for element in payload_decoded.split(' ')[8:]:
i = i + 1 i = i + 1
if i == 3: if i == 3:
file.write(' ') file.write(' ')
if i >= 3: if i >= 3:
file.write(chr(int(element, 16))) file.write(chr(int(element, 16)))
else: else:
file.write(element.upper()) file.write(element.upper())
file.write('\n') file.write('\n')
print("读取成功,联系人保存至 MDC联系人.txt") print("读取成功,联系人保存至 MDC.txt")
return True return True
def write_eeprom_byte(add,num): 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, 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') byteorder='little') + b'\x0F\x00' + b'\x82\x40\x74\x65' + num.to_bytes(1, byteorder='big')
# 将 payload 中的最后四个字节替换为当前时间戳 # 将 payload 中的最后四个字节替换为当前时间戳
@ -179,7 +187,8 @@ def write_eeprom_byte(add,num):
sys.exit() sys.exit()
def write_eeprom_select(a,my_str): 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 add = MDC_ADD[a // 4] + (a % 4) * 16
payload_data = ''.join(my_str).encode('utf-8') payload_data = ''.join(my_str).encode('utf-8')
hex1 = int(payload_data[0:2], 16) hex1 = int(payload_data[0:2], 16)
@ -219,7 +228,7 @@ def deal_blank_line():
def write_eeprom(): def write_eeprom():
print("正在将MDC联系人.txt写入到手台中") print("正在将MDC.txt写入到手台中")
global line_count # 声明 line_count 是全局变量 global line_count # 声明 line_count 是全局变量
a=0 a=0
deal_blank_line() deal_blank_line()
@ -244,6 +253,15 @@ def write_eeprom():
if __name__ == "__main__": 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 value=-1
print("第一次使用MDC联系人请先写入联系人!!") print("第一次使用MDC联系人请先写入联系人!!")
while value!=0 and value!=1: 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,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] # # 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) # 跳过头部和尾部的校验信息 # payload_decoded = convert_payload_to_hex(code) # 跳过头部和尾部的校验信息
# hex_payload = ' '.join(['{:02X}'.format(byte) for byte in payload_decoded]) # hex_payload = ' '.join(['{:02X}'.format(byte) for byte in payload_decoded])
# print(hex_payload) # print(hex_payload)

View file

@ -28,18 +28,26 @@
#include "ui/inputbox.h" #include "ui/inputbox.h"
#include "ui/ui.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; AIRCOPY_State_t gAircopyState;
uint16_t gAirCopyBlockNumber; uint16_t gAirCopyBlockNumber;
uint16_t gErrorsDuringAirCopy; uint16_t gErrorsDuringAirCopy;
uint8_t gAirCopyIsSendMode; 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; 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); 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]; g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
}
if (++gAirCopyBlockNumber >= 0x78) if (++gAirCopyBlockNumber >= 0x78) {
gAircopyState = AIRCOPY_COMPLETE; gAircopyState = AIRCOPY_COMPLETE;
}
RADIO_SetTxParameters(); RADIO_SetTxParameters();
@ -60,173 +70,173 @@ void AIRCOPY_SendMessage(void)
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
gAircopySendCountdown = 30; gAircopySendCountdown = 30;
return 0;
} }
void AIRCOPY_StorePacket(void) void AIRCOPY_StorePacket(void)
{ {
uint16_t Status; if (gFSKWriteIndex < 36) {
if (gFSKWriteIndex < 36)
return; return;
}
gFSKWriteIndex = 0; gFSKWriteIndex = 0;
gUpdateDisplay = true; gUpdateDisplay = true;
Status = BK4819_ReadRegister(BK4819_REG_0B); uint16_t Status = BK4819_ReadRegister(BK4819_REG_0B);
BK4819_PrepareFSKReceive(); BK4819_PrepareFSKReceive();
// Doc says bit 4 should be 1 = CRC OK, 0 = CRC FAIL, but original firmware checks for FAIL. // 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) if ((Status & 0x0010U) != 0 || g_FSK_Buffer[0] != 0xABCD || g_FSK_Buffer[35] != 0xDCBA) {
{ gErrorsDuringAirCopy++;
uint16_t CRC; return;
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;
}
}
} }
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) static void AIRCOPY_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{ {
if (!bKeyHeld && bKeyPressed) if (bKeyHeld || !bKeyPressed) {
{ return;
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;
} }
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) static void AIRCOPY_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{ {
if (!bKeyHeld && bKeyPressed) if (bKeyHeld || !bKeyPressed) {
{ return;
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 (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) static void AIRCOPY_Key_MENU(bool bKeyPressed, bool bKeyHeld)
{ {
if (!bKeyHeld && bKeyPressed) 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;
AIRCOPY_SendMessage();
GUI_DisplayScreen();
gAircopyState = AIRCOPY_TRANSFER;
} }
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) void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{ {
switch (Key) switch (Key) {
{ case KEY_0:
case KEY_0: case KEY_1:
case KEY_1: case KEY_2:
case KEY_2: case KEY_3:
case KEY_3: case KEY_4:
case KEY_4: case KEY_5:
case KEY_5: case KEY_6:
case KEY_6: case KEY_7:
case KEY_7: case KEY_8:
case KEY_8: case KEY_9:
case KEY_9: AIRCOPY_Key_DIGITS(Key, bKeyPressed, bKeyHeld);
AIRCOPY_Key_DIGITS(Key, bKeyPressed, bKeyHeld); break;
break; case KEY_MENU:
case KEY_MENU: AIRCOPY_Key_MENU(bKeyPressed, bKeyHeld);
AIRCOPY_Key_MENU(bKeyPressed, bKeyHeld); break;
break; case KEY_EXIT:
case KEY_EXIT: AIRCOPY_Key_EXIT(bKeyPressed, bKeyHeld);
AIRCOPY_Key_EXIT(bKeyPressed, bKeyHeld); break;
break; default:
default: break;
break;
} }
} }
#endif #endif

View file

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

View file

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

View file

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

View file

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

View file

@ -217,7 +217,7 @@ int32_t TX_freq_check(const uint32_t Frequency)
break; break;
case F_LOCK_NONE: 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) if (Frequency >= frequencyBandTable[i].lower && Frequency < frequencyBandTable[i].upper)
return 0; return 0;
break; 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); STEP_Setting_t FREQUENCY_GetStepIdxFromSortedIdx(uint8_t sortedIdx);
uint32_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t step); uint32_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t step);
int32_t TX_freq_check(const uint32_t Frequency); int32_t TX_freq_check( uint32_t Frequency);
int32_t RX_freq_check(const uint32_t Frequency); int32_t RX_freq_check( uint32_t Frequency);
#endif #endif

View file

@ -17,16 +17,20 @@
#include <string.h> #include <string.h>
#include "app/mdc1200.h" #include "app/mdc1200.h"
#include "app/dtmf.h" #include "app/dtmf.h"
#if defined(ENABLE_FMRADIO) #if defined(ENABLE_FMRADIO)
#include "app/fm.h" #include "app/fm.h"
#endif #endif
#include "audio.h" #include "audio.h"
#include "bsp/dp32g030/gpio.h" #include "bsp/dp32g030/gpio.h"
#include "dcs.h" #include "dcs.h"
#include "driver/backlight.h" #include "driver/backlight.h"
#if defined(ENABLE_FMRADIO) #if defined(ENABLE_FMRADIO)
#include "driver/bk1080.h" #include "driver/bk1080.h"
#endif #endif
#include "driver/bk4819.h" #include "driver/bk4819.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/system.h" #include "driver/system.h"
@ -41,14 +45,14 @@
#include "ui/ui.h" #include "ui/ui.h"
FUNCTION_Type_t gCurrentFunction; FUNCTION_Type_t gCurrentFunction;
inline bool FUNCTION_IsRx()
{ inline bool FUNCTION_IsRx() {
return gCurrentFunction == FUNCTION_MONITOR || return gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING || gCurrentFunction == FUNCTION_INCOMING ||
gCurrentFunction == FUNCTION_RECEIVE; gCurrentFunction == FUNCTION_RECEIVE;
} }
void FUNCTION_Init(void)
{ void FUNCTION_Init(void) {
#ifdef ENABLE_NOAA #ifdef ENABLE_NOAA
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
#endif #endif
@ -57,7 +61,7 @@ void FUNCTION_Init(void)
} }
#ifdef ENABLE_NOAA #ifdef ENABLE_NOAA
else else
gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE; gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE;
#endif #endif
#ifdef ENABLE_DTMF_CALLING #ifdef ENABLE_DTMF_CALLING
@ -65,22 +69,22 @@ void FUNCTION_Init(void)
#endif #endif
g_CxCSS_TAIL_Found = false; g_CxCSS_TAIL_Found = false;
g_CDCSS_Lost = false; g_CDCSS_Lost = false;
g_CTCSS_Lost = false; g_CTCSS_Lost = false;
#ifdef ENABLE_VOX #ifdef ENABLE_VOX
g_VOX_Lost = false; g_VOX_Lost = false;
#endif #endif
g_SquelchLost = false; g_SquelchLost = false;
gFlagTailNoteEliminationComplete = false; gFlagTailNoteEliminationComplete = false;
gTailNoteEliminationCountdown_10ms = 0; gTailNoteEliminationCountdown_10ms = 0;
gFoundCTCSS = false; gFoundCTCSS = false;
gFoundCDCSS = false; gFoundCDCSS = false;
gFoundCTCSSCountdown_10ms = 0; gFoundCTCSSCountdown_10ms = 0;
gFoundCDCSSCountdown_10ms = 0; gFoundCDCSSCountdown_10ms = 0;
gEndOfRxDetectedMaybe = false; gEndOfRxDetectedMaybe = false;
#ifdef ENABLE_NOAA #ifdef ENABLE_NOAA
gNOAACountdown_10ms = 0; gNOAACountdown_10ms = 0;
@ -89,198 +93,194 @@ void FUNCTION_Init(void)
gUpdateStatus = true; 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 FUNCTION_Type_t PreviousFunction = gCurrentFunction;
const bool bWasPowerSave = (PreviousFunction == FUNCTION_POWER_SAVE); const bool bWasPowerSave = PreviousFunction == FUNCTION_POWER_SAVE;
gCurrentFunction = Function; gCurrentFunction = Function;
if (bWasPowerSave && Function != FUNCTION_POWER_SAVE) if (bWasPowerSave && Function != FUNCTION_POWER_SAVE) {
{
BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(); BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable();
gRxIdleMode = false; gRxIdleMode = false;
UI_DisplayStatus(); UI_DisplayStatus();
} }
switch (Function) switch (Function) {
{
case FUNCTION_FOREGROUND: case FUNCTION_FOREGROUND:
#ifdef ENABLE_DTMF_CALLING FUNCTION_Foreground(PreviousFunction);
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;
return; return;
case FUNCTION_POWER_SAVE:
FUNCTION_PowerSave();
return;
case FUNCTION_TRANSMIT:
FUNCTION_Transmit();
break;
case FUNCTION_MONITOR: case FUNCTION_MONITOR:
gMonitor = true; gMonitor = true;
break; break;
case FUNCTION_INCOMING: case FUNCTION_INCOMING:
case FUNCTION_RECEIVE: 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: case FUNCTION_BAND_SCOPE:
break; break;
} }
gBatterySaveCountdown_10ms = battery_save_count_10ms; gBatterySaveCountdown_10ms = battery_save_count_10ms;
gSchedulePowerSave = false; gSchedulePowerSave = false;
#if defined(ENABLE_FMRADIO) #if defined(ENABLE_FMRADIO)
gFM_RestoreCountdown_10ms = 0; gFM_RestoreCountdown_10ms = 0;
#endif #endif
} }

4
misc.c
View file

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

7
misc.h
View file

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

View file

@ -1016,7 +1016,7 @@ void RADIO_PrepareTX(void)
) { ) {
// TX frequency not allowed // TX frequency not allowed
State = VFO_STATE_TX_DISABLE; State = VFO_STATE_TX_DISABLE;
} else if (gSerialConfigCountDown_500ms > 0) { } else if ( SerialConfigInProgress()) {
// TX is disabled or config upload/download in progress // TX is disabled or config upload/download in progress
State = VFO_STATE_TX_DISABLE; State = VFO_STATE_TX_DISABLE;
} else if (gCurrentVfo->BUSY_CHANNEL_LOCK && gCurrentFunction == FUNCTION_RECEIVE) { } 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) void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black)
{ {
const uint8_t pattern = 1 << (y % 8);
if(black) if(black)
buffer[y/8][x] |= 1 << (y%8); buffer[y/8][x] |= pattern;
else 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 * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "../misc.h"
#include <assert.h>
#include <string.h> #include <string.h>
#include "app/chFrScanner.h" #include "app/chFrScanner.h"
@ -42,37 +43,28 @@ uint8_t gAskForConfirmation;
bool gAskToSave; bool gAskToSave;
bool gAskToDelete; 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) void GUI_DisplayScreen(void)
{ {
switch (gScreenToDisplay) if (gScreenToDisplay != DISPLAY_INVALID) {
{ UI_DisplayFunctions[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;
}
} }
void GUI_SelectNextDisplay(GUI_DisplayType_t Display) void GUI_SelectNextDisplay(GUI_DisplayType_t Display)

22
ui/ui.h
View file

@ -19,17 +19,23 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
enum GUI_DisplayType_t enum GUI_DisplayType_t
{ {
DISPLAY_MAIN = 0, DISPLAY_MAIN = 0,
DISPLAY_FM, DISPLAY_MENU,
DISPLAY_MENU, DISPLAY_SCANNER,
DISPLAY_SCANNER,
DISPLAY_AIRCOPY,
DISPLAY_INVALID = 0xFFu
};
#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; typedef enum GUI_DisplayType_t GUI_DisplayType_t;
extern GUI_DisplayType_t gScreenToDisplay; extern GUI_DisplayType_t gScreenToDisplay;

View file

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