tynor@gitpyr.UUCP (Steve Tynor) (01/08/86)
Can anyone tell me how I can get a simple timer tick on my ST? I need a high resolution timer so that I can record keystrokes off of MIDI for a simple sequencer I'm writing. However, I've looked through all the developer documentation and can't figure out how to do it... Do I have to write an interupt handler to count timer interupts? (ugh...) I can't believe it's as hard as that... =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Progress means replacing something wrong with something more subtly wrong. Steve Tynor Georgia Instutute of Technology ...{akgua, allegra, amd, harpo, hplabs, ihnp4, masscomp, ut-ngp, rlgvax, sb1, uf-cgrl, unmvax, ut-sally} !gatech!gitpyr!tynor
bammi@cwruecmp.UUCP (Jwahar R. Bammi) (01/12/86)
> Can anyone tell me how I can get a simple timer tick on my ST? I need a > high resolution timer so that I can record keystrokes off of MIDI for a > simple sequencer I'm writing. However, I've looked through all the > developer documentation and can't figure out how to do it... Do I have to > write an interupt handler to count timer interupts? (ugh...) I can't believe > it's as hard as that... > > Steve Tynor > Georgia Instutute of Technology The simplest way is to read the value of the 200 Hz system timer contained in location 4BA -- The hitch Hikers guide says 4BC but that is a misprint. It has to be done in super mode otherwise you get mushrooms. Here is a example long ticks; long *_hz200 = 0x000004ba; read_ticks() { ticks = *_hz200; } main() { ...... /* Call read_ticks in super mode - this def if missing in osbind.h */ xbios(38,read_ticks); /* ticks now has the value of the 200 Hz timer */ } You could also use the Xbtimer() xbios call with timer a, but I have'nt gotten it to work correctly as yet ( I had posted a query a couple of days back, but still have no answer ). Some people over here have been hacking midi code too. One of their experiences was that incresing the size of the midi receive buffer helps a lot too in keeping up with some of the Yahama equipment that send status bytes every 200 ms (I think). this can be done by using the Iorec() xbios call. Hope this helps. -- Jwahar R. Bammi Usenet: .....!decvax!cwruecmp!bammi CSnet: bammi@case Arpa: bammi%case@csnet-relay CompuServe: 71515,155
mendoza@aero.ARPA (Lee Mendoza) (01/12/86)
In article <1241@gitpyr.UUCP> tynor@gitpyr.UUCP (Steve Tynor) writes: >Can anyone tell me how I can get a simple timer tick on my ST? > I have written a simple function which accesses the 200 Hz timer tick, unfortunately it is the highest resolution timer that I could find. [If anyone knows of a 1 ms timer I would like to hear about it.] This function requires that your program include osbind.h (for the Super() function); which requires that you include osbind.o when you link your program. Note that the address pointed to in the "Hitchhiker's Guide to the BIOS" is not correct. I suffered greatly over this until I started poking around using SID. The address is correct in the BIOS listings. Lee Mendoza ------ /* timer.h -- returns a longword containing the number of milliseconds since * booting, with a resolution of 5 ms. * * Written by Lee Mendoza * */ long timer() { long stack, time, *timer; timer = 0x4ba; /* _hz_200: 200 Hz system timer tick */ stack = 0; /* null the stack pointer */ stack = Super(stack); /* enter supervisor mode, save the stack */ time = *timer; /* get 5 ms timer tick */ stack = Super(stack); /* exit supervisor mode, restore the stack */ time = 5*time; /* calculate the time... */ return(time); /* and return it to the caller */ }
nigel@minster.UUCP (nigel) (01/12/86)
In article <1241@gitpyr.UUCP> tynor@gitpyr.UUCP (Steve Tynor) writes: >Can anyone tell me how I can get a simple timer tick on my ST? I need a >high resolution timer so that I can record keystrokes off of MIDI for a >simple sequencer I'm writing. However, I've looked through all the >developer documentation and can't figure out how to do it... Do I have to >write an interupt handler to count timer interupts? (ugh...) I can't believe >it's as hard as that... > You're right - it's not difficult. I have done this myself, so rather than just reply with the appropriate routine, I draw attention to the routine hz200() in the following program. It is a MIDI recorder - it listens to what is being played, can store it on disk, and play it back. I hacked it together in an afternoon, so it's not earth-shattering stuff. It only listens on one channel, and ignores all but note information. It does preserve velocity information, and was tested on a Yamaha DX7. If anyone does improve this, I would appreciate seeing the source code. PS - can anyone spot the deliberate mistake? -------------------------------------------------------------------------- /* mr.c */ /* Nigel Roles 1986 */ #include "osbind.h" #define MIDI 3 #define CON 2 #define GM (Bconin(MIDI)&0xff) struct event { int delay; char cmd[3]; }; struct event *buffer; int empty=1; long bc; long memsize; long bmax; long hz200() { register long save_ssp=Super(0L); register long uhz200= *(long *)0x4ba; Super(save_ssp); return uhz200; } record() { register struct event *bp; long now,then; printf("Recording (any key to stop):\n"); while (Bconstat(MIDI)) Bconin(MIDI); then=0; bp=buffer; bc=0; for (;;) { if (Bconstat(CON)) { Bconin(CON); bp->delay= -1; bc++; break; } if (Bconstat(MIDI)) { int b=GM; if (b==0xfe) continue; /* Ignore active sensing */ if (b==0x90) { now=hz200(); if (then==0) bp->delay=0; else bp->delay=now-then; then=now; bp->cmd[0]=b; bp->cmd[1]=GM; bp++->cmd[2]=GM; if (++bc==bmax) { printf("Buffer full\n"); break; } } } } } play() { register struct event *bp=buffer; long target; printf("Playing:\n"); while (bp->delay!= -1) { if (Bconstat(CON)) { Bconin(CON); break; } target=hz200()+bp->delay; while (hz200()<target) ; Midiws(2,bp->cmd); bp++; } } #define FNSIZE 20 struct filename { char lin,lout; char name[FNSIZE+1]; } fn; int h; getfn() { printf("Filename: "); fn.lin=FNSIZE; Cconrs((char *)&fn); printf("\n"); fn.name[fn.lout]='\0'; } load() { getfn(); if ((h=Fopen(fn.name,0))<0) { printf("Can't open %s for reading (error %d)\n",fn.name,h); return; } if (Fread(h,memsize,buffer)<0) printf("Read error\n"); else empty=0; Fclose(h); } save() { getfn(); Fdelete(fn.name); if ((h=Fcreate(fn.name,0))<0) { printf("Can't create %s (error %d)\n",fn.name,h); return; } if (Fwrite(h,sizeof(struct event)*(long)bc,buffer)<0) printf("Write error\n"); Fclose(h); } main() { char c; char *malloc(); memsize=(long)malloc(-1L); if ((buffer=(struct event *)malloc(memsize))==(struct event *)0L) { printf("malloc failure\n"); exit(1); } bmax=memsize/sizeof(struct event); printf("\033EMidi Recorder Version 1.0 (definitely)\n"); printf("(C) N. G. Roles 1985\n\n"); printf("Capacity: %D events\n",bmax); for (;;) { printf("MR> "); c=Bconin(CON); printf("%c\n",c); switch (c) { case 'q': break; case 'r': record(); continue; case 'p': if (empty) printf("Nothing to play!\n"); else play(); continue; case 's': if (empty) printf("Nothing to save!\n"); else save(); continue; case 'l': load(); continue; default: printf("???\n"); continue; } break; } }
knnngt@ukma.UUCP (Alan Kennington) (01/17/86)
**** "They eat lions, don't they?" - film title **** On the subject of timer A in the 78901 chip, I checked out the entire bios code that is executed upon entry to xbtimer from start to finish. And it all seemed to be beautifully in accord with the specifications for the timer chip. I was just about to give up when I read in the bios manual that some tricky business with the Hsync interrupt could be done by faking RTEs. Then I realised that timer interrupts put a short stack frame onto the supervisor stack. Which means that an RTE in Super mode is required. A C program return can presumably only ever be an RTS. Hence the program can not possibly work by diverting the timer interrupt to a C function as an interrupt handler. First, can anybody out there confirm my brief analysis of the problem. Second, has anybody discovered the means of RTEing at the end of a C program? The bios manual defines xbtimer as a C program. But it doesn't mention anything about having to write an assembly language program to handle timer interrupts. Many of you must have long ago written programs to handle such interrupts. So please tell me if I am incorrect in all of this. Thanks.............................ak.