Full Version : HOW TO BEEP BUTTERFLY SPEAKER
avr >>BEGINNERS & BUTTERFLIES >>HOW TO BEEP BUTTERFLY SPEAKER


AVR_Admin- 04-12-2006
ASSEMBLER PROGRAM: BEEP.ASM

AUTHOR: RETRODAN

PURPOSE:

Emit a Sound from Built-In Speaker on Butterfly using AVR Native Machine Language.

PREAMBLE:

As a new comer to AVR programming, when I got my first Butterfly, the first program I wanted to write was the simple "Hello World" program. However after days of total confusion trying to figure out how to use the LCD screen from the data sheets. The Butterfly does not have any LEDs I can blink (although I could have connection one easy enough) I decided that my first effort would be a program that made a sound come from the on board speaker.

UPDATE:

The initial program read the PORTB into memory, changed reversed BIT 5 and wrote the result back out to PORTB. I later found the the AVR Machine Language has instructions that allow one to just change the bits on a port. I have update the following program to use this much better method of activating and deactivating the speaker line on Pin #5 of Port B.

NOTE: An explanation of the program follows the listing.

THE PROGRAM:

CODE

;---------------------------------------------------.;
; BEEP.AMS for AVR BUTTERFLY MAKE THAT FAMOUS SOUND .;
; BY:RETRODAN  CREATED:01-MAR-06 UPDATED:28-MAR-06  .;    
;---------------------------------------------------.;

.INCLUDE "M169DEF.INC";(BUTTERFLY DEFINITIONS)

;----------------------------------------;
; FIRST I'LL DEFINE SOME REGISTER TO USE.;
;----------------------------------------;
.DEF A = R16  ;GENERAL PURPOSE ACCUMULATOR
.DEF I = R21  ;INDEXES FOR LOOP CONTROL
.DEF J = R22

.ORG 0000
   RJMP ON_RESET;REBOOT/START-UP VECTOR  
                 ;INTO OUR PROGRAM

;-----------------------------------------;
; WE START HERE ON ALL RESEST AND REBOOTS.;
; FIRST WE SETUP A STACK AREA THEN SET   .;
; DIRECTION BIT FOR PORT-B FOR OUTPUT    .;
;-----------------------------------------;
START:
ON_RESET:
   LDI A,LOW(RAMEND)  ;SETUP STACK POINTER
   OUT SPL,A          ;SO CALLS TO SUBROUTINES
   LDI A,HIGH(RAMEND);WORK CORRECTLY
   OUT SPH,A
   SBI DDRB,5    ;PORTB PIN 5 FOR OUTPUT

;--------------;
; MAIN ROUTINE.;
;--------------;
BEEP: CLR I
BLUPE:
    SBI  PORTB,5  ;SPKR ON
    RCALL PAUSE  ;WAIT
    CBI  PORTB,5  ;SPKR OFF
    RCALL PAUSE  ;WAIT
    DEC I
     BRNE BLUPE

LOOP: RJMP LOOP;DONE

;---------------.;
; PAUSE ROUTINE .;
;---------------.;
PAUSE: NOP  
      DEC J              
       BRNE PAUSE
        RET


AVR_Admin- 04-12-2006
TITLE: HOW TO BEEP THE BUTTERFLY SPEAKER

BREAKDOWN AND EXPLANATION OF THE PROGRAM:

CODE

.INCLUDE "M169DEF.INC";(BUTTERFLY DEFINITIONS)

The first thing we do is read-in the Atmel file that defines all the constants and parameters for the chip we are writing for. The Butterfly uses an Atmega169 so that's the file we use.


CODE

.DEF A = R16  ;GENERAL PURPOSE ACCUMULATOR
.DEF I = R21  ;INDEXES FOR LOOP CONTROL
.DEF J = R22

Next we give names to the registers (accumulators) we are using. The A register is for general use and the I & J are counters for loop control.


CODE

.ORG 0000

Here we tell the Assembler(Compiler) that we want our program to start at the beginning of Flash (Program Memory) and that is what the .ORG 0000 directive does.


CODE

   RJMP ON_RESET ;REBOOT/START-UP VECTOR    

When the AVR chips are first powered-up or reset they go to the first location in program memory and excecute whatever is there. Since there are usually other "interupt" vectors that appear after this line in more complex programs, it is good practice not to start your actual program at this location, but rather insert a line of code that jumps to the first line of your program. That is what we are doing here. There's no real reason for it here. It does not accomplish anything other than sticking to that programming convention.


CODE

ON_RESET:
   LDI A,LOW(RAMEND)  ;SETUP STACK POINTER
   OUT SPL,A          ;SO CALLS TO SUBROUTINES
   LDI A,HIGH(RAMEND) ;WORK CORRECTLY
   OUT SPH,A

Before we can call a subroutine, we need a stack to hold our return addresses. To do this we use the constant RAMEND which is defined in the file m169def.inc that we loaded earlier.

RAMEND is set to the last memory address in SRAM. Typically stacks are placed at the top-of-memory and are allowed to grow downwards and that is what we are doing here. We load the low-byte of that address into the low-byte of stack pointer, and then do the same with the high byte.


CODE

   SBI DDRB,5    ;PORTB PIN 5 FOR OUTPUT

From looking over the schematics for the Butterfly, it looked like the speaker was attached to PIN #5 on PORT B.

Since AVR ports can be set-up for either input or output, we need to inform the hardware that we are going to use PIN #5 on Port B as an output so we send a logic one to the Data Direction Register for port B (DDRB).


CODE

;--------------;
; MAIN ROUTINE;
;--------------;
BEEP: CLR I
BLUPE:
    SBI  PORTB,5  ;SPKR ON
    RCALL PAUSE   ;WAIT
    CBI  PORTB,5  ;SPKR OFF
    RCALL PAUSE   ;WAIT
    DEC I
     BRNE BLUPE

This is the Main Loop of the program. We set a Counter to Zero and at the end of the loop we subtract one and stop when we roll-over to Zero again, so the loop will exectute 255 times.

Inside the Loop we write a logic one to Pin #5 of Port B, wait, then send a logic Zero, then wait and loop around. This will produce a square wave from our speaker, the frequency is determined by our clock speed (normally 2Mhz for the Butterfly) and also by the amount of time we spend wasting time inside our PAUSE rotuine.

CODE

LOOP: RJMP LOOP;DONE

What do we do after we're done? I could have drove you crazy by having the program loop-back and start over, making your Butterfly beep continuously over-and-over again. Instead I just lock it into an infinite loop that does nothing but loop-back to itself.


CODE

;----------------;
;PAUSE ROUTINE  ;
;----------------;
PAUSE: NOP    
      DEC J                
       BRNE PAUSE
        RET

This is the Pause Routine that will determine the frequency of the BEEP that will come from your speaker.

We are decrementing a counter (J) until it reaches Zero. In the mean time we're executing a NOP (No OP) that does nothing 255 times. You can increase or lower the frequency by adding to removing NOPs from inside that loop.

NOTE: (Dirty Programming Trick) Normally you are "supposed-to" always initialize the J counter to Zero on each call but I "cheated" with a "Dirty Trick" to save one program step because I know it will be Zero from the previous call to this very routine and only time I might be in error is on the very first call. If you use such 'Dangerous Tricks" remember that the register (J) cannot be used anywhere else or its "default" value of Zero could get changed.

You can also change the frequency of the "Beep" by initializing the J-Register yourself to something other than Zero each time the routine is called.

Have fun turning your Butterfly into a hand-held R2D2 unit...Beep, Beep, Bloop!

AVR_Admin- 04-12-2006
CONTINUING EDUCATION:

If you would like to learn more about the Butterfly I recommend the Butterfly, STK502 and ATmega169 PDF files available as a free download from the Atmel Site at www.atmel.com.

REQUEST FOR FEED-BACK:

If you find this posting educational and would like to see more like it, please post a response in this thread.

Thank you for your time and consideration.

Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.