Graphing Calculator
ECE 476 Final Project, Spring 2003
Jeannette Lukito :: Jonathan Wang

:Introduction:
:High.Level.Design:
:Program.Design:
:Hardware.Design:
:Results:
:Pictures:
:Conclusions:
:Appendix:
:Code.of.Ethics:

 

 

 

 

 

 

 

 

Jeannette Lukito
jl259@cornell.edu
Jonathan Wang
jdw24@cornell.edu

Program Design

Interrupt
     The interrupt uses timer 1.
     The interrupt is used to regulate the sync generation. Since a uniform pulse is required every 63.5 microseconds for horizontal sync, we run the clock full-speed at 16 MHz, and interrupt on compare match after 1018 timer ticks. This means each frame is exactly 1/60th of a second. The image content is generated during lines 1 to 230. Most of our code executes within line 231-262. Thus we have a very limited time to make calculations and graph to the screen. The mcu is put to sleep right before the interrupt is to occur. This helps keep the sync accurate. The logic for counting lines, inverting horizontal sync to vertical sync, and running the i/o port is contained within the 5 microsecond pulse time.

Debounce State Machines
     Our software design is divided into three distinct debounce state machines. Each machine controls separate functions of the keys of the keypad. While it is possible to combine the second state machine with the third, we have decided to separate the task for readability and less risk running into bugs.
     Our keypad state machines utilize the basic structure of the debounce state machine that was used in the first lab of the semester. By adding a few new states, we are able to maneuver through the states well enough to run our tasks. Beside the regular four states (‘maybePush’, ‘Pushed’, ‘maybeNotPushed’, ‘noPush’), state ‘Idle’ is added to turn off the state machine when the state machine is not being used. State ‘INIT’ is a simple preliminary state to initialize character arrays and flags back to its original values before starting a new cycle of debouncing. Finally, one last new state is state ‘recorded’. This state is added to avoid recording the keypad button pushed more than once if a ‘slow’ user presses the buttons for a long period of time.
     We design 3 state machines for our graphing calculator module. State machine 1 and 2 will be used for scientific mode and state machine 1 and 3 will be used during graphing mode. The general diagram of the state machines is as follows:


Click on figure for larger picture


     From one state to another, a function called call_keypad() must be called to poll user’s input during that frame cycle time. This program is taken from ECE476 website and has been provided for us for lab 5.

State Machine 1
     State machine 1 is essentially a debounce state machine that controls the first keypad. In order to interpret the keys within the keypad, we make use of a look up table to represent an operand by a number. In the program, the operand can easily be interpreted for calculation. Below is the lookup table numtblone[] that represents the keys for keypad 1.


     Both in scientific and graphing mode, state machine 1 will record user’s input in a character array to be parsed later on after user completed the entry. When the input is an operand, program will save the location of the operand in the character array on another variable ‘oploc’. The program also avoids recording and displaying the simple operands available on this keypad more than once.

State Machine 2
     State machine 2 is active only during scientific mode. It contains our trigonometric functions and other functionalities that we implemented in our calculator. Similar format is applied to this state machine. The numtbltwo[] corresponds to different tasks or functions of the different keys on the pad.


     When user desires to compute a trigonometric function, state machine 2 will go to the state “printTrig”. This state will simply print the desired trig function to the screen, record the number representation of the trig function to the char array, and updates the appropriate x and y location of the TV.
     Along with this, the state machine checks when a user completes entering the function and wish to calculate the result. When ‘enter’ is pressed by user, state machine 1 will be turned off because it is no longer polling for user’s input. In the mean time, state machine 2 will go to a couple states that will solve the function and display the appropriate result to the TV. Since putting all the calculation in one cycle damages the NTSC signal, we have decided to separate this duty into two different states: “ParseA” and “ParseB”.
     The state “ParseA” will simply parse the first input A from the char array. The ending and the start of the next input is indicated by the location of the operand variable, ‘oploc’. A series of ‘if’ statements are needed to provide some error-checking to stop the program from performing calculation on invalid inputs. Finally, the C-provided function atof() is used to convert this char array variables into a float. The next state “ParseB” also be behaves the same way and when both inputs are safely parsed, calculation is performed and displayed to the TV.
     Besides this functionality, the state machine 2 will also go to a series of states when user demands program to ‘clear’ the TV screen. To further avoid signal damage on the TV, the ‘clearscreen’ states are separated into three states. In other words, the clear screen function needs 3 frame cycle to be accomplished.
     The delete button will set the state to ‘deleteOnScreen’. This state simply moves the character array index location back one and it will also display a blank character on top of the previous character to “delete” the input.
     Finally, when user changes the mode from scientific to graphing, state machine 2 will immediately set to idle and state machine 3 (which takes care of the functionalities in graphing mode) will be set in motion.

State Machine 3
     State machine 3 behaves very similarly to state machine 2. However, this state machine will only be active during graphing mode. It will stay in idle state during scientific mode. Upon entering the graphing mode, the state will head straight the ‘clearScreen’ states to remove the scientific mode display and change gear to graphing mode display.


     When a user enters a function, the program will display the function and start polling the user to enter the A, B and C inputs explained in the high level design to complete the function variables to be graphed. The parameter inputs are parsed in a similar way as the inputs in scientific mode. Once all the parameters are recorded, the state will automatically goes to a series of states that will graph the function. There are 3 GraphInit states that will set up the axes, labels, and calculate the desired viewing window. It will then enter the actual Graph state, which will continuously call GraphFunction to draw one point at a time. When the graphing is done, the state machine will go into GraphDone state and wait for the user to input before returning to the inital graphing mode state.

Main Functions
Graphing Functions
  • convertxCoord(float xCoord, float xVal)
    This function simply converts the calculated values to TV x coordinate values
  • convertyCoord(float yCoord, float yVal)
    This function simply converts the calculated values to TV y coordinate values
  • graphFunction(float inputA, float inputB, float inputC, float xCoord, char graphCommand)
    This function takes as input the x-Coordinates and parameters, calculates the y Coordinate, translates both x and y to TV coordinates and either plots a point or draws a line on the screen.
Calculating Functions
  • calculate(float A, float B, int command)
    This is the heart of the calculator, it uses either series approximations or math.h to generate calculations.
  • power(float A, float B)
    This calculates A^B.
Error Checking Functions
  • Myerror(char err)
    This function simply takes in an input ‘err’ that represents 1 out of the 3 possible errors: ‘Undef’ (undefined result), ‘syntax error’ (when user enters a syntax error) or ‘invalid entry’ (when user enters an input outside the boundary of trig function calculation.
  • boundCheck(float inptoCheck, char cmd)
    This boundary checking function is necessary for trigonometric computation. Due to the approximation, we can only calculate the trigonometric functions accurate within +/- 2.5pi, inverse trig functions to within +/- 1, and ln functions above 0.
Display Functions
Note: Most of the display functions have been previously coded and optimized by prof. Land. These functions are:
  • video_line(char x1, char y1, char x2, char y2, char c)
    This function simply connects a line between the two points provided
  • video_smallchar(char x, char y, char c)
    This function displays a specified character from the bitmap.
  • video_pt(char x, char y, char c)
    This function draws a point on the specified location.
     However, to produce some of the operand functions that we need, we rearranged smallbitmap[] to contain more functions. As a result, we needed to modify the function that display these characters according the position of the characters in the bitmap.

video_putsmalls(char x, char y, char *str)
     This function utilizes the ascii characters to locate the correct character in the bitmap. The previous bitmap only contains the number 0-9 and colon(‘:’) (ascii 0x30 to 0x3A) and the capitalized alphabet (ascii 0x41 to 0x90). The modified bitmap is expanded to contain the characters from ascii 0x20 to 0x3A and the usual alphabet.