add tracing and stepping
[mTask.git] / int / int.c
1 #include <netdb.h>
2 #include <netinet/in.h>
3 #include <signal.h>
4 #include <stdbool.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/socket.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include "mTaskSymbols.h"
14
15 #define PORT 8123
16
17 #define MAXTASKS 5
18 #define MAXTASKSIZE 1024
19 #define MAXSDS 50
20 #define STACKSIZE 1024
21
22 #define MSG_TASK 't'
23 #define MSG_SDS 's'
24
25 #define DEBUG
26
27 #ifdef DEBUG
28 #define debug(s, ...) printf(s, ##__VA_ARGS__);
29 #define trace(op, ...) printf("pc: %d, sp: %d, op: " op, pc, sp, ##__VA_ARGS__);
30 #else
31 #define debug(s, ...) ;
32 #define trace(pc, sp, op) ;
33 #endif
34
35 #define pdie(s) {perror(s); exit(1);}
36 #define die(s, ...) {fprintf(stderr, s, ##__VA_ARGS__); exit(1);}
37
38 struct task {
39 uint8_t bc[MAXTASKSIZE];
40 uint16_t tlen;
41 bool used;
42 };
43
44 struct task tasks[MAXTASKS] = {0};
45 int sock_fd = -1;
46 int fd = -1;
47
48 void killHandler(int i)
49 {
50 printf("%s caught, Bye...\n", strsignal(i));
51 exit(1);
52 }
53
54 bool input_available(int fd){
55 struct timeval tv;
56 fd_set fds;
57 tv.tv_sec = 0;
58 tv.tv_usec = 0;
59 FD_ZERO(&fds);
60 FD_SET(fd, &fds);
61 if (select(fd+1, &fds, NULL, NULL, &tv) == -1)
62 pdie("select");
63 return FD_ISSET(fd, &fds);
64 }
65
66 void read_message(int fd_in, int fd_out)
67 {
68 //Find next task
69 uint8_t c, ct;
70
71 for(ct = 0; ct<MAXTASKS; ct++)
72 if(!tasks[ct].used)
73 break;
74 if(ct == MAXTASKS)
75 die("Trying to add too much tasks...\n");
76
77 debug("Receiving input for task %d\n", ct);
78 read(fd_in, &c, 1);
79 switch(c){
80 case MSG_SDS:
81 debug("Receiving an sds\n");
82 break;
83 case MSG_TASK:
84 read(fd_in, &c, 1);
85 tasks[ct].tlen = 256*c;
86 read(fd_in, &c, 1);
87 tasks[ct].tlen += c;
88 if(tasks[ct].tlen > MAXTASKSIZE)
89 die("Task is too long: %d\n", tasks[ct].tlen);
90 for(int i = 0; i<tasks[ct].tlen; i++){
91 debug("Read %d\n", i);
92 read(fd_in, tasks[ct].bc+i, 1);
93 debug("t[][%i]: %d\n", i,
94 tasks[ct].bc[i]);
95 }
96 //Return the task number for later removal
97 write(fd_out, (void *)&ct, 1);
98 debug("Received a task of length %d\n", tasks[ct].tlen);
99 tasks[ct].used = true;
100 break;
101 default:
102 debug("Unknown message: %X?\n", c);
103 }
104 }
105
106 void run_task(int tasknum)
107 {
108 uint8_t *program = tasks[tasknum].bc;
109 int plen = tasks[tasknum].tlen;
110 int pc = 0;
111 int sp = 0;
112 char stack[STACKSIZE] = {0};
113 printf("Running task: %d\nWith length: %d\n", tasknum, plen);
114 while(pc != plen){
115 printf("program: %x\n", program[pc]);
116 switch(program[pc++]){
117 case BCNOP:
118 trace("nop\n");
119 break;
120 case BCPUSH:
121 trace("push %d\n", program[pc]);
122 stack[sp++] = program[pc++];
123 break;
124 case BCPOP:
125 trace("pop\n");
126 sp--;
127 break;
128 case BCNOT:
129 trace("not\n");
130 stack[sp] = stack[sp] > 0 ? 0 : 1;
131 break;
132 case BCADD:
133 trace("add\n");
134 stack[sp-1] = stack[sp] + stack[sp-1];
135 sp -= 1;
136 break;
137 case BCSUB:
138 trace("sub\n");
139 stack[sp-1] = stack[sp] - stack[sp-1];
140 sp -= 1;
141 break;
142 case BCMUL:
143 trace("mul\n");
144 stack[sp-1] = stack[sp] * stack[sp-1];
145 sp -= 1;
146 break;
147 case BCDIV:
148 trace("div\n");
149 stack[sp-1] = stack[sp] / stack[sp-1];
150 sp -= 1;
151 break;
152 case BCAND:
153 trace("and\n");
154 stack[sp-1] = stack[sp] && stack[sp-1];
155 sp -= 1;
156 break;
157 case BCOR:
158 trace("or\n");
159 stack[sp-1] = stack[sp] || stack[sp-1];
160 sp -= 1;
161 break;
162 case BCEQ:
163 trace("eq\n");
164 stack[sp-1] = stack[sp] == stack[sp-1];
165 sp -= 1;
166 break;
167 case BCNEQ:
168 trace("neq\n");
169 stack[sp-1] = stack[sp] != stack[sp-1];
170 sp -= 1;
171 break;
172 case BCLES:
173 trace("les\n");
174 stack[sp-1] = stack[sp] < stack[sp-1];
175 sp -= 1;
176 break;
177 case BCGRE:
178 trace("gre\n");
179 stack[sp-1] = stack[sp] > stack[sp-1];
180 sp -= 1;
181 break;
182 case BCLEQ:
183 trace("leq\n");
184 stack[sp-1] = stack[sp] <= stack[sp-1];
185 sp -= 1;
186 break;
187 case BCGEQ:
188 trace("geq\n");
189 stack[sp-1] = stack[sp] >= stack[sp-1];
190 sp -= 1;
191 break;
192 case BCJMP:
193 trace("jmp to %d\n", program[pc]);
194 pc = pc + program[pc];
195 break;
196 case BCJMPT:
197 trace("jmpt to %d\n", program[pc]);
198 pc += stack[sp] ? program[pc] : 1;
199 break;
200 case BCJMPF:
201 trace("jmpf to %d\n", program[pc]);
202 pc += stack[sp] ? 1 : program[pc];
203 break;
204 case BCSERIALAVAIL:
205 trace("SerialAvailable()\n");
206 break;
207 case BCSERIALPRINT:
208 trace("SerialPrint()\n");
209 break;
210 case BCSERIALPRINTLN:
211 trace("SerialPrintln()\n");
212 break;
213 case BCSERIALREAD:
214 trace("SerialRead()\n");
215 break;
216 case BCSERIALPARSEINT:
217 trace("SerialParseInt()\n");
218 break;
219 case BCANALOGREAD:
220 trace("AnalogRead(%d)\n", program[pc]);
221 pc++;
222 break;
223 case BCANALOGWRITE:
224 trace("AnalogWrite(%d)\n", program[pc]);
225 pc++;
226 break;
227 case BCDIGITALREAD:
228 trace("DigitalRead(%d)\n", program[pc]);
229 pc++;
230 break;
231 case BCDIGITALWRITE:
232 trace("DigitalWrite(%d)\n", program[pc]);
233 pc++;
234 break;
235 default:
236 die("Unrecognized command: %d\n", program[--pc]);
237 }
238 }
239 debug("Task %d terminated\n", tasknum);
240 }
241
242 void open_filedescriptors()
243 {
244 struct sockaddr_in sa;
245
246 bzero((char *) &sa, sizeof(sa));
247 sa.sin_family = AF_INET;
248 sa.sin_addr.s_addr = INADDR_ANY;
249 sa.sin_port = htons(PORT);
250
251 if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
252 pdie("socket");
253 if(bind(sock_fd, (struct sockaddr*)&sa, sizeof(sa)) == -1)
254 pdie("bind\n");
255 if(listen(sock_fd, 10) == -1)
256 pdie("bind\n");
257
258 printf("Listening on %d\n", PORT);
259 fflush(stdout);
260 if((fd = accept(sock_fd, (struct sockaddr*)NULL, NULL)) == -1)
261 pdie("accept");
262 }
263
264 int main(void)
265 {
266 int ct;
267
268 //Register signal handler
269 if(signal(SIGINT, killHandler) == SIG_ERR){
270 die("Couldn't register signal handler...\n");
271 }
272 if(signal(SIGTERM, killHandler) == SIG_ERR){
273 die("Couldn't register signal handler...\n");
274 }
275
276 open_filedescriptors();
277
278 while(true){
279 //Check for new tasks
280 if(input_available(fd))
281 read_message(fd, fd);
282 //Run tasks
283 for(ct = 0; ct<MAXTASKS; ct++){
284 if(!tasks[ct].used){
285 debug("Task %d not implemented\n", ct);
286 continue;
287 }
288 #ifdef DEBUG
289 printf("Current task to run: %d\n", ct);
290 printf("Enter to continue, s to step\n");
291 switch(getchar()){
292 case 'd':
293 die("Killed\n");
294 case 's':
295 printf("step\n");
296 break;
297 default:
298 break;
299 }
300 #endif
301 run_task(ct);
302 }
303 usleep(10);
304 }
305 return 0;
306 }