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:

Code: Select all

write_multi((14,0),(5,1),(0,1))
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