#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
const uint8_t width = 128;
const uint8_t height = 64;
unsigned long long int prev_time;
// eye related variables
const uint8_t eye_width = 15,
eye_height = 20,
eye_dist = 30,
eye_radius = 5;
int8_t eye_ver_offset = 2;
int8_t cir_ver_offset = 3;
const uint8_t blink_delay = 1; // in milliseconds
// starting positions of left eye (1) and right eye (2)
const uint8_t rsp1[2] = {( (width/2) - (eye_width + (eye_dist/2)) ), ( (height/2) - (eye_height/2) )};
const uint8_t rsp2[2] = {( rsp1[0] + eye_width + eye_dist ), rsp1[1] };
const uint8_t b1 = 3;
const uint8_t b2 = 2;
Adafruit_SSD1306 display(width, height, &Wire, -1);
void setup() {
Serial.begin(115200);
prev_time = millis();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Power mode, I2C address
display.clearDisplay(); // Clear screen
display.display(); // Send to OLED
// Open eyes image
// starting positions of left eye (1) and right eye (2)
const uint8_t rsp1[2] = {( (width/2) - (eye_width + (eye_dist/2)) ), ( (height/2) - (eye_height/2) - eye_ver_offset )};
const uint8_t rsp2[2] = {( rsp1[0] + eye_width + eye_dist ), rsp1[1] };
// drawing left eye
display.fillRoundRect(rsp1[0], rsp1[1], eye_width, eye_height, eye_radius, WHITE);
// drawing right eye
display.fillRoundRect(rsp2[0], rsp2[1], eye_width, eye_height, eye_radius, WHITE);
display.display();
delay(1000);
// Blinking animation
for(int j=0; j<2; j++){
// Closing the eye
for(int i=0; i < eye_height; i+=5){
display.clearDisplay();
display.fillRoundRect(rsp1[0], (rsp1[1] + i/2), eye_width, eye_height-i, eye_radius, WHITE);
display.fillRoundRect(rsp2[0], (rsp2[1] + i/2), eye_width, eye_height-i, eye_radius, WHITE);
display.display();
delay(blink_delay);
}
// Opening the eye
for(int i=eye_height; i >= 0; i-=5){
display.clearDisplay();
display.fillRoundRect(rsp1[0], (rsp1[1] + i/2), eye_width, eye_height-i, eye_radius, WHITE);
display.fillRoundRect(rsp2[0], (rsp2[1] + i/2), eye_width, eye_height-i, eye_radius, WHITE);
display.display();
delay(blink_delay);
}
delay(1000);
}
// drawing a black circle below eye to make the eyes cute
uint8_t blk_cir_rad = eye_width / 2;
uint8_t blk_cir_Ycentre = rsp1[1] + eye_height + blk_cir_rad;
uint8_t final_cir_Ycentre = rsp1[1] + eye_height;
uint8_t csp1[2] = { (rsp1[0] + (eye_width/2)), (rsp1[1] + eye_height - cir_ver_offset) };
uint8_t csp2[2] = { (rsp2[0] + (eye_width/2)), csp1[1] };
for(blk_cir_Ycentre; blk_cir_Ycentre >= final_cir_Ycentre; blk_cir_Ycentre --){
display.fillCircle(csp1[0], blk_cir_Ycentre, blk_cir_rad, BLACK);
display.fillCircle(csp2[0], blk_cir_Ycentre, blk_cir_rad, BLACK);
display.display();
delay(blink_delay);
}
delay(1000);
// Making the eyes rect again
final_cir_Ycentre = rsp1[1] + eye_height + blk_cir_rad;
for(blk_cir_Ycentre; blk_cir_Ycentre <= final_cir_Ycentre; blk_cir_Ycentre ++){
display.clearDisplay();
// redrawing left and rigth eyes
display.fillRoundRect(rsp1[0], rsp1[1], eye_width, eye_height, eye_radius, WHITE);
display.fillRoundRect(rsp2[0], rsp2[1], eye_width, eye_height, eye_radius, WHITE);
// drawing the black circle
display.fillCircle(csp1[0], blk_cir_Ycentre, blk_cir_rad, BLACK);
display.fillCircle(csp2[0], blk_cir_Ycentre, blk_cir_rad, BLACK);
display.display();
delay(blink_delay);
}
// Making a white circle with increasing dia
for(uint8_t r_circle = 1; r_circle <= width/2 + 10; r_circle += 2){
display.fillCircle(width/2, height/2, r_circle, WHITE);
display.display();
delay(15);
}
// Making a black circle with increasing dia
for(uint8_t r_circle = 1; r_circle <= width/2 + 10; r_circle += 2){
display.fillCircle(width/2, height/2, r_circle, BLACK);
display.display();
delay(15);
}
}
void loop() {
const uint8_t text_size = 4;
if (millis() - prev_time >= 1000) {
prev_time = millis();
// Calculating elapsed time
unsigned long total_ms = prev_time;
uint8_t hour = total_ms / 3600000;
uint8_t minute = (total_ms % 3600000) / 60000;
uint8_t sec = (total_ms % 60000) / 1000;
char time[10];
sprintf(time, "%d:%02d", hour, minute);
Serial.println(time);
display.clearDisplay();
// Calculating where to print it
uint8_t time_Xlen = ((strlen(time)*5) + strlen(time) - 1)*text_size; // pixel in X axis
uint8_t time_Ylen = text_size * 7; // pixels in Y axis
// Starting points of timer
uint8_t time_Ysp_offset = 20;
uint8_t time_sp[2] = {((width - time_Xlen)/2), (((height - time_Ysp_offset) - time_Ylen)/2) };
// displaying the timer on display
display.setTextSize(text_size);
display.setTextColor(WHITE);
display.setCursor(time_sp[0], time_sp[1]);
display.print(time);
// displaying the seconds bar
float sec_scale_factor = 1.5;
uint8_t sec_bar_Yoffset = 10;
float sec_bar_size[2] = {60*sec_scale_factor, 10};
float sec_bar_sp[2] = {((width - (60*sec_scale_factor))/2), (height - sec_bar_size[1] - sec_bar_Yoffset)};
display.drawRect(sec_bar_sp[0], sec_bar_sp[1], sec_bar_size[0], sec_bar_size[1], WHITE);
display.fillRect(sec_bar_sp[0], sec_bar_sp[1], (sec*sec_scale_factor), sec_bar_size[1], WHITE);
display.display();
}
}