/** * @file DAC5672.h * @author James Thesing * @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 #include #include #include #include #include #include #include #include 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 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] " * @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); } }