dexter93 2 weeks ago
committed by GitHub
parent
commit
0abe764056
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
7 changed files with 179 additions and 3 deletions
  1. +36
    -0
      docs/i2c_driver.md
  2. +3
    -0
      keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/config.h
  3. +6
    -0
      keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/halconf.h
  4. +55
    -0
      keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/keymap.c
  5. +32
    -0
      keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/readme.md
  6. +4
    -0
      keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/rules.mk
  7. +43
    -3
      platforms/chibios/drivers/i2c_master.c

+ 36
- 0
docs/i2c_driver.md View File

@ -117,6 +117,42 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#8_I2Cv2_I2C
|`I2C1_TIMINGR_SCLH` |`38U` |
|`I2C1_TIMINGR_SCLL` |`129U` |
### I2C Fallback :id=arm-configuration-i2cfallback
ChibiOS provides a software solution through the I2C Fallback driver for cases where hardware I2C is not available.
To enable it instead of the hardware driver, add the following to your `rules.mk`:
```make
USE_HAL_I2C_FALLBACK = yes
```
Then modify your board's `halconf.h` to select the I2C Fallback driver( assuming selected I2C peripheral is `I2CD1`).
```c
#define SW_I2C_USE_I2C1 TRUE
```
By default, the delay required for I2C communication is calculated automatically with a target frequency of 100kHz, through the ChibiOS OSAL layer. If you wish to override this behavior, further modify your board's `halconf.h`
```c
#define SW_I2C_USE_OSAL_DELAY FALSE
```
and provide the following function in your board's files
```c
void i2c_sw_delay(void) {
// custom delay goes here
}
```
The I2C Fallback configuration structure is as follows
|`config.h` Override |Default |
|-----------------------|--------|
|`I2C1_CLOCK_SPEED` |`100000`|
|`halconf.h` Override |Default |
|-----------------------|--------|
|`SW_I2C_USE_OSAL_DELAY`|`TRUE` |
Note that `I2C1_CLOCK_SPEED` is target I2C speed in `Hz` and is only respected if `SW_I2C_USE_OSAL_DELAY` is `TRUE`.
The actual speed is controlled via software delays, using the following calculation
```c
#define SW_I2C_DELAY ceil((CH_CFG_ST_FREQUENCY / I2C1_CLOCK_SPEED) / 2)
```
## API :id=api
### `void i2c_init(void)` :id=api-i2c-init


+ 3
- 0
keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/config.h View File

@ -0,0 +1,3 @@
#pragma once
//#define I2C1_CLOCK_SPEED 100000 /* 400000 */

+ 6
- 0
keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/halconf.h View File

@ -0,0 +1,6 @@
#pragma once
#define SW_I2C_USE_I2C1 TRUE
#define SW_I2C_USE_OSAL_DELAY TRUE
#include_next <halconf.h>

+ 55
- 0
keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/keymap.c View File

@ -0,0 +1,55 @@
#include QMK_KEYBOARD_H
#include "i2c_master.h"
#include "debug.h"
#define TIMEOUT 50
// TODO: remove patch
#ifdef PROTOCOL_CHIBIOS
# pragma message("ChibiOS is currently 'best effort' and might not report accurate results")
#endif
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
LAYOUT_ortho_1x1(KC_A)
};
void do_scan(void) {
uint8_t nDevices = 0;
dprintf("Scanning...\n");
for (uint8_t address = 1; address < 127; address++) {
// The i2c_scanner uses the return value of
// i2c_ping_address to see if a device did acknowledge to the address.
i2c_status_t error = i2c_ping_address(address << 1, TIMEOUT);
if (error == I2C_STATUS_SUCCESS) {
dprintf(" I2C device found at address 0x%02X\n", address);
nDevices++;
} else {
// dprintf(" Unknown error (%u) at address 0x%02X\n", error, address);
}
}
if (nDevices == 0)
dprintf("No I2C devices found\n");
else
dprintf("done\n");
}
uint16_t scan_timer = 0;
void matrix_scan_user(void) {
if (timer_elapsed(scan_timer) > 5000) {
do_scan();
scan_timer = timer_read();
}
}
void keyboard_post_init_user(void) {
debug_enable = true;
debug_matrix = true;
i2c_init();
scan_timer = timer_read();
}

+ 32
- 0
keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/readme.md View File

@ -0,0 +1,32 @@
# i2c_scanner_fallback
Aiming to provide a more qmk friendly version of <https://playground.arduino.cc/Main/I2cScanner/>
> This very simple ~~sketch~~ keymap scans the I2C-bus for devices. If a device is found, it is reported to the ~~Arduino serial monitor~~ console.
## Flashing
Pick a target that is aligned to the MCU you want to test:
```console
# ChibiOS is currently 'best effort' and might not report accurate results
make handwired/onekey/proton_c:i2c_scanner_fallback:flash
```
others might work with additional configuration.
## Usage
Output is viewable through a compatible tool <https://docs.qmk.fm/#/newbs_testing_debugging?id=debugging-tools>.
You can change the wires, and plug-in I2C devices while the i2c_scanner is running.
The output of the console will look like this:
```
Listening:
Scanning...
I2C device found at address 0x20
done
```

+ 4
- 0
keyboards/handwired/onekey/keymaps/i2c_scanner_fallback/rules.mk View File

@ -0,0 +1,4 @@
CONSOLE_ENABLE = yes
I2C_DRIVER_REQUIRED = yes
USE_HAL_I2C_FALLBACK = yes

+ 43
- 3
platforms/chibios/drivers/i2c_master.c View File

@ -32,6 +32,7 @@
#include <string.h>
#include <ch.h>
#include <hal.h>
#include <math.h>
#ifndef I2C1_SCL_PIN
# define I2C1_SCL_PIN B6
@ -70,8 +71,23 @@
# endif
#endif
#ifndef I2C_DRIVER
# define I2C_DRIVER I2CD1
#if defined(SW_I2C_USE_I2C1) || defined(SW_I2C_USE_I2C2) || defined(SW_I2C_USE_I2C3) || defined(SW_I2C_USE_I2C4)
# define USE_I2C_FALLBACK
# ifndef I2C_DRIVER
# ifdef SW_I2C_USE_I2C1
# define I2C_DRIVER I2CD1
# elif defined(SW_I2C_USE_I2C2)
# define I2C_DRIVER I2CD2
# elif defined(SW_I2C_USE_I2C3)
# define I2C_DRIVER I2CD3
# elif defined(SW_I2C_USE_I2C4)
# define I2C_DRIVER I2CD4
# endif
# endif
#else
# ifndef I2C_DRIVER
# define I2C_DRIVER I2CD1
# endif
#endif
#ifdef USE_GPIOV1
@ -91,8 +107,32 @@
# endif
#endif
#ifdef USE_I2C_FALLBACK
# ifndef I2C1_CLOCK_SPEED
# define I2C1_CLOCK_SPEED 100000 /* 400000 */
# endif
# ifndef SW_I2C_DELAY
# define SW_I2C_DELAY ceil((CH_CFG_ST_FREQUENCY / I2C1_CLOCK_SPEED) / 2)
# endif
# ifndef SW_I2C_USE_OSAL_DELAY
# define SW_I2C_USE_OSAL_DELAY TRUE
# endif
# if (SW_I2C_USE_OSAL_DELAY == FALSE)
__attribute__((weak)) void i2c_sw_delay(void) {}
# endif
#endif
static const I2CConfig i2cconfig = {
#if defined(USE_I2CV1_CONTRIB)
#if defined(USE_I2C_FALLBACK)
0,
I2C1_SCL_PIN,
I2C1_SDA_PIN,
# if (SW_I2C_USE_OSAL_DELAY == FALSE)
&i2c_sw_delay,
# else
SW_I2C_DELAY,
# endif
#elif defined(USE_I2CV1_CONTRIB)
I2C1_CLOCK_SPEED,
#elif defined(USE_I2CV1)
I2C1_OPMODE,


Loading…
Cancel
Save