├── CircuitPython_XiaoRoundDisplay.py ├── LICENSE ├── README.md └── examples └── AllFunctionTest.py /CircuitPython_XiaoRoundDisplay.py: -------------------------------------------------------------------------------- 1 | #Author: Mitsuharu Aoyama 2 | #Date: May 2024 3 | 4 | # Dependencies: 5 | # adafruit_register 6 | # gc9a01 7 | # adafruit_bus_device 8 | 9 | # Hardware: 10 | # Round Display for XIAO 11 | 12 | 13 | # Round Display for XIAO has CHSC6540 capacitive touch controller. 14 | # Datasheet: https://szzxv.com/static/upload/file/20220301/1646141990530969.pdf 15 | 16 | import board 17 | import digitalio 18 | import displayio 19 | import gc9a01 20 | from adafruit_register import i2c_bit 21 | from adafruit_bus_device.i2c_device import I2CDevice 22 | 23 | #Author: Mitsuharu Aoyama 24 | #Date: May 2024 25 | 26 | # Dependencies: 27 | # adafruit_register 28 | # gc9a01 29 | # adafruit_bus_device 30 | 31 | # Hardware: 32 | 33 | # Round Display for XIAO has CHSC6540 capacitive touch controller. 34 | # Datasheet: https://szzxv.com/static/upload/file/20220301/1646141990530969.pdf 35 | 36 | # GC9A01 display settings 37 | 38 | # FourWire pins 39 | tft_dc = board.D3 40 | tft_cs = board.D1 41 | # gc9a01 pins and settings 42 | tft_bl = board.D6 # Backlight 43 | dw = 240 # display width 44 | dh = 240 # display height 45 | 46 | # CHSC6540 Capacitive Touch 47 | CHSC6540_I2C_ADDRESS = 0x2e 48 | CHSC6540_READ_POINT_LEN = 5 49 | irq_pin = board.D7 50 | 51 | # Screen size of the Round Display for XIAO 52 | xmax = 240 53 | ymax = 240 54 | 55 | class XiaoRoundDisplay(): 56 | def __init__(self, i2c_bus, spi_bus, rotation): 57 | # Bus 58 | self._i2c = i2c_bus 59 | self._spi = spi_bus 60 | 61 | # Touch Interrupt ReQuest 62 | self._irq = digitalio.DigitalInOut(irq_pin) if irq_pin else None 63 | if self._irq: 64 | self._irq.switch_to_input(pull=digitalio.Pull.UP) 65 | 66 | self._buffer = bytearray(CHSC6540_READ_POINT_LEN) 67 | 68 | # Display 69 | self._spi = spi_bus 70 | self.rotation = rotation 71 | print("Touch panel Rotation={} degree".format(rotation)) 72 | 73 | def display(self): 74 | # GC9A01 display 75 | # IMPORTANT: You need to release_displays before creating display_bus 76 | displayio.release_displays() 77 | self.display_bus = displayio.FourWire( 78 | self._spi, 79 | command=tft_dc, 80 | chip_select=tft_cs 81 | ) 82 | d = gc9a01.GC9A01( 83 | self.display_bus, 84 | width=dw, 85 | height=dh, 86 | backlight_pin=tft_bl 87 | ,rotation=self.rotation 88 | ) 89 | return d 90 | 91 | def rotate(self, x, y): 92 | self.x = x 93 | self.y = y 94 | if self.rotation == 0: 95 | return x, y 96 | if self.rotation == 90: 97 | return y, (dw - x) 98 | if self.rotation == 180: 99 | return (dw - x), (dh - y) 100 | if self.rotation == 270: 101 | return (dh - y), x 102 | 103 | def is_touched(self): 104 | if self._irq: 105 | return not self._irq.value 106 | return self.touch_read() is not None 107 | 108 | def touch_read(self): 109 | if self._irq and not self._irq.value: 110 | try: 111 | self.i2c_dev = I2CDevice(self._i2c, CHSC6540_I2C_ADDRESS) 112 | with self.i2c_dev: 113 | self.i2c_dev.readinto(self._buffer) 114 | 115 | results = [i for i in self._buffer] 116 | 117 | if results[0]: # first byte is non-zero when touched 118 | x = results[2] # 3rd byte is x 119 | y = results[4] # 5th byte is y 120 | x1, y1 = self.rotate(x, y) 121 | return x1, y1 # Return (x1, y1) tuple 122 | return None 123 | except: 124 | # print("touching too fast!") 125 | pass 126 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 STEAM Tokyo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 日本語の説明文は下のほうにあります。 2 | 3 | # Round Display for XIAO Touch Driver for CircuitPython 4 | [Seeed Studio Round Display for XIAO](https://wiki.seeedstudio.com/get_start_round_display/) has GC9A01 LCD with the capacitive touch function. 5 | By using this CircuitPython driver, you can create the display object and also get the touched (X, Y) coordinates. 6 | You can set the screen rotation by 90 degrees. 7 | 8 | 9 | 10 | ## Installation 11 | Simply copy the CircuitPython_XiaoRoundDisplay.py to the lib folder of your board. 12 | 13 | ## Dependencies 14 | Requires following libraries. 15 | - adafruit_bus_device 16 | - adafruit_register 17 | - gc9a01 (distributed in the community bundle) 18 | 19 | [CircuitPython.org](https://circuitpython.org/libraries/) 20 | 21 | ## Usage example 22 | 23 | ```py 24 | import time 25 | import board 26 | import busio 27 | from CircuitPython_XiaoRoundDisplay import XiaoRoundDisplay 28 | import displayio 29 | 30 | # You need to release_displays after soft-rebooting the board 31 | displayio.release_displays() 32 | 33 | spi = busio.SPI(board.SCK, board.MOSI, board.MISO) 34 | i2c = busio.I2C(board.SCL, board.SDA) 35 | 36 | # GC9A01 display and Touch panel common settings 37 | rotation = 0 # 0, 90, 180 or 270 degree 38 | 39 | # Round Display for XIAO object 40 | xrd = XiaoRoundDisplay(i2c, spi, rotation) 41 | screen = xrd.display() # Screen object 42 | 43 | # displayio settings 44 | bitmap = displayio.Bitmap(screen.width, screen.height, 2) 45 | 46 | # Create a two color palette 47 | palette = displayio.Palette(2) 48 | palette[0] = 0x000000 49 | palette[1] = 0xffffff 50 | 51 | # Create a TileGrid using the Bitmap and Palette 52 | tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette) 53 | # Create a Group 54 | group = displayio.Group() 55 | # Add the TileGrid to the Group 56 | group.append(tile_grid) 57 | # Add the Group to the Display 58 | screen.root_group = group 59 | 60 | print("You can touch the screen to draw.") 61 | while True: 62 | if xrd.is_touched(): 63 | t = xrd.touch_read() 64 | if t is not None: 65 | x, y = t 66 | bitmap[x, y] = 1 67 | time.sleep(0.001) 68 | ``` 69 | 70 | # Round Display for XIAO用CircuitPythonドライバ 71 | [Seeed Studio Round Display for XIAO](https://wiki.seeedstudio.com/get_start_round_display/) にはGC9A01ディスプレイと静電容量タッチパネルが搭載されています。 72 | このCircuitPythonのドライバを使うことで、GC9A01のディスプレイオブジェクトを作成するとともに、タッチした(X, Y)座標を取得することができます。 73 | また、90度単位で画面の回転を設定できます。 74 | 75 | ## インストール 76 | 本レポジトリのCircuitPython_XiaoRoundDisplay.pyをCircuitPythonがインストールされたマイコンにコピーしてください。 77 | 78 | ## 依存関係 79 | 下記CircuitPythonライブラリのインストールが必要です。 80 | - adafruit_bus_device 81 | - adafruit_register 82 | - gc9a01 (Community Bundleに含まれています。) 83 | 84 | [ライブラリ配布元](https://circuitpython.org/libraries/) 85 | 86 | ## 使い方の例 87 | ```py 88 | import time 89 | import board 90 | import busio 91 | from CircuitPython_XiaoRoundDisplay import XiaoRoundDisplay 92 | import displayio 93 | 94 | # ボードをソフトリブートした後にはrelease_displaysが必要 95 | displayio.release_displays() 96 | 97 | spi = busio.SPI(board.SCK, board.MOSI, board.MISO) 98 | i2c = busio.I2C(board.SCL, board.SDA) 99 | 100 | # GC9A01とタッチパネルの共通設定 101 | rotation = 0 # 0, 90, 180 or 270 度 102 | 103 | # Round Display for XIAO オブジェクト 104 | xrd = XiaoRoundDisplay(i2c, spi, rotation) 105 | screen = xrd.display() # Screen object 106 | 107 | # displayio設定 108 | bitmap = displayio.Bitmap(screen.width, screen.height, 2) 109 | 110 | # 黒と白のパレットを作成 111 | palette = displayio.Palette(2) 112 | palette[0] = 0x000000 113 | palette[1] = 0xffffff 114 | 115 | # BitmapとPaletteを使ってTileGridを作成 116 | tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette) 117 | # Groupを作成 118 | group = displayio.Group() 119 | # TileGridをGroupに追加 120 | group.append(tile_grid) 121 | # GroupをDisplayに追加 122 | screen.root_group = group 123 | 124 | print("You can touch the screen to draw.") 125 | while True: 126 | if xrd.is_touched(): 127 | t = xrd.touch_read() 128 | if t is not None: 129 | x, y = t 130 | bitmap[x, y] = 1 131 | time.sleep(0.001) 132 | ``` 133 | -------------------------------------------------------------------------------- /examples/AllFunctionTest.py: -------------------------------------------------------------------------------- 1 | import time 2 | import board 3 | import busio 4 | from CircuitPython_XiaoRoundDisplay import XiaoRoundDisplay 5 | import displayio 6 | from adafruit_pcf8563.pcf8563 import PCF8563 7 | import digitalio 8 | import adafruit_sdcard 9 | import storage 10 | import os 11 | 12 | # You need to release_displays after soft-rebooting the board 13 | displayio.release_displays() 14 | 15 | spi = busio.SPI(board.SCK, board.MOSI, board.MISO) 16 | i2c = busio.I2C(board.SCL, board.SDA) 17 | 18 | # PCF8563 Realtime clock settings 19 | rtc = PCF8563(i2c) 20 | days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") 21 | 22 | # GC9A01 display and Touch panel common settings 23 | rotation = 0 # 0, 90, 180 or 270 degree 24 | 25 | # Round Display for XIAO object 26 | xrd = XiaoRoundDisplay(i2c, spi, rotation) 27 | screen = xrd.display() # Screen object 28 | 29 | # displayio settings 30 | bitmap = displayio.Bitmap(screen.width, screen.height, 2) 31 | 32 | # Create a two color palette 33 | palette = displayio.Palette(2) 34 | palette[0] = 0x000000 35 | palette[1] = 0xffffff 36 | 37 | # Create a TileGrid using the Bitmap and Palette 38 | tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette) 39 | # Create a Group 40 | group = displayio.Group() 41 | # Add the TileGrid to the Group 42 | group.append(tile_grid) 43 | # Add the Group to the Display 44 | screen.root_group = group 45 | 46 | # RTC 47 | # Set datetime 48 | t = time.struct_time((2024, 4, 30, 22, 13, 0, 1, -1, -1)) 49 | rtc.datetime = t 50 | # Get date and time 51 | print( 52 | "The date is {} {}/{}/{}".format( 53 | days[int(t.tm_wday)], t.tm_mday, t.tm_mon, t.tm_year 54 | ) 55 | ) 56 | print("The time is {}:{:02}:{:02}".format(t.tm_hour, t.tm_min, t.tm_sec)) 57 | 58 | # SD Card 59 | # IMPORTRANT: You should create the SD card object AFTER initializing Display 60 | try: 61 | cs = digitalio.DigitalInOut(board.D2) # SD_CS = board.D2 62 | sdcard = adafruit_sdcard.SDCard(spi, cs) 63 | vfs = storage.VfsFat(sdcard) 64 | storage.mount(vfs, '/sd') 65 | print(os.listdir('/sd')) 66 | except: 67 | print("No SD card found.") 68 | pass 69 | 70 | print("You can touch the screen to draw.") 71 | while True: 72 | if xrd.is_touched(): 73 | t = xrd.touch_read() 74 | if t is not None: 75 | x, y = t 76 | bitmap[x, y] = 1 77 | time.sleep(0.001) 78 | --------------------------------------------------------------------------------