/******************************************************************************
** Copyright 2015 MBARI - Monterey Bay Aquarium Research Institute
*******************************************************************************
*******************************************************************************
** Summary  : Routines to access DS1683 Elapsed-Time and Event Recorder
** Filename : ds1683.c
** Author   : Luke Coletti
** Project  :
** Version  : 1.0
** Compiler : MetroWerks Code Warrior v8.3
** Created  : 12/15/14
** Archived :
*******************************************************************************
** Modification History:
** 01/02/15 : CF2 Port, LJC
*******************************************************************************/

#include        <cfxpico.h>             // Persistor BIOS and I/O Definitions
#include        <ds1683.h>



int DS1683_Init(void)
{
	int ret;
	uchar Data;

	I2C_Select( I2C_BUS_SYS );

	I2C_Start();
	ret =  I2C_WrByte( DS1683_ADDR_WR );
	ret &= I2C_WrByte( DS1683_CONFIG_REG );
	I2C_Start();
	ret &= I2C_WrByte( DS1683_ADDR_RD );
	I2C_RdByte( &Data );
	I2C_WrNak();
	I2C_Stop();

	if ( (Data & 0x07) != DS1683_CONFIG_VAL ) {
		I2C_Start();
		ret &= I2C_WrByte( DS1683_ADDR_WR );
		ret &= I2C_WrByte( DS1683_CONFIG_REG );
		ret &= I2C_WrByte( DS1683_CONFIG_VAL );
		I2C_Stop();

		RTCDelayMicroSeconds( 40000 );                          //Allow 40ms to complete EEPROM Write Cycle (Tw = 20ms  max per spec)
	}

	I2C_Start();
	ret &= I2C_WrByte( DS1683_ADDR_WR );
	ret &= I2C_WrByte( DS1683_COMMAND_REG );
	ret &= I2C_WrByte( CLEAR_ALARM_VAL );                   //clear any asserted alarms
	I2C_Stop();

	I2C_Select( I2C_BUS_DISABLE );

	if( ret != I2C_ACK )                                                    //If device ACK'd every transmitted byte, then we're in good shape
		ret = ERROR;

	return( ret );                                                          //Return I2C Transfer Status

}


int DS1683_ReadReg(uchar Reg, uchar *Data)
{
	int ret;

	I2C_Select( I2C_BUS_SYS );

	I2C_Start();
	ret =  I2C_WrByte( DS1683_ADDR_WR );
	ret &= I2C_WrByte( Reg );
	I2C_Start();
	ret &= I2C_WrByte( DS1683_ADDR_RD );
	I2C_RdByte( Data );
	I2C_WrNak();
	I2C_Stop();

	I2C_Select( I2C_BUS_DISABLE );

	if( ret != I2C_ACK )                                                            //If device ACK'd every transmitted byte, then we're in good shape
		ret = ERROR;

	return( ret );

}


int DS1683_RdEventCounter(ushort *Events)
{
	int ret;
	uchar Data_h, Data_l;

	I2C_Select( I2C_BUS_SYS );

	I2C_Start();
	ret =  I2C_WrByte( DS1683_ADDR_WR );
	ret &= I2C_WrByte( DS1683_EVENTCTR_REG0 );
	I2C_Start();
	ret &= I2C_WrByte( DS1683_ADDR_RD );
	I2C_RdByte( &Data_l );
	I2C_WrAck();
	I2C_RdByte( &Data_h );
	I2C_WrNak();
	I2C_Stop();

	I2C_Select( I2C_BUS_DISABLE );

	*Events = (ushort)(((ushort)Data_h << 8) | Data_l);

	if( ret != I2C_ACK )                                                            //If device ACK'd every transmitted byte, then we're in good shape
		ret = ERROR;

	return( ret );

}


int DS1683_WrEventCounter(ushort *Events)
{
	int ret;
	uchar Data_h, Data_l;

	Data_h = (uchar)((*Events >> 8) & 0x00FF);
	Data_l = (uchar)(*Events & 0x00FF);

	I2C_Select( I2C_BUS_SYS );

	I2C_Start();
	ret =  I2C_WrByte( DS1683_ADDR_WR );
	ret &= I2C_WrByte( DS1683_EVENTCTR_REG0 );
	ret &= I2C_WrByte( Data_l );
	ret &= I2C_WrByte( Data_h );
	I2C_Stop();

	I2C_Select( I2C_BUS_DISABLE );

	RTCDelayMicroSeconds( 40000 );                                          //Allow 40ms to complete EEPROM Write Cycle (Tw = 20ms  max per spec)

	if( ret != I2C_ACK )                                                            //If device ACK'd every transmitted byte, then we're in good shape
		ret = ERROR;

	return( ret );

}


int DS1683_RdElapsedTimer(ulong *ElapsedSecs)
{
	int ret;
	uchar Data[4];

	I2C_Select( I2C_BUS_SYS );

	I2C_Start();
	ret =  I2C_WrByte( DS1683_ADDR_WR );
	ret &= I2C_WrByte( DS1683_ELAPSEDTIME_REG0 );
	I2C_Start();
	ret &= I2C_WrByte( DS1683_ADDR_RD );
	I2C_RdByte( &Data[3] );         //LSB
	I2C_WrAck();
	I2C_RdByte( &Data[2] );
	I2C_WrAck();
	I2C_RdByte( &Data[1] );
	I2C_WrAck();
	I2C_RdByte( &Data[0] );         //MSB - 68k uP is big-endian (MSB at lowest mem addr)
	I2C_WrNak();
	I2C_Stop();

	I2C_Select( I2C_BUS_DISABLE );

	// synthesize ulong value from uchar array.
	memcpy((ulong*)ElapsedSecs, (uchar*)Data, (size_t)4);

	// report value in secs
	*ElapsedSecs = *ElapsedSecs/4;

	if( ret != I2C_ACK )                                                            //If device ACK'd every transmitted byte, then we're in good shape
		ret = ERROR;

	return( ret );

}


int DS1683_WrElapsedTimer(ulong *ElapsedSecs)
{
	int ret;
	uchar Data[4];
	ulong ElapsedQuarterSecs;

	ElapsedQuarterSecs = *ElapsedSecs * 4;

	// decompose value into byte array.
	memcpy((uchar*)Data, &ElapsedQuarterSecs, (size_t)4);

	I2C_Select( I2C_BUS_SYS );

	I2C_Start();
	ret =  I2C_WrByte( DS1683_ADDR_WR );
	ret &= I2C_WrByte( DS1683_ELAPSEDTIME_REG0 );
	ret &= I2C_WrByte( Data[3] );           //LSB
	ret &= I2C_WrByte( Data[2] );
	ret &= I2C_WrByte( Data[1] );
	ret &= I2C_WrByte( Data[0] );           //MSB - 68k uP is big-endian (MSB at lowest mem addr)
	I2C_Stop();

	I2C_Select( I2C_BUS_DISABLE );

	RTCDelayMicroSeconds( 40000 );                                          //Allow 40ms to complete EEPROM Write Cycle (Tw = 20ms  max per spec)

	if( ret != I2C_ACK )                                                            //If device ACK'd every transmitted byte, then we're in good shape
		ret = ERROR;

	return( ret );

}









