/*
Elro AB440S
http://sven.killig.de/FTDI
gcc -o rcswitch-MPSSE rcswitch-MPSSE.c -lmpsse
a2enmod cgid
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <mpsse.h>

typedef int bool;
#define true 1
#define false 0

#include "ftdi-lib.hpp"


struct mpsse_context *flash = NULL;
uint8_t data[25600];
int m_i;


void RCLtransmit(int nHighPulses, int nLowPulses) {
    int j;
    for(j=1; j<=nHighPulses; j++) {
    	data[m_i/8]|=1<<(m_i%8);
    	m_i++;
    }
    for(j=1; j<=nLowPulses; j++) {
    	m_i++;
    }
//printf("m_i=%i\n", m_i);
}


void RCLswitch(uint16_t code) {
printf("RCLswitch(%i\n", code);
m_i=0;
memset(data, 0, sizeof(data));
	int nRepeat;
    for (nRepeat=0; nRepeat<6; nRepeat++) {
    	int i;
        for (i=4; i<16; i++) {
            RCLtransmit(1,3);
            if (((code << (i-4)) & 2048) > 0) {
                RCLtransmit(1,3);
            } else {
                RCLtransmit(3,1);
            }
        }
        RCLtransmit(1,31);
    }
Write(flash, data, m_i/8+1);
}


void delay(int ms) {
	sleep(ms/1000);
}


void loop() {
    RCLswitch(0b111000010001);  // DIPs an Steckdose:123C  An:01
    delay(2000);

    RCLswitch(0b111000010010);  // DIPs an Steckdose:123C Aus:10
    delay(2000);
}

int main(int argc, char* argv[]) {
if(getenv("REQUEST_METHOD")) {
	printf("content-type: text/plain\x0D\x0A");
	printf("\x0D\x0A");
	fflush(stdout);
}
char svidpidserial[80];
int house_code, device_number, state;
if(getenv("QUERY_STRING") && strlen(getenv("QUERY_STRING"))) {
	char query_string[80];
	strncpy(query_string, getenv("QUERY_STRING"), sizeof(query_string));
	printf("strlen(query_string):%i\n", strlen(query_string)); fflush(stdout);
	strncpy(svidpidserial, strtok(query_string, ";"), sizeof(svidpidserial));
	printf("svidpidserial=%s\n", svidpidserial); fflush(stdout);
	house_code=strtol(strtok(NULL, ";"), NULL, 2);
	device_number=strtol(strtok(NULL, ";"), NULL, 0);
	state=strtol(strtok(NULL, ";"), NULL, 0);
} else if(argc==5) {
	strncpy(svidpidserial, argv[1], sizeof(svidpidserial));
	house_code=strtol(argv[2], NULL, 2);
	device_number=strtol(argv[3], NULL, 0);
	state=strtol(argv[4], NULL, 0);
} else {
	printf("usage: %s s:vid:pid:serial house-code(2) device-number 0/1\n", argv[0]);
	fflush(stdout);
	exit(0);
}

	int retval = EXIT_FAILURE;
	
	int vid, pid; char* serial; parseFTDIString(svidpidserial, &vid, &pid, &serial); printf("Trying to open 0x%04x:0x%04x '%s'\n", vid, pid, serial); fflush(stdout);

	if((flash = Open(vid, pid, SPI0, 2857, LSB, IFACE_A, NULL, serial)) != NULL && flash->open) {
		printf("Initialized at %d Hz\n", GetClock(flash)); fflush(stdout);
		/*while(run) {
			loop();
		}*/
		// 12345ABCDE01
		RCLswitch((house_code<<(2+5)) | (1<<(6-(device_number)+(2-1))) | (state?0b10:0b01));
		retval = EXIT_SUCCESS;
	} else {
		printf("Failed to initialize MPSSE: %s\n", ErrorString(flash)); fflush(stdout);
	}

    Stop(flash); // neccessary to flush
	Close(flash);

	return retval;
}
