mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.3.1 AD985X
This commit is contained in:
parent
8eb4fbc88f
commit
3caa56c6cd
@ -4,10 +4,14 @@ name: Arduino CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
arduino_ci:
|
||||
runTest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Arduino-CI/action@master
|
||||
# Arduino-CI/action@v0.1.1
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
- run: |
|
||||
gem install arduino_ci
|
||||
arduino_ci.rb
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: AD985X.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.3.1
|
||||
// DATE: 2019-02-08
|
||||
// PURPOSE: Class for AD9850 and AD9851 function generator
|
||||
//
|
||||
@ -16,6 +16,9 @@
|
||||
// inverted SELECT line as preparation for multidevice.
|
||||
// 0.3.0 2021-06-06 fix factory bit mask + new examples + some refactor
|
||||
// added multi device document
|
||||
// 0.3.1 2021-08-25 VSPI / HSPI support for ESP32
|
||||
// faster software SPI
|
||||
// minor optimizations / refactor
|
||||
|
||||
|
||||
#include "AD985X.h"
|
||||
@ -45,40 +48,75 @@ void AD9850::begin(uint8_t select, uint8_t resetPin, uint8_t FQUDPin, uint8_t da
|
||||
_select = select;
|
||||
_reset = resetPin;
|
||||
_fqud = FQUDPin;
|
||||
_dataOut = dataOut;
|
||||
_clock = clock;
|
||||
// following 3 are always set.
|
||||
pinMode(_select, OUTPUT);
|
||||
pinMode(_reset, OUTPUT);
|
||||
pinMode(_fqud, OUTPUT);
|
||||
digitalWrite(_select, LOW); // 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(_reset, LOW);
|
||||
digitalWrite(_fqud, LOW);
|
||||
_useHW = true;
|
||||
|
||||
// SW SPI
|
||||
if ((dataOut != 0) && (clock != 0))
|
||||
_hwSPI = ((dataOut == 0) || (clock == 0));
|
||||
|
||||
_spi_settings = SPISettings(2000000, LSBFIRST, SPI_MODE0);
|
||||
|
||||
if (_hwSPI)
|
||||
{
|
||||
#if defined(ESP32)
|
||||
if (_useHSPI) // HSPI
|
||||
{
|
||||
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
|
||||
{
|
||||
_dataOut = dataOut;
|
||||
_clock = clock;
|
||||
pinMode(_dataOut, OUTPUT);
|
||||
pinMode(_clock, OUTPUT);
|
||||
digitalWrite(_dataOut, LOW);
|
||||
digitalWrite(_clock, LOW);
|
||||
_useHW = false;
|
||||
}
|
||||
|
||||
if (_useHW)
|
||||
{
|
||||
SPI.begin(); // set MOSI & MISO pin right.
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
digitalWrite(_select, HIGH); // be sure to select the correct device
|
||||
// be sure to select the correct device
|
||||
digitalWrite(_select, HIGH);
|
||||
pulsePin(_reset);
|
||||
if (_useHW) pulsePin(SPI_CLOCK);
|
||||
if (_hwSPI) pulsePin(SPI_CLOCK);
|
||||
else pulsePin(_clock);
|
||||
digitalWrite(_select, LOW);
|
||||
|
||||
@ -121,6 +159,13 @@ void AD9850::pulsePin(uint8_t pin)
|
||||
}
|
||||
|
||||
|
||||
void AD9850::setSPIspeed(uint32_t speed)
|
||||
{
|
||||
_SPIspeed = speed;
|
||||
_spi_settings = SPISettings(_SPIspeed, LSBFIRST, SPI_MODE0);
|
||||
};
|
||||
|
||||
|
||||
void AD9850::writeData()
|
||||
{
|
||||
// Serial.println(_factor, HEX);
|
||||
@ -129,17 +174,17 @@ void AD9850::writeData()
|
||||
|
||||
// used for multidevice config only - https://github.com/RobTillaart/AD985X/issues/13
|
||||
digitalWrite(_select, HIGH);
|
||||
if (_useHW)
|
||||
if (_hwSPI)
|
||||
{
|
||||
SPI.beginTransaction(SPISettings(2000000, LSBFIRST, SPI_MODE0));
|
||||
SPI.transfer(data & 0xFF);
|
||||
mySPI->beginTransaction(_spi_settings);
|
||||
mySPI->transfer(data & 0xFF);
|
||||
data >>= 8;
|
||||
SPI.transfer(data & 0xFF);
|
||||
mySPI->transfer(data & 0xFF);
|
||||
data >>= 8;
|
||||
SPI.transfer(data & 0xFF);
|
||||
SPI.transfer(data >> 8);
|
||||
SPI.transfer(_config & 0xFC); // mask factory test bit
|
||||
SPI.endTransaction();
|
||||
mySPI->transfer(data & 0xFF);
|
||||
mySPI->transfer(data >> 8);
|
||||
mySPI->transfer(_config & 0xFC); // mask factory test bit
|
||||
mySPI->endTransaction();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -160,14 +205,16 @@ void AD9850::writeData()
|
||||
|
||||
|
||||
// simple one mode version
|
||||
void AD9850::swSPI_transfer(uint8_t value)
|
||||
void AD9850::swSPI_transfer(uint8_t val)
|
||||
{
|
||||
uint8_t clk = _clock;
|
||||
uint8_t dao = _dataOut;
|
||||
// for (uint8_t mask = 0x80; mask; mask >>= 1) // MSBFIRST
|
||||
for (uint8_t mask = 0x01; mask; mask <<= 1) // LSBFIRST
|
||||
{
|
||||
digitalWrite(_dataOut,(value & mask) != 0);
|
||||
digitalWrite(_clock, HIGH);
|
||||
digitalWrite(_clock, LOW);
|
||||
digitalWrite(dao, (val & mask));
|
||||
digitalWrite(clk, HIGH);
|
||||
digitalWrite(clk, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: AD985X.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.3.1
|
||||
// DATE: 2019-02-08
|
||||
// PURPOSE: Class for AD9850 and AD9851 function generator
|
||||
//
|
||||
@ -14,7 +14,7 @@
|
||||
#include "SPI.h"
|
||||
|
||||
|
||||
#define AD985X_LIB_VERSION (F("0.3.0"))
|
||||
#define AD985X_LIB_VERSION (F("0.3.1"))
|
||||
|
||||
|
||||
#define AD9850_MAX_FREQ (40UL * 1000UL * 1000UL)
|
||||
@ -53,13 +53,40 @@ public:
|
||||
bool getAutoUpdate() { return _autoUpdate; };
|
||||
void update();
|
||||
|
||||
// speed in Hz
|
||||
void setSPIspeed(uint32_t speed);
|
||||
uint32_t getSPIspeed() { return _SPIspeed; };
|
||||
|
||||
// debugging
|
||||
bool usesHWSPI() { return _hwSPI; };
|
||||
|
||||
// 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:
|
||||
void pulsePin(uint8_t pin);
|
||||
void writeData();
|
||||
void swSPI_transfer(uint8_t value);
|
||||
void swSPI_transfer(uint8_t val);
|
||||
|
||||
bool _hwSPI = true;
|
||||
uint32_t _SPIspeed = 2000000;
|
||||
|
||||
SPIClass * mySPI;
|
||||
SPISettings _spi_settings;
|
||||
|
||||
#if defined(ESP32)
|
||||
bool _useHSPI = true;
|
||||
#endif
|
||||
|
||||
bool _useHW = true;
|
||||
// PINS
|
||||
uint8_t _dataOut = 0;
|
||||
uint8_t _clock = 0;
|
||||
|
@ -1,8 +1,11 @@
|
||||
|
||||
[![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)
|
||||
[![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)
|
||||
|
||||
|
||||
# AD985X
|
||||
|
||||
Arduino library for AD9850 and AD9851 function generators.
|
||||
@ -11,7 +14,7 @@ Arduino library for AD9850 and AD9851 function generators.
|
||||
## Description
|
||||
|
||||
Library for the AD9850 and AD9851 function generators.
|
||||
The library has a AD9850 base class that implements the commonalities.
|
||||
The library has a AD9850 as base class that implements the commonalities.
|
||||
The AD9851 is derived and has its own **setFrequency()** methods.
|
||||
Furthermore the AD9851 also has function to select the reference clock,
|
||||
a feature the AD9850 does not have.
|
||||
@ -152,28 +155,28 @@ devices at the same time.
|
||||
|
||||
### Common interface
|
||||
|
||||
- **begin(selectPin, resetPin, FQUDPin, dataOut = 0, clock = 0)**
|
||||
- **void begin(selectPin, resetPin, FQUDPin, dataOut = 0, clock = 0)**
|
||||
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
|
||||
- FQUD = Frequency UpDate Pin
|
||||
- **reset()** resets the function generator.
|
||||
- **powerDown()** idem
|
||||
- **powerUp()** idem
|
||||
- **setFrequency(uint32_t freq)** SetFrequency sets the frequency and is limited by the
|
||||
- **void reset()** resets the function generator.
|
||||
- **void powerDown()** idem
|
||||
- **void powerUp()** idem
|
||||
- **void setFrequency(uint32_t freq)** SetFrequency sets the frequency and is limited by the
|
||||
MaxFrequency of the class used. For the AD9850 => 40 MHz, for the AD9851 => 70 MHz.
|
||||
- Note that the quality of the signal gets less at higher frequencies.
|
||||
- Note setFrequency is affected by the autoUpdateFlag.
|
||||
- **setFrequencyF(float freq)** SetFrequencyF sets the frequency with a float with a maximum of **two** decimals.
|
||||
- Note that a float only has a mantisse of 6-7 digits so above ~1.000.000 decimals are lost.
|
||||
- **void setFrequencyF(float freq)** SetFrequencyF sets the frequency with a float with a maximum of **two** decimals.
|
||||
- Note that a float only has a mantissa of 6-7 digits so for frequencies above above ~1.000.000 = 1MHz all decimals are lost.
|
||||
- Note setFrequencyF is affected by the autoUpdateFlag.
|
||||
- **getMaxFrequency()** returns the maximum frequency setable. For the AD9850 this is 20 MHz.
|
||||
- **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.
|
||||
- **getFrequency()** returns the frequency set. As it returns a float it might loose some accuracy at higher frequencies.
|
||||
- **setPhase(uint8_t phase = 0)** set the phase in units of 11.25° 0..31 allowed.
|
||||
- **float getFrequency()** returns the frequency set. As it returns a float it might loose some accuracy at higher frequencies.
|
||||
- **void setPhase(uint8_t phase = 0)** set the phase in units of 11.25° 0..31 allowed.
|
||||
Default it sets the phase to 0.
|
||||
- **getPhase()** returns the phase set, 0 by default.
|
||||
- **uint8_t getPhase()** returns the phase set, 0 by default. One need to multiply by 11.25° to get the actual angle.
|
||||
|
||||
|
||||
### Calibration
|
||||
@ -194,7 +197,7 @@ Note: setting the offset reduces the range of frequencies (at the ends of scale)
|
||||
|
||||
**Warning:** use with care.
|
||||
|
||||
- **void setAutoUpdate(bool update)** sets the autoUpdate flag, default it is true.
|
||||
- **void setAutoUpdate(bool update)** sets the autoUpdate flag, default set to true.
|
||||
- **bool getAutoUpdate()** reads the autoUpdate flag.
|
||||
- **void update()** manually toggle the FQ_UD flag to update the frequency.
|
||||
|
||||
@ -205,20 +208,59 @@ The default of the flag is true, and will be reset to true by the **reset()** ca
|
||||
|
||||
|
||||
|
||||
### 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
|
||||
|
||||
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
|
||||
|
||||
- **setRefClockHigh()** set reference clock to 180 Mhz.
|
||||
- **setRefClockLow()** set reference clock to 30 Mhz.
|
||||
- **getRefClock()** returns 30 or 180.
|
||||
- **setAutoRefClock(bool arc)** sets a flag so the library switches automatically
|
||||
- **void setRefClockHigh()** set reference clock to 180 Mhz.
|
||||
- **void setRefClockLow()** set reference clock to 30 Mhz.
|
||||
- **uint8_t getRefClock()** returns 30 or 180.
|
||||
- **void setAutoRefClock(bool arc)** sets a flag so the library switches automatically
|
||||
to the reference clock of 180 MHz when the frequency is set above 10 MHz and
|
||||
to 30 MHz when the frequency is set to 10 MHz or lower.
|
||||
The initial value is **false** == OFF for backwards compatibility.
|
||||
- **getAutoRefClock()** returns true is automode is set.
|
||||
- **bool getAutoRefClock()** returns true is automode is set.
|
||||
- **void setARCCutOffFreq(uint32_t Hz = 10000000UL )** set cut off frequency
|
||||
for the auto reference clock. max value is 30 MHz, typical 10MHz
|
||||
- **uint32_t getARCCutOffFreq()** returns cut off frequency set.
|
||||
@ -236,9 +278,16 @@ See examples
|
||||
### Operational notes
|
||||
|
||||
- The quality of the signal becomes less at higher frequencies.
|
||||
Switch the refclock to find your optimal quality.
|
||||
Switch the reference clock to find your optimal quality.
|
||||
- If the calibration offset is not 0, it needs to be set by the user after every startup,
|
||||
and after switching the reference clock.
|
||||
The user is also responsible to store it e.g. in EEPROM to make it persistent.
|
||||
- Experimental parts may change or removed in the future.
|
||||
|
||||
|
||||
## Future
|
||||
|
||||
- test library with an ESP32 (check details)
|
||||
- examples for ESP32 HWSPI interface
|
||||
- performance measurements
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Syntax Coloring Map For AD985X
|
||||
# Syntax Colouring Map For AD985X
|
||||
|
||||
# Data types (KEYWORD1)
|
||||
AD9850 KEYWORD1
|
||||
@ -25,7 +25,6 @@ getAutoRefClock KEYWORD2
|
||||
setARCCutOffFreq KEYWORD2
|
||||
getARCCutOffFreq KEYWORD2
|
||||
|
||||
|
||||
setCalibration KEYWORD2
|
||||
getCalibration KEYWORD2
|
||||
getFactor KEYWORD2
|
||||
@ -33,6 +32,16 @@ setAutoUpdate KEYWORD2
|
||||
getAutoUpdate KEYWORD2
|
||||
update KEYWORD2
|
||||
|
||||
setSPIspeed KEYWORD2
|
||||
getSPIspeed KEYWORD2
|
||||
usesHWSPI KEYWORD2
|
||||
|
||||
selectHSPI KEYWORD2
|
||||
selectVSPI KEYWORD2
|
||||
usesHSPI KEYWORD2
|
||||
usesVSPI KEYWORD2
|
||||
setGPIOpins KEYWORD2
|
||||
|
||||
|
||||
# Constants (LITERAL1)
|
||||
AD9850_MAX_FREQ LITERAL1
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/AD985X.git"
|
||||
},
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=AD985X
|
||||
version=0.3.0
|
||||
version=0.3.1
|
||||
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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user