I'm learning assembler AVR and found it confusing, this simple program below is using two timers, TIMER1 is used to make "OC1" to vibrate at certain frequency (CTC and toggles OC1), TIMER0 is used to start an interrupt at certain intervals, this interrupt is loading bytes from SRAM and modifies the OCR1AL to change frequency. (to play a melody) Everything works ok only at specific TIMER1 intervals, when i change the OCR0 to longer or shorter intervals some notes are missing, any idea why ? Another problem is the last note that is stored to the memory is not being loaded as the first one by the interrupt, i have to store one extra (empty or whatever value) to match the st Z+ with ld -Z. What i do wrong ? Thanks
the chip im using is the Atmega32a
/*
* Melody.asm
*
* Created: 03/04/14 8:17:54 PM
* Author: Michal
*/
.equ MelodyStartAddr = 0x0301
.equ NoteC1 = 0xEF // C
.equ NoteD1 = 0xD4 // D
.equ NoteE1 = 0xBD // E
.equ NoteF1 = 0xB3 // F - 5 698 Hz
.equ NoteG1 = 0x9F // G
.equ NoteA1 = 0x8E // A
.equ NoteH1 = 0x7E // H
.equ NoteC2 = 0x77 // C
.def Temp = r16
.def TempH = r17
.def Zero = r0
.def Max = r1
//.cseg
.org 0x000
rjmp Start1
.org 0x014
jmp ChangeNote
Start1:
sei
ldi Temp, HIGH(RAMEND)
out SPH, Temp
ldi Temp, LOW(RAMEND)
out SPL, Temp
ldi Temp, 0b11111111 //
out DDRD, Temp
ldi YH, HIGH(MelodyStartAddr)
ldi YL, LOW(MelodyStartAddr)
ldi Temp, 0x00 // END
st Z+, Temp
ldi Temp, NoteE1
st Z+, Temp
ldi Temp, NoteE1
st Z+, Temp
ldi Temp, NoteE1
st Z+, Temp
ldi Temp, NoteE1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteG1
ldi Temp, NoteG1
st Z+, Temp
ldi Temp, NoteG1
st Z+, Temp
ldi Temp, NoteA1
st Z+, Temp
ldi Temp, NoteG1
st Z+, Temp
ldi Temp, NoteG1
st Z+, Temp
ldi Temp, NoteG1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteA1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteF1
st Z+, Temp
ldi Temp, NoteG1
st Z+, Temp
ldi Temp, NoteA1
st Z+, Temp
ldi Temp, NoteA1
st Z+, Temp
ldi Temp, NoteC2
st Z+, Temp
ldi Temp, NoteA1
st Z+, Temp
ldi Temp, NoteA1
st Z+, Temp
ldi Temp, NoteA1
st Z+, Temp
ldi Temp, NoteC2
st Z+, Temp
ldi Temp, NoteC2
st Z+, Temp
ldi Temp, NoteC2
st Z+, Temp
ldi Temp, NoteC2 // This is the extra Note that is not loaded in the interrupt
st Z+, Temp
// ************* TIMER 1 ***********************
ldi Temp, 0b01000000 // toggle oc1
out TCCR1A, Temp
ldi Temp, 0b00001010 // WGM11, prescaler x8
out TCCR1B, Temp
ldi Temp, 0x00
out OCR1AH, Temp
//********** TIMER 0*******************************
ldi Temp, 0b00011101 // 0b00011011 x64
OUT TCCR0, Temp
ldi Temp, 0xea // Speed Works with 0xef, but not with 0xaf or 0xff or 0xea, any idea ?
out OCR0, Temp
ldi Temp, 0b00000010
OUT TIMSK, Temp
Loop:
nop
rjmp Loop
ChangeNote:
push Temp
in Temp, SREG
push Temp
ldi Temp, 0x00
out OCR1AH, Temp
ld Temp, -Z
cpi Temp, 0x00
breq StopPlaying
out OCR1AL, temp
pop Temp
out SREG, Temp
pop Temp
reti
StopPlaying:
ldi Temp, 0x00
out TIMSK, Temp
ldi Temp, 0b00000000 // toggle oc1
out TCCR1A, Temp
ret
Delay:
clr R1
ldi TempH, 0xaf
mov R2, TempH
DelayLoop:
dec R1
brne DelayLoop
clr R1
dec R2
brne DelayLoop
ret