Mega Touch
"A TFT LCD with resistive touch screen powered by an ATmega644 with touch-focused minigames."
Created by:
Benjamin Harris (bth44) and Philip Bernard (pb334)
Introduction
With the increasing popularity of smartphones and tablet computers, touch has become one of the most common user interfaces encountered today. For our final project design we have converted a number of open-source C++ libraries to C in order to interface with an LCD and touch screen via the Atmel ATmega644 microcontroller. In addition to these new libraries we included three pieces of software: a free drawing mode, a game called Yellow which pays homage to the arcade game Pac-Man© developed by Namco in 1980, and the classic pencil and paper game Tic-Tac-Toe. Each piece of software serves to demonstrate some of the many capabilities of the LCD and touch screen combination.
High Level Design
Project Rationale
Our goal for the final project was to provide the ECE 4760 course with an easy to setup and cheap touch screen interface to be used with the Atmel ATmega644 microcontroller. While researching ways to implement this, we found the tutorial for an Arduino-based touch screen provided by LadyAda. The resulting C libraries that we created for our device are based upon the open-source C++ libraries provided in the tutorial.
We opted to display images with an LCD screen rather than using a CRT monitor due to the onboard memory of LCD screens. This means that the entire screen does not need to be refreshed when displaying a new image. This severely reduces the amount of overhead required by the CPU to update the screen.
Hardware Tradeoffs
The touch screen used in our project uses resistance rather than capacitance to sense touch. Resistive touch screens consist of two plastic sheets covered with a resistive coating separated by a very thin gap of air. Each sheet contains vertical and horizontal lines that allow for precise location measurement when they come in contact with the lines of the opposite sheet. Resistive touch screens have a number of advantages and disadvantages when compared to capacitive screens. The major benefit for us, due to the limited budget of the project, is the reduced cost. Resistive screens are also highly resilient to liquid damage, and so are widely used in restaurants and hospitals where liquid hazards are more common. The major disadvantage is the need for pressure in order to sense touch. This means that the screen can be easily scratched if the user is using a sharp object as a stylus. For this reason, we recommend using a plastic protective cover to mitigate damage to the screen.
Relevant Patents
Many of the touch screen design patents that were filed during the 1970s and 1980s have since expired. Therefore, use of touch screens and different designs are no longer hindered by potential patent infringements. Software patents for touch screens such as multiple input sensing and page scrolling do exist, but our project does not implement any of these methods and so is not in violation of the owners' intellectual property.
Hardware
^TopThe only hardware used for this project is the protoboard with an ATmega644 and a TFT LCD with resistive touch screen purchased from Adafruit. The LCD is a 2.8" 320x240 pixel resolution screen with an attached resistive touch screen. A built in linear regulator allows the screen to be used with either 5V or 3.3V logic. The wiring was done using a tutorial from LadyAda. The LCD screen has four control lines, eight data lines, a reset pin, a backlight pin, four pins for the touch screen, VCC and ground. VCC is connected to 5V from the MCU and ground is connected to MCU ground. The backlight should always be on, so it is simply connected to VCC. It is possible to use a PWM signal to dim the backlight, but that was not necessary for this project.
The four control signals are chip select, command/data, write, and read. They are connected to pin C0, pin C1, pin C2, and pin C3, respectively. The chip select pin is held low for the duration of register reads and writes and when a command or data is being written. Immediately following the read or write the pin is set back to high. The command/data pin is set low while writing a command or writing a register. It is kept high while writing data or reading data from the LCD. Once the command or register is finished being written, the command/data pin is set high again. When writing a register or data to the LCD, the data is written eight bits at a time. First, the eight data lines are set to their appropriate values using the write8 function. The write pin is set low and then immediately set high. If 16 bits of data need to be written, the write8 function is called again for the second 8 bits. The write pin is then toggled again to write the data. When reading data from the LCD, the read pin is toggled low and the data is read using the function read8. Once the bits are read, the read pin is set high again. If more bits need to be read, the read pin is set low and the next eight bits are read. Once finished, the read pin is set high again.
The eight data pins are connected to pins B0, B1, and D2-D7. D0 and D1 are left unconnected so that serial communication can still be used. The data pins are bidirectional; they are set to outputs when writing data and inputs when reading data. This is achieved using the setWriteDir and setReadDir functions.
The reset pin is active high. It is connected to pin C4. It is left high for the duration of the operation of the LCD screen and is only set low when the program first starts in order to reset the LCD controller chip.
The four pins for the resistive touch screen are Y+, Y-, X+, and X-. Y+ is connected to pin A0, X- is connected to A1, X+ is connected to A2, and Y- is connected to A3. The X position on the touch is determined by setting Y+, Y-, and X- to ground and X+ to high. The voltage on Y+ is then read. To get the most accurate position, the 10-bit ADC result from the microcontroller is used. This requires reading the low bits first and then reading the high bits and concatenating the results. The final raw x position returned is the 10-bit ADC result subtracted from 1023. The Y position is determined in a similar way. This time the X+, X-, and Y- pins are grounded and the Y+ pin is set high. The voltage on the X- pin is then read.
As this is a resistive touch screen, the pressure must be measured to determine if someone is actually pressing on the screen. This is accomplished by setting X+, X-, and Y+ to ground and Y- high. First the voltage across X- is read, then the voltage across Y+. The pressure is determined using the following equation:
pressure=[(Y+/X-)-1]*(330*Xpos)/(1024)
The value 330 is determined by measuring the resistance across the X+ and X- pins with a digital multimeter and is unique for each touch screen.
Software
^TopThe software for this project is based off of the open-source libraries released by Adafruit. There are three libraries: TFTLCD, TouchScreen, and Adafruit_GFX. These libraries are written for Arduino microcontrollers and are in C++. Converting the libraries to C involved removing the classes and converting all of the functions to static functions. The libraries also contained a large number of Arduino specific functions. These functions were manually replaced with code that performs the same functionality, but that works on the ATmega644. The touch screen libraries were initially using PORTC as inputs to the ADC. However, since the input to the ADC on the ATmega644 is PORTA, this had to be changed. To see the mapping of all of the pins, refer to the hardware section. To make it easier for future students to use, the converted libraries are located in separate C files from the programs we wrote. The TFT LCD and Adafruit_GFX libraries have been combined into a single C file. A few additional functions were added to the libraries. These include the map function which is included in the Arduino software package. This function remaps a number from one range to another. Additional drawing functions added include the ability to draw half a circle and the ability to draw strings instead of individual characters. Comments were also added to the header files to allow the user to quickly understand what a function does and what the appropriate inputs are.
To showcase the capabilities of the touch screen and LCD, three simple programs were written. The first is a simple drawing program based off an example provided with the TFT LCD library. The second is a Tic-Tac-Toe game which allows the player to draw X's on their turn. The final program is Yellow. Yellow is a simple demonstration that draws its inspiration from the popular arcade game Pac-Man©, created by Namco in 1980.
When the user first turns on the ATmega644 they are presented by the main menu. This menu contains the title, three virtual buttons, and instructions about how to get back to the main menu from each program.
The menu was created by first filling the entire screen black using the fillScreen function. Then three grey boxes are drawn in the middle of the screen to make the "buttons" using the fillRect function. Next, the text is drawn using the drawString function. Once the menu is drawn, the program waits in an infinite while loop for user input. On each iteration of the loop the program gets the x and y position from the touch screen as well as the pressure.
Since we are using a resistive touch screen, a threshold pressure must be used in order to determine if the user is actually touching the screen or if it is just noise. The pressure values we considered were between 250 and 750. When a valid pressure is detected, the program then determines where the user is touching. The x and y values read from the touch screen must first be mapped to the resolution of the LCD to give a useful x-y position. This is done using the map function which is provided by Arduino. The program checks the x and y position against the boundaries of each "button." If the user touches within a "button," then the program calls the function to launch the appropriate program. As indicated by the message at the bottom of the menu, the user can return to the main menu from any program by simply touching the very top of the LCD screen. When the user touches the top of the LCD screen, the running program will detect this touch, return to main and the main menu will be redrawn. The positioning of the text and "buttons" on the menu was determined by estimating the appropriate position given the resolution of the screen and then doing a bit of guess and check positioning.
Free Draw
When the user clicks on the Free Draw button, the free_draw function is called. The program first clears the screen using the fillScreen function. The program then draws 6 colored squares across the top of the screen using the fillRect function. A second row of white squares are drawn under the color buttons also using the fillRect function. The white squares are then filled in with different icons to represent their function.
The left two buttons will increase and decrease the size of the drawing pen. This is indicated by putting a small circle in the left square and a large circle in the right square. The circles were drawn using the fillCircle function. The middle two buttons are used as erasers. The left button will clear the entire drawing; it is indicated with an 'X'. This works by filling the drawing area with black using the fillRect function. The right button changes the pen to an eraser. This is indicated by an 'E.' The eraser simply turns the user's pen black. The size of the eraser can be increased and decreased in the same way the pen size is changed.
There are twenty-four different colors the user can choose from. These colors are split into four groups of six colors. When the free draw program starts, the first set of colors is displayed. The currently selected color is indicated by having a white border around it. When the user touches a different color, the pen color changes and the white border is moved to the selected color. The right two buttons on the screen allow the user to scroll between different sets of colors. The buttons are indicated by the '<' and '>' characters. Pressing one of these buttons changes the state which will then redraw the colored squares at the top of the screen to represent the colors available in the selected set. The colors in each set are generically defined at the top of the C file in the format SXCY where X represents the color set (0-3) and Y represents the color number in the set (1-6). Changing a particular color in the set is as simple as changing the defined value.
When any of the buttons are touched, the touched button will be momentarily be surrounded by a blue border to give the user visual feedback. This is achieved by using the drawRect function. This function is similar to the fillRect function except it only draws the border and therefore is much quicker to update.
Below is a sample drawing done in the free draw program.
Tic-Tac-Toe
The Tic-Tac-Toe program starts similarly by first using the fillScreen function to clear the screen. Next the program draws the text for the score keeping using the drawString function. Two grey "buttons" are drawn using the fillRect function so the user can change between easy and hard difficulty. Finally, the grid is drawn using the drawLine function.
Once the screen is initialized, the program waits for user input. To make a move, the user draws an 'X' into a chosen square. The function detects an 'X' when the user draws twice in the same square. When the program detects a touch in a square, it increments the touched variable. This variable is kept at a constant value until the user stops touching the screen; at which point touched is incremented again. When the user touches that same square again touched is incremented a third time. Finally, when the user stops touching the screen, the 'X' is considered done. When a square is occupied, the player is prevented from drawing in that square. The game ends when the player wins, the CPU wins, or there are no more unused spaces left. If a win has occurred, a white line is drawn across the winning moves to indicate the victory. The squares are then cleared and the grid is redrawn. Finally, the appropriate score is updated and redrawn. For each game the player and CPU alternate who starts.
The game can be played with two difficulty modes: easy and hard. Easy mode is segmented into two versions. The first is when the CPU has the first move of the game. In this case, the CPU simply chooses a random unused space in the 3x3 grid. This makes beating the computer quite trivial, but serves as a nice introduction to using the touch screen to place a player's moves. If the player starts the game, the CPU will make much more strategic moves. The CPU starts by seeking a victory in the next move. If this is not possible, it will determine if it can block the user from a victory. If neither of these is the case, then the CPU will choose a random unused space to occupy.
The reason the easy mode logic is parsed in this way is because we ran out of space to include the smarter moveset for both cases of either the user starting the game or the CPU starting the game. Including this more sophisticated logic for both cases, along with the rest of the software for our project, overran the limits of the instruction memory in the ATmega644. Because we wanted to keep the "perfect" AI used in hard mode intact, we decided to make easy mode significantly easier for the case when the CPU starts to decrease the total number of instructions.
For the hard mode of Tic-Tac-Toe, we have implemented a computer opponent which will always choose the correct move. This results in the game ending in a tie or a computer victory. The logic is implemented in two different state tables: one for when the CPU player makes the first move and a second for when the human player makes the first move. For the first table we used the following image from Brent Yorgey:
The image shows the optimal move (represented by a red X) to counter each of the opposing player’s moves. To read the image, start with the outermost 3x3 grid. Based on the largest red X, the best first move to make is in the bottom right corner (or any of the corners, really, and then translating the elements of the grid as necessary). Then, go to the square that the opposing player chose to use. This square now represents the current 3x3 grid, and the red X shows where to place the optimal move. This process is repeated until the game ends in a tie or the CPU wins.
To implement this image in software, we utilized many if-else statements. Though this may not be the most efficient execution, we were not under any strict timing requirements given that the CPU is playing against a human. Also, this method was the most straightforward to implement. On each passage through the if-else logic, the CPU checks what space the player chose for each of their moves. Following this check, the CPU makes the optimal move based on where the above image shows that move should be located.
A similar, yet much larger, series of if-else statements were designed to implement the CPU’s moveset for when the human player starts the game. The image depicting this optimal mapping is shown below:
Tic-Tac-Toe Code Specifics
Each space in the Tic-Tac-Toe grid is mapped to a single integer as follows:
A nine-element array, used, is declared to store whether a space in the grid is occupied or free. If the space is occupied by the human player, then that index of the array is given a value of 1. If the space is occupied by the computer, then the value in the array is set to 2. In easy mode, the computer looks for an unoccupied space by randomly picking a number between 0 and 8, and then checking the corresponding index of used. If the space is occupied, the computer picks another random space until it finds a free one. This code can be seen below:
while(used[cpu_move] != 0) {
cpu_move = rand() % 9;
}
For hard mode, a second nine-element array, user, is initialized to track where the human player moves on each of his/her turns. The index of the array represents the space in the 3x3 grid occupied by the human player, and the value represents on what turn the player moved there. The value is 0 if the player is not occupying that space. For example, consider the following sequence of moves by the human player:
- Player moves to space 4
- Player moves to space 0
- Player moves to space 7
- Player moves to space 2
At the end of this sequence user will be as follows:
user = [2, 0, 4, 0, 1, 0, 0, 3, 0]
An integer variable, user_move, keeps track of which turn the human player is on. This variable, along with the elements of the user array, are used in the conditional expressions of the if-else statements. For example:
if (user_move == 2) { // First move for CPU
if (user[0] == 1) { // User in upper left corner
cpu_move = 4;
}
This sequence of code says that if the human player is at their second move, and they occupied the upper left corner of the game grid on their first move, then the CPU should occupy the middle of the grid. Statements such as these are iterated until every possible game scenario is covered. The full code can be viewed in the Appendix.
Just as with the free draw program, touching the top of the screen returns to the menu.
Yellow
The final program is Yellow. The motivation behind Yellow was to show the capabilities and limitations of the LCD in terms of animation. Yellow is a limited-feature "game" that draws inspiration from Pac-Man©. Yellow must move around the level and eat all of the yellow circles. The user controls Yellow by swiping their finger or a stylus across the screen in the direction they want Yellow to move.
The level is drawn using the drawLine function. Placement of the lines involved a tedious combination of careful planning and guess and check work. Yellow himself is a two-step animation. The first step involves drawing a yellow circle using the fillCircle function. Then a black line is drawn for his mouth. On the second animation step, a black triangle is drawn so that is looks as if Yellow's mouth is open. This two steps are repeated to create the animation. There is a 100 millisecond delay between steps, resulting in an effective animation rate of 10 frames per second. There are three Yellows on the screen. All of them are animated in the same way.
The Yellow character motion is done by incrementing the x or y position of the circle being drawn. If the direction is up or down, the y position is incremented by -5 or 5, respectively. If the direction is left or right, the x position is incremented by -5 or 5, respectively. The animation involves an additional step when Yellow is moving. The half circle on the opposite side of direction of motion must be removed from the screen. For example, if Yellow is moving to th right, the left half circle must be cleared. To do this, the fillCircle function is duplicated four times and modified to allow drawing of half circles. These functions are: drawTopHalfCircle, drawBottomHalfCircle, drawLeftHalfCircle and drawRightHalfCircle. Once the appropriate half of the circle is cleared, Yellow's x or y position is incremented and he is redrawn in the new location.
On each animation step, the position of Yellow is checked against known legal positions. This prevents Yellow from going through walls. The animation of Yellow is also stopped when he can no longer move in his selected direction. In addition, his position is checked so that the user cannot select an invalid direction. In the center of the level, Yellow can warp from one side of the level to the other. This is done simply by checking the x position. If it is greater than 240, he warps to the left side of the screen. If it is less than 0, he warps to the right side of the screen.
The level is filled with yellow circles and the corner circles are slightly larger then the normal circles. These circles are all drawn using the fillCircle function. When Yellow moves over these circles, he draws over them. Once he passes through them, they are not redrawn, giving the impression that he has eaten the circle. As mentioned earlier, the direction of Yellow is changed by swiping the screen in the desired direction. This is done by noting the x-y position of where the user first touches the screen and then comparing it with the x-y position when the user stops touching the screen. The greater pixel change determines the direction Yellow will now move. To determine the final x-y position touched, the loop updates an x and y variable. When the user first touches the screen, a flag is set. When the user releases the screen, the flag sends the program into a conditional statement that will change the direction and the flag is reset.
The ghosts are drawn using a combination of circles and rectangles. First the top half of a circle is drawn. Then a rectangle is drawn for the body. Finally three bottom halves of circles are drawn for the "legs." The eyes are drawn by creating two white circles and then filling a single blue pixel for each pupil. The function drawPixel is used to draw individual pixels. The timeframe for the project, unfortunately, did not allow for the ghosts to be able to chase Yellow around the screen. However, to make the ghosts more interactive, several are drawn and their eyes will follow Yellow as he moves around the screen.
Two final touches added are a cherry and strawberry. The cherry is simply two overlapping circles with a stem drawn pixel by pixel. The strawberry is slightly more complicated. It required three overlapping circles. The green "hat" and the white stem as well as white dimples are drawn pixel by pixel using the drawPixel function.
The software for this project stressed the space available on the microcontroller for the program. The program takes up 98.6% of the instruction memory space. Most of this is the AI for Tic-Tac-Toe which is over 3000 lines of code in total.
We have included a small, custom Python script to convert 24-bit RGB values to 16-bit RGB values so they can be used with this LCD.
Library Functions
^TopHigh Level Drawing Functions
- void drawPixel(uint16_t x, uint16_t y, uint16_t color);
Change the pixel at position (x, y) to the specified color. - void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
Draws a line from (x0, y0) to (x1, y1) in the specified color. - void drawFastVLine(uint16_t x, uint16_t y, uint16_t h, uint16_t color);
A slightly faster version of drawLine. Draws a vertical line from x,y to x, y+h in the specified color. - void drawFastHLine(uint16_t x, uint16_t y, uint16_t w, uint16_t color);
A slightly faster version of drawLine. Draws a horizontal line from x,y to x+h,y in the specified color. - void drawRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
Draws the perimeter of a rectangle at position x,y with width w and height h in the specified color. - void fillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
Draws a rectangle at position x,y with width w and height h in teh specified color. - void fillScreen(uint16_t color);
Fills the entire LCD in the specified color. - void drawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Draws the perimeter of a circle with center x0,y0 and radius r in the specified color. - void drawCircleHelper(uint16_t x0, uint16_t y0,uint16_t r, uint8_t cornername, uint16_t color);
A helper function used to draw the corners of a rounded rectangle. The corner name indicates which corner of the rectangle. - void fillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Draws a circle at center x0,y0 with radius r in the specified color. - void fillLeftHalfCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Draws the left half of a circle with center x0,y0 with radius r in the specified color. - void fillRightHalfCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Draws the right half of a circle with center x0,y0 with radius r in the specified color. - void fillTopHalfCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Draws the top half of a circle with center x0,y0 with radius r in the specified color. - void fillBottomHalfCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Draws the bottom half of a circle with center x0,y0 with radius r in the specified color. - void fillCircleHelper(uint16_t x0, uint16_t y0, uint16_t r, uint8_t cornername, uint16_t delta, uint16_t color);
A helper function used for the fillCircle and fillRoundedRect functions. - void drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
Draws the perimeter of a triangle with corners x0,y0, x1,y1, and x2,y2 in the specified color. - void fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
Draws a triangle with corners x0,y0, x1,y1 and x2,y2 in the specified color. - void drawRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
Draws the perimeter of a rectangle with rounded corners at x0,y0 in the specified color. The width is w, the height is h and the radius of the corners is r. - void fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
Draws a rectangle with rounded corners at x0,y0 in the specified color. The width is w, the height is h and the radius of the corners is r. - void drawBitmap(uint16_t x, uint16_t y, const uint8_t *bitmap, uint16_t w, uint16_t h, uint16_t color);
Draws a Bitmap from program memory at the position x,y with width w and height h. *bitmap is the pointer to the bitmap in memory. - void drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size);
Draws the character c at position x,y in the specified color at the specified size. - void drawString(char string[]);
Draws a string to the screen at the cursor position in the current text color and size. Strings must end in '\n'. - void setCursor(uint16_t x, uint16_t y);
Sets the text cursor position to x,y. - void setTextColor(uint16_t c);
Sets the text color to c. - void setTextColor2(uint16_t c, uint16_t bg);
Sets the text color to c and the background color to bg. - void setTextSize(uint8_t s);
Sets the text size to size s. - uint16_t height(void);
Returns the height of the screen in pixels. This changes with rotation. - uint16_t width(void);
Returns the width of the screen in pixels. This changes with rotation. - void setRotation(uint8_t r);
Sets the rotation of the screen to r. r can be 0,1,2 or 3. - uint8_t getRotation(void);
Returns the current rotation of the screen.
Low Level LCD Functions
- void begin(uint16_t id );
Initializes the LCD controller. The ID for our controller was 0x9325. - void reset(void);
Resets the LCD controller. - void writeData(uint16_t d);
Writes 16-bit data d to the LCD controller. - void writeCommand(uint16_t c);
Writes 16-bit command c to the LCD controller. - void writeCommand8(uint8_t c);
Writes 8-bit command c to the LCD controller. - uint16_t readData(void);
Reads 16 bits of data from the data lines. - uint16_t readRegister(uint16_t addr);
Reads the specified register on the LCD controller. - void writeRegister8(uint8_t a, uint8_t d);
Writes the 8-bit data d to register a. - void writeRegister16(uint16_t addr, uint16_t data);
Writes the 16-bit data to register addr. - void write8(uint8_t d);
Writes 8-bit data d to the data lines. - void setWriteDir(void);
Sets the data pins to outputs. - void setReadDir(void);
Sets the data pins to inputs.
Touch Screen Functions
- long map(long x, long in_min, long in_max, long out_min, long out_max);
Maps the value x from the range in_min, in_max to the range out_min, out_max. Used to convert the raw x,y postions to usable screen positions. - int readTouchX();
Returns the raw x position of where the screen is being touched. - int readTouchY();
Returns the raw y position of where the screen is being touched. - uint16_t pressure(void);
Returns the pressure of the touch. This is used to determine if the user is actually touching the screen.
Results
^TopThe screen is capable of displaying great 16-bit colors and offers an excellent resolution of 320x240. The only disappointment with the hardware is the lack of accuracy of the touch screen. If constant pressure is not consistently applied, the touch is not always detected. Playing with the pressure threshold helped, but did not completely fix the issue. Our other complaint is with the speed of the microcontroller. Even with a 20MHz crystal, the ATmega644 was not fast enough to do animation without noticeable flickering. The compiler optimization was required to be OS since we used almost all available space on the microcontroller. Compiling with O0 optimization resulted in over 199% usage of program memory space.
The touch screen is designed to be easily usable by people of all ages. There is a small learning curve to understanding how the screen reacts to the pressure applied, but once overcome, the device becomes trivial to use.
Conclusions
^TopExpectations
The outcome of our final project met the majority of our expectations. We successfully converted the C++ libraries provided by LadyAda to be used with the ATmega644 and have an easy to setup interface between the microcontroller and LCD/touch screen combination. We were also able to develop three different pieces of software to demonstrate the capabilities of the touch screen.
Given more time, we would have liked to refine the included software demonstrations as our code consumes approximately 98% of the instruction memory in the microcontroller. We could have gone through the code to make it more efficient, reducing the instruction count and allowing us to implement some other ideas.
One expansion that could be explored for our free drawing program is being able to save a user's drawings to memory. If the microcontroller and touch screen were packaged into a portable, battery-powered device, an easy to carry drawing pad could be created. With the ability to save drawings, the user could then upload them to a computer later where they could be further developed and refined.
Applicable Standards
Since we did not use a CRT monitor, we were not restricted to conforming with the NTSC or PAL standards for video output. No other standards were applicable to this project.
Ethical Concerns
Since a considerable portion of our project was based on code provided by outside parties, we have made it our priority to adhere to the IEEE Code of Ethics and provide acknowledgement for any and all borrowed software and hardware. Throughout this report we have indicated where a specific idea or piece of code was developed by someone other than ourselves and linked to their websites where the original content may be found.
In an attempt to improve the understanding of the libraries obtained from LadyAda we have added numerous comments into our conversions so that new users will not be confused about the functions of each library.
As we used free open-source materials in our project, all of the files developed will also be open-source. Therefore, everything designed in this project, ranging from the libraries to the software demonstrations, is not meant for commercial sale and should be made freely and publicly available to anyone seeking to use them.
While working in the lab we made ourselves available to questions from any other students looking for help, and sought help from them and the TAs when necessary. It is our hope that our project may provide a simple and easy to use touch screen interface for the Atmel ATmega644 microcontrollers for use by future versions of ECE 4760 or by any other interested parties.
Legal Considerations
The C++ libraries provided by LadyAda that were converted for this project are open-source Arduino libraries, licensed under a Creative Commons Attribution Share-Alike license. This license allows for both personal and commercial use of the works so long as appropriate reference is given and that the designed works are released with the same license. By uploading our source code to the ECE 4760 website we have made our code publicly and freely available to anyone who wishes to use it, so long as they give appropriate acknowledgement to us for our work.
The demonstration Yellow that we created for this project is our small-scale interpretation of the arcade video game Pac-Man© which was created and developed by Namco and published in the United States by Midway in 1980. However, because our design is only used as a demonstration and is not being used for commercial purposes, it is protected under United States copyright law by the fair use doctrine.
No entity holds a copyright of the game Tic-Tac-Toe, and so its use is not restricted by United States copyright law.
Appendices
^TopSource code
Main.c | free_draw.c | Tic-Tac-Toe.c | Yellow.c | Programs.h |
Adafruit_GFX.c | Adafruit_GFX.h | TouchScreen.c | TouchScreen.h | glcdfont.c |
RGB.py | uart.c | uart.h | ||
Download all |
Schematics
Parts List
Part | Source | Unit Price | Quantity | Price |
ATmega644 | Lab | $8.00 | 1 | $8.00 |
Custom PC board | Lab | $4.00 | 1 | $4.00 |
Large white board | Previously owned | $0.00 | 1 | $0.00 |
Small white board | Previously owned | $0.00 | 2 | $0.00 |
12 Volt power supply | Lab | $5.00 | 1 | $5.00 |
Wires | Lab | $0.00 | 20 | $0.00 |
2.8" LCD with resistive touch screen | Adafruit | $40.00 | 1 | $40.00 |
Header pins | lab | $0.05 | 32 | $1.60 |
Total Cost: | $58.60 |
Task List
Ben | Shared | Phil |
Library conversions | Project research | Tic-Tac-Toe program |
Free Draw | Program debug | Tic-Tac-Toe AI |
Yellow | Adapting report to website template | |
Hardware setup |
References
^TopWriting tutorial
LCD product page
LCD controller Datasheet
Adafruit GFX Library
Adafruit TFTLCD Library
Adafruit Touch Screen Library
Tic-Tac-Toe solution diagrams
ATmega644 Datasheet
Acknowledgements
We would like to thank Bruce Land (brl4), Joe Montanino (jmm536), and Pavel Vasilev (ppv5) for all of their support throughout the semester.
We would also like to thank Adafruit and LadyAda for providing the libraries for the LCD and touch screen.
Thank you to Joao Diogo Falcao (jl2782) for ideas on how to improve the Yellow game. Finally, we would like to thank Dr. David R. Schneider (drs44) and the Cornell Cup team for allowing us to use their lab space and borrow parts for the project.
Website template provided by Cornell University.