/*S2SysClient1... ver 5 feb 08 Actually second attempt. 1st was called "host", and was part of a bigger prgm*/ //#define S2toClient=4; //Tell prgm which input will carry the S2toClient signal int S2toClient=4; //Tell prgm which input will carry the S2toClient signal int S2frClient=10; //Tell prgm which input will carry the S2frClient signal //#define S2HalfBit=50 //#define S2OneBit=S2OneBit*2; byte S2HalfBit=80;//Must not be more than 127 byte S2OneBit=S2HalfBit*2; //Next, create aliases for lines with LEDs... again... // not at core of S2Sys, just part of demo thereof. int ledPin2 = 11; int ledPin3 = 12; int ledPin4 = 13; // Onboard LED connected byte bDatumToDisplay=0;//Not central to S2Sys... just part of the prgm's demo built //into this "shell" //The following two globals are central to S2Sys... even if they // are using a less than "PC" programming style. Done this // crude way for the sake of clarity. byte S2Err=0; byte S2Datum=0; void setup() { pinMode(S2toClient, INPUT); pinMode(S2frClient, OUTPUT); digitalWrite(S2frClient, HIGH);/*Says "Don't want datum yet" May need to do something clever... not necessarily here... to determine/ deal with "Server not online". Will have to be able to distinquish that from a server in mid-datum send.*/ //Next three not central to core of S2Sys pinMode(ledPin2, OUTPUT); pinMode(ledPin3, OUTPUT); pinMode(ledPin4, OUTPUT); } void loop() { Display();/*Not central to S2Sys... just part of the prgm's demo built in demo routine. For this demo, all that happens is that what is in bDatumToDisplay gets put on some LEDs attached to the Arduino running this, the client, software. Initially, that is a zero. If S2GetDatum returns an error code, which can include the "error" NoDataWaitingForUsOnServer, then what is in bDatumToDisplay remains what it was before. In other words, in normal operation, the LEDs will display, say, 5,5,5,5... and so on until a NEW number is collected from the server. The persistence of a datum, in the example 5, should not be thought to indicate that the datum is being sent from the server again and again. It follows from the above that in order to see the server/client interaction work, you have to ask the server to send a different number than it sent last time, and you have to ask the client to go and fetch the data that has been made available. It would be perfectly possible to modify the parts of this that demonstrate S2Sys so that every time a datum became available on the client, the server would display it briefly (1 second?), and then go back to showing "zero". In this scenario, zero would be a rougue result, and sending zero from the server would be pointless.*/ //The following is a crude temporary kludge. //A long (> max total xmission time for one byte and all overheads) delay //must be provided before each read. Even if an attempt to read returned //"nothing available TO read" after the loop is established, the long delay //may be necessary in case of power cycle and confusion in server? delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); delay(S2OneBit); //The next delay only here so that the buffer in the server //can be tested... testing: rwill it accumulate keypresses for SUBSEQUENT //xmission? delay(3000); if (digitalRead(6)==HIGH) { digitalWrite(S2frClient,LOW); delay(S2OneBit); delay(S2OneBit); digitalWrite(S2frClient,HIGH); } S2GetDatum(); if (S2Err==0){bDatumToDisplay=S2Datum;} } void Display() { //Display whatever is in bDatumToDisplay if ((bDatumToDisplay&4)==4){digitalWrite(ledPin2,HIGH);} else {digitalWrite(ledPin2,LOW);} if ((bDatumToDisplay&2)==2){digitalWrite(ledPin3,HIGH);} else {digitalWrite(ledPin3,LOW);} if ((bDatumToDisplay&1)==1){digitalWrite(ledPin4,HIGH);} else {digitalWrite(ledPin4,LOW);} //N.B.: (bDatumToDisplay&1==1) does NOT work... doing == before & return; } void S2GetDatum() { /*Heart of S2Sys's Client software. Attempt to fetch a datum from the server. Note: The server does not have to be OFFERING a datum when this routine is called. That potential situation is provided for within this procedure. It would have been more "clever" to return a value via the language's parameter passing mechanism. Instead, for the sake of clarity for novices, S2GetDatum puts values in the following two global variables: S2Datum: The datum fetched from the server S2Err: A flag to say whether the "fetch" was successful. If it was, S2Err will be equal to zero If it wasn't, the value in S2Err will be a clue as to the nature of the problem encountered. 255 reports that the server wasn't offerring any data at the time S2GetDatum was called. S2GetDatum must not be able to "trap" the program. The program must not linger within S2GetDatum. Go in. Get out. */ S2Err=255;//Flag for "The server didn't have any data to send." // S2Err=0;//for debug // S2Datum=1;//for debug if (digitalRead(S2toClient) == LOW) { //Server has at least one datum avail... try to read it.... S2Err=0;//Flags "Server sent data".. contents of variable //may have to be revised later within the block if it //emerges from yet-to-be-implemented error checks that the //datum received was somehow bad. digitalWrite(S2frClient,LOW);//Tell server to start sending. do {//Wait until server sends start bit. } while (digitalRead(S2toClient)==LOW); digitalWrite(S2frClient,HIGH); /*Must be restored high before server finishes sending current datum and starts looking for the next "Ready for data" signal... a low S2frClient line.*/ delay(S2OneBit);//Wait for StartBit to pass delay(S2HalfBit);//Wait 'til we're in the MIDDLE of the first data bit //The above 1.5 bit's-worth delay may have to be fine tuned... the delays // do not take into account the other small delays in, for instance, the // execution of restoring S2frClient high. S2Datum=S2ReadBit();//Read first bit, bit "7". Initializes build of new S2Datum delay(S2OneBit);//May need fine tweak... It takes time to "grow" //S2Datum, and the TOTAL time between read bits should only be S2OneBit S2Datum=(2*S2Datum)+S2ReadBit();//bit 6 delay(S2OneBit); // S2Datum=(2*S2Datum)+S2ReadBit();//5 delay(S2OneBit); // S2Datum=(2*S2Datum)+S2ReadBit();//4 delay(S2OneBit); // S2Datum=(2*S2Datum)+S2ReadBit();//3 delay(S2OneBit); // S2Datum=(2*S2Datum)+S2ReadBit();//2 delay(S2OneBit); // S2Datum=(2*S2Datum)+S2ReadBit();//1 delay(S2OneBit); // S2Datum=(2*S2Datum)+S2ReadBit();//0 delay(S2OneBit);//should take us half a bit's worth past end of send //of last bit... but see note following note about error detection/correction bits //When server software upgraded to include sending error detection/correction // bits, then add "read those bits" and process them HERE. //There should be a "Wait a little while" here. The danger is that if the last // data bit from the server is a 0, and it lingers on the line just a bit too // long, the client may interpret that as a "Data Available" signal. //The wait is along the lines of respecting // some "Stop Bits"... but note that the server doesn't SEND "stop bits"... // we are merely be asking the client to act AS IF there were stop bits // to be waited through. // **** BUT.... after writing the above, I realized that a LOG wait must // occur BEFORE any attempt to read... for similar reasons... and with that // in place, the wait AFTER reading can be eliminated. }//End of "try to read it" return; } // end of S2GetDatum byte S2ReadBit(){ //Returns 0 or 1, depending on state of S2toClient at //time of call. byte result; result=0;//not init'd in declaration in hopes that this way is faster //perhaps make "result" "S2result, and global... bad practice, but maybe faster? if (digitalRead(S2toClient)==HIGH) {result=1;}//Note: Time in routine will vary, depending //on whether this assignment needed. May mess things up at high data rates. return result; }