CS644 Programming the Timer without Interrupts

blade63(11)% more $pcex/timer.c

/* timer.c  Test program to see timer running

 * Build with $pcex/makefile: "make C=timer timer.exe"

 */

/* the makefile uses gcc -I<dir> to make sure these come from $pcinc-- */

#include <stdio.h>

#include <timer.h>

 

#define NTIMES 5

#define MAX 80

void smalldelay(void);

void showcounts();

void setcount(int count);

 

void main()

{

  int count;

  char buf[MAX];

 

  printf("Enter count for timer (decimal no. <64K): ");

  fgets(buf,MAX,CONSOLE);       /* dev no. CONSOLE def'd in $pcinc/stdio.h */

  sscanf(buf, "%d" ,&count);

  setcount(count);              /* 0 = max, 65536 */

  showcounts();

  showcounts();

  showcounts();

}

/* about 10 usecs on a SAPC (400Mhz Pentium) */

void smalldelay(void)

{

  int i;

 

  for (i=0;i<1000;i++)

    ;

}

 

/* Print out timer counts after little delays, to show downcounting.

 * Note we are assuming the calling overhead to outpt and inpt provide

 * sufficient delay between the accesses to the same port */

void showcounts()

{

  int i, count[NTIMES];

 

  for (i=0;i<NTIMES;i++) {

    /* command timer 0 to latch count: */

    outpt(TIMER_CNTRL_PORT, TIMER0|TIMER_LATCH);

    count[i] = inpt(TIMER0_COUNT_PORT); /* read in LSB of count */

    count[i] |= inpt(TIMER0_COUNT_PORT)<<8; /* then MSB of count */

    smalldelay();

  }

  for (i=0;i<NTIMES;i++) {      /* this takes more time than "delay" */

    printf("%d ",count[i]);

  }

  printf("\n");

}

 

/* set count to downcount from, in timer: it gets to 0, starts over */

void setcount(int count)

{

  /* set timer 0 count, mode */

  outpt(TIMER_CNTRL_PORT, TIMER0|TIMER_SET_ALL|TIMER_MODE_RATEGEN);

  outpt(TIMER0_COUNT_PORT,count&0xff); /* set LSB here */

  outpt(TIMER0_COUNT_PORT,count>>8); /* and MSB here */

  smalldelay();                 /* let timer have a moment */

}

 

 

blade63(12)% more $pcinc/timer.h

/* timer.h  Header for Programmable Interrupt Timer */

#ifndef TIMER_H

#define TIMER_H

 

/* Timer 0 is wired to cause an interrupt when its count reaches zero */

#define TIMER0_COUNT_PORT  0x40

/* and that interrupt is irq 0 in the PIC */

#define TIMER0_IRQ 0

/* Timer 1 is set at bootup to help with RAM refresh, best to leave alone*/

/* Timer 2 is wired to speaker, so we can control pitch of sound */

#define TIMER2_COUNT_PORT  0x42

 

/* for commands to timers

 * for example, to read the 16-bit counter in timer 0:

 * --output TIMER0|TIMER_LATCH to TIMER_CNTRL_PORT, then

 * --input a byte from TIMER_COUNT_PORT to get the low 8 bits of the count,

 * --input another byte from TIMER_COUNT_PORT to get the high bits.

*/

#define TIMER_CNTRL_PORT 0x43

/* bits 6-7: which timer the command is for */

#define TIMER0 (0<<6)

#define TIMER1 (1<<6)

#define TIMER2 (2<<6)

 

/* bits 4-5: latch commands (take snapshot of counter and hold it for read) */

#define TIMER_LATCH (0<<4)      /* latch current count bits 0-15, avail in two

                                   8-bit reads (low bits, then high bits) */

#define TIMER_SET_LOW (1<<4)    /* set bits 0-7 only */

#define TIMER_SET_HIGH (2<<4)   /* set bits 8-15 only */

#define TIMER_SET_ALL (3<<4)    /* set bits 0-15 (low bits, then high bits) */

 

/* bits 1-3: Mode select */

/* For the PC, the GATE input is wired high for timers 0 and 1, and to bit 0

 * of port 0x61 for timer 2, so only timer 2 can effectively use the _GATE

 * modes at all.  The RATEGEN mode is best for timing. */

#define TIMER_MODE_1SHOT (0<<1)      /* programmable one-shot, program init'd */

#define TIMER_MODE_1SHOT_GATE (1<<1) /* programmable one-shot, GATE input */

#define TIMER_MODE_RATEGEN (2<<1)    /* rate generator (pulse train) */

#define TIMER_MODE_SQUAREWAVE (3<<1) /* low for count, hi for count, low...*/

#define TIMER_MODE_STROBE (4<<1)     /* software-triggered pulse */

#define TIMER_MODE_STROBE_GATE (5<<1) /* GATE-triggered pulse */

 

/* bit 0: BCD select (BCD = binary coded decimal format for numbers) */

#define TIMER_BINARY_COUNTER 0

#define TIMER_BCD_COUNTER 1

 

#endif