#include <stdio.h>
#include <unistd.h> /* needed for ioperm() */
#include <asm/io.h> /* for outb() and inb() */
#include <time.h>
#include <getopt.h>
#include <signal.h> // signalhandling unter Ansi C -> http://wwwsys.informatik.fh-wiesbaden.de/sysprog/buch0076.htm


/*
weitere benötigte Dateien:
    kaffee.bell    (ShellSkript zur Tonausgabe)
    KaffeeFertig.wav
    
    kompilieren mit: gcc -o kaffee kaffee.c


=> out  pin     pin     Signal          Bit     Function Notes
------  ----    ----    --------        ---     -----------------------------
=>       2       2      Data 0          D0      Set to least significant data

<=      10      10      /Ack            S6+     IRQ Low Pulse ~ 5 uS, after accept
<=      11      11      Busy            S7-     High for Busy/Offline/Error
*/

#define DATA 0x378
#define STATUS DATA+1
short statusBits, datenBits;

void handler(int signal) { // Bit auf 0 Setzen wenn Strg+c gedrückt
    //short statusBits, datenBits;
    
    if (signal == SIGINT) {
        datenBits = inb(DATA);
        datenBits &= 254; 
        outb (datenBits, DATA); 
        abort(); // statt exit(134); 
    }

}

keinWasser() {
    printf ("\n\033[22;31mSorry, die Wasser Prüfung fiel negativ aus !\n");
    printf ("Bitte füllen Sie Wasser ein !\n"); 
    printf ("ganz fettes sorry... heute Morgen wird es wohl keinen Kaffee geben\n\033[22;30m");
    sleep(10);
    exit(5); // system ("echo $?")
}

void keineTasse() {
    printf ("\n\033[22;31mSorry, die Tassen Prüfung viel Negativ aus !\n");
    printf ("Bitte stellen Sie eine Tasse drunter !\n");
    printf ("ganz fettes sorry... heute Morgen wird es wohl keinen Kaffee geben\n\033[22;30m");
    sleep(10);    
    exit(6); 
}
    
int main(int argc, char* argv[]) {
 
    // Variablendeklarationen (müssen bei ANSI C ganz oben stehen)
    int opt, i;
    int time = 80, meldungsVerzoegerung = 6; // 110;
    //short statusBits, datenBits;
    short tc=1, verbose=0, quiet=0;

    // Signalhandling (Strg+C) 
    if (SIG_ERR == signal(SIGINT, handler)) {
      fprintf(stderr, "Fehler beim Installieren des Handlers\n");
      exit(1);
    }    
          
    if (ioperm (DATA,3,1) ) {
        printf("Leider haben Sie keinen Zugriff auf die parallele Schnittstelle\n");
        printf("Sie benötigen root Recht um dieses Programm auszuführen\n");
        exit(1);
    }
 
    while (1) {
        opt = getopt (argc, argv, "v" "q");
        if (opt == -1) break;
        if (opt == 'v') verbose = 1;
        if (opt == 'q') quiet = 1;
    }
    
    // Parallelport auslesen
    statusBits = inb(STATUS);
    // printf("status Bits: %i\n", statusBits);

    for (i=1; i < argc; i++) {
        if (!strcmp(argv[i], "klein")) time=96; //90 > 100       
	else if (!strcmp(argv[i], "ntc")) tc=0;        // No Tassen Check
	else if (!strcmp(argv[i], "gross")) {
            // Tassenabfrage (busy open/closed)
            if (statusBits & 128) time=190, meldungsVerzoegerung = 4*60; // Hanftasse
            else printf ("Capputasse drunter !!!\n"), time=170, tc=0;
        }            
        else if (!strcmp(argv[i], "groß")) time=120;         
        else if (!strcmp(argv[i], "riesig")) time=135; // ???
        else if (!strcmp(argv[i], "supergross")) time=126; // ???
	else if (!strcmp(argv[i], "bohnenkaffee")) time=163, meldungsVerzoegerung = 10; // Echer Kaffee, kein Cappuccinopulver
	else if (!strcmp(argv[i], "hanftasse")) time=190, meldungsVerzoegerung = 5*60;  // die Tasse mit dem Hanfblatt, z.B. Tee
        else if (!strcmp(argv[i], "4min")) meldungsVerzoegerung = 4*60;  // für Grünen Tee
	else {
	     printf("\n\033[22;31mFalscher Parameter: %s\033[22;30m   - korrecte Parameter wären:", argv[i]); 
	     printf("\n\t klein, gross oder groß, riesig oder supergross und bohnenkaffee,");
	     printf("\n\t jetzt NEU: hanftasse [4min] für Zugzeit Grünen Tee \n\t ntc für No Tassen Check\n\n");
	     exit(7);
	}
    }


    /*
    &    AND                    00 -> 0 01 -> 0 10 -> 0 11 -> 1
    |    OR                     00 -> 0 01 -> 1 10 -> 1 11 -> 1
    ^    XOR (exklusives OR)    00 -> 0 01 -> 1 10 -> 1 11 -> 0
    ~    Komplement-Operator    0 <-> 1
    */
    
    // invertiert 8.Bit(S7): 1000000
    statusBits ^= 128; // statusBits = statusBits ^ 128;
    
    statusBits &  64 ? printf ("Wasser check\t-ok-\n") : keinWasser();    //  ack open/closed
    if (tc) statusBits & 128 ? keineTasse() : printf ("Tassen check\t-ok-\n");    // busy open/closed
    
// WAV ... START COOKING einfügen ..
            
    datenBits = inb(DATA);
    if (verbose) printf("DATEN Bits: %i\n", datenBits);
    datenBits |= 1; //auch datenBits ^= 1;
    if (verbose) printf("DATEN Bits: %i\n", datenBits);
    outb (datenBits, DATA);
    
    if (!quiet) printf("Ich koche nun Kaffee fr Sie, bitte gedulden Sie sich %i Sekunden\n", time);        
    if (!quiet) printf("mit %i Minuten an Zieh-Zeit\n" ,meldungsVerzoegerung/60 );  
    sleep(time);
    
    datenBits = inb(DATA);
    if (verbose) printf("DATEN Bits: %i\n", datenBits);
    datenBits &= 254; 
    if (verbose) printf("DATEN Bits: %i\n", datenBits);
    outb (datenBits, DATA);
    
    if (!quiet) printf("\aIhr Kaffee ist jetzt fertig und abholbereit, danke daß Sie mich benutzt haben.\n");
    
    /* system ("wavp KaffeeFertig.wav"); // nachinstallieren !
    system ("aumix -S");
    system ("sudo -u markus xmms -u");
    system ("aumix -w 100");
    system ("music123 /home/markus/c++/KaffeeFertig.wav"); // apt-get install music123
    system ("aumix -L");
    system ("sudo -u markus xmms -u");
    */
    sleep(meldungsVerzoegerung);
    system ("sudo -u markus /home/markus/c++/kaffee.bell");
    sleep(5);   
    return (0);
}