//**************************************************************************************************
// 3-line and 4-line LCD NUMBERS
// Adrian Jones, March 2015
//
//**************************************************************************************************
// Build 1
// r1 150306 - initial build
//********************************************************************************************
#define build 1
#define revision 1
//********************************************************************************************
#include <avr/pgmspace.h> // for memory storage in program space
#include <Wire.h>
//#include <LCD.h> // Standard lcd library
//#include <LiquidCrystal_I2C.h> // library for I@C interface
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
/*
#define I2C_ADDR 0x27 // address found from I2C scanner
#define RS_pin 0 // pin configuration for LCM1602 interface module
#define RW_pin 1
#define EN_pin 2
#define BACK_pin 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
LiquidCrystal_I2C lcd(I2C_ADDR, EN_pin, RW_pin, RS_pin, D4_pin, D5_pin, D6_pin, D7_pin, BACK_pin, POSITIVE);
*/
hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
//Pins for the LCD are SCL A5, SDA A4
const char custom[][8] PROGMEM =
{
{0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, // char 1: bottom right triangle
{0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F}, // char 2: bottom block
{0x10, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, // char 3: bottom left triangle
{0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00}, // char 4: top right triangle
{0x1F, 0x1E, 0x1C, 0x10, 0x00, 0x00, 0x00, 0x00}, // char 5: top left triangle
{0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00}, // char 6: upper block
{0x1F, 0x1F, 0x1E, 0x1C, 0x18, 0x18, 0x10, 0x10}, // char 7: full top right triangle
{0x01, 0x07, 0x0F, 0x1F, 0x00, 0x00, 0x00, 0x00} // char 8: top right triangle
};
const char bn3[][30] PROGMEM = // 3-line numbers
{
// 0 1 2 3 4 5 6 7 8 9
{0x01, 0x06, 0x03, 0x08, 0xFF, 0xFE, 0x08, 0x06, 0x03, 0x08, 0x06, 0x03, 0xFF, 0xFE, 0xFF, 0xFF, 0x06, 0x06, 0x01, 0x06, 0xFE, 0x06, 0x06, 0xFF, 0x01, 0x06, 0x03, 0x01, 0x06, 0x03},
{0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0x01, 0x06, 0x06, 0xFE, 0x06, 0xFF, 0x06, 0x06, 0xFF, 0x06, 0x06, 0xFF, 0xFF, 0x06, 0x03, 0xFE, 0x01, 0x07, 0xFF, 0x06, 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}
};
const char bn4[][30] PROGMEM = // 4-line numbers
{
// 0 1 2 3 4 5 6 7 8 9
{0x01, 0x06, 0x03, 0x08, 0xFF, 0xFE, 0x08, 0x06, 0x03, 0x08, 0x06, 0x03, 0xFF, 0xFE, 0xFF, 0xFF, 0x06, 0x06, 0x01, 0x06, 0x03, 0x06, 0x06, 0xFF, 0x01, 0x06, 0x03, 0x01, 0x06, 0x03},
{0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0x02, 0x02, 0xFF, 0xFE, 0x02, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0x02, 0x02, 0xFF, 0x02, 0x02, 0xFE, 0x01, 0x07, 0xFF, 0x02, 0xFF, 0xFF, 0x02, 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, 0xFE, 0xFE, 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, 0x04, 0x06, 0x05}
};
byte col, row, nb = 0, bc = 0; // general0xFE,0x01,0x07
byte bb[8]; // byte buffer for reading from PROGMEM
#include <Wire.h>
#include "RTClib.h"
RTC_Millis RTC;
byte hr, mn, se, osec;
//*****************************************************************************************//
// Initial Setup
//*****************************************************************************************//
void setup()
{
randomSeed(analogRead(0));
RTC.begin(DateTime(__DATE__, __TIME__));
lcd.begin(20, 4);
for (nb = 0; nb < 8; 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("3&4 Line BIG"));
lcd.setCursor(4, 1);
lcd.print(F("NUMERALS"));
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"));
printNum4(random(0, 10), 0);
printNum4(random(0, 10), 17);
delay(5000);
lcd.clear();
lcd.print(F("SoftClock (AJ)"));
}
//*****************************************************************************************//
// MAIN LOOP
//*****************************************************************************************//
void loop()
{
DateTime now = RTC.now();
hr = now.hour(); if (hr == 0) hr = 24;
mn = now.minute();
se = now.second();
if (se != osec)
{
printNum3(hr / 10, 0, 1);
printNum3(hr % 10, 3, 1);
printColon(6, 1);
printNum3(mn / 10, 7, 1);
printNum3(mn % 10, 10, 1);
printColon(13, 1);
printNum4(se / 10, 14);
printNum4(se % 10, 17);
osec = se;
}
delay(50);
}
// ********************************************************************************** //
// SUBROUTINES
// ********************************************************************************** //
void printNum3(byte digit, byte leftAdjust, byte topAdjust)
{
for (row = 0; row < 3; row++)
{
lcd.setCursor(leftAdjust, row + topAdjust);
for (byte num = digit * 3; num < digit * 3 + 3; num++)
{
lcd.write(pgm_read_byte( &bn3[row][num]) );
}
}
}
void printNum4(byte digit, byte leftAdjust)
{
for (row = 0; row < 4; row++)
{
lcd.setCursor(leftAdjust, row);
for (byte num = digit * 3; num < digit * 3 + 3; num++)
{
lcd.write(pgm_read_byte( &bn4[row][num]) );
}
}
}
void printColon(byte leftAdjust, byte topAdjust)
{
for (row = 0; row < (4 - topAdjust); row++)
{
lcd.setCursor(leftAdjust, row + topAdjust);
if (topAdjust == 1)
{
if (row == 0 || row == 1) lcd.print(F(".")); else lcd.print(F(" "));
}
else
{
if (row == 1 || row == 2) lcd.print(F(".")); else lcd.print(F(" "));
}
}
}
// ********************************************************************************** //
// 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;
}