forked from mirrors/qmk_firmware
I2C driver cleanup (#21273)
* remove i2c_start and i2c_stop from i2c drivers * remove static i2c_address variable from chibios i2c driver
This commit is contained in:
parent
2b0965944d
commit
e9bd7d7ad3
49 changed files with 280 additions and 603 deletions
|
@ -138,23 +138,6 @@ void i2c_init(void) {
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)` :id=api-i2c-start
|
|
||||||
|
|
||||||
Start an I2C transaction.
|
|
||||||
|
|
||||||
#### Arguments :id=api-i2c-start-arguments
|
|
||||||
|
|
||||||
- `uint8_t address`
|
|
||||||
The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
|
|
||||||
- `uint16_t timeout`
|
|
||||||
The time in milliseconds to wait for a response from the target device.
|
|
||||||
|
|
||||||
#### Return Value :id=api-i2c-start-return
|
|
||||||
|
|
||||||
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit
|
### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit
|
||||||
|
|
||||||
Send multiple bytes to the selected I2C device.
|
Send 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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `i2c_status_t i2c_stop(void)` :id=api-i2c-stop
|
### `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout)` :id=api-i2c-ping-address
|
||||||
|
|
||||||
Stop the current I2C transaction.
|
Pings the I2C bus for a specific address.
|
||||||
|
|
||||||
|
On ChibiOS a "best effort" attempt is made by reading a single byte from register 0 at the requested address. This should generally work except for I2C devices that do not not respond to a register 0 read request, which will result in a false negative result (unsucessful response to ping attempt).
|
||||||
|
|
||||||
|
This function is weakly defined, meaning it can be overridden if necessary for your particular use case:
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
- `uint8_t address`
|
||||||
|
The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
|
||||||
|
- `uint16_t timeout`
|
||||||
|
The time in milliseconds to wait for a response from the target device.
|
||||||
|
|
||||||
|
#### Return Value
|
||||||
|
|
||||||
|
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
||||||
|
|
|
@ -23,12 +23,11 @@ I2C アドレスと他の技術詳細について、さらなる情報を得る
|
||||||
| 関数 | 説明 |
|
| 関数 | 説明 |
|
||||||
|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `void i2c_init(void);` | I2C ドライバを初期化します。他のあらゆるトランザクションを開始する前に、この関数を一度だけ呼ぶ必要があります。 |
|
| `void i2c_init(void);` | I2C ドライバを初期化します。他のあらゆるトランザクションを開始する前に、この関数を一度だけ呼ぶ必要があります。 |
|
||||||
| `i2c_status_t i2c_start(uint8_t address, uint16_t timeout);` | I2C トランザクションを開始します。アドレスは方向ビットのない7ビットスレーブアドレスです。 |
|
|
||||||
| `i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを送信します。アドレスは方向ビットのない7ビットスレーブアドレスです。トランザクションのステータスを返します。 |
|
| `i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを送信します。アドレスは方向ビットのない7ビットスレーブアドレスです。トランザクションのステータスを返します。 |
|
||||||
| `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを受信します。アドレスは方向ビットのない7ビットスレーブアドレスです。 `length` で指定した長さのバイト列を `data` に保存し、トランザクションのステータスを返します。 |
|
| `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを受信します。アドレスは方向ビットのない7ビットスレーブアドレスです。 `length` で指定した長さのバイト列を `data` に保存し、トランザクションのステータスを返します。 |
|
||||||
| `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_transmit` と同様ですが、 `regaddr` でスレーブのデータ書き込み先のレジスタを指定します。 |
|
| `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_transmit` と同様ですが、 `regaddr` でスレーブのデータ書き込み先のレジスタを指定します。 |
|
||||||
| `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_receive` と同様ですが、 `regaddr` でスレーブのデータ読み込み先のレジスタを指定します。 |
|
| `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_receive` と同様ですが、 `regaddr` でスレーブのデータ読み込み先のレジスタを指定します。 |
|
||||||
| `i2c_status_t i2c_stop(void);` | I2C トランザクションを終了します。 |
|
| `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);` | I2C アドレスをテストします。アドレスは方向ビットのない7ビットスレーブアドレスです。 |
|
||||||
|
|
||||||
### 関数の戻り値 :id=function-return
|
### 関数の戻り値 :id=function-return
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,6 @@ void pca9505_init(uint8_t slave_addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: could check device connected
|
// TODO: could check device connected
|
||||||
// i2c_start(SLAVE_TO_ADDR(slave) | I2C_WRITE);
|
|
||||||
// i2c_stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pca9505_set_config(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) {
|
bool pca9505_set_config(uint8_t slave_addr, pca9505_port_t port, uint8_t conf) {
|
||||||
|
|
|
@ -29,8 +29,6 @@ void pca9555_init(uint8_t slave_addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: could check device connected
|
// TODO: could check device connected
|
||||||
// i2c_start(SLAVE_TO_ADDR(slave) | I2C_WRITE);
|
|
||||||
// i2c_stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pca9555_set_config(uint8_t slave_addr, pca9555_port_t port, uint8_t conf) {
|
bool pca9555_set_config(uint8_t slave_addr, pca9555_port_t port, uint8_t conf) {
|
||||||
|
|
|
@ -223,13 +223,8 @@ __attribute__((weak)) bool oled_send_cmd_P(const uint8_t *data, uint16_t size) {
|
||||||
spi_stop();
|
spi_stop();
|
||||||
return (status >= 0);
|
return (status >= 0);
|
||||||
# elif defined(OLED_TRANSPORT_I2C)
|
# elif defined(OLED_TRANSPORT_I2C)
|
||||||
i2c_status_t status = i2c_start((OLED_DISPLAY_ADDRESS << 1) | I2C_WRITE, OLED_I2C_TIMEOUT);
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < size && status >= 0; i++) {
|
i2c_status_t status = i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), data, size, OLED_I2C_TIMEOUT);
|
||||||
status = i2c_write(pgm_read_byte((const char *)data++), OLED_I2C_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
return (status == I2C_STATUS_SUCCESS);
|
return (status == I2C_STATUS_SUCCESS);
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -28,18 +28,14 @@ bool qp_comms_i2c_init(painter_device_t device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool qp_comms_i2c_start(painter_device_t device) {
|
bool qp_comms_i2c_start(painter_device_t device) {
|
||||||
painter_driver_t * driver = (painter_driver_t *)device;
|
return true;
|
||||||
qp_comms_i2c_config_t *comms_config = (qp_comms_i2c_config_t *)driver->comms_config;
|
|
||||||
return i2c_start(comms_config->chip_address << 1) == I2C_STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
|
uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
|
||||||
return qp_comms_i2c_send_raw(device, data, byte_count);
|
return qp_comms_i2c_send_raw(device, data, byte_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qp_comms_i2c_stop(painter_device_t device) {
|
void qp_comms_i2c_stop(painter_device_t device) {}
|
||||||
i2c_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Command+Data I2C support
|
// Command+Data I2C support
|
||||||
|
|
|
@ -19,7 +19,6 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
|
||||||
pd_dprintf("error cirque_pinnacle i2c_read_register\n");
|
pd_dprintf("error cirque_pinnacle i2c_read_register\n");
|
||||||
touchpad_init = false;
|
touchpad_init = false;
|
||||||
}
|
}
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +31,5 @@ void RAP_Write(uint8_t address, uint8_t data) {
|
||||||
pd_dprintf("error cirque_pinnacle i2c_write_register\n");
|
pd_dprintf("error cirque_pinnacle i2c_write_register\n");
|
||||||
touchpad_init = false;
|
touchpad_init = false;
|
||||||
}
|
}
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ static uint16_t i2c_timeout_timer;
|
||||||
|
|
||||||
void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
|
void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
|
||||||
uint8_t data[] = {0x00, red, green, blue, white};
|
uint8_t data[] = {0x00, red, green, blue, white};
|
||||||
i2c_transmit(TRACKBALL_WRITE, data, sizeof(data), I2C_TIMEOUT);
|
i2c_transmit(TRACKBALL_ADDRESS, data, sizeof(data), I2C_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) {
|
int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) {
|
||||||
|
@ -120,7 +120,7 @@ bool pointing_device_task(void) {
|
||||||
static uint16_t debounce_timer;
|
static uint16_t debounce_timer;
|
||||||
uint8_t state[5] = {};
|
uint8_t state[5] = {};
|
||||||
if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) {
|
if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) {
|
||||||
if (i2c_read_register(TRACKBALL_WRITE, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
|
if (i2c_read_register(TRACKBALL_ADDRESS, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
|
||||||
if (!state[4] && !debounce) {
|
if (!state[4] && !debounce) {
|
||||||
if (scrolling) {
|
if (scrolling) {
|
||||||
#ifdef PIMORONI_TRACKBALL_INVERT_X
|
#ifdef PIMORONI_TRACKBALL_INVERT_X
|
||||||
|
|
|
@ -20,10 +20,8 @@
|
||||||
#include "pointing_device.h"
|
#include "pointing_device.h"
|
||||||
|
|
||||||
#ifndef TRACKBALL_ADDRESS
|
#ifndef TRACKBALL_ADDRESS
|
||||||
# define TRACKBALL_ADDRESS 0x0A
|
# define TRACKBALL_ADDRESS (0x0A << 1)
|
||||||
#endif
|
#endif
|
||||||
#define TRACKBALL_WRITE ((TRACKBALL_ADDRESS << 1) | I2C_WRITE)
|
|
||||||
#define TRACKBALL_READ ((TRACKBALL_ADDRESS << 1) | I2C_READ)
|
|
||||||
|
|
||||||
void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
|
void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
|
||||||
void trackball_check_click(bool pressed, report_mouse_t *mouse);
|
void trackball_check_click(bool pressed, report_mouse_t *mouse);
|
||||||
|
|
|
@ -137,23 +137,16 @@ uint8_t init_mcp23018(void) {
|
||||||
// - unused : input : 1
|
// - unused : input : 1
|
||||||
// - input : input : 1
|
// - input : input : 1
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data[] = {0b00000000, 0b00111111};
|
||||||
mcp23018_status = i2c_write(IODIRA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b00000000, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b00111111, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// set pull-up
|
if (!mcp23018_status) {
|
||||||
// - unused : on : 1
|
// set pull-up
|
||||||
// - input : on : 1
|
// - unused : on : 1
|
||||||
// - driving : off : 0
|
// - input : on : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
// - driving : off : 0
|
||||||
mcp23018_status = i2c_write(GPPUA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b00000000, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
}
|
||||||
mcp23018_status = i2c_write(0b01111111, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
#ifdef LEFT_LEDS
|
#ifdef LEFT_LEDS
|
||||||
if (!mcp23018_status) mcp23018_status = bajjak_left_leds_update();
|
if (!mcp23018_status) mcp23018_status = bajjak_left_leds_update();
|
||||||
|
@ -176,21 +169,11 @@ uint8_t bajjak_left_leds_update(void) {
|
||||||
// - unused : hi-Z : 1
|
// - unused : hi-Z : 1
|
||||||
// - input : hi-Z : 1
|
// - input : hi-Z : 1
|
||||||
// - driving : hi-Z : 1
|
// - driving : hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT);
|
uint8_t data[2];
|
||||||
if (mcp23018_status) goto out;
|
data[0] = 0b11111111 & ~(bajjak_left_led_1<<LEFT_LED_1_SHIFT);
|
||||||
mcp23018_status = i2c_write(OLATA, BAJJAK_EZ_I2C_TIMEOUT);
|
data[1] = 0b11111111 & ~(bajjak_left_led_2<<LEFT_LED_2_SHIFT);
|
||||||
if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, OLATA, data, 2, BAJJAK_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b11111111
|
|
||||||
& ~(bajjak_left_led_1<<LEFT_LED_1_SHIFT),
|
|
||||||
BAJJAK_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11111111
|
|
||||||
& ~(bajjak_left_led_2<<LEFT_LED_2_SHIFT),
|
|
||||||
BAJJAK_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return mcp23018_status;
|
return mcp23018_status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,9 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "i2c_master.h"
|
#include "i2c_master.h"
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md")
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0b0100000<<1)
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -145,12 +145,7 @@ static matrix_row_t read_cols(uint8_t row) {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
// reading GPIOB (column port) since in mcp23018's sequential mode
|
// reading GPIOB (column port) since in mcp23018's sequential mode
|
||||||
// it is addressed directly after writing to GPIOA in select_row()
|
// it is addressed directly after writing to GPIOA in select_row()
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_READ, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_receive(I2C_ADDR, &data, 1, BAJJAK_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_read_nack(BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
|
|
||||||
data = ~((uint8_t)mcp23018_status);
|
|
||||||
mcp23018_status = I2C_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -195,11 +190,10 @@ static void select_row(uint8_t row) {
|
||||||
if (!mcp23018_status) {
|
if (!mcp23018_status) {
|
||||||
// set active row low : 0
|
// set active row low : 0
|
||||||
// set other rows hi-Z : 1
|
// set other rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data;
|
||||||
mcp23018_status = i2c_write(GPIOA, BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
data = 0xFF & ~(1 << row);
|
||||||
mcp23018_status = i2c_write(0xFF & ~(1 << row), BAJJAK_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, BAJJAK_EZ_I2C_TIMEOUT);
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// select on teensy
|
// select on teensy
|
||||||
|
|
|
@ -387,37 +387,13 @@ static void unselect_cols(void)
|
||||||
|
|
||||||
// Complete rows from other modules over i2c
|
// Complete rows from other modules over i2c
|
||||||
i2c_status_t i2c_transaction(uint8_t address, uint32_t mask, uint8_t col_offset) {
|
i2c_status_t i2c_transaction(uint8_t address, uint32_t mask, uint8_t col_offset) {
|
||||||
i2c_status_t status = i2c_start(address, 5);
|
uint8_t data[MATRIX_ROWS + 1];
|
||||||
if (status < 0) {
|
i2c_status_t status = i2c_readReg(address, 0x01, data, (MATRIX_ROWS + 1), 5);
|
||||||
goto error;
|
|
||||||
|
for (uint8_t i = 0; i < (MATRIX_ROWS) && status >= 0; i++) { //assemble slave matrix in main matrix
|
||||||
|
matrix[i] &= mask; //mask bits to keep
|
||||||
|
matrix[i] |= ((uint32_t)data[i+1] << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
|
||||||
}
|
}
|
||||||
|
|
||||||
status = i2c_write(0x01, 50);
|
return status;
|
||||||
if (status < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = i2c_start(address | I2C_READ, 50);
|
|
||||||
|
|
||||||
status = i2c_read_ack(50);
|
|
||||||
if (status != 0x55) { //synchronization byte
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < MATRIX_ROWS-1 && status >= 0; i++) { //assemble slave matrix in main matrix
|
|
||||||
matrix[i] &= mask; //mask bits to keep
|
|
||||||
status = i2c_read_ack(50);
|
|
||||||
matrix[i] |= ((uint32_t)status << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
|
|
||||||
}
|
|
||||||
//last read request must be followed by a NACK
|
|
||||||
if (status >= 0) {
|
|
||||||
matrix[MATRIX_ROWS - 1] &= mask; //mask bits to keep
|
|
||||||
status = i2c_read_nack(50);
|
|
||||||
matrix[MATRIX_ROWS - 1] |= ((uint32_t)status << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
return (status < 0) ? status : I2C_STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,31 +155,16 @@ uint8_t init_mcp23018(void) {
|
||||||
// - unused : input : 1
|
// - unused : input : 1
|
||||||
// - input : input : 1
|
// - input : input : 1
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
|
uint8_t data[] = {0b00000000, 0b00111111};
|
||||||
if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// set pull-up
|
if (!mcp23018_status) {
|
||||||
// - unused : on : 1
|
// set pull-up
|
||||||
// - input : on : 1
|
// - unused : on : 1
|
||||||
// - driving : off : 0
|
// - input : on : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
|
// - driving : off : 0
|
||||||
if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT);
|
}
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
#ifdef LEFT_LEDS
|
#ifdef LEFT_LEDS
|
||||||
if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update();
|
if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update();
|
||||||
|
@ -203,17 +188,11 @@ uint8_t ergodox_left_leds_update(void) {
|
||||||
// - unused : hi-Z : 1
|
// - unused : hi-Z : 1
|
||||||
// - input : hi-Z : 1
|
// - input : hi-Z : 1
|
||||||
// - driving : hi-Z : 1
|
// - driving : hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
|
uint8_t data[2];
|
||||||
if (mcp23018_status) goto out;
|
data[0] = 0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT);
|
||||||
mcp23018_status = i2c_write(OLATA, ERGODOX_EZ_I2C_TIMEOUT);
|
data[1] = 0b11111111 & ~(ergodox_left_led_2 << LEFT_LED_2_SHIFT) & ~(ergodox_left_led_1 << LEFT_LED_1_SHIFT);
|
||||||
if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, OLATA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT), ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11111111 & ~(ergodox_left_led_2 << LEFT_LED_2_SHIFT) & ~(ergodox_left_led_1 << LEFT_LED_1_SHIFT), ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return mcp23018_status;
|
return mcp23018_status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,9 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "i2c_master.h"
|
#include "i2c_master.h"
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md")
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0b0100000<<1)
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -24,30 +24,41 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
# include "ws2812.h"
|
# include "ws2812.h"
|
||||||
|
|
||||||
void setleds_custom(rgb_led_t *led, uint16_t led_num) {
|
void setleds_custom(rgb_led_t *led, uint16_t led_num) {
|
||||||
i2c_init();
|
uint16_t length = 0;
|
||||||
i2c_start(0x84, ERGODOX_EZ_I2C_TIMEOUT);
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
# ifdef RGBW
|
||||||
|
int bytes_per_led = 4;
|
||||||
|
# else
|
||||||
|
int bytes_per_led = 3;
|
||||||
|
# endif
|
||||||
# if defined(ERGODOX_LED_30)
|
# if defined(ERGODOX_LED_30)
|
||||||
// prevent right-half code from trying to bitbang all 30
|
// prevent right-half code from trying to bitbang all 30
|
||||||
// so with 30 LEDs, we count from 29 to 15 here, and the
|
// so with 30 LEDs, we count from 29 to 15 here, and the
|
||||||
// other half does 0 to 14.
|
// other half does 0 to 14.
|
||||||
uint8_t half_led_num = RGBLIGHT_LED_COUNT / 2;
|
uint8_t half_led_num = RGBLIGHT_LED_COUNT / 2;
|
||||||
|
length = half_led_num * bytes_per_led;
|
||||||
|
uint8_t data[length];
|
||||||
for (i = half_led_num + half_led_num - 1; i >= half_led_num; --i)
|
for (i = half_led_num + half_led_num - 1; i >= half_led_num; --i)
|
||||||
# elif defined(ERGODOX_LED_15_MIRROR)
|
# elif defined(ERGODOX_LED_15_MIRROR)
|
||||||
|
length = led_num * bytes_per_led;
|
||||||
|
uint8_t data[length];
|
||||||
for (i = 0; i < led_num; ++i)
|
for (i = 0; i < led_num; ++i)
|
||||||
# else // ERGDOX_LED_15 non-mirrored
|
# else // ERGDOX_LED_15 non-mirrored
|
||||||
|
length = led_num * bytes_per_led;
|
||||||
|
uint8_t data[length];
|
||||||
for (i = led_num - 1; i >= 0; --i)
|
for (i = led_num - 1; i >= 0; --i)
|
||||||
# endif
|
# endif
|
||||||
{
|
{
|
||||||
uint8_t *data = (uint8_t *)(led + i);
|
uint8_t *data_byte = (uint8_t *)(led + i);
|
||||||
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
|
data[j++] = data_byte[0];
|
||||||
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
|
data[j++] = data_byte[1];
|
||||||
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
|
data[j++] = data_byte[2];
|
||||||
#ifdef RGBW
|
#ifdef RGBW
|
||||||
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
|
data[j++] = data_byte[3];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
i2c_stop();
|
i2c_transmit(0x84, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
|
|
||||||
ws2812_setleds(led, led_num);
|
ws2812_setleds(led, led_num);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,13 +146,8 @@ static matrix_row_t read_cols(uint8_t row) {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
// reading GPIOB (column port) since in mcp23018's sequential mode
|
// reading GPIOB (column port) since in mcp23018's sequential mode
|
||||||
// it is addressed directly after writing to GPIOA in select_row()
|
// it is addressed directly after writing to GPIOA in select_row()
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_receive(I2C_ADDR, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
|
return ~data;
|
||||||
data = ~((uint8_t)mcp23018_status);
|
|
||||||
mcp23018_status = I2C_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* read from teensy
|
/* read from teensy
|
||||||
|
@ -196,11 +191,9 @@ static void select_row(uint8_t row) {
|
||||||
if (!mcp23018_status) {
|
if (!mcp23018_status) {
|
||||||
// set active row low : 0
|
// set active row low : 0
|
||||||
// set other rows hi-Z : 1
|
// set other rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data;
|
||||||
mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
data = 0xFF & ~(1 << row);
|
||||||
mcp23018_status = i2c_write(0xFF & ~(1 << row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// select on teensy
|
// select on teensy
|
||||||
|
|
|
@ -42,9 +42,7 @@ extern i2c_status_t mcp23017_status;
|
||||||
// All address pins of the mcp23017 are connected to the ground on the ferris
|
// All address pins of the mcp23017 are connected to the ground on the ferris
|
||||||
// | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
|
// | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
|
||||||
// | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
|
// | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
|
||||||
#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0b0100000 << 1)
|
||||||
#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
|
|
||||||
#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
|
|
||||||
|
|
||||||
// Register addresses
|
// Register addresses
|
||||||
// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h
|
// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h
|
||||||
|
@ -77,9 +75,9 @@ uint8_t init_mcp23017(void) {
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
// This means: we will read all the bits on GPIOA
|
// This means: we will read all the bits on GPIOA
|
||||||
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
||||||
uint8_t buf[] = {IODIRA, 0b11111111, 0b11110000};
|
uint8_t buf[] = {0b11111111, 0b11110000};
|
||||||
print("before transmit\n");
|
print("before transmit\n");
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), MCP23017_I2C_TIMEOUT);
|
mcp23017_status = i2c_writeReg(I2C_ADDR, IODIRA, buf, sizeof(buf), MCP23017_I2C_TIMEOUT)
|
||||||
uprintf("after transmit %i\n", mcp23017_status);
|
uprintf("after transmit %i\n", mcp23017_status);
|
||||||
if (!mcp23017_status) {
|
if (!mcp23017_status) {
|
||||||
// set pull-up
|
// set pull-up
|
||||||
|
@ -88,8 +86,7 @@ uint8_t init_mcp23017(void) {
|
||||||
// - driving : off : 0
|
// - driving : off : 0
|
||||||
// This means: we will read all the bits on GPIOA
|
// This means: we will read all the bits on GPIOA
|
||||||
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
||||||
uint8_t pullup_buf[] = {GPPUA, 0b11111111, 0b11110000};
|
mcp23017_status = i2c_writeReg(I2C_ADDR, GPPUA, buf, sizeof(buf), MCP23017_I2C_TIMEOUT)
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, pullup_buf, sizeof(pullup_buf), MCP23017_I2C_TIMEOUT);
|
|
||||||
uprintf("after transmit2 %i\n", mcp23017_status);
|
uprintf("after transmit2 %i\n", mcp23017_status);
|
||||||
}
|
}
|
||||||
return mcp23017_status;
|
return mcp23017_status;
|
||||||
|
@ -189,18 +186,13 @@ static matrix_row_t read_cols(uint8_t row) {
|
||||||
if (mcp23017_status) { // if there was an error
|
if (mcp23017_status) { // if there was an error
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
uint8_t buf[] = {MCP23017_GPIOA};
|
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), MCP23017_I2C_TIMEOUT);
|
|
||||||
// We read all the pins on GPIOA.
|
// We read all the pins on GPIOA.
|
||||||
// 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.
|
// 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.
|
||||||
// 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.
|
// 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.
|
||||||
// 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.
|
// 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.
|
||||||
uint8_t data[] = {0};
|
uint8_t data[] = {0};
|
||||||
if (!mcp23017_status) {
|
mcp23017_status = i2c_readReg(I2C_ADDR, MCP23017_GPIOA, data, sizeof(data), MCP23017_I2C_TIMEOUT);
|
||||||
mcp23017_status = i2c_receive(I2C_ADDR_READ, data, sizeof(data), MCP23017_I2C_TIMEOUT);
|
return ~data[0];
|
||||||
data[0] = ~(data[0]);
|
|
||||||
}
|
|
||||||
return data[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,8 +236,8 @@ static void select_row(uint8_t row) {
|
||||||
} else {
|
} else {
|
||||||
// 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.
|
// 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.
|
||||||
// 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.
|
// 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.
|
||||||
uint8_t buf[] = {MCP23017_GPIOB, 0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))};
|
uint8_t buf[] = {0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))};
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT);
|
mcp23017_status = i2c_writeReg(I2C_ADDR, MCP23017_GPIOB, buf, sizeof(buf), MCP23017_I2C_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,23 +49,17 @@ uint8_t init_mcp23018(void) {
|
||||||
// - unused : input : 1
|
// - unused : input : 1
|
||||||
// - input : input : 1
|
// - input : input : 1
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data[] = {0b00000000, 0b00111111};
|
||||||
mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// set pull-up
|
if (!mcp23018_status) {
|
||||||
// - unused : on : 1
|
// set pull-up
|
||||||
// - input : on : 1
|
// - unused : on : 1
|
||||||
// - driving : off : 0
|
// - input : on : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
// - driving : off : 0
|
||||||
mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
}
|
||||||
mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
// SREG=sreg_prev;
|
// SREG=sreg_prev;
|
||||||
//uprintf("Init %x\n", mcp23018_status);
|
//uprintf("Init %x\n", mcp23018_status);
|
||||||
return mcp23018_status;
|
return mcp23018_status;
|
||||||
|
|
|
@ -11,10 +11,7 @@ extern i2c_status_t mcp23018_status;
|
||||||
#define ERGODOX_EZ_I2C_TIMEOUT 1000
|
#define ERGODOX_EZ_I2C_TIMEOUT 1000
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md")
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
//#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0x20<<1)
|
||||||
#define I2C_ADDR 0x20
|
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -234,15 +234,8 @@ static matrix_row_t read_cols(uint8_t row)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
data = (~((uint8_t)data) >> 2) & 0x01 ;
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
|
|
||||||
data = (~((uint8_t)mcp23018_status) >> 2) & 0x01 ;
|
|
||||||
mcp23018_status = I2C_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
#ifdef DEBUG_MATRIX
|
#ifdef DEBUG_MATRIX
|
||||||
if (data != 0x00) xprintf("I2C: %d\n", data);
|
if (data != 0x00) xprintf("I2C: %d\n", data);
|
||||||
#endif
|
#endif
|
||||||
|
@ -274,11 +267,8 @@ static void select_row(uint8_t row)
|
||||||
if (mcp23018_status) { // do nothing on error
|
if (mcp23018_status) { // do nothing on error
|
||||||
// Read using bitmask
|
// Read using bitmask
|
||||||
} else { // set active row low : 0 // set other rows hi-Z : 1
|
} else { // set active row low : 0 // set other rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data = ~(1<<row);
|
||||||
mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(~(1<<row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Output low(DDR:1, PORT:0) to select
|
// Output low(DDR:1, PORT:0) to select
|
||||||
|
|
|
@ -45,23 +45,17 @@ uint8_t init_mcp23018(void) {
|
||||||
// - unused : input : 1
|
// - unused : input : 1
|
||||||
// - input : input : 1
|
// - input : input : 1
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data[] = {0b10000000, 0b11111111};
|
||||||
mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b10000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// set pull-up
|
if (!mcp23018_status) {
|
||||||
// - unused : on : 1
|
// set pull-up
|
||||||
// - input : on : 1
|
// - unused : on : 1
|
||||||
// - driving : off : 0
|
// - input : on : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
// - driving : off : 0
|
||||||
mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, 2, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b10000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
}
|
||||||
mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
// SREG=sreg_prev;
|
// SREG=sreg_prev;
|
||||||
//uprintf("Init %x\n", mcp23018_status);
|
//uprintf("Init %x\n", mcp23018_status);
|
||||||
return mcp23018_status;
|
return mcp23018_status;
|
||||||
|
|
|
@ -11,10 +11,7 @@ extern i2c_status_t mcp23018_status;
|
||||||
#define ERGODOX_EZ_I2C_TIMEOUT 1000
|
#define ERGODOX_EZ_I2C_TIMEOUT 1000
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md")
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
//#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0x20<<1)
|
||||||
#define I2C_ADDR 0x20
|
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -254,14 +254,7 @@ static matrix_row_t read_cols(uint8_t row)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
|
|
||||||
data = ~((uint8_t)mcp23018_status);
|
|
||||||
mcp23018_status = I2C_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
#ifdef DEBUG_MATRIX
|
#ifdef DEBUG_MATRIX
|
||||||
if (data != 0x00) xprintf("I2C: %d\n", data);
|
if (data != 0x00) xprintf("I2C: %d\n", data);
|
||||||
|
@ -304,11 +297,9 @@ static void select_row(uint8_t row)
|
||||||
// select on mcp23018
|
// select on mcp23018
|
||||||
if (mcp23018_status) { // do nothing on error
|
if (mcp23018_status) { // do nothing on error
|
||||||
} else { // set active row low : 0 // set other rows hi-Z : 1
|
} else { // set active row low : 0 // set other rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data = 0xFF & ~(1<<row);
|
||||||
mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0xFF & ~(1<<row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Output low(DDR:1, PORT:0) to select
|
// Output low(DDR:1, PORT:0) to select
|
||||||
|
|
|
@ -43,23 +43,17 @@ uint8_t init_mcp23018(void) {
|
||||||
// - unused : input : 1
|
// - unused : input : 1
|
||||||
// - input : input : 1
|
// - input : input : 1
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data[] = {0b10000000, 0b11111111};
|
||||||
mcp23018_status = i2c_write(IODIRA, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b10000000, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// set pull-up
|
if (!mcp23018_status) {
|
||||||
// - unused : on : 1
|
// set pull-up
|
||||||
// - input : on : 1
|
// - unused : on : 1
|
||||||
// - driving : off : 0
|
// - input : on : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
// - driving : off : 0
|
||||||
mcp23018_status = i2c_write(GPPUA, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b10000000, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
}
|
||||||
mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
// SREG=sreg_prev;
|
// SREG=sreg_prev;
|
||||||
//uprintf("Init %x\n", mcp23018_status);
|
//uprintf("Init %x\n", mcp23018_status);
|
||||||
return mcp23018_status;
|
return mcp23018_status;
|
||||||
|
|
|
@ -11,10 +11,7 @@ extern i2c_status_t mcp23018_status;
|
||||||
#define I2C_TIMEOUT 1000
|
#define I2C_TIMEOUT 1000
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md")
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
//#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0x20<<1)
|
||||||
#define I2C_ADDR 0x20
|
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -297,19 +297,12 @@ static matrix_row_t read_cols(uint8_t row) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(GPIOB, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_read_nack(I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
|
|
||||||
data = ~((uint8_t)mcp23018_status);
|
|
||||||
mcp23018_status = I2C_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
#ifdef DEBUG_MATRIX
|
#ifdef DEBUG_MATRIX
|
||||||
if (data != 0x00) xprintf("I2C: %d\n", data);
|
if (~data != 0x00) xprintf("I2C: %d\n", ~data);
|
||||||
#endif
|
#endif
|
||||||
return data;
|
return ~data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* read from teensy
|
/* read from teensy
|
||||||
|
@ -350,11 +343,8 @@ static void select_row(uint8_t row)
|
||||||
// select on mcp23018
|
// select on mcp23018
|
||||||
if (mcp23018_status) { // do nothing on error
|
if (mcp23018_status) { // do nothing on error
|
||||||
} else { // set active row low : 0 // set other rows hi-Z : 1
|
} else { // set active row low : 0 // set other rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data = 0xFF & ~(1<<row);
|
||||||
mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0xFF & ~(1<<row), I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Output low(DDR:1, PORT:0) to select
|
// Output low(DDR:1, PORT:0) to select
|
||||||
|
|
|
@ -39,30 +39,16 @@ uint8_t init_mcp23018(void) {
|
||||||
// - unused : input : 1
|
// - unused : input : 1
|
||||||
// - input : input : 1
|
// - input : input : 1
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT);
|
uint8_t data[] = {0b11000001, 0b11111111};
|
||||||
if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(IODIRA, I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11000001, I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// set pull-up
|
if (!mcp23018_status) {
|
||||||
// - unused : on : 1
|
// set pull-up
|
||||||
// - input : on : 1
|
// - unused : on : 1
|
||||||
// - driving : off : 0
|
// - input : on : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT);
|
// - driving : off : 0
|
||||||
if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(GPPUA, I2C_TIMEOUT);
|
}
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11000001, I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b11111111, I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return mcp23018_status;
|
return mcp23018_status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,7 @@ extern i2c_status_t mcp23018_status;
|
||||||
#define XXX KC_NO
|
#define XXX KC_NO
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md")
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
#define I2C_ADDR 0x20 // 0b0100000
|
#define I2C_ADDR (0x20 << 1) // 0b0100000
|
||||||
#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
|
|
||||||
#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -177,20 +177,12 @@ static matrix_row_t read_cols(uint8_t row) {
|
||||||
if (mcp23018_status) { // if there was an error
|
if (mcp23018_status) { // if there was an error
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT);
|
mcp23018_status = i2c_receive(I2C_ADDR, &data, 1, I2C_TIMEOUT);
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_read_nack(I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status < 0) goto out;
|
|
||||||
data = ~((uint8_t)mcp23018_status);
|
|
||||||
mcp23018_status = I2C_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
#ifdef DEBUG_MATRIX
|
#ifdef DEBUG_MATRIX
|
||||||
if (data != 0x00) xprintf("I2C: %d\n", data);
|
if (~data != 0x00) xprintf("I2C: %d\n", ~data);
|
||||||
#endif
|
#endif
|
||||||
return data;
|
return ~data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ~((((PINF & COL4) >> 1) | ((PINF & (COL1 | COL2 | COL3)) >> 3)) & 0xF);
|
return ~((((PINF & COL4) >> 1) | ((PINF & (COL1 | COL2 | COL3)) >> 3)) & 0xF);
|
||||||
|
@ -213,14 +205,10 @@ static void select_row(uint8_t row) {
|
||||||
// select on mcp23018
|
// select on mcp23018
|
||||||
if (mcp23018_status) { // do nothing on error
|
if (mcp23018_status) { // do nothing on error
|
||||||
} else { // set active row low : 0 // set other rows hi-Z : 1
|
} else { // set active row low : 0 // set other rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT);
|
uint8_t data;
|
||||||
if (mcp23018_status) goto out;
|
data = 0xFF & ~(1 << (row + 1));
|
||||||
mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT);
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0xFF & ~(1 << (row + 1)), I2C_TIMEOUT);
|
|
||||||
if (mcp23018_status) goto out;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setPinOutput(row_pins[row - MATRIX_ROWS_PER_SIDE]);
|
setPinOutput(row_pins[row - MATRIX_ROWS_PER_SIDE]);
|
||||||
|
|
|
@ -14,7 +14,6 @@ void ds1307_set_time(uint8_t h, uint8_t m, uint8_t s) {
|
||||||
void ds1307_get_time(uint8_t *h, uint8_t *m, uint8_t *s) {
|
void ds1307_get_time(uint8_t *h, uint8_t *m, uint8_t *s) {
|
||||||
uint8_t data[3];
|
uint8_t data[3];
|
||||||
i2c_read_register(DS1307_ADDR, 0, data, 3, 100);
|
i2c_read_register(DS1307_ADDR, 0, data, 3, 100);
|
||||||
i2c_stop();
|
|
||||||
*s = (data[0] & 0b1111) + ((data[0] & 0b1110000) >> 4) * 10;
|
*s = (data[0] & 0b1111) + ((data[0] & 0b1110000) >> 4) * 10;
|
||||||
*m = (data[1] & 0b1111) + ((data[1] & 0b1110000) >> 4) * 10;
|
*m = (data[1] & 0b1111) + ((data[1] & 0b1110000) >> 4) * 10;
|
||||||
*h = (data[2] & 0b1111) + ((data[2] & 0b0110000) >> 4) * 10;
|
*h = (data[2] & 0b1111) + ((data[2] & 0b0110000) >> 4) * 10;
|
||||||
|
|
|
@ -83,23 +83,16 @@ uint8_t init_mcp23018(void) {
|
||||||
// - unused : input : 1
|
// - unused : input : 1
|
||||||
// - input : input : 1
|
// - input : input : 1
|
||||||
// - driving : output : 0
|
// - driving : output : 0
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data[] = {0b00000000, 0b00111111};
|
||||||
mcp23018_status = i2c_write(IODIRA, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b00000000, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_write(0b00111111, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// set pull-up
|
if (!mcp23018_status) {
|
||||||
// - unused : on : 1
|
// set pull-up
|
||||||
// - input : on : 1
|
// - unused : on : 1
|
||||||
// - driving : off : 0
|
// - input : on : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
// - driving : off : 0
|
||||||
mcp23018_status = i2c_write(GPPUA, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(0b00000000, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
}
|
||||||
mcp23018_status = i2c_write(0b00111111, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
// SREG=sreg_prev;
|
// SREG=sreg_prev;
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,7 @@
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md" on tmk repository)
|
// I2C aliases and register addresses (see "mcp23018.md" on tmk repository)
|
||||||
#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0b0100000<<1)
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -224,15 +224,9 @@ static matrix_row_t read_cols(uint8_t row)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_readReg(I2C_ADDR, GPIOB, &data, 1, I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write(GPIOB, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
return ~data;
|
||||||
data = i2c_read_nack(I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
|
|
||||||
data = ~((uint8_t)mcp23018_status);
|
|
||||||
mcp23018_status = I2C_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// read from teensy
|
// read from teensy
|
||||||
|
@ -263,11 +257,10 @@ static void unselect_rows(void)
|
||||||
// do nothing
|
// do nothing
|
||||||
} else {
|
} else {
|
||||||
// set all rows hi-Z : 1
|
// set all rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data;
|
||||||
mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
data = 0xFF & ~(0<<8);
|
||||||
mcp23018_status = i2c_write( 0xFF & ~(0<<8), I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unselect on teensy
|
// unselect on teensy
|
||||||
|
@ -289,11 +282,8 @@ static void select_row(uint8_t row)
|
||||||
} else {
|
} else {
|
||||||
// set active row low : 0
|
// set active row low : 0
|
||||||
// set other rows hi-Z : 1
|
// set other rows hi-Z : 1
|
||||||
mcp23018_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
uint8_t data = 0xFF & ~(1<<row) & ~(0<<8);
|
||||||
mcp23018_status = i2c_write(GPIOA, I2C_TIMEOUT); if (mcp23018_status) goto out;
|
mcp23018_status = i2c_writeReg(I2C_ADDR, GPIOA, &data, 1, I2C_TIMEOUT);
|
||||||
mcp23018_status = i2c_write( 0xFF & ~(1<<row) & ~(0<<8), I2C_TIMEOUT); if (mcp23018_status) goto out;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// select on teensy
|
// select on teensy
|
||||||
|
|
|
@ -8,16 +8,6 @@
|
||||||
// TODO: remove patch
|
// TODO: remove patch
|
||||||
#ifdef PROTOCOL_CHIBIOS
|
#ifdef PROTOCOL_CHIBIOS
|
||||||
# pragma message("ChibiOS is currently 'best effort' and might not report accurate results")
|
# pragma message("ChibiOS is currently 'best effort' and might not report accurate results")
|
||||||
|
|
||||||
i2c_status_t i2c_start_bodge(uint8_t address, uint16_t timeout) {
|
|
||||||
i2c_start(address);
|
|
||||||
|
|
||||||
// except on ChibiOS where the only way is do do "something"
|
|
||||||
uint8_t data = 0;
|
|
||||||
return i2c_read_register(address, 0, &data, sizeof(data), TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
# define i2c_start i2c_start_bodge
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
@ -31,10 +21,9 @@ void do_scan(void) {
|
||||||
|
|
||||||
for (uint8_t address = 1; address < 127; address++) {
|
for (uint8_t address = 1; address < 127; address++) {
|
||||||
// The i2c_scanner uses the return value of
|
// The i2c_scanner uses the return value of
|
||||||
// i2c_start to see if a device did acknowledge to the address.
|
// i2c_ping_address to see if a device did acknowledge to the address.
|
||||||
i2c_status_t error = i2c_start(address << 1, TIMEOUT);
|
i2c_status_t error = i2c_ping_address(address << 1, TIMEOUT);
|
||||||
if (error == I2C_STATUS_SUCCESS) {
|
if (error == I2C_STATUS_SUCCESS) {
|
||||||
i2c_stop();
|
|
||||||
dprintf(" I2C device found at address 0x%02X\n", address);
|
dprintf(" I2C device found at address 0x%02X\n", address);
|
||||||
nDevices++;
|
nDevices++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,9 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#define I2C_TIMEOUT 100
|
#define I2C_TIMEOUT 100
|
||||||
|
|
||||||
#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0b0100000<<1)
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
@ -159,9 +157,6 @@ void init_expander(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
expander_status = i2c_write(IODIRA, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pin direction and pull-up depends on both the diode direction
|
Pin direction and pull-up depends on both the diode direction
|
||||||
and on whether the column register is GPIOA or GPIOB
|
and on whether the column register is GPIOA or GPIOB
|
||||||
|
@ -176,50 +171,27 @@ void init_expander(void) {
|
||||||
|
|
||||||
#if (EXPANDER_COL_REGISTER == GPIOA)
|
#if (EXPANDER_COL_REGISTER == GPIOA)
|
||||||
# if (DIODE_DIRECTION == COL2ROW)
|
# if (DIODE_DIRECTION == COL2ROW)
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
uint8_t data[] = { expander_input_pin_mask, 0};
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# elif (DIODE_DIRECTION == ROW2COL)
|
# elif (DIODE_DIRECTION == ROW2COL)
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
uint8_t data[] = { 0, expander_input_pin_mask};
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# endif
|
# endif
|
||||||
#elif (EXPANDER_COL_REGISTER == GPIOB)
|
#elif (EXPANDER_COL_REGISTER == GPIOB)
|
||||||
# if (DIODE_DIRECTION == COL2ROW)
|
# if (DIODE_DIRECTION == COL2ROW)
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
uint8_t data[] = { 0, expander_input_pin_mask};
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# elif (DIODE_DIRECTION == ROW2COL)
|
# elif (DIODE_DIRECTION == ROW2COL)
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
uint8_t data[] = { expander_input_pin_mask, 0};
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
expander_status = i2c_writeReg(I2C_ADDR, IODIRA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
|
|
||||||
i2c_stop();
|
if (!expander_status) {
|
||||||
|
// set pull-up
|
||||||
|
// - unused : off : 0
|
||||||
|
// - input : on : 1
|
||||||
|
// - driving : off : 0
|
||||||
|
expander_status = i2c_writeReg(I2C_ADDR, GPPUA, data, sizeof(data), I2C_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
// set pull-up
|
|
||||||
// - unused : off : 0
|
|
||||||
// - input : on : 1
|
|
||||||
// - driving : off : 0
|
|
||||||
expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
expander_status = i2c_write(GPPUA, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
#if (EXPANDER_COL_REGISTER == GPIOA)
|
|
||||||
# if (DIODE_DIRECTION == COL2ROW)
|
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# elif (DIODE_DIRECTION == ROW2COL)
|
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# endif
|
|
||||||
#elif (EXPANDER_COL_REGISTER == GPIOB)
|
|
||||||
# if (DIODE_DIRECTION == COL2ROW)
|
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# elif (DIODE_DIRECTION == ROW2COL)
|
|
||||||
expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t matrix_scan(void)
|
uint8_t matrix_scan(void)
|
||||||
|
@ -332,14 +304,9 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
|
||||||
|
|
||||||
// Read columns from expander, unless it's in an error state
|
// Read columns from expander, unless it's in an error state
|
||||||
if (! expander_status) {
|
if (! expander_status) {
|
||||||
expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
|
uint8_t data;
|
||||||
expander_status = i2c_write(EXPANDER_COL_REGISTER, I2C_TIMEOUT); if (expander_status) goto out;
|
i2c_readReg(I2C_ADDR, EXPANDER_COL_REGISTER, &data, 1, I2C_TIMEOUT);
|
||||||
expander_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (expander_status) goto out;
|
current_matrix[current_row] |= (~data) & expander_input_pin_mask;
|
||||||
|
|
||||||
current_matrix[current_row] |= (~i2c_read_nack(I2C_TIMEOUT)) & expander_input_pin_mask;
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read columns from onboard pins
|
// Read columns from onboard pins
|
||||||
|
@ -361,11 +328,8 @@ static void select_row(uint8_t row) {
|
||||||
if (! expander_status) {
|
if (! expander_status) {
|
||||||
// set active row low : 0
|
// set active row low : 0
|
||||||
// set other rows hi-Z : 1
|
// set other rows hi-Z : 1
|
||||||
expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
|
uint8_t data = 0xFF & ~(1<<row);
|
||||||
expander_status = i2c_write(EXPANDER_ROW_REGISTER, I2C_TIMEOUT); if (expander_status) goto out;
|
i2c_writeReg(I2C_ADDR, EXPANDER_ROW_REGISTER, &data, 1, I2C_TIMEOUT);
|
||||||
expander_status = i2c_write(0xFF & ~(1<<row), I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// select on teensy
|
// select on teensy
|
||||||
|
@ -421,14 +385,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
|
i2c_writeReg(I2C_ADDR, EXPANDER_ROW_REGISTER, &column_state, 1, I2C_TIMEOUT);
|
||||||
expander_status = i2c_write(EXPANDER_ROW_REGISTER, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
expander_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (expander_status) goto out;
|
|
||||||
column_state = i2c_read_nack(I2C_TIMEOUT);
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
column_state = ~column_state;
|
column_state = ~column_state;
|
||||||
} else {
|
} else {
|
||||||
for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
|
for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
bool i2c_initialized = false;
|
bool i2c_initialized = false;
|
||||||
|
|
||||||
void left_config(void);
|
void left_config(void);
|
||||||
uint8_t left_write(uint8_t reg, uint8_t data);
|
i2c_status_t left_write(uint8_t reg, uint8_t data);
|
||||||
uint8_t left_read(uint8_t reg, uint8_t *data);
|
i2c_status_t left_read(uint8_t reg, uint8_t *data);
|
||||||
|
|
||||||
uint8_t init_mcp23017(void)
|
uint8_t init_mcp23017(void)
|
||||||
{
|
{
|
||||||
|
@ -35,12 +35,11 @@ void left_init(void)
|
||||||
|
|
||||||
void left_scan(void)
|
void left_scan(void)
|
||||||
{
|
{
|
||||||
uint8_t ret = i2c_start(I2C_ADDR_WRITE, HOTDOX_I2C_TIMEOUT);
|
|
||||||
|
|
||||||
if (ret == 0)
|
i2c_status_t ret = i2c_ping_address(I2C_ADDR, HOTDOX_I2C_TIMEOUT);
|
||||||
|
|
||||||
|
if (ret == I2C_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
if (!i2c_initialized)
|
if (!i2c_initialized)
|
||||||
{
|
{
|
||||||
i2c_initialized = true;
|
i2c_initialized = true;
|
||||||
|
@ -91,40 +90,29 @@ void left_config(void)
|
||||||
left_write(MCP23017_B0_GPIOB, 0xC0);
|
left_write(MCP23017_B0_GPIOB, 0xC0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t left_write(uint8_t reg, uint8_t data)
|
i2c_status_t left_write(uint8_t reg, uint8_t data)
|
||||||
{
|
{
|
||||||
if (!i2c_initialized)
|
if (!i2c_initialized)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ret;
|
i2c_status_t ret;
|
||||||
|
|
||||||
ret = i2c_start(I2C_ADDR_WRITE, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
|
ret = i2c_writeReg(I2C_ADDR, reg, &data, sizeof(data), HOTDOX_I2C_TIMEOUT);
|
||||||
ret = i2c_write(reg, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
|
|
||||||
ret = i2c_write(data, HOTDOX_I2C_TIMEOUT);
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t left_read(uint8_t reg, uint8_t *data)
|
i2c_status_t left_read(uint8_t reg, uint8_t *data)
|
||||||
{
|
{
|
||||||
if (!i2c_initialized)
|
if (!i2c_initialized)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ret = 0;
|
i2c_status_t ret = 0;
|
||||||
|
ret = i2c_readReg(I2C_ADDR, reg, data, 1, HOTDOX_I2C_TIMEOUT);
|
||||||
|
|
||||||
ret = i2c_start(I2C_ADDR_WRITE, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
|
|
||||||
ret = i2c_write(reg, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
|
|
||||||
ret = i2c_start(I2C_ADDR_READ, HOTDOX_I2C_TIMEOUT); if (ret) goto out;
|
|
||||||
|
|
||||||
*data = i2c_read_nack(HOTDOX_I2C_TIMEOUT);
|
|
||||||
|
|
||||||
out:
|
|
||||||
i2c_stop();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,7 @@
|
||||||
#define MCP23017_A1 0
|
#define MCP23017_A1 0
|
||||||
#define MCP23017_A2 0
|
#define MCP23017_A2 0
|
||||||
|
|
||||||
#define I2C_ADDR (0x20)
|
#define I2C_ADDR ((0x20) << 1)
|
||||||
#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
|
|
||||||
#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
|
|
||||||
|
|
||||||
|
|
||||||
#define MCP23017_B0_IODIRA 0x00
|
#define MCP23017_B0_IODIRA 0x00
|
||||||
#define MCP23017_B0_IODIRB 0x01
|
#define MCP23017_B0_IODIRB 0x01
|
||||||
|
@ -40,8 +37,6 @@
|
||||||
|
|
||||||
#define HOTDOX_I2C_TIMEOUT 100
|
#define HOTDOX_I2C_TIMEOUT 100
|
||||||
|
|
||||||
typedef int16_t i2c_status_t;
|
|
||||||
|
|
||||||
void left_init(void);
|
void left_init(void);
|
||||||
void left_scan(void);
|
void left_scan(void);
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,7 @@ extern i2c_status_t mcp23017_status;
|
||||||
// All address pins of the mcp23017 are connected to the ground on the ferris
|
// All address pins of the mcp23017 are connected to the ground on the ferris
|
||||||
// | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
|
// | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
|
||||||
// | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
|
// | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
|
||||||
#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0b0100000<<1)
|
||||||
#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
|
|
||||||
#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
|
|
||||||
|
|
||||||
// Register addresses
|
// Register addresses
|
||||||
// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h
|
// See https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h
|
||||||
|
@ -77,7 +75,7 @@ uint8_t init_mcp23017(void) {
|
||||||
// This means: we will read all the bits on GPIOA
|
// This means: we will read all the bits on GPIOA
|
||||||
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
||||||
uint8_t buf[] = {IODIRA, 0b11111111, 0b11110000};
|
uint8_t buf[] = {IODIRA, 0b11111111, 0b11110000};
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT);
|
mcp23017_status = i2c_transmit(I2C_ADDR, buf, sizeof(buf), I2C_TIMEOUT);
|
||||||
if (!mcp23017_status) {
|
if (!mcp23017_status) {
|
||||||
// set pull-up
|
// set pull-up
|
||||||
// - unused : on : 1
|
// - unused : on : 1
|
||||||
|
@ -86,7 +84,7 @@ uint8_t init_mcp23017(void) {
|
||||||
// This means: we will read all the bits on GPIOA
|
// This means: we will read all the bits on GPIOA
|
||||||
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
// This means: we will write to the pins 0-4 on GPIOB (in select_rows)
|
||||||
uint8_t pullup_buf[] = {GPPUA, 0b11111111, 0b11110000};
|
uint8_t pullup_buf[] = {GPPUA, 0b11111111, 0b11110000};
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, pullup_buf, sizeof(pullup_buf), I2C_TIMEOUT);
|
mcp23017_status = i2c_transmit(I2C_ADDR, pullup_buf, sizeof(pullup_buf), I2C_TIMEOUT);
|
||||||
}
|
}
|
||||||
return mcp23017_status;
|
return mcp23017_status;
|
||||||
}
|
}
|
||||||
|
@ -205,14 +203,14 @@ static matrix_row_t read_cols(uint8_t row) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
uint8_t buf[] = {GPIOA};
|
uint8_t buf[] = {GPIOA};
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT);
|
mcp23017_status = i2c_transmit(I2C_ADDR, buf, sizeof(buf), I2C_TIMEOUT);
|
||||||
// We read all the pins on GPIOA.
|
// We read all the pins on GPIOA.
|
||||||
// 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.
|
// 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.
|
||||||
// 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.
|
// 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.
|
||||||
// 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.
|
// 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.
|
||||||
uint8_t data[] = {0};
|
uint8_t data[] = {0};
|
||||||
if (!mcp23017_status) {
|
if (!mcp23017_status) {
|
||||||
mcp23017_status = i2c_receive(I2C_ADDR_READ, data, sizeof(data), I2C_TIMEOUT);
|
mcp23017_status = i2c_receive(I2C_ADDR, data, sizeof(data), I2C_TIMEOUT);
|
||||||
data[0] = ~(data[0]);
|
data[0] = ~(data[0]);
|
||||||
}
|
}
|
||||||
return data[0];
|
return data[0];
|
||||||
|
@ -249,7 +247,7 @@ static void select_row(uint8_t row) {
|
||||||
// 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.
|
// 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.
|
||||||
// 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.
|
// 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.
|
||||||
uint8_t buf[] = {GPIOB, 0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))};
|
uint8_t buf[] = {GPIOB, 0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))};
|
||||||
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT);
|
mcp23017_status = i2c_transmit(I2C_ADDR, buf, sizeof(buf), I2C_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,10 +124,9 @@ static void board_slave_init(void) {
|
||||||
if (board_is_master(board)) {
|
if (board_is_master(board)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (i2c_start(EXPANDER_ADDR(board->i2c_address), BOARD_I2C_TIMEOUT) != I2C_STATUS_SUCCESS) {
|
if (i2c_ping_address(EXPANDER_ADDR(board->i2c_address), BOARD_I2C_TIMEOUT) != I2C_STATUS_SUCCESS) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
i2c_stop();
|
|
||||||
if (board_slave_config(board)) {
|
if (board_slave_config(board)) {
|
||||||
board->initialized = true;
|
board->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
#define I2C_ADDR 0b0100000
|
#define I2C_ADDR (0b0100000<<1)
|
||||||
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
#define IODIRA 0x00 // i/o direction register
|
#define IODIRA 0x00 // i/o direction register
|
||||||
#define IODIRB 0x01
|
#define IODIRB 0x01
|
||||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -77,51 +77,14 @@ i2c_status_t usb7206_read_reg(struct USB7206* self, uint32_t addr, uint8_t* data
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t read[2] = {
|
uint16_t read = 0x0006; // Buffer address 6 to skip header
|
||||||
0x00, // Buffer address MSB: always 0
|
uint8_t data_with_buffer_length[length];
|
||||||
0x06, // Buffer address LSB: 6 to skip header
|
status = i2c_readReg16((self->addr << 1), read, data_with_buffer_length, length, I2C_TIMEOUT);
|
||||||
};
|
|
||||||
|
|
||||||
status = i2c_start((self->addr << 1) | I2C_WRITE, I2C_TIMEOUT);
|
|
||||||
if (status >= 0) {
|
|
||||||
for (uint16_t i = 0; i < sizeof(read); i++) {
|
|
||||||
status = i2c_write(read[i], I2C_TIMEOUT);
|
|
||||||
if (status < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = i2c_start((self->addr << 1) | I2C_READ, I2C_TIMEOUT);
|
|
||||||
if (status < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read and ignore buffer length
|
|
||||||
status = i2c_read_ack(I2C_TIMEOUT);
|
|
||||||
if (status < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
|
for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
|
||||||
status = i2c_read_ack(I2C_TIMEOUT);
|
data[i] = data_with_buffer_length[i+1];
|
||||||
if (status >= 0) {
|
|
||||||
data[i] = (uint8_t)status;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status >= 0) {
|
|
||||||
status = i2c_read_nack(I2C_TIMEOUT);
|
|
||||||
if (status >= 0) {
|
|
||||||
data[(length - 1)] = (uint8_t)status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
return (status < 0) ? status : length;
|
return (status < 0) ? status : length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,35 +123,21 @@ i2c_status_t usb7206_write_reg(struct USB7206* self, uint32_t addr, uint8_t* dat
|
||||||
(uint8_t)(addr >> 8), // Register address byte 1
|
(uint8_t)(addr >> 8), // Register address byte 1
|
||||||
(uint8_t)(addr >> 0), // Register address byte 0
|
(uint8_t)(addr >> 0), // Register address byte 0
|
||||||
};
|
};
|
||||||
|
uint8_t send_buffer_length = sizeof(register_write) + length;
|
||||||
|
uint8_t send_buffer[send_buffer_length];
|
||||||
|
uint8_t j = 0;
|
||||||
|
|
||||||
status = i2c_start((self->addr << 1) | I2C_WRITE, I2C_TIMEOUT);
|
for (uint16_t i = 0; i < sizeof(register_write); i++) {
|
||||||
if (status >= 0) {
|
send_buffer[j++] = register_write[i];
|
||||||
for (uint16_t i = 0; i < sizeof(register_write); i++) {
|
|
||||||
status = i2c_write(register_write[i], I2C_TIMEOUT);
|
|
||||||
if (status < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < length; i++) {
|
|
||||||
status = i2c_write(data[i], I2C_TIMEOUT);
|
|
||||||
if (status < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_stop();
|
for (uint16_t i = 0; i < length; i++) {
|
||||||
|
send_buffer[j++] = data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
status = i2c_transmit((self->addr << 1), send_buffer, send_buffer_length, I2C_TIMEOUT);
|
||||||
|
|
||||||
status = usb7206_register_access(self);
|
status = usb7206_register_access(self);
|
||||||
if (status < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
i2c_stop();
|
|
||||||
|
|
||||||
return (status < 0) ? status : length;
|
return (status < 0) ? status : length;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ uint8_t matrix_scan(void)
|
||||||
#ifdef RIGHT_HALF
|
#ifdef RIGHT_HALF
|
||||||
uint8_t data = 0x7F;
|
uint8_t data = 0x7F;
|
||||||
// Receive the columns from right half
|
// Receive the columns from right half
|
||||||
i2c_receive(I2C_ADDR_WRITE, &data, 1, MCP23018_I2C_TIMEOUT);
|
i2c_receive(I2C_ADDR, &data, 1, MCP23018_I2C_TIMEOUT);
|
||||||
cols |= ((~(data) & 0x7F) << 7);
|
cols |= ((~(data) & 0x7F) << 7);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ static void matrix_select_row(uint8_t row)
|
||||||
//Set the remote row on port A
|
//Set the remote row on port A
|
||||||
txdata[0] = GPIOA;
|
txdata[0] = GPIOA;
|
||||||
txdata[1] = 0xFF & ~(1<<row);
|
txdata[1] = 0xFF & ~(1<<row);
|
||||||
mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)txdata, 2, MCP23018_I2C_TIMEOUT);
|
mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)txdata, 2, MCP23018_I2C_TIMEOUT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// select other half
|
// select other half
|
||||||
|
|
|
@ -39,7 +39,7 @@ uint8_t init_mcp23018(void)
|
||||||
data[0] = IODIRA;
|
data[0] = IODIRA;
|
||||||
data[1] = 0b00000000;
|
data[1] = 0b00000000;
|
||||||
data[2] = 0b11111111;
|
data[2] = 0b11111111;
|
||||||
mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
|
mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
|
||||||
if (mcp23018_status != I2C_STATUS_SUCCESS)
|
if (mcp23018_status != I2C_STATUS_SUCCESS)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ uint8_t init_mcp23018(void)
|
||||||
data[0] = GPPUA;
|
data[0] = GPPUA;
|
||||||
data[1] = 0b00000000;
|
data[1] = 0b00000000;
|
||||||
data[2] = 0b11111111;
|
data[2] = 0b11111111;
|
||||||
mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
|
mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
|
||||||
if (mcp23018_status != I2C_STATUS_SUCCESS)
|
if (mcp23018_status != I2C_STATUS_SUCCESS)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ uint8_t init_mcp23018(void)
|
||||||
data[0] = OLATA;
|
data[0] = OLATA;
|
||||||
data[1] = 0b11111111;
|
data[1] = 0b11111111;
|
||||||
data[2] = 0b11111111;
|
data[2] = 0b11111111;
|
||||||
mcp23018_status = i2c_transmit(I2C_ADDR_WRITE, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
|
mcp23018_status = i2c_transmit(I2C_ADDR, (uint8_t *)data, 3, MCP23018_I2C_TIMEOUT);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return (mcp23018_status);
|
return (mcp23018_status);
|
||||||
|
|
|
@ -23,9 +23,7 @@
|
||||||
# include "i2c_master.h"
|
# include "i2c_master.h"
|
||||||
|
|
||||||
// I2C aliases and register addresses (see "mcp23018.md")
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
# define I2C_ADDR 0b0100000
|
# define I2C_ADDR (0b0100000<<1)
|
||||||
# define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
|
|
||||||
# define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
|
|
||||||
# define IODIRA 0x00 // i/o direction register
|
# define IODIRA 0x00 // i/o direction register
|
||||||
# define IODIRB 0x01
|
# define IODIRB 0x01
|
||||||
# define GPPUA 0x0C // GPIO pull-up resistor register
|
# define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "wait.h"
|
#include "wait.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "progmem.h"
|
||||||
|
|
||||||
#ifndef F_SCL
|
#ifndef F_SCL
|
||||||
# define F_SCL 400000UL // SCL frequency
|
# define F_SCL 400000UL // SCL frequency
|
||||||
|
@ -38,7 +39,7 @@
|
||||||
|
|
||||||
#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
|
#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
|
||||||
|
|
||||||
void i2c_init(void) {
|
__attribute__((weak)) void i2c_init(void) {
|
||||||
TWSR = 0; /* no prescaler */
|
TWSR = 0; /* no prescaler */
|
||||||
TWBR = (uint8_t)TWBR_val;
|
TWBR = (uint8_t)TWBR_val;
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
|
||||||
return I2C_STATUS_SUCCESS;
|
return I2C_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
|
__attribute__((always_inline)) static inline i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
|
||||||
// Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
|
// Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
|
||||||
uint16_t timeout_timer = timer_read();
|
uint16_t timeout_timer = timer_read();
|
||||||
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
|
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) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void i2c_stop(void) {
|
||||||
|
// transmit STOP condition
|
||||||
|
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
|
||||||
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
|
i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
|
||||||
// load data into data register
|
// load data into data register
|
||||||
TWDR = data;
|
TWDR = data;
|
||||||
|
@ -167,6 +173,18 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
|
i2c_status_t status = i2c_start(address | I2C_ACTION_WRITE, timeout);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < length && status >= 0; i++) {
|
||||||
|
status = i2c_write(pgm_read_byte((const char*)data++), timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_stop();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
|
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);
|
i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);
|
||||||
|
|
||||||
|
@ -293,7 +311,8 @@ error:
|
||||||
return (status < 0) ? status : I2C_STATUS_SUCCESS;
|
return (status < 0) ? status : I2C_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_stop(void) {
|
__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
|
||||||
// transmit STOP condition
|
i2c_status_t status = i2c_start(address, timeout);
|
||||||
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
|
i2c_stop();
|
||||||
|
return status;
|
||||||
}
|
}
|
|
@ -41,14 +41,11 @@ typedef int16_t i2c_status_t;
|
||||||
#define I2C_TIMEOUT_INFINITE (0xFFFF)
|
#define I2C_TIMEOUT_INFINITE (0xFFFF)
|
||||||
|
|
||||||
void i2c_init(void);
|
void i2c_init(void);
|
||||||
i2c_status_t i2c_start(uint8_t address, uint16_t timeout);
|
|
||||||
i2c_status_t i2c_write(uint8_t data, uint16_t timeout);
|
|
||||||
int16_t i2c_read_ack(uint16_t timeout);
|
|
||||||
int16_t i2c_read_nack(uint16_t timeout);
|
|
||||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
|
i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
void i2c_stop(void);
|
i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* Copyright 2018 Jack Humbert
|
/* Copyright 2018 Jack Humbert
|
||||||
* Copyright 2018 Yiancar
|
* Copyright 2018 Yiancar
|
||||||
|
* Copyright 2023 customMK
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -90,8 +91,6 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t i2c_address;
|
|
||||||
|
|
||||||
static const I2CConfig i2cconfig = {
|
static const I2CConfig i2cconfig = {
|
||||||
#if defined(USE_I2CV1_CONTRIB)
|
#if defined(USE_I2CV1_CONTRIB)
|
||||||
I2C1_CLOCK_SPEED,
|
I2C1_CLOCK_SPEED,
|
||||||
|
@ -125,7 +124,7 @@ static i2c_status_t i2c_epilogue(const msg_t status) {
|
||||||
// From ChibiOS HAL: "After a timeout the driver must be stopped and
|
// From ChibiOS HAL: "After a timeout the driver must be stopped and
|
||||||
// restarted because the bus is in an uncertain state." We also issue that
|
// restarted because the bus is in an uncertain state." We also issue that
|
||||||
// hard stop in case of any error.
|
// hard stop in case of any error.
|
||||||
i2c_stop();
|
i2cStop(&I2C_DRIVER);
|
||||||
|
|
||||||
return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR;
|
return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -150,28 +149,19 @@ __attribute__((weak)) void i2c_init(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_start(uint8_t address) {
|
|
||||||
i2c_address = address;
|
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
|
||||||
return I2C_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
i2c_address = address;
|
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
|
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
|
||||||
return i2c_epilogue(status);
|
return i2c_epilogue(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
|
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
i2c_address = address;
|
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout));
|
msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (address >> 1), data, length, TIME_MS2I(timeout));
|
||||||
return i2c_epilogue(status);
|
return i2c_epilogue(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
i2c_address = devaddr;
|
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
|
|
||||||
uint8_t complete_packet[length + 1];
|
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*
|
||||||
}
|
}
|
||||||
complete_packet[0] = regaddr;
|
complete_packet[0] = regaddr;
|
||||||
|
|
||||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
|
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
|
||||||
return i2c_epilogue(status);
|
return i2c_epilogue(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
i2c_address = devaddr;
|
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
|
|
||||||
uint8_t complete_packet[length + 2];
|
uint8_t complete_packet[length + 2];
|
||||||
|
@ -195,25 +184,27 @@ i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8
|
||||||
complete_packet[0] = regaddr >> 8;
|
complete_packet[0] = regaddr >> 8;
|
||||||
complete_packet[1] = regaddr & 0xFF;
|
complete_packet[1] = regaddr & 0xFF;
|
||||||
|
|
||||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
|
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
|
||||||
return i2c_epilogue(status);
|
return i2c_epilogue(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
|
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
i2c_address = devaddr;
|
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®addr, 1, data, length, TIME_MS2I(timeout));
|
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), ®addr, 1, data, length, TIME_MS2I(timeout));
|
||||||
return i2c_epilogue(status);
|
return i2c_epilogue(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
|
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||||
i2c_address = devaddr;
|
|
||||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||||
uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};
|
uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};
|
||||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
|
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
|
||||||
return i2c_epilogue(status);
|
return i2c_epilogue(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_stop(void) {
|
__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
|
||||||
i2cStop(&I2C_DRIVER);
|
// ChibiOS does not provide low level enough control to check for an ack.
|
||||||
|
// Best effort instead tries reading register 0 which will either succeed or timeout.
|
||||||
|
// This approach may produce false negative results for I2C devices that do not respond to a register 0 read request.
|
||||||
|
uint8_t data = 0;
|
||||||
|
return i2c_readReg(address, 0, &data, sizeof(data), timeout);
|
||||||
}
|
}
|
|
@ -40,11 +40,10 @@ typedef int16_t i2c_status_t;
|
||||||
#define I2C_STATUS_TIMEOUT (-2)
|
#define I2C_STATUS_TIMEOUT (-2)
|
||||||
|
|
||||||
void i2c_init(void);
|
void i2c_init(void);
|
||||||
i2c_status_t i2c_start(uint8_t address);
|
|
||||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||||
void i2c_stop(void);
|
i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
|
||||||
|
|
Loading…
Reference in a new issue