• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

BASIC compiler/interpreter for PIC32MX/MZ-80K


Commit MetaInfo

Revision763a11a56ff57be184c7e6a19ab61205c86c3ffb (tree)
Zeit2019-04-07 08:59:25
AutorKatsumi <kmorimatsu@sour...>
CommiterKatsumi

Log Message

Megalopa update for TIMER, INTERRUPT, and OPTION

Ändern Zusammenfassung

Diff

--- a/mips/megalopa/class.c
+++ b/mips/megalopa/class.c
@@ -157,7 +157,8 @@ char* resolve_unresolved(int class){
157157 break;
158158 default:
159159 return ERR_UNKNOWN;
160- } }
160+ }
161+ }
161162 return 0;
162163 }
163164
@@ -194,6 +195,15 @@ char* update_class_info(int class){
194195 cstruct[z+1]: public method pointer
195196 */
196197
198+/*
199+ Object structure:
200+ object[0]: pointer to class structure
201+ object[1]: field value
202+ ...
203+ object[n]: field value
204+ (according to class structure; public field(s) first, then private field(s))
205+*/
206+
197207 char* construct_class_structure(int class){
198208 int* record;
199209 int i;
--- a/mips/megalopa/compiler.c
+++ b/mips/megalopa/compiler.c
@@ -110,8 +110,9 @@ int nextCodeIs(char* str){
110110 if (!strncmp(g_source+g_srcpos,str,len)) {
111111 if ('A'<=str[len-1] && str[len-1]<='Z') {
112112 // When the last character of str is alphabet,
113- // the next character in source must be space, enter, or ':'.
114- if (0x20<g_source[g_srcpos+len] && g_source[g_srcpos+len]!=':') return 0;
113+ // the next character in source must be space, enter, ',', or ':'.
114+ if (0x20<g_source[g_srcpos+len] &&
115+ g_source[g_srcpos+len]!=':' && g_source[g_srcpos+len]!=',') return 0;
115116 }
116117 // String matches in the current position in source.
117118 g_srcpos+=len;
@@ -160,8 +161,10 @@ char* compile_line(void){
160161 printstr(resolve_label(g_line));
161162 return ERR_MULTIPLE_LABEL;
162163 }
163- check_obj_space(1);
164- g_object[g_objpos++]=0x34160000|g_line; //ori s6,zero,xxxx;
164+ if (!g_nolinenum) {
165+ check_obj_space(1);
166+ g_object[g_objpos++]=0x34160000|g_line; //ori s6,zero,xxxx;
167+ }
165168 }
166169 while(g_source[g_srcpos]!=0x0D && g_source[g_srcpos]!=0x0A){
167170 err=statement();
--- a/mips/megalopa/compiler.h
+++ b/mips/megalopa/compiler.h
@@ -213,6 +213,7 @@ extern int g_var_mem[ALLOC_BLOCK_NUM];
213213 extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
214214 extern unsigned short g_var_size[ALLOC_BLOCK_NUM];
215215 extern char g_temp_area_used;
216+extern char g_nolinenum;
216217 extern int* g_heap_mem;
217218 extern int g_max_mem;
218219 extern char g_disable_break;
@@ -221,6 +222,7 @@ extern char g_use_graphic;
221222 extern unsigned short* g_graphic_area;
222223 extern int* g_libparams;
223224 extern int g_long_name_var_num;
225+extern char g_music_active;
224226 extern int g_class;
225227 extern int g_compiling_class;
226228 extern int g_temp;
@@ -260,6 +262,7 @@ void err_not_field(int fieldname, int classname);
260262 void err_str(char* str);
261263 char* resolve_label(int s6);
262264
265+void musicint();
263266 void set_sound(unsigned long* data, int flagsLR);
264267 int musicRemaining(int flagsLR);
265268 int waveRemaining(int mode);
@@ -367,6 +370,13 @@ char* static_statement();
367370 char* static_method(char type);
368371 char* resolve_unresolved(int class);
369372
373+void init_timer();
374+void stop_timer();
375+char* usetimer_statement();
376+char* timer_statement();
377+char* timer_function();
378+char* interrupt_statement();
379+
370380 /* Error messages */
371381 #define ERR_SYNTAX (char*)(g_err_str[0])
372382 #define ERR_NE_BINARY (char*)(g_err_str[1])
@@ -474,6 +484,25 @@ char* resolve_unresolved(int class);
474484 #define ASM_LW_A0_XXXX_S8 0x8FC40000
475485 #define ASM_LW_A0_XXXX_S5 0x8EA40000
476486
487+// Interrupt macros
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_INKEY 3
494+#define INTERRUPT_MUSIC 4
495+#define INTERRUPT_WAVE 5
496+
497+extern int g_interrupt_flags;
498+extern int g_int_vector[];
499+#define raise_interrupt_flag(x) do {\
500+ if (g_int_vector[x]) {\
501+ IFS0bits.CS1IF=1;\
502+ g_interrupt_flags|=(1<<(x));\
503+ }\
504+} while(0)
505+
477506 // Division macro for unsigned long
478507 // Valid for 31 bits for all cases and 32 bits for some cases
479508 #define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
--- a/mips/megalopa/debug.c
+++ b/mips/megalopa/debug.c
@@ -228,11 +228,14 @@ static const char initext[]=
228228 "#PRINT\n";
229229
230230 static const char bastext[]=
231-"print getdir$()\n"
232-"end\n"
233-"\n"
231+"I=1:WHILE I<=10\n"
232+"I=I+1:WEND\n"
234233 "\n"
234+"I=1:DO\n"
235+"I=I+1:LOOP UNTIL I=11\n"
235236 "\n"
237+"FOR I=1 TO 10\n"
238+"NEXT\n"
236239 "\n"
237240 "\n"
238241 "\n";
@@ -268,12 +271,10 @@ static const void* debugjumptable[]={
268271 FSfopen,
269272 };
270273
274+#define for2(x,y,z) for(x=y;x<=z;x++)
275+
271276 int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
272277 asm volatile(".set noreorder");
273- asm volatile("lw $a0,4($s5)");
274- asm volatile("lw $a1,8($s5)");
275- asm volatile("lw $a2,12($s5)");
276- asm volatile("lw $a3,16($s5)");
277278 asm volatile("nop");
278279 asm volatile("nop");
279280 asm volatile("nop");
@@ -281,6 +282,12 @@ int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
281282 asm volatile("nop");
282283 asm volatile("nop");
283284 asm volatile("nop");
285+ asm volatile("nop");
286+ asm volatile("nop");
287+ asm volatile("nop");
288+ asm volatile("nop");
289+ asm volatile("nop");
290+ a2&=0xFFFFFFFC;
284291 return a2+a3;
285292 }
286293
--- a/mips/megalopa/envspecific.h
+++ b/mips/megalopa/envspecific.h
@@ -8,6 +8,7 @@
88 // Megalopa uses I/O statements/functions
99 #include "io.h"
1010
11+#define CPU_CLOCK_HZ 95454533
1112 #define PERSISTENT_RAM_SIZE (1024*100)
1213
1314 int readbuttons();
@@ -108,3 +109,5 @@ enum extra{
108109 EXTRA_SPISWAPDATA =EXTRA_STEP*25,
109110 // MAX 63
110111 };
112+
113+#define ADDITIONAL_INTERRUPT_FUNCTIONS
--- a/mips/megalopa/exception.c
+++ b/mips/megalopa/exception.c
@@ -44,7 +44,12 @@ void dumpMemory(){
4444 void dumpMemory(){}
4545 #endif //ifdef DUMPFILE
4646
47+void _general_exception_handler_main (void);
4748 void _general_exception_handler (void){
49+ asm volatile("la $sp,%0"::"i"(&RAM[RAMSIZE-4]));
50+ asm volatile("j _general_exception_handler_main");
51+}
52+void _general_exception_handler_main (void){
4853 int i;
4954 // $v1 is g_ex_data
5055 asm volatile("la $v1,%0"::"i"(&g_ex_data[0]));
@@ -79,7 +84,9 @@ void _general_exception_handler (void){
7984 if((readbuttons()&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))
8085 !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0;
8186 }
82- asm volatile("j SoftReset");
87+ RCONbits.POR=0;
88+ RCONbits.EXTR=0;
89+ asm volatile("j 0x9FC00000");
8390 #endif
8491 }
8592
--- a/mips/megalopa/file.c
+++ b/mips/megalopa/file.c
@@ -122,7 +122,10 @@ int compile_and_link_file(char* buff,char* appname){
122122 printchar('\n');
123123 return -1;
124124 }
125-
125+
126+ // Option initialization(s)
127+ g_nolinenum=0;
128+
126129 // Compile the file
127130 err=compile_file();
128131 close_file();
--- a/mips/megalopa/function.c
+++ b/mips/megalopa/function.c
@@ -157,7 +157,6 @@ char* rnd_function(){
157157 return 0;
158158 }
159159
160-
161160 char* chr_function(void){
162161 char* err;
163162 err=get_value();
@@ -597,6 +596,7 @@ static const void* int_func_list[]={
597596 "PLAYWAVE(",playwave_function,
598597 "NEW(",new_function,
599598 "SETDIR(",setdir_function,
599+ "TIMER(",timer_function,
600600 // Additional functions follow
601601 ADDITIONAL_INT_FUNCTIONS
602602 };
--- a/mips/megalopa/globalvars.c
+++ b/mips/megalopa/globalvars.c
@@ -55,6 +55,9 @@ unsigned short g_var_size[ALLOC_BLOCK_NUM];
5555 // Flag to use temporary area when compiling
5656 char g_temp_area_used;
5757
58+// Flag to use option nolinenum
59+char g_nolinenum;
60+
5861 // Heap area
5962 int* g_heap_mem;
6063 int g_max_mem;
@@ -80,6 +83,9 @@ int* g_libparams;
8083 // Number of long name variables
8184 int g_long_name_var_num;
8285
86+// Flag for active music/sound/wave function
87+char g_music_active;
88+
8389 // Class name being compiled
8490 int g_class;
8591 // Flag to compile class file
--- a/mips/megalopa/megalopa.mcp
+++ b/mips/megalopa/megalopa.mcp
@@ -71,6 +71,7 @@ file_043=.
7171 file_044=.
7272 file_045=.
7373 file_046=.
74+file_047=.
7475 [GENERATED_FILES]
7576 file_000=no
7677 file_001=no
@@ -119,6 +120,7 @@ file_043=no
119120 file_044=no
120121 file_045=no
121122 file_046=no
123+file_047=no
122124 [OTHER_FILES]
123125 file_000=no
124126 file_001=no
@@ -163,10 +165,11 @@ file_039=no
163165 file_040=no
164166 file_041=no
165167 file_042=no
166-file_043=yes
168+file_043=no
167169 file_044=yes
168170 file_045=yes
169171 file_046=yes
172+file_047=yes
170173 [FILE_INFO]
171174 file_000=compiler.c
172175 file_001=debug.c
@@ -196,25 +199,26 @@ file_024=spi.c
196199 file_025=class.c
197200 file_026=args.c
198201 file_027=interface\keyinput.c
199-file_028=api.h
200-file_029=compiler.h
201-file_030=debug.h
202-file_031=editor.h
203-file_032=main.h
204-file_033=envspecific.h
205-file_034=io.h
206-file_035=interface\keyinput.h
207-file_036=interface\lib_video_megalopa.h
208-file_037=interface\ps2keyboard.h
209-file_038=interface\sdfsio370f.h
210-file_039=interface\lib_videoout_megalopa.X.a
211-file_040=interface\ps2keyboard370f.X.a
212-file_041=interface\sdfsio370fLib.X.a
213-file_042=app_p32MX370F512H.ld
214-file_043=help.txt
215-file_044=reservednames.js
216-file_045=class.txt
217-file_046=sharedfiles.js
202+file_028=timer.c
203+file_029=api.h
204+file_030=compiler.h
205+file_031=debug.h
206+file_032=editor.h
207+file_033=main.h
208+file_034=envspecific.h
209+file_035=io.h
210+file_036=interface\keyinput.h
211+file_037=interface\lib_video_megalopa.h
212+file_038=interface\ps2keyboard.h
213+file_039=interface\sdfsio370f.h
214+file_040=interface\lib_videoout_megalopa.X.a
215+file_041=interface\ps2keyboard370f.X.a
216+file_042=interface\sdfsio370fLib.X.a
217+file_043=app_p32MX370F512H.ld
218+file_044=help.txt
219+file_045=reservednames.js
220+file_046=class.txt
221+file_047=sharedfiles.js
218222 [SUITE_INFO]
219223 suite_guid={62D235D8-2DB2-49CD-AF24-5489A6015337}
220224 suite_state=
--- a/mips/megalopa/music.c
+++ b/mips/megalopa/music.c
@@ -142,7 +142,6 @@ int waveRemaining(int mode){
142142 return ret;
143143 }
144144
145-#pragma interrupt musicint IPL2SOFT vector 1
146145 void musicint(){
147146 static unsigned short wavtable_pos;
148147 static int music_freq_L=0;
@@ -151,7 +150,6 @@ void musicint(){
151150 static int music_timer_R=0;
152151 unsigned int i,j;
153152 // This function is called every 1/60 sec.
154- IFS0bits.CS0IF=0;
155153 switch(g_sound_mode){
156154 case SOUND_MODE_WAVE:
157155 // Initialize parameters
@@ -169,6 +167,8 @@ void musicint(){
169167 g_fhandle=0;
170168 g_sound_mode=SOUND_MODE_NONE;
171169 stop_music();
170+ // Raise WAVE interrupt flag
171+ raise_interrupt_flag(INTERRUPT_WAVE);
172172 break;
173173 }
174174 // Continue to MUSIC sound mode
@@ -197,6 +197,10 @@ void musicint(){
197197 g_musicstartL++;
198198 g_musicstartL&=31;
199199 g_musicwaitL=g_musiclenL[g_musicstartL];
200+ if (((g_musicstartL+1)&31)==g_musicendL) {
201+ // Raise MUSIC interrupt flag
202+ raise_interrupt_flag(INTERRUPT_MUSIC);
203+ }
200204 }
201205 }
202206 } else if (g_musicstartL!=g_musicendL) {
@@ -206,6 +210,10 @@ void musicint(){
206210 g_musicstartL++;
207211 g_musicstartL&=31;
208212 g_musicwaitL=g_musiclenL[g_musicstartL];
213+ if (((g_musicstartL+1)&31)==g_musicendL) {
214+ // Raise MUSIC interrupt flag
215+ raise_interrupt_flag(INTERRUPT_MUSIC);
216+ }
209217 }
210218 } else {
211219 music_freq_L=0;
@@ -234,6 +242,10 @@ void musicint(){
234242 g_musicstartR++;
235243 g_musicstartR&=31;
236244 g_musicwaitR=g_musiclenR[g_musicstartR];
245+ if (((g_musicstartR+1)&31)==g_musicendR) {
246+ // Raise MUSIC interrupt flag
247+ raise_interrupt_flag(INTERRUPT_MUSIC);
248+ }
237249 }
238250 }
239251 } else if (g_musicstartR!=g_musicendR) {
@@ -243,6 +255,10 @@ void musicint(){
243255 g_musicstartR++;
244256 g_musicstartR&=31;
245257 g_musicwaitR=g_musiclenR[g_musicstartR];
258+ if (((g_musicstartR+1)&31)==g_musicendR) {
259+ // Raise MUSIC interrupt flag
260+ raise_interrupt_flag(INTERRUPT_MUSIC);
261+ }
246262 }
247263 } else {
248264 music_freq_R=0;
@@ -420,11 +436,6 @@ void init_music(){
420436
421437 // Move OC4RS and OC3 RS from 0x00 to 0x80
422438 g_sound_mode=SOUND_MODE_NONE;
423- // Enable interrupt
424- IPC0bits.CS0IP=2;
425- IPC0bits.CS0IS=0;
426- IFS0bits.CS0IF=0;
427- IEC0bits.CS0IE=1;
428439 }
429440
430441 void musicSetL(){
@@ -629,6 +640,7 @@ void set_sound(unsigned long* data, int flagsLR){
629640 if (flagsLR & MFLAG_L) g_soundwaitL=g_soundlenL[0];
630641 if (flagsLR & MFLAG_R) g_soundwaitR=g_soundlenR[0];
631642 IEC0bits.CS0IE=1; // Restart interrupt.
643+ g_music_active=1;// Activate music system
632644 }
633645
634646 void set_music(char* str, int flagsLR){
@@ -741,6 +753,7 @@ void set_music(char* str, int flagsLR){
741753 // Go to next character
742754 while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++;
743755 }
756+ g_music_active=1;// Activate music system
744757 }
745758
746759 /*
@@ -886,6 +899,7 @@ void play_wave(char* filename, int start){
886899 // Enable intterupt
887900 IFS0bits.CS0IF=0;
888901 IEC0bits.CS0IE=1;
902+ g_music_active=1;// Activate music system
889903 }
890904
891905 void stop_music(){
@@ -899,4 +913,6 @@ void stop_music(){
899913 FSfclose(g_fhandle);
900914 g_fhandle=0;
901915 }
916+ // Inactive music
917+ g_music_active=0;
902918 }
--- a/mips/megalopa/reservednames.js
+++ b/mips/megalopa/reservednames.js
@@ -110,6 +110,7 @@ var namearray=[
110110 'NEXT',
111111 'NEW',
112112 'NOT',
113+ 'OPTION',
113114 'PCG',
114115 'PEEK',
115116 'PEEK16',
@@ -138,6 +139,7 @@ var namearray=[
138139 'SYSTEM',
139140 'TAN',
140141 'TANH',
142+ 'TIMER',
141143 'TVRAM',
142144 'UNTIL',
143145 'USEPCG',
--- a/mips/megalopa/run.c
+++ b/mips/megalopa/run.c
@@ -116,6 +116,7 @@ int runbasic(char *appname,int test){
116116
117117 // Warm up environment
118118 pre_run();
119+ init_timer();
119120
120121 // Execute program
121122 // Start program from the beginning of RAM.
@@ -126,6 +127,7 @@ int runbasic(char *appname,int test){
126127 // Cool down environment
127128 post_run();
128129 lib_file(FUNC_FINIT,0,0,0);
130+ stop_timer();
129131
130132 return 0;
131133 }
--- a/mips/megalopa/sharedfiles.js
+++ b/mips/megalopa/sharedfiles.js
@@ -28,6 +28,7 @@ var filearray=[
2828 'run.c',
2929 'string.c',
3030 'statement.c',
31+ 'timer.c',
3132 'value.c',
3233 'varname.c',
3334 'compiler.h',
--- a/mips/megalopa/statement.c
+++ b/mips/megalopa/statement.c
@@ -1550,6 +1550,24 @@ char* setdir_statement(){
15501550 return 0;
15511551 }
15521552
1553+char* option_statement(){
1554+ while(1){
1555+ next_position();
1556+ if (nextCodeIs("NOLINENUM")) {
1557+ g_nolinenum=1;
1558+ } else {
1559+ return ERR_SYNTAX;
1560+ }
1561+ next_position();
1562+ if (g_source[g_srcpos]==',') {
1563+ g_srcpos++;
1564+ } else {
1565+ break;
1566+ }
1567+ }
1568+ return 0;
1569+}
1570+
15531571 #ifdef __DEBUG
15541572 char* debug_statement(){
15551573 call_lib_code(LIB_DEBUG);
@@ -1698,6 +1716,10 @@ static const void* statement_list[]={
16981716 "CALL ",call_statement,
16991717 "STATIC ",static_statement,
17001718 "SETDIR ",setdir_statement,
1719+ "OPTION ",option_statement,
1720+ "USETIMER ",usetimer_statement,
1721+ "TIMER ",timer_statement,
1722+ "INTERRUPT ",interrupt_statement,
17011723 // List of additional statements follows
17021724 ADDITIONAL_STATEMENTS
17031725 };
--- /dev/null
+++ b/mips/megalopa/timer.c
@@ -0,0 +1,326 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include <xc.h>
13+#include "compiler.h"
14+#include "api.h"
15+
16+/*
17+ 32 different type interruptions are possible.
18+ See definition in compiler.h like:
19+ #define INTERRUPT_TIMER 0
20+ extern int g_interrupt_flags;
21+ extern int g_int_vector[];
22+ #define raise_interrupt_flag(x) do {\
23+*/
24+
25+// Timer value that increments every timer event
26+static int g_timer;
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+ "INKEY", (void*)INTERRUPT_INKEY,
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)
39+// Flags for interrupt
40+int g_interrupt_flags;
41+// Jump address when interrupt
42+int g_int_vector[NUM_INTERRUPT_TYPES];
43+
44+/*
45+ Initialize and termination
46+*/
47+
48+void init_timer(){
49+ int i;
50+ // Stop timer, first
51+ T1CON=0x0000;
52+ IEC0bits.T1IE=0;
53+ TMR1=0;
54+ PR1=0xffff;
55+ g_timer=0;
56+ // Disable interrupt
57+ IEC0bits.CS1IE=0;
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;
64+}
65+
66+void stop_timer(){
67+ // Stop timer
68+ T1CON=0x0000;
69+ IEC0bits.T1IE=0;
70+ // Disable interrupt
71+ IEC0bits.CS1IE=0;
72+}
73+
74+/*
75+ Timer interprtation
76+*/
77+
78+// Interrupt handler
79+#ifndef __DEBUG
80+ // Timer1 is also used for debug mode
81+ #pragma interrupt T1Handler IPL2SOFT vector 4
82+#endif
83+void T1Handler(void){
84+ g_timer++;
85+ // Clear Timer1 interrupt flag
86+ IFS0bits.T1IF=0;
87+ // Raise TIMER interrupt flag
88+ raise_interrupt_flag(INTERRUPT_TIMER);
89+}
90+
91+void lib_usetimer(int hz){
92+ int temppr1;
93+ // Stop timer, first
94+ T1CON=0x0000;
95+ IEC0bits.T1IE=0;
96+ TMR1=0;
97+ PR1=0xffff;
98+ if (!hz) {
99+ return;
100+ }
101+ // PR1 setting
102+ temppr1=CPU_CLOCK_HZ/hz;
103+ if (temppr1<=65536) {
104+ // no prescaler
105+ T1CON=0x0000;
106+ PR1=temppr1-1;
107+ } else if ((temppr1>>3)<=65536) {
108+ // 1/8 prescaler
109+ T1CON=0x0010;
110+ PR1=(temppr1>>3)-1;
111+ } else if ((temppr1>>6)<=65536) {
112+ // 1/64 prescaler
113+ T1CON=0x0020;
114+ PR1=(temppr1>>6)-1;
115+ } else if ((temppr1>>8)<=65536) {
116+ // 1/256 prescaler
117+ T1CON=0x0030;
118+ PR1=(temppr1>>8)-1;
119+ } else {
120+ err_invalid_param();
121+ }
122+ // Timer1 interrupt: priority 2
123+ IPC1bits.T1IP=2;
124+ IPC1bits.T1IS=0;
125+ IEC0bits.T1IE=1;
126+ // Start timer
127+ T1CONbits.ON=1;
128+}
129+
130+char* usetimer_statement(){
131+ char* err;
132+ err=get_value();
133+ if (err) return err;
134+ call_quicklib_code(lib_usetimer,ASM_ADDU_A0_V0_ZERO);
135+ return 0;
136+}
137+
138+char* timer_statement(){
139+ int i;
140+ char* err;
141+ err=get_value();
142+ if (err) return err;
143+ i=(int)(&g_timer);
144+ check_obj_space(3);
145+ g_object[g_objpos++]=0x3C030000|((i>>16)&0x0000FFFF); // lui v1,xxxx
146+ g_object[g_objpos++]=0x34630000|(i&0x0000FFFF); // ori v1,v1,xxxx
147+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
148+ return 0;
149+}
150+
151+char* timer_function(){
152+ int i;
153+ i=(int)(&g_timer);
154+ check_obj_space(3);
155+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
156+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
157+ g_object[g_objpos++]=0x8C420000; // lw v0,0(v0)
158+ return 0;
159+}
160+
161+/*
162+ Interrupt interprtation
163+ To cause interruption, use raise_interrupt_flag() macro
164+ For example,
165+ raise_interrupt_flag(INTERRUPT_TIMER);
166+
167+*/
168+
169+void BasicInt(int addr){
170+ // Note that $s0-$s7 values must be set again here.
171+ asm volatile(".set noreorder");
172+ // Set s5 for initial_s5_stack
173+ asm volatile("la $s5,%0"::"i"(&g_initial_s5_stack[2]));
174+ // Set s7 for easy calling call_library()
175+ asm volatile("la $s7,%0"::"i"(&call_library));
176+ // $a0 is the address in BASIC code
177+ asm volatile("jr $a0");
178+ asm volatile("nop");
179+}
180+#pragma interrupt CS1Handler IPL1SOFT vector 2
181+void CS1Handler(void){
182+ int i;
183+ // Store s0-s7, fp, and ra in stacks
184+ asm volatile("#":::"s0");
185+ asm volatile("#":::"s1");
186+ asm volatile("#":::"s2");
187+ asm volatile("#":::"s3");
188+ asm volatile("#":::"s4");
189+ asm volatile("#":::"s5");
190+ asm volatile("#":::"s6");
191+ asm volatile("#":::"s7");
192+ asm volatile("#":::"fp");
193+ asm volatile("#":::"ra");
194+ while(g_interrupt_flags){
195+ for(i=0;i<NUM_INTERRUPT_TYPES;i++){
196+ if (g_interrupt_flags & (1<<i)) {
197+ if (g_int_vector[i]) BasicInt(g_int_vector[i]);
198+ g_interrupt_flags &= (1<<i)^0xffff;
199+ }
200+ }
201+ }
202+ IFS0bits.CS1IF=0;
203+}
204+
205+void lib_interrupt_main(int itype, int address){
206+ // Set address
207+ g_int_vector[itype]=address;
208+ // CS1 interrupt: priority 1
209+ IPC0bits.CS1IP=1;
210+ IPC0bits.CS1IS=0;
211+ IEC0bits.CS1IE=1;
212+}
213+
214+void lib_interrupt(int itype){
215+ // $ra contains the address for interrupt
216+ // $ra is 2 word before the interrupt address
217+ asm volatile("addiu $a1,$ra,8");
218+ asm volatile("j lib_interrupt_main");
219+}
220+
221+char* interrupt_statement(){
222+ int itype;
223+ int i,opos;
224+ char* err;
225+ int stop=0;
226+ // Check if STOP
227+ stop=nextCodeIs("STOP ");
228+ // Seek the interrupt
229+ for (i=0;i<NUM_INTERRUPT_TYPES;i++){
230+ if (nextCodeIs((char*)interrupt_list[i*2])) break;
231+ }
232+ if (i<NUM_INTERRUPT_TYPES) {
233+ // Interrupt found
234+ itype=(int)interrupt_list[i*2+1];
235+ } else {
236+ // Interrupt not found
237+ return ERR_SYNTAX;
238+ }
239+ // Compile INTERRUPT STOP
240+ if (stop) {
241+ // g_int_vector[itype]=0;
242+ i=(int)(&g_int_vector[itype]);
243+ i-=g_gp;
244+ check_obj_space(1);
245+ g_object[g_objpos++]=0xAF800000|(i&0x0000FFFF); // sw zero,xxxx(gp)
246+ return 0;
247+ }
248+ // Detect ','
249+ next_position();
250+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
251+ g_srcpos++;
252+ // Store address to call
253+ call_quicklib_code(lib_interrupt,ASM_ORI_A0_ZERO_|itype);
254+ check_obj_space(4);
255+ // Skip the region used for interrupt-calling
256+ opos=g_objpos;
257+ g_object[g_objpos++]=0x10000000; // b xxxxx
258+ g_object[g_objpos++]=0x00000000; // nop
259+ // Begin interrupt-calling region
260+ // Store $ra
261+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
262+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
263+ // Compile as GOSUB statement
264+ err=gosub_statement();
265+ if (err) return err;
266+ // Retore $ra and return
267+ check_obj_space(3);
268+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
269+ g_object[g_objpos++]=0x03E00008; // jr ra
270+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4
271+ // End interrupt-calling region
272+ // Complete B assembly
273+ g_object[opos]|=g_objpos-opos-1;
274+ return 0;
275+}
276+
277+/*
278+ CS0 interrupt
279+ IPL3SOFT vector 1
280+
281+ This interrupt is always active. Therefore, Do things as few as possible.
282+ 1) Call music function if needed.
283+ MUSIC interrupt is taken by music.c
284+ 2) Check buttons for KEYS interrupt
285+ 3) Check PS/2 for INKEY interrupt
286+ 4) DRAWCOUNT interrupt
287+*/
288+
289+const int* keystatus=(int*)&ps2keystatus[0];
290+
291+#pragma interrupt CS0Handler IPL3SOFT vector 1
292+void CS0Handler(void){
293+ static int s_keys=-1;
294+ static char s_inkey=0;
295+ int i;
296+ IFS0bits.CS0IF=0;
297+ // Call music function
298+ if (g_music_active) musicint();
299+ // The interrupts are valid only when CS1 is active
300+ if (IEC0bits.CS1IE) {
301+ // Raise DRAWCOUNT interrupt flag
302+ raise_interrupt_flag(INTERRUPT_DRAWCOUNT);
303+ // Check buttons
304+ if (0<=s_keys && s_keys!=(KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))) {
305+ // Raise KEYS interrupt flag
306+ raise_interrupt_flag(INTERRUPT_KEYS);
307+ }
308+ s_keys=KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE);
309+ // Check PS/2 keyboard down
310+ if (g_int_vector[INTERRUPT_INKEY]) {
311+ for(i=0;i<64;i++){
312+ if (keystatus[i]) {
313+ // Raise INKEY interrupt flag
314+ if (!s_inkey) raise_interrupt_flag(INTERRUPT_INKEY);
315+ break;
316+ }
317+ }
318+ s_inkey=(i==64) ? 0:1;
319+ }
320+ }
321+}
322+/*
323+ for(i=0;i<256;i++){
324+ if (ps2keystatus[i]) return i;
325+ }
326+*/
--- a/mips/megalopa/varname.c
+++ b/mips/megalopa/varname.c
@@ -91,6 +91,7 @@ static const int reserved_var_names[]={
9191 0x000b4321, /*NEXT*/
9292 0x000148f8, /*NEW*/
9393 0x00014a5d, /*NOT*/
94+ 0x38a658d7, /*OPTION*/
9495 0x000152c0, /*PCG*/
9596 0x000cacec, /*PEEK*/
9697 0x3b1c6aea, /*PEEK16*/
@@ -119,6 +120,7 @@ static const int reserved_var_names[]={
119120 0x47f711de, /*SYSTEM*/
120121 0x000166bf, /*TAN*/
121122 0x000f72ed, /*TANH*/
123+ 0x020ed5f3, /*TIMER*/
122124 0x02182fee, /*TVRAM*/
123125 0x022c2a2d, /*UNTIL*/
124126 0x4e8887d0, /*USEPCG*/
--- a/mips/zoea/sharedfiles.js
+++ b/mips/zoea/sharedfiles.js
@@ -28,6 +28,7 @@ var filearray=[
2828 'run.c',
2929 'string.c',
3030 'statement.c',
31+ 'timer.c',
3132 'value.c',
3233 'varname.c',
3334 'compiler.h',