arduino-audio-tools
Loading...
Searching...
No Matches
SPIRegAudioMaster.h
Go to the documentation of this file.
1#pragma once
2
3#include <SPI.h>
4
8
9namespace audio_tools {
10
16#if defined(SS)
17 int cs_pin = SS;
18#else
19 int cs_pin = 10;
20#endif
21 uint32_t clock_hz = 4000000;
22 decltype(MSBFIRST) bit_order = MSBFIRST;
23 uint8_t data_mode = SPI_MODE0;
26 size_t max_payload = 256;
30 bool is_blocking_write = false;
31};
32
49 public:
50 SPIRegAudioMaster() = default;
51 explicit SPIRegAudioMaster(SPIClass& spi) : p_spi(&spi) {}
52
54 config = cfg;
55 if (config.max_payload == 0) return false;
56 if (p_spi == nullptr) p_spi = &SPI;
57 if (config.cs_pin >= 0) {
60 }
61 p_spi->begin();
62 tx.resize(max((size_t)SPIREG_MIME_SIZE, config.max_payload) + 2);
63 active = true;
64 if (cfg) setAudioInfo(cfg);
65 return true;
66 }
67
68 void end() {
69 if (p_spi != nullptr && active) p_spi->end();
70 active = false;
71 }
72
73 bool isActive() const { return active; }
74
76 bool setMime(const char* mime) {
77 if (mime == nullptr) return false;
78 uint8_t buf[SPIREG_MIME_SIZE] = {0};
79 strncpy((char*)buf, mime, SPIREG_MIME_SIZE - 1);
80 return writeRegister(SPIREG_MIME, buf, sizeof(buf));
81 }
82
84 void setAudioInfo(AudioInfo info) override {
87 buf[0] = info.sample_rate & 0xFF;
88 buf[1] = (info.sample_rate >> 8) & 0xFF;
89 buf[2] = (info.sample_rate >> 16) & 0xFF;
90 buf[3] = (info.sample_rate >> 24) & 0xFF;
91 buf[4] = info.channels & 0xFF;
92 buf[5] = (info.channels >> 8) & 0xFF;
93 buf[6] = info.bits_per_sample;
94 buf[7] = 0;
95 if (active) writeRegister(SPIREG_AUDIO_INFO, buf, sizeof(buf));
96 }
97
101 AudioInfo result;
102 if (readRegister(SPIREG_AUDIO_INFO, buf, sizeof(buf))) {
103 result.sample_rate = (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) |
104 ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24);
105 result.channels = (uint16_t)buf[4] | ((uint16_t)buf[5] << 8);
106 result.bits_per_sample = buf[6];
107 }
108 return result;
109 }
110
112 int availableForWrite() override {
113 if (!active) return 0;
115 if (!readRegister(SPIREG_AVAILABLE, buf, sizeof(buf))) return 0;
116 return (int)((uint32_t)buf[0] | ((uint32_t)buf[1] << 8) |
117 ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24));
118 }
119
122 size_t write(const uint8_t* data, size_t len) override {
123 if (!active || data == nullptr) return 0;
124 size_t written = 0;
125 while (written < len) {
126 size_t chunk = min(len - written, config.max_payload);
127 int space = availableForWrite();
128 if (space < (int)chunk) {
130 chunk = space; // send what fits
131 } else {
132 delay(5);
133 continue;
134 }
135 }
136 if (chunk == 0) break;
137 if (!writeRegister(SPIREG_DATA, data + written, chunk)) break;
138 written += chunk;
139 }
140 return written;
141 }
142
143 protected:
145 SPIClass* p_spi = nullptr;
146 bool active = false;
148
150 bool writeRegister(uint8_t addr, const uint8_t* data, size_t len) {
151 if (len + 1 > tx.size()) return false;
152 tx[0] = addr & SPIREG_ADDR_MASK;
153 memcpy(tx.data() + 1, data, len);
154 select();
155 p_spi->transfer(tx.data(), len + 1);
156 deselect();
157 return true;
158 }
159
161 bool readRegister(uint8_t addr, uint8_t* out, size_t len) {
162 if (!active || len == 0 || len + 1 > tx.size()) return false;
163 uint8_t req[2] = {(uint8_t)(SPIREG_READ_MASK | (addr & SPIREG_ADDR_MASK)),
164 (uint8_t)len};
165 select();
166 p_spi->transfer(req, sizeof(req));
167 deselect();
169 memset(out, 0, len);
170 select();
171 p_spi->transfer(out, len); // dummy 0x00 bytes: replaced by the reply
172 deselect();
173 return true;
174 }
175
176 void select() {
177 p_spi->beginTransaction(
180 }
181
182 void deselect() {
184 p_spi->endTransaction();
185 }
186};
187
188} // namespace audio_tools
#define HIGH
Definition Arduino.h:46
#define OUTPUT
Definition Arduino.h:38
#define LOW
Definition Arduino.h:49
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
AudioInfo cfg
Definition AudioOutput.h:88
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioOutput.h:49
SPI master which streams audio to a SPIRegAudioSlave (based on the TinySPISlave library) using its re...
Definition SPIRegAudioMaster.h:48
bool active
Definition SPIRegAudioMaster.h:146
bool writeRegister(uint8_t addr, const uint8_t *data, size_t len)
Write frame: [addr][bytes...].
Definition SPIRegAudioMaster.h:150
AudioInfo readAudioInfo()
Reads the audio format which is currently defined on the slave.
Definition SPIRegAudioMaster.h:99
bool isActive() const
Definition SPIRegAudioMaster.h:73
SPIRegAudioMaster(SPIClass &spi)
Definition SPIRegAudioMaster.h:51
bool readRegister(uint8_t addr, uint8_t *out, size_t len)
Read request frame, pause, reply frame.
Definition SPIRegAudioMaster.h:161
size_t write(const uint8_t *data, size_t len) override
Definition SPIRegAudioMaster.h:122
SPIClass * p_spi
Definition SPIRegAudioMaster.h:145
void deselect()
Definition SPIRegAudioMaster.h:182
int availableForWrite() override
Free space in the slave's audio buffer in bytes.
Definition SPIRegAudioMaster.h:112
void end()
Definition SPIRegAudioMaster.h:68
Vector< uint8_t > tx
Definition SPIRegAudioMaster.h:147
SPIRegAudioMasterConfig config
Definition SPIRegAudioMaster.h:144
bool setMime(const char *mime)
Defines the mime type (max 31 characters) on the slave.
Definition SPIRegAudioMaster.h:76
bool begin(SPIRegAudioMasterConfig cfg=SPIRegAudioMasterConfig())
Definition SPIRegAudioMaster.h:53
void setAudioInfo(AudioInfo info) override
Defines the audio format on the slave.
Definition SPIRegAudioMaster.h:84
void select()
Definition SPIRegAudioMaster.h:176
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:321
int size()
Definition Vector.h:178
@ SPIREG_MIME
32 bytes (rw): zero terminated mime type
Definition SPIRegAudioRegisters.h:29
@ SPIREG_AUDIO_INFO
8 bytes (rw): sample_rate u32, channels u16, bits_per_sample u8, reserved
Definition SPIRegAudioRegisters.h:27
@ SPIREG_DATA
stream (wo): the bytes of the frame are appended to the audio buffer
Definition SPIRegAudioRegisters.h:33
@ SPIREG_AVAILABLE
4 bytes (ro): u32 free space in the slave audio buffer in bytes
Definition SPIRegAudioRegisters.h:31
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
constexpr size_t SPIREG_MIME_SIZE
Definition SPIRegAudioRegisters.h:39
constexpr uint8_t SPIREG_READ_MASK
Definition SPIRegAudioRegisters.h:36
void digitalWrite(digital_pin_t pin, bool value)
Definition Arduino.h:317
constexpr size_t SPIREG_AUDIO_INFO_SIZE
Definition SPIRegAudioRegisters.h:38
constexpr size_t SPIREG_AVAILABLE_SIZE
Definition SPIRegAudioRegisters.h:40
void delay(uint32_t ms)
Definition Arduino.h:259
void pinMode(digital_pin_t pin, int mode)
Definition Arduino.h:286
constexpr uint8_t SPIREG_ADDR_MASK
Definition SPIRegAudioRegisters.h:37
void delayMicroseconds(uint32_t us)
Definition Arduino.h:261
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:56
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:58
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:60
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:62
Configuration for SPIRegAudioMaster.
Definition SPIRegAudioMaster.h:15
uint32_t clock_hz
Definition SPIRegAudioMaster.h:21
uint8_t data_mode
Definition SPIRegAudioMaster.h:23
uint32_t reply_gap_us
Pause (us) between a read request and the reply frame.
Definition SPIRegAudioMaster.h:28
int cs_pin
Definition SPIRegAudioMaster.h:19
bool is_blocking_write
true: write() waits until the slave has enough space
Definition SPIRegAudioMaster.h:30
decltype(MSBFIRST) bit_order
Definition SPIRegAudioMaster.h:22
size_t max_payload
Definition SPIRegAudioMaster.h:26