193 |
miho |
1 |
// Melodicky zvonek MB01A_1_00 |
|
|
2 |
// |
|
|
3 |
// Prohram pro melodicky zvonek s pouzitim knihovny Sound_t1.C |
|
|
4 |
// |
|
|
5 |
// (c)miho 2004, pefi 2004 |
|
|
6 |
// |
|
|
7 |
// Historie: |
|
|
8 |
// 1.00 Uvodni verze |
|
|
9 |
// 1.01 Zaveden WDT |
|
|
10 |
|
|
|
11 |
#include <16F819.h> // Definice procesoru |
|
|
12 |
#fuses HS,NOPROTECT,WDT,PUT,NOLVP,NOBROWNOUT,WRT // Definice konfiguracniho slova |
|
|
13 |
|
|
|
14 |
#define POWER_386 PIN_A4 // L zapne napajeni pro zesilovac LM386 |
|
|
15 |
#define POWER_PIC PIN_A3 // L pripoji GND pro procesor PIC |
|
|
16 |
|
|
|
17 |
#define SOUND_HI PIN_B3 // Akusticky vystup |
|
|
18 |
#define SOUND_LO PIN_B2 // Akusticky vystup |
|
|
19 |
#define SOUND_CLOCK 20000000 // Frekvence hodin |
|
|
20 |
#define SOUND_LowOctave 1 // O oktavu vys protoze mame moc rychly krystal |
|
|
21 |
#define SOUND_WDT 1 // Budeme pouzivat WDT |
|
|
22 |
#include "Sound_T1.c" // Hudebni knihovna |
|
|
23 |
|
|
|
24 |
#include "Data.c" // Datovy blok pro predpripravene skladby |
|
|
25 |
|
|
|
26 |
#define RXD PIN_B1 // Port pro RS232 |
|
|
27 |
#use delay(CLOCK=20000000,RESTART_WDT) // Konfigurace pro casovani RS232 |
|
|
28 |
#use rs232(BAUD=9600,RCV=RXD,RESTART_WDT,INVERT,PARITY=N,BITS=8) // Prenosove parametry RS232 |
|
|
29 |
|
|
|
30 |
|
|
|
31 |
// Sada globalnich promennych |
|
|
32 |
// -------------------------- |
|
|
33 |
// Vyuzivame globalni promenne protoze je to vyhodne z hlediska spotreby zdroju. Usetri |
|
|
34 |
// se vyznmane mnoho pameti programu pri predavani parametru |
|
|
35 |
|
|
|
36 |
|
|
|
37 |
unsigned int16 Adr; // Adresovy ukazatel do pameti skladeb |
|
|
38 |
unsigned int16 Data; // Prectena data nebo data pro zapis |
|
|
39 |
unsigned int1 Mode; // 0=rezim testovani, 1=rezim zapisu do FLASH |
|
|
40 |
|
|
|
41 |
unsigned int16 Tempo; // Tempo (delka nejkratsi skladby v ms) |
|
|
42 |
unsigned int16 Pause; // Delka mezery mezi notami v ms |
|
|
43 |
unsigned int8 Octava; // Posunuti skladby v oktavach |
|
|
44 |
|
|
|
45 |
unsigned int8 Beep; // Druh pipnuti pro proceduru SoundSpec |
|
|
46 |
unsigned int1 Error; // Priznak chyby |
|
|
47 |
|
|
|
48 |
unsigned int8 CisloSkladby; // Cislo skladby pro proceduru Find a Play |
|
|
49 |
|
|
|
50 |
|
|
|
51 |
// Zvuky, posloupnost zadaneho poctu tonu |
|
|
52 |
#define SoundEndOfLine 0x01 // Kratke pipnuti na konci radky |
|
|
53 |
#define SoundPGM 0x03 // Trilek pri vstupu do rezimu programovani |
|
|
54 |
#define SoundPostPlay 0x03 // Po ukonceni prehravani |
|
|
55 |
#define SoundERASE 0x02 // Zvuk pri smazani bloku FLASH pameti |
|
|
56 |
#define SoundERR 0x05 // Chyba syntaxe |
|
|
57 |
|
|
|
58 |
void SpecBeep() |
|
|
59 |
// Data - pocet pipnuti, 0 znamena ticho |
|
|
60 |
{ |
|
|
61 |
int Oct; |
|
|
62 |
|
|
|
63 |
if (Error) Beep=SoundERR; |
|
|
64 |
|
|
|
65 |
for(Oct=2;Beep!=0;Beep--) |
|
|
66 |
{ |
|
|
67 |
SoundNote(SOUND_A,Oct++,50); |
|
|
68 |
} |
|
|
69 |
|
|
|
70 |
Error=0; |
|
|
71 |
} |
|
|
72 |
|
|
|
73 |
|
|
|
74 |
// Precti slovo z pameti programu |
|
|
75 |
int16 ReadData() |
|
|
76 |
// Adr - adresa ze ktere se cte |
|
|
77 |
// Data - prectena data |
|
|
78 |
{ |
|
|
79 |
int8 a,b; // Pomocne promenne |
|
|
80 |
|
|
|
81 |
(int8)*EEADR = Adr; // Adresa, spodni cast |
|
|
82 |
(int8)*EEADRH = Adr >> 8; // Adresa, horni cast |
|
|
83 |
bit_set(*EECON1,EECON1_EEPGD); // Pamet programu |
|
|
84 |
bit_set(*EECON1,EECON1_RD); // Operace cteni |
|
|
85 |
#ASM |
|
|
86 |
nop; // Povinne nop |
|
|
87 |
nop; |
|
|
88 |
#ENDASM |
|
|
89 |
a = (int8)*EEDATA; // Prevezmi data |
|
|
90 |
b = (int8)*EEDATAH; |
|
|
91 |
Data=make16(b,a); // Sestav vysledek ze 2 bajtu |
|
|
92 |
} |
|
|
93 |
|
|
|
94 |
|
|
|
95 |
// Smazani cele pameti vyhrazene pro skladby |
|
|
96 |
void Erase() |
|
|
97 |
{ |
|
|
98 |
for(Adr=STARTMEM; Adr<=ENDMEM; Adr++) // Cela oblast |
|
|
99 |
{ |
|
|
100 |
ReadData(); |
|
|
101 |
if (Data!=0x3FFF) // Mazu jen bloky, ktere to potrebuji |
|
|
102 |
{ |
|
|
103 |
if (input(POWER_PIC)!=0) return; // Nezapisuj pokud neni jumper povoleni programovani |
|
|
104 |
(int8)*EEADR = Adr; // Adresa bloku, spodni cast |
|
|
105 |
(int8)*EEADRH = Adr >> 8; // Adresa bloku, horni cast |
|
|
106 |
bit_set(*EECON1,EECON1_EEPGD); // Pamet programu |
|
|
107 |
bit_set(*EECON1,EECON1_WREN); // Povolit zapis |
|
|
108 |
bit_set(*EECON1,EECON1_FREE); // Operace mazani |
|
|
109 |
(int8)*EECON2 = 0x55; // Povinna sekvence pro zapis |
|
|
110 |
(int8)*EECON2 = 0xAA; |
|
|
111 |
bit_set(*EECON1,EECON1_WR); // Zahajeni mazani |
|
|
112 |
#ASM |
|
|
113 |
nop; // Povinne prazdne instrukce |
|
|
114 |
nop; |
|
|
115 |
#ENDASM |
|
|
116 |
bit_clear(*EECON1,EECON1_WREN); // Uz ne zapis |
|
|
117 |
bit_clear(*EECON1,EECON1_FREE); // Uz ne mazani |
|
|
118 |
bit_clear(*EECON1,EECON1_EEPGD); // Uz ne pamet programu |
|
|
119 |
Beep=SoundERASE; |
|
|
120 |
SpecBeep(); |
|
|
121 |
} |
|
|
122 |
} |
|
|
123 |
} |
|
|
124 |
|
|
|
125 |
|
|
|
126 |
// Zapis do pameti programu po jednotlivych slovech. |
|
|
127 |
// Soucastka vyzaduje zapis vzdy celych osmi slov najednou. Vyuziva se toho, ze pamet FLASH |
|
|
128 |
// umi zapisovat jen smerem do nuly a tak staci na pozice, ktere zrovna nechceme programovat |
|
|
129 |
// zapsat same jednicky cimz se stav jejich stav nezmeni. |
|
|
130 |
void WriteData() |
|
|
131 |
// Adr - adresa, kam se bude zapisovat |
|
|
132 |
// Data - data, ktera se budou zapisovat |
|
|
133 |
{ |
|
|
134 |
int i; |
|
|
135 |
|
|
|
136 |
bit_set(*EECON1,EECON1_EEPGD); // Pamet programu |
|
|
137 |
bit_set(*EECON1,EECON1_WREN); // Zapis |
|
|
138 |
(int8)*EEADR = Adr & ~3; // Adresa, spodni cast, zaokrouhleno dolu na nasobek 8 |
|
|
139 |
(int8)*EEADRH = Adr >> 8; // Adresa, horni cast |
|
|
140 |
for (i=0; i<4; i++) |
|
|
141 |
{ |
|
|
142 |
if ((Adr & 3) == i) // Pokud je adresa slova v bloku totozna s pozadovanou |
|
|
143 |
{ |
|
|
144 |
(int8)*EEDATA =Data; // Platne slovo, spodni cast |
|
|
145 |
(int8)*EEDATAH=Data >> 8; // Platne slovo, horni cast |
|
|
146 |
} |
|
|
147 |
else // Ostatni bunky nemenime |
|
|
148 |
{ |
|
|
149 |
(int8)*EEDATA =0xFF; // Zbytek same jednicky |
|
|
150 |
(int8)*EEDATAH=0xFF; |
|
|
151 |
} |
|
|
152 |
(int8)*EECON2 = 0x55; // Povinna sekvence pro zapis |
|
|
153 |
(int8)*EECON2 = 0xAA; |
|
|
154 |
bit_set(*EECON1,EECON1_WR); // Zahajeni zapisu |
|
|
155 |
#ASM |
|
|
156 |
nop; // Povinne dve prazdne instrukce |
|
|
157 |
nop; |
|
|
158 |
#ENDASM |
|
|
159 |
((int8)*EEADR) ++; // Dalsi slovo |
|
|
160 |
} |
|
|
161 |
bit_clear(*EECON1,EECON1_WREN); // Konec zapisu |
|
|
162 |
bit_clear(*EECON1,EECON1_EEPGD); // Uz ne pamet programu (bezpecnost) |
|
|
163 |
} |
|
|
164 |
|
|
|
165 |
|
|
|
166 |
// Zapise data Data na adresu Adr a provede posun na dalsi adresu, zapisuje se jen do |
|
|
167 |
// dovolene oblasti pameti a jen v pripade, ze je Mode=1 |
|
|
168 |
void WriteDataInc() |
|
|
169 |
// Data - co se zapisuje |
|
|
170 |
// Adr - kam se zapisuje, po zapisu se adresa posouva |
|
|
171 |
{ |
|
|
172 |
if (~Mode) return; // Neni rezim zapisu |
|
|
173 |
if ( (Adr>=STARTMEM) & (Adr<=ENDMEM) & (input(POWER_PIC)==0) ) |
|
|
174 |
{ |
|
|
175 |
WriteData(); |
|
|
176 |
Adr++; |
|
|
177 |
} |
|
|
178 |
else |
|
|
179 |
{ |
|
|
180 |
Error=1; |
|
|
181 |
} |
|
|
182 |
} |
|
|
183 |
|
|
|
184 |
|
|
|
185 |
// Najdi zacatek zadaneho cisla skladby. Promenna Adr ukazuje na zacatek skladby. |
|
|
186 |
// Neni-li skladba nalezena ukazuje Adr na koncovou znacku (0x3FFF) posledni skladby |
|
|
187 |
// nebo na konec pameti. |
|
|
188 |
int1 Find() |
|
|
189 |
// CisloSkladby - poradove cislo skladby |
|
|
190 |
// Adr - adresa zacatku skladby |
|
|
191 |
{ |
|
|
192 |
Adr=STARTMEM-1; // Od zacatku oblasti pro skladby |
|
|
193 |
for(;1;) |
|
|
194 |
{ |
|
|
195 |
Adr++; |
|
|
196 |
ReadData(); // Precti data |
|
|
197 |
if (Data==ENDOFDATA) return 1; // Priznak konce dat |
|
|
198 |
if (Adr==ENDMEM+1) return 1; // Uz jsme prosli celou pamet |
|
|
199 |
if ((Data&MASKBEGIN)==DATABEGIN) // Priznak zacatku skladby |
|
|
200 |
{ |
|
|
201 |
CisloSkladby--; // Otestuj pocitadlo skladeb |
|
|
202 |
if (CisloSkladby==0) return 0; // Je to tato skladba |
|
|
203 |
} |
|
|
204 |
} |
|
|
205 |
} |
|
|
206 |
|
|
|
207 |
|
|
|
208 |
// Zahraj jednu notu |
|
|
209 |
void PlayData() |
|
|
210 |
// Data = zakodovana nota |
|
|
211 |
// Tempo, Octava, Pause = parametry hrane noty |
|
|
212 |
{ |
|
|
213 |
SoundNote((int8)Data&0xF,Octava+(((int8)Data>>4)&0x7),Tempo*((Data>>7)&0x3F)); // Nota |
|
|
214 |
SoundNote(SOUND_Space,0,Pause); // Mezera |
|
|
215 |
} |
|
|
216 |
|
|
|
217 |
|
|
|
218 |
// Zahraj skladbu od zadane adresy v promenne Adr. |
|
|
219 |
void Play() |
|
|
220 |
// CisloSkladby - cislo skladby k hrani |
|
|
221 |
{ |
|
|
222 |
if (Find()) // Najdi zacatek skladby v pameti skladeb |
|
|
223 |
{ |
|
|
224 |
return; // Skladba nenalezena |
|
|
225 |
} |
|
|
226 |
|
|
|
227 |
Tempo=100; // Default delka noty |
|
|
228 |
Pause=100; // Default mezera mezi notami |
|
|
229 |
|
|
|
230 |
Octava=Data&~MASKBEGIN; // Posunuti oktav (povinna soucast zacatku skladby) |
|
|
231 |
Adr++; |
|
|
232 |
|
|
|
233 |
for (;1;) |
|
|
234 |
{ |
|
|
235 |
if (Adr==ENDMEM+1) return; // Konec pametove oblasti |
|
|
236 |
ReadData(); // Vezmi data |
|
|
237 |
Adr++; // Posun adresu |
|
|
238 |
if (Data==ENDOFDATA) return; // Konec dat |
|
|
239 |
if ((Data&MASKBEGIN)==DATABEGIN) return; // Zacatek dalsi skladby |
|
|
240 |
if ((Data&MASKTEMPO)==DATATEMPO) Tempo=Data&~DATATEMPO; // Paramter TEMPO |
|
|
241 |
if ((Data&MASKPAUSE)==DATAPAUSE) Pause=Data&~DATAPAUSE; // Parametr PAUSE |
|
|
242 |
if ((Data&MASKNOTE)==0) // Nota |
|
|
243 |
{ |
|
|
244 |
PlayData(); // Zahraj notu |
|
|
245 |
} |
|
|
246 |
} |
|
|
247 |
} |
|
|
248 |
|
|
|
249 |
|
|
|
250 |
// Vycisli cislo z bufferu, posune ukazovatko na prvni nezpracovany znak, preskakuje mezery |
|
|
251 |
int16 Number(char line[], int *a, len) |
|
|
252 |
{ |
|
|
253 |
int16 Data; |
|
|
254 |
char c; |
|
|
255 |
|
|
|
256 |
while((line[*a]==' ')&(*a<len)) // Vynech mezery na zacatku |
|
|
257 |
(*a)++; // Posouvej ukazovatko |
|
|
258 |
|
|
|
259 |
Data=0; |
|
|
260 |
while (1) |
|
|
261 |
{ |
|
|
262 |
if (*a>=len) return Data; // Konec retezce |
|
|
263 |
c=line[*a]; // Vezmi znak z pole |
|
|
264 |
if ((c<'0')|(c>'9')) return Data; // Koncime pokud znak neni cislice |
|
|
265 |
Data = Data * 10 + (c-'0'); // Pouzij cislici |
|
|
266 |
(*a)++; // Dalsi znak |
|
|
267 |
} |
|
|
268 |
} |
|
|
269 |
|
|
|
270 |
|
|
|
271 |
// Vyhledej klicove slovo a vrat jeho zkraceny kod |
|
|
272 |
// Pokud slovo neexistuje vraci -1 |
|
|
273 |
// Format definice - retezec ukonceny nulou + zastupny znak, na konci prazdny retezec (nula) |
|
|
274 |
const char KeyWords[] = |
|
|
275 |
{ |
|
|
276 |
'P','L','A','Y',0, 'P', |
|
|
277 |
'E','R','A','S','E',0, 'E', |
|
|
278 |
'T','E','M','P','O',0, 't', |
|
|
279 |
'P','A','U','S','E',0, 'p', |
|
|
280 |
'B','E','G','I','N',0, 'B', |
|
|
281 |
'T','E','S','T',0, 'b', |
|
|
282 |
'E','N','D',0, 'Z', |
|
|
283 |
'C',0. SOUND_C, |
|
|
284 |
'C','I','S',0, SOUND_Cis, |
|
|
285 |
'D',0, SOUND_D, |
|
|
286 |
'D','I','S',0, SOUND_Dis, |
|
|
287 |
'E',0, SOUND_E, |
|
|
288 |
'F',0, SOUND_F, |
|
|
289 |
'F','I','S',0, SOUND_Fis, |
|
|
290 |
'G',0, SOUND_G, |
|
|
291 |
'G','I','S',0, SOUND_Gis, |
|
|
292 |
'A',0, SOUND_A, |
|
|
293 |
'A','I','S',0, SOUND_Ais, |
|
|
294 |
'H',0, SOUND_H, |
|
|
295 |
'S','P','A','C','E',0, SOUND_Space |
|
|
296 |
}; |
|
|
297 |
signed int Word(char line[], unsigned int8 *a, len) |
|
|
298 |
{ |
|
|
299 |
unsigned int8 i; // Index do pole klicovych slov |
|
|
300 |
unsigned int8 j; // index do zpracovavane radky |
|
|
301 |
|
|
|
302 |
while((line[*a]==' ')&(*a<len)) // Vynech mezery na zacatku |
|
|
303 |
(*a)++; // Posouvej ukazovatko |
|
|
304 |
|
|
|
305 |
for (i=0;i<sizeof(KeyWords);) // Slova ze slovniku |
|
|
306 |
{ |
|
|
307 |
for (j=*a;(j<len)&(KeyWords[i]!=0)&(KeyWords[i]==line[j]);i++,j++) // Znaky ze slova |
|
|
308 |
{ |
|
|
309 |
} |
|
|
310 |
if ((KeyWords[i]==0)&((line[j]==' ')|(j==len))) |
|
|
311 |
{ |
|
|
312 |
if (j>=len) j=len-1; // Korekce abychom se nedostali za konec retezce |
|
|
313 |
*a=j+1; // Posun ukazovatko za zpracovane slovo |
|
|
314 |
|
|
|
315 |
return KeyWords[i+1]; // Vrat zastupnou hodnotu z tabulky klicovych slov |
|
|
316 |
} |
|
|
317 |
while(KeyWords[i]!=0) i++; // Preskoc zbytek slova v tabulce |
|
|
318 |
i++; // Preskoc oddelovac |
|
|
319 |
i++; // Preskoc polozku se zastupnou hodnotou |
|
|
320 |
} |
|
|
321 |
return -1; // Prosli jsme cely slovnik a nedoslo ke shode |
|
|
322 |
} |
|
|
323 |
|
|
|
324 |
|
|
|
325 |
// Programovani pres RS232 |
|
|
326 |
#define LINELEN 40 // Delka radky pro RS232 |
|
|
327 |
#define CR 0x0D // Odradkovani |
|
|
328 |
#define BS 0x08 // Back Space |
|
|
329 |
|
|
|
330 |
#separate |
|
|
331 |
void Download() |
|
|
332 |
{ |
|
|
333 |
char line[LINELEN]; // Buffer na radku |
|
|
334 |
unsigned char c; // Znak |
|
|
335 |
unsigned int8 a; // Ukazovatko do bufferu |
|
|
336 |
unsigned int8 len; // Delka retezce v radce |
|
|
337 |
unsigned int8 Oct; // Cislo oktavy u noty |
|
|
338 |
|
|
|
339 |
output_low(POWER_386); // Zapni napajeni zesilovace |
|
|
340 |
SoundNote(SOUND_Space,3,10); // Mezera |
|
|
341 |
Beep=SoundPGM; |
|
|
342 |
Error=0; |
|
|
343 |
SpecBeep(); // Pipni na znameni vstupu do programovani |
|
|
344 |
|
|
|
345 |
Tempo=100; // Default hodnoty |
|
|
346 |
Pause=100; |
|
|
347 |
Octava=0; |
|
|
348 |
Mode=0; // Mod hrani |
|
|
349 |
Oct=0; |
|
|
350 |
a=0; // Na zacatku je radka prazdna |
|
|
351 |
|
|
|
352 |
for(;input(POWER_PIC)==0;) // Opakuj vse dokud je PGM rezim |
|
|
353 |
{ |
|
|
354 |
Loop: |
|
|
355 |
c=Getc(); // Vezmi znak ze seriovky |
|
|
356 |
if (c>=0x80) goto Loop; // Ignoruj znaky nad ASCII |
|
|
357 |
if (c>=0x60) c=c-0x20; // Preved velka pismena na velka pismena |
|
|
358 |
if ((c==CR)|(c=='/')) // Konec radky nebo komentar |
|
|
359 |
{ |
|
|
360 |
while (c!=CR) c=Getc(); // Zpracuj znaky komentare |
|
|
361 |
len=a; // Zapamatuj si delku radky |
|
|
362 |
a=0; // Postav se na zacatek radky |
|
|
363 |
Beep=SoundEndOfLine; // Default zuk na konci radky |
|
|
364 |
// Zpracovani radky |
|
|
365 |
while(a<len) |
|
|
366 |
{ |
|
|
367 |
restart_wdt(); // Nuluj watchdog abychom se nezresetovali |
|
|
368 |
c=Word(line,&a,len); |
|
|
369 |
if (c==-1) // Nezname klicove slovo |
|
|
370 |
{ |
|
|
371 |
if (a<len) // Nejsme uz na konci radky ? |
|
|
372 |
{ |
|
|
373 |
if ((line[a]>='0')&(line[a]<='9')) // Stojime na cislici -> je to cislo |
|
|
374 |
{ |
|
|
375 |
// Oct=Number(line,&a,len)&0x7; // tohle nefunguje protoze je chyba v prekladaci |
|
|
376 |
Oct=Number(line,&a,len); // prekladac prepoklada, z W obsahuje spodni bajt vysledku |
|
|
377 |
Oct&=0x7; // ale k navratu pouziva RETLW 0 coz smaze W ! |
|
|
378 |
} |
|
|
379 |
else // Stojime na pismenu nebo oddelovaci |
|
|
380 |
{ |
|
|
381 |
if (line[a]!=' ') Error=1; // Neni to oddelovac - chyba |
|
|
382 |
a++; // Preskocim 1 znak (a kdyz to nepomuze dostanu se zase sem) |
|
|
383 |
} |
|
|
384 |
} |
|
|
385 |
} |
|
|
386 |
else if (c=='P') // Play |
|
|
387 |
{ |
|
|
388 |
CisloSkladby=Number(line,&a,len); |
|
|
389 |
Mode=0; |
|
|
390 |
Play(); |
|
|
391 |
Beep=SoundPGM; |
|
|
392 |
} |
|
|
393 |
else if (c=='E') // Erase |
|
|
394 |
{ |
|
|
395 |
Mode=0; |
|
|
396 |
Erase(); |
|
|
397 |
Beep=SoundPGM; |
|
|
398 |
} |
|
|
399 |
else if (c=='t') // Tempo |
|
|
400 |
{ |
|
|
401 |
Tempo=Number(line,&a,len)&~MASKTEMPO; |
|
|
402 |
if (Tempo==0) Tempo=100; |
|
|
403 |
Data=Tempo|DATATEMPO; |
|
|
404 |
WriteDataInc(); // Podmineny zapis do FLASH a posun na dalsi adresu |
|
|
405 |
} |
|
|
406 |
else if (c=='p') // Pause |
|
|
407 |
{ |
|
|
408 |
Pause=Number(line,&a,len)&~MASKPAUSE; |
|
|
409 |
if (Pause==0) Pause=100; |
|
|
410 |
Data=Pause|DATAPAUSE; |
|
|
411 |
WriteDataInc(); // Podmineny zapis do FLASH a posun na dalsi adresu |
|
|
412 |
} |
|
|
413 |
else if (c=='B') // Begin |
|
|
414 |
{ |
|
|
415 |
CisloSkladby=~0; // Neplatne cislo skladby |
|
|
416 |
Find(); // najde konec posledni skladby |
|
|
417 |
Octava=Number(line,&a,len)&~MASKBEGIN; |
|
|
418 |
Data=DATABEGIN|Octava; // Zacatecni znacka |
|
|
419 |
Mode=1; // Mod zapisu do FLASH pameti |
|
|
420 |
WriteDataInc(); // Podmineny zapis do FLASH a posun na dalsi adresu |
|
|
421 |
} |
|
|
422 |
else if (c=='b') // Test |
|
|
423 |
{ |
|
|
424 |
Octava=Number(line,&a,len)&~MASKBEGIN; |
|
|
425 |
Mode=0; |
|
|
426 |
} |
|
|
427 |
else if (c=='Z') // End |
|
|
428 |
{ |
|
|
429 |
Mode=0; |
|
|
430 |
} |
|
|
431 |
else // Nota |
|
|
432 |
{ |
|
|
433 |
Data=Number(line,&a,len); // Delka noty (nepovinna) |
|
|
434 |
Data&=0x3F; // Jen platny rozsah |
|
|
435 |
if (Data==0) Data++; // Je-li nulova delka - dej jednotkovou |
|
|
436 |
Data<<=7; // Delka |
|
|
437 |
Data|=c; // Nota |
|
|
438 |
Data|=(Oct<<4); // Oktava |
|
|
439 |
WriteDataInc(); // Podmineny zapis do FLASH a posun na dalsi adresu |
|
|
440 |
if (~Mode) |
|
|
441 |
{ |
|
|
442 |
PlayData(); // Zahraj notu |
|
|
443 |
Beep=0; // Po zahrani noty uz nepipej na konci radky |
|
|
444 |
} |
|
|
445 |
} |
|
|
446 |
} |
|
|
447 |
a=0; // Radka zpracovana, nuluj jeji delku |
|
|
448 |
SpecBeep(); // Pipni |
|
|
449 |
goto Loop; |
|
|
450 |
} |
|
|
451 |
if ((c==BS)&(a>0)) {a--;goto Loop;} // Smaz znak |
|
|
452 |
if ((c==',')|(c<=' ')) c=' '; // Vsechny ostatni ridici znaky i carka jsou oddelovac |
|
|
453 |
if (a<LINELEN) line[a++]=c; // Zapis znak do bufferu a posun ukazovatko |
|
|
454 |
} |
|
|
455 |
} |
|
|
456 |
|
|
|
457 |
|
|
|
458 |
// Tabulka pro prekodovani tlacitek |
|
|
459 |
const int8 KeyTranslate[16] = {0, 1, 2, 5, 3, 6, 8, 11, 4, 7, 9, 12, 10, 13, 14, 15}; |
|
|
460 |
|
|
|
461 |
void main() |
|
|
462 |
{ |
|
|
463 |
Start: |
|
|
464 |
|
|
|
465 |
if (restart_cause()==WDT_FROM_SLEEP) // Osetreni probuzeni od WDT |
|
|
466 |
{ |
|
|
467 |
sleep(); |
|
|
468 |
} |
|
|
469 |
// Inicializace WDT |
|
|
470 |
// setup_wdt(WDT_16MS); // nelze pouzit, zabira 15 instukci |
|
|
471 |
#asm |
|
|
472 |
bsf 0x03,5 // banka 1 nebo 3 aby se mohlo k OPTION registu |
|
|
473 |
bcf 0x81,3 // WDT primo tedy 16ms |
|
|
474 |
#endasm |
|
|
475 |
|
|
|
476 |
// Inicializace |
|
|
477 |
port_b_pullups(TRUE); // Zapni pull-up odpory na portu B |
|
|
478 |
set_tris_a(0b00001000); // Nastav nepouzite vyvody jako vystupy |
|
|
479 |
set_tris_b(0b11110000); // 1 znamena vstup |
|
|
480 |
*0x9F = 6; // Vsechny vstupy jsou digitalni |
|
|
481 |
|
|
|
482 |
// Test na rezim programovani |
|
|
483 |
if ((input(POWER_PIC)==0)&(input(RXD)==0)) // Podminka programovani |
|
|
484 |
Download(); // Pripojen RS232 a propojka na PGM |
|
|
485 |
|
|
|
486 |
// Zapnuti napajeni |
|
|
487 |
output_low(POWER_PIC); // Pripoj GND pro procesor |
|
|
488 |
SoundNote(SOUND_Space,3,10); // Mezera |
|
|
489 |
output_low(POWER_386); // Zapni napajeni zesilovace |
|
|
490 |
SoundNote(SOUND_Space,3,100); // Mezera (jinak se chybne detekuje tlacitko) |
|
|
491 |
|
|
|
492 |
// Cteni tlacitek |
|
|
493 |
#use FAST_IO(B) |
|
|
494 |
CisloSkladby=(input_b() >> 4) ^ 0xFF & 0xF; // Precti stav tlacitek |
|
|
495 |
#use STANDARD_IO(B) |
|
|
496 |
CisloSkladby=KeyTranslate[CisloSkladby]; // Prekoduj je do binarniho kodu |
|
|
497 |
|
|
|
498 |
// Prehrani skladby |
|
|
499 |
Play(); // Zahraj skladbu |
|
|
500 |
|
|
|
501 |
// Po odehrani usni a cekej na zmacknuti tlacitka |
|
|
502 |
#use FAST_IO(B) |
|
|
503 |
if (input_B()); // Precti stav portu B (vuci tomuto stavu se bude hlidat zmena) |
|
|
504 |
#use STANDARD_IO(B) |
|
|
505 |
bit_clear(*0xB,0); // Nuluj priznak preruseni od zmeny stavu portu B |
|
|
506 |
enable_interrupts(INT_RB); // Povol preruseni od zmeny stavu portu B |
|
|
507 |
|
|
|
508 |
output_high(POWER_386); // Vypni napajeni zesilovace |
|
|
509 |
output_float(POWER_PIC); // Odpoj GND |
|
|
510 |
|
|
|
511 |
Sleep(); // Usni aby byla minimalni klidova spotreba |
|
|
512 |
|
|
|
513 |
disable_interrupts(INT_RB); // Zakaz preruseni od portu |
|
|
514 |
goto Start; // Po probuzeni skoc na zacatek |
|
|
515 |
} |