kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
Some doc for encoder mode. Remove unwanted code/comments from demos.
rodzic
b8d8bdb0a3
commit
3a64bb5691
17
README.md
17
README.md
|
@ -19,6 +19,9 @@ to a wide range of displays. It is also portable between hosts.
|
|||
![Image](./images/ttgo.JPG) TTGO T-Display. Add a joystick switch and an SIL
|
||||
resistor for a simple, inexpensive, WiFi capable system.
|
||||
|
||||
An alternative interface consists of two pushbuttons and an encoder such as
|
||||
[this one](https://www.adafruit.com/product/377).
|
||||
|
||||
# Rationale
|
||||
|
||||
Touch GUI's have many advantages, however they have drawbacks, principally cost
|
||||
|
@ -115,7 +118,7 @@ of some display drivers.
|
|||
22.3.1 [Class Curve](./README.md#2231-class-curve)
|
||||
22.3.2 [Class PolarCurve](./README.md#2232-class-polarcurve)
|
||||
22.4 [Class TSequence](./README.md#224-class-tsequence) Plotting realtime, time sequential data.
|
||||
[Appendix 1 Application design](./README.md#appendix-1-application-design) Tab order, button layout, use of graphics primitives
|
||||
[Appendix 1 Application design](./README.md#appendix-1-application-design) Tab order, button layout, encoder interface, use of graphics primitives
|
||||
|
||||
# 1. Basic concepts
|
||||
|
||||
|
@ -385,6 +388,8 @@ files in `gui/core` are:
|
|||
The `gui/primitives` directory contains the following files:
|
||||
* `switch.py` Interface to physical pushbuttons.
|
||||
* `delay_ms.py` A software triggerable timer.
|
||||
* `encoder.py` Driver for a quadrature encoder. This offers an alternative
|
||||
interface - see [Appendix 1](./README.md#appendix-1-application-design).
|
||||
|
||||
The `gui/demos` directory contains a variety of demos and tests described
|
||||
below.
|
||||
|
@ -2202,6 +2207,16 @@ The apparently obvious solution of designing a vertical `Scale` is tricky owing
|
|||
to the fact that the length of the internal text can be substantial and
|
||||
variable.
|
||||
|
||||
## Encoder interface
|
||||
|
||||
This alternative interface comprises just two buttons `Next` and `Prev`.
|
||||
Selection and Increase/Decrease is handled by an encoder such as
|
||||
[this one](https://www.adafruit.com/product/377). Selection occurs when the
|
||||
knob is pressed, and movement when it is rotated. This is more intuitive,
|
||||
particularly with horizontally oriented controls.
|
||||
|
||||
TODO wiring details.
|
||||
|
||||
## Screen layout
|
||||
|
||||
Widgets are positioned using absolute `row` and `col` coordinates. These may
|
||||
|
|
101
gui/core/ugui.py
101
gui/core/ugui.py
|
@ -38,15 +38,15 @@ _LAST = const(3)
|
|||
# Wrapper for ssd providing buttons and framebuf compatible methods
|
||||
class Display:
|
||||
|
||||
def __init__(self, objssd, nxt, sel, prev=None, up=None, down=None):
|
||||
def __init__(self, objssd, nxt, sel, prev=None, up=None, down=None, encoder=False):
|
||||
global display, ssd
|
||||
self._next = Switch(nxt)
|
||||
self._sel = Switch(sel)
|
||||
self._last = None # Last switch pressed.
|
||||
# Mandatory buttons
|
||||
# Call current screen bound method
|
||||
self._next.close_func(self._closure, (self._next, Screen.next_ctrl))
|
||||
self._sel.close_func(self._closure, (self._sel, Screen.sel_ctrl))
|
||||
self._next.close_func(self._closure, (self._next, Screen.ctrl_move, _NEXT))
|
||||
self._sel.close_func(self._closure, (self._sel, Screen.sel_ctrl, 0))
|
||||
self._sel.open_func(Screen.unsel)
|
||||
|
||||
self.height = objssd.height
|
||||
|
@ -56,26 +56,30 @@ class Display:
|
|||
self._prev = None
|
||||
if prev is not None:
|
||||
self._prev = Switch(prev)
|
||||
self._prev.close_func(self._closure, (self._prev, Screen.prev_ctrl))
|
||||
# Up and down methods get the button as an arg.
|
||||
self._up = None
|
||||
if up is not None:
|
||||
self._up = Switch(up)
|
||||
self._up.close_func(self._closure, (self._up, self.do_up))
|
||||
self._down = None
|
||||
if down is not None:
|
||||
self._down = Switch(down)
|
||||
self._down.close_func(self._closure, (self._down, self.do_down))
|
||||
self._prev.close_func(self._closure, (self._prev, Screen.ctrl_move, _PREV))
|
||||
if encoder:
|
||||
if up is None or down is None:
|
||||
raise ValueError('Must specify pins for encoder.')
|
||||
from gui.primitives.encoder import Encoder
|
||||
self._enc = Encoder(up, down, div=encoder, callback=Screen.adjust)
|
||||
else:
|
||||
# Up and down methods get the button as an arg.
|
||||
if up is not None:
|
||||
sup = Switch(up)
|
||||
sup.close_func(self._closure, (sup, Screen.adjust, 1))
|
||||
if down is not None:
|
||||
sdown = Switch(down)
|
||||
sdown.close_func(self._closure, (sdown, Screen.adjust, -1))
|
||||
self._is_grey = False # Not greyed-out
|
||||
display = self # Populate globals
|
||||
ssd = objssd
|
||||
|
||||
# Reject button presses where a button is already pressed.
|
||||
# Execute if initialising, if same switch re-pressed or if last switch released
|
||||
def _closure(self, switch, func):
|
||||
def _closure(self, switch, func, arg):
|
||||
if (self._last is None) or (self._last == switch) or self._last():
|
||||
self._last = switch
|
||||
func()
|
||||
func(switch, arg)
|
||||
|
||||
def print_centred(self, writer, x, y, text, fgcolor=None, bgcolor=None, invert=False):
|
||||
sl = writer.stringlen(text)
|
||||
|
@ -94,12 +98,6 @@ class Display:
|
|||
writer.printstring(txt, invert)
|
||||
writer.setcolor() # Restore defaults
|
||||
|
||||
def do_up(self):
|
||||
Screen.up_ctrl(self._up)
|
||||
|
||||
def do_down(self):
|
||||
Screen.down_ctrl(self._down)
|
||||
|
||||
# Greying out has only one option given limitation of 4-bit display driver
|
||||
# It would be possible to do better with RGB565 but would need inverse transformation
|
||||
# to (r, g, b), scale and re-convert to integer.
|
||||
|
@ -204,35 +202,27 @@ class Screen:
|
|||
is_shutdown = Event()
|
||||
|
||||
@classmethod
|
||||
def next_ctrl(cls):
|
||||
def ctrl_move(cls, _, v):
|
||||
if cls.current_screen is not None:
|
||||
cls.current_screen.move(_NEXT)
|
||||
cls.current_screen.move(v)
|
||||
|
||||
@classmethod
|
||||
def prev_ctrl(cls):
|
||||
if cls.current_screen is not None:
|
||||
cls.current_screen.move(_PREV)
|
||||
|
||||
@classmethod
|
||||
def sel_ctrl(cls):
|
||||
def sel_ctrl(cls, b, _):
|
||||
if cls.current_screen is not None:
|
||||
cls.current_screen.do_sel()
|
||||
|
||||
|
||||
@classmethod
|
||||
def unsel(cls):
|
||||
if cls.current_screen is not None:
|
||||
cls.current_screen.unsel_i()
|
||||
|
||||
# Adjust the value of a widget. If an encoder is used, button arg
|
||||
# is an int (discarded), val is the delta. If using buttons, 1st
|
||||
# arg is the button, delta is +1 or -1
|
||||
@classmethod
|
||||
def up_ctrl(cls, button):
|
||||
def adjust(cls, button, val):
|
||||
if cls.current_screen is not None:
|
||||
cls.current_screen.do_up(button)
|
||||
|
||||
@classmethod
|
||||
def down_ctrl(cls, button):
|
||||
if cls.current_screen is not None:
|
||||
cls.current_screen.do_down(button)
|
||||
cls.current_screen.do_adj(button, val)
|
||||
|
||||
# Move currency to a specific widget (e.g. ButtonList)
|
||||
@classmethod
|
||||
|
@ -440,19 +430,12 @@ class Screen:
|
|||
if co is not None:
|
||||
co.unsel()
|
||||
|
||||
def do_up(self, button):
|
||||
def do_adj(self, button, val):
|
||||
co = self.get_obj()
|
||||
if co is not None and hasattr(co, 'do_up'):
|
||||
co.do_up(button) # Widget handles up/down
|
||||
if co is not None and hasattr(co, 'do_adj'):
|
||||
co.do_adj(button, val) # Widget can handle up/down
|
||||
else:
|
||||
Screen.current_screen.move(_FIRST)
|
||||
|
||||
def do_down(self, button):
|
||||
co = self.get_obj()
|
||||
if co is not None and hasattr(co, 'do_down'):
|
||||
co.do_down(button)
|
||||
else:
|
||||
Screen.current_screen.move(_LAST)
|
||||
Screen.current_screen.move(_FIRST if val < 0 else _LAST)
|
||||
|
||||
# Methods optionally implemented in subclass
|
||||
def on_open(self):
|
||||
|
@ -710,21 +693,17 @@ class LinearIO(Widget):
|
|||
# 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):
|
||||
asyncio.create_task(self.btnhan(button, 1))
|
||||
|
||||
def do_down(self, button):
|
||||
asyncio.create_task(self.btnhan(button, -1))
|
||||
# Adjust widget's value. Args: button pressed, amount of increment
|
||||
def do_adj(self, button, val):
|
||||
encoder = isinstance(button, int)
|
||||
d = self.min_delta * 0.1 if self.precision else self.min_delta
|
||||
self.value(self.value() + val * d)
|
||||
if not encoder:
|
||||
asyncio.create_task(self.btnhan(button, val, d))
|
||||
|
||||
# Handle increase and decrease buttons. Redefined by textbox.py, scale_log.py
|
||||
async def btnhan(self, button, up):
|
||||
if self.precision:
|
||||
d = self.min_delta * 0.1
|
||||
maxd = self.max_delta
|
||||
else:
|
||||
d = self.min_delta
|
||||
maxd = d * 4 # Why move fast in precision mode?
|
||||
self.value(self.value() + up * d)
|
||||
async def btnhan(self, button, up, d):
|
||||
maxd = self.max_delta if self.precision else d * 4 # Why move fast in precision mode?
|
||||
t = ticks_ms()
|
||||
while not button():
|
||||
await asyncio.sleep_ms(0) # Quit fast on button release
|
||||
|
|
|
@ -47,13 +47,11 @@ class BaseScreen(Screen):
|
|||
self.vslider = Slider(wri, 2, 2, callback=self.slider_cb,
|
||||
bdcolor=RED, slotcolor=BLUE,
|
||||
legends=('0.0', '0.5', '1.0'), value=0.5)
|
||||
#Label(wri, 2, self.vslider.mcol, 'FF')
|
||||
col = 80
|
||||
row = 15
|
||||
self.hslider = HorizSlider(wri, row, col, callback=self.slider_cb,
|
||||
bdcolor=GREEN, slotcolor=BLUE,
|
||||
legends=('0.0', '0.5', '1.0'), value=0.7)
|
||||
Label(wri, self.hslider.mrow, self.hslider.mcol, 'FF')
|
||||
row += 30
|
||||
self.scale = Scale(wri, row, col, width = 150, tickcb = tickcb,
|
||||
pointercolor=RED, fontcolor=YELLOW, bdcolor=CYAN,
|
||||
|
|
|
@ -61,11 +61,8 @@ class FooScreen(Screen):
|
|||
|
||||
m0 = Meter(wri, 10, 240, divisions = 4, ptcolor=YELLOW, height=80, width=15,
|
||||
label='Meter example', style=Meter.BAR, legends=('0.0', '0.5', '1.0'))
|
||||
#Label(wri, 2, m0.mcol, 'FF')
|
||||
# Instantiate displayable objects. bgcolor forces complete redraw.
|
||||
dial = Dial(wri, 2, 2, height = 75, ticks = 12, bgcolor=BLACK, bdcolor=None, label=120) # Border in fg color
|
||||
#Label(wri, dial.mrow, 2, 'FF')
|
||||
#Label(wri, dial.mrow, dial.mcol, 'FF')
|
||||
scale = Scale(wri, 2, 100, width = 124, tickcb = tickcb,
|
||||
pointercolor=RED, fontcolor=YELLOW, bdcolor=CYAN)
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
# encoder.py Asynchronous driver for incremental quadrature encoder.
|
||||
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
# Released under the MIT License (MIT) - see LICENSE file
|
||||
|
||||
# This driver is intended for encoder-based control knobs. It is
|
||||
# unsuitable for NC machine applications. Please see the docs.
|
||||
|
||||
import uasyncio as asyncio
|
||||
from machine import Pin
|
||||
|
||||
class Encoder:
|
||||
delay = 100 # Pause (ms) for motion to stop
|
||||
|
||||
def __init__(self, pin_x, pin_y, v=0, vmin=None, vmax=None, div=1,
|
||||
callback=lambda a, b : None, args=()):
|
||||
self._pin_x = pin_x
|
||||
self._pin_y = pin_y
|
||||
self._v = 0 # Hardware value always starts at 0
|
||||
self._cv = v # Current (divided) value
|
||||
if ((vmin is not None) and v < min) or ((vmax is not None) and v > vmax):
|
||||
raise ValueError('Incompatible args: must have vmin <= v <= vmax')
|
||||
self._tsf = asyncio.ThreadSafeFlag()
|
||||
trig = Pin.IRQ_RISING | Pin.IRQ_FALLING
|
||||
try:
|
||||
xirq = pin_x.irq(trigger=trig, handler=self._x_cb, hard=True)
|
||||
yirq = pin_y.irq(trigger=trig, handler=self._y_cb, hard=True)
|
||||
except TypeError: # hard arg is unsupported on some hosts
|
||||
xirq = pin_x.irq(trigger=trig, handler=self._x_cb)
|
||||
yirq = pin_y.irq(trigger=trig, handler=self._y_cb)
|
||||
asyncio.create_task(self._run(vmin, vmax, div, callback, args))
|
||||
|
||||
# Hardware IRQ's
|
||||
def _x_cb(self, pin):
|
||||
fwd = pin() ^ self._pin_y()
|
||||
self._v += 1 if fwd else -1
|
||||
self._tsf.set()
|
||||
|
||||
def _y_cb(self, pin):
|
||||
fwd = pin() ^ self._pin_x() ^ 1
|
||||
self._v += 1 if fwd else -1
|
||||
self._tsf.set()
|
||||
|
||||
async def _run(self, vmin, vmax, div, cb, args):
|
||||
pv = self._v # Prior hardware value
|
||||
cv = self._cv # Current divided value as passed to callback
|
||||
pcv = cv # Prior divided value passed to callback
|
||||
mod = 0
|
||||
delay = self.delay
|
||||
while True:
|
||||
await self._tsf.wait()
|
||||
await asyncio.sleep_ms(delay) # Wait for motion to stop
|
||||
new = self._v # Sample hardware (atomic read)
|
||||
a = new - pv # Hardware change
|
||||
# Ensure symmetrical bahaviour for + and - values
|
||||
q, r = divmod(abs(a), div)
|
||||
if a < 0:
|
||||
r = -r
|
||||
q = -q
|
||||
pv = new - r # Hardware value when local value was updated
|
||||
cv += q
|
||||
if vmax is not None:
|
||||
cv = min(cv, vmax)
|
||||
if vmin is not None:
|
||||
cv = max(cv, vmin)
|
||||
self._cv = cv # For value()
|
||||
if cv != pcv:
|
||||
cb(cv, cv - pcv, *args) # User CB in uasyncio context
|
||||
pcv = cv
|
||||
|
||||
def value(self):
|
||||
return self._cv
|
|
@ -78,18 +78,17 @@ class Listbox(Widget):
|
|||
self.value(v)
|
||||
return v
|
||||
|
||||
def do_up(self, _):
|
||||
if v := self._value:
|
||||
self.value(v - 1)
|
||||
def do_adj(self, _, val):
|
||||
v = self._value
|
||||
if val > 0:
|
||||
if v:
|
||||
self.value(v - 1)
|
||||
elif val < 0:
|
||||
if v < len(self.elements) - 1:
|
||||
self.value(v + 1)
|
||||
if (self.also & Listbox.ON_MOVE): # Treat as if select pressed
|
||||
self.do_sel()
|
||||
|
||||
def do_down(self, _):
|
||||
if (v := self._value) < len(self.elements) - 1:
|
||||
self.value(v + 1)
|
||||
if (self.also & Listbox.ON_MOVE):
|
||||
self.do_sel()
|
||||
|
||||
# Callback runs if select is pressed. Also (if ON_LEAVE) if user changes
|
||||
# list currency and then moves off the control. Otherwise if we have a
|
||||
# callback that refreshes another control, that second control does not
|
||||
|
|
|
@ -23,6 +23,7 @@ dolittle = lambda *_ : None
|
|||
|
||||
# Start value is 1.0. User applies scaling to value and ticks callback.
|
||||
class ScaleLog(LinearIO):
|
||||
encoder_rate = 5
|
||||
def __init__(self, writer, row, col, *,
|
||||
decades=5, height=0, width=160,
|
||||
bdcolor=None, fgcolor=None, bgcolor=None,
|
||||
|
@ -141,6 +142,14 @@ class ScaleLog(LinearIO):
|
|||
return self._value
|
||||
|
||||
|
||||
# Adjust widget's value. Args: button pressed, amount of increment
|
||||
def do_adj(self, button, val):
|
||||
if isinstance(button, int): # Using an encoder
|
||||
delta = self.delta * self.encoder_rate * 0.1 if self.precision else self.delta * self.encoder_rate
|
||||
self.value(self.value() * (1 + delta)**val)
|
||||
else:
|
||||
asyncio.create_task(self.btnhan(button, val, d))
|
||||
|
||||
async def btnhan(self, button, up):
|
||||
up = up == 1
|
||||
if self.precision:
|
||||
|
|
|
@ -1,122 +1,54 @@
|
|||
# color_setup.py Customise for your hardware config
|
||||
# ili9341_pico.py Customise for your hardware config
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch, Ihor Nehrutsa
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# Supports:
|
||||
# TTGO T-Display 1.14" 135*240(Pixel) based on ST7789V
|
||||
# http://www.lilygo.cn/claprod_view.aspx?TypeId=62&Id=1274
|
||||
# http://www.lilygo.cn/prod_view.aspx?TypeId=50044&Id=1126
|
||||
# https://github.com/Xinyuan-LilyGO/TTGO-T-Display
|
||||
# https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/image/pinmap.jpg
|
||||
# https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/schematic/ESP32-TFT(6-26).pdf
|
||||
|
||||
# WIRING (TTGO T-Display pin numbers and names).
|
||||
# Pinout of TFT Driver
|
||||
# ST7789 ESP32
|
||||
# TFT_MISO N/A
|
||||
TFT_MOSI = 19 # (SDA on schematic pdf) SPI interface output/input pin.
|
||||
TFT_SCLK = 18 # This pin is used to be serial interface clock.
|
||||
TFT_CS = 5 # Chip selection pin, low enable, high disable.
|
||||
TFT_DC = 16 # Display data/command selection pin in 4-line serial interface.
|
||||
TFT_RST = 23 # This signal will reset the device,Signal is active low.
|
||||
TFT_BL = 4 # (LEDK on schematic pdf) Display backlight control pin
|
||||
|
||||
ADC_IN = 34 # Measuring battery or USB voltage, see comment below
|
||||
ADC_EN = 14 # (PWR_EN on schematic pdf) is the ADC detection enable port
|
||||
|
||||
BUTTON1 = 35 # right of the USB connector
|
||||
BUTTON2 = 0 # left of the USB connector
|
||||
|
||||
# ESP32 pins, free for use in user applications
|
||||
#I2C_SDA = 21 # hardware ID 0
|
||||
#I2C_SCL = 22
|
||||
|
||||
#UART2TXD = 17
|
||||
|
||||
#GPIO2 = 2
|
||||
#GPIO15 = 15
|
||||
#GPIO13 = 13
|
||||
#GPIO12 = 12
|
||||
|
||||
#GPIO37 = 37
|
||||
#GPIO38 = 38
|
||||
#UART1TXD = 4
|
||||
#UART1RXD = 5
|
||||
#GPIO18 = 18
|
||||
#GPIO19 = 19
|
||||
#GPIO17 = 17
|
||||
|
||||
#DAC1 = 25
|
||||
#DAC2 = 26
|
||||
|
||||
# Input only pins
|
||||
#GPIO36 = 36 # input only
|
||||
#GPIO39 = 39 # input only
|
||||
# As written, supports:
|
||||
# ili9341 240x320 displays on Pi Pico
|
||||
# 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.
|
||||
|
||||
from machine import Pin, SPI, ADC, freq
|
||||
# WIRING
|
||||
# Pico Display
|
||||
# GPIO Pin
|
||||
# 3v3 36 Vin
|
||||
# IO6 9 CLK Hardware SPI0
|
||||
# IO7 10 DATA (AKA SI MOSI)
|
||||
# IO8 11 DC
|
||||
# IO9 12 Rst
|
||||
# Gnd 13 Gnd
|
||||
# IO10 14 CS
|
||||
|
||||
# Pushbuttons are wired between the pin and Gnd
|
||||
# Pico pin Meaning
|
||||
# 16 Operate current control
|
||||
# 17 Decrease value of current control
|
||||
# 18 Select previous control
|
||||
# 19 Select next control
|
||||
# 20 Increase value of current control
|
||||
|
||||
from machine import Pin, SPI, freq
|
||||
import gc
|
||||
|
||||
from drivers.st7789.st7789_4bit import *
|
||||
SSD = ST7789
|
||||
|
||||
pdc = Pin(TFT_DC, Pin.OUT, value=0) # Arbitrary pins
|
||||
pcs = Pin(TFT_CS, Pin.OUT, value=1)
|
||||
prst = Pin(TFT_RST, Pin.OUT, value=1)
|
||||
pbl = Pin(TFT_BL, Pin.OUT, value=1)
|
||||
|
||||
from drivers.ili93xx.ili9341 import ILI9341 as SSD
|
||||
freq(250_000_000) # RP2 overclock
|
||||
# Create and export an SSD instance
|
||||
pdc = Pin(8, Pin.OUT, value=0) # Arbitrary pins
|
||||
prst = Pin(9, Pin.OUT, value=1)
|
||||
pcs = Pin(10, Pin.OUT, value=1)
|
||||
spi = SPI(0, baudrate=30_000_000)
|
||||
gc.collect() # Precaution before instantiating framebuf
|
||||
# Conservative low baudrate. Can go to 62.5MHz.
|
||||
spi = SPI(1, 30_000_000, sck=Pin(TFT_SCLK), mosi=Pin(TFT_MOSI))
|
||||
freq(160_000_000)
|
||||
|
||||
''' TTGO
|
||||
v +----------------+
|
||||
40 | | |
|
||||
^ | +------+ | pin 36
|
||||
| | | | |
|
||||
| | | | |
|
||||
240 | | | | |
|
||||
| | | | |
|
||||
| | | | |
|
||||
v | +------+ |
|
||||
40 | | | Reset button
|
||||
^ +----------------+
|
||||
>----<------>----<
|
||||
52 135 xx
|
||||
BUTTON2 BUTTON1
|
||||
'''
|
||||
# Right way up landscape: defined as top left adjacent to pin 36
|
||||
ssd = SSD(spi, height=135, width=240, dc=pdc, cs=pcs, rst=prst, disp_mode=LANDSCAPE, display=TDISPLAY)
|
||||
# Normal portrait display: consistent with TTGO logo at top
|
||||
# ssd = SSD(spi, height=240, width=135, dc=pdc, cs=pcs, rst=prst, disp_mode=PORTRAIT, display=TDISPLAY)
|
||||
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(32, Pin.IN, Pin.PULL_UP) # Move to next control
|
||||
sel = Pin(36, Pin.IN, Pin.PULL_UP) # Operate current control
|
||||
prev = Pin(38, Pin.IN, Pin.PULL_UP) # Move to previous control
|
||||
increase = Pin(37, Pin.IN, Pin.PULL_UP) # Increase control's value
|
||||
decrease = Pin(39, Pin.IN, Pin.PULL_UP) # Decrease control's value
|
||||
display = Display(ssd, nxt, sel, prev, increase, decrease)
|
||||
|
||||
# optional
|
||||
# b1 = Pin(BUTTON1, Pin.IN)
|
||||
# b2 = Pin(BUTTON2, Pin.IN)
|
||||
# adc_en = Pin(ADC_EN, Pin.OUT, value=1)
|
||||
# adc_in = ADC(Pin(ADC_IN))
|
||||
# adc_en.value(0)
|
||||
'''
|
||||
Set ADC_EN to "1" and read voltage in BAT_ADC,
|
||||
if this voltage more than 4.3 V device have powered from USB.
|
||||
If less then 4.3 V - device have power from battery.
|
||||
To save battery you can set ADC_EN to "0" and in this case the USB converter
|
||||
will be power off and do not use your battery.
|
||||
When you need to measure battery voltage first set ADC_EN to "1",
|
||||
measure voltage and then set ADC_EN back to "0" for save battery.
|
||||
'''
|
||||
nxt = Pin(19, Pin.IN, Pin.PULL_UP) # Move to next control
|
||||
sel = Pin(16, Pin.IN, Pin.PULL_UP) # Operate current control
|
||||
prev = Pin(18, Pin.IN, Pin.PULL_UP) # Move to previous control
|
||||
increase = Pin(20, Pin.IN, Pin.PULL_UP) # Increase control's value
|
||||
decrease = Pin(17, Pin.IN, Pin.PULL_UP) # Decrease control's value
|
||||
display = Display(ssd, nxt, sel, prev, increase, decrease, 5) # Encoder
|
||||
|
|
|
@ -101,9 +101,14 @@ from gui.core.ugui import Display
|
|||
nxt = Pin(32, Pin.IN, Pin.PULL_UP) # Move to next control
|
||||
sel = Pin(36, Pin.IN, Pin.PULL_UP) # Operate current control
|
||||
prev = Pin(38, Pin.IN, Pin.PULL_UP) # Move to previous control
|
||||
increase = Pin(37, Pin.IN, Pin.PULL_UP) # Increase control's value
|
||||
decrease = Pin(39, Pin.IN, Pin.PULL_UP) # Decrease control's value
|
||||
display = Display(ssd, nxt, sel, prev, increase, decrease)
|
||||
encoder = 5 # Divide by 5
|
||||
if encoder:
|
||||
increase = Pin(25, Pin.IN, Pin.PULL_UP) # Encoder x and y pins
|
||||
decrease = Pin(33, Pin.IN, Pin.PULL_UP)
|
||||
else:
|
||||
increase = Pin(37, Pin.IN, Pin.PULL_UP) # Increase control's value
|
||||
decrease = Pin(39, Pin.IN, Pin.PULL_UP) # Decrease control's value
|
||||
display = Display(ssd, nxt, sel, prev, increase, decrease, encoder)
|
||||
|
||||
# optional
|
||||
# b1 = Pin(BUTTON1, Pin.IN)
|
||||
|
|
Ładowanie…
Reference in New Issue