Hi, i dont have any problem with the r2r. here is my whole code. i used serial communication to see the data printed out. i noticed that the value of wav file are 7F,7F,7F,7F,7F,7F,7F,7F etc. is it because the output has no prefixed? like 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F etc??

by explaining how you managed to get a four-and-half megabyte array into an AVR with thirty-two kilobytes of flash and two kilobytes of SRAM

!

Also I find your non-formatted code very difficult to read but in audio_playback() you appear to be using the automatic variable "i" without initialisation. (assuming "i" is non zero it actually makes things even worse than this apparent 4MB your AVR magically has!).

In case you haven't spotted it your current code reads just one block then tries to play it but using a for() loop that assumes a HUGE block size. You were sort of on the right lines but MMC blocks are just 512 bytes. So to play 4MB or whatever you don't need the "big" for() loop inside the auto_playback() routine. Inside audio_playback() you just want it to run from 0 to 511 and play the single block. But then "outside" is where you need the big loop so:

by explaining how you managed to get a four-and-half megabyte array into an AVR with thirty-two kilobytes of flash and two kilobytes of SRAM

!

i don't that get. what do joey's mean by that?

Also I find your non-formatted code very difficult to read but in audio_playback() you appear to be using the automatic variable "i" without initialisation. (assuming "i" is non zero it actually makes things even worse than this apparent 4MB your AVR magically has!).

First, as I already said above. This routine creates "i" but never gives it an initial value. Local variables, unlike globals are not guaranteed to be 0 when created so "i" may take on any random value (it's created on the stack and will just have the value of whatever happens to be at that stack location from previous execution).

Next you create "i" and "j" as 16 bit variables which means (unsigned) they can only old 0..65535. Yet later on you test j for being less than 4521984. Well as the max value it could possibly hold is 65535 it's always going to be less than that number so the for() loop is infinite.

Next. Even if "j" just runs 0..65535 and even if "i" happened to hold 0, then "block_address[i * 16 + j];" might refer to "block_address[0 * 16 + 65535];" or just "block_address[65535];". How can you have an array of 65536 bytes in the RAM of a micro that only has 2048 bytes of RAM? If "i" happened to hold 255 then it would have been block_address[255 * 16 + 65535]; which is block_address[69615].

Also note that array indices are limited to max positive int. For AVR that is 32767 so [65535] isn't valid anyway.

the lenght of wav audio is 4521984 array. so i think the loop would be like these?

Then you clearly have not understood a word of what has been explained to you above!

Don't you get it? (a) the AVR only has 2048 bytes of RAM so even if you could read multiple blocks and the software used no other RAM at all the best you could hope for would be to read 4 blocks of 512 bytes into the AVR memory at once. Realistically, you need SOME other RAM so at best it's really only three lots of 512 you could hold in RAM at once. (b) it simply doesn't work by reading one 512 byte block then somehow you start playing and the other 8,800+ blocks that make up the 4MB magically follow.

The way to play 4MB as already explained is to read ONE block of 512 bytes to the AVR's RAM. Play that. Then read another block of 512. Play that. Repeat for 8,832 blocks and you will have read/played the entire file.

As it stands your code only reads one block - that's not going to work. I already shows you how your read/play stuff needs to be looped "some_number" of times. I now know that number is 8,832 times in fact.

Somehow, I always thought there was more too extracting the data from a .wav file.

Yes an no. As long as he's used Audacity or something similar to ensure that the file contains 8bit PCM then it pretty much is as simple as reading the bytes and outputting them. Of course 8bit PCM has a 0x80 offset so just writing to PORTD (which I assume is an R-2R) is going to be a bit "odd". Also an 8bit PCM WAV file has the RIFF container on the front so the first 62 bytes will be meaningless garbage but at normal sample rates that just means a fraction of second of noise at the front.

Of course WAV is just a RIFF container format - it can actually hold 50..100 different formats and if the content is encoded like ADPC, uLaw, aLaw, etc then just using the bytes "as is" will be meaningless. But I assume dsese1234 knows this?

Well that block of data is "silence" - I presume it gets "noisy" in some block later on beyond block 645?

You do realise that the "samples" of audio in this file are going to look a bit like this:

So values around 0x7F, 0x80, 0x81 (like those 0x7F and 0x80 values you show above) are around the "center line" and effectively represent silence. It's only when the wave goes much more positive - towards 0xFF - or much more negative - towards 0x00 - that it really represents significant amounts of sound energy.

You have 2 parts... reading the wav file and playing 512 byte buffers full of 8 bit samples double buffered. I bet you could get 12KHz samples per sec or better. Try putting a 512 byte table in flash or ram of several cycles of a 400Hz sin wave and playing it. Should sound like a flute.

I always test these wav players with a table that has a correct wave in it. You only need about 16 samples to make a sine wave or a sawtooth wave. 4 samps from center to full scale, then 8 samps down to 0, then 4 more back to center. Play that in a loop.

So, let me see if I understand all this: You are here asking for help, "to edit your codes". But you want to use the codes that you posted.

But we can edit your code to make it work--in the manner of a proven library. But you cannot use any previous work as a reference?

I agree this does not make sense. I'm all for learning by doing but if you do it and it doesn't work one of the best ways to learn why (now that you kind of understand what is supposed to be happening) is to then look at known/working/proven code and you'll see the error you have made. This doesn't mean you are just "using" someone else's library as a "black box" - you UNDERSTAND how their implementation works as it's probably pretty close to what you've been attempting. There's no shame in learning this way - it's how a lot of us have learned various techniques in the past.

You just aren't listening!!! I already told you that if you create a stack based automatic variable (such as j and the mysterious x here) that they are NOT initialised to 0. So when this function is entered "j" and "x" could have any value from 0 to 65535. Even if "j" were 0 what do you think it going to happen? It will output the first element of block_address[] and then increment "j". When j reaches 512 (the end of the data) what happens then? j just keeps on going. It will reach 512 in 125us * 512 which is 0.064 of a second. So you might expect to hear "real" data for a little short of 1/10th of a second then it will play random noise. What is the point in this??

I am only going to explain this once more and if you don't get it on this third occasion I'm afraid you are on your own. The design of this program should be:

locate first MMC block of WAV data
loop:
get next block of data
play that block
while still blocks to be played go to loop
play_that_block:
for 512 bytes
output data byte
delay

It's as simple as that - now just implement what I told you (you already have most of this code close to completion anyway).

This (and my previous posts) illustrate an important concept in software engineering: don't just wade straight in and start writing lines of C code. Instead start with a high level design. Then add more and more detail to each step of that design until finally you are close to a step by step description. Then turn those steps into C.

If you try to do it the other way round - just write it line by line in C you miss the "big picture". The "big picture" here is that you have a 4MB file made up of 8832 blocks of 512 bytes so the way to play it is to get one block of 512 bytes, then play that, then get the next block of 512 bytes then play that and keep doing all this 8,832 times. THAT is your program design.

Now other's have raised an issue above that you will need to think about later once you have this basic looping design working. The problem is that each time you go to read the next block of 512 bytes it may take a finite time. As long as it's less than the 125us inter-sample delay it won't matter - in that case, on the last byte output don't delay but use the reading of the next block as the inter-sample delay. If, however, reading takes longer (and I suspect it may) you could have problem as there will be "clicks" in the audio at each gap while the next 512 is being read. In this case you'll need a strategy where you have TWO lots of 512 bytes. While one is being played you spend some of the wasted 125us delay times reading the next 512 so that when the current buffer is used up the next one is already filled and ready to be played. This is known as "ping-pong" or "dual buffering". The one thing that must happen on time is the actual sample playing while the reading can be done in the "gaps inbetween". So the way you'd likely have the micro do "two things at once" is to set up a timer interrupt (every 125us). When the interrupt occurs you play the next sample from the currently filled buffer. Meanwhile, when you are not in the interrupt the "background" code can slowly but surely be reading the MMC block and filling the "other" buffer. But don't worry about this just yet - this is for the future - get your simple looping version working first then worry about this.

How can you debug double buffering from the sd card when you cant load and play one buffer from the sd card? Record a wav file with you saying 'Testing One Two Three' and save it 8 bit mono 8KHz sample rate. Play it on the PC. Sounds OK? Save it to the sd card. Play it from the sd card. Sounds OK except for some pops when loading the next sector? NOW you can load into buffer1 or buffer2 while playing from the other buffer.

In case it hasn't sunk in yet, we will NOT write this code for you. We will HELP you to find and resolve the problems within YOUR code, but you've got to do the work yourself.

So far you have more-or-less ignored every question asked of you. You're not going to get very far that way. Go back to the beginning of this thread. Re-read all of the responses. Answer the questions.

"Experience is what enables you to recognise a mistake the second time you make it."

What makes you think it's MikroC? _delay_us() would usually mean avr-gcc

As to OP, you need to DESIGN this before implementing it. What is the point of passing block_address as a parameter to audio_playback () then ignoring it and accessing the buffers as globals? The ping-pong should occur ABOVE audio_playback () then pass in one or other block address.

You may think it's better just to think about the design as you write the lines of C but this will not deliver a great solution.

I think there is a communication problem. Can you add your city and country to your profile? The guys that are responding to your messages are asking questions that you do not answer, and making suggestions that you ignore. Since you can play back 512 byte sectors from the sd card using a double buffer technique, your player is almost done. Do you have an lcd to show song and title? Do you have an encoder with pushbutton to select artist and song? I assume that there wasn't any problem playing the first sector that was full of 7f7f7f, that was just the silence at the beginning of the song. All my assumptions correct so far? Over to you.

I want to know how to include extra .c files in my make file ... i downloaded sd card library from roland.com website and it many files named --- byteordering .c , fat.c , partiotion.c ....etc ....and also main.c

I did changes in Makefile under
# List C source files here. (C dependencies are automatically generated.) like this .....

# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =

# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS =

#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100

# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)

MATH_LIB = -lm

# List any extra directories to look for libraries here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRALIBDIRS =

# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost

i have downloaded some code when i put it on avr it shows following errors : c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm64.o:(.init9+0x0): undefined reference to `main'
make.exe: *** [dar.elf] Error 1

MY AVR ATMEGA 128 ....

i checked opening and closing braces everything is fine ....is there any problem with make file ...i have copied make file also ....

All C programs must contain one file that contains a function called main(). If you build and link a set of .c files and none of them contains main() then you get exactly the error you are seeing. So I'd suggest the file above (dar.c ?) is not being compiled correctly. Try adding -save-temps to the CFLAGS and then after building see if you have a dar.i file in the build directory. If you do attach it to a post here.

Then clearly dar.c is not being compiled - which explains the lack of main().

To be honest while the makefile template you are using is a great one I've never been keen on the TARGET= and the later SRC = $(TARGET).c as it assumes you are going to have a foo.c if you call your target "foo". Personally I might be tempted to actually call the file that contains main() the name main.c so that the next reader of the project/files knows where to start looking to see the hierarchy of the execution. So maybe just change:

The use of "+=" on all but the first is VERY important. Because you just used "=" rather than "+=" only the last line:

SRC = UART_routinesd.c

really had any effect as you were over-writing the setting of "SRC=" each time.

To be honest why bother with Makefiles? Surely you can find an IDE that can "hide" all this for you? If you use Windows then Atmel's own Studio 6.2 is the obvious choice. If something other than Windows then there are several IDE's that can be used to build avr-gcc code like Eclipse and Netbeans though personally my favourite is Code::Blocks.