Monday, 7 August 2023

6502 : BEN2 : Clock Timer

Basic timer

In addition to hardware interrupts the VIA (Versatile Interface Adapter) provides two timers which can generate interrupts and Ben Eater has a very good tutorial which explains their use.  In the first example a one shot timer counts down to 0 then sets a bit in the IFR (Interrupt Flag Register).  The counter is a 16-bit register and is decremented each clock pulse so the maximum count down is 65535, approximately 65mS.  If we toggle an LED and restart the counter each time the interrupt occurs we have an LED flashing at about 10Hz.

As you can see from the code below, a loop via_delay is used to check whether the IFR flag has been set by the counter.  Clearly it isn't very useful to sit in a loop waiting for a flag to be set although you could add more code to do other functions within that loop.


Tick Timer

Ben's second example shows a very good clock feature which we will be able to use regularly.  The timer is put into freerun mode so that it starts again as soon as it reaches zero.  In addition to setting the IFR a 6502 interrupt is generated.  The interrupt service routine (ISR) is invoked on the 6502 each time the counter hits zero, and simply updates a four-byte tick counter in zeropage memory.

The counter is setup to hit zero every 10ms so, if we want to toggle an LED every second, we simply check whether the tick counter has increased by 100.  The following program shows the various parts of the tick timer.  On startup init_timer is executed to zero the tick counter and the timer is set to $207e giving 10mS interrupts.  Irqvia is at a fixed address $1003 and is invoked to increase the tick count each time a timer interrupt occurs.  For this demo there is a loop which updates LED and LCD periodically.


Clock program

My VIAtest program is used to check out all the VIA functions so I need to add the timer function in.  As the VIA button interrupt, LED shift register and timer each use a selection of ACR (Auxiliary Control Register), PCR (Peripheral control register) and IER (Interrupt enable register) I first disabled the button and shift register temporarily.  I copied across the timer initialisatio routine and ISR (Interrupt Service Routine) code easily.  With these in place the tick count was automatically incremented, although it wasn't in use.

VIAtest displays a menu and waits for the user to enter a character to choose a function such as displaying an LCD message or turning on an LED.  I amended the program so that it checks to see whether a character has been entered rather using term_getc to wait for a character.  If no character has been entered, other routines are called to see whether the LCD or LED needs updating based on the tick count.  In fact this is a simple state machine which multi-tasks by looping round a number of functions.

To enable the shift register and button, I had to check the VIA initialisation routine carefully and ensure that all bits were set correctly.  The button and LED bar then worked as normal.

The LCD clock display was straightforward to setup.  I added some variables clock_time, hours, minutes and seconds to my zeropage variable list and arranged for the seconds counter to be incremented after 100 ticks.  As each tick is 10mS this gives me an update every second.  Minutes and hours variables were incremented after 60 seconds or 60 minutes were reached.
I could then display the time using the three variables as hh:mm:ss on the LCD.
The update works independently of other VIA test functions.



No comments:

Post a Comment