86 lines
2.5 KiB
C++
86 lines
2.5 KiB
C++
/*
|
|
SinglePinI2SDriver
|
|
ESP8266Audio I2S Minimal driver
|
|
|
|
Copyright (C) 2020 Ivan Kostoski
|
|
|
|
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
|
|
*/
|
|
|
|
#pragma once
|
|
#if defined(ESP8266)
|
|
|
|
#include <Arduino.h>
|
|
#include "osapi.h"
|
|
#include "ets_sys.h"
|
|
#include "i2s_reg.h"
|
|
|
|
struct SLCDecriptor {
|
|
uint32_t blocksize : 12;
|
|
uint32_t datalen : 12;
|
|
uint32_t unused : 5;
|
|
uint32_t sub_sof : 1;
|
|
uint32_t eof : 1;
|
|
volatile uint32_t owner : 1;
|
|
uint32_t* buf_ptr;
|
|
SLCDecriptor* next_link_ptr;
|
|
};
|
|
|
|
class SinglePinI2SDriver
|
|
{
|
|
public:
|
|
enum : uint8_t { I2SO_DATA = 3 }; // GPIO3/RX0
|
|
|
|
SinglePinI2SDriver(): descriptors(NULL), bufCount(0), bufSize(0) {};
|
|
~SinglePinI2SDriver();
|
|
|
|
bool begin(uint8_t bufCount, uint16_t bufSize);
|
|
void stop();
|
|
void setRate(const uint32_t rateHz);
|
|
float getActualRate();
|
|
bool write(uint32_t sample);
|
|
bool writeInterleaved(uint32_t samples[4]);
|
|
int getUnderflowCount();
|
|
|
|
protected:
|
|
bool allocateBuffers();
|
|
void freeBuffers(int allocated);
|
|
void zeroBuffers();
|
|
void advanceHead(const SLCDecriptor *finished);
|
|
void configureSLC();
|
|
void stopSLC();
|
|
void setDividers(uint8_t div1, uint8_t div2);
|
|
void startI2S();
|
|
void stopI2S();
|
|
SLCDecriptor *descriptors;
|
|
uint16_t bufCount;
|
|
uint16_t bufSize;
|
|
SLCDecriptor *head;
|
|
uint32_t headPos;
|
|
uint32_t currentRate;
|
|
int underflowCount;
|
|
|
|
// (Re)Start transmission ("TX" DMA always needed to be enabled)
|
|
static inline void startSLC() { SLCTXL |= SLCTXLS; SLCRXL |= SLCRXLS; }
|
|
static inline uint32_t isSLCRunning() { return (SLCRXS & SLCRXF); };
|
|
static inline uint32_t isSLCStopped() { return (SLCRXS & SLCRXE); };
|
|
static inline SLCDecriptor *lastSentDescriptor() { return (SLCDecriptor*)SLCRXEDA; }
|
|
};
|
|
|
|
// Global instance
|
|
extern SinglePinI2SDriver I2SDriver;
|
|
|
|
#endif // defined(ESP8266)
|