Open AngainorDev opened 3 years ago
Currently in progress
I2S is already supported here, as part of espidf module.
Try import espidf
"espidf" is an additional library that comes as part of LVGL.
It includes I2S, SPI master, ADC, Heap functions, PCNT, MDNS. Latest version (which is not yet integrated here) also includes HTTP client.
I2S is already supported here, as part of espidf module
It would be interesting to try this approach. At this point I don't know if anyone has attempted using the espidf module to implement I2S. It's certainly worth checking out. The way to do this is to look at the C code in the PR and duplicate that in MicroPython.
If developer time efficiency and certainty of operation are a concern, then integrating the I2S PR is likely the way to go. It's been used by 100's of people and has documentation. https://github.com/miketeachman/micropython-esp32-i2s-examples
The PR integration consists of adding one C file, and one-line edits to 3 others.
It would be interesting to try this approach. At this point I don't know if anyone has attempted using the espidf module to implement I2S. It's certainly worth checking out. The way to do this is to look at the C code in the PR and duplicate that in MicroPython.
@miketeachman - I have used it.
I'm using it with SPH0645 microphone and it works well.
It's currently on a private repo as part of an internal project but I could probably send an example if anyone would be interested.
If developer time efficiency and certainty of operation are a concern, then integrating the I2S PR is likely the way to go. It's been used by 100's of people and has documentation.
It's great that there are alternatives!
If your I2S PR works well and tested by 100's of people, by all means I would recommend anyone to use it.
My alternative is just a transparent translation of esp-idf API to Micropython, and in this case it's already part of this ttgo twatch repo so anyone can already use it with an existing prebuilt FW. I2S is just part of it. The module provides many other esp-idf APIs.
@amirgon the example of using esp-idf I2S binding would be much appreciated!
@jmiskovic Here is a simplified example, extracted from a private project with some irrelevant parts removed:
import gc
import espidf as esp
from espidf import I2S_MODE
from espidf import I2S_COMM_FORMAT
from espidf import I2S_CHANNEL_FMT
from espidf import I2S_BITS_PER_SAMPLE
from espidf import I2S_CHANNEL
from espidf import GPIO_MODE
class Recorder:
I2S_PIN_NO_CHANGE = const(-1)
BYTES_PER_SAMPLE = const(4)
BYTES_PER_OUTPUT_SAMPLE = const(2)
OVERSAMPLE_MULTIPLIER = const(1)
def __init__(self, bclk = 2, dout = 36, ws = 22, freq = 16000, i2s_num = esp.I2S_NUM._0):
self.bclk = bclk
self.dout = dout
self.ws = ws
self.freq = freq
self.sample_rate = freq * OVERSAMPLE_MULTIPLIER
self.i2s_num = i2s_num
self.bits_per_sample = self.BYTES_PER_SAMPLE * 8
self.dma_buf_count = 6
self.dma_buf_len = 1024
self.bytes_to_read = (self.dma_buf_count * self.dma_buf_len)
# Init I2S
self.i2s_config = esp.i2s_config_t({
'mode': I2S_MODE.MASTER | I2S_MODE.RX,
'sample_rate': self.sample_rate,
'bits_per_sample': self.bits_per_sample,
'communication_format': I2S_COMM_FORMAT.I2S | I2S_COMM_FORMAT.I2S_MSB,
'channel_format': I2S_CHANNEL_FMT.ONLY_RIGHT,
'intr_alloc_flags': (1<<1), # ESP_INTR_FLAG_LEVEL1
'dma_buf_count': self.dma_buf_count,
'dma_buf_len': self.dma_buf_len,
'use_apll':0
})
self.i2s_pin_config = esp.i2s_pin_config_t({
'bck_io_num': self.bclk,
'ws_io_num': self.ws,
'data_out_num': self.I2S_PIN_NO_CHANGE,
'data_in_num': self.dout,
})
esp.i2s_driver_install(self.i2s_num, self.i2s_config, 0, None)
esp.i2s_set_pin(self.i2s_num, self.i2s_pin_config)
esp.SPH0645_WORKAROUND(self.i2s_num)
esp.i2s_stop(self.i2s_num)
def close(self):
esp.i2s_driver_uninstall(self.i2s_num)
def record(self):
input_buf = bytearray(self.bytes_to_read)
self.input_view = memoryview(input_buf)
bytes_read_ptr = esp.C_Pointer()
gc.disable()
esp.i2s_start(self.i2s_num)
while self.recording:
res = esp.i2s_read(self.i2s_num, self.input_view, self.bytes_to_read, bytes_read_ptr, 0)
if res != 0: raise RuntimeError('i2s_read completed with error %d' % res)
bytes_read = bytes_read_ptr.uint_val
if bytes_read == 0: continue
# Do something with input_buf
esp.i2s_stop(self.i2s_num)
gc.endale()
Thank you!
Because I also wanted to play sounds, I searched around some more. There is a fork of this repo that already integrated I2S.
It should be useful to someone.
@miketeachman published an i2s module targeting i2s audio on esp32, see https://github.com/micropython/micropython/pull/4471 and related examples: https://github.com/miketeachman/micropython-esp32-i2s-examples
This would make a perfect addition to this nice T-Watch 2020 Micropython fork.