Sunday, April 7, 2013

atmega8 flash sound player source code


This code is from project: 8 bit sound player

main.h



#ifndef _H_MAIN_
#define _H_MAIN_

#define  F_CPU 8000000L

#define H(a,b) a |=(1<<(b))
#define L(a,b) a &=~(1<<(b))
#define IS(a,b) bit_is_set(a,b)
#define BS(a,b) (a & (1<<(b)))

#endif


#ifndef F_CPU
   #error CPU speed unknown
#endif


main.c


#include "main.h"
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>


// for SPI
#define SPI_PORT  PORTB
#define SPI_DDR   DDRB

#define SPI_SS    PB2

#define SPI_SI    PB3
#define SPI_SO    PB4
#define SPI_SCK   PB5


// for flash
#define S1  1  // sound start page
#define S2  64
#define S3  84


// for delay
#define nop()  __asm__ __volatile__("nop")


/****************************************************************************/
/* Declarations (this shoud be in .h file).                                 */
/****************************************************************************/
void delay_ms(unsigned short);
void delay_us(unsigned short);

void disable();
void enable();
void initSPI();
uint8_t write(uint8_t);

void play(uint16_t);

void initPWM();


/****************************************************************************/
/* Main function                                                            */
/****************************************************************************/
int main()
{
       
//    while(1);   // when programming flash from raspberry, this should
               // be uncommented, otherwise, amtega8 will disturb whole
               // operation
   
   initSPI(); 
   initPWM();

   while(1) {
      play(S1);      // play sound one  
      delay_ms(200); // delay
      play(S2);   
      delay_ms(200);
      play(S3);   
   };      

   return 0;
}


/****************************************************************************/
/* Delay functions                                                          */
/****************************************************************************/
void delay_ms(unsigned short ms) {
    while ( ms ) {
      ms--;
      _delay_ms(1);
   }
}

void delay_us(unsigned short us) {
    while ( us ) {
      us--;
      _delay_us(1);
   }
}


/****************************************************************************/
/* SPI functions.                                                           */
/****************************************************************************/
void disable() {
   H(SPI_PORT, SPI_SS); // logic '1' on Chip Select mens 'disable slave'
}


void enable() {
   H(SPI_PORT, SPI_SS); // logic '1->0' change means 'enable slave'
   L(SPI_PORT, SPI_SS);
}


void initSPI() {

   H(SPI_DDR, SPI_SS);  // set directoins on pins
   H(SPI_DDR, SPI_SI);
   L(SPI_DDR, SPI_SO);
   H(SPI_DDR, SPI_SCK);

   SPSR = (1<<SPI2X);   // set SPI specified registers
   SPCR = (1<<SPE) | (1<<MSTR) | (1 << SPR1) | (1 << SPR0);

   disable();           // make sure to disable at init
}


uint8_t write(uint8_t data) {
   SPDR = data;
   while(!(SPSR & (1 << SPIF)));
   return SPDR;
}


/****************************************************************************/
/* PWM/SPI functoins                                                        */
/****************************************************************************/
void play(uint16_t addr) {
   
   enable();   // enable SPI slave (Chip Select)

   // continous read from Flash memmory (check datasheet)
   write(0x03);

   // move to current page
   write( (addr >> 7) & 0x1F ); 
   write( ((uint8_t) (addr << 1) & 0xFF) | (0 & 0x01) ); 

   // move to current byte in page (here is 0, no offset)
   write( (uint8_t) 0);

   // play loop
   while(1) {

      // read one byte from flash memory, and write it directly
      // to OCR1A register
      OCR1A = write(0x00);

      // found End Of Sound flag
      if(OCR1A == 0)
         break;      
        
      // SPI is in x2 mode, so slow down here 
      delay_us(17);
   }
   disable();  // disable SPI slave
}


/****************************************************************************/
/* PWM functions.                                                           */
/****************************************************************************/
void initPWM() {   
   H(DDRB, PB1);  

   // values below are experimental 
   TCCR1A = (1<<COM1A1) | (1<<COM1A0) |  (1<<WGM10);
   TCCR1B = (1<<CS10) | (1<<WGM12);
   OCR1A = 0;
}

Makefile


CPU=atmega8

GCC=avr-gcc
CFLAGS= -Os -mmcu=$(CPU) -Wall -fpack-struct -fshort-enums -funsigned-bitfields -Wl,--relax -fno-move-loop-invariants -funsigned-char -fno-inline-small-functions -fdata-sections -fno-tree-loop-optimize -lprintf_min 

INCLUDES=
LIBS=

OBJCPY=avr-objcopy
OBJECTS=main.o 

PROJECT_NAME=mega8
HEX_FILE=$(PROJECT_NAME).hex
HEX_FILE_DUMP=$(PROJECT_NAME)_dump.hex

PROG=uisp
PROG_FLAGS=-dprog=dapa 

all:    cls $(PROJECT_NAME) obj size #upload

$(PROJECT_NAME):    $(OBJECTS)
        $(GCC) -o $(PROJECT_NAME) $(OBJECTS) $(CFLAGS) $(LIBS) $(INCLUDES)

main.o:    main.c main.h
        $(GCC) $(CFLAGS) $(INCLUDES) -c main.c

obj:    $(OBJECTS)
        $(OBJCPY) -O ihex $(PROJECT_NAME) $(HEX_FILE)

clean:
        rm -f $(PROJECT_NAME) $(OBJECTS) $(HEX_FILE)

cls:
        clear

size:
        du -b $(HEX_FILE) 

upload: all $(HEX_FILE)
        $(PROG) $(PROG_FLAGS) --erase --upload if=$(HEX_FILE)

download:
        $(PROG) $(PROG_FLAGS) --download of=$(HEX_FILE_DUMP)

No comments:

Post a Comment