disable only turns off ENABLE but doesn't set the init tracking that
nrfx uses. uninit hangs if ENABLE is off and is called because it
waits forever for TX to stop.
.. a requirement that oofatfs needs to be taught to respect.
This problem can be demonstrated with the following snippet, except
that the related file ("test.bin") must also be contiguous on the
filesystem. You can ensure this by reformatting your device's filesystem
before testing, then copying any single file bigger than 4kB to test.bin.
f = open("test.bin", "rb")
f.seek(2048)
b = bytearray(2048)
v = memoryview(b)
f.readinto(v[909:])
Closes: #2332
The "spacing" of "buffer structure" is confusing, use the "channel count"
instead.
Testing performed on nrf52840 feather:
Play stereo and mono, 8- and 16-bit, 8kHz RawSamples representing 333.33Hz
square waves.
Use both mono and stereo PWMAudioOut instances.
Scope the RC-filtered signal and use the scope's frequency
measurement function, verify the frequency is 333 or 334Hz in all tested
cases.
In the "stereo output" cases, verify both the L and R channels. Verify
the output amplitude is the same in both channels.
In the "stereo output" cases, run a second test where the L channel's
amplitude is attenuated 50%. Verify the output amplitude is correct
in each channel.
This adapts the "inline assembler" code from the UF2 bootloader, which
in turn is said to be adapted from the arduino neopixel library.
This requires the cache remain ON when using M0, and be turned OFF on M4
(determined by trial and error)
Testing performed on a Metro M4:
* measured timings using o'scope and found all values within
datasheet tolerance.
* Drove a string of 96 neopixels without visible glitches
* on-board neopixel worked
Testing performed on a Circuit Playground Express (M0):
* Color wheel code works on built-in neopixels
* Color wheel code works on 96 neopixel strip
As a bonus, this may have freed up a bit of flash on M0 targets. (2988 ->
3068 bytes free on Trinket M0)
Closes: #2297
Protocols are nice, but there is no way for C code to verify whether
a type's "protocol" structure actually implements some particular
protocol. As a result, you can pass an object that implements the
"vfs" protocol to one that expects the "stream" protocol, and the
opposite of awesomeness ensues.
This patch adds an OPTIONAL (but enabled by default) protocol identifier
as the first member of any protocol structure. This identifier is
simply a unique QSTR chosen by the protocol designer and used by each
protocol implementer. When checking for protocol support, instead of
just checking whether the object's type has a non-NULL protocol field,
use `mp_proto_get` which implements the protocol check when possible.
The existing protocols are now named:
protocol_framebuf
protocol_i2c
protocol_pin
protocol_stream
protocol_spi
protocol_vfs
(most of these are unused in CP and are just inherited from MP; vfs and
stream are definitely used though)
I did not find any crashing examples, but here's one to give a flavor of what
is improved, using `micropython_coverage`. Before the change,
the vfs "ioctl" protocol is invoked, and the result is not intelligible
as json (but it could have resulted in a hard fault, potentially):
>>> import uos, ujson
>>> u = uos.VfsPosix('/tmp')
>>> ujson.load(u)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: syntax error in JSON
After the change, the vfs object is correctly detected as not supporting
the stream protocol:
>>> ujson.load(p)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: stream operation not supported