Thursday, March 22, 2012

6522 VIA Experiment #3

Up to now we've been playing with output so let's look at an example that uses input. Any lines of the 2 8-bit VIA ports can set as inputs and the value of the input (high or low) read from the output register. Timer 2 has an interesting mode - it can count pulses on line PB6. Once set up it will count pulses and update the timer registers, counting down. You can even have it generate an interrupt when the counter reaches zero.

For our example let's count pulses on the input. To do that we need a little hardware: a pullup resistor to +5V to keep the line high and a push button to ground to drive it low when pressed. The timer counts a pulse each time the PB6 line goes from high to low.

Below is our program. We set up the VIA not to generate any interrupts and set T2 to pulse counting mode. We initially set the timer to the maximum possible count, $FFFF. Then we start reading the low order count register to see when it changes. When it does, we display the upper and lower counter values.

Now the counter counts down. We really want to count pulses, counting up. If we want to convert this count down to a count up we can use a little trick. If we take the 1's complement (i.e. flip all the bits) we will get an increasing count. For example, here are the first four numbers counting down from $FFFF:

       Value                    1's Complement
 Hex        Binary             Binary         Hex
$FFFF  %1111111111111111  00000000000000  $0000
$FFFE  %1111111111111110  00000000000001  $0001
$FFFD  %1111111111111101  00000000000010  $0002

To take the 1's complement we can use the EOR (Exclusive OR) instruction with a value of all ones (i.e. $FF).

Here is the complete code.

       .include ""

        ECHO    = $FFEF     ; Woz monitor
        PRBYTE  = $FFDC     ; Woz monitor

        CR      = $0D       ; Carriage return

        LDA #$00
        STA IER             ; disable all interrupts
        LDA #100000
        STA ACR             ; Set to T2 pulse count mode
        LDA #$FF
        STA T2CL            ; Set low byte of count
        LDA #$FF
        STA T2CH            ; Set high byte of count
        LDA #CR
        JSR ECHO            ; print newline
        LDA T2CL
        CMP T2CL            ; wait for LSB to change
        BEQ SAME
        LDA T2CH            ; get high byte of count
        EOR #$FF            ; complement the bits
        JSR PRBYTE          ; print it
        LDA T2CL            ; get low byte of count
        EOR #$FF            ; complement the bits
        JSR PRBYTE          ; print it
        LDA #CR
        JSR ECHO            ; print newline
        BCC LOOP            ; forever

The picture below shows our switch and pullup resistor on a breadboard wired to PB6.

Hardware Setup for Pulse Counting Experiment

Closeup of Switch and Pullup Resistor

And here we see the output counting down as the button is pressed repeatedly. I took this picture with an earlier version of the program that didn't convert the value to an increasing count so it is actually counting down here.

Program Output
In the next instalment we'll extend this idea of counting pulses to measure frequency.

No comments: