diff --git a/README.md b/README.md index 736ff55..ec72426 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ under development so check for updates. [Appendix 2 Freezing bytecode](./README.md#appendix-2-freezing-bytecode) Optional way to save RAM. [Appendix 3 Cross compiling](./README.md#appendix-3-cross-compiling) Another way to save RAM. [Appendix 4 GUI Design notes](./README.md#appendix-4-gui-design-notes) The reason for continuous refresh. +[Appendix 5 Bus sharing](./README.md#appendix-5-bus-sharing) Using the SD card on Waveshare boards. # 1. Basic concepts @@ -3578,3 +3579,45 @@ def test(): test() ``` ###### [Contents](./README.md#0-contents) + +## Appendix 5 Bus sharing + +Boards from Waveshare use the same SPI bus to access the display controller, the +touch controller, and an optional SD card. If an SD card is fitted, it is +possible to mount this in `boot.py`: doing this enables the filesystem on the +SD card to be managed at the Bash prompt using `mpremote`. There is a "gotcha" +here. For this to work reliably, the `CS\` pins of the display controller and +the touch controller must be set high, otherwise bus contention on the `miso` +line can occur. Note that this still applies even if the touch controller is +unused: it should still be prevented from asserting `miso`. The following is an +example of a `boot.py` for the 2.8" Pico Res touch. +```py +from machine import SPI, Pin +from sdcard import SDCard +import os +BAUDRATE = 3_000_000 # Much higher rates seem OK, but may depend on card. +# Initialise all CS\ pins +cst = Pin(16, Pin.OUT, value=1) # Touch XPT2046 +csd = Pin(9, Pin.OUT, value=1) # Display ST7789 +css = Pin(22, Pin.OUT, value=1) # SD card +spi = SPI(1, BAUDRATE, sck=Pin(10), mosi=Pin(11), miso=Pin(12)) +sd = SDCard(spi, css, BAUDRATE) +vfs = os.VfsFat(sd) +os.mount(vfs, "/sd") +``` +An application which is to access the SD card must ensure that the GUI is +prevented from accessing the SPI bus for the duration of SD card access. This +may be done with an asynchronous context manager. When the context manager +terminates, refresh will re-start. +```py +async def read_data(): + async with Screen.rfsh_lock: + # set up the SPI bus baudrate for the SD card + # read the data + await asyncio.sleep_ms(0) # Allow refresh and touch to proceed + # Do anything else you need +``` +See section 8 for further background. Tested by @bianc104 in micropython-touch +[iss 15](https://github.com/peterhinch/micropython-touch/issues/15#issuecomment-2397988225) + +###### [Contents](./README.md#0-contents) diff --git a/gui/demos/audio.py b/gui/demos/audio.py index 6b58064..efb9c03 100644 --- a/gui/demos/audio.py +++ b/gui/demos/audio.py @@ -22,13 +22,14 @@ pyb.Pin("EN_3V3").on() # provide 3.3V on 3V3 output pin # ======= I2S CONFIGURATION ======= -I2S_ID = 1 # allocate sample array once wav_samples = bytearray(WAVSIZE) # The proper way is to parse the WAV file as per # https://github.com/miketeachman/micropython-i2s-examples/blob/master/examples/wavplayer.py # Here for simplicity we assume stereo files ripped from CD's. +# Pyboard D +I2S_ID = 1 config = { "sck": Pin("W29"), "ws": Pin("W16"), @@ -40,6 +41,19 @@ config = { "ibuf": BUFSIZE, # Buffer size } +# RP2 from https://docs.micropython.org/en/latest/rp2/quickref.html#i2s-bus +# I2S_ID = 0 +# config = { +# "sck": Pin(16), +# "ws": Pin(17), +# "sd": Pin(18), +# "mode": I2S.TX, +# "bits": 16, # Sample size in bits/channel +# "format": I2S.STEREO, +# "rate": 44100, # Sample rate in Hz +# "ibuf": BUFSIZE, # Buffer size +# } + audio_out = I2S(I2S_ID, **config) # ======= GUI ======= diff --git a/setup_examples/pico_epaper_42_v2_pico.py b/setup_examples/pico_epaper_42_v2_pico.py new file mode 100644 index 0000000..1a635a7 --- /dev/null +++ b/setup_examples/pico_epaper_42_v2_pico.py @@ -0,0 +1,24 @@ +# pico_epaper_42_v2.py +# hardware_setup file for a Pico ePaper 4.2" V2 with a Pico plugged in. +# The two user buttons on the display provide the interface +from machine import Pin, SPI, freq +import gc +from drivers.epaper.pico_epaper_42_v2 import EPD as SSD + +freq(250_000_000) # RP2 overclock + +gc.collect() # Precaution before instantiating framebuf + +# Using the onboard socket connection default args apply +ssd = SSD() +gc.collect() +from gui.core.ugui import Display, quiet + +# quiet() +# Create and export a Display instance +# Define control buttons: these are the buttons on the display unit. +nxt = Pin(17, Pin.IN, Pin.PULL_UP) # Move to next control +sel = Pin(15, Pin.IN, Pin.PULL_UP) # Operate current control +# display = Display(ssd, nxt, sel, prev) # 3-button mode +display = Display(ssd, nxt, sel) # 2-button mode +ssd.wait_until_ready() # Blocking wait