aboutsummaryrefslogtreecommitdiff
path: root/platforms/avr
diff options
context:
space:
mode:
Diffstat (limited to 'platforms/avr')
-rw-r--r--platforms/avr/drivers/spi_master.c84
-rw-r--r--platforms/avr/drivers/spi_master.h9
-rw-r--r--platforms/avr/drivers/ws2812_bitbang.c52
-rw-r--r--platforms/avr/drivers/ws2812_i2c.c22
-rw-r--r--platforms/avr/timer.c19
5 files changed, 129 insertions, 57 deletions
diff --git a/platforms/avr/drivers/spi_master.c b/platforms/avr/drivers/spi_master.c
index 74b847c71a..ba7d782ab0 100644
--- a/platforms/avr/drivers/spi_master.c
+++ b/platforms/avr/drivers/spi_master.c
@@ -36,9 +36,18 @@
# define SPI_TIMEOUT 100
#endif
-static pin_t currentSlavePin = NO_PIN;
-static uint8_t currentSlaveConfig = 0;
-static bool currentSlave2X = false;
+static pin_t current_slave_pin = NO_PIN;
+static bool current_cs_active_low = true;
+static uint8_t current_slave_config = 0;
+static bool current_slave_2x = false;
+
+static inline void spi_select(void) {
+ gpio_write_pin(current_slave_pin, current_cs_active_low ? 0 : 1);
+}
+
+static inline void spi_unselect(void) {
+ gpio_write_pin(current_slave_pin, current_cs_active_low ? 1 : 0);
+}
void spi_init(void) {
gpio_write_pin_high(SPI_SS_PIN);
@@ -50,63 +59,74 @@ void spi_init(void) {
}
bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
- if (currentSlavePin != NO_PIN || slavePin == NO_PIN) {
+ spi_start_config_t start_config = {0};
+ start_config.slave_pin = slavePin;
+ start_config.lsb_first = lsbFirst;
+ start_config.mode = mode;
+ start_config.divisor = divisor;
+ start_config.cs_active_low = true;
+ return spi_start_extended(&start_config);
+}
+
+bool spi_start_extended(spi_start_config_t *start_config) {
+ if (current_slave_pin != NO_PIN || start_config->slave_pin == NO_PIN) {
return false;
}
- currentSlaveConfig = 0;
+ current_slave_config = 0;
- if (lsbFirst) {
- currentSlaveConfig |= _BV(DORD);
+ if (start_config->lsb_first) {
+ current_slave_config |= _BV(DORD);
}
- switch (mode) {
+ switch (start_config->mode) {
case 1:
- currentSlaveConfig |= _BV(CPHA);
+ current_slave_config |= _BV(CPHA);
break;
case 2:
- currentSlaveConfig |= _BV(CPOL);
+ current_slave_config |= _BV(CPOL);
break;
case 3:
- currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA));
+ current_slave_config |= (_BV(CPOL) | _BV(CPHA));
break;
}
uint16_t roundedDivisor = 1;
- while (roundedDivisor < divisor) {
+ while (roundedDivisor < start_config->divisor) {
roundedDivisor <<= 1;
}
switch (roundedDivisor) {
case 16:
- currentSlaveConfig |= _BV(SPR0);
+ current_slave_config |= _BV(SPR0);
break;
case 64:
- currentSlaveConfig |= _BV(SPR1);
+ current_slave_config |= _BV(SPR1);
break;
case 128:
- currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0));
+ current_slave_config |= (_BV(SPR1) | _BV(SPR0));
break;
case 2:
- currentSlave2X = true;
+ current_slave_2x = true;
break;
case 8:
- currentSlave2X = true;
- currentSlaveConfig |= _BV(SPR0);
+ current_slave_2x = true;
+ current_slave_config |= _BV(SPR0);
break;
case 32:
- currentSlave2X = true;
- currentSlaveConfig |= _BV(SPR1);
+ current_slave_2x = true;
+ current_slave_config |= _BV(SPR1);
break;
}
- SPCR |= currentSlaveConfig;
- if (currentSlave2X) {
+ SPCR |= current_slave_config;
+ if (current_slave_2x) {
SPSR |= _BV(SPI2X);
}
- currentSlavePin = slavePin;
- gpio_set_pin_output(currentSlavePin);
- gpio_write_pin_low(currentSlavePin);
+ current_slave_pin = start_config->slave_pin;
+ current_cs_active_low = start_config->cs_active_low;
+ gpio_set_pin_output(current_slave_pin);
+ spi_select();
return true;
}
@@ -168,13 +188,13 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) {
}
void spi_stop(void) {
- if (currentSlavePin != NO_PIN) {
- gpio_set_pin_output(currentSlavePin);
- gpio_write_pin_high(currentSlavePin);
- currentSlavePin = NO_PIN;
+ if (current_slave_pin != NO_PIN) {
+ gpio_set_pin_output(current_slave_pin);
+ spi_unselect();
+ current_slave_pin = NO_PIN;
SPSR &= ~(_BV(SPI2X));
- SPCR &= ~(currentSlaveConfig);
- currentSlaveConfig = 0;
- currentSlave2X = false;
+ SPCR &= ~(current_slave_config);
+ current_slave_config = 0;
+ current_slave_2x = false;
}
}
diff --git a/platforms/avr/drivers/spi_master.h b/platforms/avr/drivers/spi_master.h
index 8a30f47ae4..ebbf7ddeab 100644
--- a/platforms/avr/drivers/spi_master.h
+++ b/platforms/avr/drivers/spi_master.h
@@ -41,9 +41,18 @@ typedef int16_t spi_status_t;
#ifdef __cplusplus
extern "C" {
#endif
+typedef struct spi_start_config_t {
+ pin_t slave_pin;
+ bool lsb_first;
+ uint8_t mode;
+ uint16_t divisor;
+ bool cs_active_low;
+} spi_start_config_t;
+
void spi_init(void);
bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor);
+bool spi_start_extended(spi_start_config_t *start_config);
spi_status_t spi_write(uint8_t data);
diff --git a/platforms/avr/drivers/ws2812_bitbang.c b/platforms/avr/drivers/ws2812_bitbang.c
index be127e501c..183690c967 100644
--- a/platforms/avr/drivers/ws2812_bitbang.c
+++ b/platforms/avr/drivers/ws2812_bitbang.c
@@ -29,28 +29,6 @@
#define pinmask(pin) (_BV((pin)&0xF))
/*
- * Forward declare internal functions
- *
- * The functions take a byte-array and send to the data output as WS2812 bitstream.
- * The length is the number of bytes to send - three per LED.
- */
-
-static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi);
-
-void ws2812_init(void) {
- DDRx_ADDRESS(WS2812_DI_PIN) |= pinmask(WS2812_DI_PIN);
-}
-
-void ws2812_setleds(rgb_led_t *ledarray, uint16_t number_of_leds) {
- uint8_t masklo = ~(pinmask(WS2812_DI_PIN)) & PORTx_ADDRESS(WS2812_DI_PIN);
- uint8_t maskhi = pinmask(WS2812_DI_PIN) | PORTx_ADDRESS(WS2812_DI_PIN);
-
- ws2812_sendarray_mask((uint8_t *)ledarray, number_of_leds * sizeof(rgb_led_t), masklo, maskhi);
-
- _delay_us(WS2812_TRST_US);
-}
-
-/*
This routine writes an array of bytes with RGB values to the Dataout pin
using the fast 800kHz clockless WS2811/2812 protocol.
*/
@@ -172,3 +150,33 @@ static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t
SREG = sreg_prev;
}
+
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
+void ws2812_init(void) {
+ DDRx_ADDRESS(WS2812_DI_PIN) |= pinmask(WS2812_DI_PIN);
+}
+
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ ws2812_leds[index].r = red;
+ ws2812_leds[index].g = green;
+ ws2812_leds[index].b = blue;
+#if defined(WS2812_RGBW)
+ ws2812_rgb_to_rgbw(&ws2812_leds[index]);
+#endif
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+ for (int i = 0; i < WS2812_LED_COUNT; i++) {
+ ws2812_set_color(i, red, green, blue);
+ }
+}
+
+void ws2812_flush(void) {
+ uint8_t masklo = ~(pinmask(WS2812_DI_PIN)) & PORTx_ADDRESS(WS2812_DI_PIN);
+ uint8_t maskhi = pinmask(WS2812_DI_PIN) | PORTx_ADDRESS(WS2812_DI_PIN);
+
+ ws2812_sendarray_mask((uint8_t *)ws2812_leds, WS2812_LED_COUNT * sizeof(ws2812_led_t), masklo, maskhi);
+
+ _delay_us(WS2812_TRST_US);
+}
diff --git a/platforms/avr/drivers/ws2812_i2c.c b/platforms/avr/drivers/ws2812_i2c.c
index 86a5ac8394..e6b922f4bf 100644
--- a/platforms/avr/drivers/ws2812_i2c.c
+++ b/platforms/avr/drivers/ws2812_i2c.c
@@ -1,3 +1,6 @@
+// Copyright 2024 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include "ws2812.h"
#include "i2c_master.h"
@@ -13,11 +16,24 @@
# define WS2812_I2C_TIMEOUT 100
#endif
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
void ws2812_init(void) {
i2c_init();
}
-// Setleds for standard RGB
-void ws2812_setleds(rgb_led_t *ledarray, uint16_t leds) {
- i2c_transmit(WS2812_I2C_ADDRESS, (uint8_t *)ledarray, sizeof(rgb_led_t) * leds, WS2812_I2C_TIMEOUT);
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ ws2812_leds[index].r = red;
+ ws2812_leds[index].g = green;
+ ws2812_leds[index].b = blue;
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+ for (int i = 0; i < WS2812_LED_COUNT; i++) {
+ ws2812_set_color(i, red, green, blue);
+ }
+}
+
+void ws2812_flush(void) {
+ i2c_transmit(WS2812_I2C_ADDRESS, (uint8_t *)ws2812_leds, WS2812_LED_COUNT * sizeof(ws2812_led_t), WS2812_I2C_TIMEOUT);
}
diff --git a/platforms/avr/timer.c b/platforms/avr/timer.c
index 9fb671ae8d..26ba0e29fa 100644
--- a/platforms/avr/timer.c
+++ b/platforms/avr/timer.c
@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// counter resolution 1ms
// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
volatile uint32_t timer_count;
+static uint32_t saved_ms;
/** \brief timer initialization
*
@@ -78,6 +79,24 @@ inline void timer_clear(void) {
}
}
+/** \brief timer save
+ *
+ * Set saved_ms to current time.
+ */
+void timer_save(void) {
+ saved_ms = timer_read32();
+}
+
+/** \brief timer restore
+ *
+ * Set timer_count to saved_ms
+ */
+void timer_restore(void) {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ timer_count = saved_ms;
+ }
+}
+
/** \brief timer read
*
* FIXME: needs doc