|
准备工具:格式工厂,Windows录音机,SD卡(小于等于2G),音箱
首先,选一首MP3,用格式工场转化成WAV格式。可以看到转化后的文件变得很大,因为WAV就是AD采样值加个文件头,所以数据量巨大,这也是MP3压缩算法流行的原因。
将转化后的WAV文件用Windows录音机打开编辑,采样率设置为8Khz,16位立体声,然后写入到SD卡里,恩,这里提一句,可以写入任意数量的歌曲,我写的程序是播放完卡里所有的WAV文件。当然别放其他文件例如图片文件进去捣乱啊,文件系统里没有识别其他文件的过程,开学了,要忙活了就没做。
硬件搭建:
SD卡的部分就不说了,前面博客提过了。说说WM8731吧,我们管这个芯片叫霸气闪耀,因为它里面有24位的ADC和DAC,而且是CD音质,听起来感觉不错的。驱动芯片首先当然是看手册,50多页的手册,还凑合。我们关心的只有几个部分:DAC,控制接口,数据接口。先来看看它的框图:
由于我们是将SD卡里的数字数据读出来,写入DAC,所以我们不管ADC的部分,注意这三个红圈,上面的红圈是控制接口,是用户控制8731工作模式写命令的接口,接口采用I2C协议;右边的红圈是耳机输出,默认是静音,坑爹啊,这个设置一样要改,不然没声的。下面的红圈是数据接口,我们的数据数据从这里串行输入。好,明确了这些概念后,我们来看8731的控制寄存器。如下图:
8731一共11个寄存器,保守起见,每个都设置一遍最好。这里还有个坑爹的地方,开始看手册不细,被耍的够惨。这个复位寄存器,当我们写入复位命令后,8731就将所有的控制寄存器先写入0.本来一上电,8731会自己复位,并且自动配置寄存器的值,但是这个软件复位的效果和上电复位的不一样,上电复位后控制寄存器里的值不是0,而是一些默认的设置,软件复位后,所有的都是零了。
扯一扯I2C协议
I2C协议点对点传输还是比较简单的,不用考虑仲裁等乱七八糟的事。8731的I2C协议如下图所示:
注意8731的设备号是可变的,而DE2-115上已经将其固定为0X34了,最后一位是读写选择,8731是只写的,不能读,所以地址加上R/W位就是0X34。发送完8位设备地址加读写位后,接下来发送16位数据,前7位是8731内部寄存器的地址,后9位是寄存器配置的数据。每一个命令封装成24位的一帧,每次发送命令都要完整的发送:起始标志,设备号,读写位,7位寄存器地址,9位数据。
命令接口说完了,接下来是数据接口,这个有些麻烦。我们要写入串行的数据,就要自己写并转串的接口。数据写入有四种模式:左对齐,I2S,和右对齐,DSP模式。继续看手册:
左对齐模式,也是我采用的模式,数据在DACLRCK的下降沿后BCLK的第一个上升沿就有效。
I2S模式,数据会延迟一个BCLK才有效。
右对齐模式,就是数据最高位和DACLRCK的下降沿对齐。
不在以DACLRCK的高低电平来区分左右声道了。数据时连续的。
我们采用左对齐方式,用硬件去实现高速的并转串接口。在检测到DACLRCK的下降沿或者上升沿后,使能模16计数器,当计数器计满时,使计数使能无效。在计数过程中,将并行数据移位输出到DACDAT引脚上。模块代码如下:
/*
*this file is use to connect the dule port ram and 8731
*when the up edge of lrck,read from the ram,and when the down edge of lrck,increace the ram address
*when the up edge of bclk,shift the 64 regs,and the msb is out to the 8731 dacda pin
*/
module data_64
(
input clk,
input rst_n,
input [31:0]q,
input bclk,
input lrck,
output q_out,
output rd_en,
output [16:0]ram_addr
);
//**************************************************************************************************
//up and down edge of lrck detect module
reg latch0;
reg latch1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
latch0<=1'b0;
latch1<=1'b0;
end
else
begin
latch0<=lrck;
latch1<=latch0;
end
end
wire up_detect;
wire down_detect;
assign up_detect=latch0 && (~latch1);
assign rd_en=up_detect;
assign down_detect=latch1 && (~latch0);
//****************************************************************************************************************
//up and down edge of bclk detect module
reg latch2;
reg latch3;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
latch2<=1'b0;
latch3<=1'b0;
end
else
begin
latch2<=bclk;
latch3<=latch2;
end
end
wire up;
wire down;
assign up=latch2 && (~latch3);
assign down=latch3 && (~latch2);
//************************************************************************************************************
//latch up_detect module,delay the up_detect for one clk for the data read from ram
reg write;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
write<=1'b0;
else
write<=up_detect;
end
//*************************************************************************************************************
//64 reg module
reg[31:0]data;
wire[23:0]gnd;
wire shift;
assign gnd=24'b0;
assign shift=1'b0;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
data<=32'b0;
else if(write)
data<=q[31:0];
else if(up && en)
data<={data[30:0],shift};
end
assign q_out=data[31];
//************************************************************************************************************
//ram addr generater
reg[16:0]addr;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
addr<=17'b0;
else if((addr==17'b11111_1111_1111_1111) && (down_detect ||up_detect))
addr<=15'b0;
else if(down_detect ||up_detect)
addr<=addr+1'b1;
end
assign ram_addr=addr;
//************************************************************************************************************
//counter enable module
reg en;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
en<=1'b0;
else if(cnt_over)
en<=1'b0;
else if(up_detect || down_detect)
en<=1'b1;
end
//*************************************************************************************************************
//16 bits counter,count the BCLK posedge
reg[7:0]cnt;
wire cnt_over;
wire not_over;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt<=8'b0;
// cnt_over<=1'b0;
end
else if((cnt==8'd16) && en )
begin
cnt<=8'b0;
// cnt_over<=1'b1;
end
else if(en && up)
begin
cnt<=cnt+1'b1;
// cnt_over<=1'b0;
end
end
assign cnt_over=(cnt==8'd16)?1'b1:1'b0;
assign not_over=~cnt_over;
endmodule
本来这个模块式用来从ram里读数据的,后来发现ram只能缓存很小的数据,就改用FIFO了,但是地址线没有去掉。
建立一个FIFO来缓冲数据,数据位宽为32位,1024*32bit大小,其实用256*32bit也可以的。利用FIFO里面的WRUSEW的最高位(就是FIFO一半满时的标记),来决定是否写入数据。如图:
写请求是软件发出的,宽度不确定,那么我们写一个模块来检测它的上升沿,在上升沿出现时,产生一个clk宽度的信号,来向fifo写入数据。clk为100M。
module wr_req_detect
(
input clk,
input rst_n,
input wr_req,
output wr_req_detect
);
reg latch0;
reg latch1;
reg latch2;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
latch0<=1'b0;
latch1<=1'b0;
latch2<=1'b0;
end
else
begin
latch0<=wr_req;
latch1<=latch0;
latch2<=latch1;
end
end
assign wr_req_detect=latch0 && (~latch1);
endmodule
如果是assign wr_req_detect=latch0 && (~latch2);那么就是产生了2个clk宽度的写请求信号,具体原理不讲了,自己体会吧。
NIOS系统的搭建就是在SD卡系统的基础上多了几个PIO,分别是I2C的两条线,还有FIFO的数据线和写请求线。注意一个问题,FIFO的读写时钟全部同步到系统时钟,即用全局时钟来控制全局,利用使能时钟解决跨时钟域问题,用一个100M的时钟去检测几M的时钟的上升下降沿自然是没有问题的。
硬件就这么多可说的。
软件部分,FAT32文件系统,读取WAV跟读取BMP没有什么区别,只是后缀名不同而已,注意文件名不要搞太长,控制在8个字节内。直接贴代码了,我C语言是自学的,写的很菜,因为当时学汇编学的太狠了,导致写出来的C程序跟汇编一个味道,冗长,但是易懂,一看就明白。
头文件:
/*
* sopc.h
*
* Created on: 2011-8-10
* Author: Fu-xiaoliang
*/
#ifndef SOPC_H_
#define SOPC_H_
#include "system.h"
#define _LED
typedef struct
{
unsigned long int DATA;
unsigned long int DIRECTION;
unsigned long int INTERRUPT_MASK;
unsigned long int EDGE_CAPTURE;
}PIO_STR;
#ifdef _LED
#define SD_DA ((PIO_STR *)SD_DA_BASE)
#define SD_CMD ((PIO_STR *)SD_CMD_BASE)
#define SD_CS ((PIO_STR *)SD_CS_N_BASE)
#define SD_CLK ((PIO_STR *)SD_CLK_BASE)
#define WR_ADDR ((PIO_STR *)WR_ADDR_BASE)
#define WR_CLK ((PIO_STR *)WR_CLK_BASE)
#define WR_DAT ((PIO_STR *)WR_DAT_BASE)
#define WR_EN ((PIO_STR *)WR_EN_BASE)
#define WR_USE_W ((PIO_STR *)WR_USE_W_BASE)
#define RD_EN ((PIO_STR *)RD_EN_BASE)
#define I2C_DAT ((PIO_STR *)I2C_DAT_BASE)
#define I2C_SCLK ((PIO_STR *)I2C_SCLK_BASE)
#define LED ((PIO_STR *)LED_BASE)
#define _SD
#endif
#ifdef _SD
#define data (SD_DA->DATA)
#define cmd (SD_CMD->DATA)
#define cs (SD_CS->DATA)
#define clk (SD_CLK->DATA)
#endif
#define uc unsigned char
#endif /* SOPC_H_ */
主函数:
view sourceprint?
001
/*
002
* "Hello World" example.
003
*
004
* This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
005
* the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example
006
* designs. It runs with or without the MicroC/OS-II RTOS and requires a STDOUT
007
* device in your system's hardware.
008
* The memory footprint of this hosted application is ~69 kbytes by default
009
* using the standard reference design.
010
*
011
* For a reduced footprint version of this template, and an explanation of how
012
* to reduce the memory footprint for a given application, see the
013
* "small_hello_world" template.
014
*
015
*/
016
017
#include <stdio.h>
018
#include "alt_types.h" // alt_u32
019
#include <unistd.h>
020
#include "sys/alt_irq.h"
021
#include "D:\FPGA-PROJECT\myself\SD_WAV_DE2\software\DE2_SD_WAV\inc\sopc.h"
022
023
//****************************************************************************************************************************
024
//static variable
025
uc Resp_buffer[16]={0};
026
uc data_buffer[512]={0};
027
uc data_buffer1[512]={0};
028
unsigned long int FDT_DIRECT[16]={0};
029
uc not_finish=0;
030
031
unsigned long int DBR_ADDR=0;
032
unsigned long int FAT1_ADDR=0;
033
unsigned long int FAT2_ADDR=0;
034
unsigned long int FDT_ADDR=0;
035
unsigned long int CLUS_ADDR=0;
036
unsigned long int CLUS_CURRENT=0;//current clus number
037
unsigned long int CLUS_LEN=0;//clus lenth
038
unsigned long int CLUS_NEXT=0;
039
unsigned long int RAM_ADDR=0;
040
041
struct
042
{
043
union
044
{
045
unsigned char CSD[16];
046
unsigned char CSD1[16];
047
}CSD_DA;
048
union
049
{
050
unsigned char buf1[16];
051
unsigned char buf2[16];
052
053
}CID_DA;
054
}REG;
055
056
struct
057
{
058
uc RIFF_ID[4];
059
unsigned long long int WAV_SIZE;
060
uc RIFF_TYPE[4];
061
}WAV_RIFF_CHUNK;
062
063
struct
064
{
065
uc FORMAT_ID[4];
066
unsigned long long int FORMAT_SIZE;
067
unsigned long int FORMAT_TAG;
068
unsigned long int CHANNELS;
069
unsigned long long int SAMPLES_PER_SEC;
070
unsigned long long int BYTE_PER_SEC;
071
unsigned long int BLOCK_ALIGN;
072
unsigned long int BITS_PER_SAMPLE;
073
unsigned long int ADDITION;
074
}WAV_FORMAT_CHUNK;
075
076
struct
077
{
078
uc FACT_ID[4];
079
unsigned long long int FACT_SIZE;
080
unsigned long long int FACT_DATA;
081
}WAV_FACT_CHUNK;
082
083
struct
084
{
085
uc DATA_ID[4];
086
unsigned long long int DATA_SIZE;
087
088
}WAV_DATA_CHUNK;
089
090
//*********************************************************************************************************************************************
091
//function define and statement
092
uc send_byte(uc sda)
093
{
094
uc cnt=0,rda=0;
095
SD_CLK->DATA=1;
096
SD_CMD->DIRECTION=1;
097
for(cnt=0;cnt<8;cnt++)
098
{
099
SD_CLK->DATA=0;
100
SD_CMD->DATA=0;
101
if(sda & 0x80)
102
SD_CMD->DATA=1;
103
usleep(50);
104
sda=sda<<1;
105
rda=rda<<1;
106
SD_CLK->DATA=1;
107
if(SD_DA->DATA)
108
{
109
110
rda=rda|0x01;
111
}
112
113
}
114
115
SD_CLK->DATA=1;
116
return rda;
117
}
118
uc send_byte_fast(uc sda)
119
{
120
uc cnt=0,rda=0;
121
SD_CLK->DATA=1;
122
SD_CMD->DIRECTION=1;
123
for(cnt=0;cnt<8;cnt++)
124
{
125
SD_CLK->DATA=0;
126
SD_CMD->DATA=0;
127
if(sda & 0x80)
128
SD_CMD->DATA=1;
129
// usleep(70);
130
sda=sda<<1;
131
rda=rda<<1;
132
SD_CLK->DATA=1;
133
if(SD_DA->DATA)
134
{
135
136
rda=rda|0x01;
137
}
138
}
139
SD_CLK->DATA=1;
140
return rda;
141
}
142
uc i2c_send_3byte(uc x,uc y,uc z)
143
{
144
uc i=0;uc a=0;
145
I2C_SCLK->DATA=0;
146
I2C_DAT->DIRECTION=1;
147
I2C_DAT->DATA=1;
148
I2C_SCLK->DATA=1;//initial I2C clk and data line
149
usleep(10);
150
I2C_DAT->DATA=0;//start transfer
151
usleep(10);
152
I2C_SCLK->DATA=0;
153
usleep(10);
154
for(i=0;i<8;i++)//send first byte
155
{
156
usleep(10);
157
I2C_DAT->DATA=(x & 0x80)?1:0;
158
I2C_SCLK->DATA=1;
159
x=x<<1;
160
usleep(10);
161
I2C_SCLK->DATA=0;
162
}
163
I2C_DAT->DIRECTION=0;
164
I2C_SCLK->DATA=1;
165
usleep(10);
166
a=I2C_DAT->DATA;
167
if(a==0)
168
{
169
printf("slave replay first byte!\n");
170
}
171
else
172
printf("slave no replay !\n");
173
174
I2C_DAT->DIRECTION=1;
175
I2C_SCLK->DATA=0;
176
usleep(10);
177
for(i=0;i<8;i++)//send second byte
178
{
179
I2C_DAT->DATA=(y & 0x80)?1:0;
180
usleep(10);
181
I2C_SCLK->DATA=1;
182
y=y<<1;
183
usleep(10);
184
I2C_SCLK->DATA=0;
185
}
186
I2C_DAT->DIRECTION=0;
187
I2C_SCLK->DATA=1;
188
usleep(10);
189
a=I2C_DAT->DATA;
190
if(a==0)
191
{
192
printf("slave replay second byte!\n");
193
}
194
else
195
printf("slave no replay !\n");
196
197
I2C_DAT->DIRECTION=1;
198
I2C_SCLK->DATA=0;
199
usleep(10);
200
for(i=0;i<8;i++)//send third byte
201
{
202
I2C_DAT->DATA=(z & 0x80)?1:0;
203
usleep(10);
204
I2C_SCLK->DATA=1;
205
z=z<<1;
206
usleep(10);
207
I2C_SCLK->DATA=0;
208
}
209
I2C_DAT->DIRECTION=0;
210
I2C_SCLK->DATA=1;
211
usleep(10);
212
a=I2C_DAT->DATA;
213
if(a==0)
214
{
215
printf("slave replay third byte!\n");
216
}
217
else
218
printf("slave no replay !\n");
219
220
I2C_DAT->DIRECTION=1;
221
I2C_SCLK->DATA=0;
222
I2C_DAT->DATA=0;
223
I2C_SCLK->DATA=1;
224
usleep(10);
225
I2C_DAT->DATA=1;//form the stop bit
226
227
return 0;
228
}
229
230
uc wav_init()
231
{
232
uc i=0;
233
for(i=0;i<4;i++)
234
{
235
WAV_RIFF_CHUNK.RIFF_ID=data_buffer1;
236
WAV_RIFF_CHUNK.RIFF_TYPE=data_buffer1[i+8];
237
}
238
WAV_RIFF_CHUNK. WAV_SIZE=data_buffer1[4]|(data_buffer1[5]<<8)|(data_buffer1[6]<<16)|(data_buffer1[24]);
239
240
for(i=0;i<4;i++)
241
{
242
WAV_FORMAT_CHUNK.FORMAT_ID=data_buffer1[i+12];
243
}
244
WAV_FORMAT_CHUNK.FORMAT_SIZE=data_buffer1[16]|(data_buffer1[17]<<8)|(data_buffer1[18]<<16)|(data_buffer1[19]<<24);
245
WAV_FORMAT_CHUNK.FORMAT_TAG=data_buffer1[20]|(data_buffer1[21]<<8);
246
WAV_FORMAT_CHUNK.CHANNELS=data_buffer1[22]|(data_buffer1[23]<<8);
247
WAV_FORMAT_CHUNK.SAMPLES_PER_SEC=data_buffer1[24]|(data_buffer1[25]<<8)|(data_buffer1[26]<<16)|(data_buffer1[27]<<24);
248
WAV_FORMAT_CHUNK.BYTE_PER_SEC=data_buffer1[28]|(data_buffer1[29]<<8)|(data_buffer1[30]<<16)|(data_buffer1[31]<<24);
249
WAV_FORMAT_CHUNK.BLOCK_ALIGN=data_buffer1[32]|(data_buffer1[33]<<8);
250
WAV_FORMAT_CHUNK.BITS_PER_SAMPLE=data_buffer1[34]|(data_buffer1[35]<<8);
251
WAV_FORMAT_CHUNK.ADDITION=data_buffer1[36]|(data_buffer1[37]<<8);
252
253
for(i=0;i<4;i++)
254
{
255
WAV_FACT_CHUNK.FACT_ID=data_buffer1[i+38];
256
}
257
WAV_FACT_CHUNK.FACT_SIZE=data_buffer1[42]|(data_buffer1[43]<<8)|(data_buffer1[44]<<16)|(data_buffer1[45]<<24);
258
WAV_FACT_CHUNK.FACT_DATA=data_buffer1[46]|(data_buffer1[47]<<8)|(data_buffer1[48]<<16)|(data_buffer1[49]<<24);
259
260
for(i=0;i<4;i++)
261
{
262
WAV_DATA_CHUNK.DATA_ID=data_buffer1[i+50];
263
}
264
WAV_DATA_CHUNK.DATA_SIZE=data_buffer1[54]|(data_buffer1[55]<<8)|(data_buffer1[56]<<16)|(data_buffer1[57]<<24);
265
266
return 0;
267
}
268
269
uc wm8731_init()
270
{
271
i2c_send_3byte(0x34,0x1e,0x00);//reset 8731
272
i2c_send_3byte(0x34,0x12,0x00);//inactive
273
i2c_send_3byte(0x34,0x00,0x17);//left volume
274
i2c_send_3byte(0x34,0x02,0x17);//right volume
275
i2c_send_3byte(0x34,0x04,0x7b);//left headphone
276
i2c_send_3byte(0x34,0x06,0x7b);//right headphone
277
i2c_send_3byte(0x34,0x08,0x3d);//select DAC channel
278
i2c_send_3byte(0x34,0x0a,0x00);//do not quiet
279
i2c_send_3byte(0x34,0x0c,0x00);//power on the device
280
i2c_send_3byte(0x34,0x0e,0x41);//master ,16bit and left mode
281
i2c_send_3byte(0x34,0x10,0x0c);//sampling clock control set normal mode,8KHZ
282
i2c_send_3byte(0x34,0x12,0x01);//active
283
i2c_send_3byte(0x34,0x12,0x00);//inactive
284
return 0;
285
}
286
287
uc write_CMD0(void)
288
{
289
uc a=0,i=0;
290
SD_CS->DATA=1;
291
send_byte(0xff);
292
SD_CS->DATA=0;
293
send_byte(0x40);
294
send_byte(0x00);
295
send_byte(0x00);
296
send_byte(0x00);
297
send_byte(0x00);
298
send_byte(0x95);
299
do
300
{
301
a=send_byte(0xff);
302
i++;
303
if(i==200)
304
{
305
printf("CMD0 no replay\n");
306
break;
307
}
308
}while(a!=0x01);
309
return a;
310
}
311
uc send_CMD(uc number,uc x,uc y,uc z,uc w, uc u,uc v,uc r)
312
{
313
uc b=0,i=0;
314
SD_CS->DATA=1;
315
send_byte_fast(0xff);
316
SD_CS->DATA=0;
317
send_byte_fast(x);
318
send_byte_fast(y);
319
send_byte_fast(z);
320
send_byte_fast(w);
321
send_byte_fast(u);
322
send_byte_fast(v);
323
do
324
{
325
b=send_byte_fast(0xff);
326
i++;
327
if(i==200)
328
{
329
printf("CMD%d no replay\n",number);
330
break;
331
}
332
}while(b!=r);
333
return b;
334
}
335
uc write_CMD1(void)
336
{
337
uc a=0,i=0;
338
SD_CS->DATA=1;
339
send_byte(0xff);
340
SD_CS->DATA=0;
341
send_byte(0x41);
342
send_byte(0x00);
343
send_byte(0x00);
344
send_byte(0x00);
345
send_byte(0x00);
346
send_byte(0xff);
347
do
348
{
349
a=send_byte(0xff);
350
i++;
351
if(i==200)
352
{
353
printf("CMD1 no replay\n");
354
break;
355
}
356
}while(a!=0x00);
357
return a;
358
}
359
360
uc sd_init(void)
361
{
362
uc i=0;
363
uc a,b;
364
SD_CS->DATA=1;
365
for(i=0;i<100;i++)
366
{
367
send_byte(0xff);
368
}
369
usleep(250);
370
i=0;
371
do
372
{
373
b=write_CMD0();
374
i++;
375
if(i==100)
376
break;
377
}while(b!=0x01);
378
printf("CMD0 replay %x\n",b);
379
i=0;
380
do
381
{
382
a=write_CMD1();
383
i++;
384
if(i==100)
385
break;
386
}while(a!=0x00);
387
printf("CMD1 replay %x\n",a);
388
i=0;
389
do
390
{
391
a=send_CMD(16,0x50,0x00,0x00,0x02,0x00,0xff,0x00);
392
i++;
393
if(i==10)
394
break;
395
}while(a!=0x00);
396
printf("CMD16 replay %x\n",a);
397
i=0;
398
do
399
{
400
a=send_CMD(59,0x7b,0x00,0x00,0x00,0x00,0xff,0x00);
401
i++;
402
if(i==10)
403
break;
404
}while(a!=0x00);
405
printf("CMD59 replay %x\n",a);
406
i=0;
407
do
408
{
409
a=send_CMD(9,0x49,0x00,0x00,0x00,0x00,0xff,0x00);
410
i++;
411
if(i==10)
412
break;
413
}while(a!=0x00);
414
printf("CMD9 replay %x\n",a);
415
if(a==0x00)
416
{
417
uc tem=0;
418
do
419
{
420
printf("tem is %x\n",tem);
421
tem=send_byte(0xff);
422
}while(tem!=0xfe);
423
printf("tem is %x\n",tem);
424
if(tem==0xfe)
425
{
426
printf("0xfe is received\n");
427
for(i=0;i<16;i++)
428
{
429
Resp_buffer=send_byte(0xff);
430
}
431
send_byte(0xff);
432
send_byte(0xff);
433
SD_CS->DATA=1;
434
send_byte(0xff);
435
}
436
}
437
for(i=0;i<16;i++)
438
{
439
printf("CSD is %x\n",Resp_buffer);
440
REG.CSD_DA.CSD=Resp_buffer;
441
}
442
return 0;
443
}
444
445
void ISR_neg(void *context,unsigned long id)
446
{
447
/* i=0;
448
do{
449
a=send_CMD(17,0x51,(((CLUS_ADDR+512*k)&0xff000000)>>24),(((CLUS_ADDR+512*k)&0x00ff0000)>>16),(((CLUS_ADDR+512*k)&0x0000ff00)>>8),((CLUS_ADDR+512*k)&0xff),0xff,0x00);
450
i++;
451
if(i==100)
452
break;
453
}while(a!=0x00);
454
if(a==0x00)
455
{
456
uc temp=0;
457
int j=0;;
458
do{
459
temp=send_byte_fast(0xff);
460
j++;
461
}while(temp!=0xfe && j<100);*/
462
int j;
463
for(j=0;j<509;j=j+4)
464
{
465
466
data_buffer1[j]=send_byte_fast(0xff);
467
data_buffer1[j+1]=send_byte_fast(0xff);
468
data_buffer1[j+2]=send_byte_fast(0xff);
469
data_buffer1[j+3]=send_byte_fast(0xff);
470
if((data_buffer1[0]==0x52) && (data_buffer1[1]=0x49) && (data_buffer1[2]==0x46) && (data_buffer1[3]==0x46))
471
{
472
if(j>=58)
473
{
474
WR_EN->DATA=0;
475
WR_DAT->DATA=data_buffer1[j]|(data_buffer1[j+1]<<8)|(data_buffer1[j+2]<<16)|(data_buffer1[j+3]<<24);
476
WR_EN->DATA=1;
477
}
478
}
479
else
480
{
481
WR_EN->DATA=0;
482
WR_DAT->DATA=data_buffer1[j]|(data_buffer1[j+1]<<8)|(data_buffer1[j+2]<<16)|(data_buffer1[j+3]<<24);
483
WR_EN->DATA=1;
484
}
485
}
486
}
487
488
int init_neg(void)
489
{
490
WR_USE_W->INTERRUPT_MASK=1;
491
return alt_irq_register(WR_USE_W_IRQ,NULL,ISR_neg);
492
}
493
494
//*********************************************************************************************************************************************
495
//the main function
496
int main()
497
{
498
int i=0,j=0,k=0,cnt=0;
499
unsigned int index=0;
500
uc a;
501
for(i=0;i<8;i++)
502
{
503
LED->DATA=1<<i;
504
usleep(500000);
505
}
506
SD_CS->DATA=1;
507
SD_CMD->DIRECTION=1;
508
SD_CMD->DATA=1;
509
510
sd_init();
511
wm8731_init();
512
i=0;
513
do
514
{
515
a=send_CMD(10,0x4a,0x00,0x00,0x00,0x00,0xff,0x00);
516
i++;
517
if(i==10)
518
break;
519
}while(a!=0x00);
520
printf("CMD10 replay %x\n",a);
521
if(a==0x00)
522
{
523
uc tem=0;
524
do
525
{
526
printf("tem is %x\n",tem);
527
tem=send_byte(0xff);
528
}while(tem!=0xfe);
529
printf("tem is %x\n",tem);
530
if(tem==0xfe)
531
{
532
printf("0xfe is received\n");
533
for(i=0;i<16;i++)
534
{
535
536
Resp_buffer=send_byte(0xff);
537
}
538
send_byte(0xff);
539
send_byte(0xff);
540
SD_CS->DATA=1;
541
send_byte(0xff);
542
}
543
for(i=0;i<16;i++)
544
{
545
printf("CID is %x\n",Resp_buffer);
546
REG.CID_DA.buf1=Resp_buffer;
547
}
548
}
549
550
i=0;
551
do
552
{
553
a=send_CMD(17,0x51,0x00,0x00,0x00,0x00,0xff,0x00);
554
i++;
555
if(i==100)
556
break;
557
}while(a!=0x00);
558
printf("CMD17 replay %x\n",a);
559
if(a==0x00)
560
{
561
uc temp=0;
562
int j=0;;
563
do{
564
printf("temp is %x\n",temp);
565
temp=send_byte_fast(0xff);
566
j++;
567
}while(temp!=0xfe && j<100);
568
printf("temp is %x\n",temp);
569
if(temp==0xfe)
570
{
571
printf("0xfe is received\n");
572
printf("block 0 data is followed\n");
573
for(j=0;j<512;j++)
574
{
575
576
data_buffer[j]=send_byte_fast(0xff);
577
}
578
i=0;
579
for(j=0;j<512;j++)
580
{
581
printf("%x ",data_buffer[j]);
582
i++;
583
if(i==16)
584
{
585
i=0;
586
printf("\n");
587
}
588
}
589
}
590
}
591
if((data_buffer[0]==0x00)||(data_buffer[0]!=0xeb)||(data_buffer[0]!=0xe9))//judge the weather first block is DBR or not
592
{
593
594
DBR_ADDR=(((DBR_ADDR|data_buffer[457])<<24)|((DBR_ADDR|data_buffer[456])<<16)|((DBR_ADDR|data_buffer[455])<<8)|data_buffer[454])*512;
595
i=0;
596
do{
597
a=send_CMD(17,0x51,((DBR_ADDR&0xff000000)>>24),((DBR_ADDR&0x00ff0000)>>16),((DBR_ADDR&0x0000ff00)>>8),(DBR_ADDR&0xff),0xff,0x00);
598
i++;
599
if(i==100)
600
break;
601
}while(a!=0x00);
602
if(a==0x00)
603
{
604
uc temp=0;
605
int j=0;;
606
do{
607
printf("temp is %x\n",temp);
608
temp=send_byte_fast(0xff);
609
j++;
610
}while(temp!=0xfe && j<100);
611
printf("temp is %x\n",temp);
612
if(temp==0xfe)
613
{
614
printf("0xfe is received\n");
615
printf("DBR data is followed\n");
616
for(j=0;j<512;j++)
617
{
618
619
data_buffer[j]=send_byte_fast(0xff);
620
}
621
i=0;
622
for(j=0;j<512;j++)
623
{
624
printf("%x ",data_buffer[j]);
625
i++;
626
if(i==16)
627
{
628
i=0;
629
printf("\n");
630
}
631
}
632
633
}
634
}
635
}
636
else
637
{
638
DBR_ADDR=0;
639
}
640
FAT1_ADDR=DBR_ADDR+((data_buffer[14]|(data_buffer[15]<<8))*512);
641
FAT2_ADDR=FAT1_ADDR+((data_buffer[36]|(data_buffer[37]<<8))*512);
642
FDT_ADDR=FAT2_ADDR+((data_buffer[36]|(data_buffer[37]<<8))*512);
643
CLUS_LEN=data_buffer[13]*512;
644
printf("FAT1_ADDR is %lx \n",FAT1_ADDR);
645
printf("FAT2_ADDR is %lx \n",FAT2_ADDR);
646
printf("FDT_ADDR is %lx \n",FDT_ADDR);
647
printf("DBR_ADDR is %lx \n",DBR_ADDR);
648
printf("CLUS_LEN is %lx \n",CLUS_LEN);
649
i=0;
650
do{
651
//read the FDT
652
a=send_CMD(17,0x51,((FDT_ADDR&0xff000000)>>24),((FDT_ADDR&0x00ff0000)>>16),((FDT_ADDR&0x0000ff00)>>8),(FDT_ADDR&0xff),0xff,0x00);
653
i++;
654
if(i==100)
655
break;
656
}while(a!=0x00);
657
if(a==0x00)
658
{
659
uc temp=0;
660
int j=0;
661
do{
662
printf("temp is %x\n",temp);
663
temp=send_byte_fast(0xff);
664
j++;
665
}while(temp!=0xfe && j<100);
666
printf("temp is %x\n",temp);
667
if(temp==0xfe)
668
{
669
printf("0xfe is received\n");
670
printf("FDT data is followed\n");
671
for(j=0;j<512;j++)
672
{
673
data_buffer[j]=send_byte_fast(0xff);
674
}
675
i=0;
676
for(j=0;j<512;j++)
677
{
678
printf("%x ",data_buffer[j]);
679
i++;
680
if(i==16)
681
{
682
i=0;
683
printf("\n");
684
}
685
}
686
}
687
}
688
for(i=0,j=0;i<512;i=i+32)
689
{
690
if((data_buffer[11+i]==0x08)&&(data_buffer!=0xe5))//find the juan biao
691
{
692
printf("juan biao is %d\n",i+11);
693
continue;
694
}
695
else if((data_buffer[11+i]==0x20)&&(data_buffer!=0xe5))//find the file
696
{
697
CLUS_CURRENT=(data_buffer[20+i]<<16)|(data_buffer[21+i]<<24)|(data_buffer[27+i]<<8)|(data_buffer[26+i]);//first clus addr
698
printf("first clus is %ld\n",CLUS_CURRENT);
699
FDT_DIRECT[j]=CLUS_CURRENT;//store the current clus addr
700
j++;
701
continue;
702
}
703
else if(data_buffer==0xe5)
704
continue;
705
else if(data_buffer==0x00)
706
{
707
break;
708
not_finish=0;//no file behind
709
}
710
}
711
i=0;
712
do{
713
//read FAT1
714
a=send_CMD(17,0x51,((FAT1_ADDR&0xff000000)>>24),((FAT1_ADDR&0x00ff0000)>>16),((FAT1_ADDR&0x0000ff00)>>8),(FAT1_ADDR&0xff),0xff,0x00);
715
i++;
716
if(i==100)
717
break;
718
}while(a!=0x00);
719
if(a==0x00)
720
{
721
uc temp=0;
722
int j=0;;
723
do{
724
printf("temp is %x\n",temp);
725
temp=send_byte_fast(0xff);
726
j++;
727
}while(temp!=0xfe && j<100);
728
printf("temp is %x\n",temp);
729
if(temp==0xfe)
730
{
731
printf("0xfe is received\n");
732
printf("FAT1 data is followed\n");
733
for(j=0;j<512;j++)
734
{
735
data_buffer[j]=send_byte_fast(0xff);
736
}
737
i=0;
738
for(j=0;j<512;j++)
739
{
740
printf("%x ",data_buffer[j]);
741
i++;
742
if(i==16)
743
{
744
i=0;
745
printf("\n");
746
}
747
}
748
749
}
750
}
751
CLUS_ADDR=(FDT_DIRECT[0]-2)*CLUS_LEN+FDT_ADDR;//first data clus address
752
CLUS_NEXT=data_buffer[(FDT_DIRECT[0]*4)]|(data_buffer[(FDT_DIRECT[0]*4+1)]<<8)|(data_buffer[(FDT_DIRECT[0]*4+2)]<<16)|(data_buffer[(FDT_DIRECT[0]*4+3)]<<24);
753
// CLUS_ADDR=(CLUS_CURRENT-2)*CLUS_LEN+FDT_ADDR;//first data clus address
754
// CLUS_NEXT=data_buffer[CLUS_CURRENT*4]|(data_buffer[CLUS_CURRENT*4+1]<<8)|(data_buffer[CLUS_CURRENT*4+2]<<16)|(data_buffer[CLUS_CURRENT*4+3]<<24);
755
// printf("CLUS_NEXT is %lx\n",CLUS_NEXT);
756
index=0;
757
cnt=0;
758
do{
759
do{
760
CLUS_ADDR=(FDT_DIRECT[cnt]-2)*CLUS_LEN+FDT_ADDR;//first data clus address
761
FDT_DIRECT[cnt]=CLUS_NEXT;
762
CLUS_NEXT=FDT_DIRECT[cnt]+1;//data_buffer[(FDT_DIRECT[cnt]*4-512*index)]|(data_buffer[(FDT_DIRECT[cnt]*4+1-512*index)]<<8)|(data_buffer[(FDT_DIRECT[cnt]*4+2-512*index)]<<16)|(data_buffer[(FDT_DIRECT[cnt]*4+3-512*index)]<<24);
763
// FDT_DIRECT[cnt]=CLUS_NEXT;
764
/* if((FDT_DIRECT[cnt]*4+3)>=511)
765
{
766
FDT_DIRECT[cnt]=0;
767
index++;
768
i=0;
769
do{
770
//read FAT1 next 512 byte
771
a=send_CMD(17,0x51,(((FAT1_ADDR+512*index)&0xff000000)>>24),(((FAT1_ADDR+512*index)&0x00ff0000)>>16),(((FAT1_ADDR+512*index)&0x0000ff00)>>8),((FAT1_ADDR+512*index)&0xff),0xff,0x00);
772
i++;
773
if(i==100)
774
break;
775
}while(a!=0x00);
776
printf("a is %x\n",a);
777
if(a==0x00)
778
{
779
uc temp=0;
780
int j=0;;
781
do{
782
printf("temp is %x\n",temp);
783
temp=send_byte_fast(0xff);
784
j++;
785
}while(temp!=0xfe && j<100);
786
printf("temp is %x\n",temp);
787
if(temp==0xfe)
788
{
789
printf("0xfe is received\n");
790
printf("FAT1 next 512b data is followed\n");
791
for(j=0;j<512;j++)
792
{
793
data_buffer[j]=send_byte_fast(0xff);
794
}
795
i=0;
796
for(j=0;j<512;j++)
797
{
798
printf("%x ",data_buffer[j]);
799
i++;
800
if(i==16)
801
{
802
i=0;
803
printf("\n");
804
}
805
}
806
807
}
808
}
809
}*/
810
// CLUS_ADDR=(CLUS_CURRENT-2)*CLUS_LEN+FDT_ADDR;
811
// CLUS_CURRENT=CLUS_NEXT;
812
// CLUS_NEXT=data_buffer[CLUS_CURRENT*4]|(data_buffer[CLUS_CURRENT*4+1]<<8)|(data_buffer[CLUS_CURRENT*4+2]<<16)|(data_buffer[CLUS_CURRENT*4+3]<<24);
813
// for(k=0;k<8;k++)//for each clus has 8 512Byte
814
// {
815
k=0;
816
while(!WR_USE_W->DATA)
817
{
818
i=0;
819
do{
820
a=send_CMD(17,0x51,(((CLUS_ADDR+512*k)&0xff000000)>>24),(((CLUS_ADDR+512*k)&0x00ff0000)>>16),(((CLUS_ADDR+512*k)&0x0000ff00)>>8),((CLUS_ADDR+512*k)&0xff),0xff,0x00);
821
i++;
822
if(i==100)
823
break;
824
}while(a!=0x00);
825
// printf("read data a is %x\n",a);
826
if(a==0x00)
827
{
828
uc temp=0;
829
int j=0;
830
do{
831
// printf("temp is %x\n",temp);
832
temp=send_byte_fast(0xff);
833
j++;
834
}while(temp!=0xfe && j<100);
835
// printf("temp is %x\n",temp);
836
if(temp==0xfe)
837
{
838
// printf("0xfe is received\n");
839
// printf("first clus data is followed\n");
840
for(j=0;j<509;j=j+4)
841
{
842
843
data_buffer1[j]=send_byte_fast(0xff);
844
data_buffer1[j+1]=send_byte_fast(0xff);
845
data_buffer1[j+2]=send_byte_fast(0xff);
846
data_buffer1[j+3]=send_byte_fast(0xff);
847
if((data_buffer1[0]==0x52) && (data_buffer1[1]=0x49) && (data_buffer1[2]==0x46) && (data_buffer1[3]==0x46))
848
{
849
if(j>=58)
850
{
851
WR_EN->DATA=0;
852
WR_DAT->DATA=data_buffer1[j]|(data_buffer1[j+1]<<8)|(data_buffer1[j+2]<<16)|(data_buffer1[j+3]<<24);
853
WR_EN->DATA=1;
854
}
855
}
856
else
857
{
858
WR_EN->DATA=0;
859
WR_DAT->DATA=data_buffer1[j]|(data_buffer1[j+1]<<8)|(data_buffer1[j+2]<<16)|(data_buffer1[j+3]<<24);
860
WR_EN->DATA=1;
861
}
862
}
863
/* i=0;
864
for(j=0;j<512;j++)
865
{
866
usleep(10);
867
printf("%x ",data_buffer1[j]);
868
i++;
869
if(i==16)
870
{
871
i=0;
872
printf("\n");
873
}
874
}*/
875
876
}
877
}
878
k++;
879
// if(k==8)
880
// break;
881
}
882
i2c_send_3byte(0x34,0x12,0x01);//active
883
// printf("enable display!\n");
884
// while(WR_USE_W->DATA);
885
while(1)
886
{
887
while(!WR_USE_W->DATA)
888
{
889
i=0;
890
do{
891
a=send_CMD(17,0x51,(((CLUS_ADDR+512*k)&0xff000000)>>24),(((CLUS_ADDR+512*k)&0x00ff0000)>>16),(((CLUS_ADDR+512*k)&0x0000ff00)>>8),((CLUS_ADDR+512*k)&0xff),0xff,0x00);
892
i++;
893
if(i==100)
894
break;
895
}while(a!=0x00);
896
if(a==0x00)
897
{
898
uc temp=0;
899
int j=0;
900
do{
901
// printf("temp is %x\n",temp);
902
temp=send_byte_fast(0xff);
903
j++;
904
}while(temp!=0xfe && j<100);
905
// printf("temp is %x\n",temp);
906
if(temp==0xfe)
907
{
908
// printf("0xfe is received\n");
909
// printf("first clus data is followed\n");
910
for(j=0;j<509;j=j+4)
911
{
912
913
data_buffer1[j]=send_byte_fast(0xff);
914
data_buffer1[j+1]=send_byte_fast(0xff);
915
data_buffer1[j+2]=send_byte_fast(0xff);
916
data_buffer1[j+3]=send_byte_fast(0xff);
917
/* if((data_buffer1[0]==0x52) && (data_buffer1[1]=0x49) && (data_buffer1[2]==0x46) && (data_buffer1[3]==0x46))
918
{
919
if(j>=58)
920
{
921
WR_EN->DATA=0;
922
WR_DAT->DATA=data_buffer1[j]|(data_buffer1[j+1]<<8)|(data_buffer1[j+2]<<16)|(data_buffer1[j+3]<<24);
923
WR_EN->DATA=1;
924
}
925
}*/
926
// else
927
// {
928
WR_EN->DATA=0;
929
WR_DAT->DATA=data_buffer1[j]|(data_buffer1[j+1]<<8)|(data_buffer1[j+2]<<16)|(data_buffer1[j+3]<<24);
930
WR_EN->DATA=1;
931
// }
932
}
933
}
934
}
935
k++;
936
if(k==8)
937
break;
938
}
939
if(k==8)
940
break;
941
}
942
// } //the for loop
943
}while(CLUS_NEXT!=0x0fffffff);
944
cnt++;
945
CLUS_NEXT=data_buffer[(FDT_DIRECT[cnt]*4)]|(data_buffer[(FDT_DIRECT[cnt]*4+1)]<<8)|(data_buffer[(FDT_DIRECT[cnt]*4+2)]<<16)|(data_buffer[(FDT_DIRECT[cnt]*4+3)]<<24);
946
}while(FDT_DIRECT[cnt]!=0);
947
SD_CS->DATA=1;
948
unsigned long int cap;
949
double c;
950
//(c_size+1)*mult*(1<<read_bl_len)
951
cap=((((REG.CSD_DA.CSD[6]&0x03)<<10) | (REG.CSD_DA.CSD[7]<<2) | ((REG.CSD_DA.CSD[8]&0xC0)>>6) + 1))*(1 << ((((REG.CSD_DA.CSD[9]&0x03)<<1) | ((REG.CSD_DA.CSD[10]&0x80)>>7)) + 2))*(1<<(REG.CSD_DA.CSD[5]&0x0f));
952
printf("capacity is %ld MB\n",cap/1048576);
953
printf("read_bl_len is %d B\n",(1<<(REG.CSD_DA.CSD[5]&0x0f)));
954
c=((double)cap/1073741824);
955
printf("capacity is %f GB\n",c);
956
printf("send CMD0!\n");
957
return 0;
958
959
}
有很多没用到的引脚,我没删除,留着扩展用吧,另外我没用中断,虽然生命了函数,但是是用电平检测来做的,担心中断容易出BUG。
采样频率没法再提高了,SD卡读取还是比较慢的,我尝试了32K和48K ,都失败了,放出来的声音简直是闹鬼,不过我同学说,8K的效果也很不错了,一点噪音没有。
播放结束后,手动按复位键重新开始播放,不然会将卡里的数据都用DAC播放出来,呵呵,我没检测文件簇结束标志0X0FFFFFFF,所以它会一直不停的播放下去,我也懒得改了。
我觉得应该有办法将采样频率提高到48K的,因为友晶的范例是用的44.1K的采样频率,我这篇是原创,完全没有按他们的思路来。从电路到程序全是自己搞的。 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|