TISControlProtocol 0.2.4__tar.gz → 0.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/.vscode/c_cpp_properties.json +17 -17
  2. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/.vscode/launch.json +23 -23
  3. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/.vscode/settings.json +58 -58
  4. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/PKG-INFO +2 -2
  5. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/pyproject.toml +3 -3
  6. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/ST7789/__init__.py +383 -383
  7. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/.gitignore +0 -0
  8. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/.vscode/tasks.json +0 -0
  9. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/LICENSE +0 -0
  10. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/README.md +0 -0
  11. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/dev/pump_version.py +0 -0
  12. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/BytesHelper.py +0 -0
  13. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/__init__.py +0 -0
  14. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/AckCoordinator.py +0 -0
  15. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketDispatcher.py +0 -0
  16. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketExtractor.py +0 -0
  17. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/AutoBinaryFeedbackHandler.py +0 -0
  18. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/BinaryFeedbackHandler.py +0 -0
  19. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/ClimateBinaryFeedbackHandler.py +0 -0
  20. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/ClimateControlFeedbackHandler.py +0 -0
  21. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/ControlResponseHandler.py +0 -0
  22. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/DiscoveryFeedbackHandler.py +0 -0
  23. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/LunaTempFeedbackHandler.py +0 -0
  24. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/RealTimeFeedbackHandler.py +0 -0
  25. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/SearchResponseHandler.py +0 -0
  26. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/UpdateResponseHandler.py +0 -0
  27. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketHandlers/__init__.py +0 -0
  28. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketProtocol.py +0 -0
  29. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketReceiver.py +0 -0
  30. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/PacketSender.py +0 -0
  31. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/ProtocolHandler.py +0 -0
  32. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/UpdateCoordinator.py +0 -0
  33. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/Protocols/udp/__init__.py +0 -0
  34. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/__init__.py +0 -0
  35. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/api.py +0 -0
  36. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/crc.py +0 -0
  37. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/dev_api.py +0 -0
  38. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/logo.png +0 -0
  39. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/mock_api.py +0 -0
  40. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/src/TISControlProtocol/shared.py +0 -0
  41. {tiscontrolprotocol-0.2.4 → tiscontrolprotocol-0.2.5}/tests/test.py +0 -0
@@ -1,18 +1,18 @@
1
- {
2
- "configurations": [
3
- {
4
- "name": "windows-gcc-x64",
5
- "includePath": [
6
- "${workspaceFolder}/**"
7
- ],
8
- "compilerPath": "gcc",
9
- "cStandard": "${default}",
10
- "cppStandard": "${default}",
11
- "intelliSenseMode": "windows-gcc-x64",
12
- "compilerArgs": [
13
- ""
14
- ]
15
- }
16
- ],
17
- "version": 4
1
+ {
2
+ "configurations": [
3
+ {
4
+ "name": "windows-gcc-x64",
5
+ "includePath": [
6
+ "${workspaceFolder}/**"
7
+ ],
8
+ "compilerPath": "gcc",
9
+ "cStandard": "${default}",
10
+ "cppStandard": "${default}",
11
+ "intelliSenseMode": "windows-gcc-x64",
12
+ "compilerArgs": [
13
+ ""
14
+ ]
15
+ }
16
+ ],
17
+ "version": 4
18
18
  }
@@ -1,24 +1,24 @@
1
- {
2
- "version": "0.2.0",
3
- "configurations": [
4
- {
5
- "name": "C/C++ Runner: Debug Session",
6
- "type": "cppdbg",
7
- "request": "launch",
8
- "args": [],
9
- "stopAtEntry": false,
10
- "externalConsole": true,
11
- "cwd": "d:/TIS/dev/TISControlProtocol",
12
- "program": "d:/TIS/dev/TISControlProtocol/build/Debug/outDebug",
13
- "MIMode": "gdb",
14
- "miDebuggerPath": "gdb",
15
- "setupCommands": [
16
- {
17
- "description": "Enable pretty-printing for gdb",
18
- "text": "-enable-pretty-printing",
19
- "ignoreFailures": true
20
- }
21
- ]
22
- }
23
- ]
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "C/C++ Runner: Debug Session",
6
+ "type": "cppdbg",
7
+ "request": "launch",
8
+ "args": [],
9
+ "stopAtEntry": false,
10
+ "externalConsole": true,
11
+ "cwd": "d:/TIS/dev/TISControlProtocol",
12
+ "program": "d:/TIS/dev/TISControlProtocol/build/Debug/outDebug",
13
+ "MIMode": "gdb",
14
+ "miDebuggerPath": "gdb",
15
+ "setupCommands": [
16
+ {
17
+ "description": "Enable pretty-printing for gdb",
18
+ "text": "-enable-pretty-printing",
19
+ "ignoreFailures": true
20
+ }
21
+ ]
22
+ }
23
+ ]
24
24
  }
@@ -1,59 +1,59 @@
1
- {
2
- "C_Cpp_Runner.cCompilerPath": "gcc",
3
- "C_Cpp_Runner.cppCompilerPath": "g++",
4
- "C_Cpp_Runner.debuggerPath": "gdb",
5
- "C_Cpp_Runner.cStandard": "",
6
- "C_Cpp_Runner.cppStandard": "",
7
- "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat",
8
- "C_Cpp_Runner.useMsvc": false,
9
- "C_Cpp_Runner.warnings": [
10
- "-Wall",
11
- "-Wextra",
12
- "-Wpedantic",
13
- "-Wshadow",
14
- "-Wformat=2",
15
- "-Wcast-align",
16
- "-Wconversion",
17
- "-Wsign-conversion",
18
- "-Wnull-dereference"
19
- ],
20
- "C_Cpp_Runner.msvcWarnings": [
21
- "/W4",
22
- "/permissive-",
23
- "/w14242",
24
- "/w14287",
25
- "/w14296",
26
- "/w14311",
27
- "/w14826",
28
- "/w44062",
29
- "/w44242",
30
- "/w14905",
31
- "/w14906",
32
- "/w14263",
33
- "/w44265",
34
- "/w14928"
35
- ],
36
- "C_Cpp_Runner.enableWarnings": true,
37
- "C_Cpp_Runner.warningsAsError": false,
38
- "C_Cpp_Runner.compilerArgs": [],
39
- "C_Cpp_Runner.linkerArgs": [],
40
- "C_Cpp_Runner.includePaths": [],
41
- "C_Cpp_Runner.includeSearch": [
42
- "*",
43
- "**/*"
44
- ],
45
- "C_Cpp_Runner.excludeSearch": [
46
- "**/build",
47
- "**/build/**",
48
- "**/.*",
49
- "**/.*/**",
50
- "**/.vscode",
51
- "**/.vscode/**"
52
- ],
53
- "C_Cpp_Runner.useAddressSanitizer": false,
54
- "C_Cpp_Runner.useUndefinedSanitizer": false,
55
- "C_Cpp_Runner.useLeakSanitizer": false,
56
- "C_Cpp_Runner.showCompilationTime": false,
57
- "C_Cpp_Runner.useLinkTimeOptimization": false,
58
- "C_Cpp_Runner.msvcSecureNoWarnings": false
1
+ {
2
+ "C_Cpp_Runner.cCompilerPath": "gcc",
3
+ "C_Cpp_Runner.cppCompilerPath": "g++",
4
+ "C_Cpp_Runner.debuggerPath": "gdb",
5
+ "C_Cpp_Runner.cStandard": "",
6
+ "C_Cpp_Runner.cppStandard": "",
7
+ "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat",
8
+ "C_Cpp_Runner.useMsvc": false,
9
+ "C_Cpp_Runner.warnings": [
10
+ "-Wall",
11
+ "-Wextra",
12
+ "-Wpedantic",
13
+ "-Wshadow",
14
+ "-Wformat=2",
15
+ "-Wcast-align",
16
+ "-Wconversion",
17
+ "-Wsign-conversion",
18
+ "-Wnull-dereference"
19
+ ],
20
+ "C_Cpp_Runner.msvcWarnings": [
21
+ "/W4",
22
+ "/permissive-",
23
+ "/w14242",
24
+ "/w14287",
25
+ "/w14296",
26
+ "/w14311",
27
+ "/w14826",
28
+ "/w44062",
29
+ "/w44242",
30
+ "/w14905",
31
+ "/w14906",
32
+ "/w14263",
33
+ "/w44265",
34
+ "/w14928"
35
+ ],
36
+ "C_Cpp_Runner.enableWarnings": true,
37
+ "C_Cpp_Runner.warningsAsError": false,
38
+ "C_Cpp_Runner.compilerArgs": [],
39
+ "C_Cpp_Runner.linkerArgs": [],
40
+ "C_Cpp_Runner.includePaths": [],
41
+ "C_Cpp_Runner.includeSearch": [
42
+ "*",
43
+ "**/*"
44
+ ],
45
+ "C_Cpp_Runner.excludeSearch": [
46
+ "**/build",
47
+ "**/build/**",
48
+ "**/.*",
49
+ "**/.*/**",
50
+ "**/.vscode",
51
+ "**/.vscode/**"
52
+ ],
53
+ "C_Cpp_Runner.useAddressSanitizer": false,
54
+ "C_Cpp_Runner.useUndefinedSanitizer": false,
55
+ "C_Cpp_Runner.useLeakSanitizer": false,
56
+ "C_Cpp_Runner.showCompilationTime": false,
57
+ "C_Cpp_Runner.useLinkTimeOptimization": false,
58
+ "C_Cpp_Runner.msvcSecureNoWarnings": false
59
59
  }
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: TISControlProtocol
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: A library for TIS Control Protocol
5
5
  Project-URL: Homepage, https://github.com/TISControlHass
6
6
  Project-URL: Issues, https://github.com/TISControlHass/issues
7
- Author-email: Mostafa Ashraf <mustafaashraf744@gmail.com>
7
+ Author-email: Karim Bahgat <eng.karimbahgat@gmail.com>
8
8
  License-File: LICENSE
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: POSIX :: Linux
@@ -4,14 +4,14 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "TISControlProtocol"
7
- version = "0.2.4"
7
+ version = "0.2.5"
8
8
  description = "A library for TIS Control Protocol"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
11
11
  classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: POSIX :: Linux",]
12
12
  [[project.authors]]
13
- name = "Mostafa Ashraf"
14
- email = "mustafaashraf744@gmail.com"
13
+ name = "Karim Bahgat"
14
+ email = "eng.karimbahgat@gmail.com"
15
15
 
16
16
  [project.urls]
17
17
  Homepage = "https://github.com/TISControlHass"
@@ -1,383 +1,383 @@
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
- import numbers
22
- import time
23
- import numpy as np
24
-
25
- import spidev
26
- import RPi.GPIO as GPIO
27
-
28
-
29
- __version__ = "0.0.4"
30
-
31
- BG_SPI_CS_BACK = 0
32
- BG_SPI_CS_FRONT = 1
33
-
34
- SPI_CLOCK_HZ = 16000000
35
-
36
- ST7789_NOP = 0x00
37
- ST7789_SWRESET = 0x01
38
- ST7789_RDDID = 0x04
39
- ST7789_RDDST = 0x09
40
-
41
- ST7789_SLPIN = 0x10
42
- ST7789_SLPOUT = 0x11
43
- ST7789_PTLON = 0x12
44
- ST7789_NORON = 0x13
45
-
46
- ST7789_INVOFF = 0x20
47
- ST7789_INVON = 0x21
48
- ST7789_DISPOFF = 0x28
49
- ST7789_DISPON = 0x29
50
-
51
- ST7789_CASET = 0x2A
52
- ST7789_RASET = 0x2B
53
- ST7789_RAMWR = 0x2C
54
- ST7789_RAMRD = 0x2E
55
-
56
- ST7789_PTLAR = 0x30
57
- ST7789_MADCTL = 0x36
58
- ST7789_COLMOD = 0x3A
59
-
60
- ST7789_FRMCTR1 = 0xB1
61
- ST7789_FRMCTR2 = 0xB2
62
- ST7789_FRMCTR3 = 0xB3
63
- ST7789_INVCTR = 0xB4
64
- ST7789_DISSET5 = 0xB6
65
-
66
- ST7789_GCTRL = 0xB7
67
- ST7789_GTADJ = 0xB8
68
- ST7789_VCOMS = 0xBB
69
-
70
- ST7789_LCMCTRL = 0xC0
71
- ST7789_IDSET = 0xC1
72
- ST7789_VDVVRHEN = 0xC2
73
- ST7789_VRHS = 0xC3
74
- ST7789_VDVS = 0xC4
75
- ST7789_VMCTR1 = 0xC5
76
- ST7789_FRCTRL2 = 0xC6
77
- ST7789_CABCCTRL = 0xC7
78
-
79
- ST7789_RDID1 = 0xDA
80
- ST7789_RDID2 = 0xDB
81
- ST7789_RDID3 = 0xDC
82
- ST7789_RDID4 = 0xDD
83
-
84
- ST7789_GMCTRP1 = 0xE0
85
- ST7789_GMCTRN1 = 0xE1
86
-
87
- ST7789_PWCTR6 = 0xFC
88
-
89
-
90
- class ST7789(object):
91
- """Representation of an ST7789 TFT LCD."""
92
-
93
- def __init__(
94
- self,
95
- port,
96
- cs,
97
- dc,
98
- backlight=None,
99
- rst=None,
100
- width=240,
101
- height=240,
102
- rotation=90,
103
- invert=True,
104
- spi_speed_hz=4000000,
105
- offset_left=0,
106
- offset_top=0,
107
- ):
108
- """Create an instance of the display using SPI communication.
109
-
110
- Must provide the GPIO pin number for the D/C pin and the SPI driver.
111
-
112
- Can optionally provide the GPIO pin number for the reset pin as the rst parameter.
113
-
114
- :param port: SPI port number
115
- :param cs: SPI chip-select number (0 or 1 for BCM
116
- :param backlight: Pin for controlling backlight
117
- :param rst: Reset pin for ST7789
118
- :param width: Width of display connected to ST7789
119
- :param height: Height of display connected to ST7789
120
- :param rotation: Rotation of display connected to ST7789
121
- :param invert: Invert display
122
- :param spi_speed_hz: SPI speed (in Hz)
123
-
124
- """
125
- if rotation not in [0, 90, 180, 270]:
126
- raise ValueError("Invalid rotation {}".format(rotation))
127
-
128
- if width != height and rotation in [90, 270]:
129
- raise ValueError(
130
- "Invalid rotation {} for {}x{} resolution".format(
131
- rotation, width, height
132
- )
133
- )
134
-
135
- GPIO.setwarnings(False)
136
- GPIO.setmode(GPIO.BCM)
137
-
138
- self._spi = spidev.SpiDev(port, cs)
139
- self._spi.mode = 0
140
- self._spi.lsbfirst = False
141
- self._spi.max_speed_hz = spi_speed_hz
142
-
143
- self._dc = dc
144
- self._rst = rst
145
- self._width = width
146
- self._height = height
147
- self._rotation = rotation
148
- self._invert = invert
149
-
150
- self._offset_left = offset_left
151
- self._offset_top = offset_top
152
-
153
- # Set DC as output.
154
- GPIO.setup(dc, GPIO.OUT)
155
-
156
- # Setup backlight as output (if provided).
157
- self._backlight = backlight
158
- if backlight is not None:
159
- GPIO.setup(backlight, GPIO.OUT)
160
- GPIO.output(backlight, GPIO.LOW)
161
- time.sleep(0.1)
162
- GPIO.output(backlight, GPIO.HIGH)
163
-
164
- # Setup reset as output (if provided).
165
- if rst is not None:
166
- GPIO.setup(self._rst, GPIO.OUT)
167
- self.reset()
168
- self._init()
169
-
170
- def send(self, data, is_data=True, chunk_size=4096):
171
- """Write a byte or array of bytes to the display. Is_data parameter
172
- controls if byte should be interpreted as display data (True) or command
173
- data (False). Chunk_size is an optional size of bytes to write in a
174
- single SPI transaction, with a default of 4096.
175
- """
176
- # Set DC low for command, high for data.
177
- GPIO.output(self._dc, is_data)
178
- # Convert scalar argument to list so either can be passed as parameter.
179
- if isinstance(data, numbers.Number):
180
- data = [data & 0xFF]
181
- # Write data a chunk at a time.
182
- for start in range(0, len(data), chunk_size):
183
- end = min(start + chunk_size, len(data))
184
- self._spi.xfer(data[start:end])
185
-
186
- def set_backlight(self, value):
187
- """Set the backlight on/off."""
188
- if self._backlight is not None:
189
- GPIO.output(self._backlight, value)
190
-
191
- @property
192
- def width(self):
193
- return (
194
- self._width
195
- if self._rotation == 0 or self._rotation == 180
196
- else self._height
197
- )
198
-
199
- @property
200
- def height(self):
201
- return (
202
- self._height
203
- if self._rotation == 0 or self._rotation == 180
204
- else self._width
205
- )
206
-
207
- def command(self, data):
208
- """Write a byte or array of bytes to the display as command data."""
209
- self.send(data, False)
210
-
211
- def data(self, data):
212
- """Write a byte or array of bytes to the display as display data."""
213
- self.send(data, True)
214
-
215
- def reset(self):
216
- """Reset the display, if reset pin is connected."""
217
- if self._rst is not None:
218
- GPIO.output(self._rst, 1)
219
- time.sleep(0.500)
220
- GPIO.output(self._rst, 0)
221
- time.sleep(0.500)
222
- GPIO.output(self._rst, 1)
223
- time.sleep(0.500)
224
-
225
- def _init(self):
226
- # Initialize the display.
227
-
228
- self.command(ST7789_SWRESET) # Software reset
229
- time.sleep(0.150) # delay 150 ms
230
-
231
- self.command(ST7789_MADCTL)
232
- self.data(0x70)
233
-
234
- self.command(ST7789_FRMCTR2) # Frame rate ctrl - idle mode
235
- self.data(0x0C)
236
- self.data(0x0C)
237
- self.data(0x00)
238
- self.data(0x33)
239
- self.data(0x33)
240
-
241
- self.command(ST7789_COLMOD)
242
- self.data(0x05)
243
-
244
- self.command(ST7789_GCTRL)
245
- self.data(0x14)
246
-
247
- self.command(ST7789_VCOMS)
248
- self.data(0x37)
249
-
250
- self.command(ST7789_LCMCTRL) # Power control
251
- self.data(0x2C)
252
-
253
- self.command(ST7789_VDVVRHEN) # Power control
254
- self.data(0x01)
255
-
256
- self.command(ST7789_VRHS) # Power control
257
- self.data(0x12)
258
-
259
- self.command(ST7789_VDVS) # Power control
260
- self.data(0x20)
261
-
262
- self.command(0xD0)
263
- self.data(0xA4)
264
- self.data(0xA1)
265
-
266
- self.command(ST7789_FRCTRL2)
267
- self.data(0x0F)
268
-
269
- self.command(ST7789_GMCTRP1) # Set Gamma
270
- self.data(0xD0)
271
- self.data(0x04)
272
- self.data(0x0D)
273
- self.data(0x11)
274
- self.data(0x13)
275
- self.data(0x2B)
276
- self.data(0x3F)
277
- self.data(0x54)
278
- self.data(0x4C)
279
- self.data(0x18)
280
- self.data(0x0D)
281
- self.data(0x0B)
282
- self.data(0x1F)
283
- self.data(0x23)
284
-
285
- self.command(ST7789_GMCTRN1) # Set Gamma
286
- self.data(0xD0)
287
- self.data(0x04)
288
- self.data(0x0C)
289
- self.data(0x11)
290
- self.data(0x13)
291
- self.data(0x2C)
292
- self.data(0x3F)
293
- self.data(0x44)
294
- self.data(0x51)
295
- self.data(0x2F)
296
- self.data(0x1F)
297
- self.data(0x1F)
298
- self.data(0x20)
299
- self.data(0x23)
300
-
301
- if self._invert:
302
- self.command(ST7789_INVON) # Invert display
303
- else:
304
- self.command(ST7789_INVOFF) # Don't invert display
305
-
306
- self.command(ST7789_SLPOUT)
307
-
308
- self.command(ST7789_DISPON) # Display on
309
- time.sleep(0.100) # 100 ms
310
-
311
- def begin(self):
312
- """Set up the display
313
-
314
- Deprecated. Included in __init__.
315
-
316
- """
317
- pass
318
-
319
- def set_window(self, x0=0, y0=0, x1=None, y1=None):
320
- """Set the pixel address window for proceeding drawing commands. x0 and
321
- x1 should define the minimum and maximum x pixel bounds. y0 and y1
322
- should define the minimum and maximum y pixel bound. If no parameters
323
- are specified the default will be to update the entire display from 0,0
324
- to width-1,height-1.
325
- """
326
- if x1 is None:
327
- x1 = self._width - 1
328
-
329
- if y1 is None:
330
- y1 = self._height - 1
331
-
332
- y0 += self._offset_top
333
- y1 += self._offset_top
334
-
335
- x0 += self._offset_left
336
- x1 += self._offset_left
337
-
338
- self.command(ST7789_CASET) # Column addr set
339
- self.data(x0 >> 8)
340
- self.data(x0 & 0xFF) # XSTART
341
- self.data(x1 >> 8)
342
- self.data(x1 & 0xFF) # XEND
343
- self.command(ST7789_RASET) # Row addr set
344
- self.data(y0 >> 8)
345
- self.data(y0 & 0xFF) # YSTART
346
- self.data(y1 >> 8)
347
- self.data(y1 & 0xFF) # YEND
348
- self.command(ST7789_RAMWR) # write to RAM
349
-
350
- def display(self, image):
351
- """Write the provided image to the hardware.
352
-
353
- :param image: Should be RGB format and the same dimensions as the display hardware.
354
-
355
- """
356
- # Set address bounds to entire display.
357
- self.set_window()
358
-
359
- # Convert image to 16bit RGB565 format and
360
- # flatten into bytes.
361
- pixelbytes = self.image_to_data(image, self._rotation)
362
-
363
- # Write data to hardware.
364
- for i in range(0, len(pixelbytes), 4096):
365
- self.data(pixelbytes[i : i + 4096])
366
-
367
- def image_to_data(self, image, rotation=0):
368
- if not isinstance(image, np.ndarray):
369
- image = np.array(image.convert("RGB"))
370
-
371
- # Rotate the image
372
- pb = np.rot90(image, rotation // 90).astype("uint16")
373
-
374
- # Mask and shift the 888 RGB into 565 RGB
375
- red = (pb[..., [0]] & 0xF8) << 8
376
- green = (pb[..., [1]] & 0xFC) << 3
377
- blue = (pb[..., [2]] & 0xF8) >> 3
378
-
379
- # Stick 'em together
380
- result = red | green | blue
381
-
382
- # Output the raw bytes
383
- return result.byteswap().tobytes()
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
+ import numbers
22
+ import time
23
+ import numpy as np
24
+
25
+ import spidev
26
+ import RPi.GPIO as GPIO
27
+
28
+
29
+ __version__ = "0.0.4"
30
+
31
+ BG_SPI_CS_BACK = 0
32
+ BG_SPI_CS_FRONT = 1
33
+
34
+ SPI_CLOCK_HZ = 16000000
35
+
36
+ ST7789_NOP = 0x00
37
+ ST7789_SWRESET = 0x01
38
+ ST7789_RDDID = 0x04
39
+ ST7789_RDDST = 0x09
40
+
41
+ ST7789_SLPIN = 0x10
42
+ ST7789_SLPOUT = 0x11
43
+ ST7789_PTLON = 0x12
44
+ ST7789_NORON = 0x13
45
+
46
+ ST7789_INVOFF = 0x20
47
+ ST7789_INVON = 0x21
48
+ ST7789_DISPOFF = 0x28
49
+ ST7789_DISPON = 0x29
50
+
51
+ ST7789_CASET = 0x2A
52
+ ST7789_RASET = 0x2B
53
+ ST7789_RAMWR = 0x2C
54
+ ST7789_RAMRD = 0x2E
55
+
56
+ ST7789_PTLAR = 0x30
57
+ ST7789_MADCTL = 0x36
58
+ ST7789_COLMOD = 0x3A
59
+
60
+ ST7789_FRMCTR1 = 0xB1
61
+ ST7789_FRMCTR2 = 0xB2
62
+ ST7789_FRMCTR3 = 0xB3
63
+ ST7789_INVCTR = 0xB4
64
+ ST7789_DISSET5 = 0xB6
65
+
66
+ ST7789_GCTRL = 0xB7
67
+ ST7789_GTADJ = 0xB8
68
+ ST7789_VCOMS = 0xBB
69
+
70
+ ST7789_LCMCTRL = 0xC0
71
+ ST7789_IDSET = 0xC1
72
+ ST7789_VDVVRHEN = 0xC2
73
+ ST7789_VRHS = 0xC3
74
+ ST7789_VDVS = 0xC4
75
+ ST7789_VMCTR1 = 0xC5
76
+ ST7789_FRCTRL2 = 0xC6
77
+ ST7789_CABCCTRL = 0xC7
78
+
79
+ ST7789_RDID1 = 0xDA
80
+ ST7789_RDID2 = 0xDB
81
+ ST7789_RDID3 = 0xDC
82
+ ST7789_RDID4 = 0xDD
83
+
84
+ ST7789_GMCTRP1 = 0xE0
85
+ ST7789_GMCTRN1 = 0xE1
86
+
87
+ ST7789_PWCTR6 = 0xFC
88
+
89
+
90
+ class ST7789(object):
91
+ """Representation of an ST7789 TFT LCD."""
92
+
93
+ def __init__(
94
+ self,
95
+ port,
96
+ cs,
97
+ dc,
98
+ backlight=None,
99
+ rst=None,
100
+ width=240,
101
+ height=240,
102
+ rotation=90,
103
+ invert=True,
104
+ spi_speed_hz=4000000,
105
+ offset_left=0,
106
+ offset_top=0,
107
+ ):
108
+ """Create an instance of the display using SPI communication.
109
+
110
+ Must provide the GPIO pin number for the D/C pin and the SPI driver.
111
+
112
+ Can optionally provide the GPIO pin number for the reset pin as the rst parameter.
113
+
114
+ :param port: SPI port number
115
+ :param cs: SPI chip-select number (0 or 1 for BCM
116
+ :param backlight: Pin for controlling backlight
117
+ :param rst: Reset pin for ST7789
118
+ :param width: Width of display connected to ST7789
119
+ :param height: Height of display connected to ST7789
120
+ :param rotation: Rotation of display connected to ST7789
121
+ :param invert: Invert display
122
+ :param spi_speed_hz: SPI speed (in Hz)
123
+
124
+ """
125
+ if rotation not in [0, 90, 180, 270]:
126
+ raise ValueError("Invalid rotation {}".format(rotation))
127
+
128
+ if width != height and rotation in [90, 270]:
129
+ raise ValueError(
130
+ "Invalid rotation {} for {}x{} resolution".format(
131
+ rotation, width, height
132
+ )
133
+ )
134
+
135
+ GPIO.setwarnings(False)
136
+ GPIO.setmode(GPIO.BCM)
137
+
138
+ self._spi = spidev.SpiDev(port, cs)
139
+ self._spi.mode = 0
140
+ self._spi.lsbfirst = False
141
+ self._spi.max_speed_hz = spi_speed_hz
142
+
143
+ self._dc = dc
144
+ self._rst = rst
145
+ self._width = width
146
+ self._height = height
147
+ self._rotation = rotation
148
+ self._invert = invert
149
+
150
+ self._offset_left = offset_left
151
+ self._offset_top = offset_top
152
+
153
+ # Set DC as output.
154
+ GPIO.setup(dc, GPIO.OUT)
155
+
156
+ # Setup backlight as output (if provided).
157
+ self._backlight = backlight
158
+ if backlight is not None:
159
+ GPIO.setup(backlight, GPIO.OUT)
160
+ GPIO.output(backlight, GPIO.LOW)
161
+ time.sleep(0.1)
162
+ GPIO.output(backlight, GPIO.HIGH)
163
+
164
+ # Setup reset as output (if provided).
165
+ if rst is not None:
166
+ GPIO.setup(self._rst, GPIO.OUT)
167
+ self.reset()
168
+ self._init()
169
+
170
+ def send(self, data, is_data=True, chunk_size=4096):
171
+ """Write a byte or array of bytes to the display. Is_data parameter
172
+ controls if byte should be interpreted as display data (True) or command
173
+ data (False). Chunk_size is an optional size of bytes to write in a
174
+ single SPI transaction, with a default of 4096.
175
+ """
176
+ # Set DC low for command, high for data.
177
+ GPIO.output(self._dc, is_data)
178
+ # Convert scalar argument to list so either can be passed as parameter.
179
+ if isinstance(data, numbers.Number):
180
+ data = [data & 0xFF]
181
+ # Write data a chunk at a time.
182
+ for start in range(0, len(data), chunk_size):
183
+ end = min(start + chunk_size, len(data))
184
+ self._spi.xfer(data[start:end])
185
+
186
+ def set_backlight(self, value):
187
+ """Set the backlight on/off."""
188
+ if self._backlight is not None:
189
+ GPIO.output(self._backlight, value)
190
+
191
+ @property
192
+ def width(self):
193
+ return (
194
+ self._width
195
+ if self._rotation == 0 or self._rotation == 180
196
+ else self._height
197
+ )
198
+
199
+ @property
200
+ def height(self):
201
+ return (
202
+ self._height
203
+ if self._rotation == 0 or self._rotation == 180
204
+ else self._width
205
+ )
206
+
207
+ def command(self, data):
208
+ """Write a byte or array of bytes to the display as command data."""
209
+ self.send(data, False)
210
+
211
+ def data(self, data):
212
+ """Write a byte or array of bytes to the display as display data."""
213
+ self.send(data, True)
214
+
215
+ def reset(self):
216
+ """Reset the display, if reset pin is connected."""
217
+ if self._rst is not None:
218
+ GPIO.output(self._rst, 1)
219
+ time.sleep(0.500)
220
+ GPIO.output(self._rst, 0)
221
+ time.sleep(0.500)
222
+ GPIO.output(self._rst, 1)
223
+ time.sleep(0.500)
224
+
225
+ def _init(self):
226
+ # Initialize the display.
227
+
228
+ self.command(ST7789_SWRESET) # Software reset
229
+ time.sleep(0.150) # delay 150 ms
230
+
231
+ self.command(ST7789_MADCTL)
232
+ self.data(0x70)
233
+
234
+ self.command(ST7789_FRMCTR2) # Frame rate ctrl - idle mode
235
+ self.data(0x0C)
236
+ self.data(0x0C)
237
+ self.data(0x00)
238
+ self.data(0x33)
239
+ self.data(0x33)
240
+
241
+ self.command(ST7789_COLMOD)
242
+ self.data(0x05)
243
+
244
+ self.command(ST7789_GCTRL)
245
+ self.data(0x14)
246
+
247
+ self.command(ST7789_VCOMS)
248
+ self.data(0x37)
249
+
250
+ self.command(ST7789_LCMCTRL) # Power control
251
+ self.data(0x2C)
252
+
253
+ self.command(ST7789_VDVVRHEN) # Power control
254
+ self.data(0x01)
255
+
256
+ self.command(ST7789_VRHS) # Power control
257
+ self.data(0x12)
258
+
259
+ self.command(ST7789_VDVS) # Power control
260
+ self.data(0x20)
261
+
262
+ self.command(0xD0)
263
+ self.data(0xA4)
264
+ self.data(0xA1)
265
+
266
+ self.command(ST7789_FRCTRL2)
267
+ self.data(0x0F)
268
+
269
+ self.command(ST7789_GMCTRP1) # Set Gamma
270
+ self.data(0xD0)
271
+ self.data(0x04)
272
+ self.data(0x0D)
273
+ self.data(0x11)
274
+ self.data(0x13)
275
+ self.data(0x2B)
276
+ self.data(0x3F)
277
+ self.data(0x54)
278
+ self.data(0x4C)
279
+ self.data(0x18)
280
+ self.data(0x0D)
281
+ self.data(0x0B)
282
+ self.data(0x1F)
283
+ self.data(0x23)
284
+
285
+ self.command(ST7789_GMCTRN1) # Set Gamma
286
+ self.data(0xD0)
287
+ self.data(0x04)
288
+ self.data(0x0C)
289
+ self.data(0x11)
290
+ self.data(0x13)
291
+ self.data(0x2C)
292
+ self.data(0x3F)
293
+ self.data(0x44)
294
+ self.data(0x51)
295
+ self.data(0x2F)
296
+ self.data(0x1F)
297
+ self.data(0x1F)
298
+ self.data(0x20)
299
+ self.data(0x23)
300
+
301
+ if self._invert:
302
+ self.command(ST7789_INVON) # Invert display
303
+ else:
304
+ self.command(ST7789_INVOFF) # Don't invert display
305
+
306
+ self.command(ST7789_SLPOUT)
307
+
308
+ self.command(ST7789_DISPON) # Display on
309
+ time.sleep(0.100) # 100 ms
310
+
311
+ def begin(self):
312
+ """Set up the display
313
+
314
+ Deprecated. Included in __init__.
315
+
316
+ """
317
+ pass
318
+
319
+ def set_window(self, x0=0, y0=0, x1=None, y1=None):
320
+ """Set the pixel address window for proceeding drawing commands. x0 and
321
+ x1 should define the minimum and maximum x pixel bounds. y0 and y1
322
+ should define the minimum and maximum y pixel bound. If no parameters
323
+ are specified the default will be to update the entire display from 0,0
324
+ to width-1,height-1.
325
+ """
326
+ if x1 is None:
327
+ x1 = self._width - 1
328
+
329
+ if y1 is None:
330
+ y1 = self._height - 1
331
+
332
+ y0 += self._offset_top
333
+ y1 += self._offset_top
334
+
335
+ x0 += self._offset_left
336
+ x1 += self._offset_left
337
+
338
+ self.command(ST7789_CASET) # Column addr set
339
+ self.data(x0 >> 8)
340
+ self.data(x0 & 0xFF) # XSTART
341
+ self.data(x1 >> 8)
342
+ self.data(x1 & 0xFF) # XEND
343
+ self.command(ST7789_RASET) # Row addr set
344
+ self.data(y0 >> 8)
345
+ self.data(y0 & 0xFF) # YSTART
346
+ self.data(y1 >> 8)
347
+ self.data(y1 & 0xFF) # YEND
348
+ self.command(ST7789_RAMWR) # write to RAM
349
+
350
+ def display(self, image):
351
+ """Write the provided image to the hardware.
352
+
353
+ :param image: Should be RGB format and the same dimensions as the display hardware.
354
+
355
+ """
356
+ # Set address bounds to entire display.
357
+ self.set_window()
358
+
359
+ # Convert image to 16bit RGB565 format and
360
+ # flatten into bytes.
361
+ pixelbytes = self.image_to_data(image, self._rotation)
362
+
363
+ # Write data to hardware.
364
+ for i in range(0, len(pixelbytes), 4096):
365
+ self.data(pixelbytes[i : i + 4096])
366
+
367
+ def image_to_data(self, image, rotation=0):
368
+ if not isinstance(image, np.ndarray):
369
+ image = np.array(image.convert("RGB"))
370
+
371
+ # Rotate the image
372
+ pb = np.rot90(image, rotation // 90).astype("uint16")
373
+
374
+ # Mask and shift the 888 RGB into 565 RGB
375
+ red = (pb[..., [0]] & 0xF8) << 8
376
+ green = (pb[..., [1]] & 0xFC) << 3
377
+ blue = (pb[..., [2]] & 0xF8) >> 3
378
+
379
+ # Stick 'em together
380
+ result = red | green | blue
381
+
382
+ # Output the raw bytes
383
+ return result.byteswap().tobytes()