GY-63_MS5611/libraries/AD9833/AD9833.cpp

330 lines
6.6 KiB
C++
Raw Normal View History

2023-08-27 14:28:30 -04:00
//
// FILE: AD9833.cpp
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino library for AD9833 function generator
2023-10-16 09:53:57 -04:00
// VERSION: 0.1.2
2023-08-27 14:28:30 -04:00
// 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;
2023-09-03 04:16:41 -04:00
_useSelect = (_selectPin != 255);
if (_useSelect)
{
pinMode(_selectPin, OUTPUT);
digitalWrite(_selectPin, HIGH);
}
2023-08-27 14:28:30 -04:00
_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);
2023-09-03 04:16:41 -04:00
digitalWrite(_clockPin, HIGH);
2023-08-27 14:28:30 -04:00
}
reset();
}
void AD9833::begin(uint8_t selectPin, SPIClass * spi)
{
_selectPin = selectPin;
2023-09-03 04:16:41 -04:00
_useSelect = (_selectPin != 255);
if (_useSelect)
{
pinMode(_selectPin, OUTPUT);
digitalWrite(_selectPin, HIGH);
}
2023-08-27 14:28:30 -04:00
_hwSPI = true;
_spi_settings = SPISettings(8000000, MSBFIRST, SPI_MODE2);
mySPI = spi;
mySPI->end();
mySPI->begin();
reset();
}
void AD9833::reset()
{
2023-09-03 04:16:41 -04:00
hardwareReset();
_control = AD9833_B28;
writeControlRegister(_control);
}
void AD9833::hardwareReset()
{
writeControlRegister(_control | 0x0100);
// reset all library variables to be in "sync" with hardware.
_control = 0;
_waveform = AD9833_OFF;
_freq[0] = _freq[1] = 0;
_phase[0] = _phase[1] = 0;
}
bool AD9833::setPowerMode(uint8_t mode)
{
if (mode > 3) return false;
_control &= 0xFF3F; // clear previous power flags
_control |= (mode << 6); // set the new power flags
writeControlRegister(_control);
return true;
2023-08-27 14:28:30 -04:00
}
2023-09-03 04:16:41 -04:00
void AD9833::setWave(uint8_t waveform)
2023-08-27 14:28:30 -04:00
{
2023-09-03 04:16:41 -04:00
if (waveform > 4) return;
2023-08-27 14:28:30 -04:00
2023-09-03 04:16:41 -04:00
// store waveform
_waveform = waveform;
2023-08-27 14:28:30 -04:00
// clear bits in control register
2023-10-16 09:53:57 -04:00
_control &= ~(AD9833_SLEEP1 | AD9833_SLEEP12 | AD9833_OPBITEN | AD9833_MODE | AD9833_DIV2);
2023-08-27 14:28:30 -04:00
// set bits in control register
2023-09-03 04:16:41 -04:00
switch(_waveform)
2023-08-27 14:28:30 -04:00
{
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()
{
2023-09-03 04:16:41 -04:00
return _waveform;
2023-08-27 14:28:30 -04:00
}
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
2023-09-03 04:16:41 -04:00
uint32_t fr = round(_freq[channel] * (268435456.0 / 25000000.0));
2023-08-27 14:28:30 -04:00
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
2023-09-03 04:16:41 -04:00
data |= (freq & 0x3FFF); // least significant 14 bits
2023-08-27 14:28:30 -04:00
writeData(data);
2023-09-03 04:16:41 -04:00
data &= 0xC000; // remove freq data LSB
data |= (freq >> 14); // most significant 14 bits
2023-08-27 14:28:30 -04:00
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)
{
2023-09-03 04:16:41 -04:00
if (_useSelect) digitalWrite(_selectPin, LOW);
2023-08-27 14:28:30 -04:00
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)
{
2023-09-03 04:16:41 -04:00
digitalWrite(dao, (data & mask) !=0 ? HIGH : LOW);
2023-08-27 14:28:30 -04:00
digitalWrite(clk, LOW);
digitalWrite(clk, HIGH);
}
digitalWrite(dao, LOW);
}
2023-09-03 04:16:41 -04:00
if (_useSelect) digitalWrite(_selectPin, HIGH);
2023-08-27 14:28:30 -04:00
}
// -- END OF FILE --