Mercurial > public > ostc4
annotate Discovery/Src/tHome.c @ 240:625d20070261 div-fixes-5
Improvement SPI stability/recoverability
The core part of this commit comes from careful code reading. The core is the
swap of Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_SOFT) and
SPI_Start_single_TxRx_with_Master(). This code is sitting in an if-clause
that is triggered on SPI comms failure. Instead of blindly trying to
communicate again (which will very likely fail again), first try to reset
the comms link, and then try to communicate again. That simply makes
more sense in this case.
This is heavily tested, on 2 simple dives, and 5 very long deco schedules
from the simulator (10+ hour deco's), and a lot of small simulated dives
(upto 2h runtime). Of all these tests, only one long session failed after
9 out of 11h runtime. Analyzing that one failure, suggests that the
RTE is looping in some error handler, which (obviously) results in
a SPI comms failure as a result. I consider this not part of this change.
Additionally, some more cleanup is done in this code.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Mon, 08 Apr 2019 11:49:13 +0200 |
parents | b2a9e9b02df0 |
children | 74a8296a2318 |
rev | line source |
---|---|
38 | 1 /////////////////////////////////////////////////////////////////////////////// |
2 /// -*- coding: UTF-8 -*- | |
3 /// | |
4 /// \file Discovery/Src/tHome.c | |
5 /// \brief Control for Surface and Dive Templates | |
6 /// \author heinrichs weikamp gmbh | |
7 /// \date 10-November-2014 | |
8 /// | |
9 /// \details | |
10 /// | |
11 /// $Id$ | |
12 /////////////////////////////////////////////////////////////////////////////// | |
13 /// \par Copyright (c) 2014-2018 Heinrichs Weikamp gmbh | |
14 /// | |
15 /// This program is free software: you can redistribute it and/or modify | |
16 /// it under the terms of the GNU General Public License as published by | |
17 /// the Free Software Foundation, either version 3 of the License, or | |
18 /// (at your option) any later version. | |
19 /// | |
20 /// This program is distributed in the hope that it will be useful, | |
21 /// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
23 /// GNU General Public License for more details. | |
24 /// | |
25 /// You should have received a copy of the GNU General Public License | |
26 /// along with this program. If not, see <http://www.gnu.org/licenses/>. | |
27 ////////////////////////////////////////////////////////////////////////////// | |
28 | |
29 /* Includes ------------------------------------------------------------------*/ | |
30 #include "tHome.h" | |
31 | |
32 #include "data_exchange_main.h" // for dataOutGetPointer() | |
33 #include "gfx_fonts.h" | |
34 #include "t3.h" | |
35 #include "t4_tetris.h" | |
36 #include "t5_gauge.h" | |
37 #include "t6_apnea.h" | |
38 #include "t7.h" | |
39 #include "tDebug.h" | |
40 #include "timer.h" // for timer_Stopwatch_Restart | |
41 #include "tMenu.h" | |
42 #include "tMenuEditGasOC.h" // for openEdit_DiveSelectBetterGas() | |
43 #include "tMenuEditSetpoint.h" // for openEdit_DiveSelectBetterSetpoint() | |
44 #include "simulation.h" | |
45 | |
46 /* Private types -------------------------------------------------------------*/ | |
47 | |
48 /* Exported variables --------------------------------------------------------*/ | |
49 _Bool warning_count_high_time = 0; | |
50 _Bool display_count_high_time = 0; | |
51 | |
52 uint8_t errorsInSettings = 0; | |
53 /* Private variables ---------------------------------------------------------*/ | |
54 static uint8_t warning_toogle_count; | |
55 static uint16_t display_toogle_count; | |
56 static uint16_t tHome_tick_count_cview; | |
57 static uint16_t tHome_tick_count_field; | |
58 | |
59 const uint8_t cv_changelist[6] = {CVIEW_Compass, CVIEW_SummaryOfLeftCorner, CVIEW_Tissues, CVIEW_Profile, CVIEW_EADTime, CVIEW_Gaslist}; | |
60 | |
61 /* Private function prototypes -----------------------------------------------*/ | |
62 | |
63 /* Exported functions --------------------------------------------------------*/ | |
64 | |
65 void set_globalState_tHome(void) | |
66 { | |
67 if(stateUsed->mode == MODE_DIVE) | |
68 set_globalState(StD); | |
69 else | |
70 set_globalState(StS); | |
71 } | |
72 | |
73 | |
74 void switch_to_SimData_tHome(void) | |
75 { | |
76 set_stateUsedToSim(); | |
77 } | |
78 | |
79 | |
80 void switch_to_RealData_tHome(void) | |
81 { | |
82 set_stateUsedToReal(); | |
83 } | |
84 | |
85 | |
86 void tHome_init(void) | |
87 { | |
88 t7_init(); // standard + surface | |
89 t3_init(); // big font | |
90 t4_init(); // game | |
91 t5_init(); // gauge | |
92 t6_init(); // apnea | |
93 } | |
94 | |
95 | |
96 void tHome_init_compass(void) | |
97 { | |
98 init_t7_compass(); | |
99 } | |
100 | |
101 | |
102 void tHome_refresh(void) | |
103 { | |
104 SSettings* pSettings = settingsGetPointer(); | |
105 | |
106 warning_toogle_count++; | |
107 if(warning_toogle_count >= 2* pSettings->warning_blink_dsec) | |
108 warning_toogle_count = 0; | |
109 | |
110 if(warning_toogle_count >= pSettings->warning_blink_dsec) | |
111 warning_count_high_time = 1; | |
112 else | |
113 warning_count_high_time = 0; | |
114 | |
115 | |
116 display_toogle_count++; | |
117 if(display_toogle_count >= 2* pSettings->display_toogle_desc) | |
118 display_toogle_count = 0; | |
119 | |
120 if(display_toogle_count >= pSettings->display_toogle_desc) | |
121 display_count_high_time = 1; | |
122 else | |
123 display_count_high_time = 0; | |
124 | |
125 | |
126 if(pSettings->design == 6) | |
127 t6_refresh(); | |
128 else | |
129 if(pSettings->design == 5) | |
130 t5_refresh(); | |
131 else | |
132 if(pSettings->design == 4) | |
133 t4_refresh(); | |
134 else | |
135 if(pSettings->design == 3) | |
136 t3_refresh(); | |
137 else | |
138 if(pSettings->design == 7) | |
139 t7_refresh(); | |
140 else | |
141 { | |
142 pSettings->design = 7; | |
143 t7_refresh(); | |
144 } | |
145 } | |
146 | |
147 | |
148 void tHome_sleepmode_fun(void) | |
149 { | |
150 t7_refresh_sleepmode_fun(); | |
151 } | |
152 | |
153 | |
154 void tHomeDiveMenuControl(uint8_t sendAction) | |
155 { | |
156 if(sendAction == ACTION_BUTTON_NEXT) | |
157 { | |
158 if(settingsGetPointer()->design == 4) | |
159 return; | |
160 | |
161 if(settingsGetPointer()->design == 3) | |
162 settingsGetPointer()->design = 7; | |
163 | |
164 switch(get_globalState()) | |
165 { | |
166 case StD: | |
167 if(settingsGetPointer()->design == 6) | |
168 { | |
169 if(is_stateUsedSetToSim()) | |
170 set_globalState(StDSIM1); | |
171 else | |
172 set_globalState(StDQUIT); | |
173 break; | |
174 } | |
175 | |
176 if(settingsGetPointer()->design == 5) | |
177 { | |
178 if(t5_getCustomView() == CVIEW_Compass) | |
179 set_globalState(StDBEAR); | |
180 else | |
181 set_globalState(StDRAVG); | |
182 break; | |
183 } | |
184 | |
185 if(stateUsed->warnings.betterGas) | |
186 set_globalState(StDMGAS); | |
187 else | |
188 if(stateUsed->warnings.betterSetpoint) | |
189 set_globalState(StDMSPT); | |
190 else | |
191 set_globalState(StDMENU); | |
192 break; | |
193 | |
194 case StDMGAS: | |
195 if(stateUsed->warnings.betterSetpoint) | |
196 set_globalState(StDMSPT); | |
197 else | |
198 set_globalState(StDMENU); | |
199 break; | |
200 | |
201 case StDMSPT: | |
202 set_globalState(StDMENU); | |
203 break; | |
204 | |
205 case StDMENU: | |
206 if(is_stateUsedSetToSim()) | |
207 set_globalState(StDSIM1); | |
208 else | |
209 set_globalState(StD); | |
210 break; | |
211 | |
212 case StDSIM1: | |
213 set_globalState(StDSIM2); | |
214 break; | |
215 | |
216 case StDSIM2: | |
217 set_globalState(StDSIM3); | |
218 break; | |
219 | |
220 case StDSIM3: | |
221 set_globalState(StDSIM4); | |
222 break; | |
223 | |
224 case StDSIM4: | |
225 set_globalState(StD); | |
226 break; | |
227 | |
228 case StDBEAR: // t5_gauge | |
229 set_globalState(StDRAVG); | |
230 break; | |
231 | |
232 case StDRAVG: // t5_gauge | |
233 if(is_stateUsedSetToSim()) | |
234 set_globalState(StDSIM1); | |
235 else | |
236 set_globalState(StD); | |
237 break; | |
238 | |
239 case StDQUIT: // t6_apnea | |
240 set_globalState(StD); | |
241 break; | |
242 | |
243 default: | |
244 set_globalState(StD); | |
245 } | |
246 } | |
247 | |
248 if(sendAction == ACTION_BUTTON_ENTER) | |
249 { | |
250 if(settingsGetPointer()->design == 4) | |
251 return; | |
252 | |
253 if(settingsGetPointer()->design == 3) | |
254 settingsGetPointer()->design = 7; | |
255 | |
256 switch(get_globalState()) | |
257 { | |
258 case StDMGAS: | |
259 openEdit_DiveSelectBetterGas(); | |
260 set_globalState(StD); | |
261 break; | |
262 case StDMSPT: | |
263 openEdit_DiveSelectBetterSetpoint(); | |
264 set_globalState(StD); | |
265 break; | |
266 | |
267 case StDMENU: | |
268 openMenu_first_page_with_OC_gas_update(); | |
269 break; | |
270 | |
271 case StDSIM1: | |
272 Sim_Quit(); | |
273 break; | |
274 | |
275 case StDSIM2: | |
276 Sim_Ascend(); | |
277 break; | |
278 | |
279 case StDSIM3: | |
280 Sim_Descend(); | |
281 break; | |
282 | |
283 case StDSIM4: | |
284 Sim_Divetime(); | |
285 break; | |
286 | |
287 case StDBEAR: // t5_gauge | |
288 if(is_stateUsedSetToSim()) | |
289 stateSimGetPointerWrite()->diveSettings.compassHeading = (uint16_t)stateUsed->lifeData.compass_heading; | |
290 else | |
291 stateRealGetPointerWrite()->diveSettings.compassHeading = (uint16_t)stateUsed->lifeData.compass_heading; | |
292 set_globalState(StD); | |
293 break; | |
294 | |
295 case StDRAVG: // t5_gauge | |
296 timer_Stopwatch_Restart(); | |
297 set_globalState(StD); | |
298 break; | |
299 | |
300 case StDQUIT: // t6_apnea | |
301 set_globalState(StD); // used to end StDQUIT, is called before everything else because changes are made in the next lines | |
302 if(is_stateUsedSetToSim()) | |
303 Sim_Quit(); | |
304 else | |
305 dataOutGetPointer()->setEndDive = 1; | |
306 break; | |
307 | |
308 default: | |
309 break; | |
310 } | |
311 } | |
312 } | |
313 | |
314 | |
315 void tHome_findNextStop(const uint16_t *list, uint8_t *depthOutMeter, uint16_t *lengthOutSeconds) | |
316 { | |
317 uint8_t ptr = DECOINFO_STRUCT_MAX_STOPS - 1; | |
318 | |
319 while(ptr && !list[ptr]) | |
320 ptr--; | |
321 | |
322 *lengthOutSeconds = list[ptr]; | |
323 if(!(*lengthOutSeconds)) | |
324 { | |
325 *depthOutMeter = 0; | |
326 } | |
327 else | |
328 if(ptr == 0) | |
329 { | |
330 *depthOutMeter = (uint8_t)((stateUsed->diveSettings.last_stop_depth_bar*10.0f) + 0.1f); | |
331 } | |
332 else | |
333 { | |
334 ptr -= 1; | |
335 *depthOutMeter = (uint8_t)(((stateUsed->diveSettings.input_second_to_last_stop_depth_bar + (stateUsed->diveSettings.input_next_stop_increment_depth_bar * ptr))*10.0f) + 0.1f); | |
336 } | |
337 } | |
338 | |
339 | |
340 void tHome_change_field_button_pressed(void) | |
341 { | |
342 tHome_tick_count_field = 0; | |
343 if(settingsGetPointer()->design == 7) | |
344 t7_change_field(); | |
345 } | |
346 | |
347 | |
348 void tHome_change_customview_button_pressed(void) | |
349 { | |
350 tHome_tick_count_cview = 0; | |
351 if(settingsGetPointer()->design == 7) | |
352 t7_change_customview(); | |
353 else | |
354 if(settingsGetPointer()->design == 3) | |
355 t3_change_customview(); | |
356 else | |
357 if(settingsGetPointer()->design == 5) | |
358 t5_change_customview(); | |
359 else | |
360 if(settingsGetPointer()->design == 6) | |
361 t6_change_customview(); | |
362 } | |
363 | |
364 | |
365 void tHome_tick(void) | |
366 { | |
367 uint16_t field = settingsGetPointer()->tX_userselectedLeftLowerCornerTimeout; | |
368 uint16_t cview = settingsGetPointer()->tX_customViewTimeout; | |
369 | |
370 if(field) | |
371 { | |
372 tHome_tick_count_field++; | |
373 if(tHome_tick_count_field > (field * 10)) | |
374 { | |
375 tHome_tick_count_field = 0; | |
376 if(settingsGetPointer()->design == 7) | |
377 { | |
378 t7_set_field_to_primary(); | |
379 } | |
380 } | |
381 } | |
382 | |
383 if(cview) | |
384 { | |
385 tHome_tick_count_cview++; | |
386 if(tHome_tick_count_cview > (cview *10)) | |
387 { | |
388 tHome_tick_count_cview = 0; | |
389 if(settingsGetPointer()->design == 7) | |
390 { | |
391 t7_set_customview_to_primary(); | |
392 } | |
393 } | |
394 } | |
395 } | |
396 | |
397 | |
398 uint32_t tHome_DateCode(RTC_DateTypeDef *dateInput) | |
399 { | |
400 uint32_t answer = 0; | |
401 | |
402 answer = 0; | |
403 answer += (dateInput->Year & 0x7F)<< 9; | |
404 answer += (dateInput->Month & 0x0F)<< 5; | |
405 answer += (dateInput->Date & 0x1F); | |
406 | |
407 return answer; | |
408 } | |
409 | |
410 | |
411 uint8_t tHome_gas_writer(uint8_t oxygen_percentage, uint8_t helium_percentage, char *text) | |
412 { | |
413 if(oxygen_percentage == 100) | |
414 return (uint8_t) snprintf(text,10,"Oxy"); | |
415 else if((oxygen_percentage == 21) && (!helium_percentage)) | |
416 return (uint8_t) snprintf(text,10,"Air"); | |
417 else if(!helium_percentage) | |
418 return (uint8_t) snprintf(text,10,"NX%02i",oxygen_percentage); | |
419 else if((oxygen_percentage + helium_percentage) == 100) | |
420 return (uint8_t) snprintf(text,10,"HX%02i",oxygen_percentage); | |
421 else | |
422 return (uint8_t) snprintf(text,10,"%02i/%02i",oxygen_percentage,helium_percentage); | |
423 } | |
424 | |
425 uint8_t tHome_show_lost_connection_count(GFX_DrawCfgScreen *ScreenToWriteOn) | |
426 { | |
208 | 427 static uint8_t LastKnowRTEState = SPI_RX_STATE_INVALID; |
428 | |
99 | 429 if(!SPI_MIN_ERROR_SHOW) return 0; |
172
c659fda83e44
Minor: Button defaults, release date adjusted, use SPI_SHOW_SYNC_STATS
heinrichsweikamp
parents:
138
diff
changeset
|
430 if(DataEX_lost_connection_count()>=SPI_MIN_ERROR_SHOW && SPI_SHOW_SYNC_STATS){ |
38 | 431 |
99 | 432 char text[64]; |
38 | 433 |
82 | 434 SDataExchangeSlaveToMaster* dataIn=get_dataInPointer(); |
208 | 435 SDataReceiveFromMaster* pDataOut = dataOutGetPointer(); |
82 | 436 |
99 | 437 snprintf(text,32,"spi err:\002 %i/%i",DataEX_lost_connection_count(),get_num_SPI_CALLBACKS()); |
438 Gfx_write_label_var(ScreenToWriteOn, 100,300, 0,&FontT24,CLUT_ButtonSymbols,text); | |
82 | 439 |
104 | 440 // snprintf(text,32,"header:\002%X%X%X%X",dataIn->header.checkCode[0],dataIn->header.checkCode[1],dataIn->header.checkCode[2],dataIn->header.checkCode[3]); |
441 // Gfx_write_label_var(ScreenToWriteOn, 350,550, 0,&FontT24,CLUT_ButtonSymbols,text); | |
82 | 442 |
208 | 443 //snprintf(text,32,"footer:\002%X%X%X%X",dataIn->footer.checkCode[0],dataIn->footer.checkCode[1],dataIn->footer.checkCode[2],dataIn->footer.checkCode[3]); |
444 | |
445 /* data shifted => ignore received data */ | |
446 if((pDataOut->header.checkCode[SPI_HEADER_INDEX_RX_STATE] == SPI_RX_STATE_SHIFTED) || (pDataOut->header.checkCode[SPI_HEADER_INDEX_RX_STATE] == SPI_RX_STATE_OFFLINE)) | |
447 { | |
448 dataIn->header.checkCode[SPI_HEADER_INDEX_RX_STATE] = LastKnowRTEState; | |
449 } | |
450 else | |
451 { | |
452 LastKnowRTEState =dataIn->header.checkCode[SPI_HEADER_INDEX_RX_STATE]; | |
453 } | |
454 snprintf(text,32,"RX State M|R:\002%X|%X",pDataOut->header.checkCode[SPI_HEADER_INDEX_RX_STATE], dataIn->header.checkCode[SPI_HEADER_INDEX_RX_STATE] ); | |
99 | 455 Gfx_write_label_var(ScreenToWriteOn, 600,800, 0,&FontT24,CLUT_ButtonSymbols,text); |
456 } | |
82 | 457 |
99 | 458 |
459 | |
460 // snprintf(text,32,"cpt:\002%i",get_num_SPI_CALLBACKS()); | |
461 // Gfx_write_label_var(ScreenToWriteOn, 600,800, 90,&FontT24,CLUT_ButtonSymbols,text); | |
82 | 462 |
463 // snprintf(text,10,"i2c:\002%i",get_DataEX_Error_place()); | |
464 // Gfx_write_label_var(ScreenToWriteOn, 600,800, 90,&FontT24,CLUT_ButtonSymbols,text); | |
38 | 465 |
466 return DataEX_lost_connection_count(); | |
467 } |