Parent directory

pca9505.c

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