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.
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.
-
\$\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\$chux– chux2022年11月13日 05:56:16 +00:00Commented 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\$Toby Speight– Toby Speight2022年11月13日 08:49:55 +00:00Commented Nov 13, 2022 at 8:49
1 Answer 1
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;
...
-
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\$Toby Speight– Toby Speight2022年11月12日 21:42:00 +00:00Commented Nov 12, 2022 at 21:42 -
\$\begingroup\$ Does constexpr apply for C or is it only C++? \$\endgroup\$2022年11月19日 22:19:38 +00:00Commented Nov 19, 2022 at 22:19
-
1\$\begingroup\$ @pacmaninbw No (well, not until C23), but Arduino is a C++ environment. \$\endgroup\$G. Sliepen– G. Sliepen2022年11月20日 09:36:51 +00:00Commented Nov 20, 2022 at 9:36