#include <Wire.h>
//#include <TinyWireM.h>
//#include "flap4.h"
//#include "flap5V.h"
#define I2C_ADDRESS 0x3C
#define FADE_SIZE 400
#define LOGO_WIDTH 80
#define LOGO_HEIGTH 40
int count = 0;
int fade [FADE_SIZE];
const unsigned char logo [] PROGMEM = {
0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0xEC, 0xED, 0xF1, 0xF0, 0xFB, 0xFB, 0xF8, 0xF8, 0xFC, 0xFD, 0xF9, 0xF8, 0xFB, 0xFB, 0xF8, 0xF0, 0xEC, 0xCD, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xF9, 0xF8, 0xFB, 0xFB, 0xF8, 0xF8, 0xFC, 0x8D, 0xB1, 0x30, 0x03, 0xFB, 0xF8, 0xF8, 0xFC, 0xFD, 0xF9, 0xF8, 0x03, 0x1B, 0xD8, 0xD8, 0x3C, 0xFD, 0xF9, 0xF8, 0xFB, 0xFB, 0xF8, 0xF8, 0xFC, 0xCD, 0xB1, 0x30, 0x03, 0xDB, 0xF8, 0xF0, 0xFC, 0xFD, 0xF9, 0xF8, 0xFB, 0xFB, 0xF8, 0xF8, 0x1C, 0x8D,
0xB1, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x3F, 0x07, 0x1F, 0xDB, 0xC3, 0x0F, 0x8F, 0xB3, 0x37, 0x07, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xD8, 0xC0, 0x0C, 0x8D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xF1, 0xF0, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x0C, 0x8D,
0xB3, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0xC3, 0xDB, 0xD8, 0xC0, 0x8C, 0x8D, 0xB1, 0xF0, 0xC3, 0xFB, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xDF, 0xC0, 0x0C, 0x8D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xBF, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x8D, 0xB1, 0x37, 0x03, 0x1B, 0xD8, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x0C, 0x8D,
0xB1, 0x30, 0x03, 0x1B, 0xDB, 0xC7, 0x0F, 0x9F, 0xBF, 0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0xBF, 0xBF, 0x3F, 0x3F, 0x3F, 0xDF, 0xDF, 0x0F, 0x8F, 0xB3, 0x31, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xBF, 0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x8D, 0xB1, 0x30, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0xBF, 0xBF, 0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xC0, 0x0C, 0x8D,
0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1F, 0xDF, 0xC3, 0x0D, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D, 0xB1, 0x30, 0x03, 0x1B, 0xD8, 0xC0, 0x1F, 0x8F, 0xB3, 0x31, 0x03, 0x1B, 0xD8, 0xC0, 0x0C, 0x8D
};
const byte init_commands[]{
0xAE, // disp off
0xD5, // clk div
0x80, // suggested ratio
0xA8, 0x3F, // set multiplex: 0x1F for 128x32, 0x3F for 128x64
0xD3,0x0, // display offset
0x40, // start line
0x8D, // charge pump
0x14, // charge pump arg
0x20,0x0, // memory mode
0xA1, // seg remap 1
0xC8, // comscandec
0xDA,0x02, // set compins - use 0x12 for 128x64
0x81,0x7F, // set contrast (halfway)
0xD9,0x22, // set precharge (default)
0xDb,0x40, // set vcom detect
// My stuff, starting with memory adressing type (go with Horizontal first)
// Original:
0x20, // address mode
0x00, // Horizontal-0x00, Vertical-0x01, Page-0x02
0xA4,
0xAF,
0x22, // Set page address range
0,
7, // 4 pages = 8*4 = 32 pixels
0x21, // column start and end address
0,
127,
// Vertical:
/*
In Horizontal and Vertical mode you:
Set the range of columns that you want to write (using 0x22)
Set the range of pages you want to write (using 0x21)
Write bytes
*/
/*
0x20, // address mode
0x01, // Horizontal-0x00, Vertical-0x01, Page-0x02
0x22, // Set column adress range
0, // Start at column 0
0x80, // End at 128
0x21, // Set page address range
0, // Start at page 1
3, // End at 4 (4 pages = 8*4 = 32 pixels)
*/
// All done, wwitch display on.
0xA4, // display all on
0xA7, // Invert screen (A6-normal, A7-inverted)
0xAf // display on
};
// =================================================================================
// SETUP()
// =================================================================================
//
void setup() {
Serial.begin(9600);
Wire.begin();
delay(200);
InitDisplay();
delay(200);
clearDisplay();
//SendCommand(0xA6); // Not inverted
//delay(300);
SendCommand(0xA7); // Inverted
delay(300);
// ---------------------------------
// Moving this here temporarily
//SendCommand(0x20); // address mode
//SendCommand(0x02); // Horizontal-0x00, Vertical-0x01, Page-0x02
randomSeed(analogRead(0));
// Init and Shuffle fade array
for(int i = 0; i < FADE_SIZE; i++) {
fade[i] = i;
}
shuffle(fade, FADE_SIZE);
//DrawBackground();
//DrawBackgroundOffset(0);
FadeIn();
delay(500);
Serial.println("Start!");
}
char xpos = 0;
// =================================================================================
// LOOP()
// =================================================================================
//
void loop() {
/*
for (int i=0; i<128; i++) {
cursorTo(0, 0);
DrawBackgroundOffset(xpos);
delay(30);
}
*/
delay(1000);
}
#define DATA_MODE 0x40
//#define DATA_MODE 0xC0 // Really Single command??
//#define DATA_MODE 0x00
void FadeIn() {
for (int i=0; i<FADE_SIZE; i++) {
int index = fade[i];
int slice = pgm_read_byte(logo + index);
int col = index % LOGO_WIDTH;
int page = (int)index/LOGO_WIDTH;
SetCursor(col, page);
SendData(slice);
}
}
// Nicked from Stack Overflow. It's mine now.
void shuffle(int *array, size_t n)
{
if (n > 1)
{
size_t i;
for (i = 0; i < n - 1; i++)
{
size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
int t = array[j];
array[j] = array[i];
array[i] = t;
}
}
}
void InitDisplay() {
//int len = sizeof(init_commands) / sizeof(init_commands[0]);
int len = sizeof(init_commands);
for (int i=0; i<len; i++) {
SendCommand(init_commands[i]);
}
clearDisplay();
}
/*
void remove_element(char *array, int index, int array_length)
{
int i;
for(i = index; i < array_length - 1; i++) array[i] = array[i + 1];
fadeCursor--;
}
*/
/*
void DrawBackground() {
int count = 0;
int size = sizeof(logo) / sizeof(logo[0]);
cursorTo(0,0);
//for (int i=0; i<80; i++) {
// SendData(pgm_read_byte(logo + i));
//}
for (int i=0; i<size; i++) {
SendData(pgm_read_byte(logo + i));
//if (!(i % 80)) {
// int page = (int)i/80;
// SetCursor(0, page);
//}
count++;
if (count == 80) {
int page = (int)i/80;
int col = (i % 80);
page++;
Serial.print("col: ");
Serial.print(col);
Serial.print(" page: ");
Serial.print(page);
Serial.print(" size: ");
Serial.print(size);
Serial.println();
SetCursor(col, page);
count = 0;
}
}
}
*/
void SetCursor(int col, int page) {
SendCommand(0x21); // Set Column Address
SendCommand(col); // Column start address
//SendCommand(0x50); // Column end address
SendCommand(col); // Column end address
SendCommand(0x22); // Set Page Address
SendCommand(page); // Page start address
SendCommand(page); // Page end address
}
void ResetCursor() {
SendCommand(0x21); // Set Column Address
SendCommand(0x00); // Column start address
SendCommand(0x00); // Column end address
SendCommand(0x22); // Set Page Address
SendCommand(0x00); // Page start address
SendCommand(0x00); // Page end address
}
void SendRawPixel() {
Wire.beginTransmission(0x3c);
Wire.write(0x40);
Wire.write(1);
Wire.endTransmission();
}
void clearDisplay() {
// 128x32 has 4 pages
for(byte page=0; page<4; page++) {
cursorTo(0, page);
for(byte column=0; column<128; column++){ //clear all columns
SendData(0);
}
}
cursorTo(0,0);
}
void cursorTo( unsigned char col, unsigned char row ){
// From original Game85
SendCommand(0x00 | (0x0F & col) ); // low col = 0
SendCommand(0x10 | (0x0F & (col >> 4)) ); // hi col = 0
SendCommand(0xb0 | (0x03 & row) ); // hi col = 0
// Oz library. Probably not using this.
//SendCommand(0x00 + (8*col & 0x0F)); //set column lower address
//SendCommand(0x10 + ((8*col>>4)&0x0F)); //set column higher address
//SendCommand(0xB0 + row); //set page address
}
void drawPixel(uint8_t x, uint8_t y) {
//cursorTo(x, y >> 3); // page (row)
cursorTo(x, y);
Wire.beginTransmission(0x3c);
Wire.write(0x40);
//Wire.write(0 | (1 << y % 8)); // Bit shift the remainder.
Wire.write(1);
Wire.endTransmission();
}
void SendCommand(byte cmd) {
Wire.beginTransmission(0x3C); // START I2C COMMUNICATION WITH OLED (0x3c=OLED ADDRESS)
Wire.write(0x80); // WRITE I2C COMMAND WORD TO OLED
Wire.write(cmd); // SEND I2C VALUE TO OLED
Wire.endTransmission(); // STOP I2C COMMUNICATION
}
void SendData(unsigned char data){
Wire.beginTransmission(0x3C); // Begin transmitting
Wire.write(0x40); // Data mode
Wire.write(data); // Send data
Wire.endTransmission(); // Stop transmitting
}
// ============================================================================================================
// DrawBackgroundOffset
// ============================================================================================================
//
/*
void DrawBackgroundOffset(char xpos) {
cursorTo(0, 0);
char startPos = xpos * 4;
TinyWireM.beginTransmission(0x3C); // Begin transmitting
TinyWireM.send(DATA_MODE); // Data mode, multiple data (0x40-single datum, 0xC0-multiple)
for (int i=startPos; i<512; i++) {
//SendData(pgm_read_byte(flap + i));
TinyWireM.send(pgm_read_byte(flap + i)); // Send data
delay(5);
count++;
if (count > 32) {
TinyWireM.endTransmission(); // Stop transmitting
delay(20);
TinyWireM.beginTransmission(I2C_ADDRESS); // Begin transmitting
TinyWireM.send(DATA_MODE); // Data mode
count = 0;
}
}
TinyWireM.endTransmission(); // Stop transmitting
//if (startPos) {
// for (int i=0; i<startPos; i++) {
// SendData(pgm_read_byte(flap + i));
// }
//}
}
void DrawBackgroundChunks() {
int size = sizeof(flap) / sizeof(flap[0]);
for (int i=0; i<512; i++) {
SendData(pgm_read_byte(flap + i));
}
}
*/