Contiki-NG
Loading...
Searching...
No Matches
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/*---------------------------------------------------------------------------*/
116static uint8_t initialized = 0;
117static int mp3_line_command(uint16_t cmd);
118/*---------------------------------------------------------------------------*/
119int
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/*---------------------------------------------------------------------------*/
152int
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/*---------------------------------------------------------------------------*/
162int
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/*---------------------------------------------------------------------------*/
172int
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/*---------------------------------------------------------------------------*/
184int
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/*---------------------------------------------------------------------------*/
197int
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/*---------------------------------------------------------------------------*/
213int
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/*---------------------------------------------------------------------------*/
224int
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/*---------------------------------------------------------------------------*/
234int
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/*---------------------------------------------------------------------------*/
244int
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/*---------------------------------------------------------------------------*/
254int
255mp3_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 */
Header file with register and macro declarations for the cc2538 GPIO module.
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition clock.c:150
#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_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition gpio.h:106
#define GPIO_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition gpio.h:113
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition gpio.h:85
#define GPIO_READ_PIN(PORT_BASE, PIN_MASK)
Read pins with PIN_MASK of port with PORT_BASE.
Definition gpio.h:147
int mp3_wtv020sd_async_play(uint16_t track)
Plays the selected track and returns immediately.
int mp3_wtv020sd_reset(void)
Trigger a module reset.
int mp3_wtv020sd_gpio_stop(void)
Function to stop a current track.
int mp3_wtv020sd_gpio_play(void)
Function to play a current track.
int mp3_wtv020sd_pause(void)
Pauses the current track.
int mp3_wtv020sd_stop(void)
Stops the current track.
int mp3_wtv020sd_busy(void)
Get the current status of the device (playing/stopped)
int mp3_wtv020sd_sync_play(uint16_t track)
Plays the selected track and waits until it stops.
int mp3_wtv020sd_gpio_next(void)
Advances and play the next track, wraps over the playlist.
int mp3_wtv020sd_config(uint8_t mode)
Init function for the MP3 driver.
Header file for the MP3 WTV020SD driver.