I have a 16-bit integer, in one's complement, and I'm trying to retrieve it's 7-seg display equivalence. Using only bitwise operations.
I'm doing it for a Minecraft project/hobby, just trying to build a full adder with negative operands.
I want the resulting integer to be transformed from a 16 bit integer, to a 5 digit 7-segment display, like this:
I understand logic gates but am a beginner in computer logic, so if you can explain me in the simplest terms or maybe programatically, like using Java or Python, it'd be better.
Actually, I don't know a bit of how to do it, I tried to search for answers and ask AI, but didn't got any plausible answer. I need something that uses only bitwise operations, and to be explained using them, if possible. I'm a begginer in computer theory. If you can explain me step-by-step and/or using simple terms, I'd be grateful.
In a comment, the O/P said "... Better yet, if you can only explain how binary to BCD conversion work, it'd already be sufficient."
So, this answer will be mostly about converting to BCD. Converting a number to a seven segment display limited to bitwise operations is more than I care to get into.
BCD (Binary Coded Decimal) is simply any representation of a number such that, when the number is expressed in base ten, each digit is represented in binary.
Suppose I have 27 (decimal). In binary, that is 11011
. If it is coded in BCD, the bits would look like this: 0010 0111
. Note that 0010
is 2
in decimal, representing the first digit, and 0111
is 7
in decimal, representing the second digit.
BCD uses 4 bits, or one nybble, for each digit. The storage units used are up to the developer. The developer could choose to have 1 byte
, short
, or int
for each digit. Or, two digits might be stored in each byte
. Or, 4 digits might be stored in each short
. Or, 8 digits might be stored in each int
.
Here is a method that converts an integer to BCD with 8 digits in an int
return type. There is no provision allowing for a sign:
public static int bcd8Pack (int n) {
int packed = 0;
for (int i = 0; i < 8; ++i) {
int digit = n % 10;
n /= 10;
int place = digit << (i * 4);
packed = packed | place;
}
return packed;
}
Example use:
System.out.println (Integer.toUnsignedString (bcd8Pack (98_765_432),16));`
Output: 98765432
Let us suppose we have a class
with an instance field private final byte [] bcd;
. It might convert an int
to BCD with one digit per byte:
public void set (int n) {
int m = Math.abs (n);
for (int i = bcd.length - 1 ; i >= 1 ; --i ) {
bcd [i] = (byte) (m % 10);
m /= 10;
}
bcd [0] = (byte) ( n < 0 ? MINUS_FLAG : PLUS_FLAG );
}
This assumes element [0]
has been reserved for a sign, which may have one of two values (MINUS_FLAG
or PLUS_FLAG
).
For converting a decimal digit to a 7 segment display, we want to convert the digit into a binary number such that each bit corresponds to one segment. The bit to segment matching can be arbitrary. A "map" is in the code below. For the conversion, instead of using bitwise operations, I would use a translation table.
The code below includes a simulation of a 7-segment display using a low resolution 7 x 5 dot-matrix format. The code uses a 7 x 7 dot-matrix because I reserved the left and right columns for spacing. The dot matrix output is there only to test the translation table approach.
public class DigitalDisplay {
/* Seven segment map:
* -5-
* | |
* 4 0
* | |
* -6-
* | |
* 3 1
* | |
* -2-
*/
/* 0123456
*** 0
* * 1
* * 2
*** 3
* * 4
* * 5
*** 6
*/
private static final byte MINUS_FLAG = 0xd;
private static final byte PLUS_FLAG = 0xc;
public static final char SPACE = ' ';
public static final char ON = '*';
private final byte [] bcd;
static class Digit {
private static final byte [] translate = {
0b00111111, 0b00000011, 0b01101101, 0b01100111, 0b01010011
, 0b01110110, 0b01111110, 0b00110011, 0b01111111, 0b01110111 };
private static final byte MINUS_SIGN = 0b01000000;
private static final byte PLUS_SIGN = 0;
char [][] display;
Digit () {
setEmpty ();
}
/* value is from 0 to 9 or 12 or 13.
12 represents a plus sign. 13 represents a minus sign
*/
Digit (byte value) {
setEmpty ();
byte register;
switch (value) {
case MINUS_FLAG:
register = MINUS_SIGN;
break;
case PLUS_FLAG:
register = PLUS_SIGN;
break;
default:
register = translate [value];
break;
} // end switch (value)
if ((register & 0b1) == 1) { // segment 0
display [1][5] = ON;
display [2][5] = ON;
}
if ((register & 0b10) == 2) { // segment 1
display [4][5] = ON;
display [5][5] = ON;
}
if ((register & 0b100) == 4) { // segment 2
display [6][2] = ON;
display [6][3] = ON;
display [6][4] = ON;
}
if ((register & 0b1000) == 8) { // segment 3
display [4][1] = ON;
display [5][1] = ON;
}
if ((register & 0b1_0000) == 16 ) { // segment 4
display [1][1] = ON;
display [2][1] = ON;
}
if ((register & 0b10_0000) == 32) { // segment 5
display [0][2] = ON;
display [0][3] = ON;
display [0][4] = ON;
}
if ((register & 0b100_0000) == 64) { // segment 6
display [3][2] = ON;
display [3][3] = ON;
display [3][4] = ON;
}
}
private void setEmpty () {
display = new char [7][7];
for (int i = 0; i < display.length; ++i) {
Arrays.fill (display [i], SPACE);
}
}
} // end class Digit
public DigitalDisplay () {
bcd = new byte [6]; // default size = 5 digits and 1 sign
}
public DigitalDisplay (int numDigits) {
bcd = new byte [numDigits + 1]; // alow an extra for the sign
}
public void set (int n) {
int m = Math.abs (n);
for (int i = bcd.length - 1 ; i >= 1 ; --i ) {
bcd [i] = (byte) (m % 10);
m /= 10;
}
bcd [0] = (byte) ( n < 0 ? MINUS_FLAG : PLUS_FLAG );
}
public String[] display () {
Digit [] displayDigit = new Digit [bcd.length];
for (int i = 0; i < displayDigit.length; ++i) {
displayDigit [i] = new Digit (bcd[i]);
}
String [] theDisplay = new String [displayDigit[1].display.length];
StringBuilder [] displayNumber =
new StringBuilder [displayDigit[1].display.length];
for (int lineIndex = 0; lineIndex < displayNumber.length; ++lineIndex) {
displayNumber [lineIndex] = new StringBuilder
(bcd.length * displayDigit[1].display[0].length);
for (int digitIndex = 0
; digitIndex < displayDigit.length
; ++digitIndex) {
for (int digitColumnIndex = 0;
digitColumnIndex < displayDigit[digitIndex].display.length;
++digitColumnIndex) {
displayNumber[lineIndex]
.append (displayDigit[digitIndex]
.display[lineIndex][digitColumnIndex]);
}
}
theDisplay [lineIndex] = displayNumber[lineIndex].toString();
}
return theDisplay;
}
public static void print (DigitalDisplay disp) {
String [] out = disp.display ();
for (int i = 0; i < out.length; ++i) {
System.out.println (out[i]);
}
System.out.println ("\n\n");
}
public static void main(String[] args) {
DigitalDisplay tenDigits = new DigitalDisplay (10);
tenDigits.set (-1234567890);
print (tenDigits);
DigitalDisplay fiveDigits = new DigitalDisplay (5);
fiveDigits.set (1234567);
print (fiveDigits);
}
}
Output:
:
98765432
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * * * *
* * * * * * * * * * * * * * *
*** *** *** *** *** *** *** ***
* * * * * * * * * * * * *
* * * * * * * * * * * * *
*** *** *** *** *** *** ***
*** *** *** ***
* * * * * * *
* * * * * * *
*** *** *** ***
* * * * * *
* * * * * *
*** *** ***
If there were a real 7-segment display, the value of register
would be passed to an area tied to the display. The if ((register & ...
statements are present only to set the values in the dot-matrix simulation.
Perhaps someone can edit this answer to replace the dot-matrix simulation with Swing or other graphics.
Note that this answer does not address one's-complement and two's complement.