Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
GSCmax authored Feb 27, 2024
2 parents 732e4e8 + 9b08259 commit bd81e02
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 91 deletions.
135 changes: 119 additions & 16 deletions functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ def todo_function():
return


def check_eeprom_writeable(serial_port: serial.Serial, offset: int, extra: int) -> bool:
def check_eeprom_writeable(serial_port: serial.Serial, addr: int) -> bool:
# 读取原始数据
read_data = serial_utils.read_extra_eeprom(serial_port, offset, extra, 8)
read_data = serial_utils.read_extra_eeprom(serial_port, addr, 8)
# 写入随机数据
random_bytes = bytes([random.randint(0, 255) for _ in range(8)])
serial_utils.write_extra_eeprom(serial_port, offset, extra, random_bytes)
serial_utils.write_extra_eeprom(serial_port, addr, random_bytes)
# 读取写入的数据
read_write_data = serial_utils.read_extra_eeprom(serial_port, offset, extra, 8)
read_write_data = serial_utils.read_extra_eeprom(serial_port, addr, 8)
# 恢复原始数据
serial_utils.write_extra_eeprom(serial_port, offset, extra, read_data)
serial_utils.write_extra_eeprom(serial_port, addr, read_data)

return read_write_data == random_bytes

Expand All @@ -72,7 +72,7 @@ def check_serial_port(serial_port: serial.Serial,
for i in range(1, 5):
# 128 KiB offset 0x1, 256 KiB offset 0x3, 384 KiB offset 0x5, 512 KiB offset 0x7
# 1 -> 0x1, 2 -> 0x3, 3 -> 0x5, 4 -> 0x7 符合 2n-1
if check_eeprom_writeable(serial_port, 2 * i - 1, 0x8000):
if check_eeprom_writeable(serial_port, (2 * i - 1) * 0x10000 + 0x8000):
eeprom_size = i
else:
break
Expand Down Expand Up @@ -114,7 +114,6 @@ def write_data(serial_port: Serial, start_addr: int, data: Union[bytes, List[int
total_page = data_len // 128
addr = start_addr
current_step = 0
offset = 0
while addr < start_addr + data_len:
percent_float = (current_step / total_page) * 100
percent = int(percent_float)
Expand All @@ -127,9 +126,7 @@ def write_data(serial_port: Serial, start_addr: int, data: Union[bytes, List[int
if start_addr + data_len < 0x10000:
serial_utils.write_eeprom(serial_port, addr, writing_data)
else:
if addr - offset * 0x10000 >= 0x10000:
offset += 1
serial_utils.write_extra_eeprom(serial_port, offset, addr - offset * 0x10000, writing_data)
serial_utils.write_extra_eeprom(serial_port, addr, writing_data)
addr += step
current_step += 1
progress['value'] = 0
Expand Down Expand Up @@ -394,18 +391,16 @@ def auto_write_font(serial_port_text: str, window: tk.Tk, progress: ttk.Progress
log(f'正在进行 3/{n}: 写入亚音参数')
write_tone_options(serial_port_text, window, progress, status_label, eeprom_size, firmware_version, True)
if n == 4:
log(f'正在进行 4/{n}: 写入拼音检索表')
log(f'正在进行 4/4: 写入拼音检索表')
if version_number == 123:
write_pinyin_index(serial_port_text, window, progress, status_label, eeprom_size, firmware_version,
True)
elif version_number > 123:
write_pinyin_index(serial_port_text, window, progress, status_label, eeprom_size, firmware_version,
True, True)
reset_radio(serial_port_text, status_label)
messagebox.showinfo('提示', f'{version_number}{version_code}版本字库\n字库配置\n亚音参数\n拼音检索表\n写入成功!')
else:
reset_radio(serial_port_text, status_label)
messagebox.showinfo('提示', f'{version_number}{version_code}版本字库\n字库配置\n亚音参数\n写入成功!')
reset_radio(serial_port_text, status_label)
extra_msg = '拼音检索表\n' if n == 4 else ''
messagebox.showinfo('提示', f'{version_number}{version_code}版本字库\n字库配置\n亚音参数\n{extra_msg}写入成功!')
else:
messagebox.showinfo('提示', f'非LOSEHU扩容固件,无法写入')

Expand Down Expand Up @@ -636,3 +631,111 @@ def write_pinyin_index(serial_port_text: str, window: tk.Tk, progress: ttk.Progr
serial_utils.reset_radio(serial_port)
messagebox.showinfo('提示', '写入拼音检索表成功!')
status_label['text'] = '当前操作: 无'


def backup_eeprom(serial_port_text: str, window: tk.Tk, progress: ttk.Progressbar,
status_label: tk.Label, eeprom_size: int):
log('开始备份')
log('选择的串口: ' + serial_port_text)
status_label['text'] = f'当前操作: 备份eeprom'
if len(serial_port_text) == 0:
log('没有选择串口!')
messagebox.showerror('错误', '没有选择串口!')
status_label['text'] = '当前操作: 无'
return

if eeprom_size > 0:
target_eeprom_offset = 0x20000 * eeprom_size
else:
target_eeprom_offset = 0x2000

with serial.Serial(serial_port_text, 38400, timeout=2) as serial_port:
serial_check = check_serial_port(serial_port, False)
if not serial_check.status:
messagebox.showerror('错误', serial_check.message)
status_label['text'] = '当前操作: 无'
return

start_addr = 0x0 # 起始地址为0x0
total_steps = (target_eeprom_offset - start_addr) // 128 # 计算总步数
current_step = 0
addr = start_addr

backup_data = b''

while addr < target_eeprom_offset: # 限制地址范围为start_addr到target_eeprom_offset
if target_eeprom_offset < 0x10000:
read_data = serial_utils.read_eeprom(serial_port, addr, 128)
else:
read_data = serial_utils.read_extra_eeprom(serial_port, addr, 128)
backup_data += read_data
addr += 128
current_step += 1
percent_float = (current_step / total_steps) * 100
log(f'进度: {percent_float:.1f}%, addr={hex(addr)}', '')
progress['value'] = percent_float
window.update()

# 弹出文件保存对话框
file_path = filedialog.asksaveasfilename(defaultextension=".bin",
filetypes=[("Binary files", "*.bin"), ("All files", "*.*")])

if not file_path:
log('用户取消保存')
messagebox.showinfo('提示', '用户取消保存')
return # 用户取消保存,直接返回

with open(file_path, 'wb') as fp:
fp.write(backup_data)

log('EEPROM 备份完成')
status_label['text'] = '当前操作: 无'
messagebox.showinfo('提示', '保存成功!')


def restore_eeprom(serial_port_text: str, window: tk.Tk, progress: ttk.Progressbar,
status_label: tk.Label, eeprom_size: int):
log('开始恢复eeprom')
log('选择的串口: ' + serial_port_text)
status_label['text'] = f'当前操作: 恢复eeprom'
if len(serial_port_text) == 0:
log('没有选择串口!')
messagebox.showerror('错误', '没有选择串口!')
status_label['text'] = '当前操作: 无'
return

start_addr = 0x0
if eeprom_size > 0:
target_eeprom_offset = 0x20000 * eeprom_size
else:
target_eeprom_offset = 0x2000

file_path = filedialog.askopenfilename(filetypes=[("Binary files", "*.bin"), ("All files", "*.*")])

if not file_path:
log('用户取消选择')
messagebox.showinfo('提示', '用户取消选择')
return # 用户取消选择,直接返回

with open(file_path, 'rb') as fp:
restore_data = fp.read()

if len(restore_data) != target_eeprom_offset:
if messagebox.askquestion('提示', f'选择的文件大小为{len(restore_data)},但目标eeprom大小为{target_eeprom_offset},是否继续?') == 'no':
log('用户取消恢复')
messagebox.showinfo('提示', '用户取消恢复')
return # 用户取消恢复,直接返回

with serial.Serial(serial_port_text, 38400, timeout=2) as serial_port:
serial_check = check_serial_port(serial_port, False)
if not serial_check.status:
messagebox.showerror('错误', serial_check.message)
status_label['text'] = '当前操作: 无'
return

write_data(serial_port, start_addr, restore_data, progress, window)

log('EEPROM恢复完成')
status_label['text'] = '当前操作: 无'
serial_utils.reset_radio(serial_port)
messagebox.showinfo('提示', '写入成功!')
49 changes: 20 additions & 29 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
read_config,
write_config,
write_pinyin_index,
todo_function
todo_function,
backup_eeprom,
restore_eeprom
)

window = ttk.Window()
version = '0.5'
version = '0.6'

appdata_path = os.getenv('APPDATA') if os.getenv('APPDATA') is not None else ''
config_dir = os.path.join(appdata_path, 'K5_Tools')
Expand Down Expand Up @@ -364,26 +366,30 @@ def main():
width=14,
command=lambda: write_pinyin_index(
serial_port_combo.get(), window, progress, label2,
EEPROM_SIZE.index(eeprom_size_combo.get()), FIRMWARE_VERSION_LIST.index(firmware_combo.get()), True
EEPROM_SIZE.index(eeprom_size_combo.get()), FIRMWARE_VERSION_LIST.index(firmware_combo.get()), False, True
)
)
write_pinyin_new_index_button.pack(side='left', padx=3, pady=(2, 15))

todo_button = tk.Button(
backup_eeprom_button = tk.Button(
frame7,
text=translations[language]['todo_button_text'],
text='备份EEPROM',
width=14,
command=todo_function
command=lambda:backup_eeprom(
serial_port_combo.get(), window, progress, label2,EEPROM_SIZE.index(eeprom_size_combo.get())
)
)
todo_button.pack(side='left', padx=3, pady=(2, 15))
backup_eeprom_button.pack(side='left', padx=3, pady=(2, 15))

todo_button = tk.Button(
restore_eeprom_button = tk.Button(
frame7,
text=translations[language]['todo_button_text'],
text='恢复EEPROM',
width=14,
command=todo_function
command=lambda:restore_eeprom(
serial_port_combo.get(), window, progress, label2,EEPROM_SIZE.index(eeprom_size_combo.get())
)
)
todo_button.pack(side='left', padx=3, pady=(2, 15))
restore_eeprom_button.pack(side='left', padx=3, pady=(2, 15))

todo_button = tk.Button(
frame7,
Expand Down Expand Up @@ -412,24 +418,6 @@ def main():
log('所有操作均有一定的风险,请确保您已备份校准等文件!!!\n')

# 在此统一设置tooltip
#Tooltip(serial_port_combo, "点击选择K5/K6所在串口")
#Tooltip(eeprom_size_combo, "EEPROM芯片容量,若自动检测正确则无需修改")
#Tooltip(firmware_combo, "固件版本,若自动检测正确则无需修改")
#Tooltip(clean_eeprom_button, "清除EEPROM中的所有数据")
#Tooltip(auto_write_font_button, "自动写入机器固件所需字库等文件,如不清楚点那个按钮的情况下,点这个总没错")
#Tooltip(read_calibration_button, "校准文件包含硬件参数校准信息,必须备份!建议终身保留以备恢复")
#Tooltip(write_calibration_button, "校准文件只在更换芯片或清除EEPROM数据后写一次即可")
#Tooltip(read_config_button, "配置文件包含了菜单设置信息、开机字符和信道信息等,如无特别需要可不备份,不同固件的菜单设置可能不通用")
#Tooltip(write_config_button, "配置文件如无特别需要,可以不写")
#Tooltip(write_font_conf_button, "写入字库配置,如果不使用自动写入,请在执行完字库写入后点击")
#Tooltip(write_tone_options_button, "写入亚音参数,如果不使用自动写入,请在执行完字库写入后点击")
#Tooltip(write_font_compressed_button, "压缩GB2312字库,萝狮虎118K、123H版本及后续版本使用")
#Tooltip(write_font_uncompressed_button, "全量GB2312字库,用于萝狮虎118H版本,后续未使用")
#Tooltip(write_font_old_button, "萝狮虎117版本及之前版本使用,旧字库")
#Tooltip(write_pinyin_old_index_button, "123版本拼音索引,如果不使用自动写入,请在执行完字库写入后点击")
#Tooltip(write_pinyin_new_index_button, "124及以上版本拼音索引,如果不使用自动写入,请在执行完字库写入后点击")
#Tooltip(language_combo, "Change language.")

Tooltip(language_combo, translations[language]['language_combo_tooltip_text'])
Tooltip(eeprom_size_combo, translations[language]['eeprom_size_combo_tooltip_text'])
Tooltip(firmware_combo, translations[language]['firmware_combo_tooltip_text'])
Expand All @@ -447,6 +435,9 @@ def main():
Tooltip(write_font_old_button, translations[language]['write_font_old_button_tooltip_text'])
Tooltip(write_pinyin_old_index_button, translations[language]['write_pinyin_old_index_button_tooltip_text'])
Tooltip(write_pinyin_new_index_button, translations[language]['write_pinyin_new_index_button_tooltip_text'])
Tooltip(backup_eeprom_button, "备份EEPROM中的数据,使用EEPROM下拉框可以选择所要备份的大小")
Tooltip(restore_eeprom_button, "恢复EEPROM中的数据,使用EEPROM下拉框可以选择所要恢复的大小")
Tooltip(todo_button, "敬请期待")

window.mainloop()

Expand Down
35 changes: 1 addition & 34 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
[tool.poetry]
name = "k5-tools"
version = "0.5"
version = "0.6"
description = ""
authors = ["hank9999 <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.8"
pyserial = "^3.5"
importlib-resources = "^6.1.1"
ttkbootstrap = "^1.10.1"

[build-system]
Expand Down
3 changes: 1 addition & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pyserial>=3.5
ttkbootstrap>=1.10.1
importlib-resources>=6.1.1
ttkbootstrap>=1.10.1
14 changes: 6 additions & 8 deletions serial_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,9 @@ def read_eeprom(serial_port: serial.Serial, offset: int, length: int):
return o[8:]


def read_extra_eeprom(serial_port: serial.Serial, offset: int, extra: int, length: int):
if extra > 0xFFFF:
offset = extra >> 16
extra = extra & 0xFFFF
def read_extra_eeprom(serial_port: serial.Serial, addr: int, length: int):
offset = addr >> 16
extra = addr & 0xFFFF
extra_bytes = struct.pack("<H", extra)
read_mem = b"\x2b\x05\x08\x00" + \
struct.pack("<HBB", offset, length, 0) + \
Expand Down Expand Up @@ -135,10 +134,9 @@ def write_eeprom(serial_port: serial.Serial, offset: int, data: bytes):
raise Exception("写入前8KiB EEPROM响应错误!")


def write_extra_eeprom(serial_port: serial.Serial, offset: int, extra: int, data: bytes):
if extra > 0xFFFF:
offset = extra >> 16
extra = extra & 0xFFFF
def write_extra_eeprom(serial_port: serial.Serial, addr: int, data: bytes):
offset = addr >> 16
extra = addr & 0xFFFF
extra = struct.pack("<H", extra)
length = len(data) + len(extra)

Expand Down

0 comments on commit bd81e02

Please sign in to comment.