Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > High Speed IRQ Timer/Clock in C

Reply
Thread Tools

High Speed IRQ Timer/Clock in C

 
 
Andrew Wan
Guest
Posts: n/a
 
      12-27-2007
I found this excellent High Speed Timer (in Pascal). I compiled it
(using Turbo Pascal 7 and it runs fine):

http://www.sorucevap.com/bilisimtekn...ers.asp?207995
and same High Speed Timer here too:
http://groups.google.com/group/comp....7ff3cf587648ef

I converted it to C (using p2c), compiled it using Borland C++ 4.5 and
it runs. But it crashes when it gets to setvect(...) in TimerOn.

Does anyone know how IRQ programming works in C? If you know IRQ timer/
clock please contact me. I need urgent help in understanding why it's
not working.
 
Reply With Quote
 
 
 
 
Jason Burgon
Guest
Posts: n/a
 
      12-27-2007
"Andrew Wan" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> I found this excellent High Speed Timer (in Pascal). I compiled it
> (using Turbo Pascal 7 and it runs fine):
>
>

http://www.sorucevap.com/bilisimtekn...ers.asp?207995

That isn't particularly good code or particularly high speed either. It is
not too diffucult with a standard PC to have timers with a resolution of
836ns, and have as many of them as you want as well.

--
Jay

Jason Burgon - author of Graphic Vision
http://homepage.ntlworld.com/gvision


 
Reply With Quote
 
 
 
 
Andrew Wan
Guest
Posts: n/a
 
      12-28-2007
And so we have a translated C code here:
#include "p2c.h"
#include "extra.h"

#define TIMER_G
#include "timer.h"



#define MaxRate 1193180L


void interrupt(__far *OldInt0();//Static _PROCEDURE OldInt08,
OldInt1C;
void interrupt(__far *OldInt1C)();
Static unsigned short IntCount08, Trigger;
Static boolean TimerAlreadySet;
Static unsigned short Frequency;

void GetIntVec(int a, void interrupt(__far *b)())
{
b = getvect(a);
}

void SetIntVec(int a, void interrupt(__far *b)())
{
setvect(a, b);
}


Static Void IrqOn()
{
/* p2c: timer1.pas, line 37:
* Note: Inline assembly language encountered [254] */
asm{sti;}//asm(" inline $FB");
}


Static Void IrqOff()
{
/* p2c: timer1.pas, line 40:
* Note: Inline assembly language encountered [254] */
asm{cli;}//asm(" inline $FA");
}
/* p2c: timer1.pas, line 43: Note: Ignoring INTERRUPT keyword [258] */


/*$F+*/
void interrupt NewInt1C()//Static Void NewInt1C()
{printf("\nNewInt1C()");
ClockTicks++;
}
/* p2c: timer1.pas, line 50: Note: Ignoring INTERRUPT keyword [258] */


/*$F-*/

/*$F+*/
void interrupt NewInt08()//Static Void NewInt08()
{printf("\nNewInt08()");
IrqOff();
/* p2c: timer1.pas, line 53:
* Note: Inline assembly language encountered [254] */
asm{int 1Ch;}//asm(" inline $CD");
//asm(" inline $1C"); /*Generate INT 1Ch instruction to call
interrupt 1Ch*/
if (IntCount08 == Trigger) {
IntCount08 = 0;
/* p2c: timer1.pas, line 57:
* Note: Inline assembly language encountered [254] */
asm{pushf;}//asm(" inline $9C");
OldInt08();/*if (OldInt08.link != NULL)
(*(Void(*) PP((Anyptr _link)))OldInt08.proc)(OldInt08.link);
else
(*(Void(*) PV())OldInt08.proc)();*/
} else
IntCount08++;
outportb( 0x20, 0x20 );//PORT(0x20) = 0x20; /*Sends non-specific
EOI to the PIC*/
/* p2c: timer1.pas, line 64: Note: Reference to PORT [191] */
/* p2c: timer1.pas, line 64: Warning: Invalid assignment [168] */
IrqOn();
}


/*$F-*/

Void TimerOn(Freq)
long Freq;
{
LONGINT Temp = MaxRate;
unsigned short Count;
_PROCEDURE TEMP1;
printf("\nTimerOn()");
if (TimerAlreadySet)
return;
ClockTicks = 0;
IntCount08 = 0;
Frequency = Freq;
Trigger = (long)(Freq / 18.2);
Temp = (long)((double)Temp / Freq);
Count = Temp;
GetIntVec(0x8, OldInt0;
TEMP1.proc = (Anyptr)NewInt08;
TEMP1.link = (Anyptr)NULL;
/* p2c: timer1.pas, line 83:
* Warning: Symbol 'GETINTVEC' is not defined [221] */
SetIntVec(0x8, NewInt0;//SetIntVec(0x8, TEMP1);
/* p2c: timer1.pas, line 84:
* Warning: Symbol 'SETINTVEC' is not defined [221] */
GetIntVec(0x1c, OldInt1C);
TEMP1.proc = (Anyptr)NewInt1C;
TEMP1.link = (Anyptr)NULL;
/* p2c: timer1.pas, line 85:
* Warning: Symbol 'GETINTVEC' is not defined [221] */
SetIntVec(0x1c, NewInt1C);//SetIntVec(0x1c, TEMP1);
/* p2c: timer1.pas, line 86:
* Warning: Symbol 'SETINTVEC' is not defined [221] */
outportb( 0x43, 0xb6);
/* p2c: timer1.pas, line 87: Note: Reference to PORT [191] */
/* p2c: timer1.pas, line 87: Warning: Invalid assignment [168] */
outportb( 0x40, Count & 255);
/* p2c: timer1.pas, line 88: Note: Reference to PORT [191] */
/* p2c: timer1.pas, line 88: Warning: Invalid assignment [168] */
outportb( 0x40, Count >> ;
/* p2c: timer1.pas, line 89: Note: Reference to PORT [191] */
/* p2c: timer1.pas, line 89: Warning: Invalid assignment [168] */
TimerAlreadySet = true;
}


Void TimerOff()
{printf("\nTimerOff()");
if (!TimerAlreadySet)
return;
outportb( 0x43, 0xb6);
/* p2c: timer1.pas, line 98: Note: Reference to PORT [191] */
/* p2c: timer1.pas, line 98: Warning: Invalid assignment [168] */
outportb( 0x40, 0xff);
/* p2c: timer1.pas, line 99: Note: Reference to PORT [191] */
/* p2c: timer1.pas, line 99: Warning: Invalid assignment [168] */
outportb( 0x40, 0xff);
/* p2c: timer1.pas, line 100: Note: Reference to PORT [191] */
/* p2c: timer1.pas, line 100: Warning: Invalid assignment [168] */
SetIntVec(0x8, OldInt0;
/* p2c: timer1.pas, line 101:
* Warning: Symbol 'SETINTVEC' is not defined [221] */
SetIntVec(0x1c, OldInt1C);
/* p2c: timer1.pas, line 102:
* Warning: Symbol 'SETINTVEC' is not defined [221] */
TimerAlreadySet = false;
}


Void ResetTimer()
{
ClockTicks = 0;
}


double TimeElapsed()
{
return ((double)ClockTicks / Frequency);
}


void _Timer_init()
{
static int _was_initialized = 0;
if (_was_initialized++)
return;
TimerAlreadySet = false;
}
/* p2c: Note: Remember to call _Timer_init() in main program [215] */



/* End. */

void main()
{
int i;
_Timer_init();

TimerOn(546);
for(i=0; i<100000; i++) {
if (i%10000==0)
printf("\n... %d", i);
}
TimerOff();

}
 
Reply With Quote
 
Rod Pemberton
Guest
Posts: n/a
 
      12-28-2007

"Andrew Wan" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...

Dropped comp.lang.c++, openwatcom.users.c_cpp NG's. Francis Glassborow
posted to
comp.lang.learn.c-c++,alt.lang.asm,alt.msdos.programmer,comp.os.msdo s.progra
mmer NG's, so you may get some responses on those too.

The code is very close to compiling for OpenWatcom. Mostly some incorrect
keywords, wrong location for keywords, and differently named environment
specific functions... You should replace the "Static", "boolean", "Void"
etc. with the correct text instead of using the #define's like I did below.
Many of the functions have K&R style void arg's, e.g., the () in "Static
Void IrqOn()". These should be reworked to "Static Void IrqOn(void)". You
should replace the C++ comments // with C comments /* */ or #if 0 #endif.
Once you get it compile, if it doesn't work as you expect, you can post to
openwatcom.users.c_cpp, alt.os.development, comp.os.msdos.programmer, etc.
for IRQ programming.


Rod Pemberton

> And so we have a translated C code here:
> #include "p2c.h"
> #include "extra.h"
>


//#include "p2c.h"
//#include "extra.h"

> #define TIMER_G
> #include "timer.h"


//#include "timer.h"

>
>
>
> #define MaxRate 1193180L
>


#if 1
#define Static static
#define boolean int
#define Void void
#define LONGINT long int
#define getvect _dos_getvect
#define setvect _dos_setvect
#if 0
#define asm _asm
#endif
#define outportb outp
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#define true 1
#define false 0
unsigned long ClockTicks;
#endif


>
> void interrupt(__far *OldInt0();//Static _PROCEDURE OldInt08,
> OldInt1C;


//void interrupt(__far *OldInt0();//Static _PROCEDURE OldInt08, OldInt1C;
void (__interrupt __far *OldInt0();

> void interrupt(__far *OldInt1C)();


//void interrupt(__far *OldInt1C)();
void (__interrupt __far *OldInt1C)();

> Static unsigned short IntCount08, Trigger;
> Static boolean TimerAlreadySet;
> Static unsigned short Frequency;
>
> void GetIntVec(int a, void interrupt(__far *b)())


//void GetIntVec(int a, void interrupt(__far *b)())
void GetIntVec(int a, void (__interrupt __far *b)())

> {
> b = getvect(a);
> }
>
> void SetIntVec(int a, void interrupt(__far *b)())


//void SetIntVec(int a, void interrupt(__far *b)())
void SetIntVec(int a, void (__interrupt __far *b)())

> {
> setvect(a, b);
> }
>
>
> Static Void IrqOn()
> {
> /* p2c: timer1.pas, line 37:
> * Note: Inline assembly language encountered [254] */
> asm{sti;}//asm(" inline $FB");


//asm{sti;}//asm(" inline $FB");
_asm{sti}

> }
>
>
> Static Void IrqOff()
> {
> /* p2c: timer1.pas, line 40:
> * Note: Inline assembly language encountered [254] */
> asm{cli;}//asm(" inline $FA");


//asm{cli;}//asm(" inline $FA");
_asm{cli}

> }
> /* p2c: timer1.pas, line 43: Note: Ignoring INTERRUPT keyword [258] */
>
>
> /*$F+*/
> void interrupt NewInt1C()//Static Void NewInt1C()
> {printf("\nNewInt1C()");
> ClockTicks++;
> }
> /* p2c: timer1.pas, line 50: Note: Ignoring INTERRUPT keyword [258] */
>
>
> /*$F-*/
>
> /*$F+*/
> void interrupt NewInt08()//Static Void NewInt08()
> {printf("\nNewInt08()");
> IrqOff();
> /* p2c: timer1.pas, line 53:
> * Note: Inline assembly language encountered [254] */
> asm{int 1Ch;}//asm(" inline $CD");


//asm{int 1Ch;}//asm(" inline $CD");
_asm{int 1Ch}

> //asm(" inline $1C"); /*Generate INT 1Ch instruction to call
> interrupt 1Ch*/
> if (IntCount08 == Trigger) {
> IntCount08 = 0;
> /* p2c: timer1.pas, line 57:
> * Note: Inline assembly language encountered [254] */
> asm{pushf;}//asm(" inline $9C");


//asm{pushf;}//asm(" inline $9C");
_asm{pushf}

> OldInt08();/*if (OldInt08.link != NULL)
> (*(Void(*) PP((Anyptr _link)))OldInt08.proc)(OldInt08.link);
> else
> (*(Void(*) PV())OldInt08.proc)();*/
> } else
> IntCount08++;
> outportb( 0x20, 0x20 );//PORT(0x20) = 0x20; /*Sends non-specific
> EOI to the PIC*/
> /* p2c: timer1.pas, line 64: Note: Reference to PORT [191] */
> /* p2c: timer1.pas, line 64: Warning: Invalid assignment [168] */
> IrqOn();
> }
>
>
> /*$F-*/
>
> Void TimerOn(Freq)
> long Freq;
> {
> LONGINT Temp = MaxRate;
> unsigned short Count;
> _PROCEDURE TEMP1;


// _PROCEDURE TEMP1;

> printf("\nTimerOn()");
> if (TimerAlreadySet)
> return;
> ClockTicks = 0;
> IntCount08 = 0;
> Frequency = Freq;
> Trigger = (long)(Freq / 18.2);
> Temp = (long)((double)Temp / Freq);
> Count = Temp;
> GetIntVec(0x8, OldInt0;
> TEMP1.proc = (Anyptr)NewInt08;
> TEMP1.link = (Anyptr)NULL;


//TEMP1.proc = (Anyptr)NewInt08;
//TEMP1.link = (Anyptr)NULL;

> /* p2c: timer1.pas, line 83:
> * Warning: Symbol 'GETINTVEC' is not defined [221] */
> SetIntVec(0x8, NewInt0;//SetIntVec(0x8, TEMP1);
> /* p2c: timer1.pas, line 84:
> * Warning: Symbol 'SETINTVEC' is not defined [221] */
> GetIntVec(0x1c, OldInt1C);
> TEMP1.proc = (Anyptr)NewInt1C;
> TEMP1.link = (Anyptr)NULL;


//TEMP1.proc = (Anyptr)NewInt1C;
//TEMP1.link = (Anyptr)NULL;

> /* p2c: timer1.pas, line 85:
> * Warning: Symbol 'GETINTVEC' is not defined [221] */
> SetIntVec(0x1c, NewInt1C);//SetIntVec(0x1c, TEMP1);
> /* p2c: timer1.pas, line 86:
> * Warning: Symbol 'SETINTVEC' is not defined [221] */
> outportb( 0x43, 0xb6);
> /* p2c: timer1.pas, line 87: Note: Reference to PORT [191] */
> /* p2c: timer1.pas, line 87: Warning: Invalid assignment [168] */
> outportb( 0x40, Count & 255);
> /* p2c: timer1.pas, line 88: Note: Reference to PORT [191] */
> /* p2c: timer1.pas, line 88: Warning: Invalid assignment [168] */
> outportb( 0x40, Count >> ;
> /* p2c: timer1.pas, line 89: Note: Reference to PORT [191] */
> /* p2c: timer1.pas, line 89: Warning: Invalid assignment [168] */
> TimerAlreadySet = true;
> }
>
>
> Void TimerOff()
> {printf("\nTimerOff()");
> if (!TimerAlreadySet)
> return;
> outportb( 0x43, 0xb6);
> /* p2c: timer1.pas, line 98: Note: Reference to PORT [191] */
> /* p2c: timer1.pas, line 98: Warning: Invalid assignment [168] */
> outportb( 0x40, 0xff);
> /* p2c: timer1.pas, line 99: Note: Reference to PORT [191] */
> /* p2c: timer1.pas, line 99: Warning: Invalid assignment [168] */
> outportb( 0x40, 0xff);
> /* p2c: timer1.pas, line 100: Note: Reference to PORT [191] */
> /* p2c: timer1.pas, line 100: Warning: Invalid assignment [168] */
> SetIntVec(0x8, OldInt0;
> /* p2c: timer1.pas, line 101:
> * Warning: Symbol 'SETINTVEC' is not defined [221] */
> SetIntVec(0x1c, OldInt1C);
> /* p2c: timer1.pas, line 102:
> * Warning: Symbol 'SETINTVEC' is not defined [221] */
> TimerAlreadySet = false;
> }
>
>
> Void ResetTimer()
> {
> ClockTicks = 0;
> }
>
>
> double TimeElapsed()
> {
> return ((double)ClockTicks / Frequency);
> }
>
>
> void _Timer_init()
> {
> static int _was_initialized = 0;
> if (_was_initialized++)
> return;
> TimerAlreadySet = false;
> }
> /* p2c: Note: Remember to call _Timer_init() in main program [215] */
>
>
>
> /* End. */
>
> void main()


int main(void)

> {
> int i;
> _Timer_init();
>
> TimerOn(546);
> for(i=0; i<100000; i++) {
> if (i%10000==0)
> printf("\n... %d", i);
> }
> TimerOff();
>


return(0);

> }



 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      12-28-2007
Andrew Wan wrote:
>
> And so we have a translated C code here:
> #include "p2c.h"
> #include "extra.h"
>
> #define TIMER_G
> #include "timer.h"

.... snip ...

And what does this have to do with the C language?

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee, Frohe Weihnachten
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>



--
Posted via a free Usenet account from http://www.teranews.com

 
Reply With Quote
 
Marco van de Voort
Guest
Posts: n/a
 
      12-28-2007
On 2007-12-28, CBFalconer <(E-Mail Removed)> wrote:
> Andrew Wan wrote:
>>
>> And so we have a translated C code here:
>> #include "p2c.h"
>> #include "extra.h"
>>
>> #define TIMER_G
>> #include "timer.h"

> ... snip ...
>
> And what does this have to do with the C language?


1. Dunno, but neither does it with Pascal language.
2. The OP didn't suffix "-language". That's yours.
 
Reply With Quote
 
Andrew Wan
Guest
Posts: n/a
 
      01-16-2008
On Dec 28 2007, 11:30 pm, Marco van de Voort <(E-Mail Removed)> wrote:
> On 2007-12-28, CBFalconer <(E-Mail Removed)> wrote:
>
> > Andrew Wan wrote:

>
> >> And so we have a translated C code here:
> >> #include "p2c.h"
> >> #include "extra.h"

>
> >> #define TIMER_G
> >> #include "timer.h"

> > ... snip ...

>
> > And what does this have to do with the C language?

>
> 1. Dunno, but neither does it with Pascal language.
> 2. The OP didn't suffix "-language". That's yours.


Rod, thanks for converting the code for OpenWatcom. It compiles fine
under Borland C++ 4.5 and Turbo C 3.0. I posted it to both Pascal & C
newsgroups for help in understanding both low level Pascal & C
language.

I found the closest Turbo C DOS timer source code written by David
Oshinsky at:

http://www.bookcase.com/library/soft...-<br /> c.html (TIMERTST)

To get my own timer (original Pascal port) I had to comment out
asm{ int 1Ch;} & asm{pushf;} in NewInt08() function. Also I had to
omit all debugging printfs in the interrupt functions. Afterwards my
program doesn't crash anymore.

What am wondering is:

1. In Pascal version it uses inline($CD / $1C); & inline($9C); before
the OldInt08() call. I though I could call the equivalent asm{ int
1Ch;} & asm{pushf;} but I guess this was wrong since it crashed my
program. Is there an inline assembly call in C?

2. David's initializing the timer code uses
Code:
/* Set up 8259 PIC chip to allow INT0 interrupt. */
outportb(0x21, inportb(0x21) & 0xfe);

/* issue command to 8253:  counter 0, binary counter, rate generator
*/
/* (mode 2), load least significant byte of counter followed by
*/
/* most significant byte                         */
outportb(0x43, 0x34);

/* Timer is set for 0x4cd * 813.8 ns = 1 ms (LSB followed by MSB). */
outportb(0x40, 0xcd); /* least significant byte of timer count */
outportb(0x40, 0x04); /* most significant byte of timer count  */
But mine uses
Code:
outportb( 0x43, 0xb6);
outportb( 0x40, Count & 255);
outportb( 0x40, Count >> 8);
What is the difference? Even though both works.

3. Same goes for the clean up code:
His is:
Code:
/* restore 8253 to original state set during PC boot  */
/* NOTE:  this program leaves 8259 mask register with */
/* least significant bit clear (i.e., INT0 enabled).  */
outportb(0x43, 0x34);
outportb(0x40, 0);
outportb(0x40, 0);
Mine is:
Code:
outportb( 0x43, 0xb6);
outportb( 0x40, 0xff);
outportb( 0x40, 0xff);
Again both works but I don't understand why different?
 
Reply With Quote
 
Marco van de Voort
Guest
Posts: n/a
 
      01-16-2008
On 2008-01-16, Andrew Wan <(E-Mail Removed)> wrote:
>
> What am wondering is:
>
> 1. In Pascal version it uses inline($CD / $1C); & inline($9C); before
> the OldInt08() call. I though I could call the equivalent asm{ int
> 1Ch;} & asm{pushf;} but I guess this was wrong since it crashed my
> program. Is there an inline assembly call in C?


TP has support for interrupt routines, that end with "Retf" instead of
"Ret". It could be that the C compiler did it differently, or somehow reacts
more badly to the stack modification.

 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      01-16-2008
Marco van de Voort wrote:
> Andrew Wan <(E-Mail Removed)> wrote:
>
>> What am wondering is:
>>
>> 1. In Pascal version it uses inline($CD / $1C); & inline($9C);
>> before the OldInt08() call. I though I could call the equivalent
>> asm{int 1Ch;} & asm{pushf;} but I guess this was wrong since it
>> crashed my program. Is there an inline assembly call in C?

>
> TP has support for interrupt routines, that end with "Retf"
> instead of "Ret". It could be that the C compiler did it
> differently, or somehow reacts more badly to the stack
> modification.


In the x86 an interrupt 1) pushes the flags. 2) disables further
interrupts 3) performs a call. 1 and 2 are not performed by an
ordinary call. Therefore the return instruction has to be
different, to reverse effects 1 and 2. That is done by the retf
instruction.

This has nothing to do with C, but handles the characteristics of
the hardware. Thus it is OT here on c.l.c. It also has nothing to
do with Pascal. Some group with 'asm' in its name is probably
suitable.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.



--
Posted via a free Usenet account from http://www.teranews.com

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
High Speed IRQ Timer/Clock in C Andrew Wan C++ 7 01-16-2008 11:43 AM
speed speed speed a.metselaar Computer Support 14 12-30-2003 03:34 AM
irq numbers and AGP Bus hooter Computer Support 2 09-08-2003 03:23 PM
USB High Speed against USB Non High Speed DannyD1355 Computer Support 1 09-07-2003 02:59 AM
Permanent IRQ's Emrys Davies Computer Support 4 07-28-2003 10:35 AM



Advertisments