Mercurial > public > hwos_code
diff src/adc_lightsensor.asm @ 0:11d4fc797f74
init
author | heinrichsweikamp |
---|---|
date | Wed, 24 Apr 2013 19:22:45 +0200 |
parents | |
children | 0e1723f2761e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/adc_lightsensor.asm Wed Apr 24 19:22:45 2013 +0200 @@ -0,0 +1,253 @@ +;============================================================================= +; +; File adc.asm +; +; +; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved. +;============================================================================= +; HISTORY +; 2011-08-08 : [mH] moving from OSTC code + +#include "ostc3.inc" +#include "math.inc" +#include "wait.inc" +#include "eeprom_rs232.inc" + +sensors CODE + +wait_adc: + movwf ADCON0 + nop + bsf ADCON0,1 ; start ADC +wait_adc2: + btfsc ADCON0,1 ; Wait... + bra wait_adc2 + return + + global get_battery_voltage +get_battery_voltage: ; starts ADC and waits until fnished + bsf adc_running ; =1: The ADC is in use + movlw b'00100000' ; 2.048V Vref+ -> 1LSB = 500µV + movwf ADCON1 + movlw b'00011001' ; power on ADC, select AN6 + rcall wait_adc + + movff ADRESH,batt_voltage+1 ; store value + movff ADRESL,batt_voltage+0 ; store value + bcf ADCON0,0 ; power off ADC + +; Multiply with 2,006 to be excact here... +; bcf STATUS,C +; rlcf xA+0,F +; +; rlcf xA+1,F ; x2 + +; movff xA+0,batt_voltage+0 ; store value +; movff xA+1,batt_voltage+1 + + movlw LOW lithium_36v_low + movwf sub_a+0 + movlw HIGH lithium_36v_low + movwf sub_a+1 + movff batt_voltage+0,sub_b+0 + movff batt_voltage+1,sub_b+1 + call subU16 ; sub_c = sub_a - sub_b +; Battery is 3,6V (>lithium_36v_low?) + btfss neg_flag + bra get_battery_voltage4 ; No, use 1,5V + + bsf battery_is_36v ; Yes, set flag (Cleared in power-on reset only!) + +; Check if the battery is near-dead already + movlw LOW lithium_36v_empty + movwf sub_a+0 + movlw HIGH lithium_36v_empty + movwf sub_a+1 + call subU16 ; sub_c = sub_a - sub_b +; Battery is not dead yet (>lithium_36v_empty?) + btfsc neg_flag + bra get_battery_voltage2 ; Yes, battery is still ok + + ; Battery is probably dead very soon + ; Set ">=24Ah used" into battery gauge registers + movlw .128 + movff WREG,battery_gauge+5 + +get_battery_voltage2: + ; Use 3,6V battery gauging mode + movff battery_gauge+5,xC+3 + movff battery_gauge+4,xC+2 + movff battery_gauge+3,xC+1 + movff battery_gauge+2,xC+0 + ; battery_gauge:6 is nAs + ; devide through 65536 + ; devide through 364 + ; Result is in percent of a 2,4Ah Battery + movlw LOW .364 + movwf xB+0 + movlw HIGH .364 + movwf xB+1 + call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder + movff xC+0,lo + ; Limit to 100 + movlw .100 + cpfslt lo + movwf lo + ; lo will be between 0 (Full) and 100 (empty) + movf lo,W + sublw .100 + movwf lo +get_battery_voltage3: + movlw .100 + cpfslt lo + movwf lo + ; lo will be between 100 (Full) and 0 (empty) + movf batt_percent,W + cpfsgt lo ; keep batt_percent on the lowest value found + movff lo,batt_percent ; store value + btfsc battery_is_36v ; but always use computed value for 3,6V battery + movff lo,batt_percent ; store value + bcf adc_running ; =1: The ADC is in use + return + +get_battery_voltage4: + ; Use 1,5V battery voltage mode + ; Use approximation (batt_voltage:2-aa_15v_low)/4 = lo + movff batt_voltage+0,sub_a+0 + movff batt_voltage+1,sub_a+1 + movlw LOW aa_15v_low + movwf sub_b+0 + movlw HIGH aa_15v_low + movwf sub_b+1 + call subU16 ; sub_c = sub_a - sub_b + bcf STATUS,C + rrcf sub_c+1 + rrcf sub_c+0 ; /2 + bcf STATUS,C + rrcf sub_c+1 + rrcf sub_c+0 ; /4 + movff sub_c+0,lo + bra get_battery_voltage3 ; Check limits and return + + global get_ambient_level +get_ambient_level: ; starts ADC and waits until finished + btfsc adc_running ; ADC in use? + return ; Yes, return + + movlw b'00000000' ; Vref+ = Vdd + movwf ADCON1 + movlw b'00011101' ; power on ADC, select AN7 + rcall wait_adc + + movff ADRESH,ambient_light+1 + movff ADRESL,ambient_light+0 + bcf ADCON0,0 ; power off ADC + + ; ambient_light:2 is between 4096 (direct sunlight) and about 200 (darkness) + ; First: Devide through 16 + bcf STATUS,C + rrcf ambient_light+1 + rrcf ambient_light+0 + bcf STATUS,C + rrcf ambient_light+1 + rrcf ambient_light+0 + bcf STATUS,C + rrcf ambient_light+1 + rrcf ambient_light+0 + bcf STATUS,C + rrcf ambient_light+1 + rrcf ambient_light+0 + ; Result: ambient_light:2/16 + ; Now, make sure to have value between ambient_light_low and ambient_light_max + + movlw .254 + tstfsz ambient_light+1 ; >255? + movwf ambient_light+0 ; avoid ADC clipping + + incfsz ambient_light+0,W ; =255? + bra get_ambient_level2 ; No, continue + + movlw .254 + movwf ambient_light+0 ; avoid ADC clipping + +get_ambient_level2: + banksel isr_backup ; Back to Bank0 ISR data + movff opt_brightness,isr1_temp + + btfsc RCSTA1,7 ; UART module on? + clrf isr1_temp ; Yes, set temporally to eco mode + + incf isr1_temp,F ; adjust 0-2 to 1-3 + + banksel common ; flag is in bank1 + movlw ambient_light_max_high ; brightest setting + btfsc battery_is_36v ; 3,6V battery in use? + movlw ambient_light_max_high_36V ; Yes... + banksel isr_backup ; Back to Bank0 ISR data + + dcfsnz isr1_temp,F + movlw ambient_light_max_eco ; brightest setting + dcfsnz isr1_temp,F + movlw ambient_light_max_medium; brightest setting + + banksel common ; ambient_light is in Bank1 + incf ambient_light+0,F ; +1 + cpfslt ambient_light+0 ; smaller then WREG? + movwf ambient_light+0 ; No, set to max. + + banksel isr_backup ; Back to Bank0 ISR data + movff opt_brightness,isr1_temp + incf isr1_temp,F ; adjust 0-2 to 1-3 + movlw ambient_light_min_high ; darkest setting + + dcfsnz isr1_temp,F + movlw ambient_light_min_eco ; darkest setting + dcfsnz isr1_temp,F + movlw ambient_light_min_medium; darkest setting + dcfsnz isr1_temp,F + movlw ambient_light_min_high ; darkest setting + + banksel common ; ambient_light is in Bank1 + cpfsgt ambient_light+0 ; bigger then WREG? + movwf ambient_light+0 ; No, set to min + + movff ambient_light+0,max_CCPR1L ; Store value for dimming in TMR7 interrupt + return + + global get_rssi_level +get_rssi_level: ; starts ADC and waits until fnished + bsf adc_running ; =1: The ADC is in use + movlw b'00100000' ; 2.048V Vref+ + movwf ADCON1 + movlw b'01000101' ; power on ADC, select AN17 + rcall wait_adc + + movff ADRESL,rssi_value + bcf ADCON0,0 ; power off ADC + bcf adc_running ; =1: The ADC is in use + return + + global reset_battery_pointer +reset_battery_pointer: ; Resets battery pointer 0x07-0x0C and battery_gauge:5 + clrf EEADRH + clrf EEDATA ; Delete to zero + write_int_eeprom 0x07 + write_int_eeprom 0x08 + write_int_eeprom 0x09 + write_int_eeprom 0x0A + write_int_eeprom 0x0B + write_int_eeprom 0x0C + banksel battery_gauge+0 + clrf battery_gauge+0 + clrf battery_gauge+1 + clrf battery_gauge+2 + clrf battery_gauge+3 + clrf battery_gauge+4 + clrf battery_gauge+5 + banksel common + movlw .100 + movwf batt_percent + return + + + END \ No newline at end of file