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.

164 lines
3.6 KiB

  1. // Copyright 2022 nirim000
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "i2c_master.h"
  4. #include "pca9505.h"
  5. #include "debug.h"
  6. #define SLAVE_TO_ADDR(n) (n << 1)
  7. #define TIMEOUT 100
  8. enum {
  9. CMD_INPUT_0 = 0,
  10. CMD_INPUT_1,
  11. CMD_INPUT_2,
  12. CMD_INPUT_3,
  13. CMD_INPUT_4,
  14. CMD_OUTPUT_0 = 8,
  15. CMD_OUTPUT_1,
  16. CMD_OUTPUT_2,
  17. CMD_OUTPUT_3,
  18. CMD_OUTPUT_4,
  19. CMD_INVERSION_0 = 16,
  20. CMD_INVERSION_1,
  21. CMD_INVERSION_2,
  22. CMD_INVERSION_3,
  23. CMD_INVERSION_4,
  24. CMD_CONFIG_0 = 24,
  25. CMD_CONFIG_1,
  26. CMD_CONFIG_2,
  27. CMD_CONFIG_3,
  28. CMD_CONFIG_4,
  29. };
  30. void pca9505_init(uint8_t slave_addr) {
  31. static uint8_t s_init = 0;
  32. if (!s_init) {
  33. i2c_init();
  34. s_init = 1;
  35. }
  36. // TODO: could check device connected
  37. }
  38. bool pca9505_set_config(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) {
  39. uint8_t addr = SLAVE_TO_ADDR(slave_addr);
  40. uint8_t cmd = 0;
  41. switch (port) {
  42. case 0:
  43. cmd = CMD_CONFIG_0;
  44. break;
  45. case 1:
  46. cmd = CMD_CONFIG_1;
  47. break;
  48. case 2:
  49. cmd = CMD_CONFIG_2;
  50. break;
  51. case 3:
  52. cmd = CMD_CONFIG_3;
  53. break;
  54. case 4:
  55. cmd = CMD_CONFIG_4;
  56. break;
  57. }
  58. i2c_status_t ret = i2c_write_register(addr, cmd, &conf, sizeof(conf), TIMEOUT);
  59. if (ret != I2C_STATUS_SUCCESS) {
  60. print("pca9505_set_config::FAILED\n");
  61. return false;
  62. }
  63. return true;
  64. }
  65. bool pca9505_set_polarity(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) {
  66. uint8_t addr = SLAVE_TO_ADDR(slave_addr);
  67. uint8_t cmd = 0;
  68. switch (port) {
  69. case 0:
  70. cmd = CMD_INVERSION_0;
  71. break;
  72. case 1:
  73. cmd = CMD_INVERSION_1;
  74. break;
  75. case 2:
  76. cmd = CMD_INVERSION_2;
  77. break;
  78. case 3:
  79. cmd = CMD_INVERSION_3;
  80. break;
  81. case 4:
  82. cmd = CMD_INVERSION_4;
  83. break;
  84. }
  85. i2c_status_t ret = i2c_write_register(addr, cmd, &conf, sizeof(conf), TIMEOUT);
  86. if (ret != I2C_STATUS_SUCCESS) {
  87. print("pca9505_set_polarity::FAILED\n");
  88. return false;
  89. }
  90. return true;
  91. }
  92. bool pca9505_set_output(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) {
  93. uint8_t addr = SLAVE_TO_ADDR(slave_addr);
  94. uint8_t cmd = 0;
  95. switch (port) {
  96. case 0:
  97. cmd = CMD_OUTPUT_0;
  98. break;
  99. case 1:
  100. cmd = CMD_OUTPUT_1;
  101. break;
  102. case 2:
  103. cmd = CMD_OUTPUT_2;
  104. break;
  105. case 3:
  106. cmd = CMD_OUTPUT_3;
  107. break;
  108. case 4:
  109. cmd = CMD_OUTPUT_4;
  110. break;
  111. }
  112. i2c_status_t ret = i2c_write_register(addr, cmd, &conf, sizeof(conf), TIMEOUT);
  113. if (ret != I2C_STATUS_SUCCESS) {
  114. print("pca9505_set_output::FAILED\n");
  115. return false;
  116. }
  117. return true;
  118. }
  119. bool pca9505_readPins(uint8_t slave_addr, pca9505_port_t port, uint8_t* out) {
  120. uint8_t addr = SLAVE_TO_ADDR(slave_addr);
  121. uint8_t cmd = 0;
  122. switch (port) {
  123. case 0:
  124. cmd = CMD_INPUT_0;
  125. break;
  126. case 1:
  127. cmd = CMD_INPUT_1;
  128. break;
  129. case 2:
  130. cmd = CMD_INPUT_2;
  131. break;
  132. case 3:
  133. cmd = CMD_INPUT_3;
  134. break;
  135. case 4:
  136. cmd = CMD_INPUT_4;
  137. break;
  138. }
  139. i2c_status_t ret = i2c_read_register(addr, cmd, out, sizeof(uint8_t), TIMEOUT);
  140. if (ret != I2C_STATUS_SUCCESS) {
  141. print("pca9505_readPins::FAILED\n");
  142. return false;
  143. }
  144. return true;
  145. }