# @name Tix_Clock # @config interval select "Update Interval in Seconds" default=60 options=1,2,3,4,6,10,12,15,20,30,60 help="Display will update at the specified increment from :00 and whenever the app is launched" # @config mil_time bool "24 Hour Time" default=true # @config hour_tens_color color "Hour Tens Digit Color" default=#FF0000 # @config hour_ones_color color "Hour Ones Digit Color" default=#FFFF00 # @config minute_tens_color color "Minutes Tens Digit Color" default=#00FF00 # @config minute_ones_color color "Minute Ones Digit Color" default=#0000FF # @config off_color color "Off Pixel Color" default=#FFFFFF import math #import string class Tix_Clock var values_0 var values_1 var values_2 var values_3 var values_4 var values_5 var values_6 var values_7 var values_8 var values_9 var values_ht_0 var values_ht_1 var values_ht_2 var values var hour_tens var hour_ones var minute_tens var minute_ones var prev_update var columns var digits var colors var mil_time var off_color var interval var logging var random_values def init() # Really ugly lookup table of values who binary representation have the appropriate number of bits set self.values_0 = [0] self.values_1 = [1,2,4,8,16,32,64,128,256] self.values_2 = [3,5,6,9,10,12,17,18,20,24,33,34,36,40,48,65,66,68,72,80,96,129,130,132,136,144,160,192,257,258,260,264,272,288,320,384] self.values_3 = [7,11,13,14,19,21,22,25,26,28,35,37,38,41,42,44,49,50,52,56,67,69,70,73,74,76,81,82,84,88,97,98,100,104,112,131,133,134,137,138,140,145,146,148,152,161,162,164,168,176,193,194,196,200,208,224,259,261,262,265,266,268,273,274,276,280,289,290,292,296,304,321,322,324,328,336,352,385,386,388,392,400,416,448] self.values_4 = [15,23,27,29,30,39,43,45,46,51,53,54,57,58,60,71,75,77,78,83,85,86,89,90,92,99,101,102,105,106,108,113,114,116,120,135,139,141,142,147,149,150,153,154,156,163,165,166,169,170,172,177,178,180,184,195,197,198,201,202,204,209,210,212,216,225,226,228,232,240,263,267,269,270,275,277,278,281,282,284,291,293,294,297,298,300,305,306,308,312,323,325,326,329,330,332,337,338,340,344,353,354,356,360,368,387,389,390,393,394,396,401,402,404,408,417,418,420,424,432,449,450,452,456,464,480] self.values_5 = [31,47,55,59,61,62,79,87,91,93,94,103,107,109,110,115,117,118,121,122,124,143,151,155,157,158,167,171,173,174,179,181,182,185,186,188,199,203,205,206,211,213,214,217,218,220,227,229,230,233,234,236,241,242,244,248,271,279,283,285,286,295,299,301,302,307,309,310,313,314,316,327,331,333,334,339,341,342,345,346,348,355,357,358,361,362,364,369,370,372,376,391,395,397,398,403,405,406,409,410,412,419,421,422,425,426,428,433,434,436,440,451,453,454,457,458,460,465,466,468,472,481,482,484,488,496] self.values_6 = [63,95,111,119,123,125,126,159,175,183,187,189,190,207,215,219,221,222,231,235,237,238,243,245,246,249,250,252,287,303,311,315,317,318,335,343,347,349,350,359,363,365,366,371,373,374,377,378,380,399,407,411,413,414,423,427,429,430,435,437,438,441,442,444,455,459,461,462,467,469,470,473,474,476,483,485,486,489,490,492,497,498,500,504] self.values_7 = [127,191,223,239,247,251,253,254,319,351,367,375,379,381,382,415,431,439,443,445,446,463,471,475,477,478,487,491,493,494,499,501,502,505,506,508] self.values_8 = [255,383,447,479,495,503,507,509,510] self.values_9 = [511] # Special lists for the Hour Tens digit, that only include bits 0, 3, 6; makes it easier when we get to draw() self.values_ht_0 = [0] self.values_ht_1 = [1, 8, 64] self.values_ht_2 = [9, 65, 72] # Store all of them in a map self.values = {0: self.values_0, 1: self.values_1, 2: self.values_2, 3: self.values_3, 4: self.values_4, 5: self.values_5, 6: self.values_6, 7: self.values_7, 8: self.values_8, 9: self.values_9, 10: self.values_ht_0, 11: self.values_ht_1, 12: self.values_ht_2} # These will store the digits that represent the time we wish to display self.hour_tens = -1 self.hour_ones = -1 self.minute_tens = -1 self.minute_ones = -1 self.digits = [] # This will keep track of what second (derived from epoch) we last updated, so that we only update the displayed values at the approriate interval; -1 will tell us to do an update on reset self.prev_update = -1 # These will be the left most columns on the display for the 4 digits (assumes 32x8 display, will need to revisit for other displays) self.columns = [0, 4, 14, 24] # Update interval, in seconds self.interval = -1 # And this list will hold said values for when draw() is called but we don't need to display new random binary values self.random_values = [-1, -1, -1, -1] end def setup() math.srand(second()) # Seed the RNG # Get our user config values self.colors = [store.get("hour_tens_color"), store.get("hour_ones_color"), store.get("minute_tens_color"), store.get("minute_ones_color")] self.mil_time = store.get("mil_time") self.off_color = store.get("off_color") self.interval = int(store.get("interval")) end def loop() # If this is the first time the app has run or we've hit the update interval, get new values if (self.prev_update == -1) || ((int(epoch_ms() / 1000) % self.interval == 0) && int(epoch_ms() / 1000) != self.prev_update) # Break the time to display into the 4 separate digits and store them in a list if (self.mil_time) || (hour() < 13) # Use slightly different math for the hour depending on if we're in 24 hour mode or not self.hour_tens = math.floor(hour() / 10) self.hour_ones = hour() % 10 else self.hour_tens = math.floor((hour() - 12) / 10) self.hour_ones = (hour() - 12) % 10 end self.minute_tens = math.floor(minute() / 10) self.minute_ones = minute() % 10 self.digits = [self.hour_tens, self.hour_ones, self.minute_tens, self.minute_ones] # Store what time in epoch seconds we performed this update so that we update at the appropriate interval self.prev_update = int(epoch_ms() / 1000) # Iterate through the 4 digits and get random binary values to display for them for i: 0 .. 3 var bin_list = [] var bin_value = -1 if i != 0 bin_list = self.values.find(int(self.digits[i])) # Get the approriate list from the values map that have i number of bits set else bin_list = self.values.find(int(self.digits[i]) + 10) # Since it's the Hour Tens digit, need the special lists that are at keys 10-12 of the values map end bin_value = bin_list[math.rand() % int(size(bin_list))] # Pick a random value from the list we got self.random_values[i] = bin_value # Store the random values that the draw() sequence will display end end end def draw() var out_color var out_x = -1 var out_y = -1 # Go through the 4 digits and draw the appropriate pixels for i: 0 .. 3 for j: 0 .. 8 # Go through each pixel location for the digit if ((i != 0) || (j % 3 == 0)) # For the Hour Tens digit, only go through i = 0, 3, 6, as it's a 1x3 area and not a 3x3 like the others # If the bit representing this pixel in the random value is set, use the "on" color for that pixel, otherwise use the "off" color if self.random_values[i] & (1 << j) out_color = self.colors[i] else out_color = self.off_color end # Get the X and Y coordinates of the pixel we will be drawing out_x = self.columns[i] + 3 * (j % 3) out_y = 3 * math.floor(j / 3) # Draw the pixel rect(out_x, out_y, 2, 2, out_color) end end end end end return Tix_Clock()