QNX X86 82c54
/*
* This program will set up a irq handler, and
* set up a 82c54-10 on the parrallel port inorder
* to generate interrupts at a controlled pace.
* This program uses the eventattach call, it is not as fast as
* the interruptattach version
*
* the commandline args are
* portevent [PORT address] [interrupt number] [divisor]
*
* the comand word is made from the following
* d7 d6 d5 d4 d3 d2 d1 d0
* * bcd =1 binary=0
* * * * --- mode <<1 ie mode 1 is 02 mode 2 is 0x04 mode 3 is 0x06
* * * ----------- read write control: 00 latch cnt, 01 is r/w lsb only
* 10 is r/w msb only and 11 is r/w lsb then msb
* * * ------------------ select counter 00 is c/t 1, 01 is c/t2 10 is c/t3
* and the read back command is 11
* Pat Ford april 18 2000
*/
#include <stdio.h>
#include <stdlib.h>
#include <hw/inout.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
/*
mapping info for base + 2 (control)
where d3 d2 d1 d0
__ __
what A1 A0 RD WR Hex
------------------------------------------------------------
wr_cntr0 0 0 1 0 0x09
wr_cntr1 0 1 1 0 0x01
wr_cntr2 1 0 1 0 0x0D
wr_cntrl 1 1 1 0 0x05
rd_cntr0 0 0 0 1 0x0A
rd_cntr1 0 1 0 1 0x02
rd_cntr2 1 0 0 1 0x0E
It looks funky but remember that d0, d1, d3, are inverted
*/
#define wr_ct1 0x09
#define wr_ct2 0x01
#define wr_ct3 0x0D
#define wr_cntrl 0x05
#define rd_ct1 0x0A
#define rd_ct2 0x02
#define rd_ct3 0x0E
#define rd_cntrl 0x06
#define cntrl_off 0x0B
#define idle 0x08
#define A0 0x04
#define A1 0x08
#define WR 0x02
#define RD 0x01
#define A0 0x04
#define A1 0x08
#define WR 0x02
#define RD 0x01
#define control_word_ct1 0x00
#define control_word_ct2 0x40
#define control_word_ct3 0x80
#define control_word_lsb 0x10
#define control_word_msb 0x20
#define control_word_word 0x30
#define control_mode_0 0x00
#define control_mode_1 0x02
#define control_mode_2 0x04
#define control_mode_3 0x06
#define control_mode_4 0x08
#define control_mode_5 0x0A
#define control_mode_bcd 0x01
#define control_mode_bin 0x00
#define base PORT
#define inputs PORT+1
#define control PORT+2
struct sigevent event;
volatile unsigned counter;
int main(int argc, char *argv[])
{
int i=0, j=0, mode=0, lsb=0, msb=0, tmp=0, c=0, id=0, cnt=400, PORT=0, IRQ=0;
uintptr_t lpt1;
size_t len=6;
uint64_t cps=0, t1=0, t2=0, sum=0, td;
float sec,hi, lo=1.0;
// Initialize event structure
event.sigev_notify = SIGEV_INTR;
mode=0x34;
PORT=strtol(argv[1], 0, 0);
IRQ=strtol(argv[2], 0, 0);
i=strtol(argv[3], 0, 0);
lsb=i & 0xff;
msb= i>>8;
if ( PORT==0 || IRQ==0 || i==0 )
{
printf("\n You MUST include [PORT address] [interrupt number] and [divisor] as commandline args\n");
exit(EXIT_FAILURE);
}
// Request I/O privity
ThreadCtl(_NTO_TCTL_IO, 0);
// map the io space we want
lpt1=mmap_device_io( len, PORT );
if( errno != EOK)
printf("\nMmap_device errno %s\n", strerror( errno ) );
//set up the counter timer
out8( control, 0x04); // set the address bus
out8(base,mode); // have to setup data
out8(control,wr_cntrl); // then drop the write enable
out8(control, idle); // raise the write enable
out8(control, 0x08);
out8(base,lsb);
out8(control,wr_ct1);
printf ("\noutputing %x as lsb",lsb);
out8(control, idle);
out8(control, 0x08);
out8(base,msb);
out8(control,wr_ct1);
printf ("\noutputing %x as msb",msb);
out8(control, idle);
// assert the irq enable
out8(control, ( idle | 0x10));
out8(base,0x00);
//out8(control,0xD8);
// Attach ISR vector
id=InterruptAttachEvent(IRQ, &event, _NTO_INTR_FLAGS_TRK_MSK);
if (id == -1)
{
perror("InterruptAttachEvent failed");
exit(EXIT_FAILURE);
}
cps = SYSPAGE_ENTRY(qtime)->cycles_per_sec;
printf("\nwaiting to be interrupted\n");
for (i = 0; i < cnt; ++i)
{
InterruptWait(0, NULL);
tmp=InterruptUnmask(7, id);
t1=ClockCycles();
if (i!=0)
{
td=t1-t2;
sec=(float)td/cps;
if (sec<lo)
lo=sec;
if (sec>hi)
hi=sec;
sum+=sec;
t2=t1;
}
else
{
sum=t1;
t2=t1;
}
}
td=sum/(cnt-1);
printf(" the value for cps is %lld \n",cps);
printf ("the value of lo is %2.8f \n",lo);
printf ("the value of hi is %2.8f \n",hi);
printf("the average time was.. %2.8f\n ", sec);
return 0;
}