Skip to content

Commit

Permalink
Merge pull request #2 from HLammers/v0.2.0
Browse files Browse the repository at this point in the history
V0.2.0
  • Loading branch information
HLammers authored Nov 16, 2024
2 parents 31cc6c5 + e0de801 commit cef8c06
Show file tree
Hide file tree
Showing 11 changed files with 336 additions and 361 deletions.
48 changes: 28 additions & 20 deletions README.md

Large diffs are not rendered by default.

41 changes: 19 additions & 22 deletions src/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,62 +26,58 @@
_IRQ_RISING_FALLING = Pin.IRQ_RISING | Pin.IRQ_FALLING

_DEBOUNCE_DELAY = const(50) # ms
_KEPT_PRESSED_DELAY = const(200) # ms
_LONG_PRESS_DELAY = const(200) # ms

_IRQ_LAST_STATE = const(0)
_IRQ_IDLE_STATE = const(1)
_IRQ_LAST_TIME = const(2)
_IRQ_AVAILABLE = const(3)
_IRQ_ONE_BUT_LAST_TIME = const(3)
_IRQ_AVAILABLE = const(4)

_BUTTON_EVENT_RELEASED = const(0)
_BUTTON_EVENT_PRESSED = const(1)
_BUTTON_EVENT_KEPT = const(2)
_BUTTON_EVENT_PRESS = const(0)
_BUTTON_EVENT_LONG_PRESS = const(1)

class Button():
'''button handling class; initiated by ui.__init__'''

def __init__(self, pin_number: int, pull_up: bool = False, trigger_kept_pressed: bool = False) -> None:
def __init__(self, pin_number: int, pull_up: bool = False, long_press: bool = False) -> None:
self.pin_number = pin_number
self.trigger_kept_pressed = trigger_kept_pressed
self.irq_data = array('l', [_NONE, _NONE, 0, 0])
self.long_press = long_press
self.irq_data = array('l', [_NONE, _NONE, 0, _NONE, 0])
self.irq_data[_IRQ_IDLE_STATE] = int(pull_up)
_pin = Pin
pull_direction = _pin.PULL_UP if pull_up else _pin.PULL_DOWN
_pin = _pin(pin_number, _pin.IN, pull_direction)
self.pin = _pin
self.last_pressed_time = _NONE
_pin.irq(self._callback, _IRQ_RISING_FALLING)

def close(self) -> None:
self.pin.irq(handler=None)

@micropython.viper
def value(self) -> int:
'''return 1 if triggered and trigger_kept_pressed == False, 1 if short pressed and trigger_kept_pressed == True, 2 if
kept pressed and trigger_kept_pressed == True, 0 if released and trigger_kept_ressed == True or _NONE if no new data is
available (yet); called by ui.process_user_input'''
'''if long_press == False: return _BUTTON_EVENT_PRESS if pressed; if long_press == True: return _BUTTON_EVENT_PRESS if pressed
shorter then _LONG_PRESS_DELAY milliseconds or return _BUTTON_EVENT_LONG_PRESS if pressed longer (if kept pressed the trigger
happens after _LONG_PRESS_DELAY milliseconds); called by ui.process_user_input'''
irq_data = ptr32(self.irq_data) # type: ignore
if not irq_data[_IRQ_AVAILABLE]:
return _NONE
now = int(time.ticks_ms())
if int(time.ticks_diff(now, irq_data[_IRQ_LAST_TIME])) < _DEBOUNCE_DELAY:
return _NONE
pressed = irq_data[_IRQ_LAST_STATE] != irq_data[_IRQ_IDLE_STATE]
if bool(self.trigger_kept_pressed):
if bool(self.long_press):
if pressed:
if int(self.last_pressed_time) == _NONE:
self.last_pressed_time = irq_data[_IRQ_LAST_TIME]
difference = int(time.ticks_diff(now, int(self.last_pressed_time)))
if difference < _KEPT_PRESSED_DELAY:
difference = int(time.ticks_diff(now, irq_data[_IRQ_LAST_TIME]))
if difference < _LONG_PRESS_DELAY:
return _NONE
irq_data[_IRQ_AVAILABLE] = 0
return _BUTTON_EVENT_KEPT
difference = int(time.ticks_diff(irq_data[_IRQ_LAST_TIME], int(self.last_pressed_time)))
self.last_pressed_time = _NONE
return _BUTTON_EVENT_LONG_PRESS
difference = int(time.ticks_diff(irq_data[_IRQ_LAST_TIME], irq_data[_IRQ_ONE_BUT_LAST_TIME]))
irq_data[_IRQ_AVAILABLE] = 0
return _BUTTON_EVENT_PRESSED if difference < _KEPT_PRESSED_DELAY else _BUTTON_EVENT_RELEASED
return _BUTTON_EVENT_PRESS if difference < _LONG_PRESS_DELAY else _NONE
irq_data[_IRQ_AVAILABLE] = 0
return _BUTTON_EVENT_PRESSED if pressed else _NONE
return _BUTTON_EVENT_PRESS if pressed else _NONE

@micropython.viper
def _callback(self, pin):
Expand All @@ -92,4 +88,5 @@ def _callback(self, pin):
return
irq_data[_IRQ_LAST_STATE] = state
irq_data[_IRQ_AVAILABLE] = 1
irq_data[_IRQ_ONE_BUT_LAST_TIME] = irq_data[_IRQ_LAST_TIME]
irq_data[_IRQ_LAST_TIME] = int(time.ticks_ms())
4 changes: 2 additions & 2 deletions src/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def load_program_json_file(self, id: int) -> dict|None:

def save_data_json_file(self, file: str = 'data.json') -> None:
'''save data set (self.data) to json file; called by self.save_back_up, router._save, router._save_program, Page*._save_*_settings
or Page*.process_user_input and Page*.midi_learn'''
and Page*.process_user_input'''
data_file = open(f'/data_files/{file}', 'w')
json.dump(self.data, data_file)
data_file.close()
Expand Down Expand Up @@ -177,7 +177,7 @@ def load(self) -> None:
self.settings = self.data['settings']
self.programs_tuple = tuple((program[0] for program in programs))

###### this might not be necessary if the set-up is changed to ID-based data mapping
###### this might not be necessary if the set-up is changed to ID-based data mapping
def change_in_programs(self, field: str, old_value: str, new_value: str, condition_field: str = '', condition_value: str = '') -> None:
'''change an old value into a new value for a given field in all program data files; called by router.rename_device and
router.rename_preset'''
Expand Down
8 changes: 0 additions & 8 deletions src/main_loops.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,12 @@ def main():
monitor data'''
_ticks_diff = time.ticks_diff
_ticks_ms = time.ticks_ms
######
# _get_encoder_input = ui._get_encoder_input
_process_encoder_input = ui.process_encoder_input
_read_midi_learn_data = router.read_midi_learn_data
_process_midi_learn_data = ui.process_midi_learn_data
_process_user_input = ui.process_user_input
_process_monitor = ui.process_monitor
_process_program_change_break = router.process_program_change_break
######
# previous_encoder_input = (None, None)
previous_midi_learn_data = None
main_loop_time = time.ticks_ms()
while True:
Expand All @@ -87,10 +83,6 @@ def main():
# turn display off after prolonged inactivity
ui.check_sleep_time_out()
# process encoders
######
# encoder_input = _get_encoder_input()
# if encoder_input != (None, None):
# _process_encoder_input(encoder_input)
_process_encoder_input()
# process buttons and other input
_process_user_input()
Expand Down
6 changes: 4 additions & 2 deletions src/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ def update(self, reload_input_devices: bool = True, reload_output_devices: bool
reload_output_triggers: bool = True, reload_input_presets: bool = True, reload_output_presets: bool = True,
program_number: int = _NONE, already_waiting: bool = False) -> None:
'''reload data and call ui.program_change to triggers redraw; called by main_loops.py: init, self._save, self._save_program,
Page*.process_user_input, Page*.midi_learn, Page*._save_*_settings, Page*._callback_menu, Page*._callback_select'''
ui._callback_confirm, ui._callback_select, Page*.process_user_input, Page*._save_*_settings, Page*._callback_menu,
Page*._callback_select'''
if not already_waiting:
# request second thread to wait (handshake)
with self.thread_lock:
Expand Down Expand Up @@ -416,7 +417,8 @@ def trigger(self) -> None:
self.ui_trigger = key_int

def save_active_program(self, replace: bool) -> None:
'''save active program changes, either replacing or as a new program after the original; called by PageProgram._callback_confirm'''
'''save active program changes, either replacing or as a new program after the original; called by ui._callback_confirm and
PageProgram._callback_confirm'''
# request second thread to wait (handshake)
with self.thread_lock:
self.request_wait = True
Expand Down
Loading

0 comments on commit cef8c06

Please sign in to comment.