From cd94d589b2b01b92d9a69a847b4e9ce877ac5af0 Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Sun, 27 Aug 2023 20:28:30 +0200 Subject: [PATCH] 0.1.0 AD9833 --- libraries/AD9833/.arduino-ci.yml | 28 ++ libraries/AD9833/.github/FUNDING.yml | 4 + .../AD9833/.github/workflows/arduino-lint.yml | 13 + .../.github/workflows/arduino_test_runner.yml | 17 + .../AD9833/.github/workflows/jsoncheck.yml | 18 ++ libraries/AD9833/AD9833.cpp | 303 ++++++++++++++++++ libraries/AD9833/AD9833.h | 111 +++++++ libraries/AD9833/CHANGELOG.md | 11 + libraries/AD9833/LICENSE | 21 ++ libraries/AD9833/README.md | 209 ++++++++++++ .../AD9833_1000_Hz/AD9833_1000_Hz.ino | 35 ++ .../AD9833_minimal/AD9833_minimal.ino | 29 ++ .../AD9833_performance/AD9833_performance.ino | 55 ++++ .../performance_0.1.0. - ESP32.txt | 19 ++ .../AD9833_performance/performance_0.1.0..txt | 17 + libraries/AD9833/keywords.txt | 45 +++ libraries/AD9833/library.json | 23 ++ libraries/AD9833/library.properties | 11 + libraries/AD9833/test/unit_test_001.cpp | 115 +++++++ 19 files changed, 1084 insertions(+) create mode 100644 libraries/AD9833/.arduino-ci.yml create mode 100644 libraries/AD9833/.github/FUNDING.yml create mode 100644 libraries/AD9833/.github/workflows/arduino-lint.yml create mode 100644 libraries/AD9833/.github/workflows/arduino_test_runner.yml create mode 100644 libraries/AD9833/.github/workflows/jsoncheck.yml create mode 100644 libraries/AD9833/AD9833.cpp create mode 100644 libraries/AD9833/AD9833.h create mode 100644 libraries/AD9833/CHANGELOG.md create mode 100644 libraries/AD9833/LICENSE create mode 100644 libraries/AD9833/README.md create mode 100644 libraries/AD9833/examples/AD9833_1000_Hz/AD9833_1000_Hz.ino create mode 100644 libraries/AD9833/examples/AD9833_minimal/AD9833_minimal.ino create mode 100644 libraries/AD9833/examples/AD9833_performance/AD9833_performance.ino create mode 100644 libraries/AD9833/examples/AD9833_performance/performance_0.1.0. - ESP32.txt create mode 100644 libraries/AD9833/examples/AD9833_performance/performance_0.1.0..txt create mode 100644 libraries/AD9833/keywords.txt create mode 100644 libraries/AD9833/library.json create mode 100644 libraries/AD9833/library.properties create mode 100644 libraries/AD9833/test/unit_test_001.cpp diff --git a/libraries/AD9833/.arduino-ci.yml b/libraries/AD9833/.arduino-ci.yml new file mode 100644 index 00000000..77a333f9 --- /dev/null +++ b/libraries/AD9833/.arduino-ci.yml @@ -0,0 +1,28 @@ +platforms: + rpipico: + board: rp2040:rp2040:rpipico + package: rp2040:rp2040 + gcc: + features: + defines: + - ARDUINO_ARCH_RP2040 + warnings: + flags: + +packages: + rp2040:rp2040: + url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + - esp32 + - esp8266 + # - mega2560 + - rpipico + diff --git a/libraries/AD9833/.github/FUNDING.yml b/libraries/AD9833/.github/FUNDING.yml new file mode 100644 index 00000000..90d9ab4c --- /dev/null +++ b/libraries/AD9833/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: RobTillaart + diff --git a/libraries/AD9833/.github/workflows/arduino-lint.yml b/libraries/AD9833/.github/workflows/arduino-lint.yml new file mode 100644 index 00000000..8a26f14a --- /dev/null +++ b/libraries/AD9833/.github/workflows/arduino-lint.yml @@ -0,0 +1,13 @@ + +name: Arduino-lint + +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + compliance: strict diff --git a/libraries/AD9833/.github/workflows/arduino_test_runner.yml b/libraries/AD9833/.github/workflows/arduino_test_runner.yml new file mode 100644 index 00000000..fadfa904 --- /dev/null +++ b/libraries/AD9833/.github/workflows/arduino_test_runner.yml @@ -0,0 +1,17 @@ +--- +name: Arduino CI + +on: [push, pull_request] + +jobs: + runTest: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - run: | + gem install arduino_ci + arduino_ci.rb diff --git a/libraries/AD9833/.github/workflows/jsoncheck.yml b/libraries/AD9833/.github/workflows/jsoncheck.yml new file mode 100644 index 00000000..37a11298 --- /dev/null +++ b/libraries/AD9833/.github/workflows/jsoncheck.yml @@ -0,0 +1,18 @@ +name: JSON check + +on: + push: + paths: + - '**.json' + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: json-syntax-check + uses: limitusus/json-syntax-check@v1 + with: + pattern: "\\.json$" + diff --git a/libraries/AD9833/AD9833.cpp b/libraries/AD9833/AD9833.cpp new file mode 100644 index 00000000..5a0f2252 --- /dev/null +++ b/libraries/AD9833/AD9833.cpp @@ -0,0 +1,303 @@ +// +// FILE: AD9833.cpp +// AUTHOR: Rob Tillaart +// PURPOSE: Arduino library for AD9833 function generator +// VERSION: 0.1.0 +// URL: https://github.com/RobTillaart/AD9833 +// + +#include "AD9833.h" + +// CONTROL REGISTER BITS +#define AD9833_B28 (1 << 13) +#define AD9833_HLB (1 << 12) +#define AD9833_FSELECT (1 << 11) +#define AD9833_PSELECT (1 << 10) +#define AD9833_RESET (1 << 8) +#define AD9833_SLEEP1 (1 << 7) +#define AD9833_SLEEP12 (1 << 6) +#define AD9833_OPBITEN (1 << 5) +#define AD9833_DIV2 (1 << 3) +#define AD9833_MODE (1 << 1) + + +AD9833::AD9833() +{ +} + + +void AD9833::begin(uint8_t selectPin, uint8_t dataPin, uint8_t clockPin) +{ + _selectPin = selectPin; + _dataPin = dataPin; + _clockPin = clockPin; + + pinMode(_selectPin, OUTPUT); + digitalWrite(_selectPin, HIGH); + + _hwSPI = ((dataPin == 0) || (clockPin == 0)); + + _spi_settings = SPISettings(8000000, MSBFIRST, SPI_MODE2); + + if (_hwSPI) + { + #if defined(ESP32) + if (_useHSPI) // HSPI + { + mySPI = new SPIClass(HSPI); + mySPI->end(); + mySPI->begin(14, 12, 13, selectPin); // CLK = 14 MISO = 12 MOSI = 13 + } + else // VSPI + { + mySPI = new SPIClass(VSPI); + mySPI->end(); + mySPI->begin(18, 19, 23, selectPin); // CLK = 18 MISO = 19 MOSI = 23 + } + #else // generic hardware SPI + mySPI = &SPI; + mySPI->end(); + mySPI->begin(); + #endif + } + else // software SPI + { + pinMode(_dataPin, OUTPUT); + pinMode(_clockPin, OUTPUT); + digitalWrite(_dataPin, LOW); + digitalWrite(_clockPin, LOW); + } + reset(); +} + + +void AD9833::begin(uint8_t selectPin, SPIClass * spi) +{ + _selectPin = selectPin; + pinMode(_selectPin, OUTPUT); + digitalWrite(_selectPin, HIGH); + + _hwSPI = true; + _spi_settings = SPISettings(8000000, MSBFIRST, SPI_MODE2); + + mySPI = spi; + mySPI->end(); + mySPI->begin(); + + reset(); +} + + +void AD9833::reset() +{ + setWave(AD9833_OFF); + setFrequency(1000, 0); + setFrequency(1000, 1); + setPhase(0, 0); + setPhase(0, 1); +} + + +void AD9833::setWave(uint8_t waveType) +{ + if (waveType > 4) return; + + // store wave type + _waveType = waveType; + + // clear bits in control register + _control &= ~(AD9833_SLEEP1 | AD9833_SLEEP12 | AD9833_OPBITEN | AD9833_MODE); + + // set bits in control register + switch(_waveType) + { + case AD9833_OFF: + _control |= (AD9833_SLEEP1 | AD9833_SLEEP12); + break; + case AD9833_SINE: + // no bits need to set + break; + case AD9833_SQUARE1: + _control |= (AD9833_DIV2 | AD9833_OPBITEN); + break; + case AD9833_SQUARE2: + _control |= (AD9833_OPBITEN); + break; + case AD9833_TRIANGLE: + _control |= (AD9833_MODE); + break; + } + writeControlRegister(_control); +} + + +uint8_t AD9833::getWave() +{ + return _waveType; +} + + +float AD9833::setFrequency(float freq, uint8_t channel) +{ + if (channel > 1) return -1; + _freq[channel] = freq; + if (_freq[channel] > AD9833_MAX_FREQ) _freq[channel] = AD9833_MAX_FREQ; + if (_freq[channel] < 0) _freq[channel] = 0; + + // convert to bit pattern + // fr = round(freq * pow(2, 28) / 25 MHz)); + // rounding + uint32_t fr = (_freq[channel] * (268435456.0 / 25000000.0) + 0.5); + + _control |= AD9833_B28; + writeControlRegister(_control); + writeFreqRegister(channel, fr); + + return _freq[channel]; +} + + +float AD9833::getFrequency(uint8_t channel) +{ + return _freq[channel]; +} + + +float AD9833::getMaxFrequency() +{ + return AD9833_MAX_FREQ; +} + + +void AD9833::setFrequencyChannel(uint8_t channel) +{ + if (channel > 1) return; + + if (channel == 0) _control &= ~AD9833_FSELECT; + if (channel == 1) _control |= AD9833_FSELECT; + writeControlRegister(_control); +} + + +float AD9833::setPhase(float phase, uint8_t channel) +{ + if (channel > 1) return -1; + _phase[channel] = phase; + while (_phase[channel] >= AD9833_MAX_PHASE) _phase[channel] -= AD9833_MAX_PHASE; + while (_phase[channel] < 0) _phase[channel] += AD9833_MAX_PHASE; + + uint16_t ph = _phase[channel] * (4095.0 / 360.0); + writePhaseRegister(channel, ph); + + return _phase[channel]; +} + + +float AD9833::getPhase(uint8_t channel) +{ + return _phase[channel]; +} + + +float AD9833::getMaxPhase() +{ + return AD9833_MAX_PHASE; +} + + +void AD9833::setPhaseChannel(uint8_t channel) +{ + if (channel > 1) return; + + if (channel == 0) _control &= ~AD9833_PSELECT; + if (channel == 1) _control |= AD9833_PSELECT; + writeControlRegister(_control); +} + + +void AD9833::setSPIspeed(uint32_t speed) +{ + _SPIspeed = speed; + _spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE2); +} + + +uint32_t AD9833::getSPIspeed() +{ + return _SPIspeed; +} + + +bool AD9833::usesHWSPI() +{ + return _hwSPI; +} + + +//////////////////////////////////////////////////////////////// +// +// PRIVATE +// +void AD9833::writeControlRegister(uint16_t value) +{ + uint16_t data = value & 0x3FFF; // bit 15 and 14 == 00 + writeData(data); +} + + +void AD9833::writeFreqRegister(uint8_t reg, uint32_t freq) +{ + uint16_t data = 0; + if (reg > 1) return; + if (reg == 0) data = 0x4000; // bit 15 and 14 01 + if (reg == 1) data = 0x8000; // bit 15 and 14 10 + + // 28 bits in two sets of 14 + data |= (freq & 0x3FFF); + writeData(data); + data &= 0xC000; + data |= (freq >> 14); + writeData(data); +} + + +void AD9833::writePhaseRegister(uint8_t reg, uint16_t value) +{ + uint16_t data = 0; + if (reg > 1) return; + if (reg == 0) data = 0xC000; // bit 15 and 14 and 13 110 + if (reg == 1) data = 0xE000; // bit 15 and 14 and 13 111 + + data |= (value & 0x0FFF); + writeData(data); +} + + +void AD9833::writeData(uint16_t data) +{ + digitalWrite(_selectPin, LOW); + if (_hwSPI) + { + mySPI->beginTransaction(_spi_settings); + mySPI->transfer16(data); + mySPI->endTransaction(); + } + else + { + // local variables is fast. + uint8_t clk = _clockPin; + uint8_t dao = _dataPin; + // MSBFIRST + for (uint16_t mask = 0x8000; mask; mask >>= 1) + { + digitalWrite(dao, (data & mask)); + digitalWrite(clk, LOW); + digitalWrite(clk, HIGH); + } + digitalWrite(dao, LOW); + } + digitalWrite(_selectPin, HIGH); +} + + +// -- END OF FILE -- diff --git a/libraries/AD9833/AD9833.h b/libraries/AD9833/AD9833.h new file mode 100644 index 00000000..52560de4 --- /dev/null +++ b/libraries/AD9833/AD9833.h @@ -0,0 +1,111 @@ +#pragma once +// +// FILE: AD9833.h +// AUTHOR: Rob Tillaart +// PURPOSE: Arduino library for AD9833 function generator. +// VERSION: 0.1.0 +// URL: https://github.com/RobTillaart/AD9833 + + +#include "Arduino.h" +#include "SPI.h" + + +#define AD9833_LIB_VERSION (F("0.1.0")) + + +#define AD9833_MAX_FREQ (12500000UL) // 12.5 MHz. +#define AD9833_MAX_PHASE (360.0) + + +// MODE OPERANDI +#define AD9833_OFF 0 +#define AD9833_SINE 1 +#define AD9833_SQUARE1 2 +#define AD9833_SQUARE2 3 +#define AD9833_TRIANGLE 4 + + +class AD9833 +{ +public: + AD9833(); + + // selectPin == fsyncPin + void begin(uint8_t selectPin, uint8_t dataPin = 0, uint8_t clockPin = 0); + void begin(uint8_t selectPin, SPIClass * spi); + + void reset(); + + void setWave(uint8_t wave = AD9833_OFF); + uint8_t getWave(); + + + // returns frequency set + // 0 .. 12.5 MHz == AD9833_MAX_FREQ + float setFrequency(float freq, uint8_t channel = 0); + float getFrequency(uint8_t channel = 0); + float getMaxFrequency(); + void setFrequencyChannel(uint8_t channel); + + // returns phase set + // [0 .. 360> + float setPhase(float phase, uint8_t channel = 0); + float getPhase(uint8_t channel = 0); + float getMaxPhase(); + void setPhaseChannel(uint8_t channel); + + + // Hardware SPI settings + void setSPIspeed(uint32_t speed); // speed in Hz + uint32_t getSPIspeed(); + bool usesHWSPI(); + + + // ESP32 specific + #if defined(ESP32) + void selectHSPI() { _useHSPI = true; }; + void selectVSPI() { _useHSPI = false; }; + bool usesHSPI() { return _useHSPI; }; + bool usesVSPI() { return !_useHSPI; }; + + // to overrule ESP32 default hardware pins + void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select); + #endif + +private: + + void writeControlRegister(uint16_t value); + void writeFreqRegister(uint8_t reg, uint32_t freq); + void writePhaseRegister(uint8_t reg, uint16_t value); + void writeData(uint16_t data); + + bool _hwSPI = true; + uint32_t _SPIspeed = 8000000; + + SPIClass * mySPI; + SPISettings _spi_settings; + +#if defined(ESP32) + bool _useHSPI = true; +#endif + + // PINS + uint8_t _dataPin = 0; + uint8_t _clockPin = 0; + uint8_t _selectPin = 0; + + + // SIGNAL + uint16_t _control = 0; + uint8_t _waveType = AD9833_OFF; + + + float _freq[2] = { 1000, 1000 }; // Hz + float _phase[2] = { 0, 0 }; // angle +}; + + + +// -- END OF FILE -- + diff --git a/libraries/AD9833/CHANGELOG.md b/libraries/AD9833/CHANGELOG.md new file mode 100644 index 00000000..89750187 --- /dev/null +++ b/libraries/AD9833/CHANGELOG.md @@ -0,0 +1,11 @@ +# Change Log AD9833 + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + + +## [0.1.0] - 2023-08-25 +- initial version + diff --git a/libraries/AD9833/LICENSE b/libraries/AD9833/LICENSE new file mode 100644 index 00000000..16ef1551 --- /dev/null +++ b/libraries/AD9833/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023-2023 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/AD9833/README.md b/libraries/AD9833/README.md new file mode 100644 index 00000000..0aebd3c5 --- /dev/null +++ b/libraries/AD9833/README.md @@ -0,0 +1,209 @@ + +[![Arduino CI](https://github.com/RobTillaart/AD9833/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) +[![Arduino-lint](https://github.com/RobTillaart/AD9833/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/AD9833/actions/workflows/arduino-lint.yml) +[![JSON check](https://github.com/RobTillaart/AD9833/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/AD9833/actions/workflows/jsoncheck.yml) +[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/AD9833.svg)](https://github.com/RobTillaart/AD9833/issues) + +[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/AD9833/blob/master/LICENSE) +[![GitHub release](https://img.shields.io/github/release/RobTillaart/AD9833.svg?maxAge=3600)](https://github.com/RobTillaart/AD9833/releases) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/AD9833.svg)](https://registry.platformio.org/libraries/robtillaart/AD9833) + + +# AD9833 + +Arduino library for AD9833 function generator. + + +## Description + +Experimental library for the AD9833 function generator. +The library supports both hardware SPI and software SPI. + +TODO: test with hardware. + +The AD9833 is a signal generator that has two channels for frequency and +two channels for the phase. These channels can be set separately to give +maximum flexibility. + +The AD9833 can generate three types of wave: sine, square (2x) and triangle. +The frequency of the waves cover a range from 0 to 12.5 MHz. +The step size for frequency is ~0.1 Hz (using 25 MHz reference clock). + +The library also can set the phase of each wave from 0° to 360°. +The step size for phase is ~0.1°. + +| type | freq max | freq step | phase | phase step | +|:--------:|:----------:|:-----------:|:--------:|:-----------:| +| AD9833 | 12.5 MHz | 0.1 Hz | 0..360 | 0.1° | + + +#### Related + +- https://github.com/RobTillaart/AD985X +- https://github.com/RobTillaart/functionGenerator + + +## Connection + +Schema AD9833 chip, breakout will have different pins. + +``` + TOP VIEW + +-----------+ + COMP | 1 10 | VOUT + VDD | 2 9 | A-GND + CAP / 2.5 V | 3 8 | FSYNC (select) + D-GND | 4 7 | SCLK + MCLK | 5 6 | SDATA + +-----------+ + +``` + +| PIN | Description | +|:--------------|:---------------------| +| COMP | DAC Bias Pin | +| VDD | Power supply | +| CAP / 2.5 V | (datasheet) | +| D-GND | Digital Ground | +| MCLK | Digital Clock Input | +| SDATA | Serial Data In | +| SCLK | Serial Clock In | +| FSYNC | Select | +| A-GND | Analog Ground | +| VOUT | Analog Out | + +Read datasheet for detailed description of the pins. + + +## Interface + +```cpp +#include "AD9833.h" +``` + +#### Constructor + +- **AD9833()** 12.5 MHz signal generator +- **void begin(uint8_t selectPin, uint8_t dataPin = 0, uint8_t clockPin = 0)** +For hardware SPI only use the first two parameters, +for SW SPI you need to define the data and clock pin too. + - selectPin = chip select. +- **void begin(uint8_t selectPin, SPIClass \* spi)** +For hardware SPI only, to select a specific hardware SPI port e.g. SPI2. +- **void reset()** resets the function generator. + + +#### Wave + +- **void setWave(uint8_t wave)** +- **uint8_t getWave()** + +| wave type | define name | value | notes | +|:-----------:|:-----------------:|:-------:|:--------| +| No output | AD9833_OFF | 0 | +| Sine | AD9833_SINE | 1 | +| Square | AD9833_SQUARE1 | 2 | +| Square2 | AD9833_SQUARE2 | 3 | half frequency +| Triangle | AD9833_TRIANGLE | 4 | + + +#### Frequency + +Default channel is 0, which makes the function calls simpler +when only using one channel. + +- **float setFrequency(float freq, uint8_t channel = 0)** +SetFrequency sets the frequency and is limited by the MaxFrequency of 12.5 MHz. +Returns the frequency set. +- **float getFrequency(uint8_t channel = 0)** returns the frequency set. +- **float getMaxFrequency()** returns the maximum frequency to set (convenience). +- **void selectFreqChannel(uint8_t channel)** select the active frequency channel (0 or 1). + + +#### Phase + +Default channel is 0, which makes the function calls simpler +when only using one channel. + +- **float setPhase(float phase, uint8_t channel = 0)** +setPhase sets the phase and is limited to 0° - 360°. +Returns the phase set. +- **float getPhase(uint8_t channel = 0)** returns the phase set. +- **float getMaxPhase()** returns the maximum phase to set (convenience). +- **void selectPhaseChannel(uint8_t channel)** select the active phase channel (0 or 1). + + +#### Hardware SPI + +To be used only if one needs a specific speed. + +- **void setSPIspeed(uint32_t speed)** set SPI transfer rate. +- **uint32_t getSPIspeed()** returns SPI transfer rate. +- **bool usesHWSPI()** returns true if HW SPI is used. + + +#### ESP32 specific + +- **void selectHSPI()** in case hardware SPI, the ESP32 has two options HSPI and VSPI. +- **void selectVSPI()** see above. +- **bool usesHSPI()** returns true if HSPI is used. +- **bool usesVSPI()** returns true if VSPI is used. + +The **selectVSPI()** or the **selectHSPI()** needs to be called +BEFORE the **begin()** function. + +- **void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)** +to overrule ESP32 default hardware pins (to be tested). +Needs to be called AFTER the **begin()** function. + +In code, something like this (TODO write example) +```cpp +void setup() +{ + freqGen.selectVSPI(); + freqGen.begin(15); + freqGen.setGPIOpins(CLK, MISO, MOSI, SELECT); // SELECT should match the parameter of begin() + ... +} +``` + + +## Future + +#### Must + +- test with hardware +- update documentation + + +#### Should + +- examples + - for ESP32 HWSPI interface + - use of channels (freq & phase) +- do tests on ESP32 +- performance measurements + + +#### Could + +- extend unit tests +- move code to .cpp +- solve MAGIC numbers (defaults) +- setting half freq register for performance mode. +- investigate different power down / sleep modi (page 16) +- investigate hardware reset (page 16) + + +#### Wont + + + +## Support + +If you appreciate my libraries, you can support the development and maintenance. +Improve the quality of the libraries by providing issues and Pull Requests, or +donate through PayPal or GitHub sponsors. + +Thank you, + diff --git a/libraries/AD9833/examples/AD9833_1000_Hz/AD9833_1000_Hz.ino b/libraries/AD9833/examples/AD9833_1000_Hz/AD9833_1000_Hz.ino new file mode 100644 index 00000000..99511a41 --- /dev/null +++ b/libraries/AD9833/examples/AD9833_1000_Hz/AD9833_1000_Hz.ino @@ -0,0 +1,35 @@ +// +// FILE: AD9833_1000_Hz.ino +// AUTHOR: Rob Tillaart +// DATE: 2023-08-25 +// PURPOSE: create a 1000 Hz reference signal + +#include "AD9833.h" + +AD9833 AD; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + + AD.begin(10); + AD.setFrequency(1000, 0); + Serial.println(AD.getFrequency(0)); + AD.setFrequencyChannel(0); + + AD.setPhase(0, 0); + Serial.println(AD.getPhase(0)); + AD.setPhaseChannel(0); + + AD.setWave(AD9833_SINE); + Serial.println(AD.getWave()); +} + + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/libraries/AD9833/examples/AD9833_minimal/AD9833_minimal.ino b/libraries/AD9833/examples/AD9833_minimal/AD9833_minimal.ino new file mode 100644 index 00000000..775a3db4 --- /dev/null +++ b/libraries/AD9833/examples/AD9833_minimal/AD9833_minimal.ino @@ -0,0 +1,29 @@ +// +// FILE: AD9833_minimal.ino +// AUTHOR: Rob Tillaart +// DATE: 2023-08-25 +// PURPOSE: demo AD9833 wave form generator + +#include "AD9833.h" + +AD9833 AD; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + + AD.begin(10); // HW SPI, select pin 10 + AD.setFrequency(1000, 0); + + AD.setWave(AD9833_SQUARE1); + Serial.println(AD.getWave()); +} + + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/libraries/AD9833/examples/AD9833_performance/AD9833_performance.ino b/libraries/AD9833/examples/AD9833_performance/AD9833_performance.ino new file mode 100644 index 00000000..50d6d537 --- /dev/null +++ b/libraries/AD9833/examples/AD9833_performance/AD9833_performance.ino @@ -0,0 +1,55 @@ +// +// FILE: AD9833_performance.ino +// AUTHOR: Rob Tillaart +// DATE: 2023-08-25 +// PURPOSE: demo AD9833 wave form generator + +#include "AD9833.h" + +AD9833 AD; + + +uint32_t start, stop; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + delay(10); + + AD.begin(7, 8, 9); // software SPI + // AD.begin(10); // hardware SPI + + Serial.print("hardware:\t"); + Serial.println(AD.usesHWSPI()); + delay(10); + + start = micros(); + AD.setFrequency(1000, 0); + stop = micros(); + Serial.print("setFrequency:\t"); + Serial.println(stop - start); + delay(10); + + start = micros(); + AD.setPhase(45, 0); + stop = micros(); + Serial.print("setPhase:\t"); + Serial.println(stop - start); + delay(10); + + start = micros(); + AD.setWave(AD9833_SQUARE1); + stop = micros(); + Serial.print("setWave:\t"); + Serial.println(stop - start); + delay(10); +} + + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/libraries/AD9833/examples/AD9833_performance/performance_0.1.0. - ESP32.txt b/libraries/AD9833/examples/AD9833_performance/performance_0.1.0. - ESP32.txt new file mode 100644 index 00000000..19e25314 --- /dev/null +++ b/libraries/AD9833/examples/AD9833_performance/performance_0.1.0. - ESP32.txt @@ -0,0 +1,19 @@ + +Board: ESP32 (240 Mhz) +IDE: 1.8.19 + +AD9833_performance.ino + +hardware: 1 +setFrequency: 32 +setPhase: 11 +setWave: 13 + + +hardware: 0 (software SPI) +setFrequency: 22 +setPhase: 8 +setWave: 10 + + + diff --git a/libraries/AD9833/examples/AD9833_performance/performance_0.1.0..txt b/libraries/AD9833/examples/AD9833_performance/performance_0.1.0..txt new file mode 100644 index 00000000..d30f1655 --- /dev/null +++ b/libraries/AD9833/examples/AD9833_performance/performance_0.1.0..txt @@ -0,0 +1,17 @@ + +Board: UNO +IDE: 1.8.19 + +AD9833_performance.ino + +hardware: 1 +setFrequency: 56 +setPhase: 48 +setWave: 20 + +hardware: 0 (software SPI) +setFrequency: 640 +setPhase: 244 +setWave: 212 + + diff --git a/libraries/AD9833/keywords.txt b/libraries/AD9833/keywords.txt new file mode 100644 index 00000000..b3a77041 --- /dev/null +++ b/libraries/AD9833/keywords.txt @@ -0,0 +1,45 @@ +# Syntax Colouring Map For AD9833 + +# Data types (KEYWORD1) +AD9833 KEYWORD1 + + +# Methods and Functions (KEYWORD2) +begin KEYWORD2 +reset KEYWORD2 + +setWave KEYWORD2 +getWave KEYWORD2 + +setFrequency KEYWORD2 +getFrequency KEYWORD2 +getMaxFrequency KEYWORD2 +setFrequencyChannel KEYWORD2 + +setPhase KEYWORD2 +getPhase KEYWORD2 +getMaxPhase KEYWORD2 +setPhaseChannel KEYWORD2 + +setSPIspeed KEYWORD2 +getSPIspeed KEYWORD2 +usesHWSPI KEYWORD2 + +selectHSPI KEYWORD2 +selectVSPI KEYWORD2 +usesHSPI KEYWORD2 +usesVSPI KEYWORD2 +setGPIOpins KEYWORD2 + + +# Constants (LITERAL1) +AD9833_LIB_VERSION LITERAL1 + +AD9833_MAX_FREQ LITERAL1 +AD9833_MAX_PHASE LITERAL1 + +AD9833_OFF LITERAL1 +AD9833_SINE LITERAL1 +AD9833_SQUARE1 LITERAL1 +AD9833_SQUARE2 LITERAL1 +AD9833_TRIANGLE LITERAL1 \ No newline at end of file diff --git a/libraries/AD9833/library.json b/libraries/AD9833/library.json new file mode 100644 index 00000000..ff3feb25 --- /dev/null +++ b/libraries/AD9833/library.json @@ -0,0 +1,23 @@ +{ + "name": "AD9833", + "keywords": "wave,frequency,sinus,square,triangle,generator", + "description": "Arduino library for AD9833 function generator.", + "authors": + [ + { + "name": "Rob Tillaart", + "email": "Rob.Tillaart@gmail.com", + "maintainer": true + } + ], + "repository": + { + "type": "git", + "url": "https://github.com/RobTillaart/AD9833.git" + }, + "version": "0.1.0", + "license": "MIT", + "frameworks": "*", + "platforms": "*", + "headers": "AD9833.h" +} diff --git a/libraries/AD9833/library.properties b/libraries/AD9833/library.properties new file mode 100644 index 00000000..830ef9f6 --- /dev/null +++ b/libraries/AD9833/library.properties @@ -0,0 +1,11 @@ +name=AD9833 +version=0.1.0 +author=Rob Tillaart +maintainer=Rob Tillaart +sentence=Arduino library for AD9833 function generator. Supports both hardware SPI as software SPI. +paragraph= +category=Signal Input/Output +url=https://github.com/RobTillaart/AD9833 +architectures=* +includes=AD9833.h +depends= diff --git a/libraries/AD9833/test/unit_test_001.cpp b/libraries/AD9833/test/unit_test_001.cpp new file mode 100644 index 00000000..7b99846b --- /dev/null +++ b/libraries/AD9833/test/unit_test_001.cpp @@ -0,0 +1,115 @@ +// +// FILE: unit_test_001.cpp +// AUTHOR: Rob Tillaart +// DATE: 2023-08-27 +// PURPOSE: unit tests for the AD9833 function generator +// https://github.com/RobTillaart/AD9833 +// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md +// + +// supported assertions +// ---------------------------- +// assertEqual(expected, actual) +// assertNotEqual(expected, actual) +// assertLess(expected, actual) +// assertMore(expected, actual) +// assertLessOrEqual(expected, actual) +// assertMoreOrEqual(expected, actual) +// assertTrue(actual) +// assertFalse(actual) +// assertNull(actual) + +#include + +#include "Arduino.h" +#include "AD9833.h" + + +unittest_setup() +{ + fprintf(stderr, "AD9833_LIB_VERSION: %s\n", AD9833_LIB_VERSION); +} + + +unittest_teardown() +{ +} + + +unittest(test_constants) +{ + assertEqual(12500000UL, AD9833_MAX_FREQ); + assertEqual(360, AD9833_MAX_PHASE); + + assertEqual(0, AD9833_OFF); + assertEqual(1, AD9833_SINE); + assertEqual(2, AD9833_SQUARE1); + assertEqual(3, AD9833_SQUARE2); + assertEqual(4, AD9833_TRIANGLE); +} + + +unittest(test_constructor) +{ + AD9833 funcgen; + AD9833 fgsw; + + funcgen.begin(10); + fgsw.begin(4,5,6); + + assertEqual(AD9833_MAX_FREQ, funcgen.getMaxFrequency()); + assertEqual(AD9833_MAX_PHASE, funcgen.getMaxPhase()); + + assertTrue(funcgen.usesHWSPI()); + assertFalse(fgsw.usesHWSPI()); +} + + +unittest(test_wave) +{ + AD9833 funcgen; + funcgen.begin(4, 5, 6); + + for (long wave = 0; wave < 5; wave++) + { + funcgen.setWave(wave); + int w = funcgen.getWave(); + assertEqual(w, wave); + } +} + + +unittest(test_frequency) +{ + AD9833 funcgen; + funcgen.begin(4, 5, 6); + + for (long freq = 0; freq < 10000000; freq += 1000000) + { + funcgen.setFrequency(freq); + long fr = funcgen.getFrequency(); + assertEqual(fr, freq); + } +} + + +unittest(test_phase) +{ + AD9833 funcgen; + funcgen.begin(4, 5, 6); + + for (int ph = 0; ph < 360; ph += 30) + { + funcgen.setPhase(ph); + int phase = funcgen.getPhase(); + assertEqual(ph, phase); + } +} + + +unittest_main() + + +// -- END OF FILE -- + +