/* 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 #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)