From 7ce7b70499f0ad216713d22d3997b3c94215f50c Mon Sep 17 00:00:00 2001 From: jpunkt Date: Mon, 24 Jan 2022 20:12:59 +0100 Subject: [PATCH] implemented reset command. fixing bugs in statemachine and storyboard. --- pizzactrl/hal_serial.py | 39 ++++++++++++++++++++++++++++----- pizzactrl/main.py | 6 +++--- pizzactrl/statemachine.py | 28 ++++++++++++------------ pizzactrl/storyboard.py | 45 ++++++++++++++++++++++----------------- 4 files changed, 76 insertions(+), 42 deletions(-) diff --git a/pizzactrl/hal_serial.py b/pizzactrl/hal_serial.py index c3bf21f..86f35e9 100644 --- a/pizzactrl/hal_serial.py +++ b/pizzactrl/hal_serial.py @@ -58,6 +58,7 @@ class SerialCommands(Enum): RECORD = b'C' REWIND = b'R' + RESET = b'X' DEBUG_SCROLL = b'S' DEBUG_SENSORS = b'Z' @@ -106,6 +107,24 @@ class PizzaHAL: """ return self.lid_switch.is_pressed + @property + def helo1(self) -> bool: + """ + Returns the status of the HELO1 pin + """ + return bool(self.helo1.value) + + @helo1.setter + def helo1(self, value: bool): + self.helo1.value = 1 if value else 0 + + @property + def helo2(self) -> bool: + """ + Returns the value of the HELO2 pin (read only) + """ + return bool(self.helo2.value) + def init_connection(self): """ Set HELO1 pin to `High`, wait for HELO2 to be set `High` by microcontroller. @@ -213,6 +232,9 @@ class PizzaHAL: return resp def flush_serial(self): + """ + Clear the serial connection from unhandled responses. + """ self.serialcon.read_all() @@ -240,6 +262,13 @@ def rewind(hal: PizzaHAL, **kwargs): hal.send_cmd(SerialCommands.REWIND, ignore_lid=True) +def reset(hal: PizzaHAL, **kwargs): + """ + Prepare microcontroller for reset. + """ + hal.send_cmd(SerialCommands.RESET, ignore_lid=True) + + def turn_off(hal: PizzaHAL, **kwargs): """ Turn off the lights. @@ -303,15 +332,15 @@ def wait_for_input(hal: PizzaHAL, resp = resp[1] if resp == 1: - blue_cb(**kwargs) + blue_cb() elif resp == 2: - red_cb(**kwargs) + red_cb() elif resp == 4: - yellow_cb(**kwargs) + yellow_cb() elif resp == 8: - green_cb(**kwargs) + green_cb() elif timeout_cb is not None: - timeout_cb(**kwargs) + timeout_cb() def set_light(hal: PizzaHAL, diff --git a/pizzactrl/main.py b/pizzactrl/main.py index 583bcd2..9475ffa 100644 --- a/pizzactrl/main.py +++ b/pizzactrl/main.py @@ -1,3 +1,4 @@ +from email.policy import default import sys import click @@ -11,18 +12,17 @@ logger = logging.getLogger('pizzactrl.main') @click.command() -@click.option('--move', is_flag=True) @click.option('--test', is_flag=True, default=False) @click.option('--debug', is_flag=True, default=False) @click.option('--loop', is_flag=True, default=False) -def main(move: bool=False, test: bool=False, debug: bool=False, loop: bool=False): +def main(test: bool=False, debug: bool=False, loop: bool=False): if debug or test: logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) else: logging.basicConfig(level=logging.INFO, stream=sys.stdout) hal = PizzaHAL() - sm = Statemachine(hal, STORYBOARD, move=move, loop=loop, test=test) + sm = Statemachine(hal, STORYBOARD, loop=loop, test=test) sm.test = test diff --git a/pizzactrl/statemachine.py b/pizzactrl/statemachine.py index 15c2e4e..12ec59b 100644 --- a/pizzactrl/statemachine.py +++ b/pizzactrl/statemachine.py @@ -5,7 +5,7 @@ from enum import Enum, auto from pizzactrl import fs_names from .storyboard import Language, Storyboard -from .hal_serial import SerialCommunicationError, CommunicationError, PizzaHAL, wait_for_input, play_sound, turn_off +from .hal_serial import SerialCommunicationError, CommunicationError, PizzaHAL, wait_for_input, play_sound, turn_off, reset logger = logging.getLogger(__name__) @@ -32,7 +32,6 @@ class Statemachine: hal: PizzaHAL, story: Storyboard, default_lang=Language.NOT_SET, - move: bool = False, loop: bool = True, test: bool = False): self.hal = hal @@ -41,7 +40,7 @@ class Statemachine: self.lang = None self.story = story - self.story.MOVE = move + self.story.MOVE = True self.test = test self.loop = loop @@ -71,8 +70,7 @@ class Statemachine: State.IDLE_END: self._idle_end } - while (self.state is not State.ERROR) and \ - (self.state is not State.SHUTDOWN): + while (self.state is not State.ERROR) and (self.state is not State.SHUTDOWN): logger.debug(f'Run(state={self.state})') try: choice[self.state]() @@ -185,22 +183,24 @@ class Statemachine: turn_off(self.hal) self.story.skip_flag = False self.story.rewind() - - if self.loop: - self.state = State.IDLE_START - else: - self._next_state() - + self._next_state() + def _idle_end(self): """ - Initialize shutdown + Initialize shutdown or go back to POST if `self.loop=True` """ - self._next_state() + reset(self.hal) + self.hal.helo1 = False + + if self.loop: + self.state = State.POST + else: + self._next_state() def _shutdown(self): """ Clean up, end execution """ - self.hal.pin_helo1.off() del self.hal del self.story + diff --git a/pizzactrl/storyboard.py b/pizzactrl/storyboard.py index 7eb060e..d0ba54e 100644 --- a/pizzactrl/storyboard.py +++ b/pizzactrl/storyboard.py @@ -25,10 +25,11 @@ class Option(Enum): """ Options can be chosen by the user in WAIT_FOR_INPUT """ - CONTINUE = {'skip_flag': False} # Continue with chapter. Set `skip_flag=True` to skip all chapters marked with `skip_flag` - REPEAT = {'rewind': True} # Repeat chapter from beginning. `rewind=True`: reset scrolls to starting position - GOTO = {'chapter': 0} # Jump to chapter number - QUIT = {'quit': True} # End playback. + CONTINUE = {'skip_flag': None} # Continue with chapter. Set `skip_flag=True` to skip all chapters marked with `skip_flag` + REPEAT = {'rewind': True} # Repeat chapter from beginning. `rewind=True`: reset scrolls to starting position + GOTO = {'chapter': 0, + 'skip_flag': None} # Jump to chapter number + QUIT = {} # End playback. Will cause restart if `statemachine.loop=True` class Select: @@ -65,10 +66,10 @@ class Activity(Enum): RECORD_VIDEO = {'duration': 60.0, 'filename': ''} TAKE_PHOTO = {'filename': ''} - ADVANCE_UP = {'steps': 46, + ADVANCE_UP = {'steps': 48, 'scroll': Scrolls.VERTICAL, 'speed': 3} - ADVANCE_LEFT = {'steps': 96, + ADVANCE_LEFT = {'steps': 92, 'scroll': Scrolls.HORIZONTAL, 'speed': 3} LIGHT_FRONT = {'r': 0, @@ -211,7 +212,7 @@ class Storyboard: self.skip_flag = False # Set `True` to skip chapters marked with skip_flag - self.MOVE = False # self.move is reset to this value + self.MOVE = True # self.move is reset to this value self._move = self.MOVE self._lang = Language.NOT_SET @@ -255,39 +256,40 @@ class Storyboard: Return a callback for the appropriate option and parameters. Callbacks set the properties of `Statemachine` to determine it's behaviour. """ - # rewind = selection.values.get('rewind', Option.REPEAT.value['rewind']) - # next_chapter = selection.values.get('chapter', Option.GOTO.value['chapter']) - # shutdown = selection.values.get('shutdown', Option.QUIT.value['shutdown']) + _rewind = selection.values.get('rewind', None) + _next_chapter = selection.values.get('chapter', None) _skip_flag = selection.values.get('skip_flag', None) - if _skip_flag is not None: - self.skip_flag = _skip_flag - def _continue(**kwargs): + def _continue(): """ Continue in the Storyboard. Prepare advancing to the next chapter. """ logger.debug('User selected continue') if len(self.story) > (self._index + 1): self.next_chapter = self._index + 1 + if _skip_flag is not None: + self.skip_flag = _skip_flag else: self.next_chapter = None - def _repeat(rewind: bool=None, **kwargs): + def _repeat(): """ Repeat the current chapter. Do not rewind if the selection says so. """ logger.debug('User selected repeat') self.next_chapter = self._index - self.move = rewind + self.move = _rewind - def _goto(chapter: int=None, **kwargs): + def _goto(): """ Jump to a specified chapter. """ - logger.debug(f'User selected goto {chapter}') - self.next_chapter = chapter + logger.debug(f'User selected goto {_next_chapter}') + self.next_chapter = _next_chapter + if _skip_flag is not None: + self.skip_flag = _skip_flag - def _quit(**kwargs): + def _quit(): logger.debug('User selected quit') self.next_chapter = None @@ -346,6 +348,8 @@ class Storyboard: def _move(hal, do_now=True, **kwargs): logger.debug(f'Storyboard._move({kwargs})') + if not self.move: + return set_movement(hal, **kwargs) if do_now: do_it(hal) @@ -421,12 +425,12 @@ class Storyboard: steps = ch.rewind() h_steps += steps['h_steps'] v_steps += steps['v_steps'] - elif diff > 0: """ Skip all chapters up to target """ for ch in self.story[self._index:self._next_chapter]: + logger.debug(f'Queueing chapter {ch} for skipping') steps = ch.skip() h_steps += steps['h_steps'] v_steps += steps['v_steps'] @@ -438,6 +442,7 @@ class Storyboard: h_steps = steps['h_steps'] v_steps = steps['v_steps'] + logger.debug(f'storyboard.move={self.move} and h_steps={h_steps}, v_steps={v_steps}.') if self.move and ((h_steps != 0) or (v_steps != 0)): set_movement(self.hal, scroll=Scrolls.HORIZONTAL, steps=h_steps, speed=4) set_movement(self.hal, scroll=Scrolls.VERTICAL, steps=v_steps, speed=4)