1
\$\begingroup\$

You are to simulate a 2-bit half adder. You are not required to implement a real 2-bit half adder using logic gates; you are going to implement a black-box system using the microcontroller that functions as a 2-bit half adder.

Your system will have 4 inputs (2 for the first 2-bit number, and another 2 for the second 2-bit number), and 2 outputs (2-bit output for the sum).

Inputs: Each input is controlled via a separate push-down button. The inputs should be toggled each time the buttons are released,as opposed to being LOW while the button is released, and HIGH while the button is pushed. The initial values of inputs will be LOW.

Outputs: Each output is controlled via a separate LED. The LED will be off while the output is LOW, and on while the output is HIGH.

Since the states of the inputs will be invisible to the naked eye, you are to represent the input states with additional LEDs as well.

circuit

byte numberOneFirstDigit = 3;
byte numberOneSecondDigit = 2;
byte numberTwoFirstDigit = 5;
byte numberTwoSecondDigit = 4;

byte sumFirstDigit=7;
byte sumSecondDigit=6;
byte carryDigit=12;

byte numberOneFirstDigitButton = 9;
byte numberOneSecondDigitButton = 8;
byte numberTwoFirstDigitButton = 11;
byte numberTwoSecondDigitButton= 10;

void setup()
{
  pinMode(numberOneFirstDigit,OUTPUT);
  pinMode(numberOneSecondDigit,OUTPUT);
  pinMode(numberTwoFirstDigit,OUTPUT);
  pinMode(numberTwoSecondDigit,OUTPUT);
  
  pinMode(sumFirstDigit,OUTPUT);
  pinMode(sumSecondDigit,OUTPUT);
  pinMode(carryDigit,OUTPUT);
 
  pinMode(numberOneFirstDigitButton,INPUT);
  pinMode(numberOneSecondDigitButton,INPUT);
  pinMode(numberTwoFirstDigitButton,INPUT);
  pinMode(numberTwoSecondDigitButton,INPUT);
  
}

void loop()
{
  byte numberOneFirstDigit_state = digitalRead(numberOneFirstDigitButton);
  byte numberOneSecondDigit_state = digitalRead(numberOneSecondDigitButton);
  byte numberTwoFirstDigit_state = digitalRead(numberTwoFirstDigitButton);
  byte numberTwoSecondDigit_state = digitalRead(numberTwoSecondDigitButton);
  
  if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , LOW);
     
  }
  else if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , LOW);
     
  }
  else if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , LOW);
     
  }
  else if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , LOW);
     
  }
  else if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , LOW);
  }
  else if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , LOW);
  }
  else if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , LOW);
  }
  else if(numberOneSecondDigit_state == LOW && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , LOW);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , HIGH); 
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , LOW); 
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , LOW); 
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , HIGH);
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == LOW && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , LOW);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , HIGH);
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , LOW);
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == LOW && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , LOW);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , HIGH);
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == LOW)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , LOW);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , HIGH);
     digitalWrite(sumSecondDigit , LOW);
     digitalWrite(carryDigit , HIGH);
  }
  else if(numberOneSecondDigit_state == HIGH && numberOneFirstDigit_state == HIGH && numberTwoSecondDigit_state == HIGH && numberTwoFirstDigit_state == HIGH)
  {
     digitalWrite(numberOneFirstDigit , HIGH);
     digitalWrite(numberOneSecondDigit , HIGH);
     digitalWrite(numberTwoFirstDigit , HIGH);
     digitalWrite(numberTwoSecondDigit , HIGH);
    
     digitalWrite(sumFirstDigit , LOW);
     digitalWrite(sumSecondDigit , HIGH);
     digitalWrite(carryDigit , HIGH);
  }
    
  
  
}

I have showed the question and the circuit I did.

I am open to any suggestions to improve my code (and maybe the circuit).

I want a program which is not too many lines.

\$\endgroup\$
2
  • \$\begingroup\$ Casm, I suspect the next assignment is "our system will have 5 inputs (2 for the first 2-bit number, another 2 for the second 2-bit number and a carry), and 2 outputs (2-bit output for the sum).". Be prepared for that - think of how a solution here would readily progress to that. \$\endgroup\$ Commented Nov 13, 2022 at 5:56
  • \$\begingroup\$ Please avoid changing the question code after it has been reviewed. In this case, it doesn't seem to invalidate the answer(s), so I'll let it stand, but in general, you can expect such changes to be rolled back. \$\endgroup\$ Commented Nov 13, 2022 at 8:49

1 Answer 1

2
\$\begingroup\$

Avoid code duplication

Your implementation is like that of a truth table: for all possible inputs, you have pre-calculated the output. That is one way of doing it. But instead of having lots of if-then statements, implement it using a look-up table. This is quite easy if you pack all the bits in a single integer:

static const byte table[16] = {
    /* 0b0000 -> */ 0b000,
    /* 0b0001 -> */ 0b001,
    /* 0b0010 -> */ 0b010,
    ...
    /* 0b1101 -> */ 0b100,
    /* 0b1110 -> */ 0b101,
    /* 0b1111 -> */ 0b110,
};

Then in loop(), you just need to do this (un)packing using a combination of bit shifting, OR and AND operations:

loop() {
    byte input = digitalRead(numberOneFirstDigitButton)  << 0
               | digitalRead(numberOneSecondDigitButton) << 1
               | digitalRead(numberTwoFirstDigitButton)  << 2
               | digitalRead(numberTwoSecondDigitButton) << 3;

    byte result = table[input];

    digitalWrite(numberOneFirstDigit,  (input >> 0) & 1);
    digitalWrite(numberOneSecondDigit, (input >> 1) & 1);
    digitalWrite(numberTwoFirstDigit,  (input >> 2) & 1);
    digitalWrite(numberTwoSecondDigit, (input >> 3) & 1);

    digitalWrite(sumFirstDigit,  (result >> 0) & 1);
    digitalWrite(sumSecondDigit, (result >> 1) & 1);
    digitalWrite(carryDigit,     (result >> 2) & 1);
}

Note how this removes a huge amount of code duplication, which makes the code easier to read and easier to maintain.

The implementation using a table has a counterpart in digital logic, and that is using a ROM chip to implement combinatorial logic.

Alternatively, you can also implement this by parsing the input as two int values, adding them together, and then writing the result back to the output pins:

unsigned int numberOne = digitalRead(numberOneFirstDigitButton)  << 0
                       | digitalRead(numberOneSecondDigitButton) << 1;
unsigned int numberTwo = digitalRead(numberTwoFirstDigitButton)  << 0
                       | digitalRead(numberTwoSecondDigitButton) << 1;

unsigned int result = numberOne + numberTwo;

digitalWrite(sumFirstDigit,  (result >> 0) & 1));
digitalWrite(sumSecondDigit, (result >> 1) & 1));
digitalWrite(carryDigit,     (result >> 2) & 1));

This avoids needing to make a table.

Make constants static const or even static constexpr

The constants used for the pin numbers, like numberOneFirstDigit, are stored in non-const variables. It is better to make them const, or even better, constexpr. Also, make it a habit of marking constants and functions that don't have to be accessed by anything outside of the current source file as static. Both of these things can allow the compiler to generate more optimal code (also in size), and const will ensure the compiler generates an error if you accidentally do write to one of these constants. So:

static constexpr byte numberOneFirstDigit = 3;
...
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Pedantic note: static restricts the scope to a single translation unit, which may comprise one or more source files, via #include. Roughly speaking, a translation unit usually corresponds to a single object file, or its conceptual equivalent. (I'm sure you know this @G.Sliepen - just throwing this in for other readers!) \$\endgroup\$ Commented Nov 12, 2022 at 21:42
  • \$\begingroup\$ Does constexpr apply for C or is it only C++? \$\endgroup\$
    – pacmaninbw
    Commented Nov 19, 2022 at 22:19
  • 1
    \$\begingroup\$ @pacmaninbw No (well, not until C23), but Arduino is a C++ environment. \$\endgroup\$
    – G. Sliepen
    Commented Nov 20, 2022 at 9:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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