Skip to content

Commit

Permalink
I2C driver cleanup (qmk#21273)
Browse files Browse the repository at this point in the history
* remove i2c_start and i2c_stop from i2c drivers

* remove static i2c_address variable from chibios i2c driver
  • Loading branch information
infinityis authored and nuess0r committed Sep 8, 2024
1 parent de0af0e commit 9032b12
Show file tree
Hide file tree
Showing 49 changed files with 288 additions and 611 deletions.
36 changes: 17 additions & 19 deletions docs/i2c_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,23 +138,6 @@ void i2c_init(void) {

---

### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)` :id=api-i2c-start

Start an I2C transaction.

#### Arguments :id=api-i2c-start-arguments

- `uint8_t address`
The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.

#### Return Value :id=api-i2c-start-return

`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.

---

### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit

Send multiple bytes to the selected I2C device.
Expand Down Expand Up @@ -285,6 +268,21 @@ Reads from a register with a 16-bit address (big endian) on the I2C device.

---

### `i2c_status_t i2c_stop(void)` :id=api-i2c-stop
### `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout)` :id=api-i2c-ping-address

Stop the current I2C transaction.
Pings the I2C bus for a specific address.

On ChibiOS a "best effort" attempt is made by reading a single byte from register 0 at the requested address. This should generally work except for I2C devices that do not not respond to a register 0 read request, which will result in a false negative result (unsucessful response to ping attempt).

This function is weakly defined, meaning it can be overridden if necessary for your particular use case:

#### Arguments

- `uint8_t address`
The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.

#### Return Value

`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
3 changes: 1 addition & 2 deletions docs/ja/i2c_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ I2C アドレスと他の技術詳細について、さらなる情報を得る
| 関数 | 説明 |
|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `void i2c_init(void);` | I2C ドライバを初期化します。他のあらゆるトランザクションを開始する前に、この関数を一度だけ呼ぶ必要があります。 |
| `i2c_status_t i2c_start(uint8_t address, uint16_t timeout);` | I2C トランザクションを開始します。アドレスは方向ビットのない7ビットスレーブアドレスです。 |
| `i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを送信します。アドレスは方向ビットのない7ビットスレーブアドレスです。トランザクションのステータスを返します。 |
| `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを受信します。アドレスは方向ビットのない7ビットスレーブアドレスです。 `length` で指定した長さのバイト列を `data` に保存し、トランザクションのステータスを返します。 |
| `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_transmit` と同様ですが、 `regaddr` でスレーブのデータ書き込み先のレジスタを指定します。 |
| `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_receive` と同様ですが、 `regaddr` でスレーブのデータ読み込み先のレジスタを指定します。 |
| `i2c_status_t i2c_stop(void);` | I2C トランザクションを終了します。 |
| `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);` | I2C アドレスをテストします。アドレスは方向ビットのない7ビットスレーブアドレスです。 |

### 関数の戻り値 :id=function-return

Expand Down
2 changes: 0 additions & 2 deletions drivers/gpio/pca9505.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ void pca9505_init(uint8_t slave_addr) {
}

// TODO: could check device connected
// i2c_start(SLAVE_TO_ADDR(slave) | I2C_WRITE);
// i2c_stop();
}

bool pca9505_set_config(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) {
Expand Down
2 changes: 0 additions & 2 deletions drivers/gpio/pca9555.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ void pca9555_init(uint8_t slave_addr) {
}

// TODO: could check device connected
// i2c_start(SLAVE_TO_ADDR(slave) | I2C_WRITE);
// i2c_stop();
}

bool pca9555_set_config(uint8_t slave_addr, pca9555_port_t port, uint8_t conf) {
Expand Down
7 changes: 1 addition & 6 deletions drivers/oled/oled_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,8 @@ __attribute__((weak)) bool oled_send_cmd_P(const uint8_t *data, uint16_t size) {
spi_stop();
return (status >= 0);
# elif defined(OLED_TRANSPORT_I2C)
i2c_status_t status = i2c_start((OLED_DISPLAY_ADDRESS << 1) | I2C_WRITE, OLED_I2C_TIMEOUT);

for (uint16_t i = 0; i < size && status >= 0; i++) {
status = i2c_write(pgm_read_byte((const char *)data++), OLED_I2C_TIMEOUT);
}

i2c_stop();
i2c_status_t status = i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), data, size, OLED_I2C_TIMEOUT);

return (status == I2C_STATUS_SUCCESS);
# endif
Expand Down
8 changes: 2 additions & 6 deletions drivers/painter/comms/qp_comms_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,14 @@ bool qp_comms_i2c_init(painter_device_t device) {
}

bool qp_comms_i2c_start(painter_device_t device) {
painter_driver_t * driver = (painter_driver_t *)device;
qp_comms_i2c_config_t *comms_config = (qp_comms_i2c_config_t *)driver->comms_config;
return i2c_start(comms_config->chip_address << 1) == I2C_STATUS_SUCCESS;
return true;
}

uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
return qp_comms_i2c_send_raw(device, data, byte_count);
}

void qp_comms_i2c_stop(painter_device_t device) {
i2c_stop();
}
void qp_comms_i2c_stop(painter_device_t device) {}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Command+Data I2C support
Expand Down
2 changes: 0 additions & 2 deletions drivers/sensors/cirque_pinnacle_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
pd_dprintf("error cirque_pinnacle i2c_read_register\n");
touchpad_init = false;
}
i2c_stop();
}
}

Expand All @@ -32,6 +31,5 @@ void RAP_Write(uint8_t address, uint8_t data) {
pd_dprintf("error cirque_pinnacle i2c_write_register\n");
touchpad_init = false;
}
i2c_stop();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static uint16_t i2c_timeout_timer;

void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
uint8_t data[] = {0x00, red, green, blue, white};
i2c_transmit(TRACKBALL_WRITE, data, sizeof(data), I2C_TIMEOUT);
i2c_transmit(TRACKBALL_ADDRESS, data, sizeof(data), I2C_TIMEOUT);
}

int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) {
Expand Down Expand Up @@ -120,7 +120,7 @@ bool pointing_device_task(void) {
static uint16_t debounce_timer;
uint8_t state[5] = {};
if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) {
if (i2c_read_register(TRACKBALL_WRITE, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
if (i2c_read_register(TRACKBALL_ADDRESS, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
if (!state[4] && !debounce) {
if (scrolling) {
#ifdef PIMORONI_TRACKBALL_INVERT_X
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
#include "pointing_device.h"

#ifndef TRACKBALL_ADDRESS
# define TRACKBALL_ADDRESS 0x0A
# define TRACKBALL_ADDRESS (0x0A << 1)
#endif
#define TRACKBALL_WRITE ((TRACKBALL_ADDRESS << 1) | I2C_WRITE)
#define TRACKBALL_READ ((TRACKBALL_ADDRESS << 1) | I2C_READ)

void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
void trackball_check_click(bool pressed, report_mouse_t *mouse);
Expand Down
47 changes: 15 additions & 32 deletions keyboards/bajjak/bajjak.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,23 +137,16 @@ uint8_t init_mcp23018(void) {
// - unused : input : 1
// - input : input : 1
// - driving : output : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(IODIRA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00111111, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
i2c_stop();

// set pull-up
// - unused : on : 1
// - input : on : 1
// - driving : off : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPPUA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b01111111, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;

out:
i2c_stop();
uint8_t data[] = {0b00000000, 0b00111111};
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);

if (!mcp23018_status) {
// set pull-up
// - unused : on : 1
// - input : on : 1
// - driving : off : 0
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);
}

#ifdef LEFT_LEDS
if (!mcp23018_status) mcp23018_status = bajjak_left_leds_update();
Expand All @@ -176,21 +169,11 @@ uint8_t bajjak_left_leds_update(void) {
// - unused : hi-Z : 1
// - input : hi-Z : 1
// - driving : hi-Z : 1
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(OLATA, BAJJAK_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b11111111
& ~(bajjak_left_led_1<<LEFT_LED_1_SHIFT),
BAJJAK_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b11111111
& ~(bajjak_left_led_2<<LEFT_LED_2_SHIFT),
BAJJAK_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;

out:
i2c_stop();
uint8_t data[2];
data[0] = 0b11111111 & ~(bajjak_left_led_1<<LEFT_LED_1_SHIFT);
data[1] = 0b11111111 & ~(bajjak_left_led_2<<LEFT_LED_2_SHIFT);
mcp23018_status = i2c_writeReg(I2C_ADDR, OLATA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);

return mcp23018_status;
}
#endif
Expand Down
4 changes: 1 addition & 3 deletions keyboards/bajjak/bajjak.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "i2c_master.h"

// I2C aliases and register addresses (see "mcp23018.md")
#define I2C_ADDR 0b0100000
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
#define I2C_ADDR (0b0100000<<1)
#define IODIRA 0x00 // i/o direction register
#define IODIRB 0x01
#define GPPUA 0x0C // GPIO pull-up resistor register
Expand Down
16 changes: 5 additions & 11 deletions keyboards/bajjak/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,7 @@ static matrix_row_t read_cols(uint8_t row) {
uint8_t data = 0;
// reading GPIOB (column port) since in mcp23018's sequential mode
// it is addressed directly after writing to GPIOA in select_row()
mcp23018_status = i2c_start(I2C_ADDR_READ, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_read_nack(BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
data = ~((uint8_t)mcp23018_status);
mcp23018_status = I2C_STATUS_SUCCESS;
out:
i2c_stop();
mcp23018_status = i2c_receive(I2C_ADDR, &data, 1, BAJJAK_EZ_I2C_TIMEOUT);
return data;
}
} else {
Expand Down Expand Up @@ -195,11 +190,10 @@ static void select_row(uint8_t row) {
if (!mcp23018_status) {
// set active row low : 0
// set other rows hi-Z : 1
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPIOA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0xFF & ~(1 << row), BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
out:
i2c_stop();
uint8_t data;
data = 0xFF & ~(1 << row);
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, BAJJAK_EZ_I2C_TIMEOUT);

}
} else {
// select on teensy
Expand Down
36 changes: 6 additions & 30 deletions keyboards/dc01/left/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,37 +387,13 @@ static void unselect_cols(void)

// Complete rows from other modules over i2c
i2c_status_t i2c_transaction(uint8_t address, uint32_t mask, uint8_t col_offset) {
i2c_status_t status = i2c_start(address, 5);
if (status < 0) {
goto error;
}

status = i2c_write(0x01, 50);
if (status < 0) {
goto error;
}

status = i2c_start(address | I2C_READ, 50);
uint8_t data[MATRIX_ROWS + 1];
i2c_status_t status = i2c_readReg(address, 0x01, data, (MATRIX_ROWS + 1), 5);

status = i2c_read_ack(50);
if (status != 0x55) { //synchronization byte
goto error;
for (uint8_t i = 0; i < (MATRIX_ROWS) && status >= 0; i++) { //assemble slave matrix in main matrix
matrix[i] &= mask; //mask bits to keep
matrix[i] |= ((uint32_t)data[i+1] << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
}

for (uint8_t i = 0; i < MATRIX_ROWS-1 && status >= 0; i++) { //assemble slave matrix in main matrix
matrix[i] &= mask; //mask bits to keep
status = i2c_read_ack(50);
matrix[i] |= ((uint32_t)status << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
}
//last read request must be followed by a NACK
if (status >= 0) {
matrix[MATRIX_ROWS - 1] &= mask; //mask bits to keep
status = i2c_read_nack(50);
matrix[MATRIX_ROWS - 1] |= ((uint32_t)status << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
}

error:
i2c_stop();

return (status < 0) ? status : I2C_STATUS_SUCCESS;
return status;
}
51 changes: 15 additions & 36 deletions keyboards/ergodox_ez/ergodox_ez.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,31 +155,16 @@ uint8_t init_mcp23018(void) {
// - unused : input : 1
// - input : input : 1
// - driving : output : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
i2c_stop();

// set pull-up
// - unused : on : 1
// - input : on : 1
// - driving : off : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;

out:
i2c_stop();
uint8_t data[] = {0b00000000, 0b00111111};
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);

if (!mcp23018_status) {
// set pull-up
// - unused : on : 1
// - input : on : 1
// - driving : off : 0
mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
}

#ifdef LEFT_LEDS
if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update();
Expand All @@ -203,17 +188,11 @@ uint8_t ergodox_left_leds_update(void) {
// - unused : hi-Z : 1
// - input : hi-Z : 1
// - driving : hi-Z : 1
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(OLATA, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT), ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b11111111 & ~(ergodox_left_led_2 << LEFT_LED_2_SHIFT) & ~(ergodox_left_led_1 << LEFT_LED_1_SHIFT), ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;

out:
i2c_stop();
uint8_t data[2];
data[0] = 0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT);
data[1] = 0b11111111 & ~(ergodox_left_led_2 << LEFT_LED_2_SHIFT) & ~(ergodox_left_led_1 << LEFT_LED_1_SHIFT);
mcp23018_status = i2c_writeReg(I2C_ADDR, OLATA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);

return mcp23018_status;
}
#endif
Expand Down
4 changes: 1 addition & 3 deletions keyboards/ergodox_ez/ergodox_ez.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "i2c_master.h"

// I2C aliases and register addresses (see "mcp23018.md")
#define I2C_ADDR 0b0100000
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
#define I2C_ADDR (0b0100000<<1)
#define IODIRA 0x00 // i/o direction register
#define IODIRB 0x01
#define GPPUA 0x0C // GPIO pull-up resistor register
Expand Down
Loading

0 comments on commit 9032b12

Please sign in to comment.