Skip to content

Commit

Permalink
First attempt to naively update to Master-Follower
Browse files Browse the repository at this point in the history
  • Loading branch information
rmwphd committed Jun 11, 2020
1 parent d0ffa10 commit 079cf9a
Show file tree
Hide file tree
Showing 244 changed files with 1,475 additions and 1,475 deletions.
2 changes: 1 addition & 1 deletion common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
# Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
ifeq ($(PLATFORM),AVR)
QUANTUM_LIB_SRC += i2c_master.c \
i2c_slave.c
i2c_follower.c
endif

SERIAL_DRIVER ?= bitbang
Expand Down
10 changes: 5 additions & 5 deletions docs/config_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in yo

### Setting Handedness

One thing to remember, the side that the USB port is plugged into is always the master half. The side not plugged into USB is the slave.
One thing to remember, the side that the USB port is plugged into is always the master half. The side not plugged into USB is the follower.

There are a few different ways to set handedness for split keyboards (listed in order of precedence):

Expand All @@ -243,7 +243,7 @@ There are a few different ways to set handedness for split keyboards (listed in
* For boards with Caterina bootloader (like stock Pro Micros), use `:avrdude-split-left`/`:avrdude-split-right`
* For boards with ARM DFU bootloader (like Proton C), use `:dfu-util-split-left`/`:dfu-util-split-right`
3. Set `MASTER_RIGHT`: Half that is plugged into the USB port is determined to be the master and right half (inverse of the default)
4. Default: The side that is plugged into the USB port is the master half and is assumed to be the left half. The slave side is the right half
4. Default: The side that is plugged into the USB port is the master half and is assumed to be the left half. The follower side is the right half

#### Defines for handedness

Expand Down Expand Up @@ -285,15 +285,15 @@ There are a few different ways to set handedness for split keyboards (listed in
* 5: about 20kbps

* `#define SPLIT_USB_DETECT`
* Detect (with timeout) USB connection when delegating master/slave
* Detect (with timeout) USB connection when delegating master/follower
* Default behavior for ARM
* Required for AVR Teensy

* `#define SPLIT_USB_TIMEOUT 2000`
* Maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT`
* Maximum timeout when detecting master/follower when using `SPLIT_USB_DETECT`

* `#define SPLIT_USB_TIMEOUT_POLL 10`
* Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`
* Poll frequency when detecting master/follower when using `SPLIT_USB_DETECT`

# The `rules.mk` File

Expand Down
2 changes: 1 addition & 1 deletion docs/eeprom_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Currently QMK supports 25xx-series chips over SPI. As such, requires a working s

`config.h` override | Description | Default Value
-----------------------------------------------|--------------------------------------------------------------------------------------|--------------
`#define EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN` | SPI Slave select pin in order to inform that the EEPROM is currently being addressed | _none_
`#define EXTERNAL_EEPROM_SPI_follower_SELECT_PIN` | SPI follower select pin in order to inform that the EEPROM is currently being addressed | _none_
`#define EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR` | Clock divisor used to divide the peripheral clock to derive the SPI frequency | `64`
`#define EXTERNAL_EEPROM_BYTE_COUNT` | Total size of the EEPROM in bytes | 8192
`#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32
Expand Down
2 changes: 1 addition & 1 deletion docs/feature_ps2_mouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ In your keyboard config.h:
#define PS2_DATA_BIT 2

/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */
/* set DDR of CLOCK as input to be slave */
/* set DDR of CLOCK as input to be follower */
#define PS2_USART_INIT() do { \
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
Expand Down
4 changes: 2 additions & 2 deletions docs/feature_rgblight.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,9 @@ rgblight_set(); // Utility functions do not call rgblight_set() automatically, s
|`rgblight_sethsv_range(h, s, v, start, end)`|Set a continuous range of LEDs to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
|`rgblight_setrgb(r, g, b)` |Set effect range LEDs to the given RGB value where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|`rgblight_setrgb_master(r, g, b)` |Set the LEDs on the master side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|`rgblight_setrgb_slave(r, g, b)` |Set the LEDs on the slave side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|`rgblight_setrgb_follower(r, g, b)` |Set the LEDs on the follower side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|`rgblight_sethsv_master(h, s, v)` |Set the LEDs on the master side to the given HSV value, where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
|`rgblight_sethsv_slave(h, s, v)` |Set the LEDs on the slave side to the given HSV value, where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
|`rgblight_sethsv_follower(h, s, v)` |Set the LEDs on the follower side to the given HSV value, where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |

Example:
```c
Expand Down
6 changes: 3 additions & 3 deletions docs/feature_split_keyboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,19 +204,19 @@ This sets how many LEDs are directly connected to each controller. The first nu
```c
#define SPLIT_USB_DETECT
```
This option changes the startup behavior to detect an active USB connection when delegating master/slave. If this operation times out, then the half is assume to be a slave. This is the default behavior for ARM, and required for AVR Teensy boards (due to hardware limitations).
This option changes the startup behavior to detect an active USB connection when delegating master/follower. If this operation times out, then the half is assume to be a follower. This is the default behavior for ARM, and required for AVR Teensy boards (due to hardware limitations).

?> This setting will stop the ability to demo using battery packs.

```c
#define SPLIT_USB_TIMEOUT 2000
```
This sets the maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT`.
This sets the maximum timeout when detecting master/follower when using `SPLIT_USB_DETECT`.
```c
#define SPLIT_USB_TIMEOUT_POLL 10
```
This sets the poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`
This sets the poll frequency when detecting master/follower when using `SPLIT_USB_DETECT`

## Additional Resources

Expand Down
2 changes: 1 addition & 1 deletion docs/feature_wpm.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Enable the WPM system by adding this to your `rules.mk`:
WPM_ENABLE = yes

For split keyboards using soft serial, the computed WPM
score will be available on the master AND slave half.
score will be available on the master AND follower half.

## Public Functions

Expand Down
10 changes: 5 additions & 5 deletions docs/i2c_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ See https://www.robot-electronics.co.uk/i2c-tutorial for more information about
|Function |Description |
|------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|`void i2c_init(void);` |Initializes the I2C driver. This function should be called once before any transaction is initiated. |
|`i2c_status_t i2c_start(uint8_t address, uint16_t timeout);` |Starts an I2C transaction. Address is the 7-bit slave address without the direction bit. |
|`i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Transmit data over I2C. Address is the 7-bit slave address without the direction. Returns status of transaction. |
|`i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Receive data over I2C. Address is the 7-bit slave address without the direction. Saves number of bytes specified by `length` in `data` array. Returns status of transaction. |
|`i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_transmit` function but `regaddr` sets where in the slave the data will be written. |
|`i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_receive` function but `regaddr` sets from where in the slave the data will be read. |
|`i2c_status_t i2c_start(uint8_t address, uint16_t timeout);` |Starts an I2C transaction. Address is the 7-bit follower address without the direction bit. |
|`i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Transmit data over I2C. Address is the 7-bit follower address without the direction. Returns status of transaction. |
|`i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Receive data over I2C. Address is the 7-bit follower address without the direction. Saves number of bytes specified by `length` in `data` array. Returns status of transaction. |
|`i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_transmit` function but `regaddr` sets where in the follower the data will be written. |
|`i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_receive` function but `regaddr` sets from where in the follower the data will be read. |
|`i2c_status_t i2c_stop(void);` |Ends an I2C transaction. |

### Function Return :id=function-return
Expand Down
2 changes: 1 addition & 1 deletion docs/serial_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This driver powers the [Split Keyboard](feature_split_keyboard.md) feature.

All drivers in this category have the following characteristics:
* Provides data and signaling over a single conductor
* Limited to single master, single slave
* Limited to single master, single follower

## Supported Driver Types

Expand Down
12 changes: 6 additions & 6 deletions docs/spi_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ No special setup is required - just connect the `SS`, `SCK`, `MOSI` and `MISO` p
|ATmega32A |`B4`|`B7` |`B5` |`B6` |
|ATmega328P |`B2`|`B5` |`B3` |`B4` |

You may use more than one slave select pin, not just the `SS` pin. This is useful when you have multiple devices connected and need to communicate with them individually.
You may use more than one follower select pin, not just the `SS` pin. This is useful when you have multiple devices connected and need to communicate with them individually.
`SPI_SS_PIN` can be passed to `spi_start()` to refer to `SS`.

## ChibiOS/ARM Configuration
Expand All @@ -23,7 +23,7 @@ You'll need to determine which pins can be used for SPI -- as an example, STM32
To enable SPI, modify your board's `halconf.h` to enable SPI - both `HAL_USE_SPI` and `SPI_USE_WAIT` should be `TRUE`, and `SPI_SELECT_MODE` should be `SPI_SELECT_MODE_PAD`.
Then, modify your board's `mcuconf.h` to enable the SPI peripheral you've chosen -- in the case of using SPI2, modify `STM32_SPI_USE_SPI2` to be `TRUE`.

As per the AVR configuration, you may select any other standard GPIO as a slave select pin, and can be supplied to `spi_start()`.
As per the AVR configuration, you may select any other standard GPIO as a follower select pin, and can be supplied to `spi_start()`.

Configuration-wise, you'll need to set up the peripheral as per your MCU's datasheet -- the defaults match the pins for a Proton-C, i.e. STM32F303.

Expand All @@ -45,14 +45,14 @@ Initialize the SPI driver. This function must be called only once, before any of

---

### `bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor)`
### `bool spi_start(pin_t followerPin, bool lsbFirst, uint8_t mode, uint16_t divisor)`

Start an SPI transaction.

#### Arguments

- `pin_t slavePin`
The QMK pin to assert as the slave select pin, eg. `B4`.
- `pin_t followerPin`
The QMK pin to assert as the follower select pin, eg. `B4`.
- `bool lsbFirst`
Determines the endianness of the transmission. If `true`, the least significant bit of each byte is sent first.
- `uint8_t mode`
Expand Down Expand Up @@ -135,4 +135,4 @@ Receive multiple bytes from the selected SPI device.

### `void spi_stop(void)`

End the current SPI transaction. This will deassert the slave select pin and reset the endianness, mode and divisor configured by `spi_start()`.
End the current SPI transaction. This will deassert the follower select pin and reset the endianness, mode and divisor configured by `spi_start()`.
30 changes: 15 additions & 15 deletions drivers/avr/i2c_slave.c → drivers/avr/i2c_follower.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* Library made by: g4lvanix
* GitHub repository: https://github.com/g4lvanix/I2C-slave-lib
* GitHub repository: https://github.com/g4lvanix/I2C-follower-lib
*/

#include <avr/io.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#include <stdbool.h>

#include "i2c_slave.h"
#include "i2c_follower.h"

volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
volatile uint8_t i2c_follower_reg[I2C_follower_REG_COUNT];

static volatile uint8_t buffer_address;
static volatile bool slave_has_register_set = false;
static volatile bool follower_has_register_set = false;

void i2c_slave_init(uint8_t address) {
void i2c_follower_init(uint8_t address) {
// load address into TWI address register
TWAR = address;
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
}

void i2c_slave_stop(void) {
void i2c_follower_stop(void) {
// clear acknowledge and enable bits
TWCR &= ~((1 << TWEA) | (1 << TWEN));
}
Expand All @@ -46,31 +46,31 @@ ISR(TWI_vect) {

switch (TW_STATUS) {
case TW_SR_SLA_ACK:
// The device is now a slave receiver
slave_has_register_set = false;
// The device is now a follower receiver
follower_has_register_set = false;
break;

case TW_SR_DATA_ACK:
// This device is a slave receiver and has received data
// This device is a follower receiver and has received data
// First byte is the location then the bytes will be writen in buffer with auto-incriment
if (!slave_has_register_set) {
if (!follower_has_register_set) {
buffer_address = TWDR;

if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack
if (buffer_address >= I2C_follower_REG_COUNT) { // address out of bounds dont ack
ack = 0;
buffer_address = 0;
}
slave_has_register_set = true; // address has been receaved now fill in buffer
follower_has_register_set = true; // address has been receaved now fill in buffer
} else {
i2c_slave_reg[buffer_address] = TWDR;
i2c_follower_reg[buffer_address] = TWDR;
buffer_address++;
}
break;

case TW_ST_SLA_ACK:
case TW_ST_DATA_ACK:
// This device is a slave transmitter and master has requested data
TWDR = i2c_slave_reg[buffer_address];
// This device is a follower transmitter and master has requested data
TWDR = i2c_follower_reg[buffer_address];
buffer_address++;
break;

Expand Down
16 changes: 8 additions & 8 deletions drivers/avr/i2c_slave.h → drivers/avr/i2c_follower.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* Library made by: g4lvanix
* GitHub repository: https://github.com/g4lvanix/I2C-slave-lib
* GitHub repository: https://github.com/g4lvanix/I2C-follower-lib
Info: Inititate the library by giving the required address.
Read or write to the necessary buffer according to the opperation.
*/

#ifndef I2C_SLAVE_H
#define I2C_SLAVE_H
#ifndef I2C_follower_H
#define I2C_follower_H

#define I2C_SLAVE_REG_COUNT 30
#define I2C_follower_REG_COUNT 30

extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
extern volatile uint8_t i2c_follower_reg[I2C_follower_REG_COUNT];

void i2c_slave_init(uint8_t address);
void i2c_slave_stop(void);
void i2c_follower_init(uint8_t address);
void i2c_follower_stop(void);

#endif // I2C_SLAVE_H
#endif // I2C_follower_H
4 changes: 2 additions & 2 deletions drivers/avr/i2c_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void i2c_init(void) {
// enable TWI (two-wire interface)
TWCR |= (1 << TWEN);

// enable TWI interrupt and slave address ACK
// enable TWI interrupt and follower address ACK
TWCR |= (1 << TWIE);
TWCR |= (1 << TWEA);
#endif
Expand All @@ -65,7 +65,7 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
return I2C_STATUS_ERROR;
}

// load slave address into data register
// load follower address into data register
TWDR = address;
// start transmission of address
TWCR = (1 << TWINT) | (1 << TWEN);
Expand Down
Loading

0 comments on commit 079cf9a

Please sign in to comment.