#ifndef AUDIO_H #define AUDIO_H #include "../io/Timer0.h" #include "../io/SoftSPI.h" #include "../io/IO.h" #include "../ESP.h" #include "../data/RingBuffer.h" #include "../data/DoubleBuffer.h" class Audio; extern Audio audio; class Audio { private: static constexpr uint32_t Hz = 22050; RingBuffer bufPlayback; DoubleBuffer bufRecord; Timer0 timer; SoftSPI spi; public: Audio() { // NOT CALLED // CALL init() manually! } /** init the audio system */ void init() { spi.init(); bufPlayback.init(); bufRecord.init(); timer.attachInterrupt(&Audio::onInterrupt); timer.fireLoopHz(Hz); } bool needsFlush() const { return bufRecord.needsFlush(); } /** get the recording buffer */ DoubleBuffer& getRecord() {return bufRecord;} /** get the playback buffer */ RingBuffer& getPlayback() {return bufPlayback;} void markFlushed() { bufRecord.markFlushed(); } public: inline uint8_t playAndRecord8(const uint8_t out) { // start spi.chipSelect(); // build output word for the DAC const uint16_t out16 = (0 << 15) | (1 << 13) | (1 << 12) | (((uint16_t)out) << 4); // read 12-bit sample from the ADC while sending the word to the DAC const uint16_t inp12 = (spi.readWriteWord(out16) & 0b0001111111111110) >> 1; //const uint16_t inp8 = (inp12>>0) - (2048+128); //const uint16_t inp8 = (inp12>>2) - (512-128); //const uint16_t inp8 = (inp12>>3) - (256-128); const uint16_t inp8 = (inp12>>4); //const int16_t sinp12 = (int16_t)inp12 - 2048 - 256; //const uint8_t inp8 = (sinp12 / 12) + 128; // done spi.chipDeselect(); return inp8; } inline void process() { // loop-back // static volatile uint8_t inp; // inp = playAndRecord8(inp); // bufRecord.add(inp); // next sample to write [zero level (128) if none available] const uint8_t out = (bufPlayback.getNumUsed() < 200) ? (128) : (bufPlayback.get()); // send output-sample and thereby read the input sample const uint8_t inp = playAndRecord8(out); // append sample for writing bufRecord.add(inp); } // uint8_t rand() { // static volatile uint8_t val = 131; // val *= 17; // val += 11; // return val; // } private: static inline void onInterrupt() { //IO::toggleLED1(); audio.process(); } }; #endif // AUDIO_H