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