Page 2 of 3
Re: Set Pins values synchroniously
Posted: Thu Nov 07, 2019 8:44 pm
by Roberthh
You test code above would with viper and including masking for instance look like:
Code: Select all
from machine import Pin, mem16
p12=Pin(12, Pin.OUT)
p14=Pin(14, Pin.OUT)
@micropython.viper
def set_gpio(value:int, mask:int):
GPIO_OUT = ptr32(0x3FF44004) # GPIO Output register
GPIO_OUT[0] = (GPIO_OUT[0] & mask) | value
p12.value(0)
print(p12.value())
p14.value(0)
print(p14.value())
#esp32
set_gpio(0b00000000000000000101000000000000,
0b11111111111111111010111111111111)
print(p12.value())
print(p14.value())
Re: Set Pins values synchroniously
Posted: Thu Nov 07, 2019 9:16 pm
by pidou46
Nice, it works like a charm with the latest build.
Thank you
Re: Set Pins values synchroniously
Posted: Thu Nov 07, 2019 9:23 pm
by pidou46
Still, I think OutoftheBOTS_ is right it could be usefull to have synchro pin value setting build in micropython, it would bring easyness and portability, I will probably open an issue on git repository since I'm (still) not able to make a PR by myself...
Re: Set Pins values synchroniously
Posted: Fri Nov 08, 2019 9:08 am
by pythoncoder
It could be difficult to achieve in machine since registers are platform dependent. A Pyboard-only solution could be implemented as a user module.
Re: Set Pins values synchroniously
Posted: Fri Nov 08, 2019 10:13 am
by Roberthh
A lot of the stuff in machine is platform dependent. machine is the API that hides it. I see more the problem on how the api should look like, in contrast to the simplicity of self implemented functions, which hardly are longer than a few lines, and, if implemented as viper code, are pretty fast.
P.S.: The API could be something like:
gpio_set(value, GPIO_number_list, init=False)
If init is true, the GPIO's would be configured to OUT mode. still easy to implement as Python function.
Re: Set Pins values synchroniously
Posted: Fri Nov 08, 2019 8:18 pm
by OutoftheBOTS_
It is correct that it isn't many lines of code but for a beginner python programmer (python mainly being a higher level language) it is a little confusing understanding viper code and masking and reset(&= ~) or set(|=)
It is true that working out just how the python implementation should look and work is the hardest part.
Sometimes people will want to do 4 bit parallel, sometimes 8 bit parallel and sometimes 16 bit.
A machine.write_mulit(number_bits, first_pin, data) method that takes the inputted bits e.g 8 bits then shifts it to the needed position to correspond to correct parallel pins e.g pin5 to pin12 then reads the ODR first sets the needed 8 bits to 0 then && the new bits in then writes it back to the ODR. Then also a similar function for reading in parallel
Re: Set Pins values synchroniously
Posted: Fri Nov 08, 2019 8:29 pm
by Roberthh
Yes, that is similar to what I sketched in my post. Only that I though of a list of pin numbers, to allow for non-consecutive port bits to be set. Looking at the various boards on my desk, there is no common set of bits which is available. Protoyping that in Python & Viper is easy - and maybe sufficient.
Re: Set Pins values synchroniously
Posted: Fri Nov 08, 2019 9:15 pm
by Roberthh
Here is a simple implementation of that. Whithin the limits of my cheap 10€ saleae clone, the bits are set simultaneously. The bits of value are in the same order as the pin list. Lowest order bit of the data goes to the last pin in the list. Using mem32 instead of the viper helper function works too, but is a little bit worse in timing consistency.
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
for pin in list[::-1]:
if init:
Pin(pin, Pin.OUT)
mask |= 1 << pin
value |= (data & 1) << pin
data >>= 1
mask = 0xffffffff - mask
set_gpio(value, mask)
# mem32[0x3FF44004] = (mem32[0x3FF44004] & mask) | value
def run():
init = True
for n in range(8):
write_multi(n, [14, 18, 4], init)
init = False
See:
https://hidrive.ionos.com/lnk/naYGqITP
Re: Set Pins values synchroniously
Posted: Sat Nov 09, 2019 6:55 am
by kevinkk525
Would it be possible to change the API to accept tuples of pin number and pin value?
So you could call it like:
Or would that not feel more natural?
Re: Set Pins values synchroniously
Posted: Sat Nov 09, 2019 7:52 am
by Roberthh
That's obviously possible, the code would then e.g. look like the one below. But calling may be a little bit more effort, if the bits are in a single value at the callers side.
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(*pv_list, init=False):
mask = 0
value = 0
for pin, bit in pv_list:
if init:
Pin(pin, Pin.OUT)
mask |= 1 << pin
value |= ((bit & 1) << pin)
mask = 0xffffffff - mask
set_gpio(value, mask)
# mem32[0x3FF44004] = (mem32[0x3FF44004] & mask) | value
def run():
init = True
for n in range(8):
write_multi((14, n >> 2), (18, n >> 1), (4, n), init=init)
init = False