The LCD section of this lab was written by Mark Post. He will be the lead T.A. for this lab, his email address is mark@eyetap.org.
The $9.95 LCD from Active has the ribbon connector on the wrong side of the board (the "chip" side). This means that when you connect a ribbon cable to it, instead of the pin numbers going "1,2,3,4..." across the cable, they go "2,1,4,3,...". (look at the way the pin numbers map to the ribbon connectors to see this) The cables I gave out on Friday 22'nd reverse each pair of pins to correct this. Alternatively, if you have one of the $14.95 24x2 displays (the ones that don't come with a ribbon connector), you can solder the ribbon connector on to the "display" side. Then, the ribbon cable wil go "1,2,3,4..." and will be easier to wire.
Also, you can ignore the potentiometer if it's too much trouble. Just connect the Vcont pin (pin 3) to ground and it'll work OK.
When programming the LCD, keep in mind that the LEDs on the STK500 were inverted, i.e. if you send a 1, the LED turns off. The LCD pins aren't inverted, so you should send it the normal 8-bit values.
To connect your keyer switches to the STK500 board, you may want to look at the STK500 manual (the green booklet in your kit, or on the Atmel website). It has diagrams of the way they wired the LEDs and switches that you used for last lab. Keep in mind that this arrangement means that your switch inputs will be bitwise-inverted (just like the STK500 switches)
You need to have both a path to +5v and a path to ground for each of the port pins you're using for your keyer. Generally, the path to +5V should be a large (~10k) resistor called a "pull up" resistor, and the path to ground should be your switch. Assuming your switches are the normally-open type, this means that when the switch is off, the resistor "pulls up" the pin voltage to +5V. When the switch is on (closed), the pin is grounded, and "pulled down" to 0V. Because this means that power flows through the resistor to ground when the switch is on, it's assumed that the switch will be off more often than on (to save power).
The 8515 has internal pull-up resistors, so you don't actually have to use your own external resistors. To activate the internal resistors, after you write 0x00 to the DDR of your port (to make it an input), write 0xFF to the port itself. This seems odd, but writing 1 "out" to the pins of an input port will turn on the internal pull-ups. Then you just need to connect your switches between the port and ground.
Note that this keyer "keyboard" is a very simple set of switches you will buy to learn how keyboards work, and it does not need to be a fullsize keyboard. A fullsize keyboard costs much more (e.g. $10 to $15) but a small surplus keyboard with just a few keys on it (e.g. a calculator keyboard or just a few switches) is a lot cheaper (e.g. 25 cents to $2) and is sufficient to learn the concepts of how larger keyboards work. It will also be a lot simpler to connect than a fullsize keyboard but will still teach important fundamentals of microprocessor systems. However, this lab will also cover the ps/2 protocol. Therefore, if you choose, you may use a ps/2 keyboard or mouse as an input to the AVR. If you already have a keyboard available, a female ps/2 connector is available from Active Surplus or Supremetronic for $2 or less.
If you are implementing a ps/2 keyboard, you may want to get a female ps/2 connector from Active Surplus or Supremetronics.
The HD44780 is a common LCD controller/driver used to display ASCII and other fonts on a dot matrix LCD panel. These panels can be of varying sizes, but all are wired and controlled the same way. Control involves sending command code data and ASCII data bytes over an 8- (or 4-) bit bus. Three control signals - Edge Enable (E), Read/Write (R/W), and Register Select (RS) determine what is done with this data. The specification sheet "hd44780u.pdf" contains all other details about this controller, and is a good read to help understand what's going on.
| AVR ports | Function | LCD Pins |
| GND (0V) | Ground | 1 (GND) |
| VTG (+5V) | Vcc | 2 (Vcc) |
| (pot 0V-5V) | Contrast | 3 (Vcont) |
| PB2 (CTRL2) | Register Select | 4 (RS) |
| PB1 (CTRL1) | Read/Write | 5 (R/W) |
| PB0 (CTRL0) | Edge Enable | 6 (E) |
| PD0 (DATA0) | Data Bit 0 (LSB) | 7 (D0) |
| PD1 (DATA1) | Data Bit 1 | 8 (D1) |
| PD2 (DATA2) | Data Bit 2 | 9 (D2) |
| PD3 (DATA3) | Data Bit 3 | 10(D3) |
| PD4 (DATA4) | Data Bit 4 | 11(D4) |
| PD5 (DATA5) | Data Bit 5 | 12(D5) |
| PD6 (DATA6) | Data Bit 6 | 13(D6) |
| PD7 (DATA7) | Data Bit 7 (MSB) | 14(D7) |
Function Set: 0x30 -- set to use 8-bit data length, one display line, and 5x8 dot fonts
Display on/off control: 0x0e -- Turn on entire display and cursor, nonblinking
Entry Mode Set: 0x06 -- specify to increment memory counter with each write (move the cursor right)
Clear Display: 0x01 -- clear out the DDRAM
When Register Select (RS) is low (0V), the current data byte (D0-D7) is interpreted as a command. When it is high (+5V), the data byte is interpreted as an ASCII character, and recorded in display data RAM (DDRAM). After most command bytes are sent, the LCD will be busy for a few microseconds. During this time any other commands will be ignored. Although it is possible to test if the LCD is busy, the easiest way to aviod this problem is to delay the AVR for about 100 cycles.
Also, for the LCD to "read in" a data byte, Edge Enable (E) has to be high when anything is "sent" from the AVR (the LCD latches data on positive edges). Finally, Read/Write (R/W) must be low for any write operation to occur.
Putting these requirements together, we get the following control sequence to clear the display: (using PORTB for commands and PORTD for data)
The LCD is now configured to display any ASCII character data sent to it. Character bytes are sent in the same way as command bytes, except that RS is set high. To write an 'A', the following is used:
To clear the display, send a Clear Display command (0x01) as above. This will clear DDRAM and reset the address counter to 0. Note that this command takes at least 200 AVR cycles to finish, so an extra delay is needed. To reset the write position without clearing the display, the Return Home command (0x02) can be sent as well.
The most common problem that occurs with the LCD is insufficient delay times, especially if your AVR is running at more than the STK500 default (3.68Mhz). Missed characters and commands often occur because of this. Adding more of a delay after each instruction should fix things. Also be sure to check that all 14 LCD wires are connected properly.
The "avrlcd.c" program contains a more complete implementation of LCD functions, as well as a set of defines for the HD44780 commmand set. More complex LCD functions and programs can be experimented with based on this code.
If you choose a calculator keypad (from a 50 cent calculator at active surplus or salvation army or amity goodwill or other scrap), or a phone keypad, you may be able to get away with only 8 inputs, since these often scan in rows (of 4) and columns (of 4) for a total of 4+4=8 inputs, but this may be a little more difficult than just using separate switches. in some cases, though, you may easily connect four of the inputs (e.g. one row or column) but getting more than four working will be a little more difficult. (it will certainly be a good exercise in understanding the fundamentals.)
Choose pushbutton switches that are easy to press, and small enough to glue to a small handle, or attach to a frame.
Active Surplus sells a large variety of really cheap switches, or you can salvage microswitches from an old machine with cams, or you can make your own switches from metal strips, conductive cloth, or other household materials.
Obviously the 7 button keyboard uses less than 8 inputs. if you choose the simple 7 input switch you will not need to do much additional wiring on AVRs.
To properly wire the switches, look at page 3-2 in the STK500 manual. If you have any questions about the wiring email mark@eyetap.org, any problems will be explained.
You won't be expected to implement the entire character set of all inputs including alt delete, etc. (bonus points if you do, though, and get it working well, e.g. see for example http://wearcam.org/keyboard7buttons.htm and for general interest reading, see also http://wearcam.org/septambi/index.html). Instead, select a reasonable number of letters and symbols and numbers, and implement a reliable entry of this limited set.
You can get full grade (points) for showing a system that would scale to all symbols and numbers without actually implementing all of them, as long as you prove you know all the concepts, and demonstrate the fundamentals of keyers.
Just show us that you know the issues and could easily make a full keyer.
For example, if you choose the 7 button keyboard, show us the letters A,B, and C, as chords, and demonstrate some of the concepts of keyers, such as the seven stages of a single keypress. (See Appendix B of Intelligent Image Processing which is on reserve in the engineering library on the 2nd floor of sandford fleming building, or linked from this site.)
Start by showing us for example, simply 127 numbers corresponding to the binary bits pressed on the keyboard (e.g. print a 1 on the screen when switch 1 is pressed, a 2 when switch 2 is pressed, a 3 when both switch 1 and 2 are pressed together, a 4 when switch 3 is pressed, a 5 when switches 1 and 3 are pressed together, and so on), and then the corresponding letters and other numbers or symbols you decided to map to each of these numbers.
Comment on timing issues and how you might incorporate timing, as in the seven stages described in Appendix B, above.
Implement a timing loop to debounce the switches.
Here is a timing diagram for chording:
_______ _________
\__________/ sw1
_______ _________
\__________/ sw2
This is clearly a 3 (e.g. sw1 and sw2 pressed together).
__________ _________
\__________/ sw1
_______ ____________
\__________/ sw2
However, if you press one key, then let go, and then press another, as in the following timing diagram:
_____________________ _________
\__________/ sw1
_______ _______________________
\__________/ sw2
Your program should assume you meant to press two different characters,
(e.g. a 1 and then a 2) one after the other.
There is a very good website explaining ps/2 protocol at http://panda.cs.ndsu.nodak.edu/%7Eachapwes/PICmicro/PS2/ps2.htm. What follows here is simply a condensed version of that page.
The first thing to do to get the keyboard working is to wire it to the AVR. On a ps/2 connector, there is a clock line, a data line, +5 volts, and ground. If you are connecting the ps/2 device to the AVR there are several ways to go about this. However, any way you choose, you can get +5 volts from VTG of the 10-pin port connectors of the STK500 and ground from a GND line on the 10-pin connector.
The pinouts for each connector are shown below:
|
(Plug) |
(Socket) |
5-pin DIN (AT/XT): 1 - Clock 2 - Data 3 - Not Implemented 4 - Ground 5 - Vcc (+5V) |
|
(Plug) |
(Socket) |
6-pin Mini-DIN (PS/2): 1 - Data 2 - Not Implemented 3 - Ground 4 - Vcc (+5V) 5 - Clock 6 - Not Implemented |
|
|
|
6-pin SDL: A - Not Implemented B - Data C - Ground D - Clock E - Vcc (+5V) F - Not Implemented |
Once you made the necessary connections, you can connect a keyboard to an AVR. If you connect the keyboard directly to the LEDs, you should see the clock and data lines flickering when a key is struck.
The Data and Clock lines are both open collector. A resistor is connected between each line and +5V, so the idle state of the bus is high. When the keyboard or mouse wants to send information, it first checks the Clock line to make sure it's at a high logic level. If it's not, the host is inhibiting communication and the device must buffer any to-be-sent data until the host releases Clock. The Clock line must be continuously high for at least 50 microseconds before the device can begin to transmit its data.
As I mentioned in the previous section, the keyboard and mouse use a serial protocol with 11-bit frames. These bits are:
Figure 2: Device-to-host communication.
The Data line changes state when Clock is high and that data is valid
when Clock is low.
Figure 3: Scan code for the "Q" key (15h) being sent from a keyboard to the computer. Channel A is the Clock signal; channel B is the Data signal.
---![]()
The clock frequency is 10-16.7 kHz. The time from the rising
edge of a clock pulse to a Data transition must be at least 5 microseconds.
The time from a data transition to the falling edge of a clock pulse must
be at least 5 microseconds and no greater than 25 microseconds.
The host may inhibit communication at any time by pulling the Clock
line low for at least 100 microseconds. If a transmission is inhibited
before the 11th clock pulse, the device must abort the current transmission
and prepare to retransmit the current "chunk" of data when host releases
Clock. A "chunk" of data could be a make code, break code, device ID,
mouse movement packet, etc. For example, if a keyboard is interrupted
while sending the second byte of a two-byte break code, it will need to retransmit
both bytes of that break code, not just the one that was interrupted.
If the host pulls clock low before the first high-to-low clock transition, or after the falling edge of the last clock pulse, the keyboard/mouse does not need to retransmit any data. However, if new data is created that needs to be transmitted, it will have to be buffered until the host releases Clock. Keyboards have a 16-byte buffer for this purpose. If more than 16 bytes worth of keystrokes occur, further keystrokes will be ignored until there's room in the buffer. Mice only store the most current movement packet for transmission.
Given this protocol, you may want to connect the clock line of the ps/2 keyboard to an interrupt, and the data line to a line which is easily read. Remember you will need to "shift in" bits when you read data after the interrupt is generated. Generally, the number of bits you will read is 10. When strinking a key on the keyboard, there will be one "scancode" for when the key is pressed, and one when it is released.
| Activity | Mark |
| Show you have the display running by writing a character to the display. | |
| Write a function called printa, a simplified version of printf in C. The function should be such that you may call the function as printa("ECE 385 is great!!!"), and the text will show up on the display. The main function calling the printa function should only have the printa line in it. | |
| Get both lines of the 24x2 display working, and modify your printa function accordingly. | |
| Modify the uart_recv code from the previous lab to display information you enter with sendd on the 2x24 display. | |
| Show a working keyer / ps/2 reader where information can be entered. The design and ease of use of the keyer will decide if 1 or 2 marks a awarded. | |
| Prove that you have taken care of any deboucing issues in the keyer in the case of a microswitch keyer. If you built a ps/2 input device, show a program which reliably reads ps/2 scancodes. | |
| 2 bonus points may be awarded at the discretion of the TA. | |
| Survivability directorate |