diff --git a/README.md b/README.md index 3f8b28f..0cba9e0 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,37 @@ to a wide range of displays. It is also portable between hosts. # Project status -Code has been tested on ESP32 and Pi Pico. It is new and bugs are likely. This -document is also incomplete and under review. - +Code has been tested on ESP32 and Pi Pico. The API shuld be stable. I'm not +aware of any bugs but code is new and issues are likely. This document is +likely to have errors, typos and omissions. It is under review. # 0. Contents -**TODO** +**TODO** Add sub-headings + +1. [Basic concepts](./README.md#1-basic-concepts) Including installation and test. +2. [Usage](./README.md#2-usage) Application design. +3. [The ssd and display objects](./README.md#3-the-ssd-and-display-objects) +4. [Screen class](./README.md#4-screen-class) Full screen window. +5. [Window class](./README.md#5-window-class) +6. [Label widget](./README.md#6-label-widget) Single line text display. +7. [LED widget](./README.md#7-led-widget) Display Boolean values. +8. [Checkbox widget](./README.md#8-checkbox-widget) Enter Boolean values. +9. [Button and CloseButton widgets](./README.md#9-button-and-closebutton-widgets) Pushbutton emulation. +10. [ButtonList object](./README.md#10-buttonlist-object) Pushbuttons with multiple states. +11. [RadioButtons object](./README.md#11-radiobuttons-object) One-of-N pushbuttons. +12. [Listbox widget](./README.md#12-listbox-widget) +13. [Dropdown widget](./README.md#13-dropdown-widget) Dropdown lists. +14. [DialogBox class](./README.md#14-dialogbox class) Pop-up modal dialog boxes. +15. [Textbox widget](./README.md#15-textbox-widget) Scrolling text display. +16. [Meter widget](./README.md#16-meter-widget) Display floats on an analog meter. +17. [Slider and HorizSlider widgets](./README.md#17-slider-and-horizslider-widgets) Linear potentiometer float data entry and display +18. [Scale widget](./README.md#18-scale-widget) High precision float entry and display. +19. [ScaleLog widget](./README.md#19-scalelog-widget) Wide dynamic range float entry and display. +20. [Dial widget](./README.md#20-dial-widget) Display multiple vectors. +21. [Knob widget](./README.md#21-knob-widget) Rotary potentiometer float entry. +22. [Graph plotting](./README.md#22-graph-plotting) Widgets for Cartesian and polar graphs. +[Appendix 1 Application design](./README.md#appendix-1-application-design) # 1. Basic concepts @@ -54,12 +78,14 @@ attributes. It can overlay part of an underlying `Screen` and is typically used for modal dialog boxes. A `Widget` is an object capable of displaying data. Some are also capable of -data input. The latter can be capable of accepting focus, see -[navigation](./README.md#13-navigation). `Widget` objects have dimensions -defined as `height` and `width`. The space requred by them exceeds these by two -pixels all round, as a white border is drawn to show which object currently has -focus. Thus to place a `Widget` at the extreme top left, `row` and `col` values -should be 2. +data input: such a widget is defined as `active`. A `passive` widget can only +display data. An `active` widget can acquire `focus`. The widget with `focus` +is able to respond to user input. See [navigation](./README.md#14-navigation). +`Widget` objects have dimensions defined as `height` and `width`. The space +requred by them exceeds these dimensions by two pixels all round. This is +because `micro-gui` displays a white border to show which object currently has +`focus`. Thus to place a `Widget` at the extreme top left, `row` and `col` +values should be 2. ## 1.3 Fonts @@ -87,16 +113,16 @@ The GUI requires from 2 to 5 pushbuttons for control. These are: 1. `Next` Move to the next widget. 2. `Select` Operate the currently selected widget. 3. `Prev` Move to the previous widget. - 4. `Increase` Move within the widget. + 4. `Increase` Move within the widget (i.e. adjust its value). 5. `Decrease` Move within the widget. Many widgets such as `Pushbutton` or `Checkbox` objects require only the -`Select` button to operate: it is possible to design an interface using only -the first two buttons. +`Select` button to operate: it is possible to design an interface with a subset +of `micro-gui` widgets which requires only the first two buttons. Widgets such as `Listbox` objects, dropdown lists (`Dropdown`), and those for -floating point data entry require the `Increase` and `Decrease` buttons to move -within the widget or to adjust the linear value. +floating point data entry require the `Increase` and `Decrease` buttons to +select a data item or to adjust the linear value. A `LinearIO` is a `Widget` that responds to the `increase` and `decrease` buttons by running an `asyncio` task. These typically output floating point @@ -104,25 +130,67 @@ values using an accelerating algorithm responding to the duration of the button press. This enables floats with a wide dynamic range to be adjusted with precision. -The currently selected `Widget` is identified by a white border: the focus -moves between widgets via `Next` and `Prev`. Only `Widget` instances that can -accept input can receive the focus; such widgets are defined as `active`. -Widgets are defined as `active` or passive in the constructor, and this status -cannot be changed. In some cases the state can be specified as a constructor -arg. An `active` widget can be disabled and re-enabled at runtime. A disabled -`active` widget is shown "greyed-out" and, until enabled, cannot accept the -focus. +The currently selected `Widget` is identified by a white border: the `focus` +moves between widgets via `Next` and `Prev`. Only `active` `Widget` instances +(those that can accept input) can receive the `focus`. Widgets are defined as +`active` or `passive` in the constructor, and this status cannot be changed. In +some cases the state can be specified as a constructor arg. An `active` widget +can be disabled and re-enabled at runtime. A disabled `active` widget is shown +"greyed-out" and, until re-enabled, cannot accept the focus. ## 1.5 Hardware definition A file `hardware_setup.py` must exist in the GUI root directory. This defines the connections to the display, the display driver, and pins used for the -pushbuttons. Example files may be found in the `setup_examples` directory. +pushbuttons. Example files may be found in the `setup_examples` directory. The +following is a typical example for a Raspberry Pi Pico driving an ILI9341 +display: + +```python +from machine import Pin, SPI, freq +import gc + +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 +ssd = SSD(spi, pcs, pdc, prst, usd=True) + +from gui.core.ugui import Display, setup +# Create and export a Display instance +# Define control buttons +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) +setup(display) +``` Display drivers are documented [here](https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md). -## 1.6 Installation +## 1.6 Quick hardware check + +The following may be pasted at the REPL to verify correct connection to the +display. It also confirms that `hardware_setup.py` is specifying a suitable +display driver. +```python +from hardware_setup import ssd # Create a display instance +from gui.core.colors import * +ssd.fill(0) +ssd.line(0, 0, ssd.width - 1, ssd.height - 1, GREEN) # Green diagonal corner-to-corner +ssd.rect(0, 0, 15, 15, RED) # Red square at top left +ssd.rect(ssd.width -15, ssd.height -15, 15, 15, BLUE) # Blue square at bottom right +ssd.show() +``` + +## 1.7 Installation The easy way to start is to use `mpremote` which allows a directory on your PC to be mounted on the host. In this way the filesystem on the host is left @@ -155,21 +223,6 @@ kept. There is scope for speeding loading and saving RAM by using frozen bytecode. Once again, directory structure must be maintained. -## 1.7 Quick hardware check - -The following may be pasted at the REPL to verify correct connection to the -display. It also confirms that `hardware_setup.py` is specifying a suitable -display driver. -```python -from hardware_setup import ssd # Create a display instance -from gui.core.colors import * -ssd.fill(0) -ssd.line(0, 0, ssd.width - 1, ssd.height - 1, GREEN) # Green diagonal corner-to-corner -ssd.rect(0, 0, 15, 15, RED) # Red square at top left -ssd.rect(ssd.width -15, ssd.height -15, 15, 15, BLUE) # Blue square at bottom right -ssd.show() -``` - ## 1.8 Performance and hardware notes The largest supported display is a 320x240 ILI9341 unit. On a Pi Pico with no @@ -182,29 +235,25 @@ Snappy navigation benefits from several approaches: 3. Device driver support for `uasyncio`. Currently this exists on ILI9341 and ST7789 (e.g. TTGO T-Display). I intend to extend this to other drivers. -On ESP32 I found it necessary to use physical pullup resistors on the -pushbutton GPIO lines. +On the TTGO T-Display I found it necessary to use physical pullup resistors on +the pushbutton GPIO lines. According to the ESP32 gurus pins 36-39 do not have +pullup support. ## 1.9 Firmware and dependencies -Firmware should be V1.15 or later. - -The source tree includes all dependencies. These are listed to enable users to -check for newer versions: +Firmware should be V1.15 or later. The source tree includes all dependencies. +These are listed to enable users to check for newer versions: * [writer.py](https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/writer.py) Provides text rendering of Python font files. - -A copy of the official driver for OLED displays using the SSD1306 chip is -provided. The official file is here: * [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py). - -Displays based on the Nokia 5110 (PCD8544 chip) require this driver. It is not -in this repo but may be found here: - * [PCD8544/Nokia 5110](https://github.com/mcauser/micropython-pcd8544.git) - -Synchronisation primitives for `uasyncio` may be found here: - * [My async repo](https://github.com/peterhinch/micropython-async/tree/master/v3/primitives). + A copy of the official driver for OLED displays using the SSD1306 chip is + provided. The link is to the official file. + * [Synchronisation primitives](https://github.com/peterhinch/micropython-async/tree/master/v3/primitives). + The link is to my `uasyncio` support repo. + * [PCD8544/Nokia 5110](https://github.com/mcauser/micropython-pcd8544.git). + Displays based on the Nokia 5110 (PCD8544 chip) require this driver. It is not + provided in this repo. The link is to its source. ## 1.10 Supported hosts and displays @@ -250,6 +299,8 @@ require a large (320x240) display. Demos are run by issuing (for example): * `various.py` Assorted widgets including the different types of pushbutton. * `vtest.py` Clock and compass styles of vector display. +###### [Contents](./README.md#0-contents) + # 2. Usage ## 2.1 Program structure and operation @@ -309,7 +360,7 @@ Note how the `Next` pushbutton moves the focus between the two buttons and the it is not `active`: a `Label` cannot accept user input. Pushing the `Select` pushbutton while the focus is on a `Pushbutton` causes the callback to run. -Applications start by performing `Screen.change()` to a user-defined Screen +Applications start by performing `Screen.change()` to a user-defined `Screen` object. This must be subclassed from the GUI's `Screen` class. Note that `Screen.change` accepts a class name, not a class instance. @@ -340,41 +391,41 @@ optional: a default null function and empty list are provided. Callbacks may optionally be written as bound methods. This facilitates communication between widgets. -When writing callbacks take care to ensure that the number of arguments passed -is correct, bearing in mind the first arg listed above. Failure to do this will -result in tracebacks which implicate the GUI code rather than the buggy user -code: this is because the GUI runs the callbacks. +When writing callbacks take care to ensure that the correct number of arguments +are passed, bearing in mind the first arg described above. An incorrect +argument count results in puzzling tracebacks which appear to implicate the GUI +code. This is because it is the GUI which actually executes the callbacks. ## 2.3 Colors -The file `gui/core/colors.py` defines standard color constants which may be +The file `gui/core/colors.py` defines a set of color constants which may be used with any display driver. This section describes how to change these or -to create additional colors. +to create additional colors. Most of the color display drivers define colors +as 8-bit or larger values. For the larger displays 4-bit drivers are provided +with the aim of conserving RAM. -Most of the color display drivers define colors as 8-bit or larger values. -In such cases colors may be created and assigned to variables as follows: -```python -from hardware_setup import ssd -PALE_YELLOW = ssd.rgb(150, 150, 0) -``` -The GUI also provides drivers with 4-bit color to minimise RAM use. Colors are -assigned to a lookup table having 16 entries. The frame buffer stores 4-bit -color values, which are converted to the correct color depth for the hardware -when the display is refreshed. +In the 4-bit case colors are assigned to a lookup table (LUT) with 16 entries. +The frame buffer stores 4-bit color values, which are converted to the correct +color depth for the hardware when the display is refreshed. Of the 16 possible +colors 13 are assigned in `gui/core/colors.py`, leaving color numbers 12, 13 +and 14 free. -Of the possible 16 colors 13 are assigned in `gui/core/colors.py`, leaving -color numbers 12, 13 and 14 free. Any color can be assigned as follows: +The following code is portable between displays and creates a user defined +color `PALE_YELLOW`. ```python from gui.core.colors import * # Imports the create_color function -PALE_YELLOW = create_color(12, 150, 150, 0) +PALE_YELLOW = create_color(12, 150, 150, 0) # index, r, g, b ``` -This creates a color `rgb(150, 150, 0)` assigns it to "spare" color number 12 -then sets `PALE_YELLOW` to 12. Any color number in range `0 <= n <= 15` may be -used (implying that predefined colors may be reassigned). It is recommended -that `BLACK` (0) and `WHITE` (15) are not changed. If code is to be ported -between 4-bit and other drivers, use `create_color()` for all custom colors: -it will produce appropriate behaviour. For an example see the `nano-gui` demo -`color15.py` - in particular the `vari_fields` function. +If a 4-bit driver is in use, the color `rgb(150, 150, 0)` will be assigned to +"spare" color number 12. Any color number in range `0 <= n <= 15` may be +used, implying that predefined colors may be reassigned. It is recommended +that `BLACK` (0) and `WHITE` (15) are not changed. If an 8-bit or larger driver +is in use, the first `index` arg is ignored and there is no restriction on the +number of colors that may be created. + +Regardless of the display driver the `PALE_YELLOW` variable may be used to +refer to the color. An example of custom color definition may be found in +[this nano-gui demo](https://github.com/peterhinch/micropython-nano-gui/blob/4ef0e20da27ef7c0b5c34136dcb372200f0e5e66/gui/demos/color15.py#L92). ### 2.3.1 Monochrome displays @@ -391,7 +442,24 @@ There is an issue regarding ePaper displays discussed I don't consider ePaper displays as suitable for I/O because of their slow refresh time. -# 3. Class details +###### [Contents](./README.md#0-contents) + +# 3. The ssd and display objects + +The following code, issued as the first executable line of an application, +initialises the display. +```python +from hardware_setup import display, ssd +``` +It creates singleton instances of `SSD` and `Display` classes. Normal GUI +applications only need to import `ssd`. This refererence to the display driver +is used to initialise `Writer` objects. Bound variables `.height` and `.width` +may be read to determine the dimensions of the display hardware. + +Use of `display` is restricted to applications which use graphics primitives to +write directly to the screen. See Appendix 1. + +###### [Contents](./README.md#0-contents) # 4. Screen class @@ -454,6 +522,8 @@ base screen are cancelled. For finer control applications can ignore this method and handle cancellation explicitly in code. +###### [Contents](./README.md#0-contents) + # 5. Window class This is a `Screen` subclass providing for modal windows. As such it has @@ -485,6 +555,8 @@ callbacks to the user window constructor args. These may be called by widgets to send data to the calling screen. Note that widgets on the screen below will not be updated until the window has closed. +###### [Contents](./README.md#0-contents) + # 6. Label widget ```python @@ -562,6 +634,8 @@ class BaseScreen(Screen): Screen.change(BaseScreen) ``` +###### [Contents](./README.md#0-contents) + # 7. LED widget ```python @@ -600,6 +674,8 @@ Methods: passed, no border is displayed. This clears a previously drawn border. 3. `show` No args. (Re)draws the LED. Primarily for internal use by GUI. +###### [Contents](./README.md#0-contents) + # 8. Checkbox widget ```python @@ -638,6 +714,8 @@ Methods: correspond to the control's current value, updates it; the checkbox is re-drawn and the callback executed. Always returns the control's value. +###### [Contents](./README.md#0-contents) + # 9. Button and CloseButton widgets ```python @@ -694,6 +772,8 @@ right hand corner of the current `Screen`. Operating it causes the screen to close, with the screen below being revealed. On the bottom level screen, a `CloseButton` will shut down the application. +###### [Contents](./README.md#0-contents) + # 10. ButtonList object ```python @@ -741,6 +821,8 @@ for t in table: # Buttons overlay each other at same location bl.add_button(wri, 10, 10, textcolor = BLACK, **t) ``` +###### [Contents](./README.md#0-contents) + # 11. RadioButtons object ```python @@ -787,6 +869,8 @@ for t in table: col += 60 # Horizontal row of buttons ``` +###### [Contents](./README.md#0-contents) + # 12. Listbox widget ```python @@ -845,6 +929,8 @@ The callback's first argument is the listbox instance followed by any args specified to the constructor. The currently selected item may be retrieved by means of the instance's `value` or `textvalue` methods. +###### [Contents](./README.md#0-contents) + # 13. Dropdown widget ```python @@ -914,6 +1000,8 @@ The callback's first argument is the dropdown instance followed by any args specified to the constructor. The currently selected item may be retrieved by means of the instance's `value` or `textvalue` methods. +###### [Contents](./README.md#0-contents) + # 14. DialogBox class ```python @@ -959,6 +1047,8 @@ flexible designs. For example these might have widgets other than pushbuttons. The approach is to write a user subclass of `Window`. Example code may be found in `gui/demos/screens.py`. +###### [Contents](./README.md#0-contents) + # 15. Textbox widget ```python @@ -1024,6 +1114,8 @@ If text is regularly appended to a `Textbox` its buffer grows, using RAM. The value of `ntrim` sets a limit to the number of lines which are retained, with the oldest (topmost) being discarded as required. +###### [Contents](./README.md#0-contents) + # 16. Meter widget ```python @@ -1078,6 +1170,8 @@ Methods: passed, no border is displayed. This clears a previously drawn border. 3. `show` No args. (Re)draws the meter. Primarily for internal use by GUI. +###### [Contents](./README.md#0-contents) + # 17. Slider and HorizSlider widgets ```python @@ -1141,6 +1235,8 @@ user supplied args. They can be a bound methods, typically of a `Screen` subclass. The callback runs whenever the value changes enabling dynamic color change. See `gui/demos/active.py`. +###### [Contents](./README.md#0-contents) + # 18. Scale widget ```python @@ -1249,6 +1345,8 @@ For performance reasons the control stores values as integers. This means that if you set `value` and subsequently retrieve it, there may be some loss of precision. Each visible division on the control represents 10 integer units. +###### [Contents](./README.md#0-contents) + # 19. ScaleLog widget ```python @@ -1363,6 +1461,8 @@ def tickcb(f, c): return c ``` +###### [Contents](./README.md#0-contents) + # 20. Dial widget ```python @@ -1479,6 +1579,8 @@ class BaseScreen(Screen): Screen.change(BaseScreen) ``` +###### [Contents](./README.md#0-contents) + # 21. Knob widget ```python @@ -1520,6 +1622,8 @@ Methods: 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. +###### [Contents](./README.md#0-contents) + # 22. Graph Plotting ```python @@ -1769,9 +1873,11 @@ class TSeq(Screen): t += 1 ``` -# 23. Application design +###### [Contents](./README.md#0-contents) -## 23.1 Tab order and button layout +# Appendix 1 Application design + +## Tab order and button layout The "tab order" of widgets on a `Screen` is the order with which they acquire focus with successive presses of the `Next` button. It is determined by the @@ -1796,7 +1902,7 @@ 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. -## 23.2 Use of graphics primitives +## Use of graphics primitives These notes are for those wishing to draw directly to the `Screen` instance. This is done by providing the user `Screen` class with an `after_open()` method diff --git a/gui/demos/active.py b/gui/demos/active.py index 3503921..bb2e345 100644 --- a/gui/demos/active.py +++ b/gui/demos/active.py @@ -1,7 +1,7 @@ # active.py micro-gui demo of widgets that respond to user control -# Import SSD and Display instances. Must be done first because of RAM use. -from hardware_setup import display, ssd # Create a display instance +# Create SSD instance. Must be done first because of RAM use. +from hardware_setup import ssd from gui.core.ugui import Screen from gui.core.writer import CWriter import gui.fonts.arial10 as arial10 # Font for CWriter @@ -90,7 +90,7 @@ class BaseScreen(Screen): s.color(GREEN) def test(): - if display.height < 240 or display.width < 320: + if ssd.height < 240 or ssd.width < 320: print(' This test requires a display of at least 320x240 pixels.') else: print('Testing micro-gui...') diff --git a/gui/demos/plot.py b/gui/demos/plot.py index 60ac8f9..1903bb8 100644 --- a/gui/demos/plot.py +++ b/gui/demos/plot.py @@ -7,8 +7,8 @@ # Released under the MIT License (MIT). See LICENSE. # Copyright (c) 2021 Peter Hinch -# Initialise hardware and framebuf before importing modules. -from hardware_setup import ssd, display # Create a display instance +# Create SSD instance. Must be done first because of RAM use. +from hardware_setup import ssd import cmath import math @@ -241,7 +241,7 @@ class BaseScreen(Screen): Screen.change(d[lb.textvalue()]) def test(): - if display.height < 128 or display.width < 200: + if ssd.height < 128 or ssd.width < 200: print(' This test requires a display of at least 128x200 pixels.') else: print('Testing micro-gui...') diff --git a/gui/demos/screens.py b/gui/demos/screens.py index 5bab5b3..6da5a8d 100644 --- a/gui/demos/screens.py +++ b/gui/demos/screens.py @@ -1,7 +1,7 @@ # screens.py micro-gui demo of multiple screens, dropdowns etc -# Initialise hardware and framebuf before importing modules. -# Import SSD and Display instances. Must be done first because of RAM use. -from hardware_setup import display, ssd # Create a display instance + +# Create SSD instance. Must be done first because of RAM use. +from hardware_setup import ssd # Create a display instance from gui.core.ugui import Screen, Window from gui.widgets.label import Label @@ -100,7 +100,7 @@ class BaseScreen(Screen): CloseButton(wri) # Quit the application def test(): - if display.height < 128 or display.width < 240: + if ssd.height < 128 or ssd.width < 240: print('This test requires a display of at least 240x128 pixels.') else: print('Testing micro-gui...') diff --git a/gui/demos/tbox.py b/gui/demos/tbox.py index 2155a66..2ac4bdb 100644 --- a/gui/demos/tbox.py +++ b/gui/demos/tbox.py @@ -7,7 +7,7 @@ # import gui.demos.tbox # Initialise hardware and framebuf before importing modules. -from hardware_setup import display, ssd # Create a display instance +from hardware_setup import ssd # Create a display instance from gui.core.ugui import Screen from gui.core.writer import CWriter @@ -111,7 +111,7 @@ class MainScreen(Screen): def test(): - if display.height < 128 or display.width < 128: + if ssd.height < 128 or ssd.width < 128: print(' This test requires a display of at least 128x128 pixels.') else: print('Testing micro-gui...') diff --git a/gui/demos/various.py b/gui/demos/various.py index b21cdef..8ccfd8e 100644 --- a/gui/demos/various.py +++ b/gui/demos/various.py @@ -1,8 +1,9 @@ # various.py micro-gui demo of multiple controls on a large display # Initialise hardware and framebuf before importing modules. -# Import SSD and Display instances. Must be done first because of RAM use. -from hardware_setup import display, ssd # Create a display instance +# Create SSD instance. Must be done first because of RAM use. +from hardware_setup import ssd + from gui.core.ugui import Screen from gui.core.writer import CWriter import gui.fonts.arial10 as arial10 # Font for CWriter @@ -159,7 +160,7 @@ async def run(dial, lbltim, m0, scale): def test(): - if display.height < 240 or display.width < 320: + if ssd.height < 240 or ssd.width < 320: print(' This test requires a display of at least 320x240 pixels.') else: print('Testing micro-gui...') diff --git a/gui/demos/vtest.py b/gui/demos/vtest.py index 65f896a..1ddb7c7 100644 --- a/gui/demos/vtest.py +++ b/gui/demos/vtest.py @@ -3,8 +3,8 @@ # Released under the MIT License (MIT). See LICENSE. # Copyright (c) 2021 Peter Hinch -# Initialise hardware and framebuf before importing modules. -from hardware_setup import display, ssd # Create a display instance +# Create SSD instance. Must be done first because of RAM use. +from hardware_setup import ssd import urandom import time @@ -104,7 +104,7 @@ class VScreen(Screen): self.reg_task(aclock(dial, lbldate, lbltim)) def test(): - if display.height < 240 or display.width < 320: + if ssd.height < 240 or ssd.width < 320: print(' This test requires a display of at least 320x240 pixels.') else: print('Testing micro-gui...')