|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+//! Audio buffer type to transfer audio data within different software/hardware components.
|
|
1
|
2
|
#![warn(missing_docs)]
|
|
2
|
3
|
|
|
3
|
4
|
use core::cell::{Cell, UnsafeCell};
|
|
|
@@ -8,9 +9,12 @@ use cortex_m::interrupt::{CriticalSection, Mutex};
|
|
8
|
9
|
///
|
|
9
|
10
|
/// This translates two twice the number of values, as each sample contains two channels.
|
|
10
|
11
|
pub const SAMPLES_PER_PACKET: usize = 48;
|
|
|
12
|
+/// Number of channels for all audio data.
|
|
11
|
13
|
pub const CHANNELS: usize = 2;
|
|
|
14
|
+/// Number of packets that can be stored in each `AudioBuffer`.
|
|
12
|
15
|
pub const PACKETS: usize = 3;
|
|
13
|
16
|
|
|
|
17
|
+/// Buffer for a single packet with audio data.
|
|
14
|
18
|
pub type Packet = [u32; SAMPLES_PER_PACKET * CHANNELS];
|
|
15
|
19
|
|
|
16
|
20
|
/// Type for audio packet buffering.
|
|
|
@@ -57,11 +61,16 @@ impl AudioBuffer {
|
|
57
|
61
|
}
|
|
58
|
62
|
|
|
59
|
63
|
/// Returns whether there are any buffers with valid data ready for reading.
|
|
60
|
|
- pub fn read_data_available(&self, cs: &CriticalSection) -> bool {
|
|
|
64
|
+ pub fn can_read(&self, cs: &CriticalSection) -> bool {
|
|
61
|
65
|
let inner = self.mutex.borrow(cs);
|
|
62
|
66
|
inner.valid.get() != 0
|
|
63
|
67
|
}
|
|
64
|
68
|
|
|
|
69
|
+ /// Borrows a single buffer for reading, returns `None` if no buffer with valid data is
|
|
|
70
|
+ /// available.
|
|
|
71
|
+ ///
|
|
|
72
|
+ /// The caller needs to return the buffer via `read_finished()` once the data has been
|
|
|
73
|
+ /// processed.
|
|
65
|
74
|
pub fn borrow_read(&'static self, cs: &CriticalSection) -> Option<ReadPacket> {
|
|
66
|
75
|
let inner = self.mutex.borrow(cs);
|
|
67
|
76
|
let valid = inner.valid.get();
|
|
|
@@ -80,17 +89,24 @@ impl AudioBuffer {
|
|
80
|
89
|
})
|
|
81
|
90
|
}
|
|
82
|
91
|
|
|
83
|
|
- pub fn read_finished(&'static self, _packet: ReadPacket, _cs: &CriticalSection) {
|
|
84
|
|
- // TODO
|
|
85
|
|
- panic!("Not yet implemented.");
|
|
|
92
|
+ /// Returns a buffer that was allocated via `borrow_read()` and marks it as empty.
|
|
|
93
|
+ pub fn read_finished(&'static self, packet: ReadPacket, cs: &CriticalSection) {
|
|
|
94
|
+ assert!((self as *const _) == (packet.buffer as *const _));
|
|
|
95
|
+ let inner = self.mutex.borrow(cs);
|
|
|
96
|
+ let index = packet.index;
|
|
|
97
|
+ inner.reading.set(inner.reading.get() & !(1 << index));
|
|
|
98
|
+ inner.invalid.set(inner.invalid.get() | (1 << index));
|
|
86
|
99
|
}
|
|
87
|
100
|
|
|
88
|
101
|
/// Returns whether there are any empty buffers ready for writing.
|
|
89
|
|
- pub fn write_data_available(&self, cs: &CriticalSection) -> bool {
|
|
|
102
|
+ pub fn can_write(&self, cs: &CriticalSection) -> bool {
|
|
90
|
103
|
let inner = self.mutex.borrow(cs);
|
|
91
|
104
|
inner.invalid.get() != 0
|
|
92
|
105
|
}
|
|
93
|
106
|
|
|
|
107
|
+ /// Borrows a single buffer for writing, returns `None` if no empty buffer is available.
|
|
|
108
|
+ ///
|
|
|
109
|
+ /// The caller needs to return the buffer via `write_finished()` once it was filled with data.
|
|
94
|
110
|
pub fn borrow_write(&'static self, cs: &CriticalSection) -> Option<WritePacket> {
|
|
95
|
111
|
let inner = self.mutex.borrow(cs);
|
|
96
|
112
|
let invalid = inner.invalid.get();
|
|
|
@@ -109,20 +125,44 @@ impl AudioBuffer {
|
|
109
|
125
|
})
|
|
110
|
126
|
}
|
|
111
|
127
|
|
|
112
|
|
- pub fn write_finished(&'static self, _packet: WritePacket, _cs: &CriticalSection) {
|
|
113
|
|
- // TODO
|
|
114
|
|
- panic!("Not yet implemented.");
|
|
|
128
|
+ /// Returns a buffer that was allocated via `borrow_write()` and marks it as ready for reading.
|
|
|
129
|
+ pub fn write_finished(&'static self, packet: WritePacket, cs: &CriticalSection) {
|
|
|
130
|
+ assert!((self as *const _) == (packet.buffer as *const _));
|
|
|
131
|
+ let inner = self.mutex.borrow(cs);
|
|
|
132
|
+ let index = packet.index;
|
|
|
133
|
+ inner.writing.set(inner.writing.get() & !(1 << index));
|
|
|
134
|
+ inner.valid.set(inner.valid.get() | (1 << index));
|
|
115
|
135
|
}
|
|
116
|
136
|
}
|
|
117
|
137
|
|
|
|
138
|
+/// Packet buffer that has been borrowed for reading (i.e., the buffer contains valid data).
|
|
118
|
139
|
pub struct ReadPacket {
|
|
119
|
140
|
buffer: &'static AudioBuffer,
|
|
120
|
141
|
data: &'static Packet,
|
|
121
|
142
|
index: usize,
|
|
122
|
143
|
}
|
|
123
|
144
|
|
|
|
145
|
+impl AsRef<[u32]> for ReadPacket {
|
|
|
146
|
+ fn as_ref(&self) -> &[u32] {
|
|
|
147
|
+ self.data
|
|
|
148
|
+ }
|
|
|
149
|
+}
|
|
|
150
|
+
|
|
|
151
|
+/// Packet buffer that has been borrowed for writing (i.e., the buffer was previously empty).
|
|
124
|
152
|
pub struct WritePacket {
|
|
125
|
153
|
buffer: &'static AudioBuffer,
|
|
126
|
154
|
data: &'static mut Packet,
|
|
127
|
155
|
index: usize,
|
|
128
|
156
|
}
|
|
|
157
|
+
|
|
|
158
|
+impl AsRef<[u32]> for WritePacket {
|
|
|
159
|
+ fn as_ref(&self) -> &[u32] {
|
|
|
160
|
+ self.data
|
|
|
161
|
+ }
|
|
|
162
|
+}
|
|
|
163
|
+
|
|
|
164
|
+impl AsMut<[u32]> for WritePacket {
|
|
|
165
|
+ fn as_mut(&mut self) -> &mut [u32] {
|
|
|
166
|
+ self.data
|
|
|
167
|
+ }
|
|
|
168
|
+}
|