stream.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/usr/bin/env python3
  2. import argparse
  3. import time
  4. import control
  5. class PanelControl(control.BoardControlBase):
  6. def __init__(self, n_banks=2, n_rows=32, n_cols=64, colordepth=16, **kwargs):
  7. # Super call
  8. super().__init__(**kwargs)
  9. # Save panel description
  10. self.n_banks = n_banks
  11. self.n_rows = n_rows
  12. self.n_cols = n_cols
  13. self.colordepth = colordepth
  14. # Pre-create buffers
  15. self.line_bytes = n_cols * (colordepth // 8)
  16. self.send_buf = bytearray(1 + self.line_bytes)
  17. self.send_buf_view = memoryview(self.send_buf)
  18. def send_line_file(self, fh):
  19. self.send_buf_view[0] = 0x80
  20. rb = fh.readinto(self.send_buf_view[1:])
  21. if rb != self.line_bytes:
  22. return False
  23. self.slave.exchange(self.send_buf)
  24. return True
  25. def send_line_data(self, data):
  26. self.send_buf_view[0] = 0x80
  27. self.send_buf_view[1:] = data
  28. self.slave.exchange(self.send_buf)
  29. def send_frame_file(self, fh):
  30. # Scan all line
  31. for y in range(self.n_banks * self.n_rows):
  32. # Send write command to line buffer
  33. if not self.send_line_file(fh):
  34. return False
  35. # Swap line buffer & Write it to line y of back frame buffer
  36. self.reg_w8(0x03, y)
  37. # Send frame swap command
  38. self.reg_w8(0x04, 0x00)
  39. # Wait for the frame swap to occur
  40. while (self.read_status() & 0x02 == 0):
  41. pass
  42. return True
  43. def send_frame_data(self, frame):
  44. # View on the data
  45. frame_view = memoryview(frame)
  46. # Scan all line
  47. for y in range(self.n_banks * self.n_rows):
  48. # Send write command to line buffer
  49. self.send_line_data(frame_view[y*self.line_bytes:(y+1)*self.line_bytes])
  50. # Swap line buffer & Write it to line y of back frame buffer
  51. self.reg_w8(0x03, y)
  52. # Send frame swap command
  53. self.reg_w8(0x04, 0x00)
  54. # Wait for the frame swap to occur
  55. while (self.read_status() & 0x02 == 0):
  56. pass
  57. def main():
  58. # Parse options
  59. parser = argparse.ArgumentParser(
  60. formatter_class=argparse.ArgumentDefaultsHelpFormatter
  61. )
  62. g_input = parser.add_argument_group('input', 'Input options')
  63. g_panel = parser.add_argument_group('panel', 'Panel configuation options')
  64. g_brd = parser.add_argument_group('board', 'Board configuration options')
  65. g_input.add_argument('--input', type=argparse.FileType('rb'), metavar='FILE', help='Input file', required=True)
  66. g_input.add_argument('--fps', type=float, help='Target FPS to regulate to (None=no regulation)')
  67. g_input.add_argument('--loop', help='Play in a loop', action='store_true', default=False)
  68. g_panel.add_argument('--n_banks', type=int, metavar='N', help='Number of banks', default=2)
  69. g_panel.add_argument('--n_rows', type=int, metavar='N', help='Number of rows', default=32)
  70. g_panel.add_argument('--n_cols', type=int, metavar='N', help='Number of columns', default=64)
  71. g_panel.add_argument('--colordepth', type=int, metavar='DEPTH', help='Bit per color', default=16)
  72. control.arg_group_setup(g_brd)
  73. args = parser.parse_args()
  74. # Build the actual panel control object with those params
  75. kwargs = control.arg_to_kwargs(args)
  76. kwargs['n_banks'] = args.n_banks
  77. kwargs['n_rows'] = args.n_rows
  78. kwargs['n_cols'] = args.n_cols
  79. kwargs['colordepth'] = args.colordepth
  80. panel = PanelControl(**kwargs)
  81. # Streaming loop
  82. if args.fps:
  83. tpf = 1.0 / args.fps
  84. tt = time.time() + tpf
  85. while True:
  86. # Send one frame
  87. rv = panel.send_frame_file(args.input)
  88. # Loop ?
  89. if not rv:
  90. if args.loop:
  91. args.input.seek(0)
  92. continue
  93. else:
  94. break
  95. # FPS regulation
  96. if args.fps:
  97. w = tt - time.time()
  98. if w > 0:
  99. time.sleep(w)
  100. tt += tpf
  101. if __name__ == '__main__':
  102. main()