#include <stdio.h>
#include <fcntl.h>

# define ROOD   2
# define GEEL   3
# define BLAUW  4
# define GROEN  7

# define OFF    1
# define ON     2
# define TOGGLE 3
# define READ   4

/* trali.c rik 20081206 traffic light manipulation based on gpio.c
   http://downloads.openwrt.org/utils/gpio.tar.gz
   rik's first attempts at writing/hacking C

   changelog
   20081220: default command is now ON
             ON will now first switch all lights off before switching on the requested lights
             "trali on" still effectively switches them all ON because
             requesting no lights at all equals requesting all of them
             new command: READ
             any command will now produce output in nagios plugin style
*/

int main(int argc, char **argv) {

        unsigned int gpio;          // read-write var /dev/gpio/*
        unsigned int usrcol = 0 ;   // user requested colours
        unsigned int usrcmd = ON ;  // user requested command
        unsigned int outison ;      // initially detected outputpins that are on
        int i ;

        unsigned int allcol = (1<<GROEN) + (1<<GEEL) + (1<<ROOD) + (1<<BLAUW);

        int gpioouten=open("/dev/gpio/outen",O_RDWR);
        int gpioout=open("/dev/gpio/out",O_RDWR);
        //int gpioin=open("/dev/gpio/in",O_RDWR);        // why write to input pins?

        for (i = 1; i < argc; i++) {
                if (!strcmp(argv[i],"groen")) {
                        usrcol += (1<<GROEN) ;
                }
                if (!strcmp(argv[i],"geel")) {
                        usrcol += (1<<GEEL) ;
                }
                if (!strcmp(argv[i],"rood")) {
                        usrcol += (1<<ROOD) ;
                }
                if (!strcmp(argv[i],"blauw")) {
                        usrcol += (1<<BLAUW) ;
                }
                if (!strcmp(argv[i],"on")) {
                        usrcmd = ON ;
                }
                if (!strcmp(argv[i],"off")) {
                        usrcmd = OFF ;
                }
                if (!strcmp(argv[i],"toggle")) {
                        usrcmd = TOGGLE ;
                }
                if (!strcmp(argv[i],"read")) {
                        usrcmd = READ ;
                }
        }

        if (! usrcol) {
                usrcol = allcol ;
        }

// ------------------------------------------------------------------

        // read the status of all output pins for future refence
        //printf("dd reading gpio_out\n");
        read(gpioout, &gpio, sizeof(gpio));
        //printf ("dd output pins are now       %i      ", gpio) ;
        //print_bin(gpio) ;
        outison = gpio ;

        // figure out which gpio pins are already enabled as outputs
        //printf("dd reading gpio_out_en\n");
        read(gpioouten, &gpio, sizeof(gpio));
        //printf ("dd enabled for output        %i      ", gpio) ;
        //print_bin(gpio) ;

        // add the pins we wired and enable them all as outputs
        gpio = gpio | allcol ;
        //printf("dd enabling for output        %i...   ", gpio) ;
        //print_bin(gpio) ;
        write(gpioouten, &gpio, sizeof(gpio));

// ------------------------------------------------------------------

        // investigate the user's request
        if (usrcmd != READ) {
                if (usrcmd == ON) {
                        // switch all lights off before switching them on
                        gpio = outison & ~allcol;
                        gpio = gpio    |  usrcol;
                } else if (usrcmd == OFF) {
                        gpio = outison & ~usrcol;
                } else if (usrcmd == TOGGLE) {
                        // toggle gpio
                        int keep = outison & ~usrcol ;
                        gpio = outison & allcol ;
                        gpio = gpio ^ usrcol ;
                        gpio = gpio | keep ;
                }
                // alter status to new setting
                //printf("dd writing to output  %i...   ", gpio);
                //print_bin(gpio) ;
                write(gpioout, &gpio, sizeof(gpio));
        }

        // read the status of all output pins again
        //printf("dd reading gpio_out\n");
        read(gpioout, &gpio, sizeof(gpio));
        //printf ("dd output pins are now       %i      ", gpio) ;
        //print_bin(gpio) ;

        // print current status of lights and exit
        printf("OK:");
        if (gpio & 1<<GROEN) {printf(" groen");}
        if (gpio & 1<<GEEL ) {printf(" geel" );}
        if (gpio & 1<<ROOD ) {printf(" rood" );}
        if (gpio & 1<<BLAUW) {printf(" blauw");}
        printf("|status=%i\n", gpio & allcol);
        //print_bin(gpio) ;
        return 0;
}

// ------------------------------------------------------------------

int print_bin(int n) {
        // print integer value as binary number (MSB to LSB)
        int k ;
        //printf("dd ");
        for (k=7; k>=0; k--) {
                printf("%i", (n&(1<<k))?1:0);
        }
        printf("\n");
}

