/*
 * Copyright(C) Paul und Scherer (mct.de/mct.net)
 *
 * This example demonstrates how to...
 *
 *  ... read and set the RTC.
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "ow.h"

#define SkipROM		0xcc			// 1-wire command
#define ReadClock	0x66
#define WriteClock	0x99			//  commands

/*
 * Read RTC to tp, compare with cp and return 0 if equal.
 */
static int
getrtc(time_t *tp, time_t *cp)
{
	OW_PROBE;				// reset pulse
	ow_tx(SkipROM);				// skip serial number
	ow_tx(ReadClock);			// read clock cmd
	ow_rx();				// device control byte
	*tp  = ow_rx()	  ;			// # of
	*tp |= ow_rx()<<8 ;
	*tp |= ow_rx()<<16;
	*tp |= ow_rx()<<24;			//  seconds
	return *tp != *cp;
}

/*
 * Probe for RTC.
 */
static void
probe(void)
{
	static int done;			// skip if already done

	if (!done) {
		if (OW_PROBE) puts("RTC not found!"), abort();
		done = 1;
	}
}

/*
 * Return date (the alarm flag is ignored!)
 * in seconds since 00:00:00, Jan. 1, 1970.
 */
time_t
_gettime(int alarm)
{
	time_t t1, t2;

	probe();				// RTC functional?

	/*
	 * Read until two successive reads are equal.
	 */
	while (getrtc(&t1, &t2) && getrtc(&t2, &t1)) ;

	return t1;
}

/*
 * Set date (the alarm flag is ignored!) to t
 * (t = seconds since 00:00:00, Jan. 1, 1970).
 */
void
_settime(time_t t, int alarm)
{
	probe();				// RTC functional?
	OW_PROBE;				// reset pulse
	ow_tx(SkipROM);				// skip serial number
	ow_tx(WriteClock);			// write clock cmd
	ow_tx(0xc);				// device control byte
	ow_tx(t	   );				// # of
	ow_tx(t>> 8);
	ow_tx(t>>16);
	ow_tx(t>>24);				//  seconds
	OW_PROBE;				// reset pulse
}

/*
 * The current date is displayed. When a new date is entered,
 * the current date is modified and written back to the RTC.
 *
 * Note: Reading from and writing to the RTC is done without
 * checking return values. Both functions probe once for the
 * RTC and if found, assume proper operation.
 *
 * If you use these functions in your own program, you could
 * extract the RTC probing to your global init section.
 */
int
main(void)
{
	while (1) {
		char line[30];			// input buffer
		time_t t = time(0);		// current date

		printf("Current date: %s\n"
		       "New date (hh mm ss DD MM YYYY, no check!): ",
			ctime(&t)
		);
		if (*fgets(line, sizeof(line), stdin) != '\n') {
			struct tm *tp = localtime(&t);

			tp->tm_mon++;			// correct month
			tp->tm_year += 1900;		//         year
			sscanf(line, "%d%d%d%d%d%d",	// scan line
				&tp->tm_hour,
				&tp->tm_min,
				&tp->tm_sec,
				&tp->tm_mday,
				&tp->tm_mon,
				&tp->tm_year
			);
			tp->tm_mon--;			// tm_mon  : 0.. 11
			tp->tm_year -= 1900;		// tm_year : years since 1900
			_settime(mktime(tp), 0);	// set new date
		}
	}
}

