Skip to content

Instantly share code, notes, and snippets.

@anecdata
Created June 17, 2019 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anecdata/771c7ad55e41fd1baa1b846d6994b0f9 to your computer and use it in GitHub Desktop.
Save anecdata/771c7ad55e41fd1baa1b846d6994b0f9 to your computer and use it in GitHub Desktop.
3.5" FeatherWing (HX8357) [FeatherM4, 4.1.0-beta.0, Library Bundle 20190615]
"""
This test will initialize the display using displayio
and draw a solid red background
"""
import board
import displayio
import time
print('Begin')
spi = board.SPI()
tft_cs = board.D9
tft_dc = board.D10
displayio.release_displays()
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)
try:
from adafruit_hx8357 import HX8357
display = HX8357(display_bus, width=480, height=320)
time.sleep(5) # https://learn.adafruit.com/adafruit-3-5-tft-featherwing/troubleshooting
print('Display: HX8357')
except RuntimeError as e:
print('HX8357 Error:', e)
# SPI Frequency
while not spi.try_lock():
pass
try:
print("SPI:", "{:>8}".format(spi.frequency), "Hz old")
attempt_baud = 3000000
print("SPI:", "{:>8}".format(attempt_baud), "Hz try")
spi.configure(baudrate=attempt_baud)
except RuntimeError as e:
print('SPI Error:', e)
finally:
print("SPI:", "{:>8}".format(spi.frequency), "Hz new")
spi.unlock()
print("SPI:", "{:>8}".format(spi.frequency), "Hz unlocked")
# Make the display context
splash = displayio.Group(max_size=10)
display.show(splash)
color_bitmap = displayio.Bitmap(480, 320, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFF0000
bg_sprite = displayio.TileGrid(color_bitmap,
pixel_shader=color_palette,
x=0, y=0)
splash.append(bg_sprite)
time.sleep(1)
display.show(None)
print("SPI:", "{:>8}".format(spi.frequency), "Hz pre-loop")
loop = 0
while True:
time.sleep(.1)
print(loop, "SPI:", "{:>8}".format(spi.frequency), "Hz")
loop += 1
@anecdata
Copy link
Author

anecdata commented Jun 17, 2019

3.5" FeatherWing has gotten into a super slow displayio (including terminalio) mode that persists across power cycles and across reverting to 4.0.1 (and back). Shipped example code for HX8357 (with addition of display.show(None) and a simple print in the loop) behaves the same. Behaves the same with or without the SPI Frequency change block.

@anecdata
Copy link
Author

Simplest example:

"""
  This test will initialize the display using displayio
  and draw a solid red background
  """

import board
import time
import displayio
from adafruit_hx8357 import HX8357

spi = board.SPI()
tft_cs = board.D9
tft_dc = board.D10

displayio.release_displays()
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)

display = HX8357(display_bus, width=480, height=320)

# Make the display context
splash = displayio.Group(max_size=10)
display.show(splash)

color_bitmap = displayio.Bitmap(480, 320, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFF0000

bg_sprite = displayio.TileGrid(color_bitmap,
                               pixel_shader=color_palette,
                               x=0, y=0)
splash.append(bg_sprite)

time.sleep(1)
display.show(None)

loop = 0
while True:
    time.sleep(.1)
    print(loop, "Test")
    loop += 1

@anecdata
Copy link
Author

3.5" FeatherWing was behaving fine initially 4.1.0-beta.0: significant speedup and no lost display area at the bottom, and this code will probably work fine for others, at least initially. But once the board got into this slow mode (while trying to re-test the lost display area issue), it won't come out by any means I've tried.

@anecdata
Copy link
Author

anecdata commented Jun 17, 2019

Powered off, disconnected the display for about 15 minutes, and reconnected the display. It then operated at proper 4.1.0-beta.0 speeds again with only intermittent loss of display area at the bottom through successive reloads. A hardware reset re-established the full screen terminalio, but re-triggered a slow mode (and changes the SPI frequency change behavior).

@anecdata
Copy link
Author

anecdata commented Jun 17, 2019

Once in slow mode, removing the display-specific code and reloading restores run speed. Run speed stays fast when display-specific code is re-inserted and system is reloaded. The processor / circuitpython (as opposed to the display itself - the behavior is independent of whether a display is actually connected) seems to be holding onto some display initialization state across reloads, even when the displayio.release_displays() line remains in the code.

@anecdata
Copy link
Author

anecdata commented Jun 17, 2019

"""
    This test will initialize the display using displayio
    and draw a solid red background
    """

import board
import displayio
import time

print('Begin')

spi = board.SPI()
tft_cs = board.D9
tft_dc = board.D10

displayio.release_displays()
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)

try:
    from adafruit_hx8357 import HX8357
    display = HX8357(display_bus, width=480, height=320)
    time.sleep(5)  # https://learn.adafruit.com/adafruit-3-5-tft-featherwing/troubleshooting
    print('Display: HX8357')
except RuntimeError as e:
    print('HX8357 Error:', e)

# SPI Frequency
while not spi.try_lock():
    pass
try:
    print("SPI:", "{:>8}".format(spi.frequency), "Hz old")
    attempt_baud = 3000000
    print("SPI:", "{:>8}".format(attempt_baud), "Hz try")
    spi.configure(baudrate=attempt_baud)
except RuntimeError as e:
    print('SPI Error:', e)
finally:
    print("SPI:", "{:>8}".format(spi.frequency), "Hz new")
    spi.unlock()
print("SPI:", "{:>8}".format(spi.frequency), "Hz unlocked")

# Make the display context
splash = displayio.Group(max_size=10)
display.show(splash)

color_bitmap = displayio.Bitmap(480, 320, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFF0000
bg_sprite = displayio.TileGrid(color_bitmap,
                               pixel_shader=color_palette,
                               x=0, y=0)
splash.append(bg_sprite)

time.sleep(1)

display.show(None)

print("SPI:", "{:>8}".format(spi.frequency), "Hz pre-loop")

loop = 0
while True:
    time.sleep(1)
    print(loop, time.monotonic_ns(), "SPI:", "{:>8}".format(spi.frequency), "Hz")
    loop += 1

With this code running (primary change is the SPI frequency change block), pressing the reset button (with or without display actually connected) triggers the slowdown as shown:

236 900178000000 SPI:  3000000 Hz
237 902079000000 SPI:  3000000 Hz
238 903980000000 SPI:  3000000 Hz
239 905881000000 SPI:  3000000 Hz
240 907782000000 SPI:  3000000 Hz
...{reset button}...
Display: HX8357
SPI:   250000 Hz old
SPI:  3000000 Hz try
SPI:  3000000 Hz new
SPI:  3000000 Hz unlocked
SPI:   250000 Hz pre-loop
0 39399000000 SPI:   250000 Hz
1 49976000000 SPI:   250000 Hz
2 60553000000 SPI:   250000 Hz
3 71130000000 SPI:   250000 Hz
4 81707000000 SPI:   250000 Hz

It seems related to the SPI frequency. Once in slow mode, spi.configure(baudrate=x) isn't sticky.

Even after a reload... same non-stickiness of SPI frequency:

code.py output:
Begin
Display: HX8357
SPI:   250000 Hz old
SPI:  3000000 Hz try
SPI:  3000000 Hz new
SPI:  3000000 Hz unlocked
SPI:   250000 Hz pre-loop
0 122040000000 SPI:   250000 Hz
1 132551000000 SPI:   250000 Hz
2 143062000000 SPI:   250000 Hz
3 153573000000 SPI:   250000 Hz
4 164084000000 SPI:   250000 Hz

@anecdata
Copy link
Author

anecdata commented Jun 17, 2019

Once restored to "normal" beta mode, spi.configure(baudrate=x) is sticky again:

Begin
Display: HX8357
SPI:  3000000 Hz old
SPI:  3000000 Hz try
SPI:  3000000 Hz new
SPI:  3000000 Hz unlocked
SPI:  3000000 Hz pre-loop
0 849656000000 SPI:  3000000 Hz
1 851557000000 SPI:  3000000 Hz
2 853458000000 SPI:  3000000 Hz
3 855359000000 SPI:  3000000 Hz
4 857260000000 SPI:  3000000 Hz
5 859161000000 SPI:  3000000 Hz

@anecdata
Copy link
Author

It looks like baudrate shouldn't be changed once the SPI display is initialized, so "slow mode" can be avoided with a different code sequence by doing any SPI frequency changes before setting up SPI devices. It will then be static for the life of the program. It's not clear whether this is intentional. Without context manager, SPI frequency does seem to persist across reloads, hardware reset, and power loss.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment