Project

General

Profile

RE: SPI interface for ADC5560 (MityDSP L138F) » DAC5672.cpp

Vivek Ponnani, 07/24/2017 03:40 PM

 
/**
* @file DAC5672.h
* @author James Thesing <james.thesing@criticallink.com>
* @version 1.0
*
* @section LICENSE
*
*
* o 0
* | / Copyright (c) 2005-2011
* (CL)---o Critical Link, LLC
* \
* O
*
*
* @section DESCRIPTION
*
* This class handles exercising the DAC5672 on the DSP. Input data is
* generated by the DSPAPP and then sent over upp to the DAC. Output
* is generated as two analog signals to two coaxial outputs.
*/

#include "DAC5672.h"
#include "core/DspUpp.h"
#include "core/DspSyscfg.h"
#include "core/chipconfig.h"
#include "core/cl_ipc_inbound.h"
#include "core/cl_ipc_outbound.h"

#include <std.h>
#include <tsk.h>
#include <clk.h>
#include <vector>
#include <string>
#include <cmath>
#include <stdio.h>
#include <string.h>
#include <sstream>

using namespace std;
using namespace MityDSP;

const int SAMPLE_SIZE = 32000;
//set up buffers
#pragma DATA_ALIGN( 64 );
int16_t buff1[ SAMPLE_SIZE ];
int16_t buff2[ SAMPLE_SIZE ];
int16_t buff3[ SAMPLE_SIZE ];

//set up data
int16_t data[32000];

static int32_t FREQUENCY = 1000000;
static float AMPLITUDE = .5;

// Forward declarations
void init();
void debugPrint( char *buffer );
int handleInboundMessage( void *apBuffer, uint32_t anLength, void *apUserArg ) ;

// Object for sending debug messages (these are received and printed to stdout by tcDspApp)
tcCL_IPCOutbound* gpDebug;
// Object for sending GPPMSGQ1 messages that the ARM will receive
tcCL_IPCOutbound* gpOutbound;
// Object for receiving DSPMSGQ0 messages that the DSP will receive
tcCL_IPCInbound* gpInbound;

// Initialize static member variables
DAC5672* DAC5672::mpDAC5672 = NULL;

#define CORE_DAWG_MODULE 0x66000180

// uPP configuration record
static const tcDspUpp::tsDspUppConfig gsUppConfig =
{
4, // Interrupt level. Must be between 4 and 15.
9, // Chan A DMA thread handling priority
9, // Chan B DMA thread handling priority
tcDspUpp::eeTransmit, // Directionality of Channel A.
tcDspUpp::eeReceive, // Directionality of Channel B.
tcDspUpp::ee16Bit, // Chan A data bit width.
tcDspUpp::ee16Bit, // Chan B data bit width.
false, // Use XData[7:0] for ChanA[15:8] even if ChanB is
// disabled. See Table 3 in uPP User's Guide for details.
4, // Size of MBX for Channel A.
4, // Size of MBX for Channel B.
0, // Clock divider for Channel A (75 MHz output clock)
// (only in transmit mode). See Section 2.1.1 in uPP User's
// Guide for details. Value must be between 1 and 16.
0, // Clock divider for Channel B
// (only in transmit mode). See Section 2.1.1 in uPP User's
// Guide for details. Value must be between 1 and 16.
tcDspUpp::ee256Bytes, // Chan A Transmit Thresh
tcDspUpp::ee256Bytes, // Chan A Receive Thresh
tcDspUpp::ee256Bytes, // Chan B Transmit Thresh
tcDspUpp::ee256Bytes, // Chan B Receive Thresh
false, // Do not use Chan A start signal
false, // Do not use Chan B start signal
//tcDspUpp::eeUPP_2xTXCLK, // Using external 2xTxClk for Transmit
tcDspUpp::eePLL0_SYSCLK2,
0 // uPP DMA Master Priority
};

/**
* Private Constructor - initializes the digital output logic
*/
DAC5672::DAC5672()
: mpDspUpp(NULL)
, meXmitChan(tcDspUpp::eeChanA)
, mhXmitMbx(NULL)
, meRecvChan(tcDspUpp::eeChanB)
, mhRecvMbx(NULL)
, filled(false)
{
// Get instance of DspUpp
mpDspUpp = tcDspUpp::getInstance();

// Configure uPP
if (0 != mpDspUpp->initialize(&gsUppConfig))
{
char debug1[] = "failed configuring upp";
debugPrint(debug1);
}
else
{
// Get the receive and transmit mailboxes
mhXmitMbx = mpDspUpp->getMBX(meXmitChan);
mhRecvMbx = mpDspUpp->getMBX(meRecvChan);
}
}

/**
* Initializes the DSP link and registers message handler
*/
void init()
{

// Message to ARM core.
char lpReturnMessage[] = "DSP Initialization finished.";
// Buffer for return message
char* lpMessageBuffer = NULL;

//adjust clock divisor for the EMIF clock in FPGA to be 0.
*(unsigned short*)(0x66000180+2) = 0x000;

// Create the outbound debug link
gpDebug = new tcCL_IPCOutbound("debug");

// Create the inbound link for messages to the DSP
gpInbound = new tcCL_IPCInbound();

gpInbound->Open("DSPMSGQ0", 8);

// Create the outbound controller for sending messages to the ARM
gpOutbound = new tcCL_IPCOutbound("GPPMSGQ1");

if (NULL != gpInbound)
{
// Register a callback function to handle messages from the ARM
gpInbound->RegisterCallback(handleInboundMessage, (void*)NULL);
}

// Now that initialization is complete, let the ARM know with a message

// Obtain a dsplink buffer for the return message
lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(lpReturnMessage) + 1);

// Make sure we received a valid buffer
if (NULL != lpMessageBuffer)
{
// Copy our message to the buffer
strcpy(lpMessageBuffer, lpReturnMessage);

// Send the message back to the ARM
gpOutbound->SendMessage(lpMessageBuffer);
}
}

/**
* Generates a 14bit signwave from given paramaters
* @param amplitude amplitude of sine wave (0,1]
* @param frequency frequency of sine wave
* @param data data table that is filled
*/
void DAC5672::fillData( float amplitude, int32_t frequency, int16_t *data){
// Buffer for return message
char* lpMessageBuffer = NULL;

string tdebug1 = "The max sign value is: ";
string tdebug2 = "The min sign value is: ";
float temp;
float maxSign = 0;
float minSign = 0;
if(!filled)
{
/*for( int i = 0; i <SAMPLE_SIZE/2; i++ )
{
data[i] = i;
}
int r = 0;
for( int i = SAMPLE_SIZE/2; i < SAMPLE_SIZE; i++ )
{

data[i] = r;
r++;
}*/
const double PI = 4.0*atan(1.0);
for( int i = 0; i < SAMPLE_SIZE; i++){
temp = amplitude;
temp *= (1<<13-1);
//the 40 MHz used to be uppClock. There is a n issue with timing with the fpga,
//which requires the generation of the wave to be based on the fpga's sampling frequency.
temp *= 1.0+sin(2.0f * PI * ( ( float ) 500000 / 40000000 ) * i);
//remember min and max values
if (temp > maxSign)
{
maxSign = temp;
}
if (temp < minSign)
{
minSign = temp;
}
data[i] = temp;
//send back sample debug to ARM
#if 0
stringstream sARM;
sARM << i;
sARM << ": ";
sARM << data[i];
std::string currentSample = sARM.str();
char* samplebuffer = (char*)currentSample.c_str();

// Obtain a dsplink buffer for the return message
lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(samplebuffer) + 1);

// Make sure we received a valid buffer
if (NULL != lpMessageBuffer)
{
// Copy our message to the buffer
strcpy(lpMessageBuffer, samplebuffer);

// Send the message back to the ARM
gpOutbound->SendMessage(lpMessageBuffer);
}

#endif
}
}

//format min and max value in dps -> arm message
stringstream s1;
stringstream s2;
s1 << maxSign;
std::string t = s1.str();
tdebug1.append( t );
//tdebug1.append( "\n" ); //don't need this
s2 << minSign;
t = s2.str();
tdebug2.append( t );
//tdebug2.append( "\n" ); //don't need this

char *debug1 = (char*)tdebug1.c_str();
char *debug2 = (char*)tdebug2.c_str();
// Obtain a dsplink buffer for the return message
lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(debug1) + 1);

// Make sure we received a valid buffer
if (NULL != lpMessageBuffer)
{
// Copy our message to the buffer
strcpy(lpMessageBuffer, debug1);

// Send the message back to the ARM
gpOutbound->SendMessage(lpMessageBuffer);
}
// Obtain a dsplink buffer for the return message
lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(debug2) + 1);
if (NULL != lpMessageBuffer)
{
// Copy our message to the buffer
strcpy(lpMessageBuffer, debug2);

// Send the message back to the ARM
gpOutbound->SendMessage(lpMessageBuffer);
}

filled = true;
}

/**
* sends data to DAC continuously through upp
* @param buff1 - buffer used to send data to upp
* @param buff2 - buffer used to send data to upp
* @param buff3 - buffer used to send data to upp
* @param data - table of data to copy to buffer
*/
void DAC5672::communicate(int16_t* buff1, int16_t* buff2, int16_t* buff3, int16_t *data ){
tcDspUpp::tsMbxMsg lsXmitMbxMsg;
//tcDspUpp::tsMbxMsg lsRecvMbxMsg;
int rv;

char* lpMessageBuffer = NULL;
char debug1[] = "transmitFailure\n";
char debug2[] = "failure to communicate with ARM";
lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(debug1) + 1);
if (NULL != lpMessageBuffer)
{
// Copy our message to the buffer
strcpy(lpMessageBuffer, debug1);
}
else
{
debugPrint( debug2 );
}

// fill buffers
memcpy(buff1, data, sizeof(int16_t)*SAMPLE_SIZE);
memcpy(buff2, data, sizeof(int16_t)*SAMPLE_SIZE);
memcpy(buff3, data, sizeof(int16_t)*SAMPLE_SIZE);


//transmit
rv = mpDspUpp->transmit(meXmitChan , (uint8_t*)buff1, (uint16_t)(SAMPLE_SIZE * 2) );
if (rv != 0){
gpOutbound->SendMessage( lpMessageBuffer );
return;
}

rv = mpDspUpp->transmit(meXmitChan, (uint8_t*)buff2, (uint16_t)(SAMPLE_SIZE * 2) );
if( rv != 0)
{
gpOutbound->SendMessage( lpMessageBuffer );
return;
}

rv = mpDspUpp->transmit(meXmitChan, (uint8_t*)buff3, (uint16_t)(SAMPLE_SIZE * 2) );
if( rv !=0)
{
gpOutbound->SendMessage( lpMessageBuffer );
return;
}

//wait for buffers, fill, transmit
while(true){
MBX_pend(mhXmitMbx, &lsXmitMbxMsg, SYS_FOREVER);
memcpy((void*)lsXmitMbxMsg.pBufPtr, data, sizeof(int16_t)*SAMPLE_SIZE );
rv = mpDspUpp->transmit(meXmitChan,(uint8_t*)lsXmitMbxMsg.pBufPtr, (uint16_t)(SAMPLE_SIZE * 2 ));
if( rv != 0 )
{
gpOutbound->SendMessage( lpMessageBuffer );
return;
}
}

}

/**
* Return instance of object or create one to enforce
* singleton use
*/
DAC5672*
DAC5672::getInstance()
{
if (NULL == mpDAC5672)
mpDAC5672 = new DAC5672();
return mpDAC5672;
}

/**
* Destructor
*/
DAC5672::~DAC5672()
{

}


/**
* Main routine for DSPAPP
*/
int main(int argc, char* argv[])
{



// initialize the DSPLink system
tcCL_IPCInit::GetInstance();

// Launch an initialization task
TSK_Attrs* lpAttrs = new TSK_Attrs;
*lpAttrs = TSK_ATTRS;
lpAttrs->name = "Initialize";
lpAttrs->stacksize = 8192*2;
lpAttrs->priority = 5;
TSK_create((Fxn)init,lpAttrs);
return 0;
}

/**
* handles messages received from the arm
* @param apBuffer buffer location of message
* @param anLength length of buffer used
* @param apUserArg user given arguments
* @return 0;
*/
int handleInboundMessage(void* apBuffer, uint32_t anLength, void* apUserArg)
{
//char buffer[50];
string str = (const char*)apBuffer;
string cmp = "convert";
AMPLITUDE = 1;
if (strcmp(str.c_str(), cmp.c_str()))
{
AMPLITUDE = atof( (const char*)apBuffer );
}
DAC5672* mhDAC5672 = DAC5672::getInstance();
mhDAC5672->fillData(AMPLITUDE, FREQUENCY, data);
mhDAC5672->communicate(buff1, buff2, buff3, data);
return 0;
}

/**
* prints a character array through a debug IPC object
* output is: "[DSP] <msg>"
* @param pMsg - character array of message to print
*/
void debugPrint(char* pMsg)
{
// The length of the message to be sent
int len = strlen(pMsg);
// Pointer to dsplink buffer where to write the message
char* pBuffer;

// Make sure the debug IPC outbound object has been initialized
if (gpDebug == NULL)
return;

// Get a buffer for the message
pBuffer = (char *)gpDebug->GetBuffer(len+1);

// Check that the buffer is valid
if (pBuffer)
{
// Copy the message to the buffer
strcpy(pBuffer, pMsg);
// Send the message
gpDebug->SendMessage(pBuffer);
}
}
(3-3/4)