summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/arm/i2c_master.c26
-rw-r--r--drivers/arm/i2c_master.h5
-rwxr-xr-xdrivers/avr/i2c_master.c7
-rwxr-xr-xdrivers/avr/i2c_slave.c25
-rwxr-xr-xdrivers/avr/i2c_slave.h13
-rw-r--r--drivers/avr/ws2812.h3
-rw-r--r--drivers/boards/GENERIC_STM32_F303XC/board.c126
-rw-r--r--drivers/boards/GENERIC_STM32_F303XC/board.h1187
-rw-r--r--drivers/boards/GENERIC_STM32_F303XC/board.mk5
-rw-r--r--drivers/boards/GENERIC_STM32_F303XC/bootloader_defs.h7
-rw-r--r--drivers/haptic/DRV2605L.c129
-rw-r--r--drivers/haptic/DRV2605L.h394
-rw-r--r--drivers/issi/is31fl3218.c102
-rw-r--r--drivers/issi/is31fl3218.h24
-rw-r--r--drivers/issi/is31fl3731.c (renamed from drivers/is31fl3731.c)51
-rw-r--r--drivers/issi/is31fl3731.h (renamed from drivers/is31fl3731.h)16
-rw-r--r--drivers/issi/is31fl3733.c252
-rw-r--r--drivers/issi/is31fl3733.h255
-rw-r--r--drivers/issi/is31fl3736.c306
-rw-r--r--drivers/issi/is31fl3736.h172
-rw-r--r--drivers/qwiic/micro_oled.c691
-rw-r--r--drivers/qwiic/micro_oled.h134
-rw-r--r--drivers/qwiic/qwiic.c31
-rw-r--r--drivers/qwiic/qwiic.h28
-rw-r--r--drivers/qwiic/qwiic.mk18
-rw-r--r--drivers/qwiic/util/font5x7.h288
-rw-r--r--drivers/qwiic/util/font8x16.h127
27 files changed, 4352 insertions, 70 deletions
diff --git a/drivers/arm/i2c_master.c b/drivers/arm/i2c_master.c
index 2fdd9f65e1..385bd97cb8 100644
--- a/drivers/arm/i2c_master.c
+++ b/drivers/arm/i2c_master.c
@@ -15,21 +15,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* This library follows the convention of the AVR i2c_master library.
+/* This library is only valid for STM32 processors.
+ * This library follows the convention of the AVR i2c_master library.
* As a result addresses are expected to be already shifted (addr << 1).
* I2CD1 is the default driver which corresponds to pins B6 and B7. This
* can be changed.
* Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
- * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file.
+ * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used
+ * but using any other I2C pins should be trivial.
*/
#include "i2c_master.h"
+#include "quantum.h"
#include <string.h>
#include <hal.h>
static uint8_t i2c_address;
-// This configures the I2C clock to 400Mhz assuming a 72Mhz clock
+// This configures the I2C clock to 400khz assuming a 72Mhz clock
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
static const I2CConfig i2cconfig = {
STM32_TIMINGR_PRESC(15U) |
@@ -39,13 +42,17 @@ static const I2CConfig i2cconfig = {
0
};
+__attribute__ ((weak))
void i2c_init(void)
{
- palSetGroupMode(GPIOB,6,7, PAL_MODE_INPUT); // Try releasing special pins for a short time
- chThdSleepMilliseconds(10);
+ // Try releasing special pins for a short time
+ palSetPadMode(GPIOB, 6, PAL_MODE_INPUT);
+ palSetPadMode(GPIOB, 7, PAL_MODE_INPUT);
- palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP);
- palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP);
+ chThdSleepMilliseconds(10);
+
+ palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN);
+ palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN);
//i2cInit(); //This is invoked by halInit() so no need to redo it.
}
@@ -82,12 +89,12 @@ uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t l
{
complete_packet[i+1] = data[i];
}
- complete_packet[0] = regaddr
+ complete_packet[0] = regaddr;
return i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, MS2ST(timeout));
}
-uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
+uint8_t i2c_readReg(uint8_t devaddr, uint8_t* regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
{
i2c_address = devaddr;
i2cStart(&I2C_DRIVER, &i2cconfig);
@@ -97,7 +104,6 @@ uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t le
// This is usually not needed. It releases the driver to allow pins to become GPIO again.
uint8_t i2c_stop(uint16_t timeout)
{
- i2c_address = address;
i2cStop(&I2C_DRIVER);
return 0;
}
diff --git a/drivers/arm/i2c_master.h b/drivers/arm/i2c_master.h
index 9d51245be1..392760328f 100644
--- a/drivers/arm/i2c_master.h
+++ b/drivers/arm/i2c_master.h
@@ -34,6 +34,7 @@ void i2c_init(void);
uint8_t i2c_start(uint8_t address);
uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
+uint8_t i2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t * rx_body, uint16_t rx_length);
uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-void i2c_stop(void);
+uint8_t i2c_readReg(uint8_t devaddr, uint8_t* regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+uint8_t i2c_stop(uint16_t timeout);
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c
index 47c6f8e6c6..19bae33e9f 100755
--- a/drivers/avr/i2c_master.c
+++ b/drivers/avr/i2c_master.c
@@ -8,7 +8,9 @@
#include "i2c_master.h"
#include "timer.h"
+#ifndef F_SCL
#define F_SCL 400000UL // SCL frequency
+#endif
#define Prescaler 1
#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)
@@ -177,6 +179,9 @@ i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16
status = i2c_write(regaddr, timeout);
if (status) return status;
+ status = i2c_stop(timeout);
+ if (status) return status;
+
status = i2c_start(devaddr | 0x01, timeout);
if (status) return status;
@@ -215,4 +220,4 @@ i2c_status_t i2c_stop(uint16_t timeout)
}
return I2C_STATUS_SUCCESS;
-} \ No newline at end of file
+}
diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c
index 27696ca01a..18a29a45a5 100755
--- a/drivers/avr/i2c_slave.c
+++ b/drivers/avr/i2c_slave.c
@@ -9,23 +9,26 @@
#include "i2c_slave.h"
-void i2c_init(uint8_t address){
+volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
+
+static volatile uint8_t buffer_address;
+static volatile bool slave_has_register_set = false;
+
+void i2c_slave_init(uint8_t address){
// load address into TWI address register
TWAR = (address << 1);
// 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_stop(void){
+void i2c_slave_stop(void){
// clear acknowledge and enable bits
TWCR &= ~((1 << TWEA) | (1 << TWEN));
}
ISR(TWI_vect){
uint8_t ack = 1;
- // temporary stores the received data
- //uint8_t data;
-
+
switch(TW_STATUS){
case TW_SR_SLA_ACK:
// The device is now a slave receiver
@@ -38,13 +41,13 @@ ISR(TWI_vect){
if(!slave_has_register_set){
buffer_address = TWDR;
- if (buffer_address >= RX_BUFFER_SIZE){ // address out of bounds dont ack
- ack = 0;
- buffer_address = 0;
+ if (buffer_address >= I2C_SLAVE_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
} else {
- rxbuffer[buffer_address] = TWDR;
+ i2c_slave_reg[buffer_address] = TWDR;
buffer_address++;
}
break;
@@ -52,7 +55,7 @@ ISR(TWI_vect){
case TW_ST_SLA_ACK:
case TW_ST_DATA_ACK:
// This device is a slave transmitter and master has requested data
- TWDR = txbuffer[buffer_address];
+ TWDR = i2c_slave_reg[buffer_address];
buffer_address++;
break;
@@ -63,6 +66,6 @@ ISR(TWI_vect){
break;
}
- // Reset i2c state mahcine to be ready for next interrupt
+ // Reset i2c state machine to be ready for next interrupt
TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN);
} \ No newline at end of file
diff --git a/drivers/avr/i2c_slave.h b/drivers/avr/i2c_slave.h
index 1c3b9ecc00..7b5dcbdc3e 100755
--- a/drivers/avr/i2c_slave.h
+++ b/drivers/avr/i2c_slave.h
@@ -8,16 +8,11 @@
#ifndef I2C_SLAVE_H
#define I2C_SLAVE_H
-#define TX_BUFFER_SIZE 30
-#define RX_BUFFER_SIZE 30
+#define I2C_SLAVE_REG_COUNT 30
-volatile uint8_t buffer_address;
-static volatile bool slave_has_register_set = false;
-volatile uint8_t txbuffer[TX_BUFFER_SIZE];
-volatile uint8_t rxbuffer[RX_BUFFER_SIZE];
+extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
-void i2c_init(uint8_t address);
-void i2c_stop(void);
-ISR(TWI_vect);
+void i2c_slave_init(uint8_t address);
+void i2c_slave_stop(void);
#endif // I2C_SLAVE_H \ No newline at end of file
diff --git a/drivers/avr/ws2812.h b/drivers/avr/ws2812.h
index f7e0c31440..1f9299ffb5 100644
--- a/drivers/avr/ws2812.h
+++ b/drivers/avr/ws2812.h
@@ -69,7 +69,4 @@ void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask);
#define CONCAT_EXP(a, b) CONCAT(a, b)
#endif
-// #define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port)
-// #define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port)
-
#endif /* LIGHT_WS2812_H_ */
diff --git a/drivers/boards/GENERIC_STM32_F303XC/board.c b/drivers/boards/GENERIC_STM32_F303XC/board.c
new file mode 100644
index 0000000000..4331155df4
--- /dev/null
+++ b/drivers/boards/GENERIC_STM32_F303XC/board.c
@@ -0,0 +1,126 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "hal.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+/**
+ * @brief PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ * This variable is used by the HAL when initializing the PAL driver.
+ */
+const PALConfig pal_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}
+#endif
+};
+#endif
+
+void enter_bootloader_mode_if_requested(void);
+
+/**
+ * @brief Early initialization code.
+ * @details This initialization must be performed just after stack setup
+ * and before any other initialization.
+ */
+void __early_init(void) {
+ enter_bootloader_mode_if_requested();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* TODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* TODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* TODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* TODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @todo Add your board-specific code, if any.
+ */
+void boardInit(void) {
+}
diff --git a/drivers/boards/GENERIC_STM32_F303XC/board.h b/drivers/boards/GENERIC_STM32_F303XC/board.h
new file mode 100644
index 0000000000..11120dfd74
--- /dev/null
+++ b/drivers/boards/GENERIC_STM32_F303XC/board.h
@@ -0,0 +1,1187 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for Generic STM32_F303 Board
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_GENERIC_STM32_F303XC
+#define BOARD_NAME "STM32_F303"
+
+/*
+ * Board oscillators-related settings.
+ * NOTE: LSE not fitted.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 0U
+#endif
+
+#define STM32_LSEDRV (3U << 3U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+// #define STM32_HSE_BYPASS
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32F303xC
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_PIN0 0U
+#define GPIOA_PIN1 1U
+#define GPIOA_PIN2 2U
+#define GPIOA_PIN3 3U
+#define GPIOA_PIN4 4U
+#define GPIOA_PIN5 5U
+#define GPIOA_PIN6 6U
+#define GPIOA_PIN7 7U
+#define GPIOA_PIN8 8U
+#define GPIOA_PIN9 9U
+#define GPIOA_PIN10 10U
+#define GPIOA_USB_DM 11U
+#define GPIOA_USB_DP 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_PIN0 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_PIN3 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_PIN5 5U
+#define GPIOB_PIN6 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_PIN8 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_PIN10 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_PIN0 0U
+#define GPIOC_PIN1 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_PIN7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_PIN13 13U
+#define GPIOC_PIN14 14U
+#define GPIOC_PIN15 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_I2C2_SDA 0U
+#define GPIOF_I2C2_SCL 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_PIN6 6U
+#define GPIOG_PIN7 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_PIN11 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_PIN13 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+#define GPIOH_PIN0 0U
+#define GPIOH_PIN1 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_L3GD20_SDI PAL_LINE(GPIOA, 7U)
+#define LINE_USB_DM PAL_LINE(GPIOA, 11U)
+#define LINE_USB_DP PAL_LINE(GPIOA, 12U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+
+#define LINE_PIN6 PAL_LINE(GPIOF, 0U)
+#define LINE_PIN7 PAL_LINE(GPIOF, 1U)
+
+#define LINE_CAPS_LOCK PAL_LINE(GPIOB, 7U)
+
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - NC
+ * PA1 - NC
+ * PA2 - COL1
+ * PA3 - COL2
+ * PA4 - SPEAKER1
+ * PA5 - SPEAKER2
+ * PA6 - COL3
+ * PA7 - COL8
+ * PA8 - COL6
+ * PA9 - COL7
+ * PA10 - ROW5
+ * PA11 - USB_DM (alternate 14).
+ * PA12 - USB_DP (alternate 14).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - ROW4
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \
+ PIN_MODE_ALTERNATE(GPIOA_PIN1) | \
+ PIN_MODE_INPUT(GPIOA_PIN2) | \
+ PIN_MODE_INPUT(GPIOA_PIN3) | \
+ PIN_MODE_INPUT(GPIOA_PIN4) | \
+ PIN_MODE_INPUT(GPIOA_PIN5) | \
+ PIN_MODE_INPUT(GPIOA_PIN6) | \
+ PIN_MODE_INPUT(GPIOA_PIN7) | \
+ PIN_MODE_INPUT(GPIOA_PIN8) | \
+ PIN_MODE_INPUT(GPIOA_PIN9) | \
+ PIN_MODE_INPUT(GPIOA_PIN10) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_INPUT(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_DM) | \
+ PIN_OSPEED_VERYLOW(GPIOA_USB_DP) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \
+ PIN_ODR_HIGH(GPIOA_PIN1) | \
+ PIN_ODR_HIGH(GPIOA_PIN2) | \
+ PIN_ODR_HIGH(GPIOA_PIN3) | \
+ PIN_ODR_HIGH(GPIOA_PIN4) | \
+ PIN_ODR_HIGH(GPIOA_PIN5) | \
+ PIN_ODR_HIGH(GPIOA_PIN6) | \
+ PIN_ODR_HIGH(GPIOA_PIN7) | \
+ PIN_ODR_HIGH(GPIOA_PIN8) | \
+ PIN_ODR_HIGH(GPIOA_PIN9) | \
+ PIN_ODR_HIGH(GPIOA_PIN10) | \
+ PIN_ODR_HIGH(GPIOA_USB_DM) | \
+ PIN_ODR_HIGH(GPIOA_USB_DP) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0) | \
+ PIN_AFIO_AF(GPIOA_PIN1, 1) | \
+ PIN_AFIO_AF(GPIOA_PIN2, 0) | \
+ PIN_AFIO_AF(GPIOA_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOA_PIN4, 0) | \
+ PIN_AFIO_AF(GPIOA_PIN5, 5) | \
+ PIN_AFIO_AF(GPIOA_PIN6, 5) | \
+ PIN_AFIO_AF(GPIOA_PIN7, 5))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOA_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOA_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOA_USB_DM, 14) | \
+ PIN_AFIO_AF(GPIOA_USB_DP, 14) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - PIN0 (input pullup).
+ * PB1 - PIN1 (input pullup).
+ * PB2 - PIN2 (input pullup).
+ * PB3 - PIN3 (alternate 0).
+ * PB4 - PIN4 (input pullup).
+ * PB5 - PIN5 (input pullup).
+ * PB6 - PIN6 LSM303DLHC_SCL (alternate 4).
+ * PB7 - PIN7 LSM303DLHC_SDA (alternate 4).
+ * PB8 - PIN8 (input pullup).
+ * PB9 - PIN9 (input pullup).
+ * PB10 - PIN10 (input pullup).
+ * PB11 - PIN11 (input pullup).
+ * PB12 - PIN12 (input pullup).
+ * PB13 - PIN13 (input pullup).
+ * PB14 - PIN14 (input pullup).
+ * PB15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_ALTERNATE(GPIOB_PIN3) | \
+ PIN_MODE_INPUT(GPIOB_PIN4) | \
+ PIN_MODE_INPUT(GPIOB_PIN5) | \
+ PIN_MODE_ALTERNATE(GPIOB_PIN6) | \
+ PIN_MODE_OUTPUT(GPIOB_PIN7) | \
+ PIN_MODE_INPUT(GPIOB_PIN8) | \
+ PIN_MODE_INPUT(GPIOB_PIN9) | \
+ PIN_MODE_INPUT(GPIOB_PIN10) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_INPUT(GPIOB_PIN13) | \
+ PIN_MODE_INPUT(GPIOB_PIN14) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \
+ PIN_OTYPE_OPENDRAIN(GPIOB_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN6) | \
+ PIN_PUPDR_PULLDOWN(GPIOB_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_PIN3) | \
+ PIN_ODR_HIGH(GPIOB_PIN4) | \
+ PIN_ODR_HIGH(GPIOB_PIN5) | \
+ PIN_ODR_HIGH(GPIOB_PIN6) | \
+ PIN_ODR_LOW(GPIOB_PIN7) | \
+ PIN_ODR_HIGH(GPIOB_PIN8) | \
+ PIN_ODR_HIGH(GPIOB_PIN9) | \
+ PIN_ODR_HIGH(GPIOB_PIN10) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_PIN13) | \
+ PIN_ODR_HIGH(GPIOB_PIN14) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN4, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN5, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN6, 4) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - PIN0 (input pullup).
+ * PC1 - PIN1 (input pullup).
+ * PC2 - PIN2 (input pullup).
+ * PC3 - PIN3 (input pullup).
+ * PC4 - PIN4 (input pullup).
+ * PC5 - PIN5 (input pullup).
+ * PC6 - PIN6 (input pullup).
+ * PC7 - PIN7 (input pullup).
+ * PC8 - PIN8 (input pullup).
+ * PC9 - PIN9 (input pullup).
+ * PC10 - PIN10 (input pullup).
+ * PC11 - PIN11 (input pullup).
+ * PC12 - PIN12 (input pullup).
+ * PC13 - PIN13 (input pullup).
+ * PC14 - PIN14 (input floating).
+ * PC15 - PIN15 (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \
+ PIN_MODE_INPUT(GPIOC_PIN1) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_INPUT(GPIOC_PIN4) | \
+ PIN_MODE_INPUT(GPIOC_PIN5) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_PIN7) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_PIN13) | \
+ PIN_MODE_INPUT(GPIOC_PIN14) | \
+ PIN_MODE_INPUT(GPIOC_PIN15))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN15))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN15))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN15))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \
+ PIN_ODR_HIGH(GPIOC_PIN1) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_PIN4) | \
+ PIN_ODR_HIGH(GPIOC_PIN5) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_PIN7) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_PIN13) | \
+ PIN_ODR_HIGH(GPIOC_PIN14) | \
+ PIN_ODR_HIGH(GPIOC_PIN15))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN1, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN7, 0))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN13, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN14, 0) | \
+ PIN_AFIO_AF(GPIOC_PIN15, 0))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (input pullup).
+ * PD1 - PIN1 (input pullup).
+ * PD2 - PIN2 (input pullup).
+ * PD3 - PIN3 (input pullup).
+ * PD4 - PIN4 (input pullup).
+ * PD5 - PIN5 (input pullup).
+ * PD6 - PIN6 (input pullup).
+ * PD7 - PIN7 (input pullup).
+ * PD8 - PIN8 (input pullup).
+ * PD9 - PIN9 (input pullup).
+ * PD11 - PIN10 (input pullup).
+ * PD11 - PIN11 (input pullup).
+ * PD12 - PIN12 (input pullup).
+ * PD13 - PIN13 (input pullup).
+ * PD14 - PIN14 (input pullup).
+ * PD15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \
+ PIN_MODE_INPUT(GPIOD_PIN1) | \
+ PIN_MODE_INPUT(GPIOD_PIN2) | \
+ PIN_MODE_INPUT(GPIOD_PIN3) | \
+ PIN_MODE_INPUT(GPIOD_PIN4) | \
+ PIN_MODE_INPUT(GPIOD_PIN5) | \
+ PIN_MODE_INPUT(GPIOD_PIN6) | \
+ PIN_MODE_INPUT(GPIOD_PIN7) | \
+ PIN_MODE_INPUT(GPIOD_PIN8) | \
+ PIN_MODE_INPUT(GPIOD_PIN9) | \
+ PIN_MODE_INPUT(GPIOD_PIN10) | \
+ PIN_MODE_INPUT(GPIOD_PIN11) | \
+ PIN_MODE_INPUT(GPIOD_PIN12) | \
+ PIN_MODE_INPUT(GPIOD_PIN13) | \
+ PIN_MODE_INPUT(GPIOD_PIN14) | \
+ PIN_MODE_INPUT(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_PIN8) | \
+ PIN_ODR_HIGH(GPIOD_PIN9) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (input pullup).
+ * PE1 - PIN1 (input pullup).
+ * PE2 - PIN2 (input pullup).
+ * PE3 - PIN3 L3GD20_CS (output pushpull maximum).
+ * PE4 - PIN4 (input pullup).
+ * PE5 - PIN5 (input pullup).
+ * PE6 - PIN6 (input pullup).
+ * PE7 - PIN7 (input pullup).
+ * PE8 - PIN8 (output pushpull maximum).
+ * PE9 - PIN9 (output pushpull maximum).
+ * PE10 - PIN10 (output pushpull maximum).
+ * PE11 - PIN11 (output pushpull maximum).
+ * PE12 - PIN12 (output pushpull maximum).
+ * PE13 - PIN13 (output pushpull maximum).
+ * PE14 - PIN14 (output pushpull maximum).
+ * PE15 - PIN15 (output pushpull maximum).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \
+ PIN_MODE_INPUT(GPIOE_PIN1) | \
+ PIN_MODE_INPUT(GPIOE_PIN2) |\
+ PIN_MODE_OUTPUT(GPIOE_PIN3) | \
+ PIN_MODE_INPUT(GPIOE_PIN4) |\
+ PIN_MODE_INPUT(GPIOE_PIN5) |\
+ PIN_MODE_INPUT(GPIOE_PIN6) | \
+ PIN_MODE_INPUT(GPIOE_PIN7) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN8) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN9) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN10) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN11) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN12) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN13) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN14) | \
+ PIN_MODE_OUTPUT(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) |\
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) |\
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) |\
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) |\
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) |\
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) |\
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) |\
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) |\
+ PIN_OSPEED_VERYLOW(GPIOE_PIN1) |\
+ PIN_OSPEED_VERYLOW(GPIOE_PIN2) |\
+ PIN_OSPEED_HIGH(GPIOE_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN4) |\
+ PIN_OSPEED_VERYLOW(GPIOE_PIN5) |\
+ PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN2) |\
+ PIN_PUPDR_FLOATING(GPIOE_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN4) |\
+ PIN_PUPDR_PULLUP(GPIOE_PIN5) |\
+ PIN_PUPDR_PULLUP(GPIOE_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN14) |\
+ PIN_PUPDR_FLOATING(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \
+ PIN_ODR_HIGH(GPIOE_PIN1) | \
+ PIN_ODR_HIGH(GPIOE_PIN2) | \
+ PIN_ODR_HIGH(GPIOE_PIN3) | \
+ PIN_ODR_HIGH(GPIOE_PIN4) | \
+ PIN_ODR_HIGH(GPIOE_PIN5) | \
+ PIN_ODR_HIGH(GPIOE_PIN6) | \
+ PIN_ODR_HIGH(GPIOE_PIN7) | \
+ PIN_ODR_LOW(GPIOE_PIN8) | \
+ PIN_ODR_LOW(GPIOE_PIN9) | \
+ PIN_ODR_LOW(GPIOE_PIN10) | \
+ PIN_ODR_LOW(GPIOE_PIN11) | \
+ PIN_ODR_LOW(GPIOE_PIN12) | \
+ PIN_ODR_LOW(GPIOE_PIN13) | \
+ PIN_ODR_LOW(GPIOE_PIN14) | \
+ PIN_ODR_LOW(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0) |\
+ PIN_AFIO_AF(GPIOE_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0) |\
+ PIN_AFIO_AF(GPIOE_PIN5, 0) |\
+ PIN_AFIO_AF(GPIOE_PIN6, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - I2C2_SDA (input floating).
+ * PF1 - I2C2_SCL (input floating).
+ * PF2 - PIN2 (input pullup).
+ * PF3 - PIN3 (input pullup).
+ * PF4 - PIN4 (input pullup).
+ * PF5 - PIN5 (input pullup).
+ * PF6 - PIN6 (input pullup).
+ * PF7 - PIN7 (input pullup).
+ * PF8 - PIN8 (input pullup).
+ * PF9 - PIN9 (input pullup).
+ * PF10 - PIN10 (input pullup).
+ * PF11 - PIN11 (input pullup).
+ * PF12 - PIN12 (input pullup).
+ * PF13 - PIN13 (input pullup).
+ * PF14 - PIN14 (input pullup).
+ * PF15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_I2C2_SDA) | \
+ PIN_MODE_INPUT(GPIOF_I2C2_SCL) | \
+ PIN_MODE_INPUT(GPIOF_PIN2) | \
+ PIN_MODE_INPUT(GPIOF_PIN3) | \
+ PIN_MODE_INPUT(GPIOF_PIN4) | \
+ PIN_MODE_INPUT(GPIOF_PIN5) | \
+ PIN_MODE_INPUT(GPIOF_PIN6) | \
+ PIN_MODE_INPUT(GPIOF_PIN7) | \
+ PIN_MODE_INPUT(GPIOF_PIN8) | \
+ PIN_MODE_INPUT(GPIOF_PIN9) | \
+ PIN_MODE_INPUT(GPIOF_PIN10) | \
+ PIN_MODE_INPUT(GPIOF_PIN11) | \
+ PIN_MODE_INPUT(GPIOF_PIN12) | \
+ PIN_MODE_INPUT(GPIOF_PIN13) | \
+ PIN_MODE_INPUT(GPIOF_PIN14) | \
+ PIN_MODE_INPUT(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SDA) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SCL) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_I2C2_SDA) | \
+ PIN_OSPEED_HIGH(GPIOF_I2C2_SCL) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_I2C2_SDA) | \
+ PIN_PUPDR_FLOATING(GPIOF_I2C2_SCL) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_I2C2_SDA) | \
+ PIN_ODR_HIGH(GPIOF_I2C2_SCL) | \
+ PIN_ODR_HIGH(GPIOF_PIN2) | \
+ PIN_ODR_HIGH(GPIOF_PIN3) | \
+ PIN_ODR_HIGH(GPIOF_PIN4) | \
+ PIN_ODR_HIGH(GPIOF_PIN5) | \
+ PIN_ODR_HIGH(GPIOF_PIN6) | \
+ PIN_ODR_HIGH(GPIOF_PIN7) | \
+ PIN_ODR_HIGH(GPIOF_PIN8) | \
+ PIN_ODR_HIGH(GPIOF_PIN9) | \
+ PIN_ODR_HIGH(GPIOF_PIN10) | \
+ PIN_ODR_HIGH(GPIOF_PIN11) | \
+ PIN_ODR_HIGH(GPIOF_PIN12) | \
+ PIN_ODR_HIGH(GPIOF_PIN13) | \
+ PIN_ODR_HIGH(GPIOF_PIN14) | \
+ PIN_ODR_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_I2C2_SDA, 0) | \
+ PIN_AFIO_AF(GPIOF_I2C2_SCL, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (input pullup).
+ * PG1 - PIN1 (input pullup).
+ * PG2 - PIN2 (input pullup).
+ * PG3 - PIN3 (input pullup).
+ * PG4 - PIN4 (input pullup).
+ * PG5 - PIN5 (input pullup).
+ * PG6 - PIN6 (input pullup).
+ * PG7 - PIN7 (input pullup).
+ * PG8 - PIN8 (input pullup).
+ * PG9 - PIN9 (input pullup).
+ * PG10 - PIN10 (input pullup).
+ * PG11 - PIN11 (input pullup).
+ * PG12 - PIN12 (input pullup).
+ * PG13 - PIN13 (input pullup).
+ * PG14 - PIN14 (input pullup).
+ * PG15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \
+ PIN_MODE_INPUT(GPIOG_PIN1) | \
+ PIN_MODE_INPUT(GPIOG_PIN2) | \
+ PIN_MODE_INPUT(GPIOG_PIN3) | \
+ PIN_MODE_INPUT(GPIOG_PIN4) | \
+ PIN_MODE_INPUT(GPIOG_PIN5) | \
+ PIN_MODE_INPUT(GPIOG_PIN6) | \
+ PIN_MODE_INPUT(GPIOG_PIN7) | \
+ PIN_MODE_INPUT(GPIOG_PIN8) | \
+ PIN_MODE_INPUT(GPIOG_PIN9) | \
+ PIN_MODE_INPUT(GPIOG_PIN10) | \
+ PIN_MODE_INPUT(GPIOG_PIN11) | \
+ PIN_MODE_INPUT(GPIOG_PIN12) | \
+ PIN_MODE_INPUT(GPIOG_PIN13) | \
+ PIN_MODE_INPUT(GPIOG_PIN14) | \
+ PIN_MODE_INPUT(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \
+ PIN_ODR_HIGH(GPIOG_PIN1) | \
+ PIN_ODR_HIGH(GPIOG_PIN2) | \
+ PIN_ODR_HIGH(GPIOG_PIN3) | \
+ PIN_ODR_HIGH(GPIOG_PIN4) | \
+ PIN_ODR_HIGH(GPIOG_PIN5) | \
+ PIN_ODR_HIGH(GPIOG_PIN6) | \
+ PIN_ODR_HIGH(GPIOG_PIN7) | \
+ PIN_ODR_HIGH(GPIOG_PIN8) | \
+ PIN_ODR_HIGH(GPIOG_PIN9) | \
+ PIN_ODR_HIGH(GPIOG_PIN10) | \
+ PIN_ODR_HIGH(GPIOG_PIN11) | \
+ PIN_ODR_HIGH(GPIOG_PIN12) | \
+ PIN_ODR_HIGH(GPIOG_PIN13) | \
+ PIN_ODR_HIGH(GPIOG_PIN14) | \
+ PIN_ODR_HIGH(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN6, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN7, 0))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN11, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN13, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - PIN0 (input pullup).
+ * PH1 - PIN1 (input pullup).
+ * PH2 - PIN2 (input pullup).
+ * PH3 - PIN3 (input pullup).
+ * PH4 - PIN4 (input pullup).
+ * PH5 - PIN5 (input pullup).
+ * PH6 - PIN6 (input pullup).
+ * PH7 - PIN7 (input pullup).
+ * PH8 - PIN8 (input pullup).
+ * PH9 - PIN9 (input pullup).
+ * PH10 - PIN10 (input pullup).
+ * PH11 - PIN11 (input pullup).
+ * PH12 - PIN12 (input pullup).
+ * PH13 - PIN13 (input pullup).
+ * PH14 - PIN14 (input pullup).
+ * PH15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_PIN0) | \
+ PIN_MODE_INPUT(GPIOH_PIN1) | \
+ PIN_MODE_INPUT(GPIOH_PIN2) | \
+ PIN_MODE_INPUT(GPIOH_PIN3) | \
+ PIN_MODE_INPUT(GPIOH_PIN4) | \
+ PIN_MODE_INPUT(GPIOH_PIN5) | \
+ PIN_MODE_INPUT(GPIOH_PIN6) | \
+ PIN_MODE_INPUT(GPIOH_PIN7) | \
+ PIN_MODE_INPUT(GPIOH_PIN8) | \
+ PIN_MODE_INPUT(GPIOH_PIN9) | \
+ PIN_MODE_INPUT(GPIOH_PIN10) | \
+ PIN_MODE_INPUT(GPIOH_PIN11) | \
+ PIN_MODE_INPUT(GPIOH_PIN12) | \
+ PIN_MODE_INPUT(GPIOH_PIN13) | \
+ PIN_MODE_INPUT(GPIOH_PIN14) | \
+ PIN_MODE_INPUT(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOH_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_PULLUP(GPIOH_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_PIN0) | \
+ PIN_ODR_HIGH(GPIOH_PIN1) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_PIN0, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN1, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0))
+
+
+/*
+ * USB bus activation macro, required by the USB driver.
+ */
+// #define usb_lld_connect_bus(usbp)
+#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)))
+// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT)
+/*
+ * USB bus de-activation macro, required by the USB driver.
+ */
+// #define usb_lld_disconnect_bus(usbp)
+#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)); palClearPad(GPIOA, GPIOA_USB_DP)
+// #define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12)
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/drivers/boards/GENERIC_STM32_F303XC/board.mk b/drivers/boards/GENERIC_STM32_F303XC/board.mk
new file mode 100644
index 0000000000..43377629a3
--- /dev/null
+++ b/drivers/boards/GENERIC_STM32_F303XC/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC/board.c
+
+# Required include directories
+BOARDINC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC
diff --git a/drivers/boards/GENERIC_STM32_F303XC/bootloader_defs.h b/drivers/boards/GENERIC_STM32_F303XC/bootloader_defs.h
new file mode 100644
index 0000000000..3b0e9d20a6
--- /dev/null
+++ b/drivers/boards/GENERIC_STM32_F303XC/bootloader_defs.h
@@ -0,0 +1,7 @@
+/* Address for jumping to bootloader on STM32 chips. */
+/* It is chip dependent, the correct number can be looked up here:
+ * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+ * This also requires a patch to chibios:
+ * <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+ */
+#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800
diff --git a/drivers/haptic/DRV2605L.c b/drivers/haptic/DRV2605L.c
new file mode 100644
index 0000000000..97ca292b9b
--- /dev/null
+++ b/drivers/haptic/DRV2605L.c
@@ -0,0 +1,129 @@
+/* Copyright 2018 ishtob
+ * Driver for DRV2605L written for QMK
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "DRV2605L.h"
+#include "print.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+
+uint8_t DRV2605L_transfer_buffer[20];
+uint8_t DRV2605L_tx_register[0];
+uint8_t DRV2605L_read_buffer[0];
+uint8_t DRV2605L_read_register;
+
+
+void DRV_write(uint8_t drv_register, uint8_t settings) {
+ DRV2605L_transfer_buffer[0] = drv_register;
+ DRV2605L_transfer_buffer[1] = settings;
+ i2c_transmit(DRV2605L_BASE_ADDRESS << 1, DRV2605L_transfer_buffer, 2, 100);
+}
+
+uint8_t DRV_read(uint8_t regaddress) {
+ DRV2605L_tx_register[0] = regaddress;
+ if (MSG_OK != i2c_transmit_receive(DRV2605L_BASE_ADDRESS << 1,
+ DRV2605L_tx_register, 1,
+ DRV2605L_read_buffer, 1
+)){
+ printf("err reading reg \n");
+ }
+ DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];
+return DRV2605L_read_register;
+}
+
+void DRV_init(void)
+{
+ i2c_init();
+ i2c_start(DRV2605L_BASE_ADDRESS);
+
+ /* 0x07 sets DRV2605 into calibration mode */
+ DRV_write(DRV_MODE,0x07);
+
+// DRV_write(DRV_FEEDBACK_CTRL,0xB6);
+
+ #if FB_ERM_LRA == 0
+ /* ERM settings */
+ DRV_write(DRV_RATED_VOLT, (RATED_VOLTAGE/21.33)*1000);
+ #if ERM_OPEN_LOOP == 0
+ DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (((V_PEAK*(DRIVE_TIME+BLANKING_TIME+IDISS_TIME))/0.02133)/(DRIVE_TIME-0.0003)));
+ #elif ERM_OPEN_LOOP == 1
+ DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196));
+ #endif
+ #elif FB_ERM_LRA == 1
+ DRV_write(DRV_RATED_VOLT, ((V_RMS * sqrt(1 - ((4 * ((150+(SAMPLE_TIME*50))*0.000001)) + 0.0003)* F_LRA)/0.02071)));
+ #if LRA_OPEN_LOOP == 0
+ DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, ((V_PEAK/sqrt(1-(F_LRA*0.0008))/0.02133)));
+ #elif LRA_OPEN_LOOP == 1
+ DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196));
+ #endif
+ #endif
+
+ DRVREG_FBR FB_SET;
+ FB_SET.Bits.ERM_LRA = FB_ERM_LRA;
+ FB_SET.Bits.BRAKE_FACTOR = FB_BRAKEFACTOR;
+ FB_SET.Bits.LOOP_GAIN =FB_LOOPGAIN;
+ FB_SET.Bits.BEMF_GAIN = 0; /* auto-calibration populates this field*/
+ DRV_write(DRV_FEEDBACK_CTRL, (uint8_t) FB_SET.Byte);
+ DRVREG_CTRL1 C1_SET;
+ C1_SET.Bits.C1_DRIVE_TIME = DRIVE_TIME;
+ C1_SET.Bits.C1_AC_COUPLE = AC_COUPLE;
+ C1_SET.Bits.C1_STARTUP_BOOST = STARTUP_BOOST;
+ DRV_write(DRV_CTRL_1, (uint8_t) C1_SET.Byte);
+ DRVREG_CTRL2 C2_SET;
+ C2_SET.Bits.C2_BIDIR_INPUT = BIDIR_INPUT;
+ C2_SET.Bits.C2_BRAKE_STAB = BRAKE_STAB;
+ C2_SET.Bits.C2_SAMPLE_TIME = SAMPLE_TIME;
+ C2_SET.Bits.C2_BLANKING_TIME = BLANKING_TIME;
+ C2_SET.Bits.C2_IDISS_TIME = IDISS_TIME;
+ DRV_write(DRV_CTRL_2, (uint8_t) C2_SET.Byte);
+ DRVREG_CTRL3 C3_SET;
+ C3_SET.Bits.C3_LRA_OPEN_LOOP = LRA_OPEN_LOOP;
+ C3_SET.Bits.C3_N_PWM_ANALOG = N_PWM_ANALOG;
+ C3_SET.Bits.C3_LRA_DRIVE_MODE = LRA_DRIVE_MODE;
+ C3_SET.Bits.C3_DATA_FORMAT_RTO = DATA_FORMAT_RTO;
+ C3_SET.Bits.C3_SUPPLY_COMP_DIS = SUPPLY_COMP_DIS;
+ C3_SET.Bits.C3_ERM_OPEN_LOOP = ERM_OPEN_LOOP;
+ C3_SET.Bits.C3_NG_THRESH = NG_THRESH;
+ DRV_write(DRV_CTRL_3, (uint8_t) C3_SET.Byte);
+ DRVREG_CTRL4 C4_SET;
+ C4_SET.Bits.C4_ZC_DET_TIME = ZC_DET_TIME;
+ C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME;
+ DRV_write(DRV_CTRL_4, (uint8_t) C4_SET.Byte);
+ DRV_write(DRV_LIB_SELECTION,LIB_SELECTION);
+ //start autocalibration
+ DRV_write(DRV_GO, 0x01);
+
+ /* 0x00 sets DRV2605 out of standby and to use internal trigger
+ * 0x01 sets DRV2605 out of standby and to use external trigger */
+ DRV_write(DRV_MODE,0x00);
+
+ /* 0x06: LRA library */
+ DRV_write(DRV_WAVEFORM_SEQ_1, 0x01);
+
+ /* 0xB9: LRA, 4x brake factor, medium gain, 7.5x back EMF
+ * 0x39: ERM, 4x brake factor, medium gain, 1.365x back EMF */
+
+ /* TODO: setup auto-calibration as part of initiation */
+
+}
+
+void DRV_pulse(uint8_t sequence)
+{
+ DRV_write(DRV_GO, 0x00);
+ DRV_write(DRV_WAVEFORM_SEQ_1, sequence);
+ DRV_write(DRV_GO, 0x01);
+} \ No newline at end of file
diff --git a/drivers/haptic/DRV2605L.h b/drivers/haptic/DRV2605L.h
new file mode 100644
index 0000000000..de9d294e9d
--- /dev/null
+++ b/drivers/haptic/DRV2605L.h
@@ -0,0 +1,394 @@
+/* Copyright 2018 ishtob
+ * Driver for DRV2605L written for QMK
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include "i2c_master.h"
+
+/* Initialization settings
+
+ * Feedback Control Settings */
+#ifndef FB_ERM_LRA
+#define FB_ERM_LRA 1 /* For ERM:0 or LRA:1*/
+#endif
+#ifndef FB_BRAKEFACTOR
+#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
+#endif
+#ifndef FB_LOOPGAIN
+#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
+#endif
+
+#ifndef RATED_VOLTAGE
+#define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */
+#ifndef V_PEAK
+#define V_PEAK 2.8
+#endif
+#endif
+
+/* LRA specific settings */
+#if FB_ERM_LRA == 1
+#ifndef V_RMS
+#define V_RMS 2.0
+#endif
+#ifndef V_PEAK
+#define V_PEAK 2.1
+#endif
+#ifndef F_LRA
+#define F_LRA 205
+#endif
+#endif
+
+/* Library Selection */
+#ifndef LIB_SELECTION
+#if FB_ERM_LRA == 1
+#define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */
+#else
+#define LIB_SELECTION 1
+#endif
+#endif
+
+/* Control 1 register settings */
+#ifndef DRIVE_TIME
+#define DRIVE_TIME 25
+#endif
+#ifndef AC_COUPLE
+#define AC_COUPLE 0
+#endif
+#ifndef STARTUP_BOOST
+#define STARTUP_BOOST 1
+#endif
+
+/* Control 2 Settings */
+#ifndef BIDIR_INPUT
+#define BIDIR_INPUT 1
+#endif
+#ifndef BRAKE_STAB
+#define BRAKE_STAB 1 /* Loopgain is reduced when braking is almost complete to improve stability */
+#endif
+#ifndef SAMPLE_TIME
+#define SAMPLE_TIME 3
+#endif
+#ifndef BLANKING_TIME
+#define BLANKING_TIME 1
+#endif
+#ifndef IDISS_TIME
+#define IDISS_TIME 1
+#endif
+
+/* Control 3 settings */
+#ifndef NG_THRESH
+#define NG_THRESH 2
+#endif
+#ifndef ERM_OPEN_LOOP
+#define ERM_OPEN_LOOP 1
+#endif
+#ifndef SUPPLY_COMP_DIS
+#define SUPPLY_COMP_DIS 0
+#endif
+#ifndef DATA_FORMAT_RTO
+#define DATA_FORMAT_RTO 0
+#endif
+#ifndef LRA_DRIVE_MODE
+#define LRA_DRIVE_MODE 0
+#endif
+#ifndef N_PWM_ANALOG
+#define N_PWM_ANALOG 0
+#endif
+#ifndef LRA_OPEN_LOOP
+#define LRA_OPEN_LOOP 0
+#endif
+
+/* Control 4 settings */
+#ifndef ZC_DET_TIME
+#define ZC_DET_TIME 0
+#endif
+#ifndef AUTO_CAL_TIME
+#define AUTO_CAL_TIME 3
+#endif
+
+/* register defines -------------------------------------------------------- */
+#define DRV2605L_BASE_ADDRESS 0x5A /* DRV2605L Base address */
+#define DRV_STATUS 0x00
+#define DRV_MODE 0x01
+#define DRV_RTP_INPUT 0x02
+#define DRV_LIB_SELECTION 0x03
+#define DRV_WAVEFORM_SEQ_1 0x04
+#define DRV_WAVEFORM_SEQ_2 0x05
+#define DRV_WAVEFORM_SEQ_3 0x06
+#define DRV_WAVEFORM_SEQ_4 0x07
+#define DRV_WAVEFORM_SEQ_5 0x08
+#define DRV_WAVEFORM_SEQ_6 0x09
+#define DRV_WAVEFORM_SEQ_7 0x0A
+#define DRV_WAVEFORM_SEQ_8 0x0B
+#define DRV_GO 0x0C
+#define DRV_OVERDRIVE_TIME_OFFSET 0x0D
+#define DRV_SUSTAIN_TIME_OFFSET_P 0x0E
+#define DRV_SUSTAIN_TIME_OFFSET_N 0x0F
+#define DRV_BRAKE_TIME_OFFSET 0x10
+#define DRV_AUDIO_2_VIBE_CTRL 0x11
+#define DRV_AUDIO_2_VIBE_MIN_IN 0x12
+#define DRV_AUDIO_2_VIBE_MAX_IN 0x13
+#define DRV_AUDIO_2_VIBE_MIN_OUTDRV 0x14
+#define DRV_AUDIO_2_VIBE_MAX_OUTDRV 0x15
+#define DRV_RATED_VOLT 0x16
+#define DRV_OVERDRIVE_CLAMP_VOLT 0x17
+#define DRV_AUTO_CALIB_COMP_RESULT 0x18
+#define DRV_AUTO_CALIB_BEMF_RESULT 0x19
+#define DRV_FEEDBACK_CTRL 0x1A
+#define DRV_CTRL_1 0x1B
+#define DRV_CTRL_2 0x1C
+#define DRV_CTRL_3 0x1D
+#define DRV_CTRL_4 0x1E
+#define DRV_CTRL_5 0x1F
+#define DRV_OPEN_LOOP_PERIOD 0x20
+#define DRV_VBAT_VOLT_MONITOR 0x21
+#define DRV_LRA_RESONANCE_PERIOD 0x22
+
+void DRV_init(void);
+void DRV_write(const uint8_t drv_register, const uint8_t settings);
+uint8_t DRV_read(const uint8_t regaddress);
+void DRV_pulse(const uint8_t sequence);
+
+
+typedef enum DRV_EFFECT{
+ clear_sequence = 0,
+ strong_click = 1,
+ strong_click_60 = 2,
+ strong_click_30 = 3,
+ sharp_click = 4,
+ sharp_click_60 = 5,
+ sharp_click_30 = 6,
+ soft_bump = 7,
+ soft_bump_60 = 8,
+ soft_bump_30 = 9,
+ dbl_click = 10,
+ dbl_click_60 = 11,
+ trp_click = 12,
+ soft_fuzz = 13,
+ strong_buzz = 14,
+ alert_750ms = 15,
+ alert_1000ms = 16,
+ strong_click1 = 17,
+ strong_click2_80 = 18,
+ strong_click3_60 = 19,
+ strong_click4_30 = 20,
+ medium_click1 = 21,
+ medium_click2_80 = 22,
+ medium_click3_60 = 23,
+ sharp_tick1 = 24,
+ sharp_tick2_80 = 25,
+ sharp_tick3_60 = 26,
+ sh_dblclick_str = 27,
+ sh_dblclick_str_80 = 28,
+ sh_dblclick_str_60 = 29,
+ sh_dblclick_str_30 = 30,
+ sh_dblclick_med = 31,
+ sh_dblclick_med_80 = 32,
+ sh_dblclick_med_60 = 33,
+ sh_dblsharp_tick = 34,
+ sh_dblsharp_tick_80 = 35,
+ sh_dblsharp_tick_60 = 36,
+ lg_dblclick_str = 37,
+ lg_dblclick_str_80 = 38,
+ lg_dblclick_str_60 = 39,
+ lg_dblclick_str_30 = 40,
+ lg_dblclick_med = 41,
+ lg_dblclick_med_80 = 42,
+ lg_dblclick_med_60 = 43,
+ lg_dblsharp_tick = 44,
+ lg_dblsharp_tick_80 = 45,
+ lg_dblsharp_tick_60 = 46,
+ buzz = 47,
+ buzz_80 = 48,
+ buzz_60 = 49,
+ buzz_40 = 50,
+ buzz_20 = 51,
+ pulsing_strong = 52,
+ pulsing_strong_80 = 53,
+ pulsing_medium = 54,
+ pulsing_medium_80 = 55,
+ pulsing_sharp = 56,
+ pulsing_sharp_80 = 57,
+ transition_click = 58,
+ transition_click_80 = 59,
+ transition_click_60 = 60,
+ transition_click_40 = 61,
+ transition_click_20 = 62,
+ transition_click_10 = 63,
+ transition_hum = 64,
+ transition_hum_80 = 65,
+ transition_hum_60 = 66,
+ transition_hum_40 = 67,
+ transition_hum_20 = 68,
+ transition_hum_10 = 69,
+ transition_rampdown_long_smooth1 = 70,
+ transition_rampdown_long_smooth2 = 71,
+ transition_rampdown_med_smooth1 = 72,
+ transition_rampdown_med_smooth2 = 73,
+ transition_rampdown_short_smooth1 = 74,
+ transition_rampdown_short_smooth2 = 75,
+ transition_rampdown_long_sharp1 = 76,
+ transition_rampdown_long_sharp2 = 77,
+ transition_rampdown_med_sharp1 = 78,
+ transition_rampdown_med_sharp2 = 79,
+ transition_rampdown_short_sharp1 = 80,
+ transition_rampdown_short_sharp2 = 81,
+ transition_rampup_long_smooth1 = 82,
+ transition_rampup_long_smooth2 = 83,
+ transition_rampup_med_smooth1 = 84,
+ transition_rampup_med_smooth2 = 85,
+ transition_rampup_short_smooth1 = 86,
+ transition_rampup_short_smooth2 = 87,
+ transition_rampup_long_sharp1 = 88,
+ transition_rampup_long_sharp2 = 89,
+ transition_rampup_med_sharp1 = 90,
+ transition_rampup_med_sharp2 = 91,
+ transition_rampup_short_sharp1 = 92,
+ transition_rampup_short_sharp2 = 93,
+ transition_rampdown_long_smooth1_50 = 94,
+ transition_rampdown_long_smooth2_50 = 95,
+ transition_rampdown_med_smooth1_50 = 96,
+ transition_rampdown_med_smooth2_50 = 97,
+ transition_rampdown_short_smooth1_50 = 98,
+ transition_rampdown_short_smooth2_50 = 99,
+ transition_rampdown_long_sharp1_50 = 100,
+ transition_rampdown_long_sharp2_50 = 101,
+ transition_rampdown_med_sharp1_50 = 102,
+ transition_rampdown_med_sharp2_50 = 103,
+ transition_rampdown_short_sharp1_50 = 104,
+ transition_rampdown_short_sharp2_50 = 105,
+ transition_rampup_long_smooth1_50 = 106,
+ transition_rampup_long_smooth2_50 = 107,
+ transition_rampup_med_smooth1_50 = 108,
+ transition_rampup_med_smooth2_50 = 109,
+ transition_rampup_short_smooth1_50 = 110,
+ transition_rampup_short_smooth2_50 = 111,
+ transition_rampup_long_sharp1_50 = 112,
+ transition_rampup_long_sharp2_50 = 113,
+ transition_rampup_med_sharp1_50 = 114,
+ transition_rampup_med_sharp2_50 = 115,
+ transition_rampup_short_sharp1_50 = 116,
+ transition_rampup_short_sharp2_50 = 117,
+ long_buzz_for_programmatic_stopping = 118,
+ smooth_hum1_50 = 119,
+ smooth_hum2_40 = 120,
+ smooth_hum3_30 = 121,
+ smooth_hum4_20 = 122,
+ smooth_hum5_10 = 123,
+} DRV_EFFECT;
+
+/* Register bit array unions */
+
+typedef union DRVREG_STATUS { /* register 0x00 */
+ uint8_t Byte;
+ struct {
+ uint8_t OC_DETECT :1; /* set to 1 when overcurrent event is detected */
+ uint8_t OVER_TEMP :1; /* set to 1 when device exceeds temp threshold */
+ uint8_t FB_STS :1; /* set to 1 when feedback controller has timed out */
+ /* auto-calibration routine and diagnostic result
+ * result | auto-calibation | diagnostic |
+ * 0 | passed | actuator func normal |
+ * 1 | failed | actuator func fault* |
+ * * actuator is not present or is shorted, timing out, or giving out–of-range back-EMF */
+ uint8_t DIAG_RESULT :1;
+ uint8_t :1;
+ uint8_t DEVICE_ID :3; /* Device IDs 3: DRV2605 4: DRV2604 5: DRV2604L 6: DRV2605L */
+ } Bits;
+} DRVREG_STATUS;
+
+typedef union DRVREG_MODE { /* register 0x01 */
+ uint8_t Byte;
+ struct {
+ uint8_t MODE :3; /* Mode setting */
+ uint8_t :3;
+ uint8_t STANDBY :1; /* 0:standby 1:ready */
+ } Bits;
+} DRVREG_MODE;
+
+typedef union DRVREG_WAIT {
+ uint8_t Byte;
+ struct {
+ uint8_t WAIT_MODE :1; /* Set to 1 to interpret as wait for next 7 bits x10ms */
+ uint8_t WAIT_TIME :7;
+ } Bits;
+} DRVREG_WAIT;
+
+typedef union DRVREG_FBR{ /* register 0x1A */
+ uint8_t Byte;
+ struct {
+ uint8_t BEMF_GAIN :2;
+ uint8_t LOOP_GAIN :2;
+ uint8_t BRAKE_FACTOR :3;
+ uint8_t ERM_LRA :1;
+ } Bits;
+} DRVREG_FBR;
+
+typedef union DRVREG_CTRL1{ /* register 0x1B */
+ uint8_t Byte;
+ struct {
+ uint8_t C1_DRIVE_TIME :5;
+ uint8_t C1_AC_COUPLE :1;
+ uint8_t :1;
+ uint8_t C1_STARTUP_BOOST :1;
+ } Bits;
+} DRVREG_CTRL1;
+
+typedef union DRVREG_CTRL2{ /* register 0x1C */
+ uint8_t Byte;
+ struct {
+ uint8_t C2_IDISS_TIME :2;
+ uint8_t C2_BLANKING_TIME :2;
+ uint8_t C2_SAMPLE_TIME :2;
+ uint8_t C2_BRAKE_STAB :1;
+ uint8_t C2_BIDIR_INPUT :1;
+ } Bits;
+} DRVREG_CTRL2;
+
+typedef union DRVREG_CTRL3{ /* register 0x1D */
+ uint8_t Byte;
+ struct {
+ uint8_t C3_LRA_OPEN_LOOP :1;
+ uint8_t C3_N_PWM_ANALOG :1;
+ uint8_t C3_LRA_DRIVE_MODE :1;
+ uint8_t C3_DATA_FORMAT_RTO :1;
+ uint8_t C3_SUPPLY_COMP_DIS :1;
+ uint8_t C3_ERM_OPEN_LOOP :1;
+ uint8_t C3_NG_THRESH :2;
+ } Bits;
+} DRVREG_CTRL3;
+
+typedef union DRVREG_CTRL4{ /* register 0x1E */
+ uint8_t Byte;
+ struct {
+ uint8_t C4_OTP_PROGRAM :1;
+ uint8_t :1;
+ uint8_t C4_OTP_STATUS :1;
+ uint8_t :1;
+ uint8_t C4_AUTO_CAL_TIME :2;
+ uint8_t C4_ZC_DET_TIME :2;
+ } Bits;
+} DRVREG_CTRL4;
+
+typedef union DRVREG_CTRL5{ /* register 0x1F */
+ uint8_t Byte;
+ struct {
+ uint8_t C5_IDISS_TIME :2;
+ uint8_t C5_BLANKING_TIME :2;
+ uint8_t C5_PLAYBACK_INTERVAL :1;
+ uint8_t C5_LRA_AUTO_OPEN_LOOP :1;
+ uint8_t C5_AUTO_OL_CNT :2;
+ } Bits;
+} DRVREG_CTRL5; \ No newline at end of file
diff --git a/drivers/issi/is31fl3218.c b/drivers/issi/is31fl3218.c
new file mode 100644
index 0000000000..db44f72564
--- /dev/null
+++ b/drivers/issi/is31fl3218.c
@@ -0,0 +1,102 @@
+/* Copyright 2018 Jason Williams (Wilba)
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "is31fl3218.h"
+#include "i2c_master.h"
+
+// This is the full 8-bit address
+#define ISSI_ADDRESS 0b10101000
+
+// These are the register addresses
+#define ISSI_REG_SHUTDOWN 0x00
+#define ISSI_REG_PWM 0x01
+#define ISSI_REG_CONTROL 0x13
+#define ISSI_REG_UPDATE 0x16
+#define ISSI_REG_RESET 0x17
+
+// Default timeout if no I2C response
+#define ISSI_TIMEOUT 100
+
+// Reusable buffer for transfers
+uint8_t g_twi_transfer_buffer[20];
+
+// IS31FL3218 has 18 PWM outputs and a fixed I2C address, so no chaining.
+// If used as RGB LED driver, LEDs are assigned RGB,RGB,RGB,RGB,RGB,RGB
+uint8_t g_pwm_buffer[18];
+bool g_pwm_buffer_update_required = false;
+
+void IS31FL3218_write_register( uint8_t reg, uint8_t data )
+{
+ g_twi_transfer_buffer[0] = reg;
+ g_twi_transfer_buffer[1] = data;
+ i2c_transmit( ISSI_ADDRESS, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
+}
+
+void IS31FL3218_write_pwm_buffer( uint8_t *pwm_buffer )
+{
+ g_twi_transfer_buffer[0] = ISSI_REG_PWM;
+ for ( int i=0; i<18; i++ ) {
+ g_twi_transfer_buffer[1+i] = pwm_buffer[i];
+ }
+
+ i2c_transmit( ISSI_ADDRESS, g_twi_transfer_buffer, 19, ISSI_TIMEOUT);
+}
+
+void IS31FL3218_init(void)
+{
+ // In case we ever want to reinitialize (?)
+ IS31FL3218_write_register( ISSI_REG_RESET, 0x00 );
+
+ // Turn off software shutdown
+ IS31FL3218_write_register( ISSI_REG_SHUTDOWN, 0x01 );
+
+ // Set all PWM values to zero
+ for ( uint8_t i = 0; i < 18; i++ ) {
+ IS31FL3218_write_register( ISSI_REG_PWM+i, 0x00 );
+ }
+
+ // Enable all channels
+ for ( uint8_t i = 0; i < 3; i++ ) {
+ IS31FL3218_write_register( ISSI_REG_CONTROL+i, 0b00111111 );
+ }
+
+ // Load PWM registers and LED Control register data
+ IS31FL3218_write_register( ISSI_REG_UPDATE, 0x01 );
+}
+
+void IS31FL3218_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
+{
+ g_pwm_buffer[index * 3 + 0] = red;
+ g_pwm_buffer[index * 3 + 1] = green;
+ g_pwm_buffer[index * 3 + 2] = blue;
+ g_pwm_buffer_update_required = true;
+}
+
+void IS31FL3218_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
+{
+ for ( int i = 0; i < 6; i++ ) {
+ IS31FL3218_set_color( i, red, green, blue );
+ }
+}
+
+void IS31FL3218_update_pwm_buffers(void)
+{
+ if ( g_pwm_buffer_update_required ) {
+ IS31FL3218_write_pwm_buffer( g_pwm_buffer );
+ // Load PWM registers and LED Control register data
+ IS31FL3218_write_register( ISSI_REG_UPDATE, 0x01 );
+ }
+ g_pwm_buffer_update_required = false;
+}
diff --git a/drivers/issi/is31fl3218.h b/drivers/issi/is31fl3218.h
new file mode 100644
index 0000000000..2d24e51463
--- /dev/null
+++ b/drivers/issi/is31fl3218.h
@@ -0,0 +1,24 @@
+/* Copyright 2018 Jason Williams (Wilba)
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+void IS31FL3218_init(void);
+void IS31FL3218_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3218_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3218_update_pwm_buffers(void);
diff --git a/drivers/is31fl3731.c b/drivers/issi/is31fl3731.c
index 0524feb49f..c9155f5a37 100644
--- a/drivers/is31fl3731.c
+++ b/drivers/issi/is31fl3731.c
@@ -91,7 +91,7 @@ bool g_led_control_registers_update_required = false;
// 0x10 - R16,R15,R14,R13,R12,R11,R10,R09
-void IS31_write_register( uint8_t addr, uint8_t reg, uint8_t data )
+void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data )
{
g_twi_transfer_buffer[0] = reg;
g_twi_transfer_buffer[1] = data;
@@ -106,7 +106,7 @@ void IS31_write_register( uint8_t addr, uint8_t reg, uint8_t data )
#endif
}
-void IS31_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
+void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
{
// assumes bank is already selected
@@ -135,7 +135,7 @@ void IS31_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
}
}
-void IS31_init( uint8_t addr )
+void IS31FL3731_init( uint8_t addr )
{
// In order to avoid the LEDs being driven with garbage data
// in the LED driver's PWM registers, first enable software shutdown,
@@ -143,10 +143,10 @@ void IS31_init( uint8_t addr )
// then disable software shutdown.
// select "function register" bank
- IS31_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
+ IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
// enable software shutdown
- IS31_write_register( addr, ISSI_REG_SHUTDOWN, 0x00 );
+ IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x00 );
// this delay was copied from other drivers, might not be needed
#ifdef __AVR__
_delay_ms( 10 );
@@ -155,47 +155,47 @@ void IS31_init( uint8_t addr )
#endif
// picture mode
- IS31_write_register( addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE );
+ IS31FL3731_write_register( addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE );
// display frame 0
- IS31_write_register( addr, ISSI_REG_PICTUREFRAME, 0x00 );
+ IS31FL3731_write_register( addr, ISSI_REG_PICTUREFRAME, 0x00 );
// audio sync off
- IS31_write_register( addr, ISSI_REG_AUDIOSYNC, 0x00 );
+ IS31FL3731_write_register( addr, ISSI_REG_AUDIOSYNC, 0x00 );
// select bank 0
- IS31_write_register( addr, ISSI_COMMANDREGISTER, 0 );
+ IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 );
// turn off all LEDs in the LED control register
for ( int i = 0x00; i <= 0x11; i++ )
{
- IS31_write_register( addr, i, 0x00 );
+ IS31FL3731_write_register( addr, i, 0x00 );
}
// turn off all LEDs in the blink control register (not really needed)
for ( int i = 0x12; i <= 0x23; i++ )
{
- IS31_write_register( addr, i, 0x00 );
+ IS31FL3731_write_register( addr, i, 0x00 );
}
// set PWM on all LEDs to 0
for ( int i = 0x24; i <= 0xB3; i++ )
{
- IS31_write_register( addr, i, 0x00 );
+ IS31FL3731_write_register( addr, i, 0x00 );
}
// select "function register" bank
- IS31_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
+ IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
// disable software shutdown
- IS31_write_register( addr, ISSI_REG_SHUTDOWN, 0x01 );
+ IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x01 );
// select bank 0 and leave it selected.
// most usage after initialization is just writing PWM buffers in bank 0
// as there's not much point in double-buffering
- IS31_write_register( addr, ISSI_COMMANDREGISTER, 0 );
+ IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 );
}
-void IS31_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
+void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
{
if ( index >= 0 && index < DRIVER_LED_TOTAL ) {
is31_led led = g_is31_leds[index];
@@ -208,15 +208,15 @@ void IS31_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
}
}
-void IS31_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
+void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
{
for ( int i = 0; i < DRIVER_LED_TOTAL; i++ )
{
- IS31_set_color( i, red, green, blue );
+ IS31FL3731_set_color( i, red, green, blue );
}
}
-void IS31_set_led_control_register( uint8_t index, bool red, bool green, bool blue )
+void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue )
{
is31_led led = g_is31_leds[index];
@@ -247,25 +247,24 @@ void IS31_set_led_control_register( uint8_t index, bool red, bool green, bool bl
}
-void IS31_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
+void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
{
if ( g_pwm_buffer_update_required )
{
- IS31_write_pwm_buffer( addr1, g_pwm_buffer[0] );
- IS31_write_pwm_buffer( addr2, g_pwm_buffer[1] );
+ IS31FL3731_write_pwm_buffer( addr1, g_pwm_buffer[0] );
+ IS31FL3731_write_pwm_buffer( addr2, g_pwm_buffer[1] );
}
g_pwm_buffer_update_required = false;
}
-void IS31_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
+void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
{
if ( g_led_control_registers_update_required )
{
for ( int i=0; i<18; i++ )
{
- IS31_write_register(addr1, i, g_led_control_registers[0][i] );
- IS31_write_register(addr2, i, g_led_control_registers[1][i] );
+ IS31FL3731_write_register(addr1, i, g_led_control_registers[0][i] );
+ IS31FL3731_write_register(addr2, i, g_led_control_registers[1][i] );
}
}
}
-
diff --git a/drivers/is31fl3731.h b/drivers/issi/is31fl3731.h
index 9e195c240e..f354a12db2 100644
--- a/drivers/is31fl3731.h
+++ b/drivers/issi/is31fl3731.h
@@ -31,21 +31,21 @@ typedef struct is31_led {
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
-void IS31_init( uint8_t addr );
-void IS31_write_register( uint8_t addr, uint8_t reg, uint8_t data );
-void IS31_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );
+void IS31FL3731_init( uint8_t addr );
+void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data );
+void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );
-void IS31_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
-void IS31_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
-void IS31_set_led_control_register( uint8_t index, bool red, bool green, bool blue );
+void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue );
// This should not be called from an interrupt
// (eg. from a timer interrupt).
// Call this while idle (in between matrix scans).
// If the buffer is dirty, it will update the driver with the buffer.
-void IS31_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
-void IS31_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
+void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
+void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
#define C1_1 0x24
#define C1_2 0x25
diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c
new file mode 100644
index 0000000000..c18ed7ca30
--- /dev/null
+++ b/drivers/issi/is31fl3733.c
@@ -0,0 +1,252 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2018 Yiancar
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __AVR__
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#else
+#include "wait.h"
+#endif
+
+#include "is31fl3733.h"
+#include <string.h>
+#include "i2c_master.h"
+#include "progmem.h"
+
+// This is a 7-bit address, that gets left-shifted and bit 0
+// set to 0 for write, 1 for read (as per I2C protocol)
+// The address will vary depending on your wiring:
+// 00 <-> GND
+// 01 <-> SCL
+// 10 <-> SDA
+// 11 <-> VCC
+// ADDR1 represents A1:A0 of the 7-bit address.
+// ADDR2 represents A3:A2 of the 7-bit address.
+// The result is: 0b101(ADDR2)(ADDR1)
+#define ISSI_ADDR_DEFAULT 0x50
+
+#define ISSI_COMMANDREGISTER 0xFD
+#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
+#define ISSI_INTERRUPTMASKREGISTER 0xF0
+#define ISSI_INTERRUPTSTATUSREGISTER 0xF1
+
+#define ISSI_PAGE_LEDCONTROL 0x00 //PG0
+#define ISSI_PAGE_PWM 0x01 //PG1
+#define ISSI_PAGE_AUTOBREATH 0x02 //PG2
+#define ISSI_PAGE_FUNCTION 0x03 //PG3
+
+#define ISSI_REG_CONFIGURATION 0x00 //PG3
+#define ISSI_REG_GLOBALCURRENT 0x01 //PG3
+#define ISSI_REG_RESET 0x11// PG3
+#define ISSI_REG_SWPULLUP 0x0F //PG3
+#define ISSI_REG_CSPULLUP 0x10 //PG3
+
+#ifndef ISSI_TIMEOUT
+ #define ISSI_TIMEOUT 100
+#endif
+
+#ifndef ISSI_PERSISTENCE
+ #define ISSI_PERSISTENCE 0
+#endif
+
+// Transfer buffer for TWITransmitData()
+uint8_t g_twi_transfer_buffer[20];
+
+// These buffers match the IS31FL3733 PWM registers.
+// The control buffers match the PG0 LED On/Off registers.
+// Storing them like this is optimal for I2C transfers to the registers.
+// We could optimize this and take out the unused registers from these
+// buffers and the transfers in IS31FL3733_write_pwm_buffer() but it's
+// probably not worth the extra complexity.
+uint8_t g_pwm_buffer[DRIVER_COUNT][192];
+bool g_pwm_buffer_update_required = false;
+
+uint8_t g_led_control_registers[DRIVER_COUNT][24] = { { 0 }, { 0 } };
+bool g_led_control_registers_update_required = false;
+
+void IS31FL3733_write_register( uint8_t addr, uint8_t reg, uint8_t data )
+{
+ g_twi_transfer_buffer[0] = reg;
+ g_twi_transfer_buffer[1] = data;
+
+ #if ISSI_PERSISTENCE > 0
+ for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0)
+ break;
+ }
+ #else
+ i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
+ #endif
+}
+
+void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
+{
+ // assumes PG1 is already selected
+
+ // transmit PWM registers in 12 transfers of 16 bytes
+ // g_twi_transfer_buffer[] is 20 bytes
+
+ // iterate over the pwm_buffer contents at 16 byte intervals
+ for ( int i = 0; i < 192; i += 16 ) {
+ g_twi_transfer_buffer[0] = i;
+ // copy the data from i to i+15
+ // device will auto-increment register for data after the first byte
+ // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
+ for ( int j = 0; j < 16; j++ ) {
+ g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
+ }
+
+ #if ISSI_PERSISTENCE > 0
+ for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0)
+ break;
+ }
+ #else
+ i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
+ #endif
+ }
+}
+
+void IS31FL3733_init( uint8_t addr )
+{
+ // In order to avoid the LEDs being driven with garbage data
+ // in the LED driver's PWM registers, shutdown is enabled last.
+ // Set up the mode and other settings, clear the PWM registers,
+ // then disable software shutdown.
+
+ // Unlock the command register.
+ IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+ // Select PG0
+ IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
+ // Turn off all LEDs.
+ for ( int i = 0x00; i <= 0x17; i++ )
+ {
+ IS31FL3733_write_register( addr, i, 0x00 );
+ }
+
+ // Unlock the command register.
+ IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+ // Select PG1
+ IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );
+ // Set PWM on all LEDs to 0
+ // No need to setup Breath registers to PWM as that is the default.
+ for ( int i = 0x00; i <= 0xBF; i++ )
+ {
+ IS31FL3733_write_register( addr, i, 0x00 );
+ }
+
+ // Unlock the command register.
+ IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+ // Select PG3
+ IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION );
+ // Set global current to maximum.
+ IS31FL3733_write_register( addr, ISSI_REG_GLOBALCURRENT, 0xFF );
+ // Disable software shutdown.
+ IS31FL3733_write_register( addr, ISSI_REG_CONFIGURATION, 0x01 );
+
+ // Wait 10ms to ensure the device has woken up.
+ #ifdef __AVR__
+ _delay_ms( 10 );
+ #else
+ wait_ms(10);
+ #endif
+}
+
+void IS31FL3733_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
+{
+ if ( index >= 0 && index < DRIVER_LED_TOTAL ) {
+ is31_led led = g_is31_leds[index];
+
+ g_pwm_buffer[led.driver][led.r] = red;
+ g_pwm_buffer[led.driver][led.g] = green;
+ g_pwm_buffer[led.driver][led.b] = blue;
+ g_pwm_buffer_update_required = true;
+ }
+}
+
+void IS31FL3733_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
+{
+ for ( int i = 0; i < DRIVER_LED_TOTAL; i++ )
+ {
+ IS31FL3733_set_color( i, red, green, blue );
+ }
+}
+
+void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, bool blue )
+{
+ is31_led led = g_is31_leds[index];
+
+ uint8_t control_register_r = led.r / 8;
+ uint8_t control_register_g = led.g / 8;
+ uint8_t control_register_b = led.b / 8;
+ uint8_t bit_r = led.r % 8;
+ uint8_t bit_g = led.g % 8;
+ uint8_t bit_b = led.b % 8;
+
+ if ( red ) {
+ g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
+ } else {
+ g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
+ }
+ if ( green ) {
+ g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
+ } else {
+ g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
+ }
+ if ( blue ) {
+ g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
+ } else {
+ g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
+ }
+
+ g_led_control_registers_update_required = true;
+
+}
+
+void IS31FL3733_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
+{
+ if ( g_pwm_buffer_update_required )
+ {
+ // Firstly we need to unlock the command register and select PG1
+ IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+ IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );
+
+ IS31FL3733_write_pwm_buffer( addr1, g_pwm_buffer[0] );
+ //IS31FL3733_write_pwm_buffer( addr2, g_pwm_buffer[1] );
+ }
+ g_pwm_buffer_update_required = false;
+}
+
+void IS31FL3733_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
+{
+ if ( g_led_control_registers_update_required )
+ {
+ // Firstly we need to unlock the command register and select PG0
+ IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+ IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
+ for ( int i=0; i<24; i++ )
+ {
+ IS31FL3733_write_register(addr1, i, g_led_control_registers[0][i] );
+ //IS31FL3733_write_register(addr2, i, g_led_control_registers[1][i] );
+ }
+ }
+}
diff --git a/drivers/issi/is31fl3733.h b/drivers/issi/is31fl3733.h
new file mode 100644
index 0000000000..3d23b188aa
--- /dev/null
+++ b/drivers/issi/is31fl3733.h
@@ -0,0 +1,255 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2018 Yiancar
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef IS31FL3733_DRIVER_H
+#define IS31FL3733_DRIVER_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct is31_led {
+ uint8_t driver:2;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} __attribute__((packed)) is31_led;
+
+extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+
+void IS31FL3733_init( uint8_t addr );
+void IS31FL3733_write_register( uint8_t addr, uint8_t reg, uint8_t data );
+void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );
+
+void IS31FL3733_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3733_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
+
+void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, bool blue );
+
+// This should not be called from an interrupt
+// (eg. from a timer interrupt).
+// Call this while idle (in between matrix scans).
+// If the buffer is dirty, it will update the driver with the buffer.
+void IS31FL3733_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
+void IS31FL3733_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
+
+#define A_1 0x00
+#define A_2 0x01
+#define A_3 0x02
+#define A_4 0x03
+#define A_5 0x04
+#define A_6 0x05
+#define A_7 0x06
+#define A_8 0x07
+#define A_9 0x08
+#define A_10 0x09
+#define A_11 0x0A
+#define A_12 0x0B
+#define A_13 0x0C
+#define A_14 0x0D
+#define A_15 0x0E
+#define A_16 0x0F
+
+#define B_1 0x10
+#define B_2 0x11
+#define B_3 0x12
+#define B_4 0x13
+#define B_5 0x14
+#define B_6 0x15
+#define B_7 0x16
+#define B_8 0x17
+#define B_9 0x18
+#define B_10 0x19
+#define B_11 0x1A
+#define B_12 0x1B
+#define B_13 0x1C
+#define B_14 0x1D
+#define B_15 0x1E
+#define B_16 0x1F
+
+#define C_1 0x20
+#define C_2 0x21
+#define C_3 0x22
+#define C_4 0x23
+#define C_5 0x24
+#define C_6 0x25
+#define C_7 0x26
+#define C_8 0x27
+#define C_9 0x28
+#define C_10 0x29
+#define C_11 0x2A
+#define C_12 0x2B
+#define C_13 0x2C
+#define C_14 0x2D
+#define C_15 0x2E
+#define C_16 0x2F
+
+#define D_1 0x30
+#define D_2 0x31
+#define D_3 0x32
+#define D_4 0x33
+#define D_5 0x34
+#define D_6 0x35
+#define D_7 0x36
+#define D_8 0x37
+#define D_9 0x38
+#define D_10 0x39
+#define D_11 0x3A
+#define D_12 0x3B
+#define D_13 0x3C
+#define D_14 0x3D
+#define D_15 0x3E
+#define D_16 0x3F
+
+#define E_1 0x40
+#define E_2 0x41
+#define E_3 0x42
+#define E_4 0x43
+#define E_5 0x44
+#define E_6 0x45
+#define E_7 0x46
+#define E_8 0x47
+#define E_9 0x48
+#define E_10 0x49
+#define E_11 0x4A
+#define E_12 0x4B
+#define E_13 0x4C
+#define E_14 0x4D
+#define E_15 0x4E
+#define E_16 0x4F
+
+#define F_1 0x50
+#define F_2 0x51
+#define F_3 0x52
+#define F_4 0x53
+#define F_5 0x54
+#define F_6 0x55
+#define F_7 0x56
+#define F_8 0x57
+#define F_9 0x58
+#define F_10 0x59
+#define F_11 0x5A
+#define F_12 0x5B
+#define F_13 0x5C
+#define F_14 0x5D
+#define F_15 0x5E
+#define F_16 0x5F
+
+#define G_1 0x60
+#define G_2 0x61
+#define G_3 0x62
+#define G_4 0x63
+#define G_5 0x64
+#define G_6 0x65
+#define G_7 0x66
+#define G_8 0x67
+#define G_9 0x68
+#define G_10 0x69
+#define G_11 0x6A
+#define G_12 0x6B
+#define G_13 0x6C
+#define G_14 0x6D
+#define G_15 0x6E
+#define G_16 0x6F
+
+#define H_1 0x70
+#define H_2 0x71
+#define H_3 0x72
+#define H_4 0x73
+#define H_5 0x74
+#define H_6 0x75
+#define H_7 0x76
+#define H_8 0x77
+#define H_9 0x78
+#define H_10 0x79
+#define H_11 0x7A
+#define H_12 0x7B
+#define H_13 0x7C
+#define H_14 0x7D
+#define H_15 0x7E
+#define H_16 0x7F
+
+#define I_1 0x80
+#define I_2 0x81
+#define I_3 0x82
+#define I_4 0x83
+#define I_5 0x84
+#define I_6 0x85
+#define I_7 0x86
+#define I_8 0x87
+#define I_9 0x88
+#define I_10 0x89
+#define I_11 0x8A
+#define I_12 0x8B
+#define I_13 0x8C
+#define I_14 0x8D
+#define I_15 0x8E
+#define I_16 0x8F
+
+#define J_1 0x90
+#define J_2 0x91
+#define J_3 0x92
+#define J_4 0x93
+#define J_5 0x94
+#define J_6 0x95
+#define J_7 0x96
+#define J_8 0x97
+#define J_9 0x98
+#define J_10 0x99
+#define J_11 0x9A
+#define J_12 0x9B
+#define J_13 0x9C
+#define J_14 0x9D
+#define J_15 0x9E
+#define J_16 0x9F
+
+#define K_1 0xA0
+#define K_2 0xA1
+#define K_3 0xA2
+#define K_4 0xA3
+#define K_5 0xA4
+#define K_6 0xA5
+#define K_7 0xA6
+#define K_8 0xA7
+#define K_9 0xA8
+#define K_10 0xA9
+#define K_11 0xAA
+#define K_12 0xAB
+#define K_13 0xAC
+#define K_14 0xAD
+#define K_15 0xAE
+#define K_16 0xAF
+
+#define L_1 0xB0
+#define L_2 0xB1
+#define L_3 0xB2
+#define L_4 0xB3
+#define L_5 0xB4
+#define L_6 0xB5
+#define L_7 0xB6
+#define L_8 0xB7
+#define L_9 0xB8
+#define L_10 0xB9
+#define L_11 0xBA
+#define L_12 0xBB
+#define L_13 0xBC
+#define L_14 0xBD
+#define L_15 0xBE
+#define L_16 0xBF
+
+#endif // IS31FL3733_DRIVER_H
diff --git a/drivers/issi/is31fl3736.c b/drivers/issi/is31fl3736.c
new file mode 100644
index 0000000000..c5d4310971
--- /dev/null
+++ b/drivers/issi/is31fl3736.c
@@ -0,0 +1,306 @@
+/* Copyright 2018 Jason Williams (Wilba)
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef __AVR__
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#else
+#include "wait.h"
+#endif
+
+#include "is31fl3736.h"
+#include <string.h>
+#include "i2c_master.h"
+#include "progmem.h"
+
+
+
+// This is a 7-bit address, that gets left-shifted and bit 0
+// set to 0 for write, 1 for read (as per I2C protocol)
+// The address will vary depending on your wiring:
+// 00 <-> GND
+// 01 <-> SCL
+// 10 <-> SDA
+// 11 <-> VCC
+// ADDR1 represents A1:A0 of the 7-bit address.
+// ADDR2 represents A3:A2 of the 7-bit address.
+// The result is: 0b101(ADDR2)(ADDR1)
+#define ISSI_ADDR_DEFAULT 0x50
+
+#define ISSI_COMMANDREGISTER 0xFD
+#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
+#define ISSI_INTERRUPTMASKREGISTER 0xF0
+#define ISSI_INTERRUPTSTATUSREGISTER 0xF1
+
+#define ISSI_PAGE_LEDCONTROL 0x00 //PG0
+#define ISSI_PAGE_PWM 0x01 //PG1
+#define ISSI_PAGE_AUTOBREATH 0x02 //PG2
+#define ISSI_PAGE_FUNCTION 0x03 //PG3
+
+#define ISSI_REG_CONFIGURATION 0x00 //PG3
+#define ISSI_REG_GLOBALCURRENT 0x01 //PG3
+#define ISSI_REG_RESET 0x11// PG3
+#define ISSI_REG_SWPULLUP 0x0F //PG3
+#define ISSI_REG_CSPULLUP 0x10 //PG3
+
+#ifndef ISSI_TIMEOUT
+ #define ISSI_TIMEOUT 100
+#endif
+
+#ifndef ISSI_PERSISTENCE
+ #define ISSI_PERSISTENCE 0
+#endif
+
+// Transfer buffer for TWITransmitData()
+uint8_t g_twi_transfer_buffer[20];
+
+// These buffers match the IS31FL3736 PWM registers.
+// The control buffers match the PG0 LED On/Off registers.
+// Storing them like this is optimal for I2C transfers to the registers.
+// We could optimize this and take out the unused registers from these
+// buffers and the transfers in IS31FL3736_write_pwm_buffer() but it's
+// probably not worth the extra complexity.
+uint8_t g_pwm_buffer[DRIVER_COUNT][192];
+bool g_pwm_buffer_update_required = false;
+
+uint8_t g_led_control_registers[DRIVER_COUNT][24] = { { 0 }, { 0 } };
+bool g_led_control_registers_update_required = false;
+
+void IS31FL3736_write_register( uint8_t addr, uint8_t reg, uint8_t data )
+{
+ g_twi_transfer_buffer[0] = reg;
+ g_twi_transfer_buffer[1] = data;
+
+ #if ISSI_PERSISTENCE > 0
+ for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0)
+ break;
+ }
+ #else
+ i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
+ #endif
+}
+
+void IS31FL3736_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
+{
+ // assumes PG1 is already selected
+
+ // transmit PWM registers in 12 transfers of 16 bytes
+ // g_twi_transfer_buffer[] is 20 bytes
+
+ // iterate over the pwm_buffer contents at 16 byte intervals
+ for ( int i = 0; i < 192; i += 16 ) {
+ g_twi_transfer_buffer[0] = i;
+ // copy the data from i to i+15
+ // device will auto-increment register for data after the first byte
+ // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
+ for ( int j = 0; j < 16; j++ ) {
+ g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
+ }
+
+ #if ISSI_PERSISTENCE > 0
+ for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0)
+ break;
+ }
+ #else
+ i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
+ #endif
+ }
+}
+
+void IS31FL3736_init( uint8_t addr )
+{
+ // In order to avoid the LEDs being driven with garbage data
+ // in the LED driver's PWM registers, shutdown is enabled last.
+ // Set up the mode and other settings, clear the PWM registers,
+ // then disable software shutdown.
+
+ // Unlock the command register.
+ IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+ // Select PG0
+ IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
+ // Turn off all LEDs.
+ for ( int i = 0x00; i <= 0x17; i++ )
+ {
+ IS31FL3736_write_register( addr, i, 0x00 );
+ }
+
+ // Unlock the command register.
+ IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+ // Select PG1
+ IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );
+ // Set PWM on all LEDs to 0
+ // No need to setup Breath registers to PWM as that is the default.
+ for ( int i = 0x00; i <= 0xBF; i++ )
+ {
+ IS31FL3736_write_register( addr, i, 0x00 );
+ }
+
+ // Unlock the command register.
+ IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+ // Select PG3
+ IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION );
+ // Set global current to maximum.
+ IS31FL3736_write_register( addr, ISSI_REG_GLOBALCURRENT, 0xFF );
+ // Disable software shutdown.
+ IS31FL3736_write_register( addr, ISSI_REG_CONFIGURATION, 0x01 );
+
+ // Wait 10ms to ensure the device has woken up.
+ #ifdef __AVR__
+ _delay_ms( 10 );
+ #else
+ wait_ms(10);
+ #endif
+}
+
+void IS31FL3736_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
+{
+ if ( index >= 0 && index < DRIVER_LED_TOTAL ) {
+ is31_led led = g_is31_leds[index];
+
+ g_pwm_buffer[led.driver][led.r] = red;
+ g_pwm_buffer[led.driver][led.g] = green;
+ g_pwm_buffer[led.driver][led.b] = blue;
+ g_pwm_buffer_update_required = true;
+ }
+}
+
+void IS31FL3736_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
+{
+ for ( int i = 0; i < DRIVER_LED_TOTAL; i++ )
+ {
+ IS31FL3736_set_color( i, red, green, blue );
+ }
+}
+
+void IS31FL3736_set_led_control_register( uint8_t index, bool red, bool green, bool blue )
+{
+ is31_led led = g_is31_leds[index];
+
+ // IS31FL3733
+ // The PWM register for a matrix position (0x00 to 0xBF) can be
+ // divided by 8 to get the LED control register (0x00 to 0x17),
+ // then mod 8 to get the bit position within that register.
+
+ // IS31FL3736
+ // The PWM register for a matrix position (0x00 to 0xBF) is interleaved, so:
+ // A1=0x00 A2=0x02 A3=0x04 A4=0x06 A5=0x08 A6=0x0A A7=0x0C A8=0x0E
+ // B1=0x10 B2=0x12 B3=0x14
+ // But also, the LED control registers (0x00 to 0x17) are also interleaved, so:
+ // A1-A4=0x00 A5-A8=0x01
+ // So, the same math applies.
+
+ uint8_t control_register_r = led.r / 8;
+ uint8_t control_register_g = led.g / 8;
+ uint8_t control_register_b = led.b / 8;
+
+ uint8_t bit_r = led.r % 8;
+ uint8_t bit_g = led.g % 8;
+ uint8_t bit_b = led.b % 8;
+
+ if ( red ) {
+ g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
+ } else {
+ g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
+ }
+ if ( green ) {
+ g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
+ } else {
+ g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
+ }
+ if ( blue ) {
+ g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
+ } else {
+ g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
+ }
+
+ g_led_control_registers_update_required = true;
+
+}
+
+void IS31FL3736_mono_set_brightness( int index, uint8_t value )
+{
+ if ( index >= 0 && index < 96 ) {
+ // Index in range 0..95 -> A1..A8, B1..B8, etc.
+ // Map index 0..95 to registers 0x00..0xBE (interleaved)
+ uint8_t pwm_register = index * 2;
+ g_pwm_buffer[0][pwm_register] = value;
+ g_pwm_buffer_update_required = true;
+ }
+}
+
+void IS31FL3736_mono_set_brightness_all( uint8_t value )
+{
+ for ( int i = 0; i < 96; i++ )
+ {
+ IS31FL3736_mono_set_brightness( i, value );
+ }
+}
+
+void IS31FL3736_mono_set_led_control_register( uint8_t index, bool enabled )
+{
+ // Index in range 0..95 -> A1..A8, B1..B8, etc.
+
+ // Map index 0..95 to registers 0x00..0xBE (interleaved)
+ uint8_t pwm_register = index * 2;
+ // Map register 0x00..0xBE (interleaved) into control register and bit
+ uint8_t control_register = pwm_register / 8;
+ uint8_t bit = pwm_register % 8;
+
+ if ( enabled ) {
+ g_led_control_registers[0][control_register] |= (1 << bit);
+ } else {
+ g_led_control_registers[0][control_register] &= ~(1 << bit);
+ }
+
+ g_led_control_registers_update_required = true;
+}
+
+void IS31FL3736_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
+{
+ if ( g_pwm_buffer_update_required )
+ {
+ // Firstly we need to unlock the command register and select PG1
+ IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+ IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );
+
+ IS31FL3736_write_pwm_buffer( addr1, g_pwm_buffer[0] );
+ //IS31FL3736_write_pwm_buffer( addr2, g_pwm_buffer[1] );
+ }
+ g_pwm_buffer_update_required = false;
+}
+
+void IS31FL3736_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
+{
+ if ( g_led_control_registers_update_required )
+ {
+ // Firstly we need to unlock the command register and select PG0
+ IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+ IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
+ for ( int i=0; i<24; i++ )
+ {
+ IS31FL3736_write_register(addr1, i, g_led_control_registers[0][i] );
+ //IS31FL3736_write_register(addr2, i, g_led_control_registers[1][i] );
+ }
+ }
+}
+
diff --git a/drivers/issi/is31fl3736.h b/drivers/issi/is31fl3736.h
new file mode 100644
index 0000000000..cff50fd0d8
--- /dev/null
+++ b/drivers/issi/is31fl3736.h
@@ -0,0 +1,172 @@
+/* Copyright 2018 Jason Williams (Wilba)
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+// Simple interface option.
+// If these aren't defined, just define them to make it compile
+
+
+#ifndef DRIVER_COUNT
+#define DRIVER_COUNT 2
+#endif
+
+#ifndef DRIVER_LED_TOTAL
+#define DRIVER_LED_TOTAL 96
+#endif
+
+
+typedef struct is31_led {
+ uint8_t driver:2;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} __attribute__((packed)) is31_led;
+
+extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+
+void IS31FL3736_init( uint8_t addr );
+void IS31FL3736_write_register( uint8_t addr, uint8_t reg, uint8_t data );
+void IS31FL3736_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );
+
+void IS31FL3736_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3736_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
+
+void IS31FL3736_set_led_control_register( uint8_t index, bool red, bool green, bool blue );
+
+void IS31FL3736_mono_set_brightness( int index, uint8_t value );
+void IS31FL3736_mono_set_brightness_all( uint8_t value );
+void IS31FL3736_mono_set_led_control_register( uint8_t index, bool enabled );
+
+// This should not be called from an interrupt
+// (eg. from a timer interrupt).
+// Call this while idle (in between matrix scans).
+// If the buffer is dirty, it will update the driver with the buffer.
+void IS31FL3736_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
+void IS31FL3736_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
+
+#define A_1 0x00
+#define A_2 0x02
+#define A_3 0x04
+#define A_4 0x06
+#define A_5 0x08
+#define A_6 0x0A
+#define A_7 0x0C
+#define A_8 0x0E
+
+#define B_1 0x10
+#define B_2 0x12
+#define B_3 0x14
+#define B_4 0x16
+#define B_5 0x18
+#define B_6 0x1A
+#define B_7 0x1C
+#define B_8 0x1E
+
+#define C_1 0x20
+#define C_2 0x22
+#define C_3 0x24
+#define C_4 0x26
+#define C_5 0x28
+#define C_6 0x2A
+#define C_7 0x2C
+#define C_8 0x2E
+
+#define D_1 0x30
+#define D_2 0x32
+#define D_3 0x34
+#define D_4 0x36
+#define D_5 0x38
+#define D_6 0x3A
+#define D_7 0x3C
+#define D_8 0x3E
+
+#define E_1 0x40
+#define E_2 0x42
+#define E_3 0x44
+#define E_4 0x46
+#define E_5 0x48
+#define E_6 0x4A
+#define E_7 0x4C
+#define E_8 0x4E
+
+#define F_1 0x50
+#define F_2 0x52
+#define F_3 0x54
+#define F_4 0x56
+#define F_5 0x58
+#define F_6 0x5A
+#define F_7 0x5C
+#define F_8 0x5E
+
+#define G_1 0x60
+#define G_2 0x62
+#define G_3 0x64
+#define G_4 0x66
+#define G_5 0x68
+#define G_6 0x6A
+#define G_7 0x6C
+#define G_8 0x6E
+
+#define H_1 0x70
+#define H_2 0x72
+#define H_3 0x74
+#define H_4 0x76
+#define H_5 0x78
+#define H_6 0x7A
+#define H_7 0x7C
+#define H_8 0x7E
+
+#define I_1 0x80
+#define I_2 0x82
+#define I_3 0x84
+#define I_4 0x86
+#define I_5 0x88
+#define I_6 0x8A
+#define I_7 0x8C
+#define I_8 0x8E
+
+#define J_1 0x90
+#define J_2 0x92
+#define J_3 0x94
+#define J_4 0x96
+#define J_5 0x98
+#define J_6 0x9A
+#define J_7 0x9C
+#define J_8 0x9E
+
+#define K_1 0xA0
+#define K_2 0xA2
+#define K_3 0xA4
+#define K_4 0xA6
+#define K_5 0xA8
+#define K_6 0xAA
+#define K_7 0xAC
+#define K_8 0xAE
+
+#define L_1 0xB0
+#define L_2 0xB2
+#define L_3 0xB4
+#define L_4 0xB6
+#define L_5 0xB8
+#define L_6 0xBA
+#define L_7 0xBC
+#define L_8 0xBE
+
diff --git a/drivers/qwiic/micro_oled.c b/drivers/qwiic/micro_oled.c
new file mode 100644
index 0000000000..35c5d6ee1d
--- /dev/null
+++ b/drivers/qwiic/micro_oled.c
@@ -0,0 +1,691 @@
+/* Jim Lindblom @ SparkFun Electronics
+ * October 26, 2014
+ * https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
+ *
+ * Modified by:
+ * Emil Varughese @ Edwin Robotics Pvt. Ltd.
+ * July 27, 2015
+ * https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
+ *
+ * This code was heavily based around the MicroView library, written by GeekAmmo
+ * (https://github.com/geekammo/MicroView-Arduino-Library).
+ *
+ * Adapted for QMK by:
+ * Jack Humbert <jack.humb@gmail.com>
+ * October 11, 2018
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "micro_oled.h"
+#include <stdlib.h>
+#include "util/font5x7.h"
+#include "util/font8x16.h"
+#include "string.h"
+
+#define TOTALFONTS 2
+const unsigned char * fonts_pointer[]= { font5x7, font8x16 };
+
+uint8_t foreColor,drawMode,fontWidth, fontHeight, fontType, fontStartChar, fontTotalChar, cursorX, cursorY;
+uint16_t fontMapWidth;
+
+#define _BV(x) (1 << (x))
+#define swap(a, b) { uint8_t t = a; a = b; b = t; }
+
+uint8_t micro_oled_transfer_buffer[20];
+static uint8_t micro_oled_screen_current[LCDWIDTH*LCDWIDTH/8] = { 0 };
+
+/* LCD Memory organised in 64 horizontal pixel and 6 rows of byte
+ B B .............B -----
+ y y .............y \
+ t t .............t \
+ e e .............e \
+ 0 1 .............63 \
+ \
+ D0 D0.............D0 \
+ D1 D1.............D1 / ROW 0
+ D2 D2.............D2 /
+ D3 D3.............D3 /
+ D4 D4.............D4 /
+ D5 D5.............D5 /
+ D6 D6.............D6 /
+ D7 D7.............D7 ----
+ */
+
+#if LCDWIDTH == 64
+ #if LCDWIDTH == 48
+static uint8_t micro_oled_screen_buffer[] = {
+// QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php
+//64x48 image
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00,
+0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00,
+0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60,
+0xF8, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE,
+0xFE, 0xF8, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF,
+0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7,
+0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
+0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
+0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
+0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00
+};
+ #endif
+#elif LCDWIDTH == 128
+ #if LCDHEIGHT == 32
+ static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {
+//128x32 qmk image
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xFC, 0xFC,
+0xE0, 0xF0, 0xFC, 0xE0, 0xE0, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC,
+0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x30, 0xE0, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xB2, 0xB2, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0x03,
+0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF,
+0xFF, 0xB7, 0xB2, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1F, 0x02, 0x02, 0x03, 0x01, 0x00, 0x06, 0x1F, 0x10,
+0x10, 0x10, 0x1F, 0x06, 0x00, 0x03, 0x1E, 0x18, 0x0F, 0x01,
+0x0F, 0x18, 0x1E, 0x01, 0x00, 0x0F, 0x1F, 0x12, 0x02, 0x12,
+0x13, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x12,
+0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x1F,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x48, 0x4D, 0x4D, 0xFF, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFE, 0xF8, 0xF9, 0xF3, 0xF3, 0xC0, 0x80, 0xF3,
+0xF3, 0xF3, 0xF9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED,
+0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0xC0, 0x00, 0x70, 0xC0,
+0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C,
+0x04, 0x04, 0x04, 0x04, 0x1C, 0xF0, 0x00, 0x00, 0xFC, 0x0C,
+0x38, 0xE0, 0x00, 0x00, 0xC0, 0x38, 0x0C, 0xFC, 0x00, 0x00,
+0xFC, 0xFC, 0x60, 0x90, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x3F,
+0x3F, 0x07, 0x3F, 0x3F, 0x07, 0x0F, 0x3F, 0x07, 0x07, 0x3F,
+0x07, 0x07, 0x3F, 0x3F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+0x06, 0x04, 0x04, 0x07, 0x01, 0x00, 0x00, 0x13, 0x1E, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x04,
+0x04, 0x04, 0x07, 0x0D, 0x08, 0x00, 0x07, 0x00, 0x00, 0x01,
+0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x07,
+0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00
+ };
+ #elif LCDHEIGHT == 64
+ static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0,
+0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00,
+0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xC0, 0xC0, 0xC0, 0xC0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF,
+0x7F, 0x7E, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0x7F, 0x7F, 0xFE,
+0xFE, 0xFF, 0xFF, 0xFE, 0x7E, 0x7F, 0xFF, 0xFE, 0xFE, 0xFC,
+0xFC, 0xF8, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x88, 0x88, 0x88, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xDD, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF3, 0xF3, 0xE7, 0xE7, 0x00,
+0x00, 0xE7, 0xE7, 0xF3, 0xF3, 0xF0, 0xF8, 0xFE, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x1F, 0x3F,
+0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F,
+0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF,
+0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00,
+0x80, 0x03, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x80, 0x01,
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xFF, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x70,
+0x88, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x00, 0x3C, 0xE0, 0xC0,
+0x38, 0x1C, 0xE0, 0x80, 0x70, 0x0C, 0x00, 0xF8, 0xAC, 0x24,
+0x24, 0x3C, 0x30, 0x00, 0x00, 0xFC, 0x0C, 0x04, 0x00, 0xF8,
+0xAC, 0x24, 0x24, 0x2C, 0x30, 0x00, 0x70, 0xDC, 0x04, 0x04,
+0x88, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+0x8C, 0x04, 0x04, 0xF8, 0x00, 0x04, 0x3C, 0xE0, 0x80, 0xF0,
+0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x83, 0x01, 0x01,
+0x01, 0x81, 0xFE, 0x3C, 0x00, 0x00, 0xFF, 0x03, 0x0E, 0x70,
+0xC0, 0xE0, 0x38, 0x06, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x18,
+0x38, 0x66, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+//TODO: generate bitmap of QMK logo here
+ #endif
+#else
+//catchall for custom screen szies
+ static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {0};
+#endif
+
+
+
+void micro_oled_init(void) {
+
+ i2c_init();
+ i2c_start(I2C_ADDRESS_SA0_1);
+
+ // Display Init sequence for 64x48 OLED module
+ send_command(DISPLAYOFF); // 0xAE
+
+ send_command(SETDISPLAYCLOCKDIV); // 0xD5
+ send_command(0x80); // the suggested ratio 0x80
+
+ send_command(SETMULTIPLEX); // 0xA8
+ send_command(LCDHEIGHT - 1);
+
+ send_command(SETDISPLAYOFFSET); // 0xD3
+ send_command(0x00); // no offset
+
+ send_command(SETSTARTLINE | 0x00); // line #0
+
+ send_command(CHARGEPUMP); // enable charge pump
+ send_command(0x14);
+
+ send_command(NORMALDISPLAY); // 0xA6
+ send_command(DISPLAYALLONRESUME); // 0xA4
+
+//display at regular orientation
+ send_command(SEGREMAP | 0x1);
+ send_command(COMSCANDEC);
+
+//rotate display 180
+#ifdef micro_oled_rotate_180
+ send_command(SEGREMAP);
+ send_command(COMSCANINC);
+#endif
+
+ send_command(MEMORYMODE);
+ send_command(0x10);
+
+ send_command(SETCOMPINS); // 0xDA
+if (LCDHEIGHT > 32) {
+ send_command(0x12);
+} else {
+ send_command(0x02);
+}
+ send_command(SETCONTRAST); // 0x81
+ send_command(0x8F);
+
+ send_command(SETPRECHARGE); // 0xd9
+ send_command(0xF1);
+
+ send_command(SETVCOMDESELECT); // 0xDB
+ send_command(0x40);
+
+ send_command(DISPLAYON); //--turn on oled panel
+ clear_screen(); // Erase hardware memory inside the OLED controller to avoid random data in memory.
+ send_buffer();
+}
+
+void send_command(uint8_t command) {
+ micro_oled_transfer_buffer[0] = I2C_COMMAND;
+ micro_oled_transfer_buffer[1] = command;
+ i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
+}
+
+void send_data(uint8_t data) {
+ micro_oled_transfer_buffer[0] = I2C_DATA;
+ micro_oled_transfer_buffer[1] = data;
+ i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
+}
+
+/** \brief Set SSD1306 page address.
+ Send page address command and address to the SSD1306 OLED controller.
+*/
+void set_page_address(uint8_t address) {
+ address = (0xB0 | address);
+ send_command(address);
+}
+
+/** \brief Set SSD1306 column address.
+ Send column address command and address to the SSD1306 OLED controller.
+*/
+void set_column_address(uint8_t address) {
+ send_command( ( 0x10 | (address >> 4) ) + ((128 - LCDWIDTH) >> 8) );
+ send_command( 0x0F & address );
+}
+
+/** \brief Clear SSD1306's memory.
+ To clear GDRAM inside the LCD controller.
+*/
+void clear_screen(void) {
+ for (int i=0;i<8; i++) {
+ set_page_address(i);
+ set_column_address(0);
+ for (int j=0; j<0x80; j++) {
+ send_data(0);
+ }
+ }
+}
+
+/** \brief Clear SSD1306's memory.
+ To clear GDRAM inside the LCD controller.
+*/
+void clear_buffer(void) {
+//384
+ memset(micro_oled_screen_buffer, 0, LCDWIDTH*LCDWIDTH/8);
+}
+
+/** \brief Invert display.
+ The PIXEL_ON color of the display will turn to PIXEL_OFF and the PIXEL_OFF will turn to PIXEL_ON.
+*/
+void invert_screen(bool invert) {
+ if (invert) {
+ send_command(INVERTDISPLAY);
+ } else {
+ send_command(NORMALDISPLAY);
+ }
+}
+
+/** \brief Set contrast.
+ OLED contract value from 0 to 255. Note: Contrast level is not very obvious.
+*/
+void set_contrast(uint8_t contrast) {
+ send_command(SETCONTRAST); // 0x81
+ send_command(contrast);
+}
+
+/** \brief Transfer display buffer.
+ Sends the updated buffer to the controller - the current status is checked before to save i2c exectution time
+*/
+void send_buffer(void) {
+ uint8_t i, j;
+
+ uint8_t page_addr = 0xFF;
+ for (i = 0; i < LCDHEIGHT/8; i++) {
+ uint8_t col_addr = 0xFF;
+ for (j = 0; j < LCDWIDTH; j++) {
+ if (micro_oled_screen_buffer[i*LCDWIDTH+j] != micro_oled_screen_current[i*LCDWIDTH+j]) {
+ if (page_addr != i) {
+ set_page_address(i);
+ }
+ if (col_addr != j) {
+ set_column_address(j);
+ }
+ send_data(micro_oled_screen_buffer[i*LCDWIDTH+j]);
+ micro_oled_screen_current[i*LCDWIDTH+j] = micro_oled_screen_buffer[i*LCDWIDTH+j];
+ col_addr = j + 1;
+ }
+ }
+ }
+}
+
+/** \brief Draw pixel with color and mode.
+ Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode.
+*/
+void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) {
+ if ((x<0) || (x>=LCDWIDTH) || (y<0) || (y>=LCDHEIGHT))
+ return;
+
+ if (mode == XOR) {
+ if (color == PIXEL_ON)
+ micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] ^= _BV((y%8));
+ } else {
+ if (color == PIXEL_ON)
+ micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] |= _BV((y%8));
+ else
+ micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] &= ~_BV((y%8));
+ }
+}
+
+/** \brief Draw line with color and mode.
+Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.
+*/
+void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) {
+ uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
+ if (steep) {
+ swap(x0, y0);
+ swap(x1, y1);
+ }
+
+ if (x0 > x1) {
+ swap(x0, x1);
+ swap(y0, y1);
+ }
+
+ uint8_t dx, dy;
+ dx = x1 - x0;
+ dy = abs(y1 - y0);
+
+ int8_t err = dx / 2;
+ int8_t ystep;
+
+ if (y0 < y1) {
+ ystep = 1;
+ } else {
+ ystep = -1;}
+
+ for (; x0<x1; x0++) {
+ if (steep) {
+ draw_pixel(y0, x0, color, mode);
+ } else {
+ draw_pixel(x0, y0, color, mode);
+ }
+ err -= dy;
+ if (err < 0) {
+ y0 += ystep;
+ err += dx;
+ }
+ }
+}
+
+/** \brief Draw horizontal line with color and mode.
+Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.
+*/
+void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode) {
+ draw_line(x,y,x+width,y,color,mode);
+}
+
+/** \brief Draw vertical line.
+Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.
+*/
+void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode) {
+ draw_line(x,y,x,y+height,color,mode);
+}
+
+/** \brief Draw rectangle with color and mode.
+Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
+*/
+void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
+ uint8_t tempHeight;
+
+ draw_line_hori(x,y, width, color, mode);
+ draw_line_hori(x,y+height-1, width, color, mode);
+
+ tempHeight=height-2;
+
+ // skip drawing vertical lines to avoid overlapping of pixel that will
+ // affect XOR plot if no pixel in between horizontal lines
+ if (tempHeight<1) return;
+
+ draw_line_vert(x,y+1, tempHeight, color, mode);
+ draw_line_vert(x+width-1, y+1, tempHeight, color, mode);
+}
+
+/** \brief Draw rectangle with color and mode.
+Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
+*/
+void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
+ uint8_t tempHeight;
+
+ draw_line_hori(x+1,y, width-2, color, mode);
+ draw_line_hori(x+1,y+height-1, width-2, color, mode);
+
+ tempHeight=height-2;
+
+ // skip drawing vertical lines to avoid overlapping of pixel that will
+ // affect XOR plot if no pixel in between horizontal lines
+ if (tempHeight<1) return;
+
+ draw_line_vert(x,y+1, tempHeight, color, mode);
+ draw_line_vert(x+width-1, y+1, tempHeight, color, mode);
+}
+
+/** \brief Draw filled rectangle with color and mode.
+Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
+*/
+void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
+ // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
+ for (int i=x; i<x+width;i++) {
+ draw_line_vert(i,y, height, color, mode);
+ }
+}
+
+/** \brief Draw filled rectangle with color and mode.
+Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
+*/
+void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
+ // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
+ for (int i=x; i<x+width;i++) {
+ if (i == x || i == (x + width - 1))
+ draw_line_vert(i, y+1, height-2, color, mode);
+ else
+ draw_line_vert(i, y, height, color, mode);
+ }
+}
+
+/** \brief Draw character with color and mode.
+ Draw character c using color and draw mode at x,y.
+*/
+void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font) {
+ // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels
+
+ uint8_t rowsToDraw,row, tempC;
+ uint8_t i,j,temp;
+ uint16_t charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition;
+
+ if ((font>=TOTALFONTS) || (font<0))
+ return;
+
+ uint8_t fontType = font;
+ uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0);
+ uint8_t fontHeight = pgm_read_byte(fonts_pointer[fontType]+1);
+ uint8_t fontStartChar = pgm_read_byte(fonts_pointer[fontType]+2);
+ uint8_t fontTotalChar = pgm_read_byte(fonts_pointer[fontType]+3);
+ uint16_t fontMapWidth = (pgm_read_byte(fonts_pointer[fontType]+4)*100)+pgm_read_byte(fonts_pointer[fontType]+5); // two bytes values into integer 16
+
+ if ((c<fontStartChar) || (c>(fontStartChar+fontTotalChar-1))) // no bitmap for the required c
+ return;
+
+ tempC=c-fontStartChar;
+
+ // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn
+ rowsToDraw=fontHeight/8; // 8 is LCD's page size, see SSD1306 datasheet
+ if (rowsToDraw<=1) rowsToDraw=1;
+
+ // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw
+ if (rowsToDraw==1) {
+ for (i=0;i<fontWidth+1;i++) {
+ if (i==fontWidth) // this is done in a weird way because for 5x7 font, there is no margin, this code add a margin after col 5
+ temp=0;
+ else
+ temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(tempC*fontWidth)+i);
+
+ for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation)
+ if (temp & 0x1) {
+ draw_pixel(x+i, y+j, color,mode);
+ }
+ else {
+ draw_pixel(x+i, y+j, !color,mode);
+ }
+
+ temp >>=1;
+ }
+ }
+ return;
+ }
+
+ // font height over 8 bit
+ // take character "0" ASCII 48 as example
+ charPerBitmapRow = fontMapWidth/fontWidth; // 256/8 =32 char per row
+ charColPositionOnBitmap = tempC % charPerBitmapRow; // =16
+ charRowPositionOnBitmap = (int)(tempC/charPerBitmapRow); // =1
+ charBitmapStartPosition = (charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ;
+
+ // each row on LCD is 8 bit height (see datasheet for explanation)
+ for(row=0;row<rowsToDraw;row++) {
+ for (i=0; i<fontWidth;i++) {
+ temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(charBitmapStartPosition+i+(row*fontMapWidth)));
+ for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation)
+ if (temp & 0x1) {
+ draw_pixel(x+i,y+j+(row*8), color, mode);
+ }
+ else {
+ draw_pixel(x+i,y+j+(row*8), !color, mode);
+ }
+ temp >>=1;
+ }
+ }
+ }
+
+}
+
+void draw_string(uint8_t x, uint8_t y, char * string, uint8_t color, uint8_t mode, uint8_t font) {
+
+ if ((font>=TOTALFONTS) || (font<0))
+ return;
+
+ uint8_t fontType = font;
+ uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0);
+
+ uint8_t cur_x = x;
+ for (int i = 0; i < strlen(string); i++) {
+ draw_char(cur_x, y, string[i], color, mode, font);
+ cur_x += fontWidth + 1;
+ }
+
+}
diff --git a/drivers/qwiic/micro_oled.h b/drivers/qwiic/micro_oled.h
new file mode 100644
index 0000000000..5d6a1029ed
--- /dev/null
+++ b/drivers/qwiic/micro_oled.h
@@ -0,0 +1,134 @@
+/* Jim Lindblom @ SparkFun Electronics
+ * October 26, 2014
+ * https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
+ *
+ * Modified by:
+ * Emil Varughese @ Edwin Robotics Pvt. Ltd.
+ * July 27, 2015
+ * https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
+ *
+ * This code was heavily based around the MicroView library, written by GeekAmmo
+ * (https://github.com/geekammo/MicroView-Arduino-Library).
+ *
+ * Adapted for QMK by:
+ * Jack Humbert <jack.humb@gmail.com>
+ * October 11, 2018
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include "qwiic.h"
+
+void micro_oled_init(void);
+
+void send_command(uint8_t command);
+void send_data(uint8_t data);
+void set_page_address(uint8_t address);
+void set_column_address(uint8_t address);
+void clear_screen(void);
+void clear_buffer(void);
+void send_buffer(void);
+void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode);
+void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode);
+void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode);
+void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode);
+void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
+void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
+void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
+void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
+void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font);
+void draw_string(uint8_t x, uint8_t y, char * string, uint8_t color, uint8_t mode, uint8_t font);
+
+#define I2C_ADDRESS_SA0_0 0b0111100
+#ifndef I2C_ADDRESS_SA0_1
+#define I2C_ADDRESS_SA0_1 0b0111101
+#endif
+#define I2C_COMMAND 0x00
+#define I2C_DATA 0x40
+#define PIXEL_OFF 0
+#define PIXEL_ON 1
+
+#ifndef LCDWIDTH
+#define LCDWIDTH 64
+#endif
+#ifndef LCDWIDTH
+#define LCDHEIGHT 48
+#endif
+#define FONTHEADERSIZE 6
+
+#define NORM 0
+#define XOR 1
+
+#define PAGE 0
+#define ALL 1
+
+#define WIDGETSTYLE0 0
+#define WIDGETSTYLE1 1
+#define WIDGETSTYLE2 2
+
+#define SETCONTRAST 0x81
+#define DISPLAYALLONRESUME 0xA4
+#define DISPLAYALLON 0xA5
+#define NORMALDISPLAY 0xA6
+#define INVERTDISPLAY 0xA7
+#define DISPLAYOFF 0xAE
+#define DISPLAYON 0xAF
+#define SETDISPLAYOFFSET 0xD3
+#define SETCOMPINS 0xDA
+#define SETVCOMDESELECT 0xDB
+#define SETDISPLAYCLOCKDIV 0xD5
+#define SETPRECHARGE 0xD9
+#define SETMULTIPLEX 0xA8
+#define SETLOWCOLUMN 0x00
+#define SETHIGHCOLUMN 0x10
+#define SETSTARTLINE 0x40
+#define MEMORYMODE 0x20
+#define COMSCANINC 0xC0
+#define COMSCANDEC 0xC8
+#define SEGREMAP 0xA0
+#define CHARGEPUMP 0x8D
+#define EXTERNALVCC 0x01
+#define SWITCHCAPVCC 0x02
+
+// Scroll
+#define ACTIVATESCROLL 0x2F
+#define DEACTIVATESCROLL 0x2E
+#define SETVERTICALSCROLLAREA 0xA3
+#define RIGHTHORIZONTALSCROLL 0x26
+#define LEFT_HORIZONTALSCROLL 0x27
+#define VERTICALRIGHTHORIZONTALSCROLL 0x29
+#define VERTICALLEFTHORIZONTALSCROLL 0x2A
+
+typedef enum CMD {
+ CMD_CLEAR, //0
+ CMD_INVERT, //1
+ CMD_CONTRAST, //2
+ CMD_DISPLAY, //3
+ CMD_SETCURSOR, //4
+ CMD_PIXEL, //5
+ CMD_LINE, //6
+ CMD_LINEH, //7
+ CMD_LINEV, //8
+ CMD_RECT, //9
+ CMD_RECTFILL, //10
+ CMD_CIRCLE, //11
+ CMD_CIRCLEFILL, //12
+ CMD_DRAWCHAR, //13
+ CMD_DRAWBITMAP, //14
+ CMD_GETLCDWIDTH, //15
+ CMD_GETLCDHEIGHT, //16
+ CMD_SETCOLOR, //17
+ CMD_SETDRAWMODE //18
+} commCommand_t; \ No newline at end of file
diff --git a/drivers/qwiic/qwiic.c b/drivers/qwiic/qwiic.c
new file mode 100644
index 0000000000..9047919927
--- /dev/null
+++ b/drivers/qwiic/qwiic.c
@@ -0,0 +1,31 @@
+/* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qwiic.h"
+
+void qwiic_init(void) {
+ #ifdef QWIIC_JOYSTIIC_ENABLE
+ joystiic_init();
+ #endif
+ #ifdef QWIIC_MICRO_OLED_ENABLE
+ micro_oled_init();
+ #endif
+}
+
+void qwiic_task(void) {
+ #ifdef QWIIC_JOYSTIIC_ENABLE
+ joystiic_task();
+ #endif
+}
diff --git a/drivers/qwiic/qwiic.h b/drivers/qwiic/qwiic.h
new file mode 100644
index 0000000000..160fb28dfd
--- /dev/null
+++ b/drivers/qwiic/qwiic.h
@@ -0,0 +1,28 @@
+/* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
+ *
+ * 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
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include "i2c_master.h"
+
+#ifdef QWIIC_JOYSTIIC_ENABLE
+ #include "joystiic.h"
+#endif
+#ifdef QWIIC_MICRO_OLED_ENABLE
+ #include "micro_oled.h"
+#endif
+
+void qwiic_init(void);
+void qwiic_task(void);
diff --git a/drivers/qwiic/qwiic.mk b/drivers/qwiic/qwiic.mk
new file mode 100644
index 0000000000..4ae2d78e3e
--- /dev/null
+++ b/drivers/qwiic/qwiic.mk
@@ -0,0 +1,18 @@
+ifneq ($(strip $(QWIIC_ENABLE)),)
+ COMMON_VPATH += $(DRIVER_PATH)/qwiic
+ OPT_DEFS += -DQWIIC_ENABLE
+ SRC += qwiic.c
+ ifeq ($(filter "i2c_master.c", $(SRC)),)
+ SRC += i2c_master.c
+ endif
+endif
+
+ifneq ($(filter JOYSTIIC, $(QWIIC_ENABLE)),)
+ OPT_DEFS += -DQWIIC_JOYSTIIC_ENABLE
+ SRC += joystiic.c
+endif
+
+ifneq ($(filter MICRO_OLED, $(QWIIC_ENABLE)),)
+ OPT_DEFS += -DQWIIC_MICRO_OLED_ENABLE
+ SRC += micro_oled.c
+endif
diff --git a/drivers/qwiic/util/font5x7.h b/drivers/qwiic/util/font5x7.h
new file mode 100644
index 0000000000..0bad206b7c
--- /dev/null
+++ b/drivers/qwiic/util/font5x7.h
@@ -0,0 +1,288 @@
+/******************************************************************************
+font5x7.h
+Definition for small font
+
+This file was imported from the MicroView library, written by GeekAmmo
+(https://github.com/geekammo/MicroView-Arduino-Library), and released under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Modified by:
+Emil Varughese @ Edwin Robotics Pvt. Ltd.
+July 27, 2015
+https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
+
+******************************************************************************/
+#pragma once
+
+#include "progmem.h"
+
+// Standard ASCII 5x7 font
+static const unsigned char font5x7[] PROGMEM = {
+ // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
+ 5,8,0,255,12,75,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
+ 0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
+ 0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
+ 0x18, 0x3C, 0x7E, 0x3C, 0x18,
+ 0x1C, 0x57, 0x7D, 0x57, 0x1C,
+ 0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
+ 0x00, 0x18, 0x3C, 0x18, 0x00,
+ 0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
+ 0x00, 0x18, 0x24, 0x18, 0x00,
+ 0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
+ 0x30, 0x48, 0x3A, 0x06, 0x0E,
+ 0x26, 0x29, 0x79, 0x29, 0x26,
+ 0x40, 0x7F, 0x05, 0x05, 0x07,
+ 0x40, 0x7F, 0x05, 0x25, 0x3F,
+ 0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
+ 0x7F, 0x3E, 0x1C, 0x1C, 0x08,
+ 0x08, 0x1C, 0x1C, 0x3E, 0x7F,
+ 0x14, 0x22, 0x7F, 0x22, 0x14,
+ 0x5F, 0x5F, 0x00, 0x5F, 0x5F,
+ 0x06, 0x09, 0x7F, 0x01, 0x7F,
+ 0x00, 0x66, 0x89, 0x95, 0x6A,
+ 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x94, 0xA2, 0xFF, 0xA2, 0x94,
+ 0x08, 0x04, 0x7E, 0x04, 0x08,
+ 0x10, 0x20, 0x7E, 0x20, 0x10,
+ 0x08, 0x08, 0x2A, 0x1C, 0x08,
+ 0x08, 0x1C, 0x2A, 0x08, 0x08,
+ 0x1E, 0x10, 0x10, 0x10, 0x10,
+ 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
+ 0x30, 0x38, 0x3E, 0x38, 0x30,
+ 0x06, 0x0E, 0x3E, 0x0E, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x5F, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07, 0x00,
+ 0x14, 0x7F, 0x14, 0x7F, 0x14,
+ 0x24, 0x2A, 0x7F, 0x2A, 0x12,
+ 0x23, 0x13, 0x08, 0x64, 0x62,
+ 0x36, 0x49, 0x56, 0x20, 0x50,
+ 0x00, 0x08, 0x07, 0x03, 0x00,
+ 0x00, 0x1C, 0x22, 0x41, 0x00,
+ 0x00, 0x41, 0x22, 0x1C, 0x00,
+ 0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
+ 0x08, 0x08, 0x3E, 0x08, 0x08,
+ 0x00, 0x80, 0x70, 0x30, 0x00,
+ 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x00, 0x00, 0x60, 0x60, 0x00,
+ 0x20, 0x10, 0x08, 0x04, 0x02,
+ 0x3E, 0x51, 0x49, 0x45, 0x3E,
+ 0x00, 0x42, 0x7F, 0x40, 0x00,
+ 0x72, 0x49, 0x49, 0x49, 0x46,
+ 0x21, 0x41, 0x49, 0x4D, 0x33,
+ 0x18, 0x14, 0x12, 0x7F, 0x10,
+ 0x27, 0x45, 0x45, 0x45, 0x39,
+ 0x3C, 0x4A, 0x49, 0x49, 0x31,
+ 0x41, 0x21, 0x11, 0x09, 0x07,
+ 0x36, 0x49, 0x49, 0x49, 0x36,
+ 0x46, 0x49, 0x49, 0x29, 0x1E,
+ 0x00, 0x00, 0x14, 0x00, 0x00,
+ 0x00, 0x40, 0x34, 0x00, 0x00,
+ 0x00, 0x08, 0x14, 0x22, 0x41,
+ 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x00, 0x41, 0x22, 0x14, 0x08,
+ 0x02, 0x01, 0x59, 0x09, 0x06,
+ 0x3E, 0x41, 0x5D, 0x59, 0x4E,
+ 0x7C, 0x12, 0x11, 0x12, 0x7C,
+ 0x7F, 0x49, 0x49, 0x49, 0x36,
+ 0x3E, 0x41, 0x41, 0x41, 0x22,
+ 0x7F, 0x41, 0x41, 0x41, 0x3E,
+ 0x7F, 0x49, 0x49, 0x49, 0x41,
+ 0x7F, 0x09, 0x09, 0x09, 0x01,
+ 0x3E, 0x41, 0x41, 0x51, 0x73,
+ 0x7F, 0x08, 0x08, 0x08, 0x7F,
+ 0x00, 0x41, 0x7F, 0x41, 0x00,
+ 0x20, 0x40, 0x41, 0x3F, 0x01,
+ 0x7F, 0x08, 0x14, 0x22, 0x41,
+ 0x7F, 0x40, 0x40, 0x40, 0x40,
+ 0x7F, 0x02, 0x1C, 0x02, 0x7F,
+ 0x7F, 0x04, 0x08, 0x10, 0x7F,
+ 0x3E, 0x41, 0x41, 0x41, 0x3E,
+ 0x7F, 0x09, 0x09, 0x09, 0x06,
+ 0x3E, 0x41, 0x51, 0x21, 0x5E,
+ 0x7F, 0x09, 0x19, 0x29, 0x46,
+ 0x26, 0x49, 0x49, 0x49, 0x32,
+ 0x03, 0x01, 0x7F, 0x01, 0x03,
+ 0x3F, 0x40, 0x40, 0x40, 0x3F,
+ 0x1F, 0x20, 0x40, 0x20, 0x1F,
+ 0x3F, 0x40, 0x38, 0x40, 0x3F,
+ 0x63, 0x14, 0x08, 0x14, 0x63,
+ 0x03, 0x04, 0x78, 0x04, 0x03,
+ 0x61, 0x59, 0x49, 0x4D, 0x43,
+ 0x00, 0x7F, 0x41, 0x41, 0x41,
+ 0x02, 0x04, 0x08, 0x10, 0x20,
+ 0x00, 0x41, 0x41, 0x41, 0x7F,
+ 0x04, 0x02, 0x01, 0x02, 0x04,
+ 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x00, 0x03, 0x07, 0x08, 0x00,
+ 0x20, 0x54, 0x54, 0x78, 0x40,
+ 0x7F, 0x28, 0x44, 0x44, 0x38,
+ 0x38, 0x44, 0x44, 0x44, 0x28,
+ 0x38, 0x44, 0x44, 0x28, 0x7F,
+ 0x38, 0x54, 0x54, 0x54, 0x18,
+ 0x00, 0x08, 0x7E, 0x09, 0x02,
+ 0x18, 0xA4, 0xA4, 0x9C, 0x78,
+ 0x7F, 0x08, 0x04, 0x04, 0x78,
+ 0x00, 0x44, 0x7D, 0x40, 0x00,
+ 0x20, 0x40, 0x40, 0x3D, 0x00,
+ 0x7F, 0x10, 0x28, 0x44, 0x00,
+ 0x00, 0x41, 0x7F, 0x40, 0x00,
+ 0x7C, 0x04, 0x78, 0x04, 0x78,
+ 0x7C, 0x08, 0x04, 0x04, 0x78,
+ 0x38, 0x44, 0x44, 0x44, 0x38,
+ 0xFC, 0x18, 0x24, 0x24, 0x18,
+ 0x18, 0x24, 0x24, 0x18, 0xFC,
+ 0x7C, 0x08, 0x04, 0x04, 0x08,
+ 0x48, 0x54, 0x54, 0x54, 0x24,
+ 0x04, 0x04, 0x3F, 0x44, 0x24,
+ 0x3C, 0x40, 0x40, 0x20, 0x7C,
+ 0x1C, 0x20, 0x40, 0x20, 0x1C,
+ 0x3C, 0x40, 0x30, 0x40, 0x3C,
+ 0x44, 0x28, 0x10, 0x28, 0x44,
+ 0x4C, 0x90, 0x90, 0x90, 0x7C,
+ 0x44, 0x64, 0x54, 0x4C, 0x44,
+ 0x00, 0x08, 0x36, 0x41, 0x00,
+ 0x00, 0x00, 0x77, 0x00, 0x00,
+ 0x00, 0x41, 0x36, 0x08, 0x00,
+ 0x02, 0x01, 0x02, 0x04, 0x02,
+ 0x3C, 0x26, 0x23, 0x26, 0x3C,
+ 0x1E, 0xA1, 0xA1, 0x61, 0x12,
+ 0x3A, 0x40, 0x40, 0x20, 0x7A,
+ 0x38, 0x54, 0x54, 0x55, 0x59,
+ 0x21, 0x55, 0x55, 0x79, 0x41,
+ 0x21, 0x54, 0x54, 0x78, 0x41,
+ 0x21, 0x55, 0x54, 0x78, 0x40,
+ 0x20, 0x54, 0x55, 0x79, 0x40,
+ 0x0C, 0x1E, 0x52, 0x72, 0x12,
+ 0x39, 0x55, 0x55, 0x55, 0x59,
+ 0x39, 0x54, 0x54, 0x54, 0x59,
+ 0x39, 0x55, 0x54, 0x54, 0x58,
+ 0x00, 0x00, 0x45, 0x7C, 0x41,
+ 0x00, 0x02, 0x45, 0x7D, 0x42,
+ 0x00, 0x01, 0x45, 0x7C, 0x40,
+ 0xF0, 0x29, 0x24, 0x29, 0xF0,
+ 0xF0, 0x28, 0x25, 0x28, 0xF0,
+ 0x7C, 0x54, 0x55, 0x45, 0x00,
+ 0x20, 0x54, 0x54, 0x7C, 0x54,
+ 0x7C, 0x0A, 0x09, 0x7F, 0x49,
+ 0x32, 0x49, 0x49, 0x49, 0x32,
+ 0x32, 0x48, 0x48, 0x48, 0x32,
+ 0x32, 0x4A, 0x48, 0x48, 0x30,
+ 0x3A, 0x41, 0x41, 0x21, 0x7A,
+ 0x3A, 0x42, 0x40, 0x20, 0x78,
+ 0x00, 0x9D, 0xA0, 0xA0, 0x7D,
+ 0x39, 0x44, 0x44, 0x44, 0x39,
+ 0x3D, 0x40, 0x40, 0x40, 0x3D,
+ 0x3C, 0x24, 0xFF, 0x24, 0x24,
+ 0x48, 0x7E, 0x49, 0x43, 0x66,
+ 0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
+ 0xFF, 0x09, 0x29, 0xF6, 0x20,
+ 0xC0, 0x88, 0x7E, 0x09, 0x03,
+ 0x20, 0x54, 0x54, 0x79, 0x41,
+ 0x00, 0x00, 0x44, 0x7D, 0x41,
+ 0x30, 0x48, 0x48, 0x4A, 0x32,
+ 0x38, 0x40, 0x40, 0x22, 0x7A,
+ 0x00, 0x7A, 0x0A, 0x0A, 0x72,
+ 0x7D, 0x0D, 0x19, 0x31, 0x7D,
+ 0x26, 0x29, 0x29, 0x2F, 0x28,
+ 0x26, 0x29, 0x29, 0x29, 0x26,
+ 0x30, 0x48, 0x4D, 0x40, 0x20,
+ 0x38, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x38,
+ 0x2F, 0x10, 0xC8, 0xAC, 0xBA,
+ 0x2F, 0x10, 0x28, 0x34, 0xFA,
+ 0x00, 0x00, 0x7B, 0x00, 0x00,
+ 0x08, 0x14, 0x2A, 0x14, 0x22,
+ 0x22, 0x14, 0x2A, 0x14, 0x08,
+ 0xAA, 0x00, 0x55, 0x00, 0xAA,
+ 0xAA, 0x55, 0xAA, 0x55, 0xAA,
+ 0x00, 0x00, 0x00, 0xFF, 0x00,
+ 0x10, 0x10, 0x10, 0xFF, 0x00,
+ 0x14, 0x14, 0x14, 0xFF, 0x00,
+ 0x10, 0x10, 0xFF, 0x00, 0xFF,
+ 0x10, 0x10, 0xF0, 0x10, 0xF0,
+ 0x14, 0x14, 0x14, 0xFC, 0x00,
+ 0x14, 0x14, 0xF7, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF,
+ 0x14, 0x14, 0xF4, 0x04, 0xFC,
+ 0x14, 0x14, 0x17, 0x10, 0x1F,
+ 0x10, 0x10, 0x1F, 0x10, 0x1F,
+ 0x14, 0x14, 0x14, 0x1F, 0x00,
+ 0x10, 0x10, 0x10, 0xF0, 0x00,
+ 0x00, 0x00, 0x00, 0x1F, 0x10,
+ 0x10, 0x10, 0x10, 0x1F, 0x10,
+ 0x10, 0x10, 0x10, 0xF0, 0x10,
+ 0x00, 0x00, 0x00, 0xFF, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0xFF, 0x10,
+ 0x00, 0x00, 0x00, 0xFF, 0x14,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF,
+ 0x00, 0x00, 0x1F, 0x10, 0x17,
+ 0x00, 0x00, 0xFC, 0x04, 0xF4,
+ 0x14, 0x14, 0x17, 0x10, 0x17,
+ 0x14, 0x14, 0xF4, 0x04, 0xF4,
+ 0x00, 0x00, 0xFF, 0x00, 0xF7,
+ 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0xF7, 0x00, 0xF7,
+ 0x14, 0x14, 0x14, 0x17, 0x14,
+ 0x10, 0x10, 0x1F, 0x10, 0x1F,
+ 0x14, 0x14, 0x14, 0xF4, 0x14,
+ 0x10, 0x10, 0xF0, 0x10, 0xF0,
+ 0x00, 0x00, 0x1F, 0x10, 0x1F,
+ 0x00, 0x00, 0x00, 0x1F, 0x14,
+ 0x00, 0x00, 0x00, 0xFC, 0x14,
+ 0x00, 0x00, 0xF0, 0x10, 0xF0,
+ 0x10, 0x10, 0xFF, 0x10, 0xFF,
+ 0x14, 0x14, 0x14, 0xFF, 0x14,
+ 0x10, 0x10, 0x10, 0x1F, 0x00,
+ 0x00, 0x00, 0x00, 0xF0, 0x10,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0x38, 0x44, 0x44, 0x38, 0x44,
+ 0x7C, 0x2A, 0x2A, 0x3E, 0x14,
+ 0x7E, 0x02, 0x02, 0x06, 0x06,
+ 0x02, 0x7E, 0x02, 0x7E, 0x02,
+ 0x63, 0x55, 0x49, 0x41, 0x63,
+ 0x38, 0x44, 0x44, 0x3C, 0x04,
+ 0x40, 0x7E, 0x20, 0x1E, 0x20,
+ 0x06, 0x02, 0x7E, 0x02, 0x02,
+ 0x99, 0xA5, 0xE7, 0xA5, 0x99,
+ 0x1C, 0x2A, 0x49, 0x2A, 0x1C,
+ 0x4C, 0x72, 0x01, 0x72, 0x4C,
+ 0x30, 0x4A, 0x4D, 0x4D, 0x30,
+ 0x30, 0x48, 0x78, 0x48, 0x30,
+ 0xBC, 0x62, 0x5A, 0x46, 0x3D,
+ 0x3E, 0x49, 0x49, 0x49, 0x00,
+ 0x7E, 0x01, 0x01, 0x01, 0x7E,
+ 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
+ 0x44, 0x44, 0x5F, 0x44, 0x44,
+ 0x40, 0x51, 0x4A, 0x44, 0x40,
+ 0x40, 0x44, 0x4A, 0x51, 0x40,
+ 0x00, 0x00, 0xFF, 0x01, 0x03,
+ 0xE0, 0x80, 0xFF, 0x00, 0x00,
+ 0x08, 0x08, 0x6B, 0x6B, 0x08,
+ 0x36, 0x12, 0x36, 0x24, 0x36,
+ 0x06, 0x0F, 0x09, 0x0F, 0x06,
+ 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x00, 0x10, 0x10, 0x00,
+ 0x30, 0x40, 0xFF, 0x01, 0x01,
+ 0x00, 0x1F, 0x01, 0x01, 0x1E,
+ 0x00, 0x19, 0x1D, 0x17, 0x12,
+ 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/drivers/qwiic/util/font8x16.h b/drivers/qwiic/util/font8x16.h
new file mode 100644
index 0000000000..c070e4ec8c
--- /dev/null
+++ b/drivers/qwiic/util/font8x16.h
@@ -0,0 +1,127 @@
+/******************************************************************************
+font8x16.h
+Definition for medium font
+
+This file was imported from the MicroView library, written by GeekAmmo
+(https://github.com/geekammo/MicroView-Arduino-Library), and released under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Modified by:
+Emil Varughese @ Edwin Robotics Pvt. Ltd.
+July 27, 2015
+https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
+******************************************************************************/
+#pragma once
+
+#include "progmem.h"
+
+static const unsigned char font8x16[] PROGMEM = {
+ // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
+ 8,16,32,96,2,56,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xBE, 0x90, 0xD0, 0xBE, 0x90, 0x00,
+ 0x00, 0x1C, 0x62, 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x0C, 0x12, 0x92, 0x4C, 0xB0, 0x88, 0x06, 0x00,
+ 0x80, 0x7C, 0x62, 0xB2, 0x1C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xE0, 0x18, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00,
+ 0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, 0x00, 0x80, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00,
+ 0xF8, 0x04, 0xC2, 0x32, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x04, 0x04, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00,
+ 0xC0, 0xA0, 0x98, 0x84, 0xFE, 0x80, 0x80, 0x00, 0x00, 0x1E, 0x12, 0x12, 0x22, 0xC2, 0x00, 0x00,
+ 0xF8, 0x44, 0x22, 0x22, 0x22, 0xC0, 0x00, 0x00, 0x00, 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00,
+ 0x00, 0x8C, 0x52, 0x22, 0x52, 0x8C, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x26, 0xF8, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
+ 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x04, 0x0F, 0x04, 0x03, 0x00, 0x00, 0x04, 0x02, 0x01, 0x03, 0x04, 0x04, 0x03, 0x00,
+ 0x03, 0x04, 0x04, 0x04, 0x05, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x06, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x06, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x03, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x01, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+ 0x04, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xF8, 0x04, 0x72, 0x8A, 0xFA, 0x84, 0x78, 0x00, 0x00, 0xC0, 0x38, 0x06, 0x38, 0xC0, 0x00, 0x00,
+ 0x00, 0xFE, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+ 0xFE, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
+ 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x22, 0xE2, 0x00, 0x00,
+ 0xFE, 0x20, 0x20, 0x20, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0xFE, 0x40, 0xB0, 0x08, 0x04, 0x02, 0x00, 0x00,
+ 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0C, 0x70, 0x80, 0x70, 0x0C, 0xFE, 0x00,
+ 0xFE, 0x0C, 0x30, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00,
+ 0xFE, 0x42, 0x42, 0x42, 0x22, 0x1C, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00,
+ 0x00, 0xFE, 0x42, 0x42, 0xA2, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x42, 0x80, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x02, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00,
+ 0x06, 0x38, 0xC0, 0x00, 0xC0, 0x38, 0x06, 0x00, 0x3E, 0xC0, 0xF0, 0x0E, 0xF0, 0xC0, 0x3E, 0x00,
+ 0x00, 0x06, 0x98, 0x60, 0x98, 0x06, 0x00, 0x00, 0x00, 0x06, 0x18, 0xE0, 0x18, 0x06, 0x00, 0x00,
+ 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x06, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00,
+ 0x40, 0x30, 0x0C, 0x0C, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x07, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0C, 0x12, 0x11, 0x10, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x06, 0x01, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00,
+ 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
+ 0x00, 0xE0, 0x10, 0x10, 0x10, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0x00, 0x00,
+ 0x00, 0x20, 0xFC, 0x22, 0x22, 0x22, 0x02, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00,
+ 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x80, 0x40, 0x20, 0x10, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x10, 0xF0, 0x20, 0x10, 0xF0, 0x00,
+ 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xE0, 0x00, 0x00,
+ 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00,
+ 0x00, 0xF0, 0x20, 0x10, 0x10, 0x70, 0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x20, 0x00, 0x00,
+ 0x00, 0x20, 0x20, 0xFC, 0x20, 0x20, 0x20, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
+ 0x00, 0x70, 0x80, 0x00, 0x80, 0x70, 0x00, 0x00, 0xF0, 0x00, 0xC0, 0x30, 0xC0, 0x00, 0xF0, 0x00,
+ 0x00, 0x30, 0xC0, 0xC0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00,
+ 0x00, 0x10, 0x10, 0x90, 0x50, 0x30, 0x00, 0x00, 0x00, 0x80, 0x80, 0x7E, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x7E, 0x80, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x24, 0x24, 0x22, 0x1F, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x3F, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x3F, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x01, 0x06, 0x01, 0x00,
+ 0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x20, 0x20, 0x31, 0x0E, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x05, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};