/*
* 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 0x09wr_cntr1 0 1 1 0 0x01wr_cntr2 1 0 1 0 0x0Dwr_cntrl 1 1 1 0 0x05rd_cntr0 0 0 0 1 0x0Ard_cntr1 0 1 0 1 0x02rd_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+2struct 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 wantlpt1=mmap_device_io( len, PORT );if( errno != EOK) printf("\nMmap_device errno %s\n", strerror( errno ) ); //set up the counter timerout8( control, 0x04); // set the address busout8(base,mode); // have to setup dataout8(control,wr_cntrl); // then drop the write enableout8(control, idle); // raise the write enableout8(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;}