Page 3 of 3
Re: Set Pins values synchroniously
Posted: Sat Nov 09, 2019 8:11 am
by pythoncoder
I'd think, when doing parallel I/O, it was more common to send a multi-bit data value to a list of pins as per the original version. Speed is also an issue here: if doing parallel I/O it's usually because you need performance.
Re: Set Pins values synchroniously
Posted: Sat Nov 09, 2019 8:29 am
by Roberthh
I made a variant which allows either a singe value or a list of bits, only that two lists o tuples are provided. One for the bits and one for the pins . Speed is the same in both cases, about 100µs per bit.
Code: Select all
from machine import Pin, mem32
@micropython.viper
def set_gpio(value:int, mask:int):
GPIO_OUT = ptr32(0x3FF44004) # GPIO Output register
GPIO_OUT[0] = (GPIO_OUT[0] & mask) | value
def write_multi(data, pin_list, init=False):
mask = 0
value = 0
if type(data) is int:
for i in range(len(pin_list) - 1, -1, -1):
pin = pin_list[i]
if init:
Pin(pin, Pin.OUT)
mask |= 1 << pin
value |= ((data & 1) << pin)
data >>= 1
else:
for i in range(len(pin_list)):
pin = pin_list[i]
if init:
Pin(pin, Pin.OUT)
mask |= 1 << pin
value |= ((data[i] & 1) << pin)
mask = 0xffffffff - mask
set_gpio(value, mask)
def run():
init = True
for n in range(8): # supplying a singe value
write_multi(n, (14, 18, 4), init)
init = False
for n in range(8): # supplying a list of bits
write_multi((n >> 2, n >> 1, n), (14, 18, 4), init)
Re: Set Pins values synchroniously
Posted: Sat Nov 09, 2019 12:25 pm
by Roberthh
Another variant, but just for the int value, using viper code. The init is outside the call. The first call takes 20µs, the following ones 8µs:
Code: Select all
from machine import Pin
@micropython.viper
def write_multi(data:int, pin_list:ptr8, plen:int):
GPIO_OUT = ptr32(0x3FF44004) # GPIO Output register
mask = 0
value = 0
i = plen - 1
while i >= 0:
pin = pin_list[i]
mask |= 1 << pin
value |= ((data & 1) << pin)
data >>= 1
i -= 1
mask = int(0xffffffff) - mask
GPIO_OUT[0] = (GPIO_OUT[0] & mask) | value
def run():
pin_list = bytearray((14,18,4))
for p in pin_list:
Pin(p, Pin.OUT)
pl = len(pin_list)
for n in range(8):
write_multi(n, pin_list, pl)
Viper does not like range(), so the loop is made in a basic mode. And it is very sensitive to the code size. If I add both variants (int and tuple for data), the call takes ~18µs.