~foura/uxn900

25bea2e6b0c9ecb4a734773be4bde7665893471d — james palmer 2 months ago 612e4d8
datetime: use the twl4030 rtc for an almost complete datetime device.

no way of checking daylight saving time with the rtc,
so that will have to stay out for now.
4 files changed, 141 insertions(+), 1 deletions(-)

M Makefile
A src/dev/datetime.c
A src/inc/dev/datetime.h
M src/main.c
M Makefile => Makefile +1 -0
@@ 14,6 14,7 @@ OFILES = \
	src/uxn.o \
	src/dev/console.o \
	src/dev/controller.o \
	src/dev/datetime.o \
	src/dev/nil.o \
	src/dev/screen.o \
	src/dev/system.o

A src/dev/datetime.c => src/dev/datetime.c +136 -0
@@ 0,0 1,136 @@
#include "uxn.h"
#include "dat.h"
#include "fns.h"

#define bcd2bin(x) (((x) & 0x0f) + ((x) >> 4) * 10)

enum {
	Rseconds = 0x1c,
	Rminutes = 0x1d,
	Rhours   = 0x1e,
	Rdays    = 0x1f,
	Rmonths  = 0x20,
	Ryears   = 0x21,	
	Rweeks   = 0x22,

	Rctrl   = 0x29,
		Rctrlget = 0x40,
	Rstatus = 0x2a,
	Rie     = 0x2b,
};

static void
datetime_latch(void)
{
	Uint8 buf[2];

	buf[0] = Rctrl;
	buf[1] = 0;
	
	i2c_read(PHYSI2C1, 0x4b, buf, 1, 1);
	buf[1] |= Rctrlget;
	i2c_write(PHYSI2C1, 0x4b, buf, 1, 1);
}

static Uint8
datetime_snarf(Uint8 reg)
{
	Uint8 buf[2];

	buf[0] = reg;
	buf[1] = 0;

	i2c_read(PHYSI2C1, 0x4b, buf, 1, 1);
	return bcd2bin(buf[1]);
}

Uint8
datetime_dotw(void)
{
	Uint8 day = datetime_snarf(Rdays) - 1;
	Uint8 month = datetime_snarf(Rmonths) - 1;
	Uint8 year = datetime_snarf(Ryears);

	return (day + month + year + year / 4 + 21) % 7;
} 

Uint16
datetime_doty(void)
{
	Uint16 ret;

	Uint8 day = datetime_snarf(Rdays) - 1;
	Uint8 month = datetime_snarf(Rmonths) - 1;
	Uint8 year = datetime_snarf(Ryears);

	ret = 0;
	for(Uint8 i = 0; i < month; i++) {
		switch(i) {
		case 0:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			ret += 31;
			break;

		case 2:	
			ret += 28;
			if(year % 4 == 0)
				ret += 1;

			break;

		default:
			ret += 30;
		}
	}

	return ret + day;
}

Uint8 
datetime_dei(Device *d, Uint8 port)
{
	Uint16 tmp = 0;

	datetime_latch();
	switch(port) {
	case 0x0:
	case 0x1:
		tmp = datetime_snarf(Ryears);		
		tmp += 2000; 

		if(port == 0x0)
			tmp = tmp >> 8;	

		break;

	case 0x2:
		tmp = datetime_snarf(Rmonths);	
		tmp += 1;
		break;

	case 0x3: tmp = datetime_snarf(Rdays); break;
	case 0x4: tmp = datetime_snarf(Rhours); break;
	case 0x5: tmp = datetime_snarf(Rminutes); break;
	case 0x6: tmp = datetime_snarf(Rseconds); break;
	case 0x7: tmp = datetime_dotw(); break;

	case 0x8:
	case 0x9:
		tmp = datetime_doty();
		if(port == 0x8)
			tmp = tmp >> 8;
	}

	return tmp & 0xff;
}

void 
datetime_deo(Device *d, Uint8 port)
{
	/* TODO: set the date and time */
}

A src/inc/dev/datetime.h => src/inc/dev/datetime.h +2 -0
@@ 0,0 1,2 @@
void  datetime_deo(Device *d, Uint8 port);
Uint8 datetime_dei(Device *d, Uint8 port);

M src/main.c => src/main.c +2 -1
@@ 4,6 4,7 @@

#include "dev/console.h"
#include "dev/controller.h"
#include "dev/datetime.h"
#include "dev/nil.h"
#include "dev/screen.h"
#include "dev/system.h"


@@ 77,6 78,7 @@ main(void)
	uxn_port(&u, 0x1, nil_dei,    console_deo);
	uxn_port(&u, 0x2, screen_dei, screen_deo);
	uxn_port(&u, 0x8, controller_dei, controller_deo);
	uxn_port(&u, 0xc, datetime_dei, datetime_deo);

	uxn_port(&u, 0x3, nil_dei, nil_deo);
	uxn_port(&u, 0x4, nil_dei, nil_deo);


@@ 86,7 88,6 @@ main(void)
	uxn_port(&u, 0x9, nil_dei, nil_deo);
	uxn_port(&u, 0xa, nil_dei, nil_deo);
	uxn_port(&u, 0xb, nil_dei, nil_deo);
	uxn_port(&u, 0xc, nil_dei, nil_deo);
	uxn_port(&u, 0xd, nil_dei, nil_deo);
	uxn_port(&u, 0xe, nil_dei, nil_deo);
	uxn_port(&u, 0xf, nil_dei, nil_deo);