BASIC compiler/interpreter for PIC32MX/MZ-80K
Revisão | 14e935808ee06a8e15b95d2457fece6d667ea400 (tree) |
---|---|
Hora | 2019-03-25 09:26:35 |
Autor | Katsumi <kmorimatsu@sour...> |
Commiter | Katsumi |
INTERRUPT TIMER
@@ -110,8 +110,9 @@ int nextCodeIs(char* str){ | ||
110 | 110 | if (!strncmp(g_source+g_srcpos,str,len)) { |
111 | 111 | if ('A'<=str[len-1] && str[len-1]<='Z') { |
112 | 112 | // 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; | |
115 | 116 | } |
116 | 117 | // String matches in the current position in source. |
117 | 118 | g_srcpos+=len; |
@@ -373,7 +373,7 @@ void stop_timer(); | ||
373 | 373 | char* usetimer_statement(); |
374 | 374 | char* timer_statement(); |
375 | 375 | char* timer_function(); |
376 | - | |
376 | +char* interrupt_statement(); | |
377 | 377 | |
378 | 378 | /* Error messages */ |
379 | 379 | #define ERR_SYNTAX (char*)(g_err_str[0]) |
@@ -229,9 +229,10 @@ static const char initext[]= | ||
229 | 229 | |
230 | 230 | static const char bastext[]= |
231 | 231 | "USETIMER 600\n" |
232 | +"INTERRUPT TIMER,LABEL1\n" | |
232 | 233 | "END\n" |
233 | -"\n" | |
234 | -"\n" | |
234 | +"LABEL LABEL1\n" | |
235 | +"RETURN\n" | |
235 | 236 | "\n" |
236 | 237 | "\n" |
237 | 238 | "\n" |
@@ -270,10 +271,11 @@ static const void* debugjumptable[]={ | ||
270 | 271 | |
271 | 272 | int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){ |
272 | 273 | asm volatile(".set noreorder"); |
274 | + asm volatile("b label1"); | |
273 | 275 | asm volatile("lui $v1,0x1234"); |
274 | 276 | asm volatile("ori $v1,$v1,0x5678"); |
275 | 277 | asm volatile("sw $v0,0($v1)"); |
276 | - asm volatile("nop"); | |
278 | + asm volatile("label1:"); | |
277 | 279 | asm volatile("nop"); |
278 | 280 | asm volatile("nop"); |
279 | 281 | asm volatile("nop"); |
@@ -1719,6 +1719,7 @@ static const void* statement_list[]={ | ||
1719 | 1719 | "OPTION ",option_statement, |
1720 | 1720 | "USETIMER ",usetimer_statement, |
1721 | 1721 | "TIMER ",timer_statement, |
1722 | + "INTERRUPT ",interrupt_statement, | |
1722 | 1723 | // List of additional statements follows |
1723 | 1724 | ADDITIONAL_STATEMENTS |
1724 | 1725 | }; |
@@ -1,149 +1,191 @@ | ||
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 | - | |
15 | -// Timer value that increments every timer event | |
16 | -static int g_timer; | |
17 | - | |
18 | -// Enable or disable interrupt | |
19 | -static char g_interrupt_enabled; | |
20 | -// Jump address when interrupt | |
21 | -static void* g_int_vector; | |
22 | - | |
23 | -void init_timer(){ | |
24 | - // Stop timer, first | |
25 | - T1CON=0x0000; | |
26 | - IEC0bits.T1IE=0; | |
27 | - TMR1=0; | |
28 | - PR1=0xffff; | |
29 | - g_timer=0; | |
30 | - // Disable interrupt | |
31 | - IEC0bits.CS1IE=0; | |
32 | - g_interrupt_enabled=0; | |
33 | -} | |
34 | - | |
35 | -void stop_timer(){ | |
36 | - // Stop timer | |
37 | - T1CON=0x0000; | |
38 | - IEC0bits.T1IE=0; | |
39 | - // Disable interrupt | |
40 | - IEC0bits.CS1IE=0; | |
41 | - g_interrupt_enabled=0; | |
42 | -} | |
43 | - | |
44 | -// Interrupt handler | |
45 | -#ifndef __DEBUG | |
46 | - // Timer1 is also used for debug mode | |
47 | - #pragma interrupt T1Handler IPL2SOFT vector 4 | |
48 | -#endif | |
49 | -void T1Handler(void){ | |
50 | - g_timer++; | |
51 | - // Clear Timer1 interrupt flag | |
52 | - IFS0bits.T1IF=0; | |
53 | - // Raise CS1 interrupt flag if required | |
54 | - IFS0bits.CS1IF=g_interrupt_enabled; | |
55 | -} | |
56 | - | |
57 | -//CS1 ? Core Software Interrupt 1 2 2 IFS0<2> IEC0<2> IPC0<20:18> IPC0<17:16> | |
58 | -void BasicInt(void){ | |
59 | -//TODO: here | |
60 | - // Do the same thing as gosub statement does: 4($sp) is the return address | |
61 | - asm volatile(".set noreorder"); | |
62 | - asm volatile("la $v0,%0"::"i"(&g_int_vector)); | |
63 | - asm volatile("addiu $sp,$sp,-12"); | |
64 | - asm volatile("sw $ra,8($sp)"); | |
65 | - asm volatile("bgezall $zero,label1"); | |
66 | - asm volatile("lw $v0,0($v0)"); | |
67 | - asm volatile("beq $zero,$zero,label2"); | |
68 | - asm volatile("nop"); | |
69 | - asm volatile("label1:"); | |
70 | - asm volatile("jr $v0"); | |
71 | - asm volatile("sw $ra,4($sp)"); | |
72 | - asm volatile("label2:"); | |
73 | - asm volatile("lw $ra,4($sp)"); | |
74 | - asm volatile("addiu $sp,$sp,8"); // 4 was already added by RETURN statement | |
75 | -} | |
76 | -#pragma interrupt CS1Handler IPL1SOFT vector 2 | |
77 | -void CS1Handler(void){ | |
78 | - IFS0bits.CS1IF=0; | |
79 | - BasicInt(); | |
80 | -} | |
81 | - | |
82 | -void lib_usetimer(int hz){ | |
83 | - int temppr1; | |
84 | - // Stop timer, first | |
85 | - T1CON=0x0000; | |
86 | - IEC0bits.T1IE=0; | |
87 | - TMR1=0; | |
88 | - PR1=0xffff; | |
89 | - if (!hz) { | |
90 | - return; | |
91 | - } | |
92 | - // PR1 setting | |
93 | - temppr1=CPU_CLOCK_HZ/hz; | |
94 | - if (temppr1<=65536) { | |
95 | - // no prescaler | |
96 | - T1CON=0x0000; | |
97 | - PR1=temppr1-1; | |
98 | - } else if ((temppr1>>3)<=65536) { | |
99 | - // 1/8 prescaler | |
100 | - T1CON=0x0010; | |
101 | - PR1=(temppr1>>3)-1; | |
102 | - } else if ((temppr1>>6)<=65536) { | |
103 | - // 1/64 prescaler | |
104 | - T1CON=0x0020; | |
105 | - PR1=(temppr1>>6)-1; | |
106 | - } else if ((temppr1>>8)<=65536) { | |
107 | - // 1/256 prescaler | |
108 | - T1CON=0x0030; | |
109 | - PR1=(temppr1>>8)-1; | |
110 | - } else { | |
111 | - err_invalid_param(); | |
112 | - } | |
113 | - // Timer1 interrupt: priority 2 | |
114 | - IPC1bits.T1IP=2; | |
115 | - IPC1bits.T1IS=0; | |
116 | - IEC0bits.T1IE=1; | |
117 | - // Start timer | |
118 | - T1CONbits.ON=1; | |
119 | -} | |
120 | - | |
121 | -char* usetimer_statement(){ | |
122 | - char* err; | |
123 | - err=get_value(); | |
124 | - if (err) return err; | |
125 | - call_quicklib_code(lib_usetimer,ASM_ADDU_A0_V0_ZERO); | |
126 | - return 0; | |
127 | -} | |
128 | - | |
129 | -char* timer_statement(){ | |
130 | - int i; | |
131 | - char* err; | |
132 | - err=get_value(); | |
133 | - if (err) return err; | |
134 | - check_obj_space(3); | |
135 | - g_object[g_objpos++]=0x3C030000|((i>>16)&0x0000FFFF); // lui v1,xxxx | |
136 | - g_object[g_objpos++]=0x34630000|(i&0x0000FFFF); // ori v1,v1,xxxx | |
137 | - g_object[g_objpos++]=0xAC620000; // sw v0,0(v1) | |
138 | - return 0; | |
139 | -} | |
140 | - | |
141 | -char* timer_function(){ | |
142 | - int i; | |
143 | - i=(int)(&g_timer); | |
144 | - check_obj_space(3); | |
145 | - g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx | |
146 | - g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx | |
147 | - g_object[g_objpos++]=0x8C420000; // lw v0,0(v0) | |
148 | - return 0; | |
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 | + | |
15 | +#define INTERRUPT_TIMER 1 | |
16 | + | |
17 | +// Timer value that increments every timer event | |
18 | +static int g_timer; | |
19 | + | |
20 | +// Enable or disable interrupt | |
21 | +static char g_interrupt_enabled; | |
22 | +// Jump address when interrupt | |
23 | +static int g_int_vector; | |
24 | + | |
25 | +void init_timer(){ | |
26 | + // Stop timer, first | |
27 | + T1CON=0x0000; | |
28 | + IEC0bits.T1IE=0; | |
29 | + TMR1=0; | |
30 | + PR1=0xffff; | |
31 | + g_timer=0; | |
32 | + // Disable interrupt | |
33 | + IEC0bits.CS1IE=0; | |
34 | + g_interrupt_enabled=0; | |
35 | +} | |
36 | + | |
37 | +void stop_timer(){ | |
38 | + // Stop timer | |
39 | + T1CON=0x0000; | |
40 | + IEC0bits.T1IE=0; | |
41 | + // Disable interrupt | |
42 | + IEC0bits.CS1IE=0; | |
43 | + g_interrupt_enabled=0; | |
44 | +} | |
45 | + | |
46 | +// Interrupt handler | |
47 | +#ifndef __DEBUG | |
48 | + // Timer1 is also used for debug mode | |
49 | + #pragma interrupt T1Handler IPL2SOFT vector 4 | |
50 | +#endif | |
51 | +void T1Handler(void){ | |
52 | + g_timer++; | |
53 | + // Clear Timer1 interrupt flag | |
54 | + IFS0bits.T1IF=0; | |
55 | + // Raise CS1 interrupt flag if required | |
56 | + IFS0bits.CS1IF=g_interrupt_enabled; | |
57 | +} | |
58 | + | |
59 | +void lib_usetimer(int hz){ | |
60 | + int temppr1; | |
61 | + // Stop timer, first | |
62 | + T1CON=0x0000; | |
63 | + IEC0bits.T1IE=0; | |
64 | + TMR1=0; | |
65 | + PR1=0xffff; | |
66 | + if (!hz) { | |
67 | + return; | |
68 | + } | |
69 | + // PR1 setting | |
70 | + temppr1=CPU_CLOCK_HZ/hz; | |
71 | + if (temppr1<=65536) { | |
72 | + // no prescaler | |
73 | + T1CON=0x0000; | |
74 | + PR1=temppr1-1; | |
75 | + } else if ((temppr1>>3)<=65536) { | |
76 | + // 1/8 prescaler | |
77 | + T1CON=0x0010; | |
78 | + PR1=(temppr1>>3)-1; | |
79 | + } else if ((temppr1>>6)<=65536) { | |
80 | + // 1/64 prescaler | |
81 | + T1CON=0x0020; | |
82 | + PR1=(temppr1>>6)-1; | |
83 | + } else if ((temppr1>>8)<=65536) { | |
84 | + // 1/256 prescaler | |
85 | + T1CON=0x0030; | |
86 | + PR1=(temppr1>>8)-1; | |
87 | + } else { | |
88 | + err_invalid_param(); | |
89 | + } | |
90 | + // Timer1 interrupt: priority 2 | |
91 | + IPC1bits.T1IP=2; | |
92 | + IPC1bits.T1IS=0; | |
93 | + IEC0bits.T1IE=1; | |
94 | + // Start timer | |
95 | + T1CONbits.ON=1; | |
96 | +} | |
97 | + | |
98 | +char* usetimer_statement(){ | |
99 | + char* err; | |
100 | + err=get_value(); | |
101 | + if (err) return err; | |
102 | + call_quicklib_code(lib_usetimer,ASM_ADDU_A0_V0_ZERO); | |
103 | + return 0; | |
104 | +} | |
105 | + | |
106 | +char* timer_statement(){ | |
107 | + int i; | |
108 | + char* err; | |
109 | + err=get_value(); | |
110 | + if (err) return err; | |
111 | + check_obj_space(3); | |
112 | + g_object[g_objpos++]=0x3C030000|((i>>16)&0x0000FFFF); // lui v1,xxxx | |
113 | + g_object[g_objpos++]=0x34630000|(i&0x0000FFFF); // ori v1,v1,xxxx | |
114 | + g_object[g_objpos++]=0xAC620000; // sw v0,0(v1) | |
115 | + return 0; | |
116 | +} | |
117 | + | |
118 | +char* timer_function(){ | |
119 | + int i; | |
120 | + i=(int)(&g_timer); | |
121 | + check_obj_space(3); | |
122 | + g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx | |
123 | + g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx | |
124 | + g_object[g_objpos++]=0x8C420000; // lw v0,0(v0) | |
125 | + return 0; | |
126 | +} | |
127 | + | |
128 | +//CS1 ? Core Software Interrupt 1 2 2 IFS0<2> IEC0<2> IPC0<20:18> IPC0<17:16> | |
129 | +void BasicInt(int addr){ | |
130 | +//TODO: here | |
131 | + // $a0 is the address in BASIC code | |
132 | + asm volatile(".set noreorder"); | |
133 | + asm volatile("jr $a0"); | |
134 | + asm volatile("nop"); | |
135 | +} | |
136 | +#pragma interrupt CS1Handler IPL1SOFT vector 2 | |
137 | +void CS1Handler(void){ | |
138 | + IFS0bits.CS1IF=0; | |
139 | + BasicInt(g_int_vector); | |
140 | +} | |
141 | + | |
142 | +void _lib_interrupt(int itype, int address){ | |
143 | + // Ignore itype in the first imprementation | |
144 | + g_int_vector=address; | |
145 | + g_interrupt_enabled=1; | |
146 | + // CS1 interrupt: priority 1 | |
147 | + IPC0bits.CS1IP=1; | |
148 | + IPC0bits.CS1IS=0; | |
149 | + IEC0bits.CS1IE=1; | |
150 | +} | |
151 | + | |
152 | +void lib_interrupt(int itype){ | |
153 | + // $ra is 2 word before the interrupt address | |
154 | + asm volatile("addiu $a1,$ra,8"); | |
155 | + asm volatile("j _lib_interrupt"); | |
156 | +} | |
157 | + | |
158 | +char* interrupt_statement(){ | |
159 | + int itype; | |
160 | + int i,opos; | |
161 | + char* err; | |
162 | + next_position(); | |
163 | + if (nextCodeIs("TIMER")) { itype=INTERRUPT_TIMER; | |
164 | + } else { | |
165 | + return ERR_SYNTAX; | |
166 | + } | |
167 | + // Detect ',' | |
168 | + next_position(); | |
169 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; g_srcpos++; | |
170 | + // Store address to call | |
171 | + call_quicklib_code(lib_interrupt,ASM_ORI_A0_ZERO_|itype); | |
172 | + check_obj_space(2); | |
173 | + opos=g_objpos; | |
174 | + g_object[g_objpos++]=0x10000000; // b xxxxx | |
175 | + g_object[g_objpos++]=0x00000000; // nop | |
176 | + // Store $ra | |
177 | + check_obj_space(2); | |
178 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
179 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
180 | + // Compile as GOSUB statement | |
181 | + err=gosub_statement(); | |
182 | + if (err) return err; | |
183 | + // Retore $ra and return | |
184 | + check_obj_space(3); | |
185 | + g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp) | |
186 | + g_object[g_objpos++]=0x03E00008; // jr ra | |
187 | + g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 | |
188 | + // Complete B assembly | |
189 | + g_object[opos]|=g_objpos-opos-1; | |
190 | + return 0; | |
149 | 191 | } |
\ No newline at end of file |