For our final project, we implemented a drawing program similar to Microsoft Paint using a PS/2 mouse to draw onto a TV screen.
Microsoft Paint is a drawing program that allows the user to create color images by using an assortment of painting tools like the pencil tool, the line tool, the rectangle tool, and the oval tool. The program is relatively simple, yet very useful as well. This made it ideal for a project such as this. We got the idea after looking at various past final projects that implemented basic drawing pads using various other input devices. We decided to expand upon these projects, by implementing additional tools and using a PS/2 mouse as the input device. In the end, the user should be able to easily create complex images on the TV screen through a user-friendly interface.
High Level Design
Our initial goal was to be able to draw and erase images on a black and white TV screen by using the mouse like the pencil tool in Paint. After this goal was completed, we hoped add more tool options, starting with the line tool, moving onto the shape tools like the rectangle and oval tools, and finally finishing up with paint and fill tools. Another potential goal was to implement a more advanced display like gray-scale or color.
After looking at the TV Minesweeper project that previously dealt with video generation interfaced with a PS/2 mouse, we discovered that a single microcontroller would probably not be sufficient to implement our project. The reason for this is that there is not enough time to read all the data from the mouse in the single line interval between each sync pulse generation interrupt. Instead, we would need 2 microcontrollers, one to handle the TV video generation and another to deal with the mouse and the paint program. We could then use the TV microcontroller to send and receive commands to and from the mouse microcontroller via UART communication. An added advantage of this setup is that it enabled us to break up the project into 2 separate main tasks with separate speed and memory considerations. This greatly simplified the programming and debugging process since we were able to better pinpoint the area of concern.
A high-level block diagram of our design is shown below:
1 The two main standards that are relevant to our project are the PS/2 Mouse Protocol developed by IBM and the National Television System Committee (NTSC) video standard for the TV. The PS/2 Mouse Protocol specifies the physical PS/2 port as a 6-pin mini-DIN, with Pin 1 carrying the mouse data, Pin 3 to ground, Pin 4 to 5V DC Power, and Pin 5 carrying the mouse clock. A pinout of the PS/2 mouse port, from Adam Chapweske’s page on the PS/2 mouse, is shown below:
The mouse uses a serial protocol to transmit the data, starting with a start bit, followed by 8 data bits, followed by a parity bit, and finally a stop bit. In the remote mode of operation, the mouse sends its movement and button information using three bytes every time the host microcontroller requests data. For this project, we used an adaptation of the NTSC standard that we also used in Lab 4.
There are a number of various paint programs (such as Microsoft Paint) which are well-known for accomplishing similar functions as our design. We do not feel we have infringed upon any existing copyrights or patents since our design is very simple and has limited commercial applications. As a result, there is no potential for receiving a patent for our design.
We split up the code between our 2 different microcontrollers. One, mcu_mouse.c, received information from the mouse and sent information about the status of the mouse to the TV and the other, mcu_tv.c, generated the TV signal and contained the code that allowed the user to draw various shapes. For the mcu_mouse.c code, we used the basic mouse communication functions (mouse_send, mouse_read, poll_mouse, and reset_mouse) that were developed by Chee Ming, Chaw and Elaine Siu for their Minesweeper Project for this course last year. For the mcu_tv.c code, we used Professor Land’s code from Lab 4 as the basis for our own code.
In the mouse code, we would handle the selection of tools from the left hand side of the screen and limit the mouse to the portion of the screen the user was allowed to draw to. We would not notify the TV of a mouse click if the user was selecting a new tool. By doing this, we prevented the tool menu from being part of the drawable screen while allowing the TV to know that a new tool had been selected.
At a regular interval, scheduled by timer 1, we polled the mouse for information and updated the state variables related to the cursor position and button state. We then sent this mouse information to the TV MCU. The information sent by Mouse MCU to the TV MCU is shown in the diagram below:
Figure 3: Information sent over UART from Mouse MCU to TV MCU
The information includes the cursor position, button status, and current tool. This information is sent through UART communication at 57600 bps.
The mouse button could be in one of four different states: button not pressed, button initially down, button dragging, and button released. Given information about whether the button was down or up and the state of the mouse the last time it was polled, we determined the current state of the mouse button that would then be sent to the TV. The button initially down state would occur once per mouse click and would only last for the instant at which the user clicked the mouse button. The button dragging state would exist while the mouse button was being held down and the mouse was being moved around the screen. The button released state would occur once per mouse click after the user released the button. A state transition diagram of our mouse button states is shown below:
Figure 4: Mouse Button State Machine
The TV MCU receives information from the Mouse MCU at a regular intervals and then processes this information. Depending on the button state and current tool, the TV MCU would then store relevant information or draw what needed to be drawn to the screen. If in the button initially down state, the TV MCU stores the cursor position into a variable called click_origin which would be used as the initial point for the line or the initial point representing the bounding box of the rectangle or oval. In the button dragging state, the pixels in the screen array are permanently updated if the current tool is the point tool, spray tool, brush tool, or erase tool. In the case of the line, rectangle, or oval tools, we would draw a wire frame or set of points representing the final shape so that the user could preview what the final image would look like before printing something to the screen. For these 3 tools, we used the invert option in the drawing routines so that we could draw a line and then invert at the next frame in order to easily erase it without affecting the permanent image that would be displayed on the screen. In the button released state, the line, rectangle, or oval would be drawn permanently to the screen with paint. In this state, the cursor location would be used to determine the second point of the line or bounding box for the oval or rectangle.
To draw the ovals, we used arrays of sine and cosine values stored in flash which could then be used to accurately draw a circle. During the final painting of the circle in the button released state, we had to disable the screen refresh because the calculation was intensive and took a long time to draw to the screen buffer. For our spray paint tool, we created 8 frames of bitmaps containing randomly-generated pixels which would be drawn to the screen buffer at the cursor location.
One of the most challenging problems that we ran into was how to draw a pixel at the cursor location without affecting the permanent image that would be drawn to the screen. During each screen buffer refresh we would store the color of the cursor location and then invert that pixel to show where the cursor was. Additionally, we needed to set the pixel at the last cursor location to what it was before the mouse was moved there. The situation became more complicated if that pixel was drawn to with permanent paint. We had to use information about the color of the pixel in order to overcome this.
In order to fully implement our design, we needed to add 2 additional functions, put_icon and put_spray. Put_icon would draw a bitmap with an opaque mask which would overwrite all the pixels in the area of the bitmap with the bitmap image. Put_spray would draw an icon from a bitmap but would only draw specific pixels if they were a 1 and would leave other pixels untouched.
- 1 PS/2 mouse ($1.75)
- 1 PS/2 receptacle to connect mouse port to our hardware (1 x $0.75)
- 1 small solder board (1 x $0.80)
- 1 TV with cable (free from lab)
- 2 Atmel Mega32 microcontrollers (2 x $8.00)
- 1 STK-500 board (free from lab)
- 1 white boards (1 x $5.00)
- Resistors, capacitors, LEDs, wires (free from lab)
- TOTAL COST = $24.30
For more detail: Paint Program with Mouse Control Using Atmel Mega32