//file name: skinnyPrint.h
/***********************************************************
                  Skinny Print Library

This software works with SkinnyPrint hardware and software: 

https://rick.sparber.org/SPrint.pdf

Using a single pin which is specified via the constructor, bytes can be transmitted from an ATtiny85 to a monitor.

ATtiny85 --> single pin --> optoisolator --> Pro Micro  --> USB  --> monitor

After setup() and before loop(), place the constructor:

Example:

singlePinPrint sPP(3);

sPP is the user defined name of one copy of the singlePinPrint class. 
3 is the logical pin number that will be used to pass the data.

My setup() defined this pin as an input. By placing this line after setup(), I override that setting. I do not change it in loop().

To print a single byte, used

                      PrintN(byte data)
                      
 It will print Now which means your program will stop for about 60 ms 
 as the bits go out. 

To print a single byte quickly, used

                       PrintF(byte data)
                       
It will print Fast which means the byte will be put in a queue. This queue can hold up to 128 bytes. When there it time, call

                          Printer()
                          
It will send all of the bytes in the queue to the monitor. If the queue is full, this will take 8 seconds.                          

*************************************************************/

#ifndef skinnyPrint_h
#define skinnyPrint_h

#include "Arduino.h"

class singlePinPrint //this is the class name
{
        public:
                singlePinPrint(byte pin);//constructor
                void PrintN(byte data);//print now
                void PrintF(byte data);//print fast and output later with Printer()
                void Printer();//takes up to 10 bytes and sends the out pin
                
    
        private:
                byte SkinnyPrintPin; //logical port that will be used as output  this will go into begin()
                unsigned int InterByteTimeMicroS = 250; //time from thetransmission of the last bit of one byte to the header of thenext byte
                unsigned int TimeUnitMicroS = 1500; //a TimeUnit is actually about 0.2 milliseconds long than this value
                byte ByteBeingSent = 0;
                byte Stack[130];//holds 128 or fewer bytes waiting to betransmitted plus the overflow symbol of FF FF
                byte LocalTimeUnitCounter = 0;
                byte SkinnyTransmitterCounter = 0; //used to shift stack down
                byte StackPointer = 0; //next available location in stack
                boolean StackOverflowQ = false;
                boolean SendingStreamQ = false;
                unsigned long start = 0;
                byte TimeUnitCounter = 0;
                unsigned long TimeLastBitSentMicroS = micros(); //used to tellwhen to start sending next byte
                unsigned long TimeTimeUnitSentMicroS = micros() - 2*TimeUnitMicroS; //used to tell when to send next TimeUnit. Initialized to insure immediate transmission
                unsigned long TimeAllOfByteSentMicroS = micros(); // used totell when to send next byte. I set it so first byte is sentwithout delay.
                //long RemainingEnergyCountLong = 0;
                //long ApproximateFullChargeCountLong = 362353L;//this is close to the right answer so until Calibration can run, this will work.
                //long FullChargeCountLong = ApproximateFullChargeCountLong;
                
                void SkinnyPrinter();
                void MonitorStack();
                void SendFromStack();
                void PrepareToSendStream(byte data);
                void SendStream();
                void SendHeader();
                void SendBits();
                void SkinnyPrintByte(byte data);
};        
#endif        
    
    