Dmitry Kiryashov [zews at AHA.RU] says
Below the examples of convertation of 8 bits input value to bit sum.; On fly solution ; 7 clocks per convertation , 256 bytes for table is required movfw portX call bit_cnt ;... bit_cnt: addwf pcl,f ;256 bytes of data at all dt 0,1,1,2,1,2,2,3,..... ; Less program memory requiring solution ; 14 clock per convertation but only ; 14 words of program memory is required movfw portX movwf temp_w andlw 0x77 addwf temp_w,f rrf temp_w,f andlw 0x33 addwf temp_w,f rrf temp_w,f andlw 0x11 addwf temp_w,f rrf temp_w,f swapf temp_w,w addwf temp_w,w andlw 0x0F According to your requirements you will choose the right way. Good luck ;-)
Brian Scearce [bls at BEST.COM] says
bits_set_in_lower_half: andlw 0x0f addwf pcl, w retlw 0 ; 0000 retlw 1 ; 0001 retlw 1 ; 0010 retlw 2 ; 0011 retlw 1 ; 0100 retlw 2 ; 0101 retlw 2 ; 0110 retlw 3 ; 0111 retlw 1 ; 1000 retlw 2 ; 1001 retlw 2 ; 1010 retlw 3 ; 1011 retlw 2 ; 1100 retlw 3 ; 1101 retlw 3 ; 1110 retlw 4 ; 1111 movf portX, w movwf tmp_w call bits_set_in_lower_half movwf sum swapf tmp_w, w call bits_set_in_lower_half addwf sum, fThis is both slower (19 clocks vs. 14) and larger (25 words vs. 14) than Dmitry Kiryashov's amazing solution to the problem, but it does have the advantage of clarity.
There's also the trick that "X & (X-1)" clears the lowest set bit on X; you might be able to take advantage of that, especially if you can fix the threshold number of bits. I don't have my PIC book with me, pardon me if I get tests backward or forget which instructions can set the Z-flag, but I think you can get the gist from this code:
clrf sum movf portX, w movwf tmp_w loop: btfsc status, z goto done incf sum, f decf tmp_w, f andwf tmp_w, w movwf tmp_w goto loop done:Only ten instructions, but it takes longer the more 1's there are. If you can fix the threshold number of 1's, you can make it better. Say you require at least three bits be set:
movlw 3 movwf count movf portX, w movwf tmp_w loop: btfsc status, z goto not_enough_set decf tmp_w, f andwf tmp_w, w movwf tmp_w decfsz count, f goto loop goto enough_setTwelve instructions, but you save two instructions by not needing to do a compare and test after the number of set bits has been calculated, and this one will finish early if possible.
And, of course, if the threshold is fixed and high enough, you can do it with inlined code:
comf portX, w btfsc status, z goto eight_bits_set movwf tmp_w addlw -1 andwf tmp_w, w btfsc status, z goto seven_bits_set fewer_than_seven_bits_set:
see also:
Comments:
For what it's worth, it can be done in nine lines and 51 cycles.
clrf sum
movlw 08
moxwf count
loop rrf portx
btfsc status ,c
incf sum
decfsz count
goto loop
rrf portx
Far from elegant, and the highest average cycle count (but constant).