Comp24
My computer for year 2024
Sound
2026.05.21 04:00:32 end MHF Gilhad

1   Sound

Pro generování tónů na pozadí potřebuju nějaký nepoužitý Timer a jeho pin, se kterým můžu kmitat.

Piny jsou použity všechny. Ale asi nejmíň to bude vadit na portu L, kde jsou adresy pro Shared RAM, kterou zrovna nepoužívám (až MHF bude grafickou kartou, tak to moc nepůjde).

Je to "zneužití", takže budeme předpokládat, že může být kdykoli odstřeleno, tudíž provedu inicializaci při každém spuštění a kdokoli kdykoli může spustit stop.

Princip

Frekvence na OC5A:

f_OUT = f_CPU / (2*N*(1+OCR5A))

a obráceně

OCR5A= f_CPU / (2*N*f_OUT) - 1

kde:

  • f_CPU = 16 MHz
  • N = prescaler
  • OCR5A = compare registr

Použijeme prescaler 8, protože dobře vychází pro audio tóny.

;
; sound.S
; ATmega2560
; OC5A = PL3
;

#include <avr/io.h>

.global sound_init
.global sound_play
.global sound_stop

; ============================================================
; sound_init
; ============================================================
sound_init:

        ; PL3 / OC5A jako output
        sbi DDRL, 3

        ; Timer stopped
        ldi r16, 0
        sts TCCR5A, r16
        sts TCCR5B, r16

ret

; ============================================================
; sound_play
;
; vstup:
;   r25:r24 = OCR5A hodnota
;
; ============================================================
sound_play:

// sound_init:

        ; PL3 / OC5A jako output
        sbi DDRL, 3

//      ; Timer stopped - rovnou ho rozebehnu o kousek niz
//      ldi r16, 0
//      sts TCCR5A, r16
//      sts TCCR5B, r16
        ; nastavit compare value
        sts OCR5AL, r24
        sts OCR5AH, r25

        ;
        ; Toggle OC5A on compare match
        ;
        ; COM5A0 = 1
        ;
        ldi r24, (1<<COM5A0)
        sts TCCR5A, r24

        ;
        ; CTC mode
        ; WGM52 = 1
        ;
        ; prescaler = 8
        ; CS51 = 1
        ;
        ldi r24, (1<<WGM52) | (1<<CS51)
        sts TCCR5B, r24

ret

; ============================================================
; sound_stop
; ============================================================
sound_stop:

        ; stop timer
        ldi r24, 0
        sts TCCR5B, r24

        ; disconnect OC5A
        sts TCCR5A, r24

        ; output low
        cbi PORTL, 3

ret

2   Tabulka tónů

Pro F_CPU = 16 MHz, prescaler 8.

Tyto hodnoty dáváš do OCR5A.

;
; Tone table
;

.equ NOTE_C4  = 3821
.equ NOTE_CS4 = 3607
.equ NOTE_D4  = 3405
.equ NOTE_DS4 = 3214
.equ NOTE_E4  = 3033
.equ NOTE_F4  = 2863
.equ NOTE_FS4 = 2702
.equ NOTE_G4  = 2551
.equ NOTE_GS4 = 2407
.equ NOTE_A4  = 2272
.equ NOTE_AS4 = 2145
.equ NOTE_B4  = 2024

.equ NOTE_C5  = 1911
.equ NOTE_D5  = 1702
.equ NOTE_E5  = 1516
.equ NOTE_F5  = 1431
.equ NOTE_G5  = 1275
.equ NOTE_A5  = 1136
.equ NOTE_B5  = 1012

Jak přehrát tón

Například A4 (440 Hz):

ldi r24, low(NOTE_A4)
ldi r25, high(NOTE_A4)
rcall sound_play

Jak tón vypnout

rcall sound_stop

3   HW

  • Test na beeper 4312 zapojeny na Timer 1A pin D9 na Arduino Nano
  • Zapojeni pin -- beeper -- +5V funguje
  • Zapojeni pin -- emitor NPN , colector -- beeper -- +5V je hlasitejsi
  • pridavani odporu to ztisuje, diodu to taky nepotrebuje.