#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <SD.h>
#include <SPI.h>
LiquidCrystal_I2C lcd(0x27,20,4);
#define BUZZER_PIN 2
#define LED_RED_PIN 3
#define LED_GREEN_PIN 4
#define CMD_ENSTROBE 0x01
#define CMD_DISTROBE 0x02
const int chipSelect = 53; // Change this to your SD module's chip select pin
#define CMD_DRAWPIX 0x10
#define CMD_DRAWSCREEN 0x11
int screenWidth=128;
int screenHeight=64;
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} rgba_t;
void enableStrobe(uint8_t strobe)
{
Wire.beginTransmission(0x21);
Wire.write(CMD_ENSTROBE);
Wire.write(strobe);
Wire.endTransmission();
}
void disableStrobe(uint8_t strobe)
{
Wire.beginTransmission(0x21);
Wire.write(CMD_DISTROBE);
Wire.write(strobe);
Wire.endTransmission();
}
void drawPixel(uint32_t x, uint32_t y, rgba_t color)
{
Wire.beginTransmission(0x22);
Wire.write(CMD_DRAWPIX);
uint8_t writeValues[4];
uint8_t posValues[8];
writeValues[0] = color.r;
writeValues[1] = color.g;
writeValues[2] = color.b;
writeValues[3] = color.a;
posValues[0] = (x >> 24) & 0xff;
posValues[1] = (x >> 16) & 0xff;
posValues[2] = (x >> 8) & 0xff;
posValues[3] = (x) & 0xff;
posValues[4] = (y >> 24) & 0xff;
posValues[5] = (y >> 16) & 0xff;
posValues[6] = (y >> 8) & 0xff;
posValues[7] = (y) & 0xff;
for(int i=0; i<4; i++)
{
Wire.write(writeValues[i]);
}
for(int i=0; i<8; i++)
{
Wire.write(posValues[i]);
}
Wire.endTransmission();
}
uint32_t x, y=0;
void drawHLine(uint32_t width, uint32_t y, rgba_t color)
{
for(int x=0; x<width; x++)
{
drawPixel(x, y, color);
}
}
void drawVLine(uint32_t height, uint32_t x, rgba_t color)
{
for(int y=0; y<height; y++)
{
drawPixel(x, y, color);
}
}
void drawGrid()
{
for(y=0; y<screenWidth; y+=6)
{
drawVLine(screenHeight, y, (rgba_t){.r=0, .g=0, .b=0, .a=0xff});
}
for(x=0; x<screenHeight; x+=6)
{
drawHLine(screenWidth, x, (rgba_t){.r=0, .g=0, .b=0, .a=0xff});
}
}
void drawBinaryImage(int offsetX, int offsetY, int w, int h, char* filename)
{
File file = SD.open(filename, FILE_READ);
if (file) {
uint16_t x = 0+offsetX;
uint16_t y = 0+offsetY;
while (file.available()) {
// Read the RGBA data from the file
uint8_t red = file.read();
uint8_t green = file.read();
uint8_t blue = file.read();
uint8_t alpha = file.read();
rgba_t color;
color.r = red;
color.g = green;
color.b = blue;
color.a = alpha;
drawPixel(x,y, color);
// Move to the next pixel
x++;
// If we reach the end of the display width, move to the next row
if (x == offsetX+w) {
x = 0+offsetX;
y++;
}
}
} else {
Serial.println("Error opening file");
}
}
void initMsg(char* msg)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(msg);
}
void setup() {
Serial.begin(9600);
// Initialize the SD card
if (!SD.begin(chipSelect)) {
Serial.println("SD card initialization failed!");
return;
}
// init strobe circ
Wire.begin();
// put your setup code here, to run once:
lcd.init();
lcd.backlight();
// Init pins
initMsg("INIT PINS");
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
// Notify user about init with buzzer
initMsg("BEEP");
tone(BUZZER_PIN, 2000, 1000);
delay(1000);
initMsg("Set i2c Speed");
Wire.setClock(1000000);
// image
initMsg("Draw \"bg.bin\"");
drawBinaryImage(0,0, 128,64, "bg.bin"); // bg
initMsg("Draw grid");
drawGrid();
int imageWidth=128;
int imageHeight=64;
uint16_t offsetX=screenWidth/2-(imageWidth/2); // center
uint16_t offsetY=screenHeight/2-(imageHeight/2); // center
initMsg("Draw \"output.bin\"");
drawBinaryImage(offsetX,offsetY, imageWidth,imageHeight, "output.bin"); // bg
initMsg("");
lcd.print("Testing Strobe Chip.");
// disable all strobes.
for(int i=0; i<4; i++)
{
disableStrobe(i);
}
delay(1000);
digitalWrite(LED_GREEN_PIN, HIGH);
}
void loop() {
// time
tmElements_t tm;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Welcome User!");
if (RTC.read(tm)) {
lcd.setCursor(0,2);
print2digits(tm.Hour);
lcd.write(':');
print2digits(tm.Minute);
lcd.write(':');
print2digits(tm.Second);
lcd.setCursor(0,3);
lcd.print(tm.Day);
lcd.write('/');
lcd.print(tm.Month);
lcd.write('/');
lcd.print(tmYearToCalendar(tm.Year));
}
// Loop through strobes (testing)
for(int i=0; i<4; i++)
{
enableStrobe(i);
delay(500);
disableStrobe(i);
delay(500);
}
}
void print2digits(int number) {
if (number >= 0 && number < 10) {
lcd.write('0');
}
lcd.print(number);
}