1
\$\begingroup\$

I'm trying to write a zeros and ones counter in assembly with the AVR ATmega328P.

To choose between the ones and zeros, I have a switch in PC5.

For the input there are 8 switches connected to PORTB and one to a pin in PORTC.

The bits are like this:

  • PC1(Most significant bit)
  • PB7
  • ... PB0(least significant bit)

For the output, I have to send the zeros or the ones count to a 7-segment display.

Ignore SW2

I am trying reading PORTB, use a mask(ANDI) to get the least significant bit, compare if it is one or lower(zero), add one to one register dependig if its zero or one to another register if its one, shift the entry(LSR) to keep checking and so on.

Reading the control switch and printing the display are no problem, but I found some circunstances where it gets a little bit complicated. For example, how to concatenate in a register the value of PORTB and the pin in PORTC?

Im trying to use a cicle and at some point I would have to check if I have already the 9 bits and them send the count out, should I use a counter?

I had made a reaserch of easier ways to implement this problem but no relevant info found.

Begin:
    IN R23, PINB
Jump:
    ANDI R23, 0x01
    CPI R23,0x01
    BRLO Zero
    BREQ One
Shift:
    IN R23, PINB
    LSR R23
    RJMP Jump
Zero:
    INC R18
    INC R16 //counter??
    RJMP Shift
One:
    INC R17
    INC R16//counter??
    RJMP Shift

The counter idea is not completed, just an example where the actualization would be. For the counter(INC R16), I'm also missing the bit in PC0. I could manage to read after reading PORTB, but I was trying to use a more elgant implementation. I know I have to check the counter at the beginning to see if it's done, and send the output if it is.

Thanks a lot for the help. (:

\$\endgroup\$
2
\$\begingroup\$

Examining the LSB, classifying it as 0 or 1, then shift right one and on to the next bit sounds like a reasonable strategy. It's not clear what exactly you are stuck on, but your basic approach makes sense.

Another way to do this if speed were very important is to use the 8 bits as a index into a table, which then tells you explicitly how many 0s and how many 1s in the byte. Actually, it only needs to tell you one of them. The other is 8-N.

\$\endgroup\$
2
\$\begingroup\$

If one has a byte value b, one can quickly count the number of bits that are set using the following strategy:

  1. Start with b = ((b & 0xAA)>1) + (b & 0xAA);. Bits 6-7 of b will now hold a two-bit value containing the number of set bits in {6,7} were set; bits 4-5 will indicate how many bits in {4,5} were set, etc.
  2. Then perform b = ((b & 0xCC)>>2) + (b & 0x33);. Bits 4-7 of b will now hold a four-bit value containing the number of set bits in {4,5,6,7}, and bits 0-3 will hold a four-bit value containing the number of set bits in {0,1,2,3}.
  3. Finally, b = (b >> 4) + (b & 0x0F). Now b will contain the total number of bits that were set.

The approach is amenable to 16-bit or 32-bit quantities as well; with 16-bit quantities it will require four steps, and with 32-bit quantities it will require five.

\$\endgroup\$
1
\$\begingroup\$

Don't have enough reputation to comment. But, could you just sum all the inputs, result will be number of ones.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.