/* * 5963DEMO.CPP * * * A program to exercise Rohm BU5963AS OSD chip through PC printer port. * * Copyright (c) 1992 by Michael A. Hardwick. All rights reserved. * Completed version 1.00 July 31, 1992. In Turbo C++ 3.0. * * * Connect BU5963AS to printer port pins as follows: * * port pin: 1 -> OSD Chip Select...pin 29 * port pin: 2 -> OSD Data Input....pin 31 * port pin: 14 -> OSD Clock Input...pin 30 * * Printer port pins 18~25 should be grounded to BU5963AS test/demo * fixture. If the cable is long, line terminations should be added * at the BU5963AS pins. 330/680 (330 pullup/680 pulldown) resistive * terminations were adequate in my experiments, using an average * quality 3 meter cable with two different (486, 286) computers. * * * * */ #include #include #include #define true 1 #define false 0 //the following structure types are typedef struct { //all 16 bits total size... unsigned start : 6; //display starting position unsigned size1 : 2; //char size for top line unsigned size2 : 2; //char size for all other lines unsigned lovr : 6; //leftover bits } hvreg; //this struct type used for H & V OSD regs typedef struct { unsigned bkcol : 3; //main background color unsigned cscol : 3; //char background color unsigned olcol : 3; //char outline color unsigned lovr : 7; //leftover bits } colreg; //for OSD color register typedef struct { unsigned omode : 3; //output mode, 1=norm(?), table in OSD data unsigned bfreq : 1; //blink frequency, 0=fast, 1=slow unsigned bduty : 2; //blink duty-- off, 25%, 50%, 75% unsigned bi : 1; //if blink off, 0 sets reverse/blank chars unsigned brb : 1; //blink mode, 1=blank, 0=reverse video unsigned oline : 1; //char outline control, 1=on unsigned csize : 1; //char background control, 1=on unsigned port1 : 1; //digital output ports, 1=high... unsigned port2 : 1; // unsigned port3 : 1; // unsigned lovr : 3; //leftover bits } miscreg; //for OSD misc. register typedef struct { char ochar : 8; //ascii char for OSD chip goes here unsigned blnk : 1; //1=blink/rev on, 0=blink/rev off unsigned color : 3; //color for this char unsigned spc : 1; //1=superimpose (normal), 0=RGB out unsigned lovr : 3; //leftover bits } charword; //for sending displayable chars to OSD hvreg hreg, vreg; //declare some globals colreg creg; miscreg mreg; charword cvar, image[240]; unsigned char curpos, oldcurpos, ncolor = 7; char nblink = false; int pport, cport; void ship(int *pword) { //ship() shifts 16 bits out the parallel port //serially on D0, with clocking on CTL bit 1 char i; //note: D1~7 are driven with garbage! int sdat; sdat = *pword; //get the word to be shipped for(i = 0; i < 16; i++) { outport(pport, (sdat >> i)); //put data on parallel port outport(cport, 0x01); //raise the clock line to latch bit outport(cport, 0x03); //then lower it again } //(CS\ & SCLK are inverted in hdwe) } void setadd(unsigned char addr) //setadd() loads the OSD address register { int adword = 0x2000; //address mode bit is preset high adword |= addr; //or in the address byte ship(&adword); //call the serial output function } //regup() maintains OSD control registers, void regup(char amount) { //and PC screen. unsigned char tempy; if(amount == 0) goto Init; //complete setup. if(amount == 10) goto OSDsend; //just writes PC screen, //and ships current data to OSD regs. if(amount == 11) goto CBonly; //updates color & blink data on PC screen. else goto Normal; //+/-1 in field at PC cursor Y location. // Init: // hreg.start = 41; //set default OSD register values... hreg.size1 = 0; // hreg.size2 = 0; // hreg.lovr = 0; //all leftover bits to be zeros vreg.start = 41; vreg.size1 = 0; vreg.size2 = 0; vreg.lovr = 0; creg.bkcol = 0; creg.cscol = 0; creg.olcol = 0; creg.lovr = 0; mreg.omode = 1; mreg.bfreq = 0; mreg.bduty = 3; mreg.bi = 0; mreg.brb = 0; mreg.oline = 1; mreg.csize = 0; mreg.port1 = 0; mreg.port2 = 0; mreg.port3 = 0; mreg.lovr = 0; OSDsend: clrscr(); gotoxy(37,1); printf("Rohm BU5963AS Demo Program"); gotoxy(40,3); printf("Copyright (c) 1992 by"); gotoxy(40,4); printf("Decade Video Products"); gotoxy(40,5); printf(" All rights reserved."); gotoxy(30,10); printf("F1: Increment Color F2: Toggle Blink "); gotoxy(30,11); printf("F3: Field Select Up F4: Increment Field"); gotoxy(30,12); printf("F5: Field Select Down F6: Decrement Field"); gotoxy(30,13); printf("F7: Color Bars F8: Clear Screen "); gotoxy(30,15); printf("Esc: Quit Program"); gotoxy(1,1); printf(" %2d : hreg.start\n", hreg.start); //1 printf(" %2d : hreg.size1\n", hreg.size1); //2 printf(" %2d : hreg.size2\n", hreg.size2); printf(" %2d : vreg.start\n", vreg.start); printf(" %2d : vreg.size1\n", vreg.size1); printf(" %2d : vreg.size2\n", vreg.size2); printf(" %2d : creg.bkcol\n", creg.bkcol); printf(" %2d : creg.cscol\n", creg.cscol); printf(" %2d : creg.olcol\n", creg.olcol); printf(" %2d : mreg.omode\n", mreg.omode); printf(" %2d : mreg.bfreq\n", mreg.bfreq); printf(" %2d : mreg.bduty\n", mreg.bduty); printf(" %2d : mreg.bi \n", mreg.bi ); printf(" %2d : mreg.brb \n", mreg.brb ); printf(" %2d : mreg.oline\n", mreg.oline); printf(" %2d : mreg.csize\n", mreg.csize); printf(" %2d : mreg.port1\n", mreg.port1); printf(" %2d : mreg.port2\n", mreg.port2); printf(" %2d : mreg.port3\n", mreg.port3); //19 printf(" %2d : cvar.color\n", ncolor % 8); //20 if(nblink) printf( " 1 : cvar.blnk " ); //21 else printf( " 0 : cvar.blnk " ); //21 gotoxy(1,1); amount = 0; Normal: switch(wherey()) { case 1: hreg.start += amount; printf(" %2d", hreg.start); gotoxy(1, wherey()); break; case 2: hreg.size1 += amount; printf(" %2d", hreg.size1); gotoxy(1, wherey()); break; case 3: hreg.size2 += amount; printf(" %2d", hreg.size2); gotoxy(1, wherey()); break; case 4: vreg.start += amount; printf(" %2d", vreg.start); gotoxy(1, wherey()); break; case 5: vreg.size1 += amount; printf(" %2d", vreg.size1); gotoxy(1, wherey()); break; case 6: vreg.size2 += amount; printf(" %2d", vreg.size2); gotoxy(1, wherey()); break; case 7: creg.bkcol += amount; printf(" %2d", creg.bkcol); gotoxy(1, wherey()); break; case 8: creg.cscol += amount; printf(" %2d", creg.cscol); gotoxy(1, wherey()); break; case 9: creg.olcol += amount; printf(" %2d", creg.olcol); gotoxy(1, wherey()); break; case 10:mreg.omode += amount; printf(" %2d", mreg.omode); gotoxy(1, wherey()); break; case 11:mreg.bfreq += amount; printf(" %2d", mreg.bfreq); gotoxy(1, wherey()); break; case 12:mreg.bduty += amount; printf(" %2d", mreg.bduty); gotoxy(1, wherey()); break; case 13:mreg.bi += amount; printf(" %2d", mreg.bi ); gotoxy(1, wherey()); break; case 14:mreg.brb += amount; printf(" %2d", mreg.brb ); gotoxy(1, wherey()); break; case 15:mreg.oline += amount; printf(" %2d", mreg.oline); gotoxy(1, wherey()); break; case 16:mreg.csize += amount; printf(" %2d", mreg.csize); gotoxy(1, wherey()); break; case 17:mreg.port1 += amount; printf(" %2d", mreg.port1); gotoxy(1, wherey()); break; case 18:mreg.port2 += amount; printf(" %2d", mreg.port2); gotoxy(1, wherey()); break; case 19:mreg.port3 += amount; printf(" %2d", mreg.port3); gotoxy(1, wherey()); break; default: ; } setadd(240); //load base address for control registers ship((int *) &hreg); //cast struct pointer to an int pointer ship((int *) &vreg); //OSD address autoincrements ship((int *) &creg); ship((int *) &mreg); goto End; CBonly: tempy = wherey(); gotoxy(1, 20); printf(" %2d", ncolor % 8); gotoxy(1, 21); if(nblink) printf( " 1"); else printf( " 0"); gotoxy(1,tempy); End: } void colorbar(void) { //puts up the color bar pattern unsigned char i, j=0, c, t; cvar.ochar = 0x7f; //we're going to display colored blocks cvar.blnk = 0; // setadd(0); //starting in upper left corner for(i=0; i<10; i++) { //line counter, do every line for(c=0; c<8; c++) { //color bar counter, need 8 cvar.color = c; // for(t=0; t<3; t++) { //char counter, 3 blocks to a bar ship((int *) &cvar); image[j++] = cvar; } //OSD address autoincrements } } curpos = 0; } void clrOSD(void) { //clear OSD display RAM & image memory unsigned char i; setadd(0); cvar.ochar = ' '; //by filling both with cvar.color = 7; //lovely WHITE blanks! //The reason for this is OSD chip //interprets black chars (even blanks) //as transparent, and they wouldn't //show up when reversed, which would //prevent my cursor from showing! // cvar.blnk = 0; // for(i=0; i<240; i++) { // ship((int *) &cvar); //OSD address autoincrements here too. image[i] = cvar; } curpos = 0; //reset cursor to upper left corner } main(int argc, char *argv[]) { unsigned char i; char tchar, ublink, blflag; if(argc < 3) { sscanf(argv[1], "%x", &pport); if(pport == 0x378) goto Skate; if(pport == 0x278) goto Skate; } puts("Required argument for port address: 378 or 278 (hex)."); goto Quit; Skate: //Hey, it's OK to do my thing! cport = pport + 2; //set the control port address cvar.ochar = ' '; //start with a blank space cvar.blnk = 0; //not blinking cvar.color = 7; //character color = white cvar.spc = 1; //normal superimposed mode cvar.lovr = 0; //leftover bits must be zeros //OSD chip initialization... outport(cport, 0x02); //set SCLK low outport(cport, 0x03); //select OSD chip clrOSD(); //wipe OSD display RAM & local image regup(0); //initialize OSD control registers, //and PC screen //The Great OSD Screen Editor... ublink = image[curpos].blnk; //remember blink state under cursor image[curpos].blnk = 1; //cursor is a blinking whatever setadd(curpos); //make the OSD chip show it... ship((int *) &image[curpos]); // while((tchar = getch()) != 0x1B) { //escape hatch = esc switch(tchar) { // case 0x00 : //nul always preceeds special char tchar = getch(); //get the special char immediately switch(tchar) { //and act on it... case 'P' : //cursor down if(curpos <= (239 - 24)) curpos += 24; break; case 'H' : //cursor up if(curpos >= 24) curpos -= 24; break; case 'K' : //cursor left if(curpos > 0 && curpos < 24) curpos -= 1; if(curpos > 23 && (curpos % 24) != 0) curpos -= 1; break; case 'M' : //cursor right if(((curpos + 1) % 24) != 0) curpos += 1; break; case ';' : //F1 key, char color changer ncolor += 1; regup(11); break; case '<' : //F2 key, char blink bit changer nblink = !nblink; regup(11); break; case '=' : //F3 key, PC cursor up if(wherey() >1) gotoxy(1,(wherey()-1)); break; case '?' : //F5 key, PC cursor down if(wherey() < 19) gotoxy(1,(wherey()+1)); break; case '>' : //F4 key, increase reg value at PC cursor regup(1); break; case '@' : //F6 key, decrease reg value at PC cursor regup(-1); break; case 'A' : //F7 key, put up color bars colorbar(); break; case 'B' : //F8 key, clear OSD screen clrOSD(); break; case 'C' : //F9 key, spare break; case 'D' : //F10 key, spare break; default:; break; } break; case 0x08 : // <- rubout handler if(curpos > 0) { cvar.ochar = ' '; cvar.color = 7; cvar.blnk = 0; setadd(--curpos); ship((int *) &cvar); image[curpos] = cvar; } break; case 0x0D : //CR handler curpos -= (curpos % 24); //subtract space to left if(curpos < 216) curpos += 24; //216 is lower left corner break; default: //normal "printable" char handler if(curpos <= 239) { cvar.ochar = tchar; cvar.blnk = nblink; cvar.color = ncolor; setadd(curpos); ship((int *) &cvar); image[curpos] = cvar; if(nblink == true) blflag = true; else blflag = false; //true blflag tells cursor handler //to let this character blink! } if(curpos < 239) curpos++; break; } //cursor movement handler if(blflag == true) ublink = true; // blflag = false; // image[oldcurpos].blnk = ublink; //retrieve old blink state setadd(oldcurpos); //and restore old OSD char ship((int *) &image[oldcurpos]); // ublink = image[curpos].blnk; //remember blink state image[curpos].blnk = 1; //under new cursor position setadd(curpos); //then show new cursor ship((int *) &image[curpos]); // oldcurpos = curpos; //remember cursor position } //That's the Editor! outport(cport, 0x02); //deselect OSD chip clrscr(); //clean up the PC screen Quit: //Take my marbles and go home. return 0; }