diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/chibios/analog.c | 57 | ||||
| -rw-r--r-- | drivers/chibios/ws2812_pwm.c | 11 | ||||
| -rw-r--r-- | drivers/chibios/ws2812_spi.c | 45 | ||||
| -rw-r--r-- | drivers/oled/oled_driver.c | 29 | ||||
| -rw-r--r-- | drivers/oled/oled_driver.h | 12 | 
5 files changed, 139 insertions, 15 deletions
| diff --git a/drivers/chibios/analog.c b/drivers/chibios/analog.c index 2b3872afbb..b1081623d3 100644 --- a/drivers/chibios/analog.c +++ b/drivers/chibios/analog.c @@ -101,7 +101,11 @@  // Options are 12, 10, 8, and 6 bit.  #ifndef ADC_RESOLUTION -#    define ADC_RESOLUTION ADC_CFGR1_RES_10BIT +#    ifdef ADC_CFGR_RES_10BITS  // ADCv3, ADCv4 +#        define ADC_RESOLUTION ADC_CFGR_RES_10BITS +#    else  // ADCv1, ADCv5, or the bodge for ADCv2 above +#        define ADC_RESOLUTION ADC_CFGR1_RES_10BIT +#    endif  #endif  static ADCConfig   adcCfg = {}; @@ -161,8 +165,8 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) {          case B0:  return TO_MUX( ADC_CHANNEL_IN12, 2 );          case B1:  return TO_MUX( ADC_CHANNEL_IN1,  2 );          case B2:  return TO_MUX( ADC_CHANNEL_IN12, 1 ); -        case B12: return TO_MUX( ADC_CHANNEL_IN2,  3 ); -        case B13: return TO_MUX( ADC_CHANNEL_IN3,  3 ); +        case B12: return TO_MUX( ADC_CHANNEL_IN3,  3 ); +        case B13: return TO_MUX( ADC_CHANNEL_IN5,  2 );          case B14: return TO_MUX( ADC_CHANNEL_IN4,  3 );          case B15: return TO_MUX( ADC_CHANNEL_IN5,  3 );          case C0:  return TO_MUX( ADC_CHANNEL_IN6,  0 ); // Can also be ADC2 @@ -189,11 +193,52 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) {          case E15: return TO_MUX( ADC_CHANNEL_IN2,  3 );          case F2:  return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2          case F4:  return TO_MUX( ADC_CHANNEL_IN5,  0 ); -#elif defined(STM32F4XX) // TODO: add all pins +#elif defined(STM32F4XX)          case A0:  return TO_MUX( ADC_CHANNEL_IN0,  0 ); -        //case A1:  return TO_MUX( ADC_CHANNEL_IN1,  0 ); -#elif defined(STM32F1XX) // TODO: add all pins +        case A1:  return TO_MUX( ADC_CHANNEL_IN1,  0 ); +        case A2:  return TO_MUX( ADC_CHANNEL_IN2,  0 ); +        case A3:  return TO_MUX( ADC_CHANNEL_IN3,  0 ); +        case A4:  return TO_MUX( ADC_CHANNEL_IN4,  0 ); +        case A5:  return TO_MUX( ADC_CHANNEL_IN5,  0 ); +        case A6:  return TO_MUX( ADC_CHANNEL_IN6,  0 ); +        case A7:  return TO_MUX( ADC_CHANNEL_IN7,  0 ); +        case B0:  return TO_MUX( ADC_CHANNEL_IN8,  0 ); +        case B1:  return TO_MUX( ADC_CHANNEL_IN9,  0 ); +        case C0:  return TO_MUX( ADC_CHANNEL_IN10, 0 ); +        case C1:  return TO_MUX( ADC_CHANNEL_IN11, 0 ); +        case C2:  return TO_MUX( ADC_CHANNEL_IN12, 0 ); +        case C3:  return TO_MUX( ADC_CHANNEL_IN13, 0 ); +        case C4:  return TO_MUX( ADC_CHANNEL_IN14, 0 ); +        case C5:  return TO_MUX( ADC_CHANNEL_IN15, 0 ); +#    if STM32_ADC_USE_ADC3 +        case F3:  return TO_MUX( ADC_CHANNEL_IN9,  2 ); +        case F4:  return TO_MUX( ADC_CHANNEL_IN14, 2 ); +        case F5:  return TO_MUX( ADC_CHANNEL_IN15, 2 ); +        case F6:  return TO_MUX( ADC_CHANNEL_IN4,  2 ); +        case F7:  return TO_MUX( ADC_CHANNEL_IN5,  2 ); +        case F8:  return TO_MUX( ADC_CHANNEL_IN6,  2 ); +        case F9:  return TO_MUX( ADC_CHANNEL_IN7,  2 ); +        case F10: return TO_MUX( ADC_CHANNEL_IN8,  2 ); +#    endif +#elif defined(STM32F1XX)          case A0:  return TO_MUX( ADC_CHANNEL_IN0,  0 ); +        case A1:  return TO_MUX( ADC_CHANNEL_IN1,  0 ); +        case A2:  return TO_MUX( ADC_CHANNEL_IN2,  0 ); +        case A3:  return TO_MUX( ADC_CHANNEL_IN3,  0 ); +        case A4:  return TO_MUX( ADC_CHANNEL_IN4,  0 ); +        case A5:  return TO_MUX( ADC_CHANNEL_IN5,  0 ); +        case A6:  return TO_MUX( ADC_CHANNEL_IN6,  0 ); +        case A7:  return TO_MUX( ADC_CHANNEL_IN7,  0 ); +        case B0:  return TO_MUX( ADC_CHANNEL_IN8,  0 ); +        case B1:  return TO_MUX( ADC_CHANNEL_IN9,  0 ); +        case C0:  return TO_MUX( ADC_CHANNEL_IN10, 0 ); +        case C1:  return TO_MUX( ADC_CHANNEL_IN11, 0 ); +        case C2:  return TO_MUX( ADC_CHANNEL_IN12, 0 ); +        case C3:  return TO_MUX( ADC_CHANNEL_IN13, 0 ); +        case C4:  return TO_MUX( ADC_CHANNEL_IN14, 0 ); +        case C5:  return TO_MUX( ADC_CHANNEL_IN15, 0 ); +        // STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the +        // ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable.  #endif      } diff --git a/drivers/chibios/ws2812_pwm.c b/drivers/chibios/ws2812_pwm.c index 140120d488..e6af55b6b3 100644 --- a/drivers/chibios/ws2812_pwm.c +++ b/drivers/chibios/ws2812_pwm.c @@ -27,6 +27,15 @@  #    error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_DMAMUX_ID STM32_DMAMUX1_TIM?_UP"  #endif +#ifndef WS2812_PWM_COMPLEMENTARY_OUTPUT +#    define WS2812_PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH +#else +#    if !STM32_PWM_USE_ADVANCED +#        error "WS2812_PWM_COMPLEMENTARY_OUTPUT requires STM32_PWM_USE_ADVANCED == TRUE" +#    endif +#    define WS2812_PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH +#endif +  // Push Pull or Open Drain Configuration  // Default Push Pull  #ifndef WS2812_EXTERNAL_PULLUP @@ -247,7 +256,7 @@ void ws2812_init(void) {          .channels =              {                  [0 ... 3]                = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL},     // Channels default to disabled -                [WS2812_PWM_CHANNEL - 1] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL},  // Turn on the channel we care about +                [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL},  // Turn on the channel we care about              },          .cr2  = 0,          .dier = TIM_DIER_UDE,  // DMA on update event for next period diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 89df2987b5..e02cbabc02 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -32,6 +32,37 @@  #    endif  #endif +// Define SPI config speed +// baudrate should target 3.2MHz +// F072 fpclk = 48MHz +// 48/16 = 3Mhz +#if WS2812_SPI_DIVISOR == 2 +#    define WS2812_SPI_DIVISOR (0) +#elif WS2812_SPI_DIVISOR == 4 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 8 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 16  // same as default +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 32 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) +#elif WS2812_SPI_DIVISOR == 64 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 128 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 256 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) +#else +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0)  // default +#endif + +// Use SPI circular buffer +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER +#    define WS2812_SPI_BUFFER_MODE 1  // circular buffer +#else +#    define WS2812_SPI_BUFFER_MODE 0  // normal buffer +#endif +  #define BYTES_FOR_LED_BYTE 4  #define NB_COLORS 3  #define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) @@ -81,14 +112,14 @@ void ws2812_init(void) {      palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE);      // TODO: more dynamic baudrate -    static const SPIConfig spicfg = { -        0, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), -        SPI_CR1_BR_1 | SPI_CR1_BR_0  // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) -    }; +    static const SPIConfig spicfg = {WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), WS2812_SPI_DIVISOR};      spiAcquireBus(&WS2812_SPI);     /* Acquire ownership of the bus.    */      spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters.       */      spiSelect(&WS2812_SPI);         /* Slave Select assertion.          */ +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER +    spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +#endif  }  void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { @@ -104,9 +135,11 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {      // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues.      // Instead spiSend can be used to send synchronously (or the thread logic can be added back). -#ifdef WS2812_SPI_SYNC +#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER +#    ifdef WS2812_SPI_SYNC      spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -#else +#    else      spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +#    endif  #endif  } diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c index 92c64399e2..082115d534 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/oled_driver.c @@ -24,6 +24,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "progmem.h" +#include "keyboard.h" +  // 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 @@ -71,6 +73,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define PRE_CHARGE_PERIOD 0xD9  #define VCOM_DETECT 0xDB +// Advance Graphic Commands +#define FADE_BLINK 0x23 +#define ENABLE_FADE 0x20 +#define ENABLE_BLINK 0x30 +  // Charge Pump Commands  #define CHARGE_PUMP 0x8D @@ -152,6 +159,12 @@ static void InvertCharacter(uint8_t *cursor) {  }  bool oled_init(uint8_t rotation) { +#if defined(USE_I2C) && defined(SPLIT_KEYBOARD) +    if (!is_keyboard_master()) { +        return true; +    } +#endif +      oled_rotation = oled_init_user(rotation);      if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {          oled_rotation_width = OLED_DISPLAY_WIDTH; @@ -539,7 +552,13 @@ bool oled_on(void) {      oled_timeout = timer_read32() + OLED_TIMEOUT;  #endif -    static const uint8_t PROGMEM display_on[] = {I2C_CMD, DISPLAY_ON}; +    static const uint8_t PROGMEM display_on[] = +#ifdef OLED_FADE_OUT +        {I2C_CMD, FADE_BLINK, 0x00}; +#else +        {I2C_CMD, DISPLAY_ON}; +#endif +      if (!oled_active) {          if (I2C_TRANSMIT_P(display_on) != I2C_STATUS_SUCCESS) {              print("oled_on cmd failed\n"); @@ -555,7 +574,13 @@ bool oled_off(void) {          return !oled_active;      } -    static const uint8_t PROGMEM display_off[] = {I2C_CMD, DISPLAY_OFF}; +    static const uint8_t PROGMEM display_off[] = +#ifdef OLED_FADE_OUT +        {I2C_CMD, FADE_BLINK, ENABLE_FADE | OLED_FADE_OUT_INTERVAL}; +#else +        {I2C_CMD, DISPLAY_OFF}; +#endif +      if (oled_active) {          if (I2C_TRANSMIT_P(display_off) != I2C_STATUS_SUCCESS) {              print("oled_off cmd failed\n"); diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h index 72ab21247d..cbf5380ee0 100644 --- a/drivers/oled/oled_driver.h +++ b/drivers/oled/oled_driver.h @@ -154,10 +154,22 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    endif  #endif +#if !defined(OLED_FADE_OUT_INTERVAL) +#    define OLED_FADE_OUT_INTERVAL 0x00 +#endif + +#if OLED_FADE_OUT_INTERVAL > 0x0F || OLED_FADE_OUT_INTERVAL < 0x00 +#    error OLED_FADE_OUT_INTERVAL must be between 0x00 and 0x0F +#endif +  #if !defined(OLED_I2C_TIMEOUT)  #    define OLED_I2C_TIMEOUT 100  #endif +#if !defined(OLED_UPDATE_INTERVAL) && defined(SPLIT_KEYBOARD) +#    define OLED_UPDATE_INTERVAL 50 +#endif +  typedef struct __attribute__((__packed__)) {      uint8_t *current_element;      uint16_t remaining_element_count; | 
