summaryrefslogtreecommitdiff
path: root/platforms
diff options
context:
space:
mode:
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_STM32_G431XB/configs/hal_lld.h8
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_G431XB/configs/stm32_registry.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/ws2812_bitbang.c8
-rw-r--r--platforms/chibios/drivers/ws2812_pwm.c3
-rw-r--r--platforms/chibios/gpio.h34
-rw-r--r--platforms/gpio.h19
26 files changed, 413 insertions, 181 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_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/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/ws2812_bitbang.c b/platforms/chibios/drivers/ws2812_bitbang.c
index 883a845d88..593377068b 100644
--- a/platforms/chibios/drivers/ws2812_bitbang.c
+++ b/platforms/chibios/drivers/ws2812_bitbang.c
@@ -57,15 +57,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/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)