diff --git a/src/gui/core/canvas.py b/src/gui/core/canvas.py deleted file mode 100644 index 9b1d84f..0000000 --- a/src/gui/core/canvas.py +++ /dev/null @@ -1,25 +0,0 @@ -# Flowshutter -# Copyright (C) 2021 Hugo Chiang - -# Flowshutter is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# Flowshutter is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. - -# You should have received a copy of the GNU Affero General Public License -# along with flowshutter. If not, see . -import target - -def init_canvas(screen): - if target.oled_height == 64: - import gui.lib.canvas_128x64 as c - Canvas = c.Canvas_128x64(screen) - elif target.oled_height == 32: - import gui.lib.canvas_128x32 as c - Canvas = c.Canvas_128x32(screen) - return Canvas diff --git a/src/gui/lib/canvas_128x32.py b/src/gui/lib/canvas_128x32.py index 8d7324b..1b76e1e 100644 --- a/src/gui/lib/canvas_128x32.py +++ b/src/gui/lib/canvas_128x32.py @@ -13,42 +13,12 @@ # You should have received a copy of the GNU Affero General Public License # along with flowshutter. If not, see . -from gui.core.writer import Writer -from gui.fonts.icons import Icons -import gui.fonts.arial10 as a10 -import target -import framebuf, time +from gui.lib.common import Canvas_Abstract -class Canvas_128x32(Icons): +class Canvas(Canvas_Abstract): def __init__(self,screen): - self.settings = { - 'version': '0.66', - 'camera_protocol': 'NO', - 'device_mode': 'MASTER', - 'inject_mode': 'OFF', - 'ota_source': 'GitHub', - 'ota_channel': 'stable', - 'target_name': target.name - } - self.vol = 0 - self.erase_flag = False - self.screen = screen - self.a10 = Writer(self.screen, a10) self.animation = False - super().__init__() - - def update(self, info, sub_state, sub_menu, sub_info): - if sub_info != '': - if sub_info == 'BATTERY': - self.display_battery() - else: - self.display_hint(sub_info) - elif info == "home": - self.display_state(sub_state) - elif info == "menu": - self.display_menu(sub_menu) - else: - print(str(time.ticks_us()) + " [ Error] Unkown info: " + info) + super().__init__(screen) def draw_batterymask(self, voltage): @@ -83,19 +53,19 @@ def draw_batterymask(self, voltage): self.screen.fill_rect(5,5,108,22,0) # else: # less than 0%, then do nothing - def display_state(self, state): - if state == 'WELCOME': + def display_work_state(self, state): + if state == 0: self.screen.fill(0) self.screen.blit(self.icon_gyroflow, 0, 2) self.screen.show() else: - if state == 'HOME': + if state == 1: fb, header, content1, content2, content3 = self.icon_cam, 'Flowshutter', 'Powered by', 'DusKing', ''.join(tuple(self.settings['version'])) - elif state == 'STARTING': + elif state == 2: fb, header, content1, content2, content3 = self.icon_cam, 'Starting', 'FC Disarmed', 'Camera start', '' - elif state == 'RECORDING': + elif state == 3: fb, header, content1, content2, content3 = self.icon_cam_wk, 'Flowshutter', 'FC Armed', 'Recording', '' - elif state == 'STOPPING': + elif state == 4: fb, header, content1, content2, content3 = self.icon_cam_wk, 'Stopping', 'FC Armed', 'Camera stop', '' else: print('Unkown state: ' + state) @@ -117,35 +87,49 @@ def display_battery(self): self.screen.text(voltage_str,44,13,1) self.screen.show() - def display_menu(self, sub_cat): - if sub_cat == 'camera_protocol': - index, head, content, fb = 1, 'Camera Protocol',''.join(tuple(self.settings['camera_protocol'])), self.icon_settings - elif sub_cat == 'device_mode': - index, head, content, fb = 2, 'Device Mode', ''.join(tuple(self.settings['device_mode'])), self.icon_settings - elif sub_cat == 'inject_mode': + def display_menu(self, sub_menu, field,field_state): + self.screen.fill(0) + if sub_menu == 0: + index, head, content, fb = 0, 'General Infomation','Land Page', self.icon_settings + elif sub_menu == 1: + index, head, content, fb = 1, 'Camera Protocol',''.join(tuple(self.settings['camera_protocol'])), self.icon_settings + elif sub_menu == 2: + index, head, content, fb = 2, 'Device Mode', ''.join(tuple(self.settings['device_mode'])), self.icon_settings + elif sub_menu == 3: index, head, content, fb = 3, 'Audio Injection',''.join(tuple(self.settings['inject_mode'])), (self.icon_audio if self.settings['inject_mode'] == "ON" else self.icon_audio_off) - elif sub_cat == 'erase_blackbox': + elif sub_menu == 4: index, head, content, fb = 4, 'Blackbox Erase', ('Erasing...' if self.erase_flag else 'Erase stop'),self.icon_blackbox - elif sub_cat == 'internet': - import mwlan - index, head, content, fb = 5, 'Internet', ''.join(tuple(mwlan.wlan_state)), (self.self.icon_wifi if mwlan.wlan_state == "CONNECTED" else self.self.icon_wifi_dis) - elif sub_cat == 'ota_source': - index, head, content, fb = 6, 'OTA Source', ''.join(tuple(self.settings['ota_source'])), (self.icon_github if self.settings['ota_source'] == "GitHub" else self.icon_gitee) - elif sub_cat == 'ota_channel': - index, head, content, fb = 7, 'OTA Channel', ''.join(tuple(self.settings['ota_channel'])), self.icon_settings - elif sub_cat == 'ota_check': - index, head, content, fb = 8, 'OTA Check', "".join(tuple(self.settings['ota_source']))+"/"+"".join(tuple(self.settings['ota_channel'])),self.icon_settings - elif sub_cat == 'ota_update': - index, head, content, fb = 9, 'OTA Update', 'ENT = START', self.icon_settings else: - print('Unknown sub_menu:', sub_cat) - self.screen.fill(0) + print('Unknown sub_menu:', sub_menu) + self.screen.blit(fb, 95, 0) self.a10.set_textpos(self.screen,0,0) self.a10.printstring(head) self.screen.hline(0,10,94,1) - self.screen.text(content, 0, 14, 1) - self.screen.text('<< '+str(index)+'/4 >>', 0, 24, 1) + + if field == 0: + self.screen.text(('<< '+str(index)+'/4 >>'),0, 24, 1) + cont_color = 1 + elif field == 1: + self.screen.fill_rect(40,23,40,11,1) + self.screen.text('SAVE',0, 24, 1) + self.screen.text('LEAVE',40, 24, 0) + cont_color = 1 + elif field == 2: + self.screen.text('SAVE',0, 24, 1) + self.screen.text('LEAVE',40, 24, 1) + if field_state ==0: + self.screen.fill_rect(0,12,int(len(content)*8),11,1) + cont_color = 0 + else: + self.screen.rect(0,12,int(len(content)*8),11,1) + cont_color = 1 + elif field == 3: + self.screen.fill_rect(0,23,32,11,1) + self.screen.text('SAVE',0, 24, 0) + self.screen.text('LEAVE',40, 24, 1) + cont_color = 1 + self.screen.text(content, 0, 14, cont_color) self.screen.show() def display_hint(self, sub_info): @@ -161,13 +145,17 @@ def display_hint(self, sub_info): elif sub_info == 'STARTING_TIMEOUT': self.screen.text('No ACK back', 17, 6, 1) self.screen.text('Start failed', 17, 16, 1) - elif sub_info == 'AP_HINT': - self.screen.text('SSID:'+ 'Flowshutter', 3, 6, 1) - self.screen.text('Pswd:'+ 'ilovehugo', 3, 16, 1) - elif sub_info == 'WLAN_CONNECTING': - self.screen.text('Connecting', 21, 6, 1) - self.screen.text('Please wait', 21, 16, 1) elif sub_info == 'SETTINGS_FAULT': self.screen.text('Settings Fault', 26, 8, 1) self.screen.text('Please Reboot', 26, 20, 1) self.screen.show() + + def display_reboot_page(self, state): + self.screen.fill(0) + self.screen.text('Exit',0,0,1) + self.screen.text('Reboot',0,12,1) + if state == 0: + self.screen.text('<<',56,0,1) + elif state == 1: + self.screen.text('<<',56,12,1) + self.screen.show() diff --git a/src/gui/lib/canvas_128x64.py b/src/gui/lib/canvas_128x64.py index 8296941..ab9f698 100644 --- a/src/gui/lib/canvas_128x64.py +++ b/src/gui/lib/canvas_128x64.py @@ -13,46 +13,12 @@ # You should have received a copy of the GNU Affero General Public License # along with flowshutter. If not, see . -from gui.core.writer import Writer -from gui.fonts.icons import Icons -import gui.fonts.arial10 as a10 -import gui.fonts.font6 as f6 -import gui.fonts.font10 as f10 -import target -import framebuf, time +from gui.lib.common import Canvas_Abstract -class Canvas_128x64(Icons): +class Canvas(Canvas_Abstract): def __init__(self,screen): - self.settings = { - 'version': '0.66', - 'camera_protocol': 'NO', - 'device_mode': 'MASTER', - 'inject_mode': 'OFF', - 'ota_source': 'GitHub', - 'ota_channel': 'stable', - 'target_name': target.name - } - self.vol = 0 - self.erase_flag = False - self.screen = screen - self.f6 = Writer(self.screen, f6) - self.a10 = Writer(self.screen, a10) - self.f10 = Writer(self.screen, f10) - self.animation = True - super().__init__() - - def update(self, info, sub_state, sub_menu, sub_info): - if sub_info != '': - if sub_info == 'BATTERY': - self.display_battery() - else: - self.display_hint(sub_info) - elif info == "home": - self.display_state(sub_state) - elif info == "menu": - self.display_menu(sub_menu) - else: - print(str(time.ticks_us()) + " [ Error] Unkown info: " + info) + self.animation = False + super().__init__(screen) def draw_batterymask(self, voltage): @@ -87,19 +53,19 @@ def draw_batterymask(self, voltage): self.screen.fill_rect(5,5,108,22,0) # else: # less than 0%, then do nothing - def display_state(self, state): - if state == "WELCOME": + def display_work_state(self, state): + if state == 0: self.screen.fill(0) - self.screen.blit(self.icon_gyroflow, 0, 2+16) + self.screen.blit(self.icon_gyroflow, 0, 18) self.screen.show() else: - if state == 'HOME': + if state == 1: fb, header, content1, content2, content3 = self.icon_cam, 'Flowshutter', 'Powered by', 'DusKing', ''.join(tuple(self.settings['version'])) - elif state == 'STARTING': + elif state == 2: fb, header, content1, content2, content3 = self.icon_cam, 'Starting', 'FC Disarmed', 'Camera start', '' - elif state == 'RECORDING': + elif state == 3: fb, header, content1, content2, content3 = self.icon_cam_wk, 'Flowshutter', 'FC Armed', 'Recording', '' - elif state == 'STOPPING': + elif state == 4: fb, header, content1, content2, content3 = self.icon_cam_wk, 'Stopping', 'FC Armed', 'Camera stop', '' else: print('Unkown state: ' + state) @@ -121,37 +87,52 @@ def display_battery(self): self.screen.text(voltage_str,44,13,1) self.screen.show() - def display_menu(self, sub_cat): - if sub_cat == 'camera_protocol': - index, head, content, fb = 1, 'Camera Protocol',''.join(tuple(self.settings['camera_protocol'])), self.icon_settings - elif sub_cat == 'device_mode': - index, head, content, fb = 2, 'Device Mode', ''.join(tuple(self.settings['device_mode'])), self.icon_settings - elif sub_cat == 'inject_mode': + def display_menu(self, sub_menu, field,field_state): + self.screen.fill(0) + if sub_menu == 0: + index, head, content, fb = 0, 'General Infomation','Land Page', self.icon_settings + elif sub_menu == 1: + index, head, content, fb = 1, 'Camera Protocol',''.join(tuple(self.settings['camera_protocol'])), self.icon_settings + elif sub_menu == 2: + index, head, content, fb = 2, 'Device Mode', ''.join(tuple(self.settings['device_mode'])), self.icon_settings + elif sub_menu == 3: index, head, content, fb = 3, 'Audio Injection',''.join(tuple(self.settings['inject_mode'])), (self.icon_audio if self.settings['inject_mode'] == "ON" else self.icon_audio_off) - elif sub_cat == 'erase_blackbox': + elif sub_menu == 4: index, head, content, fb = 4, 'Blackbox Erase', ('Erasing...' if self.erase_flag else 'Erase stop'),self.icon_blackbox - elif sub_cat == 'internet': - import mwlan - index, head, content, fb = 5, 'Internet', ''.join(tuple(mwlan.wlan_state)), (self.self.icon_wifi if mwlan.wlan_state == "CONNECTED" else self.self.icon_wifi_dis) - elif sub_cat == 'ota_source': - index, head, content, fb = 6, 'OTA Source', ''.join(tuple(self.settings['ota_source'])), (self.icon_github if self.settings['ota_source'] == "GitHub" else self.icon_gitee) - elif sub_cat == 'ota_channel': - index, head, content, fb = 7, 'OTA Channel', ''.join(tuple(self.settings['ota_channel'])), self.icon_settings - elif sub_cat == 'ota_check': - index, head, content, fb = 8, 'OTA Check', "".join(tuple(self.settings['ota_source']))+"/"+"".join(tuple(self.settings['ota_channel'])),self.icon_settings - elif sub_cat == 'ota_update': - index, head, content, fb = 9, 'OTA Update', 'ENT = START', self.icon_settings else: - print('Unknown sub_menu:', sub_cat) - self.screen.fill(0) - # self.screen.blit(fb, 95, 0) - self.a10.set_textpos(self.screen,0,int(64-self.a10.stringlen(head)/2)) + print('Unknown sub_menu:', sub_menu) + + self.screen.blit(fb, 95, 0) + self.a10.set_textpos(self.screen,0,0) self.a10.printstring(head) - # self.screen.hline(0,10,94,1) - # self.screen.text(content, 0, 14, 1) - # self.screen.text('<< '+str(index)+'/4 >>', 0, 24, 1) + self.screen.hline(0,10,94,1) + + if field == 0: + cont_color = 1 + elif field == 1: + self.screen.fill_rect(40,23,40,11,1) + self.screen.text('SAVE',0, 24, 1) + self.screen.text('LEAVE',40, 24, 0) + cont_color = 1 + elif field == 2: + self.screen.text('SAVE',0, 24, 1) + self.screen.text('LEAVE',40, 24, 1) + if field_state ==0: + self.screen.fill_rect(0,12,int(len(content)*8),11,1) + cont_color = 0 + else: + self.screen.rect(0,12,int(len(content)*8),11,1) + cont_color = 1 + elif field == 3: + self.screen.fill_rect(0,23,32,11,1) + self.screen.text('SAVE',0, 24, 0) + self.screen.text('LEAVE',40, 24, 1) + cont_color = 1 + self.screen.text(content, 0, 14, cont_color) + self.screen.text(('<< '+str(index)+'/4 >>'),0, 34, 1) self.screen.show() + def display_hint(self, sub_info): self.screen.fill(0) self.screen.fill_rect(2,1,124,30,1) @@ -165,13 +146,17 @@ def display_hint(self, sub_info): elif sub_info == 'STARTING_TIMEOUT': self.screen.text('No ACK back', 17, 6, 1) self.screen.text('Start failed', 17, 16, 1) - elif sub_info == 'AP_HINT': - self.screen.text('SSID:'+ 'Flowshutter', 3, 6, 1) - self.screen.text('Pswd:'+ 'ilovehugo', 3, 16, 1) - elif sub_info == 'WLAN_CONNECTING': - self.screen.text('Connecting', 21, 6, 1) - self.screen.text('Please wait', 21, 16, 1) elif sub_info == 'SETTINGS_FAULT': self.screen.text('Settings Fault', 26, 8, 1) self.screen.text('Please Reboot', 26, 20, 1) self.screen.show() + + def display_reboot_page(self, state): + self.screen.fill(0) + self.screen.text('Exit',0,0,1) + self.screen.text('Reboot',0,12,1) + if state == 0: + self.screen.text('<<',56,0,1) + elif state == 1: + self.screen.text('<<',56,12,1) + self.screen.show() diff --git a/src/gui/lib/common.py b/src/gui/lib/common.py new file mode 100644 index 0000000..61289ef --- /dev/null +++ b/src/gui/lib/common.py @@ -0,0 +1,53 @@ +# Flowshutter +# Copyright (C) 2021 Hugo Chiang + +# Flowshutter is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# Flowshutter is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with flowshutter. If not, see . +from gui.core.writer import Writer +from gui.fonts.icons import Icons +import gui.fonts.arial10 as a10 +import target +import time + +class Canvas_Abstract(Icons): + def __init__(self,screen): + self.settings = { + 'version': '0.66', + 'camera_protocol': 'NO', + 'device_mode': 'MASTER', + 'inject_mode': 'OFF', + 'ota_source': 'GitHub', + 'ota_channel': 'stable', + 'target_name': target.name + } + self.vol = 0 + self.erase_flag = False + self.screen = screen + self.a10 = Writer(self.screen, a10) + super().__init__() + + def update(self, gui_state): + print('canvas update called') + if gui_state['notification'] != '': + if gui_state['notification'] =='BATTERY': + self.display_battery() + else: + self.display_hint(gui_state['notification']) + elif gui_state['root_state'] == 0: + self.display_work_state(gui_state['work_state']) + elif gui_state['root_state'] == 1: + self.display_menu(gui_state['menu_page'],gui_state['field'],gui_state['field_state']) + elif gui_state['root_state'] == 2: + self.display_reboot_page(gui_state['field_state']) + else: + print(str(time.ticks_us()) + " [ Error] Unkown info: " + info) diff --git a/src/gui/logic.py b/src/gui/logic.py index 6c2faa3..97bba9d 100644 --- a/src/gui/logic.py +++ b/src/gui/logic.py @@ -15,7 +15,6 @@ # along with flowshutter. If not, see . import uasyncio as asyncio import time -import gui.core.canvas as canvas import gui.settings as settings import hal.ahal as ahal import hal.shal as shal @@ -24,28 +23,33 @@ class Logic: def __init__(self): print(str(time.ticks_us()) + " [ INIT ] UI logic object") - self.init_variables() + self.refresh = [False, False] + self.update_count = 0 + self.state = { + 'notification': '', + 'root_state': 0, + 'work_state': 0, + 'menu_page': 0, + 'field': 0, + 'field_state':0, + } + self.prev_state = self.state self.settings = settings.UserSettings() self.sync_hal = shal.SyncPeripherals() - self.canvas = canvas.init_canvas(self.sync_hal.screen) + self.init_canvas() self.async_hal = ahal.AsnycPeripherals(camera = self.settings.settings['camera_protocol']) print(str(time.ticks_us()) + " [ SYNC ] UI logic HAL") self.init_sync_hal() print(str(time.ticks_us()) + " [ ASYNC] UI logic HAL") self.init_async_hal() - def init_variables(self): - self.shutter_state = "home" - self.sub_state = "WELCOME" - self.sub_info = '' - self.update_count = 0 - self.refresh = [False, False] # native flag, flag from camera - self.prev_state = 'blank' - self.substate_index = 0 - self.substate = ['HOME', 'STARTING', 'RECORDING', 'STOPPING'] - self.submenu_index = 0 - self.submenu = ['camera_protocol', 'device_mode', 'inject_mode', 'erase_blackbox'] - # self.submenu = ['camera_protocol', 'device_mode', 'inject_mode', 'erase_blackbox', 'internet', 'ota_source', 'ota_channel', 'ota_check', 'ota_update'] + def init_canvas(self): + height = self.sync_hal.screen.height + if height == 32: + import gui.lib.canvas_128x32 as canvas + elif height == 64: + import gui.lib.canvas_128x64 as canvas + self.canvas = canvas.Canvas(self.sync_hal.screen) def init_sync_hal(self): timer0 = Timer(0) @@ -68,309 +72,306 @@ def init_async_hal(self): loop.create_task(self.async_hal.camera.uart_handler()) loop.run_forever() - def exchange_data(self): - self.sync_hal.fc_link.inject_mode = self.settings.settings['inject_mode'] - self.canvas.settings = self.settings.settings - self.async_hal.camera.oled_update_flag = False - self.canvas.vol = self.async_hal.battery.vol - - def check_camera(self): - self.sync_hal.fc_link.arm_state = self.async_hal.camera.state - self.refresh[1] = self.async_hal.camera.oled_update_flag - if self.async_hal.camera.state == True and (self.sub_state == "HOME" or self.sub_state == "STARTING"): - self.sub_state = 'RECORDING' - elif self.async_hal.camera.state == False and (self.sub_state == "RECORDING" or self.sub_state == "STOPPING"): - self.sub_state = 'HOME' - if self.async_hal.camera.notification != "": - self.sub_info = self.async_hal.camera.notification - - async def update(self): # UI tasks controller + async def update(self): print(str(time.ticks_us()) + " [ OK ] Async UI state machine") while True: - self.check_shutter_state() # check working state and assign handler - self.check_camera() - self.check_oled() # check if OLED needs update + self.collect_data() + self.check_state() + self.compare_state() + self.update_oled() await asyncio.sleep_ms(5) - def check_oled(self):# check if we need to update the OLED - if self.prev_state != self.shutter_state: - self.prev_state = self.shutter_state - self.refresh[0] = True + def update_oled(self): if self.refresh[0] or self.refresh[1]: self.refresh = [False, False] - self.exchange_data() - self.canvas.update(self.shutter_state,self.sub_state,self.submenu[self.submenu_index],self.sub_info) + self.deliver_data() + self.canvas.update(self.state) - def check_shutter_state(self): - if self.sub_info != '': - if self.sub_info == 'REBOOT': + def collect_data(self): + # read camera refresh request + self.refresh[1] = self.async_hal.camera.oled_update_flag + # read camera state and update work state + if self.async_hal.camera.state == True and (self.state['work_state'] == 1 or self.state['work_state'] == 2): + self.state['work_state'] = 3 + elif self.async_hal.camera.state == False and (self.state['work_state'] == 3 or self.state['work_state'] == 4): + self.state['work_state'] = 1 + # read camera notification + if self.async_hal.camera.notification != "": + self.state['notification'] = self.async_hal.camera.notification + # sync FC arm state with camera + self.sync_hal.fc_link.arm_state = self.async_hal.camera.state + + def deliver_data(self): + # pass settings and voltage to canvas + self.canvas.settings = self.settings.settings + self.canvas.vol = self.async_hal.battery.vol + # clear camera refresh request + self.async_hal.camera.oled_update_flag = False + # pass inject mode from settings to fc_link + self.sync_hal.fc_link.inject_mode = self.settings.settings['inject_mode'] + + def compare_state(self): + # compare_w_prev_state + if self.prev_state != self.state: + self.refresh[0] = True + self.prev_state = self.state + + def check_state(self): + # check notification field first + if self.state['notification'] != '': + notification = self.state['notification'] + if notification == 'REBOOT': self.info_reboot() - elif self.sub_info == 'BATTERY': + elif notification == 'BATTERY': self.info_battery() - elif self.sub_info == 'STARTING_TIMEOUT': + elif notification == 'STARTING_TIMEOUT': self.info_starting_timeout() - elif self.sub_info == 'SONY_MTP_ACK': + elif notification == 'SONY_MTP_ACK': self.info_sony_mtp_ack() - elif self.shutter_state == "home": - if self.sub_state == "WELCOME": - self.welcome() - elif self.sub_state == "HOME": - self.home() - elif self.sub_state == "STARTING": - self.starting() - elif self.sub_state == "RECORDING": - self.recording() - elif self.sub_state == "STOPPING": - self.stopping() - elif self.shutter_state == "menu": - if self.submenu[self.submenu_index] == "menu_root": - self.menu_root() - elif self.submenu[self.submenu_index] == "camera_protocol": - self.menu_camera_protocol() - elif self.submenu[self.submenu_index] == "device_mode": - self.menu_device_mode() - elif self.submenu[self.submenu_index] == "inject_mode": - self.menu_inject_mode() - elif self.submenu[self.submenu_index] == "erase_blackbox": - self.menu_erase_blackbox() - elif self.submenu[self.submenu_index] == "internet": - self.menu_internet() - elif self.submenu[self.submenu_index] == "ota_source": - self.menu_ota_source() - elif self.submenu[self.submenu_index] == "ota_channel": - self.menu_ota_channel() - elif self.submenu[self.submenu_index] == "ota_check": - self.menu_ota_check() else: - print('Unkown menu!' + self.submenu[self.submenu_index]) - else: - print("Unknown UI state") - - def welcome(self): - self.update_count += 5 - self.bind_btn(0, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(1, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(2, "LONG", "BLANK", 0, 0, 0) - # welcome auto switch - if self.update_count == 2500: - self.update_count = 0 - self.sub_state = "HOME" - self.refresh[0] = True - - def home(self): - self.bind_btn(0, "SHORT", "INFO", 0, 0, "BATTERY") - self.bind_btn(0, "LONG", "MENU", 0, 0, "menu") - self.bind_btn(1, "SHORT", "SHUTTER", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "INFO", 0, 0, "BATTERY") - self.bind_btn(2, "LONG", "MENU", 0, 0, "menu") - - def starting(self): - self.update_count += 5 - self.bind_btn(0, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(0, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(1, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(2, "LONG", "BLANK", 0, 0, 0) - - # starting timeout - if self.update_count < 5000: - self.async_hal.camera.rec() - elif self.update_count == 5000: - self.sub_info = "STARTING_TIMEOUT" - self.refresh[0] = True - - def recording(self): - self.update_count = 0 - self.bind_btn(0, "SHORT", "INFO", 0, 0, 0) - self.bind_btn(0, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(1, "SHORT", "SHUTTER", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "INFO",0, 0, 0) - self.bind_btn(2, "LONG", "BLANK", 0, 0, 0) - - def stopping(self): - self.update_count += 5 - self.bind_btn(0, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(0, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(1, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(2, "LONG", "BLANK", 0, 0, 0) - - # stopping timeout - if self.update_count < 5000: - self.async_hal.camera.rec() - elif self.update_count == 5000: - self.sub_info = "STARTING_TIMEOUT" - self.async_hal.camera.state = False - self.sync_hal.fc_link.state = False - self.refresh[0] = True + print('Unknown notification: ' + str(notification)) + else: # then check rest of state + self.check_rest_state() + + def check_rest_state(self): + if self.state['root_state'] == 0: # work state + + if self.state['work_state'] == 0: # welcome + self.update_count+=5 + self.bind_btn(0, 'SHORT', 'BLANK') + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'BLANK') + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'BLANK') + self.bind_btn(2, 'LONG', 'BLANK') + if self.update_count == 1500: + self.update_count = 0 + self.state['work_state'] = 1 + self.refresh[0] = True + + elif self.state['work_state'] == 1 or self.state['work_state'] == 3: #home/recording + state = self.state['work_state'] + self.bind_btn(0, 'SHORT', 'NOTIF') + self.bind_btn(0, 'LONG', ('ROOT' if state ==1 else 'BLANK')) + self.bind_btn(1, 'SHORT', 'REC' ) + self.bind_btn(1, 'LONG', 'ROOT', 'REBOOT PAGE') + self.bind_btn(2, 'SHORT', 'NOTIF') + self.bind_btn(2, 'LONG', ('ROOT' if state ==1 else 'BLANK')) + + elif self.state['work_state'] == 2 or self.state['work_state'] == 4: # starting/stopting + self.update_count += 5 + self.bind_btn(0, 'SHORT', 'BLANK') + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'BLANK') + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'BLANK') + self.bind_btn(2, 'LONG', 'BLANK') + # timeout + if self.update_count < 5000: + self.async_hal.camera.rec() + elif self.update_count == 5000: + self.state['notification'] = "STARTING_TIMEOUT" + self.refresh[0] = True + + elif self.state['root_state'] == 1: # menu state + + if self.state['menu_page'] == 0: # status info + self.bind_btn(0, 'SHORT', 'MENU', 'prv') + self.bind_btn(0, 'LONG', 'ROOT') + self.bind_btn(1, 'SHORT', 'BLANK') + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'MENU', 'nxt') + self.bind_btn(2, 'LONG', 'ROOT') + + elif ( self.state['menu_page'] == 1 or# camera_protocol + self.state['menu_page'] == 2 or# device_mode + self.state['menu_page'] == 3): # inject_mode + if self.state['field'] == 0: # hang on field + self.bind_btn(0, 'SHORT', 'MENU', 'prv') # previous page + self.bind_btn(0, 'LONG', 'ROOT') # back to home + self.bind_btn(1, 'SHORT', 'FIELD','ent') # enter the field + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'MENU', 'nxt') # next page + self.bind_btn(2, 'LONG', 'ROOT') # back to home + elif self.state['field'] == 1: # filed: leave + self.bind_btn(0, 'SHORT', 'FIELD', 'prv') # previous field + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'FIELD', 'lev') # leave the field + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'FIELD', 'nxt') # next field + self.bind_btn(2, 'LONG', 'BLANK') + elif self.state['field'] == 2: # filed: settings + if self.state['field_state'] == 0: # hang on + self.bind_btn(0, 'SHORT', 'FIELD', 'prv') # previous field + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'INFIELD','ent') # change settings and preview it + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'FIELD', 'nxt') # next field + self.bind_btn(2, 'LONG', 'BLANK') + if self.state['field_state'] == 1: # land on filed + self.bind_btn(0, 'SHORT', 'INFIELD', 'prv') # previous field + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'INFIELD', 'lev') # change settings and preview it + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'INFIELD', 'nxt') # next field + self.bind_btn(2, 'LONG', 'BLANK') + elif self.state['field'] == 3: # filed: save + self.bind_btn(0, 'SHORT', 'FIELD', 'prv') # previous field + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'SAVE') # save settings + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'FIELD', 'nxt') # next field + self.bind_btn(2, 'LONG', 'BLANK') + + elif self.state['menu_page'] == 4: # blackbox + if self.state['field'] == 0: # hang on glance + self.bind_btn(0, 'SHORT', 'MENU', 'prv') # previous page + self.bind_btn(0, 'LONG', 'ROOT') # back to home + self.bind_btn(1, 'SHORT', 'FIELD','ent') # enter the field + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'MENU', 'nxt') # next page + self.bind_btn(2, 'LONG', 'ROOT') + elif self.state['field'] == 1: # filed: leave + self.bind_btn(0, 'SHORT', 'FIELD', 'prv') # previous field + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'FIELD', 'lev') # leave the field + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'FIELD', 'nxt') # next field + self.bind_btn(2, 'LONG', 'BLANK') + elif self.state['field'] == 2: # filed: erase + self.bind_btn(0, 'SHORT', 'FIELD', 'prv') # previous field + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'FC') # erase blackbox + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'FIELD', 'nxt') # next field + self.bind_btn(2, 'LONG', 'BLANK') + + elif self.state['root_state'] == 2: # reboot state + if self.state['field_state'] == 0: + self.bind_btn(0, 'SHORT', 'INFIELD', 'ent') + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'ROOT') + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'INFIELD', 'ent') + self.bind_btn(2, 'LONG', 'BLANK') + + elif self.state['field_state'] == 1: + self.bind_btn(0, 'SHORT', 'INFIELD', 'lev') + self.bind_btn(0, 'LONG', 'BLANK') + self.bind_btn(1, 'SHORT', 'REBOOT') + self.bind_btn(1, 'LONG', 'BLANK') + self.bind_btn(2, 'SHORT', 'INFIELD', 'lev') + self.bind_btn(2, 'LONG', 'BLANK') def info_battery(self): self.update_count += 5 if self.update_count ==5000: self.update_count = 0 self.refresh[0] = True + self.bind_btn(0, "SHORT", 'NOTIF') + self.bind_btn(0, "LONG", 'BLANK') + self.bind_btn(1, "SHORT", 'BLANK') + self.bind_btn(1, "LONG", 'BLANK') + self.bind_btn(2, "SHORT", 'NOTIF') + self.bind_btn(2, "LONG", 'BLANK') - # self.bind_btn(1, "SHORT", "MENU", 0, 0, "menu_internet") - self.bind_btn(0, "SHORT", "INFO", 0, 0, 0) - self.bind_btn(0, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(1, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "INFO", 0, 0, 0) - self.bind_btn(2, "LONG", "BLANK", 0, 0, 0) - - def menu_camera_protocol(self): - self.bind_btn(0, "SHORT", "SUBMENU", 0, 0, 3) - self.bind_btn(0, "LONG", "MENU", 0, 0, "home") - self.bind_btn(1, "SHORT", "SETTING", self.settings.settings['camera_protocol'], self.settings.camera_protocol_range, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "SUBMENU", 0, 0, 1) - self.bind_btn(2, "LONG", "MENU", 0, 0, "home") - - def menu_device_mode(self): - self.bind_btn(0, "SHORT", "SUBMENU", 0, 0, 0) - self.bind_btn(0, "LONG", "MENU", 0, 0, "home") - self.bind_btn(1, "SHORT", "SETTING", self.settings.settings['device_mode'], self.settings.device_mode_range, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "SUBMENU", 0, 0, 2) - self.bind_btn(2, "LONG", "MENU", 0, 0, "home") - - def menu_inject_mode(self): - self.bind_btn(0, "SHORT", "SUBMENU", 0, 0, 1) - self.bind_btn(0, "LONG", "MENU", 0, 0, "home") - self.bind_btn(1, "SHORT", "SETTING", self.settings.settings['inject_mode'], self.settings.inject_mode_range, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "SUBMENU", 0, 0, 3) - self.bind_btn(2, "LONG", "MENU", 0, 0, "home") - - def menu_erase_blackbox(self): - self.bind_btn(0, "SHORT", "SUBMENU", 0, 0, 2) - self.bind_btn(0, "LONG", "MENU", 0, 0, "home") - self.bind_btn(1, "SHORT", "FC", 0,0,0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "SUBMENU", 0, 0, 0) - self.bind_btn(2, "LONG", "MENU", 0, 0, "home") + def info_reboot(self): + self.bind_btn(0, "SHORT", "NOTIF") + self.bind_btn(1, "SHORT", "NOTIF") + self.bind_btn(2, "SHORT", "NOTIF") def info_sony_mtp_ack(self): self.update_count += 5 - self.bind_btn(0, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(0, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(1, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(2, "LONG", "BLANK", 0, 0, 0) - - if self.update_count == 2000: + if self.update_count ==2000: self.update_count = 0 self.async_hal.camera.notification = '' - self.sub_info = '' - self.refresh[0] = True - - def info_reboot(self): - self.bind_btn(0, "SHORT", "INFO", 0, 0, 0) - self.bind_btn(0, "LONG", "INFO", 0, 0, 0) - self.bind_btn(1, "SHORT", "INFO", 0, 0, 0) - self.bind_btn(1, "LONG", "INFO", 0, 0, 0) - self.bind_btn(2, "SHORT", "INFO", 0, 0, 0) - self.bind_btn(2, "LONG", "INFO", 0, 0, 0) - - def info_starting_timeout(self): - self.update_count += 5 - self.bind_btn(0, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(0, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(1, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "BLANK", 0, 0, 0) - self.bind_btn(2, "LONG", "BLANK", 0, 0, 0) - - if self.update_count == 10000: - self.update_count = 0 - self.sub_info = '' - self.sub_state = "HOME" + self.state['notification'] = '' self.refresh[0] = True - self.async_hal.camera.timeout() - - def menu_root(self): - self.bind_btn(0, "SHORT", "SUBMENU", 0, 0, "erase_blackbox") - self.bind_btn(0, "LONG", "MENU", 0, 0, "home") - self.bind_btn(1, "SHORT", "BLANK", 0,0,0) - self.bind_btn(1, "LONG", "BLANK", 0, 0, 0) - self.bind_btn(2, "SHORT", "SUBMENU", 0, 0, "camera_protocol") - self.bind_btn(2, "LONG", "MENU", 0, 0, "home") - def bind_btn(self, button, event, dest, setting, setting_range, new_state): + def bind_btn(self, button, event, _type, keywords=None): if self.async_hal.buttons.state[button] == event: self.async_hal.buttons.state[button] = "RLS" - if dest == 'MENU': - self.shutter_state = new_state - elif dest == 'SUBMENU': - self.shutter_state = 'menu' - self.submenu_index = new_state - elif dest == 'INFO': - if self.shutter_state == 'home': - if self.sub_state == "RECORDING" or self.sub_state == 'HOME': - if self.sub_info == "": - self.sub_info = "BATTERY" - elif self.sub_info == "BATTERY": - self.sub_info = "" - elif self.shutter_state == "menu": - print('called from btn cb: INFO.menu') - self.sub_info = "" - elif dest == 'BLANK': + if _type == 'BLANK': pass - elif dest == "SETTING": - setting = self.settings.cycle('nxt',setting_range,setting) - if self.submenu_index == 0: - self.settings.settings['camera_protocol'] = setting - self.settings.update_camera_preset() - self.sub_info = 'REBOOT' - elif self.submenu_index == 1: - self.settings.settings['device_mode'] = setting - elif self.submenu_index == 2: - self.settings.settings['inject_mode'] = setting - elif self.submenu_index == 5: - self.settings.settings['ota_source'] = setting - elif self.submenu_index == 6: - self.settings.settings['ota_channel'] = setting + elif _type == 'REC': + if self.settings.settings['device_mode'] == "MASTER" or self.settings.settings['device_mode'] == "MASTER/SLAVE": + self.state['work_state'] += 1 + elif _type == 'ROOT': # change root_state + if keywords == None: + self.state['root_state'] = (1 if self.state['root_state'] == 0 else 0) + elif keywords == 'REBOOT PAGE': + self.state['root_state'] = (2 if self.state['root_state'] == 0 else 0) + elif _type == 'NOTIF': # change notification + if self.state['root_state'] == 0 and self.state['notification'] == '': + self.state['notification'] = 'BATTERY' else: - print("Hey what's this?") - self.settings.update() - elif dest == 'FC': - if self.submenu_index == 3: + self.state['notification'] = '' + elif _type == 'MENU': # change menu_page + self.settings.read() + if keywords == 'nxt': + if self.state['menu_page'] !=4: + self.state['menu_page'] += 1 + else: + self.state['menu_page'] = 0 + elif keywords == 'prv': + if self.state['menu_page'] !=0: + self.state['menu_page'] -= 1 + else: + self.state['menu_page'] = 4 + elif _type == 'FIELD': # change menu field + if keywords == 'ent': + self.state['field'] = 1 + elif keywords == 'lev': + self.settings.read() + self.state['field'] = 0 + elif keywords == 'prv': + if self.state['menu_page'] != 4: + self.state['field'] = (self.state['field']-1 if self.state['field'] != 1 else 3) + else: + self.state['field'] = (self.state['field']-1 if self.state['field'] != 1 else 2) + elif keywords == 'nxt': + if self.state['menu_page'] != 4: + self.state['field'] = (self.state['field']+1 if self.state['field'] != 3 else 1) + else: + self.state['field'] = (self.state['field']+1 if self.state['field'] != 2 else 1) + elif _type == 'INFIELD':# in field, change field_state + if keywords == 'ent': + self.state['field_state'] = 1 + elif keywords == 'lev': + self.state['field_state'] = 0 + else: # prv or nxt + if self.state['menu_page'] == 1: #camera_protocol + _range = self.settings.camera_protocol_range + argv = 'camera_protocol' + elif self.state['menu_page'] == 2: # device_mode + _range = self.settings.device_mode_range + argv = 'device_mode' + elif self.state['menu_page'] == 3: # inject_mode + _range = self.settings.inject_mode_range + argv = 'inject_mode' + setting = self.settings.cycle(keywords, _range, self.settings.settings[argv]) + self.canvas.settings[argv] = setting + self.refresh[0] = True + elif _type == 'SAVE': # save settings + self.settings.update_camera_preset() + self.settings.write() + self.state['notification'] = 'REBOOT' + elif _type == 'FC': + if self.state['menu_page'] == 4: # blackbox if self.sync_hal.fc_link.erase_flag == False: self.sync_hal.fc_link.erase_flag = True else: self.sync_hal.fc_link.erase_flag = False self.canvas.erase_flag = self.sync_hal.fc_link.erase_flag - # print('FC link flag: '+ str(self.sync_hal.fc_link.erase_flag)) - # print('Canvas flag: '+str(self.canvas.erase_flag)) - elif dest == 'SHUTTER': - if self.sub_state == "internet": - if wlan is None: - import internet.wlan as wlan - if mwlan.wlan_state == "DISCONNECTED": - wlan.up() - else: - wlan.down() - elif self.sub_state == "ota_check": - import internet.ota as ota - self.ota = ota.OTA() - self.ota.check() - elif self.sub_state == "HOME": - if self.settings.settings['device_mode'] == "MASTER" or self.settings.settings['device_mode'] == "MASTER/SLAVE": - self.sub_state = "STARTING" - elif self.settings.settings['device_mode'] == "TEST": - self.async_hal.camera.set_mode() - elif self.sub_state == "RECORDING": - if self.settings.settings['device_mode'] == "MASTER" or self.settings.settings['device_mode'] == "MASTER/SLAVE": - self.sub_state = "STOPPING" - # print('sub_info: '+str(self.sub_info)) - # print('sub_state: '+str(self.sub_state)) - # print('shutter_state: '+str(self.shutter_state)) + self.refresh[0] = True + elif _type == 'REBOOT': + import machine + machine.reset() self.refresh[0] = True + # print(str(button) + ' ' + str(event) + ' Callback!'+ ' Type is ' + str(_type) + ' ' + str(keywords)) + # print('Notif: ' + str(self.state['notification'])) + # print('root state: ' + str(self.state['root_state'])) + # print('work state: ' + str(self.state['work_state'])) + # print('menu page: ' + str(self.state['menu_page'])) + # print('field: ' + str(self.state['field'])) + # print('field state: ' + str(self.state['field_state'])) diff --git a/src/gui/settings.py b/src/gui/settings.py index 7c316e1..b1410c4 100644 --- a/src/gui/settings.py +++ b/src/gui/settings.py @@ -50,7 +50,7 @@ def read(self): self.load_json('force') print(str(time.ticks_us()) + " [ OK ] User Settings Loaded") - def update(self): + def write(self): with open("settings.json", "w") as f: json.dump(self.settings, f) f.close() @@ -63,7 +63,7 @@ def verify(self,content): if self.settings['version'] != local_settings["version"]: print(str(time.ticks_us()) + " [ ERROR] User Settings: Version changed. Overwriting default settings") f.close() - self.update() # here we should write the default settings + self.write() # here we should write the default settings print(str(time.ticks_us()) + " [ ERROR] User Settings: Default settings overwritten") else: self.settings['version'] = local_settings["version"] @@ -84,7 +84,7 @@ def verify(self,content): except ValueError: # one of the current settings is not in the valid range print("settings.json is invalid") f.close() - self.update() + self.write() print("updated settings.json") f = open("settings.json", "r") # then read again, cuz update() closed the file local_settings = json.load(f) @@ -98,7 +98,7 @@ def verify(self,content): def load_json(self,argv): if argv == 'force': - self.update() + self.write() elif argv == 'read': pass else: diff --git a/src/hal/protocols/common.py b/src/hal/protocols/common.py index bfa8b10..935e934 100644 --- a/src/hal/protocols/common.py +++ b/src/hal/protocols/common.py @@ -71,6 +71,7 @@ def _inject_(self): def send_packet(self, t): if (self.arm_state == True) & (self.inject_mode == "OFF"): + self.erase_flag = False self.uart.write(self.arm_packet) # just ARM the FC elif (self.arm_state == True) & (self.inject_mode == "ON"): diff --git a/src/sha.json b/src/sha.json index 185d2fb..525a90e 100644 --- a/src/sha.json +++ b/src/sha.json @@ -24,10 +24,6 @@ "name": "gui/core/animation.py", "sha1": "3b6115a6441de9ddf72c1e21fc06d2cf156dee06" }, - { - "name": "gui/core/canvas.py", - "sha1": "cc78e7d8c1bceae41d4dc8af66aeedb0c6f391f4" - }, { "name": "gui/core/writer.py", "sha1": "0f2c18c81181021d931dec2ce398df338e11cfec" @@ -58,19 +54,23 @@ }, { "name": "gui/lib/canvas_128x32.py", - "sha1": "8b69a5eb085bfd40fce8d27afadcfa3a65b96ff6" + "sha1": "86cb93591a98e62700774fa636b7288b9e45138d" }, { "name": "gui/lib/canvas_128x64.py", - "sha1": "8e99e6e4bdb0f67b57dd3d1651dd287dd8e1a6c9" + "sha1": "46137d1263def6b7928b6e782d97a8e365d8a8e9" + }, + { + "name": "gui/lib/common.py", + "sha1": "ad8f5d3112307c9d8eed895d733050cc52e08617" }, { "name": "gui/logic.py", - "sha1": "039b7246ec65b85a134f7bb47530e0097a54b7c4" + "sha1": "2499bebaaf9dcbc4c1888fef1effcce3122b827a" }, { "name": "gui/settings.py", - "sha1": "56181e7f1296155e438969c4c0accd89a3216a6f" + "sha1": "2f5cad11d86653f09703d2c66ed46dd3a21fb108" }, { "name": "hal/ahal.py", @@ -126,7 +126,7 @@ }, { "name": "hal/protocols/common.py", - "sha1": "781de39f59c8f1a3feb0cbfa4c23c642b5672630" + "sha1": "4f8359f0dfd59fb89200f5e1248c1ccaeccf65de" }, { "name": "hal/protocols/crsf.py",