/* ; ************************************************ ; * SkinnyPrint Receiver for ATtiny85 * ; * this software runs on a Pro Micro * ; * It reads header plus 8 bits * ; * and outputs a byte. * ; * Version 0.8 * ; This work is licensed under the Creative * ; Commons Attribution 4.0 International License. * ; To view a copy of this license, visit * ; http://creativecommons.org/licenses/by/4.0/ * ; or send a letter to Creative Commons, * ; PO Box 1866, Mountain View, CA 94042, USA. * ; * by R.G. Sparber * ; ************************************************ ; ; ============================================ ; H A R D W A R E I N F O R M A T I O N ; ============================================ ; ; physical pin logical pin use ; 12 D9 serial input ; ============================================ ; P O R T S A N D L O G I C A L P I N N A M E S ; ============================================ */ const int SerialInput = 9; //the logical port that will receive the serial stream; /* ; ============================================ ; C O N S T A N T S ; ============================================ In order to get 2 places past decimal point in detection of header, I multiply LongOneTime by 10^4, divide it by a time tolerance times 10^2 and compare it to the tolerance which has been multiplied by 10^4/10^2 = 100. */ const unsigned long MinimumTimeToleranceTimesOneHundred = 250; // allowed variation in TimeUnit for a LongOne times 10000 const unsigned long MaximumTimeToleranceTimesOneHundred = 350; // allowed variation in TimeUnit for a LongOne times 10000 /* ; ============================================ ; V A R I A B L E S ; ============================================ */ unsigned long TimeUnit = 0; //fundamental unit of time in serial stream unsigned long TimeUnitTimesOneHundred = 0; unsigned long ReadDelay = 0; unsigned long TimeStamp = 0; unsigned long LongOneTime = 0; unsigned long LongOneTimeTimesTenThousand = 0; unsigned long Heartbeat = 0; byte NewLine=0; unsigned int BitCounter = 0; byte ReceivedByte = 0; /* ; ============================================ ; S E T U P ; ============================================ */ void setup(){ //set up physical pin 12 (logical port 9) as digital input pinMode(SerialInput,INPUT); Serial.begin(9600); //This pipes text to the PC's Serial monitor } /* ; ============================================ ; L 0 0 P ; ============================================ */ void loop(){ DetectHeader(); ReceiveByte(); OutputByte(); } /* ; ============================================ ; S U B R O U T I N E S ; ============================================ */ void DetectHeader(){ // -_-___- WaitForNegativeEdgeAndTimeStampIt(); WaitForPostiveEdge(); TimeUnit = micros() - TimeStamp; //calculate how long signal was low and call it my TimeUnit ScanForLongOne: WaitForNegativeEdgeAndTimeStampIt(); WaitForPostiveEdge(); LongOneTime = micros() - TimeStamp; //calculate how long signal was low if (FoundLongOneQ() == false){ //try this time interval out as new TimeUnit and see if next pulse is the LongOne TimeUnit = LongOneTime; Serial.println("E"); //tell user of sync error goto ScanForLongOne; } } void ReceiveByte(){ ReadDelay = 1.5*TimeUnit; //record stream starting with LSB. Always 8 bits BitCounter = 0; ReceivedByte = 0; //initialize data to be sent out serial port while (BitCounter < 8){ //so goes from 0 to 7 WaitForNegativeEdgeAndTimeStampIt();//wait for negative edge; either z1 or o1 PrepareToRecordBit(); WaitToReadBitValue();//this puts us in the center of the second TimeUnit ReadBitValueAndRecord(); ++BitCounter; //have recorded a bit so move on to the next bit } } void OutputByte(){ Serial.println(ReceivedByte);//send resulting byte out serial port as a new line } void WaitForNegativeEdgeAndTimeStampIt(){ WaitForHigh(); WaitForLow(); TimeStamp = micros();//record time of negative edge return; } void WaitForPostiveEdge(){ WaitForLow(); WaitForHigh(); return; } boolean FoundLongOneQ(){ LongOneTimeTimesTenThousand = 10000*LongOneTime; TimeUnitTimesOneHundred = 100*TimeUnit; if (((LongOneTimeTimesTenThousand/MinimumTimeToleranceTimesOneHundred) > TimeUnitTimesOneHundred) && ((LongOneTimeTimesTenThousand/MaximumTimeToleranceTimesOneHundred) < TimeUnitTimesOneHundred)){ //LongOne width in spec so header has been detected return true; }else{ return false; } } void PrepareToRecordBit(){ ReceivedByte = ReceivedByte >>1; //shift bits over 1 place to the right in preparation for next bit being recorded. } void WaitToReadBitValue(){ WaitToReadBitValue: if ((micros() - TimeStamp) < ReadDelay){ goto WaitToReadBitValue; } } void WaitForHigh(){ WaitingForHigh: if (digitalRead(SerialInput) == 0)goto WaitingForHigh; } void WaitForLow(){ //while waiting for data, output a dot every 10 seconds WaitingForLow: if (digitalRead(SerialInput) == 1)goto WaitingForLow; } void ReadBitValueAndRecord(){ if(digitalRead(SerialInput)== 0){ //this means a 1 was sent ReceivedByte = ReceivedByte | 0b10000000; //set MSB to 1 } }