added sds operators, timing and task deletion
[mTask.git] / int / int.c
index a2dd745..c89a6a8 100644 (file)
--- a/int/int.c
+++ b/int/int.c
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <sys/time.h>
 #include <unistd.h>
 
 #include "mTaskSymbols.h"
 #define MAXSDS 50
 #define STACKSIZE 1024
 
+#define MSG_TASK 't'
+#define MSG_DELTASK 'd'
+#define MSG_SDS 's'
+
 #define DEBUG
+
 #ifdef DEBUG
 #define debug(s, ...) printf(s, ##__VA_ARGS__);
+#define trace(op, ...) printf("pc: %d, sp: %d, op: " op, pc, sp, ##__VA_ARGS__);
 #else
 #define debug(s, ...) ;
+#define trace(pc, sp, op) ;
 #endif
 
 #define pdie(s) {perror(s); exit(1);}
 #define die(s, ...) {fprintf(stderr, s, ##__VA_ARGS__); exit(1);}
 
-char tasks[MAXTASKS][MAXTASKSIZE] = {0};
-bool tasks_used[MAXTASKS] = {0};
+struct task {
+       uint8_t bc[MAXTASKSIZE];
+       uint16_t tlen;
+       uint16_t interval;
+       long lastrun;
+       bool used;
+};
+
+struct timeval tv1;
+struct task tasks[MAXTASKS] = {0};
 int sock_fd = -1;
 int fd = -1;
+int port = 8123;
 
 void killHandler(int i)
 {
@@ -50,150 +67,179 @@ bool input_available(int fd){
        return FD_ISSET(fd, &fds);
 }
 
+long millis() {
+       if (gettimeofday(&tv1, NULL) == -1)
+               pdie("gettimeofday");
+       return tv1.tv_sec*1000 + tv1.tv_usec/1000;
+}
+
 void read_message(int fd_in, int fd_out)
 {
        //Find next task
        uint8_t c, ct;
-       uint16_t tasklen;
 
        for(ct = 0; ct<MAXTASKS; ct++)
-               if(!tasks_used[ct])
+               if(!tasks[ct].used)
                        break;
        if(ct == MAXTASKS)
                die("Trying to add too much tasks...\n");
 
        debug("Receiving input for task %d\n", ct);
        read(fd_in, &c, 1);
-       if(c == 's') {
+       switch(c){
+       case MSG_SDS:
                debug("Receiving an sds\n");
-       } else if(c == 't'){
+               break;
+       case MSG_DELTASK:
+               debug("Receiving a delete task request\n");
+               //Read task number and set unused
+               read(fd_in, &c, 1);
+               tasks[ct].used = false;
+               break;
+       case MSG_TASK:
+               debug("Receiving a task\n");
+               bzero(&tasks[ct], sizeof(struct task));
+               //Read interval
+               read(fd_in, &c, 1);
+               tasks[ct].interval = 256*c;
                read(fd_in, &c, 1);
-               tasklen = 256*c;
+               tasks[ct].interval += c;
+               //Read tasklength
                read(fd_in, &c, 1);
-               tasklen += c;
-               if(tasklen > MAXTASKSIZE)
-                       die("Task is too long: %d\n", tasklen);
-               for(int i = 0; i<tasklen; i++){
+               tasks[ct].tlen = 256*c;
+               read(fd_in, &c, 1);
+               tasks[ct].tlen += c;
+               if(tasks[ct].tlen > MAXTASKSIZE)
+                       die("Task is too long: %d\n", tasks[ct].tlen);
+               //Read task bytecode
+               for(int i = 0; i<tasks[ct].tlen; i++){
                        debug("Read %d\n", i);
-                       read(fd_in, tasks[ct]+i, 1);
+                       read(fd_in, tasks[ct].bc+i, 1);
                        debug("t[][%i]: %d\n", i,
-                               tasks[ct][i]);
+                               tasks[ct].bc[i]);
                }
                //Return the task number for later removal
                write(fd_out, (void *)&ct, 1);
-               debug("Received a task of length %d\n", tasklen);
-               tasks_used[ct] = true;
-       } else {
+               debug("Received a task of length %d\n", tasks[ct].tlen);
+               tasks[ct].used = true;
+               break;
+       default:
                debug("Unknown message: %X?\n", c);
        }
 }
 
-void run_task(char *program)
+void run_task(int tasknum)
 {
+       uint8_t *program = tasks[tasknum].bc;
+       int plen = tasks[tasknum].tlen;
        int pc = 0;
        int sp = 0;
-       int plen = strlen(program);
-       char stack[1024] = {0};
+       char stack[STACKSIZE] = {0};
+       printf("Running task: %d\nWith length: %d\n", tasknum, plen);
        while(pc != plen){
+               printf("program: %x\n", program[pc]);
                switch(program[pc++]){
-               case BCNOP:
+               case BCNOP: trace("nop\n");
                        break;
-               case BCPUSH:
+               case BCPUSH: trace("push %d\n", program[pc]);
                        stack[sp++] = program[pc++];
                        break;
-               case BCPOP:
+               case BCPOP: trace("pop\n");
                        sp--;
                        break;
-               case BCNOT:
+               case BCSDSSTORE: trace("sds store\n");
+                       break;
+               case BCSDSFETCH: trace("sds fetch\n");
+                       break;
+               case BCSDSPUBLISH: trace("sds publish\n");
+                       break;
+               case BCNOT: trace("not\n");
                        stack[sp] = stack[sp] > 0 ? 0 : 1;
                        break;
-               case BCADD:
+               case BCADD: trace("add\n");
                        stack[sp-1] = stack[sp] + stack[sp-1];
                        sp -= 1;
                        break;
-               case BCSUB:
+               case BCSUB: trace("sub\n");
                        stack[sp-1] = stack[sp] - stack[sp-1];
                        sp -= 1;
                        break;
-               case BCMUL:
+               case BCMUL: trace("mul\n");
                        stack[sp-1] = stack[sp] * stack[sp-1];
                        sp -= 1;
                        break;
-               case BCDIV:
+               case BCDIV: trace("div\n");
                        stack[sp-1] = stack[sp] / stack[sp-1];
                        sp -= 1;
                        break;
-               case BCAND:
+               case BCAND: trace("and\n");
                        stack[sp-1] = stack[sp] && stack[sp-1];
                        sp -= 1;
                        break;
-               case BCOR:
+               case BCOR: trace("or\n");
                        stack[sp-1] = stack[sp] || stack[sp-1];
                        sp -= 1;
                        break;
-               case BCEQ:
+               case BCEQ: trace("eq\n");
                        stack[sp-1] = stack[sp] == stack[sp-1];
                        sp -= 1;
                        break;
-               case BCNEQ:
+               case BCNEQ: trace("neq\n");
                        stack[sp-1] = stack[sp] != stack[sp-1];
                        sp -= 1;
                        break;
-               case BCLES: stack[sp-1] = stack[sp] < stack[sp-1];
+               case BCLES: trace("les\n");
+                       stack[sp-1] = stack[sp] < stack[sp-1];
                        sp -= 1;
                        break;
-               case BCGRE:
+               case BCGRE: trace("gre\n");
                        stack[sp-1] = stack[sp] > stack[sp-1];
                        sp -= 1;
                        break;
-               case BCLEQ:
+               case BCLEQ: trace("leq\n");
                        stack[sp-1] = stack[sp] <= stack[sp-1];
                        sp -= 1;
                        break;
-               case BCGEQ:
+               case BCGEQ: trace("geq\n");
                        stack[sp-1] = stack[sp] >= stack[sp-1];
                        sp -= 1;
                        break;
-               case BCJMP:
+               case BCJMP: trace("jmp to %d\n", program[pc]);
                        pc = pc + program[pc];
                        break;
-               case BCJMPT:
+               case BCJMPT: trace("jmpt to %d\n", program[pc]);
                        pc += stack[sp] ? program[pc] : 1;
                        break;
-               case BCJMPF:
+               case BCJMPF: trace("jmpf to %d\n", program[pc]);
                        pc += stack[sp] ? 1 : program[pc];
                        break;
-               case BCSERIALAVAIL:
-                       printf("SerialAvailable()\n");
+               case BCSERIALAVAIL: trace("SerialAvailable()\n");
                        break;
-               case BCSERIALPRINT:
-                       printf("SerialPrint()\n");
+               case BCSERIALPRINT: trace("SerialPrint()\n");
                        break;
-               case BCSERIALPRINTLN:
-                       printf("SerialPrintln()\n");
+               case BCSERIALPRINTLN: trace("SerialPrintln()\n");
                        break;
-               case BCSERIALREAD:
-                       printf("SerialRead()\n");
+               case BCSERIALREAD: trace("SerialRead()\n");
                        break;
-               case BCSERIALPARSEINT:
-                       printf("SerialParseInt()\n");
+               case BCSERIALPARSEINT: trace("SerialParseInt()\n");
                        break;
-               case BCANALOGREAD:
-                       printf("AnalogRead(%d)\n", program[pc++]);
+               case BCANALOGREAD: trace("AnalogRead(%d)\n", program[pc]);
+                       pc++;
                        break;
-               case BCANALOGWRITE:
-                       printf("AnalogWrite(%d)\n", program[pc++]);
+               case BCANALOGWRITE: trace("AnalogWrite(%d)\n", program[pc]);
+                       pc++;
                        break;
-               case BCDIGITALREAD:
-                       printf("DigitalRead(%d)\n", program[pc++]);
+               case BCDIGITALREAD: trace("DigitalRead(%d)\n", program[pc]);
+                       pc++;
                        break;
-               case BCDIGITALWRITE:
-                       printf("DigitalWrite(%d)\n", program[pc++]);
+               case BCDIGITALWRITE: trace("DigitalWrite(%d)\n", program[pc]);
+                       pc++;
                        break;
                default:
                        die("Unrecognized command: %d\n", program[--pc]);
                }
        }
+       debug("Task %d terminated\n", tasknum);
 }
 
 void open_filedescriptors()
@@ -203,7 +249,7 @@ void open_filedescriptors()
        bzero((char *) &sa, sizeof(sa));
        sa.sin_family = AF_INET;
        sa.sin_addr.s_addr = INADDR_ANY;
-       sa.sin_port = htons(8124);
+       sa.sin_port = htons(port);
 
        if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
                pdie("socket");
@@ -212,13 +258,22 @@ void open_filedescriptors()
        if(listen(sock_fd, 10) == -1)
                pdie("bind\n");
 
-       printf("Listinging on 8123\n");
+       printf("Listening on %d\n", port);
        fflush(stdout);
        if((fd = accept(sock_fd, (struct sockaddr*)NULL, NULL)) == -1)
                pdie("accept");
 }
 
-int main(void)
+void usage(FILE *o, char *arg0){
+       fprintf(o,
+               "Usage: %s [opts]\n"
+               "\n"
+               "Options\n"
+               "-p PORT  Custom port number, default: 8123\n"
+               , arg0);
+}
+
+int main(int argc, char *argv[])
 {
        int ct;
 
@@ -230,42 +285,61 @@ int main(void)
                die("Couldn't register signal handler...\n");
        }
 
+       //Command line arguments
+       int opt;
+       while((opt = getopt(argc, argv, "hp:")) != -1){
+               switch(opt){
+                       case 'p':
+                               port = atoi(optarg);
+                               if(port < 1)
+                                       die("Port numbers are > 1\n");
+                               break;
+                       case 'h':
+                               usage(stdout, argv[0]);
+                               exit(EXIT_SUCCESS);
+                       default:
+                               usage(stderr, argv[0]);
+                               exit(EXIT_FAILURE);
+               }
+
+       }
+
        open_filedescriptors();
 
+       long cyclestart;
        while(true){
                //Check for new tasks
-               if(input_available(fd)){
+               if(input_available(fd))
                        read_message(fd, fd);
-               }
                //Run tasks
+               cyclestart = millis();
                for(ct = 0; ct<MAXTASKS; ct++){
-                       if(!tasks_used[ct]){
+                       //See whether the task is even in use
+                       if(!tasks[ct].used){
                                debug("Task %d not implemented\n", ct);
                                continue;
                        }
-                       debug("Going to execute task %d\n", ct);
-                       run_task(tasks[ct]);
-                       exit(1);
+                       //See whether the task interval has passed
+                       if(cyclestart-tasks[ct].lastrun < tasks[ct].interval){
+                               debug("Task %d not scheduled\n", ct);
+                               continue;
+                       }
+#ifdef DEBUG
+                       printf("Current task to run: %d\n", ct);
+                       printf("Enter to continue, s to step\n");
+                       switch(getchar()){
+                       case 'd':
+                               die("Killed\n");
+                       case 's':
+                               printf("step\n");
+                               break;
+                       default:
+                               break;
+                       }
+#endif
+                       run_task(ct);
                }
-//             exit(1);
                usleep(10);
        }
-
-/*     //Read program
-       pc = 0;
-       while ((c = getchar()) != EOF && pc < PROGRAMSIZE)
-               program[pc++] = c;
-       if (pc >= PROGRAMSIZE)
-               die("Max program size: %d\n", PROGRAMSIZE);
-       pl = pc;
-       debug("Done reading, program length: %d\n", pl);
-
-       //Evaluate program
-       //Reset program counter and stack counter
-       pc = 0;
-       sp = 0;
-       while(pc != pl){
-       }
-*/
        return 0;
 }