//show the time in small 3x5 characters with seconds display
void small_mode() {
char textchar[8]; // the 16 characters on the display
byte mins = 100; //mins
byte secs = rtc[0]; //seconds
byte old_secs = secs; //holds old seconds value - from last time seconds were updated o display - used to check if seconds have changed
cls();
//run clock main loop as long as run_mode returns true
while (run_mode()) {
get_time();
//check for button press
if (buttonA.uniquePress()) {
switch_mode();
return;
}
if (buttonB.uniquePress()) {
display_date();
return;
}
//if secs changed then update them on the display
secs = rtc[0];
if (secs != old_secs) {
//secs
char buffer[3];
itoa(secs, buffer, 10);
//fix - as otherwise if num has leading zero, e.g. "03" secs, itoa coverts this to chars with space "3 ".
if (secs < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
puttinychar( 20, 1, ':'); //seconds colon
puttinychar( 24, 1, buffer[0]); //seconds
puttinychar( 28, 1, buffer[1]); //seconds
old_secs = secs;
}
//if minute changes change time
if (mins != rtc[1]) {
//reset these for comparison next time
mins = rtc[1];
byte hours = rtc[2];
if (hours > 12) {
hours = hours - ampm * 12;
}
if (hours < 1) {
hours = hours + ampm * 12;
}
//byte dow = rtc[3]; // the DS1307 outputs 0 - 6 where 0 = Sunday0 - 6 where 0 = Sunday.
//byte date = rtc[4];
//set characters
char buffer[3];
itoa(hours, buffer, 10);
//fix - as otherwise if num has leading zero, e.g. "03" hours, itoa coverts this to chars with space "3 ".
if (hours < 10) {
buffer[1] = buffer[0];
//if we are in 12 hour mode blank the leading zero.
if (ampm) {
buffer[0] = ' ';
}
else {
buffer[0] = '0';
}
}
//set hours chars
textchar[0] = buffer[0];
textchar[1] = buffer[1];
textchar[2] = ':';
itoa (mins, buffer, 10);
if (mins < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
//set mins characters
textchar[3] = buffer[0];
textchar[4] = buffer[1];
//do seconds
textchar[5] = ':';
buffer[3];
secs = rtc[0];
itoa(secs, buffer, 10);
//fix - as otherwise if num has leading zero, e.g. "03" secs, itoa coverts this to chars with space "3 ".
if (secs < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
//set seconds
textchar[6] = buffer[0];
textchar[7] = buffer[1];
byte x = 0;
byte y = 0;
//print each char
for (byte x = 0; x < 6 ; x++) {
puttinychar( x * 4, 1, textchar[x]);
}
}
delay(50);
}
fade_down();
}
// basic_mode()
// show the time in 5x7 characters
void basic_mode()
{
cls();
char buffer[3]; //for int to char conversion to turn rtc values into chars we can print on screen
byte offset = 0; //used to offset the x postition of the digits and centre the display when we are in 12 hour mode and the clock shows only 3 digits. e.g. 3:21
byte x, y; //used to draw a clear box over the left hand "1" of the display when we roll from 12:59 -> 1:00am in 12 hour mode.
//do 12/24 hour conversion if ampm set to 1
byte hours = rtc[2];
if (hours > 12) {
hours = hours - ampm * 12;
}
if (hours < 1) {
hours = hours + ampm * 12;
}
//do offset conversion
if (ampm && hours < 10) {
offset = 2;
}
//set the next minute we show the date at
//set_next_date();
// initially set mins to value 100 - so it wll never equal rtc[1] on the first loop of the clock, meaning we draw the clock display when we enter the function
byte secs = 100;
byte mins = 100;
int count = 0;
//run clock main loop as long as run_mode returns true
while (run_mode()) {
//get the time from the clock chip
get_time();
//check for button press
if (buttonA.uniquePress()) {
switch_mode();
return;
}
if (buttonB.uniquePress()) {
display_date();
return;
}
//check whether it's time to automatically display the date
//check_show_date();
//draw the flashing : as on if the secs have changed.
if (secs != rtc[0]) {
//update secs with new value
secs = rtc[0];
//draw :
plot (15 - offset, 2, 1); //top point
plot (15 - offset, 5, 1); //bottom point
count = 400;
}
//if count has run out, turn off the :
if (count == 0) {
plot (15 - offset, 2, 0); //top point
plot (15 - offset, 5, 0); //bottom point
}
else {
count--;
}
//re draw the display if button pressed or if mins != rtc[1] i.e. if the time has changed from what we had stored in mins, (also trigggered on first entering function when mins is 100)
if (mins != rtc[1]) {
//update mins and hours with the new values
mins = rtc[1];
hours = rtc[2];
//adjust hours of ampm set to 12 hour mode
if (hours > 12) {
hours = hours - ampm * 12;
}
if (hours < 1) {
hours = hours + ampm * 12;
}
itoa(hours, buffer, 10);
//if hours < 10 the num e.g. "3" hours, itoa coverts this to chars with space "3 " which we dont want
if (hours < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
//print hours
//if we in 12 hour mode and hours < 10, then don't print the leading zero, and set the offset so we centre the display with 3 digits.
if (ampm && hours < 10) {
offset = 2;
//if the time is 1:00am clear the entire display as the offset changes at this time and we need to blank out the old 12:59
if ((hours == 1 && mins == 0) ) {
cls();
}
}
else {
//else no offset and print hours tens digit
offset = 0;
//if the time is 10:00am clear the entire display as the offset changes at this time and we need to blank out the old 9:59
if (hours == 10 && mins == 0) {
cls();
}
putnormalchar(1, 0, buffer[0]);
}
//print hours ones digit
putnormalchar(7 - offset, 0, buffer[1]);
//print mins
//add leading zero if mins < 10
itoa (mins, buffer, 10);
if (mins < 10) {
buffer[1] = buffer[0];
buffer[0] = '0';
}
//print mins tens and ones digits
putnormalchar(19 - offset, 0, buffer[0]);
putnormalchar(25 - offset, 0, buffer[1]);
}
}
fade_down();
}
//like basic_mode but with slide effect
void slide() {
byte digits_old[4] = {99, 99, 99, 99}; //old values we store time in. Set to somthing that will never match the time initially so all digits get drawn wnen the mode starts
byte digits_new[4]; //new digits time will slide to reveal
byte digits_x_pos[4] = {25, 19, 7, 1}; //x pos for which to draw each digit at
char old_char[2]; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function
char new_char[2]; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function
//old_chars - stores the 5 day and date suffix chars on the display. e.g. "mon" and "st". We feed these into the slide animation as the current char when these chars are updated.
//We sent them as A initially, which are used when the clocl enters the mode and no last chars are stored.
//char old_chars[6] = "AAAAA";
//plot the clock colon on the display
cls();
putnormalchar( 13, 0, ':');
byte old_secs = rtc[0]; //store seconds in old_secs. We compare secs and old secs. WHen they are different we redraw the display
//run clock main loop as long as run_mode returns true
while (run_mode()) {
get_time();
//check for button press
if (buttonA.uniquePress()) {
switch_mode();
return;
}
if (buttonB.uniquePress()) {
display_date();
return;
}
//if secs have changed then update the display
if (rtc[0] != old_secs) {
old_secs = rtc[0];
//do 12/24 hour conversion if ampm set to 1
byte hours = rtc[2];
if (hours > 12) {
hours = hours - ampm * 12;
}
if (hours < 1) {
hours = hours + ampm * 12;
}
//split all date and time into individual digits - stick in digits_new array
//digits_new[7] = ((rtc[4]/10)%10); //7 - date tens
//draw initial screen of all chars. After this we just draw the changes.
//compare digits 0 to 3 (mins and hours)
for (byte i = 0; i <= 3; i++) {
//see if digit has changed...
if (digits_old[i] != digits_new[i]) {
//run 9 step animation sequence for each in turn
for (byte seq = 0; seq <= 8 ; seq++) {
//convert digit to string
itoa(digits_old[i], old_char, 10);
itoa(digits_new[i], new_char, 10);
//if set to 12 hour mode and we're on digit 2 (hours tens mode) then check to see if this is a zero. If it is, blank it instead so we get 2.00pm not 02.00pm
//compare date digit 6 (ones) and (7) tens - if either of these change we need to update the date line. We compare date tens as say from Jan 31 -> Feb 01 then ones digit doesn't change
if ((digits_old[6] != digits_new[6]) || (digits_old[7] != digits_new[7])) {
//change the day shown. Loop below goes through each of the 3 chars in turn e.g. "MON"
for (byte day_char = 0; day_char <=2 ; day_char++){
//run the anim sequence for each char
for (byte seq = 0; seq <=8 ; seq++){
//the day (0 - 6) Read this number into the days char array. the seconds number in the array 0-2 gets the 3 chars of the day name, e.g. m o n
slideanim(6*day_char,8,seq,old_chars[day_char],days[rtc[3]][day_char]); //6 x day_char gives us the x pos for the char
delay(SLIDE_DELAY);
}
//save the old day chars into the old_chars array at array pos 0-2. We use this next time we change the day and feed it to the animation as the current char. The updated char is fed in as the new char.
old_chars[day_char] = days[rtc[3]][day_char];
}
//change the date tens digit (if needed) and ones digit. (the date ones digit wil alwaus change, but putting this in the 'if' loop makes it a bit neater code wise.)
//print the day suffix "nd" "rd" "th" etc. First work out date 2 letter suffix - eg st, nd, rd, th
byte s = 3; //the pos to read our suffix array from.
byte date = rtc[4];
if(date == 1 || date == 21 || date == 31) {
s = 0;
}
else if (date == 2 || date == 22) {
s = 1;
}
else if (date == 3 || date == 23) {
s = 2;
}
for (byte suffix_char = 0; suffix_char <=1 ; suffix_char++){
for (byte seq = 0; seq <=8 ; seq++){
slideanim((suffix_char*6)+36,8,seq,old_chars[suffix_char+3],suffix[s][suffix_char]); // we pass in the old_char array char as the current char and the suffix array as the new char
delay(SLIDE_DELAY);
}
//save the suffic char in the old chars array at array pos 3 and 5. We use these chars next time we change the suffix and feed it to the animation as the current char. The updated char is fed in as the new char.
//save digita array tol old for comparison next loop
for (byte i = 0; i <= 3; i++) {
digits_old[i] = digits_new[i];
}
}//secs/oldsecs
}//while loop
fade_down();
}
//called by slide
//this draws the animation of one char sliding on and the other sliding off. There are 8 steps in the animation, we call the function to draw one of the steps from 0-7
//inputs are are char x and y, animation frame sequence (0-7) and the current and new chars being drawn.
// To slide one char off and another on we need 9 steps or frames in sequence...
// seq# 0123456 <-rows of the display
// | |||||||
// seq0 0123456 START - all rows of the display 0-6 show the current characters rows 0-6
// seq1 012345 current char moves down one row on the display. We only see it's rows 0-5. There are at display positions 1-6 There is a blank row inserted at the top
// seq2 6 01234 current char moves down 2 rows. we now only see rows 0-4 at display rows 2-6 on the display. Row 1 of the display is blank. Row 0 shows row 6 of the new char
// seq3 56 0123
// seq4 456 012 half old / half new char
// seq5 3456 01
// seq6 23456 0
// seq7 123456
// seq8 0123456 END - all rows show the new char
//from above we can see...
//currentchar runs 0-6 then 0-5 then 0-4 all the way to 0. starting Y position increases by 1 row each time.
//new char runs 6 then 5-6 then 4-6 then 3-6. starting Y position increases by 1 row each time.
//if sequence number is below 7, we need to draw the current char
plot(x + col, y + start_y, 0); //else plot led off
}
start_y++;//add one to y so we draw next row one down
}
}
//draw a blank line between the characters if sequence is between 1 and 7. If we don't do this we get the remnants of the current chars last position left on the display
if (sequence >= 1 && sequence <= 8) {
for (byte col = 0; col < 5; col++) {
plot(x + col, y + (sequence - 1), 0); //the y position to draw the line is equivalent to the sequence number - 1
}
}
//if sequence is above 2, we also need to start drawing the new char
byte newcharrowmin = 6 - (sequence - 2); //minimumm row num to draw for new char - this generates an output of 6 to 0 when fed sequence numbers 2-8. This is the minimum row to draw for the new char
byte start_y = 0; //y position to start at - is same as sequence number. we inc it each row
//plot each row up from row minimum (calculated by sequence number) up to 6
for (byte newcharrow = newcharrowmin; newcharrow <= 6; newcharrow++) {
for (byte col = 0; col < 5; col++) {
dots = pgm_read_byte_near(&myfont[new_c][col]);
if (dots & (64 >> newcharrow))
plot(x + col, y + start_y, 1); //plot led on
else
plot(x + col, y + start_y, 0); //else plot led off
}
start_y++;//add one to y so we draw next row one down
//byte hours_y, mins_y; //hours and mins and positions for hours and mins lines
byte hours = rtc[2];
if (hours > 12) {
hours = hours - ampm * 12;
}
if (hours < 1) {
hours = hours + ampm * 12;
}
get_time(); //get the time from the clock chip
byte old_mins = 100; //store mins in old_mins. We compare mins and old mins & when they are different we redraw the display. Set this to 100 initially so display is drawn when mode starts.
byte mins;
//run clock main loop as long as run_mode returns true
while (run_mode()) {
//check for button press
if (buttonA.uniquePress()) {
switch_mode();
return;
}
if (buttonB.uniquePress()) {
display_date();
}
get_time(); //get the time from the clock chip
mins = rtc[1]; //get mins
//if mins is different from old_mins - redraw display
if (mins != old_mins) {
//update old_mins with current mins value
old_mins = mins;
//reset these for comparison next time
mins = rtc[1];
hours = rtc[2];
//make hours into 12 hour format
if (hours > 12) {
hours = hours - 12;
}
if (hours == 0) {
hours = 12;
}
//split mins value up into two separate digits
int minsdigit = rtc[1] % 10;
byte minsdigitten = (rtc[1] / 10) % 10;
//if mins <= 10 , then top line has to read "minsdigti past" and bottom line reads hours
if (mins < 10) {
strcpy (str_a, numbers[minsdigit - 1]);
strcpy (str_b, "PAST");
strcpy (str_c, numbers[hours - 1]);
}
//if mins = 10, cant use minsdigit as above, so soecial case to print 10 past /n hour.
if (mins == 10) {
strcpy (str_a, numbers[9]);
strcpy (str_b, " PAST");
strcpy (str_c, numbers[hours - 1]);
}
//if time is not on the hour - i.e. both mins digits are not zero,
//then make first line read "hours" and 2 & 3rd lines read "minstens" "mins" e.g. "three /n twenty /n one"
else if (minsdigitten != 0 && minsdigit != 0 ) {
strcpy (str_a, numbers[hours - 1]);
//if mins is in the teens, use teens from the numbers array for the 2nd line, e.g. "fifteen"
//if (mins >= 11 && mins <= 19) {
if (mins <= 19) {
strcpy (str_b, numbers[mins - 1]);
}
else {
strcpy (str_b, numberstens[minsdigitten - 1]);
strcpy (str_c, numbers[minsdigit - 1]);
}
}
// if mins digit is zero, don't print it. read read "hours" "minstens" e.g. "three /n twenty"
else if (minsdigitten != 0 && minsdigit == 0 ) {
strcpy (str_a, numbers[hours - 1]);
strcpy (str_b, numberstens[minsdigitten - 1]);
strcpy (str_c, "");
}
//if both mins are zero, i.e. it is on the hour, the top line reads "hours" and bottom line reads "o'clock"