#define VERSION "V22" /* WSPR / RTTY/ CW Transmitter AD9850. History: V2.2 10/6/18 .. DDS_OSET 160 was 110 .. CW trans missions always 5watts .. CW sked times increased to 33-39 past the hour V2.1 09/06/17, 12/8/17, 10/6/18 .. new DDS module Lost last version, added version number to CW message, changed locator to Cala en porter V1.1 6/10/14 .. Change DDS_OSET to 1250Hz(was 250Hz) done .. add 1200z to Sked list and remove 1400z -done .. change CW start from hh:32 to hh:33 upto 38 - done .. CW, do 2 cycles @5Watts and 2 @3Watts - see above Pin data D0 GPS data A0 D1 Tx A1 D2 A2 D3 A3 D4 A4 D5 RF Pwr A5 D6 A6 Thermo D7 A7 Baro D8 Data D9 Load D10 Clock D11 D12 D13 LED */ // DDS Reference Oscilliator Frequency, in Hz. (Remember, the PLL). #define DDS_REF 125000000 // 1Hz == 32.8 tunning steps #define DDS_OSET 160 //was 110 DDS #define RTTY_SHIFT 170 /* Band Dial freq (MHz) Tx freq (MHz) 160m 1.836600 1.838000 - 1.838200 80m 3.592600 3.594000 - 3.594200 60m 5.287200 5.288600 - 5.288800 40m 7.038600 7.040000 - 7.040200 30m 10.138700 10.140100 - 10.140300 20m 14.095600 14.097000 - 14.097200 17m 18.104600 18.106000 - 18.106200 15m 21.094600 21.096000 - 21.096200 12m 24.924600 24.926000 - 24.926200 10m 28.124600 28.126000 - 28.126200 6m 50.293000 50.294400 - 50.294600 2m 144.488500 144.489900 - 144.490100 RTTY 20m 14080 - 14100kHz 45/50 bauds with a 170 Hz 14,000-14,060 kHz 200 Hz Telegraphy - contest preferred 14,055 kHz QRS (slow telegraphy Centre of Activity 14,060-14,070 200 Hz Telegraphy 14,060 kHz QRP (low power) Centre of Activity 14,070-14,089 500 Hz Narrow band modes 14,089-14,099 500 Hz Narrow band modes - automatically controlled data stations (unattended) to add :-WSPR_TXF = (WSPR_TX_A+DDS_OSET) + random(10, 190); // always choose a frequency, it mixes it all up a little with the pRNG. */ // WSPR Output Frequency #define WSPR_TX_A 10.140100e6 // this is the bottom of the 30m band. The station moves about. #define WSPR_TX_B 14.097100e6 // this is the bottom of the 20m band. The station moves about. #define RTTY_TX_A 14.090000e6 // #define CW_TX_A 14.102500e6 // move away from IBP #define WSPR_DUTY 2 // transmit every N slices. #define HIGH_PWR LOW #define LOW_PWR HIGH static String Months[] ={"xxx","JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"}; static byte DaysInMonth[] ={31,28,31,30,31,30,31,31,30,31,30,31}; static String DaysOfWeek[] = {"SUN","MON","TUE","WED","THR","FRI","SAT"}; // lllccccc l=length, c=code static byte MorseCode[] ={ // Start at ascii 0x2F B10101001, /// B10111111, //0 B10111110, //1 B10111100, //2 B10111000, //3 B10110000, //4 B10100000, //5 B10100001, //6 B10100011, //7 B10100111, //8 B10101111, //9 0, //: 0, //; 0, //< B10101010, // =AR barred, was = 0, //> 0, //? 0, //@ B01000010, //A B10000001, //B B10000101, //C B01100001, //D B00100000, //E B10000100, //F B01100011, //G B10000000, //H B01000000, //I B10001110, //J B01100101, //K B10000010, //L B01000011, //M B01000001, //N B01100111, //O B10000110, //P B10001011, //Q B01100010, //R B01100000, //S B00100001, //T B01100100, //U B10001000, //V B01100110, //W B10001001, //X B10001101, //Y B10000011}; //Z //G0VXG IO82 30dB static byte WSPR_DATA_G0VXG[] = { 3,1,0,2,0,2,2,0,1,0,2,0,1,3,3,0,2,0,1,0,2,3,2,1,1,1,1,2,0,2,0,0,0, 2,3,0,0,3,0,3,0,2,2,2,2,0,1,2,1,3,0,2,3,3,0,3,0,2,2,3,3,2,3,0,2,0, 0,1,1,2,1,2,3,2,1,2,1,2,2,3,2,0,1,2,3,1,2,2,2,3,3,0,1,2,1,2,2,0,3, 2,2,2,0,2,3,2,2,3,0,2,3,1,1,0,1,3,2,2,3,1,2,3,0,2,0,3,1,1,2,2,0,0, 2,1,0,1,2,0,3,1,0,0,0,2,2,2,2,3,3,2,3,2,1,1,2,0,0,1,3,2,2,0}; //G0VXG JN20 33dB [JN20CC //Type 1: G0VXG JN20 33 //Type 2: EA6/G0VXG 33 //Type 3: FK52UD 37 //Son Parc G0VXG JN20 33 //static byte WSPR_DATA_EA6XG[] = { //3,3,0,0,0,2,0,0,1,2,2,2,1,3,3,0,2,0,1,0,2,1,0,1,1,3,3,0,0,2,0,2,0, //0,3,2,0,3,0,1,0,2,2,0,2,0,1,0,1,1,0,2,3,1,2,3,0,2,2,3,3,2,1,2,2,2, //0,1,1,0,3,0,3,0,1,2,1,2,2,3,2,2,1,2,3,1,0,0,2,1,1,2,1,2,1,2,2,0,3, //2,2,0,2,0,3,0,2,1,0,2,3,3,1,2,1,1,2,0,3,1,2,3,2,2,0,3,3,3,2,0,0,2, //2,3,2,3,2,0,3,1,0,0,2,0,2,2,2,3,3,2,3,2,1,3,0,2,0,1,1,2,2,2}; //Cala en Porter G0VXG JM29 30 [pwr level other than 30 seem to cause problems static byte WSPR_DATA_EA6XG[] = { 3,3,0,2,0,0,0,2,1,2,2,0,1,3,3,0,2,0,1,2,2,3,0,3,1,3,3,2,0,0,0,0, 0,2,3,0,0,1,0,3,0,2,2,2,2,2,1,2,1,1,0,2,3,1,2,3,0,2,2,1,3,2,1,0, 2,0,0,1,1,2,3,2,3,0,1,2,1,0,2,3,2,2,1,2,3,1,0,2,2,3,1,2,1,2,1,2, 2,0,3,2,2,2,2,0,3,2,2,3,0,0,3,1,1,2,1,1,2,0,3,1,2,1,2,2,0,3,3,1, 2,2,0,0,2,1,2,3,2,2,3,1,0,2,2,2,2,0,2,1,3,2,3,2,1,1,0,0,0,1,1,2, 2,2}; /* Baudot Here is the complete code table. Remark: the lsb (least significant bit) is transmitted first. bitcode LTRS FIGS hex oct bitcode LTRS FIGS hex oct ------------------------------------ ------------------------------------ 00011 A - 03 03 10111 Q 1 17 27 11001 B ? 19 31 01010 R 4 0A 12 01110 C : 0E 16 00101 S BELL 05 05 01001 D $ 09 11 10000 T 5 10 20 00001 E 3 01 01 00111 U 7 07 07 01101 F ! 0D 15 11110 V ; 1E 36 11010 G & 1A 32 10011 W 2 13 23 10100 H STOP 14 24 11101 X / 1D 35 00110 I 8 06 06 10101 Y 6 15 25 01011 J ' 0B 13 10001 Z " 11 21 01111 K ( 0F 17 01000 CR CR 08 20 10010 L ) 12 22 00010 LF LF 02 02 11100 M . 1C 34 00100 SP SP 04 04 01100 N , 0C 14 11111 LTRS LTRS 1F 37 11000 O 9 18 30 11011 FIGS FIGS 1B 33 10110 P 0 16 26 00000 n/a n/a 00 00 */ static byte Baudot[]={0x04,0x0d,0x11,0xff,0x09,0xff,0xff,0x0b,0x0f,0x12,0xff,0xff,0x0c,0x03,0x0c,0x1d, 0x16,0x17,0x13,0x01,0x0a,0x10,0x15,0x07,0x06,0x18,0x0e,0xff,0x08,0xff,0x02,0x19,0xff, 0x03,0x19,0x0E,0x09,0x01,0x0D,0x1A,0x14,0x06,0x0B,0x0F,0x12,0x1C,0x0C,0x18,0x16,0x17,0x0A, 0x05,0x10,0x07,0x1E,0x13,0x1D,0x15,0x11}; // " " to Z //nb < equ CR, > equ LF //static int SkedHours[]={7,8,9,10,11,12,13,14,15,16,17,18,19,-1}; testing //hours UTC static int SkedHours[]={8,10,12,14,16,18,-1}; //hours UTC -EA6 static byte WSPRmins[]={0,20}; //run between m1 and m2 minutes past the Sked hour //static byte WSPRmins[]={0,55}; //run between m1 and m2 minutes past the Sked hour TEST ONLY static byte RTTYmins[]={30,32};//run between m1 and m2 minutes past the hour static byte CWmins[]={33,39}; //run between m1 and m2 minutes past the hour //#define WSPR_DATA WSPR_DATA_G0VXG #define WSPR_DATA WSPR_DATA_EA6XG // DDS/Arduino Connections #define GPS data A0 //23,in #define nu A1 //24,out #define Baro A7 //22,in #define Thermo A6 //19 in #define DDS_DATA 8 //12,out #define DDS_LOAD 9 //14,out #define DDS_CLOCK 10 //13,out #define RFpower 5 // 9,out #define LED 13 //17,out ///// #define WSPR_RUN 1 #define RTTY_RUN 2 #define CW_RUN 3 #define NO_RUN -1 // Variables unsigned long WSPR_TXF = WSPR_TX_B; //20m //Globals______________________________________ char NMEA_code[] = {"$GPRMC"}; String inputString = ""; // a string to hold Serial incoming data boolean bStringComplete = false; // whether the string is complete boolean bCodeFound = false; // $GPxxx found String sNextMinutes="01"; int iHeartbeat=0; boolean bPower; int iSerialCount = 0; int iDutyCycle=0; boolean bRunOnce=false; //Function defines---------------------------------------------- void FlushBuffer(); int analogReadReference(byte, byte); ////////////////////////////////////////////////////////////////////////////// ////////////////////////////// SetUp ///////////////////////////////////////// void setup() { // Set all pins to output states digitalWrite(RFpower,LOW_PWR); analogReference(INTERNAL); //1.1volts //analogReference(DEFAULT); //5volts inputString.reserve(255); pinMode (Baro, INPUT); pinMode (Thermo, INPUT); pinMode (DDS_DATA, OUTPUT); pinMode (DDS_CLOCK, OUTPUT); pinMode (RFpower, OUTPUT); pinMode (DDS_LOAD, OUTPUT); pinMode (LED, OUTPUT); //pinMode (RTTY_Code, INPUT); //pinMode (RTTY_Ack, OUTPUT); Serial.begin(9600); Serial.print("DDS Reset "); delay(900); frequency(0); delay(100); Serial.println("OK"); Serial.flush(); FlashLed(5,LED); FlushBuffer(); //Serial.println(FormatGrid("5237.4311"),4); float fLat = FormatGrid("5237.4311"); float fLon = FormatGrid("00227.7916"); String sText = MaidenheadSquare(fLon,fLat, 'W'); //nb from GPS 00227.7916 DDDMM.mmmm Serial.println(sText); } ////////////////////////////////////////////////////////////////////////////// ///////////////////////////// Main Loop ////////////////////////////////////// void loop() { if(bCodeFound && bStringComplete) { String arText[15]; String sTime, sDate; inputString += "x,x"; int i = SplitString(inputString,arText); sTime = arText[1]; //sLat = arText[2]; //sNS = arText[3]; //sLong = arText[4]; //sEW = arText[5]; sDate = arText[9]; // String sMins = sTime.substring(2,4); //mins String sHours = sTime.substring(0,2); // int iResult = ScheduleTasks(sHours,sMins); //need to test CW and RTTY on switch on if(!bRunOnce) { wsprTXtone(1); delay(20000); frequency(0); SendCWmessage(sDate,sTime); //force TX on switch on bRunOnce = true; } switch(iResult) { case NO_RUN: break; case WSPR_RUN: digitalWrite(RFpower,LOW_PWR); CheckLastMinute(sDate,sTime); break; case RTTY_RUN: bPower = !bPower; if(bPower) digitalWrite(RFpower,HIGH_PWR); else digitalWrite(RFpower,LOW_PWR); SendRTTYmessage(sDate,sTime); break; case CW_RUN: //bPower = !bPower; //if(bPower) digitalWrite(RFpower,HIGH_PWR); //else digitalWrite(RFpower,LOW_PWR); digitalWrite(RFpower,HIGH_PWR); //version SendCWmessage(sDate,sTime); break; } bCodeFound = false; bStringComplete = false; FlushBuffer(); } } //////////////////////////////////////////////////////////////// //----------------------- End of loop -------------------- //////////////////////////////////////////////////////////////// //***************************** SUBROUTINES ********************************* //********************** ScheduleTasks ************************************** int ScheduleTasks(String sHours, String sMins) { int i=0; boolean bTest=false; int iHours = AscToInt(sHours); while(SkedHours[i] != -1) { if(iHours==SkedHours[i]) bTest = true; i++; } if(bTest==false) return NO_RUN; // int iMins = AscToInt(sMins); if(iMins >=WSPRmins[0] && iMins < WSPRmins[1]) { return WSPR_RUN; } if(iMins >=RTTYmins[0] && iMins < RTTYmins[1]) { return RTTY_RUN; } if(iMins >=CWmins[0] && iMins < CWmins[1]) { return CW_RUN; } return NO_RUN; } //*************************************************************************** //********************** CheckLastMinute() ********************************** void CheckLastMinute(String sDateNow, String sTimeNow) { String sSecs = sTimeNow.substring(4,6); //secs String sMins = sTimeNow.substring(2,4); //mins String sYears = sDateNow.substring(4,6); //years int iMins, iLen; iHeartbeat+=1;// to overcome problem when GPS initially has no time. // normally will get reset every 120s if(sSecs == "00") { Serial.print(" Heartbeat: "); Serial.print(iHeartbeat,DEC); Serial.println(""); if(iHeartbeat > 70) sNextMinutes = sMins; // no propper GPS time at start up if(GetLastminute(sMins)) { iHeartbeat=0; int iTemp = iDutyCycle % WSPR_DUTY; if(iTemp == 0) { Serial.println("GO! " + sTimeNow); wsprTX(); FlashLed(2,LED); iDutyCycle=0; } iDutyCycle++; Serial.println("Nextmins: " + sNextMinutes); } } } //****************************************************************** //***************** GetLastMinute() ********************************* boolean GetLastminute(String sMins) { int i, iMins=0, iLength; boolean bTest=false; iLength = 2; //sMins.length(); if(sMins == sNextMinutes) { iMins = AscToInt(sMins); if((iMins % 2) ==0) { iMins += 2; bTest = true; } else { iMins += 3;//make sure that we are on 2min boundary bTest = false; // ie 10:00,12:00,hh:14:00 } if(iMins > 59) iMins -= 60; sNextMinutes = String(iMins); if(iMins < 10) sNextMinutes = "0" + sNextMinutes; //zero pad return bTest; } else { return bTest; } } //******************* RTTY subs ******************************** //nb lower side band - Baudot void SendRTTYmessage(String sDate, String sTime) { String sRTTY=FormatMessage(sDate,sTime); String sRTTYmessage = "RYRYRYRYRY<>"; //cr lf sRTTYmessage += sRTTY; //had to use += here, probs with just str1 = str2+str1 char c,cSend; char cChar=1; //init for while loop char cLast='\0'; int iChar,i=0; rtty_txbit(1); //send a tone so that RX can sync to it. delay(500); while(cChar != '\0') { cChar = sRTTYmessage[i]; if(cLast == '\0') { if(cChar < 'A') cLast = 'A'; // forces next IF to send NUMS else cLast = '0'; // else send LETS } if(cLast < 'A' && cChar >= 'A') { Baudrtty_txbyte (0x1f); //LETS } if(cLast >= 'A' && cChar < 'A') { Baudrtty_txbyte (0x1b); //NUMS } iChar = cChar - (int) ' '; cLast = cChar; cSend = Baudot[iChar]; Baudrtty_txbyte (cSend); i++; } frequency(0); FlashLed(3,LED); delay(15000); } //********************************************************** void Baudrtty_txbyte (char c) { int i; rtty_txbit(0); // Start bit for (i=0;i<5;i++) // 5 bits for Baudot { if (c & 1) rtty_txbit(1); //lsb first else rtty_txbit(0); c = c >> 1; } rtty_txbit (1); // Stop bit rtty_txbit (1); // Stop bit } //************************ ASCII rtty_txbyte ********************************** void rtty_txbyte (char c) { int i; rtty_txbit(0); // Start bit for (i=0;i<7;i++) // Change this here 7 or 8 for ASCII-7 / ASCII-8 { if (c & 64) rtty_txbit(1); //msb first else rtty_txbit(0); c = c << 1; } rtty_txbit (1); // Stop bit rtty_txbit (1); // Stop bit } //******************* rtty_txbit ********************* void rtty_txbit(int ibit) { unsigned long freq; if (ibit) { // high freq = DDS_OSET + RTTY_SHIFT + RTTY_TX_A; frequency(freq); } else { //low freq = DDS_OSET + RTTY_TX_A; //USB frequency(freq); } // delayMicroseconds(3370); // 300 baud delayMicroseconds(10000); // For 50 Baud uncomment this and the line below. delayMicroseconds(10150); // You can't do 20150 it just doesn't work. } //******************************************************************** //******************* frequency() ************************************ void frequency(unsigned long frequency) { unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_REF; digitalWrite (DDS_LOAD, LOW); // take load pin low for(int i = 0; i < 32; i++) { if ((tuning_word & 1) == 1) outOne(); else outZero(); tuning_word = tuning_word >> 1; } byte_out(0x00); //for AD9850 digitalWrite (DDS_LOAD, HIGH); // Take load pin high again } //*************************************************************** void byte_out(unsigned char byte) { int i; for (i = 0; i < 8; i++) { if ((byte & 1) == 1) outOne(); else outZero(); byte = byte >> 1; } } //**************************************************************** void outOne() { digitalWrite(DDS_CLOCK, LOW); digitalWrite(DDS_DATA, HIGH); digitalWrite(DDS_CLOCK, HIGH); digitalWrite(DDS_DATA, LOW); } void outZero() { digitalWrite(DDS_CLOCK, LOW); digitalWrite(DDS_DATA, LOW); digitalWrite(DDS_CLOCK, HIGH); } //*************************************************************************** //************************* Flash Led *************************************** void FlashLed(unsigned int t, int l) { unsigned int i = 0; if (t > 25) { digitalWrite(l, HIGH); delay(2000); digitalWrite(l, LOW); } else { for (i=0;i> 5; for(ix=0;ix"; //String sCWMessage = "EA6/B JM29BS 1450 UTC 21NOV14 PWR 3 BARO 1023 THERMO 23C V21>"; //return sCWMessage; String sChars; sChars = "EA6/B JM29BS "; //Cala en Porter sChars += sTime.substring(0,2); //hours sChars += sTime.substring(2,4); //mins sChars += "UTC "; String sDays = sDate.substring(0,2); //days String sMonths = sDate.substring(2,4); //months String sYears = sDate.substring(4,6); //years //String sDayOfWeek = DayOfWeek(sDays,sMonths,sYears); //sChars += sDayOfWeek; int iMindex = AscToInt(sMonths); sChars += sDays; //days sMonths = Months[iMindex]; sChars += sMonths; sChars += sDate.substring(4,6); //years sChars += " PWR "; String sPower = "5W"; if (digitalRead(RFpower) == LOW_PWR) sPower = "3W"; sChars += sPower; String sBaro = BaroRead(); sChars += " BARO "; sChars += sBaro; sChars += " THERMO "; String sThermo = ThermoRead(); sChars += sThermo; sChars += "C "; sChars += VERSION; sChars += " "; return sChars; } //********************************************************************* //********************** AscToInt ************************************* int AscToInt(String sNum) { int iNum=0,iLen,i; iLen = sNum.length(); for(i=0; i 0) { arText[byCount] = sMsg;// + '\0'; } } } while(iCommaPosition >=0); } //////////////////////// BaroRead /////////////////////////////// String BaroRead() { char sBuff[8]; //analogReference(DEFAULT); //5volts delay(500); //settle time int iBaro = analogReadReference(Baro,DEFAULT); unsigned long lBaro = (iBaro * 1.127) + 65; ltoa(lBaro,sBuff,10); return sBuff; }//////////////////////// BaroRead /////////////////////////////// String ThermoRead() { char sBuff[8]; //String sThermo; unsigned long lThermo; int iThermo = analogReadReference(Thermo,INTERNAL); lThermo = iThermo; //int to long lThermo = lThermo / 10; ltoa(lThermo,sBuff,10); return sBuff; } //************************* FormatGrid() *************************** float FormatGrid(String sLoc) //"00227.7916" { int iDegs; int iLen = sLoc.length(); String sDegs = sLoc.substring(iLen-9,iLen-7); iDegs = AscToInt(sDegs); String sMins = sLoc.substring(iLen-7,iLen); char carray[sMins.length() + 1]; sMins.toCharArray(carray, sizeof(carray)); float fn = atof(carray); fn = fn / 60; //convert to degrees fn+=iDegs; //add Degrees and decimal portion return fn; } //************************* MaidenheadSquare()******************** String MaidenheadSquare( float lon, float lat, char EorW) { int loni,lati,i; char lonc,latc; String sText; if(EorW == 'W') lon = (180-lon)/20; //west else lon = (180+lon)/20; //east lat = (lat+90)/10; //north i=0; while(i<3) //3==6chars ie IO82so { i++; loni=int(lon); lati=int(lat); if(i%2) { lonc = 'A'+loni; sText += lonc; latc = 'A'+lati; sText += latc; lon=(lon-loni)*10; lat=(lat-lati)*10; } else { lonc = '0'+loni; sText += lonc; latc = '0'+lati; sText += latc; lon=(lon-loni)*24; lat=(lat-lati)*24; } } return sText; } //***************************** DayOfWeek() ********************************************** String DayOfWeek(String sDays, String sMonths, String sYears) { int iCurrDay = AscToInt(sDays); int iCurrMonth = AscToInt(sMonths); int iCurrYear = AscToInt(sYears); int iMonths =1, iYear =0; int iTotalDays = DaysInMonth[1] - 5; // start with 1st Sun in Jan 14 == 5th iYear = 14; // sb global while((iMonths < iCurrMonth) && (iYear <= iCurrYear)) { iTotalDays += DaysInMonth[iMonths]; iMonths++; if (iMonths > 12) { iMonths=1; iYear++; } if ((iMonths == 2) && ((iYear + 2000) % 4 == 0)) { iTotalDays++; //leap } } //iTotalDays+= iCurrDays //iTest = iTotalDays % 7; //String sDay=DaysOfWeek[iTest]; return sDays; } /***************************************************************************************** * Returns the analog value at #pin# by using the analog reference mode * specified by #mode#. Switches back to original mode after. */ int analogReadReference(byte pin, byte mode) { // Makes sure mode has been set in ADMUX by calling analogRead() on method's first call static bool firstCall = true; if (firstCall) analogRead(pin); uint8_t currentReference = (ADMUX >> 6); // copy current reference analogReference(mode); // switch to new reference // XXX I don't know why but without these lines the switch from // DEFAULT to INTERNAL does not work well or at all!. analogRead(pin); delay(100); int value = analogRead(pin); // read value analogReference(currentReference); // switch back to original reference return (value); } //////////////////////// Flush buffer ///////////////////////////// void FlushBuffer() { while (Serial.available()) { // get the new byte: char inChar = (char)Serial.read(); } inputString=""; } /* SerialEvent occurs whenever a new data comes in the hardware serial RX. This routine is run between each time loop() runs, so using delay inside loop can delay response. Multiple bytes of data may be available. */ //****************************************************************************** void serialEvent() { boolean bStart = false; static int iCodeCount; //inputString = ""; while (Serial.available()) { // get the new byte: char inChar = (char)Serial.read(); if(inChar == NMEA_code[0]) //==$ { iCodeCount = 0; bStart = true; inputString = "";//clear string ready for rest of data iSerialCount=0; } if (bStart = true) { if (NMEA_code[iCodeCount] == inChar) { iCodeCount++; if(iCodeCount==6) { bCodeFound=true; bStart = false; bStringComplete = false; // clear flag and wait for end of string char } } else { bStart = false; //look for next $ } } if(bCodeFound == true) { iSerialCount+=1; inputString += inChar; } // if the incoming character is a newline, set a flag // so the main loop can do something about it: if (inChar == '\n') { bStringComplete = true; } } }