ePaper display driven by a Raspberry Pi Pico
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 

199 righe
6.1 KiB

  1. import epaper
  2. import microbmp
  3. import time
  4. import random
  5. import os
  6. import storage
  7. import gc
  8. gc.enable()
  9. epd_resolution = [600, 448]
  10. epd_colormap = [
  11. [0x00, 0x00, 0x00], # black
  12. [0xff, 0xff, 0xff], # white
  13. [0x00, 0x90, 0x10], # green
  14. [0x00, 0x00, 0xee], # blue
  15. [0xff, 0x00, 0x00], # red
  16. [0xff, 0xdd, 0x00], # yellow
  17. [0xff, 0x77, 0x00], # orange
  18. ]
  19. max_free_height = 200
  20. def init_display():
  21. #print("ePaper init ", str(time.localtime()))
  22. epd = epaper.EPD_5in65()
  23. epd.fill(epd.White)
  24. return epd
  25. def draw_image(filename):
  26. global epd
  27. global epd_colormap
  28. global free_x, free_y, free_width, free_height
  29. offset_x = 0
  30. offset_y = 0
  31. free_x = 0
  32. free_y = 0
  33. free_width = 0
  34. free_height = 0
  35. color_map = {}
  36. def header_callback(header):
  37. #print("header callback: ", str(header))
  38. global epd_resolution
  39. global offset_x, offset_y
  40. global free_x, free_y, free_width, free_height
  41. global max_free_height
  42. w = header[0]
  43. h = header[1]
  44. rest_x = (epd_resolution[0] - w)
  45. rest_y = (epd_resolution[1] - h)
  46. free_x = 0
  47. free_y = max(h, epd_resolution[1] - max_free_height)
  48. free_width = epd_resolution[0]
  49. free_height = min(rest_y, max_free_height)
  50. offset_x = rest_x//2
  51. offset_y = max(0, rest_y - max_free_height)//2
  52. def pixel_callback(x, y, color):
  53. global epd
  54. global epd_colormap
  55. global offset_x, offset_y
  56. # translate color to color index
  57. color_index = 0
  58. color_key = color[0] + color[1] << 8 + color[2] << 16
  59. if color_key in color_map:
  60. color_index = color_map[color_key]
  61. else:
  62. # search for the best color
  63. best_index = 0
  64. best_score = 1000
  65. for index in range(len(epd_colormap)):
  66. c1 = epd_colormap[index]
  67. c2 = color
  68. score = abs(c1[0] - c2[0]) + abs(c1[1] - c2[1]) + abs(c1[2] - c2[2])
  69. if score < best_score:
  70. best_score = score
  71. best_index = index
  72. if score < 10:
  73. break
  74. color_index = best_index
  75. color_map[color_key] = color_index
  76. epd.pixel(offset_x + x, offset_y + y, color_index)
  77. def pixel_row_callback(x, y, colors):
  78. pass
  79. #global epd
  80. #print("PXL ", str([color, r,g,b, pixel]))
  81. #for i in range(len(colors)):
  82. # epd.pixel(offset_x + x + i, offset_y + y, color_to_index(colors[i]))
  83. #print(str(time.localtime()), " BMP ", filename, " loading")
  84. time_start = time.ticks_ms()
  85. epd.fill(epd.White)
  86. microbmp.MicroBMP(header_callback=header_callback, data_callback=pixel_callback).load(filename)
  87. time_loaded = time.ticks_ms()
  88. print(" time to load: ", (time_loaded - time_start) / 1000, " s")
  89. #print(str(time.localtime()), " BMP loaded")
  90. #epd.EPD_5IN65F_Display(epd.buffer)
  91. #print(str(time.localtime()), " ePaper printed")
  92. return [free_x, free_y, free_width, free_height]
  93. def draw_pattern():
  94. global epd
  95. global epd_resolution
  96. free_x = 0
  97. free_y = 400
  98. free_width = epd_resolution[0]
  99. free_height = epd_resolution[1] - free_y
  100. epd.fill_rect(0, 0, epd_resolution[0], free_y, random.randrange(2,7))
  101. return [free_x, free_y, free_width, free_height]
  102. def load_joke(root):
  103. filename = root + "/jokes.json"
  104. num_lines = sum(1 for line in open(filename))
  105. with open(filename, mode="r") as f:
  106. joke = None
  107. start_pattern = "\"joke\": \""
  108. end_pattern = "\""
  109. for i in range(random.randrange(num_lines)):
  110. line = f.readline()
  111. for i in range(10):
  112. line = f.readline()
  113. joke_start = line.find(start_pattern)
  114. joke_end = line.rfind(end_pattern)
  115. if joke_start >= 0 and joke_end >= 0:
  116. joke = line[joke_start+len(start_pattern):joke_end]
  117. return joke
  118. return None
  119. def print_text(text, region, center=False):
  120. global epd
  121. fnt = 8
  122. x = region[0]
  123. y = region[1]
  124. w = region[2]
  125. h = region[3]
  126. if center:
  127. x = (w - len(text)*fnt) // 2
  128. epd.text(text, x, y, epd.Black)
  129. def draw_extra(region, caption):
  130. fnt = 8
  131. region[0] += 5
  132. region[1] += 8
  133. if region[2] < fnt or region[3] < fnt:
  134. print("Not enough space for extra: ", str(region))
  135. return
  136. #epd.rect(region[0], region[1], region[2], region[3], epd.Black)
  137. #region[0] += random.randrange(50)
  138. #print_text(str(time.localtime()), region, center=True)
  139. if caption is not None:
  140. #region[1] += fnt * 2
  141. print_text(caption, region)
  142. print("Caption: ", caption)
  143. else:
  144. print("No caption")
  145. # MAIN
  146. epd = init_display()
  147. disk = storage.Storage()
  148. while True:
  149. disk.mount()
  150. images = list(filter(lambda x : x.endswith(".bmp"), os.listdir(disk.get_root_path())))
  151. epd.EPD_5IN65F_Init()
  152. epd.fill(epd.White)
  153. filename = random.choice(images)
  154. print("TV drawing image ", filename)
  155. free_space = [0,0,0,0]
  156. try:
  157. free_space = draw_image(disk.get_root_path() + "/" + filename)
  158. except Exception as e:
  159. print("Failed drawing image from disk: ", e)
  160. try:
  161. free_space = draw_image("tiny.bmp")
  162. except Exception as e:
  163. print("Failed drawing fallback image: ", e)
  164. free_space = draw_pattern()
  165. caption = None
  166. try:
  167. caption = load_joke(disk.get_root_path())
  168. except Exception as e:
  169. print("Failed loading a joke: ", e)
  170. try:
  171. draw_extra(free_space, caption)
  172. except Exception as e:
  173. print("Failed drawing extra: ", e)
  174. time_render_start = time.ticks_ms()
  175. epd.EPD_5IN65F_Display(epd.buffer)
  176. time_render_stop = time.ticks_ms()
  177. print(" time to render: ", (time_render_stop - time_render_start) / 1000, " s")
  178. print("TV showing ", filename)
  179. epd.Sleep()
  180. disk.umount()
  181. print("")
  182. gc.collect()
  183. epd.delay_ms(60000 * 1)