BASIC compiler/interpreter for PIC32MX/MZ-80K
修订版 | 7c79891e314b2ab755effc915620ccbe1537db54 (tree) |
---|---|
时间 | 2019-04-04 08:05:37 |
作者 | Katsumi <kmorimatsu@sour...> |
Commiter | Katsumi |
Implement several interrupts
@@ -222,6 +222,7 @@ extern char g_use_graphic; | ||
222 | 222 | extern unsigned short* g_graphic_area; |
223 | 223 | extern int* g_libparams; |
224 | 224 | extern int g_long_name_var_num; |
225 | +extern char g_music_active; | |
225 | 226 | extern int g_class; |
226 | 227 | extern int g_compiling_class; |
227 | 228 | extern int g_temp; |
@@ -261,6 +262,7 @@ void err_not_field(int fieldname, int classname); | ||
261 | 262 | void err_str(char* str); |
262 | 263 | char* resolve_label(int s6); |
263 | 264 | |
265 | +void musicint(); | |
264 | 266 | void set_sound(unsigned long* data, int flagsLR); |
265 | 267 | int musicRemaining(int flagsLR); |
266 | 268 | int waveRemaining(int mode); |
@@ -483,11 +485,17 @@ char* interrupt_statement(); | ||
483 | 485 | #define ASM_LW_A0_XXXX_S5 0x8EA40000 |
484 | 486 | |
485 | 487 | // Interrupt macros |
486 | -// 16 different type interruptions are possible | |
487 | -#define NUM_INTERRUPT_TYPES 1 | |
488 | -#define INTERRUPT_TIMER 0 | |
489 | -extern short g_interrupt_flags; | |
490 | -extern int g_int_vector[NUM_INTERRUPT_TYPES]; | |
488 | +// 32 different type interruptions are possible | |
489 | +// See also envspecific.h for additional interruptions | |
490 | +#define INTERRUPT_TIMER 0 | |
491 | +#define INTERRUPT_DRAWCOUNT 1 | |
492 | +#define INTERRUPT_KEYS 2 | |
493 | +#define INTERRUPT_KEYINPUT 3 | |
494 | +#define INTERRUPT_MUSIC 4 | |
495 | +#define INTERRUPT_WAVE 5 | |
496 | + | |
497 | +extern int g_interrupt_flags; | |
498 | +extern int g_int_vector[]; | |
491 | 499 | #define raise_interrupt_flag(x) do {\ |
492 | 500 | if (g_int_vector[x]) {\ |
493 | 501 | IFS0bits.CS1IF=1;\ |
@@ -280,8 +280,8 @@ int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){ | ||
280 | 280 | asm volatile("ori $v1,$v1,0x5678"); |
281 | 281 | asm volatile("sw $v0,0($v1)"); |
282 | 282 | asm volatile("label1:"); |
283 | - asm volatile("nop"); | |
284 | - asm volatile("nop"); | |
283 | + asm volatile("sw $zero,0x1234($v1)"); | |
284 | + asm volatile("sw $zero,0x1234($gp)"); | |
285 | 285 | asm volatile("nop"); |
286 | 286 | int i; |
287 | 287 | for2(i,1,10){ |
@@ -34,4 +34,4 @@ int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g | ||
34 | 34 | #define ADDITIONAL_INT_FUNCTIONS |
35 | 35 | #define ADDITIONAL_STR_FUNCTIONS |
36 | 36 | #define ADDITIONAL_RESERVED_VAR_NAMES |
37 | - | |
37 | +#define ADDITIONAL_INTERRUPT_FUNCTIONS |
@@ -83,6 +83,9 @@ int* g_libparams; | ||
83 | 83 | // Number of long name variables |
84 | 84 | int g_long_name_var_num; |
85 | 85 | |
86 | +// Flag for active music/sound/wave function | |
87 | +char g_music_active; | |
88 | + | |
86 | 89 | // Class name being compiled |
87 | 90 | int g_class; |
88 | 91 | // Flag to compile class file |
@@ -253,10 +253,23 @@ TIMER() | ||
253 | 253 | |
254 | 254 | INTERRUPT xxx,yyy[,z1[,z2 ... ]] |
255 | 255 | 割り込みを設定する。xxxは割り込みの種類、yyyは割り込み時のサブルーチンをラベ |
256 | - ルで指定。z1, z2等を指定すると、割り込み用サブルーチンの引数となる。現在使用 | |
257 | - 可能な割り込みの種類は以下の通り。 | |
256 | + ルで指定。z1, z2等を指定すると、割り込み用サブルーチンの引数となる。使用可能 | |
257 | + な割り込みの種類は以下の通り。 | |
258 | 258 | TIMER |
259 | 259 | タイマー割り込み。タイマー値が1増えるごとに割り込みがかかる。 |
260 | + DRAWCOUNT | |
261 | + 1/60秒毎の割り込み。 | |
262 | + KEYS | |
263 | + ボタンの押下状態が変化した時。 | |
264 | + KEYINPUT | |
265 | + キーボード押下時。 | |
266 | + MUSIC | |
267 | + 音楽再生の時、最後の音の再生時に割り込み。 | |
268 | + WAVE | |
269 | + WAVEファイル再生終了時。 | |
270 | + | |
271 | +INTERRUPT STOP xxx | |
272 | + 割り込みを停止する。xxxは割り込みの種類。 | |
260 | 273 | |
261 | 274 | <整数型関数> |
262 | 275 | 以下、x, y, zは整数値を、x$, y$, z$は文字列を指します。[ ]は省略可能である事 |
@@ -106,12 +106,10 @@ int musicRemaining(int flagsLR){ | ||
106 | 106 | return (g_musicend-g_musicstart)&31; |
107 | 107 | } |
108 | 108 | |
109 | -#pragma interrupt musicint IPL3SOFT vector 1 | |
110 | 109 | void musicint(){ |
111 | 110 | unsigned int i; |
112 | 111 | static unsigned short wavtable_pos; |
113 | 112 | // This function is called every 1/60 sec. |
114 | - IFS0bits.CS0IF=0; | |
115 | 113 | switch(g_sound_mode){ |
116 | 114 | case SOUND_MODE_MUSIC: |
117 | 115 | if (g_soundstart!=g_soundend){ |
@@ -160,6 +158,10 @@ void musicint(){ | ||
160 | 158 | g_musicstart++; |
161 | 159 | g_musicstart&=31; |
162 | 160 | g_musicwait=g_musiclen[g_musicstart]; |
161 | + if (((g_musicstart+1)&31)==g_musicend) { | |
162 | + // Raise MUSIC interrupt flag | |
163 | + raise_interrupt_flag(INTERRUPT_MUSIC); | |
164 | + } | |
163 | 165 | } |
164 | 166 | } else { |
165 | 167 | // Stop timer |
@@ -181,6 +183,8 @@ void musicint(){ | ||
181 | 183 | g_fhandle=0; |
182 | 184 | g_sound_mode=SOUND_MODE_MUSIC; |
183 | 185 | stop_music(); |
186 | + // Raise WAVE interrupt flag | |
187 | + raise_interrupt_flag(INTERRUPT_WAVE); | |
184 | 188 | break; |
185 | 189 | } |
186 | 190 | break; |
@@ -216,12 +220,6 @@ void stop_music(){ | ||
216 | 220 | OC4CONSET=0x8000;// Start OC4 |
217 | 221 | T3CON=0x0050; // Prescaller: 1:32 (1.8 MHz), not yet started |
218 | 222 | |
219 | - // Software interrupt every 1/60 sec (triggered by Timer5) | |
220 | - IPC0bits.CS0IP=3; | |
221 | - IPC0bits.CS0IS=0; | |
222 | - IFS0bits.CS0IF=0; | |
223 | - IEC0bits.CS0IE=1; | |
224 | - | |
225 | 223 | // Initializations for music/sound. |
226 | 224 | g_musicstart=g_musicend=g_musicwait=g_soundstart=g_soundend=g_soundwait=g_soundrepeat=0; |
227 | 225 | g_sound_mode=SOUND_MODE_MUSIC; |
@@ -238,6 +236,9 @@ void stop_music(){ | ||
238 | 236 | // Close handle if open. |
239 | 237 | if (g_fhandle) FSfclose(g_fhandle); |
240 | 238 | g_fhandle=0; |
239 | + | |
240 | + // Inactive music first | |
241 | + g_music_active=0; | |
241 | 242 | } |
242 | 243 | |
243 | 244 | void init_music(){ |
@@ -445,6 +446,7 @@ void set_sound(unsigned long* data, int flagsLR){ | ||
445 | 446 | g_soundend=pos; |
446 | 447 | g_soundwait=g_soundlen[0]; |
447 | 448 | IEC0bits.T4IE=1; // Restart interrupt. |
449 | + g_music_active=1;// Activate music system | |
448 | 450 | } |
449 | 451 | |
450 | 452 | void set_music(char* str, int flagsLR){ |
@@ -547,6 +549,7 @@ void set_music(char* str, int flagsLR){ | ||
547 | 549 | // Go to next character |
548 | 550 | while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++; |
549 | 551 | } |
552 | + g_music_active=1;// Activate music system | |
550 | 553 | } |
551 | 554 | |
552 | 555 | /* |
@@ -636,4 +639,5 @@ void play_wave(char* filename, int start){ | ||
636 | 639 | init_dma_music(); |
637 | 640 | g_sound_mode=SOUND_MODE_WAVE; |
638 | 641 | |
642 | + g_music_active=1;// Activate music system | |
639 | 643 | } |
@@ -11,22 +11,33 @@ | ||
11 | 11 | |
12 | 12 | #include <xc.h> |
13 | 13 | #include "compiler.h" |
14 | +#include "api.h" | |
14 | 15 | |
15 | 16 | /* |
16 | - 16 different type interruptions are possible. | |
17 | + 32 different type interruptions are possible. | |
17 | 18 | See definition in compiler.h like: |
18 | - #define NUM_INTERRUPT_TYPES 1 | |
19 | 19 | #define INTERRUPT_TIMER 0 |
20 | - extern short g_interrupt_flags; | |
21 | - extern int g_int_vector[NUM_INTERRUPT_TYPES]; | |
20 | + extern int g_interrupt_flags; | |
21 | + extern int g_int_vector[]; | |
22 | 22 | #define raise_interrupt_flag(x) do {\ |
23 | 23 | */ |
24 | 24 | |
25 | 25 | // Timer value that increments every timer event |
26 | 26 | static int g_timer; |
27 | 27 | |
28 | +// Interrupt types | |
29 | +static const void* interrupt_list[]={ | |
30 | + "TIMER", (void*)INTERRUPT_TIMER, | |
31 | + "DRAWCOUNT",(void*)INTERRUPT_DRAWCOUNT, | |
32 | + "KEYS", (void*)INTERRUPT_KEYS, | |
33 | + "KEYINPUT", (void*)INTERRUPT_KEYINPUT, | |
34 | + "MUSIC", (void*)INTERRUPT_MUSIC, | |
35 | + "WAVE", (void*)INTERRUPT_WAVE, | |
36 | + ADDITIONAL_INTERRUPT_FUNCTIONS | |
37 | +}; | |
38 | +#define NUM_INTERRUPT_TYPES ((sizeof(interrupt_list)/sizeof(interrupt_list[0]))/2) | |
28 | 39 | // Flags for interrupt |
29 | -short g_interrupt_flags; | |
40 | +int g_interrupt_flags; | |
30 | 41 | // Jump address when interrupt |
31 | 42 | int g_int_vector[NUM_INTERRUPT_TYPES]; |
32 | 43 |
@@ -45,6 +56,11 @@ void init_timer(){ | ||
45 | 56 | // Disable interrupt |
46 | 57 | IEC0bits.CS1IE=0; |
47 | 58 | for(i=0;i<NUM_INTERRUPT_TYPES;i++) g_int_vector[i]=0; |
59 | + // CS0 interrupt every 1/60 sec (triggered by Timer2) | |
60 | + IPC0bits.CS0IP=3; | |
61 | + IPC0bits.CS0IS=0; | |
62 | + IFS0bits.CS0IF=0; | |
63 | + IEC0bits.CS0IE=1; | |
48 | 64 | } |
49 | 65 | |
50 | 66 | void stop_timer(){ |
@@ -190,12 +206,29 @@ char* interrupt_statement(){ | ||
190 | 206 | int itype; |
191 | 207 | int i,opos; |
192 | 208 | char* err; |
193 | - next_position(); | |
194 | - if (nextCodeIs("TIMER")) { | |
195 | - itype=INTERRUPT_TIMER; | |
209 | + int stop=0; | |
210 | + // Check if STOP | |
211 | + stop=nextCodeIs("STOP "); | |
212 | + // Seek the interrupt | |
213 | + for (i=0;i<NUM_INTERRUPT_TYPES;i++){ | |
214 | + if (nextCodeIs((char*)interrupt_list[i*2])) break; | |
215 | + } | |
216 | + if (i<NUM_INTERRUPT_TYPES) { | |
217 | + // Interrupt found | |
218 | + itype=(int)interrupt_list[i*2+1]; | |
196 | 219 | } else { |
220 | + // Interrupt not found | |
197 | 221 | return ERR_SYNTAX; |
198 | 222 | } |
223 | + // Compile INTERRUPT STOP | |
224 | + if (stop) { | |
225 | + // g_int_vector[itype]=0; | |
226 | + i=(int)(&g_int_vector[itype]); | |
227 | + i-=g_gp; | |
228 | + check_obj_space(1); | |
229 | + g_object[g_objpos++]=0xAF800000|(i&0x0000FFFF); // sw zero,xxxx(gp) | |
230 | + return 0; | |
231 | + } | |
199 | 232 | // Detect ',' |
200 | 233 | next_position(); |
201 | 234 | if (g_source[g_srcpos]!=',') return ERR_SYNTAX; |
@@ -225,3 +258,40 @@ char* interrupt_statement(){ | ||
225 | 258 | return 0; |
226 | 259 | } |
227 | 260 | |
261 | +/* | |
262 | + CS0 interrupt | |
263 | + IPL3SOFT vector 1 | |
264 | + | |
265 | + This interrupt is always active. Therefore, Do things as few as possible. | |
266 | + 1) Call music function if needed. | |
267 | + MUSIC interrupt is taken by music.c | |
268 | + 2) Check buttons for KEYS interrupt | |
269 | + 3) Check PS/2 for KEYINPUT interrupt | |
270 | + 4) DRAWCOUNT interrupt | |
271 | +*/ | |
272 | + | |
273 | +#pragma interrupt CS0Handler IPL3SOFT vector 1 | |
274 | +void CS0Handler(void){ | |
275 | + static int s_keys=-1; | |
276 | + static int s_vkey=0; | |
277 | + IFS0bits.CS0IF=0; | |
278 | + // Call music function | |
279 | + if (g_music_active) musicint(); | |
280 | + // The interrupts are valid only when CS1 is active | |
281 | + if (IEC0bits.CS1IE) { | |
282 | + // Raise DRAWCOUNT interrupt flag | |
283 | + raise_interrupt_flag(INTERRUPT_DRAWCOUNT); | |
284 | + // Check buttons | |
285 | + if (0<=s_keys && s_keys!=(KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))) { | |
286 | + // Raise KEYS interrupt flag | |
287 | + raise_interrupt_flag(INTERRUPT_KEYS); | |
288 | + } | |
289 | + s_keys!=KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE); | |
290 | + // Check PS/2 keyboard down | |
291 | + if ((vkey&0xff) && !s_vkey) { | |
292 | + // Raise KEYINPUT interrupt flag | |
293 | + raise_interrupt_flag(INTERRUPT_KEYINPUT); | |
294 | + } | |
295 | + s_vkey=vkey&0xff; | |
296 | + } | |
297 | +} | |
\ No newline at end of file |