├── .gitignore ├── LICENSE ├── Python_ILI9486 ├── ILI9486.py └── __init__.py ├── README.md ├── examples ├── ca.ttf ├── happyNewY.py ├── image.py ├── image_gif.py ├── image_timed.py ├── mini.ttf ├── miniN.ttf ├── shapes.py ├── vacatronics_320x480.png └── vacatronics_rotate.gif ├── ez_setup.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.egg-info/ 3 | build/ 4 | dist/ 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adafruit Industries 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 | -------------------------------------------------------------------------------- /Python_ILI9486/ILI9486.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 myway work 2 | # Author: Liqun Hu 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import numbers 22 | import time 23 | import numpy as np 24 | 25 | from PIL import Image, ImageDraw 26 | 27 | import Adafruit_GPIO as GPIO 28 | import Adafruit_GPIO.SPI as SPI 29 | 30 | 31 | # Constants for interacting with display registers. 32 | ILI9486_TFTWIDTH = 320 33 | ILI9486_TFTHEIGHT = 480 34 | 35 | ILI9486_NOP = 0x00 36 | ILI9486_SWRESET = 0x01 37 | ILI9486_RDDID = 0x04 38 | ILI9486_RDDST = 0x09 39 | 40 | ILI9486_SLPIN = 0x10 41 | ILI9486_SLPOUT = 0x11 42 | ILI9486_PTLON = 0x12 43 | ILI9486_NORON = 0x13 44 | 45 | ILI9486_RDMODE = 0x0A 46 | ILI9486_RDMADCTL = 0x0B 47 | ILI9486_RDPIXFMT = 0x0C 48 | ILI9486_RDIMGFMT = 0x0A 49 | ILI9486_RDSELFDIAG = 0x0F 50 | 51 | ILI9486_INVOFF = 0x20 52 | ILI9486_INVON = 0x21 53 | ILI9486_GAMMASET = 0x26 54 | ILI9486_DISPOFF = 0x28 55 | ILI9486_DISPON = 0x29 56 | 57 | ILI9486_CASET = 0x2A 58 | ILI9486_PASET = 0x2B 59 | ILI9486_RAMWR = 0x2C 60 | ILI9486_RAMRD = 0x2E 61 | 62 | ILI9486_PTLAR = 0x30 63 | ILI9486_MADCTL = 0x36 64 | ILI9486_PIXFMT = 0x3A 65 | 66 | ILI9486_FRMCTR1 = 0xB1 67 | ILI9486_FRMCTR2 = 0xB2 68 | ILI9486_FRMCTR3 = 0xB3 69 | ILI9486_INVCTR = 0xB4 70 | ILI9486_DFUNCTR = 0xB6 71 | 72 | ILI9486_PWCTR1 = 0xC0 73 | ILI9486_PWCTR2 = 0xC1 74 | ILI9486_PWCTR3 = 0xC2 75 | ILI9486_PWCTR4 = 0xC3 76 | ILI9486_PWCTR5 = 0xC4 77 | ILI9486_VMCTR1 = 0xC5 78 | ILI9486_VMCTR2 = 0xC7 79 | 80 | ILI9486_RDID1 = 0xDA 81 | ILI9486_RDID2 = 0xDB 82 | ILI9486_RDID3 = 0xDC 83 | ILI9486_RDID4 = 0xDD 84 | 85 | ILI9486_GMCTRP1 = 0xE0 86 | ILI9486_GMCTRN1 = 0xE1 87 | 88 | ILI9486_PWCTR6 = 0xFC 89 | 90 | ILI9486_BLACK = 0x0000 91 | ILI9486_BLUE = 0x001F 92 | ILI9486_RED = 0xF800 93 | ILI9486_GREEN = 0x07E0 94 | ILI9486_CYAN = 0x07FF 95 | ILI9486_MAGENTA = 0xF81F 96 | ILI9486_YELLOW = 0xFFE0 97 | ILI9486_WHITE = 0xFFFF 98 | 99 | 100 | def color565(r, g, b): 101 | """Convert red, green, blue components to a 16-bit 565 RGB value. Components 102 | should be values 0 to 255. 103 | """ 104 | return ((r & 0xF0) << 8) | ((g & 0xFC) << 3) | (b >> 3) 105 | 106 | def image_to_data(image): 107 | """Generator function to convert a PIL image to 16-bit 565 RGB bytes.""" 108 | #NumPy is much faster at doing this. NumPy code provided by: 109 | #Keith (https://www.blogger.com/profile/02555547344016007163) 110 | pb = np.array(image.convert('RGB')).astype('uint16') 111 | # color = ((pb[:,:,0] & 0xF8) << 8) | ((pb[:,:,1] & 0xFC) << 3) | (pb[:,:,2] >> 3) 112 | # return np.dstack(((color >> 8) & 0xFF, color & 0xFF)).flatten().tolist() 113 | return np.dstack((pb[:,:,0] & 0xFC, pb[:,:,1] & 0xFC, pb[:,:,2] & 0xFC)).flatten().tolist() 114 | # pixels = image.convert('RGB').load() 115 | # width, height = image.size 116 | # for y in range(height): 117 | # for x in range(width): 118 | # r,g,b = pixels[(x,y)] 119 | ## color = color565(r, g, b) 120 | # #yield (color >> 8) & 0xFF 121 | # #yield color & 0xFF 122 | # yield r 123 | # yield g 124 | # yield b 125 | 126 | 127 | class ILI9486(object): 128 | """Representation of an ILI9486 TFT LCD.""" 129 | 130 | def __init__(self, dc, spi, rst=None, gpio=None, width=ILI9486_TFTWIDTH, 131 | height=ILI9486_TFTHEIGHT): 132 | """Create an instance of the display using SPI communication. Must 133 | provide the GPIO pin number for the D/C pin and the SPI driver. Can 134 | optionally provide the GPIO pin number for the reset pin as the rst 135 | parameter. 136 | """ 137 | self._dc = dc 138 | self._rst = rst 139 | self._spi = spi 140 | self._gpio = gpio 141 | self.width = width 142 | self.height = height 143 | if self._gpio is None: 144 | self._gpio = GPIO.get_platform_gpio() 145 | # Set DC as output. 146 | self._gpio.setup(dc, GPIO.OUT) 147 | # Setup reset as output (if provided). 148 | if rst is not None: 149 | self._gpio.setup(rst, GPIO.OUT) 150 | # Set SPI to mode 0, MSB first. 151 | spi.set_mode(2) 152 | spi.set_bit_order(SPI.MSBFIRST) 153 | spi.set_clock_hz(64000000) 154 | # Create an image buffer. 155 | self.buffer = Image.new('RGB', (width, height)) 156 | 157 | def send(self, data, is_data=True, chunk_size=4096): 158 | """Write a byte or array of bytes to the display. Is_data parameter 159 | controls if byte should be interpreted as display data (True) or command 160 | data (False). Chunk_size is an optional size of bytes to write in a 161 | single SPI transaction, with a default of 4096. 162 | """ 163 | # Set DC low for command, high for data. 164 | self._gpio.output(self._dc, is_data) 165 | # Convert scalar argument to list so either can be passed as parameter. 166 | if isinstance(data, numbers.Number): 167 | data = [data & 0xFF] 168 | # Write data a chunk at a time. 169 | for start in range(0, len(data), chunk_size): 170 | end = min(start+chunk_size, len(data)) 171 | self._spi.write(data[start:end]) 172 | 173 | def command(self, data): 174 | """Write a byte or array of bytes to the display as command data.""" 175 | self.send(data, False) 176 | 177 | def data(self, data): 178 | """Write a byte or array of bytes to the display as display data.""" 179 | self.send(data, True) 180 | 181 | def reset(self): 182 | """Reset the display, if reset pin is connected.""" 183 | if self._rst is not None: 184 | self._gpio.set_high(self._rst) 185 | time.sleep(0.005) 186 | self._gpio.set_low(self._rst) 187 | time.sleep(0.02) 188 | self._gpio.set_high(self._rst) 189 | time.sleep(0.150) 190 | 191 | def _init(self): 192 | # Initialize the display. Broken out as a separate function so it can 193 | # be overridden by other displays in the future. 194 | self.command(0xB0) 195 | self.data(0x00) 196 | self.command(0x11) 197 | time.sleep(0.020) 198 | 199 | self.command(0x3A) 200 | self.data(0x66) 201 | 202 | self.command(0x0C) 203 | self.data(0x66) 204 | 205 | #self.command(0xB6) 206 | #self.data(0x00) 207 | #self.data(0x42) 208 | #self.data(0x3B) 209 | 210 | self.command(0xC2) 211 | self.data(0x44) 212 | 213 | self.command(0xC5) 214 | self.data(0x00) 215 | self.data(0x00) 216 | self.data(0x00) 217 | self.data(0x00) 218 | 219 | self.command(0xE0) 220 | self.data(0x0F) 221 | self.data(0x1F) 222 | self.data(0x1C) 223 | self.data(0x0C) 224 | self.data(0x0F) 225 | self.data(0x08) 226 | self.data(0x48) 227 | self.data(0x98) 228 | self.data(0x37) 229 | self.data(0x0A) 230 | self.data(0x13) 231 | self.data(0x04) 232 | self.data(0x11) 233 | self.data(0x0D) 234 | self.data(0x00) 235 | 236 | self.command(0xE1) 237 | self.data(0x0F) 238 | self.data(0x32) 239 | self.data(0x2E) 240 | self.data(0x0B) 241 | self.data(0x0D) 242 | self.data(0x05) 243 | self.data(0x47) 244 | self.data(0x75) 245 | self.data(0x37) 246 | self.data(0x06) 247 | self.data(0x10) 248 | self.data(0x03) 249 | self.data(0x24) 250 | self.data(0x20) 251 | self.data(0x00) 252 | 253 | self.command(0xE2) 254 | self.data(0x0F) 255 | self.data(0x32) 256 | self.data(0x2E) 257 | self.data(0x0B) 258 | self.data(0x0D) 259 | self.data(0x05) 260 | self.data(0x47) 261 | self.data(0x75) 262 | self.data(0x37) 263 | self.data(0x06) 264 | self.data(0x10) 265 | self.data(0x03) 266 | self.data(0x24) 267 | self.data(0x20) 268 | self.data(0x00) 269 | 270 | self.command(0x36) 271 | self.data(0x88) #change the direct 272 | 273 | self.command(0x11) 274 | self.command(0x29) 275 | 276 | def begin(self): 277 | """Initialize the display. Should be called once before other calls that 278 | interact with the display are called. 279 | """ 280 | self.reset() 281 | self._init() 282 | 283 | def set_window(self, x0=0, y0=0, x1=None, y1=None): 284 | """Set the pixel address window for proceeding drawing commands. x0 and 285 | x1 should define the minimum and maximum x pixel bounds. y0 and y1 286 | should define the minimum and maximum y pixel bound. If no parameters 287 | are specified the default will be to update the entire display from 0,0 288 | to 239,319. 289 | """ 290 | if x1 is None: 291 | x1 = self.width-1 292 | if y1 is None: 293 | y1 = self.height-1 294 | self.command(0x2A) # Column addr set 295 | self.data(x0 >> 8) 296 | self.data(x0 & 0xFF) # XSTART 297 | self.data(x1 >> 8) 298 | self.data(x1 & 0xFF) # XEND 299 | self.command(0x2B) # Row addr set 300 | self.data(y0 >> 8) 301 | self.data(y0 & 0xFF) # YSTART 302 | self.data(y1 >> 8) 303 | self.data(y1 & 0xFF) # YEND 304 | self.command(0x2C) # write to RAM 305 | 306 | def display(self, image=None): 307 | """Write the display buffer or provided image to the hardware. If no 308 | image parameter is provided the display buffer will be written to the 309 | hardware. If an image is provided, it should be RGB format and the 310 | same dimensions as the display hardware. 311 | """ 312 | # By default write the internal buffer to the display. 313 | if image is None: 314 | image = self.buffer 315 | # Set address bounds to entire display. 316 | self.set_window() 317 | # Convert image to array of 16bit 565 RGB data bytes. 318 | # Unfortunate that this copy has to occur, but the SPI byte writing 319 | # function needs to take an array of bytes and PIL doesn't natively 320 | # store images in 16-bit 565 RGB format. 321 | pixelbytes = list(image_to_data(image)) 322 | # Write data to hardware. 323 | self.data(pixelbytes) 324 | 325 | def clear(self, color=(0,0,0)): 326 | """Clear the image buffer to the specified RGB color (default black).""" 327 | width, height = self.buffer.size 328 | self.buffer.putdata([color]*(width*height)) 329 | 330 | def draw(self): 331 | """Return a PIL ImageDraw instance for 2D drawing on the image buffer.""" 332 | return ImageDraw.Draw(self.buffer) 333 | -------------------------------------------------------------------------------- /Python_ILI9486/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | from .ILI9486 import * 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Python ILI9486 2 | ======================= 3 | 4 | Python library to control an ILI9486 TFT LCD display. Allows simple drawing on the display without installing a kernel module. 5 | 6 | Designed specifically to work with the 3.5" LCD's 7 | 8 | For all platforms (Raspberry Pi) make sure you have the following dependencies: 9 | 10 | ```` 11 | sudo apt update 12 | sudo apt upgrade -y 13 | sudo apt install build-essential python3-dev python3-smbus python3-venv 14 | sudo apt install libfreetype6-dev libjpeg-dev 15 | ```` 16 | 17 | ## Installation and use 18 | 19 | Create a virtualenv: 20 | 21 | ```` 22 | mkdir -p lcd 23 | cd lcd 24 | python3 -m venv .venv 25 | source .venv/bin/activate 26 | ```` 27 | 28 | Install dependencies: 29 | 30 | ```` 31 | pip install wheel 32 | pip install adafruit-gpio 33 | pip install pillow 34 | pip install numpy 35 | pip install rpi.gpio 36 | ```` 37 | 38 | Install the library by downloading with the download link on the right, unzipping the archive, navigating inside the library's directory and executing: 39 | 40 | ```` 41 | sudo python setup.py install 42 | ```` 43 | 44 | See example of usage in the examples folder. 45 | 46 | ### Observation 47 | 48 | SPI access must be done by a root user. So, if a Permission Error occurs, run the script as sudo: 49 | 50 | ```` 51 | sudo .venv/bin/python image.py 52 | ```` 53 | 54 | 55 | ## Notes 56 | 57 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 58 | 59 | Written by Tony DiCola for Adafruit Industries. 60 | 61 | MIT license, all text above must be included in any redistribution 62 | -------------------------------------------------------------------------------- /examples/ca.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustropo/Python_ILI9486/a311f1df32bf458806ae8f8b35e65c573c15eabc/examples/ca.ttf -------------------------------------------------------------------------------- /examples/happyNewY.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # Copyright (c) 2016 Myway Freework 3 | # Author: Myway 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 13 | # all 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 21 | # THE SOFTWARE. 22 | from PIL import Image, ImageDraw, ImageFont 23 | 24 | import Python_ILI9486 as TFT 25 | import Adafruit_GPIO as GPIO 26 | import Adafruit_GPIO.SPI as SPI 27 | 28 | 29 | # Raspberry Pi configuration. 30 | DC = 24 31 | RST = 25 32 | SPI_PORT = 0 33 | SPI_DEVICE = 0 34 | 35 | # Create TFT LCD display class. 36 | disp = TFT.ILI9486(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000)) 37 | 38 | # Initialize display. 39 | disp.begin() 40 | 41 | # Clear the display to a red background. 42 | # Can pass any tuple of red, green, blue values (from 0 to 255 each). 43 | disp.clear((255, 0, 0)) 44 | 45 | # Alternatively can clear to a black screen by calling: 46 | # disp.clear() 47 | 48 | # Get a PIL Draw object to start drawing on the display buffer. 49 | draw = disp.draw() 50 | 51 | # Draw some shapes. 52 | # Draw a blue ellipse with a green outline. 53 | #draw.ellipse((10, 10, 250, 110), outline=(0,255,0), fill=(0,0,255)) 54 | 55 | # Draw a purple rectangle with yellow outline. 56 | #draw.rectangle((10, 120, 250, 220), outline=(255,255,0), fill=(255,0,255)) 57 | 58 | # Draw a white X. 59 | #draw.line((10, 230, 250, 330), fill=(255,255,255)) 60 | #draw.line((10, 330, 250, 230), fill=(255,255,255)) 61 | 62 | # Draw a cyan triangle with a black outline. 63 | #draw.polygon([(10, 405), (250, 340), (250, 470)], outline=(0,0,0), fill=(0,255,255)) 64 | 65 | # Load default font. 66 | #font = ImageFont.load_default() 67 | 68 | # Alternatively load a TTF font. 69 | # Some other nice fonts to try: http://www.dafont.com/bitmap.php 70 | font = ImageFont.truetype('mini.ttf', 100) 71 | fontEn = ImageFont.truetype('ca.ttf', 40) 72 | fontN = ImageFont.truetype('miniN.ttf', 40) 73 | 74 | # Define a function to create rotated text. Unfortunately PIL doesn't have good 75 | # native support for rotated fonts, but this function can be used to make a 76 | # text image and rotate it so it's easy to paste in the buffer. 77 | def draw_rotated_text(image, text, position, angle, font, fill=(255,255,255)): 78 | # Get rendered font width and height. 79 | draw = ImageDraw.Draw(image) 80 | width, height = draw.textsize(text, font=font) 81 | # Create a new image with transparent background to store the text. 82 | textimage = Image.new('RGBA', (width, height), (0,0,0,0)) 83 | # Render the text. 84 | textdraw = ImageDraw.Draw(textimage) 85 | textdraw.text((0,0), text, font=font, fill=fill) 86 | # Rotate the text image. 87 | rotated = textimage.rotate(angle, expand=1) 88 | # Paste the text into the image, using it as a mask for transparency. 89 | image.paste(rotated, position, rotated) 90 | 91 | # Write two lines of white text on the buffer, rotated 90 degrees counter clockwise. 92 | draw_rotated_text(disp.buffer, 'Happy New Year!', (160, 40), 90, fontEn, fill=(255,255,255)) 93 | draw_rotated_text(disp.buffer, u'--by Ustropo', (200, 40), 90, fontN, fill=(255,255,255)) 94 | draw_rotated_text(disp.buffer, u'2020-05-08', (230, 40), 90, fontN, fill=(255,255,255)) 95 | 96 | # Write buffer to display hardware, must be called to make things visible on the 97 | # display! 98 | disp.display() 99 | -------------------------------------------------------------------------------- /examples/image.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Myway Freework 2 | # Author: Myway 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | from PIL import Image 22 | 23 | import Python_ILI9486 as TFT 24 | import Adafruit_GPIO as GPIO 25 | import Adafruit_GPIO.SPI as SPI 26 | 27 | 28 | # Raspberry Pi configuration. 29 | DC = 24 30 | RST = 25 31 | SPI_PORT = 0 32 | SPI_DEVICE = 0 33 | 34 | # Create TFT LCD display class. 35 | disp = TFT.ILI9486(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000)) 36 | 37 | # Initialize display. 38 | disp.begin() 39 | 40 | # Load an image. 41 | print('Loading image...') 42 | image = Image.open('vacatronics_320x480.png') 43 | 44 | # Resize the image and rotate it so it's 240x320 pixels. 45 | # image = image.rotate(90).resize((320, 480)) 46 | 47 | # Draw the image on the display hardware. 48 | print('Drawing image') 49 | disp.display(image) 50 | -------------------------------------------------------------------------------- /examples/image_gif.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 2 | # Author: Fernando C. Souza 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | from PIL import Image, ImageSequence 22 | 23 | import Python_ILI9486 as TFT 24 | import Adafruit_GPIO as GPIO 25 | import Adafruit_GPIO.SPI as SPI 26 | 27 | 28 | # Raspberry Pi configuration. 29 | DC = 24 30 | RST = 25 31 | SPI_PORT = 0 32 | SPI_DEVICE = 0 33 | 34 | # Create TFT LCD display class. 35 | disp = TFT.ILI9486(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000)) 36 | 37 | # Initialize display. 38 | disp.begin() 39 | 40 | # Import gif 41 | image = Image.open('vacatronics_rotate.gif') 42 | 43 | # Iterate over frames 44 | print('Press Ctrl+C to end...') 45 | try: 46 | while True: 47 | for frame in ImageSequence.Iterator(image): 48 | disp.display(frame) 49 | except KeyboardInterrupt: 50 | pass 51 | print('Bye') 52 | -------------------------------------------------------------------------------- /examples/image_timed.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Myway Freework 2 | # Author: Myway 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | from PIL import Image 22 | import time 23 | import Python_ILI9486 as TFT 24 | import Adafruit_GPIO as GPIO 25 | import Adafruit_GPIO.SPI as SPI 26 | 27 | 28 | # Raspberry Pi configuration. 29 | DC = 24 30 | RST = 25 31 | SPI_PORT = 0 32 | SPI_DEVICE = 0 33 | 34 | # BeagleBone Black configuration. 35 | #DC = 'P9_15' 36 | #RST = 'P9_12' 37 | #SPI_PORT = 1 38 | #SPI_DEVICE = 0 39 | 40 | # Create TFT LCD display class. 41 | disp = TFT.ILI9486(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000)) 42 | 43 | # Initialize display. 44 | disp.begin() 45 | 46 | # Load an image. 47 | print('Loading image...') 48 | image = Image.open('vacatronics_320x480.png') 49 | 50 | # Resize the image and rotate it so it's 240x320 pixels. 51 | # image = image.rotate(90).resize((320, 480)) 52 | 53 | print('Press Ctrl-C to exit') 54 | while(True): 55 | # Draw the image on the display hardware. 56 | print('Drawing image') 57 | start_time = time.time() 58 | disp.display(image) 59 | end_time = time.time() 60 | print('Time to draw image: ' + str(end_time - start_time)) 61 | disp.clear((0, 0, 0)) 62 | disp.display() 63 | -------------------------------------------------------------------------------- /examples/mini.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustropo/Python_ILI9486/a311f1df32bf458806ae8f8b35e65c573c15eabc/examples/mini.ttf -------------------------------------------------------------------------------- /examples/miniN.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustropo/Python_ILI9486/a311f1df32bf458806ae8f8b35e65c573c15eabc/examples/miniN.ttf -------------------------------------------------------------------------------- /examples/shapes.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | from PIL import Image, ImageDraw, ImageFont 22 | 23 | import Python_ILI9486 as TFT 24 | import Adafruit_GPIO as GPIO 25 | import Adafruit_GPIO.SPI as SPI 26 | 27 | 28 | # Raspberry Pi configuration. 29 | DC = 24 30 | RST = 25 31 | SPI_PORT = 0 32 | SPI_DEVICE = 0 33 | 34 | # Create TFT LCD display class. 35 | disp = TFT.ILI9486(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000)) 36 | 37 | # Initialize display. 38 | disp.begin() 39 | 40 | # Clear the display to a red background. 41 | # Can pass any tuple of red, green, blue values (from 0 to 255 each). 42 | disp.clear((255, 0, 0)) 43 | 44 | # Alternatively can clear to a black screen by calling: 45 | # disp.clear() 46 | 47 | # Get a PIL Draw object to start drawing on the display buffer. 48 | draw = disp.draw() 49 | 50 | # Draw some shapes. 51 | # Draw a blue ellipse with a green outline. 52 | draw.ellipse((10, 10, 250, 110), outline=(0,255,0), fill=(0,0,255)) 53 | 54 | # Draw a purple rectangle with yellow outline. 55 | draw.rectangle((10, 120, 250, 220), outline=(255,255,0), fill=(255,0,255)) 56 | 57 | # Draw a white X. 58 | draw.line((10, 230, 250, 330), fill=(255,255,255)) 59 | draw.line((10, 330, 250, 230), fill=(255,255,255)) 60 | 61 | # Draw a cyan triangle with a black outline. 62 | draw.polygon([(10, 405), (250, 340), (250, 470)], outline=(0,0,0), fill=(0,255,255)) 63 | 64 | # Load default font. 65 | font = ImageFont.load_default() 66 | 67 | # Alternatively load a TTF font. 68 | # Some other nice fonts to try: http://www.dafont.com/bitmap.php 69 | #font = ImageFont.truetype('Minecraftia.ttf', 16) 70 | 71 | # Define a function to create rotated text. Unfortunately PIL doesn't have good 72 | # native support for rotated fonts, but this function can be used to make a 73 | # text image and rotate it so it's easy to paste in the buffer. 74 | def draw_rotated_text(image, text, position, angle, font, fill=(255,255,255)): 75 | # Get rendered font width and height. 76 | draw = ImageDraw.Draw(image) 77 | width, height = draw.textsize(text, font=font) 78 | # Create a new image with transparent background to store the text. 79 | textimage = Image.new('RGBA', (width, height), (0,0,0,0)) 80 | # Render the text. 81 | textdraw = ImageDraw.Draw(textimage) 82 | textdraw.text((0,0), text, font=font, fill=fill) 83 | # Rotate the text image. 84 | rotated = textimage.rotate(angle, expand=1) 85 | # Paste the text into the image, using it as a mask for transparency. 86 | image.paste(rotated, position, rotated) 87 | 88 | # Write two lines of white text on the buffer, rotated 90 degrees counter clockwise. 89 | draw_rotated_text(disp.buffer, 'Hello World!', (280, 200), 90, font, fill=(255,255,255)) 90 | draw_rotated_text(disp.buffer, 'This is a line of text.', (300, 160), 90, font, fill=(255,255,255)) 91 | 92 | # Write buffer to display hardware, must be called to make things visible on the 93 | # display! 94 | disp.display() 95 | -------------------------------------------------------------------------------- /examples/vacatronics_320x480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustropo/Python_ILI9486/a311f1df32bf458806ae8f8b35e65c573c15eabc/examples/vacatronics_320x480.png -------------------------------------------------------------------------------- /examples/vacatronics_rotate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustropo/Python_ILI9486/a311f1df32bf458806ae8f8b35e65c573c15eabc/examples/vacatronics_rotate.gif -------------------------------------------------------------------------------- /ez_setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Bootstrap setuptools installation 3 | 4 | To use setuptools in your package's setup.py, include this 5 | file in the same directory and add this to the top of your setup.py:: 6 | 7 | from ez_setup import use_setuptools 8 | use_setuptools() 9 | 10 | To require a specific version of setuptools, set a download 11 | mirror, or use an alternate download directory, simply supply 12 | the appropriate options to ``use_setuptools()``. 13 | 14 | This file can also be run as a script to install or upgrade setuptools. 15 | """ 16 | import os 17 | import shutil 18 | import sys 19 | import tempfile 20 | import zipfile 21 | import optparse 22 | import subprocess 23 | import platform 24 | import textwrap 25 | import contextlib 26 | 27 | from distutils import log 28 | 29 | try: 30 | from site import USER_SITE 31 | except ImportError: 32 | USER_SITE = None 33 | 34 | DEFAULT_VERSION = "3.5.1" 35 | DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" 36 | 37 | def _python_cmd(*args): 38 | """ 39 | Return True if the command succeeded. 40 | """ 41 | args = (sys.executable,) + args 42 | return subprocess.call(args) == 0 43 | 44 | 45 | def _install(archive_filename, install_args=()): 46 | with archive_context(archive_filename): 47 | # installing 48 | log.warn('Installing Setuptools') 49 | if not _python_cmd('setup.py', 'install', *install_args): 50 | log.warn('Something went wrong during the installation.') 51 | log.warn('See the error message above.') 52 | # exitcode will be 2 53 | return 2 54 | 55 | 56 | def _build_egg(egg, archive_filename, to_dir): 57 | with archive_context(archive_filename): 58 | # building an egg 59 | log.warn('Building a Setuptools egg in %s', to_dir) 60 | _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) 61 | # returning the result 62 | log.warn(egg) 63 | if not os.path.exists(egg): 64 | raise IOError('Could not build the egg.') 65 | 66 | 67 | def get_zip_class(): 68 | """ 69 | Supplement ZipFile class to support context manager for Python 2.6 70 | """ 71 | class ContextualZipFile(zipfile.ZipFile): 72 | def __enter__(self): 73 | return self 74 | def __exit__(self, type, value, traceback): 75 | self.close 76 | return zipfile.ZipFile if hasattr(zipfile.ZipFile, '__exit__') else \ 77 | ContextualZipFile 78 | 79 | 80 | @contextlib.contextmanager 81 | def archive_context(filename): 82 | # extracting the archive 83 | tmpdir = tempfile.mkdtemp() 84 | log.warn('Extracting in %s', tmpdir) 85 | old_wd = os.getcwd() 86 | try: 87 | os.chdir(tmpdir) 88 | with get_zip_class()(filename) as archive: 89 | archive.extractall() 90 | 91 | # going in the directory 92 | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) 93 | os.chdir(subdir) 94 | log.warn('Now working in %s', subdir) 95 | yield 96 | 97 | finally: 98 | os.chdir(old_wd) 99 | shutil.rmtree(tmpdir) 100 | 101 | 102 | def _do_download(version, download_base, to_dir, download_delay): 103 | egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' 104 | % (version, sys.version_info[0], sys.version_info[1])) 105 | if not os.path.exists(egg): 106 | archive = download_setuptools(version, download_base, 107 | to_dir, download_delay) 108 | _build_egg(egg, archive, to_dir) 109 | sys.path.insert(0, egg) 110 | 111 | # Remove previously-imported pkg_resources if present (see 112 | # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). 113 | if 'pkg_resources' in sys.modules: 114 | del sys.modules['pkg_resources'] 115 | 116 | import setuptools 117 | setuptools.bootstrap_install_from = egg 118 | 119 | 120 | def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, 121 | to_dir=os.curdir, download_delay=15): 122 | to_dir = os.path.abspath(to_dir) 123 | rep_modules = 'pkg_resources', 'setuptools' 124 | imported = set(sys.modules).intersection(rep_modules) 125 | try: 126 | import pkg_resources 127 | except ImportError: 128 | return _do_download(version, download_base, to_dir, download_delay) 129 | try: 130 | pkg_resources.require("setuptools>=" + version) 131 | return 132 | except pkg_resources.DistributionNotFound: 133 | return _do_download(version, download_base, to_dir, download_delay) 134 | except pkg_resources.VersionConflict as VC_err: 135 | if imported: 136 | msg = textwrap.dedent(""" 137 | The required version of setuptools (>={version}) is not available, 138 | and can't be installed while this script is running. Please 139 | install a more recent version first, using 140 | 'easy_install -U setuptools'. 141 | 142 | (Currently using {VC_err.args[0]!r}) 143 | """).format(VC_err=VC_err, version=version) 144 | sys.stderr.write(msg) 145 | sys.exit(2) 146 | 147 | # otherwise, reload ok 148 | del pkg_resources, sys.modules['pkg_resources'] 149 | return _do_download(version, download_base, to_dir, download_delay) 150 | 151 | def _clean_check(cmd, target): 152 | """ 153 | Run the command to download target. If the command fails, clean up before 154 | re-raising the error. 155 | """ 156 | try: 157 | subprocess.check_call(cmd) 158 | except subprocess.CalledProcessError: 159 | if os.access(target, os.F_OK): 160 | os.unlink(target) 161 | raise 162 | 163 | def download_file_powershell(url, target): 164 | """ 165 | Download the file at url to target using Powershell (which will validate 166 | trust). Raise an exception if the command cannot complete. 167 | """ 168 | target = os.path.abspath(target) 169 | cmd = [ 170 | 'powershell', 171 | '-Command', 172 | "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" % vars(), 173 | ] 174 | _clean_check(cmd, target) 175 | 176 | def has_powershell(): 177 | if platform.system() != 'Windows': 178 | return False 179 | cmd = ['powershell', '-Command', 'echo test'] 180 | devnull = open(os.path.devnull, 'wb') 181 | try: 182 | try: 183 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 184 | except Exception: 185 | return False 186 | finally: 187 | devnull.close() 188 | return True 189 | 190 | download_file_powershell.viable = has_powershell 191 | 192 | def download_file_curl(url, target): 193 | cmd = ['curl', url, '--silent', '--output', target] 194 | _clean_check(cmd, target) 195 | 196 | def has_curl(): 197 | cmd = ['curl', '--version'] 198 | devnull = open(os.path.devnull, 'wb') 199 | try: 200 | try: 201 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 202 | except Exception: 203 | return False 204 | finally: 205 | devnull.close() 206 | return True 207 | 208 | download_file_curl.viable = has_curl 209 | 210 | def download_file_wget(url, target): 211 | cmd = ['wget', url, '--quiet', '--output-document', target] 212 | _clean_check(cmd, target) 213 | 214 | def has_wget(): 215 | cmd = ['wget', '--version'] 216 | devnull = open(os.path.devnull, 'wb') 217 | try: 218 | try: 219 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 220 | except Exception: 221 | return False 222 | finally: 223 | devnull.close() 224 | return True 225 | 226 | download_file_wget.viable = has_wget 227 | 228 | def download_file_insecure(url, target): 229 | """ 230 | Use Python to download the file, even though it cannot authenticate the 231 | connection. 232 | """ 233 | try: 234 | from urllib.request import urlopen 235 | except ImportError: 236 | from urllib2 import urlopen 237 | src = dst = None 238 | try: 239 | src = urlopen(url) 240 | # Read/write all in one block, so we don't create a corrupt file 241 | # if the download is interrupted. 242 | data = src.read() 243 | dst = open(target, "wb") 244 | dst.write(data) 245 | finally: 246 | if src: 247 | src.close() 248 | if dst: 249 | dst.close() 250 | 251 | download_file_insecure.viable = lambda: True 252 | 253 | def get_best_downloader(): 254 | downloaders = [ 255 | download_file_powershell, 256 | download_file_curl, 257 | download_file_wget, 258 | download_file_insecure, 259 | ] 260 | 261 | for dl in downloaders: 262 | if dl.viable(): 263 | return dl 264 | 265 | def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, 266 | to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader): 267 | """ 268 | Download setuptools from a specified location and return its filename 269 | 270 | `version` should be a valid setuptools version number that is available 271 | as an egg for download under the `download_base` URL (which should end 272 | with a '/'). `to_dir` is the directory where the egg will be downloaded. 273 | `delay` is the number of seconds to pause before an actual download 274 | attempt. 275 | 276 | ``downloader_factory`` should be a function taking no arguments and 277 | returning a function for downloading a URL to a target. 278 | """ 279 | # making sure we use the absolute path 280 | to_dir = os.path.abspath(to_dir) 281 | zip_name = "setuptools-%s.zip" % version 282 | url = download_base + zip_name 283 | saveto = os.path.join(to_dir, zip_name) 284 | if not os.path.exists(saveto): # Avoid repeated downloads 285 | log.warn("Downloading %s", url) 286 | downloader = downloader_factory() 287 | downloader(url, saveto) 288 | return os.path.realpath(saveto) 289 | 290 | def _build_install_args(options): 291 | """ 292 | Build the arguments to 'python setup.py install' on the setuptools package 293 | """ 294 | return ['--user'] if options.user_install else [] 295 | 296 | def _parse_args(): 297 | """ 298 | Parse the command line for options 299 | """ 300 | parser = optparse.OptionParser() 301 | parser.add_option( 302 | '--user', dest='user_install', action='store_true', default=False, 303 | help='install in user site package (requires Python 2.6 or later)') 304 | parser.add_option( 305 | '--download-base', dest='download_base', metavar="URL", 306 | default=DEFAULT_URL, 307 | help='alternative URL from where to download the setuptools package') 308 | parser.add_option( 309 | '--insecure', dest='downloader_factory', action='store_const', 310 | const=lambda: download_file_insecure, default=get_best_downloader, 311 | help='Use internal, non-validating downloader' 312 | ) 313 | parser.add_option( 314 | '--version', help="Specify which version to download", 315 | default=DEFAULT_VERSION, 316 | ) 317 | options, args = parser.parse_args() 318 | # positional arguments are ignored 319 | return options 320 | 321 | def main(): 322 | """Install or upgrade setuptools and EasyInstall""" 323 | options = _parse_args() 324 | archive = download_setuptools( 325 | version=options.version, 326 | download_base=options.download_base, 327 | downloader_factory=options.downloader_factory, 328 | ) 329 | return _install(archive, _build_install_args(options)) 330 | 331 | if __name__ == '__main__': 332 | sys.exit(main()) 333 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Workaround for issue in Python 2.7.3 2 | # See http://bugs.python.org/issue15881#msg170215 3 | try: 4 | import multiprocessing 5 | except ImportError: 6 | pass 7 | 8 | from ez_setup import use_setuptools 9 | use_setuptools() 10 | from setuptools import setup, find_packages 11 | 12 | setup(name = 'Python_ILI9486', 13 | version = '1.1.0', 14 | author = 'Liqun Hu', 15 | author_email = 'huliquns@126.com', 16 | description = 'Library to control an ILI9486 TFT LCD display.', 17 | license = 'MIT', 18 | url = 'https://github.com/adafruit/Adafruit_Python_ILI9341/', 19 | dependency_links = ['https://github.com/adafruit/Adafruit_Python_GPIO/tarball/master#egg=Adafruit-GPIO-0.6.5'], 20 | install_requires = ['Adafruit-GPIO>=0.6.5'], 21 | packages = find_packages()) 22 | --------------------------------------------------------------------------------