A Binary Clock

[Home]   [Puzzles & Projects]    [Delphi Techniques]   [Math topics]   [Library]   [Utilities]




Search WWW

Search DelphiForFun.org

As of October, 2016, Embarcadero is offering a free release of Delphi (Delphi 10.1 Berlin Starter Edition ).     There are a few restrictions, but it is a welcome step toward making more programmers aware of the joys of Delphi.  They do say "Offer may be withdrawn at any time", so don't delay if you want to check it out.  Please use the feedback link to let me know if the link stops working.


Support DFF - Shop

 If you shop at Amazon anyway,  consider using this link. 


We receive a few cents from each purchase.  Thanks


Support DFF - Donate

 If you benefit from the website,  in terms of knowledge, entertainment value, or something otherwise useful, consider making a donation via PayPal  to help defray the costs.  (No PayPal account necessary to donate via credit card.)  Transaction is secure.

Mensa Daily Puzzlers

For over 15 years Mensa Page-A-Day calendars have provided several puzzles a year for my programming pleasure.  Coding "solvers" is most fun, but many programs also allow user solving, convenient for "fill in the blanks" type.  Below are Amazon  links to the two most recent years.

Mensa 365 Puzzlers  Calendar 2017

Mensa 365 Puzzlers Calendar 2018

(Hint: If you can wait, current year calendars are usually on sale in January.)


Feedback:  Send an e-mail with your comments about this program (or anything else).

Search DelphiForFun.org only




Problem Description

Here's a binary clock that may be useful when learning the binary number system.

Background & Techniques

I received a hardware version of this clock as a Christmas gift this year.    It occurred to me that a software version might be helpful in an educational environment.    I.e., for someone teaching or learning the binary number system.  

In the familiar decimal number system, we use 10 symbols  (0 through 9) and  positions from the left side of the number represent increasing powers of 10.   So 289 in decimal means 2 "hundreds" + 8 "tens" + 9 "ones".   In the binary system, we use two symbols (0 and 1) and  positions from the left represent increasing powers of 2.    So 1101 in binary represents 1 "eight" + 1 "four" + 0 "twos" + 1 "one"   (or 13 in decimal). 

In our clock we are going to represent each of the six digits used for hours, minutes and seconds as a binary number.  Since each number represents a single decimal digit, we will need 4 binary digits for each.  The maximum number we can represent with three binary digits (bits) is 111 which is 4+2+1=7 and we will also need to show bit representation of 8 and 9, thus the need for four.  

To match the hardware version of the clock, I represent the numbers vertically with the  top LED representing "8" .  So, using  "light off" for 0 and  "light on"  for 1, the clock above  represents 09:50:34.

Binary Values  Decimal value of row
0 1 0 0 0 0 "8"
0 0 1 0 0 1 "4"
0 0 0 0 1 0 "2"
0 1 1 0 1 0 "1"
H H M M S S  
0 9 5 0 3 4 Decimal -- time 

The clock starts with the current system clock time and is updated every second.    You may left click anywhere on the clock to start and stop it.   Right mouse clicks will bring up a configuration panel with a number of options.  You can change the background, LED, and label  colors,  set 12 or 24 hr. time formats, hide or display labels, etc. 

I added way to enter an arbitrary time value to be displayed, even hiding it as entered if appropriate, so that students could be tested on their ability to convert fixed binary values to decimal.   By default clocks with manually entered times will be in stopped mode - clicking can start  such clocks running from the entered time. 

Non-programmers are welcome to read on, but may want to skip to the bottom of this page to download executable version of the program.

This was a fun little program providing a chance to practice with  several Delphi features. 

bulletThe timer's OnTimer timer exit, Timer1Timer,  updates the clock (if the clock is running).  It actually calls the UpdateTime procedure to put the current time value in binary format, ready to display.  I'm checking for seconds change every 1/10 second, just to ensure that clock updates stay accurate.  
bulletThe form's OnPaint exit , FormPaint, does the actual drawing on the form's canvas.
bulletThe form's OnResize exit, FormResize,  is called by windows initially and every time that the form is resized.  This exit calculates the "cell size" for each binary digit or label character, and the size of the LED image and the size of the label font (HHMMSS or 8421 labels).
bulletIn the configuration dialog, ConfigDlg,  I used the PasswordChar property of the edit box to optionally hide or display times being manually entered. 

There is some confusion over the best way to update a form's canvas.  We can choose from calling FormPaint procedure directly, Invalidate, Update, Repaint.

Here's the way I understand it:

bulletOur OnPaint exit procedure, FormPaint, issues commands (windows messages really) which  write to the form's canvas. It is called automatically by Windows when, for example, the window is resized, moved, restored after being minimized, is redrawn when some popup window that covered the clock is removed, etc.   We can also call it directly when we know that the display needs to be redrawn.   These paint messages are normally considered low priority and will be processed by windows the next time it is idle.   
bulletInvalidate marks the entire window as invalid so that it will be erased and entirely redrawn the next time that paint messages are processed.
bulletUpdate forces window to immediately processes any outstanding paint messages for this window.
bulletRepaint calls Invalidate followed by Update.

In this case, it is adequate just to call FormPaint from UpdateTime.  We will be waiting for the next timer pop most of the time anyway, so there is plenty of time for windows to update the screen.   Just for fun, I tried several other techniques and left them as comments in the code.   The only noticeable difference is a slight flicker when Invalidate is used.  I suppose because it erases the background before repainting the screen.  

Why can't we just  embed the drawing code in the UpdateTime procedure?  If the clock is running, we could since it will be redrawn every second anyway.   Try stopping the clock though and then minimize and restore it, and you'll see the problem.   

Running/Exploring the Program 

bulletDownload source
bulletDownload  executable

Suggestions for Further Explorations

How about an "advanced"  configuration option that switches to 3 columns (one each for hours, minutes, and seconds) with 6 bits each  - we would need 6 bits to represent 59 minutes or seconds.   
Add an option to the configuration panel to switch display from vertical to horizontal layout.


Original Date: February 14, 2003 

Modified: May 15, 2018

  [Feedback]   [Newsletters (subscribe/view)] [About me]
Copyright 2000-2018, Gary Darby    All rights reserved.