/*******************************************************************************
 *	BRtc.h		Real Time Clock interface
 *			T.Barnaby,	BEAM Ltd,	19/5/04
 *******************************************************************************
 */
#include <BRtc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/rtc.h>

BRtc::BRtc(){
	ofd = -1;
	orate = 0;
}

BRtc::~BRtc(){
	if(ofd > 0)
		close(ofd);
}

BError BRtc::init(int rate){
	BError	err;
	
	orate = rate;
	
	if((ofd = open("/dev/rtc", O_RDONLY)) < 0)
		err.set(ErrorMisc, BString("Unable to open /dev/rtc: ") + strerror(errno));

	if(!err && (ioctl(ofd, RTC_IRQP_SET, orate) < 0))
		err.set(ErrorMisc, BString("Unable to set RTC rate: ") + strerror(errno));
		
	if(!err && (ioctl(ofd, RTC_PIE_ON, 0) < 0))
		err.set(ErrorMisc, BString("Unable to set RTC interrupt: ") + strerror(errno));
	return err;
}

void BRtc::wait(int delayUs){
	int		n;
	unsigned long	data;
	
	n = (orate * delayUs) / 1000000;
	if(n < 1)
		n = 1;
		
	while(n--)
		read(ofd, &data, sizeof(data));
}

BRtcThreaded::BRtcThreaded(){
	orate = 0;
}

BRtcThreaded::~BRtcThreaded(){
}

BError BRtcThreaded::init(int rate){
	BError	err;

	orate = rate;
	if(! (err = ortc.init(rate))){
		setInitStackSize(100 * 1024);
		start();
	}

	return err;
}

void* BRtcThreaded::function(){
	while(1){
		ortc.wait(1000000 / orate);
		ocond.signal();
	}
	return 0;
}

void BRtcThreaded::wait(int delayUs){
	int		n;
	
	n = (orate * delayUs) / 1000000;
	if(n < 1)
		n = 1;

	while(n--)
		ocond.wait();
}
