kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
Fixes to precision mode. README improvements.
rodzic
8d3171334c
commit
696dcb68a8
112
README.md
112
README.md
|
@ -1314,10 +1314,12 @@ focus, `increase` and `decrease` buttons adjust the value. Brief presses cause
|
||||||
small changes, longer presses cause accelerating change. A long press of
|
small changes, longer presses cause accelerating change. A long press of
|
||||||
`select` invokes high precision mode.
|
`select` invokes high precision mode.
|
||||||
|
|
||||||
The callback receives an initial arg being the slider instance followed by any
|
### Callback
|
||||||
user supplied args. They can be a bound methods, typically of a `Screen`
|
|
||||||
subclass. The callback runs whenever the value changes enabling dynamic color
|
The callback receives an initial arg being the widget instance followed by any
|
||||||
change. See `gui/demos/active.py`.
|
user supplied args. The callback can be a bound method, typically of a `Screen`
|
||||||
|
subclass. The callback runs when the widget is instantiated and whenever the
|
||||||
|
value changes. This enables dynamic color change. See `gui/demos/active.py`.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
|
@ -1339,14 +1341,15 @@ The `Scale` may be `active` or `passive`. A description of the user interface
|
||||||
in the `active` case may be found in
|
in the `active` case may be found in
|
||||||
[Floating Point Widgets](./README.md#112-floating-point-widgets).
|
[Floating Point Widgets](./README.md#112-floating-point-widgets).
|
||||||
|
|
||||||
Legends for the scale are created dynamically as it scrolls past the window.
|
The scale handles floats in range `-1.0 <= V <= 1.0`, however data values may
|
||||||
The user may control this by means of a callback. The example `lscale.py` in
|
be scaled to match any given range.
|
||||||
`nano-gui` illustrates a variable with range 88.0 to 108.0, the callback
|
|
||||||
ensuring that the display legends match the user variable. A further callback
|
|
||||||
enables the scale's color to change over its length or in response to other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
The scale handles floats in range `-1.0 <= V <= 1.0`.
|
Legends for the scale are created dynamically as it scrolls past the window.
|
||||||
|
The user may control this by means of a callback. Example code may be found
|
||||||
|
[in nano-gui](https://github.com/peterhinch/micropython-nano-gui/blob/master/gui/demos/scale.py) which has a `Scale` whose value range is 88.0 to 108.0.
|
||||||
|
A callback ensures that the display legends match the user variable. A further
|
||||||
|
callback can enable the scale's color to change over its length or in response
|
||||||
|
to other circumstances.
|
||||||
|
|
||||||
Constructor mandatory positional args:
|
Constructor mandatory positional args:
|
||||||
1. `writer` The `Writer` instance (defines font) to use.
|
1. `writer` The `Writer` instance (defines font) to use.
|
||||||
|
@ -1355,26 +1358,27 @@ Constructor mandatory positional args:
|
||||||
|
|
||||||
Optional keyword only arguments:
|
Optional keyword only arguments:
|
||||||
* `ticks=200` Number of "tick" divisions on scale. Must be divisible by 2.
|
* `ticks=200` Number of "tick" divisions on scale. Must be divisible by 2.
|
||||||
* `legendcb=None` Callback for populating scale legends (see below).
|
* `value=0.0` Initial value.
|
||||||
* `tickcb=None` Callback for setting tick colors (see below).
|
* `height=0` Default is a minimum height based on the font height.
|
||||||
* `height=0` Pass 0 for a minimum height based on the font height.
|
|
||||||
* `width=100`
|
* `width=100`
|
||||||
* `fgcolor=None` Color of foreground (the control itself). If `None` the
|
* `fgcolor=None` Color of foreground (the control itself). If `None` the
|
||||||
`Writer` foreground default is used.
|
`Writer` foreground default is used.
|
||||||
* `bgcolor=None` Background color of object. If `None` the `Writer` background
|
* `bgcolor=None` Background color of object. If `None` the `Writer` background
|
||||||
default is used.
|
default is used.
|
||||||
* `bdcolor=False` Color of border. If `False` no border will be drawn. If a
|
* `bdcolor=None` Color of border, default `fgcolor`. If `False` no border will
|
||||||
color is provided, a border line will be drawn around the control.
|
be drawn. If a color is provided, a border line will be drawn around the
|
||||||
|
control.
|
||||||
* `prcolor=None` If `active`, in precision mode the white focus border changes
|
* `prcolor=None` If `active`, in precision mode the white focus border changes
|
||||||
to yellow to for a visual indication. An alternative color can be provided.
|
to yellow to for a visual indication. An alternative color can be provided.
|
||||||
`WHITE` will defeat this change.
|
`WHITE` will defeat this change.
|
||||||
* `pointercolor=None` Color of pointer. Defaults to `.fgcolor`.
|
* `pointercolor=None` Color of pointer. Defaults to `.fgcolor`.
|
||||||
* `fontcolor=None` Color of legends. Default `fgcolor`.
|
* `fontcolor=None` Color of legends. Default `fgcolor`.
|
||||||
* `callback=dolittle` Callback function which runs whenever the control's
|
* `legendcb=None` Callback for populating scale legends (see below).
|
||||||
value changes. If the control is `active` it also runs on instantiation. This
|
* `tickcb=None` Callback for setting tick colors (see below).
|
||||||
enables dynamic color changes. Default is a null function.
|
* `callback=dolittle` Callback function which runs when the user moves the
|
||||||
|
scale or the value is changed programmatically. If the control is `active` it
|
||||||
|
also runs on instantiation. Default is a null function.
|
||||||
* `args=[]` A list/tuple of arguments for above callback.
|
* `args=[]` A list/tuple of arguments for above callback.
|
||||||
* `value=0.0` Initial value.
|
|
||||||
* `active=False` By default the widget is passive. By setting `active=True`
|
* `active=False` By default the widget is passive. By setting `active=True`
|
||||||
the widget can acquire focus; its value can then be adjusted with the
|
the widget can acquire focus; its value can then be adjusted with the
|
||||||
`increase` and `decrease` buttons.
|
`increase` and `decrease` buttons.
|
||||||
|
@ -1390,12 +1394,21 @@ Methods:
|
||||||
|
|
||||||
For example code see `gui/demos/active.py`.
|
For example code see `gui/demos/active.py`.
|
||||||
|
|
||||||
|
### Control algorithm
|
||||||
|
|
||||||
If instantiated as `active`, the floating point widget behaves as per
|
If instantiated as `active`, the floating point widget behaves as per
|
||||||
[section 1.12](./README.md#112-floating-point-widgets). When the widget has
|
[section 1.12](./README.md#112-floating-point-widgets). When the widget has
|
||||||
focus, `increase` and `decrease` buttons adjust the value. Brief presses cause
|
focus, `increase` and `decrease` buttons adjust the value. Brief presses cause
|
||||||
small changes, longer presses cause accelerating change. A long press of
|
small changes, longer presses cause accelerating change. A long press of
|
||||||
`select` invokes high precision mode.
|
`select` invokes high precision mode.
|
||||||
|
|
||||||
|
### Callback
|
||||||
|
|
||||||
|
The callback receives an initial arg being the widget instance followed by any
|
||||||
|
user supplied args. The callback can be a bound method, typically of a `Screen`
|
||||||
|
subclass. The callback runs when the widget is instantiated and whenever the
|
||||||
|
value changes. This enables dynamic color change.
|
||||||
|
|
||||||
### Callback legendcb
|
### Callback legendcb
|
||||||
|
|
||||||
The display window contains 20 ticks comprising two divisions; by default a
|
The display window contains 20 ticks comprising two divisions; by default a
|
||||||
|
@ -1404,8 +1417,8 @@ whose text is defined by the `legendcb` callback. If no user callback is
|
||||||
supplied, legends will be of the form `0.3`, `0.4` etc. User code may override
|
supplied, legends will be of the form `0.3`, `0.4` etc. User code may override
|
||||||
these to cope with cases where a user variable is mapped onto the control's
|
these to cope with cases where a user variable is mapped onto the control's
|
||||||
range. The callback takes a single `float` arg which is the value of the tick
|
range. The callback takes a single `float` arg which is the value of the tick
|
||||||
(in range -1.0 <= v <= 1.0). It must return a text string. An example from the
|
(in range -1.0 <= v <= 1.0). It must return a text string. An example from
|
||||||
`lscale.py` demo shows FM radio frequencies:
|
[ths nano-gui demo](https://github.com/peterhinch/micropython-nano-gui/blob/master/gui/demos/scale.py) shows FM radio frequencies:
|
||||||
```python
|
```python
|
||||||
def legendcb(f):
|
def legendcb(f):
|
||||||
return '{:2.0f}'.format(88 + ((f + 1) / 2) * (108 - 88))
|
return '{:2.0f}'.format(88 + ((f + 1) / 2) * (108 - 88))
|
||||||
|
@ -1453,13 +1466,14 @@ from gui.widgets.scale_log import ScaleLog
|
||||||
```
|
```
|
||||||
![Image](./images/log_scale.JPG)
|
![Image](./images/log_scale.JPG)
|
||||||
|
|
||||||
This enables the input and/or display of floating point values with extremely
|
This displays floating point values with extremely wide dynamic range and
|
||||||
wide dynamic range. This is done by means of a base 10 logarithmic scale. In
|
optionally enables their input. The dynamic range is handled by means of a base
|
||||||
other respects the concept is that of the `Scale` class.
|
10 logarithmic scale. In other respects the concept is that of the `Scale`
|
||||||
|
class.
|
||||||
|
|
||||||
The control is modelled on old radios where a large scale scrolls past a small
|
The control is modelled on old radios where a large scale scrolls past a small
|
||||||
window having a fixed pointer. The use of a logarithmic scale enables the
|
window having a fixed pointer. The use of a logarithmic scale enables the
|
||||||
display and input of a value which can change by many orders of magnitude.
|
value to span a range of multiple orders of magnitude.
|
||||||
|
|
||||||
The `Scale` may be `active` or `passive`. A description of the user interface
|
The `Scale` may be `active` or `passive`. A description of the user interface
|
||||||
in the `active` case may be found in
|
in the `active` case may be found in
|
||||||
|
@ -1471,7 +1485,7 @@ decades to be traversed quickly.
|
||||||
|
|
||||||
Legends for the scale are created dynamically as it scrolls past the window,
|
Legends for the scale are created dynamically as it scrolls past the window,
|
||||||
with one legend for each decade. The user may control this by means of a
|
with one legend for each decade. The user may control this by means of a
|
||||||
callback, for example to display units, e.g. `10nF`. A further callback
|
callback, for example to display units, e.g. `10MHz`. A further callback
|
||||||
enables the scale's color to change over its length or in response to other
|
enables the scale's color to change over its length or in response to other
|
||||||
circumstances.
|
circumstances.
|
||||||
|
|
||||||
|
@ -1489,14 +1503,15 @@ Keyword only arguments (all optional):
|
||||||
* `decades=5` Defines the control's maximum value (i.e. `10**decades`).
|
* `decades=5` Defines the control's maximum value (i.e. `10**decades`).
|
||||||
* `value=1.0` Initial value for control. Will be constrained to
|
* `value=1.0` Initial value for control. Will be constrained to
|
||||||
`1.0 <= value <= 10**decades` if outside this range.
|
`1.0 <= value <= 10**decades` if outside this range.
|
||||||
* `height=0` Pass 0 for a minimum height based on the font height.
|
* `height=0` Default is a minimum height based on the font height.
|
||||||
* `width=160`
|
* `width=160`
|
||||||
* `fgcolor=None` Color of foreground (the control itself). If `None` the
|
* `fgcolor=None` Color of foreground (the control itself). If `None` the
|
||||||
`Writer` foreground default is used.
|
`Writer` foreground default is used.
|
||||||
* `bgcolor=None` Background color of object. If `None` the `Writer` background
|
* `bgcolor=None` Background color of object. If `None` the `Writer` background
|
||||||
default is used.
|
default is used.
|
||||||
* `bdcolor=False` Color of border. If `False` no border will be drawn. If a
|
* `bdcolor=None` Color of border, default `fgcolor`. If `False` no border will
|
||||||
color is provided, a border line will be drawn around the control.
|
be drawn. If a color is provided, a border line will be drawn around the
|
||||||
|
control.
|
||||||
* `prcolor=None` If `active`, in precision mode the white focus border changes
|
* `prcolor=None` If `active`, in precision mode the white focus border changes
|
||||||
to yellow to for a visual indication. An alternative color can be provided.
|
to yellow to for a visual indication. An alternative color can be provided.
|
||||||
`WHITE` will defeat this change.
|
`WHITE` will defeat this change.
|
||||||
|
@ -1504,11 +1519,11 @@ Keyword only arguments (all optional):
|
||||||
* `fontcolor=None` Color of legends. Default `WHITE`.
|
* `fontcolor=None` Color of legends. Default `WHITE`.
|
||||||
* `legendcb=None` Callback for populating scale legends (see below).
|
* `legendcb=None` Callback for populating scale legends (see below).
|
||||||
* `tickcb=None` Callback for setting tick colors (see below).
|
* `tickcb=None` Callback for setting tick colors (see below).
|
||||||
* `callback=dolittle` Callback function which will run when the user moves the
|
* `callback=dolittle` Callback function which runs when the user moves the
|
||||||
scale or the value is changed programmatically. Default is a null function.
|
scale or the value is changed programmatically. If the control is `active` it
|
||||||
|
also runs on instantiation. Default is a null function.
|
||||||
* `args=[]` A list/tuple of arguments for above callback. The callback's
|
* `args=[]` A list/tuple of arguments for above callback. The callback's
|
||||||
arguments are the `ScaleLog` instance, followed by any user supplied args.
|
arguments are the `ScaleLog` instance, followed by any user supplied args.
|
||||||
* `value=1.0` Initial value.
|
|
||||||
* `delta=0.01` This determines the smallest amount of change which can be
|
* `delta=0.01` This determines the smallest amount of change which can be
|
||||||
achieved with a brief button press. See Control Algorithm below.
|
achieved with a brief button press. See Control Algorithm below.
|
||||||
* `active=False` Determines whether the widget accepts user input.
|
* `active=False` Determines whether the widget accepts user input.
|
||||||
|
@ -1517,7 +1532,7 @@ Methods:
|
||||||
* `value=None` Set or get the current value. Always returns the current value.
|
* `value=None` Set or get the current value. Always returns the current value.
|
||||||
A passed `float` is constrained to the range `1.0 <= V <= 10**decades` and
|
A passed `float` is constrained to the range `1.0 <= V <= 10**decades` and
|
||||||
becomes the control's current value. The `ScaleLog` is updated. Always returns
|
becomes the control's current value. The `ScaleLog` is updated. Always returns
|
||||||
the control's current value. See note below on precision.
|
the control's current value.
|
||||||
* `greyed_out` Optional Boolean argument `val=None`. If `None` returns the
|
* `greyed_out` Optional Boolean argument `val=None`. If `None` returns the
|
||||||
current 'greyed out' status of the control. Otherwise enables or disables it,
|
current 'greyed out' status of the control. Otherwise enables or disables it,
|
||||||
showing it in its new state.
|
showing it in its new state.
|
||||||
|
@ -1543,10 +1558,10 @@ reduced by a factor of 10.
|
||||||
|
|
||||||
### Callback
|
### Callback
|
||||||
|
|
||||||
This receives an initial arg being the widget instance followed by any user
|
The callback receives an initial arg being the widget instance followed by any
|
||||||
supplied args. They can be bound methods, typically of a `Screen` subclass.
|
user supplied args. The callback can be a bound method, typically of a `Screen`
|
||||||
`cb_move` runs when the value changes but before the update is processed,
|
subclass. The callback runs when the widget is instantiated and whenever the
|
||||||
enabling dynamic color change.
|
value changes. This enables dynamic color change.
|
||||||
|
|
||||||
### Callback legendcb
|
### Callback legendcb
|
||||||
|
|
||||||
|
@ -1630,7 +1645,7 @@ Keyword only args:
|
||||||
foreground color will be used. If `False` is passed, no pip will be drawn. The
|
foreground color will be used. If `False` is passed, no pip will be drawn. The
|
||||||
pip is suppressed if the shortest pointer would be hard to see.
|
pip is suppressed if the shortest pointer would be hard to see.
|
||||||
|
|
||||||
Methods:
|
Method:
|
||||||
|
|
||||||
1. `text` Updates the label if present (otherwise throws a `ValueError`). Args:
|
1. `text` Updates the label if present (otherwise throws a `ValueError`). Args:
|
||||||
* `text=None` The text to display. If `None` displays last value.
|
* `text=None` The text to display. If `None` displays last value.
|
||||||
|
@ -1639,7 +1654,6 @@ Methods:
|
||||||
* `bgcolor=None` Background color, as per foreground.
|
* `bgcolor=None` Background color, as per foreground.
|
||||||
* `bdcolor=None` Border color. As per above except that if `False` is
|
* `bdcolor=None` Border color. As per above except that if `False` is
|
||||||
passed, no border is displayed. This clears a previously drawn border.
|
passed, no border is displayed. This clears a previously drawn border.
|
||||||
2. `show` No args. (Re)draws the control. Primarily for internal use by GUI.
|
|
||||||
|
|
||||||
When a `Pointer` is instantiated it is assigned to the `Dial` by the `Pointer`
|
When a `Pointer` is instantiated it is assigned to the `Dial` by the `Pointer`
|
||||||
constructor.
|
constructor.
|
||||||
|
@ -1678,7 +1692,7 @@ async def run(dial):
|
||||||
mins.value(0 + 0.9j, YELLOW)
|
mins.value(0 + 0.9j, YELLOW)
|
||||||
dm = cmath.exp(-1j * cmath.pi / 30) # Rotate by 1 minute
|
dm = cmath.exp(-1j * cmath.pi / 30) # Rotate by 1 minute
|
||||||
dh = cmath.exp(-1j * cmath.pi / 1800) # Rotate hours by 1 minute
|
dh = cmath.exp(-1j * cmath.pi / 1800) # Rotate hours by 1 minute
|
||||||
# Twiddle the hands: see aclock.py for an actual clock
|
# Twiddle the hands: see vtest.py for an actual clock
|
||||||
while True:
|
while True:
|
||||||
await asyncio.sleep_ms(200)
|
await asyncio.sleep_ms(200)
|
||||||
mins.value(mins.value() * dm, RED)
|
mins.value(mins.value() * dm, RED)
|
||||||
|
@ -1717,23 +1731,24 @@ Constructor mandatory positional args:
|
||||||
|
|
||||||
Optional keyword only arguments:
|
Optional keyword only arguments:
|
||||||
* `height=70` Dimension of the square bounding box.
|
* `height=70` Dimension of the square bounding box.
|
||||||
* `arc=TWOPI` Movement available. Default 2*PI radians (360 degrees).
|
* `arc=TWOPI` Movement available. Default 2*PI radians (360 degrees). May be
|
||||||
|
reduced, e.g. to provide a 270° range of movement.
|
||||||
* `ticks=9` Number of graduations around the dial.
|
* `ticks=9` Number of graduations around the dial.
|
||||||
|
* `value=0.0` Initial value. By default the knob will be at its most
|
||||||
|
counter-clockwise position.
|
||||||
* `fgcolor=None` Color of foreground (the control itself). If `None` the
|
* `fgcolor=None` Color of foreground (the control itself). If `None` the
|
||||||
`Writer` foreground default is used.
|
`Writer` foreground default is used.
|
||||||
* `bgcolor=None` Background color of object. If `None` the `Writer` background
|
* `bgcolor=None` Background color of object. If `None` the `Writer` background
|
||||||
default is used.
|
default is used.
|
||||||
|
* `color=None` Fill color for the control knob. Default: no fill.
|
||||||
* `bdcolor=False` Color of border. If `False` no border will be drawn. If a
|
* `bdcolor=False` Color of border. If `False` no border will be drawn. If a
|
||||||
color is provided, a border line will be drawn around the control.
|
color is provided, a border line will be drawn around the control.
|
||||||
* `prcolor=None` If `active`, in precision mode the white focus border changes
|
* `prcolor=None` If `active`, in precision mode the white focus border changes
|
||||||
to yellow to for a visual indication. An alternative color can be provided.
|
to yellow to for a visual indication. An alternative color can be provided.
|
||||||
`WHITE` will defeat this change.
|
`WHITE` will defeat this change.
|
||||||
* `color=None` Fill color for the control knob. Default: no fill.
|
|
||||||
* `callback=dolittle` Callback function runs when the user moves the knob or
|
* `callback=dolittle` Callback function runs when the user moves the knob or
|
||||||
the value is changed programmatically.
|
the value is changed programmatically.
|
||||||
* `args=[]` A list/tuple of arguments for above callback.
|
* `args=[]` A list/tuple of arguments for above callback.
|
||||||
* `value=0.0` Initial value. By default the knob will be at its most
|
|
||||||
counter-clockwise position.
|
|
||||||
* `active=True` Enable user input via the `increase` and `decrease` buttons.
|
* `active=True` Enable user input via the `increase` and `decrease` buttons.
|
||||||
|
|
||||||
Methods:
|
Methods:
|
||||||
|
@ -1744,6 +1759,13 @@ Methods:
|
||||||
correspond to the new value. The move callback will run. The method constrains
|
correspond to the new value. The move callback will run. The method constrains
|
||||||
the range to 0.0 to 1.0. Always returns the control's value.
|
the range to 0.0 to 1.0. Always returns the control's value.
|
||||||
|
|
||||||
|
### Callback
|
||||||
|
|
||||||
|
The callback receives an initial arg being the widget instance followed by any
|
||||||
|
user supplied args. The callback can be a bound method, typically of a `Screen`
|
||||||
|
subclass. The callback runs when the widget is instantiated and whenever the
|
||||||
|
value changes. This enables dynamic color change.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 22. Graph Plotting
|
# 22. Graph Plotting
|
||||||
|
|
|
@ -21,7 +21,7 @@ display = None # Singleton instance
|
||||||
ssd = None
|
ssd = None
|
||||||
|
|
||||||
gc.collect()
|
gc.collect()
|
||||||
__version__ = (0, 1, 0)
|
__version__ = (0, 1, 1)
|
||||||
|
|
||||||
# Null function
|
# Null function
|
||||||
dolittle = lambda *_ : None
|
dolittle = lambda *_ : None
|
||||||
|
@ -688,21 +688,24 @@ class Widget:
|
||||||
class LinearIO(Widget):
|
class LinearIO(Widget):
|
||||||
def __init__(self, writer, row, col, height, width,
|
def __init__(self, writer, row, col, height, width,
|
||||||
fgcolor, bgcolor, bdcolor,
|
fgcolor, bgcolor, bdcolor,
|
||||||
value=None, active=True,
|
value=None, active=True, prcolor=False,
|
||||||
min_delta=0.01, max_delta=0.1):
|
min_delta=0.01, max_delta=0.1):
|
||||||
self.min_delta = min_delta
|
self.min_delta = min_delta
|
||||||
self.max_delta = max_delta
|
self.max_delta = max_delta
|
||||||
super().__init__(writer, row, col, height, width,
|
super().__init__(writer, row, col, height, width,
|
||||||
fgcolor, bgcolor, bdcolor,
|
fgcolor, bgcolor, bdcolor,
|
||||||
value, active)
|
value, active)
|
||||||
# Handle variable precision
|
# Handle variable precision. Start normal
|
||||||
self.precision = False
|
self.precision = False
|
||||||
# 1 sec long press to set precise
|
self.do_precision = prcolor is not False
|
||||||
self.lpd = Delay_ms(self.precise, (True,))
|
if self.do_precision:
|
||||||
# Precision mode can only be entered when the active control has focus.
|
# Subclass supports precision mode
|
||||||
# In this state it will have a white border. By default this turns yellow
|
# 1 sec long press to set precise
|
||||||
# but subclass can be defeat this with None or another color
|
self.lpd = Delay_ms(self.precise, (True,))
|
||||||
self.prcolor = YELLOW
|
# Precision mode can only be entered when the active control has focus.
|
||||||
|
# In this state it will have a white border. By default this turns yellow
|
||||||
|
# but subclass can be defeat this with WHITE or another color
|
||||||
|
self.prcolor = YELLOW if prcolor is None else prcolor
|
||||||
|
|
||||||
def do_up(self, button):
|
def do_up(self, button):
|
||||||
asyncio.create_task(self.btnhan(button, 1))
|
asyncio.create_task(self.btnhan(button, 1))
|
||||||
|
@ -717,7 +720,7 @@ class LinearIO(Widget):
|
||||||
maxd = self.max_delta
|
maxd = self.max_delta
|
||||||
else:
|
else:
|
||||||
d = self.min_delta
|
d = self.min_delta
|
||||||
maxd = d * 4 # Why move fast in slow mode?
|
maxd = d * 4 # Why move fast in precision mode?
|
||||||
self.value(self.value() + up * d)
|
self.value(self.value() + up * d)
|
||||||
t = ticks_ms()
|
t = ticks_ms()
|
||||||
while not button():
|
while not button():
|
||||||
|
@ -729,17 +732,17 @@ class LinearIO(Widget):
|
||||||
|
|
||||||
def precise(self, v): # Timed out while button pressed
|
def precise(self, v): # Timed out while button pressed
|
||||||
self.precision = v
|
self.precision = v
|
||||||
if self.prcolor is not None:
|
self.draw = True
|
||||||
self.draw = True
|
|
||||||
|
|
||||||
def do_sel(self): # Select button was pushed
|
def do_sel(self): # Select button was pushed
|
||||||
if self.precision: # Already in mode
|
if self.do_precision: # Subclass handles precision mode
|
||||||
self.precise(False)
|
if self.precision: # Already in mode
|
||||||
else: # Require a long press to enter mode
|
self.precise(False)
|
||||||
self.lpd.trigger()
|
else: # Require a long press to enter mode
|
||||||
|
self.lpd.trigger()
|
||||||
|
|
||||||
def unsel(self): # Select button was released
|
def unsel(self): # Select button was released
|
||||||
self.lpd.stop()
|
self.do_precision and self.lpd.stop()
|
||||||
|
|
||||||
def leave(self): # Control has lost focus
|
def leave(self): # Control has lost focus
|
||||||
self.precise(False)
|
self.precise(False)
|
||||||
|
|
|
@ -42,13 +42,13 @@ class BaseScreen(Screen):
|
||||||
self.lbl = Label(wri, row, col, 70, bdcolor=RED)
|
self.lbl = Label(wri, row, col, 70, bdcolor=RED)
|
||||||
|
|
||||||
self.vslider = Slider(wri, 2, 2, callback=self.slider_cb,
|
self.vslider = Slider(wri, 2, 2, callback=self.slider_cb,
|
||||||
bdcolor=RED, slotcolor=BLUE, prcolor=CYAN,
|
bdcolor=RED, slotcolor=BLUE,
|
||||||
legends=('0.0', '0.5', '1.0'), value=0.5)
|
legends=('0.0', '0.5', '1.0'), value=0.5)
|
||||||
|
|
||||||
col = 80
|
col = 80
|
||||||
row = 15
|
row = 15
|
||||||
self.hslider = HorizSlider(wri, row, col, callback=self.slider_cb,
|
self.hslider = HorizSlider(wri, row, col, callback=self.slider_cb,
|
||||||
bdcolor=YELLOW, slotcolor=BLUE,
|
bdcolor=GREEN, slotcolor=BLUE,
|
||||||
legends=('0.0', '0.5', '1.0'), value=0.7)
|
legends=('0.0', '0.5', '1.0'), value=0.7)
|
||||||
row += 30
|
row += 30
|
||||||
self.scale = Scale(wri, row, col, width = 150, tickcb = tickcb,
|
self.scale = Scale(wri, row, col, width = 150, tickcb = tickcb,
|
||||||
|
@ -70,7 +70,7 @@ class BaseScreen(Screen):
|
||||||
|
|
||||||
|
|
||||||
def cb(self, obj):
|
def cb(self, obj):
|
||||||
self.lbl.value('{:4.2f}'.format(obj.value()))
|
self.lbl.value('{:5.3f}'.format(obj.value()))
|
||||||
|
|
||||||
def cbcb(self, cb):
|
def cbcb(self, cb):
|
||||||
val = cb.value()
|
val = cb.value()
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Knob(LinearIO):
|
||||||
def __init__(self, writer, row, col, *, height=70, arc=TWOPI, ticks=9, value=0.0,
|
def __init__(self, writer, row, col, *, height=70, arc=TWOPI, ticks=9, value=0.0,
|
||||||
fgcolor=None, bgcolor=None, color=None, bdcolor=None, prcolor=None,
|
fgcolor=None, bgcolor=None, color=None, bdcolor=None, prcolor=None,
|
||||||
callback=dolittle, args=[], active=True):
|
callback=dolittle, args=[], active=True):
|
||||||
super().__init__(writer, row, col, height, height, fgcolor, bgcolor, bdcolor, value, active)
|
super().__init__(writer, row, col, height, height, fgcolor, bgcolor, bdcolor, value, active, prcolor)
|
||||||
super()._set_callbacks(callback, args)
|
super()._set_callbacks(callback, args)
|
||||||
radius = height / 2
|
radius = height / 2
|
||||||
self.arc = min(max(arc, 0), TWOPI) # Usable angle of control
|
self.arc = min(max(arc, 0), TWOPI) # Usable angle of control
|
||||||
|
@ -28,10 +28,8 @@ class Knob(LinearIO):
|
||||||
self.ticks = max(ticks, 2) # start and end of travel
|
self.ticks = max(ticks, 2) # start and end of travel
|
||||||
self.color = color
|
self.color = color
|
||||||
self.draw = True # Ensure a redraw on next refresh
|
self.draw = True # Ensure a redraw on next refresh
|
||||||
if active: # Run callback (e.g. to set dynamic colors)
|
# Run callback (e.g. to set dynamic colors)
|
||||||
if prcolor is not None:
|
self.callback(self, *self.args)
|
||||||
self.prcolor = prcolor # Option for different bdcolor in precision mode
|
|
||||||
self.callback(self, *self.args)
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
if super().show(False): # Honour bgcolor
|
if super().show(False): # Honour bgcolor
|
||||||
|
|
|
@ -37,9 +37,8 @@ class Scale(LinearIO):
|
||||||
else:
|
else:
|
||||||
ctrl_ht = height - min_ht # adjust ticks for greater height
|
ctrl_ht = height - min_ht # adjust ticks for greater height
|
||||||
width &= 0xfffe # Make divisible by 2: avoid 1 pixel pointer offset
|
width &= 0xfffe # Make divisible by 2: avoid 1 pixel pointer offset
|
||||||
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, self._to_int(value), active)
|
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, self._to_int(value), active, prcolor)
|
||||||
if active:
|
super()._set_callbacks(callback, args)
|
||||||
super()._set_callbacks(callback, args)
|
|
||||||
self.minval = -1.0 # By default scales run from -1.0 to +1.0
|
self.minval = -1.0 # By default scales run from -1.0 to +1.0
|
||||||
self.fontcolor = fontcolor if fontcolor is not None else self.fgcolor
|
self.fontcolor = fontcolor if fontcolor is not None else self.fgcolor
|
||||||
self.x0 = col + 2
|
self.x0 = col + 2
|
||||||
|
@ -57,10 +56,8 @@ class Scale(LinearIO):
|
||||||
self.ldl = ctrl_ht # Large tick
|
self.ldl = ctrl_ht # Large tick
|
||||||
self.ldy0 = ycl - self.ldl // 2
|
self.ldy0 = ycl - self.ldl // 2
|
||||||
self.draw = True # Ensure a redraw on next refresh
|
self.draw = True # Ensure a redraw on next refresh
|
||||||
if active: # Run callback (e.g. to set dynamic colors)
|
# Run callback (e.g. to set dynamic colors)
|
||||||
if prcolor is not None:
|
self.callback(self, *self.args)
|
||||||
self.prcolor = prcolor # Option for different bdcolor in precision mode
|
|
||||||
self.callback(self, *self.args)
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
wri = self.writer
|
wri = self.writer
|
||||||
|
|
|
@ -48,9 +48,8 @@ class ScaleLog(LinearIO):
|
||||||
else:
|
else:
|
||||||
ctrl_ht = height - min_ht # adjust ticks for greater height
|
ctrl_ht = height - min_ht # adjust ticks for greater height
|
||||||
width &= 0xfffe # Make divisible by 2: avoid 1 pixel pointer offset
|
width &= 0xfffe # Make divisible by 2: avoid 1 pixel pointer offset
|
||||||
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, self._constrain(value), active)
|
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, self._constrain(value), active, prcolor)
|
||||||
if active:
|
super()._set_callbacks(callback, args)
|
||||||
super()._set_callbacks(callback, args)
|
|
||||||
self.fontcolor = fontcolor if fontcolor is not None else self.fgcolor
|
self.fontcolor = fontcolor if fontcolor is not None else self.fgcolor
|
||||||
|
|
||||||
self.x0 = col + 2
|
self.x0 = col + 2
|
||||||
|
@ -69,10 +68,8 @@ class ScaleLog(LinearIO):
|
||||||
self.ldy0 = ycl - self.ldl // 2
|
self.ldy0 = ycl - self.ldl // 2
|
||||||
self.dw = (self.x1 - self.x0) // 2 # Pixel width of a decade
|
self.dw = (self.x1 - self.x0) // 2 # Pixel width of a decade
|
||||||
self.draw = True # Ensure a redraw on next refresh
|
self.draw = True # Ensure a redraw on next refresh
|
||||||
if active: # Run callback (e.g. to set dynamic colors)
|
# Run callback (e.g. to set dynamic colors)
|
||||||
if prcolor is not None:
|
self.callback(self, *self.args)
|
||||||
self.prcolor = prcolor # Option for different bdcolor in precision mode
|
|
||||||
self.callback(self, *self.args)
|
|
||||||
|
|
||||||
# Pre calculated log10(x) for x in range(1, 10)
|
# Pre calculated log10(x) for x in range(1, 10)
|
||||||
def show(self, logs=(0.0, 0.3010, 0.4771, 0.6021, 0.6990, 0.7782, 0.8451, 0.9031, 0.9542)):
|
def show(self, logs=(0.0, 0.3010, 0.4771, 0.6021, 0.6990, 0.7782, 0.8451, 0.9031, 0.9542)):
|
||||||
|
|
|
@ -24,9 +24,8 @@ class Slider(LinearIO):
|
||||||
slotcolor=None, prcolor=None,
|
slotcolor=None, prcolor=None,
|
||||||
callback=dolittle, args=[], value=0.0, active=True):
|
callback=dolittle, args=[], value=0.0, active=True):
|
||||||
width &= 0xfe # ensure divisible by 2
|
width &= 0xfe # ensure divisible by 2
|
||||||
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, value, active)
|
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, value, active, prcolor)
|
||||||
if active:
|
super()._set_callbacks(callback, args)
|
||||||
super()._set_callbacks(callback, args)
|
|
||||||
self.divisions = divisions
|
self.divisions = divisions
|
||||||
self.legends = legends
|
self.legends = legends
|
||||||
self.fontcolor = self.fgcolor if fontcolor is None else fontcolor
|
self.fontcolor = self.fgcolor if fontcolor is None else fontcolor
|
||||||
|
@ -42,10 +41,8 @@ class Slider(LinearIO):
|
||||||
self.slot_y0 = row + _SLIDE_DEPTH // 2
|
self.slot_y0 = row + _SLIDE_DEPTH // 2
|
||||||
self.slot_h = height - _SLIDE_DEPTH - 1
|
self.slot_h = height - _SLIDE_DEPTH - 1
|
||||||
self.draw = True # Ensure a redraw on next refresh
|
self.draw = True # Ensure a redraw on next refresh
|
||||||
if active: # Run callback (e.g. to set dynamic colors)
|
# Run callback (e.g. to set dynamic colors)
|
||||||
if prcolor is not None:
|
self.callback(self, *self.args)
|
||||||
self.prcolor = prcolor # Option for different bdcolor in precision mode
|
|
||||||
self.callback(self, *self.args)
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
# Blank slot, ticks and slider
|
# Blank slot, ticks and slider
|
||||||
|
@ -97,9 +94,8 @@ class HorizSlider(LinearIO):
|
||||||
slotcolor=None, prcolor=None,
|
slotcolor=None, prcolor=None,
|
||||||
callback=dolittle, args=[], value=0.0, active=True):
|
callback=dolittle, args=[], value=0.0, active=True):
|
||||||
height &= 0xfe # ensure divisible by 2
|
height &= 0xfe # ensure divisible by 2
|
||||||
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, value, active)
|
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, value, active, prcolor)
|
||||||
if active:
|
super()._set_callbacks(callback, args)
|
||||||
super()._set_callbacks(callback, args)
|
|
||||||
self.divisions = divisions
|
self.divisions = divisions
|
||||||
self.legends = legends
|
self.legends = legends
|
||||||
self.fontcolor = self.fgcolor if fontcolor is None else fontcolor
|
self.fontcolor = self.fgcolor if fontcolor is None else fontcolor
|
||||||
|
@ -115,10 +111,8 @@ class HorizSlider(LinearIO):
|
||||||
centre = row + height // 2
|
centre = row + height // 2
|
||||||
self.slot_y0 = centre - _HALF_SLOT_WIDTH
|
self.slot_y0 = centre - _HALF_SLOT_WIDTH
|
||||||
self.draw = True # Ensure a redraw on next refresh
|
self.draw = True # Ensure a redraw on next refresh
|
||||||
if active: # Run callback (e.g. to set dynamic colors)
|
# Run callback (e.g. to set dynamic colors)
|
||||||
if prcolor is not None:
|
self.callback(self, *self.args)
|
||||||
self.prcolor = prcolor # Option for different bdcolor in precision mode
|
|
||||||
self.callback(self, *self.args)
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
# Blank slot, ticks and slider
|
# Blank slot, ticks and slider
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
# ili9341_pyb.py Customise for your hardware config
|
||||||
|
|
||||||
|
# Released under the MIT License (MIT). See LICENSE.
|
||||||
|
# Copyright (c) 2021 Peter Hinch
|
||||||
|
|
||||||
|
# As written, supports:
|
||||||
|
# ili9341 240x320 displays on Pyboards. On a Pyboard 1.1 frozen bytecode
|
||||||
|
# is required.
|
||||||
|
# Edit the driver import for other displays.
|
||||||
|
|
||||||
|
# Demo of initialisation procedure designed to minimise risk of memory fail
|
||||||
|
# when instantiating the frame buffer. The aim is to do this as early as
|
||||||
|
# possible before importing other modules.
|
||||||
|
|
||||||
|
# WIRING
|
||||||
|
# PB Display
|
||||||
|
# GPIO Pin
|
||||||
|
# Vin Vin
|
||||||
|
# X6 CLK Hardware SPI0
|
||||||
|
# X8 DATA (AKA SI MOSI)
|
||||||
|
# Y9 DC
|
||||||
|
# Y10 Rst
|
||||||
|
# Gnd Gnd
|
||||||
|
# Y11 CS
|
||||||
|
|
||||||
|
# Pushbuttons are wired between the pin and Gnd
|
||||||
|
# PB pin Meaning
|
||||||
|
# X1 Operate current control
|
||||||
|
# X2 Decrease value of current control
|
||||||
|
# X3 Select previous control
|
||||||
|
# X4 Select next control
|
||||||
|
# X5 Increase value of current control
|
||||||
|
|
||||||
|
from machine import Pin, SPI, freq
|
||||||
|
import gc
|
||||||
|
|
||||||
|
from drivers.ili93xx.ili9341 import ILI9341 as SSD
|
||||||
|
# Create and export an SSD instance
|
||||||
|
pdc = Pin('Y9', Pin.OUT, value=0) # Arbitrary pins
|
||||||
|
prst = Pin('Y10', Pin.OUT, value=1)
|
||||||
|
pcs = Pin('Y11', Pin.OUT, value=1)
|
||||||
|
spi = SPI(1, baudrate=30_000_000)
|
||||||
|
gc.collect() # Precaution before instantiating framebuf
|
||||||
|
ssd = SSD(spi, pcs, pdc, prst, usd=True)
|
||||||
|
|
||||||
|
from gui.core.ugui import Display
|
||||||
|
# Create and export a Display instance
|
||||||
|
# Define control buttons
|
||||||
|
nxt = Pin('X4', Pin.IN, Pin.PULL_UP) # Move to next control
|
||||||
|
sel = Pin('X1', Pin.IN, Pin.PULL_UP) # Operate current control
|
||||||
|
prev = Pin('X3', Pin.IN, Pin.PULL_UP) # Move to previous control
|
||||||
|
increase = Pin('X5', Pin.IN, Pin.PULL_UP) # Increase control's value
|
||||||
|
decrease = Pin('X2', Pin.IN, Pin.PULL_UP) # Decrease control's value
|
||||||
|
display = Display(ssd, nxt, sel, prev, increase, decrease)
|
Ładowanie…
Reference in New Issue