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
|
}
|