/************************************************************************/ /* Copyright 2001 MBARI */ /************************************************************************/ /* Summary : Serial I/O routines for SOON Data Logger and Controller */ /* Filename : serial.c */ /* Author : Robert Herlien (rah) */ /* Project : SOON (Son of OASIS - Now!) Data Logger and Controller */ /* Version : 0.1 */ /* Created : 09/28/2001 rah */ /* Note - View this and all source files with a tab-width of 8! */ /************************************************************************/ /* This module implements access to the auxiliary serial ports. That */ /* is, all serial ports except the main user port, which is accessed */ /* via the TT8 Serxxx routines. The auxiliary serial ports are accessed*/ /* via the following sserxxx routines (note lower-case 's'), and the */ /* serial port channels are numbered 0 to 4. Channel 0 is the second */ /* serial port of the motherboard, while ports 1 to 4 are the 4 serial */ /* ports on the quad serial adapter. */ /************************************************************************/ /* Modification History: */ /* 28sep2001 rah - created */ /* 14Nov2001 dc - added function sserPutBuf */ /* 21Dec2004 Luke Coletti - Expanded/Adapted for use with LOBO logger */ /************************************************************************/ /* Tattle-8 Include Files */ #include /* Tattletale Model 8 Definitions */ #include /* 68332 Tattletale (7,8) Hardware Definitions */ #include /* 68332 Time Processing Unit Definitions */ #include /* definitions and prototypes for Model 8 library */ /* Aztec C Include Files */ #include #include #include /* MBARI Include Files */ #include "mbariTyp.h" /* MBARI type definitions */ //#include "mbariCon.h" /* MBARI constants */ #include "lobo.h" /********************************/ /* Module Local Data */ /********************************/ typedef short int Errno; /* Error number return code */ typedef struct { int inchan; int outchan; MBool isOpen; } SerChanDesc; MLocal SerChanDesc serChans[NUM_CHANS] = { {14, 13, FALSE}, {1, 0, FALSE}, {3, 2, FALSE}, {5, 4, FALSE}, {7, 6, FALSE}, {9, 8, FALSE}, {11, 10, FALSE} }; /* Buffers declared separately from SerChanDesc so we don't need to */ /* include the space in initialized data (Flash memory) */ MLocal char inBufs[NUM_CHANS][INBUFSIZE + TSER_MIN_MEM]; MLocal char outBufs[NUM_CHANS][OUTBUFSIZE + TSER_MIN_MEM]; MLocal char serBuf[SER_BUFLEN]; /************************************************************************/ /* Function : tserIsOpen */ /* Purpose : Test port state */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Errno tserIsOpen( Nat16 chan ) { if ( chan >= NUM_CHANS ) return( ERROR ); if ( serChans[chan].isOpen ) return( TRUE ); else return( FALSE ); } /* tserIsOpen */ /************************************************************************/ /* Function : tserGetTpuChs */ /* Purpose : Get TPU channels assoicated with Lobo Data Channel */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Errno tserGetTpuChs( Nat16 chan, Nat16 *rx_ch, Nat16 *tx_ch ) { if ( chan >= NUM_CHANS ) return( ERROR ); if ( serChans[chan].isOpen ){ *rx_ch = serChans[chan].outchan; *tx_ch = serChans[chan].outchan; return ( TRUE ); } else return( FALSE ); } /* tserGetTpuChs */ /************************************************************************/ /* Function : tserClose */ /* Purpose : Close a serial port */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Errno tserClose( Nat16 chan ) { if ( chan >= NUM_CHANS ) return( ERROR ); if ( serChans[chan].isOpen ) { TSerClose( serChans[chan].inchan ); TSerClose( serChans[chan].outchan ); } serChans[chan].isOpen = FALSE; return( OK ); } /* tserClose() */ /************************************************************************/ /* Function : tserOpen */ /* Purpose : Open a serial port */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Errno tserOpen( Nat16 chan, Int32 baud, Int16 parity, Int16 databits, Int16 stopbits ) { if ( chan >= NUM_CHANS ) return( ERROR ); if ( serChans[chan].isOpen ) tserClose( chan ); memset( inBufs[chan], 0, (size_t)(INBUFSIZE + TSER_MIN_MEM) ); memset( outBufs[chan], 0, (size_t)(OUTBUFSIZE + TSER_MIN_MEM) ); if ( TSerOpen(serChans[chan].inchan, MiddlePrior, INP, inBufs[chan], (long)INBUFSIZE, baud, parity, databits, stopbits) != tsOK ) return( ERROR ); if ( TSerOpen(serChans[chan].outchan, MiddlePrior, OUTP, outBufs[chan], (long)OUTBUFSIZE, baud, parity, databits, stopbits) != tsOK ) { TSerClose( serChans[chan].inchan ); return( ERROR ); } TSerInFlush(serChans[chan].inchan); serChans[chan].isOpen = TRUE; return( OK ); } /* tserOpen() */ /************************************************************************/ /* Function : tserInit */ /* Purpose : Initialize serial ports */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Errno tserInit( Void ) { Reg Nat16 i; for ( i = 0; i < NUM_CHANS; i++ ) if ( tserOpen(i, (Int32)DEFAULT_BAUD, DEFAULT_PARITY, DEFAULT_DATABITS, DEFAULT_STOPBITS) != OK ) return( ERROR ); return( OK ); } /* tserInit() */ /************************************************************************/ /* Function : tserPwrUp */ /* Purpose : Set Serial routines for powered operation */ /* Inputs : None */ /* Outputs : OK */ /************************************************************************/ Errno tserPwrUp( Void ) { return( tserInit() ); } /* tserPwrUp() */ /************************************************************************/ /* Function : tserPwrDown */ /* Purpose : Set Serial routines for power down (low power) */ /* Inputs : None */ /* Outputs : OK */ /************************************************************************/ Errno tserPwrDown( Void ) { Reg Nat16 i; Set_K1_K8_State( (RdLatch1() & 0xFF00) ); //open any closed relays Sleep(0); Sleep( TICKS_PER_SECOND ); for ( i = 0; i < NUM_CHANS; i++ ) tserClose( i ); return( OK ); } /* tserPwrDown() */ /************************************************************************/ /* Function : tserSetBaud */ /* Purpose : Set Baud rate for serial channel */ /* Inputs : Channel number, baud rate */ /* Outputs : Actual baud rate set, or -1L if error */ /************************************************************************/ Int32 tserSetBaud( Nat16 chan, Int32 baud ) { if ( chan >= NUM_CHANS ) return( -1L ); TSerResetBaud( serChans[chan].inchan, baud ); return( TSerResetBaud(serChans[chan].outchan, baud) ); } /* tserSetBaud() */ /************************************************************************/ /* Function : tserInFlush */ /* Purpose : Flush input queue for serial channel */ /* Inputs : Channel number */ /* Outputs : OK, or ERROR if bad channel number */ /************************************************************************/ Errno tserInFlush( Nat16 chan ) { if ( chan >= NUM_CHANS ) return( ERROR ); TSerInFlush( serChans[chan].inchan ); return( OK ); } /* tserInFlush() */ /************************************************************************/ /* Function : tserGetParity */ /* Purpose : Get Parity Value from configured TPU UART */ /* Inputs : TPU Channel Number [0-15] */ /* Outputs : Parity Value or ERROR */ /************************************************************************/ Int16 tserGetParity( Nat16 tpuch ) { Int16 ret, val; Nat16 HSQVAL; if( tpuch <= 15 ){ if( tpuch <= 7 ){ HSQVAL = GetCPURegData((ulong)HSQR1); ret = (HSQVAL & (0x0003 << tpuch*2)) >> tpuch*2; } else{ HSQVAL = GetCPURegData((ulong)HSQR0); ret = (HSQVAL & (0x0003 << (tpuch-8)*2)) >> (tpuch-8)*2; } if( ret == 0x0000 ) ret = 'N'; else if( ret == 0x0001 ) ret = 'N'; else if( ret == 0x0002 ) ret = 'E'; else if( ret == 0x0003 ) ret = 'O'; else ret = ERROR; } else ret = ERROR; return( ret ); } /* tserGetParity */ /************************************************************************/ /* Function : tserGetPriority */ /* Purpose : Get TPU Priority Value from configured TPU UART */ /* Inputs : TPU Channel Number [0-15] */ /* Outputs : TPU Priority Value or ERROR */ /************************************************************************/ Int16 tserGetPriority( Nat16 tpuch ) { Int16 ret; Nat16 CPRVAL; if( tpuch <= 15 ){ if( tpuch <= 7 ){ CPRVAL = GetCPURegData((ulong)CPR1); ret = (CPRVAL & (0x0003 << tpuch*2)) >> tpuch*2; } else{ CPRVAL = GetCPURegData((ulong)CPR0); ret = (CPRVAL & (0x0003 << (tpuch-8)*2)) >> (tpuch-8)*2; } if( ret == 0x0000 ) ret = Disabled; else if( ret == 0x0001 ) ret = LowPrior; else if( ret == 0x0002 ) ret = MiddlePrior; else if( ret == 0x0003 ) ret = HighPrior; else ret = ERROR; } else ret = ERROR; return( ret ); } /* tserGetParity */ /************************************************************************/ /* Function : tserBreak */ /* Purpose : Put Output Port of Channel into BREAK State for n ticks*/ /* Inputs : Channel number, ticks to assert */ /* Outputs : OK or ERROR */ /************************************************************************/ Int16 tserBreak( Nat16 chan, Nat32 ticks ) { Nat32 tcr1_clock, match_rate; Int32 baud_sav; Int16 tpuch, ret; Int16 bits_sav, parity_sav, priority_sav; if ( chan >= NUM_CHANS ) return( ERROR ); if( tserIsOpen( chan ) == FALSE ) return( ERROR ); tpuch = serChans[chan].outchan; if( (parity_sav = tserGetParity(tpuch)) == ERROR) return( ERROR ); if( (priority_sav = tserGetPriority(tpuch)) == ERROR) return( ERROR ); // TPU UART Trnasmitter can only generate 1 STOP bit, so don't worry about saving that tcr1_clock = TPUGetTCR1(); match_rate = PRAM[tpuch][1]; baud_sav = tcr1_clock / match_rate; bits_sav = PRAM[tpuch][3]; //printf("Baud Rate = %ld\n", baud_sav); //printf("Data Bits = %d\n", bits_sav); //printf("Parity = %c\n", (char)parity_sav); //printf("Priority = %d\n", priority_sav); TSerClose( tpuch ); TPUSetPin(tpuch, CLR); Sleep(0); Sleep(ticks); memset( outBufs[chan], 0, (size_t)(OUTBUFSIZE + TSER_MIN_MEM) ); ret = TSerOpen(tpuch, priority_sav, OUTP, outBufs[chan], (long)OUTBUFSIZE, baud_sav, parity_sav, bits_sav, TPU_TXD_STOPBITS); if( ret != tsOK ){ TSerClose( serChans[chan].inchan ); serChans[chan].isOpen = FALSE; printf("\nERROR in tserBreak() ret = %d\n", ret); return( ERROR ); } return( OK ); } /* tserBreak() */ /************************************************************************/ /* Function : tserPutc */ /* Purpose : Do a putc to a serial channel */ /* Inputs : Channel number, character */ /* Outputs : OK, or ERROR if bad channel number */ /************************************************************************/ Errno tserPutc( Nat16 chan, Int16 c ) { if ( chan >= NUM_CHANS ) return( ERROR ); TSerPutByte(serChans[chan].outchan, c); return( OK ); } /* tserPutc() */ /************************************************************************/ /* Function : tserPuts */ /* Purpose : Do a puts to a serial channel */ /* Inputs : Channel number, string */ /* Outputs : OK, or ERROR if bad channel number */ /************************************************************************/ Errno tserPuts( Nat16 chan, char *str ) { Reg Nat16 tchan; if ( chan >= NUM_CHANS ) return( ERROR ); tchan = serChans[chan].outchan; while (*str) { if (*str == '\n') TSerPutByte(tchan, '\r'); TSerPutByte(tchan, *str++); } return( OK ); } /* tserPuts() */ /************************************************************************/ /* Function : tserPutBuf */ /* Purpose : put a byte to a serial channel */ /* Inputs : Channel number, character */ /* Outputs : OK, or ERROR if bad channel number */ /************************************************************************/ Errno tserPutBuf( Nat16 chan, Char *Buf, Nat16 length ) { Nat16 i = 0; if ( chan >= NUM_CHANS ) return( ERROR ); for( i = 0; i < length; i++){ TSerPutByte(serChans[chan].outchan, *Buf++); } return( OK ); } /* tserPutBuf() */ /************************************************************************/ /* Function : tserPrintf */ /* Purpose : Do a printf to a serial channel */ /* Inputs : Channel number, format string, args */ /* Outputs : OK, or ERROR if bad channel number */ /************************************************************************/ Errno tserPrintf( Nat16 chan, char *str, ... ) { va_list ap; va_start(ap, str); vsprintf(serBuf, str, ap); va_end(ap); return( tserPuts(chan, serBuf) ); } /* tserPrintf() */ /************************************************************************/ /* Function : tserGetc */ /* Purpose : Do a getc to a serial channel */ /* Inputs : Channel number */ /* Outputs : Serial character or ERROR if bad channel number */ /* Comment : Waits for next byte if none available */ /************************************************************************/ Int16 tserGetc( Nat16 chan ) { if ( chan >= NUM_CHANS ) return( ERROR ); return( TSerGetByte(serChans[chan].inchan) ); } /* tserGetc() */ /************************************************************************/ /* Function : tserGetcTmoutTicks */ /* Purpose : Do a getc to a serial channel with timeout */ /* Inputs : Channel number, ticks to wait */ /* Outputs : Serial character or ERROR if timeout or bad channel number*/ /************************************************************************/ Int16 tserGetcTmoutTicks( Nat16 chan, Nat32 ticks ) { Reg Int16 tchan; if ( chan >= NUM_CHANS ) return( ERROR ); tchan = serChans[chan].inchan; StopWatchStart(); while( StopWatchTime() < ((1000000L/TICKS_PER_SECOND) * ticks) ) if ( TSerByteAvail(tchan) ) return( TSerGetByte(tchan) ); return( ERROR ); } /* tserGetcTmoutTicks() */ /************************************************************************/ /* Function : tserGetcTmout */ /* Purpose : Do a getc to a serial channel with timeout */ /* Inputs : Channel number, seconds to wait */ /* Outputs : Serial character or ERROR if timeout or bad channel number*/ /************************************************************************/ Int16 tserGetcTmout( Nat16 chan, Nat16 seconds ) { return( tserGetcTmoutTicks(chan, (Nat32)seconds * TICKS_PER_SECOND) ); } /* tserGetcTmout() */ /************************************************************************/ /* Function : tserGetsTmout */ /* Purpose : Do a gets to a serial channel with timeout */ /* Inputs : Channel number, buffer to fill, buffer len, timeout (secs)*/ /* Outputs : Number of characters in buffer */ /************************************************************************/ Nat16 tserGetsTmout( Nat16 chan, char *buf, Nat16 buflen, Nat16 seconds ) { Reg Int16 tchan, c; Reg Nat16 nchars; if ( chan >= NUM_CHANS ) return( 0 ); tchan = serChans[chan].inchan; StopWatchStart(); nchars = 0; buf[0] = '\0'; while( StopWatchTime() < (1000000L * seconds) ) if ( TSerByteAvail(tchan) ) switch( c = TSerGetByte(tchan) ) { case '\n': case '\r': if(nchars > 0) return( nchars ); else break; default: buf[nchars++] = (Byte)c; buf[nchars] = '\0'; if ( nchars >= (buflen-1) ) return( nchars ); break; } return( nchars ); } /* tserGetcTmout() */ /************************************************************************/ /* Function : tserGetnTmout */ /* Purpose : Get exactly N characters with a timeout */ /* Inputs : Channel number, seconds to wait */ /* Outputs : Number characters read (0 if no chars before timeout) */ /************************************************************************/ Nat16 tserGetnTmout( Nat16 chan, char *s, Nat16 len, Nat16 seconds ) { Reg Int16 tchan; Reg Nat16 nchars; if ( chan >= NUM_CHANS ) return( 0 ); tchan = serChans[chan].inchan; StopWatchStart(); for( nchars = 0; (nchars < len) && (StopWatchTime() < (1000000L * seconds)); ) if ( TSerByteAvail(tchan) ) s[nchars++] = TSerGetByte(tchan); return( nchars ); } /* tserGetnTmout() */