Mercurial > public > mk2
diff code_part1/OSTC_code_asm_part1/math.asm @ 0:96a35aeda5f2
Initial setup
author | heinrichsweikamp |
---|---|
date | Tue, 12 Jan 2010 15:05:59 +0100 |
parents | |
children | a1ccb92b59cd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/code_part1/OSTC_code_asm_part1/math.asm Tue Jan 12 15:05:59 2010 +0100 @@ -0,0 +1,323 @@ +; OSTC - diving computer code +; Copyright (C) 2008 HeinrichsWeikamp GbR + +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. + +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. + +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <http://www.gnu.org/licenses/>. + + +; Math routines +; written by: Matthias Heinrichs, info@heinrichsweikamp.com +; written: 10/30/05 +; last updated: 06/21/07 +; known bugs: +; ToDo: clean up! + +convert_time: ; converts hi:lo in minutes to hours (hi) and minutes (lo) + movff lo,xA+0 ; divide by 60... + movff hi,xA+1 ; + movlw d'60' ; + movwf xB+0 ; + clrf xB+1 ; + rcall div16x16 ; xA/xB=xC with xA as remainder + movff xC+0,hi ; Hours + movff xA+0,lo ; =remaining minutes (0.....59) + return + +div16: +; divA=divA/2^divB (divB: 8Bit only!) + bcf STATUS,C + rrcf divA+1 + rrcf divA + decfsz divB + bra div16 + return + +div32: +; xC=xC(32Bit)/2^divB (divB: 8Bit only!) + bcf STATUS,C + rrcf xC+3 + rrcf xC+2 + rrcf xC+1 + rrcf xC+0 + decfsz divB + bra div32 + return + +invert_xC: + movf xC+1, w ; inverses xC+0:xC+1 + sublw 0xFF + movwf xC+1 + movf xC+0, w + bcf STATUS,C + sublw 0xFF + movwf xC+0 + return + + +sub16: +; sub_c = sub_a - sub_b + bcf neg_flag + movf sub_b+0, w ; Get Value to be subtracted + subwf sub_a+0, w ; Do the High Byte + movwf sub_c+0 + movf sub_b+1, w ; Get the Value to be Subbed + subwfb sub_a+1, w + movwf sub_c+1 + btfss STATUS,N + return ; result positve +; sub_c = sub_a - sub_b + bsf neg_flag ; result negative + movff sub_c+0,sub_b+0 + movff sub_c+1,sub_b+1 + setf sub_a + setf sub_a+1 + movf sub_b+0, w ; Get Value to be subtracted + subwf sub_a+0, w ; Do the High Byte + movwf sub_c+0 + movf sub_b+1, w ; Get the Value to be Subbed + subwfb sub_a+1, w + movwf sub_c+1 + return + + +mult16x16: +;xA*xB=xC + clrf xC+2 ; Clear the High-Order Bits + clrf xC+3 + movf xA, w ; Do the "L" Multiplication first + mulwf xB + movf PRODL, w ; Save result + movwf xC + movf PRODH, w + movwf xC+1 + movf xA, w ; Do the "I" Multiplication + mulwf xB+1 + movf PRODL, w ; Save the Most Significant Byte First + addwf xC+1, f + movf PRODH, w + addwfc xC+2, f ; Add to the Last Result + movf xA+1, w ; Do the "O" Multiplication + mulwf xB + movf PRODL, w ; Add the Lower Byte Next + addwf xC+1, f + movf PRODH, w ; Add the High Byte First + addwfc xC+2, f + btfsc STATUS, C ; Add the Carry + incf xC+3, f + movf xA+1, w ; Do the "F" Multiplication + mulwf xB+1 + movf PRODL, w + addwf xC+2, f + movf PRODH, w + addwfc xC+3, f + return + + +div16x16: ;xA/xB=xC with xA as remainder + ;uses divB as temp variable + clrf xC+0 + clrf xC+1 + MOVF xB+0,W ; Check for zero + IORWF xB+1,W ; + BTFSC STATUS,Z ; Check for zero + RETLW H'FF' ; return 0xFF if illegal + MOVLW 1 ; Start count at 1 + MOVWF divB ; Clear Count +div16x16_1 + BTFSC xB+1,7 ; High bit set ? + bra div16x16_2 ; Yes then continue + INCF divB,F ; Increment count + + bcf STATUS,C + rlcf xB+0,F + rlcf xB+1,F + bra div16x16_1 +div16x16_2: + ; Shift result left + bcf STATUS,C + rlcf xC+0,F + rlcf xC+1,F + + ; Reduce Divisor + + MOVF xB,W ; Get low byte of subtrahend + SUBWF xA,F ; Subtract DST(low) - SRC(low) + MOVF xB+1,W ; Now get high byte of subtrahend + BTFSS STATUS,C ; If there was a borrow, rather than + INCF xB+1,W ; decrement high byte of dst we inc src + SUBWF xA+1,F ; Subtract the high byte and we're done + + + BTFSC STATUS, C ; Did it reduce? + bra div16x16_3 ; No, so it was less than + + movf xB+0,W ; Reverse subtraction + addwf xA+0,F + movf xB+1,W + addwfc xA+1,F + + bra div16x16_4 ; Continue the process +div16x16_3: + BSF xC+0,0 ; Yes it did, this gets a 1 bit +div16x16_4: + DECF divB,F ; Decrement N_COUNT + BTFSC STATUS,Z ; If its not zero then continue + return + + bcf STATUS,C + rrcf xB+1,F + rrcf xB+0,F + + bra div16x16_2 ; Next bit. + +div32x16: ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder + ; Setup + movlw .32 ; setup shift counter + movwf divB + movf xC+3,W ; move ACCb to ACCf + movwf xA+1 + movf xC+2,W + movwf xA+0 + movf xC+1,W ; move ACCc to ACCe + movwf sub_a+1 + movf xC+0,W + movwf sub_a+0 + clrf xC+3 + clrf xC+2 + clrf xC+1 + clrf xC+0 + clrf sub_b+1 + clrf sub_b+0 +div32x16_2 + bcf STATUS,C + rlcf sub_a+0,F + rlcf sub_a+1,F + rlcf xA+0,F + rlcf xA+1,F + rlcf sub_b+0,F + rlcf sub_b+1,F + movf xB+1,W + subwf sub_b+1,W ; check if a>d + btfss STATUS,Z + goto div32x16_3 + movf xB+0,W + subwf sub_b+0,W ; if msb equal then check lsb +div32x16_3 + btfss STATUS,C ; carry set if d>a + goto div32x16_4 + movf xB+0,W ; d-a into d + subwf sub_b+0,F + btfss STATUS,C + decf sub_b+1,F + movf xB+1,W + subwf sub_b+1,F + bsf STATUS,C ; shift a 1 into b (result) +div32x16_4 + rlcf xC+0,F + rlcf xC+1,F + rlcf xC+2,F + rlcf xC+3,F + decfsz divB,F ; loop until all bits checked + goto div32x16_2 + return + + +isr_div16: +; divA=divA/2^divB (divB: 8Bit only!) + bcf STATUS,C + rrcf isr_divA+1 + rrcf isr_divA + decfsz isr_divB + bra isr_div16 + return + +isr_div32: +; xC=xC(32Bit)/2^divB (divB: 8Bit only!) + bcf STATUS,C + rrcf isr_xC+3 + rrcf isr_xC+2 + rrcf isr_xC+1 + rrcf isr_xC+0 + decfsz isr_divB + bra isr_div32 + return + +isr_invert_xC: + movf isr_xC+1, w ; inverses xC+0:xC+1 + sublw 0xFF + movwf isr_xC+1 + movf isr_xC+0, w + bcf STATUS,C + sublw 0xFF + movwf isr_xC+0 + return + + +isr_sub16: +; sub_c = sub_a - sub_b + bcf neg_flag_isr + movf isr_sub_b+0, w ; Get Value to be subtracted + subwf isr_sub_a+0, w ; Do the High Byte + movwf isr_sub_c+0 + movf isr_sub_b+1, w ; Get the Value to be Subbed + subwfb isr_sub_a+1, w + movwf isr_sub_c+1 + btfss STATUS,N + return ; result positve +; sub_c = sub_a - sub_b + bsf neg_flag_isr ; result negative + movff isr_sub_c+0,isr_sub_b+0 + movff isr_sub_c+1,isr_sub_b+1 + setf isr_sub_a + setf isr_sub_a+1 + movf isr_sub_b+0, w ; Get Value to be subtracted + subwf isr_sub_a+0, w ; Do the High Byte + movwf isr_sub_c+0 + movf isr_sub_b+1, w ; Get the Value to be Subbed + subwfb isr_sub_a+1, w + movwf isr_sub_c+1 + return + + +isr_mult16x16: +;xA*xB=xC + clrf isr_xC+2 ; Clear the High-Order Bits + clrf isr_xC+3 + movf isr_xA, w ; Do the "L" Multiplication first + mulwf isr_xB + movf PRODL, w ; Save result + movwf isr_xC + movf PRODH, w + movwf isr_xC+1 + movf isr_xA, w ; Do the "I" Multiplication + mulwf isr_xB+1 + movf PRODL, w ; Save the Most Significant Byte First + addwf isr_xC+1, f + movf PRODH, w + addwfc isr_xC+2, f ; Add to the Last Result + movf isr_xA+1, w ; Do the "O" Multiplication + mulwf isr_xB + movf PRODL, w ; Add the Lower Byte Next + addwf isr_xC+1, f + movf PRODH, w ; Add the High Byte First + addwfc isr_xC+2, f + btfsc STATUS, C ; Add the Carry + incf isr_xC+3, f + movf isr_xA+1, w ; Do the "F" Multiplication + mulwf isr_xB+1 + movf PRODL, w + addwf isr_xC+2, f + movf PRODH, w + addwfc isr_xC+3, f + return + \ No newline at end of file