125 lines
2.3 KiB
C++
125 lines
2.3 KiB
C++
#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<uint8_t, 1500> bufPlayback;
|
|
DoubleBuffer<uint8_t, 512> 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<uint8_t, 512>& getRecord() {return bufRecord;}
|
|
|
|
/** get the playback buffer */
|
|
RingBuffer<uint8_t, 1500>& 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
|