0.3.6 AD985X

This commit is contained in:
Rob Tillaart 2023-10-16 15:40:00 +02:00
parent 1ffebd886c
commit 3188e13658
9 changed files with 247 additions and 45 deletions

View File

@ -1,19 +1,17 @@
//
// FILE: AD985X.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.3.4
// VERSION: 0.3.6
// DATE: 2019-02-08
// PURPOSE: Class for AD9850 and AD9851 function generator
// URL: https://github.com/RobTillaart/AD985X
//
// HISTORY: see changelog.md
#include "AD985X.h"
// UNO HARDWARE SPI PINS
#define SPI_CLOCK 13 // not portable...
#define SPI_CLOCK 13 // not portable.
#define SPI_MISO 12
#define SPI_MOSI 11
@ -58,13 +56,13 @@ void AD9850::begin(uint8_t select, uint8_t resetPin, uint8_t FQUDPin, uint8_t da
{
mySPI = new SPIClass(HSPI);
mySPI->end();
mySPI->begin(14, 12, 13, select); // CLK=14 MISO=12 MOSI=13
mySPI->begin(14, 12, 13, select); // CLK = 14 MISO = 12 MOSI = 13
}
else // VSPI
{
mySPI = new SPIClass(VSPI);
mySPI->end();
mySPI->begin(18, 19, 23, select); // CLK=18 MISO=19 MOSI=23
mySPI->begin(18, 19, 23, select); // CLK = 18 MISO = 19 MOSI = 23
}
#else // generic hardware SPI
mySPI = &SPI;
@ -143,8 +141,8 @@ void AD9850::powerUp()
bool AD9850::setPhase(uint8_t phase)
{
if (phase > 31) return false;
_config &= 0x07;
_config |= (phase << 3);
_config &= 0x07; // keep last three bits
_config |= (phase << 3); // set new phase
writeData();
return true;
}
@ -176,7 +174,8 @@ void AD9850::writeData()
// Serial.println(_config, HEX);
uint32_t data = _factor;
// used for multi device configuration only - https://github.com/RobTillaart/AD985X/issues/13
// used for multi device configuration only
// see https://github.com/RobTillaart/AD985X/issues/13
digitalWrite(_select, HIGH);
if (_hwSPI)
{
@ -233,7 +232,7 @@ bool AD9850::setFrequency(uint32_t freq)
rv = false;
freq = AD9850_MAX_FREQ;
}
// _factor = round(freq * 34.359738368); // 4294967296 / 125000000
// _factor = round(freq * 34.359738368); // 4294967296 / 125000000
_factor = (147573952589ULL * freq) >> 32;
_freq = freq;
_factor += _offset;

View File

@ -2,7 +2,7 @@
//
// FILE: AD985X.h
// AUTHOR: Rob Tillaart
// VERSION: 0.3.5
// VERSION: 0.3.6
// DATE: 2019-02-08
// PURPOSE: Class for AD9850 and AD9851 function generator
// URL: https://github.com/RobTillaart/AD985X
@ -12,13 +12,19 @@
#include "SPI.h"
#define AD985X_LIB_VERSION (F("0.3.5"))
#define AD985X_LIB_VERSION (F("0.3.6"))
#define AD9850_MAX_FREQ (40UL * 1000UL * 1000UL)
#define AD9851_MAX_FREQ (70UL * 1000UL * 1000UL)
#define AD9850_MAX_FREQ (40UL * 1000UL * 1000UL)
#define AD9851_MAX_FREQ (70UL * 1000UL * 1000UL)
#define AD9851_ARC_CUTOFF_FREQ (10000000UL)
/////////////////////////////////////////////////////////////////////
//
// BASE CLASS AD9850
//
class AD9850
{
public:
@ -46,12 +52,12 @@ public:
// offset to calibrate the frequency (internal counter)
// offset must be stored by the user.
void setCalibration(int32_t offset = 0) { _offset = offset; };
int32_t getCalibration() { return _offset; };
int32_t getCalibration() { return _offset; };
// autoUpdate is default true;
void setAutoUpdate(bool update = true) { _autoUpdate = update; };
bool getAutoUpdate() { return _autoUpdate; };
bool getAutoUpdate() { return _autoUpdate; };
void update();
@ -62,7 +68,7 @@ public:
// debugging
bool usesHWSPI() { return _hwSPI; };
// internal chip factor used for frequency. (debugging only)
uint32_t getFactor() { return _factor; };
uint32_t getFactor() { return _factor; };
// ESP32 specific
@ -110,7 +116,7 @@ protected:
/////////////////////////////////////////////////////////////////////
//
// DERIVED CLASS
// DERIVED CLASS AD9851
//
class AD9851 : public AD9850
{
@ -132,16 +138,17 @@ public:
// 10 MHz is default, set in Hz.
// will be kept <= 30 MHz as that is the freq of LOW mode.
void setARCCutOffFreq(uint32_t Hz = 10000000UL );
// ARC = AutoRefClock
void setARCCutOffFreq(uint32_t Hz = AD9851_ARC_CUTOFF_FREQ);
uint32_t getARCCutOffFreq();
protected:
bool _autoRefClock = false;
uint32_t _ARCCutOffFreq = 10000000UL;
uint32_t _ARCCutOffFreq = AD9851_ARC_CUTOFF_FREQ;
};
// -- END OF FILE --
// -- END OF FILE --

View File

@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.3.6] - 2023-10-15
- add ESP32 HSPI example
- add unit tests for setFrequency setFrequencyF
- update readme.md
- fix version number in .cpp
- minor edits
## [0.3.5] - 2023-01-11
- update GitHub actions
- update license
@ -13,7 +21,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- add bool return value to setPhase()
- add test_constants in unit test
## [0.3.4] - 2022-10-25
- add changelog.md
- add RP2040 in build-CI

View File

@ -1,9 +1,12 @@
[![Arduino CI](https://github.com/RobTillaart/AD985X/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![JSON check](https://github.com/RobTillaart/AD985X/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/AD985X/actions/workflows/jsoncheck.ym)l
[![Arduino-lint](https://github.com/RobTillaart/AD985X/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/AD985X/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/AD985X/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/AD985X/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/AD985X.svg)](https://github.com/RobTillaart/AD985X/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/AD985X/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/AD985X.svg?maxAge=3600)](https://github.com/RobTillaart/AD985X/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/AD985X.svg)](https://registry.platformio.org/libraries/robtillaart/AD985X)
# AD985X
@ -16,13 +19,13 @@ Arduino library for AD9850 and AD9851 function generators.
Library for the AD9850 and AD9851 function generators.
These devices can produce a square and a sine wave
| type | max frequency | phase (stepsize) |
|:---------|---------------:|-------------------:|
| AD9850 | 40 MHz | 0..31 x 11.25° |
| AD9851 | 70 MHz | 0..31 x 11.25° |
| type | max frequency | phase (step size) |
|:--------:|:--------------:|:-------------------:|
| AD9850 | 40 MHz | 0..31 x 11.25° |
| AD9851 | 70 MHz | 0..31 x 11.25° |
Note that at the max frequency the devices do not give a nice sine anymore.
Note that at the max frequency the devices do not give a nice sine any more.
You need to check what is acceptable for your project.
The library has a AD9850 as base class that implements the commonalities.
@ -64,7 +67,6 @@ Schema break-out
L = LED
C = chip
P = potentiometer => for duty cycle square wave
```
@ -191,13 +193,17 @@ For the AD9850 => 40 MHz, for the AD9851 => 70 MHz.
- Note setFrequencyF is affected by the autoUpdateFlag.
The frequency is limited by the MaxFrequency of the class used.
Returns false if limited.
- **uint32_t getMaxFrequency()** returns the maximum frequency that can be set. For the AD9850 this is 20 MHz.
For the AD9851 this is 70 MHz.
- **float getFrequency()** returns the frequency set. As it returns a float it might loose some accuracy at higher frequencies.
- **uint32_t getMaxFrequency()** returns the maximum frequency that can be set.
- For the AD9850 this is 20 MHz.
- For the AD9851 this is 70 MHz.
- **float getFrequency()** returns the frequency set.
As it returns a float it might loose some accuracy at higher frequencies.
- **bool setPhase(uint8_t phase = 0)** set the phase in units of 11.25° 0..31 allowed.
Default it sets the phase to 0.
Returns false if phase > 31, no change to phase in that case.
- **uint8_t getPhase()** returns the phase set, 0 by default. One need to multiply by 11.25° to get the actual angle.
- **uint8_t getPhase()** returns the phase set, 0 by default.
- multiply by 11.25° to get the actual phase angle in degrees.
- multiply by (PI \* 0.0625) to get actual phase angle in radians.
### Calibration
@ -313,20 +319,28 @@ The user is also responsible to store it e.g. in EEPROM to make it persistent.
#### Should
- examples for ESP32 HWSPI interface
- do tests on ESP32
- performance measurements
- unit tests for
- bool setFrequency
- bool setPhase
#### Could
- move code to .cpp
- create defines for MAGIC numbers (defaults)
- should other void function return bool?
- setARCCutOffFreq() ?
- should **setSPIspeed(uint32_t speed)** return bool?
- out of range?
#### Wont
- **bool setARCCutOffFreq()** no need
## 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,

View File

@ -0,0 +1,27 @@
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

View File

@ -0,0 +1,96 @@
//
// FILE: AD9850_ESP32_HWSPI.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo ESP32 hardware SPI
// URL: https://github.com/RobTillaart/AD985X
#include "AD985X.h"
AD9850 freqGen;
uint32_t freq = 0;
uint32_t prev = 0;
uint32_t maxFreq;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION);
help();
// Select HW SPI for ESP32
freqGen.selectHSPI();
freqGen.begin(15, 16, 17); // selectPin, resetPin, FQUDPin
freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency();
Serial.println(maxFreq);
}
void loop()
{
if (Serial.available() > 0)
{
int c = Serial.read();
switch (c)
{
case '?' :
help();
break;
case 'R' :
freqGen.reset();
freq = freqGen.getFrequency();
break;
case 'P' :
freqGen.powerDown();
break;
case 'U' :
freqGen.powerUp();
break;
case '+' :
freq += 1;
break;
case '-' :
freq -= 1;
break;
case '*' :
freq *= 10;
break;
case '/' :
freq /= 10;
break;
}
if (freq > maxFreq) freq = maxFreq;
}
// UPDATE AD985X IF NEW VALUE
if (prev != freq)
{
prev = freq;
freqGen.setFrequency(freq);
Serial.println(freq);
}
}
void help()
{
Serial.println();
Serial.println("+ : f = f + 1");
Serial.println("- : f = f - 1");
Serial.println("* : f = f * 10");
Serial.println("/ : f = f / 10");
Serial.println("? : help");
Serial.println("R : AD9850 reset");
Serial.println("P : AD9850 power down");
Serial.println("U : AD9850 power up");
Serial.println();
}
// -- END OF FILE --

View File

@ -15,9 +15,9 @@
"type": "git",
"url": "https://github.com/RobTillaart/AD985X.git"
},
"version": "0.3.5",
"version": "0.3.6",
"license": "MIT",
"frameworks": "arduino",
"frameworks": "*",
"platforms": "*",
"headers": "AD985X.h"
}

View File

@ -1,5 +1,5 @@
name=AD985X
version=0.3.5
version=0.3.6
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for AD9850 and AD9851 function generators. Supports both hardware SPI as software SPI.

View File

@ -74,7 +74,59 @@ unittest(test_auto_update)
}
unittest(test_ad9850)
unittest(test_ad9850_frequency)
{
AD9850 funcgen;
funcgen.begin(4, 5, 6);
for (uint32_t freq = 500; freq <= 10000; freq += 500)
{
funcgen.setFrequency(freq);
assertEqual(freq, funcgen.getFrequency());
}
}
unittest(test_ad9851_frequency)
{
AD9851 funcgen;
funcgen.begin(4, 5, 6);
for (uint32_t freq = 500; freq <= 10000; freq += 500)
{
funcgen.setFrequency(freq);
assertEqual(freq, funcgen.getFrequency());
}
}
unittest(test_ad9850_frequency_float)
{
AD9850 funcgen;
funcgen.begin(4, 5, 6);
for (float freq = 1; freq <= 5; freq += 0.31415)
{
funcgen.setFrequencyF(freq);
assertEqualFloat(freq, funcgen.getFrequency(), 0.01);
}
}
unittest(test_ad9851_frequency_float)
{
AD9851 funcgen;
funcgen.begin(4, 5, 6);
for (float freq = 1; freq <= 5; freq += 0.31415)
{
funcgen.setFrequencyF(freq);
assertEqualFloat(freq, funcgen.getFrequency(), 0.01);
}
}
unittest(test_ad9850_phase)
{
AD9850 funcgen;
funcgen.begin(4, 5, 6);
@ -92,7 +144,7 @@ unittest(test_ad9850)
}
unittest(test_ad9851)
unittest(test_ad9851_phase)
{
AD9851 funcgen;
funcgen.begin(4, 5, 6);
@ -215,4 +267,4 @@ unittest(test_ad9851_float_freq)
unittest_main()
// --------
// END OF FILE --