; *** PiepserAsm 1.0 (c) Oliver Mezger 3.7.2014
; Spielt eine Melodie aus dem Programmspeicher
; fuer melodieIndex<-0 bis ende
; Periodendauer = tone[melodie[melodieIndex]]
; Impulslaenge = Periodendauer / 2

.include "tn2313def.inc"

.equ cpuClk = 1000000   ; Taktfrequenz
.def null = R2
.def tmp = R16
.def tmpH = R17
.def melodieIndex = R18
.def warte = R19
.def aussen = R20
.def innen = R21

reset:
  ldi tmp, low(RAMEND)  ; Stackpointer initialisieren
  out SPL,tmp
  ldi tmp, 0b00010000   ; PB4 als Ausgang
  out DDRB, tmp
  ldi tmp, 0b00100011   ; Ausgang OC1B bei 0 setzen und bei OCR1B loeschen
  out TCCR1A, tmp
  ldi tmp, 0b00011001   ; Waveform Generation Mode: Fast PWM mit OCR1A als Top
  out TCCR1B,tmp        ; Timer mit CPU-CLK
  ldi warte, 150        ; Tonlaenge in ms
  
spielInit:
  ldi melodieIndex,0
spiel:
  ldi ZH, high(melodie*2) ; lade Tabellenanfang melodie[]
  ldi ZL, low(melodie*2)
  add ZL,melodieIndex     ; addiere melodieIndex
  adc ZH,null             ; addiere Uebertrag
  lpm tmp,Z               ; lade den Ton
  lsl tmp                 ; nimm mal 2 da toene 2 Byte haben
  ldi ZH, high(tone*2)    ; lade Tabellenanfang tone[]
  ldi ZL, low(tone*2)
  add ZL, tmp             ; addiere ton
  adc ZH,null             ; addiere Uebertrag
  lpm tmp,Z+              ; lade low von tone[ton]
  lpm tmpH,Z              ; lade high
  out OCR1AH, tmpH        ; speichere zuerst High
  out OCR1AL, tmp         ; speichere dann Low
  lsr tmpH                ; /2 durch rechtsschieben Bit 0 in Carry
  ror tmp                 ; teile durch 2 aber schiebe Carry oben rein
  out OCR1BH, tmpH        ; speichere zuerst High
  out OCR1BL, tmp         ; speichere dann Low
  rcall warte_ms          ; warte
  rcall warte_ms          ; warte
  inc melodieIndex        ; naechster Ton
  cpi melodieIndex,(endeMelodie-melodie)*2-1 ; Assembler berechnet Laenge der Melodie
  brge spielInit          ; wieder zum Anfang
  rjmp spiel

warte_ms:                ; warte ms warten
  mov aussen,warte
loop_aussen:
  ldi innen,250
loop_innen:
  dec innen
  nop
  brne loop_innen
  dec aussen
  brne loop_aussen
  ret

; Tabelle mit Periodendauer von c' bis h'' mit Halbtoenen
tone: .dw cpuClk/264,cpuClk/275,cpuClk/297,cpuClk/317,cpuClk/330,cpuClk/352
      .dw cpuClk/367,cpuClk/396,cpuClk/422,cpuClk/440,cpuClk/475,cpuClk/495
      .dw cpuClk/2/264,cpuClk/2/275,cpuClk/2/297,cpuClk/2/317,cpuClk/2/330,cpuClk/2/352
      .dw cpuClk/2/367,cpuClk/2/396,cpuClk/2/422,cpuClk/2/440,cpuClk/2/475,cpuClk/2/495
; Tabelle mit Melodie
melodie: .db 0,2,5,0,0,2,5,5,6,8,5,6,8,8,10,8,6,0,2,0
endeMelodie: ; Label fuer Ende der Melodie 