diff options
author | William Chang <william@factual.com> | 2019-07-13 10:18:33 -0700 |
---|---|---|
committer | William Chang <william@factual.com> | 2019-07-13 10:18:33 -0700 |
commit | 71493b2f9bbd5f3d18373c518fa14ccafcbf48fc (patch) | |
tree | 3bb3e5e496621535611e087720aa5c4d7a533e5e /drivers | |
parent | 86ad4988fe7ff64916127509d84f44c56fa097aa (diff) | |
parent | da1f05fbc19477c05c0c01bb07fabfaf1ece9d54 (diff) |
Merge branch 'master' of https://github.com/qmk/qmk_firmware
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/arm/i2c_master.c | 16 | ||||
-rw-r--r-- | drivers/arm/i2c_master.h | 40 | ||||
-rwxr-xr-x | drivers/avr/apa102.h | 2 | ||||
-rw-r--r-- | drivers/avr/ws2812.h | 2 | ||||
-rw-r--r-- | drivers/issi/is31fl3733.c | 38 | ||||
-rw-r--r-- | drivers/issi/is31fl3733.h | 6 | ||||
-rw-r--r-- | drivers/oled/oled_driver.c | 37 | ||||
-rw-r--r-- | drivers/oled/oled_driver.h | 61 | ||||
-rw-r--r-- | drivers/qwiic/qwiic.mk | 4 |
9 files changed, 160 insertions, 46 deletions
diff --git a/drivers/arm/i2c_master.c b/drivers/arm/i2c_master.c index 7369398cc4..5814375f37 100644 --- a/drivers/arm/i2c_master.c +++ b/drivers/arm/i2c_master.c @@ -32,12 +32,10 @@ static uint8_t i2c_address; -// 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) | - STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) | - STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U), + STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | + STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | + STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0 }; @@ -58,13 +56,13 @@ __attribute__ ((weak)) void i2c_init(void) { // Try releasing special pins for a short time - palSetPadMode(I2C1_BANK, I2C1_SCL, PAL_MODE_INPUT); - palSetPadMode(I2C1_BANK, I2C1_SDA, PAL_MODE_INPUT); + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT); chThdSleepMilliseconds(10); - palSetPadMode(I2C1_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); - palSetPadMode(I2C1_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); //i2cInit(); //This is invoked by halInit() so no need to redo it. } diff --git a/drivers/arm/i2c_master.h b/drivers/arm/i2c_master.h index a15f1702dd..1bb74c800f 100644 --- a/drivers/arm/i2c_master.h +++ b/drivers/arm/i2c_master.h @@ -26,9 +26,19 @@ #include "ch.h" #include <hal.h> -#ifndef I2C1_BANK - #define I2C1_BANK GPIOB +#ifdef I2C1_BANK + #define I2C1_SCL_BANK I2C1_BANK + #define I2C1_SDA_BANK I2C1_BANK #endif + +#ifndef I2C1_SCL_BANK + #define I2C1_SCL_BANK GPIOB +#endif + +#ifndef I2C1_SDA_BANK + #define I2C1_SDA_BANK GPIOB +#endif + #ifndef I2C1_SCL #define I2C1_SCL 6 #endif @@ -36,6 +46,32 @@ #define I2C1_SDA 7 #endif +// The default PAL alternate modes are used to signal that the pins are used for I2C +#ifndef I2C1_SCL_PAL_MODE + #define I2C1_SCL_PAL_MODE 4 +#endif +#ifndef I2C1_SDA_PAL_MODE + #define I2C1_SDA_PAL_MODE 4 +#endif + +// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock +// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html +#ifndef I2C1_TIMINGR_PRESC + #define I2C1_TIMINGR_PRESC 15U +#endif +#ifndef I2C1_TIMINGR_SCLDEL + #define I2C1_TIMINGR_SCLDEL 4U +#endif +#ifndef I2C1_TIMINGR_SDADEL + #define I2C1_TIMINGR_SDADEL 2U +#endif +#ifndef I2C1_TIMINGR_SCLH + #define I2C1_TIMINGR_SCLH 15U +#endif +#ifndef I2C1_TIMINGR_SCLL + #define I2C1_TIMINGR_SCLL 21U +#endif + #ifndef I2C_DRIVER #define I2C_DRIVER I2CD1 #endif diff --git a/drivers/avr/apa102.h b/drivers/avr/apa102.h index e7d7c3684f..5d852e0673 100755 --- a/drivers/avr/apa102.h +++ b/drivers/avr/apa102.h @@ -25,7 +25,7 @@ #include <avr/io.h> #include <avr/interrupt.h> -#include "rgblight_types.h" +#include "color.h" /* User Interface diff --git a/drivers/avr/ws2812.h b/drivers/avr/ws2812.h index ecb1dc4d18..95f540b184 100644 --- a/drivers/avr/ws2812.h +++ b/drivers/avr/ws2812.h @@ -28,7 +28,7 @@ //#include "ws2812_config.h" //#include "i2cmaster.h" -#include "rgblight_types.h" +#include "quantum/color.h" /* User Interface * diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c index c18ed7ca30..aa247f4e8a 100644 --- a/drivers/issi/is31fl3733.c +++ b/drivers/issi/is31fl3733.c @@ -75,10 +75,10 @@ uint8_t g_twi_transfer_buffer[20]; // 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; +bool g_pwm_buffer_update_required[DRIVER_COUNT] = { false }; uint8_t g_led_control_registers[DRIVER_COUNT][24] = { { 0 }, { 0 } }; -bool g_led_control_registers_update_required = false; +bool g_led_control_registers_update_required[DRIVER_COUNT] = { false }; void IS31FL3733_write_register( uint8_t addr, uint8_t reg, uint8_t data ) { @@ -123,12 +123,13 @@ void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) } } -void IS31FL3733_init( uint8_t addr ) +void IS31FL3733_init( uint8_t addr, uint8_t sync) { // 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. + // Sync is passed so set it according to the datasheet. // Unlock the command register. IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); @@ -161,7 +162,7 @@ void IS31FL3733_init( uint8_t addr ) // Set global current to maximum. IS31FL3733_write_register( addr, ISSI_REG_GLOBALCURRENT, 0xFF ); // Disable software shutdown. - IS31FL3733_write_register( addr, ISSI_REG_CONFIGURATION, 0x01 ); + IS31FL3733_write_register( addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01 ); // Wait 10ms to ensure the device has woken up. #ifdef __AVR__ @@ -179,7 +180,7 @@ void IS31FL3733_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) 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; + g_pwm_buffer_update_required[led.driver] = true; } } @@ -218,35 +219,34 @@ void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, b g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); } - g_led_control_registers_update_required = true; + g_led_control_registers_update_required[led.driver] = true; } -void IS31FL3733_update_pwm_buffers( uint8_t addr1, uint8_t addr2 ) +void IS31FL3733_update_pwm_buffers( uint8_t addr, uint8_t index ) { - if ( g_pwm_buffer_update_required ) + if ( g_pwm_buffer_update_required[index] ) { // 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_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); + IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM ); - IS31FL3733_write_pwm_buffer( addr1, g_pwm_buffer[0] ); - //IS31FL3733_write_pwm_buffer( addr2, g_pwm_buffer[1] ); + IS31FL3733_write_pwm_buffer( addr, g_pwm_buffer[index] ); } - g_pwm_buffer_update_required = false; + g_pwm_buffer_update_required[index] = false; } -void IS31FL3733_update_led_control_registers( uint8_t addr1, uint8_t addr2 ) +void IS31FL3733_update_led_control_registers( uint8_t addr, uint8_t index ) { - if ( g_led_control_registers_update_required ) + if ( g_led_control_registers_update_required[index] ) { // 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 ); + IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); + IS31FL3733_write_register( addr, 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] ); + IS31FL3733_write_register(addr, i, g_led_control_registers[index][i] ); } } + g_led_control_registers_update_required[index] = false; } diff --git a/drivers/issi/is31fl3733.h b/drivers/issi/is31fl3733.h index 3d23b188aa..e117b25460 100644 --- a/drivers/issi/is31fl3733.h +++ b/drivers/issi/is31fl3733.h @@ -32,7 +32,7 @@ typedef struct is31_led { extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; -void IS31FL3733_init( uint8_t addr ); +void IS31FL3733_init( uint8_t addr, uint8_t sync ); 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 ); @@ -45,8 +45,8 @@ void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, b // (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 ); +void IS31FL3733_update_pwm_buffers( uint8_t addr, uint8_t index ); +void IS31FL3733_update_led_control_registers( uint8_t addr, uint8_t index ); #define A_1 0x00 #define A_2 0x01 diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c index 96ea58ccb2..a54f5fadc3 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/oled_driver.c @@ -33,6 +33,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #endif // defined(__AVR__) // Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf +// for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf + // Fundamental Commands #define CONTRAST 0x81 #define DISPLAY_ALL_ON 0xA5 @@ -40,6 +42,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define NORMAL_DISPLAY 0xA6 #define DISPLAY_ON 0xAF #define DISPLAY_OFF 0xAE +#define NOP 0xE3 // Scrolling Commands #define ACTIVATE_SCROLL 0x2F @@ -53,6 +56,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define MEMORY_MODE 0x20 #define COLUMN_ADDR 0x21 #define PAGE_ADDR 0x22 +#define PAM_SETCOLUMN_LSB 0x00 +#define PAM_SETCOLUMN_MSB 0x10 +#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7 // Hardware Configuration Commands #define DISPLAY_START_LINE 0x40 @@ -63,6 +69,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define COM_SCAN_DEC 0xC8 #define DISPLAY_OFFSET 0xD3 #define COM_PINS 0xDA +#define COM_PINS_SEQ 0x02 +#define COM_PINS_ALT 0x12 +#define COM_PINS_SEQ_LR 0x22 +#define COM_PINS_ALT_LR 0x32 // Timing & Driving Commands #define DISPLAY_CLOCK 0xD5 @@ -154,7 +164,11 @@ bool oled_init(uint8_t rotation) { DISPLAY_OFFSET, 0x00, DISPLAY_START_LINE | 0x00, CHARGE_PUMP, 0x14, - MEMORY_MODE, 0x00, }; // Horizontal addressing mode +#if (OLED_IC != OLED_IC_SH1106) + // MEMORY_MODE is unsupported on SH1106 (Page Addressing only) + MEMORY_MODE, 0x00, // Horizontal addressing mode +#endif + }; if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) { print("oled_init cmd set 1 failed\n"); return false; @@ -182,7 +196,7 @@ bool oled_init(uint8_t rotation) { static const uint8_t PROGMEM display_setup2[] = { I2C_CMD, - COM_PINS, 0x02, + COM_PINS, OLED_COM_PINS, CONTRAST, 0x8F, PRE_CHARGE_PERIOD, 0xF1, VCOM_DETECT, 0x40, @@ -215,10 +229,25 @@ void oled_clear(void) { static void calc_bounds(uint8_t update_start, uint8_t* cmd_array) { - cmd_array[1] = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; - cmd_array[4] = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; + // Calculate commands to set memory addressing bounds. + uint8_t start_page = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; + uint8_t start_column = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; +#if (OLED_IC == OLED_IC_SH1106) + // Commands for Page Addressing Mode. Sets starting page and column; has no end bound. + // Column value must be split into high and low nybble and sent as two commands. + cmd_array[0] = PAM_PAGE_ADDR | start_page; + cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f); + cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f); + cmd_array[3] = NOP; + cmd_array[4] = NOP; + cmd_array[5] = NOP; +#else + // Commands for use in Horizontal Addressing mode. + cmd_array[1] = start_column; + cmd_array[4] = start_page; cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1]; cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1; +#endif } static void calc_bounds_90(uint8_t update_start, uint8_t* cmd_array) diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h index ec07f1d9b8..03dda2e64a 100644 --- a/drivers/oled/oled_driver.h +++ b/drivers/oled/oled_driver.h @@ -19,22 +19,47 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <stdint.h> #include <stdbool.h> +// an enumeration of the chips this driver supports +#define OLED_IC_SSD1306 0 +#define OLED_IC_SH1106 1 #if defined(OLED_DISPLAY_CUSTOM) // Expected user to implement the necessary defines #elif defined(OLED_DISPLAY_128X64) // Double height 128x64 +#ifndef OLED_DISPLAY_WIDTH #define OLED_DISPLAY_WIDTH 128 +#endif +#ifndef OLED_DISPLAY_HEIGHT #define OLED_DISPLAY_HEIGHT 64 +#endif +#ifndef OLED_MATRIX_SIZE #define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 1024 (compile time mathed) - #define OLED_BLOCK_TYPE uint32_t +#endif +#ifndef OLED_BLOCK_TYPE + #define OLED_BLOCK_TYPE uint16_t +#endif +#ifndef OLED_BLOCK_COUNT #define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 32 (compile time mathed) +#endif +#ifndef OLED_BLOCK_SIZE #define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) +#endif +#ifndef OLED_COM_PINS + #define OLED_COM_PINS COM_PINS_ALT +#endif // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode - #define OLED_SOURCE_MAP { 32, 40, 48, 56 } - #define OLED_TARGET_MAP { 24, 16, 8, 0 } +#ifndef OLED_SOURCE_MAP + #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } +#endif +#ifndef OLED_TARGET_MAP + #define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 } +#endif + // If OLED_BLOCK_TYPE is uint32_t, these tables would look like: + // #define OLED_SOURCE_MAP { 32, 40, 48, 56 } + // #define OLED_TARGET_MAP { 24, 16, 8, 0 } // If OLED_BLOCK_TYPE is uint16_t, these tables would look like: // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } // #define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 } @@ -43,23 +68,51 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. // #define OLED_TARGET_MAP { 56, 120, 48, 112, 40, 104, 32, 96, 24, 88, 16, 80, 8, 72, 0, 64 } #else // defined(OLED_DISPLAY_128X64) // Default 128x32 +#ifndef OLED_DISPLAY_WIDTH #define OLED_DISPLAY_WIDTH 128 +#endif +#ifndef OLED_DISPLAY_HEIGHT #define OLED_DISPLAY_HEIGHT 32 +#endif +#ifndef OLED_MATRIX_SIZE #define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 512 (compile time mathed) +#endif +#ifndef OLED_BLOCK_TYPE #define OLED_BLOCK_TYPE uint16_t // Type to use for segmenting the oled display for smart rendering, use unsigned types only +#endif +#ifndef OLED_BLOCK_COUNT #define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 16 (compile time mathed) +#endif +#ifndef OLED_BLOCK_SIZE #define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) +#endif +#ifndef OLED_COM_PINS + #define OLED_COM_PINS COM_PINS_SEQ +#endif // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode +#ifndef OLED_SOURCE_MAP #define OLED_SOURCE_MAP { 0, 8, 16, 24 } +#endif +#ifndef OLED_TARGET_MAP #define OLED_TARGET_MAP { 24, 16, 8, 0 } +#endif // If OLED_BLOCK_TYPE is uint8_t, these tables would look like: // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 } #endif // defined(OLED_DISPLAY_CUSTOM) -// Address to use for tthe i2d oled communication +#if !defined(OLED_IC) + #define OLED_IC OLED_IC_SSD1306 +#endif + +// the column address corresponding to the first column in the display hardware +#if !defined(OLED_COLUMN_OFFSET) + #define OLED_COLUMN_OFFSET 0 +#endif + +// Address to use for the i2c oled communication #if !defined(OLED_DISPLAY_ADDRESS) #define OLED_DISPLAY_ADDRESS 0x3C #endif diff --git a/drivers/qwiic/qwiic.mk b/drivers/qwiic/qwiic.mk index 4ae2d78e3e..b23c25657d 100644 --- a/drivers/qwiic/qwiic.mk +++ b/drivers/qwiic/qwiic.mk @@ -2,9 +2,7 @@ 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 + QUANTUM_LIB_SRC += i2c_master.c endif ifneq ($(filter JOYSTIIC, $(QWIIC_ENABLE)),) |