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