summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hoelscher <infinityis@users.noreply.github.com>2024-01-17 07:05:38 -0600
committerGitHub <noreply@github.com>2024-01-17 14:05:38 +0100
commite9bd7d7ad308f9c72c86863bf9f19382c7e2d892 (patch)
treec46ce87aaa57b8f49dc0a2b56527f0bc606038ab
parent2b0965944d9065daa65cd25540cf2dd007f23eda (diff)
I2C driver cleanup (#21273)
* remove i2c_start and i2c_stop from i2c drivers * remove static i2c_address variable from chibios i2c driver
-rw-r--r--docs/i2c_driver.md36
-rw-r--r--docs/ja/i2c_driver.md3
-rw-r--r--drivers/gpio/pca9505.c2
-rw-r--r--drivers/gpio/pca9555.c2
-rw-r--r--drivers/oled/oled_driver.c7
-rw-r--r--drivers/painter/comms/qp_comms_i2c.c8
-rw-r--r--drivers/sensors/cirque_pinnacle_i2c.c2
-rw-r--r--keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.c4
-rw-r--r--keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.h4
-rw-r--r--keyboards/bajjak/bajjak.c47
-rw-r--r--keyboards/bajjak/bajjak.h4
-rw-r--r--keyboards/bajjak/matrix.c16
-rw-r--r--keyboards/dc01/left/matrix.c36
-rw-r--r--keyboards/ergodox_ez/ergodox_ez.c51
-rw-r--r--keyboards/ergodox_ez/ergodox_ez.h4
-rw-r--r--keyboards/ergodox_ez/led_i2c.c27
-rw-r--r--keyboards/ergodox_ez/matrix.c17
-rw-r--r--keyboards/ferris/0_2/matrix.c24
-rw-r--r--keyboards/gboards/ergotaco/ergotaco.c28
-rw-r--r--keyboards/gboards/ergotaco/ergotaco.h5
-rw-r--r--keyboards/gboards/ergotaco/matrix.c18
-rw-r--r--keyboards/gboards/georgi/georgi.c26
-rw-r--r--keyboards/gboards/georgi/georgi.h5
-rw-r--r--keyboards/gboards/georgi/matrix.c17
-rw-r--r--keyboards/gboards/gergo/gergo.c24
-rw-r--r--keyboards/gboards/gergo/gergo.h5
-rw-r--r--keyboards/gboards/gergo/matrix.c20
-rw-r--r--keyboards/gboards/gergoplex/gergoplex.c34
-rw-r--r--keyboards/gboards/gergoplex/gergoplex.h4
-rw-r--r--keyboards/gboards/gergoplex/matrix.c28
-rw-r--r--keyboards/handwired/d48/ds1307.c1
-rw-r--r--keyboards/handwired/frenchdev/frenchdev.c27
-rw-r--r--keyboards/handwired/frenchdev/frenchdev.h4
-rw-r--r--keyboards/handwired/frenchdev/matrix.c28
-rw-r--r--keyboards/handwired/onekey/keymaps/i2c_scanner/keymap.c15
-rw-r--r--keyboards/handwired/pterodactyl/matrix.c83
-rw-r--r--keyboards/hotdox/left.c34
-rw-r--r--keyboards/hotdox/left.h7
-rw-r--r--keyboards/ingrained/matrix.c14
-rw-r--r--keyboards/kagizaraya/chidori/board.c3
-rw-r--r--keyboards/nek_type_a/nek_type_a.h4
-rw-r--r--keyboards/system76/launch_1/usb_mux.c77
-rw-r--r--keyboards/ymdk/sp64/matrix.c4
-rw-r--r--keyboards/ymdk/sp64/sp64.c6
-rw-r--r--keyboards/ymdk/sp64/sp64.h4
-rw-r--r--platforms/avr/drivers/i2c_master.c31
-rw-r--r--platforms/avr/drivers/i2c_master.h7
-rw-r--r--platforms/chibios/drivers/i2c_master.c39
-rw-r--r--platforms/chibios/drivers/i2c_master.h3
49 files changed, 288 insertions, 611 deletions
diff --git a/docs/i2c_driver.md b/docs/i2c_driver.md
index 2457e8e7b9..868715a62c 100644
--- a/docs/i2c_driver.md
+++ b/docs/i2c_driver.md
@@ -138,23 +138,6 @@ void i2c_init(void) {
138 138
139--- 139---
140 140
141### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)` :id=api-i2c-start
142
143Start an I2C transaction.
144
145#### Arguments :id=api-i2c-start-arguments
146
147 - `uint8_t address`
148 The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
149 - `uint16_t timeout`
150 The time in milliseconds to wait for a response from the target device.
151
152#### Return Value :id=api-i2c-start-return
153
154`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
155
156---
157
158### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit 141### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit
159 142
160Send multiple bytes to the selected I2C device. 143Send multiple bytes to the selected I2C device.
@@ -285,6 +268,21 @@ Reads from a register with a 16-bit address (big endian) on the I2C device.
285 268
286--- 269---
287 270
288### `i2c_status_t i2c_stop(void)` :id=api-i2c-stop 271### `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout)` :id=api-i2c-ping-address
289 272
290Stop the current I2C transaction. 273Pings the I2C bus for a specific address.
274
275On 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).
276
277This function is weakly defined, meaning it can be overridden if necessary for your particular use case:
278
279#### Arguments
280
281 - `uint8_t address`
282 The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
283 - `uint16_t timeout`
284 The time in milliseconds to wait for a response from the target device.
285
286#### Return Value
287
288`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
diff --git a/docs/ja/i2c_driver.md b/docs/ja/i2c_driver.md
index 1d8f70e163..92c4185370 100644
--- a/docs/ja/i2c_driver.md
+++ b/docs/ja/i2c_driver.md
@@ -23,12 +23,11 @@ I2C アドレスと他の技術詳細について、さらなる情報を得る
23| 関数 | 説明 | 23| 関数 | 説明 |
24|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 24|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
25| `void i2c_init(void);` | I2C ドライバを初期化します。他のあらゆるトランザクションを開始する前に、この関数を一度だけ呼ぶ必要があります。 | 25| `void i2c_init(void);` | I2C ドライバを初期化します。他のあらゆるトランザクションを開始する前に、この関数を一度だけ呼ぶ必要があります。 |
26| `i2c_status_t i2c_start(uint8_t address, uint16_t timeout);` | I2C トランザクションを開始します。アドレスは方向ビットのない7ビットスレーブアドレスです。 |
27| `i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを送信します。アドレスは方向ビットのない7ビットスレーブアドレスです。トランザクションのステータスを返します。 | 26| `i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを送信します。アドレスは方向ビットのない7ビットスレーブアドレスです。トランザクションのステータスを返します。 |
28| `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを受信します。アドレスは方向ビットのない7ビットスレーブアドレスです。 `length` で指定した長さのバイト列を `data` に保存し、トランザクションのステータスを返します。 | 27| `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを受信します。アドレスは方向ビットのない7ビットスレーブアドレスです。 `length` で指定した長さのバイト列を `data` に保存し、トランザクションのステータスを返します。 |
29| `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_transmit` と同様ですが、 `regaddr` でスレーブのデータ書き込み先のレジスタを指定します。 | 28| `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_transmit` と同様ですが、 `regaddr` でスレーブのデータ書き込み先のレジスタを指定します。 |
30| `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_receive` と同様ですが、 `regaddr` でスレーブのデータ読み込み先のレジスタを指定します。 | 29| `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_receive` と同様ですが、 `regaddr` でスレーブのデータ読み込み先のレジスタを指定します。 |
31| `i2c_status_t i2c_stop(void);` | I2C トランザクションを終了します。 | 30| `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);` | I2C アドレスをテストします。アドレスは方向ビットのない7ビットスレーブアドレスです。 |
32 31
33### 関数の戻り値 :id=function-return 32### 関数の戻り値 :id=function-return
34 33
diff --git a/drivers/gpio/pca9505.c b/drivers/gpio/pca9505.c
index 4a11724ecf..5617a14a8b 100644
--- a/drivers/gpio/pca9505.c
+++ b/drivers/gpio/pca9505.c
@@ -41,8 +41,6 @@ void pca9505_init(uint8_t slave_addr) {
41 } 41 }
42 42
43 // TODO: could check device connected 43 // TODO: could check device connected
44 // i2c_start(SLAVE_TO_ADDR(slave) | I2C_WRITE);
45 // i2c_stop();
46} 44}
47 45
48bool pca9505_set_config(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) { 46bool pca9505_set_config(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) {
diff --git a/drivers/gpio/pca9555.c b/drivers/gpio/pca9555.c
index 23727d21b3..0fc30099ac 100644
--- a/drivers/gpio/pca9555.c
+++ b/drivers/gpio/pca9555.c
@@ -29,8 +29,6 @@ void pca9555_init(uint8_t slave_addr) {
29 } 29 }
30 30
31 // TODO: could check device connected 31 // TODO: could check device connected
32 // i2c_start(SLAVE_TO_ADDR(slave) | I2C_WRITE);
33 // i2c_stop();
34} 32}
35 33
36bool pca9555_set_config(uint8_t slave_addr, pca9555_port_t port, uint8_t conf) { 34bool pca9555_set_config(uint8_t slave_addr, pca9555_port_t port, uint8_t conf) {
diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c
index c674675d11..8cca41394f 100644
--- a/drivers/oled/oled_driver.c
+++ b/drivers/oled/oled_driver.c
@@ -223,13 +223,8 @@ __attribute__((weak)) bool oled_send_cmd_P(const uint8_t *data, uint16_t size) {
223 spi_stop(); 223 spi_stop();
224 return (status >= 0); 224 return (status >= 0);
225# elif defined(OLED_TRANSPORT_I2C) 225# elif defined(OLED_TRANSPORT_I2C)
226 i2c_status_t status = i2c_start((OLED_DISPLAY_ADDRESS << 1) | I2C_WRITE, OLED_I2C_TIMEOUT);
227 226
228 for (uint16_t i = 0; i < size && status >= 0; i++) { 227 i2c_status_t status = i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), data, size, OLED_I2C_TIMEOUT);
229 status = i2c_write(pgm_read_byte((const char *)data++), OLED_I2C_TIMEOUT);
230 }
231
232 i2c_stop();
233 228
234 return (status == I2C_STATUS_SUCCESS); 229 return (status == I2C_STATUS_SUCCESS);
235# endif 230# endif
diff --git a/drivers/painter/comms/qp_comms_i2c.c b/drivers/painter/comms/qp_comms_i2c.c
index ec45ddfb3b..93f503f3dd 100644
--- a/drivers/painter/comms/qp_comms_i2c.c
+++ b/drivers/painter/comms/qp_comms_i2c.c
@@ -28,18 +28,14 @@ bool qp_comms_i2c_init(painter_device_t device) {
28} 28}
29 29
30bool qp_comms_i2c_start(painter_device_t device) { 30bool qp_comms_i2c_start(painter_device_t device) {
31 painter_driver_t * driver = (painter_driver_t *)device; 31 return true;
32 qp_comms_i2c_config_t *comms_config = (qp_comms_i2c_config_t *)driver->comms_config;
33 return i2c_start(comms_config->chip_address << 1) == I2C_STATUS_SUCCESS;
34} 32}
35 33
36uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint32_t byte_count) { 34uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
37 return qp_comms_i2c_send_raw(device, data, byte_count); 35 return qp_comms_i2c_send_raw(device, data, byte_count);
38} 36}
39 37
40void qp_comms_i2c_stop(painter_device_t device) { 38void qp_comms_i2c_stop(painter_device_t device) {}
41 i2c_stop();
42}
43 39
44//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45// Command+Data I2C support 41// Command+Data I2C support
diff --git a/drivers/sensors/cirque_pinnacle_i2c.c b/drivers/sensors/cirque_pinnacle_i2c.c
index c9b9bece5f..a3622e9d60 100644
--- a/drivers/sensors/cirque_pinnacle_i2c.c
+++ b/drivers/sensors/cirque_pinnacle_i2c.c
@@ -19,7 +19,6 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
19 pd_dprintf("error cirque_pinnacle i2c_read_register\n"); 19 pd_dprintf("error cirque_pinnacle i2c_read_register\n");
20 touchpad_init = false; 20 touchpad_init = false;
21 } 21 }
22 i2c_stop();
23 } 22 }
24} 23}
25 24
@@ -32,6 +31,5 @@ void RAP_Write(uint8_t address, uint8_t data) {
32 pd_dprintf("error cirque_pinnacle i2c_write_register\n"); 31 pd_dprintf("error cirque_pinnacle i2c_write_register\n");
33 touchpad_init = false; 32 touchpad_init = false;
34 } 33 }
35 i2c_stop();
36 } 34 }
37} 35}
diff --git a/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.c b/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.c
index 35a85b5476..0db58bfabd 100644
--- a/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.c
+++ b/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.c
@@ -38,7 +38,7 @@ static uint16_t i2c_timeout_timer;
38 38
39void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) { 39void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
40 uint8_t data[] = {0x00, red, green, blue, white}; 40 uint8_t data[] = {0x00, red, green, blue, white};
41 i2c_transmit(TRACKBALL_WRITE, data, sizeof(data), I2C_TIMEOUT); 41 i2c_transmit(TRACKBALL_ADDRESS, data, sizeof(data), I2C_TIMEOUT);
42} 42}
43 43
44int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) { 44int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) {
@@ -120,7 +120,7 @@ bool pointing_device_task(void) {
120 static uint16_t debounce_timer; 120 static uint16_t debounce_timer;
121 uint8_t state[5] = {}; 121 uint8_t state[5] = {};
122 if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) { 122 if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) {
123 if (i2c_read_register(TRACKBALL_WRITE, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) { 123 if (i2c_read_register(TRACKBALL_ADDRESS, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
124 if (!state[4] && !debounce) { 124 if (!state[4] && !debounce) {
125 if (scrolling) { 125 if (scrolling) {
126#ifdef PIMORONI_TRACKBALL_INVERT_X 126#ifdef PIMORONI_TRACKBALL_INVERT_X
diff --git a/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.h b/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.h
index cfcd5a47a1..ca2559bec7 100644
--- a/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.h
+++ b/keyboards/3w6/rev2/keymaps/default_pimoroni/pimoroni_trackball.h
@@ -20,10 +20,8 @@
20#include "pointing_device.h" 20#include "pointing_device.h"
21 21
22#ifndef TRACKBALL_ADDRESS 22#ifndef TRACKBALL_ADDRESS
23# define TRACKBALL_ADDRESS 0x0A 23# define TRACKBALL_ADDRESS (0x0A << 1)
24#endif 24#endif
25#define TRACKBALL_WRITE ((TRACKBALL_ADDRESS << 1) | I2C_WRITE)
26#define TRACKBALL_READ ((TRACKBALL_ADDRESS << 1) | I2C_READ)
27 25
28void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white); 26void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
29void trackball_check_click(bool pressed, report_mouse_t *mouse); 27void trackball_check_click(bool pressed, report_mouse_t *mouse);
diff --git a/keyboards/bajjak/bajjak.c b/keyboards/bajjak/bajjak.c
index 74e2b2aa8c..e6102e817b 100644
--- a/keyboards/bajjak/bajjak.c
+++ b/keyboards/bajjak/bajjak.c
@@ -137,23 +137,16 @@ uint8_t init_mcp23018(void) {
137 // - unused : input : 1 137 // - unused : input : 1
138 // - input : input : 1 138 // - input : input : 1
139 // - driving : output : 0 139 // - driving : output : 0
140 mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 140 uint8_t data[] = {0b00000000, 0b00111111};
141 mcp23018_status = i2c_write(IODIRA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 141 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);
142 mcp23018_status = i2c_write(0b00000000, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 142
143 mcp23018_status = i2c_write(0b00111111, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 143 if (!mcp23018_status) {
144 i2c_stop(); 144 // set pull-up
145 145 // - unused : on : 1
146 // set pull-up 146 // - input : on : 1
147 // - unused : on : 1 147 // - driving : off : 0
148 // - input : on : 1 148 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);
149 // - driving : off : 0 149 }
150 mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
151 mcp23018_status = i2c_write(GPPUA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
152 mcp23018_status = i2c_write(0b00000000, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
153 mcp23018_status = i2c_write(0b01111111, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
154
155out:
156 i2c_stop();
157 150
158#ifdef LEFT_LEDS 151#ifdef LEFT_LEDS
159 if (!mcp23018_status) mcp23018_status = bajjak_left_leds_update(); 152 if (!mcp23018_status) mcp23018_status = bajjak_left_leds_update();
@@ -176,21 +169,11 @@ uint8_t bajjak_left_leds_update(void) {
176 // - unused : hi-Z : 1 169 // - unused : hi-Z : 1
177 // - input : hi-Z : 1 170 // - input : hi-Z : 1
178 // - driving : hi-Z : 1 171 // - driving : hi-Z : 1
179 mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); 172 uint8_t data[2];
180 if (mcp23018_status) goto out; 173 data[0] = 0b11111111 & ~(bajjak_left_led_1<<LEFT_LED_1_SHIFT);
181 mcp23018_status = i2c_write(OLATA, BAJJAK_EZ_I2C_TIMEOUT); 174 data[1] = 0b11111111 & ~(bajjak_left_led_2<<LEFT_LED_2_SHIFT);
182 if (mcp23018_status) goto out; 175 mcp23018_status = i2c_writeReg(I2C_ADDR, OLATA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);
183 mcp23018_status = i2c_write(0b11111111 176
184 & ~(bajjak_left_led_1<<LEFT_LED_1_SHIFT),
185 BAJJAK_EZ_I2C_TIMEOUT);
186 if (mcp23018_status) goto out;
187 mcp23018_status = i2c_write(0b11111111
188 & ~(bajjak_left_led_2<<LEFT_LED_2_SHIFT),
189 BAJJAK_EZ_I2C_TIMEOUT);
190 if (mcp23018_status) goto out;
191
192 out:
193 i2c_stop();
194 return mcp23018_status; 177 return mcp23018_status;
195} 178}
196#endif 179#endif
diff --git a/keyboards/bajjak/bajjak.h b/keyboards/bajjak/bajjak.h
index 52f14ad3ea..c2d2d77ef6 100644
--- a/keyboards/bajjak/bajjak.h
+++ b/keyboards/bajjak/bajjak.h
@@ -27,9 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
27#include "i2c_master.h" 27#include "i2c_master.h"
28 28
29// I2C aliases and register addresses (see "mcp23018.md") 29// I2C aliases and register addresses (see "mcp23018.md")
30#define I2C_ADDR 0b0100000 30#define I2C_ADDR (0b0100000<<1)
31#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
32#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
33#define IODIRA 0x00 // i/o direction register 31#define IODIRA 0x00 // i/o direction register
34#define IODIRB 0x01 32#define IODIRB 0x01
35#define GPPUA 0x0C // GPIO pull-up resistor register 33#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/bajjak/matrix.c b/keyboards/bajjak/matrix.c
index 20fc3c8f23..424bc29e4e 100644
--- a/keyboards/bajjak/matrix.c
+++ b/keyboards/bajjak/matrix.c
@@ -145,12 +145,7 @@ static matrix_row_t read_cols(uint8_t row) {
145 uint8_t data = 0; 145 uint8_t data = 0;
146 // reading GPIOB (column port) since in mcp23018's sequential mode 146 // reading GPIOB (column port) since in mcp23018's sequential mode
147 // it is addressed directly after writing to GPIOA in select_row() 147 // it is addressed directly after writing to GPIOA in select_row()
148 mcp23018_status = i2c_start(I2C_ADDR_READ, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 148 mcp23018_status = i2c_receive(I2C_ADDR, &data, 1, BAJJAK_EZ_I2C_TIMEOUT);
149 mcp23018_status = i2c_read_nack(BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
150 data = ~((uint8_t)mcp23018_status);
151 mcp23018_status = I2C_STATUS_SUCCESS;
152 out:
153 i2c_stop();
154 return data; 149 return data;
155 } 150 }
156 } else { 151 } else {
@@ -195,11 +190,10 @@ static void select_row(uint8_t row) {
195 if (!mcp23018_status) { 190 if (!mcp23018_status) {
196 // set active row low : 0 191 // set active row low : 0
197 // set other rows hi-Z : 1 192 // set other rows hi-Z : 1
198 mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 193 uint8_t data;
199 mcp23018_status = i2c_write(GPIOA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 194 data = 0xFF & ~(1 << row);
200 mcp23018_status = i2c_write(0xFF & ~(1 << row), BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 195 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, BAJJAK_EZ_I2C_TIMEOUT);
201 out: 196
202 i2c_stop();
203 } 197 }
204 } else { 198 } else {
205 // select on teensy 199 // select on teensy
diff --git a/keyboards/dc01/left/matrix.c b/keyboards/dc01/left/matrix.c
index d384c6a4bc..fd21d4333b 100644
--- a/keyboards/dc01/left/matrix.c
+++ b/keyboards/dc01/left/matrix.c
@@ -387,37 +387,13 @@ static void unselect_cols(void)
387 387
388// Complete rows from other modules over i2c 388// Complete rows from other modules over i2c
389i2c_status_t i2c_transaction(uint8_t address, uint32_t mask, uint8_t col_offset) { 389i2c_status_t i2c_transaction(uint8_t address, uint32_t mask, uint8_t col_offset) {
390 i2c_status_t status = i2c_start(address, 5); 390 uint8_t data[MATRIX_ROWS + 1];
391 if (status < 0) { 391 i2c_status_t status = i2c_readReg(address, 0x01, data, (MATRIX_ROWS + 1), 5);
392 goto error;
393 }
394
395 status = i2c_write(0x01, 50);
396 if (status < 0) {
397 goto error;
398 }
399
400 status = i2c_start(address | I2C_READ, 50);
401 392
402 status = i2c_read_ack(50); 393 for (uint8_t i = 0; i < (MATRIX_ROWS) && status >= 0; i++) { //assemble slave matrix in main matrix
403 if (status != 0x55) { //synchronization byte 394 matrix[i] &= mask; //mask bits to keep
404 goto error; 395 matrix[i] |= ((uint32_t)data[i+1] << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
405 } 396 }
406 397
407 for (uint8_t i = 0; i < MATRIX_ROWS-1 && status >= 0; i++) { //assemble slave matrix in main matrix 398 return status;
408 matrix[i] &= mask; //mask bits to keep
409 status = i2c_read_ack(50);
410 matrix[i] |= ((uint32_t)status << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
411 }
412 //last read request must be followed by a NACK
413 if (status >= 0) {
414 matrix[MATRIX_ROWS - 1] &= mask; //mask bits to keep
415 status = i2c_read_nack(50);
416 matrix[MATRIX_ROWS - 1] |= ((uint32_t)status << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
417 }
418
419error:
420 i2c_stop();
421
422 return (status < 0) ? status : I2C_STATUS_SUCCESS;
423} 399}
diff --git a/keyboards/ergodox_ez/ergodox_ez.c b/keyboards/ergodox_ez/ergodox_ez.c
index f088036c4a..3d6272ae66 100644
--- a/keyboards/ergodox_ez/ergodox_ez.c
+++ b/keyboards/ergodox_ez/ergodox_ez.c
@@ -155,31 +155,16 @@ uint8_t init_mcp23018(void) {
155 // - unused : input : 1 155 // - unused : input : 1
156 // - input : input : 1 156 // - input : input : 1
157 // - driving : output : 0 157 // - driving : output : 0
158 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); 158 uint8_t data[] = {0b00000000, 0b00111111};
159 if (mcp23018_status) goto out; 159 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
160 mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); 160
161 if (mcp23018_status) goto out; 161 if (!mcp23018_status) {
162 mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); 162 // set pull-up
163 if (mcp23018_status) goto out; 163 // - unused : on : 1
164 mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT); 164 // - input : on : 1
165 if (mcp23018_status) goto out; 165 // - driving : off : 0
166 i2c_stop(); 166 mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
167 167 }
168 // set pull-up
169 // - unused : on : 1
170 // - input : on : 1
171 // - driving : off : 0
172 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
173 if (mcp23018_status) goto out;
174 mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT);
175 if (mcp23018_status) goto out;
176 mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT);
177 if (mcp23018_status) goto out;
178 mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT);
179 if (mcp23018_status) goto out;
180
181out:
182 i2c_stop();
183 168
184#ifdef LEFT_LEDS 169#ifdef LEFT_LEDS
185 if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update(); 170 if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update();
@@ -203,17 +188,11 @@ uint8_t ergodox_left_leds_update(void) {
203 // - unused : hi-Z : 1 188 // - unused : hi-Z : 1
204 // - input : hi-Z : 1 189 // - input : hi-Z : 1
205 // - driving : hi-Z : 1 190 // - driving : hi-Z : 1
206 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); 191 uint8_t data[2];
207 if (mcp23018_status) goto out; 192 data[0] = 0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT);
208 mcp23018_status = i2c_write(OLATA, ERGODOX_EZ_I2C_TIMEOUT); 193 data[1] = 0b11111111 & ~(ergodox_left_led_2 << LEFT_LED_2_SHIFT) & ~(ergodox_left_led_1 << LEFT_LED_1_SHIFT);
209 if (mcp23018_status) goto out; 194 mcp23018_status = i2c_writeReg(I2C_ADDR, OLATA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
210 mcp23018_status = i2c_write(0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT), ERGODOX_EZ_I2C_TIMEOUT); 195
211 if (mcp23018_status) goto out;
212 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);
213 if (mcp23018_status) goto out;
214
215out:
216 i2c_stop();
217 return mcp23018_status; 196 return mcp23018_status;
218} 197}
219#endif 198#endif
diff --git a/keyboards/ergodox_ez/ergodox_ez.h b/keyboards/ergodox_ez/ergodox_ez.h
index befc114617..df2dbed715 100644
--- a/keyboards/ergodox_ez/ergodox_ez.h
+++ b/keyboards/ergodox_ez/ergodox_ez.h
@@ -26,9 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
26#include "i2c_master.h" 26#include "i2c_master.h"
27 27
28// I2C aliases and register addresses (see "mcp23018.md") 28// I2C aliases and register addresses (see "mcp23018.md")
29#define I2C_ADDR 0b0100000 29#define I2C_ADDR (0b0100000<<1)
30#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
31#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
32#define IODIRA 0x00 // i/o direction register 30#define IODIRA 0x00 // i/o direction register
33#define IODIRB 0x01 31#define IODIRB 0x01
34#define GPPUA 0x0C // GPIO pull-up resistor register 32#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/ergodox_ez/led_i2c.c b/keyboards/ergodox_ez/led_i2c.c
index a8802858ec..80dabf4815 100644
--- a/keyboards/ergodox_ez/led_i2c.c
+++ b/keyboards/ergodox_ez/led_i2c.c
@@ -24,30 +24,41 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
24# include "ws2812.h" 24# include "ws2812.h"
25 25
26void setleds_custom(rgb_led_t *led, uint16_t led_num) { 26void setleds_custom(rgb_led_t *led, uint16_t led_num) {
27 i2c_init(); 27 uint16_t length = 0;
28 i2c_start(0x84, ERGODOX_EZ_I2C_TIMEOUT);
29 int i = 0; 28 int i = 0;
29 int j = 0;
30# ifdef RGBW
31 int bytes_per_led = 4;
32# else
33 int bytes_per_led = 3;
34# endif
30# if defined(ERGODOX_LED_30) 35# if defined(ERGODOX_LED_30)
31 // prevent right-half code from trying to bitbang all 30 36 // prevent right-half code from trying to bitbang all 30
32 // so with 30 LEDs, we count from 29 to 15 here, and the 37 // so with 30 LEDs, we count from 29 to 15 here, and the
33 // other half does 0 to 14. 38 // other half does 0 to 14.
34 uint8_t half_led_num = RGBLIGHT_LED_COUNT / 2; 39 uint8_t half_led_num = RGBLIGHT_LED_COUNT / 2;
40 length = half_led_num * bytes_per_led;
41 uint8_t data[length];
35 for (i = half_led_num + half_led_num - 1; i >= half_led_num; --i) 42 for (i = half_led_num + half_led_num - 1; i >= half_led_num; --i)
36# elif defined(ERGODOX_LED_15_MIRROR) 43# elif defined(ERGODOX_LED_15_MIRROR)
44 length = led_num * bytes_per_led;
45 uint8_t data[length];
37 for (i = 0; i < led_num; ++i) 46 for (i = 0; i < led_num; ++i)
38# else // ERGDOX_LED_15 non-mirrored 47# else // ERGDOX_LED_15 non-mirrored
48 length = led_num * bytes_per_led;
49 uint8_t data[length];
39 for (i = led_num - 1; i >= 0; --i) 50 for (i = led_num - 1; i >= 0; --i)
40# endif 51# endif
41 { 52 {
42 uint8_t *data = (uint8_t *)(led + i); 53 uint8_t *data_byte = (uint8_t *)(led + i);
43 i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); 54 data[j++] = data_byte[0];
44 i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); 55 data[j++] = data_byte[1];
45 i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); 56 data[j++] = data_byte[2];
46#ifdef RGBW 57#ifdef RGBW
47 i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); 58 data[j++] = data_byte[3];
48#endif 59#endif
49 } 60 }
50 i2c_stop(); 61 i2c_transmit(0x84, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
51 62
52 ws2812_setleds(led, led_num); 63 ws2812_setleds(led, led_num);
53} 64}
diff --git a/keyboards/ergodox_ez/matrix.c b/keyboards/ergodox_ez/matrix.c
index e84a5e2bd3..28bee05779 100644
--- a/keyboards/ergodox_ez/matrix.c
+++ b/keyboards/ergodox_ez/matrix.c
@@ -146,13 +146,8 @@ static matrix_row_t read_cols(uint8_t row) {
146 uint8_t data = 0; 146 uint8_t data = 0;
147 // reading GPIOB (column port) since in mcp23018's sequential mode 147 // reading GPIOB (column port) since in mcp23018's sequential mode
148 // it is addressed directly after writing to GPIOA in select_row() 148 // it is addressed directly after writing to GPIOA in select_row()
149 mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 149 mcp23018_status = i2c_receive(I2C_ADDR, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
150 mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out; 150 return ~data;
151 data = ~((uint8_t)mcp23018_status);
152 mcp23018_status = I2C_STATUS_SUCCESS;
153 out:
154 i2c_stop();
155 return data;
156 } 151 }
157 } else { 152 } else {
158 /* read from teensy 153 /* read from teensy
@@ -196,11 +191,9 @@ static void select_row(uint8_t row) {
196 if (!mcp23018_status) { 191 if (!mcp23018_status) {
197 // set active row low : 0 192 // set active row low : 0
198 // set other rows hi-Z : 1 193 // set other rows hi-Z : 1
199 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 194 uint8_t data;
200 mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 195 data = 0xFF & ~(1 << row);
201 mcp23018_status = i2c_write(0xFF & ~(1 << row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 196 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
202 out:
203 i2c_stop();
204 } 197 }
205 } else { 198 } else {
206 // select on teensy 199 // select on teensy
diff --git a/keyboards/ferris/0_2/matrix.c b/keyboards/ferris/0_2/matrix.c
index af4b045eb8..cf26385f4c 100644
--- a/keyboards/ferris/0_2/matrix.c
+++ b/keyboards/ferris/0_2/matrix.c
@@ -42,9 +42,7 @@ extern i2c_status_t mcp23017_status;
42// All address pins of the mcp23017 are connected to the ground on the ferris 42// All address pins of the mcp23017 are connected to the ground on the ferris
43// | 0 | 1 | 0 | 0 | A2 | A1 | A0 | 43// | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
44// | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 44// | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
45#define I2C_ADDR 0b0100000 45#define I2C_ADDR (0b0100000 << 1)
46#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
47#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
48 46
49// Register addresses 47// Register addresses
50// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h 48// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h
@@ -77,9 +75,9 @@ uint8_t init_mcp23017(void) {
77 // - driving : output : 0 75 // - driving : output : 0
78 // This means: we will read all the bits on GPIOA 76 // This means: we will read all the bits on GPIOA
79 // This means: we will write to the pins 0-4 on GPIOB (in select_rows) 77 // This means: we will write to the pins 0-4 on GPIOB (in select_rows)
80 uint8_t buf[] = {IODIRA, 0b11111111, 0b11110000}; 78 uint8_t buf[] = {0b11111111, 0b11110000};
81 print("before transmit\n"); 79 print("before transmit\n");
82 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), MCP23017_I2C_TIMEOUT); 80 mcp23017_status = i2c_writeReg(I2C_ADDR, IODIRA, buf, sizeof(buf), MCP23017_I2C_TIMEOUT)
83 uprintf("after transmit %i\n", mcp23017_status); 81 uprintf("after transmit %i\n", mcp23017_status);
84 if (!mcp23017_status) { 82 if (!mcp23017_status) {
85 // set pull-up 83 // set pull-up
@@ -88,8 +86,7 @@ uint8_t init_mcp23017(void) {
88 // - driving : off : 0 86 // - driving : off : 0
89 // This means: we will read all the bits on GPIOA 87 // This means: we will read all the bits on GPIOA
90 // This means: we will write to the pins 0-4 on GPIOB (in select_rows) 88 // This means: we will write to the pins 0-4 on GPIOB (in select_rows)
91 uint8_t pullup_buf[] = {GPPUA, 0b11111111, 0b11110000}; 89 mcp23017_status = i2c_writeReg(I2C_ADDR, GPPUA, buf, sizeof(buf), MCP23017_I2C_TIMEOUT)
92 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, pullup_buf, sizeof(pullup_buf), MCP23017_I2C_TIMEOUT);
93 uprintf("after transmit2 %i\n", mcp23017_status); 90 uprintf("after transmit2 %i\n", mcp23017_status);
94 } 91 }
95 return mcp23017_status; 92 return mcp23017_status;
@@ -189,18 +186,13 @@ static matrix_row_t read_cols(uint8_t row) {
189 if (mcp23017_status) { // if there was an error 186 if (mcp23017_status) { // if there was an error
190 return 0; 187 return 0;
191 } else { 188 } else {
192 uint8_t buf[] = {MCP23017_GPIOA};
193 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), MCP23017_I2C_TIMEOUT);
194 // We read all the pins on GPIOA. 189 // We read all the pins on GPIOA.
195 // The initial state was all ones and any depressed key at a given column for the currently selected row will have its bit flipped to zero. 190 // The initial state was all ones and any depressed key at a given column for the currently selected row will have its bit flipped to zero.
196 // The return value is a row as represented in the generic matrix code were the rightmost bits represent the lower columns and zeroes represent non-depressed keys while ones represent depressed keys. 191 // The return value is a row as represented in the generic matrix code were the rightmost bits represent the lower columns and zeroes represent non-depressed keys while ones represent depressed keys.
197 // Since the pins connected to eact columns are sequential, and counting from zero up (col 5 -> GPIOA0, col 6 -> GPIOA1 and so on), the only transformation needed is a bitwise not to swap all zeroes and ones. 192 // Since the pins connected to eact columns are sequential, and counting from zero up (col 5 -> GPIOA0, col 6 -> GPIOA1 and so on), the only transformation needed is a bitwise not to swap all zeroes and ones.
198 uint8_t data[] = {0}; 193 uint8_t data[] = {0};
199 if (!mcp23017_status) { 194 mcp23017_status = i2c_readReg(I2C_ADDR, MCP23017_GPIOA, data, sizeof(data), MCP23017_I2C_TIMEOUT);
200 mcp23017_status = i2c_receive(I2C_ADDR_READ, data, sizeof(data), MCP23017_I2C_TIMEOUT); 195 return ~data[0];
201 data[0] = ~(data[0]);
202 }
203 return data[0];
204 } 196 }
205 } 197 }
206} 198}
@@ -244,8 +236,8 @@ static void select_row(uint8_t row) {
244 } else { 236 } else {
245 // Select the desired row by writing a byte for the entire GPIOB bus where only the bit representing the row we want to select is a zero (write instruction) and every other bit is a one. 237 // Select the desired row by writing a byte for the entire GPIOB bus where only the bit representing the row we want to select is a zero (write instruction) and every other bit is a one.
246 // Note that the row - MATRIX_ROWS_PER_SIDE reflects the fact that being on the right hand, the columns are numbered from MATRIX_ROWS_PER_SIDE to MATRIX_ROWS, but the pins we want to write to are indexed from zero up on the GPIOB bus. 238 // Note that the row - MATRIX_ROWS_PER_SIDE reflects the fact that being on the right hand, the columns are numbered from MATRIX_ROWS_PER_SIDE to MATRIX_ROWS, but the pins we want to write to are indexed from zero up on the GPIOB bus.
247 uint8_t buf[] = {MCP23017_GPIOB, 0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))}; 239 uint8_t buf[] = {0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))};
248 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT); 240 mcp23017_status = i2c_writeReg(I2C_ADDR, MCP23017_GPIOB, buf, sizeof(buf), MCP23017_I2C_TIMEOUT);
249 } 241 }
250 } 242 }
251} 243}
diff --git a/keyboards/gboards/ergotaco/ergotaco.c b/keyboards/gboards/ergotaco/ergotaco.c
index daeba1e0a6..694e07f031 100644
--- a/keyboards/gboards/ergotaco/ergotaco.c
+++ b/keyboards/gboards/ergotaco/ergotaco.c
@@ -49,23 +49,17 @@ uint8_t init_mcp23018(void) {
49 // - unused : input : 1 49 // - unused : input : 1
50 // - input : input : 1 50 // - input : input : 1
51 // - driving : output : 0 51 // - driving : output : 0
52 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 52 uint8_t data[] = {0b00000000, 0b00111111};
53 mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 53 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
54 mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 54
55 mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 55 if (!mcp23018_status) {
56 i2c_stop(); 56 // set pull-up
57 57 // - unused : on : 1
58 // set pull-up 58 // - input : on : 1
59 // - unused : on : 1 59 // - driving : off : 0
60 // - input : on : 1 60 mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
61 // - driving : off : 0 61 }
62 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 62
63 mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
64 mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
65 mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
66
67out:
68 i2c_stop();
69 // SREG=sreg_prev; 63 // SREG=sreg_prev;
70 //uprintf("Init %x\n", mcp23018_status); 64 //uprintf("Init %x\n", mcp23018_status);
71 return mcp23018_status; 65 return mcp23018_status;
diff --git a/keyboards/gboards/ergotaco/ergotaco.h b/keyboards/gboards/ergotaco/ergotaco.h
index e23fc264f4..6ab47ced74 100644
--- a/keyboards/gboards/ergotaco/ergotaco.h
+++ b/keyboards/gboards/ergotaco/ergotaco.h
@@ -11,10 +11,7 @@ extern i2c_status_t mcp23018_status;
11#define ERGODOX_EZ_I2C_TIMEOUT 1000 11#define ERGODOX_EZ_I2C_TIMEOUT 1000
12 12
13// I2C aliases and register addresses (see "mcp23018.md") 13// I2C aliases and register addresses (see "mcp23018.md")
14//#define I2C_ADDR 0b0100000 14#define I2C_ADDR (0x20<<1)
15#define I2C_ADDR 0x20
16#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
17#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
18#define IODIRA 0x00 // i/o direction register 15#define IODIRA 0x00 // i/o direction register
19#define IODIRB 0x01 16#define IODIRB 0x01
20#define GPPUA 0x0C // GPIO pull-up resistor register 17#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/gboards/ergotaco/matrix.c b/keyboards/gboards/ergotaco/matrix.c
index 63d4c4f5f3..3c49f2802e 100644
--- a/keyboards/gboards/ergotaco/matrix.c
+++ b/keyboards/gboards/ergotaco/matrix.c
@@ -234,15 +234,8 @@ static matrix_row_t read_cols(uint8_t row)
234 return 0; 234 return 0;
235 } else { 235 } else {
236 uint8_t data = 0; 236 uint8_t data = 0;
237 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 237 mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
238 mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 238 data = (~((uint8_t)data) >> 2) & 0x01 ;
239 mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
240 mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
241 data = (~((uint8_t)mcp23018_status) >> 2) & 0x01 ;
242 mcp23018_status = I2C_STATUS_SUCCESS;
243 out:
244 i2c_stop();
245
246#ifdef DEBUG_MATRIX 239#ifdef DEBUG_MATRIX
247 if (data != 0x00) xprintf("I2C: %d\n", data); 240 if (data != 0x00) xprintf("I2C: %d\n", data);
248#endif 241#endif
@@ -274,11 +267,8 @@ static void select_row(uint8_t row)
274 if (mcp23018_status) { // do nothing on error 267 if (mcp23018_status) { // do nothing on error
275 // Read using bitmask 268 // Read using bitmask
276 } else { // set active row low : 0 // set other rows hi-Z : 1 269 } else { // set active row low : 0 // set other rows hi-Z : 1
277 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 270 uint8_t data = ~(1<<row);
278 mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 271 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
279 mcp23018_status = i2c_write(~(1<<row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
280 out:
281 i2c_stop();
282 } 272 }
283 } else { 273 } else {
284 // Output low(DDR:1, PORT:0) to select 274 // Output low(DDR:1, PORT:0) to select
diff --git a/keyboards/gboards/georgi/georgi.c b/keyboards/gboards/georgi/georgi.c
index dd95b593f1..745e8ab35d 100644
--- a/keyboards/gboards/georgi/georgi.c
+++ b/keyboards/gboards/georgi/georgi.c
@@ -45,23 +45,17 @@ uint8_t init_mcp23018(void) {
45 // - unused : input : 1 45 // - unused : input : 1
46 // - input : input : 1 46 // - input : input : 1
47 // - driving : output : 0 47 // - driving : output : 0
48 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 48 uint8_t data[] = {0b10000000, 0b11111111};
49 mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 49 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
50 mcp23018_status = i2c_write(0b10000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 50
51 mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 51 if (!mcp23018_status) {
52 i2c_stop(); 52 // set pull-up
53 53 // - unused : on : 1
54 // set pull-up 54 // - input : on : 1
55 // - unused : on : 1 55 // - driving : off : 0
56 // - input : on : 1 56 mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
57 // - driving : off : 0 57 }
58 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
59 mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
60 mcp23018_status = i2c_write(0b10000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
61 mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
62 58
63out:
64 i2c_stop();
65 // SREG=sreg_prev; 59 // SREG=sreg_prev;
66 //uprintf("Init %x\n", mcp23018_status); 60 //uprintf("Init %x\n", mcp23018_status);
67 return mcp23018_status; 61 return mcp23018_status;
diff --git a/keyboards/gboards/georgi/georgi.h b/keyboards/gboards/georgi/georgi.h
index e23fc264f4..6ab47ced74 100644
--- a/keyboards/gboards/georgi/georgi.h
+++ b/keyboards/gboards/georgi/georgi.h
@@ -11,10 +11,7 @@ extern i2c_status_t mcp23018_status;
11#define ERGODOX_EZ_I2C_TIMEOUT 1000 11#define ERGODOX_EZ_I2C_TIMEOUT 1000
12 12
13// I2C aliases and register addresses (see "mcp23018.md") 13// I2C aliases and register addresses (see "mcp23018.md")
14//#define I2C_ADDR 0b0100000 14#define I2C_ADDR (0x20<<1)
15#define I2C_ADDR 0x20
16#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
17#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
18#define IODIRA 0x00 // i/o direction register 15#define IODIRA 0x00 // i/o direction register
19#define IODIRB 0x01 16#define IODIRB 0x01
20#define GPPUA 0x0C // GPIO pull-up resistor register 17#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/gboards/georgi/matrix.c b/keyboards/gboards/georgi/matrix.c
index b66b1a194c..d1151ae80e 100644
--- a/keyboards/gboards/georgi/matrix.c
+++ b/keyboards/gboards/georgi/matrix.c
@@ -254,14 +254,7 @@ static matrix_row_t read_cols(uint8_t row)
254 return 0; 254 return 0;
255 } else { 255 } else {
256 uint8_t data = 0; 256 uint8_t data = 0;
257 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 257 mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
258 mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
259 mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
260 mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
261 data = ~((uint8_t)mcp23018_status);
262 mcp23018_status = I2C_STATUS_SUCCESS;
263 out:
264 i2c_stop();
265 258
266#ifdef DEBUG_MATRIX 259#ifdef DEBUG_MATRIX
267 if (data != 0x00) xprintf("I2C: %d\n", data); 260 if (data != 0x00) xprintf("I2C: %d\n", data);
@@ -304,11 +297,9 @@ static void select_row(uint8_t row)
304 // select on mcp23018 297 // select on mcp23018
305 if (mcp23018_status) { // do nothing on error 298 if (mcp23018_status) { // do nothing on error
306 } else { // set active row low : 0 // set other rows hi-Z : 1 299 } else { // set active row low : 0 // set other rows hi-Z : 1
307 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 300 uint8_t data = 0xFF & ~(1<<row);
308 mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 301 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
309 mcp23018_status = i2c_write(0xFF & ~(1<<row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; 302
310 out:
311 i2c_stop();
312 } 303 }
313 } else { 304 } else {
314 // Output low(DDR:1, PORT:0) to select 305 // Output low(DDR:1, PORT:0) to select
diff --git a/keyboards/gboards/gergo/gergo.c b/keyboards/gboards/gergo/gergo.c
index da2a3007a8..41d383d408 100644
--- a/keyboards/gboards/gergo/gergo.c
+++ b/keyboards/gboards/gergo/gergo.c
@@ -43,23 +43,17 @@ uint8_t init_mcp23018(void) {
43 // - unused : input : 1 43 // - unused : input : 1
44 // - input : input : 1 44 // - input : input : 1
45 // - driving : output : 0 45 // - driving : output : 0
46 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 46 uint8_t data[] = {0b10000000, 0b11111111};
47 mcp23018_status = i2c_write(IODIRA, I2C_TIMEOUT); if (mcp23018_status) goto out; 47 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
48 mcp23018_status = i2c_write(0b10000000, I2C_TIMEOUT); if (mcp23018_status) goto out;
49 mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT); if (mcp23018_status) goto out;
50 i2c_stop();
51 48
52 // set pull-up 49 if (!mcp23018_status) {
53 // - unused : on : 1 50 // set pull-up
54 // - input : on : 1 51 // - unused : on : 1
55 // - driving : off : 0 52 // - input : on : 1
56 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 53 // - driving : off : 0
57 mcp23018_status = i2c_write(GPPUA, I2C_TIMEOUT); if (mcp23018_status) goto out; 54 mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
58 mcp23018_status = i2c_write(0b10000000, I2C_TIMEOUT); if (mcp23018_status) goto out; 55 }
59 mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT); if (mcp23018_status) goto out;
60 56
61out:
62 i2c_stop();
63 // SREG=sreg_prev; 57 // SREG=sreg_prev;
64 //uprintf("Init %x\n", mcp23018_status); 58 //uprintf("Init %x\n", mcp23018_status);
65 return mcp23018_status; 59 return mcp23018_status;
diff --git a/keyboards/gboards/gergo/gergo.h b/keyboards/gboards/gergo/gergo.h
index ea6368e2f1..f6dc1498f0 100644
--- a/keyboards/gboards/gergo/gergo.h
+++ b/keyboards/gboards/gergo/gergo.h
@@ -11,10 +11,7 @@ extern i2c_status_t mcp23018_status;
11#define I2C_TIMEOUT 1000 11#define I2C_TIMEOUT 1000
12 12
13// I2C aliases and register addresses (see "mcp23018.md") 13// I2C aliases and register addresses (see "mcp23018.md")
14//#define I2C_ADDR 0b0100000 14#define I2C_ADDR (0x20<<1)
15#define I2C_ADDR 0x20
16#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
17#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
18#define IODIRA 0x00 // i/o direction register 15#define IODIRA 0x00 // i/o direction register
19#define IODIRB 0x01 16#define IODIRB 0x01
20#define GPPUA 0x0C // GPIO pull-up resistor register 17#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/gboards/gergo/matrix.c b/keyboards/gboards/gergo/matrix.c
index 8a6b38bf73..b4885361fb 100644
--- a/keyboards/gboards/gergo/matrix.c
+++ b/keyboards/gboards/gergo/matrix.c
@@ -297,19 +297,12 @@ static matrix_row_t read_cols(uint8_t row) {
297 return 0; 297 return 0;
298 } else { 298 } else {
299 uint8_t data = 0; 299 uint8_t data = 0;
300 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 300 mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, I2C_TIMEOUT);
301 mcp23018_status = i2c_write(GPIOB, I2C_TIMEOUT); if (mcp23018_status) goto out;
302 mcp23018_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (mcp23018_status) goto out;
303 mcp23018_status = i2c_read_nack(I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
304 data = ~((uint8_t)mcp23018_status);
305 mcp23018_status = I2C_STATUS_SUCCESS;
306 out:
307 i2c_stop();
308 301
309#ifdef DEBUG_MATRIX 302#ifdef DEBUG_MATRIX
310 if (data != 0x00) xprintf("I2C: %d\n", data); 303 if (~data != 0x00) xprintf("I2C: %d\n", ~data);
311#endif 304#endif
312 return data; 305 return ~data;
313 } 306 }
314 } else { 307 } else {
315 /* read from teensy 308 /* read from teensy
@@ -350,11 +343,8 @@ static void select_row(uint8_t row)
350 // select on mcp23018 343 // select on mcp23018
351 if (mcp23018_status) { // do nothing on error 344 if (mcp23018_status) { // do nothing on error
352 } else { // set active row low : 0 // set other rows hi-Z : 1 345 } else { // set active row low : 0 // set other rows hi-Z : 1
353 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 346 uint8_t data = 0xFF & ~(1<<row);
354 mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT); if (mcp23018_status) goto out; 347 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
355 mcp23018_status = i2c_write(0xFF & ~(1<<row), I2C_TIMEOUT); if (mcp23018_status) goto out;
356 out:
357 i2c_stop();
358 } 348 }
359 } else { 349 } else {
360 // Output low(DDR:1, PORT:0) to select 350 // Output low(DDR:1, PORT:0) to select
diff --git a/keyboards/gboards/gergoplex/gergoplex.c b/keyboards/gboards/gergoplex/gergoplex.c
index 1e44583895..b621201c16 100644
--- a/keyboards/gboards/gergoplex/gergoplex.c
+++ b/keyboards/gboards/gergoplex/gergoplex.c
@@ -39,30 +39,16 @@ uint8_t init_mcp23018(void) {
39 // - unused : input : 1 39 // - unused : input : 1
40 // - input : input : 1 40 // - input : input : 1
41 // - driving : output : 0 41 // - driving : output : 0
42 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); 42 uint8_t data[] = {0b11000001, 0b11111111};
43 if (mcp23018_status) goto out; 43 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
44 mcp23018_status = i2c_write(IODIRA, I2C_TIMEOUT); 44
45 if (mcp23018_status) goto out; 45 if (!mcp23018_status) {
46 mcp23018_status = i2c_write(0b11000001, I2C_TIMEOUT); 46 // set pull-up
47 if (mcp23018_status) goto out; 47 // - unused : on : 1
48 mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT); 48 // - input : on : 1
49 if (mcp23018_status) goto out; 49 // - driving : off : 0
50 i2c_stop(); 50 mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
51 51 }
52 // set pull-up
53 // - unused : on : 1
54 // - input : on : 1
55 // - driving : off : 0
56 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT);
57 if (mcp23018_status) goto out;
58 mcp23018_status = i2c_write(GPPUA, I2C_TIMEOUT);
59 if (mcp23018_status) goto out;
60 mcp23018_status = i2c_write(0b11000001, I2C_TIMEOUT);
61 if (mcp23018_status) goto out;
62 mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT);
63 if (mcp23018_status) goto out;
64 52
65out:
66 i2c_stop();
67 return mcp23018_status; 53 return mcp23018_status;
68} 54}
diff --git a/keyboards/gboards/gergoplex/gergoplex.h b/keyboards/gboards/gergoplex/gergoplex.h
index 549228104a..217cb8dff1 100644
--- a/keyboards/gboards/gergoplex/gergoplex.h
+++ b/keyboards/gboards/gergoplex/gergoplex.h
@@ -25,9 +25,7 @@ extern i2c_status_t mcp23018_status;
25#define XXX KC_NO 25#define XXX KC_NO
26 26
27// I2C aliases and register addresses (see "mcp23018.md") 27// I2C aliases and register addresses (see "mcp23018.md")
28#define I2C_ADDR 0x20 // 0b0100000 28#define I2C_ADDR (0x20 << 1) // 0b0100000
29#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
30#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
31#define IODIRA 0x00 // i/o direction register 29#define IODIRA 0x00 // i/o direction register
32#define IODIRB 0x01 30#define IODIRB 0x01
33#define GPPUA 0x0C // GPIO pull-up resistor register 31#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/gboards/gergoplex/matrix.c b/keyboards/gboards/gergoplex/matrix.c
index c9f5528b74..9437b24377 100644
--- a/keyboards/gboards/gergoplex/matrix.c
+++ b/keyboards/gboards/gergoplex/matrix.c
@@ -177,20 +177,12 @@ static matrix_row_t read_cols(uint8_t row) {
177 if (mcp23018_status) { // if there was an error 177 if (mcp23018_status) { // if there was an error
178 return 0; 178 return 0;
179 } else { 179 } else {
180 uint8_t data = 0; 180 uint8_t data = 0;
181 mcp23018_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); 181 mcp23018_status = i2c_receive(I2C_ADDR, &data, 1, I2C_TIMEOUT);
182 if (mcp23018_status) goto out;
183 mcp23018_status = i2c_read_nack(I2C_TIMEOUT);
184 if (mcp23018_status < 0) goto out;
185 data = ~((uint8_t)mcp23018_status);
186 mcp23018_status = I2C_STATUS_SUCCESS;
187 out:
188 i2c_stop();
189
190#ifdef DEBUG_MATRIX 182#ifdef DEBUG_MATRIX
191 if (data != 0x00) xprintf("I2C: %d\n", data); 183 if (~data != 0x00) xprintf("I2C: %d\n", ~data);
192#endif 184#endif
193 return data; 185 return ~data;
194 } 186 }
195 } else { 187 } else {
196 return ~((((PINF & COL4) >> 1) | ((PINF & (COL1 | COL2 | COL3)) >> 3)) & 0xF); 188 return ~((((PINF & COL4) >> 1) | ((PINF & (COL1 | COL2 | COL3)) >> 3)) & 0xF);
@@ -213,14 +205,10 @@ static void select_row(uint8_t row) {
213 // select on mcp23018 205 // select on mcp23018
214 if (mcp23018_status) { // do nothing on error 206 if (mcp23018_status) { // do nothing on error
215 } else { // set active row low : 0 // set other rows hi-Z : 1 207 } else { // set active row low : 0 // set other rows hi-Z : 1
216 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); 208 uint8_t data;
217 if (mcp23018_status) goto out; 209 data = 0xFF & ~(1 << (row + 1));
218 mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT); 210 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
219 if (mcp23018_status) goto out; 211
220 mcp23018_status = i2c_write(0xFF & ~(1 << (row + 1)), I2C_TIMEOUT);
221 if (mcp23018_status) goto out;
222 out:
223 i2c_stop();
224 } 212 }
225 } else { 213 } else {
226 setPinOutput(row_pins[row - MATRIX_ROWS_PER_SIDE]); 214 setPinOutput(row_pins[row - MATRIX_ROWS_PER_SIDE]);
diff --git a/keyboards/handwired/d48/ds1307.c b/keyboards/handwired/d48/ds1307.c
index 2b3a88f315..5f4931bbf8 100644
--- a/keyboards/handwired/d48/ds1307.c
+++ b/keyboards/handwired/d48/ds1307.c
@@ -14,7 +14,6 @@ void ds1307_set_time(uint8_t h, uint8_t m, uint8_t s) {
14void ds1307_get_time(uint8_t *h, uint8_t *m, uint8_t *s) { 14void ds1307_get_time(uint8_t *h, uint8_t *m, uint8_t *s) {
15 uint8_t data[3]; 15 uint8_t data[3];
16 i2c_read_register(DS1307_ADDR, 0, data, 3, 100); 16 i2c_read_register(DS1307_ADDR, 0, data, 3, 100);
17 i2c_stop();
18 *s = (data[0] & 0b1111) + ((data[0] & 0b1110000) >> 4) * 10; 17 *s = (data[0] & 0b1111) + ((data[0] & 0b1110000) >> 4) * 10;
19 *m = (data[1] & 0b1111) + ((data[1] & 0b1110000) >> 4) * 10; 18 *m = (data[1] & 0b1111) + ((data[1] & 0b1110000) >> 4) * 10;
20 *h = (data[2] & 0b1111) + ((data[2] & 0b0110000) >> 4) * 10; 19 *h = (data[2] & 0b1111) + ((data[2] & 0b0110000) >> 4) * 10;
diff --git a/keyboards/handwired/frenchdev/frenchdev.c b/keyboards/handwired/frenchdev/frenchdev.c
index 6eed4de5ff..65f1ccce4b 100644
--- a/keyboards/handwired/frenchdev/frenchdev.c
+++ b/keyboards/handwired/frenchdev/frenchdev.c
@@ -83,23 +83,16 @@ uint8_t init_mcp23018(void) {
83 // - unused : input : 1 83 // - unused : input : 1
84 // - input : input : 1 84 // - input : input : 1
85 // - driving : output : 0 85 // - driving : output : 0
86 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 86 uint8_t data[] = {0b00000000, 0b00111111};
87 mcp23018_status = i2c_write(IODIRA, I2C_TIMEOUT); if (mcp23018_status) goto out; 87 mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
88 mcp23018_status = i2c_write(0b00000000, I2C_TIMEOUT); if (mcp23018_status) goto out; 88
89 mcp23018_status = i2c_write(0b00111111, I2C_TIMEOUT); if (mcp23018_status) goto out; 89 if (!mcp23018_status) {
90 i2c_stop(); 90 // set pull-up
91 91 // - unused : on : 1
92 // set pull-up 92 // - input : on : 1
93 // - unused : on : 1 93 // - driving : off : 0
94 // - input : on : 1 94 mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
95 // - driving : off : 0 95 }
96 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
97 mcp23018_status = i2c_write(GPPUA, I2C_TIMEOUT); if (mcp23018_status) goto out;
98 mcp23018_status = i2c_write(0b00000000, I2C_TIMEOUT); if (mcp23018_status) goto out;
99 mcp23018_status = i2c_write(0b00111111, I2C_TIMEOUT); if (mcp23018_status) goto out;
100
101out:
102 i2c_stop();
103 96
104 // SREG=sreg_prev; 97 // SREG=sreg_prev;
105 98
diff --git a/keyboards/handwired/frenchdev/frenchdev.h b/keyboards/handwired/frenchdev/frenchdev.h
index 6bea49d87b..0f1ac7dcaa 100644
--- a/keyboards/handwired/frenchdev/frenchdev.h
+++ b/keyboards/handwired/frenchdev/frenchdev.h
@@ -7,9 +7,7 @@
7#include <util/delay.h> 7#include <util/delay.h>
8 8
9// I2C aliases and register addresses (see "mcp23018.md" on tmk repository) 9// I2C aliases and register addresses (see "mcp23018.md" on tmk repository)
10#define I2C_ADDR 0b0100000 10#define I2C_ADDR (0b0100000<<1)
11#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
12#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
13#define IODIRA 0x00 // i/o direction register 11#define IODIRA 0x00 // i/o direction register
14#define IODIRB 0x01 12#define IODIRB 0x01
15#define GPPUA 0x0C // GPIO pull-up resistor register 13#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/handwired/frenchdev/matrix.c b/keyboards/handwired/frenchdev/matrix.c
index 3e859d47ef..3afc6dcee6 100644
--- a/keyboards/handwired/frenchdev/matrix.c
+++ b/keyboards/handwired/frenchdev/matrix.c
@@ -224,15 +224,9 @@ static matrix_row_t read_cols(uint8_t row)
224 return 0; 224 return 0;
225 } else { 225 } else {
226 uint8_t data = 0; 226 uint8_t data = 0;
227 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 227 mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, I2C_TIMEOUT);
228 mcp23018_status = i2c_write(GPIOB, I2C_TIMEOUT); if (mcp23018_status) goto out; 228
229 mcp23018_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (mcp23018_status) goto out; 229 return ~data;
230 data = i2c_read_nack(I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
231 data = ~((uint8_t)mcp23018_status);
232 mcp23018_status = I2C_STATUS_SUCCESS;
233 out:
234 i2c_stop();
235 return data;
236 } 230 }
237 } else { 231 } else {
238 // read from teensy 232 // read from teensy
@@ -263,11 +257,10 @@ static void unselect_rows(void)
263 // do nothing 257 // do nothing
264 } else { 258 } else {
265 // set all rows hi-Z : 1 259 // set all rows hi-Z : 1
266 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 260 uint8_t data;
267 mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT); if (mcp23018_status) goto out; 261 data = 0xFF & ~(0<<8);
268 mcp23018_status = i2c_write( 0xFF & ~(0<<8), I2C_TIMEOUT); if (mcp23018_status) goto out; 262 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
269 out: 263
270 i2c_stop();
271 } 264 }
272 265
273 // unselect on teensy 266 // unselect on teensy
@@ -289,11 +282,8 @@ static void select_row(uint8_t row)
289 } else { 282 } else {
290 // set active row low : 0 283 // set active row low : 0
291 // set other rows hi-Z : 1 284 // set other rows hi-Z : 1
292 mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out; 285 uint8_t data = 0xFF & ~(1<<row) & ~(0<<8);
293 mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT); if (mcp23018_status) goto out; 286 mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
294 mcp23018_status = i2c_write( 0xFF & ~(1<<row) & ~(0<<8), I2C_TIMEOUT); if (mcp23018_status) goto out;
295 out:
296 i2c_stop();
297 } 287 }
298 } else { 288 } else {
299 // select on teensy 289 // select on teensy
diff --git a/keyboards/handwired/onekey/keymaps/i2c_scanner/keymap.c b/keyboards/handwired/onekey/keymaps/i2c_scanner/keymap.c
index 43e61c29d3..1d1a7c2b00 100644
--- a/keyboards/handwired/onekey/keymaps/i2c_scanner/keymap.c
+++ b/keyboards/handwired/onekey/keymaps/i2c_scanner/keymap.c
@@ -8,16 +8,6 @@
8// TODO: remove patch 8// TODO: remove patch
9#ifdef PROTOCOL_CHIBIOS 9#ifdef PROTOCOL_CHIBIOS
10# pragma message("ChibiOS is currently 'best effort' and might not report accurate results") 10# pragma message("ChibiOS is currently 'best effort' and might not report accurate results")
11
12i2c_status_t i2c_start_bodge(uint8_t address, uint16_t timeout) {
13 i2c_start(address);
14
15 // except on ChibiOS where the only way is do do "something"
16 uint8_t data = 0;
17 return i2c_read_register(address, 0, &data, sizeof(data), TIMEOUT);
18}
19
20# define i2c_start i2c_start_bodge
21#endif 11#endif
22 12
23const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 13const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
@@ -31,10 +21,9 @@ void do_scan(void) {
31 21
32 for (uint8_t address = 1; address < 127; address++) { 22 for (uint8_t address = 1; address < 127; address++) {
33 // The i2c_scanner uses the return value of 23 // The i2c_scanner uses the return value of
34 // i2c_start to see if a device did acknowledge to the address. 24 // i2c_ping_address to see if a device did acknowledge to the address.
35 i2c_status_t error = i2c_start(address << 1, TIMEOUT); 25 i2c_status_t error = i2c_ping_address(address << 1, TIMEOUT);
36 if (error == I2C_STATUS_SUCCESS) { 26 if (error == I2C_STATUS_SUCCESS) {
37 i2c_stop();
38 dprintf(" I2C device found at address 0x%02X\n", address); 27 dprintf(" I2C device found at address 0x%02X\n", address);
39 nDevices++; 28 nDevices++;
40 } else { 29 } else {
diff --git a/keyboards/handwired/pterodactyl/matrix.c b/keyboards/handwired/pterodactyl/matrix.c
index bc98bdd634..0dff65eda6 100644
--- a/keyboards/handwired/pterodactyl/matrix.c
+++ b/keyboards/handwired/pterodactyl/matrix.c
@@ -29,9 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
29 29
30#define I2C_TIMEOUT 100 30#define I2C_TIMEOUT 100
31 31
32#define I2C_ADDR 0b0100000 32#define I2C_ADDR (0b0100000<<1)
33#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
34#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
35#define IODIRA 0x00 // i/o direction register 33#define IODIRA 0x00 // i/o direction register
36#define IODIRB 0x01 34#define IODIRB 0x01
37#define GPPUA 0x0C // GPIO pull-up resistor register 35#define GPPUA 0x0C // GPIO pull-up resistor register
@@ -159,9 +157,6 @@ void init_expander(void) {
159#endif 157#endif
160 } 158 }
161 159
162 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
163 expander_status = i2c_write(IODIRA, I2C_TIMEOUT); if (expander_status) goto out;
164
165 /* 160 /*
166 Pin direction and pull-up depends on both the diode direction 161 Pin direction and pull-up depends on both the diode direction
167 and on whether the column register is GPIOA or GPIOB 162 and on whether the column register is GPIOA or GPIOB
@@ -176,50 +171,27 @@ void init_expander(void) {
176 171
177#if (EXPANDER_COL_REGISTER == GPIOA) 172#if (EXPANDER_COL_REGISTER == GPIOA)
178# if (DIODE_DIRECTION == COL2ROW) 173# if (DIODE_DIRECTION == COL2ROW)
179 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out; 174 uint8_t data[] = { expander_input_pin_mask, 0};
180 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
181# elif (DIODE_DIRECTION == ROW2COL) 175# elif (DIODE_DIRECTION == ROW2COL)
182 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out; 176 uint8_t data[] = { 0, expander_input_pin_mask};
183 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
184# endif 177# endif
185#elif (EXPANDER_COL_REGISTER == GPIOB) 178#elif (EXPANDER_COL_REGISTER == GPIOB)
186# if (DIODE_DIRECTION == COL2ROW) 179# if (DIODE_DIRECTION == COL2ROW)
187 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out; 180 uint8_t data[] = { 0, expander_input_pin_mask};
188 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
189# elif (DIODE_DIRECTION == ROW2COL) 181# elif (DIODE_DIRECTION == ROW2COL)
190 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out; 182 uint8_t data[] = { expander_input_pin_mask, 0};
191 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
192# endif
193#endif
194
195 i2c_stop();
196
197 // set pull-up
198 // - unused : off : 0
199 // - input : on : 1
200 // - driving : off : 0
201 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
202 expander_status = i2c_write(GPPUA, I2C_TIMEOUT); if (expander_status) goto out;
203#if (EXPANDER_COL_REGISTER == GPIOA)
204# if (DIODE_DIRECTION == COL2ROW)
205 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
206 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
207# elif (DIODE_DIRECTION == ROW2COL)
208 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
209 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
210# endif
211#elif (EXPANDER_COL_REGISTER == GPIOB)
212# if (DIODE_DIRECTION == COL2ROW)
213 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
214 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
215# elif (DIODE_DIRECTION == ROW2COL)
216 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
217 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
218# endif 183# endif
219#endif 184#endif
185 expander_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
186
187 if (!expander_status) {
188 // set pull-up
189 // - unused : off : 0
190 // - input : on : 1
191 // - driving : off : 0
192 expander_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
193 }
220 194
221out:
222 i2c_stop();
223} 195}
224 196
225uint8_t matrix_scan(void) 197uint8_t matrix_scan(void)
@@ -332,14 +304,9 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
332 304
333 // Read columns from expander, unless it's in an error state 305 // Read columns from expander, unless it's in an error state
334 if (! expander_status) { 306 if (! expander_status) {
335 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out; 307 uint8_t data;
336 expander_status = i2c_write(EXPANDER_COL_REGISTER, I2C_TIMEOUT); if (expander_status) goto out; 308 i2c_readReg(I2C_ADDR, EXPANDER_COL_REGISTER, &data, 1, I2C_TIMEOUT);
337 expander_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (expander_status) goto out; 309 current_matrix[current_row] |= (~data) & expander_input_pin_mask;
338
339 current_matrix[current_row] |= (~i2c_read_nack(I2C_TIMEOUT)) & expander_input_pin_mask;
340
341 out:
342 i2c_stop();
343 } 310 }
344 311
345 // Read columns from onboard pins 312 // Read columns from onboard pins
@@ -361,11 +328,8 @@ static void select_row(uint8_t row) {
361 if (! expander_status) { 328 if (! expander_status) {
362 // set active row low : 0 329 // set active row low : 0
363 // set other rows hi-Z : 1 330 // set other rows hi-Z : 1
364 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out; 331 uint8_t data = 0xFF & ~(1<<row);
365 expander_status = i2c_write(EXPANDER_ROW_REGISTER, I2C_TIMEOUT); if (expander_status) goto out; 332 i2c_writeReg(I2C_ADDR, EXPANDER_ROW_REGISTER, &data, 1, I2C_TIMEOUT);
366 expander_status = i2c_write(0xFF & ~(1<<row), I2C_TIMEOUT); if (expander_status) goto out;
367 out:
368 i2c_stop();
369 } 333 }
370 334
371 // select on teensy 335 // select on teensy
@@ -421,14 +385,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
421 return false; 385 return false;
422 } 386 }
423 387
424 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out; 388 i2c_writeReg(I2C_ADDR, EXPANDER_ROW_REGISTER, &column_state, 1, I2C_TIMEOUT);
425 expander_status = i2c_write(EXPANDER_ROW_REGISTER, I2C_TIMEOUT); if (expander_status) goto out;
426 expander_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (expander_status) goto out;
427 column_state = i2c_read_nack(I2C_TIMEOUT);
428
429 out:
430 i2c_stop();
431
432 column_state = ~column_state; 389 column_state = ~column_state;
433 } else { 390 } else {
434 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 391 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
diff --git a/keyboards/hotdox/left.c b/keyboards/hotdox/left.c
index 970d36f1b5..f963ecdae7 100644
--- a/keyboards/hotdox/left.c
+++ b/keyboards/hotdox/left.c
@@ -5,8 +5,8 @@
5bool i2c_initialized = false; 5bool i2c_initialized = false;
6 6
7void left_config(void); 7void left_config(void);
8uint8_t left_write(uint8_t reg, uint8_t data); 8i2c_status_t left_write(uint8_t reg, uint8_t data);
9uint8_t left_read(uint8_t reg, uint8_t *data); 9i2c_status_t left_read(uint8_t reg, uint8_t *data);
10 10
11uint8_t init_mcp23017(void) 11uint8_t init_mcp23017(void)
12{ 12{
@@ -35,12 +35,11 @@ void left_init(void)
35 35
36void left_scan(void) 36void left_scan(void)
37{ 37{
38 uint8_t ret = i2c_start(I2C_ADDR_WRITE, HOTDOX_I2C_TIMEOUT); 38
39 i2c_status_t ret = i2c_ping_address(I2C_ADDR, HOTDOX_I2C_TIMEOUT);
39 40
40 if (ret == 0) 41 if (ret == I2C_STATUS_SUCCESS)
41 { 42 {
42 i2c_stop();
43
44 if (!i2c_initialized) 43 if (!i2c_initialized)
45 { 44 {
46 i2c_initialized = true; 45 i2c_initialized = true;
@@ -91,40 +90,29 @@ void left_config(void)
91 left_write(MCP23017_B0_GPIOB, 0xC0); 90 left_write(MCP23017_B0_GPIOB, 0xC0);
92} 91}
93 92
94uint8_t left_write(uint8_t reg, uint8_t data) 93i2c_status_t left_write(uint8_t reg, uint8_t data)
95{ 94{
96 if (!i2c_initialized) 95 if (!i2c_initialized)
97 { 96 {
98 return 0; 97 return 0;
99 } 98 }
100 99
101 uint8_t ret; 100 i2c_status_t ret;
102 101
103 ret = i2c_start(I2C_ADDR_WRITE, HOTDOX_I2C_TIMEOUT); if (ret) goto out; 102 ret = i2c_writeReg(I2C_ADDR, reg, &data, sizeof(data), HOTDOX_I2C_TIMEOUT);
104 ret = i2c_write(reg, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
105 ret = i2c_write(data, HOTDOX_I2C_TIMEOUT);
106 103
107out:
108 i2c_stop();
109 return ret; 104 return ret;
110} 105}
111 106
112uint8_t left_read(uint8_t reg, uint8_t *data) 107i2c_status_t left_read(uint8_t reg, uint8_t *data)
113{ 108{
114 if (!i2c_initialized) 109 if (!i2c_initialized)
115 { 110 {
116 return 0; 111 return 0;
117 } 112 }
118 113
119 uint8_t ret = 0; 114 i2c_status_t ret = 0;
120 115 ret = i2c_readReg(I2C_ADDR, reg, data, 1, HOTDOX_I2C_TIMEOUT);
121 ret = i2c_start(I2C_ADDR_WRITE, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
122 ret = i2c_write(reg, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
123 ret = i2c_start(I2C_ADDR_READ, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
124
125 *data = i2c_read_nack(HOTDOX_I2C_TIMEOUT);
126 116
127out:
128 i2c_stop();
129 return ret; 117 return ret;
130} 118}
diff --git a/keyboards/hotdox/left.h b/keyboards/hotdox/left.h
index 3d8b5a6ead..32faadba21 100644
--- a/keyboards/hotdox/left.h
+++ b/keyboards/hotdox/left.h
@@ -10,10 +10,7 @@
10#define MCP23017_A1 0 10#define MCP23017_A1 0
11#define MCP23017_A2 0 11#define MCP23017_A2 0
12 12
13#define I2C_ADDR (0x20) 13#define I2C_ADDR ((0x20) << 1)
14#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
15#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
16
17 14
18#define MCP23017_B0_IODIRA 0x00 15#define MCP23017_B0_IODIRA 0x00
19#define MCP23017_B0_IODIRB 0x01 16#define MCP23017_B0_IODIRB 0x01
@@ -40,8 +37,6 @@
40 37
41#define HOTDOX_I2C_TIMEOUT 100 38#define HOTDOX_I2C_TIMEOUT 100
42 39
43typedef int16_t i2c_status_t;
44
45void left_init(void); 40void left_init(void);
46void left_scan(void); 41void left_scan(void);
47 42
diff --git a/keyboards/ingrained/matrix.c b/keyboards/ingrained/matrix.c
index 154a275d7a..3ba9d8dcf3 100644
--- a/keyboards/ingrained/matrix.c
+++ b/keyboards/ingrained/matrix.c
@@ -41,9 +41,7 @@ extern i2c_status_t mcp23017_status;
41// All address pins of the mcp23017 are connected to the ground on the ferris 41// All address pins of the mcp23017 are connected to the ground on the ferris
42// | 0 | 1 | 0 | 0 | A2 | A1 | A0 | 42// | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
43// | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 43// | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
44#define I2C_ADDR 0b0100000 44#define I2C_ADDR (0b0100000<<1)
45#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
46#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
47 45
48// Register addresses 46// Register addresses
49// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h 47// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h
@@ -77,7 +75,7 @@ uint8_t init_mcp23017(void) {
77 // This means: we will read all the bits on GPIOA 75 // This means: we will read all the bits on GPIOA
78 // This means: we will write to the pins 0-4 on GPIOB (in select_rows) 76 // This means: we will write to the pins 0-4 on GPIOB (in select_rows)
79 uint8_t buf[] = {IODIRA, 0b11111111, 0b11110000}; 77 uint8_t buf[] = {IODIRA, 0b11111111, 0b11110000};
80 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT); 78 mcp23017_status = i2c_transmit(I2C_ADDR, buf, sizeof(buf), I2C_TIMEOUT);
81 if (!mcp23017_status) { 79 if (!mcp23017_status) {
82 // set pull-up 80 // set pull-up
83 // - unused : on : 1 81 // - unused : on : 1
@@ -86,7 +84,7 @@ uint8_t init_mcp23017(void) {
86 // This means: we will read all the bits on GPIOA 84 // This means: we will read all the bits on GPIOA
87 // This means: we will write to the pins 0-4 on GPIOB (in select_rows) 85 // This means: we will write to the pins 0-4 on GPIOB (in select_rows)
88 uint8_t pullup_buf[] = {GPPUA, 0b11111111, 0b11110000}; 86 uint8_t pullup_buf[] = {GPPUA, 0b11111111, 0b11110000};
89 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, pullup_buf, sizeof(pullup_buf), I2C_TIMEOUT); 87 mcp23017_status = i2c_transmit(I2C_ADDR, pullup_buf, sizeof(pullup_buf), I2C_TIMEOUT);
90 } 88 }
91 return mcp23017_status; 89 return mcp23017_status;
92} 90}
@@ -205,14 +203,14 @@ static matrix_row_t read_cols(uint8_t row) {
205 return 0; 203 return 0;
206 } else { 204 } else {
207 uint8_t buf[] = {GPIOA}; 205 uint8_t buf[] = {GPIOA};
208 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT); 206 mcp23017_status = i2c_transmit(I2C_ADDR, buf, sizeof(buf), I2C_TIMEOUT);
209 // We read all the pins on GPIOA. 207 // We read all the pins on GPIOA.
210 // The initial state was all ones and any depressed key at a given column for the currently selected row will have its bit flipped to zero. 208 // The initial state was all ones and any depressed key at a given column for the currently selected row will have its bit flipped to zero.
211 // The return value is a row as represented in the generic matrix code were the rightmost bits represent the lower columns and zeroes represent non-depressed keys while ones represent depressed keys. 209 // The return value is a row as represented in the generic matrix code were the rightmost bits represent the lower columns and zeroes represent non-depressed keys while ones represent depressed keys.
212 // Since the pins connected to eact columns are sequential, and counting from zero up (col 5 -> GPIOA0, col 6 -> GPIOA1 and so on), the only transformation needed is a bitwise not to swap all zeroes and ones. 210 // Since the pins connected to eact columns are sequential, and counting from zero up (col 5 -> GPIOA0, col 6 -> GPIOA1 and so on), the only transformation needed is a bitwise not to swap all zeroes and ones.
213 uint8_t data[] = {0}; 211 uint8_t data[] = {0};
214 if (!mcp23017_status) { 212 if (!mcp23017_status) {
215 mcp23017_status = i2c_receive(I2C_ADDR_READ, data, sizeof(data), I2C_TIMEOUT); 213 mcp23017_status = i2c_receive(I2C_ADDR, data, sizeof(data), I2C_TIMEOUT);
216 data[0] = ~(data[0]); 214 data[0] = ~(data[0]);
217 } 215 }
218 return data[0]; 216 return data[0];
@@ -249,7 +247,7 @@ static void select_row(uint8_t row) {
249 // Select the desired row by writing a byte for the entire GPIOB bus where only the bit representing the row we want to select is a zero (write instruction) and every other bit is a one. 247 // Select the desired row by writing a byte for the entire GPIOB bus where only the bit representing the row we want to select is a zero (write instruction) and every other bit is a one.
250 // Note that the row - MATRIX_ROWS_PER_SIDE reflects the fact that being on the right hand, the columns are numbered from MATRIX_ROWS_PER_SIDE to MATRIX_ROWS, but the pins we want to write to are indexed from zero up on the GPIOB bus. 248 // Note that the row - MATRIX_ROWS_PER_SIDE reflects the fact that being on the right hand, the columns are numbered from MATRIX_ROWS_PER_SIDE to MATRIX_ROWS, but the pins we want to write to are indexed from zero up on the GPIOB bus.
251 uint8_t buf[] = {GPIOB, 0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))}; 249 uint8_t buf[] = {GPIOB, 0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))};
252 mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT); 250 mcp23017_status = i2c_transmit(I2C_ADDR, buf, sizeof(buf), I2C_TIMEOUT);
253 } 251 }
254 } 252 }
255} 253}
diff --git a/keyboards/kagizaraya/chidori/board.c b/keyboards/kagizaraya/chidori/board.c
index 117a4c0127..34e57a8874 100644
--- a/keyboards/kagizaraya/chidori/board.c
+++ b/keyboards/kagizaraya/chidori/board.c
@@ -124,10 +124,9 @@ static void board_slave_init(void) {
124 if (board_is_master(board)) { 124 if (board_is_master(board)) {
125 continue; 125 continue;
126 } 126 }
127 if (i2c_start(EXPANDER_ADDR(board->i2c_address), BOARD_I2C_TIMEOUT) != I2C_STATUS_SUCCESS) { 127 if (i2c_ping_address(EXPANDER_ADDR(board->i2c_address), BOARD_I2C_TIMEOUT) != I2C_STATUS_SUCCESS) {
128 continue; 128 continue;
129 } 129 }
130 i2c_stop();
131 if (board_slave_config(board)) { 130 if (board_slave_config(board)) {
132 board->initialized = true; 131 board->initialized = true;
133 } 132 }
diff --git a/keyboards/nek_type_a/nek_type_a.h b/keyboards/nek_type_a/nek_type_a.h
index dda9e2bdde..fe6fb27a45 100644
--- a/keyboards/nek_type_a/nek_type_a.h
+++ b/keyboards/nek_type_a/nek_type_a.h
@@ -21,9 +21,7 @@
21#include <stdbool.h> 21#include <stdbool.h>
22#include <util/delay.h> 22#include <util/delay.h>
23 23
24#define I2C_ADDR 0b0100000 24#define I2C_ADDR (0b0100000<<1)
25#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
26#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
27#define IODIRA 0x00 // i/o direction register 25#define IODIRA 0x00 // i/o direction register
28#define IODIRB 0x01 26#define IODIRB 0x01
29#define GPPUA 0x0C // GPIO pull-up resistor register 27#define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/keyboards/system76/launch_1/usb_mux.c b/keyboards/system76/launch_1/usb_mux.c
index 1c6dd2376e..dd51b7c4b2 100644
--- a/keyboards/system76/launch_1/usb_mux.c
+++ b/keyboards/system76/launch_1/usb_mux.c
@@ -77,51 +77,14 @@ i2c_status_t usb7206_read_reg(struct USB7206* self, uint32_t addr, uint8_t* data
77 return status; 77 return status;
78 } 78 }
79 79
80 uint8_t read[2] = { 80 uint16_t read = 0x0006; // Buffer address 6 to skip header
81 0x00, // Buffer address MSB: always 0 81 uint8_t data_with_buffer_length[length];
82 0x06, // Buffer address LSB: 6 to skip header 82 status = i2c_readReg16((self->addr << 1), read, data_with_buffer_length, length, I2C_TIMEOUT);
83 };
84
85 status = i2c_start((self->addr << 1) | I2C_WRITE, I2C_TIMEOUT);
86 if (status >= 0) {
87 for (uint16_t i = 0; i < sizeof(read); i++) {
88 status = i2c_write(read[i], I2C_TIMEOUT);
89 if (status < 0) {
90 goto error;
91 }
92 }
93 } else {
94 goto error;
95 }
96
97 status = i2c_start((self->addr << 1) | I2C_READ, I2C_TIMEOUT);
98 if (status < 0) {
99 goto error;
100 }
101
102 // Read and ignore buffer length
103 status = i2c_read_ack(I2C_TIMEOUT);
104 if (status < 0) {
105 goto error;
106 }
107 83
108 for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { 84 for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
109 status = i2c_read_ack(I2C_TIMEOUT); 85 data[i] = data_with_buffer_length[i+1];
110 if (status >= 0) {
111 data[i] = (uint8_t)status;
112 }
113 } 86 }
114 87
115 if (status >= 0) {
116 status = i2c_read_nack(I2C_TIMEOUT);
117 if (status >= 0) {
118 data[(length - 1)] = (uint8_t)status;
119 }
120 }
121
122error:
123 i2c_stop();
124
125 return (status < 0) ? status : length; 88 return (status < 0) ? status : length;
126} 89}
127 90
@@ -160,35 +123,21 @@ i2c_status_t usb7206_write_reg(struct USB7206* self, uint32_t addr, uint8_t* dat
160 (uint8_t)(addr >> 8), // Register address byte 1 123 (uint8_t)(addr >> 8), // Register address byte 1
161 (uint8_t)(addr >> 0), // Register address byte 0 124 (uint8_t)(addr >> 0), // Register address byte 0
162 }; 125 };
126 uint8_t send_buffer_length = sizeof(register_write) + length;
127 uint8_t send_buffer[send_buffer_length];
128 uint8_t j = 0;
163 129
164 status = i2c_start((self->addr << 1) | I2C_WRITE, I2C_TIMEOUT); 130 for (uint16_t i = 0; i < sizeof(register_write); i++) {
165 if (status >= 0) { 131 send_buffer[j++] = register_write[i];
166 for (uint16_t i = 0; i < sizeof(register_write); i++) { 132 }
167 status = i2c_write(register_write[i], I2C_TIMEOUT);
168 if (status < 0) {
169 goto error;
170 }
171 }
172 133
173 for (uint16_t i = 0; i < length; i++) { 134 for (uint16_t i = 0; i < length; i++) {
174 status = i2c_write(data[i], I2C_TIMEOUT); 135 send_buffer[j++] = data[i];
175 if (status < 0) {
176 goto error;
177 }
178 }
179 } else {
180 goto error;
181 } 136 }
182 137
183 i2c_stop(); 138 status = i2c_transmit((self->addr << 1), send_buffer, send_buffer_length, I2C_TIMEOUT);
184 139
185 status = usb7206_register_access(self); 140 status = usb7206_register_access(self);
186 if (status < 0) {
187 goto error;
188 }
189
190error:
191 i2c_stop();
192 141
193 return (status < 0) ? status : length; 142 return (status < 0) ? status : length;
194} 143}
diff --git a/keyboards/ymdk/sp64/matrix.c b/keyboards/ymdk/sp64/matrix.c
index b5f0e10462..6f8c7962eb 100644
--- a/keyboards/ymdk/sp64/matrix.c
+++ b/keyboards/ymdk/sp64/matrix.c
@@ -114,7 +114,7 @@ uint8_t matrix_scan(void)
114#ifdef RIGHT_HALF 114#ifdef RIGHT_HALF
115 uint8_t data = 0x7F; 115 uint8_t data = 0x7F;
116 // Receive the columns from right half 116 // Receive the columns from right half
117 i2c_receive(I2C_ADDR_WRITE, &data, 1, MCP23018_I2C_TIMEOUT); 117 i2c_receive(I2C_ADDR, &data, 1, MCP23018_I2C_TIMEOUT);
118 cols |= ((~(data) & 0x7F) << 7); 118 cols |= ((~(data) & 0x7F) << 7);
119#endif 119#endif
120 120
@@ -162,7 +162,7 @@ static void matrix_select_row(uint8_t row)
162 //Set the remote row on port A 162 //Set the remote row on port A
163 txdata[0] = GPIOA; 163 txdata[0] = GPIOA;
164 txdata[1] = 0xFF & ~(1<<row); 164 txdata[1] = 0xFF & ~(1<<row);
165 mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)txdata, 2, MCP23018_I2C_TIMEOUT); 165 mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)txdata, 2, MCP23018_I2C_TIMEOUT);
166#endif 166#endif
167 167
168 // select other half 168 // select other half
diff --git a/keyboards/ymdk/sp64/sp64.c b/keyboards/ymdk/sp64/sp64.c
index 12f2577713..e9f30d91f9 100644
--- a/keyboards/ymdk/sp64/sp64.c
+++ b/keyboards/ymdk/sp64/sp64.c
@@ -39,7 +39,7 @@ uint8_t init_mcp23018(void)
39 data[0] = IODIRA; 39 data[0] = IODIRA;
40 data[1] = 0b00000000; 40 data[1] = 0b00000000;
41 data[2] = 0b11111111; 41 data[2] = 0b11111111;
42 mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT); 42 mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
43 if (mcp23018_status != I2C_STATUS_SUCCESS) 43 if (mcp23018_status != I2C_STATUS_SUCCESS)
44 goto out; 44 goto out;
45 45
@@ -50,7 +50,7 @@ uint8_t init_mcp23018(void)
50 data[0] = GPPUA; 50 data[0] = GPPUA;
51 data[1] = 0b00000000; 51 data[1] = 0b00000000;
52 data[2] = 0b11111111; 52 data[2] = 0b11111111;
53 mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT); 53 mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
54 if (mcp23018_status != I2C_STATUS_SUCCESS) 54 if (mcp23018_status != I2C_STATUS_SUCCESS)
55 goto out; 55 goto out;
56 56
@@ -61,7 +61,7 @@ uint8_t init_mcp23018(void)
61 data[0] = OLATA; 61 data[0] = OLATA;
62 data[1] = 0b11111111; 62 data[1] = 0b11111111;
63 data[2] = 0b11111111; 63 data[2] = 0b11111111;
64 mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT); 64 mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
65 65
66out: 66out:
67 return (mcp23018_status); 67 return (mcp23018_status);
diff --git a/keyboards/ymdk/sp64/sp64.h b/keyboards/ymdk/sp64/sp64.h
index afad36ee9a..0e3e3c38b8 100644
--- a/keyboards/ymdk/sp64/sp64.h
+++ b/keyboards/ymdk/sp64/sp64.h
@@ -23,9 +23,7 @@
23# include "i2c_master.h" 23# include "i2c_master.h"
24 24
25// I2C aliases and register addresses (see "mcp23018.md") 25// I2C aliases and register addresses (see "mcp23018.md")
26# define I2C_ADDR 0b0100000 26# define I2C_ADDR (0b0100000<<1)
27# define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
28# define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
29# define IODIRA 0x00 // i/o direction register 27# define IODIRA 0x00 // i/o direction register
30# define IODIRB 0x01 28# define IODIRB 0x01
31# define GPPUA 0x0C // GPIO pull-up resistor register 29# define GPPUA 0x0C // GPIO pull-up resistor register
diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c
index 0183103707..64083d862a 100644
--- a/platforms/avr/drivers/i2c_master.c
+++ b/platforms/avr/drivers/i2c_master.c
@@ -24,6 +24,7 @@
24#include "timer.h" 24#include "timer.h"
25#include "wait.h" 25#include "wait.h"
26#include "util.h" 26#include "util.h"
27#include "progmem.h"
27 28
28#ifndef F_SCL 29#ifndef F_SCL
29# define F_SCL 400000UL // SCL frequency 30# define F_SCL 400000UL // SCL frequency
@@ -38,7 +39,7 @@
38 39
39#define TWBR_val (((F_CPU / F_SCL) - 16) / 2) 40#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
40 41
41void i2c_init(void) { 42__attribute__((weak)) void i2c_init(void) {
42 TWSR = 0; /* no prescaler */ 43 TWSR = 0; /* no prescaler */
43 TWBR = (uint8_t)TWBR_val; 44 TWBR = (uint8_t)TWBR_val;
44 45
@@ -94,7 +95,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
94 return I2C_STATUS_SUCCESS; 95 return I2C_STATUS_SUCCESS;
95} 96}
96 97
97i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { 98__attribute__((always_inline)) static inline i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
98 // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled. 99 // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
99 uint16_t timeout_timer = timer_read(); 100 uint16_t timeout_timer = timer_read();
100 uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries 101 uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries
@@ -105,6 +106,11 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
105 return status; 106 return status;
106} 107}
107 108
109__attribute__((always_inline)) static inline void i2c_stop(void) {
110 // transmit STOP condition
111 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
112}
113
108i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { 114i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
109 // load data into data register 115 // load data into data register
110 TWDR = data; 116 TWDR = data;
@@ -167,6 +173,18 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,
167 return status; 173 return status;
168} 174}
169 175
176i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
177 i2c_status_t status = i2c_start(address | I2C_ACTION_WRITE, timeout);
178
179 for (uint16_t i = 0; i < length && status >= 0; i++) {
180 status = i2c_write(pgm_read_byte((const char*)data++), timeout);
181 }
182
183 i2c_stop();
184
185 return status;
186}
187
170i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { 188i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
171 i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout); 189 i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);
172 190
@@ -293,7 +311,8 @@ error:
293 return (status < 0) ? status : I2C_STATUS_SUCCESS; 311 return (status < 0) ? status : I2C_STATUS_SUCCESS;
294} 312}
295 313
296void i2c_stop(void) { 314__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
297 // transmit STOP condition 315 i2c_status_t status = i2c_start(address, timeout);
298 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); 316 i2c_stop();
299} 317 return status;
318} \ No newline at end of file
diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h
index 18587c4a57..b797997619 100644
--- a/platforms/avr/drivers/i2c_master.h
+++ b/platforms/avr/drivers/i2c_master.h
@@ -41,14 +41,11 @@ typedef int16_t i2c_status_t;
41#define I2C_TIMEOUT_INFINITE (0xFFFF) 41#define I2C_TIMEOUT_INFINITE (0xFFFF)
42 42
43void i2c_init(void); 43void i2c_init(void);
44i2c_status_t i2c_start(uint8_t address, uint16_t timeout);
45i2c_status_t i2c_write(uint8_t data, uint16_t timeout);
46int16_t i2c_read_ack(uint16_t timeout);
47int16_t i2c_read_nack(uint16_t timeout);
48i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); 44i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
45i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
49i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 46i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
50i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 47i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
51i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 48i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
52i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 49i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
53i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 50i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
54void i2c_stop(void); 51i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c
index 5ee2738e6d..ad11d850dd 100644
--- a/platforms/chibios/drivers/i2c_master.c
+++ b/platforms/chibios/drivers/i2c_master.c
@@ -1,5 +1,6 @@
1/* Copyright 2018 Jack Humbert 1/* Copyright 2018 Jack Humbert
2 * Copyright 2018 Yiancar 2 * Copyright 2018 Yiancar
3 * Copyright 2023 customMK
3 * 4 *
4 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -90,8 +91,6 @@
90# endif 91# endif
91#endif 92#endif
92 93
93static uint8_t i2c_address;
94
95static const I2CConfig i2cconfig = { 94static const I2CConfig i2cconfig = {
96#if defined(USE_I2CV1_CONTRIB) 95#if defined(USE_I2CV1_CONTRIB)
97 I2C1_CLOCK_SPEED, 96 I2C1_CLOCK_SPEED,
@@ -125,7 +124,7 @@ static i2c_status_t i2c_epilogue(const msg_t status) {
125 // From ChibiOS HAL: "After a timeout the driver must be stopped and 124 // From ChibiOS HAL: "After a timeout the driver must be stopped and
126 // restarted because the bus is in an uncertain state." We also issue that 125 // restarted because the bus is in an uncertain state." We also issue that
127 // hard stop in case of any error. 126 // hard stop in case of any error.
128 i2c_stop(); 127 i2cStop(&I2C_DRIVER);
129 128
130 return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR; 129 return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR;
131} 130}
@@ -150,28 +149,19 @@ __attribute__((weak)) void i2c_init(void) {
150 } 149 }
151} 150}
152 151
153i2c_status_t i2c_start(uint8_t address) {
154 i2c_address = address;
155 i2cStart(&I2C_DRIVER, &i2cconfig);
156 return I2C_STATUS_SUCCESS;
157}
158
159i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { 152i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
160 i2c_address = address;
161 i2cStart(&I2C_DRIVER, &i2cconfig); 153 i2cStart(&I2C_DRIVER, &i2cconfig);
162 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout)); 154 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
163 return i2c_epilogue(status); 155 return i2c_epilogue(status);
164} 156}
165 157
166i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { 158i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
167 i2c_address = address;
168 i2cStart(&I2C_DRIVER, &i2cconfig); 159 i2cStart(&I2C_DRIVER, &i2cconfig);
169 msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout)); 160 msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (address >> 1), data, length, TIME_MS2I(timeout));
170 return i2c_epilogue(status); 161 return i2c_epilogue(status);
171} 162}
172 163
173i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { 164i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
174 i2c_address = devaddr;
175 i2cStart(&I2C_DRIVER, &i2cconfig); 165 i2cStart(&I2C_DRIVER, &i2cconfig);
176 166
177 uint8_t complete_packet[length + 1]; 167 uint8_t complete_packet[length + 1];
@@ -180,12 +170,11 @@ i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t*
180 } 170 }
181 complete_packet[0] = regaddr; 171 complete_packet[0] = regaddr;
182 172
183 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout)); 173 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
184 return i2c_epilogue(status); 174 return i2c_epilogue(status);
185} 175}
186 176
187i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { 177i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
188 i2c_address = devaddr;
189 i2cStart(&I2C_DRIVER, &i2cconfig); 178 i2cStart(&I2C_DRIVER, &i2cconfig);
190 179
191 uint8_t complete_packet[length + 2]; 180 uint8_t complete_packet[length + 2];
@@ -195,25 +184,27 @@ i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8
195 complete_packet[0] = regaddr >> 8; 184 complete_packet[0] = regaddr >> 8;
196 complete_packet[1] = regaddr & 0xFF; 185 complete_packet[1] = regaddr & 0xFF;
197 186
198 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout)); 187 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
199 return i2c_epilogue(status); 188 return i2c_epilogue(status);
200} 189}
201 190
202i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { 191i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
203 i2c_address = devaddr;
204 i2cStart(&I2C_DRIVER, &i2cconfig); 192 i2cStart(&I2C_DRIVER, &i2cconfig);
205 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout)); 193 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout));
206 return i2c_epilogue(status); 194 return i2c_epilogue(status);
207} 195}
208 196
209i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { 197i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
210 i2c_address = devaddr;
211 i2cStart(&I2C_DRIVER, &i2cconfig); 198 i2cStart(&I2C_DRIVER, &i2cconfig);
212 uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF}; 199 uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};
213 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), register_packet, 2, data, length, TIME_MS2I(timeout)); 200 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
214 return i2c_epilogue(status); 201 return i2c_epilogue(status);
215} 202}
216 203
217void i2c_stop(void) { 204__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
218 i2cStop(&I2C_DRIVER); 205 // ChibiOS does not provide low level enough control to check for an ack.
219} 206 // Best effort instead tries reading register 0 which will either succeed or timeout.
207 // This approach may produce false negative results for I2C devices that do not respond to a register 0 read request.
208 uint8_t data = 0;
209 return i2c_readReg(address, 0, &data, sizeof(data), timeout);
210} \ No newline at end of file
diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h
index 5f16367831..132ffd14c0 100644
--- a/platforms/chibios/drivers/i2c_master.h
+++ b/platforms/chibios/drivers/i2c_master.h
@@ -40,11 +40,10 @@ typedef int16_t i2c_status_t;
40#define I2C_STATUS_TIMEOUT (-2) 40#define I2C_STATUS_TIMEOUT (-2)
41 41
42void i2c_init(void); 42void i2c_init(void);
43i2c_status_t i2c_start(uint8_t address);
44i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); 43i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
45i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 44i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
46i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 45i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
47i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 46i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
48i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 47i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
49i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 48i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
50void i2c_stop(void); 49i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);