1#![no_std]
7use core::future::Future;
8const CMD_START: u8 = 0xaa;
9
10
11#[derive(PartialEq, Debug, Clone, Copy)]
12pub enum PlayState {
13 Stop,
14 Play,
15 Pause,
16 Unknown
17}
18
19#[derive(PartialEq, Debug, Clone, Copy)]
20pub enum Drive {
21 USB,
22 SD,
23 Flash,
24 NoDevice
25}
26
27#[derive(PartialEq, Debug, Clone, Copy)]
28pub enum EqualizerMode {
29 Normal,
30 Pop,
31 Rock,
32 Jazz,
33 Classic
34}
35
36pub struct DySv5w<T> {
37 serial: T
38}
39
40impl<T> DySv5w<T>
41where T: DySv5wSerialIO
42{
43 pub fn new(serial: T) -> DySv5w<T> {
44 DySv5w {
45 serial
46 }
47 }
48
49 pub async fn set_volume(&mut self, volume: u8) {
52 let mut cmd = [CMD_START, 0x13, 0x01, volume, 0x00];
53 self.send_with_crc(&mut cmd).await;
54 }
55
56 pub async fn play(&mut self) {
58 let mut cmd = [CMD_START, 0x02, 0x00, 0];
59 self.send_with_crc(&mut cmd).await;
60 }
61
62 pub async fn pause(&mut self) {
63 let mut cmd = [CMD_START, 0x03, 0x00, 0];
64 self.send_with_crc(&mut cmd).await;
65 }
66
67 pub async fn stop(&mut self) {
68 let mut cmd = [CMD_START, 0x04, 0x00, 0];
69 self.send_with_crc(&mut cmd).await;
70 }
71
72 pub async fn previous(&mut self) {
73 let mut cmd = [CMD_START, 0x05, 0x00, 0];
74 self.send_with_crc(&mut cmd).await;
75 }
76
77 pub async fn volume_inc(&mut self) {
78 let mut cmd = [CMD_START, 0x14, 0x00, 0];
79 self.send_with_crc(&mut cmd).await;
80 }
81
82 pub async fn volume_dec(&mut self) {
83 let mut cmd = [CMD_START, 0x15, 0x00, 0];
84 self.send_with_crc(&mut cmd).await;
85 }
86
87 pub async fn next(&mut self) {
88 let mut cmd = [CMD_START, 0x06, 0x00, 0];
89 self.send_with_crc(&mut cmd).await;
90 }
91
92 pub async fn stop_playing(&mut self) {
93 let mut cmd = [CMD_START, 0x10, 0x00, 0];
94 self.send_with_crc(&mut cmd).await;
95 }
96
97 pub async fn specify_song(&mut self, song: u16) {
98 let hl = song.to_be_bytes();
99 let mut cmd = [CMD_START, 0x07, 0x02, hl[0], hl[1], 0];
100 self.send_with_crc(&mut cmd).await;
101 }
102
103 pub async fn set_cycle_times(&mut self, times: u16) {
105 let hl = times.to_be_bytes();
106 let mut cmd = [CMD_START, 0x19, 0x02, hl[0], hl[1], 0];
107 self.send_with_crc(&mut cmd).await;
108 }
109
110 pub async fn set_equalizer_mode(&mut self, mode: EqualizerMode) {
111 let mut cmd = [CMD_START, 0x1a, 0x01, mode.to_u8(), 0];
112 self.send_with_crc(&mut cmd).await;
113 }
114
115 pub async fn query_play_status(&mut self) -> Option<PlayState> {
116 let mut cmd = [CMD_START, 0x01, 0x00, 0];
117 self.send_with_crc(&mut cmd).await;
118 let mut rcv_buffer = [0u8; 1];
119 if self.receive_answer(0x01, &mut rcv_buffer).await {
120 match rcv_buffer[0] {
121 0 => Some(PlayState::Stop),
122 1 => Some(PlayState::Play),
123 2 => Some(PlayState::Pause),
124 _ => None
125 }
126 } else {
127 None
128 }
129 }
130
131 pub async fn switch_specified_drive(&mut self, drive: Drive) {
132 let mut cmd = [CMD_START, 0x0b, 0x01, drive.to_u8(), 0];
133 self.send_with_crc(&mut cmd).await;
134 }
135
136 pub async fn query_current_play_drive(&mut self) -> Option<Drive> {
137 let mut cmd = [CMD_START, 0x0a, 0x00, 0];
138 self.send_with_crc(&mut cmd).await;
139 let mut rcv_buffer = [0u8; 1];
140 if self.receive_answer(0x0a, &mut rcv_buffer).await {
141 Some(Drive::from_u8(rcv_buffer[0]))
142 } else {
143 None
144 }
145 }
146
147 pub async fn query_current_online_drive(&mut self) -> Option<Drive> {
148 let mut cmd = [CMD_START, 0x09, 0x00, 0];
149 self.send_with_crc(&mut cmd).await;
150 let mut rcv_buffer = [0u8; 1];
151 if self.receive_answer(0x09, &mut rcv_buffer).await {
152 Some(Drive::from_u8(rcv_buffer[0]))
153 } else {
154 None
155 }
156 }
157
158 pub async fn query_number_songs(&mut self) -> Option<u16> {
159 let mut cmd = [CMD_START, 0x0c, 0x00, 0];
160 self.send_with_crc(&mut cmd).await;
161 let mut rcv_buffer = [0u8; 2];
162 if self.receive_answer(0x0c, &mut rcv_buffer).await {
163 Some(get_word(&rcv_buffer))
164 } else {
165 None
166 }
167 }
168
169 pub async fn query_current_song(&mut self) -> Option<u16> {
170 let mut cmd = [CMD_START, 0x0d, 0x00, 0];
171 self.send_with_crc(&mut cmd).await;
172 let mut rcv_buffer = [0u8; 2];
173 if self.receive_answer(0x0d, &mut rcv_buffer).await {
174 Some(get_word(&rcv_buffer))
175 } else {
176 None
177 }
178 }
179
180
181 async fn send_with_crc(&mut self, cmd: &mut [u8]) {
182 fill_in_crc(cmd);
183 self.serial.send_data(cmd).await
184 }
185 async fn receive_answer(&mut self, cmd: u8, buffer: &mut [u8]) -> bool {
186 let Some(start) = self.serial.read_byte().await else {
187 return false;
188 };
189 if start != CMD_START {
190 return false;
191 }
192 let Some(cmd_in) = self.serial.read_byte().await else {
193 return false;
194 };
195 if cmd_in != cmd {
196 return false;
197 }
198 let Some(mut len) = self.serial.read_byte().await else {
199 return false;
200 };
201 if len as usize != buffer.len() {
202 return false;
203 }
204 let mut pos = 0;
205 while len > 0 {
206 let Some(data) = self.serial.read_byte().await else {
207 return false;
208 };
209 buffer[pos] = data;
210 len -= 1;
211 pos += 1;
212 }
213 let _ = self.serial.read_byte().await; true
215 }
216}
217
218fn fill_in_crc(bytes: &mut [u8]) {
219 if bytes.is_empty() {
220 return;
221 }
222 let mut crc: u16 = 0;
223 for b in bytes.iter() {
224 crc += *b as u16;
225 }
226 bytes[bytes.len()-1] = (crc&0xff) as u8;
227}
228
229fn get_word(bytes: &[u8; 2]) -> u16 {
230 let mut word: u16 = (bytes[0] as u16) << 8;
231 word |= bytes[1] as u16;
232 word
233}
234
235pub trait DySv5wSerialIO {
238 fn send_data(&mut self, data: &[u8]) -> impl Future<Output = ()>;
240 fn read_byte(&mut self) -> impl Future<Output = Option<u8>>;
243}
244
245impl Drive {
246 fn from_u8(value: u8) -> Drive {
247 match value {
248 0 => Drive::USB,
249 1 => Drive::SD,
250 2 => Drive::Flash,
251 _ => Drive::NoDevice,
252 }
253 }
254
255 fn to_u8(self) -> u8 {
256 match self {
257 Drive::USB => { 0 }
258 Drive::SD => { 1 }
259 Drive::Flash => { 2 }
260 Drive::NoDevice => { 0xff }
261 }
262 }
263}
264
265impl EqualizerMode {
266 fn to_u8(self) -> u8 {
267 match self {
268 EqualizerMode::Normal => { 0 }
269 EqualizerMode::Pop => { 1 }
270 EqualizerMode::Rock => { 2 }
271 EqualizerMode::Jazz => { 3 }
272 EqualizerMode::Classic => { 4 }
273 }
274 }
275}