Extend the bitfields of these instructions: BitmapHandle, ClearTag, Tag, BitmapSource, PaletteSource
Add instructions: BitmapSourceH PaletteSourceH
All the new bits and opcodes are ignored by earlier hardware, so this change is backwards-compatible.
Passes tests on all EVE hardware.
The setmodel() method controls the behavior
So existing code will continue to work unchanged
Subsequent releases of the ``eve`` library will call setmodel() to enable the new behavior
Confirmed all code paths on EVE hardware
Now, try_lock (SPI & I2C) & begin_transaction (display bus core) will check
that the related objects are still valid first; if they are not,
the lock/begin transaction will fail by returning false, rather than
"other things" such as raising a Python exception where it is not
permitted, accessing invalid memory, etc.
Closes#8278 and Closes#9426
This adds support for the next RP2 microcontroller, the RP2350.
Thanks to Raspberry Pi folks for early access and to @arturo182,
@oberchoo and @SalamCytron for helping with CircuitPython.
The traditional layout of pixels in bitmaps of depth less than eight
is with the order of values in a byte reversed, but with bytes in
the same order as the pixels on the line.
Before now, displayio.Bitmap did reverse the values, but did it on a
word (four bytes) basis, not byte, which resulted in groups of four
bytes being in the order opposite to the screen order.
This patch fixes this, by making processing of pixels in bitmaps of
depth less than 8 bits based on bytes, not words. Since the internal
details are changing, any code that accessed bitmaps through the
memoryview buffer, or that created bitmaps directly from raw data,
and that used depth of less than 8 bits will be affected.
Therefore, the gen_display_resources.py script also had to be modified
to account for the changes.
These protocol operations should not raise exceptions, but sometimes
they do. Catch the exception and extract the errno value if available.
At the same time, harmonize the argument types for the underlying C
routines
* Don't consume in the case of "indata overflow".
Doing so leaves us at a bad boundary within the MP3 data
and can continue decoding from an inappropriate spot
i.e., one that looks likede mp3 data but is NOT.
because there are many crashing bugs in the helix mp3 library on
invalid input data, we must do our best to avoid them, and this
is one way to do that.
* clear the output buffer in the case there's not a sync word in the
buffer. this can also happen when too little data is available.
this changes more "stuttering" conditions into "silent" conditions.
With these changes, I can get through 3+ plays of "idea.mp3" from a local
http server with long pauses (but not stuttering glitches or safe mode
crashes).
I was also able to play through 10+ minutes of http://ice2.somafm.com/dronezone-128-mp3
without crashing or "end of stream", though again there are pauses
due to packet loss.
I think this is good now, except for the problems that arise when
the socket layer doesn't deliver a fresh packet for a long time.
You can now, e.g.,
```
with open("/whatever.mp3") as mp3_file:
mp3_file.seek(16000*30)
decoder.file = mp3_file
i2s.play(decoder)
```
to start about 30 seconds into a 128kbit/s CBR track.
If a track is looped, the loop will start at the beginning.
This also changes the behavior if the track is started & stopped: it will
continue from where it left off, except if it had prevously run to
completion. To get other behavior, you can seek the file and then re-assign
the file property.
This gets MP3 playback of a soma.fm stream working for up to a minute
at a time, though it's still vulnerable to network glitches.
* the buffer can empty, in which case a single block of audio
plays repeatedly in max headroom stutter fashion
* the server eventually (after 1 to 5 5 minutes) stops getting packets
at all. At this point stream playback stops, with the internal error
indicating a problem MP3 decoding (which doesn't quite make sense):
-9, ERR_MP3_INVALID_HUFFCODES.
* other combinations of audiomixer buffer & mp3 buffer might give
different results
```py
import time
import adafruit_connection_manager
import adafruit_requests
import audiobusio
import audiomixer
import audiomp3
import board
import wifi
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
requests = adafruit_requests.Session(pool, ssl_context)
# todo: parse PLS files like https://somafm.com/nossl/dronezone.pls
# todo: figure out why https URLs don't work at all (missing select?)
# STREAMING_URL = "http://ice2.somafm.com/dronezone-128-mp3"
STREAMING_URL = "http://ice4.somafm.com/tikitime-128-mp3"
def get_mp3_stream():
if STREAMING_URL.startswith("http:") or STREAMING_URL.startswith("https:"):
return requests.get(STREAMING_URL, headers={"connection": "close"}).socket
return open(STREAMING_URL, "rb")
mixer_buffer_size = 1152 * 2
mp3_buffer = bytearray(32768)
with audiobusio.I2SOut(
bit_clock=board.D12, word_select=board.D13, data=board.D11
) as i2s, get_mp3_stream() as stream, audiomp3.MP3Decoder(
stream, mp3_buffer
) as sample, audiomixer.Mixer(
channel_count=2, sample_rate=44100, buffer_size=mixer_buffer_size
) as m:
v = m.voice[0]
print(sample)
i2s.play(m)
v.play(sample, loop=False)
while v.playing:
time.sleep(0.1)
```
An mp3 decoder (note that this needs `audiocore.get_buffer`, not
enabled on devices):
```py
import sys
import audiomp3
import audiocore
GET_BUFFER_DONE, GET_BUFFER_MORE_DATA, GET_BUFFER_ERROR = range(3)
with audiomp3.MP3Decoder(sys.argv[1]) as decoder, open(sys.argv[2], "wb") as target:
while True:
res, samples = audiocore.get_buffer(decoder)
if res != GET_BUFFER_ERROR:
target.write(samples)
if res != GET_BUFFER_MORE_DATA:
break
```
this doesn't actually add any tests though
This can sort-of play MP3s from a http request, but the buffering is
not good enough to play glitch-free. A new kind of buffer that can
read ahead further without blocking is needed.