diff --git a/boards/arm/stm32l4/nucleo-l432kc/Kconfig b/boards/arm/stm32l4/nucleo-l432kc/Kconfig index 353f988d0fa..7ed758a07d7 100644 --- a/boards/arm/stm32l4/nucleo-l432kc/Kconfig +++ b/boards/arm/stm32l4/nucleo-l432kc/Kconfig @@ -141,4 +141,21 @@ config NUCLEOL432KC_SPWM_PHASE_NUM endif +menuconfig NUCLEOL432KC_DAC_WGEN + depends on (STM32L4_DAC_LL_OPS) && (STM32L4_DAC1_DMA) && (STM32L4_TIM2_DAC) + bool "Sinusoidal DAC wave generator example" + default n + +if NUCLEOL432KC_DAC_WGEN + +config NUCLEOL432KC_DAC_WGEN_SAMPLES + int "Sine samples" + default 40 + +config NUCLEOL432KC_SPWM_FREQ + int "Waveform frequency in Hz" + default 50 + +endif + endif # ARCH_BOARD_NUCLEO_L432KC diff --git a/boards/arm/stm32l4/nucleo-l432kc/configs/wgen/defconfig b/boards/arm/stm32l4/nucleo-l432kc/configs/wgen/defconfig new file mode 100644 index 00000000000..4fd29c90bae --- /dev/null +++ b/boards/arm/stm32l4/nucleo-l432kc/configs/wgen/defconfig @@ -0,0 +1,72 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ANALOG=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nucleo-l432kc" +CONFIG_ARCH_BOARD_NUCLEO_L432KC=y +CONFIG_ARCH_CHIP="stm32l4" +CONFIG_ARCH_CHIP_STM32L432KC=y +CONFIG_ARCH_CHIP_STM32L4=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=8499 +CONFIG_BUILTIN=y +CONFIG_DAC=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXAMPLES_ALARM=y +CONFIG_EXAMPLES_RANDOM=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="dac_wgen_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_NUCLEOL432KC_DAC_WGEN=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=65536 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_RTC_ALARM=y +CONFIG_RTC_DATETIME=y +CONFIG_RTC_DRIVER=y +CONFIG_RTC_IOCTL=y +CONFIG_RTC_NALARMS=2 +CONFIG_SCHED_WAITPID=y +CONFIG_SPI=y +CONFIG_STM32L4_DAC1=y +CONFIG_STM32L4_DAC1_DMA=y +CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE=40 +CONFIG_STM32L4_DAC1_TIMER=2 +CONFIG_STM32L4_DAC1_TIMER_FREQUENCY=2000 +CONFIG_STM32L4_DAC_LL_OPS=y +CONFIG_STM32L4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_STM32L4_DMA1=y +CONFIG_STM32L4_DMA2=y +CONFIG_STM32L4_PWR=y +CONFIG_STM32L4_RNG=y +CONFIG_STM32L4_RTC=y +CONFIG_STM32L4_SAI1PLL=y +CONFIG_STM32L4_SRAM2_HEAP=y +CONFIG_STM32L4_TIM2=y +CONFIG_STM32L4_TIM2_DAC=y +CONFIG_STM32L4_USART2=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_TESTING_OSTEST=y +CONFIG_USART2_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32l4/nucleo-l432kc/include/board.h b/boards/arm/stm32l4/nucleo-l432kc/include/board.h index 53e92e6de9a..562608b4280 100644 --- a/boards/arm/stm32l4/nucleo-l432kc/include/board.h +++ b/boards/arm/stm32l4/nucleo-l432kc/include/board.h @@ -61,6 +61,14 @@ #define ADC1_DMA_CHAN DMACHAN_ADC1_1 +/* Analog pin selections ****************************************************/ + +/* DAC + * Default is PA4 (same as ADC, do not use both at the same time) + */ + +#define GPIO_DAC1_OUT GPIO_DAC1_OUT_1 + /* Alternate function pin selections ****************************************/ /* USART1: diff --git a/boards/arm/stm32l4/nucleo-l432kc/src/Makefile b/boards/arm/stm32l4/nucleo-l432kc/src/Makefile index a06236118b0..63f775373c1 100644 --- a/boards/arm/stm32l4/nucleo-l432kc/src/Makefile +++ b/boards/arm/stm32l4/nucleo-l432kc/src/Makefile @@ -80,4 +80,8 @@ ifeq ($(CONFIG_NUCLEOL432KC_SPWM),y) CSRCS += stm32_spwm.c endif +ifeq ($(CONFIG_NUCLEOL432KC_DAC_WGEN),y) +CSRCS += stm32_dac_wgen.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/stm32l4/nucleo-l432kc/src/stm32_dac_wgen.c b/boards/arm/stm32l4/nucleo-l432kc/src/stm32_dac_wgen.c new file mode 100644 index 00000000000..f0bb1c848ab --- /dev/null +++ b/boards/arm/stm32l4/nucleo-l432kc/src/stm32_dac_wgen.c @@ -0,0 +1,285 @@ +/**************************************************************************** + * boards/arm/stm32l4/nucleo-l432kc/src/stm32_dac_wgen.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "stm32l4_dac.h" + +#include "nucleo-l432kc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_NUCLEOL432KC_DAC_WGEN_SAMPLES +# define CONFIG_NUCLEOL432KC_DAC_WGEN_SAMPLES 40 +#endif + +#ifndef CONFIG_NUCLEOL432KC_DAC_WGEN_FREQ +# define CONFIG_NUCLEOL432KC_DAC_WGEN_FREQ 50 +#endif + +/* Assertions ***************************************************************/ + +#ifndef CONFIG_ARCH_CHIP_STM32L432KC +# warning "This only have been verified with CONFIG_ARCH_CHIP_STM32L432KC" +#endif + +#ifndef CONFIG_DAC +# error "CONFIG_DAC is required" +#endif + +#ifndef CONFIG_STM32L4_DAC1 +# error "CONFIG_STM32L4_DAC1 is required" +#endif + +#ifndef CONFIG_STM32L4_DAC_LL_OPS +# error "CONFIG_STM32L4_DAC_LL_OPS is required" +#endif + +#ifndef CONFIG_STM32L4_DAC1_DMA +# error "CONFIG_STM32L4_DAC1_DMA is required" +#endif + +#if (CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE < CONFIG_NUCLEOL432KC_DAC_WGEN_SAMPLES) +# error "DMA buffer size should be equal or greater than the number of samples." +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* DAC wave generator private data */ + +struct dac_wgen_s +{ + struct stm32_dac_dev_s *dac; + uint16_t *dac_dmabuffer; + uint16_t samples; /* Waveform samples num */ + float phase_step; /* Waveform phase step */ + float waveform_freq; /* Waveform frequency */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct dac_wgen_s g_dac_wgen = +{ + .dac = NULL, + .dac_dmabuffer = stm32l4_dac1_dmabuffer, + .samples = CONFIG_NUCLEOL432KC_DAC_WGEN_SAMPLES, + .waveform_freq = ((float)CONFIG_NUCLEOL432KC_DAC_WGEN_FREQ) +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static float waveform_func(float x); +static void waveform_init(struct dac_wgen_s *dac_wgen, float (*f)(float)); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: waveform_func + * + * Description: + * Modulation function. This function must return values from <0.0, 1.0>! + * + ****************************************************************************/ + +static float waveform_func(float x) +{ + DEBUGASSERT(x >= 0 && x <= 2 * M_PI); + + /* Sine modulation */ + + return (sinf(x) + 1.0f) / 2.0f; +} + +/**************************************************************************** + * Name: waveform_init + * + * Description: + * Initialize waveform + * + ****************************************************************************/ + +static void waveform_init(struct dac_wgen_s *dac_wgen, float (*f)(float)) +{ + int i; + float value; + + /* Get phase step to achieve one sine waveform period */ + + dac_wgen->phase_step = (float)(2 * M_PI / dac_wgen->samples); + + /* Initialize sine table */ + + for (i = 0; i < dac_wgen->samples; i += 1) + { + /* We need sine in range from 0 to 1.0 */ + + value = (sinf(dac_wgen->phase_step * i) + 1.0f) / 2.0f; + dac_wgen->dac_dmabuffer[i] = (uint16_t)(value * 4095); + } +} + +/**************************************************************************** + * Name: dac_wgen_start + ****************************************************************************/ + +static int dac_wgen_start(struct dac_wgen_s *dac_wgen) +{ + DAC_ENABLE(dac_wgen->dac, true); + DAC_START_DMA(dac_wgen->dac); + + return OK; +} + +/**************************************************************************** + * Name: dac_wgen_stop + ****************************************************************************/ + +static int dac_wgen_stop(struct dac_wgen_s *dac_wgen) +{ + DAC_STOP_DMA(dac_wgen->dac); + DAC_ENABLE(dac_wgen->dac, false); + + return OK; +} + +/**************************************************************************** + * Name: dac_wgen_setup + ****************************************************************************/ + +int dac_wgen_setup(struct dac_wgen_s *dac_wgen) +{ + struct dac_dev_s *dac; + + int ret = OK; + + dac = stm32l4_dacinitialize(0); + if (dac == NULL) + { + syslog(LOG_ERR, "Failed to get DAC interface\n"); + ret = ERROR; + goto errout; + } + + dac_wgen->dac = (struct stm32_dac_dev_s *)dac->ad_priv; + +errout: + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dac_wgen_main + * + * Description: + * Entrypoint for DAC waveform generator example. + * + ****************************************************************************/ + +int dac_wgen_main(int argc, char *argv[]) +{ + struct dac_wgen_s *dac_wgen = NULL; + + int i = 0; + int ret = OK; + + dac_wgen = &g_dac_wgen; + + syslog(LOG_INFO, "\ndac_wgen_main: Started\n"); + + /* Setup DAC wave generator */ + + ret = dac_wgen_setup(dac_wgen); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to setup DAC WGEN %d!\n", ret); + goto errout; + } + + /* Initialize modulation waveform */ + + waveform_init(dac_wgen, waveform_func); + if (ret < 0) + { + syslog(LOG_ERR, "Failed initialize waveform %d!\n", ret); + goto errout; + } + + /* Start DAC wave generator */ + + ret = dac_wgen_start(dac_wgen); + if (ret < 0) + { + syslog(LOG_ERR, "Failed start DAC WGEN %d!\n", ret); + goto errout; + } + + /* Main loop */ + + while (1) + { + /* Print counter */ + + syslog(LOG_INFO, "%d\n", i); + + /* Increase counter */ + + i += 1; + + /* Sleep */ + + nxsig_sleep(1); + } + +errout: + dac_wgen_stop(dac_wgen); + + return OK; +}