-
Notifications
You must be signed in to change notification settings - Fork 131
/
binary_clock.py
executable file
·151 lines (127 loc) · 5.86 KB
/
binary_clock.py
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python
from __future__ import print_function
import unicornhat
import datetime
from time import sleep
print("""True Binary Clock made by Jarrod Price, inspired by Iorga Dragos Florian and reviewed by Philip Howard
Displays the time on the LEDs as follows:
Top row -> First 4 = Month(Pink), Last 4 = Day(Blue/Green. If Green add 16 to value shown, no lights = 16th)
Second row -> First 2 = Alarm(Orange), Last 6 = Hour(Red)
Third row -> First 2 = Alarm(Orange), Last 6 = Minute(Yellow)
Fourth row -> First 2 = Alarm(Orange), Last 6 = Second(Green)""")
unicornhat.set_layout(unicornhat.AUTO)
# default brightness does not need to be too bright
unicornhat.brightness(0.5)
# get the width of the hat because the LEDs are displayed from the righ to the left
width, height = unicornhat.get_shape()
right_most_pixel = width - 1
# colour tuples
red = (255, 0, 0)
orange = (255, 127, 0)
yellow = (255, 255, 0)
green = (0, 255, 0)
blue = (0, 127, 255)
lightblue = (100, 200, 255)
magenta = (255, 0, 255)
white = (255, 255, 255)
# alarm must be 24 hour format
alarm_time = '07:00'
# how many minutes should the alarm flash for
alarm_flash_time = 5
# inform the world what time the alarm will go off
print('Alarm set for: ', alarm_time)
def draw_time_string(time_string, length, offset, row, colour):
"""Draw the binary time on a specified row in a certain colour.
:param time_string: string containing time value that will be used for the bit comparison
:param length: width of the binary string once converted, e.g. 5 bits for day, 6 bits for hour and minute
:param offset: left offset - all values are displayed with right alignment as conventional binary dictates, the offest will move it to the left
:param row: row on which to display the time, this is the y-axis
:param colour: colour to draw in
"""
# convert the time string to an integer
value = int(time_string)
# loop through the pixels from the right to the left
for i in range(right_most_pixel, right_most_pixel - length, -1):
# use the & operator to do a bit comparison
# for example:
# 1 & 1 = 1 (ie: 0b1 & 0b1 = 0b1)
# 2 & 1 = 0 (ie: 0b10 & 0b01 = 0b00)
if value & 1:
rgb = colour
else:
rgb = (0, 0, 0)
# determine where on the row it should display this LED
# either at the given location in the loop or shifted over to the left a little
column = (i - offset)
# set the pixels colour
unicornhat.set_pixel(column, row, rgb)
# use a binary shift to move all the values over to the right
# for example:
# 10 = 0b1010 shifted by 1 place becomes 0b0101 = 5
# 5 = 0b101 shifted by place becomes 0b010 = 2
value >>= 1
# this function will make use of the remaining space to light up when indicated
def alarm(t, c):
# by default we will assume the alarm will not be triggered so keep the default states of the brightness and LED colours
unicornhat.brightness(0.5)
b = '0'
# grab the hour and minute from the set alarm time
h = int(alarm_time[:2])
m = int(alarm_time[3:])
s = 0
# create time slot for alarm for today
at = t.replace(hour=h, minute=m, second=s)
# create a new time object by adding x minutes to the alarm time
ft = at + datetime.timedelta(minutes=alarm_flash_time)
# now check if it's time to flash the alarm or not, by checking if we have passed the time it is meant to go off or 5 minutes have not gone passed
if t >= at and t < ft:
# signal the alarm!
# set the brightness to max
unicornhat.brightness(1)
# this will make it flash ON when a second is equal and OFF when it is odd
if int(t.second % 2) == 0:
# when converted to binary becomes 0b11, so this will turn ON 2 LEDs per row
b = '3'
# always update the pixels, the logic above will decide if it displays or not
# 3 rows, 2 LEDs wide for the alarm, padded to left by 6
draw_time_string(b, 2, 6, 1, c)
draw_time_string(b, 2, 6, 2, c)
draw_time_string(b, 2, 6, 3, c)
# this is the main function, will get the current time and display each time and check the alarm
def binary_clock():
try:
while True:
now = datetime.datetime.now()
# draw each time string in their specific locations
draw_time_string(now.month, 4, 4, 0, magenta)
# Day field is 4 bits (lights) long, and as we don't use 0-indexed
# days of the month, that means we can only represent 1-15 (0b1 - 0b1111)
# To solve this, if the day > 15 (0b1111), we change the colour to indidcate
# that 16 (0b10000) must be added to the displayed value.
if now.day > 0b1111:
# Day > 15
# Truncate the day to only 4 bits, as we only have 4 lights
# This will remove the bit representing 16, which will
# be encoded as colour
day = now.day & 0b1111
# Encode the missing bit as colour
day_colour = green
else:
# Day is 15 or less so the bit representing 16 is not set and the number can be displayed normally
day = now.day
day_colour = blue
draw_time_string(day, 4, 0, 0, day_colour)
draw_time_string(now.hour, 6, 0, 1, red)
draw_time_string(now.minute, 6, 0, 2, yellow)
draw_time_string(now.second, 6, 0, 3, green)
# check if the alarm needs to be signalled or not
alarm(now, orange)
# we've now set all the LEDs, time to show the world our glory!
unicornhat.show()
# sleep for 1 second, because we don't want to waste unnecessary CPU
sleep(1)
except Exception as e:
print(e)
print("Exiting")
if __name__ == "__main__":
binary_clock()