diff --git a/DEV_Config.cpp b/DEV_Config.cpp new file mode 100644 index 0000000..aa46385 --- /dev/null +++ b/DEV_Config.cpp @@ -0,0 +1,55 @@ +/***************************************************************************** +* | File : DEV_Config.c +* | Author : Waveshare team +* | Function : Hardware underlying interface +* | Info : +* Used to shield the underlying layers of each master +* and enhance portability +*---------------- +* | This version: V1.0 +* | Date : 2018-11-22 +* | Info : + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +******************************************************************************/ +#include "DEV_Config.h" + +void GPIO_Init() +{ + pinMode(DEV_CS_PIN, OUTPUT); + pinMode(DEV_RST_PIN, OUTPUT); + pinMode(DEV_DC_PIN, OUTPUT); + pinMode(DEV_BL_PIN, OUTPUT); + analogWrite(DEV_BL_PIN,140); + } + void Config_Init() + { + + GPIO_Init(); + + //Serial + Serial.begin(115200); + + //spi + SPI.setDataMode(SPI_MODE3); + SPI.setBitOrder(MSBFIRST); + SPI.setClockDivider(SPI_CLOCK_DIV2); + SPI.begin(); + } diff --git a/DEV_Config.h b/DEV_Config.h new file mode 100644 index 0000000..1857f47 --- /dev/null +++ b/DEV_Config.h @@ -0,0 +1,80 @@ +/***************************************************************************** +* | File : DEV_Config.c +* | Author : Waveshare team +* | Function : Hardware underlying interface +* | Info : +* Used to shield the underlying layers of each master +* and enhance portability +*---------------- +* | This version: V1.0 +* | Date : 2018-11-22 +* | Info : + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +******************************************************************************/ +#ifndef _DEV_CONFIG_H_ +#define _DEV_CONFIG_H_ + +#include +#include +#include +#include "Debug.h" +#include + + + +#define UBYTE uint8_t +#define UWORD uint16_t +#define UDOUBLE uint32_t + +/** + * GPIO config +**/ +#define DEV_CS_PIN 10 +#define DEV_DC_PIN 7 +#define DEV_RST_PIN 8 +#define DEV_BL_PIN 9 + + +/** + * GPIO read and write +**/ +#define DEV_Digital_Write(_pin, _value) digitalWrite(_pin, _value == 0? LOW:HIGH) +#define DEV_Digital_Read(_pin) digitalRead(_pin) + + +/** + * SPI +**/ +#define DEV_SPI_WRITE(_dat) SPI.transfer(_dat) + +/** + * delay x ms +**/ +#define DEV_Delay_ms(__xms) delay(__xms) + +/** + * PWM_BL +**/ + #define DEV_Set_PWM(_Value) analogWrite(DEV_BL_PIN, _Value) + +/*-----------------------------------------------------------------------------*/ + void Config_Init(); +#endif diff --git a/LCD_Driver.cpp b/LCD_Driver.cpp new file mode 100644 index 0000000..8e5dd87 --- /dev/null +++ b/LCD_Driver.cpp @@ -0,0 +1,267 @@ +/***************************************************************************** +* | File : LCD_Driver.c +* | Author : Waveshare team +* | Function : LCD driver +* | Info : +*---------------- +* | This version: V1.0 +* | Date : 2018-12-18 +* | Info : +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +******************************************************************************/ +#include "LCD_Driver.h" +/******************************************************************************* +function: + Hardware reset +*******************************************************************************/ +static void LCD_Reset(void) +{ + DEV_Delay_ms(200); + DEV_Digital_Write(DEV_RST_PIN, 0); + DEV_Delay_ms(200); + DEV_Digital_Write(DEV_RST_PIN, 1); + DEV_Delay_ms(200); +} + +/******************************************************************************* +function: + Write data and commands +*******************************************************************************/ +static void LCD_Write_Command(UBYTE data) +{ + DEV_Digital_Write(DEV_CS_PIN, 0); + DEV_Digital_Write(DEV_DC_PIN, 0); + DEV_SPI_WRITE(data); +} + +static void LCD_WriteData_Byte(UBYTE data) +{ + DEV_Digital_Write(DEV_CS_PIN, 0); + DEV_Digital_Write(DEV_DC_PIN, 1); + DEV_SPI_WRITE(data); + DEV_Digital_Write(DEV_CS_PIN,1); +} + +void LCD_WriteData_Word(UWORD data) +{ + DEV_Digital_Write(DEV_CS_PIN, 0); + DEV_Digital_Write(DEV_DC_PIN, 1); + DEV_SPI_WRITE((data>>8) & 0xff); + DEV_SPI_WRITE(data); + DEV_Digital_Write(DEV_CS_PIN, 1); +} + + +/****************************************************************************** +function: + Common register initialization +******************************************************************************/ +void LCD_Init(void) +{ + LCD_Reset(); + + LCD_Write_Command(0x11); //Sleep out + + LCD_Write_Command(0xCF); + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(0xC1); + LCD_WriteData_Byte(0X30); + LCD_Write_Command(0xED); + LCD_WriteData_Byte(0x64); + LCD_WriteData_Byte(0x03); + LCD_WriteData_Byte(0X12); + LCD_WriteData_Byte(0X81); + LCD_Write_Command(0xE8); + LCD_WriteData_Byte(0x85); + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(0x79); + LCD_Write_Command(0xCB); + LCD_WriteData_Byte(0x39); + LCD_WriteData_Byte(0x2C); + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(0x34); + LCD_WriteData_Byte(0x02); + LCD_Write_Command(0xF7); + LCD_WriteData_Byte(0x20); + LCD_Write_Command(0xEA); + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(0x00); + LCD_Write_Command(0xC0); //Power control + LCD_WriteData_Byte(0x1D); //VRH[5:0] + LCD_Write_Command(0xC1); //Power control + LCD_WriteData_Byte(0x12); //SAP[2:0];BT[3:0] + LCD_Write_Command(0xC5); //VCM control + LCD_WriteData_Byte(0x33); + LCD_WriteData_Byte(0x3F); + LCD_Write_Command(0xC7); //VCM control + LCD_WriteData_Byte(0x92); + LCD_Write_Command(0x3A); // Memory Access Control + LCD_WriteData_Byte(0x55); + LCD_Write_Command(0x36); // Memory Access Control + LCD_WriteData_Byte(0x08); + LCD_Write_Command(0xB1); + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(0x12); + LCD_Write_Command(0xB6); // Display Function Control + LCD_WriteData_Byte(0x0A); + LCD_WriteData_Byte(0xA2); + + LCD_Write_Command(0x44); + LCD_WriteData_Byte(0x02); + + LCD_Write_Command(0xF2); // 3Gamma Function Disable + LCD_WriteData_Byte(0x00); + LCD_Write_Command(0x26); //Gamma curve selected + LCD_WriteData_Byte(0x01); + LCD_Write_Command(0xE0); //Set Gamma + LCD_WriteData_Byte(0x0F); + LCD_WriteData_Byte(0x22); + LCD_WriteData_Byte(0x1C); + LCD_WriteData_Byte(0x1B); + LCD_WriteData_Byte(0x08); + LCD_WriteData_Byte(0x0F); + LCD_WriteData_Byte(0x48); + LCD_WriteData_Byte(0xB8); + LCD_WriteData_Byte(0x34); + LCD_WriteData_Byte(0x05); + LCD_WriteData_Byte(0x0C); + LCD_WriteData_Byte(0x09); + LCD_WriteData_Byte(0x0F); + LCD_WriteData_Byte(0x07); + LCD_WriteData_Byte(0x00); + LCD_Write_Command(0XE1); //Set Gamma + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(0x23); + LCD_WriteData_Byte(0x24); + LCD_WriteData_Byte(0x07); + LCD_WriteData_Byte(0x10); + LCD_WriteData_Byte(0x07); + LCD_WriteData_Byte(0x38); + LCD_WriteData_Byte(0x47); + LCD_WriteData_Byte(0x4B); + LCD_WriteData_Byte(0x0A); + LCD_WriteData_Byte(0x13); + LCD_WriteData_Byte(0x06); + LCD_WriteData_Byte(0x30); + LCD_WriteData_Byte(0x38); + LCD_WriteData_Byte(0x0F); + LCD_Write_Command(0x29); //Display on +} + +/****************************************************************************** +function: Set the cursor position +parameter : + Xstart: Start UWORD x coordinate + Ystart: Start UWORD y coordinate + Xend : End UWORD coordinates + Yend : End UWORD coordinatesen +******************************************************************************/ +void LCD_SetWindow(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend) +{ + LCD_Write_Command(0x2a); + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(Xstart & 0xff); + LCD_WriteData_Byte((Xend - 1) >> 8); + LCD_WriteData_Byte((Xend - 1) & 0xff); + + LCD_Write_Command(0x2b); + LCD_WriteData_Byte(0x00); + LCD_WriteData_Byte(Ystart & 0xff); + LCD_WriteData_Byte((Yend - 1) >> 8); + LCD_WriteData_Byte((Yend - 1) & 0xff); + + LCD_Write_Command(0x2C); +} + +/****************************************************************************** +function: Settings window +parameter : + Xstart: Start UWORD x coordinate + Ystart: Start UWORD y coordinate + +******************************************************************************/ +void LCD_SetCursor(UWORD X, UWORD Y) +{ + LCD_Write_Command(0x2a); + LCD_WriteData_Byte(X >> 8); + LCD_WriteData_Byte(X); + LCD_WriteData_Byte(X >> 8); + LCD_WriteData_Byte(X); + + LCD_Write_Command(0x2b); + LCD_WriteData_Byte(Y >> 8); + LCD_WriteData_Byte(Y); + LCD_WriteData_Byte(Y >> 8); + LCD_WriteData_Byte(Y); + + LCD_Write_Command(0x2C); +} + +/****************************************************************************** +function: Clear screen function, refresh the screen to a certain color +parameter : + Color : The color you want to clear all the screen +******************************************************************************/ +void LCD_Clear(UWORD Color) +{ + unsigned int i,j; + LCD_SetWindow(0, 0, LCD_WIDTH, LCD_HEIGHT); + DEV_Digital_Write(DEV_DC_PIN, 1); + for(i = 0; i < LCD_WIDTH; i++){ + for(j = 0; j < LCD_HEIGHT; j++){ + DEV_SPI_WRITE((Color>>8)&0xff); + DEV_SPI_WRITE(Color); + } + } +} + +/****************************************************************************** +function: Refresh a certain area to the same color +parameter : + Xstart: Start UWORD x coordinate + Ystart: Start UWORD y coordinate + Xend : End UWORD coordinates + Yend : End UWORD coordinates + color : Set the color +******************************************************************************/ +void LCD_ClearWindow(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend,UWORD color) +{ + UWORD i,j; + LCD_SetWindow(Xstart, Ystart, Xend-1,Yend-1); + for(i = Ystart; i <= Yend-1; i++){ + for(j = Xstart; j <= Xend-1; j++){ + LCD_WriteData_Word(color); + } + } +} + +/****************************************************************************** +function: Draw a point +parameter : + X : Set the X coordinate + Y : Set the Y coordinate + Color : Set the color +******************************************************************************/ +void LCD_DrawPaint(UWORD x, UWORD y, UWORD Color) +{ + LCD_SetCursor(x, y); + LCD_WriteData_Word(Color); +} diff --git a/LCD_Driver.h b/LCD_Driver.h new file mode 100644 index 0000000..4012548 --- /dev/null +++ b/LCD_Driver.h @@ -0,0 +1,51 @@ +/***************************************************************************** +* | File : LCD_Driver.h +* | Author : Waveshare team +* | Function : LCD driver +* | Info : +*---------------- +* | This version: V1.0 +* | Date : 2018-12-18 +* | Info : +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +******************************************************************************/ +#ifndef __LCD_DRIVER_H +#define __LCD_DRIVER_H + +#include "DEV_Config.h" + +#define LCD_WIDTH 240 //LCD width +#define LCD_HEIGHT 320 //LCD height + + +void LCD_WriteData_Word(UWORD da); + +void LCD_SetCursor(UWORD X, UWORD Y); +void LCD_SetWindow(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend); +void LCD_DrawPaint(UWORD x, UWORD y, UWORD Color); + +void LCD_Init(void); +void LCD_SetBackLight(UWORD Value); + +void LCD_Clear(UWORD Color); +void LCD_ClearWindow(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend,UWORD color); + +#endif diff --git a/arduino_clock.ino b/arduino_clock.ino new file mode 100644 index 0000000..d1b99bf --- /dev/null +++ b/arduino_clock.ino @@ -0,0 +1,175 @@ +#include +#include +#include "LCD_Driver.h" +#include "GUI_Paint.h" +#include "image.h" +#include + +RTC_DS1307 rtc; + +int DIGIT_SIZE = 40; + +// Month + weekday names +const char* MONTH_NAMES[] = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" +}; + +const char* WEEKDAY_NAMES[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" +}; + +// --------------------------- +// DRAW HELPERS +// --------------------------- +void drawSegment(int x, int y, int w, int h, uint16_t color) { + Paint_DrawRectangle(x, y, x + w, y + h, color, + DOT_PIXEL_1X1, DRAW_FILL_FULL); +} + +void drawDigit(int x, int y, int size, int digit, uint16_t color) { + int thick = size / 5; + int longSeg = size; + int wideSeg = size; + + bool A=false, B=false, C=false, D=false, E=false, F=false, G=false; + + switch (digit) { + case 0: A=B=C=D=E=F=true; break; + case 1: B=C=true; break; + case 2: A=B=G=E=D=true; break; + case 3: A=B=G=C=D=true; break; + case 4: F=G=B=C=true; break; + case 5: A=F=G=C=D=true; break; + case 6: A=F=G=E=C=D=true; break; + case 7: A=B=C=true; break; + case 8: A=B=C=D=E=F=G=true; break; + case 9: A=B=C=D=F=G=true; break; + } + + if (A) drawSegment(x + thick, y, wideSeg, thick, color); + if (B) drawSegment(x + wideSeg + thick, y + thick, thick, longSeg, color); + if (C) drawSegment(x + wideSeg + thick, y + thick + longSeg + thick, thick, longSeg, color); + if (D) drawSegment(x + thick, y + 2*longSeg + 2*thick, wideSeg, thick, color); + if (E) drawSegment(x, y + thick + longSeg + thick, thick, longSeg, color); + if (F) drawSegment(x, y + thick, thick, longSeg, color); + if (G) drawSegment(x + thick, y + longSeg + thick, wideSeg, thick, color); +} + +void drawColon(int x, int y, int size, uint16_t color) { + int dot = size / 5; + drawSegment(x, y + size/2 - 10, dot, dot, color); + drawSegment(x, y + size + 10, dot, dot, color); +} + +// --------------------------- +// SETUP +// --------------------------- +void setup() { + Wire.begin(); + rtc.begin(); + + // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // run once if needed + + Config_Init(); + LCD_Init(); + LCD_Clear(BLACK); + + Paint_NewImage(LCD_WIDTH, LCD_HEIGHT, 90, BLACK); + Paint_Clear(BLACK); + + Paint_DrawString_EN(30, 110, "Starting Up...", &Font24, BLACK, GREEN); + delay(1000); + Paint_Clear(BLACK); +} + +// --------------------------- +// LOOP +// --------------------------- +void loop() { + static unsigned long lastUpdate = 0; + static char lastTime[16] = ""; + + if (millis() - lastUpdate >= 1000) { + lastUpdate = millis(); + + DateTime now = rtc.now(); + + // Convert to 12-hour format + int hour12 = now.hour(); + if (hour12 == 0) hour12 = 12; + else if (hour12 > 12) hour12 -= 12; + + char timebuf[16]; + sprintf(timebuf, "%02d:%02d", hour12, now.minute()); + + // Build weekday + date strings + char weekdaybuf[16]; + char datebuf[32]; + + sprintf(weekdaybuf, "%s", WEEKDAY_NAMES[now.dayOfTheWeek()]); + sprintf(datebuf, "%s %d, %d", + MONTH_NAMES[now.month() - 1], + now.day(), + now.year()); + + // Draw weekday + date (always update) + Paint_DrawString_EN(15, 160, weekdaybuf, &Font24, BLACK, WHITE); + Paint_DrawString_EN(15, 200, datebuf, &Font24, BLACK, WHITE); + + // Only update digits that changed + if (strcmp(timebuf, lastTime) != 0) { + + int size = DIGIT_SIZE; + + // Extract digits + int h1 = hour12 / 10; + int h2 = hour12 % 10; + int m1 = now.minute() / 10; + int m2 = now.minute() % 10; + + // HOUR tens + if (lastTime[0] != timebuf[0]) { + if (h1 == 0) + { + drawDigit(10, 20, size, h1, BLACK); + } + else + { + drawDigit(10, 20, size, lastTime[0] - '0', BLACK); + drawDigit(10, 20, size, h1, WHITE); + } + } + + // HOUR ones + if (lastTime[1] != timebuf[1]) { + drawDigit(10 + size + 30, 20, size, lastTime[1] - '0', BLACK); + drawDigit(10 + size + 30, 20, size, h2, WHITE); + } + + // COLON (always drawn) + Paint_DrawRectangle(10 + 2*(size + 35), 50, + 10 + 2*(size + 35) + 10, 60, + WHITE, DOT_PIXEL_1X1, DRAW_FILL_FULL); + + Paint_DrawRectangle(10 + 2*(size + 35), 100, + 10 + 2*(size + 35) + 10, 110, + WHITE, DOT_PIXEL_1X1, DRAW_FILL_FULL); + + // MIN tens + if (lastTime[3] != timebuf[3]) { + drawDigit(10 + 2*(size + 30) + 30, 20, size, lastTime[3] - '0', BLACK); + drawDigit(10 + 2*(size + 30) + 30, 20, size, m1, WHITE); + } + + // MIN ones + if (lastTime[4] != timebuf[4]) { + drawDigit(10 + 3*(size + 30) + 30, 20, size, lastTime[4] - '0', BLACK); + drawDigit(10 + 3*(size + 30) + 30, 20, size, m2, WHITE); + } + + strcpy(lastTime, timebuf); + } + } +}