Mercurial > public > ostc4
comparison Discovery/Src/logbook_miniLive.c @ 620:bf574fb3efa0
Added minilog functions to allow marker synchronisation:
To keep the live data in the background a second buffer had to be added which stored the live data modified to match a specific marker. To archive this stretching and compression functions have been added.
In addition a type has been solved "life"=>"live"
author | Ideenmodellierer |
---|---|
date | Wed, 27 Jan 2021 22:12:44 +0100 |
parents | ae7f8333c900 |
children | 7bd347bdaa81 |
comparison
equal
deleted
inserted
replaced
619:8fa2de4414a8 | 620:bf574fb3efa0 |
---|---|
44 /* Replay Block data storage */ | 44 /* Replay Block data storage */ |
45 #define DEPTH_DATA_LENGTH (1800u) /* Resolution: 1 hours dive, sampling every 2 seconds */ | 45 #define DEPTH_DATA_LENGTH (1800u) /* Resolution: 1 hours dive, sampling every 2 seconds */ |
46 uint16_t ReplayDepthData[DEPTH_DATA_LENGTH]; | 46 uint16_t ReplayDepthData[DEPTH_DATA_LENGTH]; |
47 uint8_t ReplayMarkerData[DEPTH_DATA_LENGTH]; | 47 uint8_t ReplayMarkerData[DEPTH_DATA_LENGTH]; |
48 uint16_t liveDepthData[DEPTH_DATA_LENGTH]; | 48 uint16_t liveDepthData[DEPTH_DATA_LENGTH]; |
49 uint16_t liveDepthDataMod[DEPTH_DATA_LENGTH]; /* live data modified to fit to marker checks */ | |
49 uint16_t liveDecoData[DEPTH_DATA_LENGTH]; | 50 uint16_t liveDecoData[DEPTH_DATA_LENGTH]; |
50 static uint16_t lifeDataIndex = 0; | 51 uint16_t liveDecoDataMod[DEPTH_DATA_LENGTH]; |
52 static uint16_t liveDataIndex = 0; | |
53 static uint16_t liveDataIndexMod = 0; | |
51 | 54 |
52 static uint8_t ReplayDataResolution = 2; /* Time represented by one sample (second) */ | 55 static uint8_t ReplayDataResolution = 2; /* Time represented by one sample (second) */ |
53 static uint16_t ReplayDataLength = 0; /* Number of data entries */ | 56 static uint16_t ReplayDataLength = 0; /* Number of data entries */ |
54 static uint16_t ReplayDataMaxDepth = 0; | 57 static uint16_t ReplayDataMaxDepth = 0; |
55 static uint16_t ReplayDataMinutes = 0; | 58 static uint16_t ReplayDataMinutes = 0; |
56 static uint16_t ReplayDataOffset = 0xFFFF; /* Stepbackwards format used by log functions */ | 59 static uint16_t ReplayDataOffset = 0xFFFF; /* Stepbackwards format used by log functions */ |
60 static uint16_t ReplayMarkerIndex = 0; | |
57 | 61 |
58 uint16_t *getMiniLiveLogbookPointerToData(void) | 62 uint16_t *getMiniLiveLogbookPointerToData(void) |
59 { | 63 { |
60 return MLLdataDepth; | 64 return MLLdataDepth; |
61 } | 65 } |
63 | 67 |
64 uint16_t getMiniLiveLogbookActualDataLength(void) | 68 uint16_t getMiniLiveLogbookActualDataLength(void) |
65 { | 69 { |
66 return MLLpointer; | 70 return MLLpointer; |
67 } | 71 } |
72 | |
73 uint16_t MiniLiveLogbook_getNextMarkerIndex(uint16_t curIndex) | |
74 { | |
75 uint16_t index = 0; | |
68 | 76 |
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 | |
69 void compressBuffer_uint16(uint16_t* pdata, uint16_t size) | 212 void compressBuffer_uint16(uint16_t* pdata, uint16_t size) |
70 { | 213 { |
71 uint16_t* pTarget = pdata; | 214 uint16_t* pTarget = pdata; |
72 uint16_t* pSource = pdata; | 215 uint16_t* pSource = pdata; |
73 uint16_t result = 0; | 216 uint16_t result = 0; |
74 | |
75 uint16_t index = 0; | 217 uint16_t index = 0; |
76 | 218 |
77 for(index = 0; index < size/2; index++) | 219 for(index = 0; index < size/2; index++) |
78 { | 220 { |
79 *pTarget = *pSource++; | 221 *pTarget = *pSource++; |
121 bDiveMode = 1; | 263 bDiveMode = 1; |
122 MLLpointer = 1; | 264 MLLpointer = 1; |
123 for(int i=0;i<MLLsize;i++) | 265 for(int i=0;i<MLLsize;i++) |
124 MLLdataDepth[i] = 0; | 266 MLLdataDepth[i] = 0; |
125 | 267 |
126 for(lifeDataIndex = 0; lifeDataIndex < DEPTH_DATA_LENGTH; lifeDataIndex++) | 268 for(liveDataIndex = 0; liveDataIndex < DEPTH_DATA_LENGTH; liveDataIndex++) |
127 { | 269 { |
128 liveDepthData[lifeDataIndex] = 0xFFFF; | 270 liveDepthData[liveDataIndex] = 0xFFFF; |
129 liveDecoData[lifeDataIndex] = 0xFFFF; | 271 liveDecoData[liveDataIndex] = 0xFFFF; |
130 } | 272 } |
131 lifesecondsCount = 0; | 273 lifesecondsCount = 0; |
132 lifeDataIndex = 0; | 274 liveDataIndex = 0; |
133 liveDepthData[lifeDataIndex++] = 0; /* start at 0 */ | 275 liveDataIndexMod = 0; |
276 liveDepthData[liveDataIndex++] = 0; /* start at 0 */ | |
134 } | 277 } |
135 } | 278 } |
136 else if(stateUsed->mode == MODE_DIVE) | 279 else if(stateUsed->mode == MODE_DIVE) |
137 { | 280 { |
138 bDiveMode = 3; | 281 bDiveMode = 3; |
154 } | 297 } |
155 if(lifesecondsCount >= ReplayDataResolution) | 298 if(lifesecondsCount >= ReplayDataResolution) |
156 { | 299 { |
157 lifesecondsCount = 0; | 300 lifesecondsCount = 0; |
158 | 301 |
159 if(lifeDataIndex >= DEPTH_DATA_LENGTH) /* compress data */ | 302 if(liveDataIndex >= DEPTH_DATA_LENGTH) /* compress data */ |
160 { | 303 { |
161 ReplayDataResolution *= 2; | 304 ReplayDataResolution *= 2; |
162 compressBuffer_uint16(liveDepthData,DEPTH_DATA_LENGTH); | 305 compressBuffer_uint16(liveDepthData,DEPTH_DATA_LENGTH); |
163 compressBuffer_uint16(ReplayDepthData,DEPTH_DATA_LENGTH); /* also compress Replay data to siplify mapping between live and replay data */ | 306 compressBuffer_uint16(liveDepthDataMod, DEPTH_DATA_LENGTH); |
164 lifeDataIndex = DEPTH_DATA_LENGTH / 2; | 307 compressBuffer_uint16(ReplayDepthData,DEPTH_DATA_LENGTH); /* also compress Replay data to simplify mapping between live and replay data */ |
165 } | 308 liveDataIndex = DEPTH_DATA_LENGTH / 2; |
166 liveDepthData[lifeDataIndex] = (int)(stateUsed->lifeData.depth_meter * 100); | 309 liveDataIndexMod /= 2; |
310 } | |
311 liveDepthData[liveDataIndex] = (int)(stateUsed->lifeData.depth_meter * 100); | |
312 liveDepthDataMod[liveDataIndexMod] = liveDepthData[liveDataIndex]; | |
313 | |
167 if(stateUsed->diveSettings.deco_type.ub.standard == VPM_MODE) | 314 if(stateUsed->diveSettings.deco_type.ub.standard == VPM_MODE) |
168 { | 315 { |
169 pDecoinfo = &stateUsed->decolistVPM; | 316 pDecoinfo = &stateUsed->decolistVPM; |
170 } | 317 } |
171 else | 318 else |
173 pDecoinfo = &stateUsed->decolistBuehlmann; | 320 pDecoinfo = &stateUsed->decolistBuehlmann; |
174 } | 321 } |
175 tHome_findNextStop(pDecoinfo->output_stop_length_seconds, &stopDepth, &stopTime); | 322 tHome_findNextStop(pDecoinfo->output_stop_length_seconds, &stopDepth, &stopTime); |
176 if(stopDepth) | 323 if(stopDepth) |
177 { | 324 { |
178 liveDecoData[lifeDataIndex] = stopDepth * 100; | 325 liveDecoData[liveDataIndex] = stopDepth * 100; |
326 liveDecoDataMod[liveDataIndexMod] = stopDepth * 100; | |
179 } | 327 } |
180 else | 328 else |
181 { | 329 { |
182 liveDecoData[lifeDataIndex] = 0xFFFF; | 330 liveDecoData[liveDataIndex] = 0xFFFF; |
183 } | 331 liveDecoDataMod[liveDataIndexMod] = 0xFFFF; |
184 lifeDataIndex++; | 332 } |
333 liveDataIndex++; | |
334 liveDataIndexMod++; | |
185 } | 335 } |
186 } | 336 } |
187 else if(bDiveMode == 3) | 337 else if(bDiveMode == 3) |
188 { | 338 { |
189 //End of Dive | 339 //End of Dive |
269 return retVal; | 419 return retVal; |
270 } | 420 } |
271 | 421 |
272 uint16_t *getMiniLiveReplayPointerToData(void) | 422 uint16_t *getMiniLiveReplayPointerToData(void) |
273 { | 423 { |
274 return liveDepthData; | 424 if(ReplayMarkerIndex == 0) |
425 { | |
426 return liveDepthData; | |
427 } | |
428 else | |
429 { | |
430 return liveDepthDataMod; | |
431 } | |
275 } | 432 } |
276 uint16_t *getMiniLiveDecoPointerToData(void) | 433 uint16_t *getMiniLiveDecoPointerToData(void) |
277 { | 434 { |
278 return liveDecoData; | 435 if(ReplayMarkerIndex == 0) |
436 { | |
437 return liveDecoData; | |
438 } | |
439 else | |
440 { | |
441 return liveDecoDataMod; | |
442 } | |
279 } | 443 } |
280 uint16_t getMiniLiveReplayLength(void) | 444 uint16_t getMiniLiveReplayLength(void) |
281 { | 445 { |
282 return lifeDataIndex; | 446 return liveDataIndex; |
283 } | 447 } |
284 | 448 |
285 uint16_t getReplayOffset(void) | 449 uint16_t getReplayOffset(void) |
286 { | 450 { |
287 return ReplayDataOffset; | 451 return ReplayDataOffset; |