9
9
10
10
namespace audio_tools {
11
11
12
+ /* *
13
+ * @brief R2R driver base class
14
+ * @ingroup platform
15
+ * @author Phil Schatzmann
16
+ * @copyright GPLv3
17
+ */
18
+
19
+ class R2RDriverBase {
20
+ public:
21
+ virtual void setupPins (std::vector<int > &channel1_pins,
22
+ std::vector<int > &channel2_pins) = 0;
23
+
24
+ virtual void writePins (int channels, int channel, unsigned uvalue) = 0;
25
+ };
26
+
27
+ /* *
28
+ * @brief R2R driver which uses the Arduino API to setup and write to the
29
+ * digital pins
30
+ * @ingroup platform
31
+ * @author Phil Schatzmann
32
+ * @copyright GPLv3
33
+ */
34
+
35
+ class R2RDriver : public R2RDriverBase {
36
+ public:
37
+ void setupPins (std::vector<int > &channel1_pins,
38
+ std::vector<int > &channel2_pins) override {
39
+ TRACED ();
40
+ p_channel1_pins = &channel1_pins;
41
+ p_channel2_pins = &channel2_pins;
42
+
43
+ for (auto pin : channel1_pins) {
44
+ LOGI (" Setup channel1 pin %d" , pin);
45
+ pinMode (pin, OUTPUT);
46
+ }
47
+ for (int pin : channel2_pins) {
48
+ LOGI (" Setup channel2 pin %d" , pin);
49
+ pinMode (pin, OUTPUT);
50
+ }
51
+ };
52
+
53
+ void writePins (int channels, int channel, unsigned uvalue) override {
54
+ switch (channel) {
55
+ case 0 :
56
+ for (int j = 0 ; j < (*p_channel1_pins).size (); j++) {
57
+ int pin = (*p_channel1_pins)[j];
58
+ if (pin >= 0 ) digitalWrite (pin, (uvalue >> j) & 1 );
59
+ }
60
+ break ;
61
+ case 1 :
62
+ for (int j = 0 ; j < (*p_channel2_pins).size (); j++) {
63
+ int pin = (*p_channel2_pins)[j];
64
+ if (pin >= 0 ) digitalWrite (pin, (uvalue >> j) & 1 );
65
+ }
66
+ break ;
67
+ }
68
+ }
69
+
70
+ protected:
71
+ std::vector<int > *p_channel1_pins = nullptr ;
72
+ std::vector<int > *p_channel2_pins = nullptr ;
73
+
74
+ } r2r_driver;
12
75
13
76
/* *
14
77
* @brief R2R configuration
@@ -20,8 +83,10 @@ class R2RConfig : public AudioInfo {
20
83
public:
21
84
std::vector<int > channel1_pins;
22
85
std::vector<int > channel2_pins;
23
- uint16_t buffer_size = DEFAULT_BUFFER_SIZE; // automatic determination from write size
24
- uint16_t buffer_count = 2 ; // double buffer
86
+ uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
87
+ uint16_t buffer_count = 2 ; // double buffer
88
+ R2RDriverBase *driver = &r2r_driver; // by default use Arduino driver
89
+ bool is_blocking = true ;
25
90
};
26
91
27
92
/* *
@@ -60,12 +125,12 @@ class R2ROutput : public AudioOutput {
60
125
LOGE (" channel2_pins not defined" );
61
126
return false ;
62
127
}
63
- if (rcfg.buffer_size * rcfg.buffer_count == 0 ){
128
+ if (rcfg.buffer_size * rcfg.buffer_count == 0 ) {
64
129
LOGE (" buffer_size or buffer_count is 0" );
65
130
return false ;
66
131
}
67
132
buffer.resize (rcfg.buffer_size , rcfg.buffer_count );
68
- setupPins ();
133
+ rcfg. driver -> setupPins (rcfg. channel1_pins , rcfg. channel2_pins );
69
134
timer.setCallbackParameter (this );
70
135
timer.setIsSave (true );
71
136
return timer.begin (r2r_timer_callback, cfg.sample_rate , HZ);
@@ -74,9 +139,18 @@ class R2ROutput : public AudioOutput {
74
139
size_t write (const uint8_t *data, size_t len) override {
75
140
// if buffer has not been allocated (buffer_size==0)
76
141
if (len > rcfg.buffer_size ) {
77
- LOGE (" buffer_size %d too small for write size: %d" , rcfg.buffer_size , len);
142
+ LOGE (" buffer_size %d too small for write size: %d" , rcfg.buffer_size ,
143
+ len);
78
144
return len;
79
145
}
146
+
147
+ // wait for buffer to have enough space
148
+ if (rcfg.is_blocking ){
149
+ while (buffer.availableForWrite ()<len){
150
+ delay (5 );
151
+ }
152
+ }
153
+
80
154
size_t result = buffer.writeArray (data, len);
81
155
// activate output when buffer is half full
82
156
if (!is_active && buffer.bufferCountFilled () >= rcfg.buffer_count / 2 ) {
@@ -92,18 +166,6 @@ class R2ROutput : public AudioOutput {
92
166
NBuffer<uint8_t > buffer{DEFAULT_BUFFER_SIZE, 0 };
93
167
R2RConfig rcfg;
94
168
95
- virtual void setupPins () {
96
- TRACED ();
97
- for (auto pin : rcfg.channel1_pins ) {
98
- LOGI (" Setup channel1 pin %d" , pin);
99
- pinMode (pin, OUTPUT);
100
- }
101
- for (int pin : rcfg.channel2_pins ) {
102
- LOGI (" Setup channel2 pin %d" , pin);
103
- pinMode (pin, OUTPUT);
104
- }
105
- }
106
-
107
169
void writeValue (int channel) {
108
170
switch (cfg.bits_per_sample ) {
109
171
case 8 :
@@ -132,24 +194,7 @@ class R2ROutput : public AudioOutput {
132
194
// Serial.println(uvalue);
133
195
134
196
// output pins
135
- writePins (channel, uvalue);
136
- }
137
-
138
- virtual void writePins (int channel, unsigned uvalue){
139
- switch (channel) {
140
- case 0 :
141
- for (int j = 0 ; j < rcfg.channel1_pins .size (); j++) {
142
- int pin = rcfg.channel1_pins [j];
143
- if (pin >= 0 ) digitalWrite (pin, (uvalue >> j) & 1 );
144
- }
145
- break ;
146
- case 1 :
147
- for (int j = 0 ; j < rcfg.channel2_pins .size (); j++) {
148
- int pin = rcfg.channel2_pins [j];
149
- if (pin >= 0 ) digitalWrite (pin, (uvalue >> j) & 1 );
150
- }
151
- break ;
152
- }
197
+ rcfg.driver ->writePins (cfg.channels , channel, uvalue);
153
198
}
154
199
155
200
static void r2r_timer_callback (void *ptr) {
0 commit comments