diff --git a/README.rst b/README.rst index d829818..955db91 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,12 @@ +DEPRECATED LIBRARY micropython-adafruit-rgb-display +=================================================== + +This library has been deprecated! We are leaving this up for historical and research purposes but archiving the repository. + +We are only supporting CircuitPython libraries. + +Check out the CircuitPython RGB Display library for using RGB displays with Python on microcontrollers: https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display + Display drivers for MicroPython. -================================ Documentation available at http://micropython-rgb.readthedocs.io/ diff --git a/docs/display.rst b/docs/display.rst index c59aa68..08f817c 100644 --- a/docs/display.rst +++ b/docs/display.rst @@ -12,7 +12,7 @@ Utilities .. class:: DummyPin() - Can be used in place of a ``Pin()`` when you don't want to skip it. + Can be used in place of a ``Pin()`` when you want to skip it. Display Class @@ -47,3 +47,9 @@ This is the interface that all the display classes share. .. method:: vline(x, y, height, color) Draw a vertical line. + + ..method:: blit_buffer(buffer, x, y, width, height) + + Copy the pixels from the buffer onto the display, starting at position + ``(x, y)`` and assuming the copied area has width ``width`` and height + ``height``. The area has to fit entirely inside the display diff --git a/docs/displays.rst b/docs/displays.rst index 772ef5e..b2a57f8 100644 --- a/docs/displays.rst +++ b/docs/displays.rst @@ -11,7 +11,7 @@ All of those displays support the methods of the :class:`Display` class. A TFT display. .. module:: ili9341 -.. class:: ILI9241(spi, dc, cs, rst=None, width=240, height=320) +.. class:: ILI9341(spi, dc, cs, rst=None, width=240, height=320) A TFT display. diff --git a/docs/index.rst b/docs/index.rst index cd0b28f..d0330eb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,7 +3,7 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to MicroPython Adafruti RGB Displays's documentation! +Welcome to MicroPython Adafruit RGB Displays's documentation! ============================================================= Contents: diff --git a/hx8353.py b/hx8353.py index 5258c59..18b7647 100644 --- a/hx8353.py +++ b/hx8353.py @@ -15,7 +15,7 @@ class HX8353(DisplaySPI): """ - A simple driver for the ST7735-based displays. + A simple driver for the HX8383-based displays. >>> from machine import Pin, SPI >>> import hx8353 diff --git a/rgb.py b/rgb.py index 9e1f41f..cfb9551 100644 --- a/rgb.py +++ b/rgb.py @@ -8,14 +8,37 @@ def color565(r, g, b): class DummyPin: """A fake gpio pin for when you want to skip pins.""" - def init(self, *args, **kwargs): - pass - def low(self): - pass - - def high(self): - pass + OUT = 0 + IN = 0 + PULL_UP = 0 + PULL_DOWN = 0 + OPEN_DRAIN = 0 + ALT = 0 + ALT_OPEN_DRAIN = 0 + LOW_POWER = 0 + MED_POWER = 0 + HIGH_PWER = 0 + IRQ_FALLING = 0 + IRQ_RISING = 0 + IRQ_LOW_LEVEL = 0 + IRQ_HIGH_LEVEL = 0 + + def __call__(self, *args, **kwargs): + return False + + init = __call__ + value = __call__ + out_value = __call__ + toggle = __call__ + high = __call__ + low = __call__ + on = __call__ + off = __call__ + mode = __call__ + pull = __call__ + drive = __call__ + irq = __call__ class Display: @@ -81,7 +104,8 @@ def fill_rectangle(self, x, y, width, height, color): data = pixel * 512 for count in range(chunks): self._write(None, data) - self._write(None, pixel * rest) + if rest: + self._write(None, pixel * rest) def fill(self, color=0): """Fill whole screen.""" @@ -95,45 +119,57 @@ def vline(self, x, y, height, color): """Draw a vertical line.""" self.fill_rectangle(x, y, 1, height, color) + def blit_buffer(self, buffer, x, y, width, height): + """Copy pixels from a buffer.""" + if (not 0 <= x < self.width or + not 0 <= y < self.height or + not 0 < x + width <= self.width or + not 0 < y + height <= self.height): + raise ValueError("out of bounds") + self._block(x, y, x + width - 1, y + height - 1, buffer) + class DisplaySPI(Display): - def __init__(self, spi, dc, cs, rst=None, width=1, height=1): + def __init__(self, spi, dc, cs=None, rst=None, width=1, height=1): self.spi = spi self.cs = cs self.dc = dc self.rst = rst + if self.rst is None: + self.rst = DummyPin() + if self.cs is None: + self.cs = DummyPin() self.cs.init(self.cs.OUT, value=1) self.dc.init(self.dc.OUT, value=0) - if self.rst: - self.rst.init(self.rst.OUT, value=0) - self.reset() + self.rst.init(self.rst.OUT, value=1) + self.reset() super().__init__(width, height) def reset(self): - self.rst.low() + self.rst(0) utime.sleep_ms(50) - self.rst.high() + self.rst(1) utime.sleep_ms(50) def _write(self, command=None, data=None): if command is not None: - self.dc.low() - self.cs.low() + self.dc(0) + self.cs(0) self.spi.write(bytearray([command])) - self.cs.high() + self.cs(1) if data is not None: - self.dc.high() - self.cs.low() + self.dc(1) + self.cs(0) self.spi.write(data) - self.cs.high() + self.cs(1) def _read(self, command=None, count=0): - self.dc.low() - self.cs.low() + self.dc(0) + self.cs(0) if command is not None: self.spi.write(bytearray([command])) if count: data = self.spi.read(count) - self.cs.high() + self.cs(1) return data diff --git a/rgb_text.py b/rgb_text.py new file mode 100644 index 0000000..fdbf4a1 --- /dev/null +++ b/rgb_text.py @@ -0,0 +1,16 @@ +import framebuf + +def text(display, text, x=0, y=0, color=0xffff, background=0x0000): + x = min(display.width - 1, max(0, x)) + y = min(display.height - 1, max(0, y)) + w = display.width - x + h = min(display.height - y, 8) + buffer = bytearray(display.width * h * 2) + fb = framebuf.FrameBuffer(buffer, w, h, framebuf.RGB565) + for line in text.split('\n'): + fb.fill(background) + fb.text(line, 0, 0, color) + display.blit_buffer(buffer, x, y, w, h) + y += 8; + if y >= display.height: + break diff --git a/s6d02a1.py b/s6d02a1.py index d858882..546ac5b 100644 --- a/s6d02a1.py +++ b/s6d02a1.py @@ -12,7 +12,7 @@ class S6D02A1(DisplaySPI): """ - A simple driver for the ST7735-based displays. + A simple driver for the S6D02A1-based displays. >>> from machine import Pin, SPI >>> import s6d02a1 diff --git a/ssd1331.py b/ssd1331.py index 9a0808a..637e2f8 100644 --- a/ssd1331.py +++ b/ssd1331.py @@ -36,11 +36,11 @@ class SSD1331(DisplaySPI): """ >>> -from machine import Pin, HSPI +from machine import Pin, SPI import ssd1331 #spi = SPI(mosi=Pin(13), sck=Pin(14), polarity=1, phase=1) -spi = HSPI(polarity=1, phase=1) -display = ssd1331.SSD1331(spi, dc=Pin(2), cs=Pin(15), rst=Pin(16)) +spi = SPI(1, polarity=1, phase=1) +display = ssd1331.SSD1331(spi, dc=Pin(12), cs=Pin(15), rst=Pin(16)) display.fill(0x7521) display.pixel(32, 32, 0) """ @@ -57,21 +57,21 @@ class SSD1331(DisplaySPI): (_NORMALDISPLAY, b''), # (_FILL, b'\x01'), -# (_PHASEPERIOD, b'\x31'), -# (_SETMULTIPLEX, b'\x3f'), -# (_SETMASTER, b'\x8e'), -# (_POWERMODE,b'\x0b'), -# (_PRECHARGE, b'\x31'), #;//0x1F - 0x31 -# (_CLOCKDIV, b'\xf0'), -# (_VCOMH, b'\x3e'), #;//0x3E - 0x3F -# (_MASTERCURRENT, b'\x06'), # ;//0x06 - 0x0F -# (_PRECHARGEA, b'\x64'), -# (_PRECHARGEB, b'\x78'), -# (_PRECHARGEC, b'\x64'), -# (_PRECHARGELEVEL, b'\x3a'), # 0x3A - 0x00 -# (_CONTRASTA, b'\x91'), #//0xEF - 0x91 -# (_CONTRASTB, b'\x50'), #;//0x11 - 0x50 -# (_CONTRASTC, b'\x7d'), #;//0x48 - 0x7D + (_PHASEPERIOD, b'\x31'), + (_SETMULTIPLEX, b'\x3f'), + (_SETMASTER, b'\x8e'), + (_POWERMODE,b'\x0b'), + (_PRECHARGE, b'\x31'), #;//0x1F - 0x31 + (_CLOCKDIV, b'\xf0'), + (_VCOMH, b'\x3e'), #;//0x3E - 0x3F + (_MASTERCURRENT, b'\x0c'), # ;//0x06 - 0x0F + (_PRECHARGEA, b'\x64'), + (_PRECHARGEB, b'\x78'), + (_PRECHARGEC, b'\x64'), + (_PRECHARGELEVEL, b'\x3a'), # 0x3A - 0x00 + (_CONTRASTA, b'\x91'), #//0xEF - 0x91 + (_CONTRASTB, b'\x50'), #;//0x11 - 0x50 + (_CONTRASTC, b'\x7d'), #;//0x48 - 0x7D (_DISPLAYON, b''), ) _ENCODE_PIXEL = ">H" @@ -79,3 +79,15 @@ class SSD1331(DisplaySPI): def __init__(self, spi, dc, cs, rst=None, width=96, height=64): super().__init__(spi, dc, cs, rst, width, height) + + def _write(self, command=None, data=None): + if command is None: + self.dc(1) + else: + self.dc(0) + self.cs(0) + if command is not None: + self.spi.write(bytearray([command])) + if data is not None: + self.spi.write(data) + self.cs(1) diff --git a/ssd1351.py b/ssd1351.py index 1aa1f88..fa875c9 100644 --- a/ssd1351.py +++ b/ssd1351.py @@ -39,7 +39,7 @@ class SSD1351(DisplaySPI): >>> from machine import Pin, SPI import ssd1351 -spi = SPI(mosi=Pin(13), sck=Pin(14)) +spi = SPI(1, baudrate=20000000) display = ssd1351.SSD1351(spi, dc=Pin(12), cs=Pin(15), rst=Pin(16)) display.fill(0x7521) display.pixel(32, 32, 0) @@ -78,4 +78,3 @@ class SSD1351(DisplaySPI): def __init__(self, spi, dc, cs, rst=None, width=128, height=128): super().__init__(spi, dc, cs, rst, width, height) - diff --git a/st7735.py b/st7735.py index d083565..ff16a52 100644 --- a/st7735.py +++ b/st7735.py @@ -1,4 +1,5 @@ from rgb import DisplaySPI, color565 +import ustruct _NOP=const(0x00) @@ -54,8 +55,8 @@ class ST7735(DisplaySPI): >>> from machine import Pin, SPI >>> import st7735 - >>> spi = SPI(mosi=Pin(13), sck=Pin(14)) - >>> display = st7735.ST7735(spi, dc=Pin(12), cs=Pin(15), rst=Pin(16)) + >>> display = st7735.ST7735(SPI(1), dc=Pin(12), cs=Pin(15), rst=Pin(16)) + >>> display = st7735.ST7735R(SPI(1, baudrate=40000000), dc=Pin(12), cs=Pin(15), rst=Pin(16)) >>> display.fill(0x7521) >>> display.pixel(64, 64, 0) @@ -67,25 +68,32 @@ class ST7735(DisplaySPI): _INIT = ( (_SWRESET, None), (_SLPOUT, None), - (_COLMOD, b'\x05'), # 16bit color - # fastest refresh, 6 lines front porch, 3 line back porch - (_FRMCTR1, b'\x00\x06\x03'), + (_MADCTL, b'\x08'), # bottom to top refresh + (_COLMOD, b'\x05'), # 16bit color + (_INVCTR, b'0x00'), # line inversion + # 1 clk cycle nonoverlap, 2 cycle gate rise, 3 sycle osc equalie, # fix on VTL (_DISSET5, b'\x15\x02'), - (_INVCTR, b'0x00'), # line inversion + # fastest refresh, 6 lines front porch, 3 line back porch + (_FRMCTR1, b'\x00\x06\x03'), + (_PWCTR1, b'\x02\x70'), # GVDD = 4.7V, 1.0uA (_PWCTR2, b'\x05'), # VGH=14.7V, VGL=-7.35V (_PWCTR3, b'\x01\x02'), # Opamp current small, Boost frequency - (_VMCTR1, b'\x3c\x38'), # VCOMH = 4V, VOML = -1.1V (_PWCTR6, b'\x11\x15'), + + (_VMCTR1, b'\x3c\x38'), # VCOMH = 4V, VOML = -1.1V + (_GMCTRP1, b'\x09\x16\x09\x20\x21\x1b\x13\x19' b'\x17\x15\x1e\x2b\x04\x05\x02\x0e'), # Gamma (_GMCTRN1, b'\x08\x14\x08\x1e\x22\x1d\x18\x1e' b'\x18\x1a\x24\x2b\x06\x06\x02\x0f'), + (_CASET, b'\x00\x02\x00\x81'), # XSTART = 2, XEND = 129 - (_RASET, b'\x00\x02\x00\x81'), # XSTART = 2, XEND = 129 + (_RASET, b'\x00\x02\x00\x81'), # YSTART = 2, YEND = 129 + (_NORON, None), (_DISPON, None), ) @@ -94,3 +102,48 @@ class ST7735(DisplaySPI): def __init__(self, spi, dc, cs, rst=None, width=128, height=128): super().__init__(spi, dc, cs, rst, width, height) + + +class ST7735R(ST7735): + _INIT = ( + (_SWRESET, None), + (_SLPOUT, None), + + (_MADCTL, b'\xc8'), + (_COLMOD, b'\x05'), # 16bit color + (_INVCTR, b'\x07'), + + (_FRMCTR1, b'\x01\x2c\x2d'), + (_FRMCTR2, b'\x01\x2c\x2d'), + (_FRMCTR3, b'\x01\x2c\x2d\x01\x2c\x2d'), + + (_PWCTR1, b'\x02\x02\x84'), + (_PWCTR2, b'\xc5'), + (_PWCTR3, b'\x0a\x00'), + (_PWCTR4, b'\x8a\x2a'), + (_PWCTR5, b'\x8a\xee'), + + (_VMCTR1, b'\x0e'), + (_INVOFF, None), + + (_GMCTRP1, b'\x02\x1c\x07\x12\x37\x32\x29\x2d' + b'\x29\x25\x2B\x39\x00\x01\x03\x10'), # Gamma + (_GMCTRN1, b'\x03\x1d\x07\x06\x2E\x2C\x29\x2D' + b'\x2E\x2E\x37\x3F\x00\x00\x02\x10'), + ) + + def __init__(self, spi, dc, cs, rst=None, width=128, height=160): + super().__init__(spi, dc, cs, rst, width, height) + + def init(self): + super().init() + cols = ustruct.pack('>HH', 0, self.width - 1) + rows = ustruct.pack('>HH', 0, self.height - 1) + for command, data in ( + (_CASET, cols), + (_RASET, rows), + + (_NORON, None), + (_DISPON, None), + ): + self._write(command, data)