tj@XN.LL.MIT.EDU (Thomas E. Jones) (04/09/90)
I just purchased the Video Digitizer from DAK ($169.00.) It is a 256x256 64-grey level frame grabber. It comes with 3 programs to allow you to display images from your camera (or VTR,) make a slide-show of pictures, and a paint-like program. None of the software packages let you get the full 256X256 grey-level image, they all do dithering and reduce the effective resolution. I am trying to dis-assemble one of the programs to figure out how to read from the card myself, but it's fairly difficult and time-consuming. Does anyone else have one of these systems? If so, I'd like to share information with them. I have figured out a great deal about the card (both from program disassembly and examination of the hardware.) Please get ahold of me. Anyone who helps out will be entitled to all the software I get finished. - tj@xn.ll.mit.edu Thomas E. Jones -- tj@xn.ll.mit.edu or tj@ll-xn.arpa (one of these should work) Thomas E. Jones, home (617) 924-8326 work (617) 981-5093
nelson@sun.soe.clarkson.edu (Russ Nelson) (04/09/90)
In article <1788@xn.LL.MIT.EDU> tj@XN.LL.MIT.EDU (Thomas E. Jones) writes: Does anyone else have one of these systems? If so, I'd like to share information with them. I have figured out a great deal about the card (both from program disassembly and examination of the hardware.) Please get ahold of me. Anyone who helps out will be entitled to all the software I get finished. Check this program out. It digitizes continuously, and copies the image to the VGA screen. Note that you *must* have a VGA, and the program doesn't check. No copies of the frames are kept, although that's pretty simple to add. Most of the time is spent copying it to the VGA memory because of all the wait states (ick). If you have a few meg of EMS, you could probably make a cute small movie. Curiously enough, I got the information on programming it simply by calling DAK's technical support number. I didn't even have to plead and beg, they just offered to send me the technical specs and program fragments! This is in Turbo C 2.0: #include <stdio.h> #include <dos.h> #include <stdlib.h> #define VID 0x3ef /* when reading VID: */ #define HSYNC 0x40 #define VSYNC 0x80 /* when writing VID: */ #define RDFIOM 0x80 #define ELAYM 0x70 #define DELAYSHF 4 #define DELAYNOM 0x60 #define RFSHEN 8 #define READMODE 4 #define CAPTURE 2 #define VCLEAR 1 int their_palette[64*3]; int our_palette[64*3]; /* * Bios function call definitions */ #define BIOS_VIDFN 0x10 /* Video functions */ #define VID_PALETTE 0x10 /* palette access function */ #define PAL_SETPAL 0x00 /* update single palette register */ #define PAL_SETPALBLOCK 0x02 /* update all palette registers */ #define PAL_GETPALBLOCK 0x09 /* read all palette registers */ #define PAL_GETDACBLOCK 0x17 /* read current VGA DAC values */ #define PAL_SETDACBLOCK 0x12 /* set new VGA DAC values */ #define VID_SETPIXEL 0x0C /* store pixel value */ #define VID_DISPLAY 0x1A /* video display combination */ #define VID_SUBSYSTEM 0x12 /* video subsystem configuration */ /* * Arguments to the vid_vgapalette and vid_setpalette functions */ #define PAL_SAVE 0 /* Save existing values */ #define PAL_RESTORE 1 /* Restore saved values */ #define PAL_SETGREY 2 /* Set greyscale mapping */ #define PAL_SETLIN 3 /* Set 1:1 mapping (vid_setpalette) */ /* * Routine to map VGA palette registers (256 colour mode) * to and from a greyscale display. */ #define BITSPERBYTE 8 #define BITSPERVGACOLOUR 6 /* no. VGA DAC registers */ #define SIZE_DACS 256 /* no. distinct greyscale values */ #define NUM_GREY (1 << BITSPERVGACOLOUR) /* no. palette registers that map * to the same greyscale value */ #define GREY_SAME (SIZE_DACS / NUM_GREY) /* no. underlying colours on vga */ #define PRIMARY_COLOURS 3 static void vid_vgapalette(action) int action; { union REGS regs; struct SREGS sreg; static unsigned char SaveDacs[SIZE_DACS * PRIMARY_COLOURS], *GreyDacs = 0; switch(action) { case PAL_SAVE: /* Save existing palette */ regs.h.ah = VID_PALETTE; regs.h.al = PAL_GETPALBLOCK; regs.x.bx = 0; /* first palette register */ regs.x.cx = SIZE_DACS; /* read all palette registers */ segread(&sreg); sreg.es = sreg.ds; regs.x.dx = (unsigned int) SaveDacs; int86x(BIOS_VIDFN, ®s, ®s, &sreg); break; case PAL_RESTORE: /* restore saved palette */ regs.h.ah = VID_PALETTE; regs.h.al = PAL_SETDACBLOCK; regs.x.bx = 0; /* first palette register */ regs.x.cx = SIZE_DACS; /* read all palette registers */ segread(&sreg); sreg.es = sreg.ds; regs.x.dx = (unsigned int) SaveDacs; int86x(BIOS_VIDFN, ®s, ®s, &sreg); break; case PAL_SETGREY: /* set palette to greyscale */ if (GreyDacs == 0) { unsigned char *p; int c; if ((GreyDacs = malloc(SIZE_DACS*PRIMARY_COLOURS)) == 0) { return; } for (p = GreyDacs, c = 0; c < SIZE_DACS; c++) { int i; for (i = 0; i < PRIMARY_COLOURS; i++) *p++ = (c & 0x3f); } } regs.h.ah = VID_PALETTE; regs.h.al = PAL_SETDACBLOCK; regs.x.bx = 0; /* first palette register */ regs.x.cx = SIZE_DACS; /* read all palette registers */ segread(&sreg); sreg.es = sreg.ds; regs.x.dx = (unsigned int) GreyDacs; int86x(BIOS_VIDFN, ®s, ®s, &sreg); break; } } insb(int port, void far *buf, int cnt) { _DX = port; _CX = cnt; _ES = FP_SEG(buf); _DI = FP_OFF(buf); __emit__(0xf3, 0x6c); /* rep insb */ } video() { int i; geninterrupt(0x10); } vidinit() { outportb(VID, READMODE | DELAYNOM); outportb(VID, VCLEAR | RFSHEN | READMODE | DELAYNOM); } main() { int y; _AX = 0x13; video(); vid_vgapalette(PAL_SAVE); vid_vgapalette(PAL_SETGREY); while (!kbhit()) { while ((inportb(VID) & VSYNC) == VSYNC) if (kbhit()) break; outportb(VID, DELAYNOM | READMODE); outportb(VID, VCLEAR | DELAYNOM); outportb(VID, VCLEAR | DELAYNOM | CAPTURE); while ((inportb(VID) & VSYNC) == 0) if (kbhit()) break; while ((inportb(VID) & VSYNC) == VSYNC) if (kbhit()) break; outportb(VID, DELAYNOM); outportb(VID, READMODE | DELAYNOM | RDFIOM); outportb(VID, READMODE | VCLEAR | DELAYNOM | RDFIOM); for (y = 0; y < 200; y++) { insb(VID, MK_FP(0xa000, y * 320), 256); } outportb(VID, READMODE | VCLEAR | DELAYNOM); vidinit(); } getch(); vid_vgapalette(PAL_RESTORE); _AX = 0x3; video(); } -- --russ (nelson@clutx [.bitnet | .clarkson.edu]) Russ.Nelson@$315.268.6667 Violence never solves problems, it just changes them into more subtle problems
MXP122@psuvm.psu.edu (Zaphod Beeblebrox) (04/10/90)
Yeaperie. . . . The first 'guess' I made at the format was . . since its 256x256 that amounts to a nice 64K file. . and the file sizes were about half of this. . so I read in the file byte by byte in a C program. . . 128 bytes across and 256 lines down. . when the first nibble was the color for the left pixel (16 shades. . ) and the other nibble was the right pixel. . worked like a charm. . I just let the VID program grab the images (I tried to disassemble it. .but it was written in a high level language and the machine code is very messed up). . .I can post the C file if anyone's interested. . .etc etc. . . Mark
bbb@kuhub.cc.ukans.edu (04/10/90)
In article <1788@xn.LL.MIT.EDU>, tj@XN.LL.MIT.EDU (Thomas E. Jones) writes: > I just purchased the Video Digitizer from DAK ($169.00.) It is a > 256x256 64-grey level frame grabber. It comes with 3 programs to > allow you to display images from your camera (or VTR,) make a slide-show > of pictures, and a paint-like program. > > None of the software packages let you get the full 256X256 grey-level > image, they all do dithering and reduce the effective resolution. I > am trying to dis-assemble one of the programs to figure out how to > read from the card myself, but it's fairly difficult and time-consuming. > > Does anyone else have one of these systems? If so, I'd like to share > information with them. I have figured out a great deal about the card > (both from program disassembly and examination of the hardware.) Please > get ahold of me. Anyone who helps out will be entitled to all the software > I get finished. > > - tj@xn.ll.mit.edu > Thomas E. Jones > > -- > tj@xn.ll.mit.edu or tj@ll-xn.arpa (one of these should work) > Thomas E. Jones, home (617) 924-8326 work (617) 981-5093 THOMAS To answer your questions directed to BROWNRIGG (I'm his friend with the DAK card. Just got my account today.) The card really only appears to digitze about 245 lines @ 256 pix. The fundamental drivers I got from DAK software support. That number is in the manual you got with the board. I write all in MS-C and MS-QC. I have chosen MSQC for my software because is allows in-line assembly. (QC ver 2.00 that is) Below is the listing for my so called Super-Vid. (SVID) It will get about 4-6 frames/sec out to the VGA on a 286. Maybe more I haven't really tried to measure it. After that is the .h file I use. I saw you got a Turbo-C version. The major difference in my code is the watching the FRAME bit to make sure successive frames are the same one. Otherwise you will notice a 'jumping' of the image as it randomly gets different frames (even-vs-odd) of the interlace. I'm still looking for info on the Closed-Caption. In theory I should have about 33000 Usec between CC info lines and that leads me to think I could capture that single line, decode it and write it out to screen or file. Would be neat to be able to generate transcripts of CC programs of interest. ********************************************************************* SVID // modified for `max' transfer speed!!!!! I hope.. // SVID by Brett Bennett // Based orginally on information supplied by DAK // // Quick-C ver 2.0 // // compile line: QCL /G2 SVID.C // // program uses QC-2 inline assembly to max out transfer from interface // to VGA memory. Uses an INSB command that is available only on 80286's // and up. PROGRAM WILL NOT WORK ON AN 8086/88. A V-20 does seem to work. // // Program may be freely modified and distributed with proper acknowlegdments // #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include "vid.h" #include <graph.h> //#define MAXSAMP 62000l #define MAXSAMP 51200l unsigned char huge *buf; int gain,enlighten,lines; int max,ofset=20; unsigned char DELAYNOM=0x00; unsigned char far *mem; /* ignore its warnings */ // //this var is crtical for precise frame grabbing applications. unsigned char flipflop=0; //controls frame grabbers frame syncing char key; main (argc, argv) int argc; char * argv[]; { long count,sum; int avg; count=MAXSAMP; //printf("Enter multiplier factor "); //scanf("%d",&gain); //printf("Enter # scanlines"); //scanf("%d",&lines); lines=200; ofset=0; if ( (argc>1) && (0==strcmpi(argv[1],"?")) ) { printf("\n\n B&D Electronics Super VIdeo Display 1990(c)\n\n"); printf("Format:\nSVID ofset lines\n"); printf("Ofset= number of lines to skip\n"); printf("lines= number of lines to display per frame\n"); printf("SVID w/no parameters defaults to ofset=0, lines=200\n"); printf("Press CR to toggle between frames\n"); printf("Space bar to freeze then again to end\n"); exit(0); } if ( argc > 1 ) ofset=atoi(argv[1]); ofset=ofset*256; if ( argc > 2 ) lines=atoi(argv[2]); buf = (char huge *)halloc( count, sizeof( char ) ); if ( buf == 0 ) {printf("allocate failed.\n");exit(1);} if ( 0 == _setvideomode(_MRES256COLOR)) { printf("Sorry VGA required.\n"); exit(0); } //build a 64 shade gray table! 4 times _disable(); //stop interupts for (max=0;max<64;max++) { // outp(0x3c8, (char)max); //VGA's DAC reg outp(0x3c9, (char)max); //RED outp(0x3c9, (char)max); //GREEN outp(0x3c9, (char)max); //BLUE outp(0x3c8, (char)max+64); outp(0x3c9, (char)max); outp(0x3c9, (char)max); outp(0x3c9, (char)max); outp(0x3c8, (char)max+128); outp(0x3c9, (char)max); outp(0x3c9, (char)max); outp(0x3c9, (char)max); outp(0x3c8, (char)max+192); outp(0x3c9, (char)max); outp(0x3c9, (char)max); outp(0x3c9, (char)max); } vidinit(); //init the video card. while ( key != 32) //wait for a space char { do { // modified ver of vxfer goes directly to video memory. _disable(); vxfer(); _enable(); } while ( !kbhit() ); key=getch(); flipflop=!flipflop; //toggle flipflop. controls which frame of the interlace } getch(); _setvideomode(_DEFAULTMODE); } //end main /***********************************************************************/ /* DRIVING ROUTINES Original code from DAK */ /***********************************************************************/ /* THIS FUNCTION INITIALIZES TME VIDEO BOARD LOGIC */ vidinit() { outp(VIDBOARD, DELAYNOM | READMODE); /* clear the board */ outp(VIDBOARD, VCLEAR | RFSHEN | DELAYNOM | READMODE); /* clear the board */ } /*******************************************************/ pas() /* this is a wait loop (pause) function */ { int i; int j; for (i=1; i<300;++i) for (j=1; j<100;++j ); } /******************************************************/ /* the CAPTURE FUNCTION FOR OPERATING THE VIDEO CARD */ /******************************************************/ vxfer() { int i; unsigned int j; int done; i = 10000; /* Start by making sure that vertical syncs are occurring */ done = 0; while ( !done ) { //flip-flop var controls what frame to grab. //while the DAK card doesn't know which frame is the even and which is odd //(depends on when the video signal was first applied to the card) It does //keep track of one from the other. This is critical for accurate capture //of images. ESP when doing things like R-G-B color seperation work. // wait for sync high AND field bit high. if( flipflop ) { //waits for high field bit. if ( (inp(VIDBOARD) & FVSYNCM) == FVSYNCM) done = 1; if (--i < 0) done = 1; } // wait for sync high AND field bit low. if( !flipflop ) { if ( (inp(VIDBOARD) & FVSYNCM) == VSYNCM) done = 1; if (--i < 0) done = 1; } } if (i < 0) { // _setvideomode(MTEXT); printf("Vertical sync is stuck high..aborting\r"); pas(); } else { i = 10000; done = 0; while ( !done ) { //NOW WAIT FOR SYNC TO GO LOW. if ( (inp(VIDBOARD) & VSYNCM) == 0) done = 1; if (--i < 0) done = 1; } if (i < 1) { // _setvideomode(MTEXT); printf("No vertical sync detected..aborting\r" ); pas(); i=10000; } else { //ok here we know that vertical syncs are occuring. that is good! //SYNCH IS LOW AND FIELD IS HIGH TAKE A PICTURE! //go with what I was given from DAK... outp(VIDBOARD, DELAYNOM | READMODE); /* clear the board */ outp(VIDBOARD, VCLEAR | DELAYNOM); /* set board in write mcde */ outp(VIDBOARD, VCLEAR | CAPTURE | DELAYNOM); /* capture */ i = 10000; while ( ( (inp(VIDBOARD) & VSYNCM) == 0) && (--i > 0) ); /* while sync present */ //reduce i here is you don't want to wait for a full screens worth. i = 10000; //appears to be a sufficently long enough delay. while ( ( (inp(VIDBOARD) & VSYNCM) == VSYNCM) && (--i > 0) ); /* Wait */ outp(VIDBOARD, DELAYNOM); /* set clear and remove capture */ outp(VIDBOARD, READMODE | DELAYNOM | RDFIOM); /* With clear set, goto read mode */ outp(VIDBOARD, READMODE | VCLEAR | RDFIOM | DELAYNOM); { //high speed direct to video memory transfer here. _disable(); //stop any further system interupts. except NMIs _asm { push ax ;save some regs push cx push dx push di push es mov dx,0x3ef ;prepare dx for port address mov cx,ofset ;get var OFSET and skip this many lines. jcxz noeatum ;jump cx=zero. if zero then jump to eatum eatum: in al,dx ;skip over requested lines. EXPECTED to be 256*#lines. loop eatum ;loop back and eat um up noeatum: mov cx,lines ;number of lines to do. jcxz exitstageleft mov ax,0xa000 ;segment of vga memory. mov es,ax ;move segment to es for INSB instruction to come. mov di,0 ;set inital offset to zero ;regs now prep. time to get the data. line: push cx ;save number of lines left to do. mov cx,256 ;load number of pixels for next line. rep insb ;do insb cx times. add di,64 ;shift to next line of video 320x200 mode only! pop cx ;get line count back loop line ;back to get next line. exitstageleft: pop es ;restore regs. pop di pop dx pop cx pop ax } } /* now disable DMA request */ //outp(VIDBOARD, READMODE | VCLEAR | DELAYNOM); } } }//end vxfer ****************************************************************** VID.H /* VID.H taken orginally for DAK supplied user info. Some of the items in their include did not seem to be accurate for this version of the digitizer. Major mode is addition is FVSYNCM used to monitor which frame (even/odd) is taken. */ /* DAKS include. */ /* Vid.d lnclude file Aug. 11, 1987 */ #define MTEXT 1 /* the Video modes */ #define GRAPH 2 /* the VIDEO BOARO DEFS */ #define VIDBOARD 0x3ef /* the read space */ #define VIDMASK 0x3f /* the 6 Video bit sample */ //#define HSYNCM 0x40 /*horizontal sync mask DOES NOT APPLY TO THIS BOARD!*/ /* low for 5 of each 62.5 usec <- apparently a different board than DAK's*/ #define FSYNCM 0x40 /*the frame sync mask toggles with each vsync field. */ #define VSYNCM 0x80 /*Vertical sync mask high for 180 Usec every 33.3 msec */ #define FVSYNCM 0xc0 /*Frame and Vertical sync mask use to ensure vertical */ /* the write space */ #define RDFIOM 0x80 /* 1 == read frame data via i/o */ #define DELAYM 0x50 /* delay bit mask */ #define RFSHEN 0x08 /*DMA request enable mask *actually enable main-board refreshs**/ #define READMODE 0x04 /* 1 = Read Mode ; 0 = Write mode */ #define CAPTURE 0x02 /* low to hlgh transiticn initiates a capture */ #define VCLEAR 0x01 /* when low, clears the line and pixel counters */ //I like to set these in my code //#define DELAYSHF 0x04 /* delay bit shlft */ //#define DELAYNOM 0x60 /* nominal delay Value defined in the */