aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/avr/serial.c139
-rw-r--r--drivers/chibios/i2c_master.c21
-rw-r--r--drivers/chibios/spi_master.c27
-rw-r--r--drivers/eeprom/eeprom_i2c.c12
-rw-r--r--drivers/eeprom/eeprom_spi.c14
-rw-r--r--drivers/haptic/haptic.c53
-rw-r--r--drivers/haptic/solenoid.c10
-rw-r--r--drivers/haptic/solenoid.h18
-rw-r--r--drivers/oled/oled_driver.c22
9 files changed, 201 insertions, 115 deletions
diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c
index c27cbfdd0..526a0946b 100644
--- a/drivers/avr/serial.c
+++ b/drivers/avr/serial.c
@@ -20,50 +20,111 @@
20 20
21#ifdef SOFT_SERIAL_PIN 21#ifdef SOFT_SERIAL_PIN
22 22
23# ifdef __AVR_ATmega32U4__ 23# if !(defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
24// if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial. 24# error serial.c is not supported for the currently selected MCU
25# ifdef USE_AVR_I2C 25# endif
26# if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1 26// if using ATmega32U4/2, AT90USBxxx I2C, can not use PD0 and PD1 in soft serial.
27# error Using ATmega32U4 I2C, so can not use PD0, PD1 27# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
28# endif 28# if defined(USE_AVR_I2C) && (SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1)
29# error Using I2C, so can not use PD0, PD1
29# endif 30# endif
31# endif
32// PD0..PD3, common config
33# if SOFT_SERIAL_PIN == D0
34# define EIMSK_BIT _BV(INT0)
35# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01)))
36# define SERIAL_PIN_INTERRUPT INT0_vect
37# define EICRx EICRA
38# elif SOFT_SERIAL_PIN == D1
39# define EIMSK_BIT _BV(INT1)
40# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11)))
41# define SERIAL_PIN_INTERRUPT INT1_vect
42# define EICRx EICRA
43# elif SOFT_SERIAL_PIN == D2
44# define EIMSK_BIT _BV(INT2)
45# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21)))
46# define SERIAL_PIN_INTERRUPT INT2_vect
47# define EICRx EICRA
48# elif SOFT_SERIAL_PIN == D3
49# define EIMSK_BIT _BV(INT3)
50# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31)))
51# define SERIAL_PIN_INTERRUPT INT3_vect
52# define EICRx EICRA
53# endif
30 54
31# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) 55// ATmegaxxU2 specific config
32# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) 56# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)
33# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) 57// PD4(INT5), PD6(INT6), PD7(INT7), PC7(INT4)
34# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) 58# if SOFT_SERIAL_PIN == D4
35# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) 59# define EIMSK_BIT _BV(INT5)
36 60# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51)))
37# if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3 61# define SERIAL_PIN_INTERRUPT INT5_vect
38# if SOFT_SERIAL_PIN == D0 62# define EICRx EICRB
39# define EIMSK_BIT _BV(INT0) 63# elif SOFT_SERIAL_PIN == D6
40# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) 64# define EIMSK_BIT _BV(INT6)
41# define SERIAL_PIN_INTERRUPT INT0_vect 65# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
42# elif SOFT_SERIAL_PIN == D1 66# define SERIAL_PIN_INTERRUPT INT6_vect
43# define EIMSK_BIT _BV(INT1) 67# define EICRx EICRB
44# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) 68# elif SOFT_SERIAL_PIN == D7
45# define SERIAL_PIN_INTERRUPT INT1_vect 69# define EIMSK_BIT _BV(INT7)
46# elif SOFT_SERIAL_PIN == D2 70# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71)))
47# define EIMSK_BIT _BV(INT2) 71# define SERIAL_PIN_INTERRUPT INT7_vect
48# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) 72# define EICRx EICRB
49# define SERIAL_PIN_INTERRUPT INT2_vect 73# elif SOFT_SERIAL_PIN == C7
50# elif SOFT_SERIAL_PIN == D3 74# define EIMSK_BIT _BV(INT4)
51# define EIMSK_BIT _BV(INT3) 75# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41)))
52# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) 76# define SERIAL_PIN_INTERRUPT INT4_vect
53# define SERIAL_PIN_INTERRUPT INT3_vect 77# define EICRx EICRB
54# endif 78# endif
79# endif
80
81// ATmegaxxU4 specific config
82# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
83// PE6(INT6)
84# if SOFT_SERIAL_PIN == E6
85# define EIMSK_BIT _BV(INT6)
86# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
87# define SERIAL_PIN_INTERRUPT INT6_vect
88# define EICRx EICRB
89# endif
90# endif
91
92// AT90USBxxx specific config
93# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
94// PE4..PE7(INT4..INT7)
95# if SOFT_SERIAL_PIN == E4
96# define EIMSK_BIT _BV(INT4)
97# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41)))
98# define SERIAL_PIN_INTERRUPT INT4_vect
99# define EICRx EICRB
100# elif SOFT_SERIAL_PIN == E5
101# define EIMSK_BIT _BV(INT5)
102# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51)))
103# define SERIAL_PIN_INTERRUPT INT5_vect
104# define EICRx EICRB
55# elif SOFT_SERIAL_PIN == E6 105# elif SOFT_SERIAL_PIN == E6
56# define EIMSK_BIT _BV(INT6) 106# define EIMSK_BIT _BV(INT6)
57# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) 107# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
58# define SERIAL_PIN_INTERRUPT INT6_vect 108# define SERIAL_PIN_INTERRUPT INT6_vect
59# else 109# define EICRx EICRB
60# error invalid SOFT_SERIAL_PIN value 110# elif SOFT_SERIAL_PIN == E7
111# define EIMSK_BIT _BV(INT7)
112# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71)))
113# define SERIAL_PIN_INTERRUPT INT7_vect
114# define EICRx EICRB
61# endif 115# endif
116# endif
62 117
63# else 118# ifndef SERIAL_PIN_INTERRUPT
64# error serial.c now support ATmega32U4 only 119# error invalid SOFT_SERIAL_PIN value
65# endif 120# endif
66 121
122# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
123# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
124# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
125# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
126# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
127
67# define ALWAYS_INLINE __attribute__((always_inline)) 128# define ALWAYS_INLINE __attribute__((always_inline))
68# define NO_INLINE __attribute__((noinline)) 129# define NO_INLINE __attribute__((noinline))
69# define _delay_sub_us(x) __builtin_avr_delay_cycles(x) 130# define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
@@ -210,15 +271,9 @@ void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) {
210 Transaction_table_size = (uint8_t)sstd_table_size; 271 Transaction_table_size = (uint8_t)sstd_table_size;
211 serial_input_with_pullup(); 272 serial_input_with_pullup();
212 273
213 // Enable INT0-INT3,INT6 274 // Enable INT0-INT7
214 EIMSK |= EIMSK_BIT; 275 EIMSK |= EIMSK_BIT;
215# if SOFT_SERIAL_PIN == E6 276 EICRx &= EICRx_BIT;
216 // Trigger on falling edge of INT6
217 EICRB &= EICRx_BIT;
218# else
219 // Trigger on falling edge of INT0-INT3
220 EICRA &= EICRx_BIT;
221# endif
222} 277}
223 278
224// Used by the sender to synchronize timing with the reciver. 279// Used by the sender to synchronize timing with the reciver.
diff --git a/drivers/chibios/i2c_master.c b/drivers/chibios/i2c_master.c
index 4bd8e2af7..fc4bb2ab3 100644
--- a/drivers/chibios/i2c_master.c
+++ b/drivers/chibios/i2c_master.c
@@ -58,18 +58,23 @@ static i2c_status_t chibios_to_qmk(const msg_t* status) {
58} 58}
59 59
60__attribute__((weak)) void i2c_init(void) { 60__attribute__((weak)) void i2c_init(void) {
61 // Try releasing special pins for a short time 61 static bool is_initialised = false;
62 palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT); 62 if (!is_initialised) {
63 palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT); 63 is_initialised = true;
64 64
65 chThdSleepMilliseconds(10); 65 // Try releasing special pins for a short time
66 palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT);
67 palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT);
68
69 chThdSleepMilliseconds(10);
66#if defined(USE_GPIOV1) 70#if defined(USE_GPIOV1)
67 palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE); 71 palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE);
68 palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE); 72 palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE);
69#else 73#else
70 palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); 74 palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
71 palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); 75 palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
72#endif 76#endif
77 }
73} 78}
74 79
75i2c_status_t i2c_start(uint8_t address) { 80i2c_status_t i2c_start(uint8_t address) {
diff --git a/drivers/chibios/spi_master.c b/drivers/chibios/spi_master.c
index 552ac663c..5aa60742e 100644
--- a/drivers/chibios/spi_master.c
+++ b/drivers/chibios/spi_master.c
@@ -22,21 +22,26 @@ static pin_t currentSlavePin = NO_PIN;
22static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0}; 22static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0};
23 23
24__attribute__((weak)) void spi_init(void) { 24__attribute__((weak)) void spi_init(void) {
25 // Try releasing special pins for a short time 25 static bool is_initialised = false;
26 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_INPUT); 26 if (!is_initialised) {
27 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_INPUT); 27 is_initialised = true;
28 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_INPUT);
29 28
30 chThdSleepMilliseconds(10); 29 // Try releasing special pins for a short time
30 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_INPUT);
31 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_INPUT);
32 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_INPUT);
33
34 chThdSleepMilliseconds(10);
31#if defined(USE_GPIOV1) 35#if defined(USE_GPIOV1)
32 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); 36 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
33 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); 37 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
34 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); 38 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
35#else 39#else
36 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); 40 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
37 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); 41 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
38 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); 42 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
39#endif 43#endif
44 }
40} 45}
41 46
42bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { 47bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
diff --git a/drivers/eeprom/eeprom_i2c.c b/drivers/eeprom/eeprom_i2c.c
index ca8af3da5..4210f06f9 100644
--- a/drivers/eeprom/eeprom_i2c.c
+++ b/drivers/eeprom/eeprom_i2c.c
@@ -42,14 +42,6 @@
42# include "debug.h" 42# include "debug.h"
43#endif // DEBUG_EEPROM_OUTPUT 43#endif // DEBUG_EEPROM_OUTPUT
44 44
45static inline void init_i2c_if_required(void) {
46 static int done = 0;
47 if (!done) {
48 i2c_init();
49 done = 1;
50 }
51}
52
53static inline void fill_target_address(uint8_t *buffer, const void *addr) { 45static inline void fill_target_address(uint8_t *buffer, const void *addr) {
54 uintptr_t p = (uintptr_t)addr; 46 uintptr_t p = (uintptr_t)addr;
55 for (int i = 0; i < EXTERNAL_EEPROM_ADDRESS_SIZE; ++i) { 47 for (int i = 0; i < EXTERNAL_EEPROM_ADDRESS_SIZE; ++i) {
@@ -58,7 +50,7 @@ static inline void fill_target_address(uint8_t *buffer, const void *addr) {
58 } 50 }
59} 51}
60 52
61void eeprom_driver_init(void) {} 53void eeprom_driver_init(void) { i2c_init(); }
62 54
63void eeprom_driver_erase(void) { 55void eeprom_driver_erase(void) {
64#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) 56#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
@@ -80,7 +72,6 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
80 uint8_t complete_packet[EXTERNAL_EEPROM_ADDRESS_SIZE]; 72 uint8_t complete_packet[EXTERNAL_EEPROM_ADDRESS_SIZE];
81 fill_target_address(complete_packet, addr); 73 fill_target_address(complete_packet, addr);
82 74
83 init_i2c_if_required();
84 i2c_transmit(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), complete_packet, EXTERNAL_EEPROM_ADDRESS_SIZE, 100); 75 i2c_transmit(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), complete_packet, EXTERNAL_EEPROM_ADDRESS_SIZE, 100);
85 i2c_receive(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), buf, len, 100); 76 i2c_receive(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), buf, len, 100);
86 77
@@ -98,7 +89,6 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
98 uint8_t * read_buf = (uint8_t *)buf; 89 uint8_t * read_buf = (uint8_t *)buf;
99 uintptr_t target_addr = (uintptr_t)addr; 90 uintptr_t target_addr = (uintptr_t)addr;
100 91
101 init_i2c_if_required();
102 while (len > 0) { 92 while (len > 0) {
103 uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE; 93 uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE;
104 int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset; 94 int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset;
diff --git a/drivers/eeprom/eeprom_spi.c b/drivers/eeprom/eeprom_spi.c
index 7b6416eaf..182731d82 100644
--- a/drivers/eeprom/eeprom_spi.c
+++ b/drivers/eeprom/eeprom_spi.c
@@ -55,14 +55,6 @@
55# include "debug.h" 55# include "debug.h"
56#endif // CONSOLE_ENABLE 56#endif // CONSOLE_ENABLE
57 57
58static void init_spi_if_required(void) {
59 static int done = 0;
60 if (!done) {
61 spi_init();
62 done = 1;
63 }
64}
65
66static bool spi_eeprom_start(void) { return spi_start(EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN, EXTERNAL_EEPROM_SPI_LSBFIRST, EXTERNAL_EEPROM_SPI_MODE, EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR); } 58static bool spi_eeprom_start(void) { return spi_start(EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN, EXTERNAL_EEPROM_SPI_LSBFIRST, EXTERNAL_EEPROM_SPI_MODE, EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR); }
67 59
68static spi_status_t spi_eeprom_wait_while_busy(int timeout) { 60static spi_status_t spi_eeprom_wait_while_busy(int timeout) {
@@ -91,7 +83,7 @@ static void spi_eeprom_transmit_address(uintptr_t addr) {
91 83
92//---------------------------------------------------------------------------------------------------------------------- 84//----------------------------------------------------------------------------------------------------------------------
93 85
94void eeprom_driver_init(void) {} 86void eeprom_driver_init(void) { spi_init(); }
95 87
96void eeprom_driver_erase(void) { 88void eeprom_driver_erase(void) {
97#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) 89#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
@@ -110,8 +102,6 @@ void eeprom_driver_erase(void) {
110} 102}
111 103
112void eeprom_read_block(void *buf, const void *addr, size_t len) { 104void eeprom_read_block(void *buf, const void *addr, size_t len) {
113 init_spi_if_required();
114
115 //------------------------------------------------- 105 //-------------------------------------------------
116 // Wait for the write-in-progress bit to be cleared 106 // Wait for the write-in-progress bit to be cleared
117 bool res = spi_eeprom_start(); 107 bool res = spi_eeprom_start();
@@ -154,8 +144,6 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
154} 144}
155 145
156void eeprom_write_block(const void *buf, void *addr, size_t len) { 146void eeprom_write_block(const void *buf, void *addr, size_t len) {
157 init_spi_if_required();
158
159 bool res; 147 bool res;
160 uint8_t * read_buf = (uint8_t *)buf; 148 uint8_t * read_buf = (uint8_t *)buf;
161 uintptr_t target_addr = (uintptr_t)addr; 149 uintptr_t target_addr = (uintptr_t)addr;
diff --git a/drivers/haptic/haptic.c b/drivers/haptic/haptic.c
index 2ce279b75..de3f40052 100644
--- a/drivers/haptic/haptic.c
+++ b/drivers/haptic/haptic.c
@@ -33,11 +33,18 @@ void haptic_init(void) {
33 eeconfig_init(); 33 eeconfig_init();
34 } 34 }
35 haptic_config.raw = eeconfig_read_haptic(); 35 haptic_config.raw = eeconfig_read_haptic();
36 if (haptic_config.mode < 1) { 36#ifdef SOLENOID_ENABLE
37 haptic_config.mode = 1; 37 solenoid_set_dwell(haptic_config.dwell);
38 } 38#endif
39 if (!haptic_config.mode) { 39 if ((haptic_config.raw == 0)
40 dprintf("No haptic config found in eeprom, setting default configs\n"); 40#ifdef SOLENOID_ENABLE
41 || (haptic_config.dwell == 0)
42#endif
43 ) {
44 // this will be called, if the eeprom is not corrupt,
45 // but the previous firmware didn't have haptic enabled,
46 // or the previous firmware didn't have solenoid enabled,
47 // and the current one has solenoid enabled.
41 haptic_reset(); 48 haptic_reset();
42 } 49 }
43#ifdef SOLENOID_ENABLE 50#ifdef SOLENOID_ENABLE
@@ -118,25 +125,37 @@ void haptic_mode_decrease(void) {
118} 125}
119 126
120void haptic_dwell_increase(void) { 127void haptic_dwell_increase(void) {
121 uint8_t dwell = haptic_config.dwell + 1;
122#ifdef SOLENOID_ENABLE 128#ifdef SOLENOID_ENABLE
129 int16_t next_dwell = ((int16_t)haptic_config.dwell) + SOLENOID_DWELL_STEP_SIZE;
123 if (haptic_config.dwell >= SOLENOID_MAX_DWELL) { 130 if (haptic_config.dwell >= SOLENOID_MAX_DWELL) {
124 dwell = 1; 131 // if it's already at max, we wrap back to min
132 next_dwell = SOLENOID_MIN_DWELL;
133 } else if (next_dwell > SOLENOID_MAX_DWELL) {
134 // if we overshoot the max, then cap at max
135 next_dwell = SOLENOID_MAX_DWELL;
125 } 136 }
126 solenoid_set_dwell(dwell); 137 solenoid_set_dwell(next_dwell);
138#else
139 int16_t next_dwell = ((int16_t)haptic_config.dwell) + 1;
127#endif 140#endif
128 haptic_set_dwell(dwell); 141 haptic_set_dwell(next_dwell);
129} 142}
130 143
131void haptic_dwell_decrease(void) { 144void haptic_dwell_decrease(void) {
132 uint8_t dwell = haptic_config.dwell - 1;
133#ifdef SOLENOID_ENABLE 145#ifdef SOLENOID_ENABLE
134 if (haptic_config.dwell < SOLENOID_MIN_DWELL) { 146 int16_t next_dwell = ((int16_t)haptic_config.dwell) - SOLENOID_DWELL_STEP_SIZE;
135 dwell = SOLENOID_MAX_DWELL; 147 if (haptic_config.dwell <= SOLENOID_MIN_DWELL) {
148 // if it's already at min, we wrap to max
149 next_dwell = SOLENOID_MAX_DWELL;
150 } else if (next_dwell < SOLENOID_MIN_DWELL) {
151 // if we go below min, then we cap to min
152 next_dwell = SOLENOID_MIN_DWELL;
136 } 153 }
137 solenoid_set_dwell(dwell); 154 solenoid_set_dwell(next_dwell);
155#else
156 int16_t next_dwell = ((int16_t)haptic_config.dwell) - 1;
138#endif 157#endif
139 haptic_set_dwell(dwell); 158 haptic_set_dwell(next_dwell);
140} 159}
141 160
142void haptic_reset(void) { 161void haptic_reset(void) {
@@ -150,6 +169,12 @@ void haptic_reset(void) {
150#ifdef SOLENOID_ENABLE 169#ifdef SOLENOID_ENABLE
151 uint8_t dwell = SOLENOID_DEFAULT_DWELL; 170 uint8_t dwell = SOLENOID_DEFAULT_DWELL;
152 haptic_config.dwell = dwell; 171 haptic_config.dwell = dwell;
172 haptic_config.buzz = SOLENOID_DEFAULT_BUZZ;
173 solenoid_set_dwell(dwell);
174#else
175 // This is to trigger haptic_reset again, if solenoid is enabled in the future.
176 haptic_config.dwell = 0;
177 haptic_config.buzz = 0;
153#endif 178#endif
154 eeconfig_update_haptic(haptic_config.raw); 179 eeconfig_update_haptic(haptic_config.raw);
155 xprintf("haptic_config.feedback = %u\n", haptic_config.feedback); 180 xprintf("haptic_config.feedback = %u\n", haptic_config.feedback);
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c
index d645c379a..2975ef893 100644
--- a/drivers/haptic/solenoid.c
+++ b/drivers/haptic/solenoid.c
@@ -32,14 +32,6 @@ void solenoid_buzz_off(void) { haptic_set_buzz(0); }
32 32
33void solenoid_set_buzz(int buzz) { haptic_set_buzz(buzz); } 33void solenoid_set_buzz(int buzz) { haptic_set_buzz(buzz); }
34 34
35void solenoid_dwell_minus(uint8_t solenoid_dwell) {
36 if (solenoid_dwell > 0) solenoid_dwell--;
37}
38
39void solenoid_dwell_plus(uint8_t solenoid_dwell) {
40 if (solenoid_dwell < SOLENOID_MAX_DWELL) solenoid_dwell++;
41}
42
43void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; } 35void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; }
44 36
45void solenoid_stop(void) { 37void solenoid_stop(void) {
@@ -73,7 +65,7 @@ void solenoid_check(void) {
73 65
74 // Check whether to buzz the solenoid on and off 66 // Check whether to buzz the solenoid on and off
75 if (haptic_config.buzz) { 67 if (haptic_config.buzz) {
76 if (elapsed / SOLENOID_MIN_DWELL % 2 == 0) { 68 if ((elapsed % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) {
77 if (!solenoid_buzzing) { 69 if (!solenoid_buzzing) {
78 solenoid_buzzing = true; 70 solenoid_buzzing = true;
79 writePinHigh(SOLENOID_PIN); 71 writePinHigh(SOLENOID_PIN);
diff --git a/drivers/haptic/solenoid.h b/drivers/haptic/solenoid.h
index dd6ececa6..f2a3bc4c3 100644
--- a/drivers/haptic/solenoid.h
+++ b/drivers/haptic/solenoid.h
@@ -29,6 +29,22 @@
29# define SOLENOID_MIN_DWELL 4 29# define SOLENOID_MIN_DWELL 4
30#endif 30#endif
31 31
32#ifndef SOLENOID_DWELL_STEP_SIZE
33# define SOLENOID_DWELL_STEP_SIZE 1
34#endif
35
36#ifndef SOLENOID_DEFAULT_BUZZ
37# define SOLENOID_DEFAULT_BUZZ 0
38#endif
39
40#ifndef SOLENOID_BUZZ_ACTUATED
41# define SOLENOID_BUZZ_ACTUATED SOLENOID_MIN_DWELL
42#endif
43
44#ifndef SOLENOID_BUZZ_NONACTUATED
45# define SOLENOID_BUZZ_NONACTUATED SOLENOID_MIN_DWELL
46#endif
47
32#ifndef SOLENOID_PIN 48#ifndef SOLENOID_PIN
33# error SOLENOID_PIN not defined 49# error SOLENOID_PIN not defined
34#endif 50#endif
@@ -37,8 +53,6 @@ void solenoid_buzz_on(void);
37void solenoid_buzz_off(void); 53void solenoid_buzz_off(void);
38void solenoid_set_buzz(int buzz); 54void solenoid_set_buzz(int buzz);
39 55
40void solenoid_dwell_minus(uint8_t solenoid_dwell);
41void solenoid_dwell_plus(uint8_t solenoid_dwell);
42void solenoid_set_dwell(uint8_t dwell); 56void solenoid_set_dwell(uint8_t dwell);
43 57
44void solenoid_stop(void); 58void solenoid_stop(void);
diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c
index ba11db1d2..53bb8ca3f 100644
--- a/drivers/oled/oled_driver.c
+++ b/drivers/oled/oled_driver.c
@@ -119,6 +119,9 @@ uint32_t oled_timeout;
119#if OLED_SCROLL_TIMEOUT > 0 119#if OLED_SCROLL_TIMEOUT > 0
120uint32_t oled_scroll_timeout; 120uint32_t oled_scroll_timeout;
121#endif 121#endif
122#if OLED_UPDATE_INTERVAL > 0
123uint16_t oled_update_timeout;
124#endif
122 125
123// Internal variables to reduce math instructions 126// Internal variables to reduce math instructions
124 127
@@ -468,8 +471,9 @@ void oled_write_raw_byte(const char data, uint16_t index) {
468} 471}
469 472
470void oled_write_raw(const char *data, uint16_t size) { 473void oled_write_raw(const char *data, uint16_t size) {
471 if (size > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE; 474 uint16_t cursor_start_index = oled_cursor - &oled_buffer[0];
472 for (uint16_t i = 0; i < size; i++) { 475 if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index;
476 for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
473 if (oled_buffer[i] == data[i]) continue; 477 if (oled_buffer[i] == data[i]) continue;
474 oled_buffer[i] = data[i]; 478 oled_buffer[i] = data[i];
475 oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE)); 479 oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
@@ -511,8 +515,9 @@ void oled_write_ln_P(const char *data, bool invert) {
511} 515}
512 516
513void oled_write_raw_P(const char *data, uint16_t size) { 517void oled_write_raw_P(const char *data, uint16_t size) {
514 if (size > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE; 518 uint16_t cursor_start_index = oled_cursor - &oled_buffer[0];
515 for (uint16_t i = 0; i < size; i++) { 519 if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index;
520 for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
516 uint8_t c = pgm_read_byte(data++); 521 uint8_t c = pgm_read_byte(data++);
517 if (oled_buffer[i] == c) continue; 522 if (oled_buffer[i] == c) continue;
518 oled_buffer[i] = c; 523 oled_buffer[i] = c;
@@ -650,9 +655,16 @@ void oled_task(void) {
650 return; 655 return;
651 } 656 }
652 657
658#if OLED_UPDATE_INTERVAL > 0
659 if (timer_elapsed(oled_update_timeout) >= OLED_UPDATE_INTERVAL) {
660 oled_update_timeout = timer_read();
661 oled_set_cursor(0, 0);
662 oled_task_user();
663 }
664#else
653 oled_set_cursor(0, 0); 665 oled_set_cursor(0, 0);
654
655 oled_task_user(); 666 oled_task_user();
667#endif
656 668
657#if OLED_SCROLL_TIMEOUT > 0 669#if OLED_SCROLL_TIMEOUT > 0
658 if (oled_dirty && oled_scrolling) { 670 if (oled_dirty && oled_scrolling) {