Higher Computing 1B - Week 12 Laboratory Exercises

This lab involves:

Hexadecimal Output

First we need a utility function to assist in debugging. Useful C library functions like printf aren't available for you to use on the AVR. It would be very useful to have a function to print hexadecimal numbers to the USB output of the AVR board.


#include "cse_avr_board.h"

void uart_puthex(unsigned int i) {
	// code needed
}

int main(void) {
    uart_puts("Hexadecimal output");
    for (int i = 0; i < 256; i++) {
        uart_puthex(i);
        uart_putchar('\n');
    }
    return 0;
}
If you have problems you might debug your function first in a program on the lab machine.

Keypad Access

The 4x4 alpha-numeric keypad has 16 switches which are normally open. There is a wire for each row (R0..R3) and a wire for each column (C0..C3).

If no key is pressed then none of these wires are connected.

Pressing a key connects one of the row wires and one of the column wires. This table indicate the connections.

Keypad Connections
C0C1C2C3
R0123A
R1456B
R2789C
R3*0#D

Here is a program that accesses the keypad:



#include "cse_avr_board.h"

int main(void) {
    uart_puts("Keypad interface\n");
    uart_puts("Link PC0-PC3 to keypad R0-R3\n");
    uart_puts("Link PA0-PA3 to keypad C0-C3\n");

    volatile unsigned char *portc_control_address = (char *)0x34;
    volatile unsigned char *portc_output_address = (char *)0x35;
    volatile unsigned char *porta_input_address = (char *)0x39;
    volatile unsigned char *porta_control_address = (char *)0x3A;
    volatile unsigned char *porta_output_address = (char *)0x3B;
    
    *portc_control_address = 0x0f; // make PC0..PC3 outputs
    *porta_control_address = 0x00; // make PA0..PA3 inputs
    while (1) {
        *porta_output_address = 0x0f; // pull PA0..PA3 = keypad C0-C3 high
        *portc_output_address = 0x0b; // pull PC2 = keypad R2 low;
        wait(1,0);                    // wait 1 millisecond
        int input = *porta_input_address & 0xf; // input PA0..PA3 = keypad C0-C3 
        uart_puts("PA0..PA3 = ");
        uart_puthex(input);
        uart_putchar('\n');
        wait(200,0);                    // wait 0.2s
    }
    
    return 0;
}

One confusing aspect of the above code is that although port A is used for input, there is this line:


        *porta_output_address = 0x0f; 
This activates internal pullup resisters which ensure that if this line is unconnected it will be high (one).

This code pulls R2, the line for row 2, low (sets it to zero). It looks at C0..C3, the lines for columns 1..4. If any of them are low (zero) then the corresponding key in row 2 is depressed.

Notice when no keys are depressed 0xF is written out indicating PA0..PA3 are all high (ones).

But, if '7' is pressed 0xE is written out indicating PA0 is low (zero). If '8' is pressed PA1 goes low, and similarly for '9' (PA2) and 'C' (PA3).

This code only detect keys in row 2 being depressed because it pulls only R2 low. A loop which one at a time pulls R0-R3 low and examines C0..C3 can determine if any key is depressed.

Modify the code in keypad.c so it produces output like this:


You typed a: '#'
You typed a: '6'
Only one line should be printed for each key press and it should only be printed after the key is released.

If you want to see the desired behaviour download this ihex file to the AVR board.

Finished?

When you have these 2 exercises working show them to your tutor to receive this week's lab mark.

After your tutor has checked that you answers are correct and given you the lab mark, you must also submit your answers using give. Here is the command to use:


% /home/cs1721/bin/classrun -give lab12 hex.c keypad.c