提交 367b13bc 编写于 作者: B bernard.xiong

split player code to player_background and player_ui; add play list code; add...

split player code to player_background and player_ui; add play list code; add wm8978 driver for codec v2 board; add sdcard waiting check.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@187 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 6a0d1606
......@@ -42,6 +42,10 @@
// <i>Default: 1
#define STM32_CONSOLE_USART 1
// <o> Codec Version <1=>Version 1 <2=>Version 2
// <i>Default: 1
#define CODEC_VERSION 1
void rt_hw_board_led_on(int n);
void rt_hw_board_led_off(int n);
void rt_hw_board_init(void);
......
......@@ -224,9 +224,9 @@ static void _filelist_view_constructor(struct filelist_view *view)
RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
file_image = rtgui_image_create_from_mem("xpm",
(rt_uint8_t*)file_xpm, sizeof(file_xpm));
(rt_uint8_t*)file_xpm, sizeof(file_xpm), RT_TRUE);
folder_image = rtgui_image_create_from_mem("xpm",
(rt_uint8_t*)folder_xpm, sizeof(folder_xpm));
(rt_uint8_t*)folder_xpm, sizeof(folder_xpm), RT_TRUE);
}
rtgui_type_t *filelist_view_type_get(void)
......
......@@ -36,7 +36,7 @@ static rt_bool_t view_event_handler(struct rtgui_widget* widget, struct rtgui_ev
rtt_image = RT_NULL;
}
if (network_image != RT_NULL)
{
rect.x1 = rect.x2 - (network_image->w + 2);
......@@ -61,7 +61,7 @@ static void info_entry(void* parameter)
rtgui_thread_register(rt_thread_self(), mq);
network_image = rtgui_image_create_from_mem("xpm",
(rt_uint8_t*)network_xpm, sizeof(network_xpm));
(rt_uint8_t*)network_xpm, sizeof(network_xpm), RT_TRUE);
workbench = rtgui_workbench_create("info", "workbench");
if (workbench == RT_NULL) return;
......
#include <rtthread.h>
#include <dfs_posix.h>
#include <mp3/pub/mp3dec.h>
#include <string.h>
#include "board.h"
#include "netbuffer.h"
#include "player_ui.h"
#include "player_bg.h"
#define MP3_AUDIO_BUF_SZ 4096
#ifndef MIN
#define MIN(x, y) ((x) < (y)? (x) : (y))
#endif
rt_uint8_t mp3_fd_buffer[MP3_AUDIO_BUF_SZ];
......@@ -21,9 +27,8 @@ struct mp3_decoder
void* fetch_parameter;
/* mp3 read session */
rt_uint8_t *read_buffer;
rt_uint8_t* read_ptr;
rt_int32_t read_offset;
rt_uint8_t *read_buffer, *read_ptr;
rt_int32_t read_offset;
rt_uint32_t bytes_left, bytes_left_before_decoding;
/* audio device */
......@@ -99,7 +104,6 @@ void mp3_decoder_delete(struct mp3_decoder* decoder)
rt_free(decoder);
}
rt_uint16_t is_first = 1;
rt_uint32_t current_offset = 0;
static rt_int32_t mp3_decoder_fill_buffer(struct mp3_decoder* decoder)
{
......@@ -116,9 +120,6 @@ static rt_int32_t mp3_decoder_fill_buffer(struct mp3_decoder* decoder)
bytes_to_read = (MP3_AUDIO_BUF_SZ - decoder->bytes_left) & ~(512 - 1);
// rt_kprintf("read bytes: %d\n", bytes_to_read);
if (is_first) is_first = 0;
else current_offset += MP3_AUDIO_BUF_SZ - decoder->bytes_left;
bytes_read = decoder->fetch_data(decoder->fetch_parameter,
(rt_uint8_t *)(decoder->read_buffer + decoder->bytes_left),
bytes_to_read);
......@@ -141,9 +142,12 @@ int mp3_decoder_run(struct mp3_decoder* decoder)
{
int err;
rt_uint16_t* buffer;
rt_uint32_t delta;
RT_ASSERT(decoder != RT_NULL);
if (player_is_playing() != RT_TRUE) return -1;
if ((decoder->read_ptr == RT_NULL) || decoder->bytes_left < 2*MAINBUF_SIZE)
{
if(mp3_decoder_fill_buffer(decoder) != 0)
......@@ -162,6 +166,7 @@ int mp3_decoder_run(struct mp3_decoder* decoder)
// rt_kprintf("sync position: %x\n", decoder->read_offset);
decoder->read_ptr += decoder->read_offset;
delta = decoder->read_offset;
decoder->bytes_left -= decoder->read_offset;
decoder->bytes_left_before_decoding = decoder->bytes_left;
......@@ -196,6 +201,10 @@ int mp3_decoder_run(struct mp3_decoder* decoder)
err = MP3Decode(decoder->decoder, &decoder->read_ptr,
(int*)&decoder->bytes_left, (short*)buffer, 0);
delta += (decoder->bytes_left_before_decoding - decoder->bytes_left);
current_offset += delta;
player_set_position(current_offset);
// rt_kprintf("bytes left after decode: %d\n", decoder->bytes_left);
......@@ -277,26 +286,114 @@ int mp3_decoder_run(struct mp3_decoder* decoder)
/* write to sound device */
rt_device_write(decoder->snd_device, 0, buffer, decoder->frame_info.outputSamps * 2);
// rt_mp_free(buffer);
}
return 0;
}
/* audio information structure */
struct audio_info
/* get mp3 information */
void mp3_get_info(const char* filename, struct tag_info* info)
{
char* title;
char* artist;
int fd;
char* id3buffer;
rt_size_t bytes_read;
int sync_word;
HMP3Decoder decoder;
MP3FrameInfo frame_info;
rt_uint32_t duration;
rt_uint32_t bit_rate;
rt_uint32_t sampling;
};
id3buffer = (char*)&mp3_fd_buffer[0];
if (filename == RT_NULL || info == RT_NULL) return;
/* get mp3 information */
void mp3_get_info(char* filename, struct audio_info* info)
{
fd = open(filename, O_RDONLY, 0);
if (fd < 0) return; /* can't read file */
/* init decoder */
decoder = MP3InitDecoder();
/* read data */
bytes_read = read(fd, id3buffer, sizeof(mp3_fd_buffer));
/* get frame information */
sync_word = MP3FindSyncWord(id3buffer, bytes_read);
if (sync_word < 0)
{
/* can't get sync word */
close(fd);
mp3_decoder_detach(decoder);
}
/* get frame information */
MP3GetNextFrameInfo(decoder, &frame_info, &id3buffer[sync_word]);
info->bit_rate = frame_info.bitrate;
info->sampling = frame_info.samprate;
info->duration = lseek(fd, 0, SEEK_END)/ (info->bit_rate / 8); /* second */
if (strncmp("ID3", id3buffer, 4) == 0)
{
rt_uint32_t tag_size, frame_size, i;
rt_uint8_t version_major;
int frame_header_size;
tag_size = ((rt_uint32_t)id3buffer[6] << 21)|((rt_uint32_t)id3buffer[7] << 14)|((rt_uint16_t)id3buffer[8] << 7)|id3buffer[9];
info->data_start = tag_size;
version_major = id3buffer[3];
if (version_major >= 3)
{
frame_header_size = 10;
}
else
{
frame_header_size = 6;
}
i = 10;
// iterate through frames
while (i < MIN(tag_size, sizeof(id3buffer)))
{
if (version_major >= 3)
{
frame_size = ((rt_uint32_t)id3buffer[i + 4] << 24)|((rt_uint32_t)id3buffer[i + 5] << 16)|((rt_uint16_t)id3buffer[i + 6] << 8)|id3buffer[i + 7];
}
else
{
frame_size = ((rt_uint32_t)id3buffer[i + 3] << 14)|((rt_uint16_t)id3buffer[i + 4] << 7)|id3buffer[i + 5];
}
if (strncmp("TT2", id3buffer + i, 3) == 0 || strncmp("TIT2", id3buffer + i, 4) == 0)
{
strncpy(info->title, id3buffer + i + frame_header_size + 1, MIN(frame_size - 1, sizeof(info->title) - 1));
}
else if (strncmp("TP1", id3buffer + i, 3) == 0 || strncmp("TPE1", id3buffer + i, 4) == 0)
{
strncpy(info->artist, id3buffer + i + frame_header_size + 1, MIN(frame_size - 1, sizeof(info->artist) - 1));
}
i += frame_size + frame_header_size;
}
}
else
{
lseek(fd, -128, SEEK_END);
bytes_read = read(fd, id3buffer, 128);
/* ID3v1 */
if (strncmp("TAG", id3buffer, 3) == 0)
{
strncpy(info->title, id3buffer + 3, MIN(30, sizeof(info->title) - 1));
strncpy(info->artist, id3buffer + 3 + 30, MIN(30, sizeof(info->artist) - 1));
}
/* set data start position */
info->data_start = 0;
}
/* set current position */
info->position = 0;
/* release mp3 decoder */
MP3FreeDecoder(decoder);
/* close file */
close(fd);
}
#include <finsh.h>
......@@ -309,7 +406,9 @@ void mp3(char* filename)
{
int fd;
struct mp3_decoder* decoder;
extern rt_bool_t is_playing;
is_playing = RT_TRUE;
fd = open(filename, O_RDONLY, 0);
if (fd >= 0)
{
......@@ -319,6 +418,7 @@ void mp3(char* filename)
decoder->fetch_data = fd_fetch;
decoder->fetch_parameter = (void*)fd;
current_offset = 0;
while (mp3_decoder_run(decoder) != -1);
close(fd);
......@@ -326,6 +426,7 @@ void mp3(char* filename)
mp3_decoder_delete(decoder);
}
}
is_playing = RT_FALSE;
}
FINSH_FUNCTION_EXPORT(mp3, mp3 decode test);
......@@ -369,6 +470,7 @@ void http_mp3(char* url)
decoder->fetch_data = http_data_fetch;
decoder->fetch_parameter = RT_NULL;
current_offset = 0;
while (mp3_decoder_run(decoder) != -1);
/* delete decoder object */
......
#include "play_list.h"
#include "player_ui.h"
#include <string.h>
static struct play_item **play_list = RT_NULL;
static rt_uint16_t play_list_size = 0;
static rt_int16_t play_list_current = 0;
void play_list_clear()
{
rt_uint32_t index;
for (index = 0; index < play_list_size; index ++)
{
rt_free(play_list[index]->fn);
rt_free(play_list[index]);
play_list[index] = RT_NULL;
}
rt_free(play_list);
play_list = RT_NULL;
play_list_size = 0;
}
char* play_list_start()
{
play_list_current = 0;
return play_list[play_list_current]->fn;
}
rt_bool_t play_list_is_end()
{
if ((play_list_current == play_list_size - 1) ||
play_list_size == 0)
return RT_TRUE;
return RT_FALSE;
}
rt_uint32_t play_list_items(void)
{
return play_list_size;
}
struct play_item* play_list_item(rt_uint32_t n)
{
if (n > play_list_size) return RT_NULL;
return play_list[n];
}
void play_list_append(char* fn)
{
play_list_size ++;
if (play_list == RT_NULL)
play_list = (struct play_item**) rt_malloc (play_list_size * sizeof(struct play_item*));
else
play_list = (struct play_item**) rt_realloc(play_list, play_list_size * sizeof(struct play_item*));
play_list[play_list_size - 1] = (struct play_item*)rt_malloc(sizeof(struct play_item));
if (strstr(fn, ".mp3") != RT_NULL ||
strstr(fn, ".MP3") != RT_NULL)
{
struct tag_info info;
memset(&info, 0, sizeof(info));
mp3_get_info(fn, &info);
if (info.title[0] == '\0')
rt_snprintf(play_list[play_list_size - 1]->title, sizeof(play_list[play_list_size - 1]->title),
"<δ֪>");
else
strcpy(play_list[play_list_size - 1]->title, info.title);
play_list[play_list_size - 1]->fn = rt_strdup(fn);
play_list[play_list_size - 1]->duration = info.duration;
}
else
{
rt_snprintf(play_list[play_list_size - 1]->title, sizeof(play_list[play_list_size - 1]->title),
"<δ֪>");
play_list[play_list_size - 1]->fn = rt_strdup(fn);
play_list[play_list_size - 1]->duration = 0;
}
}
char* play_list_next()
{
if (play_list_current < play_list_size - 1) play_list_current ++;
return play_list[play_list_current]->fn;
}
char* play_list_prev()
{
if (play_list_current > 0) play_list_current --;
return play_list[play_list_current]->fn;
}
char* play_list_current_item()
{
return play_list[play_list_current]->fn;
}
#ifndef __PLAY_LIST_H__
#define __PLAY_LIST_H__
#include <rtthread.h>
struct play_item
{
char title[40];
char *fn;
rt_uint32_t duration;
};
void play_list_clear(void);
char* play_list_start(void);
rt_bool_t play_list_is_end(void);
rt_uint32_t play_list_items(void);
struct play_item* play_list_item(rt_uint32_t n);
void play_list_append(char* fn);
char* play_list_next(void);
char* play_list_prev(void);
char* play_list_current_item(void);
#endif
#include <rtgui/rtgui.h>
#include <rtgui/image.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/view.h>
#include <rtgui/widgets/workbench.h>
#include <string.h>
#include "listview.h"
#include "filelist.h"
static const char * next_xpm[] = {
"24 24 149 2",
" c None",
". c #373737",
"+ c #383838",
"@ c #3A3A3A",
"# c #393939",
"$ c #434343",
"% c #676767",
"& c #9D9D9D",
"* c #C1C1C1",
"= c #D3D3D3",
"- c #404040",
"; c #707070",
"> c #EDEDED",
", c #F5F5F5",
"' c #4A4A4A",
") c #909090",
"! c #D9D9D9",
"~ c #4B4B4B",
"{ c #939393",
"] c #CECECE",
"^ c #E4E4E4",
"/ c #E5E5E5",
"( c #444444",
"_ c #8B8B8B",
": c #ABABAB",
"< c #DCDCDC",
"[ c #D4D4D4",
"} c #D2D2D2",
"| c #DDDDDD",
"1 c #DEDEDE",
"2 c #DFDFDF",
"3 c #414141",
"4 c #B8B8B8",
"5 c #BBBBBB",
"6 c #ADADAD",
"7 c #B7B7B7",
"8 c #CFCFCF",
"9 c #D8D8D8",
"0 c #D6D6D6",
"a c #B2B2B2",
"b c #AEAEAE",
"c c #B6B6B6",
"d c #4C4C4C",
"e c #989898",
"f c #9E9E9E",
"g c #CDCDCD",
"h c #C5C5C5",
"i c #C7C7C7",
"j c #A1A1A1",
"k c #B3B3B3",
"l c #9F9F9F",
"m c #A2A2A2",
"n c #CACACA",
"o c #696969",
"p c #A0A0A0",
"q c #B1B1B1",
"r c #F1F1F1",
"s c #E3E3E3",
"t c #CCCCCC",
"u c #C6C6C6",
"v c #D1D1D1",
"w c #C2C2C2",
"x c #464646",
"y c #848484",
"z c #A4A4A4",
"A c #A9A9A9",
"B c #BFBFBF",
"C c #959595",
"D c #EFEFEF",
"E c #EEEEEE",
"F c #929292",
"G c #808080",
"H c #CBCBCB",
"I c #858585",
"J c #B9B9B9",
"K c #A5A5A5",
"L c #494949",
"M c #A7A7A7",
"N c #B0B0B0",
"O c #888888",
"P c #EAEAEA",
"Q c #777777",
"R c #6C6C6C",
"S c #C4C4C4",
"T c #757575",
"U c #A8A8A8",
"V c #A3A3A3",
"W c #949494",
"X c #9C9C9C",
"Y c #EBEBEB",
"Z c #575757",
"` c #4D4D4D",
" . c #ACACAC",
".. c #6B6B6B",
"+. c #9A9A9A",
"@. c #E9E9E9",
"#. c #D7D7D7",
"$. c #BDBDBD",
"%. c #515151",
"&. c #E8E8E8",
"*. c #E2E2E2",
"=. c #9B9B9B",
"-. c #4E4E4E",
";. c #B4B4B4",
">. c #525252",
",. c #BEBEBE",
"'. c #8C8C8C",
"). c #AAAAAA",
"!. c #AFAFAF",
"~. c #E7E7E7",
"{. c #5D5D5D",
"]. c #7E7E7E",
"^. c #616161",
"/. c #C8C8C8",
"(. c #747474",
"_. c #B5B5B5",
":. c #6D6D6D",
"<. c #4F4F4F",
"[. c #5A5A5A",
"}. c #A6A6A6",
"|. c #919191",
"1. c #8D8D8D",
"2. c #DBDBDB",
"3. c #7F7F7F",
"4. c #E0E0E0",
"5. c #C0C0C0",
"6. c #828282",
"7. c #595959",
"8. c #C9C9C9",
"9. c #E1E1E1",
"0. c #E6E6E6",
"a. c #D5D5D5",
"b. c #626262",
"c. c #ECECEC",
"d. c #636363",
"e. c #646464",
"f. c #F0F0F0",
"g. c #F3F3F3",
"h. c #F4F4F4",
"i. c #F6F6F6",
"j. c #F7F7F7",
"k. c #5E5E5E",
"l. c #898989",
"m. c #F9F9F9",
"n. c #F8F8F8",
"o. c #8A8A8A",
"p. c #656565",
"q. c #5C5C5C",
"r. c #5F5F5F",
" . + @ @ + . ",
" # $ % & * = = * & % $ # ",
" - ; * > , , , , , , > * ; - ",
" ' ) ! > > > > > > > > > > ! ) ' ",
" ~ { ] ^ ^ / / / / / / / / / / ] { ~ ",
" ( _ : < [ } | 1 2 2 2 2 1 | < < < : _ ( ",
" 3 ; & 4 = 5 6 7 8 9 ! ! ! 0 a b c = 4 & ; 3 ",
" d e f 4 g b h i j k ] [ [ g l } m n 4 f e d ",
" o & p q i j * r s b { k t u ) v { w q j f o ",
"x y l z A B C 4 D D E v F _ : G H I J A K j y x ",
"L { m M : N O N > > > > P 4 Q R S T U : U V W L ",
"~ X K A b 6 ; K Y Y Y Y Y Y 2 k S Z K b : M & ~ ",
"` f M .N N ..+.@.@.@.@.@.@.#.f $.%.M a k q V ` ",
"` e U b a a R +.&.&.&.&.*.=.-.( ;.>.b ,.,.$.f ` ",
"-.'.).!.;.;.R +.&.&.~.7 {.Z ].L ;.^.B /./.i ) -.",
" (.).N _.;.:.+.&.] T <.G ).A %.h _ n } } i (. ",
" [.}.q _.;.:.|.) ` :.K B t /.1.= l [ 2.2.c [. ",
" >.G _.B B 3.[.o =.,.= 4./ 2.K 5.k | s #.6.>. ",
" 7.l S H 7 q 8.#.9.0.@.@./ g H a.&.0.M 7. ",
" b. .8 a.9 1 ^ &.Y c.E > c.c.E > 7 d. ",
" e.}.= s ~.Y > f.r g.h.i.j.@. .e. ",
" k.l.5.1 E g.i.j.m.n.Y /.o.k. ",
" [.p.6.m 5 H H ,.z 6.p.[. ",
" q.k.r.r.k.q. "};
static const char * prev_xpm[] = {
"24 24 153 2",
" c None",
". c #373737",
"+ c #383838",
"@ c #3A3A3A",
"# c #393939",
"$ c #434343",
"% c #676767",
"& c #9D9D9D",
"* c #C1C1C1",
"= c #D3D3D3",
"- c #404040",
"; c #707070",
"> c #EDEDED",
", c #F5F5F5",
"' c #4A4A4A",
") c #909090",
"! c #D9D9D9",
"~ c #4B4B4B",
"{ c #939393",
"] c #CECECE",
"^ c #E5E5E5",
"/ c #E4E4E4",
"( c #444444",
"_ c #8B8B8B",
": c #ABABAB",
"< c #DCDCDC",
"[ c #DDDDDD",
"} c #DEDEDE",
"| c #DFDFDF",
"1 c #D5D5D5",
"2 c #D2D2D2",
"3 c #DADADA",
"4 c #414141",
"5 c #B8B8B8",
"6 c #D4D4D4",
"7 c #BBBBBB",
"8 c #AEAEAE",
"9 c #AFAFAF",
"0 c #D0D0D0",
"a c #D8D8D8",
"b c #ADADAD",
"c c #B5B5B5",
"d c #B7B7B7",
"e c #4C4C4C",
"f c #989898",
"g c #9E9E9E",
"h c #AAAAAA",
"i c #CCCCCC",
"j c #A3A3A3",
"k c #D1D1D1",
"l c #A1A1A1",
"m c #CDCDCD",
"n c #A5A5A5",
"o c #C5C5C5",
"p c #696969",
"q c #A0A0A0",
"r c #B1B1B1",
"s c #C8C8C8",
"t c #C9C9C9",
"u c #949494",
"v c #CACACA",
"w c #B9B9B9",
"x c #959595",
"y c #A7A7A7",
"z c #F1F1F1",
"A c #969696",
"B c #BCBCBC",
"C c #464646",
"D c #848484",
"E c #9F9F9F",
"F c #A4A4A4",
"G c #A9A9A9",
"H c #C2C2C2",
"I c #868686",
"J c #8E8E8E",
"K c #8C8C8C",
"L c #EFEFEF",
"M c #C6C6C6",
"N c #888888",
"O c #B2B2B2",
"P c #494949",
"Q c #A2A2A2",
"R c #828282",
"S c #777777",
"T c #737373",
"U c #E7E7E7",
"V c #C0C0C0",
"W c #797979",
"X c #A8A8A8",
"Y c #9C9C9C",
"Z c #B0B0B0",
"` c #686868",
" . c #B6B6B6",
".. c #EBEBEB",
"+. c #5D5D5D",
"@. c #9A9A9A",
"#. c #4D4D4D",
"$. c #ACACAC",
"%. c #B3B3B3",
"&. c #636363",
"*. c #CFCFCF",
"=. c #E9E9E9",
"-. c #575757",
";. c #515151",
">. c #E8E8E8",
",. c #BEBEBE",
"'. c #BDBDBD",
"). c #4E4E4E",
"!. c #B4B4B4",
"~. c #646464",
"{. c #525252",
"]. c #5F5F5F",
"^. c #565656",
"/. c #666666",
"(. c #C7C7C7",
"_. c #747474",
":. c #929292",
"<. c #555555",
"[. c #6B6B6B",
"}. c #C3C3C3",
"|. c #5A5A5A",
"1. c #A6A6A6",
"2. c #C4C4C4",
"3. c #BABABA",
"4. c #838383",
"5. c #DBDBDB",
"6. c #808080",
"7. c #BFBFBF",
"8. c #858585",
"9. c #5E5E5E",
"0. c #E0E0E0",
"a. c #E2E2E2",
"b. c #D7D7D7",
"c. c #595959",
"d. c #E3E3E3",
"e. c #E6E6E6",
"f. c #626262",
"g. c #D6D6D6",
"h. c #ECECEC",
"i. c #EEEEEE",
"j. c #EAEAEA",
"k. c #F0F0F0",
"l. c #F3F3F3",
"m. c #F4F4F4",
"n. c #F6F6F6",
"o. c #F7F7F7",
"p. c #898989",
"q. c #F9F9F9",
"r. c #F8F8F8",
"s. c #8A8A8A",
"t. c #656565",
"u. c #CBCBCB",
"v. c #5C5C5C",
" . + @ @ + . ",
" # $ % & * = = * & % $ # ",
" - ; * > , , , , , , > * ; - ",
" ' ) ! > > > > > > > > > > ! ) ' ",
" ~ { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / / ] { ~ ",
" ( _ : < < < [ } } | | | } } 1 2 3 : _ ( ",
" 4 ; & 5 6 7 8 9 0 a ! ! ! = 7 b c 0 d & ; 4 ",
" e f g 5 ] h i j * k 6 k 5 l * m n o d g f e ",
" p & q r s & t u c v w x y } z m A B 9 l g p ",
"C D E F G * ) H I q J K v > L L M N O y n l D C ",
"P { Q y : O R 7 S T 9 U > > > > V W E X X j u P ",
"~ Y n G 8 Z ` . .3 ............ .+.@.: : y & ~ ",
"#.g y $.r %.&.b j *.=.=.=.=.=.=.8 -.& Z %.r j #.",
"#.f X 8 %.c &.X ;.' ) } >.>.>.>.8 -.j B ,.'.g #.",
").K h 9 !.d ~.X {.W ].^.$.^ >.>.8 /. .(.s (.) ).",
" _.h Z c 5 ~.X {.:.O :.<.[.o =.H J }.0 2 (._. ",
" |.1.r c 5 ~.X {.f 2.i 3.4.T !.s Q ] ! 5. .|. ",
" {.6.c 7.H S 8.9.n *.} 0.[ *.O X .! a.b.R {. ",
" c.E 2.m .j G m 0.U =.=.U d.b.b.e.e.y c. ",
" f.$.0 g.g.a | U ..h.i.i.L i.L h.d &. ",
" ~.1.= d.U j.> k.z l.m.n.o.=.$.~. ",
" 9.p.V } i.l.n.o.q.r...s s.9. ",
" |.t.R Q 7 u.u.,.F R t.|. ",
" v.9.].].9.v. "};
static rtgui_image_t *background = RT_NULL;
static rtgui_image_t *next = RT_NULL, *prev = RT_NULL;
static struct rtgui_view* function_view;
static struct rtgui_view* home_view;
static struct rtgui_workbench* workbench;
void player_play_list(const char** list);
void player_play_file(const char * fn);
void player_next(void);
void player_prev(void);
void function_filelist(void* parameter)
{
rtgui_rect_t rect;
filelist_view_t *view;
rtgui_widget_get_rect(RTGUI_WIDGET(workbench), &rect);
view = filelist_view_create(workbench, "/", "*.*", &rect);
if (view != RT_NULL)
{
if (rtgui_view_show(RTGUI_VIEW(view), RT_TRUE) == RTGUI_MODAL_OK)
{
char fn[64];
/* get open file */
rt_kprintf("dir %s\n", view->current_directory);
rt_kprintf("item %s\n", view->items[view->current_item].name);
rt_snprintf(fn, 64, "%s/%s", view->current_directory,
view->items[view->current_item].name);
rtgui_view_show(home_view, RT_FALSE);
player_play_file(fn);
}
/* destroy view */
filelist_view_destroy(view);
}
return;
}
void function_device(void* parameter)
{
rtgui_view_t *view;
extern rtgui_view_t* device_view_create(rtgui_workbench_t* workbench);
view = device_view_create(workbench);
if (view != RT_NULL)
{
rtgui_view_show(view, RT_FALSE);
}
return;
}
void function_player(void* parameter)
{
rtgui_view_show(home_view, RT_FALSE);
return;
}
void function_action(void* parameter)
{
rt_kprintf("item action!\n");
return;
}
struct list_item function_list[] =
{
{"选择电台", RT_NULL, function_action, RT_NULL},
{"更新电台", RT_NULL, function_action, RT_NULL},
{"播放文件", RT_NULL, function_filelist, RT_NULL},
{"设备信息", RT_NULL, function_device, RT_NULL},
{"返回播放器", RT_NULL, function_player, RT_NULL},
};
static rt_bool_t home_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
if (event->type == RTGUI_EVENT_PAINT)
{
struct rtgui_dc* dc;
struct rtgui_rect rect;
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL) return RT_FALSE;
rtgui_widget_get_rect(widget, &rect);
/* draw background */
background = rtgui_image_create_from_file("hdc",
"/resource/bg.hdc", RT_FALSE);
if (background != RT_NULL)
{
rtgui_image_blit(background, dc, &rect);
rtgui_image_destroy(background);
background = RT_NULL;
}
else
{
rtgui_dc_fill_rect(dc, &rect);
}
/* draw playing information */
rect.x1 = 10; rect.y1 = 260;
rect.x2 = 25; rect.y2 = 285;
if (prev != RT_NULL) rtgui_image_blit(prev, dc, &rect);
if (next != RT_NULL)
{
rect.x2 = 230; rect.x1 = rect.x2 - 25;
rtgui_image_blit(next, dc, &rect);
}
rect.x1 = 35; rect.y1 = 260;
rect.x2 = 205; rect.y2 = 285;
rtgui_dc_fill_rect(dc, &rect);
rtgui_dc_end_drawing(dc);
return RT_FALSE;
}
else if (event->type == RTGUI_EVENT_KBD)
{
struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
if (ekbd->type == RTGUI_KEYDOWN)
{
switch (ekbd->key)
{
case RTGUIK_RIGHT:
case RTGUIK_LEFT:
break;
case RTGUIK_DOWN:
rtgui_view_show(function_view, RT_FALSE);
break;
}
}
return RT_FALSE;
}
return rtgui_view_event_handler(widget, event);
}
rt_bool_t today_workbench_event_handler(rtgui_widget_t *widget, rtgui_event_t *event)
{
if (event->type == RTGUI_EVENT_KBD)
{
struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
if ((ekbd->type == RTGUI_KEYUP) && ekbd->key == RTGUIK_HOME)
{
/* active home view */
if (workbench->current_view != home_view)
{
rtgui_view_show(home_view, RT_FALSE);
return RT_FALSE;
}
}
}
return rtgui_workbench_event_handler(widget, event);
}
static void player_entry(void* parameter)
{
rt_mq_t mq;
rtgui_rect_t rect;
mq = rt_mq_create("qPlayer", 256, 4, RT_IPC_FLAG_FIFO);
rtgui_thread_register(rt_thread_self(), mq);
next = rtgui_image_create_from_mem("xpm", (rt_uint8_t*)next_xpm,
sizeof(next_xpm));
prev = rtgui_image_create_from_mem("xpm", (rt_uint8_t*)prev_xpm,
sizeof(prev_xpm));
workbench = rtgui_workbench_create("main", "workbench");
if (workbench == RT_NULL) return;
rtgui_widget_set_event_handler(RTGUI_WIDGET(workbench), today_workbench_event_handler);
/* add home view */
home_view = rtgui_view_create("Home");
rtgui_widget_set_event_handler(RTGUI_WIDGET(home_view), home_view_event_handler);
rtgui_workbench_add_view(workbench, home_view);
/* this view can be focused */
RTGUI_WIDGET(home_view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
/* set widget focus */
rtgui_widget_focus(RTGUI_WIDGET(home_view));
rtgui_view_show(home_view, RT_FALSE);
/* add function view */
rtgui_widget_get_rect(RTGUI_WIDGET(workbench), &rect);
function_view = (struct rtgui_view*)list_view_create(function_list,
sizeof(function_list)/sizeof(struct list_item),
&rect);
rtgui_workbench_add_view(workbench, function_view);
rtgui_workbench_event_loop(workbench);
rtgui_thread_deregister(rt_thread_self());
rt_mq_delete(mq);
}
enum PLAYER_MODE
{
PLAYER_SINGLE,
PLAYER_FILE,
PLAYER_RADIO,
};
enum PLAYER_REQUEST_TYPE
{
PLAYER_REQUEST_PLAY_SINGLE_FILE,
PLAYER_REQUEST_PLAY_LIST,
PLAYER_REQUEST_STOP,
PLAYER_REQUEST_NEXT,
PLAYER_REQUEST_PREV,
};
struct player_request
{
enum PLAYER_REQUEST_TYPE type;
char fn[64];
};
static rt_mq_t player_thread_mq;
void player_play_list(const char** list)
{
}
void player_play_file(const char* fn)
{
struct player_request request;
request.type = PLAYER_REQUEST_PLAY_SINGLE_FILE;
strncpy(request.fn, fn, sizeof(request.fn));
/* send to message queue */
rt_mq_send(player_thread_mq, (void*)&request, sizeof(struct player_request));
}
void player_stop()
{
}
void player_next()
{
}
void player_prev()
{
}
void player_thread(void* parameter)
{
rt_err_t result;
struct player_request request;
while(1)
{
/* get request from message queue */
result = rt_mq_recv(player_thread_mq, (void*)&request,
sizeof(struct player_request), RT_WAITING_FOREVER);
if (result == RT_EOK)
{
switch (request.type)
{
case PLAYER_REQUEST_PLAY_SINGLE_FILE:
if ((strstr(request.fn, ".mp3") != RT_NULL) ||
(strstr(request.fn, ".MP3") != RT_NULL))
{
mp3(request.fn);
}
else if ((strstr(request.fn, ".wav") != RT_NULL) ||
(strstr(request.fn, ".WAV") != RT_NULL))
{
wav(request.fn);
}
break;
}
}
}
}
void player_init()
{
rt_thread_t tid;
tid = rt_thread_create("player",
player_entry, RT_NULL,
2048, RTGUI_APP_THREAD_PRIORITY, RTGUI_APP_THREAD_TIMESLICE);
if (tid != RT_NULL) rt_thread_startup(tid);
/* create player thread */
player_thread_mq = rt_mq_create("player", sizeof(struct player_request),
8, RT_IPC_FLAG_FIFO);
RT_ASSERT(player_thread_mq != RT_NULL);
tid = rt_thread_create("pthread", player_thread, RT_NULL,
2048, RTGUI_APP_THREAD_PRIORITY, RTGUI_APP_THREAD_TIMESLICE);
if (tid != RT_NULL) rt_thread_startup(tid);
}
#include "player_bg.h"
#include "player_ui.h"
#include <string.h>
static rt_mq_t player_thread_mq;
rt_bool_t is_playing = RT_FALSE;
rt_bool_t player_is_playing()
{
return is_playing;
}
void player_play_file(const char* fn)
{
struct player_request request;
request.type = PLAYER_REQUEST_PLAY_SINGLE_FILE;
strncpy(request.fn, fn, sizeof(request.fn));
/* send to message queue */
rt_mq_send(player_thread_mq, (void*)&request, sizeof(struct player_request));
}
void player_stop()
{
is_playing = RT_FALSE;
}
void player_thread(void* parameter)
{
rt_err_t result;
struct player_request request;
while(1)
{
/* get request from message queue */
result = rt_mq_recv(player_thread_mq, (void*)&request,
sizeof(struct player_request), RT_WAITING_FOREVER);
if (result == RT_EOK)
{
switch (request.type)
{
case PLAYER_REQUEST_PLAY_SINGLE_FILE:
if ((strstr(request.fn, ".mp3") != RT_NULL) ||
(strstr(request.fn, ".MP3") != RT_NULL))
{
is_playing = RT_TRUE;
player_notify_play();
/* get music tag information */
mp3(request.fn);
player_notify_stop();
is_playing = RT_FALSE;
}
else if ((strstr(request.fn, ".wav") != RT_NULL) ||
(strstr(request.fn, ".WAV") != RT_NULL))
{
is_playing = RT_TRUE;
wav(request.fn);
is_playing = RT_FALSE;
}
break;
}
}
}
}
void player_init()
{
rt_thread_t tid;
/* create player thread */
player_thread_mq = rt_mq_create("player", sizeof(struct player_request),
8, RT_IPC_FLAG_FIFO);
RT_ASSERT(player_thread_mq != RT_NULL);
tid = rt_thread_create("ply_bg", player_thread, RT_NULL,
2048, 20, 5);
if (tid != RT_NULL) rt_thread_startup(tid);
player_ui_init();
}
#ifndef __PLAYER_BG_H__
#define __PLAYER_BG_H__
#include <rtthread.h>
enum PLAYER_REQUEST_TYPE
{
PLAYER_REQUEST_PLAY_SINGLE_FILE,
PLAYER_REQUEST_PLAY_LIST,
PLAYER_REQUEST_STOP,
PLAYER_REQUEST_NEXT,
PLAYER_REQUEST_PREV,
};
struct player_request
{
enum PLAYER_REQUEST_TYPE type;
char fn[64];
};
rt_bool_t player_is_playing(void);
void player_stop(void);
void player_play_list(const char** list);
void player_play_file(const char* fn);
#endif
#include <rtgui/rtgui.h>
#include <rtgui/image.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/view.h>
#include <rtgui/widgets/workbench.h>
#include <string.h>
#include <dfs_posix.h>
#include "player_ui.h"
#include "player_bg.h"
#include "play_list.h"
#include "listview.h"
#include "filelist.h"
#include "play.hdh"
#include "stop.hdh"
static rtgui_image_t *background = RT_NULL;
static struct rtgui_view* function_view;
static struct rtgui_view* home_view;
static struct rtgui_workbench* workbench;
static rtgui_timer_t* info_timer;
static rt_thread_t player_ui_tid = RT_NULL;
static enum PLAYER_MODE player_mode = PLAYER_STOP;
static enum PLAYER_STEP next_step = PLAYER_STEP_STOP;
static struct tag_info tinfo;
void player_set_position(rt_uint32_t position)
{
tinfo.position = position / (tinfo.bit_rate / 8);
}
void info_timer_timeout(rtgui_timer_t* timer, void* parameter)
{
struct rtgui_dc* dc;
rtgui_color_t saved;
dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(home_view));
if (dc == RT_NULL) return ;
saved = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(home_view));
RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(home_view)) = RTGUI_RGB(206, 231, 255);
rtgui_dc_draw_hline(dc, 14, 14 + (tinfo.position * 212)/ tinfo.duration,
75);
RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(home_view)) = saved;
rtgui_dc_end_drawing(dc);
}
rt_uint32_t read_line(int fd, char* line, rt_uint32_t line_size)
{
char *pos, *next;
rt_uint32_t length;
length = read(fd, line, line_size);
if (length > 0)
{
pos = strstr(line, "\r\n");
if (pos == RT_NULL)
{
pos = strstr(line, "\n");
next = pos ++;
}
else next = pos + 2;
if (pos != RT_NULL)
{
*pos = '\0';
/* move back */
lseek(fd, -(length - (next - line)), SEEK_CUR);
length = pos - line;
}
else length = 0;
}
rt_kprintf("line %s\n", line);
return length;
}
static void player_update_tag_info(struct rtgui_dc* dc)
{
rtgui_rect_t rect;
char line[32];
rtgui_color_t saved;
saved = rtgui_dc_get_color(dc);
rtgui_dc_set_color(dc, black);
rect.x1 = 0; rect.y1 = 0;
rect.x2 = 240; rect.y2 = 65;
/* draw background */
background = rtgui_image_create_from_file("hdc",
"/resource/bg.hdc", RT_FALSE);
if (background != RT_NULL)
{
rtgui_image_blit(background, dc, &rect);
rtgui_image_destroy(background);
background = RT_NULL;
}
else
{
rtgui_dc_fill_rect(dc, &rect);
}
/* draw playing information */
rect.x1 = 28; rect.y1 = 12;
rect.x2 = 220; rect.y2 = rect.y1 + 16;
if (player_mode == PLAYER_STOP)
{
rt_snprintf(line, sizeof(line),
"网络收音机");
rtgui_dc_draw_text(dc, line, &rect);
}
else
rtgui_dc_draw_text(dc, tinfo.title, &rect);
rect.x1 = 28; rect.y1 = 39;
rect.x2 = 220; rect.y2 = 59;
if (player_mode == PLAYER_STOP)
{
rt_snprintf(line, sizeof(line),
"radio.rt-thread.org");
rtgui_dc_draw_text(dc, line, &rect);
}
else
rtgui_dc_draw_text(dc, tinfo.artist, &rect);
if ((tinfo.duration != 0) && player_mode != PLAYER_STOP)
{
rect.x1 = rect.x2 - 64;
rt_snprintf(line, sizeof(line), "%02d:%02d:%02d",
tinfo.duration / 360, tinfo.duration / 60, tinfo.duration % 60);
rtgui_dc_draw_text(dc, line, &rect);
}
rtgui_dc_set_color(dc, saved);
}
void play_mp3_file(const char* fn)
{
struct rtgui_dc* dc;
/* get music tag information */
mp3_get_info(fn, &tinfo);
if (tinfo.title[0] == '\0')
rt_snprintf(tinfo.title, sizeof(tinfo.title), "<未知名音乐>");
/* set player mode */
player_mode = PLAYER_PLAY_FILE;
dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(home_view));
if (dc != RT_NULL)
{
rtgui_rect_t play_rect;
rtgui_image_t *button;
/* update tag information */
player_update_tag_info(dc);
/* update play button */
button = rtgui_image_create_from_mem("hdc",
play_hdh, sizeof(play_hdh), RT_FALSE);
play_rect.x1 = 32; play_rect.y1 = 92;
play_rect.x2 = 61; play_rect.y2 = 114;
rtgui_image_blit(button, dc, &play_rect);
rtgui_image_destroy(button);
rtgui_dc_end_drawing(dc);
}
rtgui_view_show(home_view, RT_FALSE);
rt_kprintf("play file: %s\n", fn);
player_play_file(fn);
}
void function_filelist(void* parameter)
{
rtgui_rect_t rect;
filelist_view_t *view;
rtgui_widget_get_rect(RTGUI_WIDGET(workbench), &rect);
view = filelist_view_create(workbench, "/", "*.*", &rect);
if (view != RT_NULL)
{
if (rtgui_view_show(RTGUI_VIEW(view), RT_TRUE) == RTGUI_MODAL_OK)
{
char fn[64];
/* get open file */
rt_snprintf(fn, 64, "%s/%s", view->current_directory,
view->items[view->current_item].name);
if (strstr(view->items[view->current_item].name , ".mp3") != RT_NULL ||
strstr(view->items[view->current_item].name , ".MP3") != RT_NULL)
{
/* clear old play list */
play_list_clear();
play_list_append(fn);
player_mode = PLAYER_PLAY_FILE;
next_step = PLAYER_STEP_STOP;
play_mp3_file(play_list_start());
}
else if (strstr(view->items[view->current_item].name , ".m3u") != RT_NULL ||
strstr(view->items[view->current_item].name , ".M3U") != RT_NULL)
{
/* read all of music filename to a list */
int fd;
char line[64];
fd = open(fn, O_RDONLY, 0);
if (fd >= 0)
{
rt_uint32_t length;
length = read_line(fd, line, sizeof(line));
if (strcmp(line, "#EXTM3U") == 0)
{
/* clear old play list */
play_list_clear();
do
{
length = read_line(fd, line, sizeof(line));
if (length > 0)
{
if (line[0] != '/')
{
rt_snprintf(fn, sizeof(fn),
"%s/%s", view->current_directory, line);
play_list_append(fn);
}
else play_list_append(line);
}
} while (length > 0);
}
close(fd);
if (play_list_items() > 0)
{
player_mode = PLAYER_PLAY_FILE;
next_step = PLAYER_STEP_NEXT;
play_mp3_file(play_list_start());
}
}
}
else if (strstr(view->items[view->current_item].name , ".wav") != RT_NULL ||
strstr(view->items[view->current_item].name , ".WAV") != RT_NULL)
{
}
}
/* destroy view */
filelist_view_destroy(view);
}
return;
}
void function_device(void* parameter)
{
rtgui_view_t *view;
extern rtgui_view_t* device_view_create(rtgui_workbench_t* workbench);
view = device_view_create(workbench);
if (view != RT_NULL)
{
rtgui_view_show(view, RT_FALSE);
}
return;
}
void function_player(void* parameter)
{
rtgui_view_show(home_view, RT_FALSE);
return;
}
void function_action(void* parameter)
{
rt_kprintf("item action!\n");
return;
}
struct list_item function_list[] =
{
{"选择电台", RT_NULL, function_action, RT_NULL},
{"更新电台", RT_NULL, function_action, RT_NULL},
{"播放文件", RT_NULL, function_filelist, RT_NULL},
{"设备信息", RT_NULL, function_device, RT_NULL},
{"选项设置", RT_NULL, function_action, RT_NULL},
{"返回播放器", RT_NULL, function_player, RT_NULL},
};
static rt_bool_t home_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
if (event->type == RTGUI_EVENT_PAINT)
{
struct rtgui_dc* dc;
struct rtgui_rect rect;
rtgui_color_t saved;
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL) return RT_FALSE;
rtgui_widget_get_rect(widget, &rect);
saved = RTGUI_WIDGET_FOREGROUND(widget);
/* draw background */
background = rtgui_image_create_from_file("hdc",
"/resource/bg.hdc", RT_FALSE);
if (background != RT_NULL)
{
rtgui_image_t *play;
rtgui_rect_t play_rect;
rtgui_image_blit(background, dc, &rect);
rtgui_image_destroy(background);
background = RT_NULL;
if (player_mode == PLAYER_STOP)
play = rtgui_image_create_from_mem("hdc",
stop_hdh, sizeof(stop_hdh), RT_FALSE);
else
play = rtgui_image_create_from_mem("hdc",
play_hdh, sizeof(play_hdh), RT_FALSE);
play_rect.x1 = 32; play_rect.y1 = 92;
play_rect.x2 = 61; play_rect.y2 = 114;
rtgui_image_blit(play, dc, &play_rect);
rtgui_image_destroy(play);
}
else
{
rtgui_dc_fill_rect(dc, &rect);
}
/* draw playing information */
rtgui_dc_set_color(dc, black);
{
char line[32];
rect.x1 = 28; rect.y1 = 12;
rect.x2 = 220; rect.y2 = rect.y1 + 16;
if (player_mode == PLAYER_STOP)
{
rt_snprintf(line, sizeof(line),
"网络收音机");
rtgui_dc_draw_text(dc, line, &rect);
}
else
rtgui_dc_draw_text(dc, tinfo.title, &rect);
rect.x1 = 28; rect.y1 = 39;
rect.x2 = 220; rect.y2 = 59;
if (player_mode == PLAYER_STOP)
{
rt_snprintf(line, sizeof(line),
"radio.rt-thread.org");
rtgui_dc_draw_text(dc, line, &rect);
}
else
rtgui_dc_draw_text(dc, tinfo.artist, &rect);
if (tinfo.duration != 0)
{
rect.x1 = rect.x2 - 64;
rt_snprintf(line, sizeof(line), "%02d:%02d:%02d",
tinfo.duration / 360, tinfo.duration / 60, tinfo.duration % 60);
rtgui_dc_draw_text(dc, line, &rect);
}
}
RTGUI_WIDGET_FOREGROUND(widget) = RTGUI_RGB(82, 199, 16);
rtgui_dc_draw_hline(dc, 14, 226, 75);
RTGUI_WIDGET_FOREGROUND(widget) = saved;
if (player_mode == PLAYER_PLAY_FILE)
{
char line[32];
rt_uint32_t index;
struct play_item* item;
rect.x1 = 20; rect.y1 = 150;
rect.x2 = 220; rect.y2 = 168;
for (index = 0; index < play_list_items() && index < 8; index ++)
{
item = play_list_item(index);
rtgui_dc_draw_text(dc, item->title, &rect);
rect.x1 = rect.x2 - 64;
rt_snprintf(line, sizeof(line), "%02d:%02d:%02d",
item->duration / 360,
item->duration / 60,
item->duration % 60);
rtgui_dc_draw_text(dc, line, &rect);
/* move to next item */
rect.x1 = 20;
rect.y1 += 18; rect.y2 += 18;
}
}
rtgui_dc_end_drawing(dc);
return RT_FALSE;
}
else if (event->type == RTGUI_EVENT_KBD)
{
struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
if (ekbd->type == RTGUI_KEYDOWN)
{
switch (ekbd->key)
{
case RTGUIK_RIGHT:
if (player_mode == PLAYER_PLAY_FILE && play_list_items() > 0)
{
player_stop();
next_step = PLAYER_STEP_NEXT;
}
break;
case RTGUIK_LEFT:
if (player_mode == PLAYER_PLAY_FILE && play_list_items() > 0)
{
player_stop();
next_step = PLAYER_STEP_PREV;
}
break;
case RTGUIK_RETURN:
if (player_is_playing() == RT_TRUE)
{
player_stop();
next_step = PLAYER_STEP_STOP;
}
else
{
if ((player_mode == PLAYER_STOP) && (play_list_items() > 0))
{
next_step = PLAYER_STEP_NEXT;
play_mp3_file(play_list_current_item());
}
}
break;
case RTGUIK_DOWN:
rtgui_view_show(function_view, RT_FALSE);
break;
}
}
return RT_FALSE;
}
else if (event->type == RTGUI_EVENT_COMMAND)
{
struct rtgui_event_command* ecmd = (struct rtgui_event_command*)event;
switch (ecmd->command_id)
{
case PLAYER_REQUEST_PLAY_SINGLE_FILE:
case PLAYER_REQUEST_PLAY_LIST:
rtgui_timer_start(info_timer);
break;
case PLAYER_REQUEST_STOP:
{
rtgui_timer_stop(info_timer);
switch (next_step)
{
case PLAYER_STEP_STOP:
{
struct rtgui_dc* dc;
rtgui_color_t saved;
rtgui_image_t *button;
rtgui_rect_t play_rect;
player_mode = PLAYER_STOP;
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL) return RT_FALSE;
player_update_tag_info(dc);
RTGUI_WIDGET_FOREGROUND(widget) = RTGUI_RGB(82, 199, 16);
rtgui_dc_draw_hline(dc, 14, 226, 75);
/* update play button */
button = rtgui_image_create_from_mem("hdc",
stop_hdh, sizeof(stop_hdh), RT_FALSE);
play_rect.x1 = 32; play_rect.y1 = 92;
play_rect.x2 = 61; play_rect.y2 = 114;
rtgui_image_blit(button, dc, &play_rect);
rtgui_image_destroy(button);
RTGUI_WIDGET_FOREGROUND(widget) = saved;
rtgui_dc_end_drawing(dc);
}
break;
case PLAYER_STEP_NEXT:
if (play_list_is_end() == RT_TRUE)
{
struct rtgui_dc* dc;
rtgui_color_t saved;
rtgui_image_t *button;
rtgui_rect_t play_rect;
/* set stat */
next_step = PLAYER_STEP_STOP;
player_mode = PLAYER_STOP;
/* update UI */
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL) return RT_FALSE;
player_update_tag_info(dc);
RTGUI_WIDGET_FOREGROUND(widget) = RTGUI_RGB(82, 199, 16);
rtgui_dc_draw_hline(dc, 14, 226, 75);
/* update play button */
button = rtgui_image_create_from_mem("hdc",
stop_hdh, sizeof(stop_hdh), RT_FALSE);
play_rect.x1 = 32; play_rect.y1 = 92;
play_rect.x2 = 61; play_rect.y2 = 114;
rtgui_image_blit(button, dc, &play_rect);
rtgui_image_destroy(button);
RTGUI_WIDGET_FOREGROUND(widget) = saved;
rtgui_dc_end_drawing(dc);
}
else
{
play_mp3_file(play_list_next());
next_step = PLAYER_STEP_NEXT;
}
break;
case PLAYER_STEP_PREV:
play_mp3_file(play_list_prev());
next_step = PLAYER_STEP_NEXT;
break;
};
}
break;
default:
break;
}
return RT_FALSE;
}
return rtgui_view_event_handler(widget, event);
}
rt_bool_t player_workbench_event_handler(rtgui_widget_t *widget, rtgui_event_t *event)
{
if (event->type == RTGUI_EVENT_KBD)
{
struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
if ((ekbd->type == RTGUI_KEYUP) && ekbd->key == RTGUIK_HOME)
{
/* active home view */
if (workbench->current_view != home_view)
{
rtgui_view_show(home_view, RT_FALSE);
return RT_FALSE;
}
}
}
return rtgui_workbench_event_handler(widget, event);
}
static void player_entry(void* parameter)
{
rt_mq_t mq;
rtgui_rect_t rect;
mq = rt_mq_create("ply_ui", 256, 4, RT_IPC_FLAG_FIFO);
rtgui_thread_register(rt_thread_self(), mq);
/* create information timer */
info_timer = rtgui_timer_create(RT_TICK_PER_SECOND,
RT_TIMER_FLAG_PERIODIC,
info_timer_timeout, RT_NULL);
workbench = rtgui_workbench_create("main", "workbench");
if (workbench == RT_NULL) return;
rtgui_widget_set_event_handler(RTGUI_WIDGET(workbench), player_workbench_event_handler);
/* add home view */
home_view = rtgui_view_create("Home");
rtgui_widget_set_event_handler(RTGUI_WIDGET(home_view), home_view_event_handler);
rtgui_workbench_add_view(workbench, home_view);
/* this view can be focused */
RTGUI_WIDGET(home_view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
/* set widget focus */
rtgui_widget_focus(RTGUI_WIDGET(home_view));
rtgui_view_show(home_view, RT_FALSE);
/* add function view */
rtgui_widget_get_rect(RTGUI_WIDGET(workbench), &rect);
function_view = (struct rtgui_view*)list_view_create(function_list,
sizeof(function_list)/sizeof(struct list_item),
&rect);
rtgui_workbench_add_view(workbench, function_view);
rtgui_workbench_event_loop(workbench);
rtgui_thread_deregister(rt_thread_self());
rt_mq_delete(mq);
}
void player_notify_play(void)
{
struct rtgui_event_command ecmd;
RTGUI_EVENT_COMMAND_INIT(&ecmd);
ecmd.type = RTGUI_CMD_USER_INT;
ecmd.command_id = PLAYER_REQUEST_PLAY_SINGLE_FILE;
rtgui_thread_send(player_ui_tid, &ecmd.parent, sizeof(ecmd));
}
void player_notify_stop()
{
struct rtgui_event_command ecmd;
RTGUI_EVENT_COMMAND_INIT(&ecmd);
ecmd.type = RTGUI_CMD_USER_INT;
ecmd.command_id = PLAYER_REQUEST_STOP;
rtgui_thread_send(player_ui_tid, &ecmd.parent, sizeof(ecmd));
}
void player_ui_init()
{
player_ui_tid = rt_thread_create("ply_ui", player_entry, RT_NULL,
4096, 25, 5);
if (player_ui_tid != RT_NULL)
rt_thread_startup(player_ui_tid);
}
#ifndef __PLAYER_H__
#define __PLAYER_H__
#include <rtthread.h>
/* music tag information structure */
struct tag_info
{
char title [40]; /* music title */
char artist[40]; /* music artist */
rt_uint32_t duration; /* music total duration (second) */
rt_uint32_t position; /* music current position (second) */
rt_uint32_t bit_rate; /* bit rate */
rt_uint32_t sampling; /* sampling */
rt_uint32_t data_start; /* start position of data */
};
enum PLAYER_CMD
{
PLAYER_CMD_START,
PLAYER_CMD_STOP
};
enum PLAYER_MODE
{
PLAYER_STOP,
PLAYER_PLAY_FILE,
PLAYER_PLAY_RADIO,
};
enum PLAYER_STEP
{
PLAYER_STEP_STOP,
PLAYER_STEP_PREV,
PLAYER_STEP_NEXT,
};
void player_ui_init(void);
void player_notify_play(void);
void player_notify_stop(void);
void player_set_position(rt_uint32_t position);
#endif
此差异已折叠。
......@@ -24,7 +24,6 @@ File 1,1,<.\stm32f10x_it.c><stm32f10x_it.c>
File 1,1,<.\usart.c><usart.c>
File 1,1,<.\sdcard.c><sdcard.c>
File 1,1,<.\rtc.c><rtc.c>
File 1,1,<.\wm8753.c><wm8753.c>
File 1,1,<.\dm9000.c><dm9000.c>
File 1,1,<.\fsmc_nand.c><fsmc_nand.c>
File 1,1,<.\fsmc_sram.c><fsmc_sram.c>
......@@ -36,10 +35,14 @@ File 1,1,<.\wav.c><wav.c>
File 1,1,<.\netbuffer.c><netbuffer.c>
File 1,1,<.\key.c><key.c>
File 1,1,<.\info.c><info.c>
File 1,1,<.\player.c><player.c>
File 1,1,<.\filelist.c><filelist.c>
File 1,1,<.\device_info.c><device_info.c>
File 1,1,<.\listview.c><listview.c>
File 1,1,<.\wm8753.c><wm8753.c>
File 1,1,<.\player_ui.c><player_ui.c>
File 1,1,<.\player_bg.c><player_bg.c>
File 1,1,<.\wm8978.c><wm8978.c>
File 1,1,<.\play_list.c><play_list.c>
File 2,1,<..\..\src\clock.c><clock.c>
File 2,1,<..\..\src\idle.c><idle.c>
File 2,1,<..\..\src\ipc.c><ipc.c>
......
......@@ -21,7 +21,9 @@
/* Includes ------------------------------------------------------------------*/
#include "sdcard.h"
#include <stm32f10x_dma.h>
#include <stm32f10x_sdio.h>
#include <stm32f10x_sdio.h>
#include <rtthread.h>
/** @addtogroup STM32F10x_StdPeriph_Examples
* @{
......@@ -955,12 +957,30 @@ SD_Error SD_ReadBlock(uint32_t addr, uint32_t *readbuff, uint16_t BlockSize)
}
}
else if (DeviceMode == SD_DMA_MODE)
{
{
int cnt = 0;
SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE);
SDIO_DMACmd(ENABLE);
DMA_RxConfiguration(readbuff, BlockSize);
while (DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET)
{}
{
cnt ++;
if (cnt > 10 * 50000)
{
rt_kprintf("DMA flag 0x%08x\n", DMA_GetFlagStatus(DMA2_FLAG_TC4));
/* Clear all DPSM configuration */
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DataLength = 0;
SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_1b;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Disable;
SDIO_DataConfig(&SDIO_DataInitStructure);
SDIO_DMACmd(DISABLE);
errorstatus = SD_ERROR;
break;
}
}
}
return(errorstatus);
}
......@@ -2941,7 +2961,7 @@ static void DMA_RxConfiguration(uint32_t *BufferDST, uint32_t BufferSize)
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel4, &DMA_InitStructure);
/* DMA2 Channel4 enable */
DMA_Cmd(DMA2_Channel4, ENABLE);
}
......@@ -2978,7 +2998,7 @@ static rt_err_t rt_sdcard_init(rt_device_t dev)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
if (rt_sem_init(&sd_lock, "sdlock", 1, RT_IPC_FLAG_FIFO) != RT_EOK)
{
rt_kprintf("init sd lock semaphore failed\n");
......@@ -3009,7 +3029,7 @@ static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_
rt_sem_take(&sd_lock, RT_WAITING_FOREVER);
retry = 3;
/* read all sectors */
/* read all sectors */
for (i = 0; i < size / SECTOR_SIZE; i ++)
{
__retry:
......@@ -3017,9 +3037,10 @@ __retry:
(uint32_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE),
SECTOR_SIZE);
if (status != SD_OK)
{
if (--retry != 0) goto __retry;
break;
{
-- retry;
if (retry != 0) goto __retry;
else break;
}
}
......@@ -3130,4 +3151,3 @@ void rt_hw_sdcard_init()
__return:
rt_kprintf("sdcard init failed\n");
}
......@@ -44,7 +44,7 @@ extern void finsh_set_device(const char* device);
#endif
extern int rt_application_init(void);
extern rt_err_t wm8753_hw_init(void);
extern rt_err_t wm8978_hw_init(void);
#ifdef DEBUG
/*******************************************************************************
* Function Name : assert_failed
......@@ -101,9 +101,13 @@ void rtthread_startup(void)
#endif
/* init scheduler system */
rt_system_scheduler_init();
rt_system_scheduler_init();
#if CODEC_VERSION == 1
wm8753_hw_init();
#elif CODEC_VERSION == 2
wm8978_hw_init();
#endif
/* init hardware serial device */
rt_hw_usart_init();
......
......@@ -18,6 +18,7 @@
/* Includes ------------------------------------------------------------------*/
#include <rtthread.h>
#include <serial.h>
#include "board.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
......@@ -339,6 +340,7 @@ void DMA1_Channel4_IRQHandler(void)
{
}
#if CODEC_VERSION == 1
/*******************************************************************************
* Function Name : DMA1_Channel5_IRQHandler
* Description : This function handles DMA1 Channel 5 interrupt request.
......@@ -365,9 +367,8 @@ void DMA1_Channel5_IRQHandler(void)
/* leave interrupt */
rt_interrupt_leave();
rt_hw_interrupt_thread_switch();
}
#endif
/*******************************************************************************
* Function Name : DMA1_Channel6_IRQHandler
......@@ -394,74 +395,6 @@ void DMA1_Channel6_IRQHandler(void)
#endif
}
/*******************************************************************************
* Function Name : DMA1_Channel7_IRQHandler
* Description : This function handles DMA1 Channel 7 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void DMA1_Channel7_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : ADC1_2_IRQHandler
* Description : This function handles ADC1 and ADC2 global interrupts requests.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void ADC1_2_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : USB_HP_CAN1_TX_IRQHandler
* Description : This function handles USB High Priority or CAN TX interrupts
* requests.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USB_HP_CAN1_TX_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : USB_LP_CAN1_RX0_IRQHandler
* Description : This function handles USB Low Priority or CAN RX0 interrupts
* requests.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : CAN1_RX1_IRQHandler
* Description : This function handles CAN RX1 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void CAN1_RX1_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : CAN1_SCE_IRQHandler
* Description : This function handles CAN SCE interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void CAN1_SCE_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : EXTI9_5_IRQHandler
* Description : This function handles External lines 9 to 5 interrupt request.
......@@ -488,140 +421,7 @@ void EXTI9_5_IRQHandler(void)
#endif
}
/*******************************************************************************
* Function Name : TIM1_BRK_IRQHandler
* Description : This function handles TIM1 Break interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM1_BRK_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : TIM1_UP_IRQHandler
* Description : This function handles TIM1 overflow and update interrupt
* request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM1_UP_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : TIM1_TRG_COM_IRQHandler
* Description : This function handles TIM1 Trigger and commutation interrupts
* requests.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM1_TRG_COM_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : TIM1_CC_IRQHandler
* Description : This function handles TIM1 capture compare interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM1_CC_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : TIM2_IRQHandler
* Description : This function handles TIM2 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM2_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : TIM3_IRQHandler
* Description : This function handles TIM3 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM3_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : TIM4_IRQHandler
* Description : This function handles TIM4 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM4_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : I2C1_EV_IRQHandler
* Description : This function handles I2C1 Event interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C1_EV_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : I2C1_ER_IRQHandler
* Description : This function handles I2C1 Error interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C1_ER_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : I2C2_EV_IRQHandler
* Description : This function handles I2C2 Event interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C2_EV_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : I2C2_ER_IRQHandler
* Description : This function handles I2C2 Error interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C2_ER_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : SPI1_IRQHandler
* Description : This function handles SPI1 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SPI1_IRQHandler(void)
{
}
#if CODEC_VERSION == 1
/*******************************************************************************
* Function Name : SPI2_IRQHandler
* Description : This function handles SPI2 global interrupt request.
......@@ -640,8 +440,8 @@ void SPI2_IRQHandler(void)
/* leave interrupt */
rt_interrupt_leave();
rt_hw_interrupt_thread_switch();
}
#endif
/*******************************************************************************
* Function Name : USART1_IRQHandler
......@@ -836,17 +636,7 @@ void SDIO_IRQHandler(void)
#endif
}
/*******************************************************************************
* Function Name : TIM5_IRQHandler
* Description : This function handles TIM5 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM5_IRQHandler(void)
{
}
#if CODEC_VERSION == 2
/*******************************************************************************
* Function Name : SPI3_IRQHandler
* Description : This function handles SPI3 global interrupt request.
......@@ -856,61 +646,15 @@ void TIM5_IRQHandler(void)
*******************************************************************************/
void SPI3_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : UART4_IRQHandler
* Description : This function handles UART4 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void UART4_IRQHandler(void)
{
}
extern void wm8978_isr(void);
/*******************************************************************************
* Function Name : UART5_IRQHandler
* Description : This function handles UART5 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void UART5_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : TIM6_IRQHandler
* Description : This function handles TIM6 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM6_IRQHandler(void)
{
}
/* enter interrupt */
rt_interrupt_enter();
/*******************************************************************************
* Function Name : TIM7_IRQHandler
* Description : This function handles TIM7 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM7_IRQHandler(void)
{
}
wm8978_isr();
/*******************************************************************************
* Function Name : DMA2_Channel1_IRQHandler
* Description : This function handles DMA2 Channel 1 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void DMA2_Channel1_IRQHandler(void)
{
/* leave interrupt */
rt_interrupt_leave();
}
/*******************************************************************************
......@@ -922,61 +666,21 @@ void DMA2_Channel1_IRQHandler(void)
*******************************************************************************/
void DMA2_Channel2_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : DMA2_Channel3_IRQHandler
* Description : This function handles DMA2 Channel 3 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void DMA2_Channel3_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : DMA2_Channel4_5_IRQHandler
* Description : This function handles DMA2 Channel 4 and DMA2 Channel 5
* interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void DMA2_Channel4_5_IRQHandler(void)
{
}
void DMA2_Channel5_IRQHandler(void)
{
}
void ETH_IRQHandler(void)
{
}
void ETH_WKUP_IRQHandler(void)
{
}
void CAN2_TX_IRQHandler(void)
{
}
extern void wm8978_dma_isr(void);
void CAN2_RX0_IRQHandler(void)
{
}
/* enter interrupt */
rt_interrupt_enter();
void CAN2_RX1_IRQHandler(void)
{
}
if (DMA_GetITStatus(DMA2_IT_TC2))
{
/* clear DMA flag */
DMA_ClearFlag(DMA2_FLAG_TC2 | DMA2_FLAG_TE2);
void CAN2_SCE_IRQHandler(void)
{
}
/* transmission complete, invoke serial dma tx isr */
wm8978_dma_isr();
}
void OTG_FS_IRQHandler(void)
{
/* leave interrupt */
rt_interrupt_leave();
}
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
#endif
#include <rthw.h>
#include <rtthread.h>
#include "stm32f10x.h"
/*
* WM8978 Driver
*/
/* WM8978 register definitions */
#define WM8978_DAC 0x01
#define WM8978_ADC 0x02
#define WM8978_PCM 0x03
#define WM8978_HIFI 0x04
#define WM8978_IOCTL 0x05
#define WM8978_SRATE1 0x06
#define WM8978_SRATE2 0x07
#define WM8978_LDAC 0x08
#define WM8978_RDAC 0x09
#define WM8978_BASS 0x0a
#define WM8978_TREBLE 0x0b
#define WM8978_ALC1 0x0c
#define WM8978_ALC2 0x0d
#define WM8978_ALC3 0x0e
#define WM8978_NGATE 0x0f
#define WM8978_LADC 0x10
#define WM8978_RADC 0x11
#define WM8978_ADCTL1 0x12
#define WM8978_3D 0x13
#define WM8978_PWR1 0x14
#define WM8978_PWR2 0x15
#define WM8978_PWR3 0x16
#define WM8978_PWR4 0x17
#define WM8978_ID 0x18
#define WM8978_INTPOL 0x19
#define WM8978_INTEN 0x1a
#define WM8978_GPIO1 0x1b
#define WM8978_GPIO2 0x1c
#define WM8978_RESET 0x1f
#define WM8978_RECMIX1 0x20
#define WM8978_RECMIX2 0x21
#define WM8978_LOUTM1 0x22
#define WM8978_LOUTM2 0x23
#define WM8978_ROUTM1 0x24
#define WM8978_ROUTM2 0x25
#define WM8978_MOUTM1 0x26
#define WM8978_MOUTM2 0x27
#define WM8978_LOUT1V 0x28
#define WM8978_ROUT1V 0x29
#define WM8978_LOUT2V 0x2a
#define WM8978_ROUT2V 0x2b
#define WM8978_MOUTV 0x2c
#define WM8978_OUTCTL 0x2d
#define WM8978_ADCIN 0x2e
#define WM8978_INCTL1 0x2f
#define WM8978_INCTL2 0x30
#define WM8978_LINVOL 0x31
#define WM8978_RINVOL 0x32
#define WM8978_MICBIAS 0x33
#define WM8978_CLOCK 0x34
#define WM8978_PLL1CTL1 0x35
#define WM8978_PLL1CTL2 0x36
#define WM8978_PLL1CTL3 0x37
#define WM8978_PLL1CTL4 0x38
#define WM8978_PLL2CTL1 0x39
#define WM8978_PLL2CTL2 0x3a
#define WM8978_PLL2CTL3 0x3b
#define WM8978_PLL2CTL4 0x3c
#define WM8978_BIASCTL 0x3d
#define WM8978_ADCTL2 0x3f
/*
SCLK PB7
SDIN PB8
CSB PB9
*/
#define wm_sclk_0 GPIO_ResetBits(GPIOB,GPIO_Pin_7)
#define wm_sclk_1 GPIO_SetBits(GPIOB,GPIO_Pin_7)
#define wm_sdin_0 GPIO_ResetBits(GPIOB,GPIO_Pin_8)
#define wm_sdin_1 GPIO_SetBits(GPIOB,GPIO_Pin_8)
#define wm_csb_0 GPIO_ResetBits(GPIOB,GPIO_Pin_9)
#define wm_csb_1 GPIO_SetBits(GPIOB,GPIO_Pin_9)
#define DATA_NODE_MAX 5
/* data node for Tx Mode */
struct wm8978_data_node
{
rt_uint16_t *data_ptr;
rt_size_t data_size;
};
struct wm8978_device
{
/* inherit from rt_device */
struct rt_device parent;
/* pcm data list */
struct wm8978_data_node data_list[DATA_NODE_MAX];
rt_uint16_t read_index, put_index;
/* transmitted offset of current data node */
rt_size_t offset;
};
struct wm8978_device wm8978;
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* SPI3 IRQ Channel configuration */
NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* DMA1 IRQ Channel configuration */
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* configure GPIO B 7, 8, 9 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
/* configure GPIO B 3, 5 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* configure GPIO A15 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Disable the JTAG interface and enable the SWJ interface */
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
}
#define SPI3_DR_Address 0x40003C0C
static void DMA_Configuration(rt_uint32_t addr, rt_size_t size)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA2 Channel2 configuration ----------------------------------------------*/
DMA_Cmd(DMA2_Channel2, DISABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SPI3_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)addr;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = size;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel2, &DMA_InitStructure);
/* Enable SPI3 DMA Tx request */
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);
DMA_ITConfig(DMA2_Channel2, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Channel2, ENABLE);
}
static void I2S_Configuration(void)
{
I2S_InitTypeDef I2S_InitStructure;
/* I2S peripheral configuration */
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_High;// I2S_CPOL_Low
/* I2S2 Master Transmitter to I2S3 Slave Receiver communication -----------*/
/* I2S2 configuration */
I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveTx;
I2S_Init(SPI3, &I2S_InitStructure);
}
void wm_send(rt_uint16_t s_data)
{
u8 i;
wm_csb_0;
wm_sclk_0;
for (i=0;i<16;i++)
{
if (s_data & 0x8000)
{
wm_sdin_1;
}
else
{
wm_sdin_0;
}
wm_sclk_1;
s_data <<= 1;
wm_sclk_0;
}
wm_csb_1;
}
static rt_err_t wm8978_init (rt_device_t dev)
{
wm_send(0<<9 | 0xFF); // reset
/* POWER manager */
wm_send(1<<9 | (0<<8) | (0<<7) | (0<<6) | (0<<5) | (1<<4) | (1<<3) | (1<<2) | 3 );
wm_send(2<<9 | (1<<8) | (1<<7) | (1<<5) | (1<<4) );
wm_send(3<<9 | (0<<8) | (0<<7) | (1<<6) | (1<<5) | (1<<3) | (1<<2) | (1<<1) | 1 );
/* IIS DAC test */
wm_send(4<<9 | 0 | (2<<3) );//IIS 16BIT
#if 0
wm_send(6<<9 | (3<<5) | (3<<2)| 1);//0: slave 1: master | (3<<5) | (3<<2)
wm_send(43<<9 | (1<<4) );//INVROUT2
#else
// 12.288/3 = 4.096M 4.096M / 8 = 512K == (16K *2??)*16?
wm_send(6<<9 | (3<<5) | (3<<2)| 1); //16K MCLK/3/8
wm_send(6<<9 | (0<<5) | (3<<2)| 1); //48K MCLK/1/8
#endif
return RT_EOK;
}
#include <finsh.h>
#if 0
void vol(int v)
{
wm_send(40<<9 | 0<<8 | 1<<7 | v);
wm_send(41<<9 | 1<<8 | 1<<7 | v);
wm_send(42<<9 | 0<<8 | 1<<7 | v);
wm_send(43<<9 | 1<<8 | 1<<7 | v);
}
FINSH_FUNCTION_EXPORT(vol, set volume)
#endif
static rt_err_t wm8978_open(rt_device_t dev, rt_uint16_t oflag)
{
/* enable I2S */
I2S_Cmd(SPI3, ENABLE);
return RT_EOK;
}
static rt_err_t wm8978_close(rt_device_t dev)
{
/* interrupt mode */
if (dev->flag & RT_DEVICE_FLAG_INT_TX)
{
/* Disable the I2S2 */
I2S_Cmd(SPI3, DISABLE);
}
/* remove all data node */
return RT_EOK;
}
static rt_err_t wm8978_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
/* rate control */
return RT_EOK;
}
static rt_size_t wm8978_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
struct wm8978_device* device;
struct wm8978_data_node* node;
rt_uint32_t level;
rt_uint16_t next_index;
device = (struct wm8978_device*)dev;
RT_ASSERT(device != RT_NULL);
next_index = device->put_index + 1;
if (next_index >= DATA_NODE_MAX) next_index = 0;
/* check data_list full */
if (next_index == device->read_index)
{
rt_set_errno(-RT_EFULL);
return 0;
}
level = rt_hw_interrupt_disable();
node = &device->data_list[device->put_index];
device->put_index = next_index;
// rt_kprintf("+\n");
/* set node attribute */
node->data_ptr = (rt_uint16_t*)buffer;
node->data_size = size >> 1; /* size is byte unit, convert to half word unit */
next_index = device->read_index + 1;
if (next_index >= DATA_NODE_MAX) next_index = 0;
/* check data list whether is empty */
if (next_index == device->put_index)
{
if (dev->flag & RT_DEVICE_FLAG_INT_TX)
{
device->offset = 0;
/* enable I2S interrupt */
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE);
}
else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
{
DMA_Configuration((rt_uint32_t)node->data_ptr, node->data_size);
}
}
rt_hw_interrupt_enable(level);
return size;
}
rt_err_t wm8978_hw_init(void)
{
rt_device_t dev;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
NVIC_Configuration();
GPIO_Configuration();
I2S_Configuration();
dev = (rt_device_t)&wm8978;
dev->type = RT_Device_Class_Unknown;
dev->rx_indicate = RT_NULL;
dev->tx_complete = RT_NULL;
dev->init = wm8978_init;
dev->open = wm8978_open;
dev->close = wm8978_close;
dev->read = RT_NULL;
dev->write = wm8978_write;
dev->control = wm8978_control;
dev->private = RT_NULL;
/* set read_index and put index to 0 */
wm8978.read_index = 0;
wm8978.put_index = 0;
wm_sclk_0;
wm_sclk_1;
wm_sclk_0;
wm_sdin_0;
wm_sdin_1;
wm_sdin_0;
wm_csb_1;
wm_csb_0;
wm_csb_1;
/* register the device */
return rt_device_register(&wm8978.parent, "snd",
RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX);
}
void wm8978_isr()
{
struct wm8978_data_node* node;
node = &wm8978.data_list[wm8978.read_index]; /* get current data node */
if (SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_TXE) == SET)
{
SPI_I2S_SendData(SPI3, node->data_ptr[wm8978.offset++]);
}
if (wm8978.offset == node->data_size)
{
/* move to next node */
rt_uint16_t next_index;
next_index = wm8978.read_index + 1;
if (next_index >= DATA_NODE_MAX) next_index = 0;
/* notify transmitted complete. */
if (wm8978.parent.tx_complete != RT_NULL)
{
wm8978.parent.tx_complete (&wm8978.parent, wm8978.data_list[wm8978.read_index].data_ptr);
rt_kprintf("-\n");
}
wm8978.offset = 0;
wm8978.read_index = next_index;
if (next_index == wm8978.put_index)
{
/* no data on the list, disable I2S interrupt */
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, DISABLE);
rt_kprintf("*\n");
}
}
}
void wm8978_dma_isr()
{
/* switch to next buffer */
rt_uint16_t next_index;
void* data_ptr;
next_index = wm8978.read_index + 1;
if (next_index >= DATA_NODE_MAX) next_index = 0;
/* save current data pointer */
data_ptr = wm8978.data_list[wm8978.read_index].data_ptr;
wm8978.read_index = next_index;
if (next_index != wm8978.put_index)
{
/* enable next dma request */
DMA_Configuration((rt_uint32_t)wm8978.data_list[wm8978.read_index].data_ptr,
wm8978.data_list[wm8978.read_index].data_size);
}
else
{
rt_kprintf("*\n");
}
/* notify transmitted complete. */
if (wm8978.parent.tx_complete != RT_NULL)
{
wm8978.parent.tx_complete (&wm8978.parent, data_ptr);
// rt_kprintf("-\n");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册