1
|
/*
|
2
|
* maindsp.cpp
|
3
|
*
|
4
|
* Created on: Oct 10, 2013
|
5
|
* Author: preejith
|
6
|
*/
|
7
|
|
8
|
|
9
|
#include "core/DspUpp.h"
|
10
|
#include "core/DspSyscfg.h"
|
11
|
#include "core/chipconfig.h"
|
12
|
#include "core/cl_ipc_inbound.h"
|
13
|
#include "core/cl_ipc_outbound.h"
|
14
|
#include "core/DspGpio.h"
|
15
|
#include "core/DspIntDispatch.h"
|
16
|
#include "core/DspTimer.h"
|
17
|
#include "core/DspGpio.h"
|
18
|
#include "core/regs_gpio.h"
|
19
|
#include "core/memorymap.h"
|
20
|
#include "core/Gpio.h"
|
21
|
#include <lck.h>
|
22
|
#include <sem.h>
|
23
|
#include <std.h>
|
24
|
#include <tsk.h>
|
25
|
#include <clk.h>
|
26
|
#include <math.h>
|
27
|
#include <vector>
|
28
|
#include <string>
|
29
|
#include <stdio.h>
|
30
|
#include <c62.h>
|
31
|
#include <c6x.h>
|
32
|
#include <hwi.h>
|
33
|
#include <bcache.h>
|
34
|
|
35
|
const long int BUFF_SIZE = 2000; //size of buffers used in upp link
|
36
|
|
37
|
//set up buffer for upp
|
38
|
#pragma DATA_ALIGN( 64 );
|
39
|
volatile int16_t buff1[ BUFF_SIZE];//4096 bytes
|
40
|
|
41
|
|
42
|
//for sending data to qt app for display
|
43
|
struct data2bsent
|
44
|
{
|
45
|
int16_t indicator;
|
46
|
int16_t integer;//indicator=1
|
47
|
int16_t state;//indicator=2
|
48
|
int16_t wal1;//indicator=3
|
49
|
int16_t wal2;//indicator=4
|
50
|
int16_t dist_val; //indicator=5
|
51
|
int16_t q_value;//indicator=6
|
52
|
int16_t distension[10];//indicator=7
|
53
|
int16_t lumen[10];//indicator=8
|
54
|
int16_t echo[2000];//indicator=9
|
55
|
};
|
56
|
|
57
|
struct data2bsent data_struct;
|
58
|
|
59
|
using namespace std;
|
60
|
using namespace MityDSP;
|
61
|
|
62
|
int numbr=0;
|
63
|
int copy_mun=0;
|
64
|
int peak_index[100];
|
65
|
int valley_index[100];
|
66
|
|
67
|
#define m 10 //number of frames i.e. pulses sent from the transducer
|
68
|
#define n 2000 //number of samples i.e. output of the ADC
|
69
|
#define w 31 //size of the window
|
70
|
#define threshold_noise_removal 0.0001
|
71
|
#define A 51 //number of samples to be averaged
|
72
|
#define win_detection 11
|
73
|
#define win_track 21
|
74
|
#define delta 0.1
|
75
|
#define fs 1e8 //sampling frequency
|
76
|
#define c 1540000 //velocity of ultrasound
|
77
|
#define max_peaks 10
|
78
|
#define dia_min 2 //minimum diameter
|
79
|
#define dia_max 10 //maximum diameter
|
80
|
#define set_zero 500 //number of smaples to be set to zero
|
81
|
#define WMNCC_buffsize 50
|
82
|
#define threshold_negative_corrcheck 0
|
83
|
#define check_cons 3 // no of consecutive appro. same wall locations needed in wall detection
|
84
|
#define check_inside 10 //no of frames to be captured to calculate 1 wall1 and wall2 location
|
85
|
#define distens_array_size 10000 //no of points in the distension waveform
|
86
|
#define wmncc_array_size 50 //no of points for wmncc check
|
87
|
#define wall_det_count 10
|
88
|
|
89
|
|
90
|
int half_window_size = floor(w / 2);
|
91
|
int check=0; //interrupt polling
|
92
|
int16_t cnt=0;
|
93
|
|
94
|
//peak_det vari;
|
95
|
char debug1[] = "failed to send received buffer to upp\n";
|
96
|
char debug2[] = "getting instance of DSPuPP\n";
|
97
|
char debug3[] = "configuring UPP\n";
|
98
|
char debug4[] = "upp configured\n";
|
99
|
char debug5[] = "wmncc error back to wall detection\n";
|
100
|
char debug6[] = "wall detected to tracking\n";
|
101
|
char debug7[] = "failed to send data\n ";
|
102
|
char debug8[] = "no buffer received for shared memory\n ";
|
103
|
char debug9[] = "done tracking\n";
|
104
|
char debug10[] = "failed configuring upp\n";
|
105
|
char debug11[] = "next wall detection\n";
|
106
|
char debug12[] = "interrupt\n";
|
107
|
char debug13[] = "pin high\n";
|
108
|
char debug14[] = "pin low\n";
|
109
|
char debug15[] = "wall id\n";
|
110
|
|
111
|
MityDSP::tcDspUpp* mpDspUpp; //!< Pointer to uPP driver singleton.
|
112
|
const MityDSP::tcDspUpp::teUppChan meRecvChan = tcDspUpp::eeChanA; //!< Constant for receive channel.
|
113
|
MBX_Handle mhRecvMbx = NULL; //!< Handle to receive mailbox.
|
114
|
|
115
|
//envelope smooth and normalize variables
|
116
|
//i have no idea why but these variables have to be global but code doesn't run otherwise
|
117
|
double normal[BUFF_SIZE]; //normalized swc
|
118
|
double product[BUFF_SIZE];
|
119
|
double smooth_1[BUFF_SIZE]; //sliding window covariance
|
120
|
double smooth_2[BUFF_SIZE]; //smoothened swc
|
121
|
|
122
|
// Forward declarations
|
123
|
void init();
|
124
|
void uppngpio();
|
125
|
int handleInboundMessage( void *apBuffer, uint32_t anLength, void *apUserArg ) ;
|
126
|
void HandleInterrupt();
|
127
|
|
128
|
void envelope_smooth_normalise(int16_t* ptr,int array_size);
|
129
|
void peakdetect(double* input,int array_size,double delt);
|
130
|
|
131
|
|
132
|
void debugPrint( char *buffer );
|
133
|
void integerPrint(int* intMsg);
|
134
|
void send_data();
|
135
|
|
136
|
|
137
|
tcDspTimer myTimer;
|
138
|
|
139
|
int16_t* lpMessageBuffer = NULL;
|
140
|
MityDSP::tcDspGpio* gpDspGpio;
|
141
|
tcDspUpp::tsMbxMsg lsRecvMbxMsg;
|
142
|
|
143
|
// Object for sending debug messages (these are received and printed to stdout by tcDspApp)
|
144
|
tcCL_IPCOutbound* gpDebug;
|
145
|
// Object for sending GPPMSGQ1 messages that the ARM will receive
|
146
|
tcCL_IPCOutbound* gpOutbound;
|
147
|
// Object for receiving DSPMSGQ0 messages that the DSP will receive
|
148
|
tcCL_IPCInbound* gpInbound;
|
149
|
|
150
|
//*********uPP configuration record***********//
|
151
|
static const tcDspUpp::tsDspUppConfig gsUppConfig =
|
152
|
{
|
153
|
4, // Interrupt level. Must be between 4 and 15.
|
154
|
9, // Chan A DMA thread handling priority
|
155
|
9, // Chan B DMA thread handling priority
|
156
|
tcDspUpp::eeReceive, // Directionality of Channel A.
|
157
|
tcDspUpp::eeDisabled, // Directionality of Channel B.
|
158
|
tcDspUpp::ee14Bit, // Chan A data bit width.
|
159
|
tcDspUpp::ee16Bit, // Chan B data bit width.
|
160
|
false, // Use XData[7:0] for ChanA[15:8] even if ChanB is
|
161
|
// disabled. See Table 3 in uPP User's Guide for details.
|
162
|
4, // Size of MBX for Channel A.
|
163
|
4, // Size of MBX for Channel B.
|
164
|
0, // Clock divider for Channel A (37.5 MHz output clock)
|
165
|
// (only in transmit mode). See Section 2.1.1 in uPP User's
|
166
|
// Guide for details. Value must be between 1 and 16.
|
167
|
0, // Clock divider for Channel B
|
168
|
// (only in transmit mode). See Section 2.1.1 in uPP User's
|
169
|
// Guide for details. Value must be between 1 and 16.
|
170
|
tcDspUpp::ee256Bytes, // Chan A Transmit Thresh
|
171
|
tcDspUpp::ee64Bytes, // Chan A Receive Thresh
|
172
|
tcDspUpp::ee256Bytes, // Chan B Transmit Thresh
|
173
|
tcDspUpp::ee256Bytes, // Chan B Receive Thresh
|
174
|
false, // Do not use Chan A start signal
|
175
|
false, // Do not use Chan B start signal
|
176
|
//tcDspUpp::eeUPP_2xTXCLK, // Using external 2xTxClk for Transmit
|
177
|
tcDspUpp::eePLL0_SYSCLK2,
|
178
|
0 // uPP DMA Master Priority
|
179
|
|
180
|
};
|
181
|
|
182
|
/**
|
183
|
* Main routine for DSPAPP
|
184
|
*/
|
185
|
|
186
|
int main(int argc, char* argv[])
|
187
|
{
|
188
|
// initialize the DSPLink system
|
189
|
tcCL_IPCInit::GetInstance();
|
190
|
|
191
|
// Launch an initialization task
|
192
|
TSK_Attrs* lpAttrs = new TSK_Attrs;
|
193
|
*lpAttrs = TSK_ATTRS;
|
194
|
lpAttrs->name = "Initialize";
|
195
|
lpAttrs->stacksize = 8192*4;
|
196
|
lpAttrs->priority = 5;
|
197
|
TSK_create((Fxn)init,lpAttrs);
|
198
|
return 0;
|
199
|
}
|
200
|
|
201
|
|
202
|
/**
|
203
|
* Private Constructor - initializes upp and gpio
|
204
|
*/
|
205
|
|
206
|
void uppngpio()
|
207
|
{
|
208
|
//////////////////////////
|
209
|
///////UPP CONFIG////////
|
210
|
//////////////////////////
|
211
|
|
212
|
// Get instance of DspUpp
|
213
|
debugPrint(debug2);
|
214
|
mpDspUpp = tcDspUpp::getInstance();
|
215
|
|
216
|
// Configure uPP
|
217
|
debugPrint(debug3);
|
218
|
|
219
|
if (0 != mpDspUpp->initialize(&gsUppConfig))
|
220
|
{
|
221
|
debugPrint(debug10);
|
222
|
}
|
223
|
|
224
|
else
|
225
|
{
|
226
|
debugPrint(debug4);
|
227
|
// Get the receive and transmit mailboxes
|
228
|
mhRecvMbx = mpDspUpp->getMBX(meRecvChan);
|
229
|
}
|
230
|
|
231
|
//send buffers to upp to fill
|
232
|
|
233
|
mpDspUpp->receive(meRecvChan,(uint8_t*)buff1,4096 ) ;
|
234
|
MBX_pend(mhRecvMbx, &lsRecvMbxMsg, SYS_FOREVER);
|
235
|
|
236
|
BCACHE_inv(lsRecvMbxMsg.pBufPtr,4096,true);
|
237
|
|
238
|
/////////////////////////////
|
239
|
/////////GPIO CONFIG/////////
|
240
|
/////////////////////////////
|
241
|
|
242
|
//interrupt stuff
|
243
|
//interrupt level= 6 bank0 interrupt event = 65
|
244
|
HWI_eventMap(6, 65);
|
245
|
|
246
|
//register the interrupt handler
|
247
|
HWI_dispatchPlug(6, (Fxn)HandleInterrupt, -1, NULL);
|
248
|
|
249
|
//setup interrupt pin
|
250
|
gpDspGpio = tcDspGpio::GetInstance();
|
251
|
tcDspSyscfg::SetPinMuxConfig(GPIO0_6);
|
252
|
gpDspGpio->ConfigurePin(0,6,false,0,true,false);
|
253
|
|
254
|
//setup rising edge interrupt
|
255
|
gpDspGpio->mpGpioRegs->BANKPAIR[0].SET_RIS_TRIG |= (1<<6);
|
256
|
gpDspGpio->mpGpioRegs->BANKPAIR[0].CLR_FAL_TRIG |= (1<<6);
|
257
|
|
258
|
//eanble interrupt
|
259
|
C62_enableIER(1 << 6);
|
260
|
}
|
261
|
|
262
|
|
263
|
|
264
|
void ipc_setup()
|
265
|
{
|
266
|
// Message to ARM core.
|
267
|
char lpReturnMessage[] = "DSP Initialization finished.";
|
268
|
|
269
|
// Buffer for return message
|
270
|
char* lpMessageBuffer = NULL;
|
271
|
|
272
|
// Create the outbound debug link
|
273
|
gpDebug = new tcCL_IPCOutbound("debug");
|
274
|
|
275
|
// Create the inbound link for messages to the DSP
|
276
|
gpInbound = new tcCL_IPCInbound();
|
277
|
|
278
|
|
279
|
// Create the outbound controller for sending messages to the ARM
|
280
|
gpOutbound = new tcCL_IPCOutbound("GPPMSGQ1");
|
281
|
|
282
|
if (NULL != gpInbound)
|
283
|
{
|
284
|
gpInbound->Open("DSPMSGQ0", 8);
|
285
|
// Register a callback function to handle messages from the ARM
|
286
|
gpInbound->RegisterCallback(handleInboundMessage, (void*)NULL);
|
287
|
}
|
288
|
// Now that initialization is complete, let the ARM know with a message
|
289
|
// Obtain a dsplink buffer for the return message
|
290
|
lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(lpReturnMessage) + 1);
|
291
|
|
292
|
// Make sure we received a valid buffer
|
293
|
if (NULL != lpMessageBuffer)
|
294
|
{
|
295
|
// Copy our message to the buffer
|
296
|
strcpy(lpMessageBuffer, lpReturnMessage);
|
297
|
// Send the message back to the ARM
|
298
|
gpOutbound->SendMessage(lpMessageBuffer);
|
299
|
}
|
300
|
}
|
301
|
|
302
|
//interrupt routine
|
303
|
|
304
|
void HandleInterrupt()
|
305
|
{
|
306
|
|
307
|
if (!check)
|
308
|
{
|
309
|
mpDspUpp->receive(meRecvChan,(uint8_t*)buff1,4096 );
|
310
|
MBX_pend(mhRecvMbx, &lsRecvMbxMsg, 0);
|
311
|
|
312
|
check=1;
|
313
|
}
|
314
|
}
|
315
|
|
316
|
|
317
|
/**
|
318
|
* handles messages received from the arm
|
319
|
* @param apBuffer buffer location of message
|
320
|
* @param anLength length of buffer used
|
321
|
* @param apUserArg user given arguments
|
322
|
* @return 0;
|
323
|
*/
|
324
|
|
325
|
int handleInboundMessage(void* apBuffer, uint32_t anLength, void* apUserArg)
|
326
|
{
|
327
|
return 0;
|
328
|
}
|
329
|
|
330
|
|
331
|
void init()
|
332
|
{
|
333
|
// initialise communication protocols with qt
|
334
|
ipc_setup();
|
335
|
|
336
|
// initialise upp and gpio for interrupt
|
337
|
uppngpio();
|
338
|
|
339
|
while(1)
|
340
|
{
|
341
|
if ((check==1))
|
342
|
{
|
343
|
|
344
|
//send data to display every 10 frames
|
345
|
cnt++;
|
346
|
if(cnt%10==0)
|
347
|
{
|
348
|
memcpy((int16_t*)data_struct.echo, (int16_t*)buff1 ,sizeof(int16_t)*(BUFF_SIZE));
|
349
|
send_data();
|
350
|
}
|
351
|
|
352
|
if(cnt==50)
|
353
|
cnt=0;
|
354
|
|
355
|
//carry out processing
|
356
|
envelope_smooth_normalise((int16_t*)buff1,BUFF_SIZE);
|
357
|
|
358
|
//invalidate the cache
|
359
|
BCACHE_inv(lsRecvMbxMsg.pBufPtr,4096,true);
|
360
|
|
361
|
check=0;
|
362
|
}
|
363
|
}
|
364
|
}
|
365
|
|
366
|
|
367
|
//finds envelope smoothens the curve twice n normalises
|
368
|
|
369
|
void envelope_smooth_normalise(int16_t* ptr,int array_size)
|
370
|
{
|
371
|
|
372
|
int j,k,k1,k2;
|
373
|
double sum1=0;
|
374
|
double sum2=0;
|
375
|
double maxi=0;
|
376
|
double mini=0;
|
377
|
|
378
|
for(j=0;j<array_size;j++)
|
379
|
{
|
380
|
if((ptr[j]<250)&&(ptr[j]>-250))
|
381
|
ptr[j]=0;
|
382
|
product[j] = ptr[j] * ptr[j];
|
383
|
normal[j]=0;
|
384
|
}
|
385
|
|
386
|
j=half_window_size;
|
387
|
|
388
|
for(k=0;k<=2*half_window_size;k++)
|
389
|
sum1=sum1+product[k];
|
390
|
|
391
|
smooth_1[j]=sum1/w;
|
392
|
|
393
|
for(j=half_window_size+1;j<array_size-half_window_size;j++)
|
394
|
{
|
395
|
k1=j-half_window_size;
|
396
|
k2=j+half_window_size;
|
397
|
sum1 = sum1 - product[k1-1]+product[k2];
|
398
|
smooth_1[j]=sum1/w;
|
399
|
}
|
400
|
|
401
|
sum1=0;
|
402
|
sum2=0;
|
403
|
|
404
|
for(j=0;j<half_window_size;j++)
|
405
|
{
|
406
|
sum1+=product[j];
|
407
|
sum2+=product[array_size-1-j];
|
408
|
smooth_1[j] = sum1/(j+1);
|
409
|
smooth_1[array_size-1-j]=sum2/(j+1);
|
410
|
}
|
411
|
|
412
|
j=half_window_size;
|
413
|
sum1=0;
|
414
|
|
415
|
for(k=0;k<=2*half_window_size;k++)
|
416
|
sum1=sum1+smooth_1[k];
|
417
|
|
418
|
smooth_2[j]=sum1/w;
|
419
|
|
420
|
mini=smooth_2[j];
|
421
|
maxi=smooth_2[j];
|
422
|
|
423
|
for(j=half_window_size+1;j<array_size-half_window_size;j++)
|
424
|
{
|
425
|
k1=j-half_window_size;
|
426
|
k2=j+half_window_size;
|
427
|
sum1 = sum1 - smooth_1[k1-1]+smooth_1[k2];
|
428
|
smooth_2[j]=sum1/w;
|
429
|
if(smooth_2[j]>maxi)
|
430
|
maxi = smooth_2[j];
|
431
|
else if(smooth_2[j]<mini)
|
432
|
mini = smooth_2[j];
|
433
|
}
|
434
|
|
435
|
for (j = half_window_size; j < array_size-half_window_size; j++)
|
436
|
{
|
437
|
normal[j] = (smooth_2[j] - mini) / (maxi - mini);
|
438
|
if (normal[j] < threshold_noise_removal)
|
439
|
normal[j] = 0;
|
440
|
}
|
441
|
}
|
442
|
|
443
|
|
444
|
//////////////peak detection
|
445
|
|
446
|
void peakdetect(double* input,int array_size,double delt)
|
447
|
{
|
448
|
numbr=0;
|
449
|
int pp_pos = 0;
|
450
|
int chk=0;
|
451
|
int pv_pos = 0;
|
452
|
double pp_val = input[0];
|
453
|
double pv_val = input[0];
|
454
|
int nmbr = 0;
|
455
|
int j = 0;
|
456
|
|
457
|
for (j = 0; j < array_size; j++)
|
458
|
{
|
459
|
if (input[j] >= pp_val)
|
460
|
{
|
461
|
pp_pos = j;
|
462
|
pp_val = input[j];
|
463
|
chk=0;
|
464
|
continue;
|
465
|
}
|
466
|
else if (pp_val - input[j] < delt)
|
467
|
{
|
468
|
chk=0;
|
469
|
continue;
|
470
|
}
|
471
|
else
|
472
|
{
|
473
|
peak_index[nmbr] = pp_pos;
|
474
|
chk=1;
|
475
|
pv_pos = j;
|
476
|
pv_val = input[j];
|
477
|
}
|
478
|
|
479
|
while (j < array_size)
|
480
|
{
|
481
|
j++;
|
482
|
if (input[j] < pv_val)
|
483
|
{
|
484
|
pv_val = input[j];
|
485
|
}
|
486
|
|
487
|
else if (input[j] - pv_val < delt)
|
488
|
{
|
489
|
}
|
490
|
|
491
|
else
|
492
|
{
|
493
|
valley_index[nmbr] = pv_pos;
|
494
|
chk=2;
|
495
|
nmbr++;
|
496
|
pp_pos = j;
|
497
|
pp_val = input[j];
|
498
|
break;
|
499
|
}
|
500
|
}
|
501
|
}
|
502
|
|
503
|
if (chk!=1)
|
504
|
nmbr--;
|
505
|
|
506
|
// nmbr++;
|
507
|
|
508
|
numbr=nmbr;
|
509
|
}
|
510
|
|
511
|
|
512
|
|
513
|
/**
|
514
|
* prints a character array through a debug IPC object
|
515
|
* output is: "[DSP] <msg>"
|
516
|
* @param pMsg - character array of message to print
|
517
|
*/
|
518
|
|
519
|
void debugPrint(char* pMsg)
|
520
|
{
|
521
|
// The length of the message to be sent
|
522
|
int len = strlen(pMsg);
|
523
|
|
524
|
// Pointer to dsplink buffer where to write the message
|
525
|
char* pBuffer;
|
526
|
|
527
|
// Make sure the debug IPC outbound object has been initialized
|
528
|
if (gpDebug == NULL)
|
529
|
return;
|
530
|
|
531
|
// Get a buffer for the message
|
532
|
pBuffer = (char *)gpDebug->GetBuffer(len+1);
|
533
|
|
534
|
// Check that the buffer is valid
|
535
|
if (pBuffer)
|
536
|
{
|
537
|
// Copy the message to the buffer
|
538
|
strcpy(pBuffer, pMsg);
|
539
|
// Send the message
|
540
|
gpDebug->SendMessage(pBuffer);
|
541
|
}
|
542
|
}
|
543
|
|
544
|
//prints integer output
|
545
|
|
546
|
void integerPrint(int* intMsg)
|
547
|
{
|
548
|
int* lpMessageBuffer = NULL;
|
549
|
int bytes=sizeof(int);
|
550
|
|
551
|
// Make sure the intOutbound IPC outbound object has been initialized
|
552
|
if (gpOutbound == NULL)
|
553
|
return;
|
554
|
|
555
|
// Get a buffer for the message
|
556
|
lpMessageBuffer = (int *)gpOutbound->GetBuffer(200);
|
557
|
|
558
|
// Check that the buffer is valid
|
559
|
if (lpMessageBuffer!=NULL)
|
560
|
{
|
561
|
|
562
|
// int *Msg =lpMessageBuffer;
|
563
|
// Copy the message to the buffer
|
564
|
memmove(lpMessageBuffer, intMsg ,bytes);
|
565
|
|
566
|
|
567
|
// Send the message
|
568
|
gpOutbound->SendMessage(lpMessageBuffer);
|
569
|
}
|
570
|
else
|
571
|
debugPrint(debug8);
|
572
|
}
|
573
|
|
574
|
|
575
|
void send_data()
|
576
|
{
|
577
|
int* lpMessageBuffer = NULL;
|
578
|
|
579
|
// Make sure the intOutbound IPC outbound object has been initialized
|
580
|
if (gpOutbound == NULL)
|
581
|
return;
|
582
|
|
583
|
// Get a buffer for the message
|
584
|
lpMessageBuffer = (int *)gpOutbound->GetBuffer(sizeof(data_struct));
|
585
|
|
586
|
// Check that the buffer is valid
|
587
|
if (lpMessageBuffer!=NULL)
|
588
|
{
|
589
|
// Copy the message to the buffer
|
590
|
memmove(lpMessageBuffer, &data_struct,sizeof(data_struct));
|
591
|
|
592
|
// Send the message
|
593
|
gpOutbound->SendMessage(lpMessageBuffer);
|
594
|
}
|
595
|
|
596
|
else
|
597
|
debugPrint(debug8);
|
598
|
}
|