Finding position '1 effectively in a bitmap

I plug in a program that checks a set of wires for open or short circuits. A program that runs on AVR controls the test vector (walking "1") on the wires and returns the result back. It compares this resulting vector with the expected data that is already stored on the SD card or external EEPROM.

Here is an example, suppose we have a set of 8 wires, all of which are straight, i.e. do not have transitions. Therefore, if we drive 0b00000010, we should get 0b00000010.

Suppose we get 0b11000010. This implies a short circuit between wire 7.8 and wire 2. I can detect which bits interest me 0b00000010 ^ 0b11000010 = 0b11000000. This tells me that it is clear that wires 7 and 8 are at fault, but how can I find the position of these β€œ1s” effectively in a large bitmap. It is easy to do this in just 8 wires using bit masks, but the system I am developing should process up to 300 wires (bits). Before I started using macros, as shown below, and tested every bit in an array of 300 * 300 bits, I wanted to ask here if there was a more elegant solution.

 #define BITMASK(b) (1 << ((b) % 8))
 #define BITSLOT(b) ((b / 8))
 #define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
 #define BITCLEAR(a,b) ((a)[BITSLOT(b)] &= ~BITMASK(b))
 #define BITTEST(a,b) ((a)[BITSLOT(b)] & BITMASK(b))
 #define BITNSLOTS(nb) ((nb + 8 - 1) / 8)

Just to show how to detect an open circuit. Expected data: 0b00000010, received data: 0b00000000 (the wire does not pull high). 0b00000010 ^ 0b00000000 = 0b0b00000010 - wire 2 is open.

. , 300 - , RAM AVR Mega 1281, , .. 50 , , , .

+5
5

. , . GCC, , __builtin_ffs, __builtin_ctz, __builtin_popcount .., , parallelism.

, . .

, , de Bruijn.

+3

? , , -, "" - , , - " ".

, XOR input ^ expected == 0, , - .

" ", , , , - input ^ expected, 8 , 8 .., . , , -, .

+1

. , -2 255 1- :

uint8_t bit1 = log2[bit_mask];

log2 :

uint8_t const log2[] = {
   0,               /* not used log2[0] */
   0,               /* log2[0x01] */
   1, 1             /* log2[0x02], log2[0x03] */
   2, 2, 2, 2,      /* log2[0x04],..,log2[0x07] */
   3, 3, 3, 3, 3, 3, 3, 3, /* log2[0x08],..,log2[0x0F */ 
   ... 
} 

, , . AVR - , (ROM) , . , IAR AVR __flash. WinAVR (GNU AVR) PROGMEM, , .

0

, :

  • "outdata". , , 8- .
  • .
  • "indata".
  • , , outdata.
  • XOR outdata indata.

.

MCU 300 ?

300/8 = 37,5 . 38. , outdata indata, 38 * 2 = 76 .

76 ?

0

, . , . :  1) , / .  2) netlist, 1 sd

If you work at both the byte and bit levels, this simplifies the problem. If you activate the pin, the expected template is saved in your file. First find inappropriate bytes; identify inappropriate contacts in the byte; Finally, save the powered contact with erroneous contact numbers.

You do not need an array for search or results. general idea:

numwires=300;

numbytes=numwires/8 + (numwires%8)?1:0;

for(unsigned char currbyte=0; currbyte<numbytes; currbyte++)
{
   unsigned char testbyte=inchar(baseaddr+currbyte)
  unsigned char goodbyte=getgoodbyte(testpin,currbyte/*byte offset*/);
  if( testbyte ^ goodbyte){
  // have a mismatch report the pins
    for(j=0, mask=0x01; mask<0x80;mask<<=1, j++){
       if( (mask & testbyte) != (mask & goodbyte)) // for clarity
          logbadpin(testpin, currbyte*8+j/*pin/wirevalue*/, mask & testbyte /*bad value*/);

     }

}
0
source

All Articles