qwiic_mp3_trigger/
lib.rs

1extern crate i2cdev;
2#[macro_use] extern crate log;
3
4use i2cdev::core::I2CDevice;
5use std::{thread, time};
6
7const COMMAND_STOP: u8 = 0x00;
8const COMMAND_PLAY_TRACK: u8 = 0x01;
9const COMMAND_PLAY_FILENUMBER: u8 = 0x02;
10const COMMAND_PAUSE: u8 = 0x03;
11const COMMAND_PLAY_NEXT: u8 = 0x04;
12const COMMAND_PLAY_PREVIOUS: u8 = 0x05;
13const COMMAND_SET_EQ: u8 = 0x06;
14const COMMAND_SET_VOLUME: u8 = 0x07;
15const COMMAND_GET_SONG_COUNT: u8 = 0x08;
16const COMMAND_GET_SONG_NAME: u8 = 0x09;
17const COMMAND_GET_PLAY_STATUS: u8 = 0x0A;
18const COMMAND_GET_CARD_STATUS: u8 = 0x0B;
19const COMMAND_GET_VERSION: u8 = 0x0C;
20const COMMAND_SET_ADDRESS: u8 = 0xC7;
21
22fn read_delay() {
23    thread::sleep(time::Duration::from_millis(300));
24}
25
26/// The `EqualizerMode` type denotes different equalizer modes.
27#[derive(Debug, PartialEq)]
28#[repr(u8)]
29pub enum EqualizerMode {
30    Normal = 0,
31    Pop = 1,
32    Rock = 2,
33    Jazz = 3,
34    Classical = 4,
35    Bass = 5,
36}
37
38/// The `PlayStatus` type describes the state of the mp3 trigger.
39#[derive(Debug, PartialEq)]
40pub enum PlayStatus {
41    Playing,
42    Stopped,
43    Unknown,
44}
45
46/// The `CardStatus` type indicates if an SD card is present.
47#[derive(Debug, PartialEq)]
48pub enum CardStatus {
49    Good,
50    Bad,
51}
52
53/// This object communicates with a Sparkfun Qwiic MP3 Trigger over i2c.
54#[derive(Debug)]
55pub struct QwiicMP3Trigger<T: I2CDevice + Sized> {
56    i2cdev: T,
57}
58
59impl<T> QwiicMP3Trigger<T>
60    where T: I2CDevice + Sized
61{
62    /// Constructs a new `QwiicMP3Trigger<T>`.
63    pub fn new(i2cdev: T) -> Result<QwiicMP3Trigger<T>, T::Error> {
64        Ok(QwiicMP3Trigger { i2cdev: i2cdev })
65    }
66
67    /// Tests communication.
68    pub fn ping(&mut self) -> Result<(), T::Error> {
69        debug!("ping()");
70        self.send_data(&[COMMAND_GET_VERSION])
71    }
72
73    /// Returns the number of songs on the SD card, including trigger songs.
74    pub fn get_song_count(&mut self) -> Result<u8, T::Error> {
75        debug!("get_song_count()");
76        self.send_data(&[COMMAND_GET_SONG_COUNT])?;
77        read_delay();
78        Ok(self.read_response()?[0])
79    }
80
81    /// Returns the version of the Qwiic MP3 Trigger firmware.
82    pub fn get_version(&mut self) -> Result<String, T::Error> {
83        debug!("get_version()");
84        self.send_data(&[COMMAND_GET_VERSION])?;
85        read_delay();
86        let r = self.read_response()?;
87        Ok(format!("{}.{}", r[0], r[1]).clone())
88    }
89
90    /// Plays a track based on the sorting rules of the WT2003S.
91    pub fn play_track(&mut self, track: u8) -> Result<(), T::Error> {
92        debug!("play_track({})", track);
93        self.send_data(&[COMMAND_PLAY_TRACK, track])
94    }
95
96    /// Plays a track based on the filename.  `3` will play a file matching `F003***.mp3`.
97    pub fn play_filenumber(&mut self, filenumber: u8) -> Result<(), T::Error> {
98        debug!("play_filenumber({})", filenumber);
99        self.send_data(&[COMMAND_PLAY_FILENUMBER, filenumber])
100    }
101
102    /// Plays the next track based on the sorting rules of the WT2003S.
103    pub fn play_next(&mut self) -> Result<(), T::Error> {
104        debug!("play_next()");
105        self.send_data(&[COMMAND_PLAY_NEXT])
106    }
107
108    /// Plays the previous track based on the sorting rules of the WT2003S.
109    pub fn play_previous(&mut self) -> Result<(), T::Error> {
110        debug!("play_previous()");
111        self.send_data(&[COMMAND_PLAY_PREVIOUS])
112    }
113
114    /// Stops playing.  Note that this may result in buzzing because the audio output it
115    /// not disabled.  You may wish to play a long silence instead.
116    pub fn stop(&mut self) -> Result<(), T::Error> {
117        debug!("stop()");
118        self.send_data(&[COMMAND_STOP])
119    }
120
121    /// Pauses playing.  Note that this may result in buzzing because the audio output it
122    /// not disabled.  You may wish to play a long silence instead.
123    pub fn pause(&mut self) -> Result<(), T::Error> {
124        debug!("pause()");
125        self.send_data(&[COMMAND_PAUSE])
126    }
127
128    /// Returns the play status.
129    pub fn get_play_status(&mut self) -> Result<PlayStatus, T::Error> {
130        debug!("get_play_status()");
131        self.send_data(&[COMMAND_GET_PLAY_STATUS])?;
132        read_delay();
133        match self.read_response()?[0] {
134            1 => Ok(PlayStatus::Playing),
135            2 => Ok(PlayStatus::Stopped),
136            _ => Ok(PlayStatus::Unknown),
137        }
138    }
139
140    /// Checks the status of the SD card.
141    pub fn get_card_status(&mut self) -> Result<CardStatus, T::Error> {
142        debug!("get_card_status()");
143        self.send_data(&[COMMAND_GET_CARD_STATUS])?;
144        read_delay();
145        match self.read_response()?[0] {
146            0 => Ok(CardStatus::Bad),
147            1 => Ok(CardStatus::Good),
148            _ => Ok(CardStatus::Bad),
149        }
150    }
151
152    /// Returns the name of the currently playing song.  May return `unable to parse`.
153    pub fn get_song_name(&mut self) -> Result<String, T::Error> {
154        debug!("get_song_name()");
155        self.send_data(&[COMMAND_GET_SONG_NAME])?;
156        read_delay();
157        let string = String::from_utf8(self.read_response()?.to_vec());
158        match string {
159            Ok(s) => Ok(s),
160            Err(_) => Ok(String::from("unable to parse")),
161        }
162    }
163
164    /// Set the equalizer mode.
165    pub fn set_eq(&mut self, mode: EqualizerMode) -> Result<(), T::Error> {
166        debug!("set_eq({:?})", mode);
167        self.send_data(&[COMMAND_SET_EQ, mode as u8])
168    }
169
170    /// Set the volume between 0 (off) to 31 (max).
171    pub fn set_volume(&mut self, level: u8) -> Result<(), T::Error> {
172        debug!("set_volume({})", level);
173        self.send_data(&[COMMAND_SET_VOLUME, level])
174    }
175
176    /// Set the i2c address of the device.
177    pub fn set_address(&mut self, address: u8) -> Result<(), T::Error> {
178        debug!("set_address({})", address);
179        self.send_data(&[COMMAND_SET_ADDRESS, address])
180    }
181
182    fn send_data(&mut self, data: &[u8]) -> Result<(), T::Error> {
183        trace!("Sending: {:?}", data);
184        self.i2cdev.write(data)?;
185        trace!("Sent");
186        Ok(())
187    }
188
189    fn read_response(&mut self) -> Result<[u8; 8], T::Error> {
190        let mut buf: [u8; 8] = [0; 8];
191        self.i2cdev.read(&mut buf)?;
192        trace!("Reading: {:?}", buf);
193        Ok(buf)
194    }
195}