text.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #!/usr/bin/env python3
  2. import argparse
  3. import struct
  4. from PIL import Image
  5. import control
  6. class TextControl(control.BoardControlBase):
  7. COLOR_BASE = 0x6000
  8. SCREEN_BASE = 0x8000
  9. GLYPH_BASE = 0xc000
  10. def __init__(self, **kwargs):
  11. # Super call
  12. super().__init__(**kwargs)
  13. def bus_write(self, addr, data):
  14. self.slave.exchange(struct.pack('>BHH', 0, addr, data))
  15. def upload_font(self, fn, s=0):
  16. img = Image.open(fn)
  17. for i in range(0x0000, 0x2000):
  18. c = (i >> 5)
  19. fx = (c & 0xf) * 9
  20. fy = ((c >> 4) & 0xf) * 17
  21. cx = (i & 0x01) * 4
  22. cy = (i & 0x1e) >> 1
  23. data = (
  24. ((img.getpixel( (fx+cx+0, fy+cy) )[0] >> 7) << 12) |
  25. ((img.getpixel( (fx+cx+1, fy+cy) )[0] >> 7) << 8) |
  26. ((img.getpixel( (fx+cx+2, fy+cy) )[0] >> 7) << 4) |
  27. ((img.getpixel( (fx+cx+3, fy+cy) )[0] >> 7) << 0)
  28. )
  29. self.bus_write(self.GLYPH_BASE + s*0x2000 + i, data)
  30. def default_config(text):
  31. # Colors
  32. # FG
  33. for i in range(0x6000, 0x6008):
  34. text.bus_write(i, (i & 0x7) | ((i & 0x7) << 4))
  35. # BG
  36. for i in range(0x6008, 0x6010):
  37. text.bus_write(i, (i & 0x7) | ((i & 0x7) << 4) | 0x88)
  38. # Custom RGBI
  39. for i in range(0x6020, 0x6030):
  40. text.bus_write(i, (i & 0xf) | ((i & 0xf) << 4))
  41. # Font
  42. text.upload_font('../data/VGA-8x16.png')
  43. def show_font(text):
  44. # Char matrix
  45. for i in range(0x0000, 0x4000):
  46. text.bus_write(text.SCREEN_BASE + i,
  47. (i & 0xff) |
  48. (((i >> 8) & 0x3f) << 10) |
  49. (1 << 9)
  50. )
  51. def show_bars(text):
  52. # Create a font
  53. for i in range(16):
  54. d = (i << 0) | (i << 4) | (i << 8) | (i << 12)
  55. for w in range(32):
  56. text.bus_write(text.GLYPH_BASE + 0x2000 + i*32 + w, d)
  57. # Bands on the screen
  58. for y in range(64):
  59. for x in range(256):
  60. addr = text.SCREEN_BASE | (y << 8) | x
  61. text.bus_write(addr,
  62. ((x >> 3) & 0xf) |
  63. (1 << 8) |
  64. (2 << 12)
  65. )
  66. def main():
  67. # Parse options
  68. parser = argparse.ArgumentParser(
  69. formatter_class=argparse.ArgumentDefaultsHelpFormatter
  70. )
  71. g_text = parser.add_argument_group('test', 'Text core options')
  72. g_brd = parser.add_argument_group('board', 'Board configuration options')
  73. g_text.add_argument('--show-font', help='Show font over FG/BG palette', action='store_true', default=False)
  74. g_text.add_argument('--show-bars', help='Show color bars', action='store_true', default=False)
  75. control.arg_group_setup(g_brd)
  76. args = parser.parse_args()
  77. # Build control object with those params
  78. kwargs = control.arg_to_kwargs(args)
  79. text = TextControl(**kwargs)
  80. # Commands
  81. default_config(text)
  82. if args.show_font:
  83. show_font(text)
  84. if args.show_bars:
  85. show_bars(text)
  86. if __name__ == '__main__':
  87. main()