avr custom wav player help!

Go To Last Post
45 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i am working reading sd card data using atmega328, and i am trying to play the hex value of  wav audio data that are in sd card.

 

 

not sure why it didn't play the audio. the only that i heared is a trash of sounds. here is my code.

 

for(j = 0; j < 4521984; j++)
    {
     
    
      PORTD = block_address[i * 16 + j];
       _delay_us(125);
      
       if(j >= 4521984){
      
          j=0;
      
       }
    }

 

 

 

i am using r2r circuit for dac.

 

 

any idea?

 

 

 

Last Edited: Sun. Sep 14, 2014 - 04:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's the smallest player code I have ever seen, congratulations! wink

i am using r2r circuit for dac.

...and what else? Do you have DC blocking caps, a filter? a diagram? 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
for(j = 0; j < 4521984; j++)
    {
     
    
      PORTD = block_address[i * 16 + j];
       _delay_us(125);
      
       if(j >= 4521984){
      
          j=0;
      
       }
    }

Perhaps you'd like to start 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.

 

 

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

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Sep 14, 2014 - 04:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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??

 

#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>

#include "spi.h"

#include <avr/pgmspace.h>

/*****************************************************************************
* UART functions
******************************************************************************/

#define BAUD_RATE 57600

#if (BAUD_RATE == 115200)
#define BAUD_RATE_UBRR 8
#elif (BAUD_RATE == 57600)
#define BAUD_RATE_UBRR 16
#else
#define BAUD_RATE_UBRR (F_CPU/16/BAUD_RATE - 1)
#endif

int i = 0;
 

unsigned char mmc_buf[512];

void uart_init(void)
{
  // Setup the UART baud rate
  UBRR0H = (BAUD_RATE_UBRR >> 8);
  UBRR0L = BAUD_RATE_UBRR;

  // Enable the UART receiver and transceiver
  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
  // Set the frame format : 8 bits data, 1 bit stop
  UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
}

void uart_write(uint8_t byte)
{
  while (!(UCSR0A & (1 << UDRE0)));
  UDR0 = byte;
}

int uart_stream_write(char c, FILE *stream)
{
  if (c == '\n')
    uart_stream_write('\r', stream);

  uart_write(c);
  return 0;
}

static FILE uart_stdout = FDEV_SETUP_STREAM(uart_stream_write, NULL, _FDEV_SETUP_WRITE);

/*****************************************************************************
* MMC functions
******************************************************************************/

#define MMC_CMD_SIZE 6
uint8_t mmc_cmd[MMC_CMD_SIZE];

#define MMC_TIMEOUT  0xFF
#define MMC_BLOCK_SIZE 512

#define DDR_CS  DDRB
#define PORT_CS PORTB
#define DD_CS   DDB2

#define SET_CS()   PORT_CS |= _BV(DD_CS);
#define CLEAR_CS() PORT_CS &= ~_BV(DD_CS);

uint8_t mmc_response(uint8_t response)
{
  uint16_t count = 0xFFF;
  uint8_t result;

  while(count > 0)
  {
    result = spi_receive_byte();
    if (result == response)
      break;
    count--;
  }

  if (count == 0)
    return 1; /* Failure, loop was exited due to timeout */

  return 0; /* Normal, loop was exited before timeout */
}

void mmc_init(void)
{
  uint8_t i;
  uint8_t byte;

  /* Init the CS output */
  DDR_CS |= _BV(DD_CS);

  SET_CS();
  {
    /* Init the card in SPI mode by sending 80 clks */
    for(i = 0; i < 10; i++)
      byte = spi_receive_byte();
  }
  CLEAR_CS();

  printf("send CMD0\n");

  /* Send CMD0 GO_IDLE_STATE */
  mmc_cmd[0] = 0x40;
  mmc_cmd[1] = 0x00;
  mmc_cmd[2] = 0x00;
  mmc_cmd[3] = 0x00;
  mmc_cmd[4] = 0x00;
  mmc_cmd[5] = 0x95;
  spi_send(mmc_cmd, MMC_CMD_SIZE);

  if (mmc_response(0x01))
  {
    printf("CMD0 timeout\n");
    return;
  }

  printf("send dummy clocks\n");

  /* Send some dummy clocks after GO_IDLE_STATE */
  SET_CS();
  spi_receive_byte();
  CLEAR_CS();

  printf("send CMD1\n");

  /* Send CMD1 SEND_OP_COND until response is 0 */
  i = MMC_TIMEOUT;
  do
  {
    mmc_cmd[0] = 0x41;
    mmc_cmd[1] = 0x00;
    mmc_cmd[2] = 0x00;
    mmc_cmd[3] = 0x00;
    mmc_cmd[4] = 0x00;
    mmc_cmd[5] = 0xFF;
    spi_send(mmc_cmd, MMC_CMD_SIZE);
    i--;
  } while((mmc_response(0x00) != 0) && (i > 0));

  if (i == 0)
  {
    printf("CMD1 timeout\n");
    return;
  }

  printf("send dummy clocks\n");

  /* Send some dummy clocks after GO_IDLE_STATE */
  SET_CS();
  spi_receive_byte();
  CLEAR_CS();

  printf("send CMD16\n");

  /* Send CMD16 SET_BLOCKLEN to set the block length */
  mmc_cmd[0] = 0x50;
  mmc_cmd[1] = 0x00;   /* 4 bytes from here is the block length */
                       /* LSB is first */
                       /* 00 00 00 10 set to 16 bytes */
                       /* 00 00 02 00 set to 512 bytes */
  mmc_cmd[2] = 0x00;
  /* high block length bits - 512 bytes */
  mmc_cmd[3] = 0x02;
  /* low block length bits */
  mmc_cmd[4] = 0x00;
  mmc_cmd[5] = 0xFF; /* checksum is no longer required but we always send 0xFF */
  spi_send(mmc_cmd, MMC_CMD_SIZE);

  if ((mmc_response(0x00)) == 1)
  {
    printf("CMD16 timeout\n");
  }

  SET_CS();
  spi_receive_byte();

  printf("mmc_init end\n");
}

void mmc_read_block(uint16_t block_number, uint8_t* block_address)
{
  uint16_t checksum;
  uint16_t varh, varl;

  varl = ((block_number & 0x003F) << 9);
  varh = ((block_number & 0xFFC0) >> 7);

  printf("read block %i\n", block_number);

  CLEAR_CS();
  {
    /* send MMC CMD17(READ_SINGLE_BLOCK) to read the data from MMC card */
    mmc_cmd[0] = 0x51;
    /* high block address bits, varh HIGH and LOW */
    mmc_cmd[1] = varh >> 0x08;
    mmc_cmd[2] = varh & 0xFF;
    /* low block address bits, varl HIGH and LOW */
    mmc_cmd[3] = varl >> 0x08;
    mmc_cmd[4] = varl & 0xFF;
    /* checksum is no longer required but we always send 0xFF */
    mmc_cmd[5] = 0xFF;
    spi_send(mmc_cmd, MMC_CMD_SIZE);

    /* if mmc_response returns 1 then we failed to get a 0x00 response */
    if ((mmc_response(0x00)) == 1)
    {
      printf("read block timeout\n");
      return;
    }

    /* wait for data token */
    if ((mmc_response(0xFE)) == 1)
    {
      printf("data token missing\n");
      return;
    }

    printf("receive block\n");

    /* Get the block of data based on the length */
    spi_receive(block_address, MMC_BLOCK_SIZE);

    /* CRC bytes that are not needed */
    checksum = spi_receive_byte();
    checksum = checksum << 0x08 | spi_receive_byte();
  }
  SET_CS();
 
  spi_receive_byte();
 
  printf("block received\n");
}

void audio_playback(uint8_t *block_address, uint16_t length)
{

  uint16_t i, j;
  uint8_t byte;
  DDRD =  255;
   
   
   

   
    for(j = 0; j < 4521984; j++)
    {

    
   
      PORTD = block_address[i * 16 + j];
       
      if(j >= 4521984){
      
          j=0;
      
      }
      
      if(i >= 512){
      
      
         i = 0;
      
      }
       
       _delay_us(64);
      
      
    }
     

 
}

/*****************************************************************************
* Main program
******************************************************************************/
uint8_t mmc_block[MMC_BLOCK_SIZE];

int main (void)
{

 
  _delay_us(125);
 
  /* Init the UART */
    uart_init();
    stdout = &uart_stdout;

  /* Init the SPI */
    printf("spi_init\n");
    spi_init();

  /* Init the MMC */
    printf("mmc_init\n");
    mmc_init();

  /* Reset the MMC buffer */
    memset(mmc_block, 0xCA, MMC_BLOCK_SIZE);

  /* Read the first block */
    mmc_read_block(645, mmc_block);
    audio_playback(mmc_block, MMC_BLOCK_SIZE);

  /* Infinite loop */
  for(;;);

  return(0);
}

 

 

 

 

Thank you!

Last Edited: Mon. Sep 15, 2014 - 09:12 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi there,

 

can anyone answer my question?

 

 

thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can anyone answer my question?

Not until you answer Joey's question:

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!).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried to format the code earlier and instead I deleted it all thanks to the new way of posting code. blush

 

Trying again in another thread so as not to mess up again

#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>

#include "spi.h"

#include <avr/pgmspace.h>

/*****************************************************************************
* UART functions
******************************************************************************/

#define BAUD_RATE 57600

#if (BAUD_RATE == 115200)
#define BAUD_RATE_UBRR 8
#elif (BAUD_RATE == 57600)
#define BAUD_RATE_UBRR 16
#else
#define BAUD_RATE_UBRR (F_CPU/16/BAUD_RATE - 1)
#endif

int i = 0;
 

unsigned char mmc_buf[512];

void uart_init(void)
{
  // Setup the UART baud rate
  UBRR0H = (BAUD_RATE_UBRR >> 8);
  UBRR0L = BAUD_RATE_UBRR;

  // Enable the UART receiver and transceiver
  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
  // Set the frame format : 8 bits data, 1 bit stop
  UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
}

void uart_write(uint8_t byte)
{
  while (!(UCSR0A & (1 << UDRE0)));
  UDR0 = byte;
}

int uart_stream_write(char c, FILE *stream)
{
  if (c == '\n')
    uart_stream_write('\r', stream);

  uart_write(c);
  return 0;
}

static FILE uart_stdout = FDEV_SETUP_STREAM(uart_stream_write, NULL, _FDEV_SETUP_WRITE);

/*****************************************************************************
* MMC functions
******************************************************************************/

#define MMC_CMD_SIZE 6
uint8_t mmc_cmd[MMC_CMD_SIZE];

#define MMC_TIMEOUT  0xFF
#define MMC_BLOCK_SIZE 512

#define DDR_CS  DDRB
#define PORT_CS PORTB
#define DD_CS   DDB2

#define SET_CS()   PORT_CS |= _BV(DD_CS);
#define CLEAR_CS() PORT_CS &= ~_BV(DD_CS);

uint8_t mmc_response(uint8_t response)
{
  uint16_t count = 0xFFF;
  uint8_t result;

  while(count > 0)
  {
    result = spi_receive_byte();
    if (result == response)
      break;
    count--;
  }

  if (count == 0)
    return 1; /* Failure, loop was exited due to timeout */

  return 0; /* Normal, loop was exited before timeout */
}

void mmc_init(void)
{
  uint8_t i;
  uint8_t byte;

  /* Init the CS output */
  DDR_CS |= _BV(DD_CS);

  SET_CS();
  {
    /* Init the card in SPI mode by sending 80 clks */
    for(i = 0; i < 10; i++)
      byte = spi_receive_byte();
  }
  CLEAR_CS();

  printf("send CMD0\n");

  /* Send CMD0 GO_IDLE_STATE */
  mmc_cmd[0] = 0x40;
  mmc_cmd[1] = 0x00;
  mmc_cmd[2] = 0x00;
  mmc_cmd[3] = 0x00;
  mmc_cmd[4] = 0x00;
  mmc_cmd[5] = 0x95;
  spi_send(mmc_cmd, MMC_CMD_SIZE);

  if (mmc_response(0x01))
  {
    printf("CMD0 timeout\n");
    return;
  }

  printf("send dummy clocks\n");

  /* Send some dummy clocks after GO_IDLE_STATE */
  SET_CS();
  spi_receive_byte();
  CLEAR_CS();

  printf("send CMD1\n");

  /* Send CMD1 SEND_OP_COND until response is 0 */
  i = MMC_TIMEOUT;
  do
  {
    mmc_cmd[0] = 0x41;
    mmc_cmd[1] = 0x00;
    mmc_cmd[2] = 0x00;
    mmc_cmd[3] = 0x00;
    mmc_cmd[4] = 0x00;
    mmc_cmd[5] = 0xFF;
    spi_send(mmc_cmd, MMC_CMD_SIZE);
    i--;
  } while((mmc_response(0x00) != 0) && (i > 0));

  if (i == 0)
  {
    printf("CMD1 timeout\n");
    return;
  }

  printf("send dummy clocks\n");

  /* Send some dummy clocks after GO_IDLE_STATE */
  SET_CS();
  spi_receive_byte();
  CLEAR_CS();

  printf("send CMD16\n");

  /* Send CMD16 SET_BLOCKLEN to set the block length */
  mmc_cmd[0] = 0x50;
  mmc_cmd[1] = 0x00;   /* 4 bytes from here is the block length */
                       /* LSB is first */
                       /* 00 00 00 10 set to 16 bytes */
                       /* 00 00 02 00 set to 512 bytes */
  mmc_cmd[2] = 0x00;
  /* high block length bits - 512 bytes */
  mmc_cmd[3] = 0x02;
  /* low block length bits */
  mmc_cmd[4] = 0x00;
  mmc_cmd[5] = 0xFF; /* checksum is no longer required but we always send 0xFF */
  spi_send(mmc_cmd, MMC_CMD_SIZE);

  if ((mmc_response(0x00)) == 1)
  {
    printf("CMD16 timeout\n");
  }

  SET_CS();
  spi_receive_byte();

  printf("mmc_init end\n");
}

void mmc_read_block(uint16_t block_number, uint8_t* block_address)
{
  uint16_t checksum;
  uint16_t varh, varl;

  varl = ((block_number & 0x003F) << 9);
  varh = ((block_number & 0xFFC0) >> 7);

  printf("read block %i\n", block_number);

  CLEAR_CS();
  {
    /* send MMC CMD17(READ_SINGLE_BLOCK) to read the data from MMC card */
    mmc_cmd[0] = 0x51;
    /* high block address bits, varh HIGH and LOW */
    mmc_cmd[1] = varh >> 0x08;
    mmc_cmd[2] = varh & 0xFF;
    /* low block address bits, varl HIGH and LOW */
    mmc_cmd[3] = varl >> 0x08;
    mmc_cmd[4] = varl & 0xFF;
    /* checksum is no longer required but we always send 0xFF */
    mmc_cmd[5] = 0xFF;
    spi_send(mmc_cmd, MMC_CMD_SIZE);

    /* if mmc_response returns 1 then we failed to get a 0x00 response */
    if ((mmc_response(0x00)) == 1)
    {
      printf("read block timeout\n");
      return;
    }

    /* wait for data token */
    if ((mmc_response(0xFE)) == 1)
    {
      printf("data token missing\n");
      return;
    }

    printf("receive block\n");

    /* Get the block of data based on the length */
    spi_receive(block_address, MMC_BLOCK_SIZE);

    /* CRC bytes that are not needed */
    checksum = spi_receive_byte();
    checksum = checksum << 0x08 | spi_receive_byte();
  }
  SET_CS();
 
  spi_receive_byte();
 
  printf("block received\n");
}

void audio_playback(uint8_t *block_address, uint16_t length)
{

  uint16_t i, j;
  uint8_t byte;
  DDRD =  255;
   
   
   

   
    for(j = 0; j < 4521984; j++)
    {

    
   
      PORTD = block_address[i * 16 + j];
       
      if(j >= 4521984){
      
          j=0;
      
      }
      
      if(i >= 512){
      
      
         i = 0;
      
      }
       
       _delay_us(64);
      
      
    }
     

 
}

/*****************************************************************************
* Main program
******************************************************************************/
uint8_t mmc_block[MMC_BLOCK_SIZE];

int main (void)
{

 
  _delay_us(125);
 
  /* Init the UART */
    uart_init();
    stdout = &uart_stdout;

  /* Init the SPI */
    printf("spi_init\n");
    spi_init();

  /* Init the MMC */
    printf("mmc_init\n");
    mmc_init();

  /* Reset the MMC buffer */
    memset(mmc_block, 0xCA, MMC_BLOCK_SIZE);

  /* Read the first block */
    mmc_read_block(645, mmc_block);
    audio_playback(mmc_block, MMC_BLOCK_SIZE);

  /* Infinite loop */
  for(;;);

  return(0);
}
- See more at: http://www.avrfreaks.net/forum/avr-custom-wav-player-help#comment-1318371

 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

Last Edited: Mon. Sep 15, 2014 - 09:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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:

 mmc_read_block(645, mmc_block);
 audio_playback(mmc_block, MMC_BLOCK_SIZE);

becomes something more like:

for (some_i=0; some_i < some_big_number; some_i++) {
 mmc_read_block(645 + some_i, mmc_block);
 audio_playback(mmc_block, MMC_BLOCK_SIZE);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

can anyone answer my question?

Not until you answer Joey's question:

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!).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi clawson, i try that idea. ill get back soon.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

Just taking some parts of your current audio_playback():

void audio_playback(uint8_t *block_address, uint16_t length)
{
  uint16_t i, j;
  for(j = 0; j < 4521984; j++)
    {
      PORTD = block_address[i * 16 + j];
       _delay_us(64);
    }
}

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.

 

As I say this loop wants to be something like:

void audio_playback(uint8_t *block_address)
{

  uint16_t j;
  DDRD =  0xFF;
   
    for(j = 0; j < 512; j++)
    {
      PORTD = block_address[j];
       _delay_us(64);
    }
}

so it plays the 512 bytes of the single MMC block passed to it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

void audio_playback(uint8_t *block_address, uint16_t length)
{

    uint16_t j,x;
    DDRD = 0xFF;
    
    
    for(x = 0; x< 4521984; x++){
        
        for(j = 0; j < 512; j++) {
        
            PORTD = block_address[j];
            
            
        
            if(j >= 512){
        
                j = 0;
            }
        }
        x =  0; // get back to 0 to play it again.  
        
        _delay_us(64);
        
    }

 
}

 

Last Edited: Mon. Sep 15, 2014 - 10:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't get how you do this.

I guess you need to read 512 byte, and then play them, while you do that you read the next 512 byte so they are ready when you need them.(perhaps the 512 should be 256 or 128)

(Or do you have a timer ISR that keep the buffer full? if that's the case _delay_us don't give the correct delay). 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

274,207,281-1 The largest known Mersenne Prime

Measure twice, cry, go back to the hardware store

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All,

 

i changed my code. so that i can see the wav data. and i get this.

i really wonder why does not play the wav data on the PORTDfrown

read block 645
receive block
block received
0000: 52494646f200450057415645666d7420 RIFF..E.WAVEfmt 
0010: 1000000001000200401f0000803e0000 ........@....>..
0020: 0200080064617461000045007f7f7f7f ....data..E.....
0030: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0040: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0050: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0060: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0070: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0080: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0090: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
00a0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
00b0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
00c0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
00d0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
00e0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
00f0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0100: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0110: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0120: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0130: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0140: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0150: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0160: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f807f ................
0170: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0180: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
0190: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
01a0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
01b0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
01c0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
01d0: 7f7f7f7f7f7f807f7f7f7f7f7f7f7f7f ................
01e0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................
01f0: 7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f ................

 

Last Edited: Mon. Sep 15, 2014 - 02:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i really like you guys to edit my codes. if that is posible on you guys. cause im getting old

#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>

#include "spi.h"

#include <avr/pgmspace.h>

/*****************************************************************************
* UART functions
******************************************************************************/

#define BAUD_RATE 57600

#if (BAUD_RATE == 115200)
#define BAUD_RATE_UBRR 8
#elif (BAUD_RATE == 57600)
#define BAUD_RATE_UBRR 16
#else
#define BAUD_RATE_UBRR (F_CPU/16/BAUD_RATE - 1)
#endif

int i = 0;
 



void uart_init(void)
{
  // Setup the UART baud rate
  UBRR0H = (BAUD_RATE_UBRR >> 8);
  UBRR0L = BAUD_RATE_UBRR;

  // Enable the UART receiver and transceiver
  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
  // Set the frame format : 8 bits data, 1 bit stop
  UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
}

void uart_write(uint8_t byte)
{
  while (!(UCSR0A & (1 << UDRE0)));
  UDR0 = byte;
}

int uart_stream_write(char c, FILE *stream)
{
  if (c == '\n')
    uart_stream_write('\r', stream);

  uart_write(c);
  return 0;
}

static FILE uart_stdout = FDEV_SETUP_STREAM(uart_stream_write, NULL, _FDEV_SETUP_WRITE);

/*****************************************************************************
* MMC functions
******************************************************************************/

#define MMC_CMD_SIZE 6
uint8_t mmc_cmd[MMC_CMD_SIZE];

#define MMC_TIMEOUT  0xFF
#define MMC_BLOCK_SIZE 512

#define DDR_CS  DDRB
#define PORT_CS PORTB
#define DD_CS   DDB2

#define SET_CS()   PORT_CS |= _BV(DD_CS);
#define CLEAR_CS() PORT_CS &= ~_BV(DD_CS);

uint8_t mmc_response(uint8_t response)
{
  uint16_t count = 0xFFF;
  uint8_t result;

  while(count > 0)
  {
    result = spi_receive_byte();
    if (result == response)
      break;
    count--;
  }

  if (count == 0)
    return 1; /* Failure, loop was exited due to timeout */

  return 0; /* Normal, loop was exited before timeout */
}

void mmc_init(void)
{
  uint8_t i;
  uint8_t byte;

  /* Init the CS output */
  DDR_CS |= _BV(DD_CS);

  SET_CS();
  {
    /* Init the card in SPI mode by sending 80 clks */
    for(i = 0; i < 10; i++)
      byte = spi_receive_byte();
  }
  CLEAR_CS();

  printf("send CMD0\n");

  /* Send CMD0 GO_IDLE_STATE */
  mmc_cmd[0] = 0x40;
  mmc_cmd[1] = 0x00;
  mmc_cmd[2] = 0x00;
  mmc_cmd[3] = 0x00;
  mmc_cmd[4] = 0x00;
  mmc_cmd[5] = 0x95;
  spi_send(mmc_cmd, MMC_CMD_SIZE);

  if (mmc_response(0x01))
  {
    printf("CMD0 timeout\n");
    return;
  }

  printf("send dummy clocks\n");

  /* Send some dummy clocks after GO_IDLE_STATE */
  SET_CS();
  spi_receive_byte();
  CLEAR_CS();

  printf("send CMD1\n");

  /* Send CMD1 SEND_OP_COND until response is 0 */
  i = MMC_TIMEOUT;
  do
  {
    mmc_cmd[0] = 0x41;
    mmc_cmd[1] = 0x00;
    mmc_cmd[2] = 0x00;
    mmc_cmd[3] = 0x00;
    mmc_cmd[4] = 0x00;
    mmc_cmd[5] = 0xFF;
    spi_send(mmc_cmd, MMC_CMD_SIZE);
    i--;
  } while((mmc_response(0x00) != 0) && (i > 0));

  if (i == 0)
  {
    printf("CMD1 timeout\n");
    return;
  }

  printf("send dummy clocks\n");

  /* Send some dummy clocks after GO_IDLE_STATE */
  SET_CS();
  spi_receive_byte();
  CLEAR_CS();

  printf("send CMD16\n");

  /* Send CMD16 SET_BLOCKLEN to set the block length */
  mmc_cmd[0] = 0x50;
  mmc_cmd[1] = 0x00;   /* 4 bytes from here is the block length */
                       /* LSB is first */
                       /* 00 00 00 10 set to 16 bytes */
                       /* 00 00 02 00 set to 512 bytes */
  mmc_cmd[2] = 0x00;
  /* high block length bits - 512 bytes */
  mmc_cmd[3] = 0x02;
  /* low block length bits */
  mmc_cmd[4] = 0x00;
  mmc_cmd[5] = 0xFF; /* checksum is no longer required but we always send 0xFF */
  spi_send(mmc_cmd, MMC_CMD_SIZE);

  if ((mmc_response(0x00)) == 1)
  {
    printf("CMD16 timeout\n");
  }

  SET_CS();
  spi_receive_byte();

  printf("mmc_init end\n");
}

void mmc_read_block(uint16_t block_number, uint8_t* block_address)
{
  uint16_t checksum;
  uint16_t varh, varl;

  varl = ((block_number & 0x003F) << 9);
  varh = ((block_number & 0xFFC0) >> 7);

  printf("read block %i\n", block_number);

  CLEAR_CS();
  {
    /* send MMC CMD17(READ_SINGLE_BLOCK) to read the data from MMC card */
    mmc_cmd[0] = 0x51;
    /* high block address bits, varh HIGH and LOW */
    mmc_cmd[1] = varh >> 0x08;
    mmc_cmd[2] = varh & 0xFF;
    /* low block address bits, varl HIGH and LOW */
    mmc_cmd[3] = varl >> 0x08;
    mmc_cmd[4] = varl & 0xFF;
    /* checksum is no longer required but we always send 0xFF */
    mmc_cmd[5] = 0xFF;
    spi_send(mmc_cmd, MMC_CMD_SIZE);

    /* if mmc_response returns 1 then we failed to get a 0x00 response */
    if ((mmc_response(0x00)) == 1)
    {
      printf("read block timeout\n");
      return;
    }

    /* wait for data token */
    if ((mmc_response(0xFE)) == 1)
    {
      printf("data token missing\n");
      return;
    }

    printf("receive block\n");

    /* Get the block of data based on the length */
    spi_receive(block_address, MMC_BLOCK_SIZE);

    /* CRC bytes that are not needed */
    checksum = spi_receive_byte();
    checksum = checksum << 0x08 | spi_receive_byte();
  }
  SET_CS();
 
  spi_receive_byte();
 
  printf("block received\n");
}

void audio_playback(uint8_t *block_address, uint16_t length)
{

	uint16_t j,x; 
	DDRD = 255; 
	
	
	
		
		for(;;) { 
		
			 
			

					
			PORTD = block_address[j++]; 
			 
			_delay_us(125);		
		
		
		}

		


 
}

/*****************************************************************************
* Main program
******************************************************************************/
uint8_t mmc_block[MMC_BLOCK_SIZE];

int main (void)
{
	unsigned int some_i;
 
  _delay_us(125);
 
  /* Init the UART */
    uart_init();
    stdout = &uart_stdout;

  /* Init the SPI */
    printf("spi_init\n");
    spi_init();

  /* Init the MMC */
    printf("mmc_init\n");
    mmc_init();

  /* Reset the MMC buffer */
    memset(mmc_block, 0xCA, MMC_BLOCK_SIZE);

  /* Read the first block */
  
  

	mmc_read_block(645, mmc_block);
	audio_playback(mmc_block, MMC_BLOCK_SIZE);

  /* Infinite loop */
  for(;;);

  return(0);
}

 

Last Edited: Mon. Sep 15, 2014 - 03:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes, it output a noisy sounds. what should be the solution? i get converted to wav file into an array and i gets the same value.

these are the value when i converted the raw file to an array unsigned char.  using https://code.google.com/p/bin2h/...

   

  

 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x80,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x80,0x7F,0x7F,
    0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,

etc.............

 

Last Edited: Mon. Sep 15, 2014 - 04:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hmm any one wants to help me?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff and others have asked you some questions, which you haven't answered yet.

 

Have you looked at any other projects?  This kind of thing has been done man times before.

 

Here's one:

http://www.instructables.com/id/...

 

 

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

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i want to use the codes that i posted. i dont like to use other library...wink

simply  want to learn..

Last Edited: Mon. Sep 15, 2014 - 11:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i really like you guys to edit my codes.

 i want to use the codes that i posted.

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?

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi theusch,

 

i tried that but the structure of other is confusing to me. please help me to make it work then and i really appreciate it.

i actually posted the value www.avrfreaks.net/comment/131856... , i want to simple play the audio raw data into PORTD as R2-R DAC.

 

i edited again the audio_playback

void audio_playback(uint8_t *block_address, uint16_t length)
{
   uint16_t j,x; 
   DDRD = 255; 
			
    for(;;) { 
		
			PORTD = block_address[j++]; 
			 
			_delay_us(125);		
	}

}

 

i just hear a noisy or i sound like a beepppppppppp.. not sure.

 

check my attachement

Attachment(s): 

Last Edited: Tue. Sep 16, 2014 - 08:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

 

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@bobgardner,

 

have you test it? do you have the solution?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

 

Anyway back to your code:

void audio_playback(uint8_t *block_address, uint16_t length)
{
   uint16_t j,x; 
   DDRD = 255; 
			
   for(;;) { 
     PORTD = block_address[j++]; 
     _delay_us(125);		
   }

}

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dsese1234 wrote:

@bobgardner,

 

have you test it? do you have the solution?

 

unsigned char sawtab[16]={0x7f,0x9f,0xbf,0xdf,0xff,0xdf,0xbf,0x9f.0x7f,0x3f,0x1f,0x0f,0x00,0x0f,0x1f,0x3f};

 

Play these over and over in a loop.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i already tested that. saving the data into array and read the data via pgm_read_byte and it works.  but not sure why the data from sd card didn't work.frown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but not sure why the data from sd card didn't work

Surely that's obvious - if playback of one data worked and playback of the other didn't using an identical playback mechanism then clearly it wasn't the same data. So I'd investigate why not.

 

Rather than play it print out the bytes to a serial terminal or an LCD display or something. You should soon spot how they differ.

 

(if that shows the same then it must be timing of output).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Guy,

i am trying the pingpong buffer, which ibelieve will make the data save into another buffer. but i does not work well. can you check my codes?

please check correct my codes.

uint16_t TOGGLE_BUFFER = 0;

uint16_t mmc_buf0[512];
uint16_t mmc_buf1[512];

void audio_playback(uint8_t *block_address, uint16_t length)
{

	uint16_t ISR_i=0; 
	DDRD = 255;

		for(;;) { 
		
		if(TOGGLE_BUFFER == 0) {
				
			PORTD =  mmc_buf0[ISR_i++];
			
		}else if(TOGGLE_BUFFER == 1){
			
			PORTD =  mmc_buf1[ISR_i++];
		}
		if(ISR_i == 512) {

				TOGGLE_BUFFER = 1;
				ISR_i = 0;
		}
		
			_delay_us(125);	
		
		} 
		
 
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just a heads up to all who are trying to help...

 

These posted code fragments are from the Mikro-C AVR examples.

This is not going to end well.

 

Brad

I Like to Build Bikes : http://www.AtomicZombie.com

I Like to Hack Stuff : http://www.LucidScience.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

 

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brad, 

 

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. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am doing the pingpong buffer now. please open some suggestion...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys ,,,,

 

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 .....

SRC = $(TARGET).c
SRC +=$(fat).c
SRC +=$(byteordering).c
SRC +=$(partition).c

 Is this correct or there is any other procedure  .....i copied my make file also ........it gives an error 

make.exe: *** No rule to make target `sdmain.elf', needed by `elf'.  Stop.

 

makefile :

 

# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
#                Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging, 
#              with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
#                   bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------

# MCU name
MCU = atmega64

# Processor frequency.
#     This will define a symbol, F_CPU, in all source code files equal to the 
#     processor frequency. You can then use this symbol in your source code to 
#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
#     automatically to create a 32-bit value in your source code.
#     Typical values are:
#         F_CPU =  1000000
#         F_CPU =  1843200
#         F_CPU =  2000000
#         F_CPU =  3686400
#         F_CPU =  4000000
#         F_CPU =  7372800
#         F_CPU =  8000000
#         F_CPU = 11059200
#         F_CPU = 14745600
#         F_CPU = 16000000
#         F_CPU = 18432000
#         F_CPU = 20000000
F_CPU = 16000000

# Output format. (can be srec, ihex, binary)
FORMAT = ihex

# Target file name (without extension).
TARGET = sdmain

 

# Object files directory
#     To put object files in current directory, use a dot (.), do NOT make
#     this an empty or blank macro!
OBJDIR = .

# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c
SRC +=$(fat).c
SRC +=$(byteordering).c
SRC +=$(partition).c

 

# List C++ source files here. (C dependencies are automatically generated.)
CPPSRC = 

# 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 =

# Optimization level, can be [0, 1, 2, 3, s]. 
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s

# Debugging format.
#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
#     AVR Studio 4.10 requires dwarf-2.
#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2

# 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 = 

# Compiler flag to set the C Standard level.
#     c89   = "ANSI" C
#     gnu89 = c89 plus GCC extensions
#     c99   = ISO C99 standard (not yet fully implemented)
#     gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99

# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL

# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)

# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS

 

#---------------- Compiler Options C ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)

#---------------- Compiler Options C++ ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CPPFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)

#---------------- 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

#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt

# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB = 
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)

# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min

# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt

# 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 = 

 

#---------------- External Memory Options ----------------

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff

EXTMEMOPTS = 

 

#---------------- Linker Options ----------------
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -T linker_script.x

 

#---------------- Programming Options (avrdude) ----------------

# Programming hardware
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = usbasp

# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = usb

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep

# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y

# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V

# Increase verbosity level.  Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/proje...
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v

AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)

 

#---------------- Debugging Options ----------------

# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)

# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight

# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr

# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit

# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1

# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242

# 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

 

#============================================================================

# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd

# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = --------  end  --------
MSG_SIZE_BEFORE = Size before: 
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:

 

# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) 

# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) 

# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d

# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)

 

 

# Default target.
all: begin gccversion sizebefore build sizeafter end

# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib

elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)

 

# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
    @echo
    @echo $(MSG_BEGIN)

end:
    @echo $(MSG_END)
    @echo

# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf

sizebefore:
    @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
    2>/dev/null; echo; fi

sizeafter:
    @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
    2>/dev/null; echo; fi

 

# Display compiler version information.
gccversion : 
    @$(CC) --version

 

# Program the device.  
program: $(TARGET).hex $(TARGET).eep
    $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)

# Generate avr-gdb config/init file which does the following:
#     define the reset signal, load the target file, connect to target, and set 
#     a breakpoint at main().
gdb-config: 
    @$(REMOVE) $(GDBINIT_FILE)
    @echo define reset >> $(GDBINIT_FILE)
    @echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
    @echo end >> $(GDBINIT_FILE)
    @echo file $(TARGET).elf >> $(GDBINIT_FILE)
    @echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
    @echo load  >> $(GDBINIT_FILE)
endif
    @echo break main >> $(GDBINIT_FILE)

debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
    @echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
    @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
    $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
    @$(WINSHELL) /c pause

else
    @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
    $(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
    @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)

 

# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000

 

coff: $(TARGET).elf
    @echo
    @echo $(MSG_COFF) $(TARGET).cof
    $(COFFCONVERT) -O coff-avr $< $(TARGET).cof

extcoff: $(TARGET).elf
    @echo
    @echo $(MSG_EXTENDED_COFF) $(TARGET).cof
    $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof

 

# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
    @echo
    @echo $(MSG_FLASH) $@
    $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock $< $@

%.eep: %.elf
    @echo
    @echo $(MSG_EEPROM) $@
    -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
    --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0

# Create extended listing file from ELF output file.
%.lss: %.elf
    @echo
    @echo $(MSG_EXTENDED_LISTING) $@
    $(OBJDUMP) -h -S -z $< > $@

# Create a symbol table from ELF output file.
%.sym: %.elf
    @echo
    @echo $(MSG_SYMBOL_TABLE) $@
    $(NM) -n $< > $@

 

# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
    @echo
    @echo $(MSG_CREATING_LIBRARY) $@
    $(AR) $@ $(OBJ)

# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
    @echo
    @echo $(MSG_LINKING) $@
    $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)

# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
    @echo
    @echo $(MSG_COMPILING) $<
    $(CC) -c $(ALL_CFLAGS) $< -o $@ 

# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
    @echo
    @echo $(MSG_COMPILING_CPP) $<
    $(CC) -c $(ALL_CPPFLAGS) $< -o $@ 

# Compile: create assembler files from C source files.
%.s : %.c
    $(CC) -S $(ALL_CFLAGS) $< -o $@

# Compile: create assembler files from C++ source files.
%.s : %.cpp
    $(CC) -S $(ALL_CPPFLAGS) $< -o $@

# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
    @echo
    @echo $(MSG_ASSEMBLING) $<
    $(CC) -c $(ALL_ASFLAGS) $< -o $@

# Create preprocessed source for use in sending a bug report.
%.i : %.c
    $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 

# Target: clean project.
clean: begin clean_list end

clean_list :
    @echo
    @echo $(MSG_CLEANING)
    $(REMOVE) $(TARGET).hex
    $(REMOVE) $(TARGET).eep
    $(REMOVE) $(TARGET).cof
    $(REMOVE) $(TARGET).elf
    $(REMOVE) $(TARGET).map
    $(REMOVE) $(TARGET).sym
    $(REMOVE) $(TARGET).lss
    $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
    $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
    $(REMOVE) $(SRC:.c=.s)
    $(REMOVE) $(SRC:.c=.d)
    $(REMOVE) $(SRC:.c=.i)
    $(REMOVEDIR) .dep

# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)

# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)

# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
SRC = $(TARGET).c
SRC +=$(fat).c
SRC +=$(byteordering).c
SRC +=$(partition).c

close but what you really want is actually simpler:

SRC = $(TARGET).c
SRC += fat.c
SRC += byteordering.c
SRC += partition.c

The $(SOMETHING).c construct is using a predefined symbol and replacing it. So if the file previously had:

TARGET = foo

then when it gets to:

SRC = $(TARGET).c

It will replace $(TARGET) with what "TARGET" was already defined as. So the line will read as:

SRC = foo.c

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thks for that response it worked ,,,,

 

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 ....

 

 

//***********************************************************
// ****  routine FOR Interfacing microSD/SDHC CARD ****
//***********************************************************
//Controller: ATmega32 (Clock: 8 Mhz-internal)
//Compiler    : AVR-GCC (winAVR with AVRStudio)
//Version     : 2.3
//Author    : CC Dharmani, Chennai (India)
//              www.dharmanitech.com
//Date        : 08 May 2010
//***********************************************************

//Link to the Post: http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html

#define F_CPU 16000000        //freq 8 MHz
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "SPI_routinesd.h"
#include "SD_routinesd.h"
#include "UART_routinesd.h"
#include "FAT32d.h"


void port_init(void)
{
PORTA = 0x00;
DDRA  = 0x00;
PORTB = 0xEF;
DDRB  = 0xBF; //MISO line i/p, rest o/p
PORTC = 0x00;
DDRC  = 0x00;
PORTD = 0x00;
DDRD  = 0xFE;
}


//call this routine to initialize all peripherals
void init_devices(void)
{
 cli();  //all interrupts disabled
 port_init();
 spi_init();
 uart0_init();

 MCUCR = 0x00;
 GICR  = 0x00;
 TIMSK = 0x00; //timer interrupt sources
 //all peripherals are now initialized
}

//*************************** MAIN *******************************//
int main()
{
unsigned char option, error, data, FAT32_active;
unsigned int i;
unsigned char fileName[13];

_delay_ms(100);  //delay for VCC stabilization

init_devices();

PORTD |= 0x04; //switching ON the LED (for testing purpose only)

TX_NEWLINE;
TX_NEWLINE;
transmitString_F (PSTR("*********************************************"));
TX_NEWLINE;
transmitString_F (PSTR("    Dharmani's microSD Card Testing..  "));
TX_NEWLINE;
transmitString_F (PSTR("*********************************************"));
TX_NEWLINE;

cardType = 0;

for (i=0; i<10; i++)
{
  error = SD_init();
  if(!error) break;
}

if(error)
{
  if(error == 1) transmitString_F(PSTR("SD card not detected.."));
  if(error == 2) transmitString_F(PSTR("Card Initialization failed.."));

  while(1);  //wait here forever if error in SD init
}

switch (cardType)
{
  case 1:transmitString_F(PSTR("Standard Capacity Card (Ver 1.x) Detected!"));
           break;
  case 2:transmitString_F(PSTR("High Capacity Card Detected!"));
           break;
  case 3:transmitString_F(PSTR("Standard Capacity Card (Ver 2.x) Detected!"));
           break;
  default:transmitString_F(PSTR("Unknown SD Card Detected!"));
           break;
}


SPI_HIGH_SPEED;    //SCK - 4 MHz
_delay_ms(1);   //some delay


FAT32_active = 1;
error = getBootSectorData (); //read boot sector and keep necessary data in global variables
if(error)
{
  TX_NEWLINE;
  transmitString_F (PSTR("FAT32 not found!"));  //FAT32 incompatible drive
  FAT32_active = 0;
}

while(1)
{
TX_NEWLINE;
transmitString_F(PSTR("Press any key..."));
TX_NEWLINE;
option = receiveByte();
TX_NEWLINE;
transmitString_F(PSTR("> 0 : Erase Blocks"));
TX_NEWLINE;
transmitString_F(PSTR("> 1 : Write single Block"));
TX_NEWLINE;
transmitString_F(PSTR("> 2 : Read single Block"));

#ifndef FAT_TESTING_ONLY
TX_NEWLINE;
transmitString_F(PSTR("> 3 : Write multiple Blocks"));
TX_NEWLINE;
transmitString_F(PSTR("> 4 : Read multiple Blocks"));
#endif


TX_NEWLINE;
transmitString_F(PSTR("> 5 : Get file list"));
TX_NEWLINE;
transmitString_F(PSTR("> 6 : Read File"));
TX_NEWLINE;
transmitString_F(PSTR("> 7 : Write File"));
TX_NEWLINE;
transmitString_F(PSTR("> 8 : Delete File"));
TX_NEWLINE;
transmitString_F(PSTR("> 9 : Read SD Memory Capacity (Total/Free)"));

TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("> Select Option (0-9): "));


/*WARNING: If option 0, 1 or 3 is selected, the card may not be detected by PC/Laptop again,
as it disturbs the FAT format, and you may have to format it again with FAT32.
This options are given for learnig the raw data transfer to & from the SD Card*/

option = receiveByte();
transmitByte(option);

if(option >=0x35 && option <=0x39)  //options 5 to 9 disabled if FAT32 not found
{
  if(!FAT32_active)
  {
    TX_NEWLINE;
    TX_NEWLINE;
    transmitString_F(PSTR("FAT32 options disabled!"));
    continue;
  }
}


if((option >= 0x30) && (option <=0x34)) //get starting block address for options 0 to 4
{
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("Enter the Block number (0000-9999):"));
data = receiveByte(); transmitByte(data);
startBlock = (data & 0x0f) * 1000;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f) * 100;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f) * 10;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f);
TX_NEWLINE;
}

totalBlocks = 1;

#ifndef FAT_TESTING_ONLY

if((option == 0x30) || (option == 0x33) || (option == 0x34)) //get total number of blocks for options 0, 3 or 4
{
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("How many blocks? (000-999):"));
data = receiveByte(); transmitByte(data);
totalBlocks = (data & 0x0f) * 100;
data = receiveByte(); transmitByte(data);
totalBlocks += (data & 0x0f) * 10;
data = receiveByte(); transmitByte(data);
totalBlocks += (data & 0x0f);
TX_NEWLINE;
}
#endif

switch (option)
{
case '0': //error = SD_erase (block, totalBlocks);
          error = SD_erase (startBlock, totalBlocks);
          TX_NEWLINE;
          if(error)
              transmitString_F(PSTR("Erase failed.."));
          else
              transmitString_F(PSTR("Erased!"));
          break;

case '1': TX_NEWLINE;
          transmitString_F(PSTR(" Enter text (End with ~):"));
          i=0;
            do
            {
                data = receiveByte();
                transmitByte(data);
                buffer[i++] = data;
                if(data == 0x0d)
                {
                    transmitByte(0x0a);
                    buffer[i++] = 0x0a;
                }
                if(i == 512) break;
            }while (data != '~');

            error = SD_writeSingleBlock (startBlock);
            TX_NEWLINE;
            TX_NEWLINE;
            if(error)
                transmitString_F(PSTR("Write failed.."));
            else
                transmitString_F(PSTR("Write successful!"));
            break;

case '2': error = SD_readSingleBlock (startBlock);
          TX_NEWLINE;
          if(error)
            transmitString_F(PSTR("Read failed.."));
          else
          {
            for(i=0;i<512;i++)
            {
                if(buffer[i] == '~') break;
                transmitByte(buffer[i]);
            }
            TX_NEWLINE;
            TX_NEWLINE;
            transmitString_F(PSTR("Read successful!"));
          }

          break;
//next two options will work only if following macro is cleared from SD_routines.h
#ifndef FAT_TESTING_ONLY

case '3':
          error = SD_writeMultipleBlock (startBlock, totalBlocks);
          TX_NEWLINE;
          if(error)
            transmitString_F(PSTR("Write failed.."));
          else
            transmitString_F(PSTR("Write successful!"));
          break;

case '4': error = SD_readMultipleBlock (startBlock, totalBlocks);
          TX_NEWLINE;
          if(error)
            transmitString_F(PSTR("Read failed.."));
          else
            transmitString_F(PSTR("Read successful!"));
          break;
#endif

case '5': TX_NEWLINE;
            findFiles(GET_LIST,0);
          break;

case '6':
case '7':
case '8': TX_NEWLINE;
          TX_NEWLINE;
          transmitString_F(PSTR("Enter file name: "));
          for(i=0; i<13; i++)
            fileName[i] = 0x00;   //clearing any previously stored file name
          i=0;
          while(1)
          {
            data = receiveByte();
            if(data == 0x0d) break;  //'ENTER' key pressed
            if(data == 0x08)    //'Back Space' key pressed
             {
                   if(i != 0)
                   {
                     transmitByte(data);
                    transmitByte(' ');
                     transmitByte(data);
                     i--;
                   }
                   continue;
             }
            if(data <0x20 || data > 0x7e) continue;  //check for valid English text character
            transmitByte(data);
            fileName[i++] = data;
            if(i==13){transmitString_F(PSTR(" file name too long..")); break;}
          }
          if(i>12) break;

          TX_NEWLINE;
          if(option == '6')
             readFile( READ, fileName);
          if(option == '7')
               writeFile(fileName);
           if(option == '8')
             deleteFile(fileName);
          break;

case '9': memoryStatistics();
          break;

default: TX_NEWLINE;
         TX_NEWLINE;
         transmitString_F(PSTR(" Invalid option!"));
         TX_NEWLINE;
}

TX_NEWLINE;
}

return 0;
}

//********** END *********** www.dharmanitech.com *************

 

 

MAKE FILE 

 

 

# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
#                Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging, 
#              with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
#                   bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------


# MCU name
MCU = atmega64


# Processor frequency.
#     This will define a symbol, F_CPU, in all source code files equal to the 
#     processor frequency. You can then use this symbol in your source code to 
#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
#     automatically to create a 32-bit value in your source code.
#     Typical values are:
#         F_CPU =  1000000
#         F_CPU =  1843200
#         F_CPU =  2000000
#         F_CPU =  3686400
#         F_CPU =  4000000
#         F_CPU =  7372800
#         F_CPU =  8000000
#         F_CPU = 11059200
#         F_CPU = 14745600
#         F_CPU = 16000000
#         F_CPU = 18432000
#         F_CPU = 20000000
F_CPU = 16000000


# Output format. (can be srec, ihex, binary)
FORMAT = ihex


# Target file name (without extension).
TARGET =dar

# Object files directory
#     To put object files in current directory, use a dot (.), do NOT make
#     this an empty or blank macro!
OBJDIR = .


# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c
SRC = FAT32d.C
SRC = SD_routinesd.c
SRC = SPI_routinesd.c
SRC = UART_routinesd.c


# List C++ source files here. (C dependencies are automatically generated.)
CPPSRC = 


# 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 =


# Optimization level, can be [0, 1, 2, 3, s]. 
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s


# Debugging format.
#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
#     AVR Studio 4.10 requires dwarf-2.
#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2


# 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 = 


# Compiler flag to set the C Standard level.
#     c89   = "ANSI" C
#     gnu89 = c89 plus GCC extensions
#     c99   = ISO C99 standard (not yet fully implemented)
#     gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99


# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL


# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)


# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS

#---------------- Compiler Options C ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)


#---------------- Compiler Options C++ ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CPPFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)


#---------------- 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


#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt

# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB = 
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)


# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min

# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt

# 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 = 

#---------------- External Memory Options ----------------

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff

EXTMEMOPTS = 

#---------------- Linker Options ----------------
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -T linker_script.x

#---------------- Programming Options (avrdude) ----------------

# Programming hardware
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = usbasp

# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = usb

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep


# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y

# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V

# Increase verbosity level.  Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v

AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)

#---------------- Debugging Options ----------------

# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)

# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight

# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr

# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit

# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1

# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242

# 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

#============================================================================


# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd


# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = --------  end  --------
MSG_SIZE_BEFORE = Size before: 
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:


# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) 

# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) 


# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d


# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)

# Default target.
all: begin gccversion sizebefore build sizeafter end

# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib


elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)

# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
    @echo
    @echo $(MSG_BEGIN)

end:
    @echo $(MSG_END)
    @echo


# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf

sizebefore:
    @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
    2>/dev/null; echo; fi

sizeafter:
    @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
    2>/dev/null; echo; fi

# Display compiler version information.
gccversion : 
    @$(CC) --version

# Program the device.  
program: $(TARGET).hex $(TARGET).eep
    $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)


# Generate avr-gdb config/init file which does the following:
#     define the reset signal, load the target file, connect to target, and set 
#     a breakpoint at main().
gdb-config: 
    @$(REMOVE) $(GDBINIT_FILE)
    @echo define reset >> $(GDBINIT_FILE)
    @echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
    @echo end >> $(GDBINIT_FILE)
    @echo file $(TARGET).elf >> $(GDBINIT_FILE)
    @echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
    @echo load  >> $(GDBINIT_FILE)
endif
    @echo break main >> $(GDBINIT_FILE)

debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
    @echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
    @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
    $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
    @$(WINSHELL) /c pause

else
    @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
    $(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
    @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)


# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000

coff: $(TARGET).elf
    @echo
    @echo $(MSG_COFF) $(TARGET).cof
    $(COFFCONVERT) -O coff-avr $< $(TARGET).cof


extcoff: $(TARGET).elf
    @echo
    @echo $(MSG_EXTENDED_COFF) $(TARGET).cof
    $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof

# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
    @echo
    @echo $(MSG_FLASH) $@
    $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock $< $@

%.eep: %.elf
    @echo
    @echo $(MSG_EEPROM) $@
    -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
    --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0

# Create extended listing file from ELF output file.
%.lss: %.elf
    @echo
    @echo $(MSG_EXTENDED_LISTING) $@
    $(OBJDUMP) -h -S -z $< > $@

# Create a symbol table from ELF output file.
%.sym: %.elf
    @echo
    @echo $(MSG_SYMBOL_TABLE) $@
    $(NM) -n $< > $@

# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
    @echo
    @echo $(MSG_CREATING_LIBRARY) $@
    $(AR) $@ $(OBJ)


# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
    @echo
    @echo $(MSG_LINKING) $@
    $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)


# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
    @echo
    @echo $(MSG_COMPILING) $<
    $(CC) -c $(ALL_CFLAGS) $< -o $@ 


# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
    @echo
    @echo $(MSG_COMPILING_CPP) $<
    $(CC) -c $(ALL_CPPFLAGS) $< -o $@ 


# Compile: create assembler files from C source files.
%.s : %.c
    $(CC) -S $(ALL_CFLAGS) $< -o $@


# Compile: create assembler files from C++ source files.
%.s : %.cpp
    $(CC) -S $(ALL_CPPFLAGS) $< -o $@


# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
    @echo
    @echo $(MSG_ASSEMBLING) $<
    $(CC) -c $(ALL_ASFLAGS) $< -o $@


# Create preprocessed source for use in sending a bug report.
%.i : %.c
    $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 


# Target: clean project.
clean: begin clean_list end

clean_list :
    @echo
    @echo $(MSG_CLEANING)
    $(REMOVE) $(TARGET).hex
    $(REMOVE) $(TARGET).eep
    $(REMOVE) $(TARGET).cof
    $(REMOVE) $(TARGET).elf
    $(REMOVE) $(TARGET).map
    $(REMOVE) $(TARGET).sym
    $(REMOVE) $(TARGET).lss
    $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
    $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
    $(REMOVE) $(SRC:.c=.s)
    $(REMOVE) $(SRC:.c=.d)
    $(REMOVE) $(SRC:.c=.i)
    $(REMOVEDIR) .dep


# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)


# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)


# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config

 

Last Edited: Wed. Oct 8, 2014 - 08:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    undefined reference to `main'

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi , 

 

I did -save-temps to CFLAGS ( marked bold ) but no dar.i file  in the build directory .??? 

 

CFLAGS = -g$(DEBUG) 
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS +=-save-temps

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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:

SRC = $(TARGET).c
SRC = FAT32d.C
SRC = SD_routinesd.c
SRC = SPI_routinesd.c
SRC = UART_routinesd.c

to be:

SRC = dar.c
SRC = FAT32d.C
SRC = SD_routinesd.c
SRC = SPI_routinesd.c
SRC = UART_routinesd.c

EDIT: oh wait a minute. I see your problem now. SRC= is supposed to be a list of all the .c files in the project. You can achieve that with either:

SRC = dar.c FAT32d.C SD_routinesd.c SPI_routinesd.c UART_routinesd.c

or

SRC = dar.c
SRC += FAT32d.C
SRC += SD_routinesd.c
SRC += SPI_routinesd.c
SRC += UART_routinesd.c

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.

Last Edited: Wed. Apr 15, 2015 - 07:02 PM