/*
 * Texas Instruments TMP105 temperature sensor.
 *
 * Copyright (C) 2008 Nokia Corporation
 * Written by Andrzej Zaborowski <andrew@openedhand.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 or
 * (at your option) version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include "hw.h"
#include "i2c.h"

struct tmp105_s {
    i2c_slave i2c;
    int len;
    uint8_t buf[2];
    qemu_irq pin;

    uint8_t pointer;
    uint8_t config;
    int16_t temperature;
    int16_t limit[2];
    int faults;
    int alarm;
};

static void tmp105_interrupt_update(struct tmp105_s *s)
{
    qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1));	/* POL */
}

static void tmp105_alarm_update(struct tmp105_s *s)
{
    if ((s->config >> 0) & 1) {					/* SD */
        if ((s->config >> 7) & 1)				/* OS */
            s->config &= ~(1 << 7);				/* OS */
        else
            return;
    }

    if ((s->config >> 1) & 1) {					/* TM */
        if (s->temperature >= s->limit[1])
            s->alarm = 1;
        else if (s->temperature < s->limit[0])
            s->alarm = 1;
    } else {
        if (s->temperature >= s->limit[1])
            s->alarm = 1;
        else if (s->temperature < s->limit[0])
            s->alarm = 0;
    }

    tmp105_interrupt_update(s);
}

/* Units are 0.001 centigrades relative to 0 C.  */
void tmp105_set(i2c_slave *i2c, int temp)
{
    struct tmp105_s *s = (struct tmp105_s *) i2c;

    if (temp >= 128000 || temp < -128000) {
        fprintf(stderr, "%s: values is out of range (%i.%03i C)\n",
                        __FUNCTION__, temp / 1000, temp % 1000);
        exit(-1);
    }

    s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4;

    tmp105_alarm_update(s);
}

static const int tmp105_faultq[4] = { 1, 2, 4, 6 };

static void tmp105_read(struct tmp105_s *s)
{
    s->len = 0;

    if ((s->config >> 1) & 1) {					/* TM */
        s->alarm = 0;
        tmp105_interrupt_update(s);
    }

    switch (s->pointer & 3) {
    case 0:	/* Temperature */
        s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8);
        s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) &
                (0xf0 << ((~s->config >> 5) & 3));		/* R */
        break;

    case 1:	/* Configuration */
        s->buf[s->len ++] = s->config;
        break;

    case 2:	/* T_LOW */
        s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8;
        s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0;
        break;

    case 3:	/* T_HIGH */
        s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8;
        s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0;
        break;
    }
}

static void tmp105_write(struct tmp105_s *s)
{
    switch (s->pointer & 3) {
    case 0:	/* Temperature */
        break;

    case 1:	/* Configuration */
        if (s->buf[0] & ~s->config & (1 << 0))			/* SD */
            printf("%s: TMP105 shutdown\n", __FUNCTION__);
        s->config = s->buf[0];
        s->faults = tmp105_faultq[(s->config >> 3) & 3];	/* F */
        tmp105_alarm_update(s);
        break;

    case 2:	/* T_LOW */
    case 3:	/* T_HIGH */
        if (s->len >= 3)
            s->limit[s->pointer & 1] = (int16_t)
                    ((((uint16_t) s->buf[0]) << 8) | s->buf[1]);
        tmp105_alarm_update(s);
        break;
    }
}

static int tmp105_rx(i2c_slave *i2c)
{
    struct tmp105_s *s = (struct tmp105_s *) i2c;

    if (s->len < 2)
        return s->buf[s->len ++];
    else
        return 0xff;
}

static int tmp105_tx(i2c_slave *i2c, uint8_t data)
{
    struct tmp105_s *s = (struct tmp105_s *) i2c;

    if (!s->len ++)
        s->pointer = data;
    else {
        if (s->len <= 2)
            s->buf[s->len - 1] = data;
        tmp105_write(s);
    }

    return 0;
}

static void tmp105_event(i2c_slave *i2c, enum i2c_event event)
{
    struct tmp105_s *s = (struct tmp105_s *) i2c;

    if (event == I2C_START_RECV)
        tmp105_read(s);

    s->len = 0;
}

static void tmp105_save(QEMUFile *f, void *opaque)
{
    struct tmp105_s *s = (struct tmp105_s *) opaque;

    qemu_put_byte(f, s->len);
    qemu_put_8s(f, &s->buf[0]);
    qemu_put_8s(f, &s->buf[1]);

    qemu_put_8s(f, &s->pointer);
    qemu_put_8s(f, &s->config);
    qemu_put_be16s(f, (uint16_t *) &s->temperature);
    qemu_put_be16s(f, (uint16_t *) &s->limit[0]);
    qemu_put_be16s(f, (uint16_t *) &s->limit[1]);
    qemu_put_byte(f, s->alarm);
    s->faults = tmp105_faultq[(s->config >> 3) & 3];		/* F */

    i2c_slave_save(f, &s->i2c);
}

static int tmp105_load(QEMUFile *f, void *opaque, int version_id)
{
    struct tmp105_s *s = (struct tmp105_s *) opaque;

    s->len = qemu_get_byte(f);
    qemu_get_8s(f, &s->buf[0]);
    qemu_get_8s(f, &s->buf[1]);

    qemu_get_8s(f, &s->pointer);
    qemu_get_8s(f, &s->config);
    qemu_get_be16s(f, (uint16_t *) &s->temperature);
    qemu_get_be16s(f, (uint16_t *) &s->limit[0]);
    qemu_get_be16s(f, (uint16_t *) &s->limit[1]);
    s->alarm = qemu_get_byte(f);

    tmp105_interrupt_update(s);

    i2c_slave_load(f, &s->i2c);
    return 0;
}

void tmp105_reset(i2c_slave *i2c)
{
    struct tmp105_s *s = (struct tmp105_s *) i2c;

    s->temperature = 0;
    s->pointer = 0;
    s->config = 0;
    s->faults = tmp105_faultq[(s->config >> 3) & 3];
    s->alarm = 0;

    tmp105_interrupt_update(s);
}

static int tmp105_iid = 0;

struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm)
{
    struct tmp105_s *s = (struct tmp105_s *)
            i2c_slave_init(bus, 0, sizeof(struct tmp105_s));

    s->i2c.event = tmp105_event;
    s->i2c.recv = tmp105_rx;
    s->i2c.send = tmp105_tx;
    s->pin = alarm;

    tmp105_reset(&s->i2c);

    register_savevm("TMP105", tmp105_iid ++, 0,
                    tmp105_save, tmp105_load, s);

    return &s->i2c;
}
