### Basic Daisy Audio Callback Setup Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md This snippet shows the essential structure for initializing the Daisy hardware and starting the audio engine with a custom callback function. The callback is where audio processing logic will reside. ```cpp #include "daisy_seed.h" using namespace daisy; // to simplify syntax // Create our hardware object DaisySeed hw; void MyCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size) { // Make sound here! } int main(void) { hw.Init(); hw.StartAudio(MyCallback); while(1) {} } ``` -------------------------------- ### Initialize Daisy Hardware and Start Audio Callback Source: https://github.com/electro-smith/libdaisy/blob/master/README.md This is the main entry point for a Daisy project. It initializes the hardware, sets up the audio sample rate, initializes MIDI, starts the ADC, and begins the audio callback. The main loop continuously listens for MIDI events. ```c++ int main(void) { // Init float samplerate; hw.Init(); samplerate = hw.AudioSampleRate(); midi.Init(MidiHandler::INPUT_MODE_UART1, MidiHandler::OUTPUT_MODE_NONE); midi.StartReceive(); hw.StartAdc(); hw.StartAudio(AudioCallback); for(;;) { midi.Listen(); // Handle MIDI Events while (midi.HasEvents()) { HandleMidiMessage(midi.PopEvent()); } } } ``` -------------------------------- ### Complete GPIO Button and LED Example Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a1_Getting-Started-GPIO.md A full example demonstrating GPIO initialization for both an input button with a pull-up resistor and an output LED, along with the main loop to read the button and control the LED. ```cpp #include "daisy_seed.h" using namespace daisy; using namespace daisy::seed; DaisySeed hw; int main(void) { // Initialize the Daisy Seed hw.Init(); // Create our GPIO object GPIO my_button; GPIO my_led; // Initialize the GPIO object for our button */ my_button.Init(D0, GPIO::Mode::INPUT, GPIO::Pull::PULLUP); // Initialize the GPIO object for our LED my_led.Init(D1, GPIO::Mode::OUTPUT); while(1) { // And let's store the state of the button in a variable called "button_state" bool button_state = my_button.Read(); // And we want to light up the LED while we're pressing the button // so let's use the "!" to flip over the button_state my_led.Write(!button_state); } } ``` -------------------------------- ### Basic googletest Example Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_b1_Development-Unit-Testing.md This example demonstrates how to write a simple unit test using the googletest framework. It includes necessary headers and defines two test cases within a test suite. ```cpp // tests/myTest_gtest.cpp #include #include "myHeaderFileFromLibDaisy.h" TEST(MyTestSuiteName, a_myFirstTest) { EXPECT_EQ(2, 6 - 4); } TEST(MyTestSuiteName, b_mySecondTest) { const bool someResult = 2 == 2; EXPECT_TRUE(someResult); } ``` -------------------------------- ### Example Memory Usage for BOOT_QSPI Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a7_Getting-Started-Daisy-Bootloader.md This output illustrates memory allocation when compiling for `BOOT_QSPI`. The program is now located in the QSPIFLASH region, freeing up internal SRAM. ```sh Memory region Used Size Region Size %age Used FLASH: 0 GB 128 KB 0.00% DTCMRAM: 0 GB 128 KB 0.00% SRAM: 7440 B 512 KB 1.42% RAM_D2_DMA: 16 KB 32 KB 50.00% RAM_D2: 0 GB 256 KB 0.00% RAM_D3: 0 GB 64 KB 0.00% ITCMRAM: 0 GB 64 KB 0.00% SDRAM: 0 GB 64 MB 0.00% QSPIFLASH: 46000 B 7936 KB 0.57% ``` -------------------------------- ### Measure Audio Callback Processing Load Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md Example demonstrating how to use the CpuLoadMeter to measure and report the processing load of the audio callback. Initialization and usage within the callback and main loop are shown. Printing load information should be done from the main loop. ```cpp #include "daisy_seed.h" #include "daisysp.h" using namespace daisy; DaisySeed hw; CpuLoadMeter loadMeter; void MyCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size) { loadMeter.OnBlockStart(); for (size_t i = 0; i < size; i++) { // add your processing here out[0][i] = 0.0f; out[1][i] = 0.0f; } loadMeter.OnBlockEnd(); } int main(void) { hw.Init(); // start logging to the serial connection hw.StartLog(); // initialize the load meter so that it knows what time is available for the processing: loadMeter.Init(hw.AudioSampleRate(), hw.AudioBlockSize()); // start the audio processing callback hw.StartAudio(MyCallback); while(1) { // get the current load (smoothed value and peak values) const float avgLoad = cpuLoadMeter.GetAvgCpuLoad(); const float maxLoad = cpuLoadMeter.GetMaxCpuLoad(); const float minLoad = cpuLoadMeter.GetMinCpuLoad(); // print it to the serial connection (as percentages) hw.PrintLine("Processing Load %:"); hw.PrintLine("Max: " FLT_FMT3, FLT_VAR3(maxLoad * 100.0f)); hw.PrintLine("Avg: " FLT_FMT3, FLT_VAR3(avgLoad * 100.0f)); hw.PrintLine("Min: " FLT_FMT3, FLT_VAR3(minLoad * 100.0f)); // don't spam the serial connection too much System::Delay(500); } } ``` -------------------------------- ### Generating Audio Tones with DaisySP Oscillator Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md Initializes the Daisy hardware and a DaisySP Oscillator to generate a sine wave, then starts the audio callback to output the synthesized sound. The oscillator is initialized with the hardware's sample rate for accurate frequency. ```cpp #include "daisy_seed.h" #include "daisysp.h" using namespace daisy; DaisySeed hw; daisysp::Oscillator osc; void MyCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size) { for (size_t i = 0; i < size; i++) { // The oscillator's Process function synthesizes, and // returns the next sample. float sine_signal = osc.Process(); out[0][i] = sine_signal; out[1][i] = sine_signal; } } int main(void) { hw.Init(); // We initialize the oscillator with the sample rate of the hardware // this ensures that the frequency of the Oscillator will be accurate. osc.Init(hw.AudioSampleRate()); hw.StartAudio(MyCallback); while(1) {} } ``` -------------------------------- ### Example Memory Usage for BOOT_SRAM Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a7_Getting-Started-Daisy-Bootloader.md This output shows memory allocation when compiling for `BOOT_SRAM`. Note the zero usage in FLASH, indicating the internal flash is reserved for the bootloader itself. ```sh Memory region Used Size Region Size %age Used FLASH: 0 GB 128 KB 0.00% DTCMRAM: 7440 B 128 KB 5.68% SRAM: 46000 B 512 KB 8.77% RAM_D2_DMA: 16 KB 32 KB 50.00% RAM_D2: 0 GB 256 KB 0.00% RAM_D3: 0 GB 64 KB 0.00% ITCMRAM: 0 GB 64 KB 0.00% SDRAM: 0 GB 64 MB 0.00% QSPIFLASH: 0 GB 7936 KB 0.00% ``` -------------------------------- ### DMA SPI Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Initiate a non-blocking SPI reception using DMA. The buffer must be in DMA-accessible memory. This example does not use callbacks. ```cpp // receive 4 bytes. No callbacks or callback data. uint8_t DMA_BUFFER_MEM_SECTION buffer[4]; spi_handle.DmaReceive(buffer, 4, NULL, NULL, NULL); ``` -------------------------------- ### DMA SPI Transmit and Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Perform a non-blocking SPI transmit and receive operation using DMA. Buffers must be DMA-accessible. This example omits callbacks. ```cpp // send and receive 4 bytes. No callbacks or callback data. uint8_t DMA_BUFFER_MEM_SECTION tx_buffer[4]; uint8_t DMA_BUFFER_MEM_SECTION rx_buffer[4]; // fill the TX buffer 0, 1, 2, 3 for(uint8_t i = 0; i < 4; i++) { tx_buffer[i] = i; } // transmit and receive spi_handle.DmaTransmitAndReceive(tx_buffer, rx_buffer, 4, NULL, NULL, NULL); ``` -------------------------------- ### Initialize GPIO Output Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a1_Getting-Started-GPIO.md Use this to set up a GPIO pin as an output. Ensure the hardware is correctly wired with a resistor and LED before using this. ```cpp GPIO my_led; my_led.Init(D1, GPIO::Mode::OUTPUT); ``` -------------------------------- ### Initialize SPI Peripheral Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Demonstrates how to create and configure an SpiHandle object for SPI communication. Ensure all necessary pins and settings are correctly defined before initialization. ```cpp SpiHandle spi_handle; SpiHandle::Config spi_conf; // Set some configurations spi_conf.periph = SpiHandle::Peripheral::SPI_1; spi_conf.mode = SpiHandle::Mode::MASTER; spi_conf.direction = SpiHandle::Direction::TWO_LINES; spi_conf.nss = SpiHandle::NSS::NSS_HARD_OUTPUT; spi_conf.pin_config.sclk = Pin(PORTG, 11); spi_conf.pin_config.miso = Pin(PORTB, 4); spi_conf.pin_config.mosi = Pin(PORTB, 5); spi_conf.pin_config.nss = Pin(PORTG, 10); // Initialize the handle using our configuration spi_handle.Init(spi_conf); ``` -------------------------------- ### Configure Project and Find Packages Source: https://github.com/electro-smith/libdaisy/blob/master/tests/CMakeLists.txt Sets the minimum CMake version, names the project, and finds required packages like Threads and Google Test. Includes GoogleTest and sets up the main library directory. ```cmake cmake_minimum_required(VERSION 3.16) project(daisy-test) find_package(Threads REQUIRED) add_subdirectory(googletest) include(GoogleTest) ``` -------------------------------- ### Basic Hello World Serial Print Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Initializes the Daisy Seed hardware and prints 'Hello World!' to the serial monitor. Ensure a serial monitor is connected to view the output. ```cpp #include "daisy_seed.h" using namespace daisy; DaisySeed hw; int main(void) { // Initialize the Daisy Seed Hardware hw.Init(); // Enable Logging, and set up the USB connection. hw.StartLog(); // And Print Hello World! hw.PrintLine("Hello World!"); while(1) {} } ``` -------------------------------- ### Build and Run All Tests Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_b1_Development-Unit-Testing.md Navigate to the tests directory and execute 'make test' to build and run all unit tests. This command generates and executes the 'libDaisy_gtest' command-line program. ```bash > cd tests/ > make test ``` -------------------------------- ### Class Initialization with External Buffer Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a6_Getting-Started-External-SDRAM.md Demonstrates a basic class design pattern where an external float buffer is passed into the class's initialization function. This allows for flexible memory management. ```cpp MyClass::Init(float* buffer, size_t size); . . float *internal_buffer_; ``` -------------------------------- ### Initialize and Read GPIO Input Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a1_Getting-Started-GPIO.md Initializes a GPIO pin as an input with a pull-up resistor and reads its state. This is useful for detecting button presses. ```cpp #include "daisy_seed.h" using namespace daisy; using namespace daisy::seed; DaisySeed hw; int main(void) { // Initialize the Daisy Seed hw.Init(); // Create a GPIO object GPIO my_button; // Initialize the GPIO object my_button.Init(D0, GPIO::Mode::INPUT, GPIO::Pull::PULLUP); while(1) { // And let's store the state of the button in a variable called "button_state" bool button_state = my_button.Read(); } } ``` -------------------------------- ### GPIO Initialization Parameters Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a1_Getting-Started-GPIO.md Defines the parameters for initializing a GPIO pin, including pin selection, mode (input/output), pull-up/down resistors, and speed. ```cpp void Init(Pin p, Mode m=Mode::INPUT, Pull pu=Pull::NOPULL, Speed sp=Speed::LOW); ``` -------------------------------- ### Continuous Serial Print in Loop Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Prints 'Hello World!' repeatedly within the main loop with a delay between each print. This is useful for continuous monitoring but not for one-time initialization debugging. ```cpp hw.StartLog(); while(1) { hw.PrintLine("Hello World!"); System::Delay(1000); // Wait 1 second between printing } ``` -------------------------------- ### Serial Print Waiting for Connection Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Enables logging and waits indefinitely for a USB host connection before proceeding. This guarantees that the 'Hello World!' message will be visible on the serial monitor. ```cpp #include "daisy_seed.h" using namespace daisy; DaisySeed hw; int main(void) { // Initialize the Daisy Seed Hardware hw.Init(); // Enable Logging, and set up the USB connection. // Setting true here means that the program will wait until // a connection has been made to a USB Host hw.StartLog(true); // And Print Hello World! hw.PrintLine("Hello World!"); while(1) {} } ``` -------------------------------- ### Initialize and Read ADC Channels Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a4_Getting-Started-ADCs.md Configure ADC channels using the defined enum and read their values. Ensure the ADC configuration array size matches NUM_ADC_CHANNELS. ```cpp AdcChannelConfig my_adc_config[NUM_ADC_CHANNELS]; // ... my_adc_config[pitchCv].InitSingle(A0); // ... hw.adc.Init(my_adc_config, NUM_ADC_CHANNELS); // ... const float pitchCvValue = hw.adc.GetFloat(pitchCv); ``` -------------------------------- ### Avoid Blocking Operations in Audio Callback Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md Illustrates a safe pattern for handling time-consuming events from the audio callback by using a flag checked in the main loop. This prevents audio underruns caused by indeterminate execution times. ```cpp // Global: bool action_flag; // In callback: if (some_event) // like a button press, or something action_flag = true; // In main() while(1) { if (action_flag) { // Do the big thing that can take a while initiate_big_transfer(); // and clear the flag action_flag = false; } } ``` -------------------------------- ### Define the libdaisy Static Library Source: https://github.com/electro-smith/libdaisy/blob/master/tests/CMakeLists.txt Creates a static library named 'daisy' from source files in the 'src' directory. It also sets include directories and compile definitions for testing. ```cmake set(MODULE_DIR ../src) add_library(daisy STATIC ${MODULE_DIR}/hid/midi_parser.cpp ${MODULE_DIR}/per/qspi.cpp ${MODULE_DIR}/sys/system.cpp ${MODULE_DIR}/ui/AbstractMenu.cpp ${MODULE_DIR}/ui/UI.cpp ${MODULE_DIR}/util/MappedValue.cpp ${MODULE_DIR}/util/oled_fonts.c ) target_include_directories(daisy PUBLIC ${MODULE_DIR}) target_include_directories(daisy PUBLIC ${MODULE_DIR}/sys ../Middlewares/Third_Party/FatFs/src ) target_compile_definitions(daisy PUBLIC UNIT_TEST) target_link_libraries(daisy PUBLIC GTest::gtest_main) ``` -------------------------------- ### Configure HAL Driver Compile Options Source: https://github.com/electro-smith/libdaisy/blob/master/Drivers/CMakeLists.txt Sets compile-time options for the STM32H7XX_HAL_DRIVER, specifically disabling warnings for unused but set variables. ```cmake target_compile_options(STM32H7XX_HAL_DRIVER PRIVATE -Wno-unused-but-set-variable ) ``` -------------------------------- ### Set Audio Block Size and Sample Rate Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md Configure the audio block size and sample rate for the Daisy board. Block size can be up to 256. Refer to SaiHandle::Config::SampleRate for available options. ```cpp hw.SetAudioBlockSize(4); hw.SetAudioSampleRate(SaiHandle::Config::SampleRate::SAI_48KHZ); ``` -------------------------------- ### Print float using FLT_FMT3 and FLT_VAR3 macros Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Use these macros for printing floats with a default precision without increasing binary size. Requires including the Logger class. ```cpp float my_flt = 123.456f; hw.PrintLine("My Float: " FLT_FMT3, FLT_VAR3(my_flt)); ``` -------------------------------- ### Initialize and Read Multiple ADC Channels Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a4_Getting-Started-ADCs.md Configures and initializes multiple ADC channels using an array of `AdcChannelConfig` objects. Allows reading from several analog inputs, such as multiple potentiometers, by accessing them via their index in the configuration array. ```cpp // Create an array of two AdcChannelConfig objects const int num_adc_channels = 2; AdcChannelConfig my_adc_config[num_adc_channels]; // Initialize the first one connected to A0 my_adc_config[0].InitSingle(A0); // Initialize the second one connected to A4 my_adc_config[1].InitSingle(A4); hw.adc.Init(my_adc_config, num_adc_channels); ``` -------------------------------- ### Initialize and Read Single ADC Channel Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a4_Getting-Started-ADCs.md Sets up the Daisy Seed hardware and initializes a single ADC channel connected to pin A0. Reads integer values from the ADC and prints them to the serial console. Useful for basic analog input monitoring. ```cpp #include "daisy_seed.h" using namespace daisy; using namespace daisy::seed; // Create out Daisy Seed Hardware object DaisySeed hw; int main(void) { // Initialize the Daisy Seed hardware hw.Init(); // Start logging for printing over serial hw.StartLog(); // Create an ADC Channel Config object AdcChannelConfig adc_config; // Set up the ADC config with a connection to pin A0 adc_config.InitSingle(A0); // Initialize the ADC peripheral with that configuration hw.adc.Init(&adc_config, 1); // Start the ADC hw.adc.Start(); while(1) { // Read the first ADC that's configured. In our case, this is the only input. int value = hw.adc.Get(0); // In order to know that everything's working let's print that to a serial console: hw.PrintLine("ADC Value: %d", value); // Wait half a second (500 milliseconds) System::Delay(500); } } ``` -------------------------------- ### Configure Makefile for Bootloader Programs Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a7_Getting-Started-Daisy-Bootloader.md Add this line to your Makefile to generate programs that can run from the Daisy bootloader. This setting determines where the compiled program will reside in memory. ```makefile APP_TYPE = BOOT_SRAM ``` -------------------------------- ### Control LED with Button State Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a1_Getting-Started-GPIO.md Write the state of a button to an LED output. This snippet assumes `my_button` is already initialized as an input and `my_led` as an output. ```cpp while(1) { // And let's store the state of the button in a variable called "button_state" bool button_state = my_button.Read(); my_led.Write(button_state); } ``` -------------------------------- ### Enable Testing and Discover Tests Source: https://github.com/electro-smith/libdaisy/blob/master/tests/CMakeLists.txt Enables the testing framework and uses gtest_discover_tests to automatically find and add tests defined in the executables. ```cmake enable_testing() # Discover unit tests inside it gtest_discover_tests(${test_name}) ``` -------------------------------- ### Passing Audio Through Daisy Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md Copies audio input directly to the audio output without any processing. This is a basic pass-through implementation. ```cpp for (size_t i = 0; i < size; i++) { out[0][i] = in[0][i]; out[1][i] = in[1][i]; } ``` -------------------------------- ### Define HAL Driver Compile Definitions Source: https://github.com/electro-smith/libdaisy/blob/master/Drivers/CMakeLists.txt Specifies preprocessor definitions for the STM32H7XX_HAL_DRIVER, enabling the use of HAL and full LL drivers. ```cmake target_compile_definitions(STM32H7XX_HAL_DRIVER PRIVATE USE_HAL_DRIVER USE_FULL_LL_DRIVER ) ``` -------------------------------- ### Formatted String Output Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Demonstrates using C-style format specifiers with `PrintLine` to output formatted strings, such as a continuously incrementing counter. This allows for more complex debugging messages. ```cpp // Declare an int set to 0 int mycnt = 0; while(1) { // Print the value: hw.PrintLine("Count: %d", mycnt); // And then increment the counter mycnt++; // If the counter exceeds 100, reset it to 0 if (mycnt > 100) mycnt = 0; // And count slow enough that it's easy to watch on the Serial Monitor System::Delay(250); } ``` -------------------------------- ### Configure FatFs Include Directories Source: https://github.com/electro-smith/libdaisy/blob/master/Middlewares/Third_Party/FatFs/CMakeLists.txt Sets the public include directories for the FatFs library target in CMake. This ensures that header files are accessible during the build process. ```cmake target_include_directories(FatFs PUBLIC src ${MODULE_DIR}/sys ${MODULE_DIR} # for util/bsp_sd_diskio.h ) ``` -------------------------------- ### Print float with custom precision using FLT_FMT and FLT_VAR Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Specify the number of decimal places for float output using these generic macros. Adjust the numeric argument to control precision. ```cpp float more_precice_float = 123.456789f; hw.PrintLine("My Float: " FLT_FMT(6), FLT_VAR(6, my_flt)); ``` -------------------------------- ### Delayed Serial Print Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Adds a delay after initializing logging to ensure the serial port connection is established before printing 'Hello World!'. This helps prevent missing the initial message. ```cpp hw.StartLog(); System::Delay(5000); hw.PrintLine("Hello World!"); ``` -------------------------------- ### Add FatFs Library Target Source: https://github.com/electro-smith/libdaisy/blob/master/Middlewares/Third_Party/FatFs/CMakeLists.txt Defines the FatFs library as a static library in CMake. Includes source files and configuration options like LFN support. ```cmake add_library(FatFs STATIC src/diskio.c src/ff.c src/ff_gen_drv.c # due to config (in src/sys) which has _USE_LFN = 1 src/option/unicode.c ) ``` -------------------------------- ### Enable %f specifier for floats Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Add this linker flag to your Makefile to enable the `%f` specifier for printing floating-point numbers. This increases flash usage. ```makefile LDFLAGS += -u _printf_float ``` -------------------------------- ### Print float using %f specifier Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Once the `%f` specifier is enabled, you can print floats directly using standard printf-style formatting. ```cpp float my_flt = 123.456f; hw.PrintLine("My Float: %f", my_flt); ``` -------------------------------- ### Function to Add a Google Test Executable Source: https://github.com/electro-smith/libdaisy/blob/master/tests/CMakeLists.txt Defines a CMake function 'add_gtest' that creates an executable for a given source file, links it against necessary libraries (daisy, Threads, GTest), sets C++ and C standards, and configures runtime output directories. ```cmake function(add_gtest source_file) cmake_path(GET source_file STEM test_name) # Create the target add_executable(${test_name} ${source_file} ${CMAKE_CURRENT_LIST_DIR}/FatFsMock.cpp ) # Link it against the required libraries target_link_libraries(${test_name} PUBLIC daisy Threads::Threads GTest::gtest_main ) # Set any compile definitions target_compile_definitions(${test_name} PRIVATE UNIT_TEST ) # Set the properties set_target_properties(${test_name} PROPERTIES CXX_STANDARD 14 CXX_STANDARD_REQUIRED YES C_STANDARD 11 C_STANDARD_REQUIRED YES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" ) # Add the target as a test #add_test(NAME ${test_name} COMMAND ${test_name} --verbose) # Discover unit tests inside it gtest_discover_tests(${test_name}) endfunction(add_gtest) ``` -------------------------------- ### Link HAL Driver to CMSIS Device Source: https://github.com/electro-smith/libdaisy/blob/master/Drivers/CMakeLists.txt Links the STM32H7XX_HAL_DRIVER target to the CMSIS_DEVICE_H7 library to resolve dependencies. ```cmake target_link_libraries(STM32H7XX_HAL_DRIVER PUBLIC CMSIS_DEVICE_H7) ``` -------------------------------- ### Read ADC as Floating-Point Value Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a4_Getting-Started-ADCs.md Replaces the integer ADC read with a floating-point read, providing values scaled between 0.0 and 1.0. Requires enabling floating-point printing in the Makefile. ```cpp float value = hw.adc.GetFloat(0); // value will be 0.0 to 1.0 ``` -------------------------------- ### Amplitude Modulation with Oscillator Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md Processes incoming audio by multiplying it with a synthesized sine wave from a DaisySP Oscillator. This demonstrates a basic form of amplitude modulation (ring modulation). ```cpp for (size_t i = 0; i < size; i++) { float sine_signal = osc.Process(); out[0][i] = in[0][i] * sine_signal; out[1][i] = in[1][i] * sine_signal; } ``` -------------------------------- ### Declare Float Array in SDRAM using DSY_SDRAM_BSS Macro Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a6_Getting-Started-External-SDRAM.md A shorthand macro for declaring a float array in SDRAM, simplifying the syntax compared to the compiler attribute. ```cpp float DSY_SDRAM_BSS my_buffer[1024]; ``` -------------------------------- ### Outputting Silence to Audio Channels Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a3_Getting-Started-Audio.md Fills the audio output buffer with silence for both left and right channels. Useful for ensuring no sound is outputted. ```cpp void MyCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size) { for (size_t i = 0; i < size; i++) { out[0][i] = 0.0f; out[1][i] = 0.0f; } // you can also use standard library functions if you're familiar with C++: std::fill(&out[0][0], &out[0][size], 0.0f); } ``` -------------------------------- ### DMA SPI Transmit Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Initiate a non-blocking SPI transmission using DMA. The buffer must be allocated in DMA-accessible memory. Callbacks can be provided for transfer start/end events. ```cpp // buffer for sending data uint8_t DMA_BUFFER_MEM_SECTION buffer[4]; // fill the buffer 0, 1, 2, 3 for(uint8_t i = 0; i < 4; i++) { buffer[i] = i; } // transmit the data spi_handle.DmaTransmit(buffer, 4, NULL, NULL, NULL); ``` -------------------------------- ### DMA Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Receive data using DMA (Direct Memory Access) in a non-blocking manner. ```APIDOC ## DMA Receive ### Description Receive data using DMA (Direct Memory Access) in a non-blocking manner. A callback can be provided for when the transfer is over. **Note:** Your buffer must be in the DMA section of memory and in a global scope. ### Method ```cpp spi_handle.DmaReceive(buffer, size, callback, callback_data) ``` ### Parameters #### Path Parameters - **buffer** (uint8_t*) - Required - Pointer to the buffer where received data will be stored. Must be in DMA memory section. - **size** (size_t) - Required - The number of bytes to receive. - **callback** (void (*)(void*)) - Optional - Callback function to be called when the transfer is over. - **callback_data** (void*) - Optional - Pointer to data to be passed to the callback function. ``` -------------------------------- ### Append float to FixedCapStr with default precision Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Use the `FixedCapStr` class and its `AppendFloat` method to format and append floating-point numbers to a string buffer. The default precision is two decimal places. ```cpp FixedCapStr<16> str("Value: "); str.AppendFloat(123.456f); hw.PrintLine(str); ``` -------------------------------- ### Autogenerate Tests from Current Directory Source: https://github.com/electro-smith/libdaisy/blob/master/tests/CMakeLists.txt Calls the 'autogen_gtests' function to find and add all Google Test executables located in the current CMake directory. ```cmake autogen_gtests(${CMAKE_CURRENT_LIST_DIR} daisy) ``` -------------------------------- ### Function to Autogenerate Google Tests Source: https://github.com/electro-smith/libdaisy/blob/master/tests/CMakeLists.txt Defines a CMake function 'autogen_gtests' that finds all files ending with '_gtest.cpp' in a specified folder and calls 'add_gtest' for each found file. ```cmake function(autogen_gtests test_folder) file(GLOB_RECURSE specs ${test_folder}/*_gtest.cpp) foreach(spec IN LISTS specs) add_gtest(${spec}) endforeach() endfunction() ``` -------------------------------- ### Append float to FixedCapStr with custom precision Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a2_Getting-Started-Serial-Printing.md Specify the desired number of decimal places as a second argument to `AppendFloat` for custom precision formatting. ```cpp str.AppendFloat(123.456f, 3); ``` -------------------------------- ### DMA Transmit and Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Send and receive data simultaneously using DMA (Direct Memory Access) in a non-blocking manner. ```APIDOC ## DMA Transmit and Receive ### Description Send and receive data simultaneously using DMA (Direct Memory Access) in a non-blocking manner. Callbacks can be provided for when the transfer starts and when it is over. **Note:** Your buffers must be in the DMA section of memory and in a global scope. ### Method ```cpp spi_handle.DmaTransmitAndReceive(tx_buffer, rx_buffer, size, start_callback, end_callback, callback_data) ``` ### Parameters #### Path Parameters - **tx_buffer** (uint8_t*) - Required - Pointer to the buffer containing data to transmit. Must be in DMA memory section. - **rx_buffer** (uint8_t*) - Required - Pointer to the buffer where received data will be stored. Must be in DMA memory section. - **size** (size_t) - Required - The number of bytes to transmit and receive. - **start_callback** (void (*)(void*)) - Optional - Callback function to be called when the transfer starts. - **end_callback** (void (*)(void*)) - Optional - Callback function to be called when the transfer is over. - **callback_data** (void*) - Optional - Pointer to data to be passed to the callback functions. ``` -------------------------------- ### Blocking Transmit and Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Send and receive data simultaneously in a blocking fashion. ```APIDOC ## Blocking Transmit and Receive ### Description Send and receive data simultaneously in a blocking fashion. The code waits while the transmission and reception take place. ### Method ```cpp spi_handle.BlockingTransmitAndReceive(tx_buffer, rx_buffer, size) ``` ### Parameters #### Path Parameters - **tx_buffer** (uint8_t*) - Required - Pointer to the buffer containing data to transmit. - **rx_buffer** (uint8_t*) - Required - Pointer to the buffer where received data will be stored. - **size** (size_t) - Required - The number of bytes to transmit and receive. ``` -------------------------------- ### Blocking Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Receive data in a blocking fashion. The code waits while the reception takes place. ```APIDOC ## Blocking Receive ### Description Receive data in a blocking fashion. The code waits while the reception takes place. ### Method ```cpp spi_handle.BlockingReceive(buffer, size) ``` ### Parameters #### Path Parameters - **buffer** (uint8_t*) - Required - Pointer to the buffer where received data will be stored. - **size** (size_t) - Required - The number of bytes to receive. ``` -------------------------------- ### Blocking SPI Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Use this for synchronous data reception. The code will pause until the specified number of bytes are received into the buffer. ```cpp uint8_t buffer[4]; spi_handle.BlockingReceive(buffer, 4); ``` -------------------------------- ### Blocking SPI Transmit Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Use this for simple, synchronous data transmission where blocking is acceptable. Ensure the buffer is correctly sized for the data being sent. ```cpp uint8_t buffer[4] = {0, 1, 2, 3}; spi_handle.BlockingTransmit(buffer, 4); ``` -------------------------------- ### Define ADC Channels with Enum Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a4_Getting-Started-ADCs.md Use enums to assign meaningful names to ADC channels, making your code easier to read and manage. The NUM_ADC_CHANNELS value automatically tracks the total number of channels. ```cpp enum AdcChannel { pitchKnob = 0, pitchCv, gainKnob, gainCv, NUM_ADC_CHANNELS } ``` -------------------------------- ### Flip Boolean State Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a1_Getting-Started-GPIO.md Use the '!' operator to invert a boolean variable. This is useful for correcting inverted logic, such as when a button connected to a pull-up resistor reads true when not pressed. ```cpp bool button_state = my_button.Read(); // state is false while button is pressed bool button_pressed = !button_state; // "!" is a "not" operator, which will flip a bool var. ``` -------------------------------- ### DMA Transmit Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Send data using DMA (Direct Memory Access) in a non-blocking manner. ```APIDOC ## DMA Transmit ### Description Send data using DMA (Direct Memory Access). This allows the hardware to handle the transmission in the background while the code is doing other things, making it non-blocking. A callback can be provided for when the transfer is over. **Note:** Your buffer must be in the DMA section of memory and in a global scope. ### Method ```cpp spi_handle.DmaTransmit(buffer, size, callback, callback_data) ``` ### Parameters #### Path Parameters - **buffer** (uint8_t*) - Required - Pointer to the buffer containing data to transmit. Must be in DMA memory section. - **size** (size_t) - Required - The number of bytes to transmit. - **callback** (void (*)(void*)) - Optional - Callback function to be called when the transfer is over. - **callback_data** (void*) - Optional - Pointer to data to be passed to the callback function. ``` -------------------------------- ### Blocking Transmit Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Send data in a blocking fashion. The code waits while the transmission takes place. ```APIDOC ## Blocking Transmit ### Description Send data in a blocking fashion. The code waits while the transmission takes place. ### Method ```cpp spi_handle.BlockingTransmit(buffer, size) ``` ### Parameters #### Path Parameters - **buffer** (uint8_t*) - Required - Pointer to the buffer containing data to transmit. - **size** (size_t) - Required - The number of bytes to transmit. ``` -------------------------------- ### Declare Float Array in SDRAM using Compiler Attribute Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a6_Getting-Started-External-SDRAM.md Declares a float array in the SDRAM using the `section` attribute. This is the longform method and can be useful for specifying other memory sections. ```cpp float __attribute__((section(".sdram_bss"))) my_buffer[1024]; ``` -------------------------------- ### Blocking SPI Transmit and Receive Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a8_Getting-Started-SPI.md Perform a synchronous send and receive operation. The code waits for both the transmission and reception to complete. ```cpp uint8_t tx_buffer[4] = {0, 1, 2, 3}; uint8_t rx_buffer[4]; spi_handle.BlockingTransmitAndReceive(tx_buffer, rx_buffer, 4); ``` -------------------------------- ### Declare Standard Float Array Source: https://github.com/electro-smith/libdaisy/blob/master/doc/md/_a6_Getting-Started-External-SDRAM.md A standard C++ array of floats declared for use within normal memory regions. ```cpp float my_buffer[1024]; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.