Professional Documents
Culture Documents
// r1 150214 - initial build with glyphs and big font character table in program memory
// r2 150227 - added RTC support
//************************************************************
#define build 1
#define revision 2
//************************************************************
#include "avr/pgmspace.h" // for memory storage in program space
#include "Wire.h"
#include "LiquidCrystal_I2C.h" // library for I@C interface
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define DS3231_I2C_ADDRESS 0x68
byte decToBcd(byte val){ return( (val/10*16) + (val%10) ); }
byte bcdToDec(byte val){ return( (val/16*10) + (val%16) ); }
void readDS3231time(byte *second,byte *minute,byte *hour,byte *dayOfWeek,byte
*dayOfMonth,byte *month,byte *year){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
// request seven bytes of data from DS3231 starting from register 00h
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth,
byte month, byte year)
{
// sets time and date data to DS3231
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set next input to start at the seconds register
Wire.write(decToBcd(second)); // set seconds
Wire.write(decToBcd(minute)); // set minutes
Wire.write(decToBcd(hour)); // set hours
Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
Wire.write(decToBcd(month)); // set month
Wire.write(decToBcd(year)); // set year (0 to 99)
Wire.endTransmission();
}
const char custom[][8] PROGMEM = {
{0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0f, 0x1f}, // char 1: top left triangle
{0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f}, // char 2: upper block
{0x00, 0x00, 0x00, 0x00, 0x10, 0x1c, 0x1e, 0x1f}, // char 3: top right triangle
{0x1f, 0x0f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00}, // char 4: bottom left triangle
{0x1f, 0x1e, 0x1c, 0x10, 0x00, 0x00, 0x00, 0x00}, // char 5: bottom right triangle
{0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00}, // char 6: bottom block
{0x1f, 0x1f, 0x1e, 0x1c, 0x18, 0x18, 0x10, 0x10} // char 7: full top right triangle
// room for another one!
};
const char bn[][30] PROGMEM = { // organized by row
// 0 1 2 3 4 5 6 7
8 9
{0x01,0x02,0x03, 0x01,0x02,0xFE, 0x01,0x02,0x03, 0x01,0x02,0x03, 0x02,0xFE,0x02,
0x02,0x02,0x02, 0x01,0x02,0x03, 0x02,0x02,0x02, 0x01,0x02,0x03, 0x01,0x02,0x03},
{0xff,0xfe,0xff, 0xFE,0xFF,0xFE, 0x01,0x02,0xFF, 0xFE,0x02,0xFF, 0xFF,0x02,0xFF,
0xFF,0x02,0x02, 0xFF,0x02,0x03, 0xFE,0x01,0x07, 0xFF,0x02,0xFF, 0xFF,0xFE,0xFF},
{0xff,0xfe,0xff, 0xFE,0xFF,0xFE, 0xFF,0xFE,0xFE, 0xFE,0xFE,0xFF, 0xFE,0xFE,0xFF,
0xFE,0xFE,0xFF, 0xFF,0xFE,0xFF, 0xFE,0xFF,0xFE, 0xFF,0xFE,0xFF, 0x04,0x06,0xFF},
{0x04,0x06,0x05, 0xFE,0x06,0xFE, 0x06,0x06,0x06, 0x04,0x06,0x05, 0xFE,0xFE,0x06,
0x04,0x06,0x05, 0x04,0x06,0x05, 0xFE,0x06,0xFE, 0x04,0x06,0x05, 0xFE,0xFE,0x06}
};
byte col, row, nb=0, bc=0; // general
byte bb[8]; // byte buffer for reading from PROGMEM
int Mode = 0;
#include "RTClib.h"
RTC_Millis RTC;
byte hr, mn, se, osec;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
volatile boolean buttonA = false;
volatile boolean buttonB = false;
volatile boolean buttonC = false;
int StateOfbuttonA = 0;
int StateOfbuttonB = 0;
int StateOfbuttonC = 0;
int NewStateOfbuttonA = 0;
int NewStateOfbuttonB = 0;
int NewStateOfbuttonC = 0;
uint8_t degC[] = { 6, 3, 3, 56, 68, 68, 68 }; // Deg C
char *mon2str(uint8_t mon, char *psz, uint8_t len)
// Get a label from PROGMEM into a char array
{
const __FlashStringHelper* const Jan = F("Jan");
const __FlashStringHelper* const Feb = F("Feb");
const __FlashStringHelper* const Mar = F("Mar");
const __FlashStringHelper* const Apr = F("Apr");
const __FlashStringHelper* const May = F("May");
const __FlashStringHelper* const Jun = F("Jun");
const __FlashStringHelper* const Jul = F("Jul");
const __FlashStringHelper* const Aug = F("Aug");
const __FlashStringHelper* const Sep = F("Sep");
const __FlashStringHelper* const Oct = F("Oct");
const __FlashStringHelper* const Nov = F("Nov");
const __FlashStringHelper* const Dec = F("Dec");
const __FlashStringHelper* str[] =
{
Jan, Feb, Mar, Apr,
May, Jun, Jul, Aug,
Sep, Oct, Nov, Dec
};
}
char *dow2str(uint8_t code, char *psz, uint8_t len)
{
const __FlashStringHelper* const Sunday = F("Sunday");
const __FlashStringHelper* const Monday = F("Monday");
const __FlashStringHelper* const Tuesday = F("Tuesday");
const __FlashStringHelper* const Wednesday = F("Wednesday");
const __FlashStringHelper* const Thursday = F("Thursday");
const __FlashStringHelper* const Friday = F("Friday");
const __FlashStringHelper* const Saturday = F("Saturday");
const __FlashStringHelper* str[] =
{
Sunday, Monday, Tuesday,
Wednesday, Thursday,Friday,
Saturday ,Sunday
};
}
//*********************** INITIAL SETUP ***********************
void setup() {
randomSeed(analogRead(0));
RTC.begin(DateTime(__DATE__, __TIME__));
Serial.begin(9600);
lcd.init(); // initialize the LCD
lcd.backlight();
lcd.begin(20, 4);
for (nb=0; nb<7; nb++ ) { // create 8 custom characters
for (bc=0; bc<8; bc++) bb[bc]= pgm_read_byte( &custom[nb][bc] );
lcd.createChar( nb+1, bb );
}
lcd.clear();
lcd.setCursor(4, 0);
lcd.print(F("4-Line LARGE"));
lcd.setCursor(4, 1);
lcd.print(F("TIME DISPLAY"));
lcd.setCursor(5, 3);
lcd.print(F("V"));
lcd.print(build);
lcd.print(F("."));
lcd.print(revision);
lcd.print(F(" "));
//lcd.print(freeRam());
lcd.print(F("B"));
// printNum(random(0,10),0);
// printNum(random(0,10),17);
delay(500);
lcd.clear();
readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
&year);
//hour=hour+1;
//setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
//setDS3231time(30,42,21,4,26,11,14);
}
//************************* MAIN LOOP ************************
void loop() {
datetinme_print();
timesetup();
}
/*
// ******************* OPERATION ROUTINES ********************
// FREERAM: Returns the number of bytes currently free in RAM
int freeRam(void) {
extern int __bss_end, *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
} else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
}*/
void datetinme_print(){
readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
&year);
// DateTime now = RTC.now();
hr =hour;
mn = minute;
se = second;
if(se != osec) {
printNum(hr/10,0);
printNum(hr%10,3);
printColon(6);
printNum(mn/10,7);
printNum(mn%10,10);
printColon(13);
printNum(se/10,14);
printNum(se%10,17);
osec = se;
}
delay(50); // not strictly necessary
}
// ********************** SUBROUTINES ************************
void printNum(byte digit, byte leftAdjust) {
for(row=0; row<4; row++) {
lcd.setCursor(leftAdjust,row);
for(col=digit*3; col <digit*3+3; col++) {
lcd.write(pgm_read_byte( &bn[row][col]) );
}
}
}
void printColon(byte leftAdjust) {
for(row=0; row<4; row++) {
lcd.setCursor(leftAdjust,row);
if(row == 1 || row == 2) lcd.print(F(".")); else lcd.print(F(" "));
}
}
void timesetup(){
Serial.println(Mode);
NewStateOfbuttonA = digitalRead(3);
NewStateOfbuttonB = digitalRead(4);
NewStateOfbuttonC = digitalRead(5);
buttonAisPressed();
buttonBisPressed();
buttonCisPressed();
if (buttonB) {
buttonB = false;
Mode++;
if (Mode > 4 ) {
Mode = 0;
}
}
if (buttonA) {
if (Mode == 0 ) {
buttonA = false;
/* contrast++;
if (contrast >= 51 ) {
contrast = 50;*/
}
else if (Mode == 1 ) {
buttonA = false;
// Mode = 0;
}
else if (Mode == 2 ) {
buttonA = false;
hour++;
if (hour >= 24 ) {
hour = 0;
}
Serial.println("up");
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 3 ) {
buttonA = false;
minute++;
if (minute >= 60 ) {
minute = 0;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 4 ) {
buttonA = false;
second = 0;
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 5 ) {
buttonA = false;
dayOfWeek++;
if (dayOfWeek >= 8 ) {
dayOfWeek = 1;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
//P.displayReset(2);
}
else if (Mode == 6 ) {
buttonA = false;
dayOfMonth++;
if (dayOfMonth >= 32 ) {
dayOfMonth = 1;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 7 ) {
buttonA = false;
month++;
if (month >= 13 ) {
month = 1;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 8 ) {
buttonA = false;
year++;
if (year >= 2035 ) {
year = 2015;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
}
if (buttonC) {
if (Mode == 0 ) {
buttonC = false;
// contrast--;
// if (contrast <= 0 ) {
// contrast = 0;
//}
}
else if (Mode == 1 ) {
buttonC = false;
// Mode = 0;
}
else if (Mode == 2 ) {
buttonC = false;
hour--;
if (hour <= 0 ) {
hour = 23;
} Serial.println("Down");
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 3 ) {
buttonC = false;
minute--;
if (minute <= 0 ) {
minute = 59;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 4 ) {
buttonC = false;
second = 0;
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 5 ) {
buttonC = false;
dayOfWeek--;
if (dayOfWeek <= 0 ) {
dayOfWeek = 7;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
//P.displayReset(2);
}
else if (Mode == 6 ) {
buttonC = false;
dayOfMonth--;
if (dayOfMonth <= 0 ) {
dayOfMonth = 31;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 7 ) {
buttonC = false;
month--;
if (month <= 0 ) {
month = 12;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);
}
else if (Mode == 8 ) {
buttonC = false;
year--;
if (year <= 2010 ) {
year = 2025;
}
setDS3231time(second,minute, hour, dayOfWeek, dayOfMonth, month,year);;
}
}
if (Mode == 0)
{
static uint32_t lastTime = 0; // millis() memory
static bool flasher = false; // seconds passing flasher
if (millis() - lastTime >= 1000)
{
lastTime = millis();
flasher = !flasher;
}
}
if (Mode == 1)
{
static uint8_t display = 0; // current display mode
{
switch (display)
{
case 0: // Time
datetinme_print();
break;
case 1: // Day
break;
case 2: // Calendar
break;
}
}
}
if (Mode == 2)
{
static uint32_t lastTime = 0; // millis() memory
static bool flasher = false; // seconds passing flasher
if (millis() - lastTime >= 200)
{
lastTime = millis();
// lcd.setCursor(4,1);
//lcd.setCursor(6,4);
lcd.cursor();
printNum(hr/10,0);
printNum(hr%10,3);
flasher = !flasher;
}
}
if (Mode == 3)
{
static uint32_t lastTime = 0; // millis() memory
static bool flasher = false; // seconds passing flasher
if (millis() - lastTime >= 200)
{
lastTime = millis();
printColon(6);
printNum(mn/10,7);
printNum(mn%10,10);
flasher = !flasher;
}
}
if (Mode == 4)
{
static uint32_t lastTime = 0; // millis() memory
static bool flasher = false; // seconds passing flasher
if (millis() - lastTime >= 200)
{
lastTime = millis();
printColon(13);
printNum(se/10,14);
printNum(se%10,17);
}
}
if (Mode == 5)
{
static uint8_t display = 0; // current display mode
}
if (Mode == 6)
{
/* P.displayAnimate();
P.getZoneStatus(2);
P.setTextEffect(2, PA_PRINT, PA_NO_EFFECT);
getdyy(szMesg);
P.displayReset(2);*/
}
if (Mode == 7)
{
/*P.displayAnimate();
P.getZoneStatus(2);
P.setTextEffect(2, PA_PRINT, PA_NO_EFFECT);
getmon(szMesg);
P.displayReset(2);*/
}
if (Mode == 8)
{
/* P.displayAnimate();
P.getZoneStatus(2);
P.setTextEffect(2, PA_PRINT, PA_NO_EFFECT);
getyyyy(szMesg);
P.displayReset(2);*/
}
}
void buttonAisPressed()
{
if (NewStateOfbuttonA != StateOfbuttonA)
{
if (NewStateOfbuttonA == 0)
{
buttonA=true;
}
delay(50);
}
StateOfbuttonA = NewStateOfbuttonA;
}
void buttonBisPressed()
{
if (NewStateOfbuttonB != StateOfbuttonB)
{
if (NewStateOfbuttonB == 0) {
buttonB=true;
}
delay(50);
}
StateOfbuttonB = NewStateOfbuttonB;
}
void buttonCisPressed()
{
if (NewStateOfbuttonC != StateOfbuttonC)
{
if (NewStateOfbuttonC == 0) {
buttonC=true;
}
delay(50);
}
StateOfbuttonC = NewStateOfbuttonC;
}