Page 1 of 1

Why does pyb.SPI.init() take a nondefaulted prescaler?

Posted: Wed May 30, 2018 4:52 pm
by kwiley
According to https://docs.micropython.org/en/latest/ ... b.SPI.html the pyb.SPI init() function takes a prescaler parameter with no default value. It appears to work if none is provided (which I find a little confusing; shouldn't Python require a parameter for which no default value is provided? I realize there is a bare asterisk requiring named instead of positional args, but that shouldn't allow discarding a nondefaulted arg entirely), but even if it does work, I'm curious why no default is included when there is a default for practically every other parameter to that function? It feels like the docs don't reflect the actual underlying code (i.e., that some default actually is provided by the code even though the docs don't show it), but since the docs are surely machine generated, I can't believe that's the case.

Thanks.

Re: Why does pyb.SPI.init() take a nondefaulted prescaler?

Posted: Wed May 30, 2018 6:25 pm
by dhylands
Well, it has a default value of 0xffffffff: https://github.com/micropython/micropyt ... #L584-L597

If you don't provide a prescaler then it dynamically calculates one which is appropriate for the baudrate. The value 0xffffffff is a value that you can't provide from the python side.

The pyb.SPI module is quite old and at the time it was written, I don't think it was possible to use None, which is how I would do it now if I were writing it.

If you're trying to write a generic function, then I would have the generic function take None as a default, and I would put the args into a dict, but don't store prescaler in the dict if it has a value of None and then pass the expanded dict to pyb.SPI constructor.

Code: Select all

>>> def generic_SPI(bus, mode, prescaler=None):
...     args = {}
...     if not prescaler is None:
...         args['prescaler'] = prescaler
...     spi = pyb.SPI(bus, mode, **args)
...     print(spi)
... 
>>> generic_SPI(1, pyb.SPI.MASTER)
SPI(1, SPI.MASTER, baudrate=328125, prescaler=256, polarity=1, phase=0, bits=8)
>>> generic_SPI(1, pyb.SPI.MASTER, prescaler=128)
SPI(1, SPI.MASTER, baudrate=656250, prescaler=128, polarity=1, phase=0, bits=8)
>>> generic_SPI(1, pyb.SPI.MASTER, prescaler=None)
SPI(1, SPI.MASTER, baudrate=328125, prescaler=256, polarity=1, phase=0, bits=8)

Re: Why does pyb.SPI.init() take a nondefaulted prescaler?

Posted: Fri Jun 01, 2018 7:05 am
by pythoncoder
@kwiley has a valid point - the docs are confusing. The following suggests that prescaler is a mandatory kwonly arg:
SPI.init(mode, baudrate=328125, *, prescaler, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)

Re: Why does pyb.SPI.init() take a nondefaulted prescaler?

Posted: Fri Jun 01, 2018 9:06 pm
by kwiley
Yep. Thanks for considering the question.