Error as described in MBs email to MS

Dependencies:   SDFileSystem app epson mbed msp430 pl tests

pmic-tps65185.cpp

Committer:
marcbax
Date:
2018-01-11
Revision:
1:5874c1a074a7
Parent:
0:c643d398cdb6

File content as of revision 1:5874c1a074a7:

/*
  Plastic Logic EPD project on MSP430

  Copyright (C) 2013, 2014 Plastic Logic Limited

  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 3 of the License, or
  (at your option) any later version.

  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, see <http://www.gnu.org/licenses/>.
*/
/*
 * pmic-tps65185.c -- Driver for TI TPS65185 PMIC
 *
 * Authors:
 *  Nick Terry <nick.terry@plasticlogic.com>
 *  Guillaume Tucker <guillaume.tucker@plasticlogic.com>
 *
 */

#include <stdlib.h>
#include "assert.h"
#include "pmic-tps65185.h"
#include "vcom.h"

#define lOG printf

#define LOG_TAG "tps65185"
#include "utils.h"

/* Set to 1 to dump registers */
#define DO_REG_DUMP 0

#define HVPMIC_DAC_MAX          ((1 << 9)-1)
#define HVPMIC_DAC_MIN          0
#define HVPMIC_TEMP_DEFAULT     20
#define HVPMIC_VERSION          0x65

#if 0
#define MV_DIV	33		// Each DAC step is 33mV
#endif

enum tps65185_register {
	HVPMIC_REG_TMST_VALUE = 0x00,
	HVPMIC_REG_ENABLE     = 0x01,
	HVPMIC_REG_VADJ       = 0x02,
	HVPMIC_REG_VCOM1      = 0x03,
	HVPMIC_REG_VCOM2      = 0x04,
	HVPMIC_REG_INT_EN1    = 0x05,
	HVPMIC_REG_INT_EN2    = 0x06,
	HVPMIC_REG_INT1       = 0x07,
	HVPMIC_REG_INT2       = 0x08,
	HVPMIC_REG_UPSEQ0     = 0x09,
	HVPMIC_REG_UPSEQ1     = 0x0A,
	HVPMIC_REG_DWNSEQ0    = 0x0B,
	HVPMIC_REG_DWNSEQ1    = 0x0C,
	HVPMIC_REG_TMST1      = 0x0D,
	HVPMIC_REG_TMST2      = 0x0E,
	HVPMIC_REG_PG_STAT    = 0x0F,
	HVPMIC_REG_REV_ID     = 0x10,
	HVPMIC_REG_MAX
};

union tps65185_version {
	struct {
		char version:4;
		char minor:2;
		char major:2;
	} v;
	uint8_t byte;
};

struct pmic_data {
	uint8_t reg;
	uint8_t data;
};

static const struct pmic_data init_data[] = {
	{ HVPMIC_REG_ENABLE,     0x00 },
	{ HVPMIC_REG_VADJ,       0x03 },
	{ HVPMIC_REG_VCOM1,      0x00 },
	{ HVPMIC_REG_VCOM2,      0x00 },
	{ HVPMIC_REG_INT_EN1,    0x00 },
	{ HVPMIC_REG_INT_EN2,    0x00 },
	{ HVPMIC_REG_UPSEQ0,     0x78 },
	{ HVPMIC_REG_UPSEQ1,     0x00 },
	{ HVPMIC_REG_DWNSEQ0,    0x00 },
	{ HVPMIC_REG_DWNSEQ1,    0x00 },
	{ HVPMIC_REG_TMST1,      0x00 },
	{ HVPMIC_REG_TMST2,      0x78 }
};

int pl_i2c_reg_read_8(I2C &i2c, uint8_t i2c_addr, uint8_t reg, uint8_t *data)
{
    if (i2c.write(i2c_addr << 1, (char *) &reg, 1, true))
    {
        unsigned int log_addr = i2c_addr;
        unsigned int log_reg = reg;

        LOG("error writing I2C address %x register %x in pl_i2c_reg_read_8", log_addr, log_reg);
		i2c.stop();
        return -1;
    }

	return i2c.read(i2c_addr << 1, (char *) data, 1);
}

/* Note: reading some registers will modify the status of the device */
void reg_dump(struct tps65185_info *p)
{
	uint8_t data;
	uint8_t reg;

	for (reg = HVPMIC_REG_TMST_VALUE; reg < HVPMIC_REG_MAX; reg++) {
		if (!pl_i2c_reg_read_8(*p->i2c, p->i2c_addr, reg, &data))
			LOG("reg[0x%02X] = 0x%02X", reg, data);
	}
}

int pl_i2c_reg_write_8(I2C &i2c, uint8_t i2c_addr, uint8_t reg,
		       uint8_t data)
{
	const uint8_t w_data[2] = { reg, data };

	int status = i2c.write(i2c_addr << 1, (char *) w_data, sizeof(w_data));
    if(status)
    {
        unsigned int log_addr = i2c_addr;
        unsigned int log_reg = reg;

        LOG("error writing I2C address %x register %x in pl_i2c_reg_write_8", log_addr, log_reg);
        return -1;
    }
    return status;
}

int tps65185_init(struct tps65185_info *p, I2C &i2c,
		  uint8_t i2c_addr, const struct vcom_cal *cal)
{
	union tps65185_version ver;
	int i;

	p->i2c = &i2c;
	p->i2c_addr = i2c_addr;
	p->cal = cal; /* Cal may be NULL if not being used */

	if (pl_i2c_reg_read_8(i2c, i2c_addr, HVPMIC_REG_REV_ID, &ver.byte))
		return -1;

	LOG("Version: %d.%d.%d", ver.v.major, ver.v.minor, ver.v.version);

	if (ver.byte != HVPMIC_VERSION) {
		LOG("Wrong version: 0x%02X instead of 0x%02X",
		    ver.byte, HVPMIC_VERSION);
		return -1;
	}

	for (i = 0; i < ARRAY_SIZE(init_data); i++) {
		if (pl_i2c_reg_write_8(i2c, i2c_addr, init_data[i].reg, init_data[i].data))
			return -1;
	}

	return 0;
}

/* program the internal VCOM Dac to give us the required voltage */
int tps65185_set_vcom_voltage(struct tps65185_info *p, int mv)
{
	int dac_value;
	uint8_t v1;
	uint8_t v2;

	assert(p != NULL);

	dac_value = vcom_calculate(p->cal, mv);

	if (dac_value < HVPMIC_DAC_MIN)
		dac_value = HVPMIC_DAC_MIN;
	else if (dac_value > HVPMIC_DAC_MAX)
		dac_value = HVPMIC_DAC_MAX;

	v1 = dac_value & 0x00FF;
	v2 = ((dac_value >> 8) & 0x0001);

	if (pl_i2c_reg_write_8(*p->i2c, p->i2c_addr, HVPMIC_REG_VCOM1, v1))
	    return -1;

	return pl_i2c_reg_write_8(*p->i2c, p->i2c_addr, HVPMIC_REG_VCOM2, v2);
}