Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here's a demo showing how to change the default timer rate from 18.2 Hz to other values. Compiles with Borland Turbo C++ (as real-mode EXE app) and with Open Watcom C++ 1.9 (as DPMI/dos4gw app).</p> <pre><code>// file: tmr.c #include &lt;stddef.h&gt; #include &lt;stdio.h&gt; #include &lt;dos.h&gt; #include &lt;conio.h&gt; #ifdef __WATCOMC__ // Define Borland C aliases: #define getvect _dos_getvect #define setvect _dos_setvect #define outportb outp #define inportb inp #define disable _disable #define enable _enable #endif typedef unsigned uint; typedef unsigned char uchar; void interrupt (*pOldInt1C)(void) = NULL; volatile uint int1Ccnt = 0; void interrupt NewInt1C(void) { int1Ccnt++; pOldInt1C(); } void SetPitResolutionInHz(uint ResolutionInHz) { uint count; if (ResolutionInHz &lt; 18 || ResolutionInHz &gt;= 65535) return; count = (ResolutionInHz == 18) ? 0 : (uint)(1193181 / ResolutionInHz); disable(); outportb(0x43, 0x34); outportb(0x40, (uchar)(count &amp; 0xFF)); outportb(0x40, (uchar)(count &gt;&gt; 8)); enable(); } int main(void) { pOldInt1C = getvect(0x1C); setvect(0x1C, &amp;NewInt1C); printf("3 seconds delay, default timer rate...\n"); while (int1Ccnt &lt; 18*1*3) { static uint last = 0; if (last != int1Ccnt) { printf("1"); fflush(stdout); last = int1Ccnt; } } printf("\n"); SetPitResolutionInHz(18*2); printf("3 seconds delay, double timer rate...\n"); int1Ccnt = 0; while (int1Ccnt &lt; 18*2*3) { static uint last = 0; if (last != int1Ccnt) { printf("2"); fflush(stdout); last = int1Ccnt; } } printf("\n"); SetPitResolutionInHz(18*3); printf("3 seconds delay, triple timer rate...\n"); int1Ccnt = 0; while (int1Ccnt &lt; 18*3*3) { static uint last = 0; if (last != int1Ccnt) { printf("3"); fflush(stdout); last = int1Ccnt; } } printf("\n"); // Set default rate: 1193181 MHz / 65536 = 18.2 Hz SetPitResolutionInHz(18*1); printf("3 seconds delay, default timer rate...\n"); int1Ccnt = 0; while (int1Ccnt &lt; 18*1*3) { static uint last = 0; if (last != int1Ccnt) { printf("1"); fflush(stdout); last = int1Ccnt; } } printf("\n"); setvect(0x1C, pOldInt1C); return 0; } </code></pre> <p>It will print 1s, 2s and 3s at the default, double and triple the default rates for 3 seconds each.</p> <p>Beware, this code screws up BIOS/DOS timings (both use timer interrupts for various delays). To workaround that you want to hook vector 8 (IRQ0) instead of vector 0x1C (it's called from vector 8 ISR) and call the original IRQ0 ISR from your new IRQ0 ISR at about the default rate (you need to count interrupts for that). When you don't call it from your ISR, you need to manually signal the end of interrupt handling by doing <code>outportb(0x20, 0x20);</code> before returning from the ISR (the original ISR does that, but if you don't call it, it's your responsibility).</p> <p><strong>EDIT</strong>: Be advised that in virtualized environments timer interrupts may be lost or delivered at irregular intervals, especially if you set a high interrupt rate and your PC is busy with other tasks. Also, even on a physical machine you can have issues with high timer frequencies, System Management Interrupts (SMIs) will introduce jitter/variable latency in interrupt delivery. You can't get rid of them, they're handled transparently by the BIOS.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload