0.4.0 AD985X

This commit is contained in:
Rob Tillaart 2023-11-29 10:05:19 +01:00
parent 6118d5e642
commit 9c8c09ef71
19 changed files with 256 additions and 249 deletions

View File

@ -1,7 +1,7 @@
// //
// FILE: AD985X.cpp // FILE: AD985X.cpp
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.3.6 // VERSION: 0.4.0
// DATE: 2019-02-08 // DATE: 2019-02-08
// PURPOSE: Class for AD9850 and AD9851 function generator // PURPOSE: Class for AD9850 and AD9851 function generator
// URL: https://github.com/RobTillaart/AD985X // URL: https://github.com/RobTillaart/AD985X
@ -24,95 +24,70 @@
// AD9850 // AD9850
// //
AD9850::AD9850() // HARDWARE SPI
// spiClock needed for RESET(). TODO: nicer solution?
AD9850::AD9850(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, __SPI_CLASS__ * mySPI, uint8_t spiClock)
{ {
_select = slaveSelect;
_reset = resetPin;
_fqud = FQUDPin;
_hwSPI = true;
_mySPI = mySPI;
_dataOut = 0;
_clock = spiClock;
}
// SOFTWARE SPI
AD9850::AD9850(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, uint8_t spiData, uint8_t spiClock)
{
_select = slaveSelect;
_reset = resetPin;
_fqud = FQUDPin;
_hwSPI = false;
_mySPI = NULL;
_dataOut = 0;
_clock = spiClock;
} }
void AD9850::begin(uint8_t select, uint8_t resetPin, uint8_t FQUDPin, uint8_t dataOut , uint8_t clock) void AD9850::begin()
{ {
_select = select;
_reset = resetPin;
_fqud = FQUDPin;
_dataOut = dataOut;
_clock = clock;
// following 3 are always set. // following 3 are always set.
pinMode(_select, OUTPUT); pinMode(_select, OUTPUT);
pinMode(_reset, OUTPUT); pinMode(_reset, OUTPUT);
pinMode(_fqud, OUTPUT); pinMode(_fqud, OUTPUT);
pinMode(_clock, OUTPUT);
// device select = HIGH See - https://github.com/RobTillaart/AD985X/issues/13 // device select = HIGH See - https://github.com/RobTillaart/AD985X/issues/13
digitalWrite(_select, LOW); digitalWrite(_select, LOW);
digitalWrite(_reset, LOW); digitalWrite(_reset, LOW);
digitalWrite(_fqud, LOW); digitalWrite(_fqud, LOW);
digitalWrite(_clock, LOW);
_hwSPI = ((dataOut == 0) || (clock == 0));
_spi_settings = SPISettings(2000000, LSBFIRST, SPI_MODE0); _spi_settings = SPISettings(2000000, LSBFIRST, SPI_MODE0);
if (_hwSPI) if (_hwSPI)
{ {
#if defined(ESP32) _mySPI->end();
if (_useHSPI) // HSPI _mySPI->begin();
{
mySPI = new SPIClass(HSPI);
mySPI->end();
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
}
#else // generic hardware SPI
mySPI = &SPI;
mySPI->end();
mySPI->begin();
#endif
} }
else // software SPI else // SOFTWARE SPI
{ {
pinMode(_dataOut, OUTPUT); pinMode(_dataOut, OUTPUT);
pinMode(_clock, OUTPUT);
digitalWrite(_dataOut, LOW); digitalWrite(_dataOut, LOW);
digitalWrite(_clock, LOW);
} }
reset(); reset();
} }
#if defined(ESP32)
void AD9850::setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)
{
_clock = clk;
_dataOut = mosi;
_select = select;
pinMode(_select, OUTPUT);
digitalWrite(_select, LOW);
mySPI->end(); // disable SPI
mySPI->begin(clk, miso, mosi, select);
}
#endif
void AD9850::reset() void AD9850::reset()
{ {
// be sure to select the correct device // be sure to select the correct device
digitalWrite(_select, HIGH); digitalWrite(_select, HIGH);
pulsePin(_reset); pulsePin(_reset);
if (_hwSPI) pulsePin(_clock);
{
#if defined(ESP32)
if (_useHSPI) pulsePin(14); // HSPI magic number clock
else pulsePin(18); // VSPI magic number clock
#else
// UNO hardware SPI
pulsePin(SPI_CLOCK);
#endif
}
else pulsePin(_clock);
digitalWrite(_select, LOW); digitalWrite(_select, LOW);
_config = 0; // 0 phase no power down _config = 0; // 0 phase no power down
@ -179,15 +154,15 @@ void AD9850::writeData()
digitalWrite(_select, HIGH); digitalWrite(_select, HIGH);
if (_hwSPI) if (_hwSPI)
{ {
mySPI->beginTransaction(_spi_settings); _mySPI->beginTransaction(_spi_settings);
mySPI->transfer(data & 0xFF); _mySPI->transfer(data & 0xFF);
data >>= 8; data >>= 8;
mySPI->transfer(data & 0xFF); _mySPI->transfer(data & 0xFF);
data >>= 8; data >>= 8;
mySPI->transfer(data & 0xFF); _mySPI->transfer(data & 0xFF);
mySPI->transfer(data >> 8); _mySPI->transfer(data >> 8);
mySPI->transfer(_config & 0xFC); // mask factory test bit _mySPI->transfer(_config & 0xFC); // mask factory test bit
mySPI->endTransaction(); _mySPI->endTransaction();
} }
else else
{ {
@ -288,6 +263,15 @@ void AD9850::update()
// bit is a 6x multiplier bit P.14 datasheet // bit is a 6x multiplier bit P.14 datasheet
#define AD9851_REFCLK 0x01 #define AD9851_REFCLK 0x01
AD9851::AD9851(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, __SPI_CLASS__ * mySPI, uint8_t spiClock) : AD9850(slaveSelect, resetPin, FQUDPin, mySPI, spiClock)
{
}
AD9851::AD9851(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, uint8_t spiData, uint8_t spiClock) : AD9850(slaveSelect, resetPin, FQUDPin, spiData, spiClock)
{
}
bool AD9851::setFrequency(uint32_t freq) bool AD9851::setFrequency(uint32_t freq)
{ {

View File

@ -2,7 +2,7 @@
// //
// FILE: AD985X.h // FILE: AD985X.h
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.3.6 // VERSION: 0.4.0
// DATE: 2019-02-08 // DATE: 2019-02-08
// PURPOSE: Class for AD9850 and AD9851 function generator // PURPOSE: Class for AD9850 and AD9851 function generator
// URL: https://github.com/RobTillaart/AD985X // URL: https://github.com/RobTillaart/AD985X
@ -12,7 +12,16 @@
#include "SPI.h" #include "SPI.h"
#define AD985X_LIB_VERSION (F("0.3.6")) #define AD985X_LIB_VERSION (F("0.4.0"))
#ifndef __SPI_CLASS__
#if defined(ARDUINO_ARCH_RP2040)
#define __SPI_CLASS__ SPIClassRP2040
#else
#define __SPI_CLASS__ SPIClass
#endif
#endif
#define AD9850_MAX_FREQ (40UL * 1000UL * 1000UL) #define AD9850_MAX_FREQ (40UL * 1000UL * 1000UL)
@ -28,10 +37,13 @@
class AD9850 class AD9850
{ {
public: public:
AD9850(); // HARDWARE SPI
// spiClock needed for RESET(). TODO: nicer solution?
AD9850(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, __SPI_CLASS__ * mySPI, uint8_t spiClock);
// SOFTWARE SPI
AD9850(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, uint8_t spiData, uint8_t spiClock);
// for HW SPI only use lower 3 parameters. void begin();
void begin(uint8_t select, uint8_t resetPin, uint8_t FQUDPin, uint8_t dataOut = 0, uint8_t clock = 0);
void reset(); void reset();
void powerDown(); void powerDown();
void powerUp(); void powerUp();
@ -71,18 +83,6 @@ public:
uint32_t getFactor() { return _factor; }; uint32_t getFactor() { return _factor; };
// 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
protected: protected:
void pulsePin(uint8_t pin); void pulsePin(uint8_t pin);
void writeData(); void writeData();
@ -91,12 +91,8 @@ protected:
bool _hwSPI = true; bool _hwSPI = true;
uint32_t _SPIspeed = 2000000; uint32_t _SPIspeed = 2000000;
SPIClass * mySPI; __SPI_CLASS__ * _mySPI;
SPISettings _spi_settings; SPISettings _spi_settings;
#if defined(ESP32)
bool _useHSPI = true;
#endif
// PINS // PINS
uint8_t _dataOut = 0; uint8_t _dataOut = 0;
@ -121,6 +117,13 @@ protected:
class AD9851 : public AD9850 class AD9851 : public AD9850
{ {
public: public:
// HARDWARE SPI
// spiClock needed for RESET(). TODO: nicer solution?
AD9851(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, __SPI_CLASS__ * mySPI, uint8_t spiClock);
// SOFTWARE SPI
AD9851(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, uint8_t spiData, uint8_t spiClock);
// returns false if limited to AD9851_MAX_FREQ // returns false if limited to AD9851_MAX_FREQ
bool setFrequency(uint32_t freq); // 0..AD9851_MAX_FREQ bool setFrequency(uint32_t freq); // 0..AD9851_MAX_FREQ
bool setFrequencyF(float freq); // works best for low frequencies. bool setFrequencyF(float freq); // works best for low frequencies.

View File

@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.0] - 2023-11-27
- refactor constructor interface - breaking changes.
- minimize conditional code. -- create SPI_CLASS macro to solve it.
- reordered parameters software SPI constructor.
- update readme.md
- update examples
----
## [0.3.6] - 2023-10-15 ## [0.3.6] - 2023-10-15
- add ESP32 HSPI example - add ESP32 HSPI example
- add unit tests for setFrequency setFrequencyF - add unit tests for setFrequency setFrequencyF
@ -13,7 +22,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- fix version number in .cpp - fix version number in .cpp
- minor edits - minor edits
## [0.3.5] - 2023-01-11 ## [0.3.5] - 2023-01-11
- update GitHub actions - update GitHub actions
- update license - update license

View File

@ -19,10 +19,10 @@ Arduino library for AD9850 and AD9851 function generators.
Library for the AD9850 and AD9851 function generators. Library for the AD9850 and AD9851 function generators.
These devices can produce a square and a sine wave These devices can produce a square and a sine wave
| type | max frequency | phase (step size) | | type | max freq | phase (step size) | Notes |
|:--------:|:--------------:|:-------------------:| |:--------:|:--------:|:-------------------:|:--------|
| AD9850 | 40 MHz | 0..31 x 11.25° | | AD9850 | 40 MHz | 0..31 x 11.25° |
| AD9851 | 70 MHz | 0..31 x 11.25° | | AD9851 | 70 MHz | 0..31 x 11.25° | has more options.
Note that at the max frequency the devices do not give a nice sine any more. Note that at the max frequency the devices do not give a nice sine any more.
@ -38,7 +38,17 @@ This feature improves the tuning for both low and high frequencies.
The library is not suitable for AD9852 as that is a function generator with The library is not suitable for AD9852 as that is a function generator with
way more functionality. way more functionality.
Note: mainly tested on Arduino UNO. Tweaking for other platforms is expected. Note: mainly tested on Arduino UNO.
#### 0.4.0 breaking change
The version 0.4.0 has breaking changes in the interface.
The essence is removal of ESP32 specific code from the library.
Furthermore it moved parameters from **begin()** to the constructor.
Finally made a specific constructor for HW SPI and SW SPI.
This makes it possible to support the ESP32-S3 and other processors in the future.
Also it makes the library a bit simpler to maintain.
## Connection ## Connection
@ -70,15 +80,23 @@ Schema break-out
``` ```
#### Related
- https://github.com/RobTillaart/AD9833
- https://github.com/RobTillaart/AD985X
- https://github.com/RobTillaart/functionGenerator software waveform generator
- https://pages.mtu.edu/~suits/notefreqs.html frequency table for notes.
### Multi device ### Multi device
See **Multi_AD985X_devices.pdf** See **Multi_AD985X_devices.pdf**
Discussion leading to the document see - https://github.com/RobTillaart/AD985X/issues/13 Discussion leading to the document see - https://github.com/RobTillaart/AD985X/issues/13
The AD985X board can be connected with a SPI bus like interface. The AD985X board can be connected with a SPI bus like interface.
However there is **no Chip Select pin (CS)** so one must take other measures to control multiple AD985X devices. However there is **no Chip Select pin (CS)** so one must take
other measures to control multiple AD985X devices.
#### Trivial solution #### Trivial solution
@ -162,23 +180,26 @@ If the FQ_UD line can be shared directly it offers a way to start / change multi
devices at the same time. devices at the same time.
## Interface ## Interface
### Constructors ```cpp
#include "AD985X.h"
```
- **AD9850()** 40 MHz signal generator #### Constructors
- **AD9851()** 70 MHz signal generator, derived from AD9850 with some extra options.
- **AD9850(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, SPIClassRP2040 \* mySPI, uint8_t spiClock)** hardware SPI constructor RP2040
### Common interface - **AD9850(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, SPIClass \* mySPI, uint8_t spiClock)** hardware SPI constructor
- **AD9850(uint8_t slaveSelect, uint8_t resetPin, uint8_t FQUDPin, uint8_t spiData, uint8_t spiClock)**
- **void begin(uint8_t selectPin, uint8_t resetPin, uint8_t FQUDPin, uint8_t dataOut = 0, uint8_t clock = 0)** - slaveSelect = chip select. The library uses HIGH as active and LOW as not selected.
For hardware SPI only use the first three parameters,
for SW SPI you need to define the data and clock pin too.
- selectPin = chip select. The library uses HIGH as active and LOW as not selected.
- resetPin = reset - resetPin = reset
- FQUD = Frequency UpDate Pin - FQUDPin = Frequency UpDate Pin
- **AD9851(...)** constructors with same interface as AD9850
#### Common interface
- **void begin()** initializes library internals.
- **void reset()** resets the function generator. - **void reset()** resets the function generator.
- **void powerDown()** idem. - **void powerDown()** idem.
- **void powerUp()** idem. - **void powerUp()** idem.
@ -206,7 +227,7 @@ Returns false if phase > 31, no change to phase in that case.
- multiply by (PI \* 0.0625) to get actual phase angle in radians. - multiply by (PI \* 0.0625) to get actual phase angle in radians.
### Calibration #### Calibration
**Warning:** use with care. **Warning:** use with care.
@ -218,7 +239,7 @@ Note: **reset()** resets the offset to 0..
Note: setting the offset reduces the range of frequencies (at the ends of scale). Note: setting the offset reduces the range of frequencies (at the ends of scale).
### Auto update / manual update #### Auto update / manual update
(new since 0.2.2) (new since 0.2.2)
@ -235,7 +256,7 @@ Note: The default of the autoUpdate flag is true.
Note: **reset()** resets the autoUpdateFlag to true. Note: **reset()** resets the autoUpdateFlag to true.
### Hardware SPI #### Hardware SPI
To be used only if one needs a specific speed. To be used only if one needs a specific speed.
@ -244,41 +265,7 @@ To be used only if one needs a specific speed.
- **bool usesHWSPI()** returns true if HW SPI is used. - **bool usesHWSPI()** returns true if HW SPI is used.
### ESP32 specific ## AD9851 additional
This functionality is new in 0.3.1.
- **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.
#### ESP32 experimental
- **void setGPIOpins(clk, miso, mosi, select)** overrule GPIO pins of ESP32 for hardware SPI.
Needs to be called AFTER the **begin()** function.
```cpp
void setup()
{
freqGen.selectVSPI();
freqGen.begin(15);
freqGen.setGPIOpins(CLK, MISO, MOSI, SELECT); // SELECT should match the param of begin()
...
}
```
### AD9850 specific
The AD9850 has no specific functions.
### AD9851 specific
- **void setRefClockHigh()** set reference clock to 180 Mhz. - **void setRefClockHigh()** set reference clock to 180 Mhz.
- **void setRefClockLow()** set reference clock to 30 Mhz. - **void setRefClockLow()** set reference clock to 30 Mhz.
@ -303,7 +290,7 @@ Maximum value is 30 MHz, typical is 10 MHz.
See examples. See examples.
### Operational notes #### Operational notes
- The quality of the signal becomes less at higher frequencies. - The quality of the signal becomes less at higher frequencies.
Switch the reference clock to find your optimal quality. Switch the reference clock to find your optimal quality.
@ -317,23 +304,25 @@ The user is also responsible to store it e.g. in EEPROM to make it persistent.
#### Must #### Must
- improve documentation
#### Should #### Should
- do tests on ESP32 - test on ESP32
- performance measurements - test on RP2040
#### Could #### Could
- performance measurements
- move code to .cpp - move code to .cpp
- create defines for MAGIC numbers (defaults) - create defines for MAGIC numbers (defaults)
- should **setSPIspeed(uint32_t speed)** return bool?
- out of range?
#### Wont #### Wont
- **bool setARCCutOffFreq()** no need - **bool setARCCutOffFreq()** no need
- should **setSPIspeed(uint32_t speed)** return bool?
- out of range?
- wave quality measurements
## Support ## Support

View File

@ -7,7 +7,18 @@
#include "AD985X.h" #include "AD985X.h"
AD9850 freqGen;
#ifndef ESP32
#error ESP32 only example, please select appropriate board
#endif
// HSPI uses default SCLK=14, MISO=12, MOSI=13, SELECT=15
// VSPI uses default SCLK=18, MISO=19, MOSI=23, SELECT=5
SPIClass * myspi = new SPIClass(VSPI);
AD9850 freqGen(10, 9, 8, myspi, 18); // HW SPI note the CLOCK pin param 18.
// AD9850 freqGen(10, 9, 8, 7, 6); // SW SPI
uint32_t freq = 0; uint32_t freq = 0;
uint32_t prev = 0; uint32_t prev = 0;
@ -23,9 +34,7 @@ void setup()
help(); help();
// Select HW SPI for ESP32 freqGen.begin();
freqGen.selectHSPI();
freqGen.begin(15, 16, 17); // selectPin, resetPin, FQUDPin
freqGen.powerUp(); freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency(); maxFreq = freqGen.getMaxFrequency();

View File

@ -7,7 +7,9 @@
#include "AD985X.h" #include "AD985X.h"
AD9850 freqGen; AD9850 freqGen(10, 9, 8, 7, 6); // SW SPI
// AD9850 freqGen(10, 9, 8, &SPI, 6); // HW SPI
uint32_t freq = 0; uint32_t freq = 0;
uint32_t prev = 0; uint32_t prev = 0;
@ -23,7 +25,7 @@ void setup()
help(); help();
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
freqGen.powerUp(); freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency(); maxFreq = freqGen.getMaxFrequency();
Serial.println(maxFreq); Serial.println(maxFreq);
@ -66,7 +68,7 @@ void loop()
if (freq > maxFreq) freq = maxFreq; if (freq > maxFreq) freq = maxFreq;
} }
// UPDATE AD985X IF NEW VALUE // UPDATE AD985X IF NEW VALUE
if (prev != freq) if (prev != freq)
{ {
prev = freq; prev = freq;
@ -90,4 +92,4 @@ void help()
Serial.println(); Serial.println();
} }
// -- END OF FILE -- // -- END OF FILE --

View File

@ -8,7 +8,8 @@
#include "AD985X.h" #include "AD985X.h"
AD9850 freqGen; AD9850 freqGen(10, 9, 8, 7, 6); // SW SPI
// AD9850 freqGen(10, 9, 8, &SPI, 6); // HW SPI
uint32_t freq = 0; uint32_t freq = 0;
uint32_t prev = 0; uint32_t prev = 0;
@ -24,7 +25,7 @@ void setup()
help(); help();
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
freqGen.powerUp(); freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency(); maxFreq = freqGen.getMaxFrequency();
Serial.println(maxFreq); Serial.println(maxFreq);
@ -67,7 +68,7 @@ void loop()
if (freq > maxFreq) freq = maxFreq; if (freq > maxFreq) freq = maxFreq;
} }
// UPDATE AD985X IF NEW VALUE // UPDATE AD985X IF NEW VALUE
if (prev != freq) if (prev != freq)
{ {
prev = freq; prev = freq;
@ -91,4 +92,4 @@ void help()
Serial.println(); Serial.println();
} }
// -- END OF FILE -- // -- END OF FILE --

View File

@ -32,11 +32,12 @@
#include "AD985X.h" #include "AD985X.h"
// we want to control three hardware devices // we want to control three hardware devices
// so we declare three software objects // so we declare three software objects
AD9850 freqGen0; // in this case all using HW SPI.
AD9850 freqGen1; AD9850 freqGen0(4, 9, 10, &SPI, 13); // 13 is UNO SPI clock pin.
AD9850 freqGen2; AD9850 freqGen1(2, 9, 10, &SPI, 13);
AD9850 freqGen2(3, 9, 10, &SPI, 13);
float freq0 = 25000; float freq0 = 25000;
float freq1 = 30000; float freq1 = 30000;
@ -57,21 +58,21 @@ uint32_t now;
void setup() void setup()
{ {
// OPEN SERIAL for messages and debugging etc // OPEN SERIAL for messages and debugging etc
Serial.begin(115200); Serial.begin(115200);
Serial.println(__FILE__); Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t"); Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION); Serial.println(AD985X_LIB_VERSION);
// initialize three devices // initialize three devices
freqGen0.begin(4, 9, 10); freqGen0.begin();
freqGen0.powerUp(); freqGen0.powerUp();
freqGen1.begin(2, 9, 10); freqGen1.begin();
freqGen1.powerUp(); freqGen1.powerUp();
freqGen2.begin(3, 9, 10); freqGen2.begin();
freqGen2.powerUp(); freqGen2.powerUp();
// MAXFREQ is the same for all devices // MAXFREQ is the same for all devices
maxFreq = freqGen0.getMaxFrequency(); maxFreq = freqGen0.getMaxFrequency();
Serial.println(maxFreq); Serial.println(maxFreq);
} }
@ -79,10 +80,10 @@ void setup()
void loop() void loop()
{ {
// get the time // get the time
now = millis(); now = millis();
// do we need to update 0 // do we need to update 0
if (now - previousMillis0 >= period0) if (now - previousMillis0 >= period0)
{ {
previousMillis0 = now; previousMillis0 = now;
@ -91,7 +92,7 @@ void loop()
Serial.println( (uint32_t) freq0); Serial.println( (uint32_t) freq0);
} }
// do we need to update 1 // do we need to update 1
if (now - previousMillis1 >= period1) if (now - previousMillis1 >= period1)
{ {
previousMillis1 = now; previousMillis1 = now;
@ -100,7 +101,7 @@ void loop()
Serial.println( (uint32_t) freq1); Serial.println( (uint32_t) freq1);
} }
// do we need to update 2 // do we need to update 2
if (now - previousMillis2 >= period2) if (now - previousMillis2 >= period2)
{ {
previousMillis0 = now; previousMillis0 = now;
@ -111,4 +112,4 @@ void loop()
} }
// -- END OF FILE -- // -- END OF FILE --

View File

@ -4,9 +4,9 @@
// PURPOSE: demo multi device // PURPOSE: demo multi device
// URL: https://github.com/RobTillaart/AD985X // URL: https://github.com/RobTillaart/AD985X
// measure speed difference when updating multiple devices // measure speed difference when updating multiple devices
// - sequentially // - sequentially
// - simultaneously // - simultaneously
#include "AD985X.h" #include "AD985X.h"
@ -20,13 +20,13 @@
#define RESET 9 #define RESET 9
#define FQ_UD 10 #define FQ_UD 10
// we want to control four hardware devices // we want to control four hardware devices
// so we declare three software objects // so we declare three software objects
AD9850 freqGen0; AD9850 freqGen0(SELECT1, RESET, FQ_UD, 11, 12);
AD9850 freqGen1; AD9850 freqGen1(SELECT2, RESET, FQ_UD, 11, 12);
AD9850 freqGen2; AD9850 freqGen2(SELECT3, RESET, FQ_UD, 11, 12);
AD9850 freqGen3; AD9850 freqGen3(SELECT4, RESET, FQ_UD, 11, 12);
AD9850 freqGen4; AD9850 freqGen4(SELECT5, RESET, FQ_UD, 11, 12);
float freq = 10000; float freq = 10000;
@ -40,15 +40,15 @@ void setup()
Serial.println(AD985X_LIB_VERSION); Serial.println(AD985X_LIB_VERSION);
// initialize three devices // initialize three devices
freqGen0.begin(SELECT1, RESET, FQ_UD, 11, 12); freqGen0.begin();
freqGen0.powerUp(); freqGen0.powerUp();
freqGen1.begin(SELECT2, RESET, FQ_UD, 11, 12); freqGen1.begin();
freqGen1.powerUp(); freqGen1.powerUp();
freqGen2.begin(SELECT3, RESET, FQ_UD, 11, 12); freqGen2.begin();
freqGen2.powerUp(); freqGen2.powerUp();
freqGen3.begin(SELECT4, RESET, FQ_UD, 11, 12); freqGen3.begin();
freqGen3.powerUp(); freqGen3.powerUp();
freqGen4.begin(SELECT5, RESET, FQ_UD, 11, 12); freqGen4.begin();
freqGen4.powerUp(); freqGen4.powerUp();
test1(); test1();

View File

@ -6,7 +6,7 @@
#include "AD985X.h" #include "AD985X.h"
AD9851 freqGen; AD9851 freqGen(10, 9, 8, 7, 6);
uint32_t freq = 0; uint32_t freq = 0;
uint32_t prev = 0; uint32_t prev = 0;
@ -22,7 +22,7 @@ void setup()
help(); help();
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
freqGen.powerUp(); freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency(); maxFreq = freqGen.getMaxFrequency();
Serial.println(maxFreq); Serial.println(maxFreq);

View File

@ -8,7 +8,7 @@
#include "AD985X.h" #include "AD985X.h"
AD9851 freqGen; AD9851 freqGen(10, 9, 8, 7, 6);
uint32_t freq = 0; uint32_t freq = 0;
uint32_t prev = 0; uint32_t prev = 0;
@ -24,7 +24,8 @@ void setup()
help(); help();
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
freqGen.powerUp(); freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency(); maxFreq = freqGen.getMaxFrequency();
Serial.print(" MAX_FREQ: "); Serial.print(" MAX_FREQ: ");

View File

@ -7,7 +7,7 @@
#include "AD985X.h" #include "AD985X.h"
AD9851 freqGen; AD9851 freqGen(10, 9, 8, 7, 6);
uint32_t freq = 0; uint32_t freq = 0;
uint32_t prev = 0; uint32_t prev = 0;
@ -23,7 +23,7 @@ void setup()
help(); help();
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
freqGen.powerUp(); freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency(); maxFreq = freqGen.getMaxFrequency();
Serial.println(maxFreq); Serial.println(maxFreq);

View File

@ -8,7 +8,7 @@
#include "AD985X.h" #include "AD985X.h"
AD9851 freqGen; AD9851 freqGen(10, 9, 8, 7, 6);
uint32_t freq = 0; uint32_t freq = 0;
uint32_t maxFreq = 2000000UL; uint32_t maxFreq = 2000000UL;
@ -17,6 +17,7 @@ bool up = true;
uint32_t lastUpdate = 0; uint32_t lastUpdate = 0;
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
@ -24,7 +25,7 @@ void setup()
Serial.print("AD985X_LIB_VERSION: \t"); Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION); Serial.println(AD985X_LIB_VERSION);
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
freqGen.powerUp(); freqGen.powerUp();
freqGen.setAutoRefClock(true); freqGen.setAutoRefClock(true);
@ -55,8 +56,8 @@ void loop()
} }
freqGen.setFrequency(freq); freqGen.setFrequency(freq);
// only update once per second // only update once per second
// effectively have a random frequency // effectively have a random frequency
if (millis() - lastUpdate >= 1000) if (millis() - lastUpdate >= 1000)
{ {
lastUpdate = millis(); lastUpdate = millis();
@ -67,4 +68,6 @@ void loop()
} }
} }
// -- END OF FILE --
// -- END OF FILE --

View File

@ -8,7 +8,7 @@
#include "AD985X.h" #include "AD985X.h"
AD9851 freqGen; AD9851 freqGen(10, 9, 8, 7, 6);
void setup() void setup()
@ -18,7 +18,7 @@ void setup()
Serial.print("AD985X_LIB_VERSION: \t"); Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION); Serial.println(AD985X_LIB_VERSION);
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
} }
@ -46,4 +46,4 @@ float readFreq(bool KHZ)
return freq; return freq;
} }
// END OF FILE // -- END OF FILE --

View File

@ -8,7 +8,7 @@
#include "AD985X.h" #include "AD985X.h"
AD9851 freqGen; AD9851 freqGen(10, 9, 8, 7, 6);
uint32_t freq = 0; uint32_t freq = 0;
uint32_t maxFreq = 2000000UL; uint32_t maxFreq = 2000000UL;
@ -23,7 +23,7 @@ void setup()
Serial.print("AD985X_LIB_VERSION: \t"); Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION); Serial.println(AD985X_LIB_VERSION);
freqGen.begin(10, 9, 8, 7, 6); freqGen.begin();
freqGen.powerUp(); freqGen.powerUp();
freqGen.setAutoRefClock(true); freqGen.setAutoRefClock(true);
@ -53,4 +53,4 @@ void loop()
delay(50); delay(50);
} }
// -- END OF FILE -- // -- END OF FILE --

View File

@ -33,8 +33,14 @@
// three AD9850 objects in an array // three AD9850 objects in an array
AD9850 freqGen[3]; AD9850 freqGen[3]
uint8_t SELECT[3] = { 2, 3, 4 }; {
AD9850(2, 9, 8, 7, 6),
AD9850(3, 9, 8, 7, 6),
AD9850(4, 9, 8, 7, 6),
};
float freq[3] = { 25000, 30000, 40000 }; float freq[3] = { 25000, 30000, 40000 };
uint32_t previous[3] = { 0, 0, 0 }; uint32_t previous[3] = { 0, 0, 0 };
uint32_t period[3] = { 1000, 1100, 1200 }; uint32_t period[3] = { 1000, 1100, 1200 };
@ -51,11 +57,11 @@ void setup()
Serial.print("AD985X_LIB_VERSION: \t"); Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION); Serial.println(AD985X_LIB_VERSION);
// initialize three devices // initialize three devices
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
// select, reset, fq_ud, data, clock // select, reset, fq_ud, data, clock
freqGen[i].begin(SELECT[i], 9, 8, 7, 6); freqGen[i].begin();
freqGen[i].powerUp(); freqGen[i].powerUp();
freqGen[i].setFrequencyF(freq[i]); freqGen[i].setFrequencyF(freq[i]);
} }
@ -70,7 +76,7 @@ void loop()
{ {
now = millis(); now = millis();
// update any of the devices? // update any of the devices?
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
if ( now - previous[i] >= period[i] ) if ( now - previous[i] >= period[i] )
@ -89,4 +95,4 @@ void loop()
} }
// -- END OF FILE -- // -- END OF FILE --

View File

@ -15,7 +15,7 @@
"type": "git", "type": "git",
"url": "https://github.com/RobTillaart/AD985X.git" "url": "https://github.com/RobTillaart/AD985X.git"
}, },
"version": "0.3.6", "version": "0.4.0",
"license": "MIT", "license": "MIT",
"frameworks": "*", "frameworks": "*",
"platforms": "*", "platforms": "*",

View File

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

View File

@ -27,7 +27,7 @@
unittest_setup() unittest_setup()
{ {
fprintf(stderr, "AD985X_LIB_VERSION: %s\n", AD985X_LIB_VERSION); fprintf(stderr, "AD985X_LIB_VERSION: %s\n", (char *) AD985X_LIB_VERSION);
} }
@ -45,8 +45,8 @@ unittest(test_constants)
unittest(test_constructor) unittest(test_constructor)
{ {
AD9850 funcgen0; AD9850 funcgen0(10, 9, 8, 7, 6); // SW SPI
AD9851 funcgen1; AD9851 funcgen1(10, 11, 12, 13, 14);
assertEqual(AD9850_MAX_FREQ, funcgen0.getMaxFrequency()); assertEqual(AD9850_MAX_FREQ, funcgen0.getMaxFrequency());
assertEqual(AD9851_MAX_FREQ, funcgen1.getMaxFrequency()); assertEqual(AD9851_MAX_FREQ, funcgen1.getMaxFrequency());
@ -55,10 +55,10 @@ unittest(test_constructor)
unittest(test_auto_update) unittest(test_auto_update)
{ {
AD9850 funcgen0; AD9850 funcgen0(10, 9, 8, 7, 6); // SW SPI
AD9851 funcgen1; AD9851 funcgen1(10, 11, 12, 13, 14);
funcgen0.begin(4, 5, 6); funcgen0.begin();
funcgen1.begin(10, 11, 16); funcgen1.begin();
assertTrue(funcgen0.getAutoUpdate()); assertTrue(funcgen0.getAutoUpdate());
@ -76,8 +76,8 @@ unittest(test_auto_update)
unittest(test_ad9850_frequency) unittest(test_ad9850_frequency)
{ {
AD9850 funcgen; AD9850 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
for (uint32_t freq = 500; freq <= 10000; freq += 500) for (uint32_t freq = 500; freq <= 10000; freq += 500)
{ {
@ -89,8 +89,8 @@ unittest(test_ad9850_frequency)
unittest(test_ad9851_frequency) unittest(test_ad9851_frequency)
{ {
AD9851 funcgen; AD9851 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
for (uint32_t freq = 500; freq <= 10000; freq += 500) for (uint32_t freq = 500; freq <= 10000; freq += 500)
{ {
@ -102,8 +102,8 @@ unittest(test_ad9851_frequency)
unittest(test_ad9850_frequency_float) unittest(test_ad9850_frequency_float)
{ {
AD9850 funcgen; AD9850 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
for (float freq = 1; freq <= 5; freq += 0.31415) for (float freq = 1; freq <= 5; freq += 0.31415)
{ {
@ -115,8 +115,8 @@ unittest(test_ad9850_frequency_float)
unittest(test_ad9851_frequency_float) unittest(test_ad9851_frequency_float)
{ {
AD9851 funcgen; AD9851 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
for (float freq = 1; freq <= 5; freq += 0.31415) for (float freq = 1; freq <= 5; freq += 0.31415)
{ {
@ -128,8 +128,8 @@ unittest(test_ad9851_frequency_float)
unittest(test_ad9850_phase) unittest(test_ad9850_phase)
{ {
AD9850 funcgen; AD9850 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
funcgen.setFrequency(1000); funcgen.setFrequency(1000);
long freq = funcgen.getFrequency(); long freq = funcgen.getFrequency();
@ -146,8 +146,8 @@ unittest(test_ad9850_phase)
unittest(test_ad9851_phase) unittest(test_ad9851_phase)
{ {
AD9851 funcgen; AD9851 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
funcgen.setFrequency(1000); funcgen.setFrequency(1000);
long freq = funcgen.getFrequency(); long freq = funcgen.getFrequency();
@ -169,8 +169,8 @@ unittest(test_ad9851_phase)
unittest(test_ad9851_reset) unittest(test_ad9851_reset)
{ {
AD9851 funcgen; AD9851 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
funcgen.setFrequency(1000); funcgen.setFrequency(1000);
assertEqual(1000, funcgen.getFrequency()); assertEqual(1000, funcgen.getFrequency());
@ -189,8 +189,8 @@ unittest(test_ad9851_reset)
unittest(test_ad9851_autoRefClock) unittest(test_ad9851_autoRefClock)
{ {
AD9851 funcgen; AD9851 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
assertFalse(funcgen.getAutoRefClock()); assertFalse(funcgen.getAutoRefClock());
for (uint32_t freq = 70; freq <= 70000000; freq *= 10) for (uint32_t freq = 70; freq <= 70000000; freq *= 10)
@ -232,8 +232,8 @@ unittest(test_ad9851_autoRefClock)
unittest(test_ad9851_offset) unittest(test_ad9851_offset)
{ {
AD9851 funcgen; AD9851 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
assertEqual(0, funcgen.getCalibration()); assertEqual(0, funcgen.getCalibration());
funcgen.setFrequency(1000000); funcgen.setFrequency(1000000);
@ -253,8 +253,8 @@ unittest(test_ad9851_offset)
unittest(test_ad9851_float_freq) unittest(test_ad9851_float_freq)
{ {
AD9851 funcgen; AD9851 funcgen(10, 9, 8, 7, 6); // SW SPI
funcgen.begin(4, 5, 6); funcgen.begin();
for (float f = 100.0; f < 110.0; f += 0.1) for (float f = 100.0; f < 110.0; f += 0.1)
{ {
@ -267,4 +267,4 @@ unittest(test_ad9851_float_freq)
unittest_main() unittest_main()
// END OF FILE -- // -- END OF FILE --