Dallamcsengő Arduinóval

 

2020-07-12

A Rádiótechnika 1987/2 számában, Kinczel András tollából jelent meg egy Z80 mikroprocesszorra épülő dallamcsengő leírása. Annak idején ez eléggé közkedvelt volt, én is megépítettem. A fiam meg megtalálta a kacatjaim között. Nézegettem, hogyan lehetne felújítani, de végül arra jutottam, mai eszemmel, jobb ha nem játszunk vele. Annak idején magasra fel volt szerelve a falra, de azóta kényesebb vagyok a biztonságra. Z80. Régi szép emlékek. 4 MHz órajel, 4 órajelenként egy művelet. RAM-ot, EPROM-ot soros portot, számláló/időzítőt külön mellé kellett rakni. Viszont sokkal jobb volt az Intel 8080-nál, annak kellett +/-5V, +12V... A Z80 áramfelvétele olyan 3-400mA körül volt, talán még N-MOS technológiával készült. De lehet, hogy már nem jól emlékszem. Mindegy is, annak idején ezek a kis csodák működtek, de ma már van Arduinónk, amik 2-3 USD ellenében messze lekőrözik ezeket az öreg paripákat... Másokat sem hagy teljesen hidegen a dallamcsengő ideája, mert a Google segítségével sikerült fórumok bugyraiból előkurkászni a Z80-as kód dump-ját, különböző írásokat ezzel kapcsolatban.

Most külön rajzot, fényképet nem készíttettem az áramkörről, csupán egy PC alaplapról kukázott hangszórót akasztottam az Arduinom D3-as lábára. Az alább látható program, csak egy dalt játszik le. A lap alján lévő linkről az összes dalt tartalmazó verzió letölthető. Az eredeti program mindig váltott, és a következő zenét játszotta. Remélem az alábbi mintaprogram alapján nem lesz nehéz megcsinálni. A kreativitásotokat engedjétek szabadon, lehet különböző gombokat figyelni, egyes dalokat kihagyni... bármit. Ja és írjatok hozzá új dalokat, és küldjétek el nekem. Az eredeti programban byte-onként hexában voltak kódolva a hangok, a felső 3 bit adta a hang hosszúságát, az alsó 5 a hang magasságát, megtartottam ezt a strutúrát. A programban az eredetiből vett hexa adatok vannak, de hogy egyszerűbben lehessen dalokat beírni, írtam hozzá néhány definíciót. Azért bűvészkedtem azzal, hogy a dalokat az Arduinó program memóriájába tároljam le, mert arra készültem, hogy egy csomó dalt kell majd tárolni. Van ugye a lejatszo(), ami 0xFE, vagy 0xFF-ig beolvassa byte-onként a dalt, és byte-onként átpasszolja az adatokat a hang()-nak, ami megszólaltatja őket. Még egy megjegyzés, a sok dalos verzióban egyes daloknak nem tudtam a nevét, más dalokat *-gal jelöltem meg, amiben hiba van. A zene misztériumában mélyebben jártas olvasóimat kérem, ha kijavítják, ne feledkezzenek meg rólam!



/******************************************************************************
*   Author       -  Kiraly Tibor
*                   http://www.tkiraaly.hu
*   Date         -  2020.07.12.
*   Chip         -  Arduino nano, hangszoro
*   Compiler     -  Arduino IDE 1.8.12
*
*   Dallamcsengo
*    
******************************************************************************/

// Definiciok uj dallamok beirasahoz
//    A4+ T_1_4      - 1/4 hosszu A4 hang
//    PAUSE+ T_1_2   - 1/2 hosszu szunet 
//    END_OF_SONG    - dal veget ezzel kell lezarni, kulonben a prg. elszall

#define END_OF_SONG              255
#define PAUSE                      0

#define H5                         1             // 988 Hz, ti
#define AISZ5                      2             // 932 Hz
#define A5                         3             // 880 Hz, lá
#define GISZ5                      4             // 830 Hz
#define G5                         5             // 784 Hz, szó
#define FISZ5                      6             // 740 Hz
#define F5                         7             // 698 Hz, fá
#define E5                         8             // 658 Hz, mi
#define DISZ5                      9             // 622 Hz
#define D5                        10             // 588 Hz, ré
#define CISZ5                     11             // 554 Hz
#define C5                        12             // 522 Hz, dó
#define H4                        13             // 494 Hz, ti
#define AISZ4                     14             // 466 Hz
#define A4                        15             // 440 Hz, lá
#define GISZ4                     16             // 415 Hz
#define G4                        17             // 392 Hz, szó
#define FISZ4                     18             // 370 Hz
#define F4                        19             // 349 Hz, fá
#define E4                        20             // 329 Hz, mi
#define DISZ4                     21             // 311 Hz
#define D4                        22             // 394 Hz, ré
#define CISZ4                     23             // 277 Hz
#define C3                        24             // 261 Hz, dó            
#define H3                        25             // 247 Hz, ti
#define AISZ3                     26             // 233 Hz    
#define A3                        27             // 220 Hz, lá
#define GISZ3                     28             // 208 Hz
#define G3                        29             // 196 Hz, szó

#define T_1                B00000000             // egesz
#define T_3_4              B00100000             // 3/4
#define T_1_2              B01000000             // 1/2
#define T_3_8              B01100000             // 3/8
#define T_1_4              B10000000             // 1/4
#define T_3_16             B10100000             // 3/16
#define T_1_8              B11000000             // 1/8
#define T_1_16             B11100000             // 1/16


#define KIMENET                    3             // kimeno lab
#define TT                        62             // 1/16-od hossza msec-ben


// MAV szignal
const byte kotta[] PROGMEM=
{
   0x8C, 0xD1, 0xCF, 0x91, 0xD4, 0xD3, 0x94, 0x00,
   0xFE
};


void setup()
{
   pinMode(  KIMENET, OUTPUT);
   lejatszo( kotta); 
}


void loop() {}


void lejatszo( const byte * k)
{
   byte h;                                       // hang
   int i= 0;                                     // mutato
   while( 1)
   {
      h= pgm_read_byte_near( k+ i);
      if( h == 0xFF || h == 0xFE) break;         // vege
      hang( h);
      i++;
   }
   noTone( KIMENET);
}


void hang( byte d)
{
   //                         1     3/4    1/2    3/8    1/4   3/16    1/8  1/16
   static int hossz[]= { 16* TT, 12* TT, 8* TT, 6* TT, 4* TT, 3* TT, 2* TT, TT};
   //                    0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29
   static int freki[]= { 0, 988, 932, 880, 830, 784, 740, 698, 658, 622, 588, 554, 522, 494, 466, 440, 415, 392, 370, 349, 329, 311, 294, 277, 261, 247, 233, 220, 208, 196};
   byte f= d & B00011111;
   byte h= ( d & B11100000) >> 5;
   if( f) tone( KIMENET, freki[ f], TT* 20); 
   else   noTone( KIMENET);
   delay( hossz[ h]);
}

Itt a vége, fuss el véle, legytek az én vendégeim, innen letölthetitek a hozzávalókat összecsomagolva.