A small USV for ALIX boards with i2c support
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
2.8KB

  1. /*
  2. * config file:
  3. * - i2c device
  4. * - i2c address
  5. * - email-address
  6. * - reporting config (when logging / mailing)
  7. * - thresholds for do shutdown
  8. *
  9. * parameters:
  10. * -d run as daemon
  11. * -f foreground
  12. * -v debug
  13. * -c [idle|charge|test|poweroff] command (not with -d)
  14. * --config
  15. * --help
  16. *
  17. * in command mode try to use daemon first (via unix-socket)
  18. * then fallback to i2c
  19. */
  20. #include <stdint.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include "i2c-dev.h"
  30. enum {
  31. REG_STATUS = 0x00,
  32. REG_CURRENT = 0x10,
  33. REG_UBAT = 0x11,
  34. REG_UIN = 0x12,
  35. REG_UIN_LOSS = 0x20,
  36. REG_UIN_RESTORE = 0x21,
  37. REG_UBAT_FULL = 0x22,
  38. REG_UBAT_LOW = 0x23,
  39. REG_UBAT_CRIT = 0x24,
  40. REG_IBAT_FULL = 0x25,
  41. REG_CRC = 0x26,
  42. };
  43. struct usv_data {
  44. uint16_t sys_state;
  45. int16_t adc_current;
  46. int16_t adc_ubat;
  47. int16_t adc_uin;
  48. int16_t uin_loss;
  49. int16_t uin_restore;
  50. int16_t ubat_full;
  51. int16_t ubat_low;
  52. int16_t ubat_critical;
  53. int16_t ibat_full;
  54. uint16_t crc16;
  55. };
  56. enum {
  57. STATE_IDLE = 0x01,
  58. STATE_TEST = 0x02,
  59. STATE_CHARGE = 0x04,
  60. STATE_DISCHARGE = 0x08,
  61. STATE_POWEROFF = 0x10,
  62. };
  63. static char * state2str(uint8_t state)
  64. {
  65. switch (state) {
  66. case STATE_IDLE:
  67. return "STATE_IDLE";
  68. case STATE_TEST:
  69. return "STATE_TEST";
  70. case STATE_CHARGE:
  71. return "STATE_CHARGE";
  72. case STATE_DISCHARGE:
  73. return "STATE_DISCHARGE";
  74. case STATE_POWEROFF:
  75. return "STATE_POWEROFF";
  76. default:
  77. return "<UNKNOWN>";
  78. }
  79. }
  80. static int i2c_open(const char *path)
  81. {
  82. int fd = open(path, O_RDWR);
  83. if (fd < 0) {
  84. perror("open()");
  85. return -1;
  86. }
  87. unsigned long funcs;
  88. if (ioctl(fd, I2C_FUNCS, &funcs)) {
  89. perror("ioctl(I2C_FUNCS)");
  90. close(fd);
  91. return -1;
  92. }
  93. if ((funcs & I2C_FUNC_SMBUS_WORD_DATA) != I2C_FUNC_SMBUS_WORD_DATA) {
  94. fprintf(stderr, "I2C_FUNC_SMBUS_WORD_DATA not supported!\n");
  95. close(fd);
  96. return -1;
  97. }
  98. return fd;
  99. }
  100. static int i2c_setaddress(int fd, int address)
  101. {
  102. if (ioctl(fd, I2C_SLAVE, address) < 0) {
  103. perror("ioctl(I2C_SLAVE)");
  104. close(fd);
  105. return -1;
  106. }
  107. return 0;
  108. }
  109. int main(int argc, char *argv[])
  110. {
  111. int fd = i2c_open("/dev/i2c-0");
  112. if (fd < 0)
  113. exit(-1);
  114. if (i2c_setaddress(fd, 0x10) < 0)
  115. exit(-1);
  116. while (1) {
  117. struct usv_data usv;
  118. memset(&usv, 0, sizeof(usv));
  119. usv.sys_state = i2c_smbus_read_word_data(fd, REG_STATUS);
  120. usv.adc_current = i2c_smbus_read_word_data(fd, REG_CURRENT);
  121. usv.adc_ubat = i2c_smbus_read_word_data(fd, REG_UBAT);
  122. usv.adc_uin = i2c_smbus_read_word_data(fd, REG_UIN);
  123. printf("state:0x%02x I:%5dmA Ubat:%5dmV Usup:%5dmV (%s) [%5d,%5d,%5d,%5d,%5d,%5d,0x%04x]\n",
  124. usv.sys_state, usv.adc_current, usv.adc_ubat,
  125. usv.adc_uin, state2str(usv.sys_state),
  126. usv.uin_loss, usv.uin_restore, usv.ubat_full,
  127. usv.ubat_low, usv.ubat_critical, usv.ibat_full,
  128. usv.crc16);
  129. sleep(1);
  130. }
  131. close(fd);
  132. return 0;
  133. }