Python RGB Matrix games and animations https://www.xythobuz.de/ledmatrix_v2.html
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

mapper.py 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #!/usr/bin/env python3
  2. # ----------------------------------------------------------------------------
  3. # "THE BEER-WARE LICENSE" (Revision 42):
  4. # <xythobuz@xythobuz.de> wrote this file. As long as you retain this notice
  5. # you can do whatever you want with this stuff. If we meet some day, and you
  6. # think this stuff is worth it, you can buy me a beer in return. Thomas Buck
  7. # ----------------------------------------------------------------------------
  8. import util
  9. import time
  10. import sys
  11. useNTP = False
  12. try:
  13. import ntptime
  14. useNTP = True
  15. except:
  16. pass
  17. # Does nothing. Take this as parent for new mappers.
  18. class MapperNull:
  19. def __init__(self, g):
  20. self.gui = g
  21. self.width = self.gui.width
  22. self.height = self.gui.height
  23. self.multiplier = self.gui.multiplier
  24. self.panelW = self.gui.panelW
  25. self.panelH = self.gui.panelH
  26. if hasattr(self.gui, "matrix"):
  27. self.matrix = self.gui.matrix
  28. def batteryCache(self, refresh = False):
  29. return self.gui.batteryCache(refresh)
  30. def exit(self):
  31. self.gui.exit()
  32. def loop_start(self):
  33. return self.gui.loop_start()
  34. def loop_end(self):
  35. self.gui.loop_end()
  36. def set_pixel(self, x, y, color):
  37. self.gui.set_pixel(x, y, color)
  38. # For some reason the red and green LEDs on older Pimoroni panels
  39. # are far brighter than on newer panels.
  40. # Adjust this by multiplying rg channels with 0.75 and b channel
  41. # with 0.85, depending on hard-corded coordinate ranges.
  42. class MapperColorAdjust(MapperNull):
  43. def set_pixel(self, x, y, color):
  44. # second panel from the left, with 32 <= x,
  45. # is "old" type with brighter LEDs.
  46. # rest of panels to the left are less bright.
  47. # so adjust brightness of other panel channels down.
  48. if x >= self.gui.panelW:
  49. color = (int(color[0] * 0.75), int(color[1] * 0.75), color[2] * 0.85)
  50. self.gui.set_pixel(x, y, color)
  51. # This converts a long 128x32 strip to a 64x64 panel.
  52. # The Pi is always connected to d, the last subpanel.
  53. #
  54. # (0, 0) (128, 0)
  55. # a b c d
  56. # (0, 32) (128, 32)
  57. #
  58. # on the hardware is converted to this for the effects:
  59. #
  60. # (0, 0) (64, 0)
  61. # a b
  62. # c d
  63. # (0, 64) (64, 64)
  64. class MapperStripToRect(MapperNull):
  65. def __init__(self, g):
  66. super().__init__(g)
  67. self.width = int(self.gui.width / 2)
  68. self.height = self.gui.height * 2
  69. def set_pixel(self, x, y, color):
  70. if (x < 0) or (y < 0) or (x >= self.width) or (y >= self.height):
  71. return
  72. if y >= self.gui.height:
  73. x += self.width
  74. y -= self.panelH
  75. self.gui.set_pixel(x, y, color)
  76. # Fetches current time via NTP.
  77. # System time will be in UTC afterwards, not with local time-zone
  78. # offset like when using rshell (eg. when using with a Pico).
  79. #
  80. # Brightness of display will be adjusted according to current time.
  81. # To avoid being too bright at night.
  82. #
  83. # When used with the Interstate75 Pico implementation,
  84. # this needs to be the "first" element of the mapper chain.
  85. # Otherwise special handling for PicoText will not work.
  86. class MapperReduceBrightness(MapperNull):
  87. def __init__(self, g, i = None):
  88. super().__init__(g)
  89. self.input = i
  90. self.last = None
  91. self.connected = False
  92. self.refresh = 60 * 60 * 6
  93. self.factor = 1.0
  94. self.user_mod = None
  95. self.old_keys = {
  96. "left": False,
  97. "right": False,
  98. "up": False,
  99. "down": False,
  100. "a": False,
  101. "b": False,
  102. "x": False,
  103. "y": False,
  104. "l": False,
  105. "r": False,
  106. "start": False,
  107. "select": False,
  108. }
  109. def fetch(self):
  110. if useNTP:
  111. if not self.connected:
  112. self.connected = util.connectToWiFi()
  113. if self.connected:
  114. now = time.time()
  115. if (self.last == None) or ((now - self.last) >= self.refresh) or (now < self.last):
  116. self.last = now
  117. try:
  118. print("Before sync: " + str(time.localtime()))
  119. ntptime.settime()
  120. print("After sync: " + str(time.localtime()))
  121. except Exception as e:
  122. print()
  123. if hasattr(sys, "print_exception"):
  124. sys.print_exception(e)
  125. else:
  126. print(e)
  127. print()
  128. return
  129. else:
  130. if self.last == None:
  131. self.last = time.time()
  132. print("Time: " + str(time.localtime()))
  133. # (year, month, day, hour, minute, second, ?, ?)
  134. now = time.localtime()
  135. # TODO ntptime is setting to UTC, host is on proper timezone
  136. if useNTP:
  137. # 6pm utc == 8pm cest germany
  138. evening = (now[0], now[1], now[2], 18, 0, 0, 0, 0)
  139. # 0am utc == 2am cest germany
  140. night = (now[0], now[1], now[2], 0, 0, 0, 0, 0)
  141. # 6am utc == 8am cest germany
  142. morning = (now[0], now[1], now[2], 6, 0, 0, 0, 0)
  143. else:
  144. # 8pm cest germany
  145. evening = (now[0], now[1], now[2], 20, 0, 0, 0, 0)
  146. # 2am cest germany
  147. night = (now[0], now[1], now[2], 2, 0, 0, 0, 0)
  148. # 8am cest germany
  149. morning = (now[0], now[1], now[2], 8, 0, 0, 0, 0)
  150. if (now >= morning) and (now < evening):
  151. self.factor = 1.0
  152. elif (now >= evening) or (now < night):
  153. self.factor = 0.42
  154. else:
  155. self.factor = 0.1
  156. def buttons(self):
  157. keys = self.input.get()
  158. if (keys["select"] and keys["up"] and (not self.old_keys["up"])) or (keys["up"] and keys["select"] and (not self.old_keys["select"])):
  159. self.factor += 0.05
  160. self.factor = min(self.factor, 0.95)
  161. self.user_mod = time.time()
  162. elif (keys["select"] and keys["down"] and (not self.old_keys["down"])) or (keys["down"] and keys["select"] and (not self.old_keys["select"])):
  163. self.factor -= 0.05
  164. self.factor = max(self.factor, 0.05)
  165. self.user_mod = time.time()
  166. self.old_keys = keys.copy()
  167. def adjust(self, color):
  168. return (int(color[0] * self.factor), int(color[1] * self.factor), int(color[2] * self.factor))
  169. def loop_start(self):
  170. if self.input != None:
  171. self.buttons()
  172. return super().loop_start()
  173. def loop_end(self):
  174. super().loop_end()
  175. if self.user_mod == None:
  176. self.fetch()
  177. elif (time.time() - self.user_mod) > self.refresh:
  178. # fall back from user-modified factor after 6h
  179. self.user_mod = None
  180. def set_pixel(self, x, y, color):
  181. color = self.adjust(color)
  182. self.gui.set_pixel(x, y, color)