#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <strings.h>
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h> 
#include <pthread.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
int fd;


// gcc -std=gnu99 -pthread -Wall 20120901-C-FlipDisplay-Host-Sample.c && ./a.out


void handleChar(char c) {
	static char printBuffer[1024 * 2];
	static int buff_p = 0;
	printBuffer[buff_p++] = c;
	if (c == '\r' || c == '\n') {
		//memcpy(printBuffer, localBuffer, rb + buff_p);
		printBuffer[buff_p] = '\0';
		printf("%s", printBuffer);	
		fflush(stdout);
		buff_p = 0;
	}
}

void *uart_thread(void *threadid) {
	char localBuffer[1024 * 2];
	
	
	while (1) {
		int rb = read(fd, localBuffer, 1024);
		for (int i = 0; i < rb; i++) {			
			char c = localBuffer[i];
			handleChar(c);
		}
	}
}

void _delay_ms(uint32_t x) {
	usleep(x * 1000);
}

#define _segment_a 0b00000001
#define _segment_b 0b00000010
#define _segment_c 0b00000100
#define _segment_d 0b00001000
#define _segment_e 0b00010000
#define _segment_f 0b00100000
#define _segment_g 0b01000000
#define _segment_h 0b10000000

const char char_gen[] = {
 _segment_a+_segment_b+_segment_c+_segment_d+_segment_e+_segment_f,   			// Displays "0"
 _segment_b+_segment_c,           												// Displays "1"
 _segment_a+_segment_b+_segment_d+_segment_e+_segment_g,     					// Displays "2"
 _segment_a+_segment_b+_segment_c+_segment_d+_segment_g,     					// Displays "3"
 _segment_b+_segment_c+_segment_f+_segment_g,       							// Displays "4"
 _segment_a+_segment_c+_segment_d+_segment_f+_segment_g,     					// Displays "5"
 _segment_a+_segment_c+_segment_d+_segment_e+_segment_f+_segment_g,   			// Displays "6"
 _segment_a+_segment_b+_segment_c,         										// Displays "7"
 _segment_a+_segment_b+_segment_c+_segment_d+_segment_e+_segment_f+_segment_g, 	// Displays "8"
 _segment_a+_segment_b+_segment_c+_segment_d+_segment_f+_segment_g,   			// Displays "9"
 _segment_a+_segment_b+_segment_c+_segment_e+_segment_f+_segment_g,   			// Displays "A"
 0x00,          																// Displays  Blank
 _segment_a+_segment_d+_segment_e+_segment_f,       							// Displays "C"
 _segment_a+_segment_b+_segment_f+_segment_g,       							// Displays "degrees" o
 _segment_a+_segment_d+_segment_e+_segment_f+_segment_g,     					// Displays "E"
 _segment_a+_segment_e+_segment_f+_segment_g        							// Displays "F"   
};

int main(int argc, char *argv[]) {

	fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
	fcntl(fd, F_SETFL, 0);

	struct termios options;
	tcgetattr(fd, &options);
	cfsetispeed(&options, B19200);
	cfsetospeed(&options, B19200);
	options.c_cflag |= (CLOCAL | CREAD);

	// No parity (8N1)
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;

	options.c_iflag |= (INPCK | ISTRIP); // checking and stripping of the parity bit

	// raw
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG);

	tcsetattr(fd, TCSANOW, &options); // Make changes now without waiting for data to complete


	char buff[1024];
	int ret; 

	// clear displays
	/*sprintf(buff, "#%04d\n", 0);
		ret = write(fd, buff, 6);
	while (1) {};*/
	



	pthread_t uart_thread_p;
	pthread_create(&uart_thread_p, NULL, uart_thread, (void *) 0);

	int num = 1;
	while (1) {
		sprintf(buff, "#%4d\n", num);
		printf("%s", buff);
//		num++;
//		num *= 3;
		num += 23;
		if (num >= 10000) {
			num = (num / 10000) + 1;
//			num = 0;
		}
/*		if (num) {
			num = 0;
		} else {
			num = rand() % 10000;
		}
		*/
		for (uint8_t i = 1; i < 5; i++) {
//			buff[i] = char_gen[buff[i]];
			if (buff[i] == '0') buff[i] = ' ';
		}
		ret = write(fd, buff, 6);
//		ret = write(fd, "\n", 1);
//		fflush(fd);
		printf(" ret: %d\r\n", ret);
		_delay_ms(500);
	}

}

