File: rt_logging.c1 /* 2 * 3 * Copyright 1994-2012 The MathWorks, Inc. 4 * 5 * File: rt_logging.c 6 * 7 * Abstract: 8 * Real-Time Workshop data logging routines using circular buffers of 9 * fixed size. The buffers are allocated at start, filled in at each 10 * major time step and finally written to a MAT-file at the end of the 11 * simulation. 12 * 13 * This file handles redefining the following standard MathWorks types 14 * (see tmwtypes.h): 15 * [u]int8_T to be int32_T (logged as Matlab [u]int32) 16 * [u]int16_T to be int32_T (logged as Matlab [u]int32) 17 * real_T to be real32_T (logged as Matlab single) 18 * 19 */ 20 21 #include <stdlib.h> 22 #include <string.h> 23 #include <stdio.h> 24 #include <math.h> 25 26 27 #if !defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1) 28 29 #include <stddef.h> /* size_t */ 30 #include "rtwtypes.h" 31 #include "rt_mxclassid.h" 32 #include "rtw_matlogging.h" 33 #include "rt_logging.h" 34 35 #ifndef TMW_NAME_LENGTH_MAX 36 #define TMW_NAME_LENGTH_MAX 64 37 #endif 38 #define mxMAXNAM TMW_NAME_LENGTH_MAX /* maximum name length */ 39 #define matUNKNOWN 0 40 #define matINT8 1 41 #define matUINT8 2 42 #define matINT16 3 43 #define matUINT16 4 44 #define matINT32 5 45 #define matUINT32 6 46 #define matFLOAT 7 47 #define matDOUBLE 9 48 #define matINT64 12 49 #define matUINT64 13 50 #define matMATRIX 14 51 52 #define matLOGICAL_BIT 0x200 53 #define matCOMPLEX_BIT 0x800 54 55 #define matKEY 0x4D49 56 #define matVERSION 0x0100 57 #define matVERSION_INFO_OFFSET 124L 58 59 #define matINT64_ALIGN(e) ( ( ((unsigned)(e))+7 ) & (~7) ) 60 #define matTAG_SIZE (sizeof(int32_T) << 1) 61 62 #ifndef DEFAULT_BUFFER_SIZE 63 #define DEFAULT_BUFFER_SIZE 1024 /* used if maxRows=0 and Tfinal=0.0 */ 64 #endif 65 66 #define FREE(m) if (m != NULL) free(m) 67 68 /*==========* 69 * typedefs * 70 *==========*/ 71 72 typedef struct LogInfo_Tag { 73 LogVar *t; /* Time log variable */ 74 void *x; /* State log variable */ 75 void *sl; /* SigLog log variable */ 76 int_T ny; /* Length of "y" log variables */ 77 void **y; /* Output log vars */ 78 void *xFinal; /* Final state log variable */ 79 80 LogVar *logVarsList; /* Linked list of all LogVars */ 81 StructLogVar *structLogVarsList; /* Linked list of all StructLogVars */ 82 83 boolean_T haveLogVars; /* Are logging one or more vars? */ 84 } LogInfo; 85 86 typedef struct MatItem_tag { 87 int32_T type; 88 uint32_T nbytes; 89 const void *data; 90 } MatItem; 91 92 typedef enum { 93 DATA_ITEM, 94 MATRIX_ITEM, 95 STRUCT_LOG_VAR_ITEM, 96 SIGNALS_STRUCT_ITEM 97 } ItemDataKind; 98 99 /*===========* 100 * Constants * 101 *===========*/ 102 103 static const char_T rtMemAllocError[] = "Memory allocation error"; 104 105 #define ZEROS32 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 106 107 #if mxMAXNAM==32 108 109 #define ZERO_PAD 110 111 #elif mxMAXNAM==64 112 113 #define ZERO_PAD ZEROS32 114 115 #elif mxMAXNAM==128 116 117 #define ZERO_PAD ZEROS32 ZEROS32 ZEROS32 118 119 #else 120 121 #error "Cannot Handle mxMAXNAM other than 32,64, and 128" 122 123 #endif 124 /* field names: for variable-size signal logging */ 125 static const char_T rtStructLogVarFieldNames[] = 126 "time\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 127 "signals\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 128 "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 129 static const char_T rtLocalLoggingSignalsStructFieldNames[] = 130 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 131 "valueDimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 132 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 133 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 134 "title\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 135 "plotStyle\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 136 static const char_T rtGlobalLoggingSignalsStructFieldNames[] = 137 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 138 "valueDimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 139 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 140 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 141 "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 142 "stateName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 143 "inReferencedModel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 144 #define TIME_FIELD_NAME (rtStructLogVarFieldNames[0*mxMAXNAM]) 145 #define SIGNALS_FIELD_NAME (rtStructLogVarFieldNames[1*mxMAXNAM]) 146 #define BLOCKNAME_FIELD_NAME (rtStructLogVarFieldNames[2*mxMAXNAM]) 147 148 #define VALUES_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[0*mxMAXNAM]) 149 #define VALUEDIMENSIONS_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[1*mxMAXNAM]) 150 #define DIMENSION_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[2*mxMAXNAM]) 151 #define LABEL_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[3*mxMAXNAM]) 152 #define TITLE_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[4*mxMAXNAM]) 153 #define PLOTSTYLE_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[5*mxMAXNAM]) 154 155 #define STATENAME_FIELD_NAME (rtGlobalLoggingSignalsStructFieldNames[5*mxMAXNAM]) 156 #define CROSS_MDL_REF_FIELD_NAME (rtGlobalLoggingSignalsStructFieldNames[6*mxMAXNAM]) 157 158 /* field names: for fixed-size signal logging */ 159 static const char_T rtLocalLoggingSignalsStructFieldNames_noValDims[] = 160 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 161 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 162 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 163 "title\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 164 "plotStyle\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 165 static const char_T rtGlobalLoggingSignalsStructFieldNames_noValDims[] = 166 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 167 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 168 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 169 "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 170 "stateName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 171 "inReferencedModel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 172 173 extern real_T rtInf; /* declared by rt_nonfinite.c */ 174 extern real_T rtNaN; 175 extern real32_T rtNaNF; 176 177 /*================* 178 * Local routines * 179 *================*/ 180 181 /* Function: rt_GetSizeofDataType ============================================== 182 * Abstract: 183 * Get the element size in bytes given the data type id. 184 */ 185 static size_t rt_GetSizeofDataType(BuiltInDTypeId dTypeID) 186 { 187 size_t elSz = 0; /* unknown */ 188 189 switch (dTypeID) { 190 case SS_DOUBLE: 191 elSz = sizeof(real_T); 192 break; 193 case SS_SINGLE: 194 elSz = sizeof(real32_T); 195 break; 196 case SS_INT8: 197 elSz = sizeof(int8_T); 198 break; 199 case SS_UINT8: 200 elSz = sizeof(uint8_T); 201 break; 202 case SS_INT16: 203 elSz = sizeof(int16_T); 204 break; 205 case SS_UINT16: 206 elSz = sizeof(uint16_T); 207 break; 208 case SS_INT32: 209 elSz = sizeof(int32_T); 210 break; 211 case SS_UINT32: 212 elSz = sizeof(uint32_T); 213 break; 214 case SS_BOOLEAN: 215 elSz = sizeof(boolean_T); 216 break; 217 } 218 return(elSz); 219 220 } /* end rt_GetSizeofDataType */ 221 222 223 /* Function: rt_GetSizeofComplexType =========================================== 224 * Abstract: 225 * Get the element size in bytes given the data type id. 226 */ 227 static size_t rt_GetSizeofComplexType(BuiltInDTypeId dTypeID) 228 { 229 size_t elSz = 2*rt_GetSizeofDataType(dTypeID); 230 231 switch (dTypeID) { 232 case SS_DOUBLE: 233 #ifdef CREAL_T 234 elSz = sizeof(creal_T); 235 #endif 236 break; 237 case SS_SINGLE: 238 #ifdef CREAL_T 239 elSz = sizeof(creal32_T); 240 #endif 241 break; 242 case SS_INT8: 243 #ifdef _CINT8_T 244 elSz = sizeof(cint8_T); 245 #endif 246 break; 247 case SS_UINT8: 248 #ifdef _CUINT8_T 249 elSz = sizeof(cuint8_T); 250 #endif 251 break; 252 case SS_INT16: 253 #ifdef _CINT16_T 254 elSz = sizeof(cint16_T); 255 #endif 256 break; 257 case SS_UINT16: 258 #ifdef _CUINT16_T 259 elSz = sizeof(cuint16_T); 260 #endif 261 break; 262 case SS_INT32: 263 #ifdef _CINT32_T 264 elSz = sizeof(cint32_T); 265 #endif 266 break; 267 case SS_UINT32: 268 #ifdef _CUINT32_T 269 elSz = sizeof(cuint32_T); 270 #endif 271 break; 272 case SS_BOOLEAN: 273 elSz = sizeof(boolean_T); 274 break; 275 } 276 277 return(elSz); 278 279 } /* end rt_GetSizeofComplexType */ 280 281 282 /* Function: rt_GetDataTypeConvertInfo ========================================= 283 * Abstract: 284 * Directly copy if pointer to structure is non-NULL, otherwise set to 285 * default. 286 */ 287 static RTWLogDataTypeConvert rt_GetDataTypeConvertInfo( 288 const RTWLogDataTypeConvert *pDataTypeConvertInfo, 289 BuiltInDTypeId dTypeID 290 ) 291 { 292 RTWLogDataTypeConvert dataTypeConvertInfoCopy; 293 294 if (pDataTypeConvertInfo == NULL) { 295 dataTypeConvertInfoCopy.conversionNeeded = 0; 296 dataTypeConvertInfoCopy.dataTypeIdLoggingTo = dTypeID; 297 dataTypeConvertInfoCopy.dataTypeIdOriginal = (DTypeId)dTypeID; 298 dataTypeConvertInfoCopy.bitsPerChunk = 0; 299 dataTypeConvertInfoCopy.numOfChunk = 0; 300 dataTypeConvertInfoCopy.isSigned = 0; 301 dataTypeConvertInfoCopy.fracSlope = 1.0; 302 dataTypeConvertInfoCopy.fixedExp = 0; 303 dataTypeConvertInfoCopy.bias = 0.0; 304 } else { 305 dataTypeConvertInfoCopy = *pDataTypeConvertInfo; 306 } 307 308 return dataTypeConvertInfoCopy; 309 310 } /* end rt_GetDataTypeConvertInfo */ 311 312 313 /* Function: rt_GetDblValueFromOverSizedData =================================== 314 * Abstract: 315 */ 316 static double rt_GetDblValueFromOverSizedData( 317 const void *pVoid, 318 int bitsPerChunk, 319 int numOfChunk, 320 unsigned int isSigned, 321 double fracSlope, 322 int fixedExp, 323 double bias) 324 { 325 double retValue = 0; 326 327 double *dblValue = (double *) calloc(numOfChunk, sizeof(double)); 328 329 int i; 330 double isSignedNeg; 331 332 if(isSigned) { 333 const chunk_T *pData = (const chunk_T *) (pVoid); 334 for (i = 0; i <numOfChunk; i++) { 335 dblValue[i] = (double)(pData[i]); 336 } 337 } else { 338 const uchunk_T *pData = (const uchunk_T *) (pVoid); 339 for (i = 0; i <numOfChunk; i++) { 340 dblValue[i] = (double)(pData[i]); 341 } 342 } 343 344 /* 345 Assuming multi chunks b_n ... b_2 b_1 b_0, and the length of each chunk is N. 346 Suppose b_i is the i-th chunk's value. 347 Then for unsigned data or data with one chunk: we have 348 retValue = b_n * 2^(n*N) + ... + b_1 * 2^N + b_0 * 2^0; 349 But for signed data, we have 350 retValue = b_n * 2^(n*N) + ... + b_1 * 2^N + b_0 * 2^0+ (b_0<0) * 2^N + 351 ... (b_(n-1) <0) * 2^(n*N) 352 = (b_n + (b_(n-1)<0)) * 2^(n*N) +... + (b_1 + (b_0<0)) * 2^N + b_0 * 2^0; 353 Together: 354 retValue = 355 (b_n + isSigned * (b_(n-1)<0)) * 2^(n*N) +... + (b_1 + isSigned * (b_0<0)) * 2^N + b_0 * 2^0; 356 */ 357 358 retValue = dblValue[numOfChunk - 1]; 359 360 for(i = numOfChunk - 1; i > 0; i--) { 361 isSignedNeg = dblValue[i - 1] < 0 ? (double)isSigned : 0; 362 retValue = retValue + isSignedNeg; 363 364 retValue = ldexp(retValue, bitsPerChunk)+ dblValue[i-1]; 365 } 366 retValue = ldexp( fracSlope * retValue, fixedExp ) + bias; 367 368 FREE(dblValue); 369 return (retValue); 370 371 } /* end rt_GetDblValueFromOverSizedData */ 372 373 374 /* Function: rt_GetNonBoolMxIdFromDTypeId ====================================== 375 * Abstract: 376 * Get the mx???_CLASS given the simulink builtin data type id. 377 */ 378 mxClassID rt_GetNonBoolMxIdFromDTypeId(BuiltInDTypeId dTypeID) 379 { 380 mxClassID mxID; 381 382 switch (dTypeID) { 383 case SS_DOUBLE: 384 mxID = (sizeof(real_T)==4? mxSINGLE_CLASS: mxDOUBLE_CLASS); 385 break; 386 case SS_SINGLE: 387 mxID = mxSINGLE_CLASS; 388 break; 389 case SS_INT8: 390 mxID = (sizeof(int8_T)==4? mxINT32_CLASS: mxINT8_CLASS); 391 break; 392 case SS_UINT8: 393 mxID = (sizeof(uint8_T)==4? mxUINT32_CLASS: mxUINT8_CLASS); 394 break; 395 case SS_INT16: 396 mxID = (sizeof(int16_T)==4? mxINT32_CLASS: mxINT16_CLASS); 397 break; 398 case SS_UINT16: 399 mxID = (sizeof(uint16_T)==4? mxUINT32_CLASS: mxUINT16_CLASS); 400 break; 401 case SS_INT32: 402 mxID = mxINT32_CLASS; 403 break; 404 case SS_UINT32: 405 mxID = mxUINT32_CLASS; 406 break; 407 /*case SS_BOOLEAN: 408 mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxLOGICAL_CLASS); 409 break;*/ 410 default: 411 mxID = mxUNKNOWN_CLASS; 412 break; 413 } 414 415 return(mxID); 416 417 } /* end rt_GetNonBoolMxIdFromDTypeId */ 418 419 420 421 #ifdef __cplusplus 422 extern "C" { 423 #endif 424 425 426 /* Function: rt_GetMxIdFromDTypeIdForRSim ====================================== 427 * Abstract: 428 * Get the mx???_CLASS given the simulink builtin data type id. 429 */ 430 mxClassID rt_GetMxIdFromDTypeIdForRSim(BuiltInDTypeId dTypeID) 431 { 432 mxClassID mxID; 433 434 if (dTypeID == SS_BOOLEAN) { 435 mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxLOGICAL_CLASS); 436 } else { 437 mxID = rt_GetNonBoolMxIdFromDTypeId(dTypeID); 438 } 439 440 return(mxID); 441 442 } /* end rt_GetMxIdFromDTypeIdForRSim */ 443 444 445 #ifdef __cplusplus 446 } 447 #endif 448 449 450 451 452 #ifdef __cplusplus 453 extern "C" { 454 #endif 455 456 457 /* Function: rt_GetMxIdFromDTypeId ============================================= 458 * Abstract: 459 * Get the mx???_CLASS given the simulink builtin data type id. 460 */ 461 mxClassID rt_GetMxIdFromDTypeId(BuiltInDTypeId dTypeID) 462 { 463 mxClassID mxID; 464 465 if (dTypeID == SS_BOOLEAN) { 466 mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxUINT8_CLASS); 467 } else { 468 mxID = rt_GetNonBoolMxIdFromDTypeId(dTypeID); 469 } 470 return(mxID); 471 472 } /* end rt_GetMxIdFromDTypeId */ 473 474 475 #ifdef __cplusplus 476 } 477 #endif 478 479 480 481 /* Function: rt_GetMatIdFromMxId =============================================== 482 * Abstract: 483 * Get the MatId given the mxClassID. 484 */ 485 static int_T rt_GetMatIdFromMxId(mxClassID mxID) 486 { 487 int_T matID; 488 489 switch (mxID) { 490 case mxCELL_CLASS: 491 case mxSTRUCT_CLASS: 492 case mxOBJECT_CLASS: 493 matID = -1; 494 break; 495 case mxCHAR_CLASS: 496 matID = matUINT16; 497 break; 498 case mxDOUBLE_CLASS: 499 matID = matDOUBLE; 500 break; 501 case mxSINGLE_CLASS: 502 matID = matFLOAT; 503 break; 504 case mxINT8_CLASS: 505 matID = matINT8; 506 break; 507 case mxUINT8_CLASS: 508 matID = matUINT8; 509 break; 510 case mxINT16_CLASS: 511 matID = matINT16; 512 break; 513 case mxUINT16_CLASS: 514 matID = matUINT16; 515 break; 516 case mxINT32_CLASS: 517 matID = matINT32; 518 break; 519 case mxUINT32_CLASS: 520 matID = matUINT32; 521 break; 522 case mxINT64_CLASS: 523 matID = matINT64; 524 break; 525 case mxUINT64_CLASS: 526 matID = matUINT64; 527 break; 528 default: 529 matID = matUNKNOWN; 530 break; 531 } 532 return(matID); 533 534 } /* end rt_GetMatIdFromMxId */ 535 536 537 /* Forward declaration */ 538 static int_T rt_WriteItemToMatFile(FILE *fp, 539 MatItem *pItem, 540 ItemDataKind dataKind); 541 542 543 /* Function: rt_ProcessMatItem ================================================= 544 * Abstract: 545 * This routine along with rt_WriteItemToMatFile() write out a specified 546 * mat-item the .mat file. Note that if the input argument 547 * cmd == 0, then this function just calculates the size of the item. 548 * cmd <> 0, this function writes the mat-item to the file. 549 * Return values is 550 * -1 : coding/logic error 551 * 0 : upon success 552 * > 0 : upon write failure (1) 553 */ 554 static int_T rt_ProcessMatItem(FILE *fp, 555 MatItem *pItem, 556 ItemDataKind itemKind, 557 int_T cmd) 558 { 559 mxClassID mxID = mxUNKNOWN_CLASS; 560 uint32_T arrayFlags[2] = {0, 0}; 561 int32_T *dims = NULL; 562 int32_T _dims[3] = {0, 0, 0}; 563 int32_T nDims = 2; 564 int32_T nBytesInItem = 0; 565 const char_T *itemName; 566 MatItem item; 567 int_T retStat = 0; 568 569 switch (itemKind) { 570 case DATA_ITEM: { 571 (void)fprintf(stderr,"Unexpected itemKind = DATA_ITEM in " 572 "rt_ProcessMatItem @A\n"); 573 retStat = -1; 574 goto EXIT_POINT; 575 } 576 case MATRIX_ITEM: { 577 const MatrixData *var = (const MatrixData *) pItem->data; 578 579 mxID = var->mxID; 580 arrayFlags[0] = mxID; 581 arrayFlags[0] |= var->logical; 582 arrayFlags[0] |= var->complex; 583 if (var->nDims < 2) { 584 dims = _dims; 585 dims[0] = var->nRows; 586 dims[1] = var->nCols; 587 nDims = 2; 588 } else if (var->nDims >= 2) { 589 int32_T k; 590 dims = (int32_T*)malloc(sizeof(int32_T)*(var->nDims+1)); 591 for (k = 0; k < var->nDims; k++) { 592 dims[k] = var->dims[k]; 593 } 594 dims[var->nDims] = var->nRows; 595 nDims = var->nDims + 1; 596 } 597 itemName = var->name; 598 break; 599 } 600 case STRUCT_LOG_VAR_ITEM: { 601 const StructLogVar *var = (const StructLogVar *) pItem->data; 602 603 mxID = mxSTRUCT_CLASS; 604 arrayFlags[0] = mxID; 605 dims = _dims; 606 dims[0] = 1; 607 dims[1] = 1; 608 itemName = var->name; 609 break; 610 } 611 case SIGNALS_STRUCT_ITEM: { 612 const SignalsStruct *var = (const SignalsStruct *) pItem->data; 613 614 mxID = mxSTRUCT_CLASS; 615 arrayFlags[0] = mxID; 616 dims = _dims; 617 dims[0] = 1; 618 dims[1] = var->numSignals; 619 itemName = &SIGNALS_FIELD_NAME; 620 break; 621 } 622 default: 623 (void)fprintf(stderr,"Unexpected itemKind=%d in rt_ProcessMatItem @B\n", 624 itemKind); 625 retStat = -1; 626 goto EXIT_POINT; 627 } 628 629 /* array flags */ 630 item.nbytes = 2*sizeof(uint32_T); 631 if (cmd) { 632 item.type = matUINT32; 633 item.data = arrayFlags; 634 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 635 retStat = 1; 636 goto EXIT_POINT; 637 } 638 } else { 639 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 640 nBytesInItem += matINT64_ALIGN(matTAG_SIZE + item.nbytes); 641 } 642 /* dimensions */ 643 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 644 item.nbytes = nDims*sizeof(int32_T); 645 if (cmd) { 646 item.type = matINT32; 647 item.data = dims; 648 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 649 retStat = 1; 650 goto EXIT_POINT; 651 } 652 } else { 653 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 654 nBytesInItem += matINT64_ALIGN(matTAG_SIZE + item.nbytes); 655 } 656 /* name */ 657 item.nbytes = (int32_T)strlen(itemName); 658 if (cmd) { 659 item.type = matINT8; 660 item.data = (const char_T*) itemName; 661 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 662 retStat = 1; 663 goto EXIT_POINT; 664 } 665 } else { 666 nBytesInItem += (item.nbytes <= 4) ? /*LINTED E_CAST_INT_TO_SMALL_INT*/ 667 matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes); 668 } 669 670 if (itemKind == MATRIX_ITEM) { 671 const MatrixData *var = (const MatrixData*) pItem->data; 672 int_T matID = rt_GetMatIdFromMxId(mxID); 673 size_t elSize = var->elSize; 674 675 /* data */ 676 item.nbytes = (int32_T)(var->nRows * var->nCols * elSize); 677 if (cmd) { 678 item.type = matID; 679 item.data = var->re; 680 if (rt_WriteItemToMatFile(fp, &item, DATA_ITEM)) { 681 retStat = 1; 682 goto EXIT_POINT; 683 } 684 } else { 685 nBytesInItem += (item.nbytes <= 4) ? /*LINTED*/ 686 matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes); 687 } 688 /* imaginary part */ 689 if (var->complex) { 690 item.nbytes = (int32_T)(var->nRows * var->nCols * elSize); 691 if (cmd) { 692 item.type = matID; 693 item.data = var->im; 694 if (rt_WriteItemToMatFile(fp, &item, DATA_ITEM)) { 695 retStat = 1; 696 goto EXIT_POINT; 697 } 698 } else { 699 nBytesInItem += (item.nbytes <= 4) ? /*LINTED*/ 700 matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes); 701 } 702 } 703 } else { /* some type of structure item */ 704 const char_T *fieldNames; 705 int_T sizeofFieldNames; 706 707 /* field names */ 708 switch (itemKind) { 709 case STRUCT_LOG_VAR_ITEM: { 710 const StructLogVar *var = (const StructLogVar *) pItem->data; 711 fieldNames = rtStructLogVarFieldNames; 712 sizeofFieldNames = var->numActiveFields * mxMAXNAM; 713 break; 714 } 715 case SIGNALS_STRUCT_ITEM: { 716 const SignalsStruct *var = (const SignalsStruct *) pItem->data; 717 fieldNames = var->fieldNames; 718 sizeofFieldNames = var->numActiveFields * mxMAXNAM; 719 break; 720 } 721 default: 722 (void)fprintf(stderr, "Unexpected itemKind=%d in " 723 "rt_ProcessMatItem @C\n", itemKind); 724 retStat = -1; 725 goto EXIT_POINT; 726 } 727 728 /* write field names */ 729 if (cmd) { 730 int32_T tmpInt = mxMAXNAM; 731 732 item.nbytes = sizeof(int32_T); 733 item.type = matINT32; 734 item.data = &tmpInt; 735 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 736 retStat = 1; 737 goto EXIT_POINT; 738 } 739 740 item.nbytes = sizeofFieldNames; 741 item.type = matINT8; 742 item.data = (const char_T*) fieldNames; 743 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 744 retStat = 1; 745 goto EXIT_POINT; 746 } 747 } else { 748 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 749 nBytesInItem += matINT64_ALIGN( matTAG_SIZE + matTAG_SIZE + 750 sizeofFieldNames ); 751 } 752 753 /* process each field of the structure */ 754 switch (itemKind) { 755 case STRUCT_LOG_VAR_ITEM: { 756 const StructLogVar *var = pItem->data; 757 758 /* time */ 759 { 760 const void *data = var->time; 761 762 if (var->logTime) { /* time is a LogVar, get the MatrixData */ 763 data = &(((const LogVar*) (var->time))->data); 764 } 765 766 item.type = matMATRIX; 767 item.data = data; 768 if (cmd) { 769 if (rt_WriteItemToMatFile(fp,&item,MATRIX_ITEM)){ 770 retStat = 1; 771 goto EXIT_POINT; 772 } 773 } else { 774 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM,0)){ 775 retStat = 1; 776 goto EXIT_POINT; 777 } 778 nBytesInItem += item.nbytes + matTAG_SIZE; 779 } 780 } 781 782 /* signals */ 783 item.type = matMATRIX; 784 item.data = &(var->signals); 785 if (cmd) { 786 if (rt_WriteItemToMatFile(fp,&item,SIGNALS_STRUCT_ITEM)) { 787 retStat = 1; 788 goto EXIT_POINT; 789 } 790 } else { 791 if (rt_ProcessMatItem(fp, &item, SIGNALS_STRUCT_ITEM,0)) { 792 retStat = 1; 793 goto EXIT_POINT; 794 } 795 nBytesInItem += item.nbytes + matTAG_SIZE; 796 } 797 798 /* block name */ 799 if (var->blockName != NULL) { 800 item.type = matMATRIX; 801 item.data = var->blockName; 802 if (cmd) { 803 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 804 retStat = 1; 805 goto EXIT_POINT; 806 } 807 } else { 808 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 809 retStat = 1; 810 goto EXIT_POINT; 811 } 812 nBytesInItem += item.nbytes + matTAG_SIZE; 813 } 814 } 815 break; 816 } 817 case SIGNALS_STRUCT_ITEM: { 818 const SignalsStruct *var = pItem->data; 819 const LogVar *values = var->values; 820 const MatrixData *dimensions = var->dimensions; 821 const MatrixData *labels = var->labels; 822 const MatrixData *plotStyles = var->plotStyles; 823 const MatrixData *titles = var->titles; 824 const MatrixData *blockNames = var->blockNames; 825 const MatrixData *stateNames = var->stateNames; 826 const MatrixData *crossMdlRef = var->crossMdlRef; 827 const boolean_T logValueDimensions = var->logValueDimensions; 828 int_T i; 829 830 for (i = 0; i < var->numSignals; i++) { 831 /* values */ 832 item.type = matMATRIX; 833 item.data = &(values->data); 834 if (cmd) { 835 if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) { 836 retStat = 1; 837 goto EXIT_POINT; 838 } 839 } else { 840 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 841 retStat = 1; 842 goto EXIT_POINT; 843 } 844 nBytesInItem += item.nbytes + matTAG_SIZE; 845 } 846 847 if(logValueDimensions) 848 { 849 /* valueDimensions */ 850 /* Since the functions rt_WriteItemToMatFile and 851 rt_ProcessMatItem deal with MatrixData, 852 convert valDims to tempData, and fill up the 853 necessary fields. 854 */ 855 MatrixData tempData; 856 (void)memcpy(tempData.name, &VALUEDIMENSIONS_FIELD_NAME, mxMAXNAM); 857 tempData.nRows = values->valDims->nRows; 858 tempData.nCols = values->valDims->nCols; 859 tempData.nDims = 1; 860 tempData._dims[0] = values->valDims->nCols; 861 tempData.re = values->valDims->dimsData; 862 tempData.im = NULL; 863 tempData.dTypeID = SS_DOUBLE; 864 tempData.elSize = sizeof(real_T); 865 tempData.mxID = mxDOUBLE_CLASS; 866 tempData.logical = 0; 867 tempData.complex = 0; 868 tempData.frameData = 0; 869 tempData.frameSize = 1; 870 871 item.type = matMATRIX; 872 item.data = &tempData; /*values->valDims;*/ 873 874 if (cmd) { 875 if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) { 876 retStat = 1; 877 goto EXIT_POINT; 878 } 879 } else { 880 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 881 retStat = 1; 882 goto EXIT_POINT; 883 } 884 nBytesInItem += item.nbytes + matTAG_SIZE; 885 } 886 } 887 values = values->next; 888 889 /* dimensions */ 890 if (dimensions != NULL) { 891 item.type = matMATRIX; 892 item.data = &(dimensions[i]); 893 if (cmd) { 894 if (rt_WriteItemToMatFile(fp,&item, MATRIX_ITEM)) { 895 retStat = 1; 896 goto EXIT_POINT; 897 } 898 } else { 899 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 900 retStat = 1; 901 goto EXIT_POINT; 902 } 903 nBytesInItem += item.nbytes + matTAG_SIZE; 904 } 905 } 906 907 /* label */ 908 item.type = matMATRIX; 909 item.data = &(labels[i]); 910 if (cmd) { 911 if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) { 912 retStat = 1; 913 goto EXIT_POINT; 914 } 915 } else { 916 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 917 retStat = 1; 918 goto EXIT_POINT; 919 } 920 nBytesInItem += item.nbytes + matTAG_SIZE; 921 } 922 /* title */ 923 if (titles != NULL) { 924 item.type = matMATRIX; 925 item.data = &(titles[i]); 926 if (cmd) { 927 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 928 retStat = 1; 929 goto EXIT_POINT; 930 } 931 } else { 932 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 933 retStat = 1; 934 goto EXIT_POINT; 935 } 936 nBytesInItem += item.nbytes + matTAG_SIZE; 937 } 938 } 939 /* plot style */ 940 if (plotStyles != NULL) { 941 item.type = matMATRIX; 942 item.data = &(plotStyles[i]); 943 if (cmd) { 944 if (rt_WriteItemToMatFile(fp,&item, MATRIX_ITEM)) { 945 retStat = 1; 946 goto EXIT_POINT; 947 } 948 } else { 949 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 950 retStat = 1; 951 goto EXIT_POINT; 952 } 953 nBytesInItem += item.nbytes + matTAG_SIZE; 954 } 955 } 956 /* block name */ 957 if (blockNames != NULL) { 958 item.type = matMATRIX; 959 item.data = &(blockNames[i]); 960 if (cmd) { 961 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 962 retStat = 1; 963 goto EXIT_POINT; 964 } 965 } else { 966 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 967 retStat = 1; 968 goto EXIT_POINT; 969 } 970 nBytesInItem += item.nbytes + matTAG_SIZE; 971 } 972 } 973 /* state name */ 974 if (stateNames != NULL) { 975 item.type = matMATRIX; 976 item.data = &(stateNames[i]); 977 if (cmd) { 978 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 979 retStat = 1; 980 goto EXIT_POINT; 981 } 982 } else { 983 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 984 retStat = 1; 985 goto EXIT_POINT; 986 } 987 nBytesInItem += item.nbytes + matTAG_SIZE; 988 } 989 } 990 /* crossMdlRef */ 991 if (crossMdlRef != NULL) { 992 item.type = matMATRIX; 993 item.data = &(crossMdlRef[i]); 994 if (cmd) { 995 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 996 retStat = 1; 997 goto EXIT_POINT; 998 } 999 } else { 1000 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1001 retStat = 1; 1002 goto EXIT_POINT; 1003 } 1004 nBytesInItem += item.nbytes + matTAG_SIZE; 1005 } 1006 } 1007 } /* for i=1:numSignals */ 1008 break; 1009 } 1010 default: 1011 (void)fprintf(stderr, "Unexpected itemKind=%d in " 1012 "rt_ProcessMatItem @D\n", itemKind); 1013 retStat = -1; 1014 goto EXIT_POINT; 1015 } 1016 } /* end struct item */ 1017 1018 if (!cmd) { 1019 pItem->nbytes = nBytesInItem; 1020 } 1021 1022 EXIT_POINT: 1023 if (dims != _dims) { 1024 FREE(dims); 1025 } 1026 return(retStat); 1027 1028 } /* end rt_ProcessMatItem */ 1029 1030 1031 /* Function: rt_WriteItemToMatFile ============================================= 1032 * Abstract: 1033 * Entry function for writing out a mat item to the mat file. 1034 * 1035 * Return values is 1036 * == 0 : upon success 1037 * <> 0 : upon failure 1038 */ 1039 static int_T rt_WriteItemToMatFile(FILE *fp, 1040 MatItem *pItem, 1041 ItemDataKind itemKind) 1042 { 1043 /* Determine the item size */ 1044 if (pItem->type == matMATRIX) { 1045 if (rt_ProcessMatItem(fp, pItem, itemKind, 0)) return(1); 1046 } 1047 1048 /* Write the item tag and data */ 1049 if (pItem->nbytes > 4) { 1050 int32_T nAlignBytes; 1051 1052 if (fwrite(pItem, 1, matTAG_SIZE, fp) != matTAG_SIZE) return(1); 1053 1054 if (pItem->type == matMATRIX) { 1055 if (rt_ProcessMatItem(fp, pItem, itemKind, 1)) return(1); 1056 } else { 1057 if ( fwrite(pItem->data, 1, pItem->nbytes, fp) != 1058 ((size_t) pItem->nbytes) ) { 1059 return(1); 1060 } 1061 } 1062 1063 /* Add offset for 8-byte alignment */ 1064 nAlignBytes = matINT64_ALIGN(pItem->nbytes) - pItem->nbytes; 1065 if (nAlignBytes > 0) { 1066 int pad[2] = {0, 0}; 1067 if ( fwrite(pad,1,nAlignBytes,fp) != ((size_t) nAlignBytes) ) { 1068 return(1); 1069 } 1070 } 1071 } else { 1072 MatItem item = {0, 0, NULL}; 1073 item.type = ((uint32_T)(pItem->type))|(((uint32_T)(pItem->nbytes))<<16); 1074 (void)memcpy(&item.nbytes, pItem->data, pItem->nbytes); 1075 if (fwrite(&item, 1, matTAG_SIZE, fp) != matTAG_SIZE) return(1); 1076 } 1077 1078 return(0); 1079 1080 } /* end rt_WriteItemToMatFile */ 1081 1082 1083 /* Function: rt_WriteMat5FileHeader ============================================ 1084 * Abstract: 1085 * Function to write the mat file header. 1086 * Return values is 1087 * == 0 : upon success 1088 * <> 0 : upon failure 1089 */ 1090 static int_T rt_WriteMat5FileHeader(FILE *fp) 1091 { 1092 int_T nbytes; 1093 int_T nspaces; 1094 int_T i, n; 1095 unsigned short ver[2]; 1096 char_T spaces[16]; 1097 const char_T *matversion = "MATLAB 5.0 MAT-file"; 1098 1099 (void)memset(spaces, ' ', sizeof(spaces)); 1100 1101 n = (int_T)strlen(matversion); 1102 nbytes = (int_T)fwrite(matversion, 1, n, fp); 1103 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1104 nspaces = matVERSION_INFO_OFFSET - nbytes; 1105 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1106 n = nspaces % sizeof(spaces); 1107 nbytes += (int_T)fwrite(spaces, 1, n, fp); 1108 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1109 n = nspaces / sizeof(spaces); 1110 for (i = 0; i < n; ++i) { 1111 nbytes += (int_T)fwrite(spaces, 1, sizeof(spaces), fp); 1112 } 1113 if (nbytes == matVERSION_INFO_OFFSET) { 1114 ver[0] = matVERSION; 1115 ver[1] = matKEY; 1116 nbytes += (int_T)fwrite(ver, 1, sizeof(ver), fp); 1117 } 1118 return(nbytes != matVERSION_INFO_OFFSET + sizeof(ver)); 1119 1120 } /* end rt_WriteMat5FileHeader */ 1121 1122 1123 /* Function: rt_FixupLogVar ==================================================== 1124 * Abstract: 1125 * Make the logged variable suitable for MATLAB. 1126 */ 1127 static const char_T *rt_FixupLogVar(LogVar *var,int verbose) 1128 { 1129 int_T nCols = var->data.nCols; 1130 int_T maxRows = var->data.nRows; 1131 int_T nDims = var->data.nDims; 1132 size_t elSize = var->data.elSize; 1133 int_T nRows = (var->wrapped ? maxRows : var->rowIdx); 1134 1135 var->nDataPoints = var->rowIdx + var->wrapped * maxRows; 1136 1137 if (var->wrapped > 1 || (var->wrapped == 1 && var->rowIdx != 0)) { 1138 /* 1139 * Warn the user the circular buffer has wrapped, implying that 1140 * some data has been lost. 1141 */ 1142 if( verbose) { 1143 (void)fprintf(stdout, 1144 "*** Log variable %s has wrapped %d times\n" 1145 " using a circular buffer of size %d\n", 1146 var->data.name, var->wrapped, var->data.nRows); 1147 } 1148 if (var->usingDefaultBufSize) { 1149 /* 1150 * If wrapping occurred using the default buffer size, 1151 * let the user know what size buffer to use in the 1152 * future to avoid wrapping. If the default buffer 1153 * size was not used, the user has no control to specify 1154 * the correct value. Wrapping may occur when not using 1155 * the default buffer if we allocated too small a buffer 1156 * size for this logvar. One common case is a toWorkspace 1157 * block inside of an iterative subsystem - we can not take 1158 * the number of iterations into account (they may be 1159 * variable) when allocating the buffer. In this case, 1160 * just warn the buffer wrapped and don't tell user they 1161 * can override the buffer size. 1162 */ 1163 if( verbose ) { 1164 (void)fprintf(stdout, 1165 "*** To avoid wrapping, explicitly specify a\n" 1166 " buffer size of %d in your Simulink model\n" 1167 " by adding OPTS=\"-DDEFAULT_BUFFER_SIZE=%d\"\n" 1168 " as an argument to the ConfigSet MakeCommand\n" 1169 " parameter\n", 1170 var->nDataPoints, var->nDataPoints); 1171 } 1172 } 1173 } 1174 1175 if (nDims < 2 && nCols > 1) { /* Transpose? */ 1176 /* Don't need to transpose valueDimensions */ 1177 int_T nEl = nRows*nCols; 1178 char *src = var->data.re; 1179 char *pmT; 1180 int_T k; 1181 1182 /********************************** 1183 * If memory cannot be allocated, * 1184 * write to a temporary buffer * 1185 **********************************/ 1186 if ((pmT = malloc(nEl*elSize)) == NULL) { 1187 FILE *fptr; 1188 char fName[mxMAXNAM]; 1189 1190 (void)sprintf(fName, "%s%s", var->data.name, "_rtw_tmw.tmw"); 1191 if ((fptr=fopen(fName,"w+b")) == NULL) { 1192 (void)fprintf(stderr,"*** Error opening %s",fName); 1193 return("unable to open data file\n"); 1194 } 1195 1196 /**************************** 1197 * Write the data to a file * 1198 ****************************/ 1199 for (k=0; k<nEl; k++) { 1200 int_T kT = nCols*(k%nRows) + (k/nRows); 1201 char *dst = src + kT*elSize; 1202 (void)fwrite(dst, elSize, 1, fptr); 1203 } 1204 if (var->data.complex) { 1205 char *pmiT = var->data.re; 1206 src = var->data.im; 1207 for (k=0; k<nEl; k++) { 1208 int_T kT = nRows*(k%nCols) + (k/nCols); 1209 char *dst = pmiT + kT*elSize; 1210 (void)memcpy(dst, src, elSize); 1211 src += elSize; 1212 } 1213 var->data.re = var->data.im; 1214 var->data.im = pmiT; 1215 } 1216 1217 /******************************* 1218 * Read the data from the file * 1219 *******************************/ 1220 (void)rewind(fptr); 1221 (void)fread(var->data.re, elSize, nEl, fptr); 1222 (void)fclose(fptr); 1223 (void)remove(fName); 1224 } else { 1225 for (k=0; k<nEl; k++) { 1226 int_T kT = nRows*(k%nCols) + (k/nCols); 1227 char *dst = pmT + kT*elSize; 1228 (void)memcpy(dst, src, elSize); 1229 src += elSize; 1230 } 1231 if (var->data.complex) { 1232 char *pmiT = var->data.re; 1233 src = var->data.im; 1234 for (k=0; k<nEl; k++) { 1235 int_T kT = nRows*(k%nCols) + (k/nCols); 1236 char *dst = pmiT + kT*elSize; 1237 (void)memcpy(dst, src, elSize); 1238 src += elSize; 1239 } 1240 var->data.re = var->data.im; 1241 var->data.im = pmiT; 1242 } 1243 FREE(var->data.re); 1244 var->data.re = pmT; 1245 } 1246 } /* Transpose? */ 1247 1248 if (var->wrapped > 0 && var->rowIdx != 0 ) { /* Rotate? */ 1249 char_T *buffer = var->data.re; 1250 int_T done = 0; /* done: 0 (1) rotate real (imag) part. */ 1251 1252 do { 1253 char_T *col = buffer; 1254 int_T rowOffset = (int_T)((nDims == 1) ? (elSize) : (elSize * nCols)); 1255 int_T colOffset = (int_T)((nDims == 1)? (nRows*elSize) : elSize); 1256 int_T zeroIdx = var->rowIdx; 1257 int_T j; 1258 1259 for (j = 0 ; j < nCols; ++j, col += colOffset) { 1260 int_T swapCount; 1261 int_T srcIdx; 1262 int_T dstIdx; 1263 int_T tmpIdx; 1264 MatReal tmp; 1265 1266 for (tmpIdx=0, swapCount=0; swapCount < nRows; tmpIdx++) { 1267 (void)memcpy(&tmp, col + tmpIdx*rowOffset, elSize); 1268 1269 dstIdx=tmpIdx; 1270 srcIdx = ((dstIdx + zeroIdx) % nRows); 1271 while (srcIdx != tmpIdx) { 1272 (void)memcpy(col + dstIdx*rowOffset, 1273 col + srcIdx*rowOffset, 1274 elSize); 1275 ++swapCount; 1276 dstIdx = srcIdx; 1277 srcIdx = ((dstIdx + zeroIdx) % nRows); 1278 1279 } 1280 (void)memcpy(col + dstIdx*rowOffset, &tmp, elSize); 1281 ++swapCount; 1282 } 1283 } 1284 done ++; 1285 /* need to rotate the imaginary part */ 1286 } while ((done == 1) && ((buffer = var->data.im) != NULL)); 1287 1288 var->rowIdx = 0; 1289 } /* Rotate? */ 1290 1291 /* 1292 * We might have allocated more number of rows than the number of data 1293 * points that have been logged, in which case set nRows to nDataPoints 1294 * so that only these values get saved. 1295 */ 1296 if (var->nDataPoints < var->data.nRows) { 1297 var->data.nRows = var->nDataPoints; 1298 if(var->valDims != NULL){ 1299 size_t elSizeValDims = sizeof(real_T); 1300 int_T k; 1301 real_T *dimsData = var->valDims->dimsData + nRows; 1302 /* 1303 Keep nRows of values and that of valueDimensions consistent 1304 for variable-size signals. 1305 */ 1306 var->valDims->nRows = var->data.nRows; 1307 /* 1308 Also need to move data when shrinking the array size, 1309 because valueDimensions data is stored in array format. 1310 e.g. maxRows = 4; nRows = 2; nDims = 3; 1311 Before fixing up the logVar, the locations of data are as below: 1312 (x, y, z -- useful data / o -- junk) 1313 a[0] = x a[4] = y a[8] = z 1314 a[1] = x a[5] = y a[9] = z 1315 a[2] = o a[6] = o a[10]= o 1316 a[3] = o a[7] = o a[11]= o 1317 After fixing up the logVar, we want the data to be stored as: 1318 a[0] = x a[4] = z a[8] = o 1319 a[1] = x a[5] = z a[9] = o 1320 a[2] = y a[6] = o a[10]= o 1321 a[3] = y a[7] = o a[11]= o 1322 */ 1323 for(k = 1; k < nDims; k++){ 1324 (void) memcpy(dimsData, 1325 var->valDims->dimsData + k*maxRows, 1326 elSizeValDims * nRows); 1327 dimsData += nRows; 1328 } 1329 } 1330 } 1331 return(NULL); 1332 1333 } /* end rt_FixupLogVar */ 1334 1335 1336 /* Function: rt_LoadModifiedLogVarName ========================================= 1337 * Abstract: 1338 * The name of the logged variable is obtained from the input argument 1339 * varName and the nameModifier which is obtained from the simstruct. If 1340 * the nameModifier begins with an '_', then nameModifier is post-pended to 1341 * varName to obtain the name of the logged variable. If the first 1342 * character does not begin with an '_', then the nameModifier is 1343 * pre-pended to varName. 1344 * 1345 * Examples: 1346 * a) varName = "tout" & nameModifier = "_rt" => logVarName = "tout_rt" 1347 * b) varName = "tout" & nameModifier = "rt_" => logVarName = "rt_tout" 1348 * c) varName = "tout" & nameModifier = "none" => logVarName = "tout" 1349 */ 1350 static void rt_LoadModifiedLogVarName(const RTWLogInfo *li, /* in */ 1351 const char *varName, /* in */ 1352 char *logVarName) /* out */ 1353 { 1354 int_T nameLen; 1355 const char_T *nameModifier = rtliGetLogVarNameModifier(li); 1356 1357 if (nameModifier != NULL && strcmp(nameModifier,"none")==0) { 1358 nameModifier = NULL; 1359 } 1360 1361 logVarName[mxMAXNAM-1] = '\0'; 1362 if (nameModifier == NULL) { 1363 (void)strncpy(logVarName, varName, mxMAXNAM-1); 1364 } else if (nameModifier[0] == '_') { 1365 (void)strncpy(logVarName, varName, mxMAXNAM-1); 1366 nameLen = (int_T)strlen(logVarName); 1367 (void)strncat(logVarName, nameModifier, mxMAXNAM-1-nameLen); 1368 } else { 1369 (void)strncpy(logVarName, nameModifier, mxMAXNAM-1); 1370 nameLen = (int_T)strlen(logVarName); 1371 (void)strncat(logVarName, varName, mxMAXNAM-1-nameLen); 1372 } 1373 1374 } /* end rt_LoadModifiedLogVarName */ 1375 1376 1377 /* Function: rt_GetActualDTypeID =============================================== 1378 * Abstract: 1379 * Given a built-in data type id, return the actual data type id. 1380 * The only time these are different is when real_T has been mapped 1381 * to a single. 1382 */ 1383 static BuiltInDTypeId rt_GetActualDTypeID(BuiltInDTypeId dTypeID) 1384 { 1385 /*LINTED E_FALSE_LOGICAL_EXPR*/ 1386 if (dTypeID == SS_DOUBLE && sizeof(real_T) != 8) { 1387 return(SS_SINGLE); 1388 } else { 1389 return(dTypeID); 1390 } 1391 1392 } /* end rt_GetActualDTypeID */ 1393 1394 1395 /* Function: rt_DestroyLogVar ================================================== 1396 * Abstract: 1397 * Destroy the log var linked list. 1398 */ 1399 static void rt_DestroyLogVar(LogVar *head) 1400 { 1401 while(head) { 1402 LogVar *var = head; 1403 head = var->next; 1404 FREE(var->data.re); 1405 FREE(var->data.im); 1406 if (var->data.dims != var->data._dims) { 1407 FREE(var->data.dims); 1408 } 1409 /* free valDims if necessary */ 1410 if(var->valDims != NULL) { 1411 FREE(var->valDims->dimsData); 1412 FREE(var->valDims); 1413 } 1414 /* free coords, strides and currStrides if necessary */ 1415 FREE(var->coords); 1416 FREE(var->strides); 1417 FREE(var->currStrides); 1418 1419 FREE(var); 1420 } 1421 1422 } /* end rt_DestroyLogVar */ 1423 1424 1425 /* Function: rt_DestroyStructLogVar ============================================ 1426 * Abstract: 1427 * Destroy the struct log var linked list. 1428 */ 1429 static void rt_DestroyStructLogVar(StructLogVar *head) 1430 { 1431 while(head) { 1432 StructLogVar *var = head; 1433 1434 head = var->next; 1435 1436 if (var->logTime) { /* time is LogVar */ 1437 rt_DestroyLogVar(var->time); 1438 } else { /* time is MatrixData */ 1439 FREE(var->time); 1440 } 1441 rt_DestroyLogVar(var->signals.values); 1442 FREE(var->signals.labels); 1443 FREE(var->signals.plotStyles); 1444 FREE(var->signals.dimensions); 1445 FREE(var->signals.titles); 1446 FREE(var->signals.blockNames); 1447 FREE(var->signals.stateNames); 1448 FREE(var->signals.crossMdlRef); 1449 FREE(var->blockName); 1450 FREE(var); 1451 } 1452 1453 } /* end rt_DestroyStructLogVar */ 1454 1455 1456 /* Function: rt_InitSignalsStruct ============================================== 1457 * Abstract: 1458 * Initialize the signals structure in the struct log variable. 1459 * 1460 * Returns: 1461 * == NULL => success. 1462 * ~= NULL => failure, the return value is a pointer to the error 1463 * message, which is also set in the simstruct. 1464 */ 1465 static const char_T *rt_InitSignalsStruct(RTWLogInfo *li, 1466 const real_T startTime, 1467 const real_T finalTime, 1468 const real_T inStepSize, 1469 const char_T **errStatus, 1470 StructLogVar *var, 1471 int_T maxRows, 1472 int_T decimation, 1473 real_T sampleTime, 1474 const RTWLogSignalInfo *sigInfo) 1475 { 1476 int_T i, sigIdx; 1477 SignalsStruct *sig = &(var->signals); 1478 int_T nSignals = sigInfo->numSignals; 1479 const int_T *numCols = sigInfo->numCols; 1480 const int_T *numDims = sigInfo->numDims; 1481 const int_T *dims = sigInfo->dims; 1482 const BuiltInDTypeId *dTypes = sigInfo->dataTypes; 1483 const int_T *cSgnls = sigInfo->complexSignals; 1484 const int_T *fData = sigInfo->frameData; 1485 const char_T **labels = sigInfo->labels.cptr; 1486 const int_T *plotStyles = sigInfo->plotStyles; 1487 const char_T *titles = sigInfo->titles; 1488 const int_T *titleLen = sigInfo->titleLengths; 1489 const char_T **blockNames = sigInfo->blockNames.cptr; 1490 const char_T **stateNames = sigInfo->stateNames.cptr; 1491 const boolean_T *crossMdlRef = sigInfo->crossMdlRef; 1492 1493 void **currSigDims = sigInfo->currSigDims; 1494 int_T *currSigDimsSize = sigInfo->currSigDimsSize; 1495 LogVar *prevValues = NULL; 1496 int_T dimsOffset = 0; 1497 boolean_T *isVarDims = sigInfo->isVarDims; 1498 /* if any signal is variable-size, the field 'valueDimensions' is needed */ 1499 boolean_T logValueDimensions = false; 1500 const RTWLogDataTypeConvert *pDTConvInfo = sigInfo->dataTypeConvert; 1501 1502 /* reset error status */ 1503 *errStatus = NULL; 1504 1505 sig->numActiveFields = 1; 1506 sig->numSignals = nSignals; 1507 1508 sig->isVarDims = isVarDims; 1509 /* check whether we need valueDimensions field*/ 1510 for (i=0; i<nSignals; i++){ 1511 if(isVarDims[i]){ 1512 logValueDimensions = true; 1513 break; 1514 } 1515 } 1516 1517 /* values */ 1518 dimsOffset = 0; 1519 for (i = 0; i < nSignals; i++) { 1520 BuiltInDTypeId dt = (dTypes) ? dTypes[i] : SS_DOUBLE; 1521 int_T cs = (cSgnls) ? cSgnls[i] : 0; 1522 int_T fd = (fData) ? fData[i] : 0; 1523 int_T nd = (numDims) ? numDims[i] : 1; 1524 1525 const RTWLogDataTypeConvert *pDTConvInfoCur = 1526 (pDTConvInfo) ? (pDTConvInfo+i) : 0; 1527 1528 LogVar *values = NULL; 1529 LogValDimsStat logValDimsStat; 1530 1531 if(!logValueDimensions){ 1532 logValDimsStat = NO_LOGVALDIMS; 1533 } 1534 else{ 1535 logValDimsStat = isVarDims[i] ? LOGVALDIMS_VARDIMS : 1536 LOGVALDIMS_EMPTYMX; 1537 } 1538 1539 values = rt_CreateLogVarWithConvert(li, startTime, finalTime, 1540 inStepSize, errStatus, 1541 &VALUES_FIELD_NAME, 1542 dt, 1543 pDTConvInfoCur, 1544 0, cs, fd, 1545 numCols[i],nd, 1546 dims + dimsOffset, 1547 logValDimsStat, 1548 currSigDims + dimsOffset, 1549 currSigDimsSize + dimsOffset, 1550 maxRows,decimation,sampleTime, 0); 1551 1552 if (values == NULL) goto ERROR_EXIT; 1553 1554 if (sig->values == NULL) { 1555 sig->values = values; 1556 } else { 1557 prevValues->next = values; 1558 } 1559 prevValues = values; 1560 dimsOffset += nd; 1561 } 1562 1563 if(logValueDimensions){ 1564 ++sig->numActiveFields; 1565 sig->logValueDimensions = true; 1566 } 1567 else{ 1568 sig->logValueDimensions = false; 1569 } 1570 1571 /* Dimensions */ 1572 { 1573 real_T *data; 1574 size_t nbytes; 1575 int_T dataLen = 0; 1576 BuiltInDTypeId dTypeId = rt_GetActualDTypeID(SS_DOUBLE); 1577 size_t dataOffset = nSignals*sizeof(MatrixData); 1578 uint_T overhang = (uint_T)(dataOffset % sizeof(real_T)); 1579 1580 if (overhang) { 1581 dataOffset += (sizeof(real_T) - overhang); 1582 } 1583 for (i=0; i< nSignals; i++) { 1584 int_T nd = (numDims) ? numDims[i] : 1; 1585 dataLen += nd; 1586 } 1587 nbytes = dataOffset + dataLen*sizeof(real_T); 1588 1589 if ( (sig->dimensions = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1590 1591 data = (real_T*) (((char_T*) (sig->dimensions)) + dataOffset); 1592 1593 for (i = 0; i < dataLen; i++) { 1594 data[i] = dims[i]; /* cannot memcpy double <- int */ 1595 } 1596 1597 for (i = 0; i < nSignals; i++) { 1598 MatrixData *mtxData = &(sig->dimensions[i]); 1599 int_T nd = (numDims) ? numDims[i] : 1; 1600 1601 (void)memcpy(mtxData->name, &DIMENSION_FIELD_NAME, mxMAXNAM); 1602 1603 mtxData->nRows = 1; 1604 mtxData->nCols = nd; 1605 1606 mtxData->nDims = 1; /* assume */ 1607 mtxData->dims = mtxData->_dims; 1608 mtxData->dims[0] = mtxData->nCols; 1609 1610 mtxData->re = data; 1611 mtxData->im = NULL; 1612 mtxData->dTypeID = dTypeId; 1613 mtxData->mxID = rt_GetMxIdFromDTypeId(dTypeId); 1614 mtxData->elSize = rt_GetSizeofDataType(dTypeId); 1615 mtxData->logical = 0U; 1616 mtxData->complex = 0U; 1617 1618 data += nd; 1619 } 1620 ++sig->numActiveFields; 1621 } 1622 1623 /* labels */ 1624 if (labels != NULL) { 1625 short *data; 1626 size_t nbytes; 1627 int_T dataLen = 0; 1628 size_t dataOffset = nSignals * sizeof(MatrixData); 1629 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 1630 int_T dataIdx = 0; 1631 1632 for (i=0;i<nSignals;i++) { 1633 if (labels[i] != NULL){ 1634 dataLen = dataLen + (int_T)strlen(labels[i]); 1635 } 1636 } 1637 1638 if (overhang) { 1639 dataOffset += (sizeof(short) - overhang); 1640 } 1641 nbytes = dataOffset + dataLen*sizeof(short); 1642 1643 if ( (sig->labels = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1644 1645 data = (short*) (((char_T*) (sig->labels)) + dataOffset); 1646 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 1647 int_T labelLen = (labels[sigIdx]==NULL) ? 0 : (int_T)strlen(labels[sigIdx]); 1648 for (i = 0; i < labelLen; i++) { 1649 data[dataIdx++] = labels[sigIdx][i]; 1650 } 1651 } 1652 1653 for (i = 0; i < nSignals; i++) { 1654 MatrixData *mtxData = &(sig->labels[i]); 1655 int_T labelLen = (int_T)strlen(labels[i]); 1656 1657 (void)memcpy(mtxData->name, &LABEL_FIELD_NAME, mxMAXNAM); 1658 mtxData->nRows = (labelLen) ? 1 : 0; 1659 mtxData->nCols = labelLen; 1660 1661 mtxData->re = data; 1662 mtxData->im = NULL; 1663 1664 mtxData->nDims = 1; /* assume */ 1665 mtxData->dims = mtxData->_dims; 1666 mtxData->dims[0] = mtxData->nCols; 1667 1668 mtxData->dTypeID = SS_INT16; 1669 mtxData->mxID = mxCHAR_CLASS; 1670 mtxData->elSize = sizeof(short); 1671 mtxData->logical = 0U; 1672 mtxData->complex = 0U; 1673 1674 data += labelLen; 1675 } 1676 ++sig->numActiveFields; 1677 } 1678 1679 /* plot styles */ 1680 if (plotStyles != NULL) { 1681 real_T *data; 1682 size_t nbytes; 1683 int_T dataLen = 0; 1684 BuiltInDTypeId dTypeId = rt_GetActualDTypeID(SS_DOUBLE); 1685 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1686 size_t dataOffset = nSignals*sizeof(MatrixData); 1687 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1688 uint_T overhang = (uint_T)(dataOffset % sizeof(real_T)); 1689 1690 if (overhang) { 1691 dataOffset += (sizeof(real_T) - overhang); 1692 } 1693 for (i=0; i< nSignals; i++) { 1694 dataLen += numCols[i]; 1695 } 1696 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1697 nbytes = dataOffset + dataLen*sizeof(real_T); 1698 1699 if ( (sig->plotStyles = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1700 1701 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 1702 data = (real_T*) (((char_T*) (sig->plotStyles)) + dataOffset); 1703 1704 for (i = 0; i < dataLen; i++) { 1705 data[i] = plotStyles[i]; 1706 } 1707 1708 dimsOffset = 0; 1709 for (i = 0; i < nSignals; i++) { 1710 MatrixData *mtxData = &(sig->plotStyles[i]); 1711 1712 (void)memcpy(mtxData->name, &PLOTSTYLE_FIELD_NAME, mxMAXNAM); 1713 1714 mtxData->nRows = (numCols[i]) ? 1 : 0; 1715 mtxData->nCols = numCols[i]; 1716 1717 mtxData->nDims = numDims[i]; 1718 1719 if(mtxData->nDims > 2) { 1720 if ((mtxData->dims = calloc(mtxData->nDims, sizeof(int_T))) == NULL) goto ERROR_EXIT; 1721 } else { 1722 mtxData->dims = mtxData->_dims; 1723 } 1724 1725 mtxData->dims[0] = *(dims + dimsOffset); 1726 if(mtxData->nDims >= 2) { 1727 int32_T j; 1728 for (j=1; j<mtxData->nDims; j++) { 1729 mtxData->dims[j] = *(dims + dimsOffset + j); 1730 } 1731 } 1732 1733 mtxData->re = data; 1734 mtxData->im = NULL; 1735 mtxData->dTypeID = dTypeId; 1736 mtxData->mxID = rt_GetMxIdFromDTypeId(dTypeId); 1737 mtxData->elSize = rt_GetSizeofDataType(dTypeId); 1738 mtxData->logical = 0U; 1739 mtxData->complex = 0U; 1740 1741 data += numCols[i]; 1742 dimsOffset += numDims[i]; 1743 } 1744 ++sig->numActiveFields; 1745 } 1746 1747 /* titles */ 1748 if (titles != NULL) { 1749 short *data; 1750 size_t nbytes; 1751 int_T dataLen = (int_T)strlen(titles); 1752 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1753 size_t dataOffset = nSignals * sizeof(MatrixData); 1754 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1755 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 1756 1757 if (overhang) { 1758 dataOffset += (sizeof(short) - overhang); 1759 } 1760 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1761 nbytes = dataOffset + dataLen*sizeof(short); 1762 1763 if ( (sig->titles = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1764 1765 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 1766 data = (short*) (((char_T*) (sig->titles)) + dataOffset); 1767 for (i = 0; i < dataLen; i++) { 1768 data[i] = titles[i]; 1769 } 1770 1771 for (i = 0; i < nSignals; i++) { 1772 MatrixData *mtxData = &(sig->titles[i]); 1773 1774 (void)memcpy(mtxData->name, &TITLE_FIELD_NAME, mxMAXNAM); 1775 if (titleLen) { 1776 mtxData->nRows = (titleLen[i]) ? 1 : 0; 1777 mtxData->nCols = titleLen[i]; 1778 } else { 1779 mtxData->nRows = (dataLen) ? 1 : 0; 1780 mtxData->nCols = dataLen; 1781 } 1782 1783 mtxData->nDims = 1; /* assume */ 1784 mtxData->dims = mtxData->_dims; 1785 mtxData->dims[0] = mtxData->nCols; 1786 1787 mtxData->re = data; 1788 mtxData->im = NULL; 1789 mtxData->dTypeID = SS_INT16; 1790 mtxData->mxID = mxCHAR_CLASS; 1791 mtxData->elSize = sizeof(short); 1792 mtxData->logical = 0U; 1793 mtxData->complex = 0U; 1794 1795 data += ((titleLen) ? titleLen[i] : dataLen); 1796 } 1797 ++sig->numActiveFields; 1798 } 1799 1800 /* block names */ 1801 if (blockNames != NULL) { 1802 short *data; 1803 size_t nbytes; 1804 int_T dataLen = 0; 1805 size_t dataOffset = nSignals * sizeof(MatrixData); 1806 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 1807 int_T dataIdx = 0; 1808 1809 for (i=0;i<nSignals;i++) { 1810 if (blockNames[i] != NULL) { 1811 dataLen = dataLen + (int_T)strlen(blockNames[i]); 1812 } 1813 } 1814 1815 if (overhang) { 1816 dataOffset += (sizeof(short) - overhang); 1817 } 1818 1819 nbytes = dataOffset + dataLen*sizeof(short); 1820 1821 if ( (sig->blockNames = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1822 1823 data = (short*) (((char_T*) (sig->blockNames)) + dataOffset); 1824 1825 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 1826 int_T nameLen = (blockNames[sigIdx]==NULL) ? 0 : 1827 (int_T)strlen(blockNames[sigIdx]); 1828 for (i = 0; i < nameLen; i++) { 1829 data[dataIdx++] = blockNames[sigIdx][i]; 1830 } 1831 } 1832 1833 for (i = 0; i < nSignals; i++) { 1834 MatrixData *mtxData = &(sig->blockNames[i]); 1835 int_T blockNameLen = (int_T)strlen(blockNames[i]); 1836 1837 (void)memcpy(mtxData->name, &BLOCKNAME_FIELD_NAME, mxMAXNAM); 1838 mtxData->nRows = (blockNameLen) ? 1 : 0; 1839 mtxData->nCols = blockNameLen; 1840 1841 mtxData->nDims = 1; /* assume */ 1842 mtxData->dims = mtxData->_dims; 1843 mtxData->dims[0] = mtxData->nCols; 1844 1845 mtxData->re = data; 1846 mtxData->im = NULL; 1847 mtxData->dTypeID = SS_INT16; 1848 mtxData->mxID = mxCHAR_CLASS; 1849 mtxData->elSize = sizeof(short); 1850 mtxData->logical = 0U; 1851 mtxData->complex = 0U; 1852 1853 data += blockNameLen; 1854 } 1855 ++sig->numActiveFields; 1856 if(logValueDimensions){ 1857 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames; 1858 } 1859 else{ 1860 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames_noValDims; 1861 } 1862 1863 } else { 1864 if(logValueDimensions){ 1865 sig->fieldNames = rtLocalLoggingSignalsStructFieldNames; 1866 } 1867 else{ 1868 sig->fieldNames = rtLocalLoggingSignalsStructFieldNames_noValDims; 1869 } 1870 1871 } 1872 1873 /* state names */ 1874 if (stateNames != NULL) { 1875 short *data; 1876 size_t nbytes; 1877 int_T dataLen = 0; 1878 size_t dataOffset = nSignals * sizeof(MatrixData); 1879 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 1880 int_T dataIdx = 0; 1881 1882 for (i=0;i<nSignals;i++) { 1883 if (stateNames[i] != NULL) { 1884 dataLen = dataLen + (int_T)strlen(stateNames[i]); 1885 } 1886 } 1887 1888 if (overhang) { 1889 dataOffset += (sizeof(short) - overhang); 1890 } 1891 1892 nbytes = dataOffset + dataLen*sizeof(short); 1893 1894 if ( (sig->stateNames = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1895 1896 data = (short*) (((char_T*) (sig->stateNames)) + dataOffset); 1897 1898 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 1899 int_T nameLen = (stateNames[sigIdx]==NULL) ? 0 : 1900 (int_T)strlen(stateNames[sigIdx]); 1901 for (i = 0; i < nameLen; i++) { 1902 data[dataIdx++] = stateNames[sigIdx][i]; 1903 } 1904 } 1905 1906 for (i = 0; i < nSignals; i++) { 1907 MatrixData *mtxData = &(sig->stateNames[i]); 1908 int_T stateNameLen = (int_T)strlen(stateNames[i]); 1909 1910 (void)memcpy(mtxData->name, &STATENAME_FIELD_NAME, mxMAXNAM); 1911 mtxData->nRows = (stateNameLen) ? 1 : 0; 1912 mtxData->nCols = stateNameLen; 1913 1914 mtxData->nDims = 1; /* assume */ 1915 mtxData->dims = mtxData->_dims; 1916 mtxData->dims[0] = mtxData->nCols; 1917 1918 mtxData->re = data; 1919 mtxData->im = NULL; 1920 mtxData->dTypeID = SS_INT16; 1921 mtxData->mxID = mxCHAR_CLASS; 1922 mtxData->elSize = sizeof(short); 1923 mtxData->logical = 0U; 1924 mtxData->complex = 0U; 1925 1926 data += stateNameLen; 1927 } 1928 ++sig->numActiveFields; 1929 1930 if(logValueDimensions){ 1931 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames; 1932 } 1933 else{ 1934 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames_noValDims; 1935 } 1936 1937 } 1938 1939 /* CrossMdlRef */ 1940 if (crossMdlRef != NULL) { 1941 real_T *data; 1942 size_t nbytes; 1943 size_t dataOffset = nSignals * sizeof(MatrixData); 1944 uint_T overhang = (uint_T)(dataOffset % sizeof(real_T)); 1945 1946 if (overhang) { 1947 dataOffset += (sizeof(real_T) - overhang); 1948 } 1949 1950 nbytes = dataOffset + nSignals*sizeof(real_T); 1951 1952 if ( (sig->crossMdlRef = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1953 1954 data = (real_T*) (((char_T*) (sig->crossMdlRef)) + dataOffset); 1955 1956 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 1957 data[sigIdx] = crossMdlRef[sigIdx]; 1958 } 1959 1960 for (i = 0; i < nSignals; i++) { 1961 MatrixData *mtxData = &(sig->crossMdlRef[i]); 1962 1963 (void)memcpy(mtxData->name, &CROSS_MDL_REF_FIELD_NAME, mxMAXNAM); 1964 mtxData->nRows = 1; 1965 mtxData->nCols = 1; 1966 mtxData->nDims = 1; /* => matlab scalar */ 1967 1968 mtxData->re = &data[i]; 1969 mtxData->im = NULL; 1970 mtxData->dTypeID = SS_DOUBLE; 1971 mtxData->mxID = rt_GetMxIdFromDTypeId(SS_DOUBLE); 1972 mtxData->elSize = sizeof(real_T); 1973 mtxData->logical = matLOGICAL_BIT; 1974 mtxData->complex = 0U; 1975 mtxData->frameData = 0; 1976 mtxData->frameSize = 1; 1977 } 1978 ++sig->numActiveFields; 1979 } 1980 1981 return(NULL); /* NORMAL_EXIT */ 1982 1983 ERROR_EXIT: 1984 1985 (void)fprintf(stderr, "*** Error creating signals structure " 1986 "in the struct log variable %s\n", var->name); 1987 if (*errStatus == NULL) { 1988 *errStatus = rtMemAllocError; 1989 } 1990 rt_DestroyLogVar(sig->values); 1991 FREE(sig->labels); 1992 FREE(sig->plotStyles); 1993 FREE(sig->dimensions); 1994 FREE(sig->titles); 1995 FREE(sig->blockNames); 1996 FREE(sig->stateNames); 1997 FREE(sig->crossMdlRef); 1998 1999 return(*errStatus); 2000 2001 } /* end rt_InitSignalsStruct */ 2002 2003 2004 /* Function: local_CreateStructLogVar ========================================== 2005 * Abstract: 2006 * Create a logging variable in the structure format. 2007 * 2008 * Returns: 2009 * ~= NULL => success, returns the log variable created. 2010 * == NULL => failure, error message set in the simstruct. 2011 */ 2012 static StructLogVar *local_CreateStructLogVar( 2013 RTWLogInfo *li, 2014 const real_T startTime, 2015 const real_T finalTime, 2016 const real_T inStepSize, 2017 const char_T **errStatus, 2018 const char_T *varName, 2019 boolean_T logTime, 2020 int_T maxRows, 2021 int_T decimation, 2022 real_T sampleTime, 2023 const RTWLogSignalInfo *sigInfo, 2024 const char_T *blockName) 2025 { 2026 StructLogVar *var; 2027 LogInfo *logInfo = rtliGetLogInfo(li); 2028 2029 /* reset error status */ 2030 *errStatus = NULL; 2031 2032 if ( (var = calloc(1, sizeof(StructLogVar))) == NULL ) goto ERROR_EXIT; 2033 2034 var->numActiveFields = 2; 2035 2036 /* Setup the structure name using varName and nameModifier */ 2037 rt_LoadModifiedLogVarName(li,varName,var->name); 2038 2039 /* time field */ 2040 if (logTime) { 2041 /* need to create a LogVar to log time */ 2042 int_T dims = 1; 2043 var->time = rt_CreateLogVarWithConvert(li, startTime, finalTime, 2044 inStepSize, errStatus, 2045 &TIME_FIELD_NAME, SS_DOUBLE, 2046 NULL, 2047 0, 0, 0, 1, 2048 1, &dims, NO_LOGVALDIMS, 2049 NULL, NULL, maxRows, 2050 decimation, sampleTime, 0); 2051 if (var->time == NULL) goto ERROR_EXIT; 2052 } else { 2053 /* create a dummy MatrixData to write out time as an empty matrix */ 2054 BuiltInDTypeId dt = rt_GetActualDTypeID(SS_DOUBLE); 2055 size_t nbytes = sizeof(MatrixData); 2056 MatrixData *time; 2057 2058 if ( (var->time = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 2059 time = var->time; 2060 2061 (void)memcpy(time->name, &TIME_FIELD_NAME, mxMAXNAM); 2062 time->nRows = 0; 2063 time->nCols = 0; 2064 time->nDims = 0; 2065 time->re = NULL; 2066 time->im = NULL; 2067 time->dTypeID = dt; 2068 time->mxID = rt_GetMxIdFromDTypeId(dt); 2069 time->elSize = rt_GetSizeofDataType(dt); 2070 time->logical = 0U; 2071 time->complex = 0U; 2072 } 2073 var->logTime = logTime; 2074 2075 /* signals field */ 2076 if (sigInfo) { 2077 if (rt_InitSignalsStruct(li,startTime,finalTime,inStepSize,errStatus, 2078 var,maxRows,decimation,sampleTime,sigInfo)) { 2079 goto ERROR_EXIT; 2080 } 2081 } 2082 2083 /* blockName Field */ 2084 if (blockName != NULL) { 2085 int_T dataLen = (int_T)strlen(blockName); 2086 size_t nbytes; 2087 size_t dataOffset = sizeof(MatrixData); 2088 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 2089 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 2090 2091 if (overhang) { 2092 dataOffset += (sizeof(short) - overhang); 2093 } 2094 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 2095 nbytes = dataOffset + dataLen*sizeof(short); 2096 2097 if ( (var->blockName = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 2098 2099 (void)memcpy(var->blockName->name, &BLOCKNAME_FIELD_NAME, mxMAXNAM); 2100 var->blockName->nRows = (dataLen) ? 1 : 0; 2101 var->blockName->nCols = dataLen; 2102 2103 var->blockName->nDims = 1; 2104 var->blockName->dims = var->blockName->_dims; 2105 var->blockName->dims[0] = dataLen; 2106 { 2107 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 2108 short *data = (short*)(((char_T*) (var->blockName))+dataOffset); 2109 int_T i; 2110 2111 for (i=0; i<dataLen; i++) { 2112 data[i] = blockName[i]; 2113 } 2114 var->blockName->re = data; 2115 } 2116 var->blockName->im = NULL; 2117 var->blockName->dTypeID = SS_INT16; 2118 var->blockName->mxID = mxCHAR_CLASS; 2119 var->blockName->elSize = sizeof(short); 2120 var->blockName->logical = 0U; 2121 var->blockName->complex = 0U; 2122 2123 ++var->numActiveFields; 2124 } 2125 2126 /* Add this struct log var to the linked list in log info */ 2127 { 2128 StructLogVar *list = logInfo->structLogVarsList; 2129 2130 if (list != NULL) { 2131 while (list->next != NULL) { 2132 list = list->next; 2133 } 2134 list->next = var; 2135 } else { 2136 logInfo->structLogVarsList = var; 2137 } 2138 } 2139 2140 return(var); /* NORMAL_EXIT */ 2141 2142 ERROR_EXIT: 2143 (void)fprintf(stderr, "*** Error creating log variable %s\n", varName); 2144 if (*errStatus == NULL) { 2145 *errStatus = rtMemAllocError; 2146 } 2147 rt_DestroyStructLogVar(var); 2148 return(NULL); 2149 2150 } /* end local_CreateStructLogVar */ 2151 2152 2153 /* Function: rt_StartDataLoggingForOutput ====================================== 2154 * Abstract: 2155 */ 2156 const char_T *rt_StartDataLoggingForOutput(RTWLogInfo *li, 2157 const real_T startTime, 2158 const real_T finalTime, 2159 const real_T stepSize, 2160 const char_T **errStatus) 2161 { 2162 const char_T *varName; 2163 real_T sampleTime = stepSize; 2164 int_T maxRows = rtliGetLogMaxRows(li); 2165 int_T decimation = rtliGetLogDecimation(li); 2166 int_T logFormat = rtliGetLogFormat(li); 2167 boolean_T logTime = (logFormat==2) ? 1 : 0; 2168 2169 LogInfo * logInfo; 2170 logInfo = rtliGetLogInfo(li); 2171 2172 /* reset error status */ 2173 *errStatus = NULL; 2174 2175 /* outputs */ 2176 varName = rtliGetLogY(li); 2177 if (varName[0] != '\0') { 2178 int_T i; 2179 int_T ny; 2180 int_T yIdx; 2181 char_T name[mxMAXNAM]; 2182 const char_T *cp = strchr(varName,','); 2183 LogSignalPtrsType ySigPtrs = rtliGetLogYSignalPtrs(li); 2184 const RTWLogSignalInfo *yInfo = rtliGetLogYSignalInfo(li); 2185 2186 /* count the number of variables (matrices or structures) to create */ 2187 for (ny=1; cp != NULL; ny++) { 2188 cp = strchr(cp+1,','); 2189 } 2190 logInfo->ny = ny; 2191 2192 if (logFormat==0) { 2193 if ( (logInfo->y = calloc(ny,sizeof(LogVar*))) == NULL ) { 2194 *errStatus = rtMemAllocError; 2195 goto ERROR_EXIT; 2196 } 2197 } else { 2198 if ( (logInfo->y = calloc(ny,sizeof(StructLogVar*))) == NULL ) { 2199 *errStatus = rtMemAllocError; 2200 goto ERROR_EXIT; 2201 } 2202 } 2203 2204 for (i = yIdx = 0, cp = varName; i < ny; i++) { 2205 int_T len; 2206 const char_T *cp1 = strchr(cp+1,','); 2207 2208 if (cp1 != NULL) { 2209 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 2210 len = (int_T)(cp1 - cp); 2211 if (len >= mxMAXNAM) len = mxMAXNAM - 1; 2212 } else { 2213 len = mxMAXNAM - 1; 2214 } 2215 (void)strncpy(name, cp, len); 2216 name[len] = '\0'; 2217 2218 if (ny > 1 && ySigPtrs[i] == NULL) { 2219 goto NEXT_NAME; 2220 } 2221 2222 if (logFormat == 0) { 2223 int numCols; 2224 int nDims; 2225 const int *dims; 2226 BuiltInDTypeId dataType; 2227 int isComplex; 2228 2229 if (ny == 1) { 2230 int_T op; 2231 2232 numCols = yInfo[0].numCols[0]; 2233 for (op = 1; op < yInfo[0].numSignals; op++) { 2234 numCols += yInfo[0].numCols[op]; 2235 } 2236 /* 2237 * If we have only one "matrix" outport, 2238 * we can still log it as a matrix 2239 */ 2240 if (yInfo[0].numSignals == 1) { 2241 nDims = yInfo[0].numDims[0]; 2242 dims = yInfo[0].dims; 2243 } else { 2244 nDims = 1; 2245 dims = &numCols; 2246 } 2247 2248 dataType = yInfo[0].dataTypes[0]; 2249 isComplex = yInfo[0].complexSignals[0]; 2250 } else { 2251 numCols = yInfo[yIdx].numCols[0]; 2252 nDims = yInfo[yIdx].numDims[0]; 2253 dims = yInfo[yIdx].dims; 2254 dataType = yInfo[yIdx].dataTypes[0]; 2255 isComplex = yInfo[yIdx].complexSignals[0]; 2256 } 2257 2258 logInfo->y[yIdx] = rt_CreateLogVarWithConvert( 2259 li, startTime, finalTime, 2260 stepSize, errStatus, 2261 name, 2262 dataType, 2263 yInfo[yIdx].dataTypeConvert, 2264 0,isComplex, 2265 0,numCols,nDims,dims, 2266 NO_LOGVALDIMS, NULL, NULL, 2267 maxRows,decimation, 2268 sampleTime,1); 2269 if (logInfo->y[yIdx] == NULL) goto ERROR_EXIT; 2270 } else { 2271 logInfo->y[yIdx] = local_CreateStructLogVar(li, startTime, 2272 finalTime, stepSize, 2273 errStatus, name, 2274 logTime, maxRows, 2275 decimation, sampleTime, 2276 &yInfo[yIdx], NULL); 2277 if (logInfo->y[yIdx] == NULL) goto ERROR_EXIT; 2278 } 2279 ++yIdx; 2280 NEXT_NAME: 2281 cp = cp1; 2282 if (cp != NULL && *cp == ',') cp++; 2283 } 2284 } 2285 2286 return(NULL); /* NORMAL_EXIT */ 2287 2288 ERROR_EXIT: 2289 (void)fprintf(stderr, "*** Errors occurred when starting data logging.\n"); 2290 if (*errStatus == NULL) { 2291 *errStatus = rtMemAllocError; 2292 } 2293 if (logInfo) { 2294 rt_DestroyLogVar(logInfo->logVarsList); 2295 logInfo->logVarsList = NULL; 2296 rt_DestroyStructLogVar(logInfo->structLogVarsList); 2297 logInfo->structLogVarsList = NULL; 2298 FREE(logInfo->y); 2299 logInfo->y = NULL; 2300 } 2301 return(*errStatus); 2302 2303 } /* end rt_StartDataLoggingForOutput */ 2304 2305 2306 /* Function: rt_ReallocLogVar ================================================== 2307 * Abstract: 2308 * Allocate more memory for the data buffers in the log variable. 2309 * Exit if unable to allocate more memory. 2310 */ 2311 void rt_ReallocLogVar(LogVar *var, boolean_T isVarDims) 2312 { 2313 void *tmp; 2314 int_T nCols = var->data.nCols; 2315 int_T nRows = var->data.nRows + DEFAULT_BUFFER_SIZE; 2316 size_t elSize = var->data.elSize; 2317 2318 tmp = realloc(var->data.re, nRows*nCols*elSize); 2319 if (tmp == NULL) { 2320 (void)fprintf(stderr, 2321 "*** Memory allocation error.\n"); 2322 (void)fprintf(stderr, "" 2323 " varName = %s%s\n" 2324 " nRows = %d\n" 2325 " nCols = %d\n" 2326 " elementSize = %lu\n" 2327 " Current Size = %.16g\n" 2328 " Failed resize = %.16g\n\n", 2329 var->data.name, 2330 var->data.complex ? " (real part)" : "", 2331 var->data.nRows, 2332 var->data.nCols, 2333 (long) var->data.elSize, 2334 (double)nRows*nCols*elSize, 2335 (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize); 2336 exit(1); 2337 } 2338 var->data.re = tmp; 2339 2340 if (var->data.complex) { 2341 tmp = realloc(var->data.im, nRows*nCols*elSize); 2342 if (tmp == NULL) { 2343 (void)fprintf(stderr, 2344 "*** Memory allocation error.\n"); 2345 (void)fprintf(stderr, "" 2346 " varName = %s (complex part)\n" 2347 " nRows = %d\n" 2348 " nCols = %d\n" 2349 " elementSize = %lu\n" 2350 " Current Size = %.16g\n" 2351 " Failed resize = %.16g\n\n", 2352 var->data.name, 2353 var->data.nRows, 2354 var->data.nCols, 2355 (long) var->data.elSize, 2356 (double)nRows*nCols*elSize, 2357 (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize); 2358 exit(1); 2359 } 2360 var->data.im = tmp; 2361 } 2362 var->data.nRows = nRows; 2363 2364 /* Also reallocate memory for "valueDimensions" 2365 when logging the variable-size signal 2366 */ 2367 if(isVarDims){ 2368 int_T k; 2369 2370 nCols = var->valDims->nCols; 2371 nRows = var->valDims->nRows + DEFAULT_BUFFER_SIZE; 2372 elSize = sizeof(real_T); 2373 tmp = realloc(var->valDims->dimsData, nRows*nCols*elSize); 2374 if (tmp == NULL) { 2375 (void)fprintf(stderr, 2376 "*** Memory allocation error.\n"); 2377 (void)fprintf(stderr, "" 2378 " varName = %s\n" 2379 " nRows = %d\n" 2380 " nCols = %d\n" 2381 " elementSize = %lu\n" 2382 " Current Size = %.16g\n" 2383 " Failed resize = %.16g\n\n", 2384 var->valDims->name, 2385 var->valDims->nRows, 2386 var->valDims->nCols, 2387 (long) elSize, 2388 (double)nRows*nCols*elSize, 2389 (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize); 2390 exit(1); 2391 } 2392 2393 /* 2394 * valueDimensions data is stored in array format and must be 2395 * adjusted after reallocation (see also rt_FixupLogVar()) 2396 * 2397 * Example: maxRows = 4; nRows = 4; nDims = 3; 2398 * Before realloc of the logVar, the locations of data are as below: 2399 * (x, y, z -- useful data / o -- junk, don't care) 2400 * a[0] = x a[4] = y a[8] = z 2401 * a[1] = x a[5] = y a[9] = z 2402 * a[2] = x a[6] = y a[10]= z 2403 * a[3] = x a[7] = y a[11]= z 2404 * 2405 * After realloc of the logVar (suppose 2 extra rows are added), 2406 * the locations of data are as below: 2407 * a[0] = x a[6] = y a[12]= o 2408 * a[1] = x a[7] = y a[13]= o 2409 * a[2] = x a[8] = z a[14]= o 2410 * a[3] = x a[9] = z a[15]= o 2411 * a[4] = y a[10]= z a[16]= o 2412 * a[5] = y a[11]= z a[17]= o 2413 * 2414 * The data must be adjusted as below: 2415 * a[0] = x a[6] = y a[12]= z 2416 * a[1] = x a[7] = y a[13]= z 2417 * a[2] = x a[8] = y a[14]= z 2418 * a[3] = x a[9] = y a[15]= z 2419 * a[4] = o a[10]= o a[16]= o 2420 * a[5] = o a[11]= o a[17]= o 2421 */ 2422 for(k = var->data.nDims-1; k > 0; k--){ 2423 (void) memcpy((real_T*)tmp + k*nRows, 2424 (real_T*)tmp + k*var->valDims->nRows, 2425 elSize * var->valDims->nRows); 2426 } 2427 2428 var->valDims->dimsData = tmp; 2429 var->valDims->nRows = nRows; 2430 } 2431 2432 } /* end rt_ReallocLogVar */ 2433 2434 2435 /* Function: rt_UpdateLogVarWithDiscontiguousData ============================== 2436 * Abstract: 2437 * Log one row of the LogVar with data that is not contiguous. 2438 */ 2439 void rt_UpdateLogVarWithDiscontiguousData(LogVar *var, 2440 LogSignalPtrsType data, 2441 const int_T *segmentLengths, 2442 int_T nSegments) 2443 { 2444 size_t elSize = 0; 2445 int_T offset = 0; 2446 int segIdx = 0; 2447 2448 if (++var->numHits % var->decimation) return; 2449 var->numHits = 0; 2450 2451 /* 2452 * Reallocate or wrap the LogVar 2453 */ 2454 if (var->rowIdx == var->data.nRows) { 2455 if (var->okayToRealloc == 1) { 2456 rt_ReallocLogVar(var, false); 2457 } else { 2458 /* Circular buffer */ 2459 var->rowIdx = 0; 2460 ++(var->wrapped); /* increment the wrap around counter */ 2461 } 2462 } 2463 2464 /* This function is only used to log states, there's no var-dims issue. */ 2465 elSize = var->data.elSize; 2466 offset = (int_T)(elSize * var->rowIdx * var->data.nCols); 2467 2468 if (var->data.complex) { 2469 char_T *dstRe = (char_T*)(var->data.re) + offset; 2470 char_T *dstIm = (char_T*)(var->data.im) + offset; 2471 2472 for (segIdx = 0; segIdx < nSegments; segIdx++) { 2473 int_T nEl = segmentLengths[segIdx]; 2474 const char_T *src = (const void *)data[segIdx]; 2475 int_T el; 2476 2477 for (el = 0; el < nEl; el++) { 2478 (void)memcpy(dstRe, src, elSize); 2479 dstRe += elSize; src += elSize; 2480 (void)memcpy(dstIm, src, elSize); 2481 dstIm += elSize; src += elSize; 2482 } 2483 } 2484 } else { 2485 char_T *dst = (char_T*)(var->data.re) + offset; 2486 2487 for (segIdx = 0; segIdx < nSegments; segIdx++) { 2488 size_t segSize = elSize*segmentLengths[segIdx]; 2489 const void *src = data[segIdx]; 2490 2491 (void)memcpy(dst, src, segSize); 2492 dst += segSize; 2493 } 2494 } 2495 2496 ++var->rowIdx; 2497 return; 2498 2499 } /* end rt_UpdateLogVarWithDiscontiguousData */ 2500 2501 2502 /*==================* 2503 * Visible routines * 2504 *==================*/ 2505 2506 2507 2508 #ifdef __cplusplus 2509 extern "C" { 2510 #endif 2511 2512 2513 /* Function: rt_CreateLogVarWithConvert ======================================== 2514 * Abstract: 2515 * Create a logging variable. 2516 * 2517 * Returns: 2518 * ~= NULL => success, returns the log variable created. 2519 * == NULL => failure, error message set in the simstruct. 2520 */ 2521 LogVar *rt_CreateLogVarWithConvert( 2522 RTWLogInfo *li, 2523 const real_T startTime, 2524 const real_T finalTime, 2525 const real_T inStepSize, 2526 const char_T **errStatus, 2527 const char_T *varName, 2528 BuiltInDTypeId inpDataTypeID, 2529 const RTWLogDataTypeConvert *pDataTypeConvertInfo, 2530 int_T logical, 2531 int_T complex, 2532 int_T frameData, 2533 int_T nCols, 2534 int_T nDims, 2535 const int_T *dims, 2536 LogValDimsStat logValDimsStat, 2537 void **currSigDims, 2538 int_T *currSigDimsSize, 2539 int_T maxRows, 2540 int_T decimation, 2541 real_T sampleTime, 2542 int_T appendToLogVarsList) 2543 { 2544 int_T usingDefaultBufSize = 0; 2545 #ifdef NO_LOGGING_REALLOC 2546 int_T okayToRealloc = 0; 2547 #else 2548 int_T okayToRealloc = 1; 2549 #endif 2550 LogVar *var = NULL; 2551 /*inpDataTypeID is the rt_LoggedOutputDataTypeId*/ 2552 BuiltInDTypeId dTypeID = (BuiltInDTypeId)inpDataTypeID; 2553 size_t elementSize = rt_GetSizeofDataType(dTypeID); 2554 int_T frameSize; 2555 int_T nRows; 2556 int_T nColumns; 2557 2558 /*===================================================================* 2559 * Determine the frame size if the data is frame based * 2560 *===================================================================*/ 2561 frameSize = frameData ? dims[0] : 1; 2562 2563 /*===================================================================* 2564 * Calculate maximum number of rows needed in the buffer * 2565 *===================================================================*/ 2566 2567 if (finalTime > startTime && finalTime != rtInf) { 2568 real_T nPoints; /* Tfinal is finite ===> nRows can be */ 2569 real_T stepSize; /* computed since the StepSize is fixed */ 2570 2571 if (sampleTime == -2.0) { /* The signal being logged is constant, * 2572 * Hence, only one data point is logged. */ 2573 stepSize = finalTime; 2574 } else if (sampleTime == -1.0 || sampleTime == 0.0) { 2575 /* Signal being logged is either inside a * 2576 * triggered sub-system or it is continuous. */ 2577 stepSize = inStepSize; 2578 } else { /* Discrete signal */ 2579 stepSize = sampleTime; 2580 } 2581 2582 if (stepSize == 0.0) { 2583 /* small initial value, so as to exercise the realloc code */ 2584 nRows = maxRows+1; 2585 okayToRealloc = 1; 2586 } else { 2587 nPoints = 1.0 + floor((finalTime-startTime)/stepSize); 2588 2589 /* 2590 * Add one more data point if needed. 2591 */ 2592 if ( stepSize*(nPoints-1.0) < (finalTime-startTime) ) { 2593 nPoints += 1.0; 2594 } 2595 2596 /* 2597 * Actual number of points to log = nPoints * size of 2598 * each frame if data is frame-based 2599 */ 2600 nPoints = frameData ? (nPoints * frameSize) : nPoints; 2601 2602 nPoints /= decimation; 2603 if (nPoints != floor(nPoints)) { 2604 nPoints += 1.0; 2605 } 2606 nRows = (nPoints <= INT_MAX) ? ((int_T) nPoints) : INT_MAX; 2607 } 2608 /* 2609 * If maxRows is specified, and if this number is less 2610 * than the number we computed (nRows) then use maxRows. 2611 */ 2612 if ((maxRows > 0) && (maxRows < nRows)) { 2613 nRows = maxRows; 2614 okayToRealloc = 0; 2615 } 2616 } else if (finalTime == startTime) { 2617 /* 2618 * Number of rows to log is equal to 1 if not frame-based and 2619 * equal to frame size if frame-based 2620 */ 2621 nRows = frameData ? frameSize : 1; 2622 2623 /* 2624 * If maxRows is specified, and if this number is less 2625 * than the number we computed (nRows) then use maxRows. 2626 */ 2627 if ((maxRows > 0) && (maxRows < nRows)) { 2628 nRows = maxRows; 2629 okayToRealloc = 0; 2630 } 2631 } else if (maxRows > 0) { /* maxRows is specified => nRows=maxRows */ 2632 nRows = maxRows; 2633 okayToRealloc = 0; 2634 } else { 2635 2636 if (inStepSize == 0) { 2637 /* small initial value, so as to exercise the realloc code */ 2638 nRows = maxRows+1; 2639 okayToRealloc = 1; 2640 } else { /* Use a default value for nRows */ 2641 usingDefaultBufSize = 1; 2642 nRows = DEFAULT_BUFFER_SIZE; 2643 okayToRealloc = 0; /* No realloc with infinite stop time */ 2644 (void)fprintf(stdout, "*** Using a default buffer of size %d for " 2645 "logging variable %s\n", nRows, varName); 2646 } 2647 } 2648 2649 /* 2650 * Figure out the number of columns that the log variable should have. 2651 * If the data is not frame based, then number of columns should equal 2652 * nCols that is provided as input to the function. If the data is 2653 * frame-based, then the number of columns should be equal to the 2654 * number of channels = nCols/frameSize = dims[1]; 2655 */ 2656 nColumns = frameData ? dims[1] : nCols; 2657 2658 /* 2659 * Error out if the size of the circular buffer is absurdly large, this 2660 * error message is more informative than the one we get when we try to 2661 * malloc this many number of bytes in one fell swoop. 2662 */ 2663 { 2664 double tmpDbl = ((double)elementSize)*((double)nRows)* 2665 ((double)nColumns); 2666 2667 if (tmpDbl >= UINT_MAX) { 2668 (void)fprintf(stderr, 2669 "\n*** Memory required to log variable '%s' is too" 2670 "\n big. Use the 'Limit rows to last:' and (or)" 2671 "\n 'Decimation:' options to reduce the required" 2672 "\n memory size.\n", varName); 2673 (void)fprintf(stderr, "*** Details:\n" 2674 " varName = %s\n" 2675 " nRows = %d\n" 2676 " nCols = %d\n" 2677 " elementSize = %lu\n" 2678 " Bytes Required = %.16g\n\n", 2679 varName, nRows, nColumns, (unsigned long) 2680 elementSize, tmpDbl); 2681 goto ERROR_EXIT; 2682 } 2683 } 2684 2685 /* Allocate memory for the log variable */ 2686 if ( (var = calloc(1, sizeof(LogVar))) == NULL ) { 2687 (void)fprintf(stderr, "*** Error allocating memory for logging %s\n", 2688 varName); 2689 goto ERROR_EXIT; 2690 } 2691 2692 /* Allocate memory for the circular buffer (real part) */ 2693 if ( (var->data.re = malloc(nRows*nColumns*elementSize)) == NULL ) { 2694 (void)fprintf(stderr, 2695 "*** Error allocating memory for the circular buffer\n"); 2696 (void)fprintf(stderr, "*** Details:\n" 2697 " varName = %s\n" 2698 " nRows = %d\n" 2699 " nCols = %d\n" 2700 " elementSize = %lu\n" 2701 " Bytes Requested = %.16g\n\n", 2702 varName, nRows, nColumns, (unsigned long) elementSize, 2703 ((double)elementSize)*((double)nRows)*((double)nColumns)); 2704 goto ERROR_EXIT; 2705 } 2706 2707 /* Allocate memory for the circular buffer for the imaginary part */ 2708 if (complex) { 2709 if ( (var->data.im = malloc(nRows*nColumns*elementSize)) == NULL ) { 2710 (void)fprintf(stderr, 2711 "*** Error allocating memory for the circular buffer " 2712 "for logging the imaginary part of %s\n", varName); 2713 (void)fprintf(stderr, "*** Details:\n" 2714 " varName = %s\n" 2715 " nRows = %d\n" 2716 " nCols = %d\n" 2717 " elementSize = %lu\n" 2718 " Bytes Requested = %.16g\n\n", 2719 varName, nRows, nColumns, (unsigned long) elementSize, 2720 ((double)elementSize)*((double)nRows)* 2721 ((double)nColumns)); 2722 goto ERROR_EXIT; 2723 } 2724 } 2725 /* 2726 * Initialize the fields in LogVar structure. 2727 */ 2728 if (appendToLogVarsList) { 2729 rt_LoadModifiedLogVarName(li,varName,var->data.name); 2730 } else { 2731 var->data.name[mxMAXNAM-1] = '\0'; 2732 (void)strncpy(var->data.name,varName,mxMAXNAM-1); 2733 } 2734 var->data.nCols = nColumns; 2735 var->data.nRows = nRows; 2736 2737 var->data.nDims = frameData ? 1 : nDims; 2738 if (var->data.nDims > 2) { 2739 var->data.dims = (int_T*)malloc(sizeof(int_T)*var->data.nDims); 2740 } else { 2741 var->data.dims = var->data._dims; 2742 } 2743 if (frameData) { 2744 var->data.dims[0] = nColumns; 2745 } else { 2746 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 2747 (void)memcpy(var->data.dims, dims, (size_t)(nDims*sizeof(int_T))); 2748 } 2749 2750 var->data.dTypeID = dTypeID; 2751 var->data.elSize = elementSize; 2752 2753 var->data.dataTypeConvertInfo = rt_GetDataTypeConvertInfo( 2754 pDataTypeConvertInfo, dTypeID); 2755 2756 var->data.mxID = rt_GetMxIdFromDTypeId(dTypeID); 2757 /* over-ride logical bit if data type is boolean */ 2758 logical = dTypeID == SS_BOOLEAN ? 1 : 0; 2759 var->data.logical = (logical) ? matLOGICAL_BIT : 0x0; 2760 var->data.complex = (complex) ? matCOMPLEX_BIT : 0x0; 2761 var->data.frameData = frameData; 2762 var->data.frameSize = (frameData) ? frameSize : 1; 2763 2764 /* fill up valDims field */ 2765 if(logValDimsStat == NO_LOGVALDIMS){ 2766 /* All signals are fixed-size, no need to log valueDimensions field */ 2767 var->valDims = NULL; 2768 /* Set these pointers to NULLs in this case */ 2769 var->coords = NULL; 2770 var->strides = NULL; 2771 var->currStrides = NULL; 2772 } 2773 else{ 2774 if ( (var->valDims = calloc(1, sizeof(ValDimsData))) == NULL ) { 2775 goto ERROR_EXIT; 2776 } 2777 2778 (void)memcpy(var->valDims->name, &VALUEDIMENSIONS_FIELD_NAME, mxMAXNAM); 2779 2780 if (logValDimsStat == LOGVALDIMS_EMPTYMX) { 2781 /* At least one signal is variable-size, 2782 but the current signal is fixed-size. 2783 Therefore, create a dummy MatrixData to write out valueDimensions 2784 as an empty matrix. 2785 */ 2786 var->valDims->nRows = 0; 2787 var->valDims->nCols = 0; 2788 var->valDims->currSigDims = NULL; 2789 var->valDims->currSigDimsSize = NULL; 2790 var->valDims->dimsData = NULL; 2791 /* Set these pointers to NULLs in this case */ 2792 var->coords = NULL; 2793 var->strides = NULL; 2794 var->currStrides = NULL; 2795 } else { /* The current signal is a variable-size signal. */ 2796 /* The "valueDimensions" must be double, so re-assign element size */ 2797 elementSize = sizeof(real_T); 2798 2799 /* When signals are frame-based, 'valueDimensions' has 1 column */ 2800 if(frameData){ 2801 /* When signal is frame-based, the first dimension is always fixed, 2802 so we only need to record the second dimension. 2803 e.g. Two frame-based signals [10x4] and [10x3], 2804 'valueDimensions' and 'currSigDims' 2805 only record 4 or 3. 2806 */ 2807 nColumns = 1; 2808 var->valDims->currSigDims = (void**) (currSigDims + 1); 2809 var->valDims->currSigDimsSize = (int_T*) (currSigDimsSize + 1); 2810 } else { /* non-frame based */ 2811 nColumns = nDims; 2812 var->valDims->currSigDims = (void**) currSigDims; 2813 var->valDims->currSigDimsSize = (int_T*) currSigDimsSize; 2814 } 2815 2816 /* Allocate memory for the circular buffer */ 2817 if ( (var->valDims->dimsData = malloc(nRows*nColumns*elementSize)) == NULL ) { 2818 (void)fprintf(stderr, 2819 "*** Error allocating memory for the circular buffer\n"); 2820 (void)fprintf(stderr, "*** Details:\n" 2821 " varName = %s\n" 2822 " nRows = %d\n" 2823 " nCols = %d\n" 2824 " elementSize = %lu\n" 2825 " Bytes Requested = %.16g\n\n", 2826 var->valDims->name, nRows, nColumns, (unsigned long) elementSize, 2827 ((double)elementSize)*((double)nRows)*((double)nColumns)); 2828 goto ERROR_EXIT; 2829 } 2830 var->valDims->nRows = nRows; 2831 var->valDims->nCols = nColumns; 2832 2833 /* Allocate memory for these dynamic arrays */ 2834 { 2835 size_t nbytes = var->data.nDims*sizeof(int_T); 2836 if( ((var->coords = calloc(nbytes, 1)) == NULL) 2837 ||((var->strides = calloc(nbytes, 1)) == NULL) 2838 ||((var->currStrides = calloc(nbytes, 1)) == NULL) ) 2839 goto ERROR_EXIT; 2840 } 2841 } 2842 } 2843 2844 var->rowIdx = 0; 2845 var->wrapped = 0; 2846 var->nDataPoints = 0; 2847 var->usingDefaultBufSize = usingDefaultBufSize; 2848 var->okayToRealloc = okayToRealloc; 2849 var->decimation = decimation; 2850 var->numHits = -1; /* so first point gets logged */ 2851 2852 /* Add this log var to list in log info, if necessary */ 2853 if (appendToLogVarsList) { 2854 LogInfo *logInfo = (LogInfo*) rtliGetLogInfo(li); 2855 LogVar *varList = logInfo->logVarsList; 2856 2857 if (varList != NULL) { 2858 while (varList->next != NULL) { 2859 varList = varList->next; 2860 } 2861 varList->next = var; 2862 } else { 2863 logInfo->logVarsList = var; 2864 } 2865 } 2866 2867 return(var); /* NORMAL_EXIT */ 2868 2869 ERROR_EXIT: 2870 2871 *errStatus = rtMemAllocError; 2872 rt_DestroyLogVar(var); 2873 return(NULL); 2874 2875 } /* end rt_CreateLogVarWithConvert */ 2876 2877 2878 #ifdef __cplusplus 2879 } 2880 #endif 2881 2882 2883 2884 2885 #ifdef __cplusplus 2886 extern "C" { 2887 #endif 2888 2889 2890 /* Function: rt_CreateLogVar =================================================== 2891 * Abstract: 2892 * Create a logging variable. 2893 * 2894 * Returns: 2895 * ~= NULL => success, returns the log variable created. 2896 * == NULL => failure, error message set in the simstruct. 2897 */ 2898 LogVar *rt_CreateLogVar(RTWLogInfo *li, 2899 const real_T startTime, 2900 const real_T finalTime, 2901 const real_T inStepSize, 2902 const char_T **errStatus, 2903 const char_T *varName, 2904 BuiltInDTypeId inpDataTypeID, 2905 int_T logical, 2906 int_T complex, 2907 int_T frameData, 2908 int_T nCols, 2909 int_T nDims, 2910 const int_T *dims, 2911 LogValDimsStat logValDimsStat, 2912 void **currSigDims, 2913 int_T *currSigDimsSize, 2914 int_T maxRows, 2915 int_T decimation, 2916 real_T sampleTime, 2917 int_T appendToLogVarsList) 2918 { 2919 const RTWLogDataTypeConvert *pDataTypeConvertInfo = NULL; 2920 2921 return rt_CreateLogVarWithConvert(li, 2922 startTime, 2923 finalTime, 2924 inStepSize, 2925 errStatus, 2926 varName, 2927 inpDataTypeID, 2928 pDataTypeConvertInfo, 2929 logical, 2930 complex, 2931 frameData, 2932 nCols, 2933 nDims, 2934 dims, 2935 logValDimsStat, 2936 currSigDims, 2937 currSigDimsSize, 2938 maxRows, 2939 decimation, 2940 sampleTime, 2941 appendToLogVarsList); 2942 2943 } /* end rt_CreateLogVar */ 2944 2945 2946 #ifdef __cplusplus 2947 } 2948 #endif 2949 2950 2951 2952 2953 #ifdef __cplusplus 2954 extern "C" { 2955 #endif 2956 2957 2958 /* Function: rt_CreateStructLogVar ============================================= 2959 * Abstract: 2960 * Create a logging variable in the structure format. 2961 * 2962 * Returns: 2963 * ~= NULL => success, returns the log variable created. 2964 * == NULL => failure, error message set in the simstruct. 2965 */ 2966 StructLogVar *rt_CreateStructLogVar(RTWLogInfo *li, 2967 const real_T startTime, 2968 const real_T finalTime, 2969 const real_T inStepSize, 2970 const char_T **errStatus, 2971 const char_T *varName, 2972 boolean_T logTime, 2973 int_T maxRows, 2974 int_T decimation, 2975 real_T sampleTime, 2976 const RTWLogSignalInfo *sigInfo, 2977 const char_T *blockName) 2978 { 2979 2980 return( local_CreateStructLogVar(li, 2981 startTime, 2982 finalTime, 2983 inStepSize, 2984 errStatus, 2985 varName, 2986 logTime, 2987 maxRows, 2988 decimation, 2989 sampleTime, 2990 sigInfo, 2991 blockName)); 2992 2993 } /* end rt_CreateStructLogVar */ 2994 2995 2996 #ifdef __cplusplus 2997 } 2998 #endif 2999 3000 3001 3002 3003 #ifdef __cplusplus 3004 extern "C" { 3005 #endif 3006 3007 3008 /* Function: rt_StartDataLoggingWithStartTime ================================== 3009 * Abstract: 3010 * Initialize data logging info based upon the following settings cached 3011 * in the RTWLogging data structure of the SimStruct. 3012 * 3013 * Return value is: 3014 * == NULL => success 3015 * != NULL => failure (the return value is a pointer that points to the 3016 * error message, which is also set in the simstruct) 3017 */ 3018 const char_T *rt_StartDataLoggingWithStartTime(RTWLogInfo *li, 3019 const real_T startTime, 3020 const real_T finalTime, 3021 const real_T stepSize, 3022 const char_T **errStatus) 3023 { 3024 const char_T *varName; 3025 LogInfo *logInfo; 3026 real_T sampleTime = stepSize; 3027 int_T maxRows = rtliGetLogMaxRows(li); 3028 int_T decimation = rtliGetLogDecimation(li); 3029 int_T logFormat = rtliGetLogFormat(li); 3030 boolean_T logTime = (logFormat==2) ? 1 : 0; 3031 3032 /* reset error status */ 3033 *errStatus = NULL; 3034 3035 if ((logInfo=calloc(1,sizeof(LogInfo))) == NULL) { 3036 *errStatus = rtMemAllocError; 3037 goto ERROR_EXIT; 3038 } 3039 rtliSetLogInfo(li, (void*)logInfo); 3040 3041 /* time */ 3042 varName = rtliGetLogT(li); 3043 if (varName[0] != '\0') { 3044 int_T dims = 1; 3045 logInfo->t = rt_CreateLogVarWithConvert(li, startTime, finalTime, 3046 stepSize, errStatus, 3047 varName,SS_DOUBLE, 3048 NULL, 3049 0,0,0,1,1, 3050 &dims, NO_LOGVALDIMS, NULL, NULL, 3051 maxRows,decimation, 3052 sampleTime,1); 3053 if (logInfo->t == NULL) goto ERROR_EXIT; 3054 } 3055 3056 /* states */ 3057 if ( rtliGetLogX(li)[0] != '\0' || rtliGetLogXFinal(li)[0] != '\0' ) { 3058 const RTWLogSignalInfo *xInfo = rtliGetLogXSignalInfo(li); 3059 3060 if (logFormat == 0) { /* Matrix Format */ 3061 int numCols; 3062 int nDims; 3063 const int *dims; 3064 BuiltInDTypeId dataType; 3065 int isComplex; 3066 int_T sIdx; 3067 3068 const RTWLogDataTypeConvert *pDTConvInfo; 3069 3070 numCols = xInfo[0].numCols[0]; 3071 for (sIdx = 1; sIdx < xInfo[0].numSignals; sIdx++) { 3072 numCols += xInfo[0].numCols[sIdx]; 3073 } 3074 /* If we have only one "matrix" state, we can log as a matrix */ 3075 if (xInfo[0].numSignals == 1) { 3076 nDims = xInfo[0].numDims[0]; 3077 dims = xInfo[0].dims; 3078 } else { 3079 nDims = 1; 3080 dims = &numCols; 3081 } 3082 dataType = xInfo[0].dataTypes[0]; 3083 isComplex = xInfo[0].complexSignals[0]; 3084 3085 pDTConvInfo = xInfo[0].dataTypeConvert; 3086 3087 if (rtliGetLogX(li)[0] != '\0') { 3088 logInfo->x = rt_CreateLogVarWithConvert(li, startTime, finalTime, 3089 stepSize, errStatus, 3090 rtliGetLogX(li),dataType, 3091 pDTConvInfo, 3092 0, 3093 isComplex,0,numCols,nDims,dims, 3094 NO_LOGVALDIMS, NULL, NULL, 3095 maxRows,decimation,sampleTime,1); 3096 if (logInfo->x == NULL) goto ERROR_EXIT; 3097 } 3098 if (rtliGetLogXFinal(li)[0] != '\0') { 3099 logInfo->xFinal = rt_CreateLogVarWithConvert(li, startTime, finalTime, 3100 stepSize, errStatus, 3101 rtliGetLogXFinal(li),dataType, 3102 pDTConvInfo, 3103 0,isComplex,0,numCols,nDims, 3104 dims, NO_LOGVALDIMS, NULL, 3105 NULL, 1,decimation, 3106 sampleTime,1); 3107 if (logInfo->xFinal == NULL) goto ERROR_EXIT; 3108 } 3109 } else { /* Structure Format */ 3110 if (rtliGetLogX(li)[0] != '\0') { 3111 logInfo->x = local_CreateStructLogVar(li, startTime, finalTime, 3112 stepSize, errStatus, 3113 rtliGetLogX(li), logTime, 3114 maxRows, decimation, 3115 sampleTime, xInfo, NULL); 3116 if (logInfo->x == NULL) goto ERROR_EXIT; 3117 } 3118 if (rtliGetLogXFinal(li)[0] != '\0') { 3119 logInfo->xFinal = local_CreateStructLogVar(li, startTime, finalTime, 3120 stepSize, errStatus, 3121 rtliGetLogXFinal(li), 3122 logTime,1,decimation, 3123 sampleTime,xInfo,NULL); 3124 if (logInfo->xFinal == NULL) goto ERROR_EXIT; 3125 } 3126 } 3127 } 3128 3129 /* signal logging */ 3130 if ( rtliGetSigLog(li)[0] != '\0' ) { 3131 const RTWLogSignalInfo *slInfo = rtliGetSigLogSignalInfo(li); 3132 3133 /* log using structure format */ 3134 logInfo->sl = local_CreateStructLogVar(li, startTime, finalTime, 3135 stepSize, errStatus, 3136 rtliGetSigLog(li), logTime, 3137 maxRows, decimation, 3138 sampleTime, slInfo, NULL); 3139 if (logInfo->sl == NULL) goto ERROR_EXIT; 3140 } 3141 3142 /* outputs */ 3143 *errStatus = rt_StartDataLoggingForOutput(li,startTime,finalTime, 3144 stepSize,errStatus); 3145 if (*errStatus != NULL) goto ERROR_EXIT; 3146 3147 return(NULL); /* NORMAL_EXIT */ 3148 3149 ERROR_EXIT: 3150 (void)fprintf(stderr, "*** Errors occurred when starting data logging.\n"); 3151 if (*errStatus == NULL) { 3152 *errStatus = rtMemAllocError; 3153 } 3154 if (logInfo) { 3155 rt_DestroyLogVar(logInfo->logVarsList); 3156 logInfo->logVarsList = NULL; 3157 rt_DestroyStructLogVar(logInfo->structLogVarsList); 3158 logInfo->structLogVarsList = NULL; 3159 } 3160 return(*errStatus); 3161 3162 } /* end rt_StartDataLoggingWithStartTime */ 3163 3164 3165 #ifdef __cplusplus 3166 } 3167 #endif 3168 3169 3170 3171 3172 #ifdef __cplusplus 3173 extern "C" { 3174 #endif 3175 3176 3177 /* Function: rt_StartDataLogging =============================================== 3178 * Abstract: 3179 */ 3180 const char_T *rt_StartDataLogging(RTWLogInfo *li, 3181 const real_T finalTime, 3182 const real_T stepSize, 3183 const char_T **errStatus) 3184 { 3185 return rt_StartDataLoggingWithStartTime(li, 3186 0.0, 3187 finalTime, 3188 stepSize, 3189 errStatus); 3190 } 3191 3192 3193 #ifdef __cplusplus 3194 } 3195 #endif 3196 3197 3198 3199 3200 #ifdef __cplusplus 3201 extern "C" { 3202 #endif 3203 3204 3205 /* Function: rt_UpdateLogVar =================================================== 3206 * Abstract: 3207 * Called to log data for a log variable. 3208 */ 3209 void rt_UpdateLogVar(LogVar *var, const void *data, boolean_T isVarDims) 3210 { 3211 size_t elSize = var->data.elSize; 3212 const char_T *cData = data; 3213 const int_T frameData = var->data.frameData; 3214 const int_T frameSize = frameData ? (var->data.frameSize) : 1; 3215 const int_T logWidth = var->data.nCols; 3216 BuiltInDTypeId dTypeID = var->data.dTypeID; 3217 3218 int_T offset = 0; 3219 char_T *currRealRow = NULL; 3220 char_T *currImagRow = NULL; 3221 int_T pointSize = (int_T)((var->data.complex) ? rt_GetSizeofComplexType(dTypeID) : elSize); 3222 3223 int i, j, k; 3224 3225 /* The following variables will be used for 3226 logging variable-size signals */ 3227 const int_T nDims = var->data.nDims; 3228 const int_T *dims = var->data.dims; 3229 const void * const *currDimsPtr = NULL; 3230 const int_T *currDimsSizePtr = NULL; 3231 3232 /* The following variables will be used for 3233 logging "valueDimensions" field */ 3234 int_T offset_valDims = 0; 3235 char_T *currValDimsRow = NULL; 3236 size_t elSize_valDims = sizeof(real_T); 3237 real_T currentSigDims = 0; 3238 int_T nRows_valDims = 0; 3239 int_T logWidth_valDims = 0; 3240 3241 for (i = 0; i < frameSize; i++) { 3242 if (++var->numHits % var->decimation) continue; 3243 var->numHits = 0; 3244 3245 if (var->rowIdx == var->data.nRows) { 3246 if (var->okayToRealloc == 1) { 3247 rt_ReallocLogVar(var, isVarDims); 3248 } else { 3249 /* Circular buffer */ 3250 var->rowIdx = 0; 3251 ++(var->wrapped); /* increment the wrap around counter */ 3252 } 3253 } 3254 3255 if(isVarDims){ 3256 currDimsPtr = (const void * const *) var->valDims->currSigDims; 3257 currDimsSizePtr = (const int_T*) var->valDims->currSigDimsSize; 3258 logWidth_valDims = frameData ? 1 : var->valDims->nCols; 3259 nRows_valDims = var->valDims->nRows; 3260 3261 var->strides[0] = 1; 3262 var->currStrides[0] = 1; 3263 3264 for (k = 1; k < nDims; k++){ 3265 int32_T currDimsVal=0; 3266 switch (currDimsSizePtr[k-1]) { 3267 case 1: 3268 currDimsVal = (**(((const uint8_T * const *) currDimsPtr)+(k-1))); 3269 break; 3270 case 2: 3271 currDimsVal = (**(((const uint16_T * const *) currDimsPtr)+(k-1))); 3272 break; 3273 case 4: 3274 currDimsVal = (**(((const uint32_T * const *) currDimsPtr)+(k-1))); 3275 break; 3276 } 3277 var->strides[k] = var->strides[k-1] * dims[k-1]; 3278 var->currStrides[k] = var->currStrides[k-1] * currDimsVal; 3279 } 3280 } 3281 3282 offset = (int_T)(elSize * var->rowIdx * logWidth); 3283 currRealRow = ((char_T*) (var->data.re)) + offset; 3284 currImagRow = (var->data.complex) ? 3285 ((char_T*) (var->data.im)) + offset : NULL; 3286 3287 /* update logging data */ 3288 for (j = 0; j < logWidth; j++) { 3289 3290 boolean_T inRange = true; 3291 int idx = j; 3292 3293 /* Check whether the currently logged value is in range or not. 3294 For fixed-size signal logging, always inRange = true; idx = j; 3295 For variable-size signal logging, use strides, coordinates 3296 and current strides to decide whether the currently logged 3297 data is in range or not and its location in the logging 3298 matrix. 3299 */ 3300 if(isVarDims){ 3301 int rem = j; 3302 idx = 0; 3303 for(k = nDims-1; k>=0; k--){ 3304 int32_T currDimsVal=0; 3305 switch (currDimsSizePtr[k]) { 3306 case 1: 3307 currDimsVal = (**(((const uint8_T * const *) currDimsPtr)+k)); 3308 break; 3309 case 2: 3310 currDimsVal = (**(((const uint16_T * const *) currDimsPtr)+k)); 3311 break; 3312 case 4: 3313 currDimsVal = (**(((const uint32_T * const *) currDimsPtr)+k)); 3314 break; 3315 } 3316 var->coords[k] = rem / var->strides[k]; 3317 if( var->coords[k] >= currDimsVal ){ 3318 inRange = false; 3319 break; 3320 } 3321 rem = rem - var->coords[k] * var->strides[k]; 3322 } 3323 if(inRange){ 3324 idx = var->coords[0]; 3325 for (k = 1; k < nDims; k++){ 3326 idx += var->coords[k] * var->currStrides[k]; 3327 } 3328 } 3329 } 3330 3331 if (!var->data.dataTypeConvertInfo.conversionNeeded) { 3332 /* NO conversion needed 3333 */ 3334 if (inRange) { 3335 /* If in range, fill in data */ 3336 const char *cDataPoint = cData + (i+frameSize*idx) * pointSize; 3337 3338 (void) memcpy(currRealRow, cDataPoint, elSize); 3339 currRealRow += elSize; 3340 if (var->data.complex) { 3341 (void) memcpy(currImagRow, cDataPoint + pointSize/2, elSize); 3342 currImagRow += elSize; 3343 } 3344 } else { 3345 /* If out of range, fill in NaN or 0: 3346 1) For bool, int32, uint32, int16, uint16, etc, 3347 memset to zeros; 3348 2) For fixed-point data type, NaN conversion is not 3349 allowed, memset to zeros. 3350 */ 3351 if (dTypeID == SS_DOUBLE) { 3352 (void) memcpy(currRealRow, &rtNaN, elSize); 3353 } else if (dTypeID == SS_SINGLE){ 3354 (void) memcpy(currRealRow, &rtNaNF, elSize); 3355 } else { 3356 (void) memset(currRealRow, 0, elSize); 3357 } 3358 3359 currRealRow += elSize; 3360 if (var->data.complex) { 3361 /* For imaginary part, fill in 0 */ 3362 (void) memset(currImagRow, 0, elSize); 3363 currImagRow += elSize; 3364 } 3365 } 3366 } 3367 else 3368 { 3369 /* YES conversion needed 3370 */ 3371 DTypeId dataTypeIdOriginal = 3372 var->data.dataTypeConvertInfo.dataTypeIdOriginal; 3373 int_T DpSize = (int_T)((var->data.complex) ? 3374 rt_GetSizeofComplexType(dataTypeIdOriginal) : 3375 rt_GetSizeofDataType(dataTypeIdOriginal)); 3376 3377 DTypeId dataTypeIdLoggingTo = 3378 var->data.dataTypeConvertInfo.dataTypeIdLoggingTo; 3379 3380 int bitsPerChunk = var->data.dataTypeConvertInfo.bitsPerChunk; 3381 int numOfChunk = var->data.dataTypeConvertInfo.numOfChunk; 3382 unsigned int isSigned = var->data.dataTypeConvertInfo.isSigned; 3383 3384 double fracSlope = var->data.dataTypeConvertInfo.fracSlope; 3385 int fixedExp = var->data.dataTypeConvertInfo.fixedExp; 3386 double bias = var->data.dataTypeConvertInfo.bias; 3387 3388 double curRealValue = -0.12345678987654; 3389 double curImagValue = -0.12345678987654; 3390 3391 int_T adjIndexIfComplex = (var->data.complex) ? 2 : 1; 3392 3393 if(inRange){ 3394 if(numOfChunk > 1) 3395 { 3396 /* For multiword */ 3397 const char *pInData = (const char *)(cData); 3398 int dtSize = bitsPerChunk*numOfChunk/8; 3399 pInData += ((i+frameSize*idx) * adjIndexIfComplex) * dtSize; 3400 3401 curRealValue = rt_GetDblValueFromOverSizedData(pInData, bitsPerChunk, numOfChunk, 3402 isSigned, fracSlope, fixedExp, bias); 3403 if (var->data.complex) { 3404 curImagValue = rt_GetDblValueFromOverSizedData((pInData+dtSize), bitsPerChunk, numOfChunk, 3405 isSigned, fracSlope, fixedExp, bias); 3406 } 3407 } 3408 else 3409 { 3410 /* if in range, fill in data that is converted first */ 3411 switch ( dataTypeIdOriginal ) 3412 { 3413 case SS_DOUBLE: 3414 { 3415 const real_T *pInData = (const real_T *)(cData + (i+frameSize*idx)* DpSize); 3416 3417 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3418 if (var->data.complex) { 3419 pInData = (const real_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3420 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3421 } 3422 } 3423 break; 3424 case SS_SINGLE: 3425 { 3426 const real32_T *pInData = (const real32_T *)(cData + (i+frameSize*idx)* DpSize); 3427 3428 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3429 if (var->data.complex) { 3430 pInData = (const real32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3431 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3432 } 3433 } 3434 break; 3435 case SS_INT8: 3436 { 3437 const int8_T *pInData = (const int8_T *)(cData + (i+frameSize*idx)* DpSize); 3438 3439 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3440 if (var->data.complex) { 3441 pInData = (const int8_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3442 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3443 } 3444 } 3445 break; 3446 case SS_UINT8: 3447 { 3448 const uint8_T *pInData = (const uint8_T *)(cData + (i+frameSize*idx)* DpSize); 3449 3450 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3451 if (var->data.complex) { 3452 pInData = (const uint8_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3453 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3454 } 3455 } 3456 break; 3457 case SS_INT16: 3458 { 3459 const int16_T *pInData = (const int16_T *)(cData + (i+frameSize*idx)* DpSize); 3460 3461 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3462 if (var->data.complex) { 3463 pInData = (const int16_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3464 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3465 } 3466 } 3467 break; 3468 case SS_UINT16: 3469 { 3470 const uint16_T *pInData = (const uint16_T *)(cData + (i+frameSize*idx)* DpSize); 3471 3472 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3473 if (var->data.complex) { 3474 pInData = (const uint16_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3475 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3476 } 3477 } 3478 break; 3479 case SS_INT32: 3480 { 3481 const int32_T *pInData = (const int32_T *)(cData + (i+frameSize*idx)* DpSize); 3482 3483 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3484 if (var->data.complex) { 3485 pInData = (const int32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3486 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3487 } 3488 } 3489 break; 3490 case SS_UINT32: 3491 { 3492 const uint32_T *pInData = (const uint32_T *)(cData + (i+frameSize*idx)* DpSize); 3493 3494 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3495 if (var->data.complex) { 3496 pInData = (const uint32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3497 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3498 } 3499 } 3500 break; 3501 case SS_BOOLEAN: 3502 { 3503 const boolean_T *pInData = ((const boolean_T *)(cData)); 3504 3505 pInData += (i+frameSize*idx) * adjIndexIfComplex; 3506 3507 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3508 if (var->data.complex) { 3509 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3510 } 3511 } 3512 break; 3513 default: 3514 { 3515 /* For biglong */ 3516 const char *pInData = (const char *)(cData); 3517 int dtSize = bitsPerChunk*numOfChunk/8; 3518 pInData += ((i+frameSize*idx) * adjIndexIfComplex) * dtSize; 3519 3520 curRealValue = rt_GetDblValueFromOverSizedData(pInData, bitsPerChunk, numOfChunk, 3521 isSigned, fracSlope, fixedExp, bias); 3522 if (var->data.complex) { 3523 curImagValue = rt_GetDblValueFromOverSizedData((pInData+dtSize), bitsPerChunk, numOfChunk, 3524 isSigned, fracSlope, fixedExp, bias); 3525 } 3526 } 3527 break; 3528 } /* -- end of switch -- */ 3529 } 3530 } else { 3531 /* if out of range, just fill NaN or 0 */ 3532 if(dTypeID == SS_DOUBLE || dTypeID == SS_SINGLE){ 3533 curRealValue = ldexp( rtNaN, fixedExp ) + bias; 3534 } 3535 else{ 3536 curRealValue = ldexp( 0, fixedExp ) + bias; 3537 } 3538 if (var->data.complex) { 3539 /* fill 0 in imaginary part*/ 3540 curImagValue = ldexp( 0, fixedExp ) + bias; 3541 } 3542 } 3543 3544 switch ( dataTypeIdLoggingTo ) 3545 { 3546 case SS_DOUBLE: 3547 { 3548 *((real_T *)currRealRow) = (real_T)curRealValue; 3549 3550 if (var->data.complex) { 3551 3552 *((real_T *)currImagRow) = (real_T)curImagValue; 3553 } 3554 } 3555 break; 3556 case SS_SINGLE: 3557 { 3558 *((real32_T *)currRealRow) = (real32_T)curRealValue; 3559 3560 if (var->data.complex) { 3561 3562 *((real32_T *)currImagRow) = (real32_T)curImagValue; 3563 } 3564 } 3565 break; 3566 case SS_INT8: 3567 { 3568 *((int8_T *)currRealRow) = (int8_T)curRealValue; 3569 3570 if (var->data.complex) { 3571 3572 *((int8_T *)currImagRow) = (int8_T)curImagValue; 3573 } 3574 } 3575 break; 3576 case SS_UINT8: 3577 { 3578 *((uint8_T *)currRealRow) = (uint8_T)curRealValue; 3579 3580 if (var->data.complex) { 3581 3582 *((uint8_T *)currImagRow) = (uint8_T)curImagValue; 3583 } 3584 } 3585 break; 3586 case SS_INT16: 3587 { 3588 *((int16_T *)currRealRow) = (int16_T)curRealValue; 3589 3590 if (var->data.complex) { 3591 3592 *((int16_T *)currImagRow) = (int16_T)curImagValue; 3593 } 3594 } 3595 break; 3596 case SS_UINT16: 3597 { 3598 *((uint16_T *)currRealRow) = (uint16_T)curRealValue; 3599 3600 if (var->data.complex) { 3601 3602 *((uint16_T *)currImagRow) = (uint16_T)curImagValue; 3603 } 3604 } 3605 break; 3606 case SS_INT32: 3607 { 3608 *((int32_T *)currRealRow) = (int32_T)curRealValue; 3609 3610 if (var->data.complex) { 3611 3612 *((int32_T *)currImagRow) = (int32_T)curImagValue; 3613 } 3614 } 3615 break; 3616 case SS_UINT32: 3617 { 3618 *((uint32_T *)currRealRow) = (uint32_T)curRealValue; 3619 3620 if (var->data.complex) { 3621 3622 *((uint32_T *)currImagRow) = (uint32_T)curImagValue; 3623 } 3624 } 3625 break; 3626 case SS_BOOLEAN: 3627 { 3628 *((boolean_T *)currRealRow) = (boolean_T)(curRealValue != 0.0); 3629 3630 if (var->data.complex) { 3631 3632 *((boolean_T *)currImagRow) = (boolean_T)(curImagValue != 0.0); 3633 } 3634 } 3635 break; 3636 } /* -- end of switch -- */ 3637 3638 currRealRow += elSize; 3639 if (var->data.complex) { 3640 currImagRow += elSize; 3641 } 3642 } 3643 } 3644 3645 if(isVarDims){ /* update "valueDimensions" field */ 3646 for(j = 0; j < logWidth_valDims; j ++){ 3647 int32_T currDimsVal=0; 3648 switch (currDimsSizePtr[j]) { 3649 case 1: 3650 currDimsVal = (**(((const uint8_T * const *) currDimsPtr)+j)); 3651 break; 3652 case 2: 3653 currDimsVal = (**(((const uint16_T * const *) currDimsPtr)+j)); 3654 break; 3655 case 4: 3656 currDimsVal = (**(((const uint32_T * const *) currDimsPtr)+j)); 3657 break; 3658 } 3659 offset_valDims = (int_T)(elSize_valDims *( var->rowIdx + nRows_valDims * j)); 3660 currValDimsRow = ((char_T*) (var->valDims->dimsData)) + offset_valDims; 3661 3662 /* convert int_T to real_T */ 3663 currentSigDims = (real_T) currDimsVal; 3664 (void) memcpy(currValDimsRow, ¤tSigDims, elSize_valDims); 3665 currValDimsRow += elSize_valDims; 3666 } 3667 } 3668 3669 ++var->rowIdx; 3670 } 3671 3672 return; 3673 3674 } /* end rt_UpdateLogVar */ 3675 3676 3677 #ifdef __cplusplus 3678 } 3679 #endif 3680 3681 3682 3683 3684 #ifdef __cplusplus 3685 extern "C" { 3686 #endif 3687 3688 3689 /* Function: rt_UpdateStructLogVar ============================================= 3690 * Abstract: 3691 * Called to log data for a structure log variable. 3692 */ 3693 void rt_UpdateStructLogVar(StructLogVar *var, const real_T *t, const void *data) 3694 { 3695 LogVar *values = var->signals.values; 3696 const char_T *signal = data; 3697 boolean_T *isVarDims = var->signals.isVarDims; 3698 int i = 0; 3699 3700 /* time */ 3701 if (var->logTime) { 3702 rt_UpdateLogVar(var->time, t, false); 3703 } 3704 3705 /* signals */ 3706 while (values) { 3707 size_t elSz = values->data.elSize; 3708 3709 rt_UpdateLogVar(values, signal, isVarDims[i]); 3710 3711 if (values->data.complex) elSz *= 2; 3712 signal += elSz * values->data.nCols; 3713 3714 values = values->next; 3715 i++; 3716 } 3717 3718 } /* end rt_UpdateStructLogVar */ 3719 3720 3721 #ifdef __cplusplus 3722 } 3723 #endif 3724 3725 3726 3727 3728 #ifdef __cplusplus 3729 extern "C" { 3730 #endif 3731 3732 3733 /* Function: rt_UpdateTXYLogVars =============================================== 3734 * Abstract: 3735 * Update the T,X,Y variables that are being logged. 3736 */ 3737 const char_T *rt_UpdateTXYLogVars(RTWLogInfo *li, time_T *tPtr) 3738 { 3739 LogInfo *logInfo = rtliGetLogInfo(li); 3740 int_T matrixFormat = (rtliGetLogFormat(li) == 0); 3741 3742 /* time */ 3743 if (logInfo->t != NULL) { 3744 rt_UpdateLogVar(logInfo->t, tPtr, false); 3745 } 3746 3747 if (matrixFormat) { /* MATRIX_FORMAT */ 3748 /* states */ 3749 if (logInfo->x != NULL || logInfo->xFinal != NULL) { 3750 const RTWLogSignalInfo *xInfo = rtliGetLogXSignalInfo(li); 3751 LogSignalPtrsType segAddr = rtliGetLogXSignalPtrs(li); 3752 const int_T *segLengths = xInfo->numCols; 3753 int_T nSegments = xInfo->numSignals; 3754 if (logInfo->x != NULL) { 3755 rt_UpdateLogVarWithDiscontiguousData(logInfo->x, segAddr, 3756 segLengths, nSegments); 3757 } 3758 if (logInfo->xFinal != NULL) { 3759 rt_UpdateLogVarWithDiscontiguousData(logInfo->xFinal, segAddr, 3760 segLengths, nSegments); 3761 } 3762 } 3763 /* outputs */ 3764 if (logInfo->y != NULL) { 3765 LogVar **var = (LogVar**) (logInfo->y); 3766 int_T ny = logInfo->ny; 3767 int_T i; 3768 int yIdx; 3769 LogSignalPtrsType data = rtliGetLogYSignalPtrs(li); 3770 3771 for (i = 0, yIdx = 0; i < ny; i++) { 3772 if (data[i] != NULL) { 3773 /* 3774 When outputs are logged in Matrix format, 3775 no variable-size signal logging is allowed. 3776 */ 3777 rt_UpdateLogVar(var[yIdx++], data[i], false); 3778 } 3779 } 3780 } 3781 } else { /* STRUCTURE_FORMAT */ 3782 /* states */ 3783 if (logInfo->x != NULL) { 3784 int_T i; 3785 StructLogVar *var = logInfo->x; 3786 LogVar *val = var->signals.values; 3787 int_T nsig = var->signals.numSignals; 3788 LogSignalPtrsType data = rtliGetLogXSignalPtrs(li); 3789 3790 /* time */ 3791 if (var->logTime) { 3792 rt_UpdateLogVar(var->time, tPtr, false); 3793 } 3794 3795 /* signals */ 3796 for (i = 0; i < nsig; i++) { 3797 rt_UpdateLogVar(val, data[i], false); 3798 val = val->next; 3799 } 3800 } 3801 3802 /* outputs */ 3803 if (logInfo->y != NULL) { 3804 int_T ny = logInfo->ny; 3805 LogSignalPtrsType data = rtliGetLogYSignalPtrs(li); 3806 StructLogVar **var = (StructLogVar**) (logInfo->y); 3807 3808 if (ny == 1) { 3809 int_T i; 3810 int_T dataIdx; 3811 LogVar *val = var[0]->signals.values; 3812 int_T nsig = var[0]->signals.numSignals; 3813 boolean_T *isVarDims = var[0]->signals.isVarDims; 3814 3815 /* time */ 3816 if (var[0]->logTime) { 3817 rt_UpdateLogVar(var[0]->time, tPtr, false); 3818 } 3819 3820 /* signals */ 3821 for (i = 0, dataIdx = 0; i < nsig; i++) { 3822 while (data[dataIdx] == NULL) { 3823 ++dataIdx; 3824 } 3825 rt_UpdateLogVar(val, data[dataIdx], isVarDims[i]); 3826 val = val->next; 3827 ++dataIdx; 3828 } 3829 } else { 3830 int_T i; 3831 int_T dataIdx; 3832 3833 for (i = 0, dataIdx = 0; i < ny && var[i] != NULL; i++) { 3834 LogVar *val = var[i]->signals.values; 3835 boolean_T *isVarDims = var[i]->signals.isVarDims; 3836 3837 /* time */ 3838 if (var[i]->logTime) { 3839 rt_UpdateLogVar(var[i]->time, tPtr, false); 3840 } 3841 3842 /* signals */ 3843 while (data[dataIdx] == NULL) { 3844 ++dataIdx; 3845 } 3846 rt_UpdateLogVar(val, data[dataIdx], isVarDims[0]); 3847 val = val->next; 3848 ++dataIdx; 3849 } 3850 } 3851 } 3852 /* final state */ 3853 if (logInfo->xFinal != NULL) { 3854 StructLogVar *xf = logInfo->xFinal; 3855 LogVar *val = xf->signals.values; 3856 int_T nsig = xf->signals.numSignals; 3857 int_T i; 3858 3859 /* time */ 3860 if (xf->logTime) { 3861 rt_UpdateLogVar(xf->time, tPtr, false); 3862 } 3863 3864 /* signals */ 3865 for (i = 0; i < nsig; i++) { 3866 LogSignalPtrsType data = rtliGetLogXSignalPtrs(li); 3867 3868 rt_UpdateLogVar(val, data[i], false); 3869 val = val->next; 3870 } 3871 } 3872 } 3873 return(NULL); 3874 3875 } /* end rt_UpdateTXYLogVars */ 3876 3877 3878 #ifdef __cplusplus 3879 } 3880 #endif 3881 3882 3883 3884 3885 #ifdef __cplusplus 3886 extern "C" { 3887 #endif 3888 3889 3890 /* Function: rt_UpdateSigLogVars =============================================== 3891 * Abstract: 3892 * Update the Signal Logging testpoint variables that are being logged. 3893 * 3894 */ 3895 void rt_UpdateSigLogVars(RTWLogInfo *li, time_T *tPtr) 3896 { 3897 LogInfo *logInfo = rtliGetLogInfo(li); 3898 3899 if (logInfo->sl != NULL) { 3900 int_T i; 3901 StructLogVar *var = logInfo->sl; 3902 LogVar *val = var->signals.values; 3903 int_T nsig = var->signals.numSignals; 3904 LogSignalPtrsType data = rtliGetSigLogSignalPtrs(li); 3905 3906 /* time */ 3907 if (var->logTime) { 3908 rt_UpdateLogVar(var->time, tPtr, false); 3909 } 3910 3911 /* signals */ 3912 for (i = 0; i < nsig; i++) { 3913 /* currently, SigLog doesn't support variable-size signals */ 3914 rt_UpdateLogVar(val, data[i], false); 3915 val = val->next; 3916 } 3917 } 3918 3919 } /* end rt_UpdateSigLogVars */ 3920 3921 3922 #ifdef __cplusplus 3923 } 3924 #endif 3925 3926 3927 3928 3929 #ifdef __cplusplus 3930 extern "C" { 3931 #endif 3932 3933 3934 /* Function: rt_StopDataLoggingForRaccel ======================================= 3935 * Abstract: 3936 * Write logged data to model.mat and free memory. 3937 */ 3938 void rt_StopDataLoggingForRaccel(const char_T *file, RTWLogInfo *li, int verbose) 3939 { 3940 FILE *fptr; 3941 LogInfo *logInfo = (LogInfo*) rtliGetLogInfo(li); 3942 LogVar *var = logInfo->logVarsList; 3943 StructLogVar *svar = logInfo->structLogVarsList; 3944 3945 boolean_T emptyFile = 1; /* assume */ 3946 boolean_T errFlag = 0; 3947 const char_T *msg; 3948 3949 /******************************* 3950 * Create MAT file with header * 3951 *******************************/ 3952 if ((fptr=fopen(file,"w+b")) == NULL) { 3953 (void)fprintf(stderr,"*** Error opening %s",file); 3954 goto EXIT_POINT; 3955 } 3956 if (rt_WriteMat5FileHeader(fptr)) { 3957 (void)fprintf(stderr,"*** Error writing to %s",file); 3958 goto EXIT_POINT; 3959 } 3960 3961 /************************************************** 3962 * First log all the variables in the LogVar list * 3963 **************************************************/ 3964 while (var != NULL) { 3965 if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) { 3966 (void)fprintf(stderr,"*** Error writing %s due to: %s\n",file,msg); 3967 errFlag = 1; 3968 break; 3969 } 3970 if (var->nDataPoints > 0) { 3971 MatItem item; 3972 3973 item.type = matMATRIX; 3974 item.nbytes = 0; /* not yet known */ 3975 item.data = &(var->data); 3976 if (rt_WriteItemToMatFile(fptr, &item, MATRIX_ITEM)) { 3977 (void)fprintf(stderr,"*** Error writing log variable %s to " 3978 "file %s",var->data.name, file); 3979 errFlag = 1; 3980 break; 3981 } 3982 emptyFile = 0; 3983 } 3984 var = var->next; 3985 } 3986 /* free up some memory by destroying the log var list here */ 3987 rt_DestroyLogVar(logInfo->logVarsList); 3988 logInfo->logVarsList = NULL; 3989 3990 /******************************************************* 3991 * Next log all the variables in the StrcutLogVar list * 3992 *******************************************************/ 3993 while (svar != NULL) { 3994 MatItem item; 3995 3996 if (svar->logTime) { 3997 var = svar->time; 3998 if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) { 3999 (void)fprintf(stderr, "*** Error writing %s due to: %s\n", 4000 file, msg); 4001 errFlag = 1; 4002 break; 4003 } 4004 } 4005 4006 var = svar->signals.values; 4007 while (var) { 4008 if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) { 4009 (void)fprintf(stderr, "*** Error writing %s due to: %s\n", 4010 file, msg); 4011 errFlag = 1; 4012 break; 4013 } 4014 var = var->next; 4015 } 4016 4017 item.type = matMATRIX; 4018 item.nbytes = 0; /* not yet known */ 4019 item.data = svar; 4020 4021 if (rt_WriteItemToMatFile(fptr, &item, STRUCT_LOG_VAR_ITEM)) { 4022 (void)fprintf(stderr,"*** Error writing structure log variable " 4023 "%s to file %s",svar->name, file); 4024 errFlag = 1; 4025 break; 4026 } 4027 emptyFile = 0; 4028 4029 svar = svar->next; 4030 } 4031 4032 /****************** 4033 * Close the file * 4034 ******************/ 4035 (void)fclose(fptr); 4036 if (emptyFile || errFlag) { 4037 (void)remove(file); 4038 } else { 4039 if( verbose ) { 4040 (void)printf("** created %s **\n\n", file); 4041 } 4042 } 4043 4044 EXIT_POINT: 4045 4046 /**************** 4047 * free logInfo * 4048 ****************/ 4049 rt_DestroyLogVar(logInfo->logVarsList); 4050 logInfo->logVarsList = NULL; 4051 rt_DestroyStructLogVar(logInfo->structLogVarsList); 4052 logInfo->structLogVarsList = NULL; 4053 FREE(logInfo); 4054 rtliSetLogInfo(li,NULL); 4055 4056 } /* end rt_StopDataLoggingForRaccel */ 4057 4058 4059 #ifdef __cplusplus 4060 } 4061 #endif 4062 4063 4064 4065 4066 #ifdef __cplusplus 4067 extern "C" { 4068 #endif 4069 4070 4071 /* Function: rt_StopDataLogging ================================================ 4072 * Abstract: 4073 * Write logged data to model.mat and free memory. 4074 */ 4075 void rt_StopDataLogging(const char_T *file, RTWLogInfo *li) 4076 { 4077 rt_StopDataLoggingForRaccel(file,li,1); 4078 4079 } /* end rt_StopDataLogging */ 4080 4081 4082 #ifdef __cplusplus 4083 } 4084 #endif 4085 4086 #else /*!defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1)*/ 4087 4088 #define rt_StartDataLogging(li, finalTime, stepSize, errStatus) NULL /* do nothing */ 4089 #define rt_UpdateTXYLogVars(li, tPtr) NULL /* do nothing */ 4090 #define rt_UpdateSigLogVars(li, tPtr); /* do nothing */ 4091 #define rt_StopDataLogging(file, li); /* do nothing */ 4092 4093 #endif /*!defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1)*/ 4094 4095 4096 4097 /* [eof] rt_logging.c */ 4098 |