Rev 3235 Rev 3255
Line -... Line 1...
-   1 // Knihovna pro generovani hudebnich zvuku dane frekvence a delky nebo
-   2 // dane noty temperovaneho ladeni a delky.
-   3 //
-   4 // Pro gnerovani pouziva casovac T0, T1 a jednotku CCP1.
-   5 //
-   6 // POZOR -- POZOR -- POZOR
-   7 // Pri nizsi frekvenci XTALu (nez asi 5MHz) je rezie preruseni tak velka, ze spotrebuje
-   8 // veskery strojovy cas a uz nedojde k ukonceni rozehraneho tonu vyssi frekvence (z oktavy 7
-   9 // nebo nad cca 8KHz). Resenim je pouzit vlastni INT proceduru s minimalni rezii.
-   10 //
-   11 // (c)miho 2004
-   12 //
-   13 // Historie
-   14 // 1.00 Uvodni verze
-   15  
-   16  
-   17 // Konfiguracni parametry
-   18 //#define SOUND_HI PIN_xx // Pozitivni vystup
-   19 //#define SOUND_LO PIN_xx // Komplementarni vystup
-   20 #ifndef SOUND_CLOCK
-   21 #define SOUND_CLOCK 4000000 // Frelvence krystalu v Hz
-   22 #endif
-   23  
-   24  
-   25 // Definice hudebnich tonu (not) pro proceduru SoundNote()
-   26 #define SOUND_C 0
-   27 #define SOUND_Cis 1
-   28 #define SOUND_D 2
-   29 #define SOUND_Dis 3
-   30 #define SOUND_E 4
-   31 #define SOUND_F 5
-   32 #define SOUND_Fis 6
-   33 #define SOUND_G 7
-   34 #define SOUND_Gis 8
-   35 #define SOUND_A 9
-   36 #define SOUND_Ais 10
-   37 #define SOUND_H 11
-   38 #define SOUND_Space 12 // Pomlka
-   39  
-   40  
-   41 // Prototypy verejnych procedur
-   42  
-   43 void SoundBeep(unsigned int16 Frequency, unsigned int16 Duration);
-   44 // Predava se frekvence v Hz a doba trvani v ms (0 znamena ticho)
-   45  
-   46 void SoundNote(unsigned int8 Note, Octave, unsigned int16 Duration);
-   47 // Predava se cislo noty (0 je C), posunuti v oktavach (0 nejnizsi ton,
-   48 // SOUND_Space je ticho), doba trvani v ms
-   49  
-   50 // Alternativni makra pro generovani konstatnich tonu
-   51 // SoundBeepMacro(Frequency, Duration) - frekvence nesmi byt 0
-   52 // SoundNoteMacro(Note, Octave, Duration) - nepodporuje SOUND_Space
-   53 // SoundSpaceMacro(Duration) - hraje ticho
-   54  
-   55 // Privatni cast
-   56  
-   57  
-   58 #int_ccp1
-   59 void IntCCP1()
-   60 // Preruseni od jednotky CCP1 generuje vystup
-   61 {
-   62 volatile int1 Data; // Posledni stav vystupu
-   63 output_bit(SOUND_HI,Data); // Nastav vystup
-   64 output_bit(SOUND_LO,~Data);
-   65 Data=~Data; // Otoc stav vystupu
-   66 }
-   67  
-   68  
-   69 #if SOUND_CLOCK < (65535*32*4*2) // < 16.7 MHz
-   70 #define SOUND_PRESCALE 1
-   71 #elif SOUND_CLOCK < (65535*32*4*2*2) // < 33.6 MHz
-   72 #define SOUND_PRESCALE 2
-   73 #elif SOUND_CLOCK < (65535*32*4*2*4) // < 67.1 MHz
-   74 #define SOUND_PRESCALE 4
-   75 #elif SOUND_CLOCK < (65535*32*4*2*8) // < 134 MHz
-   76 #define SOUND_PRESCALE 8
-   77 #else
-   78 #error SOUND_CLOCK Frequency too high
-   79 #endif
-   80 #bit T0IF=0x0B.2
-   81 void SoundBeep(unsigned int16 Frequency, unsigned int16 Duration)
-   82 // Predava se frekvence v Hz a doba trvani v ms (0 znamena ticho)
-   83 // Rozumne frekvence jsou od 32Hz
-   84 {
-   85 unsigned int16 Time; // Pocitadlo zlomkoveho casu
-   86  
-   87 // Inicializace casovace
-   88 if (Frequency!=0) // Frekvence 0 znamena ticho
-   89 {
-   90 setup_ccp1(CCP_COMPARE_RESET_TIMER);
-   91 set_timer1(0);
-   92 (int16)CCP_1=SOUND_CLOCK/SOUND_PRESCALE/4/2/Frequency;
-   93 #if SOUND_PRESCALE==1
-   94 setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
-   95 #elif SOUND_PRESCALE==2
-   96 setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
-   97 #elif SOUND_PRESCALE==4
-   98 setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
-   99 #elif SOUND_PRESCALE==8
-   100 setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
-   101 #endif
-   102 enable_interrupts(int_ccp1);
-   103 enable_interrupts(global);
-   104 }
-   105  
-   106 // Delka tonu merena casovacem T0 (bez preruseni)
-   107 Time=0;
-   108 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
-   109 while (Duration)
-   110 {
-   111 if (T0IF) // Preteceni T0 - kazdych (1/CLK)*4*256
-   112 {
-   113 T0IF = 0;
-   114 Time += (256*4*1000*2048+SOUND_CLOCK/2)/SOUND_CLOCK;
-   115 }
-   116 if (Time>>11)
-   117 {
-   118 Time -= 2048;
-   119 Duration--;
-   120 }
-   121 }
-   122  
-   123 // Konec casovace
-   124 disable_interrupts(int_ccp1);
-   125 disable_interrupts(global);
-   126 }
-   127  
-   128  
-   129 // Definice casu pulperody pro nejnizsi oktavu, v kvantech casovace T1
-   130 // Pulperiody tonu v dalsich oktavach se ziskavaji rotaci vpravo
-   131 #define SOUND_Peri_C ((30578*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 30578us
-   132 #define SOUND_Peri_Cis ((28862*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 28862us
-   133 #define SOUND_Peri_D ((27242*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 27242us
-   134 #define SOUND_Peri_Dis ((25713*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 25713us
-   135 #define SOUND_Peri_E ((24270*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 24270us
-   136 #define SOUND_Peri_F ((22908*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 22908us
-   137 #define SOUND_Peri_Fis ((21622*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 21622us
-   138 #define SOUND_Peri_G ((20408*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 20408us
-   139 #define SOUND_Peri_Gis ((19263*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 19263us
-   140 #define SOUND_Peri_A ((18182*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 18182us
-   141 #define SOUND_Peri_Ais ((17161*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 17161us
-   142 #define SOUND_Peri_H ((16198*(SOUND_CLOCK/1000)/1000/4/2)/SOUND_PRESCALE) // Perioda 16198us
-   143  
-   144 // Kontrola na delku konstanty (musi byt mensi nez delka citace)
-   145 #if SOUND_Peri_C > 65535
-   146 #error "SOUND_Peri_C too long (Note C requires delay > 65535 cycles)"
-   147 #endif
-   148  
-   149 // Casove konstanty pro noty nejnizsi oktavy
-   150 const unsigned int16 Table[12] =
-   151 SOUND_Peri_C, SOUND_Peri_Cis, SOUND_Peri_D, SOUND_Peri_Dis,
-   152 SOUND_Peri_E, SOUND_Peri_F, SOUND_Peri_Fis, SOUND_Peri_G,
-   153 SOUND_Peri_Gis, SOUND_Peri_A, SOUND_Peri_Ais, SOUND_Peri_H;
-   154  
-   155  
-   156 void SoundNote(unsigned int8 Note, Octave, unsigned int16 Duration)
-   157 // Predava se cislo noty (0 je C), posunuti v oktavach (0 nejnizsi ton)
-   158 // doba trvani v ms (0 znamena ticho)
-   159 // Zahraje zadanou notu v zadane oktave dane delky
-   160 {
-   161 unsigned int16 Time; // Pocitadlo zlomkoveho casu
-   162  
-   163 // Inicializace casovace
-   164 if (Note!=SOUND_Space) // Pokud se ma hrat spust hrani
-   165 {
-   166 setup_ccp1(CCP_COMPARE_RESET_TIMER);
-   167 set_timer1(0);
-   168 (int16)CCP_1=Table[Note]>>Octave;
-   169 #if SOUND_PRESCALE==1
-   170 setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
-   171 #elif SOUND_PRESCALE==2
-   172 setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
-   173 #elif SOUND_PRESCALE==4
-   174 setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
-   175 #elif SOUND_PRESCALE==8
-   176 setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
-   177 #endif
-   178 enable_interrupts(int_ccp1);
-   179 enable_interrupts(global);
-   180 }
-   181  
-   182 // Delka tonu merena casovacem T0 (bez preruseni)
-   183 Time=0;
-   184 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
-   185 while (Duration)
-   186 {
-   187 if (T0IF) // Preteceni T0 - kazdych (1/CLK)*4*256
-   188 {
-   189 T0IF = 0;
-   190 Time += (256*4*1000*2048+SOUND_CLOCK/2)/SOUND_CLOCK;
-   191 }
-   192 if (Time>>11)
-   193 {
-   194 Time -= 2048;
-   195 Duration--;
-   196 }
-   197 }
-   198  
-   199 // Konec casovace
-   200 disable_interrupts(int_ccp1);
-   201 disable_interrupts(global);
-   202 }