Library for interfacing with AD9837, generate Sine/Triangular/Square wave
Revision 0:fdfd54fe27dc, committed 2015-06-30
- Comitter:
- nicolas97
- Date:
- Tue Jun 30 08:25:56 2015 +0000
- Commit message:
- Library to interface with AD9837 (function generator)
Changed in this revision
AD9837.cpp | Show annotated file Show diff for this revision Revisions of this file |
AD9837.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r fdfd54fe27dc AD9837.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AD9837.cpp Tue Jun 30 08:25:56 2015 +0000 @@ -0,0 +1,67 @@ +#include "AD9837.h" +#include "mbed.h" + +#define REG_FREQ1 0x8000 +#define REG_FREQ0 0x4000 +#define REG_PHASE0 0xC000 +#define REG_PHASE1 0xE000 + +#define REG_B28 0x2000 +#define REG_HLB 0x1000 +#define REG_FSEL 0x0800 +#define REG_PSEL 0x0400 +#define REG_PINSW 0x0200 +#define REG_RESET 0x0100 +#define REG_SLEEP1 0x0080 +#define REG_SLEEP12 0x0040 +#define REG_OPBITEN 0x0020 +#define REG_SIGNPIB 0x0010 +#define REG_DIV2 0x0008 +#define REG_MODE 0x0002 + +#define SIGN_OUTPUT_MASK (REG_OPBITEN | REG_SIGNPIB | REG_DIV2 | REG_MODE) + +AD9837::AD9837(PinName mosi, PinName miso, PinName sclk, PinName cs) : _spi(mosi, miso, sclk), _cs(cs) { + + _spi.format(8, 2); + _spi.frequency(1000000); +} + +void AD9837::writeReg(uint16_t value) +{ + _cs=0; + wait_us(10); + _spi.write(value >> 8); + _spi.write(value & 0xFF); + wait_us(10); + _cs=1; +} + +void AD9837::setFrequencyWord(unsigned int reg, uint32_t frequency) +{ + writeReg((reg?REG_FREQ1:REG_FREQ0) | (frequency & 0x3FFF)); + writeReg((reg?REG_FREQ1:REG_FREQ0) | ((frequency >> 14) & 0x3FFF)); +} + +void AD9837::setPhaseWord(unsigned int reg, uint32_t phase) +{ + writeReg((reg?REG_PHASE1:REG_PHASE0) | (phase & 0x0FFF)); +} + +void AD9837::setSignOutput(SignOutput out) +{ + m_reg = (m_reg & ~SIGN_OUTPUT_MASK) | out; + writeReg(m_reg); +} + +void AD9837::setOutputMode(OutputMode out) +{ + if(out == OUTPUT_MODE_TRIANGLE) { + m_reg = (m_reg & ~SIGN_OUTPUT_MASK) | out; + } if(out == OUTPUT_MODE_SINE) { + m_reg &= ~REG_MODE; + }else { + m_reg = 0x2A; + } + writeReg(m_reg); +} \ No newline at end of file
diff -r 000000000000 -r fdfd54fe27dc AD9837.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AD9837.h Tue Jun 30 08:25:56 2015 +0000 @@ -0,0 +1,52 @@ +#include "mbed.h" + +enum SignOutput { + SIGN_OUTPUT_NONE = 0x0000, + SIGN_OUTPUT_MSB = 0x0028, + SIGN_OUTPUT_MSB_2 = 0x0020, + SIGN_OUTPUT_COMPARATOR = 0x0038, +}; + +enum OutputMode { + OUTPUT_MODE_SINE = 0x0000, + OUTPUT_MODE_TRIANGLE = 0x0002, + OUTPUT_MODE_SQUARE = 0x0004, +}; + +class AD9837 +{ +public: + AD9837(PinName mosi, PinName miso, PinName sclk, PinName cs); + void setFrequencyWord(unsigned int reg, uint32_t frequency); + void setPhaseWord(unsigned int reg, uint32_t phase); + void setSignOutput(SignOutput out); + void setOutputMode(OutputMode out); + + inline uint32_t computeFrequencyWord(uint32_t frequency) { + // This is a manual expansion of (frequency * 2^28) / m_frequency_mhz + // Since it doesn't require 64 bit multiplies or divides, it results in + // substantially smaller code sizes. + uint32_t lval = ((frequency & 0xFF) << 22) / (15625l * m_frequency_mhz); + uint32_t mval = ((frequency & 0xFF00) << 14) / (15625l * m_frequency_mhz); + uint32_t hval = ((frequency & 0xFF0000) << 6) / (15625l * m_frequency_mhz); + return (hval << 16) + (mval << 8) + lval; + } + + inline void setFrequency(unsigned char reg, long int frequency) { + frequency = this->computeFrequencyWord(frequency); + this->setFrequencyWord(reg, frequency); + } + + inline void setFrequency(unsigned char reg, float frequency) { + this->setFrequencyWord(reg, (frequency * (1l << 28)) / (m_frequency_mhz * 1000000)); + } + +protected: + void writeReg(uint16_t value); + int m_frequency_mhz; + uint16_t m_reg; + +private: + SPI _spi; + DigitalOut _cs; +}; \ No newline at end of file