8000 esp32s2: Add I2SAudioOut by jepler · Pull Request #3733 · adafruit/circuitpython · GitHub
[go: up one dir, main page]

Skip to content

esp32s2: Add I2SAudioOut #3733

New issue

Have a question about this project? Sign up for a free GitHub account to open 8000 an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jan 12, 2021
Merged

esp32s2: Add I2SAudioOut #3733

merged 22 commits into from
Jan 12, 2021

Conversation

jepler
Copy link
@jepler jepler commented Nov 20, 2020

Fixes #3882.

Testing I performed:

  • used a Kaluga & UDA1334 I2S DAC breakout
  • scoped both logic & audio signals
  • Listened to RawSample tones in mono and stereo, 16-bit
  • Listened to WaveFile tones in mono and stereo, 8- and 16-bit

My test program for wave files, plus some example files:
esp32s2-i2sout-test.zip

@tannewt tannewt self-requested a review November 24, 2020 00:38
Copy link
Member
@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions. Thanks for adding this!

@jepler
Copy link
Author
jepler commented Nov 24, 2020

@microdev1 @UnexpectedMaker if either of you have a chance to test this for functionality that would be great!

@microdev1
Copy link
Collaborator

@jepler I would love to test this but I don't have the proper audio hardware at the moment.
I'll post an update if I am able to hack something up to test this out. :)

@dhalbert
Copy link
Collaborator
dhalbert commented Dec 2, 2020

@jepler I could test this but I see there are a few unresolved code suggestions to do first.

(note that the before and after files both lack trailing newlines; this is
how the esp-idf do)

OPTIMIZATION_DEFAULT is -Og, which enables optimizations that do not
interfere with the debugger:
```
    elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
        list(APPEND compile_options "-Og")
```
this is an exception class for "generic" IDF errors that don't have
their own exception type.
By surrounding most ESP-IDF API calls with this new macro, their failure will
result in a CircuitPython exception.
< 8000 div class="d-flex flex-md-row flex-column">
This can be useful so that e.g., on a Kaluga when programming via
the FTDI chip, you can override the variable to specify "--after=hard_reset"
to automatically return to running CircuitPython, choose a different
baud rate (921600 is about 2s faster than 460800), etc:
    make BOARD=espressif_kaluga_1 ESPTOOL_FLAGS="-b 921600 --before=default_reset --after=hard_reset"
@jepler
Copy link
Author
jepler commented Jan 7, 2021

Test program: mixing mono RawSamples to stereo:

import array 
import audiobusio
import audiocore
import board
import supervisor
import sys
import time
import math

def busy_sleep(n):
    deadline = time.monotonic_ns() + int(n * 1e9)
    while time.monotonic_ns() < deadline:
        pass

# wait for serial connection
while not supervisor.runtime.serial_connected:
    pass
time.sleep(.1)
while supervisor.runtime.serial_bytes_available:
    sys.stdin.read(1)

print("press any key", end='')
while not supervisor.runtime.serial_bytes_available:
    pass
sys.stdin.read(1)
print()

print("construct sample data")
busy_sleep(.1)
b1 = array.array('h', [1024, 1024, -1024, -1024]) * 61

print("construct sample object")
busy_sleep(.1)
s1 = audiocore.RawSample(b1, channel_count=1)

b2 = array.array('h', [1024, 1024, 0, 0, -1024, -1024]) * 128
s2 = audiocore.RawSample(b2, channel_count=1)

print("construct i2s object")
busy_sleep(.1)
a = audiobusio.I2SOut(bit_clock=board.IO35, word_select=board.IO33, data=board.IO34)

print("play sample")
busy_sleep(.1)

while True:
    print("s1")
    a.play(s1, loop=True)
    busy_sleep(2)
    a.stop()
    busy_sleep(.1)
    print("s2")
    a.play(s2, loop=True)
    busy_sleep(2)
    a.stop()
    busy_sleep(.1)

@jepler jepler marked this pull request as draft January 7, 2021 22:30
@jepler
Copy link
Author
jepler commented Jan 7, 2021

At this point, RawSamples seem to function properly. However, WaveFiles don't work right -- each one plays a different characteristic tone, which may be the first 256 or 512 bytes of the sample. I haven't gotten good debug information via serial prints yet, but it almost looks as though the background task stops getting called. This could be related to how busy_sleep is necessary sometimes.

jepler added 5 commits January 8, 2021 08:46
There were _possibly_ problems where this routine was being entered
by direct call AND by background callback.  Schedule the work here,
and it will be done almost immediately, without worry about interference.
I don't know if this is strictly necessary, but it doesn't hurt.  Since
the I2S clock is being run all the time, we have to enter the background
task to fill the FIFO with zeros constantly anyway.
.. otherwise, the background callback to load the I2S fifos does not get
run.  (I'm not sure this is _correct_ behavior of sleep + background
tasks, but it is the current behavior)
jepler added 2 commits January 9, 2021 13:41
Originally, I believed the implementation might be shared with AudioOut,
as on the ESP32 (non-S2) the I2S peripheral was also used to drive the DAC.
However, this is not the case on ESP32-S2 and appears it will not be
the case with the ESP32-S3 or -C3, to the extent that there's skeletal
support for either of them in esp-idf master branch.

However, it could still be shared by I2SIn or PDMIn (the latter being
hypothetically implemented as I2SIn + digital postprocessing like we did
in the atmel-sam port, to my understanding), so I moved it to
the common-hal folder.
Some ports need an extra operation to ensure that the main task is
awoken so that a queued background task will execute during an ongoing
light sleep.

This removes the need to enable supervisor ticks while I2SOut is operating.

Closes: adafruit#3952
@jepler jepler marked this pull request as ready for review January 9, 2021 20:03
@jepler jepler requested a review from tannewt January 9, 2021 20:06
tannewt
tannewt previously approved these changes Jan 11, 2021
Copy link
Member
@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Thank you!

@tannewt
Copy link
Member
tannewt commented Jan 11, 2021

FYI: This needs a translation update.

Copy link
Member
@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me! Thank you!

@dhalbert dhalbert merged commit f9c7622 into adafruit:main Jan 12, 2021
@jepler jepler deleted the audioout-esp32 branch November 3, 2021 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement I2SAudioOut on ESP32-S2
4 participants
0