Mercurial > public > hwos_code
comparison src/rx_ops.asm @ 604:ca4556fb60b9
bump to 2.99beta, work on 3.00 stable
author | heinrichsweikamp |
---|---|
date | Thu, 22 Nov 2018 19:47:26 +0100 |
parents | |
children | c40025d8e750 |
comparison
equal
deleted
inserted
replaced
603:00b24fb4324d | 604:ca4556fb60b9 |
---|---|
1 ;============================================================================= | |
2 ; | |
3 ; File rx_ops.asm V2.99c | |
4 ; | |
5 ; RX (Tank Pressure Transmitter) Routines. | |
6 ; | |
7 ; Copyright (c) 2018, heinrichs weikamp, all right reserved. | |
8 ;============================================================================= | |
9 | |
10 #include "hwos.inc" ; mandatory header | |
11 #include "shared_definitions.h" ; mailbox to p2_deco.c | |
12 #include "i2c.inc" | |
13 #include "math.inc" | |
14 #include "isr.inc" | |
15 | |
16 extern get_first_gas_to_WREG | |
17 extern get_first_dil_to_WREG | |
18 | |
19 | |
20 ; SAC calculation averaging settings | |
21 #DEFINE time_accu_target_OC .60 ; [s] target time accumulator filling level in OC modes | |
22 #DEFINE time_accu_target_CCR .180; [s] target time accumulator filling level in CCR mode | |
23 | |
24 | |
25 rx_ops CODE | |
26 | |
27 IFDEF _rx_functions | |
28 | |
29 ;============================================================================= | |
30 ; Get configured pressure readings | |
31 ; | |
32 ; input : opt_TR_1st_pres - selector for first pressure reading, in normal mode | |
33 ; opt_TR_Bail_pres - selector for first pressure reading, in bailout mode | |
34 ; opt_TR_2nd_pres - selector for second pressure reading, all modes | |
35 ; | |
36 ; output: int_IO_pressure_value+0/+2 - pressure in 0.1 bar, low byte | |
37 ; int_IO_pressure_value+1/+3 - pressure in 0.1 bar, high byte, including data not available flag | |
38 ; char_I_pressure_gas +0/+1 - associated gas (1-5) / diluent (6-10) | |
39 ; char_I_pressure_age +0/+1 - age of data in seconds (max 60) | |
40 ; char_I_pressure_stat +0/+1 - status data | |
41 ; | |
42 global get_pressure_readings | |
43 get_pressure_readings: | |
44 call I2C_get_tankdata ; get raw pressure data | |
45 get_pressure_readings_1: | |
46 movff opt_TR_1st_pres,ul ; 1st pressure to read | |
47 btfsc FLAG_bailout_mode ; in bailout mode? | |
48 movff opt_TR_Bail_pres,ul ; YES - replace with assigned bailout selection | |
49 tstfsz ul ; disabled? | |
50 bra get_pressure_readings_1a ; NO - get received pressure data | |
51 rcall get_pressure_readings_H1 ; YES - set pressure data to not available | |
52 bra get_pressure_readings_1c ; - continue with copying to result vars | |
53 get_pressure_readings_1a: | |
54 movlw .11 ; first code for "special" pressures | |
55 cpfslt ul ; opt_TR_1st_pres < 11 ? | |
56 rcall get_pressure_readings_H2 ; NO - pre-process measurement selection | |
57 rcall get_pressure_readings_H3 ; get transmitter ID | |
58 rcall get_pres_by_transmitter_id ; get data from transmitter with ID in hi:lo into hi:lo (pressure) and up (status) | |
59 get_pressure_readings_1c: | |
60 movff lo,int_IO_pressure_value+0 ; copy pressure, low byte | |
61 movff hi,int_IO_pressure_value+1 ; copy pressure, high byte | |
62 movff ul,char_I_pressure_gas+0 ; copy associated gas number | |
63 movff up,char_I_pressure_age+0 ; copy age of data | |
64 movff ex,char_I_pressure_stat+0 ; copy status data | |
65 get_pressure_readings_2: | |
66 movff opt_TR_2nd_pres,ul ; 2nd pressure to read | |
67 tstfsz ul ; disabled? | |
68 bra get_pressure_readings_2a ; NO - get received pressure data | |
69 rcall get_pressure_readings_H1 ; YES - set pressure data to not available | |
70 bra get_pressure_readings_2c ; - continue with copying to result vars | |
71 get_pressure_readings_2a: | |
72 movlw .11 ; first code for "special" pressures | |
73 cpfslt ul ; opt_TR_2nd_pres < 11 ? | |
74 rcall get_pressure_readings_H2 ; NO - pre-process measurement selection | |
75 btfss ul,7 ; gas selector >= 127 (special treatment)? | |
76 bra get_pressure_readings_2b ; NO - proceed reading a pressure | |
77 rcall get_pressure_readings_H1 ; YES - set pressure data to not available | |
78 bra get_pressure_readings_2c ; - continue wit copying to output data | |
79 get_pressure_readings_2b: | |
80 rcall get_pressure_readings_H3 ; get transmitter ID | |
81 rcall get_pres_by_transmitter_id ; get data from transmitter with ID in hi:lo into hi:lo (pressure) and up (status) | |
82 get_pressure_readings_2c: | |
83 movff lo,int_IO_pressure_value+2 ; copy pressure, low byte | |
84 movff hi,int_IO_pressure_value+3 ; copy pressure, high byte | |
85 movff ul,char_I_pressure_gas+1 ; copy associated gas number | |
86 movff up,char_I_pressure_age+1 ; copy age of data | |
87 movff ex,char_I_pressure_stat+1 ; copy status data | |
88 return | |
89 | |
90 get_pressure_readings_H1: | |
91 clrf lo ; set pressure to 0 (low byte) | |
92 clrf hi ; set pressure to 0 (high byte) | |
93 clrf up ; set age to 0 | |
94 clrf ex ; set status to 0 | |
95 bsf hi,int_not_avail_flag ; set flag for data not available | |
96 return | |
97 | |
98 get_pressure_readings_H2: | |
99 movlw .11 | |
100 subwf ul,F | |
101 bnz get_pressure_readings_H2a | |
102 call get_first_gas_to_WREG ; ul = 11 -> ul = (get_first_gas_to_WREG) | |
103 movwf ul | |
104 return | |
105 get_pressure_readings_H2a: | |
106 decfsz ul,F | |
107 bra get_pressure_readings_H2b | |
108 movff active_gas,ul ; ul = 12 -> ul = active_gas | |
109 return | |
110 get_pressure_readings_H2b: | |
111 decfsz ul,F | |
112 bra get_pressure_readings_H2c | |
113 call get_first_dil_to_WREG ; ul = 13 -> ul = (get_first_dil_to_WREG) + 5 | |
114 movwf ul | |
115 movlw .5 | |
116 addwf ul,F | |
117 return | |
118 get_pressure_readings_H2c: | |
119 decfsz ul,F | |
120 bra get_pressure_readings_H2d | |
121 movff active_dil,ul ; ul = 14 -> ul = active_dil + 5 | |
122 movlw .5 | |
123 addwf ul,F | |
124 return | |
125 get_pressure_readings_H2d: | |
126 movlw .1 | |
127 movwf ul ; ul >= 15 -> should not happen, default to ul = 1 | |
128 return | |
129 | |
130 get_pressure_readings_H3: | |
131 lfsr FSR1,opt_transmitter_id_1 ; load base address of transmitter ID array | |
132 decf ul,W ; (1-10) -> (0-9) | |
133 mullw .2 ; IDs are 2 byte in size | |
134 movf PRODL,W ; WREG is index now | |
135 movff PLUSW1,lo ; get transmitter ID (low byte) | |
136 incf WREG,W ; increment index | |
137 movff PLUSW1,hi ; get transmitter ID (high byte) | |
138 return | |
139 | |
140 | |
141 ;============================================================================= | |
142 ; Get data from transmitter with ID in (hi:lo) | |
143 ; | |
144 ; input: hi:lo = transmitter ID | |
145 ; | |
146 ; output: hi:lo = pressure in 0.1 bar if return code = 0, else 0 + int_not_avail_flag | |
147 ; up = packet age if return code = 0, else 0 | |
148 ; ex = status data if return code = 0, else 0 | |
149 ; | |
150 ; return code: 0 transmitter found | |
151 ; 254 illegal transmitter ID | |
152 ; 255 transmitter not found | |
153 ; | |
154 ; RX slot data: Byte 0 : transmitter ID high byte | |
155 ; 1 : transmitter ID low byte | |
156 ; 2 (-> hi) : pressure in 0.1 bar, high byte | |
157 ; 3 (-> lo) : pressure in 0.1 bar, low byte | |
158 ; 4 (-> ex) : status data: | |
159 ; bit 2..0: battery status | |
160 ; 5..3: sequence counter | |
161 ; 6: =1 if pressure changed (usage in RX slot data) | |
162 ; =1 if transmitter not found (usage in output data) | |
163 ; 7: =1 if pressure sensed (usage in RX slot data) | |
164 ; =1 if low battery (< 3.0V) (usage in output data) | |
165 ; 5 (-> up) : age of data in seconds, 0 if slot is unused | |
166 ; | |
167 global get_pres_by_transmitter_id | |
168 get_pres_by_transmitter_id: | |
169 ; hi:lo zero? | |
170 tstfsz hi ; hi <> zero ? | |
171 bra output_pressure_1 ; YES - search transmitter | |
172 tstfsz lo ; lo <> zero ? | |
173 bra output_pressure_1 ; YES - search transmitter | |
174 movlw .254 ; NO to both - set return code for invalid transmitter ID | |
175 bra output_pressure_6 ; - clear result vars, set data as not available and return | |
176 output_pressure_1: | |
177 lfsr FSR1,rx_buffer ; load base address of RX buffer | |
178 movlw .8 ; 8 RX slots to look at | |
179 movwf up ; up will be the loop counter | |
180 output_pressure_2: | |
181 movf POSTINC1,W ; get high byte of received transmitter ID | |
182 cpfseq hi ; match? | |
183 bra output_pressure_3 ; NO - check next slot | |
184 movf POSTINC1,W ; get low byte byte received transmitter ID | |
185 cpfseq lo ; match? | |
186 bra output_pressure_4 ; NO - check next slot | |
187 ; transmitter found, gather data ; YES - transmitter found, copy: | |
188 movff POSTINC1,hi ; - pressure high byte, | |
189 movff POSTINC1,lo ; - pressure low byte, | |
190 movff POSTINC1,ex ; - status byte, and | |
191 movff POSTINC1,up ; - packet age. | |
192 movlw rx_packet_overdue_timeout ; - load overdue time | |
193 subwf up,W ; - subtract overdue time from packet age | |
194 btfss STATUS,N ; - result negative (packet younger than overdue time)? | |
195 bsf hi,int_outdated_flag ; NO - set outdated flag | |
196 bcf ex,char_transmitter_lost ; - clear transmitter lost flag | |
197 bsf ex,char_transmitter_low_bat ; - set low battery warning by default | |
198 btfsc ex,1 ; - bit 1 of battery voltage set? | |
199 bcf ex,char_transmitter_low_bat ; - YES - revoke low battery warning | |
200 btfsc ex,2 ; - bit 2 of battery voltage set? | |
201 bcf ex,char_transmitter_low_bat ; - YES - revoke low battery warning | |
202 ;bsf ex,char_transmitter_low_bat ; DEBUG CODE TO FAKE A LOW BAT WARNING | |
203 retlw .0 ; - return with success code 0 | |
204 output_pressure_3: | |
205 movf POSTINC1,W ; dummy read to advance FSR0 to byte 2 position | |
206 output_pressure_4: | |
207 dcfsnz up,F ; decrement loop counter, last slot searched? | |
208 bra output_pressure_5 ; YES - return with error code | |
209 movf POSTINC1,W ; NO - dummy reads to advance FSR0 to byte 3 (any other code would not be more compact...) | |
210 movf POSTINC1,W ; - ... byte 4 | |
211 movf POSTINC1,W ; - ... byte 5 | |
212 movf POSTINC1,W ; - ... byte 6 = first byte of next slot | |
213 bra output_pressure_2 ; - loop | |
214 output_pressure_5: | |
215 movlw .255 ; return code for transmitter not found | |
216 clrf ex ; clear ex (status data) | |
217 bsf ex,char_transmitter_lost ; set transmitter status to lost | |
218 bra output_pressure_7 | |
219 output_pressure_6: | |
220 clrf ex ; clear ex (status data) | |
221 output_pressure_7: | |
222 clrf lo ; clear lo (pressure, low byte) | |
223 clrf hi ; clear hi (pressure, high byte) | |
224 clrf up ; clear up (age of data) | |
225 bsf hi,int_not_avail_flag ; set flag for data not available | |
226 return ; done | |
227 | |
228 | |
229 ;============================================================================= | |
230 ; Get transmitter ID in given slot | |
231 ; | |
232 ; input : WREG = slot (0-7) | |
233 ; output : hi:lo = transmitter ID | |
234 ; | |
235 global get_transmitter_id_by_slot | |
236 get_transmitter_id_by_slot: | |
237 lfsr FSR1,rx_buffer ; load base address of RX buffer | |
238 mullw .6 ; multiply WREG with 6 because each slot is 6 bytes in size | |
239 movf PRODL,W ; get result into WREG to be used as index (product is 42 at max) | |
240 movff PLUSW1,hi ; read transmitter ID high byte | |
241 incf WREG,W ; increment index | |
242 movff PLUSW1,lo ; read transmitter ID low byte | |
243 return | |
244 | |
245 | |
246 ;============================================================================= | |
247 ; Compute average pressure drop from 1st / 2nd reading | |
248 ; | |
249 ; Memory Map: | |
250 ; ------------------------------------------------------------------------------------ | |
251 ; | |
252 ; pres_accu_1st res 4 ; accumulator for pressure drop in 1/(160 * 2^16) bar | |
253 ; pres_accu_2nd res 4 ; accumulator for pressure drop in 1/(160 * 2^16) bar | |
254 ; time_accu_1st res 1 ; accumulator for reading periods in seconds | |
255 ; gas__last_1st res 1 ; last gas assignment | |
256 ; time_accu_2nd res 1 ; accumulator for reading periods in seconds | |
257 ; gas__last_2nd res 1 ; last gas assignment | |
258 ; pres_last_1st res 2 ; last pressure reading pressure in 1/160 bar | |
259 ; pres_last_2nd res 2 ; last pressure reading pressure in 1/160 bar | |
260 ; time_last_1st res 2 ; last pressure reading time in seconds | |
261 ; time_last_2nd res 2 ; last pressure reading time in seconds | |
262 ; | |
263 ; int_IO_pressure_value [1] res 2 ; current pressure reading in 1/10 bar | |
264 ; int_IO_pressure_value [2] res 2 ; current pressure reading in 1/10 bar | |
265 ; int_I_pressure_drop [1] res 2 ; calculated average pressure drop in 1/5120 bar/sec | |
266 ; int_I_pressure_drop [2] res 2 ; calculated average pressure drop in 1/5120 bar/sec | |
267 | |
268 ; relative positioning of 16 bit ASM variables | |
269 #DEFINE offset_FSR1_time_accu .0 ; offset 0 == base address of 1st/2nd | |
270 #DEFINE offset_FSR1_gas__last .1 ; offset 1 to base address of 1st/2nd | |
271 #DEFINE offset_FSR1_pres_last .4 ; offset 4 ... | |
272 #DEFINE offset_FSR1_time_last .8 ; offset 8 ... | |
273 | |
274 ; relative positioning of shared integer variables | |
275 #DEFINE offset_FSR2_press_curr .0 ; offset 0 == base address of 1st/2nd | |
276 #DEFINE offset_FSR2_press_drop .4 ; offset 4 to base address of 1st/2nd | |
277 | |
278 | |
279 calc_pres_drop_1st: | |
280 ; set up base addresses | |
281 lfsr FSR0,pres_accu_1st-1 ; load base address - 1 of pressure accumulator | |
282 lfsr FSR1,time_accu_1st ; load base address of other ASM variables | |
283 lfsr FSR2,int_IO_pressure_value+0; load base address of the shared variables | |
284 | |
285 ; get the currently assigned gas into lo | |
286 movff char_I_pressure_gas+0,lo | |
287 | |
288 ; get the age of the current reading into hi | |
289 movff char_I_pressure_age+0,hi | |
290 | |
291 ; continue with common part | |
292 bra calc_pres_drop_common | |
293 | |
294 calc_pres_drop_2nd: | |
295 ; set up base addresses | |
296 lfsr FSR0,pres_accu_2nd-1 ; load base address - 1 of pressure accumulator | |
297 lfsr FSR1,time_accu_2nd ; load base address of other ASM variables | |
298 lfsr FSR2,int_IO_pressure_value+2; load base address of the shared variables | |
299 | |
300 ; get the currently assigned gas into lo | |
301 movff char_I_pressure_gas+1,lo | |
302 | |
303 ; get the age of the current reading into hi | |
304 movff char_I_pressure_age+1,hi | |
305 | |
306 calc_pres_drop_common: | |
307 ; load the pressure accumulator into xC - FSR0 has been initialized to base address -1 | |
308 movff PREINC0,xC+0 ; copy pressure accumulator to xC, lowest byte | |
309 movff PREINC0,xC+1 ; copy pressure accumulator to xC, second byte | |
310 movff PREINC0,xC+2 ; copy pressure accumulator to xC, third byte | |
311 movff PREINC0,xC+3 ; copy pressure accumulator to xC, highest byte | |
312 | |
313 ; check if the assigned gas has changed | |
314 movlw offset_FSR1_gas__last ; load index of last assigned gas | |
315 movf PLUSW1,W ; copy last gas to WREG | |
316 cpfseq lo ; is current gas = last gas ? | |
317 bra calc_pres_drop_reset ; NO - reset everything | |
318 | |
319 ; check if the pressure reading is activated at all | |
320 tstfsz lo ; is there no gas (0=off) assigned to the reading? | |
321 bra calc_pres_drop_common_1 ; NO - continue | |
322 bra calc_pres_drop_reset ; YES - reset everything | |
323 | |
324 calc_pres_drop_common_1: | |
325 ; load the time accumulator into xB | |
326 movff INDF1,xB+0 ; load time accumulator, low byte (had been stored) | |
327 clrf xB+1 ; clear time accumulator, high byte (will be reset to 0 each round) | |
328 | |
329 ; get the current pressure value into divA - after copying, FSR2 will have been restored to initial address | |
330 movff POSTINC2,divA+0 ; copy current pressure value to divA, low byte | |
331 movff POSTDEC2,divA+1 ; copy current pressure value to divA, high byte | |
332 | |
333 ; check if the current pressure value is available and not outdated | |
334 bsf aux_flag ; set the current pressure value as not available or outdated by default | |
335 btfsc divA+1,int_not_avail_flag ; current pressure value not available? | |
336 bra calc_pres_drop_common_2 ; YES - skip updating the accumulators with new data | |
337 btfsc divA+1,int_outdated_flag ; current pressure outdated? | |
338 bra calc_pres_drop_common_2 ; YES - skip updating the accumulators with new data | |
339 bcf aux_flag ; NO to both - set current pressure value as available and up-to-date | |
340 | |
341 ; check if a new reading has been received | |
342 movlw .2 ; capture new reading at an age of 2 (age 1 sometimes slips through...) | |
343 subwf hi,W ; subtract capture-age from reading age, dump result to WREG | |
344 bnz calc_pres_drop_common_2 ; result <> 0 ? YES - skip updating the accumulators | |
345 | |
346 ; multiply the current pressure with 16 (pre-scaling), this will also remove the flags | |
347 movlw .4 ; multiply with 16 = 2^4 | |
348 call mult16 ; divA = divA * 2^WREG | |
349 | |
350 ; get the last pressure value and store the current pressure as the new last pressure value | |
351 movlw offset_FSR1_pres_last+0 ; load index of last pressure value, low byte | |
352 movff PLUSW1,sub_b+0 ; copy last pressure value to sub_b, low byte | |
353 movff divA+0,PLUSW1 ; store current pressure value as new last pressure value, low byte | |
354 movlw offset_FSR1_pres_last+1 ; load index of last pressure value, high byte | |
355 movff PLUSW1,sub_b+1 ; copy last pressure value to sub_b, high byte | |
356 movff divA+1,PLUSW1 ; store current pressure value as new last pressure value, high byte | |
357 | |
358 ; add the last pressure value to the pressure accumulator: pres_accu (xC) += pres_last (sub_b) * 2^16 | |
359 movf sub_b+0,W ; copy pres_last (sub_b) to WREG, low byte | |
360 addwf xC+2,F ; add to pres_accu (xC), third byte | |
361 movf sub_b+1,W ; copy pres_last (sub_b) to WREG, high byte | |
362 addwfc xC+3,F ; add to pres_accu (xC), highest byte | |
363 | |
364 ; subtract the current pressure from the pressure accumulator: pres_accu (xC) -= pres_curr (divA) * 2^16 | |
365 ; -> effectively, the pressure drop during the last measurement period has been added now | |
366 bcf neg_flag ; clear neg_flag by default | |
367 movf divA+0,W ; copy pres_curr (divA) to WREG, low byte | |
368 subwf xC+2,F ; subtract from pres_accu (xC), third byte | |
369 movf divA+1,W ; copy pres_curr (divA) to WREG, high byte | |
370 subwfb xC+3,F ; subtract from pres_accu (xC), highest byte | |
371 btfss STATUS,C ; did the accumulator under-run (result negative)? | |
372 bsf neg_flag ; YES - memorize this | |
373 | |
374 ; get the current time into lo | |
375 SAFE_2BYTE_COPY total_divetime_seconds,lo ; get current total dive time into lo:2 | |
376 | |
377 ; get the last pressure time and store the current time as the new last pressure time | |
378 movlw offset_FSR1_time_last+0 ; load index of last pressure time, low byte | |
379 movff PLUSW1,sub_b+0 ; copy last pressure time to sub_b, low byte | |
380 movff lo+0,PLUSW1 ; store current time as new last pressure time, low byte | |
381 movlw offset_FSR1_time_last+1 ; load index of last pressure time, high byte | |
382 movff PLUSW1,sub_b+1 ; copy last pressure time to sub_b, high byte | |
383 movff lo+1,PLUSW1 ; store current time as new last pressure time, high byte | |
384 | |
385 ; did the pressure accumulator under-run before because the current pressure is higher than the accumulator value was? | |
386 ; we can not check & abort earlier because the current time needs to be stored along with the current pressure | |
387 btfsc neg_flag ; did the pressure accumulator under-run? | |
388 bra calc_pres_drop_restart ; YES - reset both accumulators and set average pressure drop to not available | |
389 | |
390 ; add the current time to the time accumulator: time_accu (xB) += time_curr (lo) | |
391 movf lo+0,W ; copy time_curr (lo) to WREG, low byte | |
392 addwf xB+0,F ; add to time_accu (xB), low byte | |
393 movf lo+1,W ; copy time_curr (lo) to WREG, high byte | |
394 addwfc xB+1,F ; add to time_accu (xB), high_byte | |
395 | |
396 ; subtract the last pressure time from time accumulator: time_accu (xB) -= time_last (sub_b) | |
397 movf sub_b+0,W ; copy time_last (sub_b) to WREG, low byte | |
398 subwf xB+0,F ; subtract from time_accu (xB), low byte | |
399 movf sub_b+1,W ; copy time_last (sub_b) to WREG, high byte | |
400 subwfb xB+1,F ; subtract from time_accu (xB), high byte | |
401 btfss STATUS,C ; did the accumulator under-run (result negative) because of a wrap-around of the current time? | |
402 bra calc_pres_drop_restart ; YES - reset both accumulators and set average pressure drop to not available | |
403 | |
404 ; check if the time accumulator (xB) is or has become too large | |
405 ; this will happen if the last valid pressure reading is older than (256 - time_accu target) seconds | |
406 tstfsz xB+1 ; is the time accumulator < 256 [seconds], i.e. high byte = 0 ? | |
407 bra calc_pres_drop_restart ; NO - reset both accumulators and set average pressure drop to not available | |
408 | |
409 calc_pres_drop_common_2: | |
410 ; check if the time accumulator is or has become zero to avoid a div/0 | |
411 ; as long as no valid pressure value is available, the time accumulator will stay at 0 and the pressure drop calculation kept in reset | |
412 movf xB+0,W ; copy time accumulator low byte to WREG, does it set the zero flag? | |
413 bz calc_pres_drop_restart ; YES - reset both accumulators and set average pressure drop to not available | |
414 | |
415 ; duplicate pressure and time accumulators to other variables because xC and xB will get destroyed in div32x16 operation | |
416 movff xC+0,lo+0 ; duplicate pres_accu to lo, lowest byte | |
417 movff xC+1,lo+1 ; duplicate pres_accu to lo, second byte | |
418 movff xC+2,lo+2 ; duplicate pres_accu to lo, third byte | |
419 movff xC+3,lo+3 ; duplicate pres_accu to lo, highest byte | |
420 movff xB+0,divA+0 ; duplicate time_accu to divA, low byte | |
421 movff xB+1,divA+1 ; duplicate time_accu to divA, high byte | |
422 | |
423 ; calculate average pressure drop: pres_drop (xC) = pres_accu (xC) / time_accu (xB) | |
424 call div32x16 ; xC = xC / xB, xC is average pressure drop in 1/(160 * 2^16) bar/sec | |
425 | |
426 ; is the time accumulator above target level? (only the low byte needs to be evaluated)? | |
427 incf ul,W ; load the target threshold, +1 (incf) transforms cpfslt from < to <= operation | |
428 cpfslt divA+0 ; is the time accumulator > target threshold ? | |
429 rcall calc_pres_drop_reduce_accus ; YES - do an accumulator reduction | |
430 | |
431 ; do an additional half-rate (every 2nd second) accumulator reduction | |
432 btfsc total_divetime_seconds+0,0 ; are we on an even second? | |
433 rcall calc_pres_drop_reduce_accus ; YES - do an additional accumulator reduction | |
434 | |
435 ; store pressure accumulator (lo:4) - FSR0 was left pointing to address of highest byte | |
436 movff lo+3,POSTDEC0 ; store pressure accumulator, highest byte | |
437 movff lo+2,POSTDEC0 ; store pressure accumulator, third byte | |
438 movff lo+1,POSTDEC0 ; store pressure accumulator, second byte | |
439 movff lo+0,POSTDEC0 ; store pressure accumulator, lowest byte | |
440 | |
441 ; store the time accumulator | |
442 movff divA+0,INDF1 ; store time accumulator (only the low byte will be stored) | |
443 | |
444 ; check if the average pressure drop for transfer to p2deco needs to be limited | |
445 tstfsz xC+3 ; check if the highest byte is all zero | |
446 bra calc_pres_drop_limit ; NO - limit output | |
447 btfsc xC+2,7 ; check if the highest bit of the third byte is zero | |
448 bra calc_pres_drop_limit ; NO - limit output | |
449 | |
450 ; pick and adjust the bytes from pres_drop for transfer to p2deco | |
451 movff xC+1,divA+0 ; pick second byte of average pressure drop for transfer to p2deco as low byte | |
452 movff xC+2,divA+1 ; pick third byte of average pressure drop for transfer to p2deco as high byte | |
453 movlw .3 ; divide by 8 = 2^3 | |
454 call div16 ; divA = divA / 2^WREG | |
455 bra calc_pres_drop_common_3 | |
456 | |
457 calc_pres_drop_limit: | |
458 ; limit output to 0x0FFF | |
459 movlw LOW 0x0FFF ; set output to 0x0FFF | |
460 movwf divA+0 ; ... | |
461 movlw HIGH 0x0FFF ; ... | |
462 movwf divA+1 ; ... | |
463 bsf divA+1,int_warning_flag ; set warning flag indicating out-of-range | |
464 | |
465 calc_pres_drop_common_3: | |
466 ; set the average pressure drop as not available if the last pressure reading is outdated or not available | |
467 btfsc aux_flag ; is the last pressure reading outdated or not available? | |
468 bsf divA+1,int_not_avail_flag ; YES - set pressure drop to not available, too | |
469 | |
470 ; set the average pressure drop as outdated if time_accu (divA) < (target threshold / 2) | |
471 rrncf ul,W ; load time accumulator target value / 2 into WREG | |
472 decf WREG,W ; subtract 1 to transform cpfsgt from > to >= operation | |
473 cpfsgt INDF1 ; time accumulator < (target threshold / 2) ? | |
474 bsf divA+1,int_outdated_flag ; YES - set outdated flag | |
475 | |
476 ; write average pressure drop to p2deco interface | |
477 movlw offset_FSR2_press_drop+0 ; load index of average pressure drop, low byte | |
478 movff divA+0,PLUSW2 ; store average pressure drop, low byte | |
479 movlw offset_FSR2_press_drop+1 ; load index of average pressure drop, high byte | |
480 movff divA+1,PLUSW2 ; store average pressure drop, high byte | |
481 | |
482 ; done | |
483 return | |
484 | |
485 | |
486 calc_pres_drop_reduce_accus: | |
487 ; subtract 1 second from the time accumulator: time_accu (divA) -= 1 (only the low byte needs to be processed) | |
488 decf divA+0,F ; decrement low byte of time_accu | |
489 | |
490 ; subtract average pressure drop per second from pressure accumulator: press_accu (lo) -= press_drop (xC) | |
491 movf xC+0,W ; copy press_drop(xC) to WREG, lowest byte | |
492 subwf lo+0,F ; subtract from pres_accu, lowest byte | |
493 movf xC+1,W ; copy press_drop(xC) to WREG, second byte | |
494 subwfb lo+1,F ; subtract from pres_accu, second byte | |
495 movf xC+2,W ; copy press_drop(xC) to WREG, third byte | |
496 subwfb lo+2,F ; subtract from pres_accu, third byte | |
497 movf xC+3,W ; copy press_drop(xC) to WREG, highest byte | |
498 subwfb lo+3,F ; subtract from pres_accu, highest byte | |
499 btfsc STATUS,C ; did the buffer under-run (result negative)? | |
500 return ; NO - done | |
501 clrf lo+0 ; YES - clear pressure accumulator, lowest byte | |
502 clrf lo+1 ; - clear pressure accumulator, second byte | |
503 clrf lo+2 ; - clear pressure accumulator, third byte | |
504 clrf lo+3 ; - clear pressure accumulator, highest byte | |
505 return ; - done | |
506 | |
507 calc_pres_drop_reset: | |
508 ; store the current gas as the last gas | |
509 movlw offset_FSR1_gas__last ; load index of last gas | |
510 movff lo,PLUSW1 ; store current gas as new last gas | |
511 | |
512 ; clear last pressure value | |
513 movlw offset_FSR1_pres_last+0 ; load index of last pressure value, low byte | |
514 clrf PLUSW1 ; clear last pressure value, low byte | |
515 movlw offset_FSR1_pres_last+1 ; load index of last pressure value, high byte | |
516 clrf PLUSW1 ; clear last pressure value, high byte | |
517 | |
518 ; clear last pressure time | |
519 movlw offset_FSR1_time_last+0 ; load index of last pressure time, low byte | |
520 clrf PLUSW1 ; clear last pressure time, low byte | |
521 movlw offset_FSR1_time_last+1 ; load index of last pressure time, high byte | |
522 clrf PLUSW1 ; clear last pressure time, high byte | |
523 | |
524 calc_pres_drop_restart: | |
525 ; clear pressure accumulator - FSR0 was left pointing to address of highest byte | |
526 clrf POSTDEC0 ; clear pressure accumulator, highest byte | |
527 clrf POSTDEC0 ; clear pressure accumulator, third byte | |
528 clrf POSTDEC0 ; clear pressure accumulator, second byte | |
529 clrf POSTDEC0 ; clear pressure accumulator, lowest byte | |
530 | |
531 ; clear time accumulator | |
532 clrf INDF1 ; clear time accumulator | |
533 | |
534 ; clear pressure drop and set it to not available | |
535 movlw offset_FSR2_press_drop+0 ; load index of average pressure drop, low byte | |
536 clrf PLUSW2 ; clear average pressure drop, low byte | |
537 movlw offset_FSR2_press_drop+1 ; load index of average pressure drop, high byte | |
538 clrf PLUSW2 ; clear average pressure drop, high byte | |
539 bsf PLUSW2,int_not_avail_flag ; set flag for data not available | |
540 | |
541 return ; done | |
542 | |
543 | |
544 ;============================================================================= | |
545 ; set up SAC calculation dependent on TR mode | |
546 ; | |
547 global configure_sac_calculation | |
548 configure_sac_calculation: | |
549 movlw time_accu_target_OC ; load time accumulator target value for OC as default | |
550 movwf ul ; store it in ul | |
551 movff opt_TR_mode,WREG ; get TR mode | |
552 dcfsnz WREG,W ; TR mode = 1 (on)? | |
553 bra configure_sac_calculation_1 ; YES | |
554 dcfsnz WREG,W ; TR mode = 2 (ind.double)? | |
555 bra configure_sac_calculation_2 ; YES | |
556 dcfsnz WREG,W ; TR mode = 3 (CCR Dil+O2)? | |
557 bra configure_sac_calculation_3 ; YES | |
558 bra configure_sac_calculation_4 ; NO to all - was disabled then (or invalid) | |
559 | |
560 configure_sac_calculation_1: ; TR mode 1: calculate SAC on 1st reading | |
561 rcall calc_pres_drop_1st ; calculate pressure drop on 1st reading | |
562 movlw .1 ; select SAC mode 1: SAC on 1st reading | |
563 bra configure_sac_calculation_5 ; goto exit | |
564 | |
565 configure_sac_calculation_2: ; TR mode 2: independent double | |
566 rcall calc_pres_drop_1st ; calculate pressure drop on 1st reading | |
567 rcall calc_pres_drop_2nd ; calculate pressure drop on 2nd reading | |
568 movlw .3 ; select SAC mode 3: SAC on higher of both readings | |
569 bra configure_sac_calculation_5 ; goto exit | |
570 | |
571 configure_sac_calculation_3: ; TR mode 3: CCR Dil+O2 | |
572 btfsc FLAG_bailout_mode ; in bailout? | |
573 bra configure_sac_calculation_1 ; YES - handle alike TR mode 1 | |
574 movlw time_accu_target_CCR ; load time accumulator target value for CCR mode | |
575 movwf ul ; store it in ul | |
576 rcall calc_pres_drop_2nd ; calculate pressure drop on 2nd reading | |
577 movlw .4 ; select SAC mode 4: SAC on 2nd reading, O2 usage | |
578 bra configure_sac_calculation_5 ; goto exit | |
579 | |
580 configure_sac_calculation_4: | |
581 clrf WREG ; select SAC mode 0 (disabled) | |
582 | |
583 configure_sac_calculation_5: | |
584 movff WREG,char_I_SAC_mode ; write SAC mode selection | |
585 return | |
586 | |
587 ;============================================================================= | |
588 | |
589 ENDIF | |
590 | |
591 END |