mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-16 00:43:00 +03:00
Add I2S class support (#7874)
Fixes #427 Adds a basic I2S class based off of the Arduino-SAMD core. The raw i2s_xxx functions are still a better way to use I2S due to their flexibility, but this will allow basic Arduino sketches to work.
This commit is contained in:
committed by
GitHub
parent
9fc5afd5fd
commit
e99df4fe1a
@ -24,7 +24,7 @@
|
||||
#include "osapi.h"
|
||||
#include "ets_sys.h"
|
||||
#include "i2s_reg.h"
|
||||
#include "i2s.h"
|
||||
#include "core_esp8266_i2s.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -194,11 +194,11 @@ static void ICACHE_RAM_ATTR i2s_slc_isr(void) {
|
||||
}
|
||||
|
||||
void i2s_set_callback(void (*callback) (void)) {
|
||||
tx->callback = callback;
|
||||
if (tx) tx->callback = callback;
|
||||
}
|
||||
|
||||
void i2s_rx_set_callback(void (*callback) (void)) {
|
||||
rx->callback = callback;
|
||||
if (rx) rx->callback = callback;
|
||||
}
|
||||
|
||||
static bool _alloc_channel(i2s_state_t *ch) {
|
||||
@ -343,7 +343,7 @@ bool i2s_write_lr(int16_t left, int16_t right){
|
||||
|
||||
// writes a buffer of frames into the DMA memory, returns the amount of frames written
|
||||
// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel.
|
||||
static uint16_t _i2s_write_buffer(int16_t *frames, uint16_t frame_count, bool mono, bool nb) {
|
||||
static uint16_t _i2s_write_buffer(const int16_t *frames, uint16_t frame_count, bool mono, bool nb) {
|
||||
uint16_t frames_written=0;
|
||||
|
||||
while(frame_count>0) {
|
||||
@ -401,13 +401,13 @@ static uint16_t _i2s_write_buffer(int16_t *frames, uint16_t frame_count, bool mo
|
||||
return frames_written;
|
||||
}
|
||||
|
||||
uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); }
|
||||
uint16_t i2s_write_buffer_mono_nb(const int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, true); }
|
||||
|
||||
uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); }
|
||||
uint16_t i2s_write_buffer_mono(const int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, true, false); }
|
||||
|
||||
uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); }
|
||||
uint16_t i2s_write_buffer_nb(const int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, true); }
|
||||
|
||||
uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); }
|
||||
uint16_t i2s_write_buffer(const int16_t *frames, uint16_t frame_count) { return _i2s_write_buffer(frames, frame_count, false, false); }
|
||||
|
||||
bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking) {
|
||||
if (!rx) {
|
||||
|
81
cores/esp8266/core_esp8266_i2s.h
Normal file
81
cores/esp8266/core_esp8266_i2s.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
i2s.h - Software I2S library for esp8266
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef I2S_h
|
||||
#define I2S_h
|
||||
|
||||
#define I2S_HAS_BEGIN_RXTX_DRIVE_CLOCKS 1
|
||||
|
||||
/*
|
||||
How does this work? Basically, to get sound, you need to:
|
||||
- Connect an I2S codec to the I2S pins on the ESP.
|
||||
- Start up a thread that's going to do the sound output
|
||||
- Call i2s_set_bits() if you want to enable 24-bit mode
|
||||
- Call i2s_begin()
|
||||
- Call i2s_set_rate() with the sample rate you want.
|
||||
- Generate sound and call i2s_write_sample() with 32-bit samples.
|
||||
The 32bit samples basically are 2 16-bit signed values (the analog values for
|
||||
the left and right channel) concatenated as (Rout<<16)+Lout
|
||||
|
||||
i2s_write_sample will block when you're sending data too quickly, so you can just
|
||||
generate and push data as fast as you can and i2s_write_sample will regulate the
|
||||
speed.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool i2s_set_bits(int bits); // Set bits per sample, only 16 or 24 supported. Call before begin.
|
||||
// Note that in 24 bit mode each sample must be left-aligned (i.e. 0x00000000 .. 0xffffff00) as the
|
||||
// hardware shifts starting at bit 31, not bit 23.
|
||||
|
||||
void i2s_begin(); // Enable TX only, for compatibility
|
||||
bool i2s_rxtx_begin(bool enableRx, bool enableTx); // Allow TX and/or RX, returns false on OOM error
|
||||
bool i2s_rxtxdrive_begin(bool enableRx, bool enableTx, bool driveRxClocks, bool driveTxClocks);
|
||||
void i2s_end();
|
||||
void i2s_set_rate(uint32_t rate);//Sample Rate in Hz (ex 44100, 48000)
|
||||
void i2s_set_dividers(uint8_t div1, uint8_t div2);//Direct control over output rate
|
||||
float i2s_get_real_rate();//The actual Sample Rate on output
|
||||
bool i2s_write_sample(uint32_t sample);//32bit sample with channels being upper and lower 16 bits (blocking when DMA is full)
|
||||
bool i2s_write_sample_nb(uint32_t sample);//same as above but does not block when DMA is full and returns false instead
|
||||
bool i2s_write_lr(int16_t left, int16_t right);//combines both channels and calls i2s_write_sample with the result
|
||||
bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking); // RX data returned in both 16-bit outputs.
|
||||
bool i2s_is_full();//returns true if DMA is full and can not take more bytes (overflow)
|
||||
bool i2s_is_empty();//returns true if DMA is empty (underflow)
|
||||
bool i2s_rx_is_full();
|
||||
bool i2s_rx_is_empty();
|
||||
uint16_t i2s_available();// returns the number of samples than can be written before blocking
|
||||
uint16_t i2s_rx_available();// returns the number of samples than can be written before blocking
|
||||
void i2s_set_callback(void (*callback) (void));
|
||||
void i2s_rx_set_callback(void (*callback) (void));
|
||||
|
||||
// writes a buffer of frames into the DMA memory, returns the amount of frames written
|
||||
// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel.
|
||||
uint16_t i2s_write_buffer_mono(const int16_t *frames, uint16_t frame_count);
|
||||
uint16_t i2s_write_buffer_mono_nb(const int16_t *frames, uint16_t frame_count);
|
||||
uint16_t i2s_write_buffer(const int16_t *frames, uint16_t frame_count);
|
||||
uint16_t i2s_write_buffer_nb(const int16_t *frames, uint16_t frame_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,81 +1,12 @@
|
||||
/*
|
||||
i2s.h - Software I2S library for esp8266
|
||||
// This include file is a hack to ensure backward compatibility with
|
||||
// pre 3.0.0 versions of the core. There was a *lowercase* "i2s.h"
|
||||
// header which was in this directory, now renamed to "core_esp82i66s.h"
|
||||
// But, the I2S class has a header, "I2S.h" in uppercase. On Linux
|
||||
// the two names are different, but on Windows it's case-insensitive
|
||||
// so the names conflict.
|
||||
//
|
||||
// Avoid the issue by preserving the old i2s.h file and have it redirect
|
||||
// to I2S.h which will give the ESP8266-specific functions as well as
|
||||
// the generic I2S class.
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef I2S_h
|
||||
#define I2S_h
|
||||
|
||||
#define I2S_HAS_BEGIN_RXTX_DRIVE_CLOCKS 1
|
||||
|
||||
/*
|
||||
How does this work? Basically, to get sound, you need to:
|
||||
- Connect an I2S codec to the I2S pins on the ESP.
|
||||
- Start up a thread that's going to do the sound output
|
||||
- Call i2s_set_bits() if you want to enable 24-bit mode
|
||||
- Call i2s_begin()
|
||||
- Call i2s_set_rate() with the sample rate you want.
|
||||
- Generate sound and call i2s_write_sample() with 32-bit samples.
|
||||
The 32bit samples basically are 2 16-bit signed values (the analog values for
|
||||
the left and right channel) concatenated as (Rout<<16)+Lout
|
||||
|
||||
i2s_write_sample will block when you're sending data too quickly, so you can just
|
||||
generate and push data as fast as you can and i2s_write_sample will regulate the
|
||||
speed.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool i2s_set_bits(int bits); // Set bits per sample, only 16 or 24 supported. Call before begin.
|
||||
// Note that in 24 bit mode each sample must be left-aligned (i.e. 0x00000000 .. 0xffffff00) as the
|
||||
// hardware shifts starting at bit 31, not bit 23.
|
||||
|
||||
void i2s_begin(); // Enable TX only, for compatibility
|
||||
bool i2s_rxtx_begin(bool enableRx, bool enableTx); // Allow TX and/or RX, returns false on OOM error
|
||||
bool i2s_rxtxdrive_begin(bool enableRx, bool enableTx, bool driveRxClocks, bool driveTxClocks);
|
||||
void i2s_end();
|
||||
void i2s_set_rate(uint32_t rate);//Sample Rate in Hz (ex 44100, 48000)
|
||||
void i2s_set_dividers(uint8_t div1, uint8_t div2);//Direct control over output rate
|
||||
float i2s_get_real_rate();//The actual Sample Rate on output
|
||||
bool i2s_write_sample(uint32_t sample);//32bit sample with channels being upper and lower 16 bits (blocking when DMA is full)
|
||||
bool i2s_write_sample_nb(uint32_t sample);//same as above but does not block when DMA is full and returns false instead
|
||||
bool i2s_write_lr(int16_t left, int16_t right);//combines both channels and calls i2s_write_sample with the result
|
||||
bool i2s_read_sample(int16_t *left, int16_t *right, bool blocking); // RX data returned in both 16-bit outputs.
|
||||
bool i2s_is_full();//returns true if DMA is full and can not take more bytes (overflow)
|
||||
bool i2s_is_empty();//returns true if DMA is empty (underflow)
|
||||
bool i2s_rx_is_full();
|
||||
bool i2s_rx_is_empty();
|
||||
uint16_t i2s_available();// returns the number of samples than can be written before blocking
|
||||
uint16_t i2s_rx_available();// returns the number of samples than can be written before blocking
|
||||
void i2s_set_callback(void (*callback) (void));
|
||||
void i2s_rx_set_callback(void (*callback) (void));
|
||||
|
||||
// writes a buffer of frames into the DMA memory, returns the amount of frames written
|
||||
// A frame is just a int16_t for mono, for stereo a frame is two int16_t, one for each channel.
|
||||
uint16_t i2s_write_buffer_mono(int16_t *frames, uint16_t frame_count);
|
||||
uint16_t i2s_write_buffer_mono_nb(int16_t *frames, uint16_t frame_count);
|
||||
uint16_t i2s_write_buffer(int16_t *frames, uint16_t frame_count);
|
||||
uint16_t i2s_write_buffer_nb(int16_t *frames, uint16_t frame_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#include "../../libraries/I2S/src/I2S.h"
|
||||
|
Reference in New Issue
Block a user