diff --git a/README.md b/README.md index 0a2afda..f8b3fb8 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,7 @@ - + -`Arduino_AdvancedAnalog` 〰 -=========================== -[![Compile Examples status](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/actions/workflows/compile-examples.yml) -[![Spell Check status](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/actions/workflows/spell-check.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/actions/workflows/spell-check.yml) -[![Sync Labels status](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/actions/workflows/sync-labels.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/actions/workflows/sync-labels.yml) -[![Arduino Lint](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/workflows/Arduino%20Lint/badge.svg)](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/actions?workflow=Arduino+Lint) +# 〰️ Arduino AdvancedAnalog Library -Advanced Analog Library for Arduino Giga. +The Arduino AdvancedAnalog library is designed to offer high performance DAC/ADC applications on boards based on the STM32H7 microcontroller. -## :mag_right: Resources - -* [How to install a library](https://www.arduino.cc/en/guide/libraries) -* [Help Center](https://support.arduino.cc/) -* [Forum](https://forum.arduino.cc) - -## :bug: Bugs & Issues - -If you want to report an issue with this library, you can submit it to the [issue tracker](https://github.com/arduino-libraries/Arduino_AdvancedAnalog/issues) of this repository. Remember to include as much detail as you can about your hardware set-up, code and steps for reproducing the issue. Make sure you're using an original Arduino board. - -## :technologist: Development - -There are many ways to contribute: - -* Improve documentation and examples -* Fix a bug -* Test open Pull Requests -* Implement a new feature -* Discuss potential ways to improve this library - -You can submit your patches directly to this repository as Pull Requests. Please provide a detailed description of the problem you're trying to solve and make sure you test on real hardware. - -## :yellow_heart: Donations - -This open-source code is maintained by Arduino with the help of the community. We invest a considerable amount of time in testing code, optimizing it and introducing new features. Please consider [donating](https://www.arduino.cc/en/donate/) or [sponsoring](https://github.com/sponsors/arduino) to support our work, as well as [buying original Arduino boards](https://store.arduino.cc/) which is the best way to make sure our effort can continue in the long term. - -## Known issues -* ADC is running at the slowest possible clock (PCLK), should probably set up a PLL and change the clock source. +📖 For more information about this library please read the documentation [here](./docs/). \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md index 55cf3d8..3c01f87 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -1,12 +1,174 @@ # Arduino_AdvancedAnalog library -The **Arduino_AdvancedAnalog** library is designed for high performance DAC/ADC applications on boards based on the STM32H747XI microcontroller: +[![License](https://img.shields.io/badge/License-LGPLv2.1-blue.svg)](../LICENSE) + +The **Arduino_AdvancedAnalog** library is designed to offer high performance DAC/ADC applications on boards based on the STM32H747XI microcontroller: - [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/giga-r1-wifi) - [Arduino Portenta H7](https://store.arduino.cc/products/portenta-h7) -To use this library: +## Features + +- ADC/DAC parameters fine tuning: resolution, channel number, queue number and size +- ADC acquisition with DMA in double buffering mode +- ADC Multichannel acquisition +- DAC Multichannel writing +- Storing ADC samples history in multiple queues +## Guides + +To learn more about using the DAC & ADC on the GIGA R1 WiFi, check out the [GIGA Advanced DAC/ADC Guide](https://docs.arduino.cc/tutorials/giga-r1-wifi/giga-audio). + +This includes examples such as audio playback from USB storage, generate sine waves and more. +## Usage + +### ADC + +To use this library for ADC applications, you must have a supported Arduino board and include the AdvancedAnalog library in your Arduino sketch. Here is a minimal example: + +```cpp +#include + +AdvancedADC adc1(A0); + +void setup() { + Serial.begin(9600); + + // Initialize ADC with: resolution, sample rate, number of samples per channel, queue depth + if (!adc1.begin(AN_RESOLUTION_16, 16000, 32, 64)) { + Serial.println("Failed to start ADC!"); + while (1); + } +} + +void loop() { + // Check if an ADC measurement is ready + if (adc1.available()) { + // Get read buffer + SampleBuffer buf = adc1.read(); + + // Print sample from read buffer + Serial.println(buf[0]); + + // Release read buffer + buf.release(); + } +} +``` + +#### ADC Multichannel (GIGA R1 WiFi) +This library supports concurrent usage of up to **three** ADCs (_ADC1_, _ADC2_ and _ADC3_). +Each ADC instance can handle up to **five** channels. + +**Note:** It's important to be aware that certain pins cannot be used across multiple ADCs or cannot share the same ADC. + +*Please ensure that you refer to tables below when configuring your project to avoid conflicts in pin assignments.* + +Below is a table illustrating the pin mapping for each ADC in **Arduino Giga R1 WiFi**: + +| Pin | ADC1 | ADC2 | ADC3 | +|-------|-------|-------|-------| +| A0 | X | X | | +| A1 | X | X | | +| A2 | X | X | | +| A3 | X | X | | +| A4 | X | X | | +| A5 | X | X | X | +| A6 | X | X | X | +| A7 | X | | | +| A8 | | | X | +| A9 | | | X | +| A10 | X | X | | +| A11 | X | X | | + +Here is a example for the Arduino GIGA R1 WiFi: + +```cpp +#include + +AdvancedADC adc_a(A0, A1); +/* Mapped to ADC1 */ + +AdvancedADC adc_b(A2); +/* Mapped to ADC2, because ADC1 is occupied by A0 and A1 */ +void setup() { +... ``` + +#### ADC Multichannel (Portenta H7) + +Below is a table illustrating the pin mapping for each ADC in **Portenta H7**: + +| Pin | ADC1 | ADC2 | ADC3 | +|-------|-------|-------|-------| +| A0 | X | X | | +| A1 | X | X | | +| A2 | | | X | +| A3 | | | X | +| A4 | X | X | X | +| A5 | X | X | | +| A6 | X | X | | +| A7 | X | X | | + +Here is an example for the Portenta H7: + +```cpp #include + +AdvancedADC adc_c(A2, A3, A4); +/* Mapped to ADC3 */ + +AdvancedADC adc_d(A5); +/* Mapped to ADC1 */ + +void setup() { +... ``` +### DAC + +To use this library for DAC application, you must have a supported Arduino board and include the AdvancedAnalog library in your Arduino sketch. Here is a minimal example for the Arduino GIGA R1 WiFi: + +```cpp +#include + +AdvancedDAC dac1(A12); + +void setup() { + Serial.begin(9600); + + // Initialize DAC with: resolution, sample rate, number of samples per channel, queue depth + if (!dac1.begin(AN_RESOLUTION_12, 8000, 32, 64)) { + Serial.println("Failed to start DAC!"); + while (1); + } +} + +void loop() { + if (dac1.available()) { + + // Get a free buffer for writing + SampleBuffer buf = dac1.dequeue(); + + // Write data to buffer (Even position: 0, Odd position: 0xFFF) + for (int i=0; i *pool; DMABuffer *dmabuf[2]; }; +static uint32_t adc_pin_alt[3] = {0, ALT0, ALT1}; + static adc_descr_t adc_descr_all[3] = { {{ADC1}, {DMA1_Stream1, {DMA_REQUEST_ADC1}}, DMA1_Stream1_IRQn, {TIM1}, ADC_EXTERNALTRIG_T1_TRGO, - 0, nullptr, {nullptr, nullptr}}, + nullptr, {nullptr, nullptr}}, {{ADC2}, {DMA1_Stream2, {DMA_REQUEST_ADC2}}, DMA1_Stream2_IRQn, {TIM2}, ADC_EXTERNALTRIG_T2_TRGO, - ALT0, nullptr, {nullptr, nullptr}}, + nullptr, {nullptr, nullptr}}, {{ADC3}, {DMA1_Stream3, {DMA_REQUEST_ADC3}}, DMA1_Stream3_IRQn, {TIM3}, ADC_EXTERNALTRIG_T3_TRGO, - ALT1, nullptr, {nullptr, nullptr}}, + nullptr, {nullptr, nullptr}}, }; static uint32_t ADC_RES_LUT[] = { @@ -121,13 +123,31 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl return 0; } + // Clear ALTx pin. + for (size_t i=0; ipool == nullptr) { - // Check if the first channel is connected to this ADC. - PinName pin = (PinName) (adc_pins[0] | descr->pin_alt); - instance = (ADCName) pinmap_peripheral(pin, PinMap_ADC); + for (size_t i=0; instance == ADC_NP && ipool == nullptr) { + ADCName tmp_instance = (ADCName) pinmap_peripheral(pin, PinMap_ADC); + if (descr->adc.Instance == ((ADC_TypeDef*) tmp_instance)) { + instance = tmp_instance; + adc_pins[0] = pin; + } + } } } @@ -138,14 +158,29 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl } // Configure ADC pins. - for (size_t i=0; ipin_alt); - // All channels must share the same instance; if not, bail out - if (instance != pinmap_peripheral(adc_pins[i], PinMap_ADC)) { - return 0; + pinmap_pinout(adc_pins[0], PinMap_ADC); + uint8_t ch_init = 1; + for (size_t i=1; idmabuf[1] = descr->pool->allocate(); // Init and config DMA. - hal_dma_config(&descr->dma, descr->dma_irqn, DMA_PERIPH_TO_MEMORY); + if (hal_dma_config(&descr->dma, descr->dma_irqn, DMA_PERIPH_TO_MEMORY) < 0) { + return 0; + } // Init and config ADC. - hal_adc_config(&descr->adc, ADC_RES_LUT[resolution], descr->tim_trig, adc_pins, n_channels); + if (hal_adc_config(&descr->adc, ADC_RES_LUT[resolution], descr->tim_trig, adc_pins, n_channels) < 0) { + return 0; + } // Link DMA handle to ADC handle, and start the ADC. __HAL_LINKDMA(&descr->adc, DMA_Handle, descr->dma); - HAL_ADC_Start_DMA(&descr->adc, (uint32_t *) descr->dmabuf[0]->data(), descr->dmabuf[0]->size()); + if (HAL_ADC_Start_DMA(&descr->adc, (uint32_t *) descr->dmabuf[0]->data(), descr->dmabuf[0]->size()) != HAL_OK) { + return 0; + } // Re/enable DMA double buffer mode. hal_dma_enable_dbm(&descr->dma, descr->dmabuf[0]->data(), descr->dmabuf[1]->data()); // Init, config and start the ADC timer. hal_tim_config(&descr->tim, sample_rate); - HAL_TIM_Base_Start(&descr->tim); + if (HAL_TIM_Base_Start(&descr->tim) != HAL_OK) { + return 0; + } + return 1; } diff --git a/src/HALConfig.cpp b/src/HALConfig.cpp index 225029a..f6a7103 100644 --- a/src/HALConfig.cpp +++ b/src/HALConfig.cpp @@ -195,8 +195,10 @@ int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger adc->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; adc->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; - HAL_ADC_Init(adc); - HAL_ADCEx_Calibration_Start(adc, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); + if (HAL_ADC_Init(adc) != HAL_OK + || HAL_ADCEx_Calibration_Start(adc, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK) { + return -1; + } ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Offset = 0; @@ -209,7 +211,9 @@ int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger uint32_t channel = STM_PIN_CHANNEL(function); sConfig.Rank = ADC_RANK_LUT[rank]; sConfig.Channel = __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel); - HAL_ADC_ConfigChannel(adc, &sConfig); + if (HAL_ADC_ConfigChannel(adc, &sConfig) != HAL_OK) { + return -1; + } } return 0;