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 |
