summaryrefslogtreecommitdiff
path: root/platforms
diff options
context:
space:
mode:
authorNick Brassel <nick@tzarc.org>2024-02-28 21:47:37 +1100
committerNick Brassel <nick@tzarc.org>2024-02-28 21:47:37 +1100
commit4e369d405af6bba1adce6337b2e1b1ea1788566c (patch)
treeb0f020feff1809e37c9e7795d344929ff0bb290a /platforms
parent4e04da397ef643f8fcf4afbe1d19f63aee1fc561 (diff)
parentdd1706e468bb18dd7f7ae143de735a5d3be1bfb8 (diff)
Merge branch 'develop'
Diffstat (limited to 'platforms')
-rw-r--r--platforms/arm_atsam/gpio.h24
-rw-r--r--platforms/avr/_print.h7
-rw-r--r--platforms/avr/drivers/audio_pwm_hardware.c4
-rw-r--r--platforms/avr/drivers/backlight_pwm.c6
-rw-r--r--platforms/avr/drivers/i2c_master.c39
-rw-r--r--platforms/avr/drivers/i2c_master.h22
-rw-r--r--platforms/avr/drivers/ps2/ps2_io.c20
-rw-r--r--platforms/avr/drivers/serial.c10
-rw-r--r--platforms/avr/drivers/spi_master.c16
-rw-r--r--platforms/avr/gpio.h22
-rw-r--r--platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h28
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_G431XB/configs/hal_lld.h8
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_G431XB/configs/stm32_registry.h14
-rw-r--r--platforms/chibios/boards/QMK_BLOK/configs/config.h24
-rw-r--r--platforms/chibios/boards/QMK_PM2040/configs/config.h24
-rw-r--r--platforms/chibios/chibios_config.h14
-rw-r--r--platforms/chibios/converters/promicro_to_imera/_pin_defs.h36
-rw-r--r--platforms/chibios/converters/promicro_to_imera/converter.mk10
-rw-r--r--platforms/chibios/drivers/analog.c111
-rw-r--r--platforms/chibios/drivers/audio_dac.h34
-rw-r--r--platforms/chibios/drivers/audio_dac_additive.c48
-rw-r--r--platforms/chibios/drivers/audio_pwm_hardware.c8
-rw-r--r--platforms/chibios/drivers/i2c_master.c47
-rw-r--r--platforms/chibios/drivers/i2c_master.h18
-rw-r--r--platforms/chibios/drivers/serial.c12
-rw-r--r--platforms/chibios/drivers/spi_master.c14
-rw-r--r--platforms/chibios/drivers/uart.c70
-rw-r--r--platforms/chibios/drivers/uart.h194
-rw-r--r--platforms/chibios/drivers/uart_serial.c65
-rw-r--r--platforms/chibios/drivers/uart_sio.c77
-rw-r--r--platforms/chibios/drivers/ws2812_bitbang.c23
-rw-r--r--platforms/chibios/drivers/ws2812_pwm.c3
-rw-r--r--platforms/chibios/gpio.h34
-rw-r--r--platforms/chibios/platform.mk11
-rw-r--r--platforms/gpio.h19
35 files changed, 803 insertions, 313 deletions
diff --git a/platforms/arm_atsam/gpio.h b/platforms/arm_atsam/gpio.h
index a42aaff54d..fd8caeab0b 100644
--- a/platforms/arm_atsam/gpio.h
+++ b/platforms/arm_atsam/gpio.h
@@ -15,7 +15,7 @@
*/
#pragma once
-#include "stdint.h"
+#include <stdint.h>
#include "samd51j18a.h"
#include "pin_defs.h"
@@ -26,13 +26,13 @@ typedef uint8_t pin_t;
#define SAMD_PIN(pin) ((pin)&0x1f)
#define SAMD_PIN_MASK(pin) (1 << ((pin)&0x1f))
-#define setPinInput(pin) \
+#define gpio_set_pin_input(pin) \
do { \
PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \
PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
} while (0)
-#define setPinInputHigh(pin) \
+#define gpio_set_pin_input_high(pin) \
do { \
PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
@@ -40,7 +40,7 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \
} while (0)
-#define setPinInputLow(pin) \
+#define gpio_set_pin_input_low(pin) \
do { \
PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
@@ -48,27 +48,27 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \
} while (0)
-#define setPinOutputPushPull(pin) \
+#define gpio_set_pin_output_push_pull(pin) \
do { \
PORT->Group[SAMD_PORT(pin)].DIRSET.reg = SAMD_PIN_MASK(pin); \
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0)
-#define setPinOutputOpenDrain(pin) _Static_assert(0, "arm_atsam platform does not implement an open-drain output")
+#define gpio_set_pin_output_open_drain(pin) _Static_assert(0, "Open-drain outputs are not available on ATSAM")
-#define setPinOutput(pin) setPinOutputPushPull(pin)
+#define gpio_set_pin_output(pin) gpio_set_pin_output_push_pull(pin)
-#define writePinHigh(pin) \
+#define gpio_write_pin_high(pin) \
do { \
PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
} while (0)
-#define writePinLow(pin) \
+#define gpio_write_pin_low(pin) \
do { \
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0)
-#define writePin(pin, level) \
+#define gpio_write_pin(pin, level) \
do { \
if (level) \
PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
@@ -76,6 +76,6 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0)
-#define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0)
+#define gpio_read_pin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0)
-#define togglePin(pin) (PORT->Group[SAMD_PORT(pin)].OUTTGL.reg = SAMD_PIN_MASK(pin))
+#define gpio_toggle_pin(pin) (PORT->Group[SAMD_PORT(pin)].OUTTGL.reg = SAMD_PIN_MASK(pin))
diff --git a/platforms/avr/_print.h b/platforms/avr/_print.h
index 5c1fdd26d8..bf8247c2f3 100644
--- a/platforms/avr/_print.h
+++ b/platforms/avr/_print.h
@@ -24,10 +24,3 @@
#pragma once
#include "avr/xprintf.h"
-
-// Create user & normal print defines
-#define print(s) xputs(PSTR(s))
-#define println(s) xputs(PSTR(s "\r\n"))
-#define uprint(s) xputs(PSTR(s))
-#define uprintln(s) xputs(PSTR(s "\r\n"))
-#define uprintf(fmt, ...) __xprintf(PSTR(fmt), ##__VA_ARGS__) \ No newline at end of file
diff --git a/platforms/avr/drivers/audio_pwm_hardware.c b/platforms/avr/drivers/audio_pwm_hardware.c
index 6799cf2fdd..d484fba00f 100644
--- a/platforms/avr/drivers/audio_pwm_hardware.c
+++ b/platforms/avr/drivers/audio_pwm_hardware.c
@@ -216,12 +216,12 @@ void channel_2_stop(void) {
void audio_driver_initialize(void) {
#ifdef AUDIO1_PIN_SET
channel_1_stop();
- setPinOutput(AUDIO1_PIN);
+ gpio_set_pin_output(AUDIO1_PIN);
#endif
#ifdef AUDIO2_PIN_SET
channel_2_stop();
- setPinOutput(AUDIO2_PIN);
+ gpio_set_pin_output(AUDIO2_PIN);
#endif
// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B
diff --git a/platforms/avr/drivers/backlight_pwm.c b/platforms/avr/drivers/backlight_pwm.c
index 74d25753a4..f6ab9391e2 100644
--- a/platforms/avr/drivers/backlight_pwm.c
+++ b/platforms/avr/drivers/backlight_pwm.c
@@ -291,11 +291,11 @@ ISR(TIMERx_OVF_vect) {
#endif // BACKLIGHT_BREATHING
void backlight_init_ports(void) {
- setPinOutput(BACKLIGHT_PIN);
+ gpio_set_pin_output(BACKLIGHT_PIN);
#if BACKLIGHT_ON_STATE == 1
- writePinLow(BACKLIGHT_PIN);
+ gpio_write_pin_low(BACKLIGHT_PIN);
#else
- writePinHigh(BACKLIGHT_PIN);
+ gpio_write_pin_high(BACKLIGHT_PIN);
#endif
// I could write a wall of text here to explain... but TL;DW
diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c
index 58939f3e00..64083d862a 100644
--- a/platforms/avr/drivers/i2c_master.c
+++ b/platforms/avr/drivers/i2c_master.c
@@ -24,6 +24,7 @@
#include "timer.h"
#include "wait.h"
#include "util.h"
+#include "progmem.h"
#ifndef F_SCL
# define F_SCL 400000UL // SCL frequency
@@ -38,7 +39,7 @@
#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
-void i2c_init(void) {
+__attribute__((weak)) void i2c_init(void) {
TWSR = 0; /* no prescaler */
TWBR = (uint8_t)TWBR_val;
@@ -94,7 +95,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
return I2C_STATUS_SUCCESS;
}
-i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
+__attribute__((always_inline)) static inline i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
// Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
uint16_t timeout_timer = timer_read();
uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries
@@ -105,6 +106,11 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
return status;
}
+__attribute__((always_inline)) static inline void i2c_stop(void) {
+ // transmit STOP condition
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
+}
+
i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
// load data into data register
TWDR = data;
@@ -167,6 +173,18 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,
return status;
}
+i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
+ i2c_status_t status = i2c_start(address | I2C_ACTION_WRITE, timeout);
+
+ for (uint16_t i = 0; i < length && status >= 0; i++) {
+ status = i2c_write(pgm_read_byte((const char*)data++), timeout);
+ }
+
+ i2c_stop();
+
+ return status;
+}
+
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);
@@ -189,7 +207,7 @@ i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16
return (status < 0) ? status : I2C_STATUS_SUCCESS;
}
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
+i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
i2c_status_t status = i2c_start(devaddr | 0x00, timeout);
if (status >= 0) {
status = i2c_write(regaddr, timeout);
@@ -204,7 +222,7 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
return status;
}
-i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
+i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
i2c_status_t status = i2c_start(devaddr | 0x00, timeout);
if (status >= 0) {
status = i2c_write(regaddr >> 8, timeout);
@@ -223,7 +241,7 @@ i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* da
return status;
}
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
+i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
i2c_status_t status = i2c_start(devaddr, timeout);
if (status < 0) {
goto error;
@@ -256,7 +274,7 @@ error:
return (status < 0) ? status : I2C_STATUS_SUCCESS;
}
-i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
+i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
i2c_status_t status = i2c_start(devaddr, timeout);
if (status < 0) {
goto error;
@@ -293,7 +311,8 @@ error:
return (status < 0) ? status : I2C_STATUS_SUCCESS;
}
-void i2c_stop(void) {
- // transmit STOP condition
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
-}
+__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
+ i2c_status_t status = i2c_start(address, timeout);
+ i2c_stop();
+ return status;
+} \ No newline at end of file
diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h
index 04ef126c80..b797997619 100644
--- a/platforms/avr/drivers/i2c_master.h
+++ b/platforms/avr/drivers/i2c_master.h
@@ -21,6 +21,13 @@
#include <stdint.h>
+// ### DEPRECATED - DO NOT USE ###
+#define i2c_writeReg(devaddr, regaddr, data, length, timeout) i2c_write_register(devaddr, regaddr, data, length, timeout)
+#define i2c_writeReg16(devaddr, regaddr, data, length, timeout) i2c_write_register16(devaddr, regaddr, data, length, timeout)
+#define i2c_readReg(devaddr, regaddr, data, length, timeout) i2c_read_register(devaddr, regaddr, data, length, timeout)
+#define i2c_readReg16(devaddr, regaddr, data, length, timeout) i2c_read_register16(devaddr, regaddr, data, length, timeout)
+// ###############################
+
#define I2C_READ 0x01
#define I2C_WRITE 0x00
@@ -34,14 +41,11 @@ typedef int16_t i2c_status_t;
#define I2C_TIMEOUT_INFINITE (0xFFFF)
void i2c_init(void);
-i2c_status_t i2c_start(uint8_t address, uint16_t timeout);
-i2c_status_t i2c_write(uint8_t data, uint16_t timeout);
-int16_t i2c_read_ack(uint16_t timeout);
-int16_t i2c_read_nack(uint16_t timeout);
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-void i2c_stop(void);
+i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
diff --git a/platforms/avr/drivers/ps2/ps2_io.c b/platforms/avr/drivers/ps2/ps2_io.c
index b75a1ab0be..fb87474372 100644
--- a/platforms/avr/drivers/ps2/ps2_io.c
+++ b/platforms/avr/drivers/ps2/ps2_io.c
@@ -19,18 +19,18 @@ void clock_init(void) {}
void clock_lo(void) {
// Transition from input with pull-up to output low via Hi-Z instead of output high
- writePinLow(PS2_CLOCK_PIN);
- setPinOutput(PS2_CLOCK_PIN);
+ gpio_write_pin_low(PS2_CLOCK_PIN);
+ gpio_set_pin_output(PS2_CLOCK_PIN);
}
void clock_hi(void) {
- setPinInputHigh(PS2_CLOCK_PIN);
+ gpio_set_pin_input_high(PS2_CLOCK_PIN);
}
bool clock_in(void) {
- setPinInputHigh(PS2_CLOCK_PIN);
+ gpio_set_pin_input_high(PS2_CLOCK_PIN);
wait_us(1);
- return readPin(PS2_CLOCK_PIN);
+ return gpio_read_pin(PS2_CLOCK_PIN);
}
/*
@@ -40,16 +40,16 @@ void data_init(void) {}
void data_lo(void) {
// Transition from input with pull-up to output low via Hi-Z instead of output high
- writePinLow(PS2_DATA_PIN);
- setPinOutput(PS2_DATA_PIN);
+ gpio_write_pin_low(PS2_DATA_PIN);
+ gpio_set_pin_output(PS2_DATA_PIN);
}
void data_hi(void) {
- setPinInputHigh(PS2_DATA_PIN);
+ gpio_set_pin_input_high(PS2_DATA_PIN);
}
bool data_in(void) {
- setPinInputHigh(PS2_DATA_PIN);
+ gpio_set_pin_input_high(PS2_DATA_PIN);
wait_us(1);
- return readPin(PS2_DATA_PIN);
+ return gpio_read_pin(PS2_DATA_PIN);
}
diff --git a/platforms/avr/drivers/serial.c b/platforms/avr/drivers/serial.c
index 730d9b7a01..b529f9b45e 100644
--- a/platforms/avr/drivers/serial.c
+++ b/platforms/avr/drivers/serial.c
@@ -239,28 +239,28 @@ inline static void serial_delay_half2(void) {
inline static void serial_output(void) ALWAYS_INLINE;
inline static void serial_output(void) {
- setPinOutput(SOFT_SERIAL_PIN);
+ gpio_set_pin_output(SOFT_SERIAL_PIN);
}
// make the serial pin an input with pull-up resistor
inline static void serial_input_with_pullup(void) ALWAYS_INLINE;
inline static void serial_input_with_pullup(void) {
- setPinInputHigh(SOFT_SERIAL_PIN);
+ gpio_set_pin_input_high(SOFT_SERIAL_PIN);
}
inline static uint8_t serial_read_pin(void) ALWAYS_INLINE;
inline static uint8_t serial_read_pin(void) {
- return !!readPin(SOFT_SERIAL_PIN);
+ return !!gpio_read_pin(SOFT_SERIAL_PIN);
}
inline static void serial_low(void) ALWAYS_INLINE;
inline static void serial_low(void) {
- writePinLow(SOFT_SERIAL_PIN);
+ gpio_write_pin_low(SOFT_SERIAL_PIN);
}
inline static void serial_high(void) ALWAYS_INLINE;
inline static void serial_high(void) {
- writePinHigh(SOFT_SERIAL_PIN);
+ gpio_write_pin_high(SOFT_SERIAL_PIN);
}
void soft_serial_initiator_init(void) {
diff --git a/platforms/avr/drivers/spi_master.c b/platforms/avr/drivers/spi_master.c
index ae9df03c02..74b847c71a 100644
--- a/platforms/avr/drivers/spi_master.c
+++ b/platforms/avr/drivers/spi_master.c
@@ -41,10 +41,10 @@ static uint8_t currentSlaveConfig = 0;
static bool currentSlave2X = false;
void spi_init(void) {
- writePinHigh(SPI_SS_PIN);
- setPinOutput(SPI_SCK_PIN);
- setPinOutput(SPI_MOSI_PIN);
- setPinInput(SPI_MISO_PIN);
+ gpio_write_pin_high(SPI_SS_PIN);
+ gpio_set_pin_output(SPI_SCK_PIN);
+ gpio_set_pin_output(SPI_MOSI_PIN);
+ gpio_set_pin_input(SPI_MISO_PIN);
SPCR = (_BV(SPE) | _BV(MSTR));
}
@@ -105,8 +105,8 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
SPSR |= _BV(SPI2X);
}
currentSlavePin = slavePin;
- setPinOutput(currentSlavePin);
- writePinLow(currentSlavePin);
+ gpio_set_pin_output(currentSlavePin);
+ gpio_write_pin_low(currentSlavePin);
return true;
}
@@ -169,8 +169,8 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) {
void spi_stop(void) {
if (currentSlavePin != NO_PIN) {
- setPinOutput(currentSlavePin);
- writePinHigh(currentSlavePin);
+ gpio_set_pin_output(currentSlavePin);
+ gpio_write_pin_high(currentSlavePin);
currentSlavePin = NO_PIN;
SPSR &= ~(_BV(SPI2X));
SPCR &= ~(currentSlaveConfig);
diff --git a/platforms/avr/gpio.h b/platforms/avr/gpio.h
index 95f15c28dc..6f089bc663 100644
--- a/platforms/avr/gpio.h
+++ b/platforms/avr/gpio.h
@@ -22,17 +22,17 @@ typedef uint8_t pin_t;
/* Operation of GPIO by pin. */
-#define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
-#define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
-#define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low")
-#define setPinOutputPushPull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
-#define setPinOutputOpenDrain(pin) _Static_assert(0, "AVR platform does not implement an open-drain output")
-#define setPinOutput(pin) setPinOutputPushPull(pin)
+#define gpio_set_pin_input(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
+#define gpio_set_pin_input_high(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
+#define gpio_set_pin_input_low(pin) _Static_assert(0, "GPIO pulldowns in input mode are not available on AVR")
+#define gpio_set_pin_output_push_pull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
+#define gpio_set_pin_output_open_drain(pin) _Static_assert(0, "Open-drain outputs are not available on AVR")
+#define gpio_set_pin_output(pin) gpio_set_pin_output_push_pull(pin)
-#define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
-#define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
-#define writePin(pin, level) ((level) ? writePinHigh(pin) : writePinLow(pin))
+#define gpio_write_pin_high(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
+#define gpio_write_pin_low(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
+#define gpio_write_pin(pin, level) ((level) ? gpio_write_pin_high(pin) : gpio_write_pin_low(pin))
-#define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
+#define gpio_read_pin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
-#define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))
+#define gpio_toggle_pin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))
diff --git a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h
index 9209e99e76..73c2b40f46 100644
--- a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h
+++ b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h
@@ -1,4 +1,4 @@
-// Copyright 2022 Stefan Kerkmann
+// Copyright 2024 Stefan Kerkmann
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -56,7 +56,31 @@
#endif
/**======================
+ ** UART Driver
+ *========================**/
+
+#if !defined(UART_DRIVER)
+# define UART_DRIVER SIOD0
+#endif
+
+#if !defined(UART_TX_PIN)
+# define UART_TX_PIN GP0
+#endif
+
+#if !defined(UART_RX_PIN)
+# define UART_RX_PIN GP1
+#endif
+
+#if !defined(UART_CTS_PIN)
+# define UART_CTS_PIN GP2
+#endif
+
+#if !defined(UART_RTS_PIN)
+# define UART_RTS_PIN GP3
+#endif
+
+/**======================
** Double-tap
*========================**/
-#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
diff --git a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/hal_lld.h b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/hal_lld.h
new file mode 100644
index 0000000000..15d7fbec0b
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/hal_lld.h
@@ -0,0 +1,8 @@
+// Copyright 2024 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+// TODO: Remove when upstream no longer requires patching
+#include <stm32_registry.h>
+
+#include_next <hal_lld.h>
diff --git a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/stm32_registry.h b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/stm32_registry.h
new file mode 100644
index 0000000000..766df5a78e
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/stm32_registry.h
@@ -0,0 +1,14 @@
+// Copyright 2024 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+// TODO: Remove when STM32_FLASH_SECTORS_PER_BANK fixed upstream
+#ifndef STM32_FLASH_SECTORS_PER_BANK
+# define STM32_FLASH_SECTORS_PER_BANK 64
+#endif
+
+#include_next <stm32_registry.h>
+
+// TODO: Remove when STM32_FLASH_NUMBER_OF_BANKS fixed upstream
+#undef STM32_FLASH_NUMBER_OF_BANKS
+#define STM32_FLASH_NUMBER_OF_BANKS 1
diff --git a/platforms/chibios/boards/QMK_BLOK/configs/config.h b/platforms/chibios/boards/QMK_BLOK/configs/config.h
index 168afb1fc4..834dc497d3 100644
--- a/platforms/chibios/boards/QMK_BLOK/configs/config.h
+++ b/platforms/chibios/boards/QMK_BLOK/configs/config.h
@@ -3,6 +3,10 @@
#pragma once
+/**======================
+ ** I2C Driver
+ *========================**/
+
#ifndef I2C_DRIVER
# define I2C_DRIVER I2CD0
#endif
@@ -13,6 +17,26 @@
# define I2C1_SCL_PIN D0
#endif
+/**======================
+ ** UART Driver
+ *========================**/
+
+#ifndef UART_DRIVER
+# define UART_DRIVER SIOD0
+#endif
+
+#ifndef UART_TX_PIN
+# define UART_TX_PIN D3
+#endif
+
+#ifndef UART_RX_PIN
+# define UART_RX_PIN D2
+#endif
+
+/**======================
+ ** Double-tap
+ *========================**/
+
#ifndef RP2040_BOOTLOADER_DOUBLE_TAP_RESET
# define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
#endif
diff --git a/platforms/chibios/boards/QMK_PM2040/configs/config.h b/platforms/chibios/boards/QMK_PM2040/configs/config.h
index ec85ae0cf4..f8b46b7fe4 100644
--- a/platforms/chibios/boards/QMK_PM2040/configs/config.h
+++ b/platforms/chibios/boards/QMK_PM2040/configs/config.h
@@ -3,6 +3,10 @@
#pragma once
+/**======================
+ ** I2C Driver
+ *========================**/
+
#ifndef I2C_DRIVER
# define I2C_DRIVER I2CD1
#endif
@@ -13,6 +17,26 @@
# define I2C1_SCL_PIN D0
#endif
+/**======================
+ ** UART Driver
+ *========================**/
+
+#ifndef UART_DRIVER
+# define UART_DRIVER SIOD0
+#endif
+
+#ifndef UART_TX_PIN
+# define UART_TX_PIN D3
+#endif
+
+#ifndef UART_RX_PIN
+# define UART_RX_PIN D2
+#endif
+
+/**======================
+ ** Double-tap
+ *========================**/
+
#ifndef RP2040_BOOTLOADER_DOUBLE_TAP_RESET
# define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
#endif
diff --git a/platforms/chibios/chibios_config.h b/platforms/chibios/chibios_config.h
index f1636f9da0..759ac6943b 100644
--- a/platforms/chibios/chibios_config.h
+++ b/platforms/chibios/chibios_config.h
@@ -69,6 +69,20 @@
# ifndef SPI_MISO_PAL_MODE
# define SPI_MISO_PAL_MODE (PAL_MODE_ALTERNATE_SPI | PAL_RP_PAD_SLEWFAST | PAL_RP_PAD_DRIVE4)
# endif
+
+# ifndef UART_TX_PAL_MODE
+# define UART_TX_PAL_MODE PAL_MODE_ALTERNATE_UART
+# endif
+# ifndef UART_RX_PAL_MODE
+# define UART_RX_PAL_MODE PAL_MODE_ALTERNATE_UART
+# endif
+# ifndef UART_CTS_PAL_MODE
+# define UART_CTS_PAL_MODE PAL_MODE_ALTERNATE_UART
+# endif
+# ifndef UART_RTS_PAL_MODE
+# define UART_RTS_PAL_MODE PAL_MODE_ALTERNATE_UART
+# endif
+
#endif
// STM32 compatibility
diff --git a/platforms/chibios/converters/promicro_to_imera/_pin_defs.h b/platforms/chibios/converters/promicro_to_imera/_pin_defs.h
new file mode 100644
index 0000000000..475a84d697
--- /dev/null
+++ b/platforms/chibios/converters/promicro_to_imera/_pin_defs.h
@@ -0,0 +1,36 @@
+// Copyright 2023 splitkb.com
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+// Left side (front)
+#define D3 0U
+#define D2 1U
+// GND
+// GND
+#define D1 2U
+#define D0 3U
+#define D4 4U
+#define C6 5U
+#define D7 6U
+#define E6 7U
+#define B4 8U
+#define B5 9U
+
+// Right side (front)
+// RAW
+// GND
+// RESET
+// VCC
+#define F4 29U
+#define F5 28U
+#define F6 17U
+#define F7 16U
+#define B1 22U
+#define B3 20U
+#define B2 23U
+#define B6 21U
+
+// LEDs
+#define D5 24U // Power LED, default-on
+#define B0 18U // Unconnected
diff --git a/platforms/chibios/converters/promicro_to_imera/converter.mk b/platforms/chibios/converters/promicro_to_imera/converter.mk
new file mode 100644
index 0000000000..bfca20cd99
--- /dev/null
+++ b/platforms/chibios/converters/promicro_to_imera/converter.mk
@@ -0,0 +1,10 @@
+# rp2040_ce MCU settings for converting AVR projects
+MCU := RP2040
+BOARD := QMK_PM2040
+BOOTLOADER := rp2040
+
+# These are defaults based on what has been implemented for RP2040 boards
+SERIAL_DRIVER ?= vendor
+WS2812_DRIVER ?= vendor
+BACKLIGHT_DRIVER ?= software
+OPT_DEFS += -DUSB_VBUS_PIN=19U
diff --git a/platforms/chibios/drivers/analog.c b/platforms/chibios/drivers/analog.c
index bf84ce8f76..fb146df936 100644
--- a/platforms/chibios/drivers/analog.c
+++ b/platforms/chibios/drivers/analog.c
@@ -31,7 +31,15 @@
#endif
#if STM32_ADCV3_OVERSAMPLING
-# error "STM32 ADCV3 Oversampling is not supported at this time."
+// Apparently all ADCV3 chips that support oversampling (STM32L4xx, STM32L4xx+,
+// STM32G4xx, STM32WB[35]x) have errata like “Wrong ADC result if conversion
+// done late after calibration or previous conversion”; the workaround is to
+// perform a dummy conversion and discard its result. STM32G4xx chips also
+// have the “ADC channel 0 converted instead of the required ADC channel”
+// errata, one workaround for which is also to perform a dummy conversion.
+# define ADC_DUMMY_CONVERSIONS_AT_START 1
+#else
+# define ADC_DUMMY_CONVERSIONS_AT_START 0
#endif
// Otherwise assume V3
@@ -76,8 +84,10 @@
#ifndef ADC_COUNT
# if defined(RP2040) || defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx)
# define ADC_COUNT 1
-# elif defined(STM32F3XX)
+# elif defined(STM32F3XX) || defined(STM32G4XX)
# define ADC_COUNT 4
+# elif defined(STM32L4XX)
+# define ADC_COUNT 3
# else
# error "ADC_COUNT has not been set for this ARM microcontroller."
# endif
@@ -89,13 +99,24 @@
# error "The ARM ADC implementation currently only supports reading one channel at a time."
#endif
+// Add dummy conversions as extra channels (this would work only on chips that
+// have multiple channel index fields instead of a channel mask, but all chips
+// that need that workaround are like that).
+#define ADC_TOTAL_CHANNELS (ADC_DUMMY_CONVERSIONS_AT_START + ADC_NUM_CHANNELS)
+
#ifndef ADC_BUFFER_DEPTH
# define ADC_BUFFER_DEPTH 1
#endif
// For more sampling rate options, look at hal_adc_lld.h in ChibiOS
-#ifndef ADC_SAMPLING_RATE
-# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5
+#if !defined(ADC_SAMPLING_RATE) && !defined(RP2040)
+# if defined(ADC_SMPR_SMP_1P5)
+# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5
+# elif defined(ADC_SMPR_SMP_2P5) // STM32L4XX, STM32L4XXP, STM32G4XX, STM32WBXX
+# define ADC_SAMPLING_RATE ADC_SMPR_SMP_2P5
+# else
+# error "Cannot determine the default ADC_SAMPLING_RATE for this MCU."
+# endif
#endif
// Options are 12, 10, 8, and 6 bit.
@@ -108,7 +129,7 @@
#endif
static ADCConfig adcCfg = {};
-static adcsample_t sampleBuffer[ADC_NUM_CHANNELS * ADC_BUFFER_DEPTH];
+static adcsample_t sampleBuffer[ADC_TOTAL_CHANNELS * ADC_BUFFER_DEPTH];
// Initialize to max number of ADCs, set to empty object to initialize all to false.
static bool adcInitialized[ADC_COUNT] = {};
@@ -116,7 +137,7 @@ static bool adcInitialized[ADC_COUNT] = {};
// TODO: add back TR handling???
static ADCConversionGroup adcConversionGroup = {
.circular = FALSE,
- .num_channels = (uint16_t)(ADC_NUM_CHANNELS),
+ .num_channels = (uint16_t)(ADC_TOTAL_CHANNELS),
#if defined(USE_ADCV1)
.cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
.smpr = ADC_SAMPLING_RATE,
@@ -240,6 +261,74 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) {
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.
+#elif defined(STM32L4XX)
+ case A0: return TO_MUX( ADC_CHANNEL_IN5, 0 ); // Can also be ADC2 in some cases
+ case A1: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2 in some cases
+ case A2: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2
+ case A3: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2
+ case A4: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2
+ case A5: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2
+ case A6: return TO_MUX( ADC_CHANNEL_IN11, 0 ); // Can also be ADC2
+ case A7: return TO_MUX( ADC_CHANNEL_IN12, 0 ); // Can also be ADC2
+ case B0: return TO_MUX( ADC_CHANNEL_IN15, 0 ); // Can also be ADC2
+ case B1: return TO_MUX( ADC_CHANNEL_IN16, 0 ); // Can also be ADC2
+ case C0: return TO_MUX( ADC_CHANNEL_IN1, 0 ); // Can also be ADC2 or ADC3
+ case C1: return TO_MUX( ADC_CHANNEL_IN2, 0 ); // Can also be ADC2 or ADC3
+ case C2: return TO_MUX( ADC_CHANNEL_IN3, 0 ); // Can also be ADC2 or ADC3
+ case C3: return TO_MUX( ADC_CHANNEL_IN4, 0 ); // Can also be ADC2 or ADC3
+ case C4: return TO_MUX( ADC_CHANNEL_IN13, 0 ); // Can also be ADC2
+ case C5: return TO_MUX( ADC_CHANNEL_IN14, 0 ); // Can also be ADC2
+# if STM32_HAS_GPIOF && STM32_ADC_USE_ADC3
+ case F3: return TO_MUX( ADC_CHANNEL_IN6, 2 );
+ case F4: return TO_MUX( ADC_CHANNEL_IN7, 2 );
+ case F5: return TO_MUX( ADC_CHANNEL_IN8, 2 );
+ case F6: return TO_MUX( ADC_CHANNEL_IN9, 2 );
+ case F7: return TO_MUX( ADC_CHANNEL_IN10, 2 );
+ case F8: return TO_MUX( ADC_CHANNEL_IN11, 2 );
+ case F9: return TO_MUX( ADC_CHANNEL_IN12, 2 );
+ case F10: return TO_MUX( ADC_CHANNEL_IN13, 2 );
+# endif
+#elif defined(STM32G4XX)
+ case A0: return TO_MUX( ADC_CHANNEL_IN1, 0 ); // Can also be ADC2
+ case A1: return TO_MUX( ADC_CHANNEL_IN2, 0 ); // Can also be ADC2
+ case A2: return TO_MUX( ADC_CHANNEL_IN3, 0 );
+ case A3: return TO_MUX( ADC_CHANNEL_IN4, 0 );
+ case A4: return TO_MUX( ADC_CHANNEL_IN17, 1 );
+ case A5: return TO_MUX( ADC_CHANNEL_IN13, 1 );
+ case A6: return TO_MUX( ADC_CHANNEL_IN3, 1 );
+ case A7: return TO_MUX( ADC_CHANNEL_IN4, 1 );
+ case B0: return TO_MUX( ADC_CHANNEL_IN15, 0 ); // Can also be ADC3
+ case B1: return TO_MUX( ADC_CHANNEL_IN12, 0 ); // Can also be ADC3
+ case B2: return TO_MUX( ADC_CHANNEL_IN12, 1 );
+ case B11: return TO_MUX( ADC_CHANNEL_IN14, 0 ); // Can also be ADC2
+ case B12: return TO_MUX( ADC_CHANNEL_IN11, 0 ); // Can also be ADC4
+ case B13: return TO_MUX( ADC_CHANNEL_IN5, 2 );
+ case B14: return TO_MUX( ADC_CHANNEL_IN5, 0 ); // Can also be ADC4
+ case B15: return TO_MUX( ADC_CHANNEL_IN15, 1 ); // Can also be ADC4
+ case C0: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2
+ case C1: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2
+ case C2: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2
+ case C3: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2
+ case C4: return TO_MUX( ADC_CHANNEL_IN5, 1 );
+ case C5: return TO_MUX( ADC_CHANNEL_IN11, 1 );
+ case D8: return TO_MUX( ADC_CHANNEL_IN12, 3 );
+ case D9: return TO_MUX( ADC_CHANNEL_IN13, 3 );
+ case D10: return TO_MUX( ADC_CHANNEL_IN7, 2 ); // Can also be ADC4
+ case D11: return TO_MUX( ADC_CHANNEL_IN8, 2 ); // Can also be ADC4
+ case D12: return TO_MUX( ADC_CHANNEL_IN9, 2 ); // Can also be ADC4
+ case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4
+ case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4
+ case E5: return TO_MUX( ADC_CHANNEL_IN2, 3 );
+ case E7: return TO_MUX( ADC_CHANNEL_IN4, 2 );
+ case E8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); // Can also be ADC4
+ case E9: return TO_MUX( ADC_CHANNEL_IN2, 2 );
+ case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 ); // Can also be ADC4
+ case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 ); // Can also be ADC4
+ case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 ); // Can also be ADC4
+ case E13: return TO_MUX( ADC_CHANNEL_IN3, 2 );
+ case E14: return TO_MUX( ADC_CHANNEL_IN1, 3 );
+ case F0: return TO_MUX( ADC_CHANNEL_IN10, 0 );
+ case F1: return TO_MUX( ADC_CHANNEL_IN10, 1 );
#elif defined(RP2040)
case 26U: return TO_MUX(0, 0);
case 27U: return TO_MUX(1, 0);
@@ -306,7 +395,11 @@ int16_t adc_read(adc_mux mux) {
#elif defined(RP2040)
adcConversionGroup.channel_mask = 1 << mux.input;
#else
- adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input);
+ adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input)
+# if ADC_DUMMY_CONVERSIONS_AT_START >= 1
+ | ADC_SQR1_SQ2_N(mux.input)
+# endif
+ ;
#endif
ADCDriver* targetDriver = intToADCDriver(mux.adc);
@@ -321,9 +414,9 @@ int16_t adc_read(adc_mux mux) {
#if defined(USE_ADCV2) || defined(RP2040)
// fake 12-bit -> N-bit scale
- return (*sampleBuffer) >> (12 - ADC_RESOLUTION);
+ return (sampleBuffer[ADC_DUMMY_CONVERSIONS_AT_START]) >> (12 - ADC_RESOLUTION);
#else
// already handled as part of adcConvert
- return *sampleBuffer;
+ return sampleBuffer[ADC_DUMMY_CONVERSIONS_AT_START];
#endif
}
diff --git a/platforms/chibios/drivers/audio_dac.h b/platforms/chibios/drivers/audio_dac.h
index 07cd622ead..2f62d12934 100644
--- a/platforms/chibios/drivers/audio_dac.h
+++ b/platforms/chibios/drivers/audio_dac.h
@@ -24,11 +24,6 @@
#endif
/**
- * Size of the dac_buffer arrays. All must be the same size.
- */
-#define AUDIO_DAC_BUFFER_SIZE 256U
-
-/**
* Highest value allowed sample value.
* since the DAC is limited to 12 bit, the absolute max is 0xfff = 4095U;
@@ -97,6 +92,35 @@
#endif
/**
+ * Size of the dac_buffer array. This controls the length of the runtime buffer
+ * which accumulates the data to be sent to the DAC every few milliseconds, and
+ * it does not need to correspond to the length of the wavetable for the chosen
+ * waveform defined by AUDIO_DAC_SAMPLE_WAVEFORM_* in the additive DAC driver.
+ * By default, this is set to be as close to 3.3 ms as possible, giving 300 DAC
+ * interrupts per second. Any smaller and the interrupt load gets too heavy and
+ * this results in crackling due to buffer underrun in the additive DAC driver;
+ * too large and the RAM (additive driver) or flash (basic driver) usage may be
+ * too high, causing build failures, and matrix scanning is liable to have long
+ * periodic pauses that delay key presses or releases or fully lose short taps.
+ * Large buffers also cause notes to take longer to stop after they should from
+ * music mode or MIDI input.
+ * This should be a power of 2 for maximum compatibility.
+ */
+#ifndef AUDIO_DAC_BUFFER_SIZE
+# if AUDIO_DAC_SAMPLE_RATE < 5100U
+# define AUDIO_DAC_BUFFER_SIZE 16U
+# elif AUDIO_DAC_SAMPLE_RATE < 9900U
+# define AUDIO_DAC_BUFFER_SIZE 32U
+# elif AUDIO_DAC_SAMPLE_RATE < 19500U
+# define AUDIO_DAC_BUFFER_SIZE 64U
+# elif AUDIO_DAC_SAMPLE_RATE < 38700U
+# define AUDIO_DAC_BUFFER_SIZE 128U
+# else
+# define AUDIO_DAC_BUFFER_SIZE 256U
+# endif
+#endif
+
+/**
* The number of tones that can be played simultaneously. If too high a value
* is used here, the keyboard will freeze and glitch-out when that many tones
* are being played.
diff --git a/platforms/chibios/drivers/audio_dac_additive.c b/platforms/chibios/drivers/audio_dac_additive.c
index 26e044b048..d6fde42b68 100644
--- a/platforms/chibios/drivers/audio_dac_additive.c
+++ b/platforms/chibios/drivers/audio_dac_additive.c
@@ -53,35 +53,39 @@
#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SINE
/* one full sine wave over [0,2*pi], but shifted up one amplitude and left pi/4; for the samples to start at 0
*/
-static const dacsample_t dac_buffer_sine[AUDIO_DAC_BUFFER_SIZE] = {
+static const dacsample_t dac_buffer_sine[] = {
// 256 values, max 4095
0x0, 0x1, 0x2, 0x6, 0xa, 0xf, 0x16, 0x1e, 0x27, 0x32, 0x3d, 0x4a, 0x58, 0x67, 0x78, 0x89, 0x9c, 0xb0, 0xc5, 0xdb, 0xf2, 0x10a, 0x123, 0x13e, 0x159, 0x175, 0x193, 0x1b1, 0x1d1, 0x1f1, 0x212, 0x235, 0x258, 0x27c, 0x2a0, 0x2c6, 0x2ed, 0x314, 0x33c, 0x365, 0x38e, 0x3b8, 0x3e3, 0x40e, 0x43a, 0x467, 0x494, 0x4c2, 0x4f0, 0x51f, 0x54e, 0x57d, 0x5ad, 0x5dd, 0x60e, 0x63f, 0x670, 0x6a1, 0x6d3, 0x705, 0x737, 0x769, 0x79b, 0x7cd, 0x800, 0x832, 0x864, 0x896, 0x8c8, 0x8fa, 0x92c, 0x95e, 0x98f, 0x9c0, 0x9f1, 0xa22, 0xa52, 0xa82, 0xab1, 0xae0, 0xb0f, 0xb3d, 0xb6b, 0xb98, 0xbc5, 0xbf1, 0xc1c, 0xc47, 0xc71, 0xc9a, 0xcc3, 0xceb, 0xd12, 0xd39, 0xd5f, 0xd83, 0xda7, 0xdca, 0xded, 0xe0e, 0xe2e, 0xe4e, 0xe6c, 0xe8a, 0xea6, 0xec1, 0xedc, 0xef5, 0xf0d, 0xf24, 0xf3a, 0xf4f, 0xf63, 0xf76, 0xf87, 0xf98, 0xfa7, 0xfb5, 0xfc2, 0xfcd, 0xfd8, 0xfe1, 0xfe9, 0xff0, 0xff5, 0xff9, 0xffd, 0xffe,
- 0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1};
+ 0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1,
+};
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SINE
#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE
-static const dacsample_t dac_buffer_triangle[AUDIO_DAC_BUFFER_SIZE] = {
+static const dacsample_t dac_buffer_triangle[] = {
// 256 values, max 4095
0x0, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4a0, 0x4c0, 0x4e0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5a0, 0x5c0, 0x5e0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6a0, 0x6c0, 0x6e0, 0x700, 0x720, 0x740, 0x760, 0x780, 0x7a0, 0x7c0, 0x7e0, 0x800, 0x81f, 0x83f, 0x85f, 0x87f, 0x89f, 0x8bf, 0x8df, 0x8ff, 0x91f, 0x93f, 0x95f, 0x97f, 0x99f, 0x9bf, 0x9df, 0x9ff, 0xa1f, 0xa3f, 0xa5f, 0xa7f, 0xa9f, 0xabf, 0xadf, 0xaff, 0xb1f, 0xb3f, 0xb5f, 0xb7f, 0xb9f, 0xbbf, 0xbdf, 0xbff, 0xc1f, 0xc3f, 0xc5f, 0xc7f, 0xc9f, 0xcbf, 0xcdf, 0xcff, 0xd1f, 0xd3f, 0xd5f, 0xd7f, 0xd9f, 0xdbf, 0xddf, 0xdff, 0xe1f, 0xe3f, 0xe5f, 0xe7f, 0xe9f, 0xebf, 0xedf, 0xeff, 0xf1f, 0xf3f, 0xf5f, 0xf7f, 0xf9f, 0xfbf, 0xfdf,
- 0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20};
+ 0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20,
+};
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE
#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE
-static const dacsample_t dac_buffer_square[AUDIO_DAC_BUFFER_SIZE] = {
- [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = AUDIO_DAC_OFF_VALUE, // first and
- [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, // second half
+static const dacsample_t dac_buffer_square[] = {
+ AUDIO_DAC_OFF_VALUE, // first and
+ AUDIO_DAC_SAMPLE_MAX, // second steps
};
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE
/*
// four steps: 0, 1/3, 2/3 and 1
-static const dacsample_t dac_buffer_staircase[AUDIO_DAC_BUFFER_SIZE] = {
- [0 ... AUDIO_DAC_BUFFER_SIZE/3 -1 ] = 0,
- [AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE / 2 -1 ] = AUDIO_DAC_SAMPLE_MAX / 3,
- [AUDIO_DAC_BUFFER_SIZE / 2 ... 3 * AUDIO_DAC_BUFFER_SIZE / 4 -1 ] = 2 * AUDIO_DAC_SAMPLE_MAX / 3,
- [3 * AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE -1 ] = AUDIO_DAC_SAMPLE_MAX,
+static const dacsample_t dac_buffer_staircase[] = {
+ 0,
+ AUDIO_DAC_SAMPLE_MAX / 3,
+ 2 * AUDIO_DAC_SAMPLE_MAX / 3,
+ AUDIO_DAC_SAMPLE_MAX,
}
*/
#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID
-static const dacsample_t dac_buffer_trapezoid[AUDIO_DAC_BUFFER_SIZE] = {0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
- 0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+static const dacsample_t dac_buffer_trapezoid[] = {
+ 0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID
static dacsample_t dac_buffer[AUDIO_DAC_BUFFER_SIZE];
@@ -124,20 +128,30 @@ __attribute__((weak)) uint16_t dac_value_generate(void) {
uint_fast16_t value = 0;
float frequency = 0.0f;
+#if defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE)
+ const size_t wavetable_length = ARRAY_SIZE(dac_buffer_sine);
+#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE)
+ const size_t wavetable_length = ARRAY_SIZE(dac_buffer_triangle);
+#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID)
+ const size_t wavetable_length = ARRAY_SIZE(dac_buffer_trapezoid);
+#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE)
+ const size_t wavetable_length = ARRAY_SIZE(dac_buffer_square);
+#endif
+
for (size_t i = 0; i < active_tones_snapshot_length; i++) {
/* Note: a user implementation does not have to rely on the active_tones_snapshot, but
* could directly query the active frequencies through audio_get_processed_frequency */
frequency = active_tones_snapshot[i];
float new_dac_if = dac_if[i];
- new_dac_if += frequency * ((float)AUDIO_DAC_BUFFER_SIZE / AUDIO_DAC_SAMPLE_RATE * 2.0f / 3.0f);
+ new_dac_if += frequency * ((float)wavetable_length / AUDIO_DAC_SAMPLE_RATE * 2.0f / 3.0f);
/*Note: the 2/3 are necessary to get the correct frequencies on the
* DAC output (as measured with an oscilloscope), since the gpt
* timer runs with 3*AUDIO_DAC_SAMPLE_RATE; and the DAC callback
* is called twice per conversion.*/
- while (new_dac_if >= AUDIO_DAC_BUFFER_SIZE)
- new_dac_if -= AUDIO_DAC_BUFFER_SIZE;
+ while (new_dac_if >= wavetable_length)
+ new_dac_if -= wavetable_length;
dac_if[i] = new_dac_if;
// Wavetable generation/lookup
diff --git a/platforms/chibios/drivers/audio_pwm_hardware.c b/platforms/chibios/drivers/audio_pwm_hardware.c
index 40d891326f..21b5c6892c 100644
--- a/platforms/chibios/drivers/audio_pwm_hardware.c
+++ b/platforms/chibios/drivers/audio_pwm_hardware.c
@@ -22,6 +22,12 @@
# define AUDIO_PWM_COUNTER_FREQUENCY 100000
#endif
+#ifndef AUDIO_PWM_COMPLEMENTARY_OUTPUT
+# define AUDIO_PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH
+#else
+# define AUDIO_PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH
+#endif
+
extern bool playing_note;
extern bool playing_melody;
extern uint8_t note_timbre;
@@ -29,7 +35,7 @@ extern uint8_t note_timbre;
static PWMConfig pwmCFG = {.frequency = AUDIO_PWM_COUNTER_FREQUENCY, /* PWM clock frequency */
.period = 2,
.callback = NULL,
- .channels = {[(AUDIO_PWM_CHANNEL - 1)] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}}};
+ .channels = {[(AUDIO_PWM_CHANNEL - 1)] = {.mode = AUDIO_PWM_OUTPUT_MODE, .callback = NULL}}};
static float channel_1_frequency = 0.0f;
diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c
index 7c49f9d005..ad11d850dd 100644
--- a/platforms/chibios/drivers/i2c_master.c
+++ b/platforms/chibios/drivers/i2c_master.c
@@ -1,5 +1,6 @@
/* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
+ * Copyright 2023 customMK
*
* 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
@@ -90,8 +91,6 @@
# endif
#endif
-static uint8_t i2c_address;
-
static const I2CConfig i2cconfig = {
#if defined(USE_I2CV1_CONTRIB)
I2C1_CLOCK_SPEED,
@@ -125,7 +124,7 @@ static i2c_status_t i2c_epilogue(const msg_t status) {
// From ChibiOS HAL: "After a timeout the driver must be stopped and
// restarted because the bus is in an uncertain state." We also issue that
// hard stop in case of any error.
- i2c_stop();
+ i2cStop(&I2C_DRIVER);
return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR;
}
@@ -150,28 +149,19 @@ __attribute__((weak)) void i2c_init(void) {
}
}
-i2c_status_t i2c_start(uint8_t address) {
- i2c_address = address;
- i2cStart(&I2C_DRIVER, &i2cconfig);
- return I2C_STATUS_SUCCESS;
-}
-
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = address;
i2cStart(&I2C_DRIVER, &i2cconfig);
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
+ msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
return i2c_epilogue(status);
}
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = address;
i2cStart(&I2C_DRIVER, &i2cconfig);
- msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout));
+ msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (address >> 1), data, length, TIME_MS2I(timeout));
return i2c_epilogue(status);
}
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = devaddr;
+i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
i2cStart(&I2C_DRIVER, &i2cconfig);
uint8_t complete_packet[length + 1];
@@ -180,12 +170,11 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
}
complete_packet[0] = regaddr;
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
+ msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
return i2c_epilogue(status);
}
-i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = devaddr;
+i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
i2cStart(&I2C_DRIVER, &i2cconfig);
uint8_t complete_packet[length + 2];
@@ -195,25 +184,27 @@ i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* da
complete_packet[0] = regaddr >> 8;
complete_packet[1] = regaddr & 0xFF;
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
+ msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
return i2c_epilogue(status);
}
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = devaddr;
+i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
i2cStart(&I2C_DRIVER, &i2cconfig);
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout));
+ msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout));
return i2c_epilogue(status);
}
-i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = devaddr;
+i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
i2cStart(&I2C_DRIVER, &i2cconfig);
uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
+ msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
return i2c_epilogue(status);
}
-void i2c_stop(void) {
- i2cStop(&I2C_DRIVER);
-}
+__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
+ // ChibiOS does not provide low level enough control to check for an ack.
+ // Best effort instead tries reading register 0 which will either succeed or timeout.
+ // This approach may produce false negative results for I2C devices that do not respond to a register 0 read request.
+ uint8_t data = 0;
+ return i2c_readReg(address, 0, &data, sizeof(data), timeout);
+} \ No newline at end of file
diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h
index deee7ecc08..132ffd14c0 100644
--- a/platforms/chibios/drivers/i2c_master.h
+++ b/platforms/chibios/drivers/i2c_master.h
@@ -26,6 +26,13 @@
#include <stdint.h>
+// ### DEPRECATED - DO NOT USE ###
+#define i2c_writeReg(devaddr, regaddr, data, length, timeout) i2c_write_register(devaddr, regaddr, data, length, timeout)
+#define i2c_writeReg16(devaddr, regaddr, data, length, timeout) i2c_write_register16(devaddr, regaddr, data, length, timeout)
+#define i2c_readReg(devaddr, regaddr, data, length, timeout) i2c_read_register(devaddr, regaddr, data, length, timeout)
+#define i2c_readReg16(devaddr, regaddr, data, length, timeout) i2c_read_register16(devaddr, regaddr, data, length, timeout)
+// ###############################
+
typedef int16_t i2c_status_t;
#define I2C_STATUS_SUCCESS (0)
@@ -33,11 +40,10 @@ typedef int16_t i2c_status_t;
#define I2C_STATUS_TIMEOUT (-2)
void i2c_init(void);
-i2c_status_t i2c_start(uint8_t address);
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-void i2c_stop(void);
+i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
diff --git a/platforms/chibios/drivers/serial.c b/platforms/chibios/drivers/serial.c
index f199716a2b..fa8481d2dc 100644
--- a/platforms/chibios/drivers/serial.c
+++ b/platforms/chibios/drivers/serial.c
@@ -62,25 +62,25 @@ inline static void serial_delay_blip(void) {
wait_us(1);
}
inline static void serial_output(void) {
- setPinOutput(SOFT_SERIAL_PIN);
+ gpio_set_pin_output(SOFT_SERIAL_PIN);
}
inline static void serial_input(void) {
- setPinInputHigh(SOFT_SERIAL_PIN);
+ gpio_set_pin_input_high(SOFT_SERIAL_PIN);
}
inline static bool serial_read_pin(void) {
- return !!readPin(SOFT_SERIAL_PIN);
+ return !!gpio_read_pin(SOFT_SERIAL_PIN);
}
inline static void serial_low(void) {
- writePinLow(SOFT_SERIAL_PIN);
+ gpio_write_pin_low(SOFT_SERIAL_PIN);
}
inline static void serial_high(void) {
- writePinHigh(SOFT_SERIAL_PIN);
+ gpio_write_pin_high(SOFT_SERIAL_PIN);
}
void interrupt_handler(void *arg);
// Use thread + palWaitLineTimeout instead of palSetLineCallback
-// - Methods like setPinOutput and palEnableLineEvent/palDisableLineEvent
+// - Methods like gpio_set_pin_output and palEnableLineEvent/palDisableLineEvent
// cause the interrupt to lock up, which would limit to only receiving data...
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {
diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c
index 481a2e422a..57fc53d49f 100644
--- a/platforms/chibios/drivers/spi_master.c
+++ b/platforms/chibios/drivers/spi_master.c
@@ -32,12 +32,12 @@ __attribute__((weak)) void spi_init(void) {
is_initialised = true;
// Try releasing special pins for a short time
- setPinInput(SPI_SCK_PIN);
+ gpio_set_pin_input(SPI_SCK_PIN);
if (SPI_MOSI_PIN != NO_PIN) {
- setPinInput(SPI_MOSI_PIN);
+ gpio_set_pin_input(SPI_MOSI_PIN);
}
if (SPI_MISO_PIN != NO_PIN) {
- setPinInput(SPI_MISO_PIN);
+ gpio_set_pin_input(SPI_MISO_PIN);
}
chThdSleepMilliseconds(10);
@@ -271,10 +271,10 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
#if SPI_SELECT_MODE == SPI_SELECT_MODE_PAD
spiConfig.ssport = PAL_PORT(slavePin);
spiConfig.sspad = PAL_PAD(slavePin);
- setPinOutput(slavePin);
+ gpio_set_pin_output(slavePin);
#elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
if (slavePin != NO_PIN) {
- setPinOutput(slavePin);
+ gpio_set_pin_output(slavePin);
}
#else
# error "Unsupported SPI_SELECT_MODE"
@@ -284,7 +284,7 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
spiSelect(&SPI_DRIVER);
#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
if (slavePin != NO_PIN) {
- writePinLow(slavePin);
+ gpio_write_pin_low(slavePin);
}
#endif
@@ -319,7 +319,7 @@ void spi_stop(void) {
if (spiStarted) {
#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
if (currentSlavePin != NO_PIN) {
- writePinHigh(currentSlavePin);
+ gpio_write_pin_high(currentSlavePin);
}
#endif
spiUnselect(&SPI_DRIVER);
diff --git a/platforms/chibios/drivers/uart.c b/platforms/chibios/drivers/uart.c
deleted file mode 100644
index 39a59dd445..0000000000
--- a/platforms/chibios/drivers/uart.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright 2021
- *
- * 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 <https://www.gnu.org/licenses/>.
- */
-
-#include "uart.h"
-
-#if defined(MCU_KINETIS)
-static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE};
-#elif defined(WB32F3G71xx) || defined(WB32FQ95xx)
-static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_WRDLEN, SD1_STPBIT, SD1_PARITY, SD1_ATFLCT};
-#else
-static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_CR1, SD1_CR2, SD1_CR3};
-#endif
-
-void uart_init(uint32_t baud) {
- static bool is_initialised = false;
-
- if (!is_initialised) {
- is_initialised = true;
-
-#if defined(MCU_KINETIS)
- serialConfig.sc_speed = baud;
-#else
- serialConfig.speed = baud;
-#endif
-
-#if defined(USE_GPIOV1)
- palSetLineMode(SD1_TX_PIN, SD1_TX_PAL_MODE);
- palSetLineMode(SD1_RX_PIN, SD1_RX_PAL_MODE);
-#else
- palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
- palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
-#endif
- sdStart(&SERIAL_DRIVER, &serialConfig);
- }
-}
-
-void uart_write(uint8_t data) {
- sdPut(&SERIAL_DRIVER, data);
-}
-
-uint8_t uart_read(void) {
- msg_t res = sdGet(&SERIAL_DRIVER);
-
- return (uint8_t)res;
-}
-
-void uart_transmit(const uint8_t *data, uint16_t length) {
- sdWrite(&SERIAL_DRIVER, data, length);
-}
-
-void uart_receive(uint8_t *data, uint16_t length) {
- sdRead(&SERIAL_DRIVER, data, length);
-}
-
-bool uart_available(void) {
- return !sdGetWouldBlock(&SERIAL_DRIVER);
-}
diff --git a/platforms/chibios/drivers/uart.h b/platforms/chibios/drivers/uart.h
index 16983072ce..c1945575f1 100644
--- a/platforms/chibios/drivers/uart.h
+++ b/platforms/chibios/drivers/uart.h
@@ -1,18 +1,7 @@
-/* Copyright 2021
- *
- * 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 <https://www.gnu.org/licenses/>.
- */
+// Copyright 2024 Stefan Kerkmann
+// Copyright 2021 QMK
+// Copyright 2024 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -24,93 +13,188 @@
#include "gpio.h"
#include "chibios_config.h"
-#ifndef SERIAL_DRIVER
-# define SERIAL_DRIVER SD1
+// ======== DEPRECATED DEFINES - DO NOT USE ========
+#ifdef SERIAL_DRIVER
+# define UART_DRIVER SERIAL_DRIVER
+#endif
+#ifdef SD1_TX_PIN
+# define UART_TX_PIN SD1_TX_PIN
+#endif
+#ifdef SD1_RX_PIN
+# define UART_RX_PIN SD1_RX_PIN
+#endif
+#ifdef SD1_CTS_PIN
+# define UART_CTS_PIN SD1_CTS_PIN
+#endif
+#ifdef SD1_RTS_PIN
+# define UART_RTS_PIN SD1_RTS_PIN
+#endif
+#ifdef SD1_TX_PAL_MODE
+# define UART_TX_PAL_MODE SD1_TX_PAL_MODE
+#endif
+#ifdef SD1_RX_PAL_MODE
+# define UART_RX_PAL_MODE SD1_RX_PAL_MODE
+#endif
+#ifdef SD1_CTS_PAL_MODE
+# define UART_RTS_PAL_MODE SD1_CTS_PAL_MODE
+#endif
+#ifdef SD1_RTS_PAL_MODE
+# define UART_TX_PAL_MODE SD1_RTS_PAL_MODE
+#endif
+#ifdef SD1_CR1
+# define UART_CR1 SD1_CR1
+#endif
+#ifdef SD1_CR2
+# define UART_CR2 SD1_CR2
+#endif
+#ifdef SD1_CR3
+# define UART_CR3 SD1_CR3
+#endif
+#ifdef SD1_WRDLEN
+# define UART_WRDLEN SD1_WRDLEN
+#endif
+#ifdef SD1_STPBIT
+# define UART_STPBIT SD1_STPBIT
+#endif
+#ifdef SD1_PARITY
+# define UART_PARITY SD1_PARITY
+#endif
+#ifdef SD1_ATFLCT
+# define UART_ATFLCT SD1_ATFLCT
+#endif
+// ========
+
+#ifndef UART_DRIVER
+# if (HAL_USE_SERIAL == TRUE)
+# define UART_DRIVER SD1
+# elif (HAL_USE_SIO == TRUE)
+# define UART_DRIVER SIOD1
+# endif
#endif
-#ifndef SD1_TX_PIN
-# define SD1_TX_PIN A9
+#ifndef UART_TX_PIN
+# define UART_TX_PIN A9
#endif
-#ifndef SD1_RX_PIN
-# define SD1_RX_PIN A10
+#ifndef UART_RX_PIN
+# define UART_RX_PIN A10
#endif
-#ifndef SD1_CTS_PIN
-# define SD1_CTS_PIN A11
+#ifndef UART_CTS_PIN
+# define UART_CTS_PIN A11
#endif
-#ifndef SD1_RTS_PIN
-# define SD1_RTS_PIN A12
+#ifndef UART_RTS_PIN
+# define UART_RTS_PIN A12
#endif
#ifdef USE_GPIOV1
-# ifndef SD1_TX_PAL_MODE
-# define SD1_TX_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
+# ifndef UART_TX_PAL_MODE
+# define UART_TX_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
# endif
-# ifndef SD1_RX_PAL_MODE
-# define SD1_RX_PAL_MODE PAL_MODE_INPUT
+# ifndef UART_RX_PAL_MODE
+# define UART_RX_PAL_MODE PAL_MODE_INPUT
# endif
-# ifndef SD1_CTS_PAL_MODE
-# define SD1_CTS_PAL_MODE PAL_MODE_INPUT
+# ifndef UART_CTS_PAL_MODE
+# define UART_CTS_PAL_MODE PAL_MODE_INPUT
# endif
-# ifndef SD1_RTS_PAL_MODE
-# define SD1_RTS_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
+# ifndef UART_RTS_PAL_MODE
+# define UART_RTS_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
# endif
#else
-# ifndef SD1_TX_PAL_MODE
-# define SD1_TX_PAL_MODE 7
+# ifndef UART_TX_PAL_MODE
+# define UART_TX_PAL_MODE 7
# endif
-# ifndef SD1_RX_PAL_MODE
-# define SD1_RX_PAL_MODE 7
+# ifndef UART_RX_PAL_MODE
+# define UART_RX_PAL_MODE 7
# endif
-# ifndef SD1_CTS_PAL_MODE
-# define SD1_CTS_PAL_MODE 7
+# ifndef UART_CTS_PAL_MODE
+# define UART_CTS_PAL_MODE 7
# endif
-# ifndef SD1_RTS_PAL_MODE
-# define SD1_RTS_PAL_MODE 7
+# ifndef UART_RTS_PAL_MODE
+# define UART_RTS_PAL_MODE 7
# endif
#endif
-#ifndef SD1_CR1
-# define SD1_CR1 0
+#ifndef UART_CR1
+# define UART_CR1 0
#endif
-#ifndef SD1_CR2
-# define SD1_CR2 0
+#ifndef UART_CR2
+# define UART_CR2 0
#endif
-#ifndef SD1_CR3
-# define SD1_CR3 0
+#ifndef UART_CR3
+# define UART_CR3 0
#endif
-#ifndef SD1_WRDLEN
-# define SD1_WRDLEN 3
+#ifndef UART_WRDLEN
+# define UART_WRDLEN 3
#endif
-#ifndef SD1_STPBIT
-# define SD1_STPBIT 0
+#ifndef UART_STPBIT
+# define UART_STPBIT 0
#endif
-#ifndef SD1_PARITY
-# define SD1_PARITY 0
+#ifndef UART_PARITY
+# define UART_PARITY 0
#endif
-#ifndef SD1_ATFLCT
-# define SD1_ATFLCT 0
+#ifndef UART_ATFLCT
+# define UART_ATFLCT 0
#endif
+/**
+ * @brief Initialize the UART driver. This function must be called only once,
+ * before any of the below functions can be called.
+ *
+ * @param baud The baud rate to transmit and receive at. This may depend on the
+ * device you are communicating with. Common values are 1200, 2400, 4800, 9600,
+ * 19200, 38400, 57600, and 115200.
+ */
void uart_init(uint32_t baud);
+/**
+ * @brief Transmit a single byte.
+ *
+ * @param data The byte to transmit.
+ */
void uart_write(uint8_t data);
+/**
+ * @brief Receive a single byte.
+ *
+ * @return uint8_t The byte read from the receive buffer. This function will
+ * block if the buffer is empty (ie. no data to read).
+ */
uint8_t uart_read(void);
+/**
+ * @brief Transmit multiple bytes.
+ *
+ * @param data A pointer to the data to write from.
+ * @param length The number of bytes to write. Take care not to overrun the
+ * length of `data`.
+ */
void uart_transmit(const uint8_t *data, uint16_t length);
+/**
+ * @brief Receive multiple bytes.
+ *
+ * @param data A pointer to the buffer to read into.
+ * @param length The number of bytes to read. Take care not to overrun the
+ * length of `data`.
+ */
void uart_receive(uint8_t *data, uint16_t length);
+/**
+ * @brief Return whether the receive buffer contains data. Call this function
+ * to determine if `uart_read()` will return data immediately.
+ *
+ * @return true If there is data available to read.
+ * @return false If there is no data available to read.
+ */
bool uart_available(void);
diff --git a/platforms/chibios/drivers/uart_serial.c b/platforms/chibios/drivers/uart_serial.c
new file mode 100644
index 0000000000..6aff4eae47
--- /dev/null
+++ b/platforms/chibios/drivers/uart_serial.c
@@ -0,0 +1,65 @@
+// Copyright 2024 Stefan Kerkmann (@KarlK90)
+// Copyright 2021 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "uart.h"
+
+#if defined(MCU_KINETIS)
+static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE};
+#elif defined(WB32F3G71xx) || defined(WB32FQ95xx)
+static SerialConfig serialConfig = {
+ SERIAL_DEFAULT_BITRATE, UART_WRDLEN, UART_STPBIT, UART_PARITY, UART_ATFLCT,
+};
+#else
+static SerialConfig serialConfig = {
+ SERIAL_DEFAULT_BITRATE,
+ UART_CR1,
+ UART_CR2,
+ UART_CR3,
+};
+#endif
+
+void uart_init(uint32_t baud) {
+ static bool is_initialised = false;
+
+ if (is_initialised) {
+ return;
+ }
+ is_initialised = true;
+
+#if defined(MCU_KINETIS)
+ serialConfig.sc_speed = baud;
+#else
+ serialConfig.speed = baud;
+#endif
+
+#if defined(USE_GPIOV1)
+ palSetLineMode(UART_TX_PIN, UART_TX_PAL_MODE);
+ palSetLineMode(UART_RX_PIN, UART_RX_PAL_MODE);
+#else
+ palSetLineMode(UART_TX_PIN, PAL_MODE_ALTERNATE(UART_TX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
+ palSetLineMode(UART_RX_PIN, PAL_MODE_ALTERNATE(UART_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
+#endif
+
+ sdStart(&UART_DRIVER, &serialConfig);
+}
+
+void uart_write(uint8_t data) {
+ sdPut(&UART_DRIVER, data);
+}
+
+uint8_t uart_read(void) {
+ return (uint8_t)sdGet(&UART_DRIVER);
+}
+
+void uart_transmit(const uint8_t *data, uint16_t length) {
+ sdWrite(&UART_DRIVER, data, length);
+}
+
+void uart_receive(uint8_t *data, uint16_t length) {
+ sdRead(&UART_DRIVER, data, length);
+}
+
+bool uart_available(void) {
+ return !sdGetWouldBlock(&UART_DRIVER);
+}
diff --git a/platforms/chibios/drivers/uart_sio.c b/platforms/chibios/drivers/uart_sio.c
new file mode 100644
index 0000000000..ebf51ae5a8
--- /dev/null
+++ b/platforms/chibios/drivers/uart_sio.c
@@ -0,0 +1,77 @@
+// Copyright 2024 Stefan Kerkmann (@KarlK90)
+// Copyright 2021 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "uart.h"
+
+#if defined(MCU_RP)
+// 38400 baud, 8 data bits, 1 stop bit, no parity, no flow control
+static SIOConfig sioConfig = {
+ .baud = SIO_DEFAULT_BITRATE,
+ .UARTLCR_H = (UART_UARTLCR_H_WLEN_8BITS | UART_UARTLCR_H_FEN),
+ .UARTCR = 0U,
+ .UARTIFLS = (UART_UARTIFLS_RXIFLSEL_1_8F | UART_UARTIFLS_TXIFLSEL_1_8E),
+ .UARTDMACR = 0U,
+};
+#else
+static SIOConfig sioConfig = {
+ .baud = SIO_DEFAULT_BITRATE,
+# if defined(MCU_STM32) && defined(CHIBIOS_HAL_USARTv3)
+ .presc = USART_PRESC1,
+# endif
+ .cr1 = UART_CR1,
+ .cr2 = UART_CR2,
+ .cr3 = UART_CR3,
+};
+#endif
+
+void uart_init(uint32_t baud) {
+ static bool is_initialised = false;
+
+ if (is_initialised) {
+ return;
+ }
+ is_initialised = true;
+
+ sioConfig.baud = baud;
+
+#if defined(USE_GPIOV1)
+ palSetLineMode(UART_TX_PIN, UART_TX_PAL_MODE);
+ palSetLineMode(UART_RX_PIN, UART_RX_PAL_MODE);
+#else
+ palSetLineMode(UART_TX_PIN, PAL_MODE_ALTERNATE(UART_TX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
+ palSetLineMode(UART_RX_PIN, PAL_MODE_ALTERNATE(UART_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
+#endif
+
+ sioStart(&UART_DRIVER, &sioConfig);
+}
+
+void uart_write(uint8_t data) {
+ chnPutTimeout(&UART_DRIVER, data, TIME_INFINITE);
+}
+
+uint8_t uart_read(void) {
+ msg_t result = chnGetTimeout(&UART_DRIVER, TIME_INFINITE);
+
+ if (sioHasRXErrorsX(&UART_DRIVER)) {
+ sioGetAndClearErrors(&UART_DRIVER);
+ }
+
+ return (uint8_t)result;
+}
+
+void uart_transmit(const uint8_t *data, uint16_t length) {
+ chnWrite(&UART_DRIVER, data, length);
+}
+
+void uart_receive(uint8_t *data, uint16_t length) {
+ chnRead(&UART_DRIVER, data, length);
+
+ if (sioHasRXErrorsX(&UART_DRIVER)) {
+ sioGetAndClearErrors(&UART_DRIVER);
+ }
+}
+
+bool uart_available() {
+ return !sioIsRXEmptyX(&UART_DRIVER);
+}
diff --git a/platforms/chibios/drivers/ws2812_bitbang.c b/platforms/chibios/drivers/ws2812_bitbang.c
index 883a845d88..1ed87c4381 100644
--- a/platforms/chibios/drivers/ws2812_bitbang.c
+++ b/platforms/chibios/drivers/ws2812_bitbang.c
@@ -3,18 +3,23 @@
#include "gpio.h"
#include "chibios_config.h"
+// DEPRECATED - DO NOT USE
+#if defined(NOP_FUDGE)
+# define WS2812_BITBANG_NOP_FUDGE NOP_FUDGE
+#endif
+
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
-#ifndef NOP_FUDGE
+#ifndef WS2812_BITBANG_NOP_FUDGE
# if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(WB32F3G71xx) || defined(WB32FQ95xx)
-# define NOP_FUDGE 0.4
+# define WS2812_BITBANG_NOP_FUDGE 0.4
# else
# if defined(RP2040)
# error "Please use `vendor` WS2812 driver for RP2040"
# else
-# error "NOP_FUDGE configuration required"
+# error "WS2812_BITBANG_NOP_FUDGE configuration required"
# endif
-# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
+# define WS2812_BITBANG_NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
# endif
#endif
@@ -33,7 +38,7 @@
#endif
#define NUMBER_NOPS 6
-#define CYCLES_PER_SEC (CPU_CLOCK / NUMBER_NOPS * NOP_FUDGE)
+#define CYCLES_PER_SEC (CPU_CLOCK / NUMBER_NOPS * WS2812_BITBANG_NOP_FUDGE)
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
@@ -57,15 +62,15 @@ void sendByte(uint8_t byte) {
// using something like wait_ns(is_one ? T1L : T0L) here throws off timings
if (is_one) {
// 1
- writePinHigh(WS2812_DI_PIN);
+ gpio_write_pin_high(WS2812_DI_PIN);
wait_ns(WS2812_T1H);
- writePinLow(WS2812_DI_PIN);
+ gpio_write_pin_low(WS2812_DI_PIN);
wait_ns(WS2812_T1L);
} else {
// 0
- writePinHigh(WS2812_DI_PIN);
+ gpio_write_pin_high(WS2812_DI_PIN);
wait_ns(WS2812_T0H);
- writePinLow(WS2812_DI_PIN);
+ gpio_write_pin_low(WS2812_DI_PIN);
wait_ns(WS2812_T0L);
}
}
diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c
index 440687bd72..6bba22767f 100644
--- a/platforms/chibios/drivers/ws2812_pwm.c
+++ b/platforms/chibios/drivers/ws2812_pwm.c
@@ -48,9 +48,6 @@
#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
diff --git a/platforms/chibios/gpio.h b/platforms/chibios/gpio.h
index 80551abac5..a8d6554f29 100644
--- a/platforms/chibios/gpio.h
+++ b/platforms/chibios/gpio.h
@@ -22,24 +22,24 @@ typedef ioline_t pin_t;
/* Operation of GPIO by pin. */
-#define setPinInput(pin) palSetLineMode((pin), PAL_MODE_INPUT)
-#define setPinInputHigh(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLUP)
-#define setPinInputLow(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLDOWN)
-#define setPinOutputPushPull(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_PUSHPULL)
-#define setPinOutputOpenDrain(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_OPENDRAIN)
-#define setPinOutput(pin) setPinOutputPushPull(pin)
+#define gpio_set_pin_input(pin) palSetLineMode((pin), PAL_MODE_INPUT)
+#define gpio_set_pin_input_high(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLUP)
+#define gpio_set_pin_input_low(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLDOWN)
+#define gpio_set_pin_output_push_pull(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_PUSHPULL)
+#define gpio_set_pin_output_open_drain(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_OPENDRAIN)
+#define gpio_set_pin_output(pin) gpio_set_pin_output_push_pull(pin)
-#define writePinHigh(pin) palSetLine(pin)
-#define writePinLow(pin) palClearLine(pin)
-#define writePin(pin, level) \
- do { \
- if (level) { \
- writePinHigh(pin); \
- } else { \
- writePinLow(pin); \
- } \
+#define gpio_write_pin_high(pin) palSetLine(pin)
+#define gpio_write_pin_low(pin) palClearLine(pin)
+#define gpio_write_pin(pin, level) \
+ do { \
+ if (level) { \
+ gpio_write_pin_high(pin); \
+ } else { \
+ gpio_write_pin_low(pin); \
+ } \
} while (0)
-#define readPin(pin) palReadLine(pin)
+#define gpio_read_pin(pin) palReadLine(pin)
-#define togglePin(pin) palToggleLine(pin)
+#define gpio_toggle_pin(pin) palToggleLine(pin)
diff --git a/platforms/chibios/platform.mk b/platforms/chibios/platform.mk
index f38a888012..a2178412f3 100644
--- a/platforms/chibios/platform.mk
+++ b/platforms/chibios/platform.mk
@@ -330,6 +330,17 @@ ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes)
endif
#
+# Extract supported HAL drivers
+##############################################################################
+
+define add_lld_driver_define
+ $(eval driver := $(word 2,$(subst /LLD/, ,$(1))))
+ $(eval OPT_DEFS += -DCHIBIOS_HAL_$(driver))
+endef
+
+$(foreach dir,$(EXTRAINCDIRS),$(if $(findstring /LLD/,$(dir)),$(call add_lld_driver_define,$(dir))))
+
+#
# Project, sources and paths
##############################################################################
diff --git a/platforms/gpio.h b/platforms/gpio.h
index b47f6f8e43..6a87e75b01 100644
--- a/platforms/gpio.h
+++ b/platforms/gpio.h
@@ -19,4 +19,21 @@
#if __has_include_next("gpio.h")
# include_next "gpio.h" /* Include the platforms gpio.h */
-#endif \ No newline at end of file
+#endif
+
+// ======== DEPRECATED DEFINES - DO NOT USE ========
+
+#define setPinInput(pin) gpio_set_pin_input(pin)
+#define setPinInputHigh(pin) gpio_set_pin_input_high(pin)
+#define setPinInputLow(pin) gpio_set_pin_input_low(pin)
+#define setPinOutputPushPull(pin) gpio_set_pin_output_push_pull(pin)
+#define setPinOutputOpenDrain(pin) gpio_set_pin_output_open_drain(pin)
+#define setPinOutput(pin) gpio_set_pin_output_push_pull(pin)
+
+#define writePinHigh(pin) gpio_write_pin_high(pin)
+#define writePinLow(pin) gpio_write_pin_low(pin)
+#define writePin(pin, level) gpio_write_pin(pin, level)
+
+#define readPin(pin) gpio_read_pin(pin)
+
+#define togglePin(pin) gpio_toggle_pin(pin)