By Michael Rigby Jones
if you don't need random access when filling the array, then the following might work. You will have to reset the bitmask and byteptr before shifting in each chunk of bits. 23 words in Hitech.unsigned char bitmask = 0x01; unsigned char byteptr = 0x00; void set_bit(unsigned char new_state) { if(new_state) bitarray[byteptr] |= bitmask; else bitarray[byteptr] &= ~bitmask; if(bitmask && 0x80){ bitmask = 0x01; byteptr++;} else bitmask << 1; }
Peter L. Perez says:
I think that you could use a vector of shift registers (actually chars). (I assume this is a 8 bit micro). Then you would have code like:uchar data[NUM_BYTES]; p = data - 1; for(i=NUM_BITS;i>0;--i) { if( !(i%8)) // actually: (i & 0x07) == 0 ++p; *p = (*p * 2) + read_bit(); }imho for 90 bits you should unroll the outer loop unless there is a code size problem, or write it in assembly. 90 bits ~= 11 bytes of storage.
The loop above can be rewritten in assembly very efficiently (using fsr for p and rotate for *2) and can even be isochronous). Like:
movlw (VECTOR_BASE-1) movwf FSR movlw NUM_BITS movwf Fi loop: ; loop period is 8T+overhead to read input bit movlw H'07' andwf Fi,w btfsc STATUS,Z incf FSR,f ; input bit into STATUS.C here rlf INDF,f decfsz Fi,f goto loopThe same method (assembly) can be used on larger processors (i386) and it works to transmit and to receive synchronous data and sound (;-)).
The bit stream must not be tranmitted off chip, it can be fed to another register as required.
To rotate the whole register use something like:
c0 = input_carry; for(i=LENGTH;i>0;--i) { *p++ = ((c1 = (*p & 0x80)) << 1) + c0; c0 = c1; }Which can be turned into assembly like:
rlf Vector_Top,w rlf Fscratch,f movlw VECTOR_SIZE movwf Fi movlw Vector_Base movwf FSR loop: rrf Fscratch,f rlf INDF,f rlf Fscratch,f incf FSR,f decfsz Fi,f goto loopFscratch will have its lowest and highest bits changed at the end.
Michael Rigby-Jones [mrjones@NORTELNETWORKS.COM]
I tried to use Scotts code as inline asm in HiTech, but you need to do some dubious bodging to make it work due to the way to compiler passes single chars. However, this "hybrid" compiles down to 20 words including return.void set_bit(unsigned char new_state) { bitarray[byteptr] |= bitmask; if(new_state) bitarray[byteptr] ^= bitmask; #asm clrc rlf _bitmask,w rlf _bitmask,f btfsc _bitmask,0 incf _byteptr #endasm }