#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <TimerOne.h>
#include "SdFat.h"

void Compress(unsigned char *szOut, const char *szMessage) {
	unsigned long long nBuffer = 0; //This is enough to store 8 uncompressed characters or 9 compressed. We will only use 8 tho.
	char nBitsInBuffer = 0;
	while (*szMessage != 0) {
		nBuffer |= (unsigned long long)(*szMessage++ & 0x7F) << nBitsInBuffer;
		nBitsInBuffer += 7;
		if (nBitsInBuffer == 7 * 8) { //We have 8 chars in the buffer, dump them
			while (nBitsInBuffer > 0) {
				*szOut++ = nBuffer & 0xFF;
				nBuffer >>= 8;
				nBitsInBuffer -= 8;
			}
			//The following should be redundant, but just to be safe
			nBitsInBuffer = 0;
			nBuffer = 0;
		}
	}
	//Write out whatever is left in the buffer
	while (nBitsInBuffer > 0) {
		*szOut++ = nBuffer & 0xFF;
		nBuffer >>= 8;
		nBitsInBuffer -= 8;
	}
}

//uncomp()
//nCompressedLen is the number of bytes in the compressed buffer.
//NOTE: the compressed buffer does not have a NULL terminating character
void Uncompress(char *szOut, const unsigned char *szCompressed, unsigned nCompressedLen) {
	unsigned long long nBuffer = 0; //This is enough to store 8 uncompressed characters or 9 compressed. We will only use 8 tho.
	char nBitsInBuffer = 0;
	while (nCompressedLen) {
		while (nCompressedLen && nBitsInBuffer < 7 * 8) {
			nBuffer |= (unsigned long long)*szCompressed++ << nBitsInBuffer;
			nBitsInBuffer += 8;
			--nCompressedLen;
		}
		while (nBitsInBuffer > 0) {
			*szOut++ = nBuffer & 0x7F;
			nBuffer >>= 7;
			nBitsInBuffer -= 7;
		}
		//The following should be redundant, but just to be safe
		nBitsInBuffer = 0;
		nBuffer = 0;
	}
}

SdFat SD;

File file;

Adafruit_SSD1306 OLED(128, 64, &Wire, -1);

void setup() {
  OLED.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  OLED.clearDisplay();
  OLED.display();
  Serial.begin(115200);
  
  Serial.println("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("COULD NOT INITIALIZE SD CARD");
    return;
  }

  Serial.println("Loading file...");
  file = SD.open("video.rawr", FILE_READ);
  if (!file){
    Serial.print("COULD NOT LOAD FILE");
    return;
  }
  
  Serial.println("Done.");
  while (1){
    displayFrame();
  }
}
void logger(char* message, ...)
{
  char tmpPrintfBuffer[4096];
  sprintf(tmpPrintfBuffer, message);
  Serial.write(tmpPrintfBuffer);
}

void loop() {
  // Do Nothing...
}
int frame=0;
void displayFrame(void)
{
    for (int y = 0; y < 64; y+=2){
      for (int x = 0; x < 128; x+=4){
      switch(file.read()) {
        case 0x2E:
          OLED.drawFastHLine(x, y, 4, WHITE);
          OLED.drawFastHLine(x, y+1, 4, WHITE);
					//OLED.drawPixel(x,y, WHITE);	

          break;
        case 0x20:
        	OLED.drawFastHLine(x, y, 4, BLACK);
          OLED.drawFastHLine(x, y+1, 4, BLACK);
					//OLED.drawPixel(x,y, BLACK);
          break;
        }
      }
    }
  OLED.display();
	delayMicroseconds(6000);
}
mega:SCL
mega:SDA
mega:AREF
mega:GND.1
mega:13
mega:12
mega:11
mega:10
mega:9
mega:8
mega:7
mega:6
mega:5
mega:4
mega:3
mega:2
mega:1
mega:0
mega:14
mega:15
mega:16
mega:17
mega:18
mega:19
mega:20
mega:21
mega:5V.1
mega:5V.2
mega:22
mega:23
mega:24
mega:25
mega:26
mega:27
mega:28
mega:29
mega:30
mega:31
mega:32
mega:33
mega:34
mega:35
mega:36
mega:37
mega:38
mega:39
mega:40
mega:41
mega:42
mega:43
mega:44
mega:45
mega:46
mega:47
mega:48
mega:49
mega:50
mega:51
mega:52
mega:53
mega:GND.4
mega:GND.5
mega:IOREF
mega:RESET
mega:3.3V
mega:5V
mega:GND.2
mega:GND.3
mega:VIN
mega:A0
mega:A1
mega:A2
mega:A3
mega:A4
mega:A5
mega:A6
mega:A7
mega:A8
mega:A9
mega:A10
mega:A11
mega:A12
mega:A13
mega:A14
mega:A15
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA
sd1:CD
sd1:DO
sd1:GND
sd1:SCK
sd1:VCC
sd1:DI
sd1:CS