mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
0.1.0 AD9833
This commit is contained in:
parent
5dd75883af
commit
cd94d589b2
28
libraries/AD9833/.arduino-ci.yml
Normal file
28
libraries/AD9833/.arduino-ci.yml
Normal file
@ -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
|
||||
|
4
libraries/AD9833/.github/FUNDING.yml
vendored
Normal file
4
libraries/AD9833/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: RobTillaart
|
||||
|
13
libraries/AD9833/.github/workflows/arduino-lint.yml
vendored
Normal file
13
libraries/AD9833/.github/workflows/arduino-lint.yml
vendored
Normal file
@ -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
|
17
libraries/AD9833/.github/workflows/arduino_test_runner.yml
vendored
Normal file
17
libraries/AD9833/.github/workflows/arduino_test_runner.yml
vendored
Normal file
@ -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
|
18
libraries/AD9833/.github/workflows/jsoncheck.yml
vendored
Normal file
18
libraries/AD9833/.github/workflows/jsoncheck.yml
vendored
Normal file
@ -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$"
|
||||
|
303
libraries/AD9833/AD9833.cpp
Normal file
303
libraries/AD9833/AD9833.cpp
Normal file
@ -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 --
|
111
libraries/AD9833/AD9833.h
Normal file
111
libraries/AD9833/AD9833.h
Normal file
@ -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 --
|
||||
|
11
libraries/AD9833/CHANGELOG.md
Normal file
11
libraries/AD9833/CHANGELOG.md
Normal file
@ -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
|
||||
|
21
libraries/AD9833/LICENSE
Normal file
21
libraries/AD9833/LICENSE
Normal file
@ -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.
|
209
libraries/AD9833/README.md
Normal file
209
libraries/AD9833/README.md
Normal file
@ -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,
|
||||
|
35
libraries/AD9833/examples/AD9833_1000_Hz/AD9833_1000_Hz.ino
Normal file
35
libraries/AD9833/examples/AD9833_1000_Hz/AD9833_1000_Hz.ino
Normal file
@ -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 --
|
29
libraries/AD9833/examples/AD9833_minimal/AD9833_minimal.ino
Normal file
29
libraries/AD9833/examples/AD9833_minimal/AD9833_minimal.ino
Normal file
@ -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 --
|
@ -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 --
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
45
libraries/AD9833/keywords.txt
Normal file
45
libraries/AD9833/keywords.txt
Normal file
@ -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
|
23
libraries/AD9833/library.json
Normal file
23
libraries/AD9833/library.json
Normal file
@ -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"
|
||||
}
|
11
libraries/AD9833/library.properties
Normal file
11
libraries/AD9833/library.properties
Normal file
@ -0,0 +1,11 @@
|
||||
name=AD9833
|
||||
version=0.1.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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=
|
115
libraries/AD9833/test/unit_test_001.cpp
Normal file
115
libraries/AD9833/test/unit_test_001.cpp
Normal file
@ -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 <ArduinoUnitTests.h>
|
||||
|
||||
#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 --
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user