Závěrečný projekt MMIA - Generátor hudby

František Nepor, Adam Pišl

Obsah:

  1. Úvod
  2. Realizace
  3. Závěr
  4. Literatura

Úvod

Cílem projektu bylo prozkoumat možnosti generování melodií s pomocí mikrokontroléru Atmel AVR ATmega16. Program počítá s jednoduchým zadáváním přehrávané melodie a možností kalibrace při použití jiného krystalu než 16MHz. Přehrávaná melodie se stále dokola opakuje.

Realizace

Celý projekt je řešen na vývojové desce ATmega16 použivané ve cvičeních předmětu MMIA vyvinuté panem Šebestou. K projektu nebyly potřeba žádné další desky. Použitý je pouze reproduktor připojený na Port D na pin 7.

Základem programu je generátor tónu o definované prekvenci tvořený 16b čítačem 1. V obsluze přetečení tohoto časovače je negována hodnota na vnějším pinu mikrokontroléru, na kterém se nachází reproduktor. O správný výběr předvolby pro časovač 1 se stará program v hlavní smyčce. Časovač 0 se stará o správné dodržení délky jednotlivých tónů. Tento časovač je pomocí proměnné typu int ještě rozšířen na celkových 24b, aby bylo možné zpracovávat časy dostatečné délky.
Program přehrává uloženou melodii stále dokola. Průběh programů je patrný z následujících vývojových diagramů.

Vývojový diagram hlavního programu

Vývojový diagram obsluhy přerušení
časovače 1

Vývojový diagram obsluhy přerušení
časovače 0

Vložení do stávajícího programu je velice jdnoduché, stačí přilinkovat programovou knihovnu, knihovnu s melodiemi a nadefinovat správný port a pin, na kterém bude připojen reproduktor. Následuje ukázka zkušebního hlavního programu:

      #include <avr/io.h>
      #include <avr/interrupt.h>

      #define PortReproDir DDRD       // určení řídícího registru portu na kterém je reproduktor (DDRx)
      #define PortRepro PORTD         // určení portu na kterém je reproduktor (PORTx)
      #define PinRepro 7              // určení pinu portu na kterém je reproduktor (0 - 7)
      #define F_OSC 8000000           // určení kmitočtu taktovacího oscilátoru

      #include "Generator.c"          // knihovna programu
      #include "melodie.h"            // zdroj ukázkových melodií

      void main(void)                 // program přehraje ukázkové melodie a skončí v nekonečné smyčce
      {
       Prehraj(Ovcaci_Ctveraci);
       Prehraj(Arkanoid);
       Prehraj(Nesem_Vam_Noviny);
       Prehraj(Stedrej_Vecer);

       while(1);
      }
      

Program je vypracován tak, aby bylo možno jednoduchým způsobem změnit přehrávanou melodii. Z toho důvodu je pole obsahující zápis melodie vloženo v samostatném souboru, který je pak do programu vložen.
Zápis melodie se skládá z dvojic bytů, následujících po sobě.
První řádek každé melodie určuje rychlost přehrávání (tempo). Horní nibble prvního bytu určuje rychlost (1 - pomala, 2 - rychleji, ...), spodní nibble prvního bytu musí být 0xF. Druhý byte může být cokoliv.
Další řádky určují jednotlivé noty. Horní nibble prvního bytu je oktáva (0x1 - 0x3), dolní nibble prvního bytu je půltón (0x1 - C, 0x2 - C#, ..., 0xC - H). Pomlka se zadává 0x00 v prvním bytu. Druhý byte určuje délku noty nebo pomlky (0x1 - celá, 0x2 - půlová, 0x4 - čtvrťová, ....).
Přehrávání se ukončí bytem 0xFF.

Příklad melodie:

	char melodie[] = {
	0x1F, 0x01, // nastavení rychlosti 1

	0x00, 0x01, // pomlka, celá

	0x23, 0x04, // 2. oktáva, tón D, čtvrťová
	0x27, 0x04, // 2. oktáva, tón Fis, čtvrťová 
			
	0x28, 0x08, // 2. oktáva, tón G, osminová
	0x27, 0x08, // 2. oktáva, tón Fis, osminová
	0x25, 0x04, // 2. oktáva, tón E, čtvrťová

	0xFF }; // konec melodie 
				
Tabulka zápisu tónů:

TÓN C C# D D# E F F# G G# A A# H
ZÁPIS 0x*1 0x*2 0x*3 0x*4 0x*5 0x*6 0x*7 0x*8 0x*9 0x*A 0x*B 0x*C

Závěr

Program byl úspěšně odzkoušen na vývojvé desce i na vlastním testovacím procesoru ATmega16 se dvěma různými krystaly (8 a 16MHz). Použití interního RC oscilátoru 1MHz vedlo k nesprávné funkci, tento kmitočet je příliš nízký.
Jako vhodné doplnění programu by byla možnost rozšířit program a možnost zápisu vlastní melodie, s využitím znakového LCD a tlačítek.
Bylo zjištěno že použitelný rozsah melodií je asi tři oktávy, při většim rozsahu se již uplatňují odchylky frekvencí způsobené celočíselnou aritmetikou. Toto by bylo možné kompenzovat rozšířením kalibračních konstant samostatně pro každou oktávu.

Zdrojový projekt ke stažení

Literatura

[1] Atmel ATmega16 Datasheet. Atmel Corp., Dostupné z http://www.atmel.com, USA, 2008
[2] FRÝZA T., FEDRA Z., ŠEBESTA J., Mikroprocesorová technika, laboratorní cvičení. FEKT VUT, Brno, 2008
[3] Matematické fyzikální a chemické tabulky pro střední školy. SPN, Praha, 1988