//file bgterm.c //win32 console app to talk to comm1 //Apr 3 2000 Bob G initial edit from disptst bobgardner@aol.com // Modified May 2 2004 by David Chai (dtc24) & Jian Gong (jg253) // to fit 476 Final Project -- MP3 Radio #include #include #include #include #include #include #include //--ascii chars--- #define ESC 0x1b #define CR 0x0d #if 0 //stuff cut from winbase.h // // Comm provider settable parameters. #define SP_PARITY ((DWORD)0x0001) #define SP_BAUD ((DWORD)0x0002) #define SP_DATABITS ((DWORD)0x0004) #define SP_STOPBITS ((DWORD)0x0008) #define SP_HANDSHAKING ((DWORD)0x0010) #define SP_PARITY_CHECK ((DWORD)0x0020) #define SP_RLSD ((DWORD)0x0040) // // Settable baud rates in the provider. #define BAUD_075 ((DWORD)0x00000001) #define BAUD_110 ((DWORD)0x00000002) #define BAUD_134_5 ((DWORD)0x00000004) #define BAUD_150 ((DWORD)0x00000008) #define BAUD_300 ((DWORD)0x00000010) #define BAUD_600 ((DWORD)0x00000020) #define BAUD_1200 ((DWORD)0x00000040) #define BAUD_1800 ((DWORD)0x00000080) #define BAUD_2400 ((DWORD)0x00000100) #define BAUD_4800 ((DWORD)0x00000200) #define BAUD_7200 ((DWORD)0x00000400) #define BAUD_9600 ((DWORD)0x00000800) #define BAUD_14400 ((DWORD)0x00001000) #define BAUD_19200 ((DWORD)0x00002000) #define BAUD_38400 ((DWORD)0x00004000) #define BAUD_56K ((DWORD)0x00008000) #define BAUD_128K ((DWORD)0x00010000) #define BAUD_115200 ((DWORD)0x00020000) #define BAUD_57600 ((DWORD)0x00040000) #define BAUD_USER ((DWORD)0x10000000) // // Settable Data Bits #define DATABITS_5 ((WORD)0x0001) #define DATABITS_6 ((WORD)0x0002) #define DATABITS_7 ((WORD)0x0004) #define DATABITS_8 ((WORD)0x0008) #define DATABITS_16 ((WORD)0x0010) #define DATABITS_16X ((WORD)0x0020) // // Settable Stop and Parity bits. #define STOPBITS_10 ((WORD)0x0001) #define STOPBITS_15 ((WORD)0x0002) #define STOPBITS_20 ((WORD)0x0004) #define PARITY_NONE ((WORD)0x0100) #define PARITY_ODD ((WORD)0x0200) #define PARITY_EVEN ((WORD)0x0400) #define PARITY_MARK ((WORD)0x0800) #define PARITY_SPACE ((WORD)0x1000) typedef struct _COMMPROP { WORD wPacketLength; WORD wPacketVersion; DWORD dwServiceMask; DWORD dwReserved1; DWORD dwMaxTxQueue; DWORD dwMaxRxQueue; DWORD dwMaxBaud; DWORD dwProvSubType; DWORD dwProvCapabilities; DWORD dwSettableParams; DWORD dwSettableBaud; WORD wSettableData; WORD wSettableStopParity; DWORD dwCurrentTxQueue; DWORD dwCurrentRxQueue; DWORD dwProvSpec1; DWORD dwProvSpec2; WCHAR wcProvChar[1]; } COMMPROP,*LPCOMMPROP; // // Set dwProvSpec1 to COMMPROP_INITIALIZED to indicate that wPacketLength // is valid before a call to GetCommProperties(). #define COMMPROP_INITIALIZED ((DWORD)0xE73CF52E) typedef struct _COMSTAT { DWORD fCtsHold : 1; DWORD fDsrHold : 1; DWORD fRlsdHold : 1; DWORD fXoffHold : 1; DWORD fXoffSent : 1; DWORD fEof : 1; DWORD fTxim : 1; DWORD fReserved : 25; DWORD cbInQue; DWORD cbOutQue; } COMSTAT, *LPCOMSTAT; // // DTR Control Flow Values. #define DTR_CONTROL_DISABLE 0x00 #define DTR_CONTROL_ENABLE 0x01 #define DTR_CONTROL_HANDSHAKE 0x02 // // RTS Control Flow Values #define RTS_CONTROL_DISABLE 0x00 #define RTS_CONTROL_ENABLE 0x01 #define RTS_CONTROL_HANDSHAKE 0x02 #define RTS_CONTROL_TOGGLE 0x03 typedef struct _DCB { DWORD DCBlength; /* sizeof(DCB) */ DWORD BaudRate; /* Baudrate at which running */ DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ DWORD fParity: 1; /* Enable parity checking */ DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ DWORD fDtrControl:2; /* DTR Flow control */ DWORD fDsrSensitivity:1; /* DSR Sensitivity */ DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ DWORD fInX: 1; /* Enable input X-ON/X-OFF */ DWORD fErrorChar: 1; /* Enable Err Replacement */ DWORD fNull: 1; /* Enable Null stripping */ DWORD fRtsControl:2; /* Rts Flow control */ DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ DWORD fDummy2:17; /* Reserved */ WORD wReserved; /* Not currently used */ WORD XonLim; /* Transmit X-ON threshold */ WORD XoffLim; /* Transmit X-OFF threshold */ BYTE ByteSize; /* Number of bits/byte, 4-8 */ BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ char XonChar; /* Tx and Rx X-ON character */ char XoffChar; /* Tx and Rx X-OFF character */ char ErrorChar; /* Error replacement char */ char EofChar; /* End of Input character */ char EvtChar; /* Received Event character */ WORD wReserved1; /* Fill for now. */ } DCB, *LPDCB; typedef struct _COMMTIMEOUTS { DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ } COMMTIMEOUTS,*LPCOMMTIMEOUTS; typedef struct _COMMCONFIG { DWORD dwSize; /* Size of the entire struct */ WORD wVersion; /* version of the structure */ WORD wReserved; /* alignment */ DCB dcb; /* device control block */ DWORD dwProviderSubType; /* ordinal value for identifying provider-defined data structure format*/ DWORD dwProviderOffset; /* Specifies the offset of provider specific data field in bytes from the start */ DWORD dwProviderSize; /* size of the provider-specific data field */ WCHAR wcProviderData[1]; /* provider-specific data */ } COMMCONFIG,*LPCOMMCONFIG; WINBASEAPI HANDLE WINAPI CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); WINBASEAPI BOOL WINAPI ReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped ); WINBASEAPI BOOL WINAPI ClearCommError( HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat ); WINBASEAPI BOOL WINAPI GetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize ); WINBASEAPI BOOL WINAPI GetCommMask( HANDLE hFile, LPDWORD lpEvtMask ); WINBASEAPI BOOL WINAPI GetCommProperties( HANDLE hFile, LPCOMMPROP lpCommProp ); WINBASEAPI BOOL WINAPI GetCommModemStatus( HANDLE hFile, LPDWORD lpModemStat ); WINBASEAPI BOOL WINAPI GetCommState( HANDLE hFile, LPDCB lpDCB ); WINBASEAPI BOOL WINAPI GetCommTimeouts( HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts ); WINBASEAPI BOOL WINAPI PurgeComm( HANDLE hFile, DWORD dwFlags ); WINBASEAPI BOOL WINAPI SetCommBreak( HANDLE hFile ); WINBASEAPI BOOL WINAPI SetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize ); WINBASEAPI BOOL WINAPI SetCommMask( HANDLE hFile, DWORD dwEvtMask ); WINBASEAPI BOOL WINAPI SetCommState( HANDLE hFile, LPDCB lpDCB ); WINBASEAPI BOOL WINAPI SetCommTimeouts( HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts ); WINBASEAPI BOOL WINAPI TransmitCommChar( HANDLE hFile, char cChar ); WINBASEAPI BOOL WINAPI WaitCommEvent( HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped ); #endif // MY STUFF #define PLAY 0x02 #define NEXT 0x04 #define PREV 0x05 #define PAUSE 0x03 #define RECEIVE_DONE 0x06 #define STOP 0x07 // functions void sendMP3(char[]); void controlStates(void); void initPlaylistInfo(void); // vars unsigned char received, endTrack, UDR, nextTrackIndex, prevTrackIndex, totalTracks, j; char tracks[100][50]; // assumption: songs on playlist doesn't exceed 100 char playlist_MP3[50]; char *currentTrack; char commandc; //----------globals------------ unsigned char c; unsigned char buf; unsigned char tmpstr[80]; int numread,numwritten; int echo; int delay; int newsg; int comm2; int comm3; int curcomm; int hexmode; BOOL fsuccess; DCB dcb; HANDLE hcom; HANDLE hwnd; COMSTAT comstat; COMMPROP commprop; COMMCONFIG cc; OVERLAPPED overlapped; //---------------------- void initvars(void){ //init some vars echo=0; hwnd=GetStdHandle(STD_OUTPUT_HANDLE); comm2=0; comm3=1; curcomm=3; hexmode=0; } //--------------------- int initcom1(void){ //init com1 to 9600,n,8,1 hcom=CreateFile("com1", GENERIC_READ | GENERIC_WRITE, 0, //EXCLUSIVE ACCESS NULL, //no security attributes OPEN_EXISTING, 0, //NOT OVERLAPPED NULL); if(hcom==INVALID_HANDLE_VALUE) { printf("createfile failed %d\n",GetLastError()); return(1); } fsuccess=GetCommState(hcom,&dcb); if(!fsuccess){ printf("getcommstate failed %d\n",GetLastError()); return(2); } dcb.BaudRate=CBR_56000; //dcb.BaudRate = CBR_115200; dcb.ByteSize=8; dcb.Parity=NOPARITY; dcb.StopBits=ONESTOPBIT; dcb.fDtrControl=DTR_CONTROL_DISABLE; dcb.fRtsControl=RTS_CONTROL_DISABLE; fsuccess=SetCommState(hcom,&dcb); if(!fsuccess){ printf("setcommstate failed %d\n",GetLastError()); return(3); } return(0); } //--------------------- int initcom2(void){ //init com2 to 9600,n,8,1 hcom=CreateFile("com2", GENERIC_READ | GENERIC_WRITE, 0, //EXCLUSIVE ACCESS NULL, //no security attributes OPEN_EXISTING, 0, //NOT OVERLAPPED NULL); if(hcom==INVALID_HANDLE_VALUE) { printf("createfile failed %d\n",GetLastError()); return(1); } fsuccess=GetCommState(hcom,&dcb); if(!fsuccess){ printf("getcommstate failed %d\n",GetLastError()); return(2); } dcb.BaudRate=CBR_9600; //CBR_38400; dcb.ByteSize=8; dcb.Parity=NOPARITY; dcb.StopBits=ONESTOPBIT; dcb.fDtrControl=DTR_CONTROL_DISABLE; dcb.fRtsControl=RTS_CONTROL_DISABLE; fsuccess=SetCommState(hcom,&dcb); if(!fsuccess){ printf("setcommstate failed %d\n",GetLastError()); return(3); } return(0); } //--------------------- int initcom3(void){ //init com3 to 9600,n,8,1 hcom=CreateFile("com3", GENERIC_READ | GENERIC_WRITE, 0, //EXCLUSIVE ACCESS NULL, //no security attributes OPEN_EXISTING, 0, //NOT OVERLAPPED NULL); if(hcom==INVALID_HANDLE_VALUE) { printf("createfile failed %d\n",GetLastError()); return(1); } fsuccess=GetCommState(hcom,&dcb); if(!fsuccess){ printf("getcommstate failed %d\n",GetLastError()); return(2); } dcb.BaudRate=CBR_38400; dcb.ByteSize=8; dcb.Parity=NOPARITY; dcb.StopBits=ONESTOPBIT; dcb.fDtrControl=DTR_CONTROL_DISABLE; dcb.fRtsControl=RTS_CONTROL_DISABLE; fsuccess=SetCommState(hcom,&dcb); if(!fsuccess){ printf("setcommstate failed %d\n",GetLastError()); return(3); } return(0); } //------------------ void selcomm2(void){ comm2=1; initcom2(); } //------------------ void selcomm3(void){ comm3=1; initcom3(); } //--------------------- int auxchk1(void){ //return true if char waiting in com1 unsigned long err; fsuccess=ClearCommError(hcom,&err,&comstat); if(!fsuccess){ printf("auxchk failed %d\n",GetLastError()); // return(1); } if(err) printf("auxchk err %d!\n",err); return (comstat.cbInQue !=0); } //--------------------- char auxin1(void){ //return c from com1 char buf; fsuccess=ReadFile(hcom,&buf,1,&numread,0 /*&overlapped*/ ); if(!fsuccess){ printf("readfile failed %d\n",GetLastError()); return(1); } return buf; } //--------------------- void auxout1(char c){ //write c to com1 char buf; buf=c; fsuccess=WriteFile(hcom,&buf,1,&numwritten, 0 /*&overlapped*/ ); if(!fsuccess){ printf("writefile failed %d\n",GetLastError()); // return(1); } // printf("\t%02x ",c); //debug } //--------------------- void auxstr(char *s){ //send s out aux char c; while((c= *s++)!=0){ auxout1(c); } } //------------------- void gotoxy(int x, int y){ //position cursor on crt COORD coord; coord.X=x; coord.Y=y; // SetConsoleCursorPostition(hwnd,coord); } //-------------------- void auxgotoxy(int x, int y){ //issue ansi cursor positioning sequence E[y;xH down rs232 to hc11 display //6 bytes auxout1(ESC); auxout1('['); sprintf(tmpstr,"%d",y); // printf("issued curpos row %d %s\n",y,tmpstr); auxstr(tmpstr); auxout1(';'); sprintf(tmpstr,"%d",x); auxstr(tmpstr); auxout1('H'); } //---------------------- void auxclrscr(void){ //clear hc11 screen auxout1(ESC); auxout1('['); auxout1('2'); auxout1('J'); } //--------------------- void term(void){ //terminal mode ctl-e to exit char c; printf("\nTerminal mode. ctl-e to exit\n"); while(1){ if(auxchk1()){ c=auxin1(); if(hexmode){ printf("%02x ",c); }else{ putch(c); } } if(kbhit()){ c=getch(); if(c==0x05) return; if(echo) putch(c); auxout1(c); if(c==CR) putch(0x0a); //send lf after cr } } } //--------------------- void mainmenu(void){ printf("\nbgterm cmds:\n"); printf(" t term mode\n"); printf(" h toggle hex mode\n"); printf(" q quit\n"); } //--------------------- void main(void){ //main program initvars(); initcom1(); initPlaylistInfo(); sendMP3(tracks[2]); while(1) { controlStates(); } } //--------------------- void sendMP3(char track[50]) { //unsigned char prevcommandc; unsigned char temp; unsigned char mp3c;//, prevc; // NOTE: must be signed for EOF to function properly, since EOF = -1 FILE *mp3; // declare a FILE pointer // set currentTrack currentTrack = track; sprintf(playlist_MP3, "playlist/%s", track); // %c -> %s printf("%s", playlist_MP3); mp3 = fopen(playlist_MP3, "rb"); if(mp3==NULL) { printf("Error: can't open file.\n"); return; } else { printf("\nFile opened successfully. Contents:\n\n"); received = 1; while(1) { mp3c = fgetc(mp3); if(endTrack == 0) { // check if something has been received // auxchk1 returns 1 when COM1 has received data if(auxchk1()) { commandc = auxin1(); // auxin1 gets the char from COM1 printf("%02x", commandc); if(commandc == NEXT || commandc == PREV || commandc == STOP) endTrack = 1; else if(commandc == PAUSE) { // infinite pause loop while(1) { if(auxchk1()) { commandc = auxin1(); if((commandc == PLAY) || (commandc == PAUSE)) break; // break infinite pause loop } } } } // end auxchk1 auxout1(mp3c); received = 0; } else { printf("eof? %c %02x", mp3c, mp3c); break; //...break when EOF is reached } } printf("\nMP3 closed...\n"); fclose(mp3); return; } } void initPlaylistInfo(void) { DIR * dir_ptr; struct dirent * dir_ent; dir_ptr = opendir("playlist"); if (dir_ptr == NULL) perror("Error: cannot open directory"); j = 0; do { dir_ent = readdir(dir_ptr); if (dir_ent) { //printf("%s\n",dir_ent->d_name); sprintf(tracks[j], "%s", dir_ent->d_name); // %c -> %s printf("%i. %s\n", j, tracks[j]); j++; } } while (dir_ent); totalTracks = j; nextTrackIndex = 3; prevTrackIndex = (totalTracks-1); closedir(dir_ptr); } // DETERMINE WHICH TRACK TO PLAY void controlStates(void) { int i; if(endTrack == 1) { switch(commandc) { case NEXT: endTrack = 0; sendMP3(tracks[nextTrackIndex]); if(++nextTrackIndex == totalTracks) nextTrackIndex = 2; if(++prevTrackIndex == totalTracks) prevTrackIndex = 2; break; case PREV: endTrack = 0; sendMP3(tracks[prevTrackIndex]); if(prevTrackIndex-- == 2) prevTrackIndex = (totalTracks-1); if(nextTrackIndex-- == 2) nextTrackIndex = (totalTracks-1); break; if(auxchk1()) { commandc = auxin1(); if(commandc == NEXT || commandc == PREV || commandc == PLAY) break; } } break; case PLAY: endTrack = 0; sendMP3(currentTrack); } } else { // else send NEXT Track <---------- may never be reached if EOF doesn't work sendMP3(tracks[nextTrackIndex]); if(++nextTrackIndex == totalTracks) nextTrackIndex = 2; if(++prevTrackIndex == totalTracks) prevTrackIndex = 2; printf("\nNEXT TRACK SENT!!!\n"); } printf("\n%c\n", commandc); }