Commit Graph

29 Commits

Author SHA1 Message Date
Dan Halbert 79ee78e690 fix SAMD21 PDMIn DMA event use 2021-10-19 13:18:14 -04:00
Dan Halbert b8b23c97d9 improve SAMD audio DMA 2021-08-21 14:34:37 -04:00
Scott Shawcroft 0c1d6cef75
Merge remote-tracking branch 'adafruit/main' into fix_cp_irremote 2021-08-11 13:43:59 -07:00
Scott Shawcroft f0859ac954
Switch SAMD21 ticks to PER event
The EVSYS is used to generate an interrupt from the event. This
simplifies timing used in pulseio that conflicted with the
auto-reload countdown.

Fixes #3890
2021-08-10 15:23:45 -07:00
Dan Halbert 59b89fdc5c Fix various audio DMA issues:
RP2040 and SAMD51:
- Detect when DMA has finished, and stop DMA audio explicitly.
- Do not accidentally reuse `first_buffer` supplied by WaveFile or RawSample. Always realloc `first_buffer` and `second_buffer`

RP2040:
- When audio playing is stopped, write a final zero to the output register. This prevents residual PWM tones.
- Handle buffer size for 8-bit samples properly for 16-bit output.
- Fail on some edge cases (which may not be possible at the moment).
2021-08-09 09:47:13 -04:00
Dan Halbert fd71d924d2 partial buffer mgmt fix 2021-08-09 09:47:13 -04:00
Dan Halbert 33bbb8b1f4 RP2040 PWMAudioOut: Release DMA channels after play has finished. 2021-07-01 17:36:29 -04:00
Jeff Epler 34c4cc1bd9 samd: Rename dma_{allocate,free} channel
These are now used in the (video) parallel capture device as well.
2021-04-23 09:46:33 -05:00
Jeff Epler d50feebd2c atmel-sam: Factor out find_sync_event_channel_raise 2021-04-20 13:33:11 -05:00
microDev a52eb88031
run code formatting script 2021-03-15 19:27:36 +05:30
Jeff Epler 742aa740f6 samd: audio: Move to background callback
Testing performed: Played half of the Bartlebeats album :) :)
2020-07-15 09:26:47 -05:00
Jeff Epler adef45403b samd: audio dma: enable/disable supervisor tick as needed 2020-05-13 10:29:36 -05:00
Jeff Epler c8f969feb5 samd: audio-dma: avoid memory allocations
With the previous change, stereo mp3 playback changed from needing
4 2304-byte allocations to needing 2 4604-byte allocations.  This was
enough to cause MemoryErrors with regularity.

By using m_realloc() here, the existing memory region can be used.
m_realloc() also works on the first invocation, because m_realloc(NULL, sz)
just calls m_malloc of sz.
2020-01-27 08:49:41 -06:00
jepler 30a9346373 samd: audio_dma: Track channel allocation
Previously, we depended on allocated channels to always be
"dma_channel_enabled".  However, (A) sometimes, many operations
would take place between find_free_audio_dma_channel and
audio_dma_enable_channel, and (B) some debugging I did led me to believe
that "dma_channel_enabled" would become false when the hardware ended
a scheduled DMA transaction, but while a CP object would still think it
owned the DMA channel.

((B) is not documented in the datasheet and I am not 100% convinced that
my debugging session was not simply missing where we were disabling the
channel, but in either case, it shows a need to directly track allocated
separately from enabled)

Therefore,
 * Add audio_dma_{allocate,free}_channel.
   * audio_dma_free_channel implies audio_dma_disable_channel
   * track via a new array audio_dma_allocated[]
 * clear all allocated flags on soft-reboot
 * Convert find_free_audio_dma_channel to audio_dma_allocate_channel
   * use audio_dma_allocated[] instead of dma_channel_enabled() to check
     availability
 * remove find_free_audio_dma_channel
 * For each one, find a matching audio_dma_disable_channel to convert
   to audio_dma_free_channel

Closes: #2058
2019-08-28 17:00:22 -05:00
Jeff Epler 33b949abfa samd: audio_dma, audio_background: Gate with CIRCUITPY_ defines
Some ports which actually don't have audioio or audiobusio were still
calling into audio_dma_background().  This wasn't an error until
the assignment to audio_dma_state in audio_dma_stop was added, though
it's not clear why.
2019-08-07 21:29:24 -05:00
Jeff Epler 500d1bb168 samd: audio_dma.c: Remove exceptions, just return early
These were most useful debugging, but because this code can be reached
"outside of the VM", it's not actually permitted to throw exceptions here.
2019-08-07 20:20:36 -05:00
Jeff Epler 39c64bf83c samd: audio_dma_stop: don't free invalid channel
audio_dma_stop can be reached twice in normal usage of AudioOut.

This may bear further investigation, but stop it here, by making the
function check for a previously freed channel number.  This also prevents
the event channel from being disabled twice.

The first stop location is from audio_dma_get_playing, when the buffers
are exhausted; the second is from common_hal_audioio_audioout_stop when
checking the 'playing' flag.
2019-08-06 22:00:31 -05:00
Jeff Epler 8b717955ba samd: audio_dma: wrap dma_{en,dis}able_channel and add error checking
It turns out the "disable" error will fire in practice, we'll fix that
next.
2019-08-06 22:00:31 -05:00
Jeff Epler 6253f11503 samd: audio_dma_stop: Clear out audio_dma_state[]
As identified in #1908, when both AudioOut and PDMIn are used, hard
locks can occur.  Because audio_dma_stop didn't clear audio_dma_state[],
a future call to audio_dma_load_next_block could occur using a DMA
object which belongs to PDMIn.

I believe that this Closes: #1908 though perhaps it is still not the full
story.

Testing performed: Loaded a sketch similar to the one on #1908 that
tends to reproduce the bug within ~30s.  Ran for >300s without hard
lock.  HOWEVER, while my cpx is no longer hard locking, it occasionally
(<1 / 200s) announces
    Code done running. Waiting for reload.
(and does so), even though my main loop is surrounded by a 'while True:'
condition, so there are still gremlins nearby.
2019-08-06 21:34:21 -05:00
Jeff Epler 6b44e40ee8 audiocore: Factor from audioio
When nrf pwm audio is introduced, it will be called `audiopwmio`.  To
enable code sharing with the existing (dac-based) `audioio`, factor
the sample and mixer types to `audiocore`.

INCOMPATIBLE CHANGE: Now, `Mixer`, `RawSample` and `WaveFile` must
be imported from `audiocore`, not `audioio`.
2019-07-25 06:44:26 -05:00
Scott Shawcroft 76008ce304
Introduce audioio.Mixer which can mix multiple audio samples
to produce a single sample.

Only works with 16 bit samples on the M4.

Fixes #987
2018-10-05 15:12:23 -07:00
Scott Shawcroft de5a9d72dc
Compress all translated strings with Huffman coding.
This saves code space in builds which use link-time optimization.
The optimization drops the untranslated strings and replaces them
with a compressed_string_t struct. It can then be decompressed to
a c string.

Builds without LTO work as well but include both untranslated
strings and compressed strings.

This work could be expanded to include QSTRs and loaded strings if
a compress method is added to C. Its tracked in #531.
2018-08-16 17:40:57 -07:00
Scott Shawcroft a5e03b76a6 Split out the peripherals library in preparation of sharing with MakeCode. 2018-06-15 16:16:21 -07:00
Dan Halbert e724bc1c4e Fix playing audio from SD card 2018-06-14 18:47:40 -04:00
Scott Shawcroft fd71e56891 atmel-samd: Re-org helper peripheral files into their own subdirectory.
Ideally in the future they won't depend on ASF4 or MicroPython.
2018-06-01 15:07:31 -07:00
Scott Shawcroft 50fc90bc5f Add pause/resume control to AudioOut and I2SOut
Fixes #808
2018-05-08 11:53:13 -07:00
Scott Shawcroft 22b7cd3d51 Fix 8 bit recordings on CPX.
The DMA trigger source was incorrect when using serializer 1 on
the SAMD21.

Playback register was incorrect for 8 bit as well. Now fixed.
2018-05-02 15:15:25 -07:00
Scott Shawcroft cfea51ec68 Re-enable PDMIn without ASF and using the helpers added with
I2SOut.

The API is almost the same except the frequency attribute has been
renamed to sample_rate so that its less likely to be confused with
frequencies within the audio itself.

Fixes #263.
2018-05-01 14:35:43 -07:00
Scott Shawcroft 28642ab10d Add audio output support!
This evolves the API from 2.x (and breaks it). Playback devices are now
separate from the samples themselves. This allows for greater playback
flexibility. Two sample sources are audioio.RawSample and audioio.WaveFile.
They can both be mono or stereo. They can be output to audioio.AudioOut or
audiobusio.I2SOut.

Internally, the dma tracking has changed from a TC counting block transfers
to an interrupt generated by the block event sent to the EVSYS. This reduces
the overhead of each DMA transfer so multiple can occure without using up TCs.

Fixes #652. Fixes #522. Huge progress on #263
2018-04-12 16:35:13 -07:00