Κώδικας:
//#define DEBUG
#include <Time.h>
#include <Adafruit_GFX_AS.h> // Core graphics library
#include <Adafruit_ILI9341_8bit_AS.h> // Hardware-specific library
#include <SD.h>
#include <SPI.h>
#define MCUFRIENT_2_4_TFT 0x9341
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
#define SD_CS 10 // Set the chip select line to whatever you use (10 doesnt conflict with the library)
#define TIME_HEADER "Τ" // Header tag for serial time sync message
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
// 16-bit color values:
#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0x07FF//
#define GREEN 0xFBFF//
#define BLUE 0xFFE0//
#define SILVER 0xC618
#define GRAY 0x8410
#define MAROON 0x8000
#define YELLOW 0xFFE0
#define OLIVE 0x8400
#define LIME 0x07E0
#define AQUA 0x07FF
#define TEAL 0x0410
#define NAVY 0xFF0F//
#define FUCHSIA 0xF81F
#define PURPLE 0x8010
#define TRANSPARENT 0xFFFFFFFF
char *timeBuffer[] = {"0.bmp","1.bmp", "2.bmp", "3.bmp",
"4.bmp","5.bmp", "6.bmp", "7.bmp",
"8.bmp","9.bmp", "col.bmp"};
char *weekDaysBuffer[] = {0,"sunday.bmp", "monday.bmp", "tuesday.bmp",
"wednesday.bmp","thursday.bmp", "friday.bmp", "saturday.bmp",
"sunday.bmp"};
#define ANGLE_0 0
#define ANGLE_90 1
#define ANGLE_180 2
#define ANGLE_270 3
int tenths = 0;
int units = 0 ;
int temp,hours,minutes,seconds = 0;
unsigned long pctime;
boolean updateTime = false;
boolean updateDate = false;
uint8_t spi_save;
//=======================================================================
Adafruit_ILI9341_8bit_AS tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
//=======================================================================
void setup(void)
{
Serial.begin(9600);
SD.begin(SD_CS);
#ifdef DEBUG
Serial.println("Sketch'es location:");
Serial.println("C:\\Users\\MANOS\\Documents\\HN\\DXP\\AVR 2_4 TFT\\TFT_11");
Serial.println(F("Initializing SD card..."));
if (!SD.begin(SD_CS))
{
Serial.println(F("Initialization failed!"));
return;
}
Serial.println(F("Initialization done."));
spi_save = SPCR;
#endif // DEBUG
tft.reset();
delay(10);
tft.begin(0x9341);
tft.fillScreen(BLACK);
tft.setRotation(ANGLE_270);
bmpDraw("clock2.bmp", 30, 0);
delay(2000);
tft.setCursor(30, 35);
tft.setTextColor(BLUE);
tft.setTextSize(5);
tft.print("Manos Mar");
tft.setCursor(50, 95);
tft.print("TFT 2.4\"");
tft.setCursor(85, 155);
tft.print("Clock");
delay(3000);
tft.fillScreen(BLACK);
pinMode(13, OUTPUT);
tft.setCursor(15, 70);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.println("Waiting for sync message");
tft.println(" from Processing or from ");
tft.println("Serial Monitor with format");
tft.println("Txxxxxxxxxx(x = Unix time)");
setSyncProvider(requestSync); //set function to call when sync required
Serial.println("Waiting for sync message...");
tft.fillCircle(15, 210, 12, RED);
}
//=======================================================================
void loop()
{
if (Serial.available())
{
processSyncMessage();
}
if (timeStatus()!= timeNotSet)
{
digitalClockDisplay();
}
if (timeStatus() == timeSet)
{
digitalWrite(13, HIGH); // LED on if synced
}
else
{
digitalWrite(13, LOW); // LED off if needs refresh
}
delay(200);
}
//=======================================================================
#define BUFFPIXEL 20
void bmpDraw(char *filename, int x, int y)
{
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean goodBmp = false; // Set to true on valid header parse
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col;
uint8_t r, g, b;
uint32_t pos = 0, startTime = millis();
uint8_t lcdidx = 0;
boolean first = true;
if((x >= tft.width()) || (y >= tft.height())) return;
// Open requested file on SD card
if ((bmpFile = SD.open(filename)) == NULL)
{
Serial.println(F("File not found"));
return;
}
// Parse BMP header
if(read16(bmpFile) == 0x4D42)
{ // BMP signature
Serial.println(read32(bmpFile));
(void)read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
Serial.println(bmpImageoffset, DEC);
// Read DIB header
Serial.println(read32(bmpFile));
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
if(read16(bmpFile) == 1)
{ // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
Serial.println(bmpDepth);
if((bmpDepth == 24) && (read32(bmpFile) == 0))
{ // 0 = uncompressed
goodBmp = true; // Supported BMP format -- proceed!
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if(bmpHeight < 0)
{
bmpHeight = -bmpHeight;
flip = false;
}
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if((x+w-1) >= tft.width()) w = tft.width() - x;
if((y+h-1) >= tft.height()) h = tft.height() - y;
// Set TFT address window to clipped image bounds
for (row=0; row<h; row++)
{ // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if(bmpFile.position() != pos)
{ // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col=0; col<w; col++)
{ // For each column...
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
// Push LCD buffer to the display first
if(lcdidx > 0)
{
tft.drawPixel(col+x, row+y, lcdbuffer[lcdidx]);
lcdidx = 0;
first = false;
}
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}
// Convert pixel from BMP to TFT format
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
lcdbuffer[lcdidx] = color565(r,g,b);
tft.drawPixel(col+x, row+y, lcdbuffer[lcdidx]);
} // end pixel
} // end scanline
// Write any remaining data to LCD
if(lcdidx > 0)
{
tft.drawPixel(col+x, row+y, lcdbuffer[lcdidx]);
}
} // end goodBmp
}
}
bmpFile.close();
if(!goodBmp) Serial.println(F("BMP format not recognized."));
}
//=======================================================================
uint16_t read16(File &f)
{
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}
//=======================================================================
uint32_t read32(File &f)
{
uint32_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read();
((uint8_t *)&result)[2] = f.read();
((uint8_t *)&result)[3] = f.read(); // MSB
return result;
}
//=======================================================================
void digitalClockDisplay()
{
// digital clock display of the time
byte zeroes;
printDigits(hour());
bmpDraw(tenths[timeBuffer], 0, 40);
bmpDraw(units[timeBuffer], 65, 40);
Serial.print(":");
bmpDraw("col.bmp", 129, 40);
printDigits(minute());
bmpDraw(tenths[timeBuffer], 193, 40);
bmpDraw(units[timeBuffer], 257, 40);
tft.setCursor(40, 5);
if(updateDate == true)
{
tft.fillRect(40, 5, 420, 60, BLACK);
tft.setTextColor(NAVY);
tft.setTextSize(4);
tft.print(day());
tft.print("/");
tft.print(month());
tft.print("/");
tft.print(year());
updateDate = false;
}
bmpDraw(weekday()[weekDaysBuffer], 0, 190);
tft.setCursor(100, 200);
tft.setTextColor(WHITE);
tft.setTextSize(4);
/* zeroes = hour();
if(zeroes < 10)
{
tft.print("0");
}
tft.print(hour());
tft.print(":");
zeroes = minute();
if(zeroes < 10)
{
tft.print("0");
}
tft.print(minute());
tft.print(":");
zeroes = second();
if(zeroes < 10)
{
tft.print("0");
}
tft.print(second());
tft.print(" ");
*/
updateDate = true;
}
//=======================================================================
void printDigits(byte digits)
{
if(digits < 10)
{
Serial.print('0');
}
Serial.print(digits,DEC);
units = (digits%10);
tenths = ((digits/10)%10);
}
//=======================================================================
void processSyncMessage()
{
byte serBuffer = Serial.read();
const unsigned long DEFAULT_TIME = 1420070400; // Jan 1 2015
if(serBuffer == 'T' )
{
pctime = Serial.parseInt();
tft.setCursor(40, 205);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.fillRect(0, 190, 320, 50, BLACK);
tft.fillCircle(15, 210, 12, GREEN);
tft.print(pctime);
delay(1000);
if(pctime >= DEFAULT_TIME)
{ // check the integer is a valid time (greater than Jan 1 2015)
setTime(pctime); // Sync Arduino clock to the time received on the serial port
tft.fillRect(0, 190, 320, 50, BLACK);
tft.fillCircle(15, 210, 12, GREEN);
tft.setCursor(40, 205);
tft.setTextSize(2);
tft.setTextColor(WHITE);
tft.print("Clock is set.");
delay(1000);
tft.fillRect(0, 190, 320, 50, BLACK);
updateTime = true;
updateDate = true;
}
}
}
//=======================================================================
time_t requestSync()
{
Serial.write(TIME_REQUEST);
return 0; // the time will be sent later in response to serial mesg
}
//=======================================================================
uint16_t color565(uint8_t r, uint8_t g, uint8_t b)
{
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}