/*
* Simple Binary Watch
*
* Displays the time and date as a stack of horizontal binary digits, with the 'on' bits represented by a 'lit' box and the 'off' bits
* represented by an unlit box.
*
* Each row has an identifier to the left (S for seconds, M for minutes, H for hours, W for weekday, D for day, M for month, Y for year) and
* the decimal numbers for the row's value (or 2-character weekday representation).
*
* Each row has it's own color (red for seconds, pink for minutes, orange for hours, yellow for weekdays, green for days, sky blue for
* months, and blue for years).
*
* The values are shown as true binary numbers (not one binary value per decimal digit). 6 boxes for year, 4 for month, 5 for day,
* 4 for hour, 6 for minutes, 6 for seconds. But if we draw each row at the minimum number of boxes, then they look raggedy
* and the binary digits don't line up. So we'll draw 6 boxes for each of them.
*
* Because year is limited to 6 binary boxes, (years since 2000), this watch will no longer work in 2032.
*
* To keep things simple, the boxes will be drawn as characters (spaces with the background color set to the row's color). Thus everything
* can be drawn as characters.
*
* Uses Arduino Zero RTC library https://www.arduino.cc/en/Reference/RTC
* Maintained by Arturo Guadalupi https://github.com/arduino-libraries/RTCZero
*
* This code is for the TinyScreen+ board by TinyCircuits used by O Watch http://tiny-circuits.com
*
* This example is based on the Simple Watch code created by O Watch on 6 March 2016 http://theowatch.com
* Modified to use RTC, to set the display brightness based on time of day, and to use __DATE__ and __TIME__
* to preset the watch's date and time by J Koger 13 March 2016
*
* Modified to display time as an 8 x 8 character 'Micro Word Clock' by J Koger 16 March 2016, using a tweaked
* version of the code from Daniel Rojas' https://github.com/formatc1702/Micro-Word-Clock
*
* Modified into a binary watch by J Koger 17 March 2016.
*
*/
#include <TinyScreen.h> //include TinyScreen library
#include <TimeLib.h> //include the Arduino Time library
#include <RTCZero.h> //include the Arduino Zero's Real Time Clock library
#include <stdio.h> // include the C++ standard IO library
/* Create an rtc object */
RTCZero rtc;
// We'll dynamically change these values to set the current initial time
// No need to change them here.
byte seconds = 0;
byte minutes = 45;
byte hours = 9;
// We'll dynamically change these values to set the current initial date
// The preset values are only examples.
byte days = 13;
byte months = 3;
byte years = 16;
int brightness = 15; // We'll set it, 3 - 15 based on time of day
TinyScreen display = TinyScreen(TinyScreenPlus); //Create the TinyScreen object
// Our colors for boxes that are off (binary digit 0) and
// for boxes that are lit (binary digit 1) and characters, by row.
#define BOX_OFF 0B01001001 // Dark gray
#define SECONDS_COLOR TS_8b_Red
#define MINUTES_COLOR 0B10010011 // pink
#define HOURS_COLOR 0B00010111 // orange
#define WEEKDAY_COLOR TS_8b_Yellow
#define DAYS_COLOR TS_8b_Green
#define MONTHS_COLOR 0B11001110 // sky blue
#define YEARS_COLOR TS_8b_Blue
// Comment out this #define to remove the horizontal divider lines.
#define DIVIDER_COLOR TS_8b_Gray
// Number of boxes (binary digits) needed to display this value
#define SECONDS_BOXES 6
#define MINUTES_BOXES 6
#define HOURS_BOXES 5
#define WEEKDAY_BOXES 3
#define DAYS_BOXES 5
#define MONTHS_BOXES 4
#define YEARS_BOXES 6
// To make everything look less raggedy, and have the binary digits of
// the rows line up with each other, just draw the same number of boxes
// for each.
#define MAX_BOXES 6
// Vertical offset of each row
#define SECONDS_Y 0
#define MINUTES_Y 9
#define HOURS_Y 18
#define WEEKDAY_Y 27
#define DAYS_Y 36
#define MONTHS_Y 45
#define YEARS_Y 54
void setup()
{
char s_month[5];
int tmonth, tday, tyear, thour, tminute, tsecond;
static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
display.begin(); //Initializes TinyScreen board
display.setFlip(1); //Flips the TinyScreen rightside up for O Watch
display.on(); //Turns TinyScreen display on
display.fontColor(BOX_OFF, TS_8b_Black); //Set the font color, font background
display.setFont(thinPixel7_10ptFontInfo); //Set the font type
rtc.begin(); // initialize RTC
// Set the time and date. Change this to your current date and time.
// setTime(16,19,00,12,3,2016); //values in the order hr,min,sec,day,month,year
// Let's be lazy and let the compiler set the current date and time for us.
// This will be a few seconds off due to the time it takes to compile the
// .ino file and upload the app. But pretty close.
// __DATE__ is a C++ preprocessor string with the current date in it.
// It will look something like 'Mar 13 2016'.
// So we need to pull those values out and convert the month string to a number.
sscanf(__DATE__, "%s %d %d", s_month, &tday, &tyear);
// Similarly, __TIME__ will look something like '09:34:17' so get those numbers.
sscanf(__TIME__, "%d:%d:%d", &thour, &tminute, &tsecond);
// Find the position of this month's string inside month_names, do a little
// pointer subtraction arithmetic to get the offset, and divide the
// result by 3 since the month names are 3 chars long.
tmonth = (strstr(month_names, s_month) - month_names) / 3;
months = tmonth + 1; // The RTC library expects months to be 1 - 12.
days = tday;
years = tyear - 2000; // The RTC library expects years to be from 2000.
hours = thour;
minutes = tminute;
seconds = tsecond;
rtc.setTime(hours, minutes, seconds);
rtc.setDate(days, months, years);
}
void drawBinaryBoxes(int xStart, int yStart, int value, int numBoxes, uint8_t color)
{
int xPos = xStart, thisBit;
numBoxes = MAX_BOXES; // This makes all of the rows display the same number of boxes
// (binary digits). It's perhaps more confusing but looks less raggedy.
thisBit = 1 << (numBoxes - 1);
for (int i = numBoxes; i > 0; i--)
{
display.setCursor(xPos, yStart);
if (thisBit & value)
display.fontColor(color, color);
else
display.fontColor(BOX_OFF, BOX_OFF);
display.print(" ");
xPos += 8;
thisBit >>= 1;
}
}
void displayTime()
{
display.on(); //Turns TinyScreen display on
for (int i = 1; i < 30; i++) // Display for 30*1000 milliseconds (30 seconds), update display each second
{
// To correctly handle switching date at midnight while the time display is on,
// update -everything-, not just the seconds.
// Get the time now since it's used for the brightness calculations.
// We only need the hours and minutes, since they're all we have
// room to display.
months = rtc.getMonth();
days = rtc.getDay();
years = rtc.getYear();
hours = rtc.getHours();
minutes = rtc.getMinutes();
seconds = rtc.getSeconds();
if (hours <= 12)
brightness = hours + 3; // 0 hours = 3 brightness, noon = 15
else if (hours >= 18)
brightness = (24 - hours) * 2 + 2; // 23 hours = 4 brightness, 18 hours = 14
else
brightness = 15; // full brightness all afternoon
if (brightness < 3)
brightness = 3;
if (brightness > 15)
brightness = 15;
display.setBrightness(brightness); //Set display brightness 0 - 15
// Seconds row
display.setCursor(0, SECONDS_Y);
display.fontColor(SECONDS_COLOR, TS_8b_Black);
display.print("S");
display.setCursor(16, SECONDS_Y);
display.print(seconds / 10);
display.setCursor(24, SECONDS_Y);
display.print(seconds % 10);
drawBinaryBoxes(40, SECONDS_Y, seconds, SECONDS_BOXES, SECONDS_COLOR);
// Minutes row
display.setCursor(0, MINUTES_Y);
display.fontColor(MINUTES_COLOR, TS_8b_Black);
display.print("M");
display.setCursor(16, MINUTES_Y);
display.print(minutes / 10);
display.setCursor(24, MINUTES_Y);
display.print(minutes % 10);
drawBinaryBoxes(40, MINUTES_Y, minutes, MINUTES_BOXES, MINUTES_COLOR);
// Hours row
display.setCursor(0, HOURS_Y);
display.fontColor(HOURS_COLOR, TS_8b_Black);
display.print("H");
display.setCursor(16, HOURS_Y);
display.print(hours / 10);
display.setCursor(24, HOURS_Y);
display.print(hours % 10);
drawBinaryBoxes(40, HOURS_Y, hours, HOURS_BOXES, HOURS_COLOR);
// Weekday row
setTime(hours,minutes,seconds,days,months,2000 + years); //values in the order hr,min,sec,day,month,year
char tmp[2], wkday[16];
int wkdayNum = 0;
strcpy(wkday, dayStr(weekday()));
if (wkday[0] == 'S')
{
if (wkday[1] == 'u')
wkdayNum = 1; // Sunday
else
wkdayNum = 7; // Saturday
}
else if (wkday[0] == 'M')
{
wkdayNum = 2; // Monday
}
else if (wkday[0] == 'T')
{
if (wkday[1] == 'u')
wkdayNum = 3; // Tuesday
else
wkdayNum = 5; // Thursday
}
else if (wkday[0] == 'W')
wkdayNum = 4; // Wednesday
else
wkdayNum = 6; // Friday
display.setCursor(0, WEEKDAY_Y);
display.fontColor(WEEKDAY_COLOR, TS_8b_Black);
display.print("W");
display.setCursor(16, WEEKDAY_Y);
tmp[0] = wkday[0];
tmp[1] = '\0';
display.print(tmp);
display.setCursor(24, WEEKDAY_Y);
tmp[0] = wkday[1];
if (tmp[0] >= 'a')
tmp[0] = tmp[0] - 'a' + 'A';
display.print(tmp);
drawBinaryBoxes(40, WEEKDAY_Y, wkdayNum, WEEKDAY_BOXES, WEEKDAY_COLOR);
// Days row
display.setCursor(0, DAYS_Y);
display.fontColor(DAYS_COLOR, TS_8b_Black);
display.print("D");
display.setCursor(16, DAYS_Y);
display.print(days / 10);
display.setCursor(24, DAYS_Y);
display.print(days % 10);
drawBinaryBoxes(40, DAYS_Y, days, DAYS_BOXES, DAYS_COLOR);
// Months row
display.setCursor(0, MONTHS_Y);
display.fontColor(MONTHS_COLOR, TS_8b_Black);
display.print("M");
display.setCursor(16, MONTHS_Y);
display.print(months / 10);
display.setCursor(24, MONTHS_Y);
display.print(months % 10);
drawBinaryBoxes(40, MONTHS_Y, months, MONTHS_BOXES, MONTHS_COLOR);
// Years row
display.setCursor(0, YEARS_Y);
display.fontColor(YEARS_COLOR, TS_8b_Black);
display.print("Y");
display.setCursor(16, YEARS_Y);
display.print(years / 10);
display.setCursor(24, YEARS_Y);
display.print(years % 10);
drawBinaryBoxes(40, YEARS_Y, years, YEARS_BOXES, YEARS_COLOR);
#ifdef DIVIDER_COLOR
display.drawLine(0, MINUTES_Y - 1, 95, MINUTES_Y - 1, DIVIDER_COLOR);
display.drawLine(0, HOURS_Y - 1, 95, HOURS_Y - 1, DIVIDER_COLOR);
display.drawLine(0, WEEKDAY_Y - 1, 95, WEEKDAY_Y - 1, DIVIDER_COLOR);
display.drawLine(0, DAYS_Y - 1, 95, DAYS_Y - 1, DIVIDER_COLOR);
display.drawLine(0, MONTHS_Y - 1, 95, MONTHS_Y - 1, DIVIDER_COLOR);
display.drawLine(0, YEARS_Y - 1, 95, YEARS_Y - 1, DIVIDER_COLOR);
#endif
delay(1000); //display for 1 seconds
}
display.off(); //Turns TinyScreen display off
}
void loop()
{
if (display.getButtons())
{
displayTime();
}
}
Comments