;N.B. all sub routines must RETURN with memory BANK 0 selected ;N.B. lower and higher nibbles are LCD nibbles, but they are stored in two bytes ;because bytes also contain status of LCD_E and LCD_RS signals #include ; __CONFIG(_HS_OSC & _WDT_OFF & _MCLRE_OFF & _BOREN_OFF & _LVP_OFF & _CP_OFF); org 0x0000 goto MAIN_INIT org 0x0004 goto MY_INTERRUPT_HANDLER; ; ;--- MY_FLAGS --- #define SKC 5 ;Skip capture bit #define CAP 4 ;Capture mode on = 1, off = 0 #define U4B 3 ;Write upper four bits (high nibble) #define SKF 2 ;Skip frame bit #define WRT 1 ;Ready for writing bit #define LCDE 0 ;LCD Enable bit ;--- MY_MEASUREMENT --- #define AL_T1OF 4 ;allow timer 1 overflow #define DISA 3 ;display all digits #define FSTM 2 ;First measurement #define MR_0 1 ;MR[1:0] measurement range, 00 = pF, 01 = nF, 10 = uF, 11 = F #define MR_1 0 ;First digit ;-- MY_ERRORS bits -- #define OVERFLOW 0 ;Math overflow #define UNDERFLOW 1 ;Math negative value (underflow) #define DIV0 2 ;Division by zero #define BIGCAP 3 ;Capacitance overflow ; ; ;binary constants #define b00000000 0x00 #define b00000001 0x01 #define b00000011 0x03 #define b00000100 0x04 #define b00000101 0x05 #define b00000110 0x06 #define b00000111 0x07 #define b00001000 0x08 #define b00001010 0x0A #define b00001111 0x0f #define b00010000 0x10 #define b00011000 0x18 #define b00011111 0x1F #define b00100000 0x20 #define b00100111 0x27 #define b00110000 0x30 #define b00110110 0x36 #define b00111011 0x3B #define b01000000 0x40 #define b01000010 0x42 #define b01010101 0x55 #define b01100000 0x60 #define b01100100 0x64 #define b01110000 0x70 #define b10000000 0x80 #define b10000110 0x86 #define b10010110 0x96 #define b10011000 0x98 #define b10011010 0x9A #define b10100000 0xA0 #define b10101010 0xAA #define b11001010 0xCA #define b11000000 0xC0 #define b11100001 0xE1 #define b11101000 0xE8 #define b11110000 0xF0 #define b11110101 0xF5 #define b11111111 0xFF; ; ;Timer constants #define TMR_DELTA 0xF0 ;start at: 255 - x, overflow on 255+1 ; ; ;RAM data variables bank 0 cblock 0x20 ;bank 0x20, 80 bytes general purpose register MATH_RES3 ;MATH_R3...0 32 bits unsigned int 'RESULT' MATH_RES2 MATH_RES1 MATH_RES0 MATH_TMPA3 ;MATH_TMPA3...0 32 bits unsigned int 'TMPA' MATH_TMPA2 MATH_TMPA1 MATH_TMPA0 MATH_TMPB3 ;MATH_TMPB3...0 32 bits unsigned int 'TMPB' MATH_TMPB2 MATH_TMPB1 MATH_TMPB0 MATH_A3 ;MATH_A3...0 32 bits unsigned int 'A' MATH_A2 MATH_A1 MATH_A0 MATH_B3 ;MATH_B3...0 32 bits unsigned int 'B' MATH_B2 MATH_B1 MATH_B0 MATH_C3 ;MATH_C3...0 32 bits unsigned int 'C' MATH_C2 MATH_C1 MATH_C0 MATH_D3 ;MATH_D3...0 32 bits unsigned int 'D' MATH_D2 MATH_D1 MATH_D0 MATH_REM3 ;MATH_REM3...0 32 bits unsigned int 'MATH_REM' MATH_REM2 MATH_REM1 MATH_REM0 Mx_Cap3 ;Mx_Cap3...0 32 bits unsigned int 'Mx_Cap' Mx_Cap2 Mx_Cap1 Mx_Cap0 Mx_REF3 ;Mx_REF3...0 32 bits unsigned int 'Mx_REF' Mx_REF2 Mx_REF1 Mx_REF0 C_REF3 ;C_REF3...0 32 bits unsigned int 'C_REF' C_REF2 C_REF1 C_REF0 LCD_DIV3 ;LCD_DIV3..0 32 bits unsigned int 'LCD_DIV' LCD_DIV2 LCD_DIV1 LCD_DIV0 W_TEMP STATUS_TEMP MY_ERRORS MY_FLAGS MY_MEASUREMENT LCD_BUF_00 LCD_BUF_01 LCD_BUF_02 LCD_BUF_03 LCD_BUF_04 LCD_BUF_05 LCD_BUF_06 LCD_BUF_07 CNT_VAR DLY_VAR CNT0 CNT1 CNT2 CNT3 TMR1IF_C1 ;TMR1IF_C1...0 16 bits unsigend int: number of timer1 time-outs TMR1IF_C0 CNT_RW ;number of items in LCD_BUF LCD_TMP ;buffer for tmp lcd data CAP_NR1 ;CAP_NR1...0 16 bit capture number CAP_NR0 MATH_BS ;number of bits shifted LCD_C0 ;LCD_C0...LCD_C5 6 lcd characters LCD_C1 LCD_C2 LCD_C3 LCD_C4 LCD_C5 endc; ; MAIN_INIT: ;--- select bank 0 --- BCF STATUS, RP0; BCF STATUS, RP1; BCF MY_ERRORS, UNDERFLOW CLRF PORTA; CLRF PORTB; CLRF MY_FLAGS CLRF W_TEMP CLRF STATUS_TEMP CLRF CNT_RW CLRF LCD_BUF_00 CLRF LCD_BUF_01 CLRF LCD_BUF_02 CLRF LCD_BUF_03 CLRF LCD_BUF_04 CLRF LCD_BUF_05 CLRF LCD_BUF_06 CLRF LCD_BUF_07 CLRF LCD_TMP CLRF DLY_VAR CLRF CNT0 CLRF CNT1 CLRF CNT2 CLRF CNT3 CLRF Mx_REF3 CLRF Mx_REF2 CLRF Mx_REF1 CLRF Mx_REF0 ;--- select bank 1 --- BSF STATUS, RP0 CLRF INTCON ;GIE PEIE T0IE INTE RBIE T0IF INTF RBIF CLRF PIE1 ;EEIE CMIE RCIE TXIE xxx CCP1IE TMR2IE TMR1IE MOVLW b11000000 ;RA0...RA5 as outputs MOVWF TRISA ;TRISA, bank 1 MOVLW b00000000 ;RB0...RB7 as outputs MOVWF TRISB ;TRISB, bank 1 ;--- select bank 0 --- BCF STATUS, RP0 ; CLRF PIR1 ;EEIF CMIF RCIF TXIF xxx CCP1IF TMR2IF TMR1IF ;MOVLW 0x00 ;MOVWF MATH_A3 ;MOVLW 0x01 ;MOVWF MATH_A2 ;MOVLW 0x21 ;MOVWF MATH_A1 ;MOVLW 0x11 ;MOVWF MATH_A0 ;MOVLW 0x00 ;MOVWF MATH_B3 ;MOVLW 0x01 ;MOVWF MATH_B2 ;MOVLW 0x31 ;MOVWF MATH_B1 ;MOVLW 0x11 ;MOVWF MATH_B0 ;call calc_a_minus_b CALL start_lcd_timer ;RS => is wired to RB0 ;E => is wired to RB1 ;Wait for more than 30ms ;after VDD rises to 4.5v MOVLW 0x80 ;wait > 30 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec ; ;N: 0 = 1-line mode , 1 = 2-line mode ;F: 0 = 5 x 7 dots, 1 = 5 x 10 dots ; ;RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ;0 0 0 0 1 0 X X X X ;0 0 0 0 1 0 X X X X ;0 0 N F X X X X X X CALL init_write_mode; MOVLW b00100000 ; MOVWF LCD_BUF_00 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVLW b00100000 ; MOVWF LCD_BUF_01 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVLW b01000000 ; MOVWF LCD_BUF_02 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVLW b01000000 ; MOVWF LCD_BUF_03 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW BSF MY_FLAGS, WRT ;ready for writing data bank 0 MOVLW 0x80 ;wait >100 msec MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec ; ;D: 0 display off, 1 display on ;C: 0 cursor off, 1 cursor on ;B: 0 blink off, 1 blink on ;RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ;0 0 0 0 0 0 X X X X ;0 0 1 D C B X X X X CALL init_write_mode; MOVLW b00000000 ; MOVWF LCD_BUF_00 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVLW b11000000 ; MOVWF LCD_BUF_01 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW BSF MY_FLAGS, WRT ;ready for writing data bank 0 MOVLW 0x80 ;wait >50 msec MOVWF DLY_VAR ;move w to DLY_VAR bank 0 CALL delay_msec; ;Clear Display ;RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ;0 0 0 0 0 0 X X X X ;0 0 0 0 0 1 X X X X CALL init_write_mode; MOVLW b00000000 ; MOVWF LCD_BUF_00 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVLW b00010000 ; MOVWF LCD_BUF_01 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW BSF MY_FLAGS, WRT ;ready for writing data bank 0 MOVLW 0x80 ;wait >50 msec MOVWF DLY_VAR ;move w to DLY_VAR bank 0 CALL delay_msec ; ;I/D: 0 decrement mode, 1 increment mode ;SH: 0 entire shift off, 1 entire shift on ;RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ;0 0 0 0 0 0 X X X X ;0 0 0 1 I/D SH X X X X CALL init_write_mode; MOVLW b00000000 ; MOVWF LCD_BUF_00 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVLW b01100000 ; MOVWF LCD_BUF_01 ;move w to LCD_BUFxx bank 0 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW BSF MY_FLAGS, WRT ;ready for writing data bank 0 MOVLW 0x80 ;wait >100 msec MOVWF DLY_VAR ;move w to DLY_VAR bank 0 CALL delay_msec BSF MY_MEASUREMENT, FSTM ;first measurement ;; ; MAIN_LOOP: BCF MY_MEASUREMENT, AL_T1OF ;don't allow T10F ; MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0x70 ;'p' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x46 ;'F' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x6D ;'m' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x65 ;'e' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x61 ;'a' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x73 ;'s' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x75 ;'u' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x72 ;'r' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x69 ;'i' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x6E ;'n' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x67 ;'g' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x2e ;'.' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x2e ;'.' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char ; BCF MY_MEASUREMENT, MR_0 BCF MY_MEASUREMENT, MR_1 measuring: MOVLW 0x00 MOVWF Mx_Cap3 MOVWF Mx_Cap2 MOVWF Mx_Cap1 MOVWF Mx_Cap0 CALL init_capture_compare_module ; WAIT_FOR_MEASUREMENT: btfsc MY_FLAGS, CAP GOTO WAIT_FOR_MEASUREMENT ;--- select bank 1 --- BSF STATUS, RP0 BCF PIE1, CCP1IE ;bank 1, disable CCP1 Interrupt Enable BCF PIE1, TMR1IE ;bank 1, disable timer 1 interrupts ;--- select bank 0 --- BCF STATUS, RP0 BCF T1CON, TMR1ON ;bank 0, stop timer 1 ; ; check_measurement: btfss MY_ERRORS, BIGCAP GOTO display_measurement_init BTFSC MY_MEASUREMENT, MR_1 ; uF or uF2? GOTO check_measurement_uF_mF BTFSC MY_MEASUREMENT, MR_0 ; pF? GOTO check_measurement_nF BCF MY_MEASUREMENT, MR_1 ; try nF BSF MY_MEASUREMENT, MR_0 CALL start_lcd_timer MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0x6E ;'n' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x46 ;'F' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec goto measuring check_measurement_nF: BSF MY_MEASUREMENT, MR_1 ; try uF BCF MY_MEASUREMENT, MR_0 CALL start_lcd_timer MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0xe4 ;'u' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x46 ;'F' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec goto measuring check_measurement_uF_mF: BTFSC MY_MEASUREMENT, MR_0 ; uF? GOTO check_measurement_too_big BSF MY_MEASUREMENT, MR_1 ; try mF BSF MY_MEASUREMENT, MR_0 BSF MY_MEASUREMENT, AL_T1OF ;allow T10F MOVLW 0x00 MOVWF TMR1IF_C1 MOVWF TMR1IF_C0 CALL start_lcd_timer MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0xe4 ;'u' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x46 ;'F' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x32 ;'2' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec goto measuring check_measurement_too_big: ; ; CALL start_lcd_timer MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0x42 ;'B' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x49 ;'I' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x47 ;'G' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x43 ;'C' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x41 ;'A' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x50 ;'P' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x41 ;'A' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x43 ;'C' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x49 ;'I' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x54 ;'T' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x4F ;'O' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x52 ;'R' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char GOTO MAIN_LOOP_END; ; display_measurement_init: ;2 ln(2)RC = 270pF x 10000k = 76656.5329924855 ticks BTFSS MY_MEASUREMENT, FSTM GOTO display_measurement MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'Mx_REF' MOVWF Mx_REF3 MOVF Mx_Cap2, 0; MOVWF Mx_REF2 MOVF Mx_Cap1, 0; MOVWF Mx_REF1 MOVF Mx_Cap0, 0; MOVWF Mx_REF0 MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'MATH_B' MOVWF MATH_B3 MOVF Mx_Cap2, 0; MOVWF MATH_B2 MOVF Mx_Cap1, 0; MOVWF MATH_B1 MOVF Mx_Cap0, 0; MOVWF MATH_B0 ;(2700x2) x measurement Mx / (2x 76656.5) => to keep significance MOVLW 0x00 MOVWF MATH_A3 MOVWF MATH_A2 MOVLW 0x15 MOVWF MATH_A1 MOVLW 0x18 MOVWF MATH_A0 call calc_a_times_b call copy_result_to_math_a ;2x 76656.5 = 153313 = 0x256E1 MOVLW 0x00 MOVWF MATH_B3 MOVLW 0x02 MOVWF MATH_B2 MOVLW 0x56 MOVWF MATH_B1 MOVLW 0xE1 MOVWF MATH_B0 call calc_a_divided_by_b MOVF MATH_RES3, 0 ;copy 'MATH_RES' to 'Mx_REF' MOVWF C_REF3 MOVF MATH_RES2, 0; MOVWF C_REF2 MOVF MATH_RES1, 0; MOVWF C_REF1 MOVF MATH_RES0, 0; MOVWF C_REF0 MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'MATH_A' MOVWF MATH_A3 MOVWF MATH_B3 MOVF Mx_Cap2, 0; MOVWF MATH_A2 MOVWF MATH_B2 MOVF Mx_Cap1, 0; MOVWF MATH_A1 MOVWF MATH_B1 MOVF Mx_Cap0, 0; MOVWF MATH_A0 MOVWF MATH_B0 call calc_a_plus_b MOVF MATH_RES3, 0 ;copy 'MATH_RES' to 'Mx_Cap' MOVWF Mx_Cap3 MOVF MATH_RES2, 0; MOVWF Mx_Cap2 MOVF MATH_RES1, 0; MOVWF Mx_Cap1 MOVF MATH_RES0, 0; MOVWF Mx_Cap0 BCF MY_MEASUREMENT, FSTM display_measurement: MOVF Mx_Cap3, 0 ;copy 'Mx_Cap3' to 'MATH_REM' MOVWF MATH_REM3 MOVF Mx_Cap2, 0; MOVWF MATH_REM2 MOVF Mx_Cap1, 0; MOVWF MATH_REM1 MOVF Mx_Cap0, 0; MOVWF MATH_REM0 CALL clear_lcd_char_buffer MOVLW 0x4d ;'M' MOVWF LCD_C0 MOVLW 0x78 ;'x' MOVWF LCD_C1 MOVLW 0x3d ;'=' MOVWF LCD_C3 CALL display_sub_value MOVLW 0x00 ;copy '0x00 0x00 CAP_NR1 CAP_NR0' to 'REM_A' MOVWF MATH_REM3 MOVWF MATH_REM2 MOVF CAP_NR1, 0 ;bank 0, CAP_NR1 MOVWF MATH_REM1 MOVF CAP_NR0, 0 ;bank 0, CAP_NR0 MOVWF MATH_REM0 CALL clear_lcd_char_buffer MOVLW 0x4e ;'N' MOVWF LCD_C0 MOVLW 0x78 ;'x' MOVWF LCD_C1 MOVLW 0x3d ;'=' MOVWF LCD_C3 CALL display_sub_value MOVF Mx_Cap3, 0 ;copy 'Mx_Cap3' to 'MATH_RES' MOVWF MATH_RES3 MOVF Mx_Cap2, 0; MOVWF MATH_RES2 MOVF Mx_Cap1, 0; MOVWF MATH_RES1 MOVF Mx_Cap0, 0; MOVWF MATH_RES0 BTFSC MY_MEASUREMENT, MR_1 ; uF or uF2? GOTO correction_uF_uF2 BTFSC MY_MEASUREMENT, MR_0 ; pF? GOTO correction_nF call calc_measured_minus_reference call calc_multiply_result_by_100 GOTO calc_div_mxref_times_cref correction_nF: call copy_result_to_math_b ;Capture mode, every 4th rising edge (factor 4) ;prescale 1:2 (factor 2) ;2 x 4 = 8 MOVLW 0x00 ;copy '8' to 'MATH_A' MOVWF MATH_A3 MOVLW 0x00 MOVWF MATH_A2 MOVLW 0x00 MOVWF MATH_A1 MOVLW 0x08 MOVWF MATH_A0 CALL calc_a_times_b GOTO set_corrected_measurement correction_uF_uF2: BTFSC MY_MEASUREMENT, MR_0 ; uF2? GOTO correction_uF2 correction_uF: call copy_result_to_math_b MOVLW 0x00 MOVWF MATH_A3 MOVLW 0x00 MOVWF MATH_A2 MOVLW 0x00 MOVWF MATH_A1 MOVLW 0x40 ; 16 * 4 = 64 = 0x40 MOVWF MATH_A0 CALL calc_a_times_b GOTO set_corrected_measurement correction_uF2: MOVF Mx_Cap3, 0 ANDLW 0xFF BTFSS STATUS, Z ;if Mx_Cap3 == 0, then Z == 0 GOTO correction_uF2_B3_GT_ZERO ;skip if Z==1 => Mx_Cap3 == 0 MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'MATH_A' MOVWF MATH_A3 MOVF Mx_Cap2, 0; MOVWF MATH_A2 MOVF Mx_Cap1, 0; MOVWF MATH_A1 MOVF Mx_Cap0, 0; MOVWF MATH_A0 MOVLW 0x00 ;copy '0x00 0x00 CAP_NR1 CAP_NR0' to 'MATH_A' MOVWF MATH_B3 MOVWF MATH_B2 MOVF CAP_NR1, 0 ;bank 0, CAP_NR1 MOVWF MATH_B1 MOVF CAP_NR0, 0 ;bank 0, CAP_NR0 MOVWF MATH_B0 call calc_a_divided_by_b call copy_result_to_math_a MOVLW 0x00 ;copy '128' to 'MATH_B' MOVWF MATH_B3 MOVWF MATH_B2 MOVWF MATH_B1 MOVLW 0x80 MOVWF MATH_B0 call calc_a_times_b ;MOVF MATH_RES3, 0 ;copy 'Mx_Cap3' to 'MATH_REM' ;MOVWF MATH_REM3 ;MOVF MATH_RES2, 0; ;MOVWF MATH_REM2 ;MOVF MATH_RES1, 0; ;MOVWF MATH_REM1 ;MOVF MATH_RES0, 0; ;MOVWF MATH_REM0 ;CALL display_sub_value MOVF MATH_RES2, 0 ;multiply 256 MOVWF MATH_RES3 MOVF MATH_RES1, 0 MOVWF MATH_RES2 MOVF MATH_RES0, 0 MOVWF MATH_RES1 MOVLW 0x00 MOVWF MATH_RES0 call copy_result_to_math_a MOVF Mx_REF3, 0 ;copy 'Mx_REF' to 'MATH_B' MOVWF MATH_B3 MOVF Mx_REF2, 0; MOVWF MATH_B2 MOVF Mx_REF1, 0; MOVWF MATH_B1 MOVF Mx_REF0, 0; MOVWF MATH_B0 call calc_a_minus_b CALL calc_divide_result_by_Mx_ref call calc_divide_a_by_100 call calc_multiply_result_by_Cref GOTO display_result_for_uF2 correction_uF2_B3_GT_ZERO: MOVLW 0x00 ;copy 'Mx_Cap / 256' to 'MATH_A' MOVWF MATH_A3 MOVF Mx_Cap3, 0 MOVWF MATH_A2 MOVF Mx_Cap2, 0; MOVWF MATH_A1 MOVF Mx_Cap1, 0; MOVWF MATH_A0 MOVLW 0x00 ;copy '0x00 0x00 CAP_NR1 CAP_NR0' to 'MATH_A' MOVWF MATH_B3 MOVWF MATH_B2 MOVF CAP_NR1, 0 ;bank 0, CAP_NR1 MOVWF MATH_B1 MOVF CAP_NR0, 0 ;bank 0, CAP_NR0 MOVWF MATH_B0 call calc_a_divided_by_b ;MOVLW 0x00 ;copy '0x00 0x00 CAP_NR1 CAP_NR0' to 'MATH_REM' ;MOVWF MATH_REM3 ;MOVWF MATH_REM2 ;MOVF CAP_NR1, 0; ;MOVWF MATH_REM1 ;MOVF CAP_NR0, 0; ;MOVWF MATH_REM0 ;CALL display_sub_value call copy_result_to_math_a MOVLW 0x00 ;copy '128' to 'MATH_B' MOVWF MATH_B3 MOVWF MATH_B2 MOVWF MATH_B1 MOVLW 0x80 MOVWF MATH_B0 call calc_a_times_b MOVF MATH_RES2, 0 ;copy 'MATH_RES' * 256 to 'MATH_A' MOVWF MATH_A3 MOVF MATH_RES1, 0 MOVWF MATH_A2 MOVF MATH_RES0, 0 MOVWF MATH_A1 MOVLW 0x00 MOVWF MATH_A0 MOVLW 0x00 ;copy 'CAP_REF / 256' to 'MATH_B' MOVWF MATH_B3 MOVF Mx_REF3, 0 MOVWF MATH_B2 MOVF Mx_REF2, 0; MOVWF MATH_B1 MOVF Mx_REF1, 0; MOVWF MATH_B0 call calc_a_minus_b CALL calc_divide_result_by_Mx_ref MOVF MATH_RES2, 0 ;multiply 256 MOVWF MATH_RES3 MOVF MATH_RES1, 0 MOVWF MATH_RES2 MOVF MATH_RES0, 0 MOVWF MATH_RES1 MOVLW 0x00 MOVWF MATH_RES0 call calc_divide_a_by_100 call calc_multiply_result_by_Cref GOTO display_result_for_uF2 set_corrected_measurement: MOVF MATH_RES3, 0 ;copy 'MATH_RES' to 'Mx_Cap' (corrected measurement value) MOVWF Mx_Cap3 MOVF MATH_RES2, 0; MOVWF Mx_Cap2 MOVF MATH_RES1, 0; MOVWF Mx_Cap1 MOVF MATH_RES0, 0; MOVWF Mx_Cap0 call calc_measured_minus_reference calc_div_mxref_times_cref: MOVF MATH_RES3, 0; ADDLW 0xFF BTFSC STATUS, C ;>= 0x01_XX_XX_XX, then first divide then multiply GOTO first_divide_then_multiply MOVF MATH_RES2, 0; ADDLW 0xE7 BTFSC STATUS, C ;bigger than 0xXX_18_XX_XX, then first divide then multiply GOTO first_divide_then_multiply first_multiply_then_divide: call calc_multiply_result_by_Cref call calc_divide_result_by_Mx_ref GOTO display_result_for_uF2 first_divide_then_multiply: call calc_divide_result_by_Mx_ref call calc_multiply_result_by_Cref display_result_for_uF2: CALL copy_result_to_remainder CALL start_lcd_timer CALL display_measured_value ; MAIN_LOOP_END: CALL wait_a_while goto MAIN_LOOP ;--- end MAIN_LOOP --- ; ; calc_measured_minus_reference: MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'MATH_A' MOVWF MATH_A3 MOVF Mx_Cap2, 0; MOVWF MATH_A2 MOVF Mx_Cap1, 0; MOVWF MATH_A1 MOVF Mx_Cap0, 0; MOVWF MATH_A0 MOVF Mx_REF3, 0 ;copy 'CAP_REF' to 'MATH_B' MOVWF MATH_B3 MOVF Mx_REF2, 0; MOVWF MATH_B2 MOVF Mx_REF1, 0; MOVWF MATH_B1 MOVF Mx_REF0, 0; MOVWF MATH_B0 CALL calc_a_minus_b BTFSS MY_ERRORS, UNDERFLOW GOTO abs_result MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'MATH_B' MOVWF MATH_B3 MOVF Mx_Cap2, 0; MOVWF MATH_B2 MOVF Mx_Cap1, 0; MOVWF MATH_B1 MOVF Mx_Cap0, 0; MOVWF MATH_B0 MOVF Mx_REF3, 0 ;copy 'CAP_REF' to 'MATH_A' MOVWF MATH_A3 MOVF Mx_REF2, 0; MOVWF MATH_A2 MOVF Mx_REF1, 0; MOVWF MATH_A1 MOVF Mx_REF0, 0; MOVWF MATH_A0 CALL calc_a_minus_b abs_result: return;; ; calc_multiply_result_by_100: call copy_result_to_math_b MOVLW 0x00 MOVWF MATH_A3 MOVLW 0x00 MOVWF MATH_A2 MOVLW 0x00 MOVWF MATH_A1 MOVLW 0x64 MOVWF MATH_A0 CALL calc_a_times_b return; ; calc_multiply_result_by_Cref: call copy_result_to_math_a MOVF C_REF3, 0 ;copy 'C_REF' to 'MATH_B' MOVWF MATH_B3 MOVF C_REF2, 0 MOVWF MATH_B2 MOVF C_REF1, 0 MOVWF MATH_B1 MOVF C_REF0, 0 MOVWF MATH_B0 CALL calc_a_times_b return; ; calc_divide_a_by_100: call copy_result_to_math_a MOVLW 0x00 ;copy '100' to 'MATH_B' MOVWF MATH_B3 MOVWF MATH_B2 MOVWF MATH_B1 MOVLW 0x64 MOVWF MATH_B0 CALL calc_a_divided_by_b return; ; calc_divide_result_by_Mx_ref: call copy_result_to_math_a MOVF Mx_REF3, 0 ;copy 'CAP_REF' to 'MATH_B' MOVWF MATH_B3 MOVF Mx_REF2, 0; MOVWF MATH_B2 MOVF Mx_REF1, 0; MOVWF MATH_B1 MOVF Mx_REF0, 0; MOVWF MATH_B0 CALL calc_a_divided_by_b RETURN; ; clear_lcd_char_buffer: MOVLW 0x20 ;fill with space character MOVWF LCD_C0 MOVWF LCD_C1 MOVWF LCD_C2 MOVWF LCD_C3 MOVWF LCD_C4 MOVWF LCD_C5 RETURN; ; display_lcd_value: MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position BCF MY_MEASUREMENT, DISA ;don't display all digits MOVF LCD_C0, 0 ;MOVLW 0x43 ;'C' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVF LCD_C1, 0 ;MOVLW 0x61 ;'a' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVF LCD_C2, 0 ;MOVLW 0x6c ;'l' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVF LCD_C3, 0 ;MOVLW 0x63 ;'c' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVF LCD_C4, 0 ;MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char ;1000000000 = 0x3B9ACA00 = b00111011100110101100101000000000 = 10^9 MOVLW b00111011 MOVWF LCD_DIV3 MOVLW b10011010 MOVWF LCD_DIV2 MOVLW b11001010 MOVWF LCD_DIV1 MOVLW b00000000 MOVWF LCD_DIV0 CALL calc_char_n ;100000000 = 0x5F5E100 = b00000101 11110101 11100001 00000000 = 10^8 MOVLW b00000101 MOVWF LCD_DIV3 MOVLW b11110101 MOVWF LCD_DIV2 MOVLW b11100001 MOVWF LCD_DIV1 MOVLW b00000000 MOVWF LCD_DIV0 CALL calc_char_n ;100000000 = 0x989680 = b00000000 10011000 10010110 10000000 = 10^7 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b10011000 MOVWF LCD_DIV2 MOVLW b10010110 MOVWF LCD_DIV1 MOVLW b10000000 MOVWF LCD_DIV0 CALL calc_char_n ;1000000 = 0xF4240 = b00000000 00001111 01000010 01000000 = 10^6 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00001111 MOVWF LCD_DIV2 MOVLW b01000010 MOVWF LCD_DIV1 MOVLW b01000000 MOVWF LCD_DIV0 CALL calc_char_n ;100000 = 186A0 = b00000001 10000110 10100000 = 10^5 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000001 MOVWF LCD_DIV2 MOVLW b10000110 MOVWF LCD_DIV1 MOVLW b10100000 MOVWF LCD_DIV0 CALL calc_char_n ;10000 = 0x2710 = b00000000 00000000 00100111 00010000 = 10^4 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00100111 MOVWF LCD_DIV1 MOVLW b00010000 MOVWF LCD_DIV0 CALL calc_char_n ;1000 = 0x3E8 = b00000000 00000000 00000011 11101000 = 10^3 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000011 MOVWF LCD_DIV1 MOVLW b11101000 MOVWF LCD_DIV0 CALL calc_char_n ;100 = 0x64 = b00000000 00000000 00000000 01100100 = 10^2 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000000 MOVWF LCD_DIV1 MOVLW b01100100 MOVWF LCD_DIV0 CALL calc_char_n ;10 = 0x0a = b00000000 00000000 00000000 00001010 = 10^1 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000000 MOVWF LCD_DIV1 MOVLW b00001010 MOVWF LCD_DIV0 CALL calc_char_n BSF MY_MEASUREMENT, DISA ;display all digits ;1 = 0x01 = b00000000 00000000 00000000 00000001 = 10^0 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000000 MOVWF LCD_DIV1 MOVLW b00000001 MOVWF LCD_DIV0 CALL calc_char_n RETURN ; ; display_measured_value: MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position BCF MY_MEASUREMENT, DISA ;don't display all digits display_digit_n_9: ;1000000000 = 0x3B9ACA00 = b00111011100110101100101000000000 = 10^9 MOVLW b00111011 MOVWF LCD_DIV3 MOVLW b10011010 MOVWF LCD_DIV2 MOVLW b11001010 MOVWF LCD_DIV1 MOVLW b00000000 MOVWF LCD_DIV0 CALL calc_char_n display_digit_n_8: ;100000000 = 0x5F5E100 = b00000101 11110101 11100001 00000000 = 10^8 MOVLW b00000101 MOVWF LCD_DIV3 MOVLW b11110101 MOVWF LCD_DIV2 MOVLW b11100001 MOVWF LCD_DIV1 MOVLW b00000000 MOVWF LCD_DIV0 CALL calc_char_n BTFSS MY_MEASUREMENT, MR_1 ;uF or uF2? skip GOTO display_digit_n_7 BTFSS MY_MEASUREMENT, MR_0 ;uF2? skip BSF MY_MEASUREMENT, DISA ;display all digits display_digit_n_7: ;100000000 = 0x989680 = b00000000 10011000 10010110 10000000 = 10^7 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b10011000 MOVWF LCD_DIV2 MOVLW b10010110 MOVWF LCD_DIV1 MOVLW b10000000 MOVWF LCD_DIV0 CALL calc_char_n BTFSS MY_MEASUREMENT, MR_1 ;uF or uF2? skip GOTO display_digit_n_6 BTFSC MY_MEASUREMENT, MR_0 ;uF? skip GOTO display_digit_n_6 MOVLW 0x2e ;'.' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char display_digit_n_6: ;1000000 = 0xF4240 = b00000000 00001111 01000010 01000000 = 10^6 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00001111 MOVWF LCD_DIV2 MOVLW b01000010 MOVWF LCD_DIV1 MOVLW b01000000 MOVWF LCD_DIV0 CALL calc_char_n BTFSS MY_MEASUREMENT, MR_1 ;uF or uF2? GOTO display_digit_n_5 BTFSS MY_MEASUREMENT, MR_0 ;uF2? GOTO display_digit_n_5 BTFSC MY_MEASUREMENT, MR_0 ;uF2 display all digits display_digit_n_5: ;100000 = 186A0 = b00000001 10000110 10100000 = 10^5 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000001 MOVWF LCD_DIV2 MOVLW b10000110 MOVWF LCD_DIV1 MOVLW b10100000 MOVWF LCD_DIV0 CALL calc_char_n BTFSC MY_MEASUREMENT, MR_1 ;nF or pF? GOTO display_digit_n_4a BTFSC MY_MEASUREMENT, MR_0 ;nF display all digits BSF MY_MEASUREMENT, DISA GOTO display_digit_n_4 display_digit_n_4a: BTFSS MY_MEASUREMENT, MR_0 ;uF2? set . char GOTO display_digit_n_4 MOVLW 0x2e ;'.' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char display_digit_n_4: ;10000 = 0x2710 = b00000000 00000000 00100111 00010000 = 10^4 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00100111 MOVWF LCD_DIV1 MOVLW b00010000 MOVWF LCD_DIV0 CALL calc_char_n ;display '.' for nF value BTFSC MY_MEASUREMENT, MR_1 ;nF or pF? GOTO display_digit_n_3 BSF MY_MEASUREMENT, DISA BTFSS MY_MEASUREMENT, MR_0 ;nF? skip GOTO display_digit_n_3 MOVLW 0x2e ;'.' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char display_digit_n_3: ;1000 = 0x3E8 = b00000000 00000000 00000011 11101000 = 10^3 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000011 MOVWF LCD_DIV1 MOVLW b11101000 MOVWF LCD_DIV0 CALL calc_char_n BTFSC MY_MEASUREMENT, MR_1 ;nF or pF? skip GOTO display_digit_n_2 BTFSC MY_MEASUREMENT, MR_0 ;pF? skip GOTO display_digit_n_2 BSF MY_MEASUREMENT, DISA ;display all digits MOVLW 0x2e ;'.' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char display_digit_n_2: ;100 = 0x64 = b00000000 00000000 00000000 01100100 = 10^2 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000000 MOVWF LCD_DIV1 MOVLW b01100100 MOVWF LCD_DIV0 CALL calc_char_n display_digit_n_1: ;10 = 0x0a = b00000000 00000000 00000000 00001010 = 10^1 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000000 MOVWF LCD_DIV1 MOVLW b00001010 MOVWF LCD_DIV0 CALL calc_char_n display_digit_n: ;1 = 0x01 = b00000000 00000000 00000000 00000001 = 10^0 MOVLW b00000000 MOVWF LCD_DIV3 MOVLW b00000000 MOVWF LCD_DIV2 MOVLW b00000000 MOVWF LCD_DIV1 MOVLW b00000001 MOVWF LCD_DIV0 CALL calc_char_n MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char BTFSC MY_MEASUREMENT, MR_1 GOTO display_digit_uf MOVLW 0x70 ;'p' BTFSC MY_MEASUREMENT, MR_0 MOVLW 0x6E ;'n' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char GOTO display_digit_f display_digit_uf: MOVLW 0xe4 ;'u' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char display_digit_f: MOVLW 0x46 ;'F' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char RETURN ; ; display_sub_value: MOVF MATH_A3, 0 ;copy 'MATH_A' to 'MATH_C' MOVWF MATH_C3 MOVF MATH_A2, 0; MOVWF MATH_C2 MOVF MATH_A1, 0; MOVWF MATH_C1 MOVF MATH_A0, 0; MOVWF MATH_C0 MOVF MATH_B3, 0 ;copy 'MATH_B' to 'MATH_D' MOVWF MATH_D3 MOVF MATH_B2, 0; MOVWF MATH_D2 MOVF MATH_B1, 0; MOVWF MATH_D1 MOVF MATH_B0, 0; MOVWF MATH_D0 CALL start_lcd_timer CALL display_lcd_value; CALL wait_a_while BCF INTCON, T0IE ;INTCON disable timer 0 overflow MOVF MATH_C3, 0 ;copy 'MATH_C' to 'MATH_A' MOVWF MATH_A3 MOVF MATH_C2, 0; MOVWF MATH_A2 MOVF MATH_C1, 0; MOVWF MATH_A1 MOVF MATH_C0, 0; MOVWF MATH_A0 MOVF MATH_D3, 0 ;copy 'MATH_D' to 'MATH_B' MOVWF MATH_B3 MOVF MATH_D2, 0; MOVWF MATH_B2 MOVF MATH_D1, 0; MOVWF MATH_B1 MOVF MATH_D0, 0; MOVWF MATH_B0 RETURN; ; wait_a_while: MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec RETURN;; ; copy_result_to_math_a: MOVF MATH_RES3, 0 ;copy 'MATH_RES' to 'MATH_A' MOVWF MATH_A3 MOVF MATH_RES2, 0; MOVWF MATH_A2 MOVF MATH_RES1, 0; MOVWF MATH_A1 MOVF MATH_RES0, 0; MOVWF MATH_A0 RETURN ; ; copy_result_to_math_b: MOVF MATH_RES3, 0 ;copy 'MATH_RES' to 'MATH_B' MOVWF MATH_B3 MOVF MATH_RES2, 0; MOVWF MATH_B2 MOVF MATH_RES1, 0; MOVWF MATH_B1 MOVF MATH_RES0, 0; MOVWF MATH_B0 RETURN ; ; copy_result_to_remainder: MOVF MATH_RES3, 0 ;copy 'MATH_RES' to 'MATH_REM' MOVWF MATH_REM3 MOVF MATH_RES2, 0; MOVWF MATH_REM2 MOVF MATH_RES1, 0; MOVWF MATH_REM1 MOVF MATH_RES0, 0; MOVWF MATH_REM0 RETURN ; ; ;--- copy 'A' to 'TMP' and clear result copy_a_to_tmp_and_clear_result: MOVF MATH_A3, 0 ;copy 'A' to 'TMP' MOVWF MATH_TMPA3 MOVF MATH_A2, 0 MOVWF MATH_TMPA2 MOVF MATH_A1, 0 MOVWF MATH_TMPA1 MOVF MATH_A0, 0 MOVWF MATH_TMPA0 MOVLW b00000000 MOVWF MATH_RES0 ;clear 'RES' MOVWF MATH_RES1 MOVWF MATH_RES2 MOVWF MATH_RES3 RETURN ;--- endd copy 'A' to 'TMP' and clear result ; ; ;--- calc_a_plus_b --- calc_a_plus_b: BCF MY_ERRORS, OVERFLOW ;clear overflow flag BCF MY_ERRORS, UNDERFLOW ;clear UNDERFLOW flag CALL copy_a_to_tmp_and_clear_result calc_a_plus_b_b0: MOVF MATH_B0, 0 ;move MATH_B0 to W addwf MATH_TMPA0, 1 ;add W to TMP0 and store result in TMP0 btfss STATUS, C ;If result > 255 C=1 goto calc_a_plus_b_b1 INCFSZ MATH_TMPA1, 1 ;increment TMP1, skip if zero goto calc_a_plus_b_b1; INCFSZ MATH_TMPA2, 1 ;increment TMP2, skip if zero goto calc_a_plus_b_b1; INCFSZ MATH_TMPA3, 1 ;increment TMP3, skip if zero goto calc_a_plus_b_b1 goto calc_a_plus_b_overflow ;overflow occured calc_a_plus_b_b1: MOVF MATH_B1, 0 ;move MATH_B1 to W addwf MATH_TMPA1, 1 ;add W to TMP1 and store result in TMP1 btfss STATUS, C ;If result > 255 C=1 goto calc_a_plus_b_b2 INCFSZ MATH_TMPA2, 1 ;increment TMP2, skip if zero goto calc_a_plus_b_b2; INCFSZ MATH_TMPA3, 1 ;increment TMP3 and store result in TMP3 goto calc_a_plus_b_b2 goto calc_a_plus_b_overflow ;overflow occured calc_a_plus_b_b2: MOVF MATH_B2, 0 ;move MATH_B2 to W addwf MATH_TMPA2, 1 ;add W from TMP2 and store result in TMP2 btfss STATUS, C ;If result > 255 C=1 goto calc_a_plus_b_b3 INCFSZ MATH_TMPA3, 1 ;increment TMP3, skip if zero goto calc_a_plus_b_b3 goto calc_a_plus_b_overflow ;overflow occured calc_a_plus_b_b3: MOVF MATH_B3, 0 ;move MATH_B3 to W addwf MATH_TMPA3, 1 ;add W to TMP3 and store result in TMP3 btfsc STATUS, C ;If result > 255 C=1 goto calc_a_plus_b_overflow ; MOVF MATH_TMPA3, 0 ;copy MATH_TMP to MATH_RES MOVWF MATH_RES3 MOVF MATH_TMPA2, 0 MOVWF MATH_RES2 MOVF MATH_TMPA1, 0 MOVWF MATH_RES1 MOVF MATH_TMPA0, 0 MOVWF MATH_RES0 calc_a_plus_b_end: RETURN; calc_a_plus_b_overflow: MOVLW 0x00; MOVWF MATH_RES3 MOVWF MATH_RES2 MOVWF MATH_RES1 MOVWF MATH_RES0 BSF MY_ERRORS, OVERFLOW RETURN ; ; ;--- calc_a_minus_b --- calc_a_minus_b: BCF MY_ERRORS, OVERFLOW ;clear overflow flag BCF MY_ERRORS, UNDERFLOW ;clear UNDERFLOW flag CALL copy_a_to_tmp_and_clear_result calc_a_minus_b_b0: MOVF MATH_B0, 0 ;move MATH_B0 to W subwf MATH_TMPA0, 1 ;subtract W from TMP0 and store result in TMP0 ;If result is negative then C=0, Z=0 ;If result is positive then C=1, Z=0 ;If result is zero then C=1, Z=1 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_b1 MOVLW 0x01 ;decrement TMP1 subwf MATH_TMPA1, 1 ;subtract W from TMP1 and store result in TMP1 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_b1; MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA2, 1 ;subtract W from TMP2 and store result in TMP2 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_b1; MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_underflow; calc_a_minus_b_b1: MOVF MATH_B1, 0 ;move MATH_B1 to W subwf MATH_TMPA1, 1 ;subtract W from TMP1 and store result in TMP1 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_b2 MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA2, 1 ;subtract W from TMP2 and store result in TMP2 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_b2; MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_underflow; calc_a_minus_b_b2: MOVF MATH_B2, 0 ;move MATH_B2 to W subwf MATH_TMPA2, 1 ;subtract W from TMP2 and store result in TMP2 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_b3 MOVLW 0x01 ;decrement TMP3 subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_underflow; calc_a_minus_b_b3: MOVF MATH_B3, 0 ;move MATH_B3 to W subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_minus_b_copy_result calc_a_minus_b_underflow: BSF MY_ERRORS, UNDERFLOW ;set UNDERFLOW flag calc_a_minus_b_copy_result: MOVF MATH_TMPA3, 0 MOVWF MATH_RES3 MOVF MATH_TMPA2, 0 MOVWF MATH_RES2 MOVF MATH_TMPA1, 0 MOVWF MATH_RES1 MOVF MATH_TMPA0, 0 MOVWF MATH_RES0 calc_a_minus_b_end: RETURN ;--- end calc_a_minus_b ---; ; ;--- calc_a_divided_by_b --- calc_a_divided_by_b: CALL copy_a_to_tmp_and_clear_result MOVF MATH_B3, 0 ;copy 'B' to 'TMPB' MOVWF MATH_TMPB3 MOVF MATH_B2, 0 MOVWF MATH_TMPB2 MOVF MATH_B1, 0 MOVWF MATH_TMPB1 MOVF MATH_B0, 0 MOVWF MATH_TMPB0 division_by_n: MOVF MATH_TMPB3, 0 ANDLW 0xFF BTFSS STATUS, Z GOTO calc_a_divided_by_b_b0 MOVF MATH_TMPB2, 0 ANDLW 0xFF BTFSS STATUS, Z GOTO calc_a_divided_by_b_b0 MOVF MATH_TMPB1, 0 ANDLW 0xFF BTFSS STATUS, Z GOTO calc_a_divided_by_b_b0 MOVF MATH_TMPB0, 0 XORLW 0x01 BTFSS STATUS, Z GOTO test_division_by_zero division_by_one: ;A / 1 = A MOVF MATH_A3, 0 ;copy 'A' to 'RES' MOVWF MATH_RES3 MOVF MATH_A2, 0 MOVWF MATH_RES2 MOVF MATH_A1, 0 MOVWF MATH_RES1 MOVF MATH_A0, 0 MOVWF MATH_RES0 RETURN test_division_by_zero: MOVF MATH_TMPB0, 0 ANDLW 0xFF BTFSS STATUS, Z GOTO calc_a_divided_by_b_b0 BSF MY_ERRORS, OVERFLOW ;set overflow flag CALL start_lcd_timer MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0x44 ;'D' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x49 ;'I' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x56 ;'V' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x5A ;'Z' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x45 ;'E' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x52 ;'R' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x4F ;'O' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec MOVLW 0xff ;wait 255 msec; MOVWF DLY_VAR ;DLY_VAR bank 0 CALL delay_msec BCF INTCON, T0IE ;INTCON disable timer 0 overflow GOTO calc_a_divided_by_b_end calc_a_divided_by_b_b0: MOVF MATH_TMPB0, 0 ;move MATH_TMPB0 to W subwf MATH_TMPA0, 1 ;subtract W from TMP0 and store result in TMP0 ;If result is negative then C=0, Z=0 ;If result is positive then C=1, Z=0 ;If result is zero then C=1, Z=1 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_b1 MOVLW 0x01 ;decrement TMP1 subwf MATH_TMPA1, 1 ;subtract W from TMP1 and store result in TMP1 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_b1; MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA2, 1 ;subtract W from TMP2 and store result in TMP2 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_b1; MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_end; calc_a_divided_by_b_b1: MOVF MATH_TMPB1, 0 ;move MATH_TMPB1 to W subwf MATH_TMPA1, 1 ;subtract W from TMP1 and store result in TMP1 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_b2 MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA2, 1 ;subtract W from TMP2 and store result in TMP2 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_b2; MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_end; calc_a_divided_by_b_b2: MOVF MATH_TMPB2, 0 ;move MATH_TMPB2 to W subwf MATH_TMPA2, 1 ;subtract W from TMP2 and store result in TMP2 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_b3 MOVLW 0x01 ;decrement TMP3 subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_end; calc_a_divided_by_b_b3: MOVF MATH_TMPB3, 0 ;move MATH_TMPB3 to W subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_divided_by_b_end; incf MATH_RES0, 1 ;increment MATH_RES0 btfss STATUS, Z ;on overflow, Z=1 goto calc_a_divided_by_b_b0 ;try another subtraction incf MATH_RES1, 1 ;increment MATH_RES1 btfss STATUS, Z ;on overflow, Z=1 goto calc_a_divided_by_b_b0 ;try another subtraction incf MATH_RES2, 1 ;increment MATH_RES2 btfss STATUS, Z ;on overflow, Z=1 goto calc_a_divided_by_b_b0 ;try another subtraction incf MATH_RES3, 1 ;increment MATH_RES3 btfss STATUS, Z ;on overflow, Z=1 goto calc_a_divided_by_b_b0 ;try another subtraction BSF MY_ERRORS, OVERFLOW ;set overflow flag calc_a_divided_by_b_end: RETURN ;--- calc_a_divided_by_b ---; ; ;--- calc_a_times_b --- ;if a is bigger than b, you'd better swap them (perfomance tip) ;TMP0 contains current number of runs calc_a_times_b: CALL copy_a_to_tmp_and_clear_result calc_a_times_b_run: ;decrement, if < 0 then stop adding MOVLW 0x01 ;decrement TMP0 subwf MATH_TMPA0, 1 ;subtract W from TMP0 and store result in TMP0 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_times_b_b0; MOVLW 0x01 ;decrement TMP1 subwf MATH_TMPA1, 1 ;subtract W from TMP1 and store result in TMP1 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_times_b_b0; MOVLW 0x01 ;decrement TMP2 subwf MATH_TMPA2, 1 ;subtract W from TMP2 and store result in TMP2 btfsc STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_times_b_b0; MOVLW 0x01 ;decrement TMP3 subwf MATH_TMPA3, 1 ;subtract W from TMP3 and store result in TMP3 btfss STATUS, C ;If result is negative, then UNDERFLOW = 0 goto calc_a_times_b_end; ;add B to RES and store result in RES calc_a_times_b_b0: MOVF MATH_B0, 0 ;move MATH_B0 to W addwf MATH_RES0, 1 ;add W to MATH_RES0 and store result in MATH_RES0 btfss STATUS, C ;If result overflows, then UNDERFLOW = 1 goto calc_a_times_b_b1 incf MATH_RES1, 1 ;increment RES1 btfss STATUS, Z ;If result overflows, then Z = 1 goto calc_a_times_b_b1; incf MATH_RES2, 1 ;increment RES2 btfss STATUS, Z ;If result overflows, then Z = 1 goto calc_a_times_b_b1; incf MATH_RES3, 1 ;increment RES3 btfsc STATUS, Z ;If result overflows, then Z = 1 goto calc_a_times_b_overflow; calc_a_times_b_b1: MOVF MATH_B1, 0 ;move MATH_B0 to W addwf MATH_RES1, 1 ;add W to MATH_RES1 and store result in MATH_RES1 btfss STATUS, C ;If result overflows, then UNDERFLOW = 1 goto calc_a_times_b_b2 incf MATH_RES2, 1 ;increment RES2 btfss STATUS, Z ;If result overflows, then Z = 1 goto calc_a_times_b_b2; incf MATH_RES3, 1 ;increment RES3 btfsc STATUS, Z ;If result overflows, then Z = 1 goto calc_a_times_b_overflow; calc_a_times_b_b2: MOVF MATH_B2, 0 ;move MATH_B2 to W addwf MATH_RES2, 1 ;add W to MATH_RES2 and store result in MATH_RES2 btfss STATUS, C ;If result overflows, then UNDERFLOW = 1 goto calc_a_times_b_b3; incf MATH_RES3, 1 ;increment RES3 btfsc STATUS, Z ;If result overflows, then UNDERFLOW = 1 goto calc_a_times_b_overflow; calc_a_times_b_b3: MOVF MATH_B3, 0 ;move MATH_B3 to W addwf MATH_RES3, 1 ;add W to MATH_RES3 and store result in MATH_RES3 btfss STATUS, C ;If result overflows, then UNDERFLOW = 1 goto calc_a_times_b_run calc_a_times_b_overflow: BSF MY_ERRORS, OVERFLOW ;set overflow flag CALL display_overflow calc_a_times_b_end: RETURN ;--- calc_a_times_b ---; ; display_overflow: CALL start_lcd_timer MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0x4F ;'O' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x56 ;'V' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x45 ;'E' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x52 ;'R' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x46 ;'F' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x4C ;'L' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x4F ;'O' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x57 ;'W' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char CALL wait_a_while BCF INTCON, T0IE ;INTCON disable timer 0 overflow RETURN; ; display_underflow: CALL start_lcd_timer MOVLW 0x00 ;set LCD position to 0 MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_position MOVLW 0x55 ;'U' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x4D ;'N' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x44 ;'D' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x45 ;'E' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x52 ;'R' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x46 ;'F' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x4C ;'L' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x4F ;'O' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x57 ;'W' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x21 ;'!' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char CALL wait_a_while BCF INTCON, T0IE ;INTCON disable timer 0 overflow RETURN; ; init_write_mode: BCF MY_FLAGS, WRT ;not ready for writing data to LCD MOVLW 0x00 MOVWF CNT_RW ; BSF MY_FLAGS, U4B ;upper four bits RETURN; ; set_char: CALL init_write_mode MOVF LCD_TMP, 0 ;write LCD_TMP to W andlw b11110000 ;get high nibble and move result in W MOVWF LCD_BUF_00 ;write high nible to LCD_BUF MOVLW b00000001 ;or with 1 in order to set LCD_RS iorwf LCD_BUF_00, 1 ;Inclusive OR and write back to LCD_BUF_00 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVF LCD_TMP, 0 ; andlw b00001111 ;get lower nibble and move result in W MOVWF LCD_BUF_01 BCF STATUS, C ;clear UNDERFLOW rlf LCD_BUF_01,1 ;shift left and store result in LCD_BUF rlf LCD_BUF_01,1 rlf LCD_BUF_01,1 rlf LCD_BUF_01,1 MOVLW b00000001 ;or with 1 in order to set LCD_RS iorwf LCD_BUF_01, 1 ;Inclusive OR and write back to LCD_BUF_00 incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW BSF MY_FLAGS, WRT ;ready for writing data bank 0 MOVLW 0x50 ; MOVWF DLY_VAR ;move w to DLY_VAR bank 0 CALL delay_usec; RETURN; ; set_position: CALL init_write_mode ;Set DDRAM Address 0 ;RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ;0 0 1 0 AC5 AC4 AC3 AC2 AC1 AC0 MOVF LCD_TMP, 0 ;write LCD_TMP to W andlw b11110000 ;get high nibble and move result in W MOVWF LCD_BUF_00 ;write high nible to LCD_BUF MOVLW b10000000 ;set DB7 to 1 IORWF LCD_BUF_00, 1 ;write back to LCD_TMP incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW MOVF LCD_TMP, 0 ;write LCD_TMP to W andlw b00001111 ;get lower nibble and move result in W MOVWF LCD_BUF_01 ; BCF STATUS, C ;clear UNDERFLOW rlf LCD_BUF_01, 1 ;shift left and store result in LCD_BUF rlf LCD_BUF_01, 1 rlf LCD_BUF_01, 1 rlf LCD_BUF_01, 1 ;MOVLW b10000000 ;set DB7 to 1 ;IORWF LCD_BUF_01, 1 ;write back to LCD_TMP incf CNT_RW, 1 ;RW index bank 0, write result back in CNT_RW BSF MY_FLAGS, WRT ;ready for writing data bank 0 MOVLW 0x05 ; MOVWF DLY_VAR ;move w to DLY_VAR bank 0 CALL delay_msec; RETURN; ; delay_sec: ;20 Mhz MOVF DLY_VAR, 0 ;1 cycle, move content of DLY_VAR to W MOVWF CNT0 ;1 cycle delay_sec_cnt0: MOVLW 0x60 ;1 cycle 96 MOVWF CNT1 ;1 cycle delay_sec_cnt1: MOVLW 0x45 ;1 cycle 69 MOVWF CNT2 ;1 cycle delay_sec_cnt2: MOVLW 0xFA ;1 cycle 250 MOVWF CNT3 ;1 cycle delay_sec_cnt3: decfsz CNT3 ;1 cycle goto delay_sec_cnt3 ;2 cycles decfsz CNT2 ;1 cycle goto delay_sec_cnt2 ;2 cycles decfsz CNT1 ;1 cycle goto delay_sec_cnt1 ;2 cycles decfsz CNT0 ;2 cycles goto delay_sec_cnt0 ;1 cycle RETURN; ; delay_msec: ;20 Mhz MOVF DLY_VAR, 0 ;1 cycle, move content of DLY_VAR to W MOVWF CNT0 ;1 cycle delay_msec_cnt0: MOVLW 0x28 ;1 cycle 40 MOVWF CNT1 ;1 cycle delay_msec_cnt1: MOVLW 0x28 ;1 cycle 40 MOVWF CNT2 ;1 cycle delay_msec_cnt2: decfsz CNT2 ;1 cycle goto delay_msec_cnt2 ;2 cycles decfsz CNT1 ;1 cycle goto delay_msec_cnt1 ;2 cycles BTFSS PORTB, RB2 ;when RB2 is low, reset has been pressed BSF MY_MEASUREMENT, FSTM ;set first measurement decfsz CNT0 ;2 cycles goto delay_msec_cnt0 ;1 cycle RETURN; ; delay_usec: ;20 Mhz MOVF DLY_VAR, 0 ;1 cycle, move content of DLY_VAR to W MOVWF CNT0 ;1 cycle delay_usec_cnt0: nop ;1 cycle nop ;1 cycle decfsz CNT0 ;2 cycles goto delay_usec_cnt0 ;1 cycle RETURN; ; start_lcd_timer: ;--- BANK 1 --- BSF STATUS, RP0 ;select bank 1 ;disable all interrupts CLRF INTCON ;GIE PEIE T0IE INTE RBIE T0IF INTF RBIF CLRF PIE1 ;EEIE CMIE RCIE TXIE xxx CCP1IE TMR2IE TMR1IE BSF PCON, OSCF ;4 Mhz MOVLW b00011111 ; MOVWF TRISA ;TRISA, bank 1 MOVLW b00000100 ;RB0...RB1, RB3...RB7 as outputs, RB2 as input MOVWF TRISB ;TRISB, bank 1 ;bit 7 RBPU: PORTB Pull-up Enable bit ; 1 = PORTB pull-ups are disabled ; 0 = PORTB pull-ups are enabled by individual port latch values ;bit 6 INTEDG: Interrupt Edge Select bit ; 1 = Interrupt on rising edge of RB0/INT pin ; 0 = Interrupt on falling edge of RB0/INT pin ;bit 5 T0CS: TMR0 Clock Source Select bit ; 1 = Transition on RA4/T0CKI/CMP2 pin ; 0 = Internal instruction cycle clock (CLKOUT) ;bit 4 T0SE: TMR0 Source Edge Select bit ; 1 = Increment on high-to-low transition on RA4/T0CKI/CMP2 pin ; 0 = Increment on low-to-high transition on RA4/T0CKI/CMP2 pin ;bit 3 PSA: Prescaler Assignment bit ; 1 = Prescaler is assigned to the WDT ; 0 = Prescaler is assigned to the Timer0 module ;bit 2-0 PS<2:0>: Prescaler Rate Select bits ; 0 = nPBPU INTEDG T0CS T0SE PSA PS<2:0>: Prescaler Rate Select bits MOVLW b00011000 ;pull-ups, internal oscillator, WDT prescalar MOVWF OPTION_REG ;OPTION_REG, bank 1 ;--- BANK 0 --- BCF STATUS, RP0 ;select bank 0 MOVLW U4B; MOVWF MY_FLAGS; MOVLW TMR_DELTA ;set initial value MOVWF TMR0; ;TMR0, bank 0 CLRF PORTA ;PORTA, bank 0 CLRF PORTB ;PORTB, bank 0 BSF INTCON, T0IE ;INTCON enable timer 0 overflow BSF INTCON, GIE ;enable interrupts RETURN; ; init_capture_compare_module: BSF MY_FLAGS, CAP ;set capture mode flag BSF MY_FLAGS, SKC ;set skip first capture flag BCF MY_ERRORS, OVERFLOW ;clear overflow flag BCF MY_ERRORS, BIGCAP ;clear BIGCAP flag ;--- select bank 1 --- BSF STATUS, RP0 BCF INTCON, GIE ;disable all interrupt BCF INTCON, T0IE ;disable Timer 0 overflow interrupt CLRF PIE1 MOVLW b00000101 ;RA0 and RA2 as analog inputs MOVWF TRISA ;--- select bank 0 --- BCF STATUS, RP0 MOVLW b00000000 MOVWF T1CON ; - - T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON ;prescale 1:1, T1SYNC ignored, clock source: Internal clock (FOSC/4), tmr1 off MOVWF TMR1H MOVWF TMR1L MOVLW b00000110 MOVWF CMCON ;C2OUT=x, C1OUT=x, C2INV = 1, C1INV = 1, CIS = 0, CM<2:0> = 100 ;C2OUT: Comparator 2 Output bit ;C1OUT: Comparator 1 Output bit ;C2INV: Comparator 2 Output Inversion bit ;C1INV: Comparator 1 Output Inversion bit ;CIS ;Two Independent Comparators CM<2:0> = 100 ;Two Common Reference Comparators CM<2:0> = 011 ;Two Common Reference Comparators with Outputs CM<2:0> = 110 init_capture_compare_pF: MOVLW b00000111 ;Capture mode, every 16th rising edge MOVWF CCP1CON ;CCP1M<3:0>: CCPx Mode Select bits BTFSS MY_MEASUREMENT, MR_1 ; uF or F? GOTO init_capture_compare_pF_nF init_capture_compare_uF_uF2: MOVLW b00000101 ;Capture mode, every rising edge (factor 16) MOVWF CCP1CON ;CCP1M<3:0>: CCPx Mode Select bits BTFSS MY_MEASUREMENT, MR_0 ; F? GOTO init_capture_compare_uF init_capture_compare_uF2: MOVLW b00110000 ;prescale 1:8 (factor 8) MOVWF T1CON GOTO init_capture_compare_done init_capture_compare_uF: MOVLW b00100000 ;prescale 1:4 (factor 4) MOVWF T1CON GOTO init_capture_compare_done init_capture_compare_pF_nF: BTFSS MY_MEASUREMENT, MR_0 ; nF? GOTO init_capture_compare_done init_capture_compare_nF: MOVLW b00000110 ;Capture mode, every 4th rising edge (factor 4) MOVWF CCP1CON ;CCP1M<3:0>: CCPx Mode Select bits MOVLW b00010000 ;prescale 1:2 (factor 2) MOVWF T1CON init_capture_compare_done: ;0000 = Capture/Compare/PWM off (resets CCP1 module) ;0100 = Capture mode, every falling edge ;0101 = Capture mode, every rising edge ;0110 = Capture mode, every 4th rising edge ;0111 = Capture mode, every 16th rising edge ;1000 = Compare mode, set output on match (CCP1IF bit is set) ;1001 = Compare mode, clear output on match (CCP1IF bit is set) ;1010 = Compare mode, generate software interrupt on match (CCP1IF bit is set, CCP1 pin is unaffected) ;1011 = Compare mode, trigger special event (CCP1IF bit is set; CCP1 resets TMR1 ;11xx = PWM mode ;--- select bank 1 --- BSF STATUS, RP0 MOVLW b00000100 ;RB0...RB1, RB3...RB7 as outputs, RB2 as input MOVWF TRISB ;TRISB, bank 1 BCF PIE1, CMIE ;bank 1, disable comparator interrupts BSF PIE1, CCP1IE ;bank 1, enable CCP1 Interrupt Enable BSF PIE1, TMR1IE ;bank 1, enable timer 1 interrupts ;--- select bank 0 --- BCF STATUS, RP0 BSF T1CON, TMR1ON ;start timer 1 BSF INTCON, PEIE ;enable periperal interrupts BSF INTCON, GIE ;enable interrupts RETURN ; ; capture_interrupt: ;--- BANK 0 --- BCF PIR1, CCP1IF ;bank 0, reset interrupt CCP1IF btfss MY_FLAGS, CAP ;if not captureing, stop adding captured T1 GOTO capture_stop BCF STATUS, RP0 BCF STATUS, RP1 BTFSS MY_FLAGS, SKC ;skip first capture GOTO capture_ccpr1 MOVLW 0x00 MOVWF CAP_NR1 ;bank 0, Capturenummer MOVWF CAP_NR0 ;bank 0, Capturenummer BCF MY_FLAGS, SKC ;stop skipping captures GOTO capture_end capture_ccpr1: MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'MATH_A' MOVWF MATH_A3 MOVF Mx_Cap2, 0; MOVWF MATH_A2 MOVF Mx_Cap1, 0; MOVWF MATH_A1 MOVF Mx_Cap0, 0; MOVWF MATH_A0 MOVLW 0x00 ;copy '0x00 0x00 CCPR1H CCPR1L' to 'MATH_B' MOVWF MATH_B3 MOVWF MATH_B2 MOVF CCPR1H, 0 ;bank 0, CCPR1H MOVWF MATH_B1 MOVF CCPR1L, 0 ;bank 0, CCPR1L MOVWF MATH_B0 CALL calc_a_plus_b MOVF MATH_RES3, 0 ;copy 'RES' to 'Mx_Cap' MOVWF Mx_Cap3 MOVF MATH_RES2, 0 MOVWF Mx_Cap2 MOVF MATH_RES1, 0 MOVWF Mx_Cap1 MOVF MATH_RES0, 0 MOVWF Mx_Cap0 BTFSS MY_MEASUREMENT, AL_T1OF ;allow TMR1IE? GOTO capture_timer1_no_overflow INCFSZ CAP_NR0, 1 GOTO capture_check_c1 ;max 256 measurements INCF CAP_NR1, 1 GOTO capture_stop capture_check_c1: MOVF TMR1IF_C1, 0 ADDLW 0xFF BTFSS STATUS, C GOTO capture_end caputure_timer1_overflow_end: call capture_stop RETURN capture_timer1_no_overflow: INCFSZ CAP_NR0, 1 ;do 256 measurements GOTO capture_end INCF CAP_NR1, 1 capture_stop: BCF T1CON, TMR1ON ;bank 0, stop timer 1 MOVLW b00000000 ;set timer 1 to b0000000000000000 MOVWF TMR1H MOVWF TMR1L BCF INTCON, PEIE ;disable periperal interrupts BCF INTCON, GIE ;disable interrupts ;--- select bank 1 --- BSF STATUS, RP0 BCF PIE1, CCP1IE ;bank 1, disable CCP1 Interrupt Enable BCF PIE1, TMR1IE ;bank 1, disable timer 1 interrupts ;--- select bank 0 --- BCF STATUS, RP0 bcf MY_FLAGS, CAP ;end of caputure RETURN capture_end: BCF T1CON, TMR1ON ;bank 0, stop timer 1 restore_prescaler: MOVLW b00000000 ;set timer 1 to b0000000000000000 MOVWF T1CON ; - - T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON ;prescale 1:1, T1SYNC ignored, clock source: Internal clock (FOSC/4), tmr1 off MOVWF TMR1H ;setting TMR1H or L resets prescaler! MOVWF TMR1L BTFSS MY_MEASUREMENT, MR_1 ; uF or F? GOTO restore_prescaler_pF_nF restore_prescaler_uF_uF2: MOVLW b00000101 ;Capture mode, every rising edge (factor 16) MOVWF CCP1CON ;CCP1M<3:0>: CCPx Mode Select bits BTFSS MY_MEASUREMENT, MR_0 ; F? GOTO restore_prescaler_uF restore_prescaler_uF2: MOVLW b00110000 ;prescale 1:8 (factor 8) MOVWF T1CON GOTO restore_prescaler_done restore_prescaler_uF: MOVLW b00100000 ;prescale 1:4 (factor 4) MOVWF T1CON GOTO restore_prescaler_done restore_prescaler_pF_nF: BTFSS MY_MEASUREMENT, MR_0 ; nF? GOTO restore_prescaler_done restore_prescaler_nF: MOVLW b00010000 ;prescale 1:2 (factor 2) MOVWF T1CON restore_prescaler_done: BSF T1CON, TMR1ON ;bank 0, start timer 1 BCF PIR1, CCP1IF ;bank 0, reset interrupt CCP1IF RETURN ; ; comparator_interrupt: ;--- BANK 0 --- BCF STATUS, RP0 BCF STATUS, RP1 BCF PIR1, CMIF ;reset interrupt CMIF RETURN ; ; timer1_overflow: ;--- BANK 0 --- BCF STATUS, RP0 BCF STATUS, RP1 BCF PIR1, TMR1IF ;reset interrupt TMR1IF btfss MY_FLAGS, CAP ;if not captureing, stop adding captured T1 GOTO timer1_overflow_end BTFSC MY_MEASUREMENT, AL_T1OF ;allow T10F GOTO timer1_overflow_allowed BCF INTCON, PEIE ;disable periperal interrupts BCF INTCON, GIE ;disable interrupts BSF MY_ERRORS, BIGCAP BCF T1CON, TMR1ON ;bank 0, stop timer 1 MOVLW 0xFF MOVWF Mx_Cap3 MOVWF Mx_Cap2 MOVWF Mx_Cap1 MOVWF Mx_Cap0 BCF MY_FLAGS, CAP ;end of caputure RETURN timer1_overflow_allowed: MOVF Mx_Cap3, 0 ;copy 'Mx_Cap' to 'MATH_A' MOVWF MATH_A3 MOVF Mx_Cap2, 0; MOVWF MATH_A2 MOVF Mx_Cap1, 0; MOVWF MATH_A1 MOVF Mx_Cap0, 0; MOVWF MATH_A0 MOVLW 0x00 ;copy '0x00 0x01 0x00 0x00' to 'MATH_B' MOVWF MATH_B3 MOVLW 0x01 MOVWF MATH_B2 MOVLW 0x00 MOVWF MATH_B1 MOVLW 0x00 MOVWF MATH_B0 CALL calc_a_plus_b MOVF MATH_RES3, 0 ;copy 'RES' to 'Mx_Cap' MOVWF Mx_Cap3 MOVF MATH_RES2, 0 MOVWF Mx_Cap2 MOVF MATH_RES1, 0 MOVWF Mx_Cap1 MOVF MATH_RES0, 0 MOVWF Mx_Cap0 INCFSZ TMR1IF_C0, 1 RETURN INCF TMR1IF_C1, 1 MOVF TMR1IF_C1,0 ADDLW 0x80 BTFSS STATUS, C ;on overflow, stop measuring RETURN BCF MY_MEASUREMENT, AL_T1OF ;T10F no longer allowed GOTO timer1_overflow timer1_overflow_end: RETURN ; ; timer0_overflow: ;--- BANK 0 --- BCF STATUS, RP0 ;select bank 0 BCF STATUS, RP1 ;select bank 0 btfss MY_FLAGS, SKF ;Bit test flag, skip if set 'Skip frame' goto t0if_nSKF ;SKF is not set, normal mode BCF MY_FLAGS, SKF ;clear SKF-flag and go to toggle LCD_E goto t0if_toggle_lcd_e t0if_nSKF: btfss MY_FLAGS, LCDE ;Bit test flag, skip if set LCD_E == LCD enable bit is set goto t0if_reset_lcd_e ;go to reset lcde btfss MY_FLAGS, WRT ;Bit test flag, skip if set WRT == ready to write data to LCD goto t0if_reset_lcd_e ;go to reset lcde BCF STATUS, C ;clear CARRY BCF STATUS, Z ;clear ZERO MOVF CNT_RW, 0 ;check if CNT_RW is 0 addlw b11111111 btfss STATUS, C ;if CNT_RW not is 0, then CARRY flag will be set goto t0if_no_more_data ;go to toggle LCD_E MOVF LCD_BUF_00, 0 ;Move content of LCD_BUF_00 to W MOVWF PORTB ;Move content of W to PORTB MOVF LCD_BUF_01, 0 ;Move LCD_BUF one down, this could probably be optimized MOVWF LCD_BUF_00 MOVF LCD_BUF_02, 0 MOVWF LCD_BUF_01 MOVF LCD_BUF_03, 0 MOVWF LCD_BUF_02 MOVF LCD_BUF_04, 0 MOVWF LCD_BUF_03 MOVF LCD_BUF_05, 0 MOVWF LCD_BUF_04 MOVF LCD_BUF_06, 0 MOVWF LCD_BUF_05 MOVF LCD_BUF_07, 0 MOVWF LCD_BUF_06 CLRF LCD_BUF_07 decf CNT_RW, 1 ;Decrement CNT_RW and store result in CNT_RW btfsc MY_FLAGS, U4B ;Bit test flag, skip if clear goto t0if_lower_nibble BSF MY_FLAGS, SKF ;After writing lower nibble, set skip frames flag. We don't wair for LCD is busy, have build in delay BSF MY_FLAGS, U4B ;Next write will be upper nibble of next frame goto t0if_toggle_lcd_e ;go to toggle LCD_E t0if_lower_nibble: BCF MY_FLAGS, U4B ;Next write will be lower nibble of current frame. goto t0if_toggle_lcd_e ;go to toggle LCD_E t0if_no_more_data: BCF MY_FLAGS, LCDE ;clear 'LCD Enable' BCF PORTB, 1; goto t0if_toggle_lcd_e t0if_reset_lcd_e: BCF PORTB, 1 ;clear PORTB RB1, bank 0 BCF MY_FLAGS, LCDE ;clear LCDE t0if_toggle_lcd_e: btfss MY_FLAGS, LCDE ;if LCDE is set, set RB1 and clear LCDE goto t0if_set_lcd_e; ;else clear RB1 and set LCDE BSF PORTB, 1 ;set PORTB RB1, bank 0 BCF MY_FLAGS, LCDE ;clear LCDE t0if_set_lcd_e: BCF PORTB, 1 ;set PORTB RB1, bank 0 BSF MY_FLAGS, LCDE ;clear LCDE MOVLW TMR_DELTA ;set initial value MOVWF TMR0; ;TMR0, bank 0 BCF INTCON, T0IF ;reset interrupt T0IF RETURN; ; calc_char_n: BCF INTCON, T0IE ;INTCON disable timer 0 overflow MOVF MATH_REM3, 0 ;copy 'MATH_REM' to 'A' MOVWF MATH_A3 MOVF MATH_REM2, 0 MOVWF MATH_A2 MOVF MATH_REM1, 0 MOVWF MATH_A1 MOVF MATH_REM0, 0 MOVWF MATH_A0 MOVF LCD_DIV3, 0 ;copy 'LCD_DIV' to 'B' MOVWF MATH_B3 MOVF LCD_DIV2, 0 MOVWF MATH_B2 MOVF LCD_DIV1, 0 MOVWF MATH_B1 MOVF LCD_DIV0, 0 MOVWF MATH_B0 CALL calc_a_divided_by_b MOVLW TMR_DELTA ;set initial value MOVWF TMR0; ;TMR0, bank 0 BSF INTCON, T0IE ;INTCON enable timer 0 overflow BTFSC MY_MEASUREMENT, DISA ;no digit yet GOTO calc_char_n_display_number MOVLW 0x00 ;'0' ADDWF MATH_RES0, 0 ;add w and RES3 store result in W ANDLW 0xFF BTFSS STATUS, Z GOTO calc_char_n_display_number calc_char_n_display_space: MOVLW 0x20 ;' ' MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char GOTO calc_char_n_prepare_next calc_char_n_display_number: BSF MY_MEASUREMENT, DISA ;display all digits MOVLW 0x30 ;'0' ADDWF MATH_RES0, 0 ;add w and RES3 store result in W MOVWF LCD_TMP ;move w to LCD_TMP bank 0 CALL set_char calc_char_n_prepare_next: BCF INTCON, T0IE ;INTCON disable timer 0 overflow call copy_result_to_math_a CALL calc_a_times_b MOVF MATH_REM3, 0 ;copy 'MATH_REM' to 'A' MOVWF MATH_A3 MOVF MATH_REM2, 0 MOVWF MATH_A2 MOVF MATH_REM1, 0 MOVWF MATH_A1 MOVF MATH_REM0, 0 MOVWF MATH_A0 MOVF MATH_RES0, 0 ;copy 'RES' to 'B' MOVWF MATH_B0 MOVF MATH_RES1, 0 MOVWF MATH_B1 MOVF MATH_RES2, 0 MOVWF MATH_B2 MOVF MATH_RES3, 0 MOVWF MATH_B3 CALL calc_a_minus_b MOVF MATH_RES3, 0 ;copy 'RES' to 'MATH_REM' MOVWF MATH_REM3 MOVF MATH_RES2, 0 MOVWF MATH_REM2 MOVF MATH_RES1, 0 MOVWF MATH_REM1 MOVF MATH_RES0, 0 MOVWF MATH_REM0 MOVLW TMR_DELTA ;set initial value MOVWF TMR0; ;TMR0, bank 0 BSF INTCON, T0IE ;INTCON enable timer 0 overflow RETURN; ; MY_INTERRUPT_HANDLER: ;SAVING THE STATUS AND W REGISTERS IN RAM MOVWF W_TEMP ;copy W to temp register, could be in any bank swapf STATUS,W ;swap status to be saved into W BCF STATUS,RP0 ;change to bank 0 regardless of current bank MOVWF STATUS_TEMP ;save status to bank 0 register ;--- ISR --- btfsc PIR1, CCP1IF CALL capture_interrupt ;A TMR1 register capture occurred (must be cleared in software) btfsc PIR1, CMIF CALL comparator_interrupt ;Comparator output has changed btfsc PIR1, TMR1IF CALL timer1_overflow ;TMR1 register overflowed (must be cleared in software) ;--- BANK 1 --- BSF STATUS, RP0 ;select bank 1 btfsc INTCON, T0IF ;timer0 overflow? skip if clear CALL timer0_overflow ; ;--- end ISR --- swapf STATUS_TEMP,W ;swap STATUS_TEMP register into W, sets bank to original state MOVWF STATUS ;move W into STATUS register swapf W_TEMP,F ;swap W_TEMP swapf W_TEMP,W ;swap W_TEMP into W retfie ;RETURN from interrupt; ; flash_n_times: ;MOVLW b11111111 ;all leds on ;MOVWF PORTB ;MOVLW 0xff ;wait 255 msec; ;MOVWF DLY_VAR ;DLY_VAR bank 0 ;CALL delay_msec ; ;MOVLW b00000000 ;all leds off ;MOVWF PORTB ;MOVLW 0xff ;wait 255 msec; ;MOVWF DLY_VAR ;DLY_VAR bank 0 ;CALL delay_msec ; ;DECFSZ CNT_VAR, 1 ;decrement CNT_VAR and write back in CNT_VAR, skip if zero ;goto flash_n_times ;RETURN; ; debug_show_x: ;MOVLW 0x04 ;flash 4 times ;MOVWF CNT_VAR ;CALL flash_n_times ;MOVF MATH_RES3, 0 ;the register you want to see ;MOVWF PORTB ;MOVLW 0x01 ;wait 3 sec; ;MOVWF DLY_VAR ;DLY_VAR bank 0 ;CALL delay_sec ; ;MOVLW 0x03 ;flash 3 times ;MOVWF CNT_VAR ;CALL flash_n_times ;MOVF MATH_RES2, 0 ;the register you want to see ;MOVWF PORTB ;MOVLW 0x03 ;wait 3 sec; ;MOVWF DLY_VAR ;DLY_VAR bank 0 ;CALL delay_sec ; ;MOVLW 0x02 ;flash 2 times ;MOVWF CNT_VAR ;CALL flash_n_times ;MOVF MATH_RES1, 0 ;the register you want to see ;MOVWF PORTB ;MOVLW 0x03 ;wait 3 sec; ;MOVWF DLY_VAR ;DLY_VAR bank 0 ;CALL delay_sec ; ;MOVLW 0x01 ;flash 1 time ;MOVWF CNT_VAR ;CALL flash_n_times ;MOVF MATH_RES0, 0 ;the register you want to see ;MOVWF PORTB ;MOVLW 0x03 ;wait 3 sec; ;MOVWF DLY_VAR ;DLY_VAR bank 0 ;CALL delay_sec ; ;goto debug_show_x; end