Drawing Clock Digits
The Seven Segments of a Numeric Digit
Since the early history of computing, numeric displays were created using a grouping of seven individual lights to display a single digit. These are called Seven Segment Displays. An example is shown in the image below:
The segments are labeled "a" through "g" starting at the top and going around in a clockwise direction. Note that the seventh segment is in the center element is the "g" segment.
Technically, many displays have an 8th segment for the decimal point (DP). To keep things simple we will just focus on the main seven segments in this lesson.
Clocks also usually have a colon that separates the hours and minutes and an AM/PM indicator for 12-hour displays. We will be treating these and independent drawing components in this lab. Many digital clocks have the colon flash on and off every second.
The Segment Map
To start out, we need to create a "digit-to-segment map" data structure. We use this to help us figure out what segments to turn on for any given digit.
We will also need to convert the segment letters into integers. These integers will form the index of an array.
To write our code, we ask, for any given digit, is the segment on or off?
To do this, we can create an array of segments like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
For any given digit like "2" we can then just pass the index of "2" to a Python list to get a list of the segments to turn on. That line of code looks like this:
1 |
|
This will return the segments that are to be turned on for any given input digit. For example:
1 2 3 4 |
|
We now have the data structure to do the drawing. We will do this in two steps.
- Draw the three horizontal lines for a digit if they are on
- Draw all vertical lines for a given digit, keeping in mind that we need to only draw half the way down the digit for the upper left and upper right vertical segments (1 and 5)
We will start out with a simple digit drawing using a single-pixel width line. Later we will add a parameter to change the thickness of the line. But we want to take this one-step-at-a-time.
Drawing Horizontal Segments
This sample code will step through the horizontal lines
for segments 0, 3 and 6. It will check using the segmentOn[i]
line which will ONLY be true if that segment should be turned
on for a given digit.
Next, we figure out how high to draw the horizontal line. To do this we will need to figure out the vertical offset (yOffset). The top line (segment 0) has no offset and the bottom line has the full height of the digit.
Unlike the vertical lines, the horizontal lines will span the entire width of the area. That makes our code simple because the line will have a horizontal length of exactly the x plus the width of the digit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Drawing the Vertical Segments
Next, we need to create some code to draw the four vertical segments. This is a little more complex because the lines do NOT span the full height of the digit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Testing Our Drawing
We can now wrap the code above in a drawDigit()
function, and we will
test each of the digits 0-9 in a small test program.
Our first version of drawDigit is modeled after the rect() function. After we pass in the digit, it takes in the (x,y) and width and height parameters and the color value.
Draw Digit Function Parameters:
- The digit to display - an integer in the range 0-9
- x of the upper left corner
- y of the upper left corner
- the width of the digit (about 20 is a good value)
- the height of the digit
- the color (0=black, 1=white)
Here is our testing program that draws digits 0-9 in the center of a standard 128x64 monochrome OLED display:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
|
This drawDigit()
is very handy. We just need to
give the function some parameters and it will draw
the right digit at a location (x,y) as the upper
left corner with the correct width and height!
But the lines are somewhat thin. A more robust implementation will also allow us the change the thickness of the segments. That will be more complex since we will have to adjust the starting point of where we draw each segment based on the thickness of the segment. We will also need to use a rectangle, not a line. This requires we figure out the exact width and height before we draw.
We explore that function in the next lesson.