added sds operators, timing and task deletion
[mTask.git] / int / int.c
index a946908..c89a6a8 100644 (file)
--- a/int/int.c
+++ b/int/int.c
-#include <stdio.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <signal.h>
 #include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
 
 #include "mTaskSymbols.h"
 
+#define MAXTASKS 5
+#define MAXTASKSIZE 1024
+#define MAXSDS 50
 #define STACKSIZE 1024
-#define PROGRAMSIZE 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 die(s, ...) {fprintf(stderr, s, ##__VA_ARGS__); return 1;}
+#define pdie(s) {perror(s); exit(1);}
+#define die(s, ...) {fprintf(stderr, s, ##__VA_ARGS__); exit(1);}
+
+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;
 
-char program[PROGRAMSIZE+1] = {0};
-int stack[STACKSIZE+1] = {0};
+void killHandler(int i)
+{
+       printf("%s caught, Bye...\n", strsignal(i));
+       exit(1);
+}
 
-bool input_available(){
+bool input_available(int fd){
        struct timeval tv;
        fd_set fds;
        tv.tv_sec = 0;
        tv.tv_usec = 0;
        FD_ZERO(&fds);
-       FD_SET(0, &fds);
-       select(1, &fds, NULL, NULL, &tv);
-       return FD_ISSET(0, &fds);
+       FD_SET(fd, &fds);
+       if (select(fd+1, &fds, NULL, NULL, &tv) == -1)
+               pdie("select");
+       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;
+
+       for(ct = 0; ct<MAXTASKS; 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);
+       switch(c){
+       case MSG_SDS:
+               debug("Receiving an sds\n");
+               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);
+               tasks[ct].interval += c;
+               //Read tasklength
+               read(fd_in, &c, 1);
+               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].bc+i, 1);
+                       debug("t[][%i]: %d\n", 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", tasks[ct].tlen);
+               tasks[ct].used = true;
+               break;
+       default:
+               debug("Unknown message: %X?\n", c);
+       }
+}
 
-int main(void)
+void run_task(int tasknum)
 {
-       char c;
-       int pl, sp, pc;
-
-       //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){
+       uint8_t *program = tasks[tasknum].bc;
+       int plen = tasks[tasknum].tlen;
+       int pc = 0;
+       int sp = 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:
+               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: trace("SerialPrint()\n");
                        break;
-               case BCSERIALPRINT:
-                       printf("SerialPrint()\n");
+               case BCSERIALPRINTLN: trace("SerialPrintln()\n");
                        break;
-               case BCSERIALPRINTLN:
-                       printf("SerialPrintln()\n");
+               case BCSERIALREAD: trace("SerialRead()\n");
                        break;
-               case BCSERIALREAD:
-                       printf("SerialRead()\n");
+               case BCSERIALPARSEINT: trace("SerialParseInt()\n");
                        break;
-               case BCSERIALPARSEINT:
-                       printf("SerialParseInt()\n");
+               case BCANALOGREAD: trace("AnalogRead(%d)\n", program[pc]);
+                       pc++;
                        break;
-               case BCANALOGREAD:
-                       printf("AnalogRead()\n");
+               case BCANALOGWRITE: trace("AnalogWrite(%d)\n", program[pc]);
+                       pc++;
+                       break;
+               case BCDIGITALREAD: trace("DigitalRead(%d)\n", program[pc]);
+                       pc++;
+                       break;
+               case BCDIGITALWRITE: trace("DigitalWrite(%d)\n", program[pc]);
+                       pc++;
                        break;
-               case BCANALOGWRITE:
-                       printf("AnalogWrite()\n");
                default:
-                       die("Unrecognized command: %X\n", program[--pc]);
+                       die("Unrecognized command: %d\n", program[--pc]);
+               }
+       }
+       debug("Task %d terminated\n", tasknum);
+}
+
+void open_filedescriptors()
+{
+       struct sockaddr_in sa;
+
+       bzero((char *) &sa, sizeof(sa));
+       sa.sin_family = AF_INET;
+       sa.sin_addr.s_addr = INADDR_ANY;
+       sa.sin_port = htons(port);
+
+       if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+               pdie("socket");
+       if(bind(sock_fd, (struct sockaddr*)&sa, sizeof(sa)) == -1)
+               pdie("bind\n");
+       if(listen(sock_fd, 10) == -1)
+               pdie("bind\n");
+
+       printf("Listening on %d\n", port);
+       fflush(stdout);
+       if((fd = accept(sock_fd, (struct sockaddr*)NULL, NULL)) == -1)
+               pdie("accept");
+}
+
+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;
+
+       //Register signal handler
+       if(signal(SIGINT, killHandler) == SIG_ERR){
+               die("Couldn't register signal handler...\n");
+       }
+       if(signal(SIGTERM, killHandler) == SIG_ERR){
+               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))
+                       read_message(fd, fd);
+               //Run tasks
+               cyclestart = millis();
+               for(ct = 0; ct<MAXTASKS; ct++){
+                       //See whether the task is even in use
+                       if(!tasks[ct].used){
+                               debug("Task %d not implemented\n", ct);
+                               continue;
+                       }
+                       //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);
                }
+               usleep(10);
        }
        return 0;
 }