//************************************************************************************************** // CmdGnuCapDC.cpp * // ----------------- * // Started : 2008-01-29 * // Last Update : 2016-03-28 * // Copyright : (C) 2008-2016 MSWaters * //************************************************************************************************** //************************************************************************************************** // * // This program is free software; you can redistribute it and/or modify it under the * // terms of the GNU General Public License as published by the Free Software Foundation; * // either version 3 of the License, or (at your option) any later version. * // * //************************************************************************************************** #include "CmdGnuCapDC.hpp" //************************************************************************************************** // Constructor. CmdGnuCapDC::CmdGnuCapDC( void ) { bSetDefaults( ); } //************************************************************************************************** // Destructor. CmdGnuCapDC::~CmdGnuCapDC( ) { } //************************************************************************************************** // Check that the object attributes are valid. // // Return Values : // true - Success // false - Failure bool CmdGnuCapDC::bValidate( void ) { double df1, df2, df3; CmdBase::bValidate( ); // Check the sweep start and stop values if( ! CnvtType::bStrToFlt( m_osStart, &df1 ) ) SetErrMsg( wxT("Invalid sweep start value.") ); if( ! CnvtType::bStrToFlt( m_osStop, &df2 ) ) SetErrMsg( wxT("Invalid sweep stop value.") ); // Check the sweep step value and sweep scale if( ! CnvtType::bStrToFlt( m_osStep, &df3 ) ) SetErrMsg( wxT("Invalid sweep step value.") ); if( df3 == 0.0 ) SetErrMsg( wxT("Step value equal to zero.") ); switch( m_eScale ) { case eSCALE_LIN : if( df1!=df2 && df3>fabs( df2 - df1 ) ) SetErrMsg( wxT("Step value is greater than sweep range.") ); break; case eSCALE_LOG : if( df1!=df2 && df3==1.0 ) SetErrMsg( wxT("Invalid step multiplier, must be non-unity.") ); break; case eSCALE_DEC : break; default : SetErrMsg( wxT("Invalid step scale value.") ); } // Check the component to be used as the sweep source // (21/04/2011) ??? A sweep source isn't compulsory for a GNU-Cap DC sweep if( m_osSource == wxT("None") ) SetErrMsg( wxT("No source component has been selected.") ); // Set the analysis temperature if( ! CnvtType::bStrToFlt( m_osTempC, &df3 ) ) SetErrMsg( wxT("Invalid analysis temperature value.") ); return( bIsValid( ) ); } //************************************************************************************************** // Set the object attributes to they're default values. // // Return Values : // true - Success // false - Failure bool CmdGnuCapDC::bSetDefaults( void ) { CmdBase::bSetDefaults( ); m_eSimEng = eSIMR_GNUCAP; m_eCmdType = eCMD_DC; m_osStart = wxT("0.0"); m_osStop = wxT("100.0"); m_osStep = wxT("10.0"); m_osSource = wxT("None"); m_eScale = eSCALE_LIN; m_osTempC = wxT("0.0"); return( true ); } //************************************************************************************************** // Parse the command string. // // Eg.s : .DC Vin 0.00 100.00m BY 10.00m TE 27.00 BASIC // .DC Vin 0.00 100.00m TI 1.01 TE 27.00 BASIC // .DC Vin 0.00 100.00m DE 100 TE 27.00 BASIC // // Return Values : // true - Success // false - Failure bool CmdGnuCapDC::bParse( void ) { wxStringTokenizer ostk1; wxString os1; double df1; int i1; // Clear the object attributes os1 = (wxString &) *this; bSetDefaults( ); assign( os1 ); // Tokenize the command string ostk1.SetString( *this ); i1 = ostk1.CountTokens( ); if( i1!=6 && i1!=9 ) return( bValidate( ) ); // Check command type os1 = ostk1.GetNextToken( ).Left( 3 ).Upper( ); if( os1 != wxT(".DC") ) return( bValidate( ) ); // Extract the sweep source label m_osSource = ostk1.GetNextToken( ); if( m_osSource.IsEmpty( ) ) return( bValidate( ) ); // Extract the start value os1 = ostk1.GetNextToken( ); if( CnvtType::bStrToFlt( os1, &df1 ) ) m_osStart = os1; else return( bValidate( ) ); // Extract the stop voltage os1 = ostk1.GetNextToken( ); if( CnvtType::bStrToFlt( os1, &df1 ) ) m_osStop = os1; else return( bValidate( ) ); // Extract the sweep type: linear, log or steps per decade os1 = ostk1.GetNextToken( ); os1.MakeUpper( ); if( os1 == wxT("BY") ) m_eScale = eSCALE_LIN; else if( os1 == wxT("TI") ) m_eScale = eSCALE_LOG; else if( os1 == wxT("DE") ) m_eScale = eSCALE_DEC; else return( bValidate( ) ); // Extract the step size/count os1 = ostk1.GetNextToken( ); if( os1.GetChar( 0 ) == wxT('-') ) os1 = os1.Mid( 1 ); if( CnvtType::bStrToFlt( os1, &df1 ) ) m_osStep = os1; else return( bValidate( ) ); // Extract the analysis temperature os1 = ostk1.GetNextToken( ); if( os1.Upper( ) == wxT("TE") ) { os1 = ostk1.GetNextToken( ); if( CnvtType::bStrToFlt( os1, &df1 ) ) m_osTempC = os1; else return( bValidate( ) ); } // Check that the last field is "BASIC" if( ostk1.GetNextToken( ).Upper( ) != wxT("BASIC") ) return( bValidate( ) ); return( bValidate( ) ); } //************************************************************************************************** // Format the command string. // // Return Values : // true - Success // false - Failure bool CmdGnuCapDC::bFormat( void ) { wxString osCmd; double df1, df2; // Set the command name osCmd = wxT(".DC"); // Set signal source osCmd << wxT(' ') << m_osSource; // Set sweep parameters osCmd << wxT(' ') << m_osStart; osCmd << wxT(' ') << m_osStop; switch( m_eScale ) { case eSCALE_LIN : osCmd << wxT(" BY"); break; case eSCALE_LOG : osCmd << wxT(" TI"); break; case eSCALE_DEC : osCmd << wxT(" DE"); break; default : break; } osCmd << wxT(' '); if( m_eScale == eSCALE_LIN ) if( CnvtType::bStrToFlt( m_osStart, &df1 ) && CnvtType::bStrToFlt( m_osStop, &df2 ) ) if( df1 > df2 ) osCmd << wxT('-'); osCmd << m_osStep; // Set analysis temperature osCmd << wxT(" TE ") << m_osTempC; // Append format modifier osCmd << wxT(" BASIC"); assign( osCmd ); return( bValidate( ) ); } //************************************************************************************************** // Copy the contents of a CmdNgSpiceDC object. // // Argument List : // roCmdDC - A reference to a CmdNgSpiceDC object // // Return Values : // A reference to this object CmdGnuCapDC & CmdGnuCapDC::operator = ( const CmdNgSpiceDC & roCmdDC ) { (CmdBase &) *this = (CmdBase &) roCmdDC; m_osStart = roCmdDC.m_osStart; m_osStop = roCmdDC.m_osStop; m_osStep = roCmdDC.m_osStep; m_osSource = roCmdDC.m_osSource; bFormat( ); return( *this ); } //************************************************************************************************** // Print the object attributes. // // Argument List : // rosPrefix - A prefix to every line displayed (usually just spaces) void CmdGnuCapDC::Print( const wxString & rosPrefix ) { CmdBase::Print( rosPrefix + wxT("CmdBase::") ); std::cout << rosPrefix.mb_str( ) << "m_osStart : " << m_osStart .mb_str( ) << '\n'; std::cout << rosPrefix.mb_str( ) << "m_osStop : " << m_osStop .mb_str( ) << '\n'; std::cout << rosPrefix.mb_str( ) << "m_osStep : " << m_osStep .mb_str( ) << '\n'; std::cout << rosPrefix.mb_str( ) << "m_osSource : " << m_osSource.mb_str( ) << '\n'; std::cout << rosPrefix.mb_str( ) << "m_eScale : "; switch( m_eScale ) { case eSCALE_LIN : std::cout << "eSCALE_LIN\n"; break; case eSCALE_LOG : std::cout << "eSCALE_LOG\n"; break; case eSCALE_DEC : std::cout << "eSCALE_DEC\n"; break; case eSCALE_OCT : std::cout << "eSCALE_OCT\n"; break; case eSCALE_NONE : std::cout << "eSCALE_NONE\n"; break; default : std::cout << "Invalid\n"; break; } std::cout << rosPrefix.mb_str( ) << "m_osTempC : " << m_osTempC .mb_str( ) << '\n'; } //************************************************************************************************** // Test Utility * //************************************************************************************************** #ifdef TEST_CMDGNUCAPDC using namespace std; // Function prototypes void Usage( char * psAppName ); //************************************************************************************************** int main( int argc, char * argv[ ] ) { wxString osCmd; wxString os1; // Validate the argument count passed to the application if( argc > 2 ) { Usage( argv[ 0 ] ); exit( EXIT_FAILURE ); } // Process the command line arguments os1 = wxConvLibc.cMB2WC( argv[ 1 ] ); if( argc > 1 ) { if( os1 == wxT("-h") ) { Usage( argv[ 0 ] ); exit( EXIT_SUCCESS ); } else { Usage( argv[ 0 ] ); exit( EXIT_FAILURE ); } } // Display the utility banner cout << "\n Class CmdGnuCapDC Test Utility" << "\n Version 1.04 (12/08/2011)\n"; // Create a GNU-CAP DC command object CmdGnuCapDC tCmd_DC; // Use the following command example to check the formatter and the parser : osCmd = wxT(".DC Vin 0.00 100.00m TI 10.00m TE 27.00 BASIC"); // Set things up for a formatter test tCmd_DC.m_osStart = wxT("0.00"); tCmd_DC.m_osStop = wxT("100.00m"); tCmd_DC.m_osStep = wxT("10.00m"); tCmd_DC.m_osSource = wxT("Vin"); tCmd_DC.m_eScale = eSCALE_LOG; tCmd_DC.m_osTempC = wxT("27.00"); cout << "\nRun Formatter : " << ( tCmd_DC.bFormat( ) ? "OK" : "FAULT" ); cout << "\nTest Cmd Format : " << ( tCmd_DC == osCmd ? "OK" : "FAULT" ); cout << "\nExample Command : " << osCmd .mb_str( ); cout << "\ntCmd_DC Contents : " << tCmd_DC.mb_str( ) << '\n'; // Set things up for a parser test tCmd_DC.bSetString( osCmd ); cout << "\nRun Parser : " << ( tCmd_DC.bParse( ) ? "OK" : "FAULT" ); tCmd_DC.bFormat( ); cout << "\nTest Cmd Format : " << ( tCmd_DC == osCmd ? "OK" : "FAULT" ); cout << "\nExample Command : " << osCmd .mb_str( ); cout << "\ntCmd_DC Contents : " << tCmd_DC.mb_str( ) << '\n'; cout << '\n'; exit( EXIT_SUCCESS ); } //************************************************************************************************** void Usage( char * psAppName ) { cout << "\nUsage : " << psAppName << " [-OPTIONS]" << "\nOptions :" << "\n -h : Print usage (this message)\n"; } #endif // TEST_CMDGNUCAPDC //**************************************************************************************************