home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 262.lha / ciatimer / ciatimer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-02  |  4.9 KB  |  177 lines

  1.  
  2. /* TIMER - Amiga CIA Timer Control Software
  3.  
  4.   originally by Paul Higginbottom, Public Domain
  5.  
  6.   hacked on by karl to produce a monotonically increasing microsecond
  7.   clock, 12/30/88, Public Domain
  8.  
  9.   second version, released 4/27/89, incorporates changes by Bob (Kodiak)
  10.   Burns, Brian P. Dickson and C. Harald Koch.  Specifically, Bob pointed
  11.   out that the hardware manual was wrong and CIA B Timer B was the free
  12.   timer, Brian P. Dickson provided greater accuracy by using 1.396825 for
  13.   the time constant and determining the time constants based on that
  14.   number.  Finally, C. Harald Koch found a bug in which the wrong flag
  15.   was used to initialize a control bit, this made it work for CIA A but
  16.   not for CIA B.
  17.  
  18.   cc +p ciatimer.c
  19.   ln ciatimer.o -lcl32
  20.  
  21.   To start the timer, execute BeginCIATimer()
  22.  
  23.   cc +p ciatimer.c
  24.   ln ciatimer.o -lcl32
  25.  
  26.     By providing a solid, high-accuracy realtime clock, this code
  27.     provides a way for timer-releated code that needs to run at
  28.     specific realtimes, like a SMUS player, MIDI sequencer, etc,
  29.     to compensate for delays in their execution caused by interrupts,
  30.     cycle stealing by the blitter, etc.
  31.  
  32.     What you do is keep track of when in realtime you next want to 
  33.     run (by adding time intervals to a time returned by ElapsedTime
  34.     when you start, then when you're ready to set up your timer.device
  35.     MICROHZ delay timer, call ElapsedTime and calculate the difference 
  36.     in seconds and microseconds as your arguments for your timer.device
  37.     request.
  38.  
  39.     The routine ElapsedTime gets the time by getting the number of
  40.     55873 microsecond ticks that the handler has seen and retrieving
  41.     the 0-40000 number of 1.396825 microsecond tisks from the CIA timer
  42.     registers, scaling them to 1.000 microsecond ticks and returning
  43.     the shifted-and-or'ed result.
  44.  
  45.     Note that what we really want is an improved timer.device where a
  46.     flag in the timer request could say  "schedule me at this microsecond-
  47.     resolution time of day seconds and microseconds" instead of only
  48.     "schedule me in this many seconds and microseconds."
  49.  
  50.     When the CIA interrupt handler is installed, other tasks need a
  51.     way to get the count maintained by the timer routine, too.
  52.  
  53.     This release of the code supports multiple readers.
  54.  
  55.     There is a sample main routine at the end of this program, run the
  56.     program in a window to start this guy as a timer.  Control-C within
  57.     the window to get it to exit.
  58.  
  59.     Run the ciafinder program from the CLI in another window and it will
  60.     locate the interrupt data for the timer interrupt maintained by the
  61.     ciatimer task and give you the elapsed time for your time calculation
  62.     in this way.
  63. */
  64.  
  65. #include <exec/types.h>
  66. #include <exec/tasks.h>
  67. #include <functions.h>
  68. #include <exec/interrupts.h>
  69. #include <hardware/cia.h>
  70. #include <hardware/custom.h>
  71. #include <hardware/intbits.h>
  72. #include <resources/cia.h>
  73. #include <stdio.h>
  74. #include <libraries/dos.h>
  75.  
  76. #include "ciatimer.h"
  77.  
  78. struct CIA_Time CIA_CurrentTime = {0, 0};
  79.  
  80. static struct Interrupt
  81.    CIATimerInterrupt,
  82.    *OldCIAInterrupt = (struct Interrupt *)-1;
  83.  
  84. static struct Library *CIAResource = NULL;
  85.  
  86. #define ciatlo ciab.ciatblo
  87. #define ciathi ciab.ciatbhi
  88. #define ciacr ciab.ciacrb
  89. #define CIAINTBIT CIAICRB_TB
  90. #define CLEAR 0
  91.  
  92. void CIAInterrupt()
  93. {
  94.     CIA_CurrentTime.CIA_Microseconds += CIA_TIME_QUANTITY;
  95.     if (CIA_CurrentTime.CIA_Microseconds > 1000000)
  96.     {
  97.         CIA_CurrentTime.CIA_Seconds++;
  98.         CIA_CurrentTime.CIA_Microseconds -= 1000000;
  99.     }
  100. }
  101.  
  102. /* start the timer, clear pending interrupts, and enable timer A
  103.  * Interrupts */
  104. StartCIATimer()
  105. {
  106.     ciacr &= ~(CIACRBF_RUNMODE);    /* set it to reload on overflow */
  107.     ciacr |= (CIACRBF_LOAD | CIACRBF_START);
  108.     SetICR(CIAResource,CLEAR|CIAICRF_TB);
  109.     AbleICR(CIAResource, CIAICRF_SETCLR | CIAICRF_TB);
  110. }
  111.  
  112. void StopCIATimer()
  113. {
  114.     AbleICR(CIAResource, CLEAR | CIAICRF_TB);
  115.     ciacr &= ~CIACRBF_START;
  116. }
  117.  
  118. /* set period between timer increments */
  119. void SetCIATimer(micros)
  120. unsigned short micros;
  121. {
  122.     ciatlo = micros & 0xff;
  123.     ciathi = micros >> 8;
  124. }
  125.  
  126. /* stop the timer and remove its interrupt vector */
  127. EndCIATimer()
  128. {
  129.     if (OldCIAInterrupt == NULL)
  130.     {
  131.         StopCIATimer();
  132.         RemICRVector(CIAResource, CIAINTBIT, &CIATimerInterrupt);
  133.     }
  134. }
  135.  
  136. BOOL BeginCIATimer()
  137. {
  138.     /* Open the CIA resource */
  139.     if ((CIAResource = (struct Library *)OpenResource(CIABNAME)) == NULL)
  140.     {
  141.         fprintf(stderr,"cia periodic timer startup couldn't open cia resource\n");
  142.         return(0);
  143.     }
  144.  
  145.     CIATimerInterrupt.is_Node.ln_Type = NT_INTERRUPT;
  146.     CIATimerInterrupt.is_Node.ln_Pri = 127;
  147.     CIATimerInterrupt.is_Node.ln_Name =  CIATIMER_INTERRUPT_NAME;
  148.     CIATimerInterrupt.is_Code = CIAInterrupt;
  149.     CIATimerInterrupt.is_Data = (APTR)&CIA_CurrentTime;
  150.  
  151.     /* install interrupt */
  152.     if ((OldCIAInterrupt = AddICRVector(CIAResource,CIAINTBIT,&CIATimerInterrupt)) != NULL)
  153.     {
  154.         fprintf(stderr,"cia timer interrupt already in use by '%s'",OldCIAInterrupt->is_Node.ln_Name);
  155.         EndCIATimer();
  156.         return(0);
  157.     }
  158.  
  159.     SetCIATimer(CIA_TIME_SLICE);
  160.  
  161.     StartCIATimer();
  162.     return(TRUE);
  163. }
  164.  
  165. main()
  166. {
  167.     if (BeginCIATimer())
  168.     {
  169.         Wait(SIGBREAKF_CTRL_C);
  170.     }
  171.     else 
  172.         exit(1);
  173.  
  174.     EndCIATimer();
  175.     exit(0);
  176. }
  177.