Rleg  2
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
gdatalogger.c
Go to the documentation of this file.
1 /*****************************************************************************
2 // File: GDataLogger.c
3 // Contents: Functions for recording data points in matlab format.
4 // Author: G. A. Borges.
5 *****************************************************************************/
6 #if DATALOGGER_COMPILE_FOR_CMEX
7 #include "mex.h"
8 #endif
9 
10 #include <math.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <sys/mman.h>
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <errno.h>
20 
21 #if DATALOGGER_COMPILE_FOR_XENOMAI
22  #include <native/heap.h>
23  #include <native/types.h>
24 #endif
25 
26 #include "gqueue.h"
27 #include "gmatlabdatafile.h"
28 #include "gdatalogger.h"
29 
32 
33 #if DATALOGGER_COMPILE_FOR_XENOMAI
34 RT_HEAP gDataLoggerIPC_SHM_hd;
35 #else
36 static int gDataLoggerIPC_SHM_fd = 0;
37 #endif
38 
39 /**********************************************************************************************
40 ***** gDataLogger: Init
41 **********************************************************************************************/
42 int gDataLogger_Init(PGDATALOGGER pgDataLogger, char *filename, char *dirname)
43 {
44  int i;
45  int first = 0;
46 #if DATALOGGER_COMPILE_FOR_XENOMAI
47  int err;
48 #else
49  int status = 0;
50 #endif
51 
52  /* GQueue */
53  if(pgDataLogger!=NULL){
54  for (i=0;i<GDATALOGGER_MAXVARIABLES;++i){
55  sprintf(pgDataLogger->Variables[i].VariableName," ");
56  sprintf(pgDataLogger->Variables[i].VariableUnit," ");
57  pgDataLogger->Variables[i].CircularQueue = NULL;
58  pgDataLogger->Variables[i].GMatlabDataFileIndex = 0;
59  pgDataLogger->Variables[i].Nc = 1;
60  pgDataLogger->Variables[i].Nr = 1;
61  pgDataLogger->Variables[i].HasBeenWritten = 0;
62  }
63  pgDataLogger->m_NumberOfVariables = 0;
64  }
65 
66  /* IPC */
67 #if DATALOGGER_COMPILE_FOR_XENOMAI
68  if(pgDataLogger!=NULL){
69  /* cria memoria compartilhada */
70  int heapsize;
71  if(sizeof(GDATALOGGERIPC_SHM) > ((256*1024))){
72  heapsize = sizeof(GDATALOGGERIPC_SHM);
73  }
74  else{
75  heapsize = ((256*1024));
76  }
77 
78  if((err=rt_heap_create(&gDataLoggerIPC_SHM_hd,GDATALOGGER_IPC_STATEFILE,sizeof(GDATALOGGERIPC_SHM),H_SHARED))!=0){
79  printf("gDataLogger_Init: Could not create xenomai heap object (return %i)\n", err);
80  printf("\n EEXIST = %i",EEXIST);
81  printf("\n EINVAL = %i",EINVAL);
82  printf("\n ENOMEM = %i",ENOMEM);
83  printf("\n EPERM = %i",EPERM);
84  printf("\n EIDRM = %i",EIDRM);
85  printf("\n ENOSYS = %i",ENOSYS);
86  if(err==-EEXIST){
87  err=rt_heap_delete(&gDataLoggerIPC_SHM_hd);
88  printf("gDataLogger_Init: Deleting xenomai heap object (return %i)\n", err);
89  }
90  return FALSE;
91  }
92 
93  if(rt_heap_alloc(&gDataLoggerIPC_SHM_hd,sizeof(GDATALOGGERIPC_SHM),TM_NONBLOCK,(void**)&pgDataLoggerIPC_SHM)!=0){
94  printf("gDataLogger_Init: Could not allocated xenomai heap object. (return %i)\n", err);
95  return FALSE;
96  }
97 
98  first = 1; /* We are the first instance */
100  }
101  else{
102  /* abre memoria compartilhada */
103  if((err=rt_heap_bind(&gDataLoggerIPC_SHM_hd,GDATALOGGER_IPC_STATEFILE,TM_NONBLOCK))!=0){
104  /* printf("gDataLogger_Init: Could not create xenomai heap object (return %i)\n", err); */
105 /* printf("\n EEXIST = %i",EEXIST);
106  printf("\n EINVAL = %i",EINVAL);
107  printf("\n ENOMEM = %i",ENOMEM);
108  printf("\n EPERM = %i",EPERM);
109  printf("\n EIDRM = %i",EIDRM);
110  printf("\n ENOSYS = %i",ENOSYS);*/
111  return FALSE;
112  }
113 
114  if(rt_heap_alloc(&gDataLoggerIPC_SHM_hd,0,TM_NONBLOCK,(void**)&pgDataLoggerIPC_SHM)!=0){
115  printf("gDataLogger_Init: Could not allocated xenomai heap object. (return %i)\n", err);
116  return FALSE;
117  }
118 
120  }
121 
122 #else
123  /* Try to open the shm instance with O_EXCL, this tests if the shm is already opened by someone else */
124  if((gDataLoggerIPC_SHM_fd = shm_open(GDATALOGGER_IPC_STATEFILE, (O_CREAT | O_RDWR),(S_IREAD | S_IWRITE))) < 0) {
125  /* Try to open the shm instance normally and share it with existing clients */
126  printf("gDataLogger_Init: Could not create shm object. %s\n", strerror(errno));
127  return FALSE;
128  }
129  if(pgDataLogger!=NULL){
131  first = 1;
132  } else{
134  first = 0;
135  }
136 /* if((gDataLoggerIPC_SHM_fd = shm_open(GDATALOGGER_IPC_STATEFILE, (O_CREAT | O_EXCL | O_RDWR),(S_IREAD | S_IWRITE))) > 0 ) {
137 */ first = 1; /* We are the first instance */
138 /* gDataLoggerIPC_SHM_flagmodeserver = 1;
139  }
140  else if((gDataLoggerIPC_SHM_fd = shm_open(GDATALOGGER_IPC_STATEFILE, (O_CREAT | O_RDWR),(S_IREAD | S_IWRITE))) < 0) {
141 */ /* Try to open the shm instance normally and share it with existing clients */
142 /* printf("gDataLogger_Init: Could not create shm object. %s\n", strerror(errno));
143  return FALSE;
144  }
145 */ /* Set the size of the SHM to be the size of the struct. */
146  status = ftruncate(gDataLoggerIPC_SHM_fd, sizeof(GDATALOGGERIPC_SHM));
147 
148  /* Connect the conf pointer to set to the shared memory area, with desired permissions */
149  if((pgDataLoggerIPC_SHM = mmap(0, sizeof(GDATALOGGERIPC_SHM), (PROT_READ | PROT_WRITE), MAP_SHARED, gDataLoggerIPC_SHM_fd, 0)) == MAP_FAILED) {
150  return FALSE;
151  }
152 
153  /* Set permission so all can read/write to shared memory */
154  status = fchmod(gDataLoggerIPC_SHM_fd, (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH));
155 
156 #endif
157 
158  if(first){
159  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGIDDLE;
160  }
161 
162  /* GMatlabDataFile */
163  if((pgDataLogger!=NULL)&&(filename!=NULL)){
164  return(gMATLABDataFile_OpenWrite(&pgDataLogger->GMatlabDataFileConfig, filename, dirname));
165  }
166 
167  return TRUE;
168 }
169 
170 /**********************************************************************************************
171 ***** gDataLogger: DeclareVariable
172 **********************************************************************************************/
173 int gDataLogger_DeclareVariable(PGDATALOGGER pgDataLogger, char *varname, char *varunit, int nrows, int ncols, int queuesize)
174 {
175  if(pgDataLogger->m_NumberOfVariables>=GDATALOGGER_MAXVARIABLES-1){
176  return(FALSE);
177  }
178  queuesize = queuesize * nrows * ncols; /* no caso, o tamanho da fila eh calculado em numero de elementos double. */
179  sprintf(pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].VariableName,"%s",varname);
180  sprintf(pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].VariableUnit,"%s",varunit);
181  pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].CircularQueue = (double *) malloc(queuesize * nrows * ncols * sizeof(double));
182  if(pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].CircularQueue==NULL){
183  return(FALSE);
184  }
185  pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].Nr = nrows;
186  pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].Nc = ncols;
187  gQUEUE_Init(&pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].CircularQueueControl, queuesize, QUEUE_MAXDESTINATIONS);
188  pgDataLogger->Variables[pgDataLogger->m_NumberOfVariables].GMatlabDataFileIndex = 0;
189 
190  ++pgDataLogger->m_NumberOfVariables;
191 
192  return(TRUE);
193 }
194 
195 
196 /**********************************************************************************************
197 ***** gDataLogger: InsertVariable
198 **********************************************************************************************/
199 int gDataLogger_InsertVariable(PGDATALOGGER pgDataLogger, char *varname, double *varvalue)
200 {
201  int queueindex,varindex,n;
202  long int nr,nc;
203  int FlagQueueFull;
204 
205  /* Procura pela variavel */
206  varindex = -1;
207  for(n=0;n<pgDataLogger->m_NumberOfVariables;++n){
208  if(strcmp(varname,pgDataLogger->Variables[n].VariableName)==0){
209  varindex = n;
210  break;
211  }
212  }
213  if(varindex<0){
214  return(FALSE);
215  }
216 
217  if(pgDataLogger->Variables[varindex].HasBeenWritten == 1) pgDataLogger->Variables[varindex].HasBeenWritten = 2; // Second write
218  if(pgDataLogger->Variables[varindex].HasBeenWritten == 0) pgDataLogger->Variables[varindex].HasBeenWritten = 1; // First write (1 data point)
219 
220  /* Insere o conteudo */
221  for(nr=0;nr<pgDataLogger->Variables[varindex].Nr;++nr){
222  for(nc=0;nc<pgDataLogger->Variables[varindex].Nc;++nc){
223  FlagQueueFull = gQUEUE_RequestWriteIndex(&pgDataLogger->Variables[varindex].CircularQueueControl, &queueindex);
224 
225  pgDataLogger->Variables[varindex].CircularQueue[queueindex] = varvalue[nr+(nc)*pgDataLogger->Variables[varindex].Nr];
226 
227  if(!FlagQueueFull){
228  /* The queue is full. Test if it is the reading head associated to matlab data files. */
229  if(pgDataLogger->Variables[varindex].CircularQueueControl.FlagFull[QUEUE_DESTINATION_FILE]==TRUE){
230  /* Empty in matlab data file. */
231  gDataLogger_MatfileUpdate(pgDataLogger);
232  /* Clear flag: */
234  }
235  }
236  }
237  }
238 
239  return(TRUE);
240 }
241 
242 /**********************************************************************************************
243 ***** gDataLogger: Update
244 **********************************************************************************************/
246 {
247  int QueueIndex,nvar,datasize,i;
248  double *v;
249  char matvarname[70];
250 
251  /********** MATFILE **********/
252  /* Esvaziar queues de todas as variaveis que vao para o arquivo: */
253  for(nvar=0;nvar<pgDataLogger->m_NumberOfVariables;++nvar){
254  /* Metodo otimizado, que salva em uma variavel MATLAB todas as ultimas leituras. */
256  return(FALSE);
257  }
258  if(datasize>0){ /* Existem dados a serem salvos. */
259  v = (double *) malloc(datasize * sizeof(double));
260  for(i=0;i<datasize;++i){
262  v[i] = pgDataLogger->Variables[nvar].CircularQueue[QueueIndex];
263  }
264  sprintf(matvarname,"%s_%li_%li",pgDataLogger->Variables[nvar].VariableName,pgDataLogger->Variables[nvar].GMatlabDataFileIndex,pgDataLogger->Variables[nvar].GMatlabDataFileIndex+datasize-1);
265  gMATLABDataFile_SaveVector(&pgDataLogger->GMatlabDataFileConfig, matvarname, v, datasize);
266  free(v);
267  pgDataLogger->Variables[nvar].GMatlabDataFileIndex += datasize;
268  }
269  }
270 
271  return(TRUE);
272 }
273 
275 {
276  int QueueIndex,nvar,n,i;
277 
278  /********** IPC **********/
280  return FALSE;
281  }
282 
283  if(pgDataLoggerIPC_SHM->Flag == GDATALOGGER_IPC_FLAGREQUESTDATA){
284 
285  /* Procura pela variavel */
286  nvar = -1;
287  for(n=0;n<pgDataLogger->m_NumberOfVariables;++n){
288  if(strcmp(pgDataLoggerIPC_SHM->VariableName,pgDataLogger->Variables[n].VariableName)==0){
289  nvar = n;
290  break;
291  }
292  }
293  if(nvar<0){
294  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGNOTEXIST;
295  return FALSE;
296  }
297 
298  /* Metodo otimizado, que salva em uma variavel MATLAB todas as ultimas leituras. */
299  if(!gQUEUE_GetNumberOfUnreadData(&pgDataLogger->Variables[nvar].CircularQueueControl, QUEUE_DESTINATION_IPC, &pgDataLoggerIPC_SHM->QueueSize)){
300  pgDataLoggerIPC_SHM->QueueSize = 0;
301  }
302  if(pgDataLoggerIPC_SHM->QueueSize>0){ /* Existem dados a serem salvos. */
303  for(i=0;i<pgDataLoggerIPC_SHM->QueueSize;++i){
305  pgDataLoggerIPC_SHM->QueueData[i] = pgDataLogger->Variables[nvar].CircularQueue[QueueIndex];
306  }
307  }
308 
309  sprintf(pgDataLoggerIPC_SHM->VariableUnit, "%s", pgDataLogger->Variables[nvar].VariableUnit);
310  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGDATAAVAILABLE;
311  }
312 
313  return(TRUE);
314 }
315 
316 /**********************************************************************************************
317 ***** gDataLogger: gDataLogger_IPC_RetrieveVariable
318 **********************************************************************************************/
319 int gDataLogger_IPC_RetrieveVariable(char *varname, char *varunit, double *pbuffer, int *bufferlen)
320 {
321  int counter;
322 
323  sprintf(pgDataLoggerIPC_SHM->VariableName, "%s", varname);
324  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGREQUESTDATA;
325 
326 /* printf("\ngDataLogger_IPC_RetrieveVariable: solicitação feita pela variavel %s",varname); */
327 
328  counter = 0;
329  while(pgDataLoggerIPC_SHM->Flag == GDATALOGGER_IPC_FLAGREQUESTDATA){
330  usleep(10000);
331  if(++counter > 100){
332  *bufferlen = 0;
333  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGIDDLE;
334  /* printf("\ngDataLogger_IPC_RetrieveVariable: solicitação não atendida"); */
336  }
337  }
338 
339  if(pgDataLoggerIPC_SHM->Flag==GDATALOGGER_IPC_FLAGDATAAVAILABLE){
340  memcpy(pbuffer,pgDataLoggerIPC_SHM->QueueData, pgDataLoggerIPC_SHM->QueueSize * sizeof(double));
341  sprintf(varunit, "%s", pgDataLoggerIPC_SHM->VariableUnit);
342  *bufferlen = pgDataLoggerIPC_SHM->QueueSize;
343  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGIDDLE;
345  }
346 
347  if(pgDataLoggerIPC_SHM->Flag==GDATALOGGER_IPC_FLAGNOTEXIST){
348  *bufferlen = 0;
349  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGIDDLE;
351  }
352 
353  *bufferlen = 0;
354  pgDataLoggerIPC_SHM->Flag = GDATALOGGER_IPC_FLAGIDDLE;
356 }
357 
358 
359 /**********************************************************************************************
360 ***** gDataLogger: Close
361 **********************************************************************************************/
363 {
364  int nvar,datasize;
365  double v;
366  double *value;
367  char matvarname[70];
368 
369  /* Garante salvar ultimos dados inseridos: */
370  if(pgDataLogger!=NULL){
371  gDataLogger_MatfileUpdate(pgDataLogger);
372 
373  /* Se for um unico escalar, trata de forma especial: */
374  for(nvar=0;nvar<pgDataLogger->m_NumberOfVariables;++nvar){
375  if((pgDataLogger->Variables[nvar].Nc == 1)&&(pgDataLogger->Variables[nvar].Nr == 1)){
376  if(pgDataLogger->Variables[nvar].HasBeenWritten == 1){
377  value = (double *) malloc(sizeof(double));
378  value[0] = pgDataLogger->Variables[nvar].CircularQueue[0];
379  sprintf(matvarname,"%s_%li_%li",pgDataLogger->Variables[nvar].VariableName, (long int)0, (long int)0);
380  gMATLABDataFile_SaveVector(&pgDataLogger->GMatlabDataFileConfig, matvarname, value, 1);
381  free(value);
382  pgDataLogger->Variables[nvar].GMatlabDataFileIndex = 1;
383  }
384  }
385  }
386 
387  /* Cria variaveis que indicam o numero de cada variavel salva: */
388  for(nvar=0;nvar<pgDataLogger->m_NumberOfVariables;++nvar){
389  v = (double)(pgDataLogger->Variables[nvar].GMatlabDataFileIndex);
390  datasize = 1;
391  sprintf(matvarname,"%s_size",pgDataLogger->Variables[nvar].VariableName);
392  gMATLABDataFile_SaveVector(&pgDataLogger->GMatlabDataFileConfig, matvarname, &v, datasize);
393  }
394 
395  /* Salva o numero de linhas: */
396  for(nvar=0;nvar<pgDataLogger->m_NumberOfVariables;++nvar){
397  v = (double)(pgDataLogger->Variables[nvar].Nr);
398  datasize = 1;
399  sprintf(matvarname,"%s_nr",pgDataLogger->Variables[nvar].VariableName);
400  gMATLABDataFile_SaveVector(&pgDataLogger->GMatlabDataFileConfig, matvarname, &v, datasize);
401  }
402 
403  /* Salva o numero de colunas: */
404  for(nvar=0;nvar<pgDataLogger->m_NumberOfVariables;++nvar){
405  v = (double)(pgDataLogger->Variables[nvar].Nc);
406  datasize = 1;
407  sprintf(matvarname,"%s_nc",pgDataLogger->Variables[nvar].VariableName);
408  gMATLABDataFile_SaveVector(&pgDataLogger->GMatlabDataFileConfig, matvarname, &v, datasize);
409  }
410 
411  /* Fecha o arquivo. */
413 
414  /* Deletar as filas: */
415  for(nvar=0;nvar<pgDataLogger->m_NumberOfVariables;++nvar){
416  sprintf(pgDataLogger->Variables[nvar].VariableName," ");
417  sprintf(pgDataLogger->Variables[nvar].VariableUnit," ");
418  free(pgDataLogger->Variables[nvar].CircularQueue);
419  pgDataLogger->Variables[nvar].CircularQueue = NULL;
420  pgDataLogger->Variables[nvar].GMatlabDataFileIndex = 0;
421  }
422  pgDataLogger->m_NumberOfVariables = 0;
423  }
424 
425  /* IPC: */
426 #if DATALOGGER_COMPILE_FOR_XENOMAI
428  rt_heap_free(&gDataLoggerIPC_SHM_hd,pgDataLoggerIPC_SHM);
429  rt_heap_delete(&gDataLoggerIPC_SHM_hd);
430  } else{
431  rt_heap_unbind(&gDataLoggerIPC_SHM_hd);
432  }
433 #else
434  munmap(pgDataLoggerIPC_SHM, sizeof(GDATALOGGERIPC_SHM));
435  close(gDataLoggerIPC_SHM_fd);
436  shm_unlink(GDATALOGGER_IPC_STATEFILE);
437 #endif
438 
439  return(TRUE);
440 }
441 
442 /****************************************************************
443 ****
444 **** Scope
445 ****
446 ****************************************************************/
447 /*
448 int GDataLogger::ScopeCreate(CWnd *pIDCWindow, int nIDC, PGDATALOGGERSCOPEPARAMETERS pDataLoggerScopeParameters)
449 {
450  // Verify whether there is available Scope:
451  if (pgDataLogger->m_NumberOfScopes>=(GDATALOGGER_MAXSCOPES-1)){
452  return(FALSE);
453  }
454 
455  // nIDC, pWnd and pDC:
456  pgDataLogger->Scopes[m_NumberOfScopes].nIDC = nIDC;
457  pgDataLogger->Scopes[m_NumberOfScopes].pWnd = pIDCWindow;
458  pgDataLogger->Scopes[m_NumberOfScopes].pDC = pgDataLogger->Scopes[m_NumberOfScopes].pWnd->GetDC();
459  pgDataLogger->Scopes[m_NumberOfScopes].NumberOfInsertedVariables = 0;
460 
461  // Parameters:
462  memcpy(&pgDataLogger->Scopes[m_NumberOfScopes].Parameters,pDataLoggerScopeParameters,sizeof(GDATALOGGERSCOPEPARAMETERS));
463 
464  // Previously ploted? No
465  for(int i=0;i<GDATALOGGER_MAXVARIABLES;++i){
466  pgDataLogger->Scopes[m_NumberOfScopes].FirstPointPloted[i] = FALSE;
467  }
468 
469  // Compute rectangles:
470  CRect Rect;
471  TEXTMETRIC TextMetric;
472 
473  pgDataLogger->Scopes[m_NumberOfScopes].pWnd->GetWindowRect(&Rect);
474  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.left = 0;
475  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.top = 0;
476  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.right = Rect.right - Rect.left;
477  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.bottom = Rect.bottom - Rect.top;
478 
479  pgDataLogger->Scopes[m_NumberOfScopes].pDC->GetTextMetrics(&TextMetric);
480  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectPlotPix.left =
481  + pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.left
482  + 2*TextMetric.tmHeight // Numeros dos eixos
483  + 1*TextMetric.tmHeight + 2; // Label
484  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectPlotPix.top = pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.top + TextMetric.tmExternalLeading + TextMetric.tmHeight + 2;
485  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectPlotPix.right = pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.right - (2*TextMetric.tmMaxCharWidth + 2);
486  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectPlotPix.bottom = pgDataLogger->Scopes[m_NumberOfScopes].Parameters.RectDCPix.bottom - TextMetric.tmExternalLeading - 2*TextMetric.tmHeight - 2;
487 
488  // Fonts, Pens, Brushs.
489  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.TextFont.CreateFont(
490  -10,
491  0,
492  0,
493  0,
494  FW_SEMIBOLD,
495  FALSE,
496  FALSE,
497  0,
498  ANSI_CHARSET,
499  OUT_DEFAULT_PRECIS,
500  CLIP_DEFAULT_PRECIS,
501  DEFAULT_QUALITY,
502  DEFAULT_PITCH | FF_SWISS,
503  "Arial");
504 
505  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.TextFontRotated.CreateFont(
506  -10,
507  0,
508  900,
509  0,
510  FW_SEMIBOLD,
511  FALSE,
512  FALSE,
513  0,
514  ANSI_CHARSET,
515  OUT_DEFAULT_PRECIS,
516  CLIP_DEFAULT_PRECIS,
517  DEFAULT_QUALITY,
518  DEFAULT_PITCH | FF_SWISS,
519  "Arial");
520 
521  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.ScopePen.CreatePen(
522  PS_SOLID,
523  1,
524  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.ScopeColor);
525 
526  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.ScopeBrush.CreateSolidBrush(
527  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.ScopeColor);
528 
529  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.BackgroundBrush.CreateSolidBrush(
530  pgDataLogger->Scopes[m_NumberOfScopes].Parameters.BackgroundColor);
531 
532  // Increment the number of scopes:
533  ++pgDataLogger->m_NumberOfScopes;
534 
535  return(TRUE);
536 }
537 
538 void GDataLogger::ScopeClose(void)
539 {
540  int i;
541 
542  for(int nscope=0;nscope <pgDataLogger->m_NumberOfScopes;++nscope){
543  // Release DC:
544  pgDataLogger->Scopes[nscope].pWnd->ReleaseDC(pgDataLogger->Scopes[nscope].pDC);
545  // Clear inserted variables
546  pgDataLogger->Scopes[nscope].NumberOfInsertedVariables = 0;
547  // Default time source index
548  pgDataLogger->Scopes[nscope].TimeSourceIndex = -1;
549  //
550  for(i=0;i<GDATALOGGER_MAXVARIABLES;++i){
551  pgDataLogger->Scopes[nscope].FirstPointPloted[i] = FALSE;
552  }
553  }
554 }
555 
556 void GDataLogger::ScopeSetDefaultParameters(PGDATALOGGERSCOPEPARAMETERS pDataLoggerScopeParameters)
557 {
558  pDataLoggerScopeParameters->X_DivNumber = 9;
559  pDataLoggerScopeParameters->Y_DivNumber = 7;
560  pDataLoggerScopeParameters->X_Offset = 0.0;
561  pDataLoggerScopeParameters->X_DivScale = 1.0;
562  pDataLoggerScopeParameters->Y_Offset = 0.0;
563  pDataLoggerScopeParameters->Y_DivScale = 1.0;
564  pDataLoggerScopeParameters->BackgroundColor = RGB(255,255,255);
565  pDataLoggerScopeParameters->ScopeColor = RGB(0,0,255);
566  pDataLoggerScopeParameters->TextColor = RGB(128,0,64);
567 }
568 
569 int GDataLogger::ScopeDraw(int nIDC, int FlagErase)
570 {
571  int nscope;
572 
573  // Get scope index from IDC
574  if((nscope = pgDataLogger->ScopeGetIndex(nIDC))<0){
575  return(FALSE);
576  }
577  if(FlagErase)
578  pgDataLogger->ScopeDrawAxis(nscope);
579  pgDataLogger->ScopeDrawPlotVariables(nscope);
580  return(TRUE);
581 }
582 
583 int GDataLogger::ScopeInsertVariable(int nIDC, char *varname)
584 {
585  int scopeindex,varindex;
586 
587  // Get scope index from IDC
588  if((scopeindex = pgDataLogger->ScopeGetIndex(nIDC))<0){
589  return(FALSE);
590  }
591 
592  if (pgDataLogger->Scopes[scopeindex].NumberOfInsertedVariables>=(GDATALOGGER_MAXVARIABLES-1)){
593  return(FALSE);
594  }
595 
596  // Get variable index from varname
597  if((varindex = pgDataLogger->VariableGetIndex(varname))<0){
598  return(FALSE);
599  }
600 
601  pgDataLogger->Scopes[scopeindex].InsertedVariablesIndex[pgDataLogger->Scopes[scopeindex].NumberOfInsertedVariables] = varindex;
602  pgDataLogger->Scopes[scopeindex].FirstPointPloted[pgDataLogger->Scopes[scopeindex].NumberOfInsertedVariables] = FALSE;
603 
604  ++pgDataLogger->Scopes[scopeindex].NumberOfInsertedVariables;
605 
606  return(TRUE);
607 }
608 
609 int GDataLogger::ScopeDefineTimeSource(int nIDC, char *varname)
610 {
611  int scopeindex,varindex;
612 
613  // Get scope index from IDC
614  if((scopeindex = pgDataLogger->ScopeGetIndex(nIDC))<0){
615  return(FALSE);
616  }
617 
618  // Get variable index from varname
619  if (varname != NULL){
620  if((varindex = pgDataLogger->VariableGetIndex(varname))<0){
621  return(FALSE);
622  }
623  pgDataLogger->Scopes[scopeindex].TimeSourceIndex = varindex;
624  }
625  else{
626  pgDataLogger->Scopes[scopeindex].TimeSourceIndex = -1;
627  }
628 
629  return(TRUE);
630 }
631 
632 void TextOutRotated(CDC* pDC, const CString str, int x, int y, double angle)
633 {
634  // convert angle to radian
635  double pi = 3.141592654;
636  double radian = pi * 2 / 360 * angle;
637 
638  // get the center of a not-rotated text
639  CSize TextSize = pDC->GetTextExtent(str);
640  CPoint center;
641  center.x = TextSize.cx / 2;
642  center.y = TextSize.cy / 2;
643 
644  // now calculate the center of the rotated text
645  CPoint rcenter;
646  rcenter.x = long(cos(radian) * center.x - sin(radian) * center.y);
647  rcenter.y = long(sin(radian) * center.x + cos(radian) * center.y);
648 
649  // finally draw the text and move it to the center of the rectangle
650  pDC->SetTextAlign(TA_BASELINE);
651  pDC->SetBkMode(TRANSPARENT);
652  pDC->TextOut(x - rcenter.x, y + rcenter.y, str);
653 }
654 
655 int GDataLogger::ScopeDrawAxis(int nscope)
656 {
657  CPen *pScopePen;
658  CPen *pOldPen;
659  CBrush *pScopeBrush;
660  CBrush *pBackgroundBrush;
661  CBrush *pOldBrush;
662  CFont *pTextFont;
663  CFont *pTextFontRotated;
664  CFont *pOldFont;
665  COLORREF *pTextColor;
666  CRect *pRectPlotPix;
667  CRect *pRectDCPix;
668  double X_DivScale;
669  double Y_DivScale;
670  double X_Offset;
671  double Y_Offset;
672  int X_DivNumber;
673  int Y_DivNumber;
674 
675  double Xmin, Xmax, Ymin, Ymax;
676 
677  CString Strg;
678  POINT Points[10];
679  CRgn XArrow, YArrow;
680  int i,j;
681 
682  CWnd *pWnd;
683  CDC *pDC;
684 
685  pWnd = pgDataLogger->Scopes[nscope].pWnd;
686  pDC = pgDataLogger->Scopes[nscope].pDC;
687  pScopePen = &pgDataLogger->Scopes[nscope].Parameters.ScopePen;
688  pScopeBrush = &pgDataLogger->Scopes[nscope].Parameters.ScopeBrush;
689  pBackgroundBrush = &pgDataLogger->Scopes[nscope].Parameters.BackgroundBrush;
690  pTextFont = &pgDataLogger->Scopes[nscope].Parameters.TextFont;
691  pTextFontRotated = &pgDataLogger->Scopes[nscope].Parameters.TextFontRotated;
692  pTextColor = &pgDataLogger->Scopes[nscope].Parameters.TextColor;
693  pRectPlotPix = &pgDataLogger->Scopes[nscope].Parameters.RectPlotPix;
694  pRectDCPix = &pgDataLogger->Scopes[nscope].Parameters.RectDCPix;
695  X_DivScale = pgDataLogger->Scopes[nscope].Parameters.X_DivScale;
696  Y_DivScale = pgDataLogger->Scopes[nscope].Parameters.Y_DivScale;
697  X_Offset = pgDataLogger->Scopes[nscope].Parameters.X_Offset;
698  Y_Offset = pgDataLogger->Scopes[nscope].Parameters.Y_Offset;
699  X_DivNumber = pgDataLogger->Scopes[nscope].Parameters.X_DivNumber;
700  Y_DivNumber = pgDataLogger->Scopes[nscope].Parameters.Y_DivNumber;
701 
702  Xmin = X_Offset - (X_DivNumber/2)* X_DivScale;
703  Xmax = X_Offset + (X_DivNumber/2)* X_DivScale;
704  Ymin = Y_Offset - (Y_DivNumber/2)* Y_DivScale;
705  Ymax = Y_Offset + (Y_DivNumber/2)* Y_DivScale;
706 
707  // Save current drawing objects
708  pOldPen = (CPen*) pDC->GetCurrentPen();
709  pOldFont = (CFont*) pDC->GetCurrentFont();
710  pOldBrush = (CBrush*) pDC->GetCurrentBrush();
711 
712  // Draw Background:
713  pDC->SelectObject(pBackgroundBrush);
714  pDC->Rectangle(*pRectDCPix);
715 
716  // Draw Axis:
717  pDC->SetTextColor(*pTextColor);
718  pDC->SelectObject(pTextFont);
719  pDC->SelectObject(pScopePen);
720  pDC->SelectObject(pScopeBrush);
721  pDC->MoveTo(pRectPlotPix->left,pRectPlotPix->bottom);
722  pDC->LineTo(pRectPlotPix->right,pRectPlotPix->bottom);
723  pDC->MoveTo(pRectPlotPix->left,pRectPlotPix->bottom);
724  pDC->LineTo(pRectPlotPix->left,pRectPlotPix->top);
725 
726  Points[0].x = pRectPlotPix->right + 10; Points[0].y = pRectPlotPix->bottom - 5;
727  Points[1].x = pRectPlotPix->right + 15; Points[1].y = pRectPlotPix->bottom;
728  Points[2].x = pRectPlotPix->right + 10; Points[2].y = pRectPlotPix->bottom + 5;
729  XArrow.CreatePolygonRgn( Points, 3, WINDING);
730  Points[0].x = pRectPlotPix->left - 5; Points[0].y = pRectPlotPix->top - 10;
731  Points[1].x = pRectPlotPix->left; Points[1].y = pRectPlotPix->top - 15;
732  Points[2].x = pRectPlotPix->left + 5; Points[2].y = pRectPlotPix->top - 10;
733  YArrow.CreatePolygonRgn( Points, 3, WINDING);
734  pDC->MoveTo(pRectPlotPix->right,pRectPlotPix->bottom);
735  pDC->LineTo(pRectPlotPix->right + 10,pRectPlotPix->bottom);
736  pDC->MoveTo(pRectPlotPix->left,pRectPlotPix->top);
737  pDC->LineTo(pRectPlotPix->left,pRectPlotPix->top - 11);
738  pDC->SelectStockObject(BLACK_BRUSH);
739  pDC->PaintRgn(&XArrow);
740  pDC->PaintRgn(&YArrow);
741 
742  // Grades:
743  pDC->SetTextAlign(TA_CENTER | TA_TOP);
744  for (i=0; i<X_DivNumber; ++i){
745  pDC->MoveTo(
746  pRectPlotPix->left + (i*(pRectPlotPix->right-pRectPlotPix->left))/(X_DivNumber-1),
747  pRectPlotPix->bottom-3);
748  pDC->LineTo(
749  pRectPlotPix->left + (i*(pRectPlotPix->right-pRectPlotPix->left))/(X_DivNumber-1),
750  pRectPlotPix->bottom + 3);
751  Strg.Format("%1.1f",Xmin + i*(Xmax-Xmin)/(X_DivNumber-1));
752  pDC->TextOut(
753  pRectPlotPix->left + (i*(pRectPlotPix->right-pRectPlotPix->left))/(X_DivNumber-1),
754  pRectPlotPix->bottom + 3,
755  Strg);
756  }
757  pDC->SetTextAlign(TA_RIGHT | TA_BASELINE);
758  for (i=0; i<Y_DivNumber; ++i){
759  pDC->MoveTo(pRectPlotPix->left - 3,
760  pRectPlotPix->bottom - (i*(pRectPlotPix->bottom-pRectPlotPix->top))/(Y_DivNumber-1));
761  pDC->LineTo(pRectPlotPix->left + 3,
762  pRectPlotPix->bottom - (i*(pRectPlotPix->bottom-pRectPlotPix->top))/(Y_DivNumber-1));
763  Strg.Format("%1.1f",Ymin + i*(Ymax-Ymin)/(Y_DivNumber-1));
764  pDC->TextOut(pRectPlotPix->left - 5,
765  pRectPlotPix->bottom - (i*(pRectPlotPix->bottom-pRectPlotPix->top))/(Y_DivNumber-1),
766  Strg);
767  }
768 
769  // Labels:
770  if (pgDataLogger->Scopes[nscope].TimeSourceIndex >= 0){
771  Strg.Format("%s[%s]",pgDataLogger->Variables[pgDataLogger->Scopes[nscope].TimeSourceIndex].VariableName,pgDataLogger->Variables[pgDataLogger->Scopes[nscope].TimeSourceIndex].VariableUnit);
772  }
773  else{
774  Strg.Format("index");
775  }
776  pDC->SetTextAlign(TA_CENTER | TA_BASELINE);
777  pDC->TextOut(pRectDCPix->left + (pRectDCPix->right-pRectDCPix->left)/2,
778  pRectDCPix->bottom - 5,
779  Strg);
780 
781  pDC->SelectObject(pTextFontRotated);
782  Strg.Format("");
783  for(i=0; i<pgDataLogger->Scopes[nscope].NumberOfInsertedVariables; ++i){
784  j = pgDataLogger->Scopes[nscope].InsertedVariablesIndex[i];
785  Strg.Format("%s %s[%s]",LPCTSTR(Strg),pgDataLogger->Variables[j].VariableName,pgDataLogger->Variables[j].VariableUnit);
786  }
787  pDC->SetTextAlign(TA_CENTER | TA_BASELINE);
788  TextOutRotated(pDC, Strg, pRectDCPix->left + 5,
789  pRectDCPix->bottom + (pRectDCPix->top - pRectDCPix->bottom)/2,
790  90.0);
791  // Restore previous drawing objects
792  pDC->SelectObject(pOldPen);
793  pDC->SelectObject(pOldBrush);
794  pDC->SelectObject(pOldFont);
795 
796  return 1;
797 }
798 
799 
800 void GDataLogger::ScopeDrawPlotVariables(int nscope)
801 {
802  CPen PenData;
803  CPen *pPreviousPen;
804  int i,nvar,ninsertedvar,queueindex;
805  int Xpix, Ypix;
806  double Xpixfloat, Ypixfloat;
807  double X_DivScale;
808  double Y_DivScale;
809  double X_Offset;
810  double Y_Offset;
811  int X_DivNumber;
812  int Y_DivNumber;
813  double Xmin, Xmax, Ymin, Ymax, X, Y;
814  CRect *pRectPlotPix;
815  CWnd *pWnd;
816  CDC *pDC;
817 
818  pWnd = pgDataLogger->Scopes[nscope].pWnd;
819  pDC = pgDataLogger->Scopes[nscope].pDC;
820 
821  X_DivScale = pgDataLogger->Scopes[nscope].Parameters.X_DivScale;
822  Y_DivScale = pgDataLogger->Scopes[nscope].Parameters.Y_DivScale;
823  X_Offset = pgDataLogger->Scopes[nscope].Parameters.X_Offset;
824  Y_Offset = pgDataLogger->Scopes[nscope].Parameters.Y_Offset;
825  X_DivNumber = pgDataLogger->Scopes[nscope].Parameters.X_DivNumber;
826  Y_DivNumber = pgDataLogger->Scopes[nscope].Parameters.Y_DivNumber;
827  pRectPlotPix = &pgDataLogger->Scopes[nscope].Parameters.RectPlotPix;
828 
829  Xmin = X_Offset - (X_DivNumber/2)* X_DivScale;
830  Xmax = X_Offset + (X_DivNumber/2)* X_DivScale;
831  Ymin = Y_Offset - (Y_DivNumber/2)* Y_DivScale;
832  Ymax = Y_Offset + (Y_DivNumber/2)* Y_DivScale;
833 
834  pPreviousPen = (CPen*) pDC->GetCurrentPen();
835 
836  for(ninsertedvar=0;ninsertedvar<pgDataLogger->Scopes[nscope].NumberOfInsertedVariables;++ninsertedvar){
837  // Get varindex:
838  nvar = pgDataLogger->Scopes[nscope].InsertedVariablesIndex[ninsertedvar];
839  // Pen
840  PenData.CreatePen( PS_SOLID, 1, RGB(255,0,0));
841  pDC->SelectObject(&PenData);
842  // Empty queue:
843  i = 0;
844  while(gQUEUE_RequestReadIndex(&pgDataLogger->Variables[nvar].CircularQueueControl, QUEUE_DESTINATION_SCOPE, &queueindex)){
845  Y = pgDataLogger->Variables[nvar].CircularQueue[queueindex];
846  if (pgDataLogger->Scopes[nscope].TimeSourceIndex >= 0){
847  X = pgDataLogger->Variables[pgDataLogger->Scopes[nscope].TimeSourceIndex].CircularQueue[queueindex];
848  }
849  else{
850  break;
851  }
852  if ( (X>=Xmin) && (X<=Xmax) && (Y>=Ymin) && (Y<=Ymax) ){
853  Xpixfloat = (X-Xmin)/(Xmax-Xmin)*(pRectPlotPix->right-pRectPlotPix->left);
854  Ypixfloat = (Y-Ymin)/(Ymax-Ymin)*(pRectPlotPix->bottom-pRectPlotPix->top);
855  Xpix = (int)(Xpixfloat);
856  Ypix = (int)(Ypixfloat);
857  if (pgDataLogger->Scopes[nscope].FirstPointPloted[ninsertedvar]){
858  pDC->MoveTo(pRectPlotPix->left + pgDataLogger->Scopes[nscope].PreviousXpix[ninsertedvar], pRectPlotPix->bottom - pgDataLogger->Scopes[nscope].PreviousYpix[ninsertedvar]);
859  pDC->LineTo(pRectPlotPix->left + Xpix, pRectPlotPix->bottom - Ypix);
860  }
861  pgDataLogger->Scopes[nscope].PreviousXpix[ninsertedvar] = Xpix;
862  pgDataLogger->Scopes[nscope].PreviousYpix[ninsertedvar] = Ypix;
863  pgDataLogger->Scopes[nscope].FirstPointPloted[ninsertedvar] = TRUE;
864  ++i;
865  }
866  }
867  }
868 
869  pDC->SelectObject(pPreviousPen);
870 }
871 
872 int GDataLogger::ScopeGetIndex(int nIDC)
873 {
874  for(int n=0;n<pgDataLogger->m_NumberOfScopes;++n){
875  if(pgDataLogger->Scopes[n].nIDC==nIDC){
876  return(n);
877  }
878  }
879  return(-1);
880 }
881 */
int gMATLABDataFile_SaveVector(PGMATLABDATAFILECONFIG pGMatlabDataFileConfig, const char *varname, double *v, long nlin)
#define GDATALOGGER_IPC_FLAGDATAAVAILABLE
Definition: gdatalogger.h:41
GDATALOGGERVARIABLE Variables[GDATALOGGER_MAXVARIABLES]
Definition: gdatalogger.h:27
char VariableName[100]
Definition: gdatalogger.h:16
void gMATLABDataFile_Close(PGMATLABDATAFILECONFIG pGMatlabDataFileConfig)
int gDataLogger_InsertVariable(PGDATALOGGER pgDataLogger, char *varname, double *varvalue)
Definition: gdatalogger.c:199
#define QUEUE_DESTINATION_FILE
Definition: gdatalogger.h:33
#define GDATALOGGER_IPC_FLAGNOTEXIST
Definition: gdatalogger.h:42
#define GDATALOGGER_IPC_FLAGTIMEOUT
Definition: gdatalogger.h:43
int gMATLABDataFile_OpenWrite(PGMATLABDATAFILECONFIG pGMatlabDataFileConfig, char *filename, char *dirname)
char VariableUnit[50]
Definition: gdatalogger.h:47
GQUEUECONTROL CircularQueueControl
Definition: gdatalogger.h:22
int FlagFull[MAXSIZE_QUEUE_READ_GATES]
Definition: gqueue.h:45
#define FALSE
double * CircularQueue
Definition: gdatalogger.h:21
GMATLABDATAFILECONFIG GMatlabDataFileConfig
Definition: gdatalogger.h:29
int gDataLogger_IPC_RetrieveVariable(char *varname, char *varunit, double *pbuffer, int *bufferlen)
Definition: gdatalogger.c:319
char VariableUnit[50]
Definition: gdatalogger.h:17
long int GMatlabDataFileIndex
Definition: gdatalogger.h:18
static int gDataLoggerIPC_SHM_flagmodeserver
Definition: gdatalogger.c:31
int status
Definition: communication.c:10
#define TRUE
int gDataLogger_MatfileUpdate(PGDATALOGGER pgDataLogger)
Definition: gdatalogger.c:245
#define GDATALOGGER_IPC_FLAGIDDLE
Definition: gdatalogger.h:39
int m_NumberOfVariables
Definition: gdatalogger.h:28
#define GDATALOGGER_MAXVARIABLES
Definition: gdatalogger.h:13
static int gDataLoggerIPC_SHM_fd
Definition: gdatalogger.c:36
int gDataLogger_IPCUpdate(PGDATALOGGER pgDataLogger)
Definition: gdatalogger.c:274
double QueueData[GDATALOGGER_IPC_MAXQUEUESIZE]
Definition: gdatalogger.h:48
#define GDATALOGGER_IPC_STATEFILE
Definition: gdatalogger.h:56
#define GDATALOGGER_IPC_FLAGREQUESTDATA
Definition: gdatalogger.h:40
int gDataLogger_DeclareVariable(PGDATALOGGER pgDataLogger, char *varname, char *varunit, int nrows, int ncols, int queuesize)
Definition: gdatalogger.c:173
char VariableName[100]
Definition: gdatalogger.h:46
int gDataLogger_Close(PGDATALOGGER pgDataLogger)
Definition: gdatalogger.c:362
int gQUEUE_RequestWriteIndex(PGQUEUECONTROL pQueueControl, int *Index)
Definition: gqueue.c:233
#define QUEUE_MAXDESTINATIONS
Definition: gdatalogger.h:32
int gDataLogger_Init(PGDATALOGGER pgDataLogger, char *filename, char *dirname)
Definition: gdatalogger.c:42
int gQUEUE_GetNumberOfUnreadData(PGQUEUECONTROL pQueueControl, int NReader, int *Index)
Definition: gqueue.c:314
#define QUEUE_DESTINATION_IPC
Definition: gdatalogger.h:34
int gQUEUE_RequestReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int *Index)
Definition: gqueue.c:117
static GDATALOGGERIPC_SHM * pgDataLoggerIPC_SHM
Definition: gdatalogger.c:30
int gQUEUE_Init(PGQUEUECONTROL pQueueControl, int Size, int NReaders)
Definition: gqueue.c:31