0

Using MiniTFTFeatherWing and 74HC595 possible?
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Using MiniTFTFeatherWing and 74HC595 possible?

by EnlitenAudio on Tue Sep 10, 2019 11:02 pm

As a test/monitor platform we are trying, we have a M4 express with a 3321 Joystick FeatherWing running CircuitPython Rev 4.1.0. While running `adafruit_featherwing.minitft_featherwing` can we hack the example and squirt out data to a 74HC595 on a button press or are we out of luck unlocking the SPI? Releasing the display and rerunning "minitft" init routine seems to work but this also resets Seesaw flashing the backlight and takes 5 secs....

Thanks for your patience with us CircuitPython noobs...

EnlitenAudio
 
Posts: 7
Joined: Thu Aug 29, 2019 2:47 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by tannewt2 on Wed Sep 11, 2019 2:33 pm

Please rephrase what you are trying to do. The display code should be shareable with other spi devices but I haven't tested it myself.

tannewt2
 
Posts: 1297
Joined: Thu Oct 06, 2016 8:48 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by EnlitenAudio on Wed Sep 11, 2019 11:13 pm

Sure, here's a simple test:

# Test code for Athena HUI - with LCD - traceback occurs

from adafruit_featherwing import minitft_featherwing
import time
import board
import busio
import digitalio

# RCLK for the 74Hc595
cs = digitalio.DigitalInOut(board.D4)
cs.direction = digitalio.Direction.OUTPUT
cs.value = True

spi = busio.SPI(board.SCK, MOSI=board.MOSI) <<< Traceback (most recent call last): File "code.py", line 13, in <module> ValueError: SCK in use

OUCH
.... therefore we can't run:

while not spi.try_lock():
pass

.... later in code. Seems MiniTFTFeatherWing won't let go of SPI for other devices to use SPI in any case.

However based on:
"Unlike other objects in CircuitPython, Display objects live until displayio.release_displays() is called."

displayio.release_displays() releases SPI nicely. We then run 74HC595 SPI write and rerun MiniTFTFeatherWing and back to the quickie miniREPL on the LCD. Only problem with that method is it has 5secs delay to init and flashing LCD display during the re-init. Can we avoid the 5secs and display backlight flash (assuming a seesaw restart)?

EnlitenAudio
 
Posts: 7
Joined: Thu Aug 29, 2019 2:47 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by tannewt2 on Thu Sep 12, 2019 4:03 pm

Ah! You need to use the same SPI object as the FeatherWing library which is available as `board.SPI()`.

So, do:
Code: Select all | TOGGLE FULL SIZE
spi = board.SPI()

tannewt2
 
Posts: 1297
Joined: Thu Oct 06, 2016 8:48 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by EnlitenAudio on Thu Sep 12, 2019 6:38 pm

Thanks! That cleared the SPI function call. Now we run this to do the 74HC595 write and re-initialize the LCD monitor:

cs.value = False
spi.write(bytes([0x00, 0x02]))
cs.value = True

led.value = True
time.sleep(.5)
led.value = False
time.sleep(.5)

minitft = minitft_featherwing.MiniTFTFeatherWing()

time.sleep(2)
print()
print()
print()
print(" I'm Back!")
print()

...we see the 3 short LED pulse and 1 long and the display locks up with the initialize along with the REPL on Mu - so no feedback.

EnlitenAudio
 
Posts: 7
Joined: Thu Aug 29, 2019 2:47 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by tannewt2 on Fri Sep 13, 2019 12:05 pm

Try switching to CircuitPython 5.0.0 Alpha 2. We may have fixed a bug in it.

tannewt2
 
Posts: 1297
Joined: Thu Oct 06, 2016 8:48 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by EnlitenAudio on Fri Sep 13, 2019 3:17 pm

Gotit, we'll give it a try!

EnlitenAudio
 
Posts: 7
Joined: Thu Aug 29, 2019 2:47 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by EnlitenAudio on Sun Sep 15, 2019 1:11 pm

Unfortunately no help from 5.0 A2. Just to review we run the textbook minitft_featherwing pycode with an edited buttons.down routine:

if buttons.down:
print("Button DOWN!")
time.sleep(.2)
displayio.release_displays()
time.sleep(.2)
spi = board.SPI()
while not spi.try_lock():
pass

led.value = True
time.sleep(.2)
led.value = False
time.sleep(.2)
led.value = True
time.sleep(.2)
led.value = False
time.sleep(.2)
led.value = True
time.sleep(.2)
led.value = False
time.sleep(.2)

cs.value = False
spi.write(bytes([0xff, 0x02]))
cs.value = True

led.value = True
time.sleep(.5)
led.value = False
time.sleep(10)

minitft = minitft_featherwing.MiniTFTFeatherWing()

time.sleep(2)
print()
print()
print()
print(" I'm Back!")
print()

The feather runs the buttons.down completely up to time.sleep(10) and locks up. The serial link is also locked up. Mu must be closed and restarted and the featherwing express must be powercycled (reset button restarts code but does not restore serial link) to get minitft_featherwing pycode AND serial link working properly again.

EnlitenAudio
 
Posts: 7
Joined: Thu Aug 29, 2019 2:47 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by go on Mon Sep 16, 2019 12:06 am

Can you post your complete minimal example please (with [code] format)? I don't have a 74HC595, but I do regularly run various SPI displays (including the MiniTFT+Joy) alongside other SPI devices like Airlift, SD Card, etc., without issue in 4.x and 5.x There should be no conflict as long as each has its own CS pin. I can try to test your code w/o the 74HC595 at least.

go
 
Posts: 43
Joined: Fri Sep 11, 2015 10:41 am

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by EnlitenAudio on Tue Sep 17, 2019 12:34 pm

We used D4 as the RCLK. FYI 595 SPI works fine (writes to 595 properly and shows up on output pins) on inline code w/o minitft_featherwing. Seems the semaphore may be the issue, perhaps it's not released properly with displayio.release_displays()??? Here's the minitft_featherwing hack that locks up:

# Test code for Athena HUI - with monitor LCD
from adafruit_featherwing import minitft_featherwing
import time
import displayio
import board
import digitalio
minitft = minitft_featherwing.MiniTFTFeatherWing()
# RCLK for the 74Hc595
cs = digitalio.DigitalInOut(board.D4)
cs.direction = digitalio.Direction.OUTPUT
cs.value = True

spi = board.SPI()
led = digitalio.DigitalInOut(board.D13)
led.direction = digitalio.Direction.OUTPUT

led.value = False

while True:
buttons = minitft.buttons

if buttons.right:
print()
print()
print(" Button RIGHT!")
print()
print()

if buttons.down:
print("Button DOWN!")
time.sleep(.2)
displayio.release_displays()
time.sleep(.2)
spi = board.SPI()
while not spi.try_lock():
pass

led.value = True
time.sleep(.2)
led.value = False
time.sleep(.2)
led.value = True
time.sleep(.2)
led.value = False
time.sleep(.2)
led.value = True
time.sleep(.2)
led.value = False
time.sleep(.2)

cs.value = False
spi.write(bytes([0xff, 0x02]))
cs.value = True

led.value = True
time.sleep(.5)
led.value = False
time.sleep(10)

minitft = minitft_featherwing.MiniTFTFeatherWing()

time.sleep(2)
print()
print()
print()
print(" I'm Back!")
print()

if buttons.left:
print()
print()
print()
print(" Button LEFT!")
print()

if buttons.up:
print("Button UP!")

if buttons.select:
print("Button SELECT!")

if buttons.a:
print("Button A!")

if buttons.b:
print("Button B!")

time.sleep(.2)

EnlitenAudio
 
Posts: 7
Joined: Thu Aug 29, 2019 2:47 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by EnlitenAudio on Tue Sep 17, 2019 12:38 pm

BTW bottom line is we never see " I'm Back!" and the joy no longer responds.

EnlitenAudio
 
Posts: 7
Joined: Thu Aug 29, 2019 2:47 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by tannewt2 on Tue Sep 17, 2019 12:47 pm

The MiniTFTFeatherwing isn't able to initialize because you've grabbed the SPI lock with:

Code: Select all | TOGGLE FULL SIZE
while not spi.try_lock():
    pass


It's sitting in an infinite loop waiting for the lock.

After your write you need to call `spi.unlock()`. Better yet, use SPIDevice to handle the locking for you: https://github.com/adafruit/Adafruit_Ci ... _device.py

tannewt2
 
Posts: 1297
Joined: Thu Oct 06, 2016 8:48 pm

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by go on Tue Sep 17, 2019 2:15 pm

I was able to get the SPI and display to work by tweaking a few things (and commented out the empty prints so more lines could be seen on the TFT). You don't need to re-create MiniTFTFeatherWing, you just need to make sure that different SPI devices that are already set up don't step on each other's toes.

tannewt2 of course makes an excellent suggestion above (look at the example in that library). I'm not familiar with the intricacies of Seesaw, but I don't see all of the button presses. But that's I2C and should be independent of any SPI issues. I assumed button presses would be buffered, but I don't know the details.

The challenge is still that the 74HC595 operations are happening a bit manually here, so it may not coordinate perfectly with other SPI devices. The libraries are good at helping with that.

Code: Select all | TOGGLE FULL SIZE
# Test code for Athena HUI - with monitor LCD
import time
import displayio
import board
import digitalio
from adafruit_featherwing import minitft_featherwing

# MiniTFTFeatherWing will handle this if we don't
#    ...but, we need it for the 74HC595
spi = board.SPI()

# MiniTFTFeatherWing will handle this if we don't
# displayio.release_displays()

tft_cs = board.D9   # my jumpers are changed (default = D5)
tft_dc = board.D10  # my jumpers are changed (default = D6)
minitft = minitft_featherwing.MiniTFTFeatherWing(spi=spi, cs=tft_cs, dc=tft_dc)

#
display = minitft.display
display.show(None)

# RCLK for the 74Hc595
cs = digitalio.DigitalInOut(board.D4)
cs.direction = digitalio.Direction.OUTPUT
cs.value = True

led = digitalio.DigitalInOut(board.D13)
led.direction = digitalio.Direction.OUTPUT

led.value = False

while True:
    buttons = minitft.buttons

    if buttons.right:
        # print()
        # print()
        print(" Button RIGHT!")
        # print()
        # print()

    if buttons.down:
        print("Button DOWN!")
        time.sleep(.2)

    led.value = True
    time.sleep(.2)
    led.value = False
    time.sleep(.2)
    led.value = True
    time.sleep(.2)
    led.value = False
    time.sleep(.2)
    led.value = True
    time.sleep(.2)
    led.value = False
    time.sleep(.2)

    while not spi.try_lock():
        pass
    cs.value = False
    print('SPI write... ', end='')
    spi.write(bytes([0xff, 0x02]))  # RuntimeError: Function requires lock
    print('done.')
    cs.value = True
    spi.unlock()

    led.value = True
    time.sleep(.5)
    led.value = False
    # time.sleep(10)

    # minitft = minitft_featherwing.MiniTFTFeatherWing()

    time.sleep(2)
    # print()
    # print()
    # print()
    print(" I'm Back!")
    # print()

    if buttons.left:
        # print()
        # print()
        # print()
        print(" Button LEFT!")
        # print()

    if buttons.up:
        print("Button UP!")

    if buttons.select:
        print("Button SELECT!")

    if buttons.a:
        print("Button A!")

    if buttons.b:
        print("Button B!")

    time.sleep(.2)


Snippet of output:
Code: Select all | TOGGLE FULL SIZE
SPI write... done.
 I'm Back!
Button B!
SPI write... done.
 I'm Back!
Button B!
 Button RIGHT!
SPI write... done.
 I'm Back!

go
 
Posts: 43
Joined: Fri Sep 11, 2015 10:41 am

Re: Using MiniTFTFeatherWing and 74HC595 possible?

by go on Tue Sep 17, 2019 3:24 pm

After some testing, I think Seesaw is principally I/O expansion and not actually buffering, so it doesn't get buttons that happen during sleep (which is most of the time in the present code). You can use busy-waits to count out time using time.monotonic() without sleeping. And you'll probably need to fine-tune the timing of that to debounce and also feel intuitive.

go
 
Posts: 43
Joined: Fri Sep 11, 2015 10:41 am

Please be positive and constructive with your questions and comments.