Clock with hourly chime

I want to make a clock with hourly chime , then found this code on internet, but in this code the passive buzzer is used in arduino 9 and 10 pin. But I want to use it with arduino pin 7 and 8 please help me on this project....

code:

// packed date yymmdd w
uint32_t pd = 0x16010105; // obvious bogus (but valid) date

// packed time hhmmssff
uint32_t pt = 0x00000000; // intentionally bogus (for testing)

uint32_t last_tick_usec = 0UL;
char buf[50]; // this is intentionally bigger than I need

uint8_t set_state = 0;
// set_state indicates what is currently being set, as follows:
// 7 for hour tens, 6 for hour ones,
// 5 for minute tens, 4 for minute ones,
// 3 for second tens, 2 for second ones,
// 1 for normal timekeeping mode (i.e. finished setting the time)
// and it is 0 if the time has not yet been set

const uint32_t TIME_SET_MAX = 0x29595999;
// each digit is at max possible value for time

const uint32_t DATE_SET_MAX = 0x99123907;
// each digit (except units digit of month) is at max possible value for date

const uint8_t BUTTON_PIN_A = 12; // this button moves the cursor
const uint8_t BUTTON_PIN_B = 11; // this button makes the numbers change

uint8_t button_a_now;
uint8_t button_a_last;
uint8_t button_b_now;
uint8_t button_b_last;

enum rtc_status_type {
RTC_UNKNOWN,
RTC_PRESENT,
RTC_ABSENT,
RTC_TROUBLE
};

enum rtc_status_type rtc_status = RTC_UNKNOWN;

#include <LiquidCrystal.h>
#include <Wire.h>
#include <toneAC.h>

// RS EN DB4 DB5 DB6 DB7
LiquidCrystal lcd( 7, 6, 5, 4, 3, 2);

void setup() {
pinMode(BUTTON_PIN_A, INPUT_PULLUP);
pinMode(BUTTON_PIN_B, INPUT_PULLUP);
// pressing either button makes its pin's voltage go low
button_a_now = (digitalRead(BUTTON_PIN_A)==LOW);
button_a_last = button_a_now;
button_b_now = (digitalRead(BUTTON_PIN_B)==LOW);
button_b_last = button_b_now;
// set up the LCD
lcd.begin(16, 2); // LCD dimensions
// define special characters for single cell numerals 10 through 12
uint8_t singleCellTen = { 18, 21, 21, 21, 21, 21, 18, 0 };
uint8_t singleCellEleven = { 9, 27, 9, 9, 9, 9, 9, 0 };
uint8_t singleCellTwelve = { 22, 21, 17, 18, 20, 20, 23, 0 };
lcd.createChar(5, singleCellTen); // "illogical" indices, I know
lcd.createChar(6, singleCellEleven);
lcd.createChar(7, singleCellTwelve);
// initialize connection so we can read the time from the external RTC
Wire.begin();
// attempt to read the time from the external RTC
getNewTime();
// show (possibly bogus) time on display
displayTime();
}

void loop() {
button_a_last = button_a_now;
button_b_last = button_b_now;
// remember, pressing either button makes its pin's voltage go low
button_a_now = (digitalRead(BUTTON_PIN_A)==LOW);
button_b_now = (digitalRead(BUTTON_PIN_B)==LOW);
// has either button just been pushed down?
uint8_t pushed_a = (button_a_now && !button_a_last);
uint8_t pushed_b = (button_b_now && !button_b_last);
// what happens next depends on what mode we're in
if (set_state <= 1) {
// if we're in here, then the clock is running
if (pushed_a) {
// enter time setting mode
pt &= 0xFFFFFF00;
set_state = 15;
displayTime();
}
else {
// just show the time (regular timekeeping mode)
uint32_t old_pt = pt;
getNewTime();
if (pt != old_pt) {
if (set_state == 1) {
if (((pt + 0x00000030) & 0xFFFFFF80) != ((old_pt + 0x00000030) & 0xFFFFFF80)) {
uint16_t pt_hi = ((uint16_t)((pt >> 16) & 0x0000FFFF));
if ((pt_hi & 0x00FF) == 0x0000) {
// the "zeroth" minute of the hour ... but which hour?
// how many times to strike?
uint8_t strike_num = (((pt_hi >> 12) & 0xF) * 10) + ((pt_hi >> 8) & 0xF);
if (strike_num > 12) strike_num -= 12;
if (strike_num == 0) strike_num = 12;
// how many half-seconds into the minute are we?
uint16_t pt_lo = ((uint16_t)(pt & 0x0000FFFF));
uint8_t half_sec = (((pt_lo >> 12) & 0xF) * 20) + (((pt_lo >> 8) & 0xF) * 2);
if ((pt_lo & 0xFF) >= 0x50) half_sec++;
if (half_sec < 26) {
switch (half_sec) {
// Westminster Chimes
case 0: toneAC(330, 10, 420, true); break;
case 1: toneAC(415, 10, 420, true); break;
case 2: toneAC(370, 10, 420, true); break;
case 3: toneAC(247, 10, 735, true); break;
case 6: toneAC(330, 10, 420, true); break;
case 7: toneAC(370, 10, 420, true); break;
case 8: toneAC(415, 10, 420, true); break;
case 9: toneAC(330, 10, 735, true); break;
case 12: toneAC(415, 10, 420, true); break;
case 13: toneAC(330, 10, 420, true); break;
case 14: toneAC(370, 10, 420, true); break;
case 15: toneAC(247, 10, 735, true); break;
case 18: toneAC(247, 10, 420, true); break;
case 19: toneAC(370, 10, 420, true); break;
case 20: toneAC(415, 10, 420, true); break;
case 21: toneAC(330, 10, 735, true); break;
default: break;
}
}
else if ((half_sec < (26 + (3 * strike_num))) && ((half_sec % 3) == 2)){
// bong the hours
toneAC(415, 10, 750, true);
}
}
}
}
displayTime();
}
}
}
else if ((set_state >= 2) && (set_state <= 15)) {
// if we're in here, then we're in the midst of setting the date/time
if (pushed_a) {
// move the cursor
set_state--;
if (set_state == 13) set_state--; // this is not triskaidekaphobia
while ((set_state == 9) || (set_state == 8)) set_state--;
if (set_state == 7) {
pd &= 0xFFFFFF00;
pd += packedDateWeekday(pd);
}
if (set_state <= 1) {
// if we're finished setting the time, we start the clock running
if (rtc_status == RTC_PRESENT) {
// BEGIN code to write the time to the Chronodot
Wire.beginTransmission(0x68); // address DS3231
Wire.write(0x00); // select register

      Wire.write((uint8_t)((pt >> 8)  & 0xFF)); // seconds
      Wire.write((uint8_t)((pt >> 16) & 0xFF)); // minutes
      Wire.write((uint8_t)((pt >> 24) & 0xFF)); // hours
      Wire.write((uint8_t)(pd & 0xFF));         // day of week
      Wire.write((uint8_t)((pd >> 8)  & 0xFF)); // day of month
      Wire.write((uint8_t)((pd >> 16) & 0xFF)); // month
      Wire.write((uint8_t)((pd >> 24) & 0xFF)); // year

      Wire.endTransmission();
      // END code to write the time to the Chronodot
    }
    last_tick_usec = micros();
  }
  displayTime();       
}
else if (pushed_b) {
  // change the number that the cursor is pointing to
  // (that is, the number itself gets changed; the cursor does not move)
  uint32_t digit_mask = (((uint32_t)0x0000000F)<<(4*(set_state&7)));      
  if (set_state >= 8) {
    if (set_state == 12) digit_mask = 0x00FF0000; // special mask for month
    // change one digit (or maybe two digits) of the date
    if ((pd & digit_mask) >= (DATE_SET_MAX & digit_mask)) pd &= ~digit_mask;
    else pd += (digit_mask & 0x11011111);
    if (set_state == 12) {
      // the month requires special treatment
      if ((pd & 0x00FF0000) == ((uint32_t)0x00000000)) {
        // there is no month 0
        pd += 0x00010000;
      }
      if ((pd & 0x000F0000) > 0x00090000) {
        // after month 9 comes month 10
        pd = (pd & 0xFFF0FFFF) + 0x00100000;
      }
    }
  }
  else {
    // change one digit of the time
    if ((pt & digit_mask) >= (TIME_SET_MAX & digit_mask)) pt &= ~digit_mask;
    else pt += (digit_mask & 0x11111111);
  }
  // show the new time
  displayTime();         
}

}
delay(10); // poor man's switch debounce
}

void displayTime() {
// set cursor to beginning of top row
lcd.setCursor(0, 0);
// 01234567890123456
if (set_state == 0) lcd.print(F("RTC not found! "));
else if (set_state == 1) {
switch (rtc_status) {
// 01234567890123456
case RTC_PRESENT: lcd.print(F("Date Time RTC")); break;
case RTC_ABSENT: lcd.print(F("Date Time ")); break;
case RTC_TROUBLE: lcd.print(F("!DEAD RECKONING!")); break;
default: lcd.print(F("rtc_status error")); break;
}
}
else if (set_state <= 7) {
switch ((uint8_t)(pd & 0xFF)) {
// 01234567890123456
case 1: lcd.print(F("Monday, right? ")); break;
case 2: lcd.print(F("Tuesday, right? ")); break;
case 3: lcd.print(F("Wednesday,right?")); break;
case 4: lcd.print(F("Thursday, right?")); break;
case 5: lcd.print(F("Friday, right? ")); break;
case 6: lcd.print(F("Saturday, right?")); break;
case 7: lcd.print(F("Sunday, right? ")); break;
default: lcd.print(F("Calendar error! ")); break;
}
}
else if (set_state <= 15) lcd.print(F("Set date & time:"));
else lcd.print(F("Oops, Error! "));
// set cursor to beginning of bottom row
lcd.setCursor(0, 1);
// determine the correct character for the month (we'll need this for the next step)
uint8_t month_byte = (uint8_t)((pd >> 16) & 0xFF);
char month_char = '*';
if (month_byte <= 0x09) month_char = (char)('0' + month_byte);
else if (month_byte == 0x10) month_char = (char)5;
else if (month_byte == 0x11) month_char = (char)6;
else if (month_byte == 0x12) month_char = (char)7;
else if ((month_byte >= 0x0A) && (month_byte <= 0x0F)) {
// this should never happen -- I'm including it strictly for debugging purposes
month_char = (char)('a' + (month_byte - 0xA));
}
//
// 01234567890123456
// show the date and time on the display, thus: YY.M.DD HH:MM:SS
sprintf(buf, "%02x.%c.%02x %02x:%02x:%02x",
(uint8_t)((pd>>24)&0xFF), month_char, (uint8_t)((pd>>8)&0xFF),
(uint8_t)((pt>>24)&0xFF), (uint8_t)((pt>>16)&0xFF), (uint8_t)((pt>>8)&0xFF));
// change the zeros to capital "O"s
for (int i=0; i<16; i++) {
if (buf[i]=='0') buf[i]='O';
}
lcd.print(buf);
switch (set_state) {
case 15: lcd.setCursor(0, 1); lcd.cursor(); break; // cursor under year tens
case 14: lcd.setCursor(1, 1); lcd.cursor(); break; // cursor under year ones
case 12: lcd.setCursor(3, 1); lcd.cursor(); break; // cursor under month
case 11: lcd.setCursor(5, 1); lcd.cursor(); break; // cursor under date tens
case 10: lcd.setCursor(6, 1); lcd.cursor(); break; // cursor under date ones
case 7: lcd.setCursor(8, 1); lcd.cursor(); break; // cursor under hour tens
case 6: lcd.setCursor(9, 1); lcd.cursor(); break; // cursor under hour ones
case 5: lcd.setCursor(11, 1); lcd.cursor(); break; // cursor under minute tens
case 4: lcd.setCursor(12, 1); lcd.cursor(); break; // cursor under minute ones
case 3: lcd.setCursor(14, 1); lcd.cursor(); break; // cursor under second tens
case 2: lcd.setCursor(15, 1); lcd.cursor(); break; // cursor under second ones
default: lcd.noCursor(); // if not setting the time, then no cursor
}
}

void getNewTime() {
//
// In case no external RTC is available, this function can serve as a substitute.
// However, if there is an external RTC, then this function will make use of it.
//
const uint32_t ONE_TICK_USEC = 50000UL; // update the time every 0.05 second
const uint32_t ONE_TICK_PACKED = 0x00000005; // see previous line
uint32_t old_pt = pt;
while ((micros()-last_tick_usec)>=ONE_TICK_USEC) {
// figure out how much time has passed
last_tick_usec += ONE_TICK_USEC;
pt = timeAdd(pt, ONE_TICK_PACKED);
}
if (pt>=0x24000000) {
pt = timeSub(pt, 0x24000000);
// advance the date (yes, it really is this complicated!)
// BEGIN date advance code
if ((pd & 0x000000FF) >= 0x00000007) pd &= 0xFFFFFF00;
pd += 0x00000101;
if ((pd & 0x00000F00) >= 0x00000A00) pd = (pd & 0xFFFFF0FF) + 0x00001000;
if ((pd & 0x0000FF00) >= 0x00003200) pd = (pd & 0xFFFF00FF) + 0x00010100;
if ((pd & 0x00FFFF00) >= 0x00123200) pd = (pd & 0xFF0000FF) + 0x01010100;
if ((pd & 0x0FFFFF00) >= 0x09123200) pd = (pd & 0xF00000FF) + 0x10010100;
if ((pd & 0x00FFFF00) == 0x00113100) pd = (pd & 0xFF0000FF) + 0x00120100;
if ((pd & 0x00FFFF00) == 0x00093100) pd = (pd & 0xFF0000FF) + 0x00100100;
if ((pd & 0x00FFFF00) == 0x00063100) pd = (pd & 0xFF0000FF) + 0x00070100;
if ((pd & 0x00FFFF00) == 0x00043100) pd = (pd & 0xFF0000FF) + 0x00050100;
if ((pd & 0x00FFFE00) == 0x00023000) pd = (pd & 0xFF0000FF) + 0x00030100;
if (!((((pd & 0x10000000) >> 3) ^ (pd & 0x03FFFF00)) == 0x00022900)) {
if ((pd & 0x00FFFF00) == 0x00022900) {
pd = (pd & 0xFF0000FF) + 0x00030100;
}
}
// END date advance code
}
if ((rtc_status == RTC_UNKNOWN) || (old_pt != pt)) {
if ((rtc_status == RTC_UNKNOWN) || (rtc_status == RTC_PRESENT)) {
// We will attempt to read the RTC.
// If we succeed, we assume that whatever date and time it gave us is correct.
// If we fail, we assume that we don't have a good RTC, and we don't try to read it again.
uint32_t expected_pt = pt;
// BEGIN attempt to read the time
// send request to receive data starting at register 0
Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
Wire.write((uint8_t)0); // start at register 0
Wire.endTransmission();
Wire.requestFrom(0x68, 7); // request seven bytes (ss, mi, hh, wd, dd, mo, yy)
// check for a reply from the RTC, and use it if we can
if (Wire.available() >= 7) {
// if we're here, we got a reply and it is long enough
// so now we read the time
pt = (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 8); // seconds
pt += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 16); // minutes
pt += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 24); // hours
pd = (((Wire.read()) & ((uint32_t)(0x000000FF)))); // day of week
pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 8); // day of month
pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 16); // month
pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 24); // year
rtc_status = RTC_PRESENT;
set_state = 1; // because we have successfully read the time
}
else {
// if we're here, then we did not get a reply we could use
if (rtc_status == RTC_UNKNOWN) rtc_status = RTC_ABSENT;
else rtc_status = RTC_TROUBLE;
}
// END attempt to read the time
//
// Most RTC units do not handle fractional seconds.
// What follows is an attempt at estimating the missing fractional seconds.
if ((pt & 0xFFFFFF00) == (expected_pt & 0xFFFFFF00)) {
// hour, minute, and second are the same as expected
// so we assume that the fractional seconds are also the same as expected
pt = expected_pt;
}
else if (timeAdd(pt, 0x00000100) == (expected_pt & 0xFFFFFF00)) {
// time is one second earlier than expected
pt = timeAdd(pt, 0x00000099);
}
else if ((pt == 0x23595900) && (expected_pt < 0x00000100)) {
// special case the second just before midnight
pt = 0x23595999;
}
}
}
}

// some old time manipulation functions I dug up for this

uint32_t timeAdd (uint32_t x, uint32_t y) {
// no sanity checking of input
// format is hhmmssff with ff being decimal fractions of a second
// "out of range" results are e.g. A0000000 for 100 hours
uint32_t binsum = x + y;
uint32_t carry = ((binsum + 0x06A6A666) ^ x ^ y) & 0x11111110;
return (binsum + ((carry - (carry>>4)) & 0x06A6A666));
}

uint32_t timeSub (uint32_t x, uint32_t y) {
// no sanity checking of input
// format is hhmmssff with ff being decimal fractions of a second
// "negative" results are e.g. F9595999 for -0.01 second
uint32_t bindiff = x - y;
uint32_t borrow = (bindiff ^ x ^ y) & 0x11111110;
return (bindiff - ((borrow - (borrow>>4)) & 0x06A6A666) );
}

/*
Usage example:

2 h 58 min 30.98 s --> 0x02583098
0 h 1 min 44.06 s --> 0x00014406

Addition:
timeAdd(0x02583098, 0x00014406) gives 0x03001504
which means 3 h 0 min 15.04 s

Subtraction:
timeSub(0x02583098, 0x00014406) gives 0x02564692
which means 2 h 56 min 46.92 s
*/

// ... and a date manipulation function I made just for this

uint8_t packedDateWeekday(uint32_t p) {
// Input is a packed date. Last two digits are ignored.
// Format is YYMMDDXX where XX is don't care.
// Example: 0x16062688 means June 26, 2016
// Output is the day of the week corresponding to the input date.
// (1 for Monday, 2 for Tuesday, ..., 7 for Sunday)
// There is hardly any sanity checking of input.
uint8_t x = p >> 24;
x -= (6 * ((x >> 4) & 0x0F));
x += 4;
if ((p & 0x00FF0000) <= 0x00020000) x--;
x += (x >> 2);
switch ((uint8_t)((p >> 16) & 0xFF)) { // the 0xFF part is paranoia
case 0x03: x += 4; break;
case 0x04: break;
case 0x05: x += 2; break;
case 0x06: x += 5; break;
case 0x07: break;
case 0x08: x += 3; break;
case 0x09: x += 6; break;
case 0x10: x += 1; break;
case 0x11: x += 4; break;
case 0x12: x += 6; break;
case 0x01: x += 2; break;
case 0x02: x += 5; break;
default: return 0;
}
x += ((p >> 8) & 0xFF);
x += ((p >> 12) & 0x0F);
while (x > 7) x -= 7;
return x;
}

So you found some code on the Internet... does this match your hardware setup?

Post your schematic of the hardware.
Post your (someone's) code in quotes so it can be read.
Post what you have tried so far... people tend to be a lot more helpful if you have actually tried to solve a problem yourself first.

This library uses pins 9 and 10 belonging to timer 1. This is not easy to change. Why do you want to use pins 7 and 8?
Pin 7 is used by the LCD. Consider using an I2C LCD which could free up 4 pins.

Post a link to the project you found.

actually I have made a 7 segment led clock on which only pin 7 and 8 free. I want to add this hourly chime in my clock with a buzzer. can u modify this code and extract only chiming code?

If I was doing this project, I’d probably (a) try to pick out the chiming part using toneAC.h and make a separately testable function which generates all the regular chimes and (b) modify the existing code (your seven segment clock) to free up the required pins 9 and 10.

If software uses hardware timers, as toneAC does, then these require dedicated pins.

Incidentally, the “Westminster Chimes” has give me an idea for a bedroom clock with the chimes increasing in volume during the day.

thanks for comment, now I am using a separate microcontroller for chiming part. now I have a question is the chiming can be turned off during sleep time (10pm to 7am)? if it possible please give me the modified code...

Of course the chimes can be turned off a night. The code will look something like this:


if ( hour >= 7 && hour <= 22 ) {

// chime code here

else {

// don’t chime

}

Yes, if there is no way of freeing up the required pins on your current clock then a dedicated micro controller unit is one solution.

If you want to pay someone to do all this for you, there is this part of the forum:

Maybe the OP should look into shift registers first.

If no one gonna say it, I will say it.
OP, could you please edit your post and include your code in code tags? Thanks.

Not sure of the quality difference, but using the Tone library would allow for using any pin. There would be a volume difference since the toneAC library is driving the buzzer with the differential between two pins while Tone only uses a single pin, but that can be adjusted by changing the resistor value (as long as you do not exceed the maximum current of the output pin).

Either way the code for the music is blocking, that would need to be changed for the clock to display seconds properly while playing the sounds.

how to turn off chime during night time ? please provide full code... previous code does not work...

if ( hour >= 7 && hour <= 22 ) {

// chime code here

else {

// don’t chime

}

Hi @subhrodeep

To turn off your hourly chime over a time range, you need to check whether the range's start and end times cross over midnight:

if (StartTime > EndTime)
{
  // The range crosses midnight, do the comparisons independently
  return (StartTime < Now) || (Now < EndTime);
}
else
{
  // The range is on the same day, both comparisons must be true
  return StartTime < Now && Now < EndTime;
}

still i am unable to compile, can u please enter this code on my chiming code ? my chiming code is:

// packed date yymmdd w
uint32_t pd = 0x16010105; // obvious bogus (but valid) date

// packed time hhmmssff
uint32_t pt = 0x00000000; // intentionally bogus (for testing)

uint32_t last_tick_usec = 0UL;
char buf[50]; // this is intentionally bigger than I need

uint8_t set_state = 0;
// set_state indicates what is currently being set, as follows:
// 7 for hour tens, 6 for hour ones,
// 5 for minute tens, 4 for minute ones,
// 3 for second tens, 2 for second ones,
// 1 for normal timekeeping mode (i.e. finished setting the time)
// and it is 0 if the time has not yet been set

const uint32_t TIME_SET_MAX = 0x29595999;
// each digit is at max possible value for time

const uint32_t DATE_SET_MAX = 0x99123907;
// each digit (except units digit of month) is at max possible value for date

const uint8_t BUTTON_PIN_A = 12; // this button moves the cursor
const uint8_t BUTTON_PIN_B = 11; // this button makes the numbers change

uint8_t button_a_now;
uint8_t button_a_last;
uint8_t button_b_now;
uint8_t button_b_last;

enum rtc_status_type {
RTC_UNKNOWN,
RTC_PRESENT,
RTC_ABSENT,
RTC_TROUBLE
};

enum rtc_status_type rtc_status = RTC_UNKNOWN;

#include <Wire.h>
#include <toneAC.h>

// RS EN DB4 DB5 DB6 DB7

void setup() {

// pressing either button makes its pin's voltage go low

// initialize connection so we can read the time from the external RTC
Wire.begin();
// attempt to read the time from the external RTC
getNewTime();
// show (possibly bogus) time on display
displayTime();
}

void loop() {

// remember, pressing either button makes its pin's voltage go low

// has either button just been pushed down?
uint8_t pushed_a = (button_a_now && !button_a_last);
uint8_t pushed_b = (button_b_now && !button_b_last);
// what happens next depends on what mode we're in
if (set_state <= 1) {
// if we're in here, then the clock is running
if (pushed_a) {
// enter time setting mode
pt &= 0xFFFFFF00;
set_state = 15;
displayTime();
}
else {
// just show the time (regular timekeeping mode)
uint32_t old_pt = pt;
getNewTime();
if (pt != old_pt) {
if (set_state == 1) {
if (((pt + 0x00000030) & 0xFFFFFF80) != ((old_pt + 0x00000030) & 0xFFFFFF80)) {
uint16_t pt_hi = ((uint16_t)((pt >> 16) & 0x0000FFFF));
if ((pt_hi & 0x00FF) == 0x0000) {
// the "zeroth" minute of the hour ... but which hour?
// how many times to strike?
uint8_t strike_num = (((pt_hi >> 12) & 0xF) * 10) + ((pt_hi >> 8) & 0xF);
if (strike_num > 12) strike_num -= 12;
if (strike_num == 0) strike_num = 12;
// how many half-seconds into the minute are we?
uint16_t pt_lo = ((uint16_t)(pt & 0x0000FFFF));
uint8_t half_sec = (((pt_lo >> 12) & 0xF) * 20) + (((pt_lo >> 8) & 0xF) * 2);
if ((pt_lo & 0xFF) >= 0x50) half_sec++;
if (half_sec < 26) {
switch (half_sec) {
// Westminster Chimes
case 0: toneAC(330, 10, 420, true); break;
case 1: toneAC(415, 10, 420, true); break;
case 2: toneAC(370, 10, 420, true); break;
case 3: toneAC(247, 10, 735, true); break;
case 6: toneAC(330, 10, 420, true); break;
case 7: toneAC(370, 10, 420, true); break;
case 8: toneAC(415, 10, 420, true); break;
case 9: toneAC(330, 10, 735, true); break;
case 12: toneAC(415, 10, 420, true); break;
case 13: toneAC(330, 10, 420, true); break;
case 14: toneAC(370, 10, 420, true); break;
case 15: toneAC(247, 10, 735, true); break;
case 18: toneAC(247, 10, 420, true); break;
case 19: toneAC(370, 10, 420, true); break;
case 20: toneAC(415, 10, 420, true); break;
case 21: toneAC(330, 10, 735, true); break;
default: break;
}
}
else if ((half_sec < (26 + (3 * strike_num))) && ((half_sec % 3) == 2)){
// bong the hours
toneAC(415, 10, 750, true);
}
}
}
}
displayTime();
}
}
}
else if ((set_state >= 2) && (set_state <= 15)) {
// if we're in here, then we're in the midst of setting the date/time
if (pushed_a) {
// move the cursor
set_state--;
if (set_state == 13) set_state--; // this is not triskaidekaphobia
while ((set_state == 9) || (set_state == 8)) set_state--;
if (set_state == 7) {
pd &= 0xFFFFFF00;
pd += packedDateWeekday(pd);
}
if (set_state <= 1) {
// if we're finished setting the time, we start the clock running
if (rtc_status == RTC_PRESENT) {
// BEGIN code to write the time to the Chronodot
Wire.beginTransmission(0x68); // address DS3231
Wire.write(0x00); // select register

      Wire.write((uint8_t)((pt >> 8)  & 0xFF)); // seconds
      Wire.write((uint8_t)((pt >> 16) & 0xFF)); // minutes
      Wire.write((uint8_t)((pt >> 24) & 0xFF)); // hours
      Wire.write((uint8_t)(pd & 0xFF));         // day of week
      Wire.write((uint8_t)((pd >> 8)  & 0xFF)); // day of month
      Wire.write((uint8_t)((pd >> 16) & 0xFF)); // month
      Wire.write((uint8_t)((pd >> 24) & 0xFF)); // year

      Wire.endTransmission();
      // END code to write the time to the Chronodot
    }
    last_tick_usec = micros();
  }
  displayTime();       
}
else if (pushed_b) {
  // change the number that the cursor is pointing to
  // (that is, the number itself gets changed; the cursor does not move)
  uint32_t digit_mask = (((uint32_t)0x0000000F)<<(4*(set_state&7)));      
  if (set_state >= 8) {
    if (set_state == 12) digit_mask = 0x00FF0000; // special mask for month
    // change one digit (or maybe two digits) of the date
    if ((pd & digit_mask) >= (DATE_SET_MAX & digit_mask)) pd &= ~digit_mask;
    else pd += (digit_mask & 0x11011111);
    if (set_state == 12) {
      // the month requires special treatment
      if ((pd & 0x00FF0000) == ((uint32_t)0x00000000)) {
        // there is no month 0
        pd += 0x00010000;
      }
      if ((pd & 0x000F0000) > 0x00090000) {
        // after month 9 comes month 10
        pd = (pd & 0xFFF0FFFF) + 0x00100000;
      }
    }
  }
  else {
    // change one digit of the time
    if ((pt & digit_mask) >= (TIME_SET_MAX & digit_mask)) pt &= ~digit_mask;
    else pt += (digit_mask & 0x11111111);
  }
  // show the new time
  displayTime();         
}

}
delay(10); // poor man's switch debounce
}

void displayTime() {
// set cursor to beginning of top row

// 01234567890123456

switch (rtc_status) {
  //                                 01234567890123456




}

}

  //                                 01234567890123456

// set cursor to beginning of bottom row

// determine the correct character for the month (we'll need this for the next step)
uint8_t month_byte = (uint8_t)((pd >> 16) & 0xFF);
char month_char = '*';

void getNewTime() {
//
// In case no external RTC is available, this function can serve as a substitute.
// However, if there is an external RTC, then this function will make use of it.
//
const uint32_t ONE_TICK_USEC = 50000UL; // update the time every 0.05 second
const uint32_t ONE_TICK_PACKED = 0x00000005; // see previous line
uint32_t old_pt = pt;
while ((micros()-last_tick_usec)>=ONE_TICK_USEC) {
// figure out how much time has passed
last_tick_usec += ONE_TICK_USEC;
pt = timeAdd(pt, ONE_TICK_PACKED);
}
if (pt>=0x24000000) {
pt = timeSub(pt, 0x24000000);
// advance the date (yes, it really is this complicated!)
// BEGIN date advance code
if ((pd & 0x000000FF) >= 0x00000007) pd &= 0xFFFFFF00;
pd += 0x00000101;
if ((pd & 0x00000F00) >= 0x00000A00) pd = (pd & 0xFFFFF0FF) + 0x00001000;
if ((pd & 0x0000FF00) >= 0x00003200) pd = (pd & 0xFFFF00FF) + 0x00010100;
if ((pd & 0x00FFFF00) >= 0x00123200) pd = (pd & 0xFF0000FF) + 0x01010100;
if ((pd & 0x0FFFFF00) >= 0x09123200) pd = (pd & 0xF00000FF) + 0x10010100;
if ((pd & 0x00FFFF00) == 0x00113100) pd = (pd & 0xFF0000FF) + 0x00120100;
if ((pd & 0x00FFFF00) == 0x00093100) pd = (pd & 0xFF0000FF) + 0x00100100;
if ((pd & 0x00FFFF00) == 0x00063100) pd = (pd & 0xFF0000FF) + 0x00070100;
if ((pd & 0x00FFFF00) == 0x00043100) pd = (pd & 0xFF0000FF) + 0x00050100;
if ((pd & 0x00FFFE00) == 0x00023000) pd = (pd & 0xFF0000FF) + 0x00030100;
if (!((((pd & 0x10000000) >> 3) ^ (pd & 0x03FFFF00)) == 0x00022900)) {
if ((pd & 0x00FFFF00) == 0x00022900) {
pd = (pd & 0xFF0000FF) + 0x00030100;
}
}
// END date advance code
}
if ((rtc_status == RTC_UNKNOWN) || (old_pt != pt)) {
if ((rtc_status == RTC_UNKNOWN) || (rtc_status == RTC_PRESENT)) {
// We will attempt to read the RTC.
// If we succeed, we assume that whatever date and time it gave us is correct.
// If we fail, we assume that we don't have a good RTC, and we don't try to read it again.
uint32_t expected_pt = pt;
// BEGIN attempt to read the time
// send request to receive data starting at register 0
Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
Wire.write((uint8_t)0); // start at register 0
Wire.endTransmission();
Wire.requestFrom(0x68, 7); // request seven bytes (ss, mi, hh, wd, dd, mo, yy)
// check for a reply from the RTC, and use it if we can
if (Wire.available() >= 7) {
// if we're here, we got a reply and it is long enough
// so now we read the time
pt = (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 8); // seconds
pt += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 16); // minutes
pt += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 24); // hours
pd = (((Wire.read()) & ((uint32_t)(0x000000FF)))); // day of week
pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 8); // day of month
pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 16); // month
pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 24); // year
rtc_status = RTC_PRESENT;
set_state = 1; // because we have successfully read the time
}
else {
// if we're here, then we did not get a reply we could use
if (rtc_status == RTC_UNKNOWN) rtc_status = RTC_ABSENT;
else rtc_status = RTC_TROUBLE;
}
// END attempt to read the time
//
// Most RTC units do not handle fractional seconds.
// What follows is an attempt at estimating the missing fractional seconds.
if ((pt & 0xFFFFFF00) == (expected_pt & 0xFFFFFF00)) {
// hour, minute, and second are the same as expected
// so we assume that the fractional seconds are also the same as expected
pt = expected_pt;
}
else if (timeAdd(pt, 0x00000100) == (expected_pt & 0xFFFFFF00)) {
// time is one second earlier than expected
pt = timeAdd(pt, 0x00000099);
}
else if ((pt == 0x23595900) && (expected_pt < 0x00000100)) {
// special case the second just before midnight
pt = 0x23595999;
}
}
}
}

// some old time manipulation functions I dug up for this

uint32_t timeAdd (uint32_t x, uint32_t y) {
// no sanity checking of input
// format is hhmmssff with ff being decimal fractions of a second
// "out of range" results are e.g. A0000000 for 100 hours
uint32_t binsum = x + y;
uint32_t carry = ((binsum + 0x06A6A666) ^ x ^ y) & 0x11111110;
return (binsum + ((carry - (carry>>4)) & 0x06A6A666));
}

uint32_t timeSub (uint32_t x, uint32_t y) {
// no sanity checking of input
// format is hhmmssff with ff being decimal fractions of a second
// "negative" results are e.g. F9595999 for -0.01 second
uint32_t bindiff = x - y;
uint32_t borrow = (bindiff ^ x ^ y) & 0x11111110;
return (bindiff - ((borrow - (borrow>>4)) & 0x06A6A666) );
}

/*
Usage example:

2 h 58 min 30.98 s --> 0x02583098
0 h 1 min 44.06 s --> 0x00014406

Addition:
timeAdd(0x02583098, 0x00014406) gives 0x03001504
which means 3 h 0 min 15.04 s

Subtraction:
timeSub(0x02583098, 0x00014406) gives 0x02564692
which means 2 h 56 min 46.92 s
*/

// ... and a date manipulation function I made just for this

uint8_t packedDateWeekday(uint32_t p) {
// Input is a packed date. Last two digits are ignored.
// Format is YYMMDDXX where XX is don't care.
// Example: 0x16062688 means June 26, 2016
// Output is the day of the week corresponding to the input date.
// (1 for Monday, 2 for Tuesday, ..., 7 for Sunday)
// There is hardly any sanity checking of input.
uint8_t x = p >> 24;
x -= (6 * ((x >> 4) & 0x0F));
x += 4;
if ((p & 0x00FF0000) <= 0x00020000) x--;
x += (x >> 2);
switch ((uint8_t)((p >> 16) & 0xFF)) { // the 0xFF part is paranoia
case 0x03: x += 4; break;
case 0x04: break;
case 0x05: x += 2; break;
case 0x06: x += 5; break;
case 0x07: break;
case 0x08: x += 3; break;
case 0x09: x += 6; break;
case 0x10: x += 1; break;
case 0x11: x += 4; break;
case 0x12: x += 6; break;
case 0x01: x += 2; break;
case 0x02: x += 5; break;
default: return 0;
}
x += ((p >> 8) & 0xFF);
x += ((p >> 12) & 0x0F);
while (x > 7) x -= 7;
return x;
}

still i am unable to compile, can u please enter this code on my chiming code ? my chiming code is:


// packed date  yymmdd w
uint32_t pd = 0x16010105; // obvious bogus (but valid) date

// packed time  hhmmssff
uint32_t pt = 0x00000000; // intentionally bogus (for testing)

uint32_t last_tick_usec = 0UL;
char buf[50]; // this is intentionally bigger than I need

uint8_t set_state = 0;
// set_state indicates what is currently being set, as follows:
// 7 for hour tens,   6 for hour ones,
// 5 for minute tens, 4 for minute ones,
// 3 for second tens, 2 for second ones,
// 1 for normal timekeeping mode (i.e. finished setting the time)
// and it is 0 if the time has not yet been set

const uint32_t TIME_SET_MAX = 0x29595999;
// each digit is at max possible value for time

const uint32_t DATE_SET_MAX = 0x99123907;
// each digit (except units digit of month) is at max possible value for date

const uint8_t BUTTON_PIN_A = 12; // this button moves the cursor
const uint8_t BUTTON_PIN_B = 11; // this button makes the numbers change

uint8_t button_a_now;
uint8_t button_a_last;
uint8_t button_b_now;
uint8_t button_b_last;

enum rtc_status_type {
  RTC_UNKNOWN,
  RTC_PRESENT,
  RTC_ABSENT,
  RTC_TROUBLE
};

enum rtc_status_type rtc_status = RTC_UNKNOWN;

#include <Wire.h>
#include <toneAC.h>

//                RS  EN DB4 DB5 DB6 DB7


void setup() {
  pinMode(BUTTON_PIN_A, INPUT_PULLUP);
  pinMode(BUTTON_PIN_B, INPUT_PULLUP);
  // pressing either button makes its pin's voltage go low
  button_a_now = (digitalRead(BUTTON_PIN_A)==LOW);
  button_a_last = button_a_now;
  button_b_now = (digitalRead(BUTTON_PIN_B)==LOW);
  button_b_last = button_b_now;
  // set up the LCD

  // define special characters for single cell numerals 10 through 12
  uint8_t singleCellTen[]    = { 18, 21, 21, 21, 21, 21, 18,  0 };
  uint8_t singleCellEleven[] = {  9, 27,  9,  9,  9,  9,  9,  0 };
  uint8_t singleCellTwelve[] = { 22, 21, 17, 18, 20, 20, 23,  0 };



  // initialize connection so we can read the time from the external RTC
  Wire.begin();
  // attempt to read the time from the external RTC
  getNewTime();
  // show (possibly bogus) time on display
  displayTime();
}

void loop() {
  button_a_last = button_a_now;
  button_b_last = button_b_now;
  // remember, pressing either button makes its pin's voltage go low
  button_a_now = (digitalRead(BUTTON_PIN_A)==LOW);
  button_b_now = (digitalRead(BUTTON_PIN_B)==LOW);
  // has either button just been pushed down?
  uint8_t pushed_a = (button_a_now && !button_a_last);
  uint8_t pushed_b = (button_b_now && !button_b_last);
  // what happens next depends on what mode we're in
  if (set_state <= 1) {
    // if we're in here, then the clock is running
    if (pushed_a) {
      // enter time setting mode
      pt &= 0xFFFFFF00;
      set_state = 15;
      displayTime();
    }
    else {
      // just show the time (regular timekeeping mode)
      uint32_t old_pt = pt;
      getNewTime();
      if (pt != old_pt) {
        if (set_state == 1) {
          if (((pt + 0x00000030) & 0xFFFFFF80) != ((old_pt + 0x00000030) & 0xFFFFFF80)) {
            uint16_t pt_hi = ((uint16_t)((pt >> 16) & 0x0000FFFF));  
            if ((pt_hi & 0x00FF) == 0x0000) {
              // the "zeroth" minute of the hour ... but which hour?
              // how many times to strike?
              uint8_t strike_num = (((pt_hi >> 12) & 0xF) * 10) + ((pt_hi >> 8) & 0xF);
              if (strike_num > 12) strike_num -= 12;
              if (strike_num == 0) strike_num = 12;
              // how many half-seconds into the minute are we?
              uint16_t pt_lo = ((uint16_t)(pt & 0x0000FFFF));
              uint8_t half_sec = (((pt_lo >> 12) & 0xF) * 20) + (((pt_lo >> 8) & 0xF) * 2);
              if ((pt_lo & 0xFF) >= 0x50) half_sec++;
              if (half_sec < 26) {
                switch (half_sec) {
                  // Westminster Chimes
                  case 0:  toneAC(330, 10, 420, true); break;
                  case 1:  toneAC(415, 10, 420, true); break;
                  case 2:  toneAC(370, 10, 420, true); break;
                  case 3:  toneAC(247, 10, 735, true); break;
                  case 6:  toneAC(330, 10, 420, true); break;
                  case 7:  toneAC(370, 10, 420, true); break;
                  case 8:  toneAC(415, 10, 420, true); break;
                  case 9:  toneAC(330, 10, 735, true); break;
                  case 12: toneAC(415, 10, 420, true); break;
                  case 13: toneAC(330, 10, 420, true); break;
                  case 14: toneAC(370, 10, 420, true); break;
                  case 15: toneAC(247, 10, 735, true); break;
                  case 18: toneAC(247, 10, 420, true); break;
                  case 19: toneAC(370, 10, 420, true); break;
                  case 20: toneAC(415, 10, 420, true); break;
                  case 21: toneAC(330, 10, 735, true); break;
                  default: break;
                }
              }
              else if ((half_sec < (26 + (3 * strike_num))) && ((half_sec % 3) == 2)){
                // bong the hours
                toneAC(415, 10, 750, true); 
              }
            }
          }
        }
        displayTime();    
      }
    }
  }
  else if ((set_state >= 2) && (set_state <= 15)) {
    // if we're in here, then we're in the midst of setting the date/time
    if (pushed_a) {
      // move the cursor
      set_state--;
      if (set_state == 13) set_state--; // this is not triskaidekaphobia
      while ((set_state == 9) || (set_state == 8)) set_state--;
      if (set_state == 7) {
        pd &= 0xFFFFFF00;
        pd += packedDateWeekday(pd);  
      }
      if (set_state <= 1) {
        // if we're finished setting the time, we start the clock running
        if (rtc_status == RTC_PRESENT) {  
          // BEGIN code to write the time to the Chronodot
          Wire.beginTransmission(0x68); // address DS3231
          Wire.write(0x00); // select register
    
          Wire.write((uint8_t)((pt >> 8)  & 0xFF)); // seconds
          Wire.write((uint8_t)((pt >> 16) & 0xFF)); // minutes
          Wire.write((uint8_t)((pt >> 24) & 0xFF)); // hours
          Wire.write((uint8_t)(pd & 0xFF));         // day of week
          Wire.write((uint8_t)((pd >> 8)  & 0xFF)); // day of month
          Wire.write((uint8_t)((pd >> 16) & 0xFF)); // month
          Wire.write((uint8_t)((pd >> 24) & 0xFF)); // year
    
          Wire.endTransmission();
          // END code to write the time to the Chronodot
        }
        last_tick_usec = micros();
      }
      displayTime();       
    }
    else if (pushed_b) {
      // change the number that the cursor is pointing to
      // (that is, the number itself gets changed; the cursor does not move)
      uint32_t digit_mask = (((uint32_t)0x0000000F)<<(4*(set_state&7)));      
      if (set_state >= 8) {
        if (set_state == 12) digit_mask = 0x00FF0000; // special mask for month
        // change one digit (or maybe two digits) of the date
        if ((pd & digit_mask) >= (DATE_SET_MAX & digit_mask)) pd &= ~digit_mask;
        else pd += (digit_mask & 0x11011111);
        if (set_state == 12) {
          // the month requires special treatment
          if ((pd & 0x00FF0000) == ((uint32_t)0x00000000)) {
            // there is no month 0
            pd += 0x00010000;
          }
          if ((pd & 0x000F0000) > 0x00090000) {
            // after month 9 comes month 10
            pd = (pd & 0xFFF0FFFF) + 0x00100000;
          }
        }
      }
      else {
        // change one digit of the time
        if ((pt & digit_mask) >= (TIME_SET_MAX & digit_mask)) pt &= ~digit_mask;
        else pt += (digit_mask & 0x11111111);
      }
      // show the new time
      displayTime();         
    }
  }
  delay(10); // poor man's switch debounce
}

void displayTime() {
  // set cursor to beginning of top row

  //                                     01234567890123456 


    switch (rtc_status) {
      //                                 01234567890123456




    }
  }


      //                                 01234567890123456











  // set cursor to beginning of bottom row

  // determine the correct character for the month (we'll need this for the next step)
  uint8_t month_byte = (uint8_t)((pd >> 16) & 0xFF);
  char month_char = '*';





    // this should never happen -- I'm including it strictly for debugging purposes 


  //
  //                                              01234567890123456
  // show the date and time on the display, thus: YY.M.DD HH:MM:SS



  // change the zeros to capital "O"s










void getNewTime() {
  // 
  // In case no external RTC is available, this function can serve as a substitute.
  // However, if there is an external RTC, then this function will make use of it.
  //
  const uint32_t ONE_TICK_USEC = 50000UL; // update the time every 0.05 second
  const uint32_t ONE_TICK_PACKED = 0x00000005; // see previous line
  uint32_t old_pt = pt;
  while ((micros()-last_tick_usec)>=ONE_TICK_USEC) {
    // figure out how much time has passed
    last_tick_usec += ONE_TICK_USEC;
    pt = timeAdd(pt, ONE_TICK_PACKED);
  }
  if (pt>=0x24000000) {
    pt = timeSub(pt, 0x24000000);
    // advance the date (yes, it really is this complicated!)
    // BEGIN date advance code
    if ((pd & 0x000000FF) >= 0x00000007) pd &= 0xFFFFFF00;
    pd += 0x00000101;
    if ((pd & 0x00000F00) >= 0x00000A00) pd = (pd & 0xFFFFF0FF) + 0x00001000;
    if ((pd & 0x0000FF00) >= 0x00003200) pd = (pd & 0xFFFF00FF) + 0x00010100;
    if ((pd & 0x00FFFF00) >= 0x00123200) pd = (pd & 0xFF0000FF) + 0x01010100;
    if ((pd & 0x0FFFFF00) >= 0x09123200) pd = (pd & 0xF00000FF) + 0x10010100;
    if ((pd & 0x00FFFF00) == 0x00113100) pd = (pd & 0xFF0000FF) + 0x00120100;
    if ((pd & 0x00FFFF00) == 0x00093100) pd = (pd & 0xFF0000FF) + 0x00100100;
    if ((pd & 0x00FFFF00) == 0x00063100) pd = (pd & 0xFF0000FF) + 0x00070100;
    if ((pd & 0x00FFFF00) == 0x00043100) pd = (pd & 0xFF0000FF) + 0x00050100;
    if ((pd & 0x00FFFE00) == 0x00023000) pd = (pd & 0xFF0000FF) + 0x00030100;
    if (!((((pd & 0x10000000) >> 3) ^ (pd & 0x03FFFF00)) == 0x00022900)) {
        if ((pd & 0x00FFFF00) == 0x00022900) {
          pd = (pd & 0xFF0000FF) + 0x00030100;
        }
    }
    // END date advance code
  }
  if ((rtc_status == RTC_UNKNOWN) || (old_pt != pt)) {
    if ((rtc_status == RTC_UNKNOWN) || (rtc_status == RTC_PRESENT)) {
      // We will attempt to read the RTC.
      // If we succeed, we assume that whatever date and time it gave us is correct.
      // If we fail, we assume that we don't have a good RTC, and we don't try to read it again. 
      uint32_t expected_pt = pt;
      // BEGIN attempt to read the time
      // send request to receive data starting at register 0
      Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
      Wire.write((uint8_t)0); // start at register 0
      Wire.endTransmission();
      Wire.requestFrom(0x68, 7); // request seven bytes (ss, mi, hh, wd, dd, mo, yy)
      // check for a reply from the RTC, and use it if we can
      if (Wire.available() >= 7) { 
        // if we're here, we got a reply and it is long enough
        // so now we read the time
        pt =  (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 8);  // seconds
        pt += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 16); // minutes
        pt += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 24); // hours
        pd =  (((Wire.read()) &  ((uint32_t)(0x000000FF))));        // day of week
        pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 8);  // day of month
        pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 16); // month
        pd += (((Wire.read()) & (((uint32_t)(0x000000FF)))) << 24); // year
        rtc_status = RTC_PRESENT;
        set_state = 1; // because we have successfully read the time
      }
      else {
        // if we're here, then we did not get a reply we could use
        if (rtc_status == RTC_UNKNOWN)  rtc_status = RTC_ABSENT;
        else rtc_status = RTC_TROUBLE;
      }
      // END attempt to read the time
      //
      // Most RTC units do not handle fractional seconds.
      // What follows is an attempt at estimating the missing fractional seconds.
      if ((pt & 0xFFFFFF00) == (expected_pt & 0xFFFFFF00)) {
        // hour, minute, and second are the same as expected
        // so we assume that the fractional seconds are also the same as expected
        pt = expected_pt;
      }
      else if (timeAdd(pt, 0x00000100) == (expected_pt & 0xFFFFFF00)) {
        // time is one second earlier than expected
        pt = timeAdd(pt, 0x00000099);
      }
      else if ((pt == 0x23595900) && (expected_pt < 0x00000100)) {
        // special case the second just before midnight 
        pt = 0x23595999;
      }
    }
  }  
}


// some old time manipulation functions I dug up for this

uint32_t timeAdd (uint32_t x, uint32_t y) {
  // no sanity checking of input
  // format is hhmmssff with ff being decimal fractions of a second
  // "out of range" results are e.g. A0000000 for 100 hours
  uint32_t binsum = x + y;
  uint32_t carry = ((binsum + 0x06A6A666) ^ x ^ y) & 0x11111110;
  return (binsum + ((carry - (carry>>4)) & 0x06A6A666));  
}

uint32_t timeSub (uint32_t x, uint32_t y) {
  // no sanity checking of input
  // format is hhmmssff with ff being decimal fractions of a second
  // "negative" results are e.g. F9595999 for -0.01 second
  uint32_t bindiff = x - y;
  uint32_t borrow = (bindiff ^ x ^ y) & 0x11111110;
  return (bindiff - ((borrow - (borrow>>4)) & 0x06A6A666) );
}

/*
   Usage example:

   2 h 58 min 30.98 s --> 0x02583098
   0 h  1 min 44.06 s --> 0x00014406
   
   Addition:
   timeAdd(0x02583098, 0x00014406) gives 0x03001504
                             which means 3 h 0 min 15.04 s
                             
   Subtraction:
   timeSub(0x02583098, 0x00014406) gives 0x02564692
                             which means 2 h 56 min 46.92 s
*/


// ... and a date manipulation function I made just for this

uint8_t packedDateWeekday(uint32_t p) {
  // Input is a packed date. Last two digits are ignored.
  // Format is   YYMMDDXX where XX is don't care.
  // Example:  0x16062688 means June 26, 2016
  // Output is the day of the week corresponding to the input date.
  // (1 for Monday, 2 for Tuesday, ..., 7 for Sunday)
  // There is hardly any sanity checking of input.
  uint8_t x = p >> 24;
  x -= (6 * ((x >> 4) & 0x0F));
  x += 4;
  if ((p & 0x00FF0000) <= 0x00020000) x--;
  x += (x >> 2);
  switch ((uint8_t)((p >> 16) & 0xFF)) { // the 0xFF part is paranoia
    case 0x03: x += 4; break;
    case 0x04: break;
    case 0x05: x += 2; break;
    case 0x06: x += 5; break;
    case 0x07: break;
    case 0x08: x += 3; break;
    case 0x09: x += 6; break;
    case 0x10: x += 1; break;
    case 0x11: x += 4; break;
    case 0x12: x += 6; break;
    case 0x01: x += 2; break;
    case 0x02: x += 5; break;
    default: return 0;
  }
  x += ((p >> 8) & 0xFF);
  x += ((p >> 12) & 0x0F);
  while (x > 7) x -= 7;
  return x;
}




Hi @subhrodeep

I hope you don't mind me saying, but your code looks incredibly complex for a clock project.

Have you considered buying an RTC chip and using it together with a supporting library?

I'm currently uisng Adafruit's fork of Jeelab's RTC library for the PCF8523 RTC, but it also supports the DS3231 precision RTC and the good old DS1307 as well. A lot of thought has gone into it and it includes a DateTime class that makes comparing dates and times much easier.

For example, to get the current date and time from the RTC is a single line of code:

DateTime dateTime = rtc.now();

The library seamlessly handles all the underlying I2C communication.

It's then possible to use the dataTime class to extract and compare date and time information:

unsigned int hours = dateTime.hour();
unsigned int minutes = dateTime.minute();
// etc...

It can also be used to write back date and time information to the RTC, again with a single line of code:

rtc.adjust(DateTime(0, 0, 0, hours, minutes, 0));

The library additionally includes support to activate the RTC's external 1Hz square wave output as well.

Here's a link to the library: https://github.com/adafruit/RTClib.

The RTC is not needed for that library, it can implement a millis-based clock - see the "softrtc" example. Not nearly as accurate as a hardware RTC, but it does allow you to write the code without one then simply change the constructor and a line or two in setup if you want to change to an RTC.

I was about to comment a few days ago about how convoluted the code in the original post was, and that it had seemingly been done before any of the time libraries had been created, but decided not to since the OP was only interested in the actual chiming part for their pre-existing clock sketch. My thought was to implement the chiming code using the unix time format so that the comparisons are easier, but was waiting for the OP to post their actual clock code.

@david_2018 I hadn't noticed the "softrtc" example, but that's pretty neat, allows you to "try before you buy".

I said in post #5 that I had thought of an application for such a clock so I have made a quick start with just the "Westminster" melody.
It may help you get started. It uses the tone() library so you are free which pin you choose. I have not yet implemented the strikes.
You'll need the .h and .cpp file from the attached zip archive.

/*
 *  Westminster Chimes Demonstration
 *  
 *  copy Chime.h and Chime.cpp into the same folder as this sketch.
 * 
 *  alter / improve the melody bay changing the array melody[] [] 
 *  in Chime.h
 * 
 *  Set sounder pin below (any unused pin)
 * 
 * 
 */

#include "Chime.h"

Chime chime( 9 ) ;  // <<<<< sounder pin

void setup() {
  Serial.begin( 115200 ) ;
  Serial.println( "Westminster_Clock V0_01" ) ;
  chime.setup() ;
}

void loop() {
  // no blocking code allowed in loop() 
  
  // just to test every 30 seconds. You may have to wait up to 30 seconds to hear it.
  if( millis() % 30000 == 0 ) {
    chime.sound( 0 ) ; // strikes not implemented yet
  }
  
  chime.loop() ; // must always be run every loop iteration.

}

Westminster_Clock_V0_01.zip (1.7 KB)

Westminster melody works but strike missing that I have in previous code. I am using a separate microcontroller, all are working good but night time chiming cannot be stopped. Is it possible to make only melody with strike and stop it between 10pm to 7am?

Here is Westminster Chimes plus strikes. The sound quality is certainly no match for the original "Big Ben" but the melody is vaguely recognisable.
I've set a random number of strikes so you can see how to integrate it with your clock.
For advice on limiting the sound to certain time ranges, see previous posts in this thread.

/*
 *  Westminster Chimes Demonstration
 *  
 *  copy Chime.h and Chime.cpp into the same folder as this sketch.
 * 
 *  alter / improve the melody bay changing the array melody[] [] 
 *  in Chime.h
 * 
 *  Set sounder pin below (any unused pin)
 * 
 * 
 */

#include "Chime.h"

Chime chime( 9 ) ;  // <<<<< sounder pin

void setup() {
  Serial.begin( 115200 ) ;
  Serial.println( "Westminster_Clock V0_03" ) ;
  chime.setup() ;
}

void loop() {
  // no blocking code allowed in loop() 
  
  // just to test every 30 seconds. You may have to wait up to 30 seconds to hear it.
  if( millis() % 30000 == 0 ) {
    int numberOfStrikes = random( 1, 12+1 ) ;
    chime.sound( numberOfStrikes ) ; // strikes 1..12
  }
  
  chime.loop() ; // must always be run every loop iteration.

}

You'll need the .h and .cpp file from the attached zip archive.
Westminster_Clock_V0_03.zip (2.0 KB)