Contiki-NG
mp3-wtv020sd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Zolertia
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 /*---------------------------------------------------------------------------*/
31 /**
32  * \addtogroup zoul-mp3-wtv020sd
33  * @{
34  *
35  * Driver to control the MP3 WTV020SD board in MP3 mode (GPIO based) and the
36  * 2-line serial mode (CLK/DI). Loop Mode and Key Modes not implemented.
37  * More product information available at:
38  * http://avrproject.ru/chasy-budilnik/WTV020SD.pdf
39  * An example on how to wire with a sound power amplifier and speakers at
40  * http://www.hackster.io/zolertia
41  * @{
42  *
43  * \file
44  * Header file for the MP3 WTV020SD driver
45  */
46 /*---------------------------------------------------------------------------*/
47 #include "contiki.h"
48 #include "dev/gpio.h"
49 #include "mp3-wtv020sd.h"
50 
51 #include <stdint.h>
52 /*---------------------------------------------------------------------------*/
53 
54 /*
55  * The WTV020SD can be used in MP3 mode (GPIO-controlled) or 2-line mode (CLK
56  * and DATA line). The following pin-out can be implemented without reusing
57  * the pins as below (in 2-line mode the CLK/DATA functions replace the VOL+/-
58  * keys, others remain the same), but this would require more GPIOs to
59  * interface all functions, so we chose the configuration that uses the less
60  * number of GPIOs, and emulate all functions available in each mode
61  */
62 #ifndef MP3_WTV020SD_P07_PORT
63 #define MP3_WTV020SD_P07_PORT GPIO_B_NUM
64 #endif
65 #ifndef MP3_WTV020SD_P07_PIN
66 #define MP3_WTV020SD_P07_PIN 0
67 #endif
68 #ifndef MP3_WTV020SD_P02_PORT
69 #define MP3_WTV020SD_P02_PORT GPIO_B_NUM
70 #endif
71 #ifndef MP3_WTV020SD_P02_PIN
72 #define MP3_WTV020SD_P02_PIN 1
73 #endif
74 #ifndef MP3_WTV020SD_P06_PORT
75 #define MP3_WTV020SD_P06_PORT GPIO_C_NUM
76 #endif
77 #ifndef MP3_WTV020SD_P06_PIN
78 #define MP3_WTV020SD_P06_PIN 1
79 #endif
80 #ifndef MP3_WTV020SD_P04_PORT
81 #define MP3_WTV020SD_P04_PORT GPIO_B_NUM
82 #endif
83 #ifndef MP3_WTV020SD_P04_PIN
84 #define MP3_WTV020SD_P04_PIN 0
85 #endif
86 #ifndef MP3_WTV020SD_P05_PORT
87 #define MP3_WTV020SD_P05_PORT GPIO_B_NUM
88 #endif
89 #ifndef MP3_WTV020SD_P05_PIN
90 #define MP3_WTV020SD_P05_PIN 1
91 #endif
92 #ifndef MP3_WTV020SD_RESET_PORT
93 #define MP3_WTV020SD_RESET_PORT GPIO_B_NUM
94 #endif
95 #ifndef MP3_WTV020SD_RESET_PIN
96 #define MP3_WTV020SD_RESET_PIN 1
97 #endif
98 
99 /* The BUSY pin is shared between operation modes */
100 #define MP3_BUSY_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P06_PORT)
101 #define MP3_BUSY_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P06_PIN)
102 
103 #define MP3_PLAY_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P07_PORT)
104 #define MP3_PLAY_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P07_PIN)
105 #define MP3_NEXT_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P02_PORT)
106 #define MP3_NEXT_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P02_PIN)
107 
108 #define MP3_RESET_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_RESET_PORT)
109 #define MP3_RESET_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_RESET_PIN)
110 #define MP3_CLK_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P04_PORT)
111 #define MP3_CLK_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P04_PIN)
112 #define MP3_DATA_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P05_PORT)
113 #define MP3_DATA_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P05_PIN)
114 
115 /*---------------------------------------------------------------------------*/
116 static uint8_t initialized = 0;
117 static int mp3_line_command(uint16_t cmd);
118 /*---------------------------------------------------------------------------*/
119 int
120 mp3_wtv020sd_config(uint8_t mode)
121 {
122  if(mode != MP3_WTV020SD_GPIO_MODE && mode != MP3_WTV020SD_LINE_MODE) {
123  return MP3_WTV020SD_ERROR;
124  }
125 
126  if(mode == MP3_WTV020SD_GPIO_MODE) {
127  GPIO_SOFTWARE_CONTROL(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK);
128  GPIO_SET_OUTPUT(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK);
129  GPIO_SET_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK);
130  GPIO_SOFTWARE_CONTROL(MP3_NEXT_PORT_BASE, MP3_NEXT_PIN_MASK);
131  GPIO_SET_OUTPUT(MP3_NEXT_PORT_BASE, MP3_NEXT_PIN_MASK);
132  GPIO_SET_PIN(MP3_NEXT_PORT_BASE, MP3_NEXT_PIN_MASK);
133  } else {
134  GPIO_SOFTWARE_CONTROL(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK);
135  GPIO_SET_OUTPUT(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK);
136  GPIO_SET_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK);
137  GPIO_SOFTWARE_CONTROL(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
138  GPIO_SET_OUTPUT(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
139  GPIO_SET_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
140  GPIO_SOFTWARE_CONTROL(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK);
141  GPIO_SET_OUTPUT(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK);
142  GPIO_SET_PIN(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK);
143  }
144 
145  GPIO_SOFTWARE_CONTROL(MP3_BUSY_PORT_BASE, MP3_BUSY_PIN_MASK);
146  GPIO_SET_INPUT(MP3_BUSY_PORT_BASE, MP3_BUSY_PIN_MASK);
147 
148  initialized = mode;
149  return MP3_WTV020SD_SUCCESS;
150 }
151 /*---------------------------------------------------------------------------*/
152 int
154 {
155  if(initialized != MP3_WTV020SD_GPIO_MODE) {
156  return MP3_WTV020SD_ERROR;
157  }
158  GPIO_CLR_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK);
159  return MP3_WTV020SD_SUCCESS;
160 }
161 /*---------------------------------------------------------------------------*/
162 int
164 {
165  if(initialized != MP3_WTV020SD_GPIO_MODE) {
166  return MP3_WTV020SD_ERROR;
167  }
168  GPIO_SET_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK);
169  return MP3_WTV020SD_SUCCESS;
170 }
171 /*---------------------------------------------------------------------------*/
172 int
174 {
175  if(initialized != MP3_WTV020SD_GPIO_MODE) {
176  return MP3_WTV020SD_ERROR;
177  }
178  GPIO_CLR_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK);
179  clock_delay_usec(MP3_USEC_DELAY);
180  GPIO_SET_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK);
181  return MP3_WTV020SD_SUCCESS;
182 }
183 /*---------------------------------------------------------------------------*/
184 int
186 {
187  if((initialized != MP3_WTV020SD_GPIO_MODE) &&
188  (initialized != MP3_WTV020SD_LINE_MODE)) {
189  return MP3_WTV020SD_ERROR;
190  }
191  if(GPIO_READ_PIN(MP3_BUSY_PORT_BASE, MP3_BUSY_PIN_MASK)) {
192  return MP3_WTV020SD_BUSY;
193  }
194  return MP3_WTV020SD_IDLE;
195 }
196 /*---------------------------------------------------------------------------*/
197 int
199 {
200  if(initialized != MP3_WTV020SD_LINE_MODE) {
201  return MP3_WTV020SD_ERROR;
202  }
203  GPIO_CLR_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
204  GPIO_SET_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK);
205  GPIO_CLR_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK);
206  clock_delay_usec(MP3_USEC_DELAY);
207  GPIO_SET_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK);
208  GPIO_SET_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
209  clock_delay_usec(MP3_USEC_RESET_DELAY);
210  return MP3_WTV020SD_SUCCESS;
211 }
212 /*---------------------------------------------------------------------------*/
213 int
214 mp3_wtv020sd_sync_play(uint16_t track)
215 {
216  if(initialized != MP3_WTV020SD_LINE_MODE) {
217  return MP3_WTV020SD_ERROR;
218  }
219  mp3_line_command(track);
220  while(mp3_wtv020sd_busy());
221  return MP3_WTV020SD_SUCCESS;
222 }
223 /*---------------------------------------------------------------------------*/
224 int
225 mp3_wtv020sd_async_play(uint16_t track)
226 {
227  if(initialized != MP3_WTV020SD_LINE_MODE) {
228  return MP3_WTV020SD_ERROR;
229  }
230  mp3_line_command(track);
231  return MP3_WTV020SD_SUCCESS;
232 }
233 /*---------------------------------------------------------------------------*/
234 int
236 {
237  if(initialized != MP3_WTV020SD_LINE_MODE) {
238  return MP3_WTV020SD_ERROR;
239  }
240  mp3_line_command(MP3_WTV020SD_STOP_VAL);
241  return MP3_WTV020SD_SUCCESS;
242 }
243 /*---------------------------------------------------------------------------*/
244 int
246 {
247  if(initialized != MP3_WTV020SD_LINE_MODE) {
248  return MP3_WTV020SD_ERROR;
249  }
250  mp3_line_command(MP3_WTV020SD_PLAY_PAUSE_VAL);
251  return MP3_WTV020SD_SUCCESS;
252 }
253 /*---------------------------------------------------------------------------*/
254 int
255 mp3_line_command(uint16_t cmd)
256 {
257  uint16_t mask;
258  if(initialized != MP3_WTV020SD_LINE_MODE) {
259  return MP3_WTV020SD_ERROR;
260  }
261  GPIO_CLR_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
262  clock_delay_usec(MP3_USEC_CMD_DELAY / 10);
263  for(mask = 0x8000; mask > 0; mask >> 1) {
264  GPIO_CLR_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
265  clock_delay_usec(MP3_USEC_CMD_DELAY / 2);
266  if(cmd & mask) {
267  GPIO_SET_PIN(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK);
268  } else {
269  GPIO_CLR_PIN(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK);
270  }
271  clock_delay_usec(MP3_USEC_CMD_DELAY / 2);
272  GPIO_SET_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK);
273  clock_delay_usec(MP3_USEC_CMD_DELAY);
274  if(mask > 0x0001) {
275  clock_delay_usec(MP3_USEC_CMD_DELAY / 10);
276  }
277  }
278  clock_delay_usec(MP3_USEC_CMD_DELAY / 8);
279  return MP3_WTV020SD_SUCCESS;
280 }
281 /*---------------------------------------------------------------------------*/
282 
283 /**
284  * @}
285  * @}
286  */
int mp3_wtv020sd_reset(void)
Trigger a module reset.
Definition: mp3-wtv020sd.c:198
#define GPIO_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:106
int mp3_wtv020sd_sync_play(uint16_t track)
Plays the selected track and waits until it stops.
Definition: mp3-wtv020sd.c:214
Header file with register and macro declarations for the cc2538 GPIO module.
#define GPIO_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition: gpio.h:113
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
int mp3_wtv020sd_pause(void)
Pauses the current track.
Definition: mp3-wtv020sd.c:245
Header file for the MP3 WTV020SD driver.
int mp3_wtv020sd_async_play(uint16_t track)
Plays the selected track and returns immediately.
Definition: mp3-wtv020sd.c:225
#define GPIO_READ_PIN(PORT_BASE, PIN_MASK)
Read pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:147
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
Definition: gpio.h:258
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:78
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:85
int mp3_wtv020sd_gpio_play(void)
Function to play a current track.
Definition: mp3-wtv020sd.c:153
int mp3_wtv020sd_config(uint8_t mode)
Init function for the MP3 driver.
Definition: mp3-wtv020sd.c:120
int mp3_wtv020sd_busy(void)
Get the current status of the device (playing/stopped)
Definition: mp3-wtv020sd.c:185
int mp3_wtv020sd_gpio_next(void)
Advances and play the next track, wraps over the playlist.
Definition: mp3-wtv020sd.c:173
int mp3_wtv020sd_stop(void)
Stops the current track.
Definition: mp3-wtv020sd.c:235
int mp3_wtv020sd_gpio_stop(void)
Function to stop a current track.
Definition: mp3-wtv020sd.c:163