/ CLUE_I_Ching / code.py
code.py
  1  # SPDX-FileCopyrightText: 2020 Carter Nelson for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  import time
  6  import random
  7  import displayio
  8  from adafruit_bitmap_font import bitmap_font
  9  from adafruit_display_text import label
 10  from adafruit_clue import clue
 11  
 12  #--| User Config |-------------------------------
 13  BACKGROUND_COLOR = 0xCFBC17
 14  HEXAGRAM_COLOR   = 0xBB0000
 15  FONT_COLOR       = 0x005500
 16  SHAKE_THRESHOLD  = 20
 17  MELODY = ( (1000, 0.1),  # (freq, duration)
 18             (1200, 0.1),
 19             (1400, 0.1),
 20             (1600, 0.2))
 21  #--| User Config |-------------------------------
 22  
 23  # Defined in order treating each hexagram as a 6 bit value.
 24  HEXAGRAMS = (
 25      "EARTH", "RETURN", "THE ARMY", "PREVAILING", "MODESTY", "  CRYING\nPHEASANT",
 26      "ASCENDANCE", "PEACE", "WEARINESS", "THUNDER", "LETTING\n LOOSE",
 27      "MARRYING\n MAIDEN", " SMALL\nEXCESS", "ABUNDANCE", "STEADFASTNESS",
 28      " GREAT\nINJURY", "SUPPORT", "RETRENCHMENT", "WATER", "FRUGALITY",
 29      "ADMONISHMENT", "FULFILLMENT", "THE WELL", "WAITING", "ILLNESS",
 30      "THE CHASE", "TRAPPED", "LAKE", "CUTTING", "REVOLUTION", " GREAT\nEXCESS",
 31      "STRIDE", "LOSS", "THE CHEEKS", "BLINDNESS", "DECREASE", "MOUNTAIN",
 32      "DECORATION", "WORK", "   BIG\nCATTLE", "ADVANCE", "BITING", "UNFULFILLMENT",
 33      "ABANDONED", "TRAVELER", "FIRE", "    THE\nCAULDRON", " GREAT\nHARVEST",
 34      "VIEW", "INCREASE", "FLOWING", "SINCERITY", "PROGRESS", "FAMILY", "WIND",
 35      " SMALL\nCATTLE", "OBSTRUCTION", "PROPRIETY", "THE COURT", "TREADING",
 36      "LITTLE\n  PIG", "GATHERING", "RENDEZVOUS", "HEAVEN",
 37  )
 38  
 39  # Grab the CLUE's display
 40  display = clue.display
 41  
 42  # Background fill
 43  bg_bitmap = displayio.Bitmap(display.width, display.height, 1)
 44  bg_palette = displayio.Palette(1)
 45  bg_palette[0] = BACKGROUND_COLOR
 46  background = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette)
 47  
 48  # Hexagram setup
 49  sprite_sheet = displayio.Bitmap(11, 4, 2)
 50  palette = displayio.Palette(2)
 51  palette.make_transparent(0)
 52  palette[0] = 0x000000
 53  palette[1] = HEXAGRAM_COLOR
 54  
 55  for x in range(11):
 56      sprite_sheet[x, 0] = 1 # - - 0 YIN
 57      sprite_sheet[x, 1] = 0
 58      sprite_sheet[x, 2] = 1 # --- 1 YANG
 59      sprite_sheet[x, 3] = 0
 60  sprite_sheet[5, 0] = 0
 61  
 62  tile_grid = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
 63                                 width = 1,
 64                                 height = 6,
 65                                 tile_width = 11,
 66                                 tile_height = 2)
 67  
 68  hexagram = displayio.Group(x=60, y=15, scale=10)
 69  hexagram.append(tile_grid)
 70  
 71  # Hexagram name label
 72  # font credit: https://www.instagram.com/cove703/
 73  font = bitmap_font.load_font("/christopher_done_24.bdf")
 74  font.load_glyphs(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
 75  hexname = label.Label(font, text=" "*40, color=FONT_COLOR)
 76  # this will initially hold the "shake for reading" message
 77  hexname.text = " SHAKE\n   FOR\nREADING"
 78  hexname.anchor_point = (0.5, 0.5)
 79  hexname.anchored_position = (120, 120)
 80  
 81  # Set up main display group (splash)
 82  splash = displayio.Group()
 83  display.show(splash)
 84  
 85  # Add background and text label
 86  splash.append(background)
 87  splash.append(hexname)
 88  
 89  def show_hexagram(number):
 90      for i in range(6):
 91          tile_grid[5-i] = (number >> i) & 0x01
 92  
 93  def show_name(number):
 94      hexname.text = HEXAGRAMS[number]
 95      hexname.anchored_position = (120, 180)
 96  
 97  #===================================
 98  # MAIN CODE
 99  #===================================
100  print("shake")
101  # wait for shake
102  while not clue.shake(shake_threshold=SHAKE_THRESHOLD):
103      pass
104  
105  # calibrate the mystic universe
106  x, y, z = clue.acceleration
107  random.seed(int(time.monotonic() + abs(x) + abs(y) + abs(z)))
108  
109  # cast a reading
110  reading = random.randrange(64)
111  print("reading = ", reading, HEXAGRAMS[reading])
112  
113  # play a melody
114  for note, duration in MELODY:
115      clue.play_tone(note, duration)
116  
117  # prompt to show
118  display.auto_refresh = False
119  hexname.text = "      GOT IT\n\nPRESS BUTTON\n       TO SEE"
120  hexname.anchored_position = (120, 120)
121  display.auto_refresh = True
122  while not clue.button_a and not clue.button_b:
123      pass
124  
125  # and then show it
126  display.auto_refresh = False
127  splash.append(hexagram)
128  show_hexagram(reading)
129  show_name(reading)
130  display.auto_refresh = True
131  
132  # hold here until reset
133  while True:
134      pass