/*
 ============================================================================
 Name        : geigerTest001.c
 Author      : hb8be
 Version     : 0.0-0
 Description : Use Sparkfun's Geiger counter (sku:SEN-09298) as a Geiger counter
               http://hb8.be/geiger/
 Notes       : Compile with -lpthread.
               Assumes that the device is attached to /dev/ttyUSB0.
 ============================================================================
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>

#define BUFFER_SIZE 64

#ifndef _REENTRANT
#error Might be good to compile with -D_REENTRANT since we use threads
#endif

volatile int bStop = 0;
volatile int bufferPos = 0;
long buffer[BUFFER_SIZE];
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

void * runReadSerial(void *arg) {
	int usbdev; /* handle to FTDI device */
	char response[20]; /* receive buffer */
	struct timeval t1;
	long mtime, ptime;

	system("stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parity -icanon min 1 time 1");
	usbdev = open("/dev/ttyUSB0", O_RDWR);
	gettimeofday(&t1, NULL);
	ptime = t1.tv_sec * 1000 + t1.tv_usec / 1000.0;
	while (!bStop) {
		read(usbdev, response, 1);
		gettimeofday(&t1, NULL);
		fputs(".", stderr);
		fflush(stderr);
		mtime = t1.tv_sec * 1000 + t1.tv_usec / 1000.0;
		bufferPos++;
		if (bufferPos >= BUFFER_SIZE)
			bufferPos = 0;
		pthread_mutex_lock(&mymutex);
		buffer[bufferPos] = mtime - ptime;
		pthread_mutex_unlock(&mymutex);
		ptime = mtime;
	}
	close(usbdev);
	return NULL;
}

int main(void) {
	pthread_t mythread;
	int i, count;
	long sum, v;

	/* initialise buffer */
	for (i = 0; i < BUFFER_SIZE; i++)
		buffer[i] = -1;

	/* create thread */
	if (pthread_create(&mythread, NULL, runReadSerial, NULL)) {
		fputs("error creating thread.\n", stderr);
		abort();
	}

	/* output counts per minutes */
	while (1) { /* and yes, it never stops ! */
		count = 0;
		sum = 0;
		pthread_mutex_lock(&mymutex);
		for (i = 0; i < BUFFER_SIZE; i++) {
			v = buffer[i];
			if (v > 0) {
				sum += v;
				count++;
			}
		}
		pthread_mutex_unlock(&mymutex);
		printf("%.2f cpm\n", (double) 60 / (double) sum * 1000 * (double) count);
		fflush(stdout);
		sleep(2); /* sleep 2 seconds */
	}

	/* Stop the threads */
	bStop = 1;
	if (pthread_join(mythread, NULL )) {
		fputs("error joining thread.", stderr);
		abort();
	}

	exit(0);
}

