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