Part Number: MSPM0G3507
Other Parts Discussed in Thread: DAC80508
Hello,
I am using a SPI polling method for eight channel data transfer from a LP-MSPM0G3507 EVM and a DAC80508MC Chip.
My goal is to generate sine waves in the 20-27khz range. Currently the output looks more like an AM wave and after the 3 step increase the value drops below zero before reaching the next step increase.
I think the issue is related to one of the following
- Manual CS pin is deasserting during the data byte transfer and interrupt output.
- MCLK doesn’t have the bandwidth to output these frequencies on all 8 channels at once
- Issue with the delay time.
Below I have provided the 3 main files:
Main file:
#include "ti_msp_dl_config.h"
#include <math.h>
#include <stdint.h>
#include "dacINIT.h"
#define SINE_N 256u
#define SINE_AMPL 1.0f
#define MID_CODE 32768u
#define SAMPLE_DELAY 160u
#define NUM_CHANNELS 8
#define ACTUAL_FS 45455.0f
volatile uint32_t dbg_loopCount = 0;
volatile uint16_t dbg_lastVal0 = 0;
volatile uint8_t dbg_idx0 = 0;
/* Target frequencies */
static const float freqs[NUM_CHANNELS] = {
20000.0f, 21000.0f, 22000.0f, 23000.0f,
24000.0f, 25000.0f, 26000.0f, 27000.0f
};
/* 32-bit DDS */
typedef struct { uint32_t phase, step; } DDS_t;
static DDS_t dds[NUM_CHANNELS];
static void init_DDS(void)
{
for (int i = 0; i < NUM_CHANNELS; i++)
{
dds[i].phase = 0;
dds[i].step = (uint32_t)((freqs[i] * 4294967296.0f) / ACTUAL_FS);
}
}
static uint16_t sine_lut[SINE_N];
static void build_sine(void)
{
for (uint32_t i = 0; i < SINE_N; i++)
{
float s = sinf(2.0f * 3.1415926f * (float)i / (float)SINE_N);
float x = (float)MID_CODE + s * (SINE_AMPL * 32767.0f);
if (x < 0.0f) x = 0.0f;
if (x > 65535.0f) x = 65535.0f;
sine_lut[i] = (uint16_t)(x + 0.5f);
}
}
int main(void)
{
SYSCFG_DL_init();
DAC_CLR_HIGH();
delay_cycles(32000u);
delay_cycles(320000u);
DAC80508_soft_reset();
delay_cycles(320000u);
DAC_CLR_HIGH();
delay_cycles(32000u);
DAC80508_write_reg(DAC80508_REG_CONFIG, 0x0000u);
DAC80508_write_reg(DAC80508_REG_GAIN, 0x01FFu);
DAC80508_write_reg(DAC80508_REG_SYNC, 0x0000u);
for (uint8_t ch = 0; ch < NUM_CHANNELS; ch++)
dacSetChannel(ch, MID_CODE);
build_sine();
init_DDS();
ledON();
while (1)
{
dbg_loopCount++;
for (uint8_t ch = 0; ch < NUM_CHANNELS; ch++)
{
dds[ch].phase += dds[ch].step;
uint8_t idx = (uint8_t)(dds[ch].phase >> 24);
uint16_t val = sine_lut[idx];
dacSetChannel(ch, val);
if (ch == 0) { dbg_lastVal0 = val; dbg_idx0 = idx; }
}
if ((dbg_loopCount % 500) == 0)
DL_GPIO_togglePins(gpioLED_PORT, gpioLED_LED1_PIN);
delay_cycles(SAMPLE_DELAY);
}
}
SysCFG:
*/
const Board = scripting.addModule("/ti/driverlib/Board");
const GPIO = scripting.addModule("/ti/driverlib/GPIO", {}, false);
const GPIO1 = GPIO.addInstance();
const GPIO2 = GPIO.addInstance();
const SPI = scripting.addModule("/ti/driverlib/SPI", {}, false);
const SPI1 = SPI.addInstance();
const SYSCTL = scripting.addModule("/ti/driverlib/SYSCTL");
const ProjectConfig = scripting.addModule("/ti/project_config/ProjectConfig");
/**
* Write custom configuration values to the imported modules.
*/
Board.genPeriphPinFile = true;
Board.genResourceCSV = true;
Board.genResourceCSVAdvanced = "detailed";
Board.genFileMod.$name = "ti_driverlib_BoardPins0";
Board.genFileCSV.$name = "ti_driverlib_ResourcesCSV0";
GPIO1.$name = "gpioLED";
GPIO1.associatedPins[0].launchPadShortcut = "LED1En";
GPIO1.associatedPins[0].$name = "LED1";
GPIO1.associatedPins[0].initialValue = "SET";
GPIO1.associatedPins[0].pin.$assign = "PA0";
GPIO2.port = "PORTB";
GPIO2.$name = "gpioCLR";
GPIO2.associatedPins[0].$name = "clrPIN";
GPIO2.associatedPins[0].initialValue = "SET";
GPIO2.associatedPins[0].assignedPin = "7";
GPIO2.associatedPins[0].pin.$assign = "PB7";
SPI1.$name = "mySPI";
SPI1.phase = "1";
SPI1.targetBitRate = 16000000;
SPI1.peripheral.$assign = "SPI1";
SPI1.peripheral.sclkPin.$assign = "PB9";
SPI1.peripheral.mosiPin.$assign = "PB8";
SPI1.peripheral.misoPin.$assign = "PB14";
SPI1.peripheral.cs0Pin.$assign = "PB6";
SPI1.sclkPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric0";
SPI1.sclkPinConfig.direction = scripting.forceWrite("OUTPUT");
SPI1.sclkPinConfig.onlyInternalResistor = scripting.forceWrite(false);
SPI1.sclkPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
SPI1.mosiPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric1";
SPI1.mosiPinConfig.direction = scripting.forceWrite("OUTPUT");
SPI1.mosiPinConfig.hideOutputInversion = scripting.forceWrite(false);
SPI1.mosiPinConfig.onlyInternalResistor = scripting.forceWrite(false);
SPI1.mosiPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
SPI1.misoPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric2";
SPI1.misoPinConfig.onlyInternalResistor = scripting.forceWrite(false);
SPI1.misoPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
SPI1.cs0PinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric3";
SPI1.cs0PinConfig.direction = scripting.forceWrite("OUTPUT");
SPI1.cs0PinConfig.hideOutputInversion = scripting.forceWrite(false);
SPI1.cs0PinConfig.onlyInternalResistor = scripting.forceWrite(false);
SPI1.cs0PinConfig.passedPeripheralType = scripting.forceWrite("Digital");
SYSCTL.clockTreeEn = true;
ProjectConfig.genLibDrivers = true;
ProjectConfig.genLibGC = true;
/**
* Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
* version of the tool will not impact the pinmux you originally saw. These lines can be completely deleted in order to
* re-solve from scratch.
*/
Board.peripheral.$suggestSolution = "DEBUGSS";
Board.peripheral.swclkPin.$suggestSolution = "PA20";
Board.peripheral.swdioPin.$suggestSolution = "PA19";
Header:
#ifndef DACINIT_H
#define DACINIT_H
#include "ti_msp_dl_config.h"
#include <stdint.h>
#define DAC80508_REG_NOP 0x00
#define DAC80508_REG_DEVID 0x01
#define DAC80508_REG_SYNC 0x02
#define DAC80508_REG_CONFIG 0x03
#define DAC80508_REG_GAIN 0x04
#define DAC80508_REG_TRIGGER 0x05
#define DAC80508_REG_BRDCAST 0x06
#define DAC80508_REG_STATUS 0x07
#define DAC80508_REG_DAC0 0x08
#define DAC80508_REG_DAC1 0x09
#define DAC80508_REG_DAC2 0x0A
#define DAC80508_REG_DAC3 0x0B
#define DAC80508_REG_DAC4 0x0C
#define DAC80508_REG_DAC5 0x0D
#define DAC80508_REG_DAC6 0x0E
#define DAC80508_REG_DAC7 0x0F
#define dacSOFTRESET_VAL 0x000Au
/* CLR — PB7 */
#define DAC_CLR_HIGH() DL_GPIO_setPins (gpioCLR_PORT, gpioCLR_clrPIN_PIN)
#define DAC_CLR_LOW() DL_GPIO_clearPins(gpioCLR_PORT, gpioCLR_clrPIN_PIN)
/* LED — PA0 */
#define ledON() DL_GPIO_setPins (gpioLED_PORT, gpioLED_LED1_PIN)
#define ledOFF() DL_GPIO_clearPins(gpioLED_PORT, gpioLED_LED1_PIN)
/* Watchpoints */
volatile uint32_t dbg_writeCount = 0;
volatile uint32_t dbg_spiStat0 = 0;
volatile uint32_t dbg_spiDone = 0;
static inline void DAC80508_WRITE(uint8_t addr, uint16_t data)
{
while (DL_SPI_isBusy(mySPI_INST)) {}
dbg_spiStat0 = SPI1->STAT;
DL_SPI_transmitData8(mySPI_INST, addr & 0x1Fu);
DL_SPI_transmitData8(mySPI_INST, (data >> 8) & 0xFFu);
DL_SPI_transmitData8(mySPI_INST, data & 0xFFu);
//while (DL_SPI_isBusy(mySPI_INST)) {}
dbg_spiDone = SPI1->STAT;
dbg_writeCount++;
}
static inline void DAC80508_write_reg(uint8_t reg, uint16_t val)
{
DAC80508_WRITE(reg, val);
}
static inline void DAC80508_soft_reset(void)
{
DAC80508_WRITE(DAC80508_REG_TRIGGER, dacSOFTRESET_VAL);
}
static inline void dacSetChannel(uint8_t ch, uint16_t code)
{
DAC80508_WRITE((uint8_t)(DAC80508_REG_DAC0 + (ch & 0x07u)), code);
}
#endif