?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 3

Line No. Rev Author Line
1 3 kaklik // Knihovna pro generovani hudebnich zvuku dane frekvence a delky nebo
2 // dane noty temperovaneho ladeni a delky.
3 //
4 // Pro generovani nepouziva zadnou podporu HW, vse se generuje ciste SW.
5 //
6 // (c)miho 2003
7 //
8 // Historie
9 // 1.00 Uvodni verze
10 //
11  
12  
13 // Konfiguracni parametry
14 //#define SOUND_HI PIN_xx // Pozitivni vystup
15 //#define SOUND_LO PIN_xx // Komplementarni vystup
16 #ifndef SOUND_REZIE
17 #define SOUND_REZIE 72 // Piskvorcova konstanta zahrnuje celkovou rezii ve smycce
18 #endif
19 #ifndef SOUND_CLOCK
20 #define SOUND_CLOCK 4000000 // Frelvence krystalu v Hz
21 #endif
22  
23  
24 // Definice hudebnich tonu (not) pro proceduru SoundNote()
25 #define SOUND_C 0
26 #define SOUND_Cis 1
27 #define SOUND_D 2
28 #define SOUND_Dis 3
29 #define SOUND_E 4
30 #define SOUND_F 5
31 #define SOUND_Fis 6
32 #define SOUND_G 7
33 #define SOUND_Gis 8
34 #define SOUND_A 9
35 #define SOUND_Ais 10
36 #define SOUND_H 11
37 #define SOUND_Space 12 // Pomlka
38  
39  
40 // Prototypy verejnych procedur
41  
42 void SoundBeep(unsigned int16 Frequency, unsigned int16 Duration);
43 // Predava se frekvence v Hz a doba trvani v ms (0 znamena ticho)
44  
45 void SoundNote(unsigned int8 Note, Octave, unsigned int16 Duration);
46 // Predava se cislo noty (0 je C), posunuti v oktavach (0 nejnizsi ton,
47 // SOUND_Space je ticho), doba trvani v ms
48  
49 // Alternativni makra pro generovani konstatnich tonu
50 // SoundBeepMacro(Frequency, Duration) - frekvence nesmi byt 0
51 // SoundNoteMacro(Note, Octave, Duration) - nepodporuje SOUND_Space
52 // SoundSpaceMacro(Duration) - hraje ticho
53  
54 // Privatni cast
55  
56  
57 #ORG 0x100, 0x128 // Aby skok nebyl pres hranici 0x100
58 void DelaySpecial(unsigned int16 Time)
59 // Pomocna procedura pro mereni spozdeni s granularitou 1 instrukcni takt
60 // Cas v instrukcnich cyklech, skutecny cas je vetsi o _konstantni_ rezii
61 // Maximalni cas je 65536 us
62 {
63 unsigned int8 TimeHi; // Pro pristup k horni casti Time
64  
65 *0x0A = LABEL_ADDRESS(Next)>>8; // Nastav PCLATH
66 #asm
67 movf Time,w // Zpracuj nejnizsi 3 bity
68 xorlw 7 // Pro hodnotu 0 skakej pres vsechny nopy
69 andlw 7 // Ber jen spodni 3 bity
70 addwf 2,f // Preskoc zadny az vsech 8 nopu (2 je PCL)
71 Next:
72 nop // Spozdeni s granularitou 1 takt
73 nop
74 nop
75 nop
76 nop
77 nop
78 nop
79 nop
80 #endasm
81 Time = Time >> 3; // Zahod spodni 3 bity
82 TimeHi=Time>>8; // Oddel horni cast citace
83 Time++; // Korekce na casovani typu dcfsz
84 TimeHi++;
85 #asm
86 Loop:
87 nop // Smycka musi trvat 8 taktu
88 nop // a ma 16 bitu dlouhy citac
89 nop
90 decfsz Time
91 goto Next1
92 decfsz TimeHi
93 Next1:
94 goto Loop
95 #endasm
96  
97 }
98  
99  
100 unsigned int32 SoundCount; // Pocet pulperid geneovaneho signalu
101 unsigned int32 SoundPeriod; // Delka pulperiody v us (zmensene o SOUND_REZIE)
102  
103  
104 void SoundLoop()
105 // Pomocna funkce - hlavni zvukova smycka
106 {
107 int1 Data;
108 unsigned int16 i;
109  
110 for(i=SoundCount;i>0;i--) // Pocet pulperiod
111 {
112 output_bit(SOUND_HI,Data); // Nastav vystup
113 output_bit(SOUND_LO,~Data);
114 Data=~Data; // Otoc stav vystupu
115 DelaySpecial(SoundPeriod); // Pockej po dobu plperiody
116 }
117 }
118  
119  
120 void SoundBeep(unsigned int16 Frequency, unsigned int16 Duration)
121 // Predava se frekvence v Hz a doba trvani v ms (0 znamena ticho)
122 // Rozumne frekvence jsou v rozsahu cca 10Hz az 5000Hz pro krystal 4MHz,
123 // cas do cca 5s (2*Cas/1000*Freq musi byt < nez 65536)
124 {
125 if (Frequency==0)
126 {
127 for(;Duration>0;Duration--)
128 {
129 DelaySpecial(1000); // Zhruba 1ms
130 }
131 return;
132 }
133  
134 SoundPeriod=(SOUND_CLOCK/4/2)/Frequency-SOUND_REZIE;
135  
136 SoundCount=Duration; // Vypocet poctu pulperiod signalu Duration*Frequency*2/1000
137 SoundCount*=Frequency;
138 SoundCount/=500;
139  
140 SoundLoop(); // Pozor pouzivaji se globalni parametry
141 }
142  
143 // Definice casu pulperody pro nejnizsi oktavu, v mikrosekundach
144 // Periody tonu v dalsich oktavach se ziskavaji rotaci vpravo
145 #define SOUND_Peri_C (30578*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 30578us
146 #define SOUND_Peri_Cis (28862*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 28862us
147 #define SOUND_Peri_D (27242*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 27242us
148 #define SOUND_Peri_Dis (25713*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 25713us
149 #define SOUND_Peri_E (24270*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 24270us
150 #define SOUND_Peri_F (22908*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 22908us
151 #define SOUND_Peri_Fis (21622*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 21622us
152 #define SOUND_Peri_G (20408*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 20408us
153 #define SOUND_Peri_Gis (19263*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 19263us
154 #define SOUND_Peri_A (18182*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 18182us
155 #define SOUND_Peri_Ais (17161*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 17161us
156 #define SOUND_Peri_H (16198*(SOUND_CLOCK/1000)/1000/4/2) // Perioda 16198us
157  
158 #if SOUND_Peri_C > 65535
159 #error "Sound Clock too high (Note C requires delay > 65535 cycles)"
160 #endif
161  
162 const int16 Table[12] = SOUND_Peri_C, SOUND_Peri_Cis, SOUND_Peri_D, SOUND_Peri_Dis,
163 SOUND_Peri_E, SOUND_Peri_F, SOUND_Peri_Fis, SOUND_Peri_G,
164 SOUND_Peri_Gis, SOUND_Peri_A, SOUND_Peri_Ais, SOUND_Peri_H;
165  
166 void SoundNote(unsigned int8 Note, Octave, unsigned int16 Duration)
167 // Predava se cislo noty (0 je C), posunuti v oktavach (0 nejnizsi ton)
168 // doba trvani v ms (0 znamena ticho)
169 // Zahraje zadanou notu v zadane oktave dane delky
170 {
171  
172 if (Note==SOUND_Space)
173 {
174 for(;Duration>0;Duration--)
175 DelaySpecial(1000); // Zhruba 1ms
176 return;
177 }
178  
179 SoundPeriod=(Table[Note]>>Octave)-0; // Zde je chyba prekladace, nula musi zusat
180  
181 SoundCount=Duration;
182 SoundCount*=1000;
183 SoundCount/=SoundPeriod;
184  
185 SoundPeriod=SoundPeriod-SOUND_REZIE;
186  
187 SoundLoop(); // Pozor pouzivaji se globalni parametry
188 }
189  
190  
191 // Sada maker, ktera neobsahuji slozity vypocet a jsou
192 // tedy vhodna pro jednoduche pipnuti. Parametry jsou stejne
193 // jako o funkci.
194 #define SoundBeepMacro(F,D) \
195 SoundPeriod=SOUND_CLOCK/4/2/F-SOUND_REZIE; \
196 SoundCount=D*F/500; \
197 SoundLoop();
198  
199 #define SoundNoteMacro(N,O,D) \
200 SoundPeriod=(Table[N]>>O)-SOUND_REZIE; \
201 SoundCount=D*1000/(Table[N]>>O); \
202 SoundLoop();
203  
204 #define SoundPauseMacro(D) \
205 { \
206 #if D>255 \
207 unsigned int16 i=D; \
208 #else \
209 unsigned int8 i=D; \
210 #endif \
211 for(;i>0;i--) \
212 { \
213 DelaySpecial(1000); \
214 } \
215 }
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3