#include #include #include #include #include #include #include #include void initcom(int,int); void DTR_lo(int); void DTR_hi(int); unsigned int read4(char *); void dump(void); void fill(void); void execute(int); void cxmit(char,int); void ixmit(int,int); unsigned int ircv(int); unsigned char crcv(int); unsigned char crcv2(int); void autotest(void); void write_data(int, int, int *); void read_data (int, int, int *); void reset(int); void HELP(void); void usage(void); void cmdline(void); unsigned int load_file(int, char *); unsigned int load_DSK(int, char *); #define SYNCH 0 // DSK_COMM Synch value (wait for CMD) #define DL_PROG 1 // Download prog #define UL_PROG 2 // Upload prog #define DL_DATA 3 // Download data #define UL_DATA 4 // Upload data #define BRANCH 5 // BRANCH (execute at) next 16 bit value int port_no = 0x3f8; int baud = 6, userbaud = 6; int run_autotest = 0; int dtr_level = 0; // dtr_level ^ rst_val inverts DTR void GRAPH(void); int d_buf[1024]; // I/O data buffer void main(void) { char stg[20], *eptr; port_no = 0x3f8; // COM1 default clrscr(); HELP(); cmdline(); load_file(0,""); // bootloads DSK_COMM.DSK for(;;) { if(run_autotest) { autotest(); load_file(0,""); // Boot DSK_COMM.DSK basic I/O kernal } switch (toupper(getche())) { case 'A': run_autotest = 1;break; // run autotest case 'Q': exit(0) ; break; // Quit case 'R': reset(port_no); break; // Reset (Pulse DTR low) case 'I': load_file(0,""); break; // Re-Bootload DSK_COMM.DSK case 'B': load_file(3,""); break; // Bootload a user defined file case 'L': load_file(1,""); break; // Load DSK file via DSK_COMM case 'E': printf(" Execute at address (0xABCD form!)\n"); execute(strtoul(gets(stg),&eptr,0)); break; case 'D': dump(); break; // Dump DSK memory case 'F': fill(); break; // Fill DSK memory case 'G': GRAPH(); break; case 'X': execute(load_file(1,"")); break; case '?': case 'H': HELP(); default: break; } printf("\n"); } } int start_graphics(void) { int gdriver = EGA, gmode = EGAHI, errorcode; registerbgidriver(EGAVGA_driver); initgraph(&gdriver, &gmode, ""); errorcode = graphresult(); if (errorcode != grOk) { printf("Graphics error: %s\n", grapherrormsg(errorcode)); printf("Press any key to halt:"); getch(); exit(1); } setviewport(100, 50, 355, 305, 1); return 0; } void GRAPH(void) { int gdriver, gmode=EGA; int x, y, page=0; char ch; start_graphics(); for(;;) { ch = crcv(port_no); y = ch; if(y == 0) { setvisualpage(page); page ^= 1; setactivepage(page); cleardevice(); rectangle(0,0,255,255); moveto(0,255); x = 0; } y = 128 - y; lineto(x,y); x++; if(kbhit()) { closegraph(); clrscr(); printf(">>>>>> DSKL is now in command mode\n"); return; } } } void cmdline(void) { int i; char *ptr,*eptr; clrscr(); port_no = 0x3f8; // COM1 default for(i=_argc-1;i>0;i--) { ptr = strupr(_argv[i]); while(*ptr != 0) // scan each string { switch(*ptr) { case 'C': while(*ptr != 0) { if(*ptr == '1'){port_no = 0x3f8; break;} if(*ptr == '2'){port_no = 0x2f8; break;} ptr++; } break; case 'B': ptr++; baud = 115200 / strtol(ptr,&eptr,0); userbaud = baud; break; case 'A': run_autotest = 1; break; case 'I': dtr_level = 1; case 'H': case '?': usage(); HELP(); break; default: break; } ptr++; } } } void autotest(void) { char buf[10], *ptr; ptr = buf; clrscr(); execute(load_file(2,"AUTOTEST.DSK")); // Load AUTOTEST.DSK diagnostics clrscr(); printf("AUTOTEST: \n"); printf(" \n"); printf("[Q] quits AUTOTEST. It may take several tries to get a response. \n"); printf("The messages you see will be coming from the DSK with the host \n"); printf("acting as a dumb terminal. \n"); printf(" \n"); printf("Hit ENTER to begin \n"); getch(); for(;;) { *ptr = crcv(port_no); if(*ptr == 0) { if(toupper(getch())=='Q') // end MSG to host, wait for user { printf("\nEXIT AUTOTEST\nPlease wait while DSK_COMM is reloaded\n"); run_autotest = 0; return; } *ptr = crcv(port_no); } if(kbhit()) { if(toupper(getch())=='Q') { printf("\nEXIT AUTOTEST\nPlease wait while DSK_COMM is reloaded\n"); run_autotest = 0; return; } } if(*ptr == '\\') // C style escape sequence follows { *ptr = crcv(port_no); switch(*ptr) { case 'a': printf("\a"); break; // Audible bell case 'b': printf("\b"); break; // Backspace case 'f': clrscr() ; break; // Full Formfeed >>> NOT BC++ <<< case 'n': printf("\n"); break; // Newline (linefeed) case 'r': printf("\r"); break; // Carriage return case 't': printf("\t"); break; // Tab (horizontal) case 'v': printf("\v"); break; // Vertical tab case '\\': printf("\\"); break; // Backslash case '\'': printf("\'"); break; // Single quote (apostrophe) case '\"': printf("\""); break; // Double quote case '?': printf("\?"); break; // Question mark case '0': getch(); break; // end MSG to host, wait for user default : break; // sequence not understood } } else printf("%c",*ptr); } } void HELP(void) { printf("\n"); printf("DSKL: DSK LOADER, I/O AND AUTOTEST PROGRAM \n"); printf("HELP COMMANDS: \n"); printf(" A - Autotest DSK Loads and executes AUTOTEST.DSK \n"); printf(" Q - Quit DSKL \n"); printf(" R - Reset DSK (no load) \n"); printf(" I - Boot (initialize) DSK_COMM.DSK \n"); printf(" B - Bootload file \n"); printf(" L - Load file << Using DSK_COMM \n"); printf(" X - Load and execute file << Using DSK_COMM \n"); printf(" E - Execute @
\n"); printf(" Dx - Dump Data/Prog
\n"); printf(" Fx - Fill Data/Prog
\n"); printf(" G - Graph data received (EGA, signed char, 0=synch) \n"); printf(" H - HELP menu (this) \n"); printf(" \n"); printf("AUTOTEST: \n"); printf("For AUTOTEST.DSK to load, DSK_COMM.DSK must be loaded first using\n"); printf("the TMS320C26 bootloader. Bootload initialization of DSK_COMM \n"); printf("is automatic the first time, but may be corrupted by user \n"); printf("operations. Once loaded, AUTOTEST sends diagnostic messages to \n"); printf("the host which echoes them to the screen. \n"); printf(" \n"); printf("[Q]uit Any other key for more "); if(toupper(getche()) == 'Q') { printf("\n\n>>>>>> DSKL is now in command mode\n"); return; } clrscr(); printf("DSKL: \n"); printf(" \n"); printf("DSKL loads a simple communications kernal DSK_COMM.DSK which \n"); printf("performs simple I/O functions. Because of autobaud detection \n"); printf("limitations at high rates, several tries may be needed. Bootload\n"); printf("failure or erratic performance can also be caused by... \n"); printf(" \n"); printf(" 1) Wrong port selected (after 8 tries the other will be tried)\n"); printf(" 2) RS232 cable (or connection) bad or noisy \n"); printf(" 3) No power (9 VAC transformer UL CLASS 2 only!) \n"); printf(" 4) Baud rate too high \n"); printf(" 4) Autobaud not fully synchronized. \n"); printf(" 5) DSK_COMM.DSK or AUTOTEST.DSK not in directory \n"); printf(" 6) DSK is broken \n"); printf(" \n"); printf("NOTE: DSKL does not include a debugger kernal such as DSKD. \n"); printf(" You can load and execute a program, but no breakpoints or \n"); printf(" singlestep ability is provided. If you need to halt a \n"); printf(" program, use INT2 which is set by RS232 activity \n"); printf(" \n"); printf("[Q]uit Any other key for more "); if(toupper(getche()) == 'Q') { printf("\n\n>>>>>> DSKL is now in command mode\n"); return; } clrscr(); usage(); } void usage(void) { printf("DSKL: DOS Command line Usage \n"); printf(" \n"); printf("C:\DSKTOOLS\DSKL [A][Cx][Bxxxxx][I] \n"); printf(" | | | | \n"); printf(" | | | +--Inverse DTR (Reset logic) \n"); printf(" | | +---------Baud xxxxx (9600,19200,38400)\n"); printf(" | +-------------Initialy load to COM1, COM2 \n"); printf(" +-----------------Autotest \n"); printf(" \n"); printf("NOTE: \n"); printf(" \n"); printf(" Commport s will toggle every 8 initilization failures \n"); printf(" The baud rate will be halved every 16 initialization failures \n"); printf(" \n"); printf("Hit any key to continue "); getche(); printf("\n\n>>>>>> DSKL is now in command mode\n"); } void execute(int addr) { cxmit(SYNCH,port_no); cxmit(BRANCH,port_no); // Select PROG/DATA ixmit(addr,port_no); cxmit(SYNCH,port_no); } void dump(void) { int leng, i; unsigned int addr; delay(10); cxmit(0,port_no); //synch up with DSP cxmit(0,port_no); switch(toupper(getche())) { case 'D': cxmit(4,port_no); break; case 'P': cxmit(2,port_no); break; default : cxmit(0,port_no); printf("\nCOMMAND NOT RECOGNIZED\n"); return; } printf(" "); i = scanf("%x %x",&addr,&leng); if(i != 2) { printf("INPUT ERROR!\n"); cxmit(SYNCH,port_no); cxmit(SYNCH,port_no); cxmit(SYNCH,port_no); cxmit(SYNCH,port_no); } fflush(stdin); ixmit(addr,port_no); ixmit(leng-1,port_no); for(;leng>0;leng--) { if(!(addr & 0x7)) printf("\n%04x ",addr); printf("%04x ",ircv(port_no)); addr++; } cxmit(0,port_no); cxmit(0,port_no); printf("\n"); } void fill(void) { int leng, i; unsigned int addr,valu; delay(10); cxmit(0,port_no); //synch up with DSP cxmit(0,port_no); switch(toupper(getche())) { case 'D': cxmit(3,port_no); break; case 'P': cxmit(1,port_no); break; default : cxmit(0,port_no); printf("\nCOMMAND NOT RECOGNIZED\n"); return; } printf(" "); i = scanf("%x %x %x",&addr,&leng,&valu); if(i != 3) { printf("INPUT ERROR!\n"); cxmit(SYNCH,port_no); cxmit(SYNCH,port_no); cxmit(SYNCH,port_no); cxmit(SYNCH,port_no); } fflush(stdin); ixmit(addr,port_no); ixmit(leng-1,port_no); for(;leng>0;leng--) { ixmit(valu,port_no); } cxmit(0,port_no); cxmit(0,port_no); } /*********************************************************************/ /* unsigned int load_file(int arg, char *FILE) */ /* if arg = 0; DSK_COMM.DSK is bootloaded and verified (echo data) */ /* 1; INFILE.DSK is requested and loaded via DSK_COMM.DSK */ /* 2; FILE is loaded via DSK_COMM.DSK */ /* */ /* Returns the file ENTRY point */ /*********************************************************************/ unsigned int load_file(int arg, char *strg) { char fbuf[32]; unsigned int ENTRY, i, tries = 1, rate; strcpy(fbuf,"DSK_COMM.DSK"); i = 2 -((port_no-0x2f8) >> 8); switch(arg) { case 3: printf(" FILE TO BOOT >> "); strupr(gets(fbuf)); if(strstr(fbuf,".") == NULL) strcat(fbuf,".DSK"); arg = 0; case 0: while(d_buf[0] != 0x1111) { clrscr(); i = 2 -((port_no-0x2f8) >> 8); rate = 115200/baud; printf("[Q]uit exits program\n\n"); printf("%s >Boot:%d Com:%d Baud:%u\n",fbuf,tries++,i,rate); ENTRY = load_DSK(arg,fbuf); if(kbhit()) if(toupper(getch()) == 'Q') exit(0); d_buf[0] = 0x1111; write_data(0x70,1,d_buf); // write and verify a d_buf[0] = 0; // known value to the DSK read_data (0x70,1,d_buf); if(!(tries %8)) // if no success 1st try port_no ^= 0x100; // other port if(!(tries %16)) // still no success, lower baud *=2; // baud rate if(rate < 1200) baud = 3;// set lower baud limit } d_buf[0] = 0; write_data(0x70,1,d_buf); printf("%s Succesfully loaded\n",fbuf); baud = userbaud; break; case 1: printf(" FILE TO LOAD >> "); strupr(gets(fbuf)); if(strstr(fbuf,".") == NULL) strcat(fbuf,".DSK"); printf("Loading %s to DSK Com:%d\n",fbuf,i); ENTRY = load_DSK(arg,fbuf); break; case 2: arg = 1; strupr(strg); printf("Loading %s to DSK Com:%d\n",strg,i); ENTRY = load_DSK(arg,strg); break; default: break; } printf("Entry:%04x\n",ENTRY); printf("Hit >enter< to continue\n"); return(ENTRY); } /*********************************************************************/ /* unsigned int load_DSK(FILE *in_file, int pass) */ /* if pass = 0; in_file is loaded via the C26 bootloader */ /* pass = 1; in_file is loaded via DSK_COMM (must be loaded!) */ /* */ /* Returns file ENTRY point */ /*********************************************************************/ unsigned int load_DSK(int pass, char *filename) { FILE *in_file; char buf[512],*ptr; unsigned int i, ENTRY,load; int ADDR, CMD; int boot_csum, boot_len=0; if ((in_file = fopen(filename, "r")) == NULL) // Is file available? { printf("Could not open %s! Exiting program\n",filename); exit(0); } if(pass == 0) { initcom(port_no,baud); reset(port_no); } pass &=0x1; load = pass; fseek(in_file,0,SEEK_SET); // reset to first line fscanf(in_file,"%s",&buf); // Read first line if(buf[0] != 'K') { printf("Not a valid DSK file\n"); getch(); fclose(in_file); return(0); } for(;pass<2;pass++) { boot_csum= 0; fseek(in_file,0,SEEK_SET); // reset to first line fscanf(in_file,"%s",&buf); // Read first line if((pass==1) && !load) { boot_len--; ixmit((boot_len & 0x700)|0x8FF,port_no); // STATUS and BAUD_DTCT ixmit(((boot_len & 0xFF)<<8)|0x80,port_no);// LENGTH and INT boot_len=0; } while(!feof(in_file)) { fscanf(in_file,"%s\r\n",buf); // Read a line ptr = buf; switch(buf[0]) { case '1': ENTRY = read4(ptr); // 1=entry point break; case '9': ADDR = read4(ptr); // 9=address if(load) { while(buf[0] != '7') { if(buf[0] == 'M') CMD = DL_DATA; else { if(buf[0] == 'B') CMD = DL_PROG; else { printf("ERROR READING FILE\n"); exit(0); } } i = read4(ptr); cxmit(CMD,port_no); // Select PROG/DATA ixmit(ADDR++,port_no); // where to put it ixmit(0,port_no); // length 1 ixmit(i,port_no); // send the value printf("\r%d words",boot_len++); } } else /* boot */ { while(buf[0] != '7') { i = read4(ptr); if(pass==1) ixmit(i,port_no); printf("\r%d words",boot_len); boot_len++; boot_csum += i; } } break; case ':': break; default : printf("Error reading file\n"); ENTRY=0; break; } if(buf[0]==':') break; } if((pass==1) && !load) { ixmit(boot_csum,port_no); // CHECKSUM at EO 2nd pass cxmit(0xff,port_no); // same for synch } } printf("\n"); fclose(in_file); // close file when done return(ENTRY); } unsigned int read4(char *ptr) { char val[200], *nptr; unsigned int i; strcpy(val,"0x"); strcat(val,ptr+1); val[6] = 0; i = strtol(val,&nptr,16); strcpy(ptr,ptr+5); return(i); } /*********************************************************************/ /* write_data(int address, int length, int *data); */ /* if DSK_COMM is loaded, *data is transferred to the DSK */ /*********************************************************************/ void write_data(int addr, int length, int *data) { cxmit(DL_DATA,port_no); // Select DATA download to DSK ixmit(addr,port_no); // where to put it ixmit(length-1,port_no); // length for(;length>0;length--) // ixmit(*data++,port_no); // send the value } /*********************************************************************/ /* read_data(int address, int length, int *data); */ /* if DSK_COMM is loaded, *data is filled with data from the DSK */ /*********************************************************************/ void read_data(int addr, int length, int *data) { cxmit(UL_DATA,port_no); // Select DATA upload from DSK ixmit(addr,port_no); // where to get it ixmit(length-1,port_no); // length for(;length>0;length--) // *data++ = ircv(port_no); // receive the value } void initcom(int port_no,int baud) { asm mov DX,word ptr port_no // asm add DX,3 // asm mov AL,087h // SET BAUD access asm out DX,AL // asm sub DX,3 // asm mov AX,word ptr baud //LO// Set 19200 baud asm out DX,AL // asm add DX,1 // asm mov AL,byte ptr baud //HI// asm xchg AL,AH // asm out DX,AL // asm sub DX,1 // asm add DX,3 // asm mov AL,07h // CLR BAUD access... N-8-2 asm out DX,AL // asm out DX,AL // N-8-2 asm mov DX,word ptr port_no //0x3FC 0x2FC modem control register asm add DX,5 //check LINE_STATUS 0x2FD 0x3FD (+5) xempty0: // asm in AL,DX // asm and AL,060h //wait for DXR & TXR to empty before RST! asm cmp AL,060h // asm jne xempty0 // reset(port_no); } void reset(int port_no) { if(dtr_level) { DTR_lo(port_no); DTR_hi(port_no); DTR_lo(port_no); } else { DTR_hi(port_no); DTR_lo(port_no); DTR_hi(port_no); } } void DTR_lo(int port_no) { asm mov DX,word ptr port_no //modem control register 02FCh 03FCh asm add DX,4 // asm mov AL,0xA //RTS=1, DTR=0 asm out DX,AL // delay(1); } void DTR_hi(int port_no) { asm mov DX,word ptr port_no //modem control register asm add DX,4 // asm mov AL,0xB //RTS=1, DTR=0 asm out DX,AL // delay(1); } void ixmit(int i,int port_no) { cxmit(i,port_no); cxmit(i>>8,port_no); } unsigned int ircv(int port_no) { int i; i = crcv(port_no); i+= (crcv(port_no)<<8); return(i); } void cxmit(char c, int port_no) { asm mov DX,word ptr port_no // load base addr 0x2FD 0x3FD asm add DX,5 // check LINE_STATUS 0x2FD 0x3FD (+5) xempty: asm sub dx,5 // asm in AL,DX // reading RXR clears RCV bit asm add dx,5 // read status asm in AL,DX // asm and AL,061h // wait for all empty asm cmp AL,060h // asm jne xempty // asm sub DX,5 // asm mov AL,byte ptr c // asm out DX,AL // asm add DX,5 // check LINE_STATUS 0x2FD 0x3FD (+5) xempty2: // asm sub dx,5 // asm in AL,DX // reading RXR clears RCV bit asm add dx,5 // read status asm in AL,DX // asm and AL,061h // wait for DXR and XSR to empty asm cmp AL,060h // asm jne xempty2 // } unsigned char crcv(int port_no) { unsigned char c; int x,y; // cxmit(0,port_no); asm mov DX,word ptr port_no // load base addr 0x2FD 0x3FD asm add DX,5 // check LINE_STATUS 0x2FD 0x3FD (+5) xhempty: asm sub dx,5 // asm in AL,DX // reading RXR clears RCV bit asm add dx,5 // read status asm in AL,DX // asm and AL,061h // wait for all empty asm cmp AL,060h // asm jne xhempty // asm sub DX,5 // asm mov AL,0 // synch value asm out DX,AL // asm add DX,5 // check LINE_STATUS 0x2FD 0x3FD (+5) xhempty2: // asm sub dx,5 // asm in AL,DX // reading RXR clears RCV bit asm add dx,5 // read status asm in AL,DX // asm and AL,061h // wait for DXR and XSR to empty asm cmp AL,060h // asm jne xhempty2 // asm mov DX,word ptr port_no // RECV a character asm add DX,5 // check LINE_STATUS 0x2FD 0x3FD (+5) asm mov BX,10000 // 836 loops is marginal at 4800 baud. chkst: // with 33MHz 486 asm sub bx,1 // asm jz timerr // asm in AL,DX // asm and AL,061h // asm cmp AL,061h // asm jne chkst //wait for DRR & RSR to fill asm sub DX,5 // asm in AL,DX // asm mov byte ptr c,AL // return(c); timerr: /* // If a timeout occurs, a TIMEOUT message x = wherex(); // can be written to the screen. y = wherey(); // gotoxy(1,25); // printf(">>>>> RCV TIMEOUT:"); // Error MSG to bottom of screen gotoxy(x,y); // */ return(-1); } /***************************************************/ /* crcv2 does not perform a DSK xmit/rcv handshake */ /* be careful if you use this function! */ /***************************************************/ unsigned char crcv2(int port_no) { unsigned char c; int x,y; asm mov DX,word ptr port_no // RECV a character asm add DX,5 // check LINE_STATUS 0x2FD 0x3FD (+5) asm mov BX,10000 // 836 loops is marginal at 4800 baud. chkst: // with 33MHz 486 asm sub bx,1 // asm jz timerr2 // asm in AL,DX // asm and AL,061h // asm cmp AL,061h // asm jne chkst //wait for DRR & RSR to fill asm sub DX,5 // asm in AL,DX // asm mov byte ptr c,AL // timerr2: return(c); }