alix-usv/Host/i2c-test.c

176 lines
3.0 KiB
C

/*
* config file:
* - i2c device
* - i2c address
* - email-address
* - reporting config (when logging / mailing)
* - thresholds for do shutdown
*
* parameters:
* -d run as daemon
* -f foreground
* -v debug
* -c [idle|charge|test|poweroff] command (not with -d)
* --config
* --help
*
* in command mode try to use daemon first (via unix-socket)
* then fallback to i2c
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
struct read_data {
uint8_t sys_state;
int16_t adc_current;
int16_t adc_ubat;
int16_t adc_uin;
int16_t uin_loss;
int16_t uin_restore;
int16_t ubat_full;
int16_t ubat_low;
int16_t ubat_critical;
int16_t ibat_full;
uint16_t crc16;
} __attribute__((__packed__));
struct write_data {
uint8_t sys_state;
int16_t uin_loss;
int16_t uin_restore;
int16_t ubat_full;
int16_t ubat_low;
int16_t ubat_critical;
int16_t ibat_full;
uint16_t crc16;
} __attribute__((__packed__));
enum {
STATE_IDLE = 0x01,
STATE_TEST = 0x02,
STATE_CHARGE = 0x04,
STATE_DISCHARGE = 0x08,
STATE_POWEROFF = 0x10,
};
static char * state2str(uint8_t state)
{
switch (state) {
case STATE_IDLE:
return "STATE_IDLE";
case STATE_TEST:
return "STATE_TEST";
case STATE_CHARGE:
return "STATE_CHARGE";
case STATE_DISCHARGE:
return "STATE_DISCHARGE";
case STATE_POWEROFF:
return "STATE_POWEROFF";
default:
return "<UNKNOWN>";
}
}
static int i2c_open(const char *path)
{
int fd = open(path, O_RDWR);
if (fd < 0) {
perror("open()");
return -1;
}
unsigned long funcs;
if (ioctl(fd, I2C_FUNCS, &funcs)) {
perror("ioctl(I2C_FUNCS)");
close(fd);
return -1;
}
if (!(funcs & I2C_FUNC_I2C)) {
fprintf(stderr, "I2C_FUNC_I2C not supported!\n");
close(fd);
return -1;
}
return fd;
}
static int i2c_setaddress(int fd, int address)
{
if (ioctl(fd, I2C_SLAVE, address) < 0) {
perror("ioctl(I2C_SLAVE)");
close(fd);
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
int fd = i2c_open("/dev/i2c-0");
if (fd < 0)
exit(-1);
if (i2c_setaddress(fd, 0x10) < 0)
exit(-1);
int cnt = 0;
while (1) {
struct read_data rdbuf;
memset(&rdbuf, 0, sizeof(rdbuf));
int ret = read(fd, &rdbuf, sizeof(rdbuf));
if (ret <= 0)
perror("read()");
printf("state:0x%02x I:%5dmA Ubat:%5dmV Usup:%5dmV (%s) [%5d,%5d,%5d,%5d,%5d,%5d,0x%04x]\n",
rdbuf.sys_state, rdbuf.adc_current, rdbuf.adc_ubat,
rdbuf.adc_uin, state2str(rdbuf.sys_state),
rdbuf.uin_loss, rdbuf.uin_restore, rdbuf.ubat_full,
rdbuf.ubat_low, rdbuf.ubat_critical, rdbuf.ibat_full,
rdbuf.crc16);
sleep(1);
cnt++;
if (cnt == 5) {
struct write_data wrbuf = {
.sys_state = STATE_CHARGE,
.uin_loss = 12000,
.uin_restore = 14000,
.ubat_full = 13300,
.ubat_low = 12000,
.ubat_critical = 10800,
.ibat_full = 150,
.crc16 = 0x0000,
};
// write (fd, &wrbuf, sizeof(wrbuf));
write (fd, &wrbuf, 1);
}
}
close(fd);
return 0;
}