/*
 * ds75.c
 *
 *  Created on: Aug 1, 2012
 *      Author: tkl
 */

#include <stddef.h>
#include "ds75.h"

//-----------------------------------------------------------------------------
#define TEMPERATURE_REGISTER_ADDR	0x00
#define CONFIGURATION_REGISTER_ADDR	0x01

//-----------------------------------------------------------------------------
int ds75_open(const struct ds75 *device) {
	if(NULL == device) {
		return -1;
	}
	*device->config_value = 0x00;
	return device->i2c->fp->open(device->i2c->arch_dep_device);
}

//-----------------------------------------------------------------------------
int ds75_close(const struct ds75 *device) {
	if(NULL == device) {
		return -1;
	}
	return device->i2c->fp->close(device->i2c->arch_dep_device);
}

//-----------------------------------------------------------------------------
int ds75_set_precision(const struct ds75 *device, enum ds75_precision precision)
{
	if(NULL == device) {
		return -1;
	}
	char cfg = *device->config_value | (precision << 5);
	char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
	int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
			device->i2c_slave_addr, buffer, sizeof(buffer));
	if (ret >= 0) {
		*device->config_value = cfg;
	}
	return ret;
}

//-----------------------------------------------------------------------------
enum ds75_precision ds_75_get_precision(const struct ds75 *device) {
	if(NULL == device) {
		return DS_75_PRECISION_INVALID;
	}

	char cfg = *device->config_value;
	cfg >>= 5;
	cfg &= 3;
	return (enum ds75_precision) cfg;
}

//-----------------------------------------------------------------------------
int ds_75_shut_down(const struct ds75 *device) {
	if(NULL == device) {
		return -1;
	}
	char cfg = *device->config_value | (1 << 0);
	char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
	int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
			device->i2c_slave_addr, buffer, sizeof(buffer));
	if (ret >= 0) {
		*device->config_value = cfg;
	}
	return ret;
}

//-----------------------------------------------------------------------------
int ds_75_wakeup(const struct ds75 *device) {
	if(NULL == device) {
		return -1;
	}
	char cfg = *device->config_value & ~(1 << 0);
	char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
	int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
			device->i2c_slave_addr, buffer, sizeof(buffer));
	if (ret >= 0) {
		*device->config_value = cfg;
	}
	return ret;
}

//-----------------------------------------------------------------------------
struct ds75_temperature ds_75_get_temperature(const struct ds75 *device) {
	struct ds75_temperature ret;
	ret.temperature = 0xFFFF;
	ret.raw[0] = 0xFF;
	ret.raw[1] = 0xFF;
	ret.valid = false;
	if(NULL == device) {
		return ret;
	}
	// set temperature register
	char addr = TEMPERATURE_REGISTER_ADDR;
	int res = device->i2c->fp->write(device->i2c->arch_dep_device, device->i2c_slave_addr, &addr, 1);
	if(res < 0) {
		return ret;
	}

	// read temperature register
	res = device->i2c->fp->read(device->i2c->arch_dep_device, device->i2c_slave_addr, ret.raw, 2);
	if(res < 0) {
		return ret;
	}
	ret.valid = true;

	ret.temperature = ret.raw[0];
	if(ret.temperature & 0x0080) {
		ret.temperature |= 0xFF00;
	}
	ret.temperature *= 10;
	unsigned short s_low = (unsigned char)ret.raw[1];
	s_low >>= 4;
	s_low *= 625;
	s_low += 500;
	s_low /= 1000;
	ret.temperature += s_low;
	return ret;
}
