Music Synth Controller Design
Set compact rounded-rectangle board size and 4-layer stackup
Place components by functional block without routing traces
Review placement for overlaps and airwires-only expected DRC
Table
| Function | STM32 pin | Direction | Notes |
|---|---|---|---|
| QSPI NCS | PB10 | AF output | APS6404L CE# |
| QSPI CLK | PB2 | AF output | APS6404L SCLK |
| QSPI IO0 | PD11 | AF bidir | APS6404L SI/SIO0 |
| QSPI IO1 | PD12 | AF bidir | APS6404L SO/SIO1 |
| QSPI IO2 | PE2 | AF bidir | APS6404L SIO2 |
| QSPI IO3 | PD13 | AF bidir | APS6404L SIO3 |
| Audio MCLK | PA8 | AF output | PCM3060 SCKI1/SCKI2 |
| Audio BCLK | PE5 | AF output | PCM3060 BCK1/BCK2 |
| Audio LRCLK | PE4 | AF output | PCM3060 LRCK1/LRCK2 |
| Audio DAC DIN | PE6 | AF output | PCM3060 DIN |
| Audio ADC DOUT | PE3 | AF input | PCM3060 DOUT |
| Codec reset | PD3 | GPIO output | Active-low reset |
| Pot 1 ADC | PC0 | ADC input | 1 kΩ + 100 nF filter |
| Pot 2 ADC | PC1 | ADC input | 1 kΩ + 100 nF filter |
| Pot 3 ADC | PA0 | ADC input | 1 kΩ + 100 nF filter |
| Button 1 | PB12 | GPIO input | External pull-up, active-low |
| Button 2 | PB13 | GPIO input | External pull-up, active-low |
| LEDs green | PE7, PE8, PE9 | GPIO output | Active-high through 680 Ω |
| LEDs yellow | PE10, PE11 | GPIO output | Active-high through 680 Ω |
| LEDs red | PE12, PE13, PE14 | GPIO output | Active-high through 680 Ω |
| USB FS D- | PA11 | AF | USB connector through 22 Ω |
| USB FS D+ | PA12 | AF | USB connector through 22 Ω |
C
#include "main.h" #include <string.h> ADC_HandleTypeDef hadc1; SAI_HandleTypeDef hsai_BlockA1; QSPI_HandleTypeDef hqspi; #define LED_G1_Pin GPIO_PIN_7 #define LED_G2_Pin GPIO_PIN_8 #define LED_G3_Pin GPIO_PIN_9 #define LED_Y1_Pin GPIO_PIN_10 #define LED_Y2_Pin GPIO_PIN_11 #define LED_R1_Pin GPIO_PIN_12 #define LED_R2_Pin GPIO_PIN_13 #define LED_R3_Pin GPIO_PIN_14 #define LED_GPIO_Port GPIOE #define BTN1_Pin GPIO_PIN_12 #define BTN2_Pin GPIO_PIN_13 #define BTN_GPIO_Port GPIOB #define CODEC_RST_Pin GPIO_PIN_3 #define CODEC_RST_Port GPIOD static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); HAL_GPIO_WritePin(CODEC_RST_Port, CODEC_RST_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_G1_Pin|LED_G2_Pin|LED_G3_Pin|LED_Y1_Pin|LED_Y2_Pin|LED_R1_Pin|LED_R2_Pin|LED_R3_Pin, GPIO_PIN_RESET); GPIO_InitStruct.Pin = LED_G1_Pin|LED_G2_Pin|LED_G3_Pin|LED_Y1_Pin|LED_Y2_Pin|LED_R1_Pin|LED_R2_Pin|LED_R3_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = BTN1_Pin|BTN2_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; // external pull-ups are fitted HAL_GPIO_Init(BTN_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = CODEC_RST_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(CODEC_RST_Port, &GPIO_InitStruct); } static void codec_reset_release(void) { HAL_GPIO_WritePin(CODEC_RST_Port, CODEC_RST_Pin, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(CODEC_RST_Port, CODEC_RST_Pin, GPIO_PIN_SET); HAL_Delay(10); } uint16_t read_adc_channel(uint32_t channel) { ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = channel; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5; HAL_ADC_ConfigChannel(&hadc1, &sConfig); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 10); uint16_t value = (uint16_t)HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); return value; } void update_leds(uint16_t pot1, uint16_t pot2, uint16_t pot3) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_G1_Pin, pot1 > 512 ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_G2_Pin, pot1 > 2048 ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_G3_Pin, pot1 > 3584 ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_Y1_Pin, pot2 > 1024 ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_Y2_Pin, pot2 > 3072 ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_R1_Pin, pot3 > 1024 ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_R2_Pin, pot3 > 2048 ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GPIO_Port, LED_R3_Pin, pot3 > 3072 ? GPIO_PIN_SET : GPIO_PIN_RESET); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_QUADSPI_Init(); MX_SAI1_Init(); codec_reset_release(); while (1) { uint16_t pot1 = read_adc_channel(ADC_CHANNEL_10); // PC0 uint16_t pot2 = read_adc_channel(ADC_CHANNEL_11); // PC1 uint16_t pot3 = read_adc_channel(ADC_CHANNEL_16); // PA0 update_leds(pot1, pot2, pot3); GPIO_PinState b1 = HAL_GPIO_ReadPin(BTN_GPIO_Port, BTN1_Pin); GPIO_PinState b2 = HAL_GPIO_ReadPin(BTN_GPIO_Port, BTN2_Pin); (void)b1; (void)b2; HAL_Delay(5); } }
Platform and Toolchain
Pin Mapping
Complete Starter Source
Bring-Up Notes