38
+ − 1 /**
+ − 2 ******************************************************************************
+ − 3 * @copyright heinrichs weikamp
+ − 4 * @file logbook_miniLive.c
+ − 5 * @author heinrichs weikamp gmbh
+ − 6 * @date 13-March-2015
+ − 7 * @version V0.0.1
+ − 8 * @since 13-March-2015
+ − 9 * @brief little logbook for during the dive
+ − 10 * @bug
+ − 11 * @warning
+ − 12 ******************************************************************************
+ − 13 * @attention
+ − 14 *
+ − 15 * <h2><center>© COPYRIGHT(c) 2015 heinrichs weikamp</center></h2>
+ − 16 *
+ − 17 ******************************************************************************
+ − 18 */
+ − 19
+ − 20 /* Includes ------------------------------------------------------------------*/
598
+ − 21
+ − 22
+ − 23 #include <string.h>
38
+ − 24 #include "logbook_miniLive.h"
+ − 25 #include "data_exchange.h"
598
+ − 26 #include "logbook.h"
603
+ − 27 #include "tHome.h"
38
+ − 28
+ − 29 /*
+ − 30 ******************************************************************************
+ − 31 * @brief t7_updateMiniLiveLogbook. / Create depth samples for view during dive
+ − 32 * @author heinrichs weikamp gmbh
+ − 33 * @version V0.0.1
+ − 34 * @date 13-March-2015
+ − 35 ******************************************************************************
+ − 36 *
+ − 37 */
+ − 38
+ − 39 #define MLLsize (296)
300
+ − 40 static uint16_t MLLdataDepth[MLLsize];
+ − 41 static uint16_t MLLpointer = 0;
+ − 42 static uint8_t MLLtickIntervallSeconds = 2;
598
+ − 43
+ − 44 /* Replay Block data storage */
602
+ − 45 #define DEPTH_DATA_LENGTH (1800u) /* Resolution: 1 hours dive, sampling every 2 seconds */
+ − 46 uint16_t ReplayDepthData[DEPTH_DATA_LENGTH];
610
+ − 47 uint8_t ReplayMarkerData[DEPTH_DATA_LENGTH];
602
+ − 48 uint16_t liveDepthData[DEPTH_DATA_LENGTH];
620
+ − 49 uint16_t liveDepthDataMod[DEPTH_DATA_LENGTH]; /* live data modified to fit to marker checks */
603
+ − 50 uint16_t liveDecoData[DEPTH_DATA_LENGTH];
620
+ − 51 uint16_t liveDecoDataMod[DEPTH_DATA_LENGTH];
+ − 52 static uint16_t liveDataIndex = 0;
+ − 53 static uint16_t liveDataIndexMod = 0;
598
+ − 54
+ − 55 static uint8_t ReplayDataResolution = 2; /* Time represented by one sample (second) */
+ − 56 static uint16_t ReplayDataLength = 0; /* Number of data entries */
+ − 57 static uint16_t ReplayDataMaxDepth = 0;
+ − 58 static uint16_t ReplayDataMinutes = 0;
+ − 59 static uint16_t ReplayDataOffset = 0xFFFF; /* Stepbackwards format used by log functions */
620
+ − 60 static uint16_t ReplayMarkerIndex = 0;
38
+ − 61
+ − 62 uint16_t *getMiniLiveLogbookPointerToData(void)
+ − 63 {
+ − 64 return MLLdataDepth;
+ − 65 }
+ − 66
+ − 67
+ − 68 uint16_t getMiniLiveLogbookActualDataLength(void)
+ − 69 {
+ − 70 return MLLpointer;
+ − 71 }
620
+ − 72
+ − 73 uint16_t MiniLiveLogbook_getNextMarkerIndex(uint16_t curIndex)
+ − 74 {
+ − 75 uint16_t index = 0;
38
+ − 76
620
+ − 77 if((ReplayMarkerData[0] != 0xFF) && (curIndex < ReplayDataLength))
+ − 78 {
+ − 79 index = curIndex;
+ − 80 do
+ − 81 {
+ − 82 index++;
+ − 83 if (index == ReplayDataLength)
+ − 84 {
+ − 85 index = 0;
+ − 86 }
+ − 87 if(ReplayMarkerData[index] != 0)
+ − 88 {
+ − 89 break;
+ − 90 }
+ − 91 }while (index != curIndex);
+ − 92 }
+ − 93 return index;
+ − 94 }
+ − 95
+ − 96 static uint16_t workdata[DEPTH_DATA_LENGTH];
+ − 97 static void compressMarkerData(uint16_t* pSource, uint16_t* pTarget, float step, uint16_t startIndex, uint16_t stopIndex)
+ − 98 {
+ − 99 uint16_t workIndex = startIndex;
+ − 100 float nextStep = (float)workIndex;
+ − 101
+ − 102 while (workIndex <= ReplayMarkerIndex)
+ − 103 {
+ − 104 workdata[workIndex] = *pSource++;
+ − 105 nextStep += step;
+ − 106 while(nextStep < workIndex + 1)
+ − 107 {
+ − 108 if(*pSource != 0xFFFF) /* do not average "ignore" value */
+ − 109 {
+ − 110 if(workdata[workIndex] == 0xFFFF) /* first value to be shown */
+ − 111 {
+ − 112 workdata[workIndex] = *pSource;
+ − 113 }
+ − 114 else
+ − 115 {
+ − 116 workdata[workIndex] += *pSource;
+ − 117 workdata[workIndex] /= 2;
+ − 118 }
+ − 119 }
+ − 120 pSource++;
+ − 121 nextStep += step;
+ − 122 }
+ − 123 workIndex++;
+ − 124 }
+ − 125 memcpy(&pTarget[startIndex],&workdata[startIndex],(workIndex - startIndex -1) * 2);
+ − 126 while(workIndex < DEPTH_DATA_LENGTH)
+ − 127 {
+ − 128 pTarget[workIndex] = 0xFFFF;
+ − 129 workIndex++;
+ − 130 }
+ − 131 }
+ − 132 static void stretchMarkerData(uint16_t* pSource, uint16_t* pTarget, float step, uint16_t startIndex, uint16_t stopIndex)
+ − 133 {
+ − 134 uint16_t workIndex = startIndex;
+ − 135 float nextStep = (float)workIndex;
+ − 136
+ − 137 while (workIndex <= stopIndex)
+ − 138 {
+ − 139 nextStep += step;
+ − 140 if(nextStep > stopIndex)
+ − 141 {
+ − 142 nextStep = stopIndex;
+ − 143 }
+ − 144 while(workIndex <= (uint16_t)nextStep)
+ − 145 {
+ − 146 workdata[workIndex++] = *pSource;
+ − 147 }
+ − 148 pSource++;
+ − 149 }
+ − 150 memcpy(&pTarget[startIndex],&workdata[startIndex],(workIndex - startIndex) * 2);
+ − 151 while(workIndex < DEPTH_DATA_LENGTH)
+ − 152 {
+ − 153 pTarget[workIndex] = 0xFFFF;
+ − 154 workIndex++;
+ − 155 }
+ − 156 }
+ − 157
+ − 158 void MiniLiveLogbook_checkMarker(void)
+ − 159 {
+ − 160 static uint16_t lastLifeIndex = 0;
+ − 161 uint16_t* pDepthData;
+ − 162 uint16_t* pDecoData;
+ − 163 float step;
+ − 164 uint16_t lastMarkerIndex = ReplayMarkerIndex;
+ − 165
+ − 166 ReplayMarkerIndex = MiniLiveLogbook_getNextMarkerIndex(ReplayMarkerIndex);
+ − 167 if(ReplayMarkerIndex <= lastMarkerIndex) /* no other marker found or last marker checked => reset marker to 0 to deactivate check function */
+ − 168 {
+ − 169 ReplayMarkerIndex = 0;
+ − 170 lastLifeIndex = 0;
+ − 171 liveDataIndexMod = liveDataIndex;
+ − 172 }
+ − 173 else
+ − 174 {
+ − 175 if(lastMarkerIndex == 0) /* use real live data */
+ − 176 {
+ − 177 pDepthData = &liveDepthData[0];
+ − 178 pDecoData = &liveDecoData[0];
+ − 179 lastLifeIndex = 0;
+ − 180 }
+ − 181 else
+ − 182 {
+ − 183 pDepthData = &liveDepthDataMod[lastMarkerIndex]; /* work with already modified data */
+ − 184 pDecoData = &liveDecoDataMod[lastMarkerIndex];
+ − 185 }
+ − 186 if(lastLifeIndex == liveDataIndex) /* repeated button press before new data was generated => draw straight line */
+ − 187 {
+ − 188 step = ReplayMarkerIndex-lastMarkerIndex;
+ − 189 }
+ − 190 else
+ − 191 {
+ − 192 step = (ReplayMarkerIndex-lastMarkerIndex) / (float)(liveDataIndex - lastLifeIndex); /* the live data shall be modified to match the history data */
+ − 193 }
+ − 194
+ − 195 lastLifeIndex = liveDataIndex;
+ − 196
+ − 197 if(step < 1) /* compression needed */
+ − 198 {
+ − 199 compressMarkerData(pDepthData, liveDepthDataMod, step, lastMarkerIndex, ReplayMarkerIndex);
+ − 200 compressMarkerData(pDecoData, liveDecoDataMod, step, lastMarkerIndex, ReplayMarkerIndex);
+ − 201 }
+ − 202 else /* stretch data */
+ − 203 {
+ − 204 stretchMarkerData(pDepthData, liveDepthDataMod, step, lastMarkerIndex, ReplayMarkerIndex);
+ − 205 stretchMarkerData(pDecoData, liveDecoDataMod, step, lastMarkerIndex, ReplayMarkerIndex);
+ − 206 }
+ − 207 liveDataIndexMod = ReplayMarkerIndex;
+ − 208 }
+ − 209 }
+ − 210
+ − 211
598
+ − 212 void compressBuffer_uint16(uint16_t* pdata, uint16_t size)
+ − 213 {
+ − 214 uint16_t* pTarget = pdata;
+ − 215 uint16_t* pSource = pdata;
610
+ − 216 uint16_t result = 0;
598
+ − 217 uint16_t index = 0;
38
+ − 218
598
+ − 219 for(index = 0; index < size/2; index++)
+ − 220 {
+ − 221 *pTarget = *pSource++;
+ − 222 *pTarget += *pSource++;
610
+ − 223 result = *pTarget /= 2;
+ − 224 if((*pTarget != 0) && (result == 0)) /* avoid termination of information by round up to 1 */
+ − 225 {
+ − 226 *pTarget++ = 1;
+ − 227 }
+ − 228 else
+ − 229 {
+ − 230 *pTarget++ = result;
+ − 231 }
598
+ − 232 }
+ − 233 memset(pTarget,0,size/2);
+ − 234 }
+ − 235
38
+ − 236 void updateMiniLiveLogbook( _Bool checkOncePerSecond)
+ − 237 {
+ − 238 static uint8_t bDiveMode = 0;
+ − 239 static uint32_t last_second = 0;
+ − 240 static uint8_t secondsCount = 0;
602
+ − 241 static uint8_t lifesecondsCount = 0;
38
+ − 242
603
+ − 243 const SDecoinfo* pDecoinfo;
+ − 244 uint8_t stopDepth = 0;
+ − 245 uint16_t stopTime = 0;
+ − 246
38
+ − 247 if(checkOncePerSecond)
+ − 248 {
+ − 249 uint32_t now = current_second();
+ − 250 if( last_second == now)
+ − 251 return;
+ − 252 last_second = now;
+ − 253 }
+ − 254 secondsCount++;
602
+ − 255 lifesecondsCount++;
38
+ − 256
+ − 257 if(!bDiveMode)
+ − 258 {
+ − 259 if((stateUsed->mode == MODE_DIVE) && (stateUsed->lifeData.dive_time_seconds >= 5))
+ − 260 {
+ − 261 secondsCount = 0;
+ − 262 MLLtickIntervallSeconds = 2;
+ − 263 bDiveMode = 1;
+ − 264 MLLpointer = 1;
+ − 265 for(int i=0;i<MLLsize;i++)
+ − 266 MLLdataDepth[i] = 0;
598
+ − 267
620
+ − 268 for(liveDataIndex = 0; liveDataIndex < DEPTH_DATA_LENGTH; liveDataIndex++)
598
+ − 269 {
620
+ − 270 liveDepthData[liveDataIndex] = 0xFFFF;
+ − 271 liveDecoData[liveDataIndex] = 0xFFFF;
598
+ − 272 }
602
+ − 273 lifesecondsCount = 0;
620
+ − 274 liveDataIndex = 0;
+ − 275 liveDataIndexMod = 0;
+ − 276 liveDepthData[liveDataIndex++] = 0; /* start at 0 */
38
+ − 277 }
+ − 278 }
+ − 279 else if(stateUsed->mode == MODE_DIVE)
+ − 280 {
+ − 281 bDiveMode = 3;
+ − 282 //
+ − 283 if(secondsCount >= MLLtickIntervallSeconds)
+ − 284 {
+ − 285 secondsCount = 0;
598
+ − 286 /* in case of a buffer overrun the buffer is divided and the first half is filled with a compressed image of the complete buffer */
38
+ − 287 if((MLLpointer >= MLLsize) && (MLLtickIntervallSeconds < 127))
+ − 288 {
+ − 289 MLLpointer = 0;
+ − 290 MLLtickIntervallSeconds *= 2;
598
+ − 291
+ − 292 compressBuffer_uint16(MLLdataDepth,MLLsize);
38
+ − 293 MLLpointer = MLLsize/2;
+ − 294 }
+ − 295 if(MLLpointer < MLLsize)
+ − 296 MLLdataDepth[MLLpointer++] = (int)(stateUsed->lifeData.depth_meter * 10);
+ − 297 }
602
+ − 298 if(lifesecondsCount >= ReplayDataResolution)
598
+ − 299 {
602
+ − 300 lifesecondsCount = 0;
598
+ − 301
620
+ − 302 if(liveDataIndex >= DEPTH_DATA_LENGTH) /* compress data */
598
+ − 303 {
+ − 304 ReplayDataResolution *= 2;
602
+ − 305 compressBuffer_uint16(liveDepthData,DEPTH_DATA_LENGTH);
620
+ − 306 compressBuffer_uint16(liveDepthDataMod, DEPTH_DATA_LENGTH);
+ − 307 compressBuffer_uint16(ReplayDepthData,DEPTH_DATA_LENGTH); /* also compress Replay data to simplify mapping between live and replay data */
+ − 308 liveDataIndex = DEPTH_DATA_LENGTH / 2;
+ − 309 liveDataIndexMod /= 2;
598
+ − 310 }
620
+ − 311 liveDepthData[liveDataIndex] = (int)(stateUsed->lifeData.depth_meter * 100);
+ − 312 liveDepthDataMod[liveDataIndexMod] = liveDepthData[liveDataIndex];
+ − 313
603
+ − 314 if(stateUsed->diveSettings.deco_type.ub.standard == VPM_MODE)
+ − 315 {
+ − 316 pDecoinfo = &stateUsed->decolistVPM;
+ − 317 }
+ − 318 else
+ − 319 {
+ − 320 pDecoinfo = &stateUsed->decolistBuehlmann;
+ − 321 }
+ − 322 tHome_findNextStop(pDecoinfo->output_stop_length_seconds, &stopDepth, &stopTime);
+ − 323 if(stopDepth)
+ − 324 {
620
+ − 325 liveDecoData[liveDataIndex] = stopDepth * 100;
+ − 326 liveDecoDataMod[liveDataIndexMod] = stopDepth * 100;
603
+ − 327 }
+ − 328 else
+ − 329 {
620
+ − 330 liveDecoData[liveDataIndex] = 0xFFFF;
+ − 331 liveDecoDataMod[liveDataIndexMod] = 0xFFFF;
603
+ − 332 }
620
+ − 333 liveDataIndex++;
+ − 334 liveDataIndexMod++;
598
+ − 335 }
38
+ − 336 }
+ − 337 else if(bDiveMode == 3)
+ − 338 {
+ − 339 //End of Dive
+ − 340 for(int i=0;i<MLLsize;i++)
+ − 341 MLLdataDepth[i] = 0;
+ − 342 bDiveMode = 0;
+ − 343 }
+ − 344 }
+ − 345
598
+ − 346 uint8_t prepareReplayLog(uint8_t StepBackwards)
+ − 347 {
+ − 348 uint8_t retVal = 0;
610
+ − 349 uint16_t index = 0;
598
+ − 350 uint16_t dataLength = 0;
610
+ − 351 uint8_t markerDetected = 0;
38
+ − 352
598
+ − 353 SLogbookHeader logbookHeader;
+ − 354
+ − 355 if(ReplayDataOffset == StepBackwards) /* Entry already selected => reset selection */
+ − 356 {
+ − 357 ReplayDataOffset = 0xFFFF;
+ − 358 ReplayDataResolution = 2;
602
+ − 359 ReplayDataLength = 0;
+ − 360 ReplayDataMaxDepth = 0;
+ − 361 ReplayDataMinutes = 0;
+ − 362
598
+ − 363 retVal = 1;
+ − 364 }
+ − 365 else
+ − 366 {
+ − 367 ReplayDataOffset = StepBackwards;
+ − 368 logbook_getHeader(StepBackwards ,&logbookHeader);
+ − 369
610
+ − 370 dataLength = logbook_readSampleData(StepBackwards, DEPTH_DATA_LENGTH, ReplayDepthData,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ReplayMarkerData);
+ − 371
+ − 372 /* check if a marker is provided. If not disable marker functionality for the replay block */
+ − 373 for(index = 0; index < dataLength; index++)
+ − 374 {
+ − 375 if(ReplayMarkerData[index] != 0)
+ − 376 {
+ − 377 markerDetected = 1;
+ − 378 break;
+ − 379 }
+ − 380 }
+ − 381 if(markerDetected == 0)
+ − 382 {
+ − 383 ReplayMarkerData[0] = 0xFF;
+ − 384 }
598
+ − 385
910
+ − 386 ReplayDataResolution = logbookHeader.total_diveTime_seconds / dataLength;
598
+ − 387 ReplayDataLength = dataLength;
+ − 388 ReplayDataMaxDepth = logbookHeader.maxDepth;
+ − 389 ReplayDataMinutes = logbookHeader.diveTimeMinutes;
+ − 390 if(dataLength != 0)
+ − 391 {
+ − 392 retVal = 1;
+ − 393 }
+ − 394 }
+ − 395 return retVal;
+ − 396 }
+ − 397
610
+ − 398 uint8_t getReplayInfo(uint16_t** pReplayData, uint8_t** pReplayMarker, uint16_t* DataLength, uint16_t* MaxDepth, uint16_t* diveMinutes)
598
+ − 399 {
+ − 400 uint8_t retVal = 0;
+ − 401
610
+ − 402 if((ReplayDataOffset != 0xFFFF) && (pReplayData != NULL) && (DataLength != NULL) && (MaxDepth != NULL) && (pReplayMarker != 0))
598
+ − 403 {
602
+ − 404 *pReplayData = ReplayDepthData;
610
+ − 405 *pReplayMarker = ReplayMarkerData;
598
+ − 406 *DataLength = ReplayDataLength;
+ − 407 *MaxDepth = ReplayDataMaxDepth;
+ − 408 *diveMinutes = ReplayDataMinutes;
+ − 409 retVal = 1;
+ − 410 }
+ − 411
+ − 412 return retVal;
+ − 413 }
+ − 414
+ − 415 uint16_t *getMiniLiveReplayPointerToData(void)
+ − 416 {
620
+ − 417 if(ReplayMarkerIndex == 0)
+ − 418 {
+ − 419 return liveDepthData;
+ − 420 }
+ − 421 else
+ − 422 {
+ − 423 return liveDepthDataMod;
+ − 424 }
598
+ − 425 }
603
+ − 426 uint16_t *getMiniLiveDecoPointerToData(void)
+ − 427 {
620
+ − 428 if(ReplayMarkerIndex == 0)
+ − 429 {
+ − 430 return liveDecoData;
+ − 431 }
+ − 432 else
+ − 433 {
+ − 434 return liveDecoDataMod;
+ − 435 }
603
+ − 436 }
598
+ − 437 uint16_t getMiniLiveReplayLength(void)
+ − 438 {
620
+ − 439 return liveDataIndex;
598
+ − 440 }
+ − 441
+ − 442 uint16_t getReplayOffset(void)
+ − 443 {
+ − 444 return ReplayDataOffset;
+ − 445 }
+ − 446
+ − 447 uint16_t getReplayDataResolution(void)
+ − 448 {
+ − 449 return ReplayDataResolution;
+ − 450 }
38
+ − 451
+ − 452 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/