init weather_station repo
This commit is contained in:
65
docs/Nanoweb.md
Normal file
65
docs/Nanoweb.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Nanoweb
|
||||
|
||||
Nanoweb is a full asynchronous web server for micropython created in order to benefit from
|
||||
a correct ratio between memory size and features.
|
||||
|
||||
It is thus able to run on an ESP8266, ESP32, Raspberry Pico, etc...
|
||||
|
||||
## Features
|
||||
|
||||
* Completely asynchronous
|
||||
* Declaration of routes via a dictionary or directly by decorator
|
||||
* Management of static files (see assets_extensions)
|
||||
* Callbacks functions when a new query or an error occurs
|
||||
* Extraction of HTML headers
|
||||
* User code dense and conci
|
||||
* Routing wildcards
|
||||
|
||||
## Installation
|
||||
|
||||
You just have to copy the `nanoweb.py` file on the target (ESP32, Nano, etc...).
|
||||
|
||||
## Use
|
||||
|
||||
See the [example.py](example.py) file for an advanced example where you will be able to:
|
||||
|
||||
* Make a JSON response
|
||||
* Use pages protected with credentials
|
||||
* Upload file
|
||||
* Use `DELETE` method
|
||||
* Read `POST` data
|
||||
|
||||
And this is a simpler example:
|
||||
|
||||
```Python
|
||||
import uasyncio
|
||||
from nanoweb import Nanoweb
|
||||
|
||||
naw = Nanoweb()
|
||||
|
||||
async def api_status(request):
|
||||
"""API status endpoint"""
|
||||
await request.write("HTTP/1.1 200 OK\r\n")
|
||||
await request.write("Content-Type: application/json\r\n\r\n")
|
||||
await request.write('{"status": "running"}')
|
||||
|
||||
# You can declare route from the Nanoweb routes dict...
|
||||
naw.routes = {
|
||||
'/api/status': api_status,
|
||||
}
|
||||
|
||||
# ... or declare route directly from the Nanoweb route decorator
|
||||
@naw.route("/ping")
|
||||
async def ping(request):
|
||||
await request.write("HTTP/1.1 200 OK\r\n\r\n")
|
||||
await request.write("pong")
|
||||
|
||||
loop = uasyncio.get_event_loop()
|
||||
loop.create_task(naw.run())
|
||||
loop.run_forever()
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
* Your code must respects `flake8` and `isort` tools
|
||||
* Format your commits with `Commit Conventional` (https://www.conventionalcommits.org/en/v1.0.0/)
|
||||
322
docs/mp_optimize_demo.md
Normal file
322
docs/mp_optimize_demo.md
Normal file
@@ -0,0 +1,322 @@
|
||||
# Micropython程序优化实例
|
||||
|
||||
这个优化例子来自 Damien 在 pycomau 上的演讲使用MicroPython高效快速编程。
|
||||
|
||||
首先我们看下面的程序,它在循环中翻转LED,然后通过运行的时间和翻转次数,计算出每秒翻转的频率。
|
||||
|
||||
```py
|
||||
from machine import Pin
|
||||
import time
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
t0 = time.ticks_us()
|
||||
|
||||
for i in range(N):
|
||||
led.on()
|
||||
led.off()
|
||||
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / N, N / dt * 1e3))
|
||||
```
|
||||
|
||||
我们将这段代码保存为文件led1.py,然后import led1执行。在pybv10或者pyboardCN上结果是:
|
||||
|
||||
> 3.381 sec, 16.905 usec/blink : 59.16 kblink/sec
|
||||
|
||||
在 MicroPython程序优化原则 中,提到尽量在程序中执行功能,不要在主程序中运行,因此可以将LED翻转放在函数中执行。
|
||||
|
||||
```py
|
||||
from machine import Pin
|
||||
import time
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
def blink_simple(n):
|
||||
for i in range(n):
|
||||
led.on()
|
||||
led.off()
|
||||
|
||||
def time_it(f, n):
|
||||
t0 = time.ticks_us()
|
||||
f(n)
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / n, n / dt * 1e3))
|
||||
|
||||
time_it(blink_simple, N)
|
||||
```
|
||||
|
||||
|
||||
运行后的结果是:
|
||||
|
||||
> 2.902 sec, 14.509 usec/blink : 68.92 kblink/sec
|
||||
|
||||
可以看到,我们没有做什么实质的改到,就明显提高了速度。
|
||||
|
||||
循环是最消耗运行时间的,我们对循环中led.on()和led.off()两个动作进行优化,将它们预先载入内存,而无需循环中每次载入。
|
||||
|
||||
```
|
||||
from machine import Pin
|
||||
import time
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
def blink_simple(n):
|
||||
on = led.on
|
||||
off = led.off
|
||||
for i in range(n):
|
||||
on()
|
||||
off()
|
||||
|
||||
def time_it(f, n):
|
||||
t0 = time.ticks_us()
|
||||
f(n)
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / n, n / dt * 1e3))
|
||||
|
||||
time_it(blink_simple, N)
|
||||
```
|
||||
|
||||
运行结果是
|
||||
|
||||
> 1.617 sec, 8.086 usec/blink : 123.68 kblink/sec
|
||||
|
||||
速度提高了将近一倍。
|
||||
|
||||
进一步将循环中对 range(n) 也进行优化
|
||||
|
||||
```py
|
||||
from machine import Pin
|
||||
import time
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
def blink_simple(n):
|
||||
on = led.on
|
||||
off = led.off
|
||||
r = range(n)
|
||||
for i in r:
|
||||
on()
|
||||
off()
|
||||
|
||||
def time_it(f, n):
|
||||
t0 = time.ticks_us()
|
||||
f(n)
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / n, n / dt * 1e3))
|
||||
|
||||
time_it(blink_simple, N)
|
||||
```
|
||||
|
||||
|
||||
运行结果是
|
||||
|
||||
> 1.121 sec, 5.607 usec/blink : 178.35 kblink/sec
|
||||
|
||||
效果非常明显。
|
||||
|
||||
进一步对循环中的操作优化,减少循环次数
|
||||
|
||||
```py
|
||||
from machine import Pin
|
||||
import time
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
def blink_simple(n):
|
||||
n //= 8
|
||||
on = led.on
|
||||
off = led.off
|
||||
r = range(n)
|
||||
for i in r:
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
|
||||
def time_it(f, n):
|
||||
t0 = time.ticks_us()
|
||||
f(n)
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / n, n / dt * 1e3))
|
||||
|
||||
time_it(blink_simple, N)
|
||||
```
|
||||
|
||||
速度又有明显提升。
|
||||
|
||||
> 0.913 sec, 4.563 usec/blink : 219.16 kblink/sec
|
||||
|
||||
根据MicroPython的优化功能,可以将程序声明为native code(本地代码),它使用CPU的操作码(opcode),而不是字节码(bytecode)
|
||||
|
||||
```py
|
||||
from machine import Pin
|
||||
import time
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
@micropython.native
|
||||
def blink_simple(n):
|
||||
n //= 8
|
||||
on = led.on
|
||||
off = led.off
|
||||
r = range(n)
|
||||
for i in r:
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
on()
|
||||
off()
|
||||
|
||||
def time_it(f, n):
|
||||
t0 = time.ticks_us()
|
||||
f(n)
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / n, n / dt * 1e3))
|
||||
|
||||
time_it(blink_simple, N)
|
||||
```
|
||||
|
||||
结果如下
|
||||
|
||||
> 0.704 sec, 3.521 usec/blink : 284.00 kblink/sec
|
||||
|
||||
除了native,还可以使用viper code模式,它进一步提升了整数计算和位操作性能
|
||||
|
||||
```py
|
||||
from machine import Pin
|
||||
import time, stm
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
@micropython.viper
|
||||
def blink_simple(n:int):
|
||||
n //= 8
|
||||
p = ptr16(stm.GPIOB + stm.GPIO_BSRR)
|
||||
for i in range(n):
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
p[0] = 1 << 4
|
||||
p[1] = 1 << 4
|
||||
|
||||
def time_it(f, n):
|
||||
t0 = time.ticks_us()
|
||||
f(n)
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / n, n / dt * 1e3))
|
||||
|
||||
time_it(blink_simple, N)
|
||||
```
|
||||
|
||||
运行结果的确是大幅提升了性能
|
||||
|
||||
> 0.016 sec, 0.078 usec/blink : 12879.13 kblink/sec
|
||||
|
||||
最终我们还可以通过嵌入汇编方式,最大限度提升性能
|
||||
|
||||
```py
|
||||
from machine import Pin
|
||||
import time, stm
|
||||
|
||||
led = Pin('A13')
|
||||
N = 200000
|
||||
|
||||
@micropython.asm_thumb
|
||||
def blink_simple(r0):
|
||||
lsr(r0, r0, 3)
|
||||
movwt(r1, stm.GPIOB + stm.GPIO_BSRR)
|
||||
mov(r2, 1 << 4)
|
||||
label(loop)
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
strh(r2, [r1, 0])
|
||||
strh(r2, [r1, 2])
|
||||
sub(r0, 1)
|
||||
bne(loop)
|
||||
|
||||
def time_it(f, n):
|
||||
t0 = time.ticks_us()
|
||||
f(n)
|
||||
t1 = time.ticks_us()
|
||||
dt = time.ticks_diff(t1, t0)
|
||||
fmt = '{:5.3f} sec, {:6.3f} usec/blink : {:8.2f} kblink/sec'
|
||||
print(fmt.format(dt * 1e-6, dt / n, n / dt * 1e3))
|
||||
|
||||
time_it(blink_simple, N)
|
||||
```
|
||||
|
||||
运行结果是
|
||||
|
||||
> 0.007 sec, 0.037 usec/blink : 27322.40 kblink/sec
|
||||
|
||||
这个结果已经非常接近极限了。
|
||||
|
||||
从前面的优化顺序,可以看到我们并没有大幅修改程序,就可以极高程序的性能。实际使用中,大家可以灵活选择,提高程序的性能。
|
||||
762
docs/mpremote.rst
Normal file
762
docs/mpremote.rst
Normal file
@@ -0,0 +1,762 @@
|
||||
.. _mpremote:
|
||||
|
||||
MicroPython remote control: mpremote
|
||||
====================================
|
||||
|
||||
The ``mpremote`` command line tool provides an integrated set of utilities to
|
||||
remotely interact with, manage the filesystem on, and automate a MicroPython
|
||||
device over a serial connection.
|
||||
|
||||
To use mpremote, first install it via ``pip``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install --user mpremote
|
||||
|
||||
Or via `pipx <https://pypa.github.io/pipx/>`_:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pipx install mpremote
|
||||
|
||||
The simplest way to use this tool is just by invoking it without any arguments:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote
|
||||
|
||||
This command automatically detects and connects to the first available USB
|
||||
serial device and provides an interactive terminal that you can use to access
|
||||
the REPL and your program's output. Serial ports are opened in exclusive mode,
|
||||
so running a second (or third, etc) instance of ``mpremote`` will connect to
|
||||
subsequent serial devices, if any are available.
|
||||
|
||||
Additionally ``pipx`` also allows you to directly run ``mpremote`` without
|
||||
installing first:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pipx run mpremote ...args
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
``mpremote`` supports being given a series of commands given at the command line
|
||||
which will perform various actions in sequence on a remote MicroPython device.
|
||||
See the :ref:`examples section <mpremote_examples>` below to get an idea of how
|
||||
this works and for some common combinations of commands.
|
||||
|
||||
Each command is of the form ``<command name> [--options] [args...]``. For commands
|
||||
that support multiple arguments (e.g. a list of files), the argument list can
|
||||
be terminated with ``+``.
|
||||
|
||||
If no command is specified, the default command is ``repl``. Additionally, if
|
||||
any command needs to access the device, and no earlier ``connect`` has been
|
||||
specified, then an implicit ``connect auto`` is added.
|
||||
|
||||
In order to get the device into a known state for any action command
|
||||
(except ``repl``), once connected ``mpremote`` will stop any running program
|
||||
and soft-reset the device before running the first command. You can control
|
||||
this behavior using the ``resume`` and ``soft-reset`` commands.
|
||||
See :ref:`auto-connection and auto-soft-reset <mpremote_reset>` for more details.
|
||||
|
||||
Multiple commands can be specified and they will be run sequentially.
|
||||
|
||||
The full list of supported commands are:
|
||||
|
||||
- `connect <mpremote_command_connect>`
|
||||
- `disconnect <mpremote_command_disconnect>`
|
||||
- `resume <mpremote_command_resume>`
|
||||
- `soft_reset <mpremote_command_soft_reset>`
|
||||
- `repl <mpremote_command_repl>`
|
||||
- `eval <mpremote_command_eval>`
|
||||
- `exec <mpremote_command_exec>`
|
||||
- `run <mpremote_command_run>`
|
||||
- `fs <mpremote_command_fs>`
|
||||
- `df <mpremote_command_df>`
|
||||
- `edit <mpremote_command_edit>`
|
||||
- `mip <mpremote_command_mip>`
|
||||
- `mount <mpremote_command_mount>`
|
||||
- `unmount <mpremote_command_unmount>`
|
||||
- `romfs <mpremote_command_romfs>`
|
||||
- `rtc <mpremote_command_rtc>`
|
||||
- `sleep <mpremote_command_sleep>`
|
||||
- `reset <mpremote_command_reset>`
|
||||
- `bootloader <mpremote_command_bootloader>`
|
||||
|
||||
.. _mpremote_command_connect:
|
||||
|
||||
- **connect** -- connect to specified device via name:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote connect <device>
|
||||
|
||||
``<device>`` may be one of:
|
||||
|
||||
- ``list``: list available devices
|
||||
- ``auto``: connect to the first available USB serial port
|
||||
- ``id:<serial>``: connect to the device with USB serial number
|
||||
``<serial>`` (the second column from the ``connect list``
|
||||
command output)
|
||||
- ``port:<path>``: connect to the device with the given path (the first column
|
||||
from the ``connect list`` command output
|
||||
- ``rfc2217://<host>:<port>``: connect to the device using serial over TCP
|
||||
(e.g. a networked serial port based on RFC2217)
|
||||
- any valid device name/path, to connect to that device
|
||||
|
||||
**Note:** Instead of using the ``connect`` command, there are several
|
||||
:ref:`pre-defined shortcuts <mpremote_shortcuts>` for common device paths. For
|
||||
example the ``a0`` shortcut command is equivalent to
|
||||
``connect /dev/ttyACM0`` (Linux), or ``c1`` for ``COM1`` (Windows).
|
||||
|
||||
**Note:** The ``auto`` option will only detect USB serial ports, i.e. a serial
|
||||
port that has an associated USB VID/PID (i.e. CDC/ACM or FTDI-style
|
||||
devices). Other types of serial ports will not be auto-detected.
|
||||
|
||||
.. _mpremote_command_disconnect:
|
||||
|
||||
- **disconnect** -- disconnect current device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote disconnect
|
||||
|
||||
After a disconnect, :ref:`auto-soft-reset <mpremote_reset>` is enabled.
|
||||
|
||||
.. _mpremote_command_resume:
|
||||
|
||||
- **resume** -- maintain existing interpreter state for subsequent commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote resume
|
||||
|
||||
This disables :ref:`auto-soft-reset <mpremote_reset>`. This is useful if you
|
||||
want to run a subsequent command on a board without first soft-resetting it.
|
||||
|
||||
.. _mpremote_command_soft_reset:
|
||||
|
||||
- **soft-reset** -- perform a soft-reset of the device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote soft-reset
|
||||
|
||||
This will clear out the Python heap and restart the interpreter. It also
|
||||
prevents the subsequent command from triggering :ref:`auto-soft-reset <mpremote_reset>`.
|
||||
|
||||
.. _mpremote_command_repl:
|
||||
|
||||
- **repl** -- enter the REPL on the connected device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote repl [--options]
|
||||
|
||||
Options are:
|
||||
|
||||
- ``--escape-non-printable``, to print non-printable bytes/characters as their hex code
|
||||
- ``--capture <file>``, to capture output of the REPL session to the given
|
||||
file
|
||||
- ``--inject-code <string>``, to specify characters to inject at the REPL when
|
||||
``Ctrl-J`` is pressed. This allows you to automate a common command.
|
||||
- ``--inject-file <file>``, to specify a file to inject at the REPL when
|
||||
``Ctrl-K`` is pressed. This allows you to run a file (e.g. containing some
|
||||
useful setup code, or even the program you are currently working on).
|
||||
|
||||
While the ``repl`` command running, you can use ``Ctrl-]`` or ``Ctrl-x`` to
|
||||
exit.
|
||||
|
||||
**Note:** The name "REPL" here reflects that the common usage of this command
|
||||
to access the Read Eval Print Loop that is running on the MicroPython
|
||||
device. Strictly, the ``repl`` command is just functioning as a terminal
|
||||
(or "serial monitor") to access the device. Because this command does not
|
||||
trigger the :ref:`auto-reset behavior <mpremote_reset>`, this means that if
|
||||
a program is currently running, you will first need to interrupt it with
|
||||
``Ctrl-C`` to get to the REPL, which will then allow you to access program
|
||||
state. You can also use ``mpremote soft-reset repl`` to get a "clean" REPL
|
||||
with all program state cleared.
|
||||
|
||||
.. _mpremote_command_eval:
|
||||
|
||||
- **eval** -- evaluate and print the result of a Python expression:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote eval <string>
|
||||
|
||||
.. _mpremote_command_exec:
|
||||
|
||||
- **exec** -- execute the given Python code:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote exec <string>
|
||||
|
||||
By default, ``mpremote exec`` will display any output from the expression until it
|
||||
terminates. The ``--no-follow`` flag can be specified to return immediately and leave
|
||||
the device running the expression in the background.
|
||||
|
||||
.. _mpremote_command_run:
|
||||
|
||||
- **run** -- run a script from the local filesystem:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote run <file.py>
|
||||
|
||||
This will execute the file directly from RAM on the device without copying it
|
||||
to the filesystem. This is a very useful way to iterate on the development of
|
||||
a single piece of code without having to worry about deploying it to the
|
||||
filesystem.
|
||||
|
||||
By default, ``mpremote run`` will display any output from the script until it
|
||||
terminates. The ``--no-follow`` flag can be specified to return immediately and leave
|
||||
the device running the script in the background.
|
||||
|
||||
.. _mpremote_command_fs:
|
||||
|
||||
- **fs** -- execute filesystem commands on the device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote fs <sub-command>
|
||||
|
||||
``<sub-command>`` may be:
|
||||
|
||||
- ``cat <file..>`` to show the contents of a file or files on the device
|
||||
- ``ls`` to list the current directory
|
||||
- ``ls <dirs...>`` to list the given directories
|
||||
- ``cp [-rf] <src...> <dest>`` to copy files
|
||||
- ``rm [-r] <src...>`` to remove files or folders on the device
|
||||
- ``mkdir <dirs...>`` to create directories on the device
|
||||
- ``rmdir <dirs...>`` to remove directories on the device
|
||||
- ``touch <file..>`` to create the files (if they don't already exist)
|
||||
- ``sha256sum <file..>`` to calculate the SHA256 sum of files
|
||||
- ``tree [-vsh] <dirs...>`` to print a tree of the given directories
|
||||
|
||||
The ``cp`` command uses a convention where a leading ``:`` represents a remote
|
||||
path. Without a leading ``:`` means a local path. This is based on the
|
||||
convention used by the `Secure Copy Protocol (scp) client
|
||||
<https://en.wikipedia.org/wiki/Secure_copy_protocol>`_.
|
||||
|
||||
So for example, ``mpremote fs cp main.py :main.py`` copies ``main.py`` from
|
||||
the current local directory to the remote filesystem, whereas
|
||||
``mpremote fs cp :main.py main.py`` copies ``main.py`` from the device back
|
||||
to the current directory.
|
||||
|
||||
The ``mpremote rm -r`` command accepts both relative and absolute paths.
|
||||
Use ``:`` to refer to the current remote working directory (cwd) to allow a
|
||||
directory tree to be removed from the device's default path (eg ``/flash``, ``/``).
|
||||
Use ``-v/--verbose`` to see the files being removed.
|
||||
|
||||
For example:
|
||||
|
||||
- ``mpremote rm -r :libs`` will remove the ``libs`` directory and all its
|
||||
child items from the device.
|
||||
- ``mpremote rm -rv :/sd`` will remove all files from a mounted SDCard and result
|
||||
in a non-blocking warning. The mount will be retained.
|
||||
- ``mpremote rm -rv :/`` will remove all files on the device, including any
|
||||
located in mounted vfs such as ``/sd`` or ``/flash``. After removing all folders
|
||||
and files, this will also return an error to mimic unix ``rm -rf /`` behaviour.
|
||||
|
||||
.. warning::
|
||||
There is no supported way to undelete files removed by ``mpremote rm -r :``.
|
||||
Please use with caution.
|
||||
|
||||
The ``tree`` command will print a tree of the given directories.
|
||||
Using the ``--size/-s`` option will print the size of each file, or use
|
||||
``--human/-h`` to use a more human readable format.
|
||||
Note: Directory size is only printed when a non-zero size is reported by the device's filesystem.
|
||||
The ``-v`` option can be used to include the name of the serial device in
|
||||
the output.
|
||||
|
||||
All other commands implicitly assume the path is a remote path, but the ``:``
|
||||
can be optionally used for clarity.
|
||||
|
||||
All of the filesystem sub-commands take multiple path arguments, so if there
|
||||
is another command in the sequence, you must use ``+`` to terminate the
|
||||
arguments, e.g.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote fs cp main.py :main.py + repl
|
||||
|
||||
This will copy the file to the device then enter the REPL. The ``+`` prevents
|
||||
``"repl"`` being interpreted as a path.
|
||||
|
||||
The ``cp`` command supports the ``-r`` option to make a recursive copy. By
|
||||
default ``cp`` will skip copying files to the remote device if the SHA256 hash
|
||||
of the source and destination file matches. To force a copy regardless of the
|
||||
hash use the ``-f`` option.
|
||||
|
||||
**Note:** For convenience, all of the filesystem sub-commands are also
|
||||
:ref:`aliased as regular commands <mpremote_shortcuts>`, i.e. you can write
|
||||
``mpremote cp ...`` instead of ``mpremote fs cp ...``.
|
||||
|
||||
.. _mpremote_command_df:
|
||||
|
||||
- **df** -- query device free/used space
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote df
|
||||
|
||||
The ``df`` command will print size/used/free statistics for the device
|
||||
filesystem, similar to the Unix ``df`` command.
|
||||
|
||||
.. _mpremote_command_edit:
|
||||
|
||||
- **edit** -- edit a file on the device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote edit <files...>
|
||||
|
||||
The ``edit`` command will copy each file from the device to a local temporary
|
||||
directory and then launch your editor for each file (defined by the environment
|
||||
variable ``$EDITOR``). If the editor exits successfully, the updated file will
|
||||
be copied back to the device.
|
||||
|
||||
.. _mpremote_command_mip:
|
||||
|
||||
- **mip** -- install packages from :term:`micropython-lib` (or GitHub) using the ``mip`` tool:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote mip install <packages...>
|
||||
|
||||
See :ref:`packages` for more information.
|
||||
|
||||
.. _mpremote_command_mount:
|
||||
|
||||
- **mount** -- mount the local directory on the remote device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote mount [options] <local-dir>
|
||||
|
||||
This allows the remote device to see the local host directory as if it were
|
||||
its own filesystem. This is useful for development, and avoids the need to
|
||||
copy files to the device while you are working on them.
|
||||
|
||||
The device installs a filesystem driver, which is then mounted in the
|
||||
:ref:`device VFS <filesystem>` as ``/remote``, which uses the serial
|
||||
connection to ``mpremote`` as a side-channel to access files. The device
|
||||
will have its current working directory (via ``os.chdir``) set to
|
||||
``/remote`` so that imports and file access will occur there instead of the
|
||||
default filesystem path while the mount is active.
|
||||
|
||||
**Note:** If the ``mount`` command is not followed by another action in the
|
||||
sequence, a ``repl`` command will be implicitly added to the end of the
|
||||
sequence.
|
||||
|
||||
During usage, Ctrl-D will trigger a soft-reset as normal, but the mount will
|
||||
automatically be re-connected. If the unit has a main.py running at startup
|
||||
however the remount cannot occur. In this case a raw mode soft reboot can be
|
||||
used: Ctrl-A Ctrl-D to reboot, then Ctrl-B to get back to normal repl at
|
||||
which point the mount will be ready.
|
||||
|
||||
Options are:
|
||||
|
||||
- ``-l``, ``--unsafe-links``: By default an error will be raised if the device
|
||||
accesses a file or directory which is outside (up one or more directory levels) the
|
||||
local directory that is mounted. This option disables this check for symbolic
|
||||
links, allowing the device to follow symbolic links outside of the local directory.
|
||||
|
||||
.. _mpremote_command_unmount:
|
||||
|
||||
- **unmount** -- unmount the local directory from the remote device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote umount
|
||||
|
||||
This happens automatically when ``mpremote`` terminates, but it can be used
|
||||
in a sequence to unmount an earlier mount before subsequent command are run.
|
||||
|
||||
.. _mpremote_command_romfs:
|
||||
|
||||
- **romfs** -- manage ROMFS partitions on the device:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote romfs <sub-command>
|
||||
|
||||
``<sub-command>`` may be:
|
||||
|
||||
- ``romfs query`` to list all the available ROMFS partitions and their size
|
||||
- ``romfs [-o <output>] build <source>`` to create a ROMFS image from the given
|
||||
source directory; the default output file is the source appended by ``.romfs``
|
||||
- ``romfs [-p <partition>] deploy <source>`` to deploy a ROMFS image to the device;
|
||||
will also create a temporary ROMFS image if the source is a directory
|
||||
|
||||
The ``build`` and ``deploy`` sub-commands both support the ``-m``/``--mpy`` option
|
||||
to automatically compile ``.py`` files to ``.mpy`` when creating the ROMFS image.
|
||||
This option is enabled by default, but only works if the ``mpy_cross`` Python
|
||||
package has been installed (eg via ``pip install mpy_cross``). If the package is
|
||||
not installed then a warning is printed and ``.py`` files remain as is. Compiling
|
||||
of ``.py`` files can be disabled with the ``--no-mpy`` option.
|
||||
|
||||
.. _mpremote_command_rtc:
|
||||
|
||||
- **rtc** -- set/get the device clock (RTC):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote rtc
|
||||
|
||||
This will query the device RTC for the current time and print it as a datetime
|
||||
tuple.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote rtc --set
|
||||
|
||||
This will set the device RTC to the host PC's current time.
|
||||
|
||||
.. _mpremote_command_sleep:
|
||||
|
||||
- **sleep** -- sleep (delay) before executing the next command
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote sleep 0.5
|
||||
|
||||
This will pause execution of the command sequence for the specified duration
|
||||
in seconds, e.g. to wait for the device to do something.
|
||||
|
||||
.. _mpremote_command_reset:
|
||||
|
||||
- **reset** -- hard reset the device
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote reset
|
||||
|
||||
**Note:** hard reset is equivalent to :func:`machine.reset`.
|
||||
|
||||
.. _mpremote_command_bootloader:
|
||||
|
||||
- **bootloader** enter the bootloader
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote bootloader
|
||||
|
||||
This will make the device enter its bootloader. The bootloader is port- and
|
||||
board-specific (e.g. DFU on stm32, UF2 on rp2040/Pico).
|
||||
|
||||
.. _mpremote_reset:
|
||||
|
||||
Auto connection and soft-reset
|
||||
------------------------------
|
||||
|
||||
Connection and disconnection will be done automatically at the start and end of
|
||||
the execution of the tool, if such commands are not explicitly given. Automatic
|
||||
connection will search for the first available USB serial device.
|
||||
|
||||
Once connected to a device, ``mpremote`` will automatically soft-reset the
|
||||
device if needed. This clears the Python heap and restarts the interpreter,
|
||||
making sure that subsequent Python code executes in a fresh environment. Auto
|
||||
soft-reset is performed the first time one of the following commands are
|
||||
executed: ``mount``, ``eval``, ``exec``, ``run``, ``fs``. After doing a
|
||||
soft-reset for the first time, it will not be done again automatically, until a
|
||||
``disconnect`` command is issued.
|
||||
|
||||
Auto-soft-reset behaviour can be controlled by the ``resume`` command. This
|
||||
might be useful to use the ``eval`` command to inspect the state of of the
|
||||
device. The ``soft-reset`` command can be used to perform an explicit soft
|
||||
reset in the middle of a sequence of commands.
|
||||
|
||||
.. _mpremote_shortcuts:
|
||||
|
||||
Shortcuts
|
||||
---------
|
||||
|
||||
Shortcuts can be defined using the macro system. Built-in shortcuts are:
|
||||
|
||||
- ``devs``: Alias for ``connect list``
|
||||
|
||||
- ``a0``, ``a1``, ``a2``, ``a3``: Aliases for ``connect /dev/ttyACMn``
|
||||
|
||||
- ``u0``, ``u1``, ``u2``, ``u3``: Aliases for ``connect /dev/ttyUSBn``
|
||||
|
||||
- ``c0``, ``c1``, ``c2``, ``c3``: Aliases for ``connect COMn``
|
||||
|
||||
- ``cat``, ``edit``, ``ls``, ``cp``, ``rm``, ``mkdir``, ``rmdir``, ``touch``: Aliases for ``fs <sub-command>``
|
||||
|
||||
Additional shortcuts can be defined in the user configuration file ``mpremote/config.py``,
|
||||
located in the User Configuration Directory.
|
||||
The correct location for each OS is determined using the ``platformdirs`` module.
|
||||
|
||||
This is typically:
|
||||
- ``$XDG_CONFIG_HOME/mpremote/config.py``
|
||||
- ``$HOME/.config/mpremote/config.py``
|
||||
- ``$env:LOCALAPPDATA/mpremote/config.py``
|
||||
|
||||
The ``config.py``` file should define a dictionary named ``commands``. The keys of this dictionary are the shortcuts
|
||||
and the values are either a string or a list-of-strings:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
"c33": "connect id:334D335C3138",
|
||||
|
||||
The command ``c33`` is replaced by ``connect id:334D335C3138``.
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
"test": ["mount", ".", "exec", "import test"],
|
||||
|
||||
The command ``test`` is replaced by ``mount . exec "import test"``.
|
||||
|
||||
Shortcuts can also accept arguments. For example:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
"multiply x=4 y=7": "eval x*y",
|
||||
|
||||
Running ``mpremote times 3 7`` will set ``x`` and ``y`` as variables on the device, then evaluate the expression ``x*y``.
|
||||
|
||||
An example ``config.py`` might look like:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
commands = {
|
||||
"c33": "connect id:334D335C3138", # Connect to a specific device by ID.
|
||||
"bl": "bootloader", # Shorter alias for bootloader.
|
||||
"double x=4": "eval x*2", # x is an argument, with default 4
|
||||
"wl_scan": ["exec", """
|
||||
import network
|
||||
wl = network.WLAN()
|
||||
wl.active(1)
|
||||
for ap in wl.scan():
|
||||
print(ap)
|
||||
""",], # Print out nearby WiFi networks.
|
||||
"wl_ipconfig": [
|
||||
"exec",
|
||||
"import network; sta_if = network.WLAN(network.WLAN.IF_STA); print(sta_if.ipconfig('addr4'))",
|
||||
""",], # Print ip address of station interface.
|
||||
"test": ["mount", ".", "exec", "import test"], # Mount current directory and run test.py.
|
||||
"demo": ["run", "path/to/demo.py"], # Execute demo.py on the device.
|
||||
}
|
||||
|
||||
.. _mpremote_examples:
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote
|
||||
|
||||
Connect to the first available device and implicitly run the ``repl`` command.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote a1
|
||||
|
||||
Connect to the device at ``/dev/ttyACM1`` (Linux) and implicitly run the
|
||||
``repl`` command. See :ref:`shortcuts <mpremote_shortcuts>` above.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote c1
|
||||
|
||||
Connect to the device at ``COM1`` (Windows) and implicitly run the ``repl``
|
||||
command. See :ref:`shortcuts <mpremote_shortcuts>` above.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote connect /dev/ttyUSB0
|
||||
|
||||
Explicitly specify which device to connect to, and as above, implicitly run the
|
||||
``repl`` command.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote a1 ls
|
||||
|
||||
Connect to the device at ``/dev/ttyACM0`` and then run the ``ls`` command.
|
||||
|
||||
It is equivalent to ``mpremote connect /dev/ttyACM1 fs ls``.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote exec "import micropython; micropython.mem_info()"
|
||||
|
||||
Run the specified Python command and display any output. This is equivalent to
|
||||
typing the command at the REPL prompt.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote eval 1/2 eval 3/4
|
||||
|
||||
Evaluate each expression in turn and print the results.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote a0 eval 1/2 a1 eval 3/4
|
||||
|
||||
Evaluate ``1/2`` on the device at ``/dev/ttyACM0``, then ``3/4`` on the
|
||||
device at ``/dev/ttyACM1``, printing each result.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote resume exec "print_state_info()" soft-reset
|
||||
|
||||
Connect to the device without triggering a :ref:`soft reset <soft_reset>` and
|
||||
execute the ``print_state_info()`` function (e.g. to find out information about
|
||||
the current program state), then trigger a soft reset.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote reset sleep 0.5 bootloader
|
||||
|
||||
Hard-reset the device, wait 500ms for it to become available, then enter the
|
||||
bootloader.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp utils/driver.py :utils/driver.py + run test.py
|
||||
|
||||
Update the copy of utils/driver.py on the device, then execute the local
|
||||
``test.py`` script on the device. ``test.py`` is never copied to the device
|
||||
filesystem, rather it is run from RAM.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp utils/driver.py :utils/driver.py + exec "import app"
|
||||
|
||||
Update the copy of utils/driver.py on the device, then execute app.py on the
|
||||
device.
|
||||
|
||||
This is a common development workflow to update a single file and then re-start
|
||||
your program. In this scenario, your ``main.py`` on the device would also do
|
||||
``import app``.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp utils/driver.py :utils/driver.py + soft-reset repl
|
||||
|
||||
Update the copy of utils/driver.py on the device, then trigger a soft-reset to
|
||||
restart your program, and then monitor the output via the ``repl`` command.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp -r utils/ :utils/ + soft-reset repl
|
||||
|
||||
Same as above, but update the entire utils directory first.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mount .
|
||||
|
||||
Mount the current local directory at ``/remote`` on the device and starts a
|
||||
``repl`` session which will use ``/remote`` as the working directory.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mount . exec "import demo"
|
||||
|
||||
After mounting the current local directory, executes ``demo.py`` from the
|
||||
mounted directory.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mount app run test.py
|
||||
|
||||
After mounting the local directory ``app`` as ``/remote`` on the device,
|
||||
executes the local ``test.py`` from the host's current directory without
|
||||
copying it to the filesystem.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mount . repl --inject-code "import demo"
|
||||
|
||||
After mounting the current local directory, executes ``demo.py`` from the
|
||||
mounted directory each time ``Ctrl-J`` is pressed.
|
||||
|
||||
You will first need to press ``Ctrl-D`` to reset the interpreter state
|
||||
(which will preserve the mount) before pressing ``Ctrl-J`` to re-import
|
||||
``demo.py``.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mount app repl --inject-file demo.py
|
||||
|
||||
Same as above, but executes the contents of the local file demo.py at the REPL
|
||||
every time ``Ctrl-K`` is pressed. As above, use Ctrl-D to reset the interpreter
|
||||
state first.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cat boot.py
|
||||
|
||||
Displays the contents of ``boot.py`` on the device.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote edit utils/driver.py
|
||||
|
||||
Edit ``utils/driver.py`` on the device using your local ``$EDITOR``.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp :main.py .
|
||||
|
||||
Copy ``main.py`` from the device to the local directory.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp main.py :
|
||||
|
||||
Copy ``main.py`` from the local directory to the device.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp :a.py :b.py
|
||||
|
||||
Copy ``a.py`` on the device to ``b.py`` on the device.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp -r dir/ :
|
||||
|
||||
Recursively copy the local directory ``dir`` to the remote device.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote cp a.py b.py : + repl
|
||||
|
||||
Copy ``a.py`` and ``b.py`` from the local directory to the device, then run the
|
||||
``repl`` command.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mip install aioble
|
||||
|
||||
Install the ``aioble`` package from :term:`micropython-lib` to the device.
|
||||
See :ref:`packages`.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mip install github:org/repo@branch
|
||||
|
||||
Install the package from the specified branch at org/repo on GitHub to the
|
||||
device. See :ref:`packages`.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mip install gitlab:org/repo@branch
|
||||
|
||||
Install the package from the specified branch at org/repo on GitLab to the
|
||||
device. See :ref:`packages`.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote mip install --target /flash/third-party functools
|
||||
|
||||
Install the ``functools`` package from :term:`micropython-lib` to the
|
||||
``/flash/third-party`` directory on the device. See :ref:`packages`.
|
||||
746
docs/st7789_mpy.md
Normal file
746
docs/st7789_mpy.md
Normal file
@@ -0,0 +1,746 @@
|
||||
|
||||
# ST7789 Driver for MicroPython
|
||||
|
||||
This driver is based on [devbis' st7789_mpy driver.](https://github.com/devbis/st7789_mpy)
|
||||
I modified the original driver for one of my projects to add:
|
||||
|
||||
- Display Rotation.
|
||||
- Scrolling
|
||||
- Writing text using bitmaps converted from True Type fonts
|
||||
- Drawing text using 8 and 16-bit wide bitmap fonts
|
||||
- Drawing text using Hershey vector fonts
|
||||
- Drawing JPGs, including a SLOW mode to draw jpg's larger than available ram
|
||||
using the TJpgDec - Tiny JPEG Decompressor R0.01d. from
|
||||
http://elm-chan.org/fsw/tjpgd/00index.html
|
||||
- Drawing PNGs using the pngle library from https://github.com/kikuchan/pngle
|
||||
- Drawing and rotating Polygons and filled Polygons.
|
||||
- Tracking bounds
|
||||
- Custom init capability to support st7735, ili9341, ili9342 and other displays. See the examples/configs folder for M5Stack Core, M5Stack Core2, T-DONGLE-S3 and Wio_Terminal devices.
|
||||
|
||||
Included are 12 bitmap fonts derived from classic pc text mode fonts, 26
|
||||
Hershey vector fonts and several example programs for different devices.
|
||||
|
||||
## Display Configuration
|
||||
|
||||
Some displays may use a BGR color order or inverted colors. The `cfg_helper.py`
|
||||
program can be used to determine the color order, inversion_mode, colstart, and
|
||||
rowstart values needed for a display.
|
||||
|
||||
### Color Modes
|
||||
|
||||
You can test for the correct color order needed by a display by filling it with
|
||||
the `st7789.RED` color and observing the actual color displayed.
|
||||
|
||||
- If the displayed color is RED, the settings are correct.
|
||||
- If the displayed color is BLUE, `color_order` should be `st7789.BGR`.
|
||||
- If the displayed color is YELLOW, `inversion_mode` should be `True.`
|
||||
- If the displayed color is CYAN, `color_order` should be `st7789.BGR` and
|
||||
`inversion_mode` should be `True.`
|
||||
|
||||
### colstart and rowstart
|
||||
|
||||
Some displays have a frame buffer memory larger than the physical display
|
||||
matrix. In these cases, the driver must be configured with the position of the
|
||||
first physical column and row pixels relative to the frame buffer. Each
|
||||
rotation setting of the display may require different colstart and rowstart
|
||||
values.
|
||||
|
||||
The driver automatically sets the `colstart` and `rowstart` values for common
|
||||
135x240, 240x240, 170x320 and 240x320 displays. If the default values do not work for
|
||||
your display, these values can be overridden using the `offsets` method. The
|
||||
`offsets` method should be called after any `rotation` method calls.
|
||||
|
||||
#### 128x128 st7735 cfg_helper.py example
|
||||
|
||||
```
|
||||
inversion_mode(False)
|
||||
color_order = st7789.BGR
|
||||
for rotation 0 use offset(2, 1)
|
||||
for rotation 1 use offset(1, 2)
|
||||
for rotation 2 use offset(2, 3)
|
||||
for rotation 3 use offset(3, 2)
|
||||
```
|
||||
|
||||
#### 128x160 st7735 cfg_helper.py example
|
||||
|
||||
```
|
||||
inversion_mode(False)
|
||||
color_order = st7789.RGB
|
||||
for rotation 0 use offset(0, 0)
|
||||
for rotation 1 use offset(0, 0)
|
||||
for rotation 2 use offset(0, 0)
|
||||
for rotation 3 use offset(0, 0)
|
||||
```
|
||||
|
||||
## Pre-compiled firmware files
|
||||
|
||||
The firmware directory contains pre-compiled firmware for various devices with
|
||||
the st7789 C driver and frozen python font files. See the README.md file in the
|
||||
fonts folder for more information on the font files.
|
||||
|
||||
MicroPython MicroPython v1.20.0 compiled with ESP IDF v4.4.4 using CMake
|
||||
|
||||
Directory | File | Device
|
||||
--------------------- | ------------ | ----------------------------------
|
||||
GENERIC-7789 | firmware.bin | Generic ESP32 devices
|
||||
GENERIC_SPIRAM-7789 | firmware.bin | Generic ESP32 devices with SPI Ram
|
||||
GENERIC_C3 | firmware.bin | Generic ESP32-C3 devices
|
||||
LOLIN_S2_MINI | firmware.bin | Wemos S2 mini
|
||||
PYBV11 | firmware.dfu | Pyboard v1.1 (No PNG)
|
||||
RP2 | firmware.uf2 | Raspberry Pi Pico RP2040
|
||||
RP2W | firmware.uf2 | Raspberry Pi PicoW RP2040
|
||||
T-DISPLAY | firmware.bin | LILYGO® TTGO T-Display
|
||||
T-Watch-2020 | firmware.bin | LILYGO® T-Watch 2020
|
||||
WIO_TERMINAL | firmware.bin | Seeed Wio Terminal
|
||||
|
||||
|
||||
## Additional Modules
|
||||
|
||||
Module | Source
|
||||
------------------ | -----------------------------------------------------------
|
||||
axp202c | https://github.com/lewisxhe/AXP202X_Libraries
|
||||
focaltouch | https://gitlab.com/mooond/t-watch2020-esp32-with-micropython
|
||||
|
||||
## Video Examples
|
||||
|
||||
Example | Video
|
||||
--------------------- | -----------------------------------------------------------
|
||||
PYBV11 hello.py | https://youtu.be/OtcERmad5ps
|
||||
PYBV11 scroll.py | https://youtu.be/ro13rvaLKAc
|
||||
T-DISPLAY fonts.py | https://youtu.be/2cnAhEucPD4
|
||||
T-DISPLAY hello.py | https://youtu.be/z41Du4GDMSY
|
||||
T-DISPLAY scroll.py | https://youtu.be/GQa-RzHLBak
|
||||
T-DISPLAY roids.py | https://youtu.be/JV5fPactSPU
|
||||
TWATCH-2020 draw.py | https://youtu.be/O_lDBnvH1Sw
|
||||
TWATCH-2020 hello.py | https://youtu.be/Bwq39tuMoY4
|
||||
TWATCH-2020 bitmap.py | https://youtu.be/DgYzgnAW2d8
|
||||
TWATCH-2020 watch.py | https://youtu.be/NItKb6umMc4
|
||||
|
||||
This is a work in progress.
|
||||
|
||||
## Thanks go out to:
|
||||
|
||||
- https://github.com/devbis for the original driver this is based on.
|
||||
- https://github.com/hklang10 for letting me know of the new mp_raise_ValueError().
|
||||
- https://github.com/aleggon for finding the correct offsets for 240x240
|
||||
displays and for discovering issues compiling STM32 ports.
|
||||
|
||||
-- Russ
|
||||
|
||||
## Overview
|
||||
|
||||
This is a driver for MicroPython to handle cheap displays based on the ST7789
|
||||
chip. The driver is written in C. Firmware is provided for ESP32, ESP32 with SPIRAM,
|
||||
pyboard1.1, and Raspberry Pi Pico devices.
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/ST7789.jpg" alt="ST7789 display photo"/>
|
||||
</p>
|
||||
|
||||
|
||||
# Setup MicroPython Build Environment in Ubuntu 20.04.2
|
||||
|
||||
See the MicroPython
|
||||
[README.md](https://github.com/micropython/micropython/blob/master/ports/esp32/README.md#setting-up-esp-idf-and-the-build-environment)
|
||||
if you run into any build issues not directly related to the st7789 driver. The
|
||||
recommended MicroPython build instructions may have changed.
|
||||
|
||||
Update and upgrade Ubuntu using apt-get if you are using a new install of
|
||||
Ubuntu or the Windows Subsystem for Linux.
|
||||
|
||||
```bash
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y upgrade
|
||||
```
|
||||
|
||||
Use apt-get to install the required build tools.
|
||||
|
||||
```bash
|
||||
sudo apt-get -y install build-essential libffi-dev git pkg-config cmake virtualenv python3-pip python3-virtualenv
|
||||
```
|
||||
|
||||
### Install a compatible esp-idf SDK
|
||||
|
||||
The MicroPython README.md states: "The ESP-IDF changes quickly, and MicroPython
|
||||
only supports certain versions. Currently, MicroPython supports v4.0.2, v4.1.1,
|
||||
and v4.2 although other IDF v4 versions may also work." I have had good luck
|
||||
using IDF v4.4
|
||||
|
||||
Clone the esp-idf SDK repo -- this usually takes several minutes.
|
||||
|
||||
```bash
|
||||
git clone -b v4.4 --recursive https://github.com/espressif/esp-idf.git
|
||||
cd esp-idf/
|
||||
git pull
|
||||
```
|
||||
|
||||
If you already have a copy of the IDF, you can checkout a version compatible
|
||||
with MicroPython and update the submodules using:
|
||||
|
||||
```bash
|
||||
$ cd esp-idf
|
||||
$ git checkout v4.4
|
||||
$ git submodule update --init --recursive
|
||||
```
|
||||
|
||||
Install the esp-idf SDK.
|
||||
|
||||
```bash
|
||||
./install.sh
|
||||
```
|
||||
|
||||
Source the esp-idf export.sh script to set the required environment variables.
|
||||
You must source the file and not run it using ./export.sh. You will need to
|
||||
source this file before compiling MicroPython.
|
||||
|
||||
```bash
|
||||
source export.sh
|
||||
cd ..
|
||||
```
|
||||
|
||||
Clone the MicroPython repo.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/micropython/micropython.git
|
||||
```
|
||||
|
||||
Clone the st7789 driver repo.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/russhughes/st7789_mpy.git
|
||||
```
|
||||
|
||||
Update the git submodules and compile the MicroPython cross-compiler
|
||||
|
||||
```bash
|
||||
cd micropython/
|
||||
git submodule update --init
|
||||
cd mpy-cross/
|
||||
make
|
||||
cd ..
|
||||
cd ports/esp32
|
||||
```
|
||||
|
||||
Copy any .py files you want to include in the firmware as frozen python modules
|
||||
to the modules subdirectory in ports/esp32. Be aware there is a limit to the
|
||||
flash space available. You will know you have exceeded this limit if you
|
||||
receive an error message saying the code won't fit in the partition or if your
|
||||
firmware continuously reboots with an error.
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
cp ../../../st7789_mpy/fonts/bitmap/vga1_16x16.py modules
|
||||
cp ../../../st7789_mpy/fonts/truetype/NotoSans_32.py modules
|
||||
cp ../../../st7789_mpy/fonts/vector/scripts.py modules
|
||||
```
|
||||
|
||||
Build the MicroPython firmware with the driver and frozen .py files in the
|
||||
modules directory. If you did not add any .py files to the modules directory,
|
||||
you can leave out the FROZEN_MANIFEST and FROZEN_MPY_DIR settings.
|
||||
|
||||
```bash
|
||||
make USER_C_MODULES=../../../../st7789_mpy/st7789/micropython.cmake FROZEN_MANIFEST="" FROZEN_MPY_DIR=$UPYDIR/modules
|
||||
```
|
||||
|
||||
Erase and flash the firmware to your device. Set PORT= to the ESP32's usb
|
||||
serial port. I could not get the USB serial port to work under the Windows
|
||||
Subsystem (WSL2) for Linux. If you have the same issue, you can copy the
|
||||
firmware.bin file and use the Windows esptool.py to flash your device.
|
||||
|
||||
```bash
|
||||
make USER_C_MODULES=../../../../st7789_mpy/st7789/micropython.cmake PORT=/dev/ttyUSB0 erase
|
||||
make USER_C_MODULES=../../../../st7789_mpy/st7789/micropython.cmake PORT=/dev/ttyUSB0 deploy
|
||||
```
|
||||
|
||||
The firmware.bin file will be in the build-GENERIC directory. To flash using
|
||||
the python esptool.py utility. Use pip3 to install the esptool if it's not
|
||||
already installed.
|
||||
|
||||
```bash
|
||||
pip3 install esptool
|
||||
```
|
||||
|
||||
Set PORT= to the ESP32's USB serial port
|
||||
|
||||
```bash
|
||||
esptool.py --port COM3 erase_flash
|
||||
esptool.py --chip esp32 --port COM3 write_flash -z 0x1000 firmware.bin
|
||||
```
|
||||
## CMake building instructions for MicroPython 1.14 and later
|
||||
|
||||
for ESP32:
|
||||
|
||||
$ cd micropython/ports/esp32
|
||||
|
||||
And then compile the module with specified USER_C_MODULES dir.
|
||||
|
||||
$ make USER_C_MODULES=../../../../st7789_mpy/st7789/micropython.cmake
|
||||
|
||||
for Raspberry Pi PICO:
|
||||
|
||||
$ cd micropython/ports/rp2
|
||||
|
||||
And then compile the module with specified USER_C_MODULES dir.
|
||||
|
||||
$ make USER_C_MODULES=../../../st7789_mpy/st7789/micropython.cmake
|
||||
|
||||
## Working examples
|
||||
|
||||
This module was tested on ESP32, STM32 based pyboard v1.1, and the Raspberry Pi
|
||||
Pico. You have to provide an `SPI` object and the pin to use for the `dc' input
|
||||
of the screen.
|
||||
|
||||
|
||||
# ESP32 Example
|
||||
# To use baudrates above 26.6MHz you must use my firmware or modify the micropython
|
||||
# source code to increase the SPI baudrate limit by adding SPI_DEVICE_NO_DUMMY to the
|
||||
# .flag member of the spi_device_interface_config_t struct in the machine_hw_spi_init_internal.c
|
||||
# file. Not doing so will cause the ESP32 to crash if you use a baudrate that is too high.
|
||||
|
||||
import machine
|
||||
import st7789
|
||||
spi = machine.SPI(2, baudrate=40000000, polarity=1, sck=machine.Pin(18), mosi=machine.Pin(23))
|
||||
display = st7789.ST7789(spi, 240, 240, reset=machine.Pin(4, machine.Pin.OUT), dc=machine.Pin(2, machine.Pin.OUT))
|
||||
display.init()
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
- `st7789.ST7789(spi, width, height, dc, reset, cs, backlight, rotations, rotation, custom_init, color_order, inversion, options, buffer_size)`
|
||||
|
||||
### Required positional arguments:
|
||||
- `spi` spi device
|
||||
- `width` display width
|
||||
- `height` display height
|
||||
|
||||
### Required keyword arguments:
|
||||
- `dc` sets the pin connected to the display data/command selection input.
|
||||
This parameter is always required.
|
||||
|
||||
### Optional keyword arguments:
|
||||
|
||||
- `reset` sets the pin connected to the display's hardware reset input. If
|
||||
the displays reset pin is tied high, the `reset` parameter is not
|
||||
required.
|
||||
|
||||
- `cs` sets the pin connected to the displays chip select input. If the
|
||||
display's CS pin is tied low, the display must be the only device
|
||||
connected to the SPI port. The display will always be the selected
|
||||
device, and the `cs` parameter is not required.
|
||||
|
||||
- `backlight` sets the pin connected to the display's backlight enable
|
||||
input. The display's backlight input can often be left floating or
|
||||
disconnected as the backlight on some displays is always powered on and
|
||||
cannot be turned off.
|
||||
|
||||
- `rotations` sets the orientation table. The orientation table is a list
|
||||
of tuples for each `rotation` used to set the MADCTL register, display width,
|
||||
display height, start_x, and start_y values.
|
||||
|
||||
Default `rotations` are included for the following st7789 and st7735
|
||||
display sizes:
|
||||
|
||||
Display | Default Orientation Tables
|
||||
------- | --------------------------
|
||||
240x320 | [(0x00, 240, 320, 0, 0), (0x60, 320, 240, 0, 0), (0xc0, 240, 320, 0, 0), (0xa0, 320, 240, 0, 0)]
|
||||
170x320 | [(0x00, 170, 320, 35, 0), (0x60, 320, 170, 0, 35), (0xc0, 170, 320, 35, 0), (0xa0, 320, 170, 0, 35)]
|
||||
240x240 | [(0x00, 240, 240, 0, 0), (0x60, 240, 240, 0, 0), (0xc0, 240, 240, 0, 80), (0xa0, 240, 240, 80, 0)]
|
||||
135x240 | [(0x00, 135, 240, 52, 40), (0x60, 240, 135, 40, 53), (0xc0, 135, 240, 53, 40), (0xa0, 240, 135, 40, 52)]
|
||||
128x160 | [(0x00, 128, 160, 0, 0), (0x60, 160, 128, 0, 0), (0xc0, 128, 160, 0, 0), (0xa0, 160, 128, 0, 0)]
|
||||
128x128 | [(0x00, 128, 128, 2, 1), (0x60, 128, 128, 1, 2), (0xc0, 128, 128, 2, 3), (0xa0, 128, 128, 3, 2)]
|
||||
other | [(0x00, width, height, 0, 0)]
|
||||
|
||||
You may define as many rotations as you wish.
|
||||
|
||||
- `rotation` sets the display rotation according to the orientation table.
|
||||
|
||||
The default orientation table defines four counter-clockwise rotations for 240x320, 240x240,
|
||||
134x240, 128x160 and 128x128 displays with the LCD's ribbon cable at the bottom of the display.
|
||||
The default rotation is Portrait (0 degrees).
|
||||
|
||||
Index | Rotation
|
||||
----- | --------
|
||||
0 | Portrait (0 degrees)
|
||||
1 | Landscape (90 degrees)
|
||||
2 | Reverse Portrait (180 degrees)
|
||||
3 | Reverse Landscape (270 degrees)
|
||||
|
||||
- `custom_init` List of display configuration commands to send to the display during the display init().
|
||||
The list contains tuples with a bytes object, optionally followed by a delay specified in ms. The first
|
||||
byte of the bytes object contains the command to send optionally followed by data bytes.
|
||||
See the `examples/configs/t_dongle_s3/tft_config.py` file or an example.
|
||||
|
||||
- `color_order` Sets the color order used by the driver (st7789.RGB or st7789.BGR)
|
||||
|
||||
- `inversion` Sets the display color inversion mode if True, clears the
|
||||
display color inversion mode if false.
|
||||
|
||||
- `options` Sets driver option flags.
|
||||
|
||||
Option | Description
|
||||
------------- | -----------
|
||||
st7789.WRAP | pixels, lines, polygons, and Hershey text will wrap around the display both horizontally and vertically.
|
||||
st7789.WRAP_H | pixels, lines, polygons, and Hershey text will wrap around the display horizontally.
|
||||
st7789.WRAP_V | pixels, lines, polygons, and Hershey text will wrap around the display vertically.
|
||||
|
||||
- `buffer_size` If a buffer_size is not specified, a dynamically allocated
|
||||
buffer is created and freed as needed. If a buffer_size is set, it must
|
||||
be large enough to contain the largest bitmap, font character, and
|
||||
decoded JPG image used (Rows * Columns * 2 bytes, 16bit colors in RGB565
|
||||
notation). Dynamic allocation is slower and can cause heap fragmentation,
|
||||
so garbage collection (GC) should be enabled.
|
||||
|
||||
- `inversion_mode(bool)` Sets the display color inversion mode if True, clears
|
||||
the display color inversion mode if False.
|
||||
|
||||
- `madctl(value)` Returns the current value of the MADCTL register or sets the MADCTL register if a value is passed to the
|
||||
method. The MADCTL register is used to set the display rotation and color order.
|
||||
|
||||
#### [MADCTL constants](#madctl-constants)
|
||||
|
||||
Constant Name | Value | Description
|
||||
---------------- | ----- | ----------------------
|
||||
st7789.MADCTL_MY | 0x80 | Page Address Order
|
||||
st7789_MADCTL_MX | 0x40 | Column Address Order
|
||||
st7789_MADCTL_MV | 0x20 | Page/Column Order
|
||||
st7789_MADCTL_ML | 0x10 | Line Address Order
|
||||
st7789_MADCTL_MH | 0x04 | Display Data Latch Order
|
||||
st7789_RGB | 0x00 | RGB color order
|
||||
st7789_BGR | 0x08 | BGR color order
|
||||
|
||||
#### [MADCTL examples](#madctl-examples)
|
||||
|
||||
|
||||
Orientation | MADCTL Values for RGB color order, for BGR color order add 0x08 to the value.
|
||||
----------- | ---------------------------------------------------------------------------------
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_0.png" /> | 0x00
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_y.png" /> | 0x80 ( MADCTL_MY )
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_x.png" /> | 0x40 ( MADCTL_MX )
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_xy.png" /> | 0xC0 ( MADCTL_MX + MADCTL_MY )
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_v.png" /> | 0x20 ( MADCTL_MV )
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_vy.png" /> | 0xA0 ( MADCTL_MV + MADCTL_MY )
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_vx.png" /> | 0x60 ( MADCTL_MV + MADCTL_MX )
|
||||
<img src="https://raw.githubusercontent.com/russhughes/st7789_mpy/master/docs/madctl_vxy.png" /> | 0xE0 ( MADCTL_MV + MADCTL_MX + MADCTL_MY )
|
||||
|
||||
- `init()`
|
||||
|
||||
Must be called to initialize the display.
|
||||
|
||||
- `on()`
|
||||
|
||||
Turn on the backlight pin if one was defined during init.
|
||||
|
||||
- `off()`
|
||||
|
||||
Turn off the backlight pin if one was defined during init.
|
||||
|
||||
- `sleep_mode(value)`
|
||||
|
||||
If value is True, cause the display to enter sleep mode, otherwise wake up if value is False. During sleep display content may not be preserved.
|
||||
|
||||
|
||||
- `fill(color)`
|
||||
|
||||
Fill the display with the specified color.
|
||||
|
||||
- `pixel(x, y, color)`
|
||||
|
||||
Set the specified pixel to the given `color`.
|
||||
|
||||
- `line(x0, y0, x1, y1, color)`
|
||||
|
||||
Draws a single line with the provided `color` from (`x0`, `y0`) to
|
||||
(`x1`, `y1`).
|
||||
|
||||
- `hline(x, y, length, color)`
|
||||
|
||||
Draws a single horizontal line with the provided `color` and `length`
|
||||
in pixels. Along with `vline`, this is a fast version with fewer SPI calls.
|
||||
|
||||
- `vline(x, y, length, color)`
|
||||
|
||||
Draws a single horizontal line with the provided `color` and `length`
|
||||
in pixels.
|
||||
|
||||
- `rect(x, y, width, height, color)`
|
||||
|
||||
Draws a rectangle from (`x`, `y`) with corresponding dimensions
|
||||
|
||||
- `fill_rect(x, y, width, height, color)`
|
||||
|
||||
Fill a rectangle starting from (`x`, `y`) coordinates
|
||||
|
||||
- `circle(x, y, r, color)`
|
||||
|
||||
Draws a circle with radius `r` centered at the (`x`, `y`) coordinates in the given
|
||||
`color`.
|
||||
|
||||
- `fill_circle(x, y, r, color)`
|
||||
|
||||
Draws a filled circle with radius `r` centered at the (`x`, `y`) coordinates
|
||||
in the given `color`.
|
||||
|
||||
- `blit_buffer(buffer, x, y, width, height)`
|
||||
|
||||
Copy bytes() or bytearray() content to the screen internal memory. Note:
|
||||
every color requires 2 bytes in the array
|
||||
|
||||
- `text(font, s, x, y[, fg, bg])`
|
||||
|
||||
Write `s` (integer, string or bytes) to the display using the specified bitmap
|
||||
`font` with the coordinates as the upper-left corner of the text. The optional
|
||||
arguments `fg` and `bg` can set the foreground and background colors of the
|
||||
text; otherwise the foreground color defaults to `WHITE`, and the background
|
||||
color defaults to `BLACK`. See the `README.md` in the `fonts/bitmap` directory
|
||||
for example fonts.
|
||||
|
||||
- `write(bitmap_font, s, x, y[, fg, bg, background_tuple, fill_flag])`
|
||||
|
||||
Write text to the display using the specified proportional or Monospace bitmap
|
||||
font module with the coordinates as the upper-left corner of the text. The
|
||||
foreground and background colors of the text can be set by the optional
|
||||
arguments `fg` and `bg`, otherwise the foreground color defaults to `WHITE`
|
||||
and the background color defaults to `BLACK`.
|
||||
|
||||
Transparency can be emulated by providing a `background_tuple` containing
|
||||
(bitmap_buffer, width, height). This is the same format used by the jpg_decode
|
||||
method. See examples/T-DISPLAY/clock/clock.py for an example.
|
||||
|
||||
See the `README.md` in the `truetype/fonts` directory for example fonts.
|
||||
Returns the width of the string as printed in pixels. Accepts UTF8 encoded strings.
|
||||
|
||||
The `font2bitmap` utility creates compatible 1 bit per pixel bitmap modules
|
||||
from Proportional or Monospaced True Type fonts. The character size,
|
||||
foreground, background colors, and characters in the bitmap
|
||||
module may be specified as parameters. Use the -h option for details. If you
|
||||
specify a buffer_size during the display initialization, it must be large
|
||||
enough to hold the widest character (HEIGHT * MAX_WIDTH * 2).
|
||||
|
||||
- `write_len(bitap_font, s)`
|
||||
|
||||
Returns the string's width in pixels if printed in the specified font.
|
||||
|
||||
- `draw(vector_font, s, x, y[, fg, scale])`
|
||||
|
||||
Draw text to the display using the specified Hershey vector font with the
|
||||
coordinates as the lower-left corner of the text. The foreground color of the
|
||||
text can be set by the optional argument `fg`. Otherwise the foreground color
|
||||
defaults to `WHITE`. The size of the text can be scaled by specifying a
|
||||
`scale` value. The `scale` value must be larger than 0 and can be a
|
||||
floating-point or an integer value. The `scale` value defaults to 1.0. See
|
||||
the README.md in the `vector/fonts` directory, for example fonts and the
|
||||
utils directory for a font conversion program.
|
||||
|
||||
- `draw_len(vector_font, s[, scale])`
|
||||
|
||||
Returns the string's width in pixels if drawn with the specified font.
|
||||
|
||||
- `jpg(jpg, x, y [, method])`
|
||||
|
||||
Draw a `jpg` on the display with the given `x` and `y` coordinates as the
|
||||
upper left corner of the image. `jpg` may be a string containing a filename
|
||||
or a buffer containing the JPEG image data.
|
||||
|
||||
The memory required to decode and display a JPG can be considerable as a full-screen
|
||||
320x240 JPG would require at least 3100 bytes for the working area + 320 * 240 * 2
|
||||
bytes of ram to buffer the image. Jpg images that would require a buffer larger than
|
||||
available memory can be drawn by passing `SLOW` for the `method`. The `SLOW` `method`
|
||||
will draw the image one piece at a time using the Minimum Coded Unit (MCU, typically
|
||||
a multiple of 8x8) of the image. The default method is `FAST`.
|
||||
|
||||
- `jpg_decode(jpg_filename [, x, y, width, height])`
|
||||
|
||||
Decode a jpg file and return it or a portion of it as a tuple composed of
|
||||
(buffer, width, height). The buffer is a color565 blit_buffer compatible byte
|
||||
array. The buffer will require width * height * 2 bytes of memory.
|
||||
|
||||
If the optional x, y, width, and height parameters are given, the buffer will
|
||||
only contain the specified area of the image. See examples/T-DISPLAY/clock/clock.py
|
||||
examples/T-DISPLAY/toasters_jpg/toasters_jpg.py for examples.
|
||||
|
||||
- `png(png_filename, x, y [, mask])`
|
||||
|
||||
Draw a PNG file on the display with upper left corner of the image at the given `x` and `y`
|
||||
coordinates. The PNG will be clipped if it is not able to fit fully on the display. The
|
||||
PNG will be drawn one line at a time. Since the driver does not contain a frame buffer,
|
||||
transparency is not supported. Providing a `True` value for the `mask` parameter
|
||||
will prevent pixels with a zero alpha channel value from being displayed. Drawing masked PNG's is
|
||||
slower than non-masked as each visible line segment is drawn separately. For an example of using a
|
||||
mask, see the alien.py program in the examples/png folder.
|
||||
|
||||
- `polygon_center(polygon)`
|
||||
|
||||
Return the center of the `polygon` as an (x, y) tuple. The `polygon` should
|
||||
consist of a list of (x, y) tuples forming a closed convex polygon.
|
||||
|
||||
- `fill_polygon(polygon, x, y, color[, angle, center_x, center_y])`
|
||||
|
||||
Draw a filled `polygon` at the `x`, and `y` coordinates in the `color` given.
|
||||
The polygon may be rotated `angle` radians about the `center_x` and
|
||||
`center_y` point. The polygon should consist of a list of (x, y) tuples
|
||||
forming a closed convex polygon.
|
||||
|
||||
See the TWATCH-2020 `watch.py` demo for an example.
|
||||
|
||||
- `polygon(polygon, x, y, color, angle, center_x, center_y)`
|
||||
|
||||
Draw a `polygon` at the `x`, and `y` coordinates in the `color` given. The
|
||||
polygon may be rotated `angle` radians about the `center_x` and `center_y`
|
||||
point. The polygon should consist of a list of (x, y) tuples forming a closed
|
||||
convex polygon.
|
||||
|
||||
See the T-Display `roids.py` for an example.
|
||||
|
||||
- `bounding({status, as_rect})`
|
||||
|
||||
Bounding enables or disables tracking the display area that has been written
|
||||
to. Initially, tracking is disabled; pass a True value to enable tracking and
|
||||
False to disable it. Passing a True or False parameter will reset the current
|
||||
bounding rectangle to (display_width, display_height, 0, 0).
|
||||
|
||||
Returns a four integer tuple containing (min_x, min_y, max_x, max_y)
|
||||
indicating the area of the display that has been written to since the last
|
||||
clearing.
|
||||
|
||||
If `as_rect` parameter is True, the returned tuple will contain (min_x,
|
||||
min_y, width, height) values.
|
||||
|
||||
See the TWATCH-2020 `watch.py` demo for an example.
|
||||
|
||||
- `bitmap(bitmap, x , y [, index])`
|
||||
|
||||
Draw `bitmap` using the specified `x`, `y` coordinates as the upper-left
|
||||
corner of the `bitmap`. The optional `index` parameter provides a method to
|
||||
select from multiple bitmaps contained a `bitmap` module. The `index` is used
|
||||
to calculate the offset to the beginning of the desired bitmap using the
|
||||
modules HEIGHT, WIDTH, and BPP values.
|
||||
|
||||
The `imgtobitmap.py` utility creates compatible 1 to 8 bit per pixel bitmap
|
||||
modules from image files using the Pillow Python Imaging Library.
|
||||
|
||||
The `monofont2bitmap.py` utility creates compatible 1 to 8 bit per pixel
|
||||
bitmap modules from Monospaced True Type fonts. See the `inconsolata_16.py`,
|
||||
`inconsolata_32.py` and `inconsolata_64.py` files in the `examples/lib`
|
||||
folder for sample modules and the `mono_font.py` program for an example using
|
||||
the generated modules.
|
||||
|
||||
The character sizes, bit per pixel, foreground, background colors, and the
|
||||
characters to include in the bitmap module may be specified as parameters.
|
||||
Use the -h option for details. Bits per pixel settings larger than one may be
|
||||
used to create antialiased characters at the expense of memory use. If you
|
||||
specify a buffer_size during the display initialization, it must be large
|
||||
enough to hold the one character (HEIGHT * WIDTH * 2).
|
||||
|
||||
- `width()`
|
||||
|
||||
Returns the current logical width of the display. (ie a 135x240 display
|
||||
rotated 90 degrees is 240 pixels wide)
|
||||
|
||||
- `height()`
|
||||
|
||||
Returns the current logical height of the display. (ie a 135x240 display
|
||||
rotated 90 degrees is 135 pixels high)
|
||||
|
||||
- `rotation(r)`
|
||||
|
||||
Set the rotates the logical display in a counter-clockwise direction.
|
||||
0-Portrait (0 degrees), 1-Landscape (90 degrees), 2-Inverse Portrait (180
|
||||
degrees), 3-Inverse Landscape (270 degrees)
|
||||
|
||||
- `offset(x_start, y_start)` The memory in the ST7789 controller is configured
|
||||
for a 240x320 display. When using a smaller display like a 240x240 or
|
||||
135x240, an offset needs to be added to the x and y parameters so that the
|
||||
pixels are written to the memory area corresponding to the visible display.
|
||||
The offsets may need to be adjusted when rotating the display.
|
||||
|
||||
For example, the TTGO-TDisplay is 135x240 and uses the following offsets.
|
||||
|
||||
| Rotation | x_start | y_start |
|
||||
|----------|---------|---------|
|
||||
| 0 | 52 | 40 |
|
||||
| 1 | 40 | 53 |
|
||||
| 2 | 53 | 40 |
|
||||
| 3 | 40 | 52 |
|
||||
|
||||
When the rotation method is called, the driver will adjust the offsets for a
|
||||
135x240 or 240x240 display. Your display may require using different offset
|
||||
values; if so, use the `offset` method after `rotation` to set the offset
|
||||
values.
|
||||
|
||||
The values needed for a particular display may not be documented and may
|
||||
require some experimentation to determine the correct values. One technique
|
||||
is to draw a box the same size as the display and then make small changes to
|
||||
the offsets until the display looks correct. See the `cfg_helper.py` program
|
||||
in the examples folder for more information.
|
||||
|
||||
|
||||
The module exposes predefined colors:
|
||||
`BLACK`, `BLUE`, `RED`, `GREEN`, `CYAN`, `MAGENTA`, `YELLOW`, and `WHITE`
|
||||
|
||||
## Scrolling
|
||||
|
||||
The st7789 display controller contains a 240 by 320-pixel frame buffer used to
|
||||
store the pixels for the display. For scrolling, the frame buffer consists of
|
||||
three separate areas; The (`tfa`) top fixed area, the (`height`) scrolling
|
||||
area, and the (`bfa`) bottom fixed area. The `tfa` is the upper portion of the
|
||||
frame buffer in pixels not to scroll. The `height` is the center portion of the
|
||||
frame buffer in pixels to scroll. The `bfa` is the lower portion of the frame
|
||||
buffer in pixels not to scroll. These values control the ability to scroll the
|
||||
entire or a part of the display.
|
||||
|
||||
For displays that are 320 pixels high, setting the `tfa` to 0, `height` to 320,
|
||||
and `bfa` to 0 will allow scrolling of the entire display. You can set the
|
||||
`tfa` and `bfa` to a non-zero value to scroll a portion of the display. `tfa` +
|
||||
`height` + `bfa` = should equal 320, otherwise the scrolling mode is undefined.
|
||||
|
||||
Displays less than 320 pixels high, the `tfa`, `height`, and `bfa` will need to
|
||||
be adjusted to compensate for the smaller LCD panel. The actual values will
|
||||
vary depending on the configuration of the LCD panel. For example, scrolling
|
||||
the entire 135x240 TTGO T-Display requires a `tfa` value of 40, `height` value
|
||||
of 240, and `bfa` value of 40 (40+240+40=320) because the T-Display LCD shows
|
||||
240 rows starting at the 40th row of the frame buffer, leaving the last 40 rows
|
||||
of the frame buffer undisplayed.
|
||||
|
||||
Other displays like the Waveshare Pico LCD 1.3 inch 240x240 display require the
|
||||
`tfa` set to 0, `height` set to 240, and `bfa` set to 80 (0+240+80=320) to
|
||||
scroll the entire display. The Pico LCD 1.3 shows 240 rows starting at the 0th
|
||||
row of the frame buffer, leaving the last 80 rows of the frame buffer
|
||||
undisplayed.
|
||||
|
||||
The `vscsad` method sets the (VSSA) Vertical Scroll Start Address. The VSSA
|
||||
sets the line in the frame buffer that will be the first line after the `tfa`.
|
||||
|
||||
The ST7789 datasheet warns:
|
||||
|
||||
The value of the vertical scrolling start address is absolute (with reference to the frame memory),
|
||||
it must not enter the fixed area (defined by Vertical Scrolling Definition, otherwise undesirable
|
||||
image will be displayed on the panel.
|
||||
|
||||
- `vscrdef(tfa, height, bfa)` Set the vertical scrolling parameters.
|
||||
|
||||
`tfa` is the top fixed area in pixels. The top fixed area is the upper
|
||||
portion of the display frame buffer that will not be scrolled.
|
||||
|
||||
`height` is the total height in pixels of the area scrolled.
|
||||
|
||||
`bfa` is the bottom fixed area in pixels. The bottom fixed area is the lower
|
||||
portion of the display frame buffer that will not be scrolled.
|
||||
|
||||
- `vscsad(vssa)` Set the vertical scroll address.
|
||||
|
||||
`vssa` is the vertical scroll start address in pixels. The vertical scroll
|
||||
start address is the line in the frame buffer will be the first line shown
|
||||
after the TFA.
|
||||
|
||||
## Helper functions
|
||||
|
||||
- `color565(r, g, b)`
|
||||
|
||||
Pack a color into 2-bytes rgb565 format
|
||||
|
||||
- `map_bitarray_to_rgb565(bitarray, buffer, width, color=WHITE, bg_color=BLACK)`
|
||||
|
||||
Convert a `bitarray` to the rgb565 color `buffer` suitable for blitting. Bit
|
||||
1 in `bitarray` is a pixel with `color` and 0 - with `bg_color`.
|
||||
Reference in New Issue
Block a user