1. Reading the first input
To read the first input, use the 6 most right switches. The inputs from the switches will be displayed on the LEDs as well as the 7-segment display.
2. Choosing the arithmetic operation
After inputting the value for the first input, press the next button (left button), this will enable the 4 most right switches and set the 7 segment display to 0. These switches are used to choose the arithmetic operation. When choosing the arithmetic operation, the operation number will light up in the 7 segment display. (note: operations 5, 7, 8, 9, 10 only takes one input so no input will be taken in step 3. The trigonometric functions takes in the input in degrees only.)
3. Reading the second input
After choosing the arithmetic operation, press the next button, this will enable the second input switch which is the next 6 switches to the left of the first input switches. The 7 segment display will display the inputs from the second input switches.
4. Showing the results
After inputting the value for the second input, press the equal button to show the results.
5. Reset or choose next arithmetic operation
After results are shown, to reset the calculator, press the reset button (the reset button will work at any stage of the program), or to continue arithmetic operations using the result, press the next button, the calculator will go back to step 2. (pressing the next button here only works if the result is a non-decimal number, if the result is a decimal, pressing next will reset the calculator)
a. Inputting negative numbers & displaying hexadecimal
To input a negative number, press the negative button once. Pressing the negative button once more will turn the input back to positive. (note: 0 will remain 0 as negative 0 is equal to 0).
To change the display from integers to hexadecimal, press the hexadecimal button once. Pressing it again will convert the display to integers. This does not work for decimal values. (note: letters B and D are converted to b and d due to similarity with 8 and 0 in the 7 segment display.
Isolating the switches
There are 16 switches in the basys3 board, however for the calculator, there are 3 sets of switches that needs to be isolated. This is done through bit shifting. There are two bitwise shift operators in C, the left shift operator << and the right shift operator >>. These bitwise operators shifts the bits to the right or to the left by the number of positions we want. For example, the 16-bit binary for an integer will be:
Int x = 63; : 0000000000111111
Int y = x << 13; : 1110000000000000
Int z = y >> 13; : 0000000000000111
What this example does is essentially isolating the first three bits. As seen on the example, when a value is shifted to the left by 13, the last 13 bits are lost, and when the shifted bits are shifted back to the right by 13, the initial value of the last 13 bits cannot be recovered. [1]
For the case of the calculator, the first 6 bits, which are the first 6 switches, need to be isolated. This can be done by shifting the read values from the switches to the left by 10, and shift the shifted value back to the right by 10. This can be seen on figure 3 below.
This way, if there are switches that are turned on aside from the first 6 switches, the values are discarded.
The next 6 bits are also isolated similarly to the first 6 switches. The switches are switches 7 – 12 where switch 0 is the most right. First the bits are shifted to the left by 4 positions, however since these 6 switches are not the most right switches, it has to be shifted back to the right by 12 positions. This is so that when switch 7 is turned on, the value read is 1. This can be seen on figure 4 below
What this does is if all the switches from 7 – 12 are turned on, and the value read is first shifted to the left by 4 and then shifted to the left by 12, the answer would equate to 63 while still isolating switches 7 – 12.
This can be understood more easily through the example below:
If all the switches from 0 – 16 are turned on,
slideSwitchIn; :1111111111111111
counter 2 = slideSwitchIn << 4; :1111110000000000
counter 2 = counter 2 >> 12; :0000000000111111
Thus, even though the values that are saved are from the 7 – 12 bits, it can be read as the first 6 bits.
This method is also done to the last 4 switches for choosing the arithmetic operation. Since the last 4 switches do not need to be shifted to the left, it would only need to be shift once to the right by 12 positions.
Displaying Negative values
To display negative values on the 7-segment display, the previously provided code can be modified to achieve this. Firstly, the argument for the displayNumber() function inside the seg7_display.c must be changed from an unsigned integer to a signed integer to detect whether or not the value that must be displayed is a negative or positive number.
Next, a conditional statement must be added to check whether or not the input argument is negative. However, since displaying a negative number means using one of the four 7-segment displays, the biggest number it can display is -1 and the least number it can display is -999. So the condition should be something like if(number<0&&number>=-999).
Modifying the code used for displaying positive number, since displaying negative numbers mean displaying one more light than the number of digits itself for the negative sign, the while loop condition should look like while(count >= 4 – numOfDigits). Next, a conditional statement must be added inside that while loop. This is to check if the number of the 7-seg display lit is already equal to the number of digits, if this is true, then then next thing to be displayed is the negative sign. The negative sign will always be the last thing to be displayed as the displayFunction displays the number from right to left. The block used to display the negative number is shown in figure 5.
Displaying Decimal Values
To display decimal results in the calculator, the first thing to do is adding definitions for the 7-segment BCD codes inside the seg7_display.h header file. To do this, you will need to find the corresponding binary value for displaying the decimal points for each number in the 7-segment display. To help with this, using the provided values for the non decimal numbers as shown in figure 6. As you can tell from looking at the binary values for digits 1 to 9, the MSB is always one. This is because the MSB represents the decimal point. So converting all the MSB to 0 for numbers 0-9 will light up the decimal points in front of them. Remember, this is also because a ‘1’ turns off a segment while a ‘0’ turns it on. After listing all the corresponding binary values, convert them to hexadecimal. The definitions can be done like shown in figure 7.
After doing this, add the cases inside the displayDigit() function to display the decimals. To make it easier, just make the case to display the zero decimal to case 10. This way, if a value is equal to 0, adding 10 to it can call the function to display the 0 decimal. This can be done for other decimal numbers as well. Then, you must modify the displayNumber() function, by adding a conditional statement for when the input is a decimal. If the input is a decimal, you must make the second value to be displayed to be the decimal case. This is because we are only dealing with one decimal places, so, the second most right value in the 7-seg display will always be the value with the decimal. This is shown in figure 8. This is for when the value is more than 1. If the value is less than one, then you must add a 0 decimal digit after displaying the first value. For example: 0.1, 0.2, 0.3, etc.
The next thing to do is to modify the arithmetic operations that might produce a decimal value such as division, square root, exponential, etc. After performing the arithmetic inside that function, multiply it by ten and return that value. This way, the value of the first decimal can be saved inside a integer variable. this can be done like figure 9. The next step after this is checking whether the output from these operations is initially a decimal or not. This can be done by performing a modulus operation to the input by 10. If it is not equal to zero, that means that it is a decimal. This is because if the value in the arithmetic operation is initially a decimal, for example 1.5, this is then multiplied by 10 to become 15. Even though it is in integer, the value of 0.5 is saved. This means if the ones value is not equal to zero, then it is a decimal initially. If the modulus by 10 of the input is equal to 0, then just divide that by 10 to return it to its original value. This is shown in figure 10.
Displaying Hexadecimal values
To display hexadecimal in the calculator, the first thing to do is adding definitions for the 7-segment BCD codes inside the seg7_display.h header file similar to displaying the decimals. For this, we will have to be able to display A, B, C, D, E, F in the 7-seg display. An example for how displaying the letter ‘A’ is show in figure 11. Remember a ‘1’ turns off a segment while a ‘0’ turns it on. The completed definitions are shown in figure 12.
Another thing to keep in mind is that is the letter B and D are the same as the number 8 and 0 in the 7 segment display, we will be using small letters b and d instead of capital letters. After defining this, an argument must be added to the displayNumber(function) to check if a hexadecimal wants to be displayed. If a hexadecimal wants to be displayed, then the input number must be converted to hexadecimals.
To convert a number to a hexadecimal, Step 1 is to divide the decimal number by 16. Treat the division as an integer division. Step 2, The remainder here will be first value to be displayed in the 7-seg display. This remainder should be a hexadecimal. Step 3, do an integer division again to the result in step 1. Step 4, repeat steps 2 and 3 until the result is 0. This is shown in figure 13. Note: remember to add the cases inside the displayDigit() function. This calculator is only set to be able to change from integer to hexadecimal and wont be able to change from decimal to hexadeicmal.
Program Flow Control
The main file consists of mainly four program sections, these programs are executed based on conditions. There are also 4 buttons used. The buttons are used for going to the next stage, turning on the negative sign, displaying hexadecimal, and showing the result.
The first conditional block that the program will go into when the code is run is the
(if input_numbers == 0). Inside this statement, the function take_input1() is called. This function turns on the led based on the switches, then it executes bit shifting to isolate the first 6 inputs and checks if the negative button is turned on, then it returns the shifted output. This value is assigned to s32 input1. Which is used as an input to the displayNumber() function. Next pushing the next button (left button) here will make input_numbers=1 and read_op_type = 1 leaving the first conditional statement.
(if read_op_type==1). Inside this statement the XGpio_DiscreteWrite(&LED_OUT, 1, slideSwitchIn) function is called again to turn on the LED. Next the bit shifting is executed to isolate the last 4 inputs. This value is saved to disp_op and is an input to the displayNumber() function. This is the value that will be used to choose the arithmetic operation. When the next button (left) is pressed here, read_op_type = 0 and arith_op_type = 1.
switch (arith_op_type). Inside this statement, there are 10 cases, which are the 10 different type of arithmetic operation. Inside each statement, input2=take_input2(), similar to take_input1() but this is for taking the second input from the next 6 switches. Input 2 is used as input for displayNumber(). And when equal button (up) is pressed here, input1 = “arithop”(input1, input2) where arithop is the arithmetic operation chosen, show_results = 1;.
if (show_results == 1). This is the last stage of the program which shows the results of the arithmetic. If the next button is pressed here, the program will go to the read_op_type again to read another arithmetic operation type. Then the previous steps will be repeated, however if the result is a decimal, it will go back to input_numbers = 0 and the previous steps will be repeated.
[1]
D. Cross, "Bit Math Tutorial, " playground.arduino, [Online]. Available: https://playground.arduino.cc/Code/BitMath/#bit_shift.
Demo Video
Comments