Friday, March 23, 2012

6522 VIA Experiment #4

This time we're going to extend the pulse counting example from the last instalment to be able to measure frequency. The code is short but a little complex.

To measure frequency we need to count pulses over a known period of time. We saw how Timer 2 can count pulses. We can also use Timer 1 to count a period of time for us.

We'll use Timer 2 in the same pulse counting mode as before where it counts transitions on line PB6. We'll put Timer 1 in the single shot mode where it counts down to zero from a known value at the system clock rate.

We'll count the number of pulses we see over this period of time and display it. Then we'll repeat forever. This is essentially what a device called a digital frequency counter does.

We poll the timer to see when it reaches zero. This is not very efficient and a nice enhancement would be to make this interrupt driven but we want to keep it simple for now. We will look at an interrupt driven example later in this series.

Ideally we would like to convert the result to an actual frequency. To do that we need to divide the number of pulses by the time period (i.e. to get cycles per second or Hertz). If we did this, a good sample rate might be one that is one over a multiple of 2, e.g. 1/16, 1/32, or 1/64 of a second since we can do this calculation by shifting the data by a number of bits rather than doing a full divide operation. For this example I used a 20 Hertz sample rate and didn't calculate the frequency. I used the one's complement trick described in the last experiment to convert the count down to a count up.

The hardware setup here is a little messy. We need a source of pulses, i.e. a square wave at the appropriate TTL (5V) level. Initially I used the calibrate output of my oscilloscope as it puts out 2 volts peak to peak at around 1 KHz. This worked well enough to confirm that I got the right results.

I then used an audio oscillator (an old EICO model 377) to give me a source that I could vary in frequency. I set it to square wave output and then drove it through a 74LS04 inverter chip. I was concerned about possibly damaging the VIA chip if I inadvertently set the output voltage too high. This way I only risked damaging an inexpensive IC from my junk box.

You can see the setup below.

EICO Signal Generator
Breadboarded Circuit with 74LS04 Chip

The source code is below. Based on the information above and the comments in the code is should be self-explanatory.

 .include "6522.inc"

    ECHO     = $FFEF    ; Woz monitor
    PRBYTE   = $FFDC    ; Woz monitor
    CR       = $0D      ; Carriage return
    COUNT    = 49998    ; 20 Hz sample rate

    LDA #$00
    STA IER             ; disable all interrupts

    LDA #%00100000
    STA ACR             ; T1 single shot PB7 disabled, T2 pulse count mode

LOOP:
    LDA #
    STA T1CL            ; Set low byte of count
    LDA #>COUNT
    STA T1CH            ; Set high byte of count

    LDA #$FF            ; Set count for T2
    STA T2CL            ; Set low byte of count
    LDA #$FF
    STA T2CH            ; Set high byte of count

WAIT:
    LDA T1CH            ; wait for timer T1 to count down to zero
    BNE WAIT
    LDA T1CL
    BNE WAIT

    LDA T2CH            ; get high byte of T2 count
    EOR #$FF            ; take 1's complement
    JSR PRBYTE          ; print it
    LDA T2CL            ; get low byte of T2 count
    EOR #$FF            ; take 1's complement
    JSR PRBYTE          ; print it
    LDA #CR
    JSR ECHO            ; print newline
    JMP LOOP            ; repeat forever

As one example (the one shown on the display in the picture below), the input was at about 100KHz. I counted about $13AE pulses, or 5038 decimal. I used a 20 Hz sampling rate. 5038 * 20 Hz = 10,076 Hz. So my reading looks about right.

Signal Generator Output on Oscilloscope

Output of Program

My signal generator only went up to about 200KHz and I was able to measure this frequency.

You can imagine building a digital frequency counter using a 6502 and a VIA chip. In fact some modern counters a simple processor (e.g. a PIC) and some kind of display and not much more.

No comments: