Skip to content

Commit

Permalink
Version 0.4.1 (#7)
Browse files Browse the repository at this point in the history
* power is 4 tuple

* no standard library

* add warning screen
  • Loading branch information
DamTobor committed May 31, 2024
1 parent a2ab529 commit a1b11fb
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 53 deletions.
116 changes: 64 additions & 52 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import asyncio
from typing import Iterator, List, Optional, Tuple
from itertools import chain

from logging import WARN, WARNING
import app
from enum import Enum

from app_components.tokens import label_font_size
from events.input import Buttons, BUTTON_TYPES

# Motor Driver
PWM_FREQ = 5000
MAX_DUTY = 1023

VERTICAL_OFFSET = label_font_size
H_START = -78
V_START = -58
Expand All @@ -20,26 +20,20 @@

MAX_POWER = 100

class BadgeBotAppState(Enum):
MENU = 1
RECEIVE_INSTR = 2
COUNTDOWN = 3
RUN = 4
DONE = 5
# App states
WARNING = 0
MENU = 1
RECEIVE_INSTR = 2
COUNTDOWN = 3
RUN = 4
DONE = 5

class Instruction:

# tick
# Each tick update pwm
# target speed
# current speed
# Trapezium, estimate 200ms

def __init__(self, press_type: BUTTON_TYPES) -> None:
self._press_type = press_type
self._duration = 1

self.current_power_duration = (0, 0)
self.power_plan_iterator = iter([])

@property
Expand All @@ -52,13 +46,23 @@ def inc(self):
def __str__(self):
return f"{self.press_type.name} {self._duration}"


def make_power_plan(self) -> Iterator[Tuple[int, int]]:
# return collection of tuples of durations at each power
ramp_up = [(i, TICK_MS) for i in range(0, MAX_POWER, POWER_STEP_PER_TICK)]
def directional_power_tuple(self, power):
if self._press_type == BUTTON_TYPES["UP"]:
return (power, 0, power, 0)
elif self._press_type == BUTTON_TYPES["DOWN"]:
return (0, power, 0, power)
elif self._press_type == BUTTON_TYPES["LEFT"]:
return (power, 0, 0, power)
elif self._press_type == BUTTON_TYPES["RIGHT"]:
return (0, power, power, 0)

def make_power_plan(self):
# return collection of tuples of power and their duration
ramp_up = [(self.directional_power_tuple(p), TICK_MS)
for p in range(0, MAX_POWER, POWER_STEP_PER_TICK)]
power_durations = ramp_up.copy()
user_power_duration = TICK_MS * USER_TICK_MULTIPLIER * (self._duration-1)
power_durations.append((MAX_POWER, user_power_duration))
power_durations.append((self.directional_power_tuple(MAX_POWER), user_power_duration))
ramp_down = ramp_up.copy()
ramp_down.reverse()
power_durations.extend(ramp_down)
Expand All @@ -71,8 +75,6 @@ def __init__(self):
self.last_press: BUTTON_TYPES = BUTTON_TYPES["CANCEL"]
self.long_press_delta = 0

self.power = 0

self.is_scroll = False
self.scroll_offset = 0

Expand All @@ -82,11 +84,11 @@ def __init__(self):
self.instructions = []
self.current_instruction = None

self.current_power_duration = (0, 0)
self.current_power_duration = ((0,0,0,0), 0)
self.power_plan_iter = iter([])

# Overall app state
self.current_state = BadgeBotAppState.MENU
self.current_state = WARNING

def update(self, delta):
if self.button_states.get(BUTTON_TYPES["CANCEL"]):
Expand All @@ -96,14 +98,19 @@ def update(self, delta):
self.button_states.clear()
self.minimise()

if self.current_state == BadgeBotAppState.MENU:
if self.current_state == MENU:
# Exit start menu
if self.button_states.get(BUTTON_TYPES["CONFIRM"]):
self.current_state = BadgeBotAppState.RECEIVE_INSTR
self.current_state = RECEIVE_INSTR
self.button_states.clear()

elif self.current_state == WARNING:
# Exit warning screen
if self.button_states.get(BUTTON_TYPES["CONFIRM"]):
self.current_state = MENU
self.button_states.clear()

elif self.current_state == BadgeBotAppState.RECEIVE_INSTR:
elif self.current_state == RECEIVE_INSTR:
# Enable/disable scrolling and check for long press
if self.button_states.get(BUTTON_TYPES["CONFIRM"]):

Expand All @@ -113,7 +120,7 @@ def update(self, delta):
self.long_press_delta += delta
if self.long_press_delta >= LONG_PRESS_MS:
self.finalize_instruction()
self.current_state = BadgeBotAppState.COUNTDOWN
self.current_state = COUNTDOWN

else:
# Confirm is not pressed. Reset long_press state
Expand Down Expand Up @@ -141,19 +148,20 @@ def update(self, delta):
self._handle_instruction_press(BUTTON_TYPES["DOWN"])
self.button_states.clear()

elif self.current_state == BadgeBotAppState.COUNTDOWN:
elif self.current_state == COUNTDOWN:
self.run_countdown_ms += delta
if self.run_countdown_ms >= self.run_countdown_target_ms:
self.power_plan_iter = chain(*(instr.power_plan_iterator for instr in self.instructions))
self.current_state = BadgeBotAppState.RUN
self.power_plan_iter = self.instructions[0].power_plan_iterator # TODO chain all instr
self.current_state = RUN

elif self.current_state == BadgeBotAppState.RUN:
self.power = self.get_current_power_level(delta)
print(f"Using power: {self.power}")
if self.power is None:
self.current_state = BadgeBotAppState.DONE
elif self.current_state == RUN:
print(delta)
power = self.get_current_power_level(delta)
if power is None:
self.current_state = DONE
print(f"Using power: {power}")

elif self.current_state == BadgeBotAppState.DONE:
elif self.current_state == DONE:
if self.button_states.get(BUTTON_TYPES["CONFIRM"]):
self.reset()

Expand All @@ -166,13 +174,11 @@ def _handle_instruction_press(self, press_type: BUTTON_TYPES):
self.last_press = press_type

def reset(self):
self.current_state = BadgeBotAppState.MENU
self.current_state = MENU
self.button_states.clear()
self.last_press: BUTTON_TYPES = BUTTON_TYPES["CANCEL"]
self.long_press_delta = 0

self.power = 0

self.is_scroll = False
self.scroll_offset = 0

Expand All @@ -182,7 +188,7 @@ def reset(self):
self.instructions = []
self.current_instruction = None

self.current_power_duration = (0, 0)
self.current_power_duration = ((0,0,0,0), 0)
self.power_plan_iter = iter([])


Expand All @@ -195,29 +201,35 @@ def draw(self, ctx):
else:
ctx.rgb(0,0,0.1).rectangle(-120,-120,240,240).fill()

if self.current_state == BadgeBotAppState.MENU:
if self.current_state == WARNING:
ctx.rgb(1,1,1).move_to(H_START, V_START + 0*VERTICAL_OFFSET + 20).text("Please buy")
ctx.rgb(1,1,1).move_to(H_START, V_START + 1*VERTICAL_OFFSET + 20).text("BadgeBot")
ctx.rgb(1,1,0).move_to(H_START, V_START + 2*VERTICAL_OFFSET + 20).text("Hexpansion")
ctx.rgb(1,1,0).move_to(H_START, V_START + 3*VERTICAL_OFFSET + 20).text("from")
ctx.rgb(1,1,0).move_to(H_START, V_START + 4*VERTICAL_OFFSET + 20).text("RobotMad")
elif self.current_state == MENU:
ctx.rgb(1,1,1).move_to(H_START, V_START).text("To Program:")
ctx.rgb(1,1,0).move_to(H_START, V_START + VERTICAL_OFFSET).text("Press C")
ctx.rgb(1,1,1).move_to(H_START, V_START + 2*VERTICAL_OFFSET + 10).text("When finished:")
ctx.rgb(1,1,0).move_to(H_START, V_START + 3*VERTICAL_OFFSET + 10).text("Long press C")
elif self.current_state == BadgeBotAppState.RECEIVE_INSTR:
elif self.current_state == RECEIVE_INSTR:
for i_num, instr in enumerate(["START"] + self.instructions + [self.current_instruction, "END"]):
ctx.rgb(1,1,0).move_to(H_START, V_START + VERTICAL_OFFSET * (self.scroll_offset + i_num)).text(str(instr))
elif self.current_state == BadgeBotAppState.COUNTDOWN:
elif self.current_state == COUNTDOWN:
ctx.rgb(1,1,1).move_to(H_START, V_START).text("Running in:")
countdown_val = (self.run_countdown_target_ms - self.run_countdown_ms) / 1000
ctx.rgb(1,1,0).move_to(H_START, V_START+VERTICAL_OFFSET).text(countdown_val)
elif self.current_state == BadgeBotAppState.RUN:
ctx.rgb(1,0,0).move_to(H_START, V_START).text("Running power")
ctx.rgb(0,0,1).move_to(H_START, V_START + VERTICAL_OFFSET).text(str(self.power))
elif self.current_state == BadgeBotAppState.DONE:
elif self.current_state == RUN:
ctx.rgb(1,1,1).move_to(H_START, V_START).text("Running power")
ctx.rgb(1,0,0).move_to(H_START, V_START + 2*VERTICAL_OFFSET).text(str(self.current_power_duration))
elif self.current_state == DONE:
ctx.rgb(1,1,1).move_to(H_START, V_START).text(f"Complete!")
ctx.rgb(1,1,1).move_to(H_START, V_START + VERTICAL_OFFSET).text("To restart:")
ctx.rgb(1,1,0).move_to(H_START, V_START + 2*VERTICAL_OFFSET).text("Press C")
ctx.restore()


def get_current_power_level(self, delta) -> Optional[int]:
def get_current_power_level(self, delta) -> int:
# takes in delta as ms since last call
# if delta was > 20... what to do
if delta >= TICK_MS:
Expand Down
2 changes: 1 addition & 1 deletion tildagon.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ description = "A demo tildagon app for use with Hex Drive hexpansion "
# increased, we interpret this as a new version being released.
#
# Version number must be an integer!
version = "0.4.0"
version = "0.4.1"

0 comments on commit a1b11fb

Please sign in to comment.