I'd rather use the subtract version but with a bit optimized way like: Mod7Byte: movwf temp1 movlw 0xE0 ; 224 is the highest number below 256 ; that dividable by 7 (7*32) outerLoop movwf wcnt ; store new 'divider' innerLoop ; subtracts the actual 'divider' subwf temp1,f btfsc STATUS,C goto innerLoop ; ok now we reconstruct the last 'good' value addwf temp1,f bcf STATUS,C rrf wcnt,W ; continue further with smaller portions btfss STATUS,C goto outerLoop ; ok, so we finished... movf temp1,W return This one takes 78 cycles typically incl. the call to this routine. Also quite easy to implement on other numbers as well, can be extended to 16/24/32 bits easily. And of course when you use 16 bit calculus you also use higher number than 0xE0 (not surprisingly 0xE000). The only trick here with the 'special' number 7 is that the outerLoop looks the bits underflowing from the divider. You can subtract 7 from temp1 in front of the testing (putting the results in W) which has the benefit of if you are lucky with your number then you can end up the cycle at the end of the first cycle saving some time. Tamas On 03/08/06, Scott Dattalo wrote: > > On Wed, 2006-08-02 at 13:35 -0700, Brooke Clarke wrote: > > > In order to calculate the Zeller Congruence the math needs to be 16 bit > > to handle the 4 digit Year so the Modulo 7 calculation needs to start > > with a two byte unsigned integer and output 0 to 6, but so far it's > > escaped me how to calculate it and there's not even a mention of modulo > > calculations on the piclist.com source code pages. The start of the > > loop may be something like: > > > > movlw 7 ; addwf with a -7 does not work > > Mod7_Loop > > subwf Z_DowLo,F > > btfsc STATUS,C ; for subtraction the sense of carry is > inverted > > goto Mod7_Loop ; keep subtracting 7 until there's a carry > > > > but the next part has me stumped. > > > Maybe a better way to think about the problem is in terms of number > bases and modulo arithmetic. For example, your goal is to compute DOW > mod 7 where DOW is the 16-bit representation of the day of the > week. You can write this as: > > DOW = DOW_HI*256 + DOW_LO > > DOW%7 = (DOW_HI*256 + DOW_LO) % 7 > = ((DOW_HI*256)%7 + (DOW_LO % 7)) %7 > = ((DOW_HI%7 * 256%7) + (DOW_LO%7)) %7 > = ((DOW_HI%7 * 4) + (DOW_LO%7)) %7 > > Expressed in this manner, you can separately compute the modulo 7 > result for the high and low bytes. Multiply the result for the high by > 4 and add it to the low and then finally compute result modulo 7. > > Computing the mod 7 result of an 8-bit number can be performed in a > similar fashion. You can write an 8-bit number in octal like so: > > X = a*64 + b*8 + c > > Where a, b, and c are 3-bit numbers. > > X%7 = ((a%7)*(64%7) + (b%7)*(8%7) + c%7) % 7 > = (a%7 + b%7 + c%7) % 7 > = (a + b + c) % 7 > > since 64%7 = 8%7 = 1 > > Of course, a, b, and c are > > c = X & 7 > b = (X>>3) & 7 > a = (X>>6) & 7 (actually, a is only 2-bits). > > The largest possible value for a+b+c is 7+7+3 = 17. So, you'll need > one more octal step. The complete (untested) C version could be > written like: > > unsigned char Mod7Byte(unsigned char X) > { > X = (X&7) + ((X>>3)&7) + (X>>6); > X = (X&7) + (X>>3); > > return X==7 ? 0 : X; > } > > I spent a few moments writing a PIC version. The actual implementation > is slightly different than described above > > > > Mod7Byte: > movwf temp1 ; > andlw 7 ;W=c > movwf temp2 ;temp2=c > rlncf temp1,F ; > swapf temp1,W ;W= a*8+b > andlw 0x1F > addwf temp2,W ;W= a*8+b+c > movwf temp2 ;temp2 is now a 6-bit number > andlw 0x38 ;get the high 3 bits == a' > xorwf temp2,F ;temp2 now has the 3 low bits == b' > rlncf WREG,F ;shift the high bits right 4 > swapf WREG,F ; > addwf temp2,W ;W = a' + b' > > ; at this point, W is between 0 and 10 > > > addlw -7 > bc Mod7Byte_L2 > Mod7Byte_L1: > addlw 7 > Mod7Byte_L2: > return > > > > Here's a liitle routine to test the algorithm > > > clrf x > clrf count > > TestLoop: > movf x,W > RCALL Mod7Byte > cpfseq count > bra fail > > incf count,W > xorlw 7 > skpz > xorlw 7 > movwf count > > incfsz x,F > bra TestLoop > passed: > > > Finally, for the 16-bit result (which I have not tested), you could > write: > > uint16 Mod7Word(uint16 X) > { > return Mod7Byte(Mod7Byte(X & 0xff) + Mod7Byte(X>>8)*4); > } > > > Scott > -- > http://www.piclist.com PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist > -- unPIC -- The PIC Disassembler http://unpic.sourceforge.net -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist