Project

General

Profile

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

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

 
1
/**
2
 * @file 		DAC5672.h
3
 * @author		James Thesing <james.thesing@criticallink.com>
4
 * @version		1.0
5
 *
6
 * @section LICENSE
7
 *
8
 *
9
 *    o  0
10
 *    | /       Copyright (c) 2005-2011
11
 *  (CL)---o   Critical Link, LLC
12
 *    \
13
 *     O
14
 *
15
 *
16
 * @section DESCRIPTION
17
 *
18
 * This class handles exercising the DAC5672 on the DSP. Input data is
19
 * generated by the DSPAPP and then sent over upp to the DAC. Output
20
 * is generated as two analog signals to two coaxial outputs.
21
 */
22

    
23
#include "DAC5672.h"
24
#include "core/DspUpp.h"
25
#include "core/DspSyscfg.h"
26
#include "core/chipconfig.h"
27
#include "core/cl_ipc_inbound.h"
28
#include "core/cl_ipc_outbound.h"
29

    
30
#include <std.h>
31
#include <tsk.h>
32
#include <clk.h>
33
#include <vector>
34
#include <string>
35
#include <cmath>
36
#include <stdio.h>
37
#include <string.h>
38
#include <sstream>
39

    
40
using namespace std;
41
using namespace MityDSP;
42

    
43
const int SAMPLE_SIZE = 32000;
44
//set up buffers
45
#pragma DATA_ALIGN( 64 );
46
int16_t buff1[ SAMPLE_SIZE ];
47
int16_t buff2[ SAMPLE_SIZE ];
48
int16_t buff3[ SAMPLE_SIZE ];
49

    
50
//set up data
51
int16_t data[32000];
52

    
53
static int32_t FREQUENCY = 1000000;
54
static float AMPLITUDE = .5;
55

    
56
// Forward declarations
57
void init();
58
void debugPrint( char *buffer );
59
int handleInboundMessage( void *apBuffer, uint32_t anLength, void *apUserArg ) ;
60

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

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

    
71
#define CORE_DAWG_MODULE	0x66000180
72

    
73
// uPP configuration record
74
static const tcDspUpp::tsDspUppConfig gsUppConfig =
75
	{
76
	4, // Interrupt level. Must be between 4 and 15.
77
	9, // Chan A DMA thread handling priority
78
	9, // Chan B DMA thread handling priority
79
	tcDspUpp::eeTransmit, // Directionality of Channel A.
80
	tcDspUpp::eeReceive, // Directionality of Channel B.
81
	tcDspUpp::ee16Bit, // Chan A data bit width.
82
	tcDspUpp::ee16Bit, // Chan B data bit width.
83
	false, // Use XData[7:0] for ChanA[15:8] even if ChanB is
84
	// disabled. See Table 3 in uPP User's Guide for details.
85
	4, // Size of MBX for Channel A.
86
	4, // Size of MBX for Channel B.
87
	0, // Clock divider for Channel A (75 MHz output clock)
88
	// (only in transmit mode). See Section 2.1.1 in uPP User's
89
	// Guide for details. Value must be between 1 and 16.
90
	0, // Clock divider for Channel B
91
	// (only in transmit mode). See Section 2.1.1 in uPP User's
92
	// Guide for details. Value must be between 1 and 16.
93
	tcDspUpp::ee256Bytes, // Chan A Transmit Thresh
94
	tcDspUpp::ee256Bytes, // Chan A Receive Thresh
95
	tcDspUpp::ee256Bytes, // Chan B Transmit Thresh
96
	tcDspUpp::ee256Bytes, // Chan B Receive Thresh
97
	false, // Do not use Chan A start signal
98
	false, // Do not use Chan B start signal
99
	//tcDspUpp::eeUPP_2xTXCLK, // Using external 2xTxClk for Transmit
100
	tcDspUpp::eePLL0_SYSCLK2,
101
	0 // uPP DMA Master Priority
102
	};
103

    
104
/**
105
 * Private Constructor - initializes the digital output logic
106
 */
107
DAC5672::DAC5672()
108
: mpDspUpp(NULL)
109
, meXmitChan(tcDspUpp::eeChanA)
110
, mhXmitMbx(NULL)
111
, meRecvChan(tcDspUpp::eeChanB)
112
, mhRecvMbx(NULL)
113
, filled(false)
114
{
115
	// Get instance of DspUpp
116
	mpDspUpp = tcDspUpp::getInstance();
117

    
118
	// Configure uPP
119
	if (0 != mpDspUpp->initialize(&gsUppConfig))
120
	{
121
	char debug1[] = "failed configuring upp";
122
	debugPrint(debug1);
123
	}
124
	else
125
	{
126
	// Get the receive and transmit mailboxes
127
	mhXmitMbx = mpDspUpp->getMBX(meXmitChan);
128
	mhRecvMbx = mpDspUpp->getMBX(meRecvChan);
129
	}
130
}
131

    
132
/**
133
 * Initializes the DSP link and registers message handler
134
 */
135
void init()
136
{
137

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

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

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

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

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

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

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

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

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

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

    
174
		// Send the message back to the ARM
175
		gpOutbound->SendMessage(lpMessageBuffer);
176
	}
177
}
178

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

    
189
	string tdebug1 = "The max sign value is: ";
190
	string tdebug2 = "The min sign value is: ";
191
	float temp;
192
	float maxSign = 0;
193
    float minSign = 0;
194
    if(!filled)
195
	{
196
		/*for( int i = 0; i <SAMPLE_SIZE/2; i++ )
197
		{
198
			data[i] = i;
199
		}
200
		int r = 0;
201
		for( int i = SAMPLE_SIZE/2; i < SAMPLE_SIZE; i++ )
202
		{
203

    
204
			data[i] = r;
205
			r++;
206
		}*/
207
		const double PI = 4.0*atan(1.0);
208
		for( int i = 0; i < SAMPLE_SIZE; i++){	
209
			temp = amplitude;
210
			temp *= (1<<13-1);
211
			//the 40 MHz used to be uppClock. There is a n issue with timing with the fpga,
212
			//which requires the generation of the wave to be based on the fpga's sampling frequency.
213
			temp *= 1.0+sin(2.0f * PI * ( ( float ) 500000 / 40000000 ) * i);
214
			//remember min and max values
215
			if (temp > maxSign)
216
			{
217
				maxSign = temp;
218
			}
219
			if (temp < minSign)
220
			{
221
				minSign = temp;
222
			}
223
			data[i] = temp;
224
		
225
			//send back sample debug to ARM
226
#if 0
227
			stringstream sARM;
228
			sARM << i;
229
			sARM << ": ";
230
			sARM << data[i];
231
			std::string currentSample = sARM.str();
232
			
233
			char* samplebuffer = (char*)currentSample.c_str();
234

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

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

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

    
248
#endif
249
		}
250
	}
251

    
252
	//format min and max value in dps -> arm message
253
	stringstream s1;
254
	stringstream s2;
255
	s1 << maxSign;
256
	std::string t = s1.str();
257
	tdebug1.append( t );
258
	//tdebug1.append( "\n" ); //don't need this
259
	s2 << minSign;
260
	t = s2.str();
261
	tdebug2.append( t );
262
	//tdebug2.append( "\n" ); //don't need this
263

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

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

    
275
		// Send the message back to the ARM
276
		gpOutbound->SendMessage(lpMessageBuffer);
277
	}
278
	// Obtain a dsplink buffer for the return message
279
	lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(debug2) + 1);
280
	if (NULL != lpMessageBuffer)
281
	{
282
		// Copy our message to the buffer
283
		strcpy(lpMessageBuffer, debug2);
284

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

    
289
	filled = true;
290
}
291

    
292
/**
293
 * sends data to DAC continuously through upp
294
 * @param buff1 - buffer used to send data to upp
295
 * @param buff2 - buffer used to send data to upp
296
 * @param buff3 - buffer used to send data to upp
297
 * @param data - table of data to copy to buffer
298
 */
299
void DAC5672::communicate(int16_t* buff1, int16_t* buff2, int16_t* buff3, int16_t *data  ){
300
	tcDspUpp::tsMbxMsg lsXmitMbxMsg;
301
	//tcDspUpp::tsMbxMsg lsRecvMbxMsg;
302
	int rv;
303

    
304
	char* lpMessageBuffer = NULL;
305
	char debug1[] = "transmitFailure\n";
306
	char debug2[] = "failure to communicate with ARM";
307
	lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(debug1) + 1);
308
	if (NULL != lpMessageBuffer)
309
	{
310
		// Copy our message to the buffer
311
		strcpy(lpMessageBuffer, debug1);
312
	}
313
	else
314
	{
315
		debugPrint( debug2 );
316
	}
317

    
318
	// fill buffers
319
	memcpy(buff1, data, sizeof(int16_t)*SAMPLE_SIZE);
320
	memcpy(buff2, data, sizeof(int16_t)*SAMPLE_SIZE);
321
	memcpy(buff3, data, sizeof(int16_t)*SAMPLE_SIZE);
322

    
323

    
324
	//transmit
325
	rv = mpDspUpp->transmit(meXmitChan , (uint8_t*)buff1, (uint16_t)(SAMPLE_SIZE * 2) );
326
	if (rv != 0){
327
		gpOutbound->SendMessage( lpMessageBuffer );
328
		return;
329
	}
330

    
331
	rv = mpDspUpp->transmit(meXmitChan, (uint8_t*)buff2, (uint16_t)(SAMPLE_SIZE * 2) );
332
	if( rv != 0)
333
	{
334
		gpOutbound->SendMessage( lpMessageBuffer );
335
		return;
336
	}
337

    
338
	rv = mpDspUpp->transmit(meXmitChan, (uint8_t*)buff3, (uint16_t)(SAMPLE_SIZE * 2) );
339
	if( rv !=0)
340
	{
341
		gpOutbound->SendMessage( lpMessageBuffer );
342
		return;
343
	}
344

    
345
	//wait for buffers, fill, transmit
346
	while(true){
347
		MBX_pend(mhXmitMbx, &lsXmitMbxMsg, SYS_FOREVER);
348
		memcpy((void*)lsXmitMbxMsg.pBufPtr, data, sizeof(int16_t)*SAMPLE_SIZE );
349
		rv = mpDspUpp->transmit(meXmitChan,(uint8_t*)lsXmitMbxMsg.pBufPtr, (uint16_t)(SAMPLE_SIZE * 2 ));
350
		if( rv != 0 )
351
		{
352
			gpOutbound->SendMessage( lpMessageBuffer );
353
			return;
354
		}
355
	}
356

    
357
}
358

    
359
/**
360
 * Return instance of object or create one to enforce
361
 * singleton use
362
 */
363
DAC5672*
364
DAC5672::getInstance()
365
{
366
	if (NULL == mpDAC5672)
367
		mpDAC5672 = new DAC5672();
368
	return mpDAC5672;
369
}
370

    
371
/**
372
 * Destructor
373
 */
374
DAC5672::~DAC5672()
375
{
376

    
377
}
378

    
379

    
380
/**
381
 * Main routine for DSPAPP
382
 */
383
int main(int argc, char* argv[])
384
{
385

    
386

    
387

    
388
	// initialize the DSPLink system
389
	tcCL_IPCInit::GetInstance();
390

    
391
	// Launch an initialization task
392
	TSK_Attrs* lpAttrs = new TSK_Attrs;
393
	*lpAttrs           = TSK_ATTRS;
394
	lpAttrs->name      = "Initialize";
395
	lpAttrs->stacksize = 8192*2;
396
	lpAttrs->priority  = 5;
397
	TSK_create((Fxn)init,lpAttrs);
398
    return 0;
399
}
400

    
401
/**
402
 * handles messages received from the arm
403
 * @param apBuffer buffer location of message
404
 * @param anLength length of buffer used
405
 * @param apUserArg user given arguments
406
 * @return 0;
407
 */
408
int handleInboundMessage(void* apBuffer, uint32_t anLength, void* apUserArg)
409
{
410
	//char buffer[50];
411
	string str = (const char*)apBuffer;
412
	string cmp = "convert";
413
	AMPLITUDE = 1;
414
	if (strcmp(str.c_str(), cmp.c_str()))
415
	{
416
		AMPLITUDE = atof( (const char*)apBuffer );
417
	}
418
	DAC5672* mhDAC5672 = DAC5672::getInstance();
419
	mhDAC5672->fillData(AMPLITUDE, FREQUENCY, data);
420
	mhDAC5672->communicate(buff1, buff2, buff3, data);
421
	return 0;
422
}
423

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

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

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

    
443
	// Check that the buffer is valid
444
	if (pBuffer)
445
	{
446
		// Copy the message to the buffer
447
		strcpy(pBuffer, pMsg);
448
		// Send the message
449
		gpDebug->SendMessage(pBuffer);
450
	}
451
}
(3-3/4) Go to top
Add picture from clipboard (Maximum size: 1 GB)