1.5" ILI9163 lcd screen working
Posted: Tue Oct 15, 2013 10:02 am
First, I don't know if I'm posting this at the right forum, maybe it belongs to Beginners, if that's so, feel free to move it.
My brother gave me about two months ago a pair of keychain photoframes (the brand is NPlay, but it can be found under other brands), that he had bought for 2€ each as a bargain in Worten, along with the datasheet for the ILI9163 that he suspected could drive the 1,5" screen, and a URL:http://www.waitingforfriday.com/index.p ... Photoframe . Here the author, Simon Inns, explains how he deduced the pinout and built an Atmel C library to drive the screen. Well, I don't know much C and I'm trying to learn Python right now. I thought that porting it to Python for the Pi would be a fun way to learn, so I desoldered the LCD (breaking one of the two in the process) and made an adaptor PCB following Simon's Eagle CAD project. The syntax is not very dissimilar, but there were two minor problems: first, Simon used in the C code direct (parallel) writing to the GPIO registers (the LCD controller is hardwired for parallel input),something that it's not available for Pi Python, and that forced me to use loops to write to the controller with GPIO.output, 1 bit at a time. And second, he used 8 bit (short) integers, so I had to use some creative bit operations to do 2-byte writes with Python integers. I could have used char variables,but I was translating the code directly. To my surprise, my code works, I can print text, dots, lines, rectangles, filled rectangles and circles (all Simon's work, I just ported it), but very slowly. The clear_display function takes about 4 seconds, filling the display with text about the same. The bat and ball animation in the last part of the program runs at reasonable speed, but just running it the CPU load climbs to 100%.
I would like to use the display at the front of my Pi-formerly-old-DVB-T-case to select menu options with some switches or a digital joystick (for example, I would like to run a headless raspbian with a MIDI synthesizer, maybe fluidsynth, and tweak it to select the GM instrument and volume, so I could carry my USB MIDI controller and the Pi and practice anywhere... before that I have to learn lots more), but I think it's a little slow for that right now.
The question is: is there some way to speed up the code? I'm sure that someone with more Python knowledge than me (nearly everyone) can give me some clues. The easy answer is overclocking, but my Pi is already running at 800 MHz and I don't really want to overclock it more, anyway the speed gain would be small. Keep in mind that I'm beggining to learn Python, so I assume that my code is..... let's say improvable, as my english is.
Of course, I would be glad if this is useful to somebody. I think that this neat 128x128 pixels 262K colour LCD can be useful in some projects, and it's good value for the price. I have seen them (or a very similar product) on Ebay from 4$, and on Alibaba there is loads of them
Here is the code :
My brother gave me about two months ago a pair of keychain photoframes (the brand is NPlay, but it can be found under other brands), that he had bought for 2€ each as a bargain in Worten, along with the datasheet for the ILI9163 that he suspected could drive the 1,5" screen, and a URL:http://www.waitingforfriday.com/index.p ... Photoframe . Here the author, Simon Inns, explains how he deduced the pinout and built an Atmel C library to drive the screen. Well, I don't know much C and I'm trying to learn Python right now. I thought that porting it to Python for the Pi would be a fun way to learn, so I desoldered the LCD (breaking one of the two in the process) and made an adaptor PCB following Simon's Eagle CAD project. The syntax is not very dissimilar, but there were two minor problems: first, Simon used in the C code direct (parallel) writing to the GPIO registers (the LCD controller is hardwired for parallel input),something that it's not available for Pi Python, and that forced me to use loops to write to the controller with GPIO.output, 1 bit at a time. And second, he used 8 bit (short) integers, so I had to use some creative bit operations to do 2-byte writes with Python integers. I could have used char variables,but I was translating the code directly. To my surprise, my code works, I can print text, dots, lines, rectangles, filled rectangles and circles (all Simon's work, I just ported it), but very slowly. The clear_display function takes about 4 seconds, filling the display with text about the same. The bat and ball animation in the last part of the program runs at reasonable speed, but just running it the CPU load climbs to 100%.
I would like to use the display at the front of my Pi-formerly-old-DVB-T-case to select menu options with some switches or a digital joystick (for example, I would like to run a headless raspbian with a MIDI synthesizer, maybe fluidsynth, and tweak it to select the GM instrument and volume, so I could carry my USB MIDI controller and the Pi and practice anywhere... before that I have to learn lots more), but I think it's a little slow for that right now.
The question is: is there some way to speed up the code? I'm sure that someone with more Python knowledge than me (nearly everyone) can give me some clues. The easy answer is overclocking, but my Pi is already running at 800 MHz and I don't really want to overclock it more, anyway the speed gain would be small. Keep in mind that I'm beggining to learn Python, so I assume that my code is..... let's say improvable, as my english is.
Of course, I would be glad if this is useful to somebody. I think that this neat 128x128 pixels 262K colour LCD can be useful in some projects, and it's good value for the price. I have seen them (or a very similar product) on Ebay from 4$, and on Alibaba there is loads of them
Here is the code :
Code: Select all
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#************************************************************************
#
# Based on ILI9163 128x128 LCD library
# Copyright (C) 2012 Simon Inns
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Email: simon.inns@gmail.com
#
#************************************************************************/
from time import sleep
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
# array 6x8, Unicode set
font5x8=(
[0x00,0x00,0x00,0x00,0x00,0x00], # 0x00 0
[0x00,0x64,0x18,0x04,0x64,0x18], # 0x01 1
[0x00,0x3c,0x40,0x40,0x20,0x7c], # 0x02 2
[0x00,0x0c,0x30,0x40,0x30,0x0c], # 0x03 3
[0x00,0x3c,0x40,0x30,0x40,0x3c], # 0x04 4
[0x00,0x00,0x3e,0x1c,0x08,0x00], # 0x05 5
[0x00,0x04,0x1e,0x1f,0x1e,0x04], # 0x06 6
[0x00,0x10,0x3c,0x7c,0x3c,0x10], # 0x07 7
[0x00,0x20,0x40,0x3e,0x01,0x02], # 0x08 8
[0x00,0x22,0x14,0x08,0x14,0x22], # 0x09 9
[0x00,0x00,0x38,0x28,0x38,0x00], # 0x0a 10
[0x00,0x00,0x10,0x38,0x10,0x00], # 0x0b 11
[0x00,0x00,0x00,0x10,0x00,0x00], # 0x0c 12
[0x00,0x08,0x78,0x08,0x00,0x00], # 0x0d 13
[0x00,0x00,0x15,0x15,0x0a,0x00], # 0x0e 14
[0x00,0x7f,0x7f,0x09,0x09,0x01], # 0x0f 15
[0x00,0x10,0x20,0x7f,0x01,0x01], # 0x10 16
[0x00,0x04,0x04,0x00,0x01,0x1f], # 0x11 17
[0x00,0x00,0x19,0x15,0x12,0x00], # 0x12 18
[0x00,0x40,0x60,0x50,0x48,0x44], # 0x13 19
[0x00,0x06,0x09,0x09,0x06,0x00], # 0x14 20
[0x00,0x0f,0x02,0x01,0x01,0x00], # 0x15 21
[0x00,0x00,0x01,0x1f,0x01,0x00], # 0x16 22
[0x00,0x44,0x44,0x4a,0x4a,0x51], # 0x17 23
[0x00,0x14,0x74,0x1c,0x17,0x14], # 0x18 24
[0x00,0x51,0x4a,0x4a,0x44,0x44], # 0x19 25
[0x00,0x00,0x00,0x04,0x04,0x04], # 0x1a 26
[0x00,0x00,0x7c,0x54,0x54,0x44], # 0x1b 27
[0x00,0x08,0x08,0x2a,0x1c,0x08], # 0x1c 28
[0x00,0x7c,0x00,0x7c,0x44,0x7c], # 0x1d 29
[0x00,0x04,0x02,0x7f,0x02,0x04], # 0x1e 30
[0x00,0x10,0x20,0x7f,0x20,0x10], # 0x1f 31
[0x00,0x00,0x00,0x00,0x00,0x00], # 0x20 32
[0x00,0x00,0x00,0x6f,0x00,0x00], # ! 0x21 33
[0x00,0x00,0x07,0x00,0x07,0x00], # " 0x22 34
[0x00,0x14,0x7f,0x14,0x7f,0x14], # # 0x23 35
[0x00,0x00,0x07,0x04,0x1e,0x00], # $ 0x24 36
[0x00,0x23,0x13,0x08,0x64,0x62], # % 0x25 37
[0x00,0x36,0x49,0x56,0x20,0x50], # & 0x26 38
[0x00,0x00,0x00,0x07,0x00,0x00], # ' 0x27 39
[0x00,0x00,0x1c,0x22,0x41,0x00], # ( 0x28 40
[0x00,0x00,0x41,0x22,0x1c,0x00], # ) 0x29 41
[0x00,0x14,0x08,0x3e,0x08,0x14], # * 0x2a 42
[0x00,0x08,0x08,0x3e,0x08,0x08], # + 0x2b 43
[0x00,0x00,0x50,0x30,0x00,0x00], # , 0x2c 44
[0x00,0x08,0x08,0x08,0x08,0x08], # - 0x2d 45
[0x00,0x00,0x60,0x60,0x00,0x00], # . 0x2e 46
[0x00,0x20,0x10,0x08,0x04,0x02], # / 0x2f 47
[0x00,0x3e,0x51,0x49,0x45,0x3e], # 0 0x30 48
[0x00,0x00,0x42,0x7f,0x40,0x00], # 1 0x31 49
[0x00,0x42,0x61,0x51,0x49,0x46], # 2 0x32 50
[0x00,0x21,0x41,0x45,0x4b,0x31], # 3 0x33 51
[0x00,0x18,0x14,0x12,0x7f,0x10], # 4 0x34 52
[0x00,0x27,0x45,0x45,0x45,0x39], # 5 0x35 53
[0x00,0x3c,0x4a,0x49,0x49,0x30], # 6 0x36 54
[0x00,0x01,0x71,0x09,0x05,0x03], # 7 0x37 55
[0x00,0x36,0x49,0x49,0x49,0x36], # 8 0x38 56
[0x00,0x06,0x49,0x49,0x29,0x1e], # 9 0x39 57
[0x00,0x00,0x36,0x36,0x00,0x00], # : 0x3a 58
[0x00,0x00,0x56,0x36,0x00,0x00], # ; 0x3b 59
[0x00,0x08,0x14,0x22,0x41,0x00], # < 0x3c 60
[0x00,0x14,0x14,0x14,0x14,0x14], # = 0x3d 61
[0x00,0x00,0x41,0x22,0x14,0x08], # > 0x3e 62
[0x00,0x02,0x01,0x51,0x09,0x06], # ? 0x3f 63
[0x00,0x3e,0x41,0x5d,0x49,0x4e], # @ 0x40 64
[0x00,0x7e,0x09,0x09,0x09,0x7e], # A 0x41 65
[0x00,0x7f,0x49,0x49,0x49,0x36], # B 0x42 66
[0x00,0x3e,0x41,0x41,0x41,0x22], # C 0x43 67
[0x00,0x7f,0x41,0x41,0x41,0x3e], # D 0x44 68
[0x00,0x7f,0x49,0x49,0x49,0x41], # E 0x45 69
[0x00,0x7f,0x09,0x09,0x09,0x01], # F 0x46 70
[0x00,0x3e,0x41,0x49,0x49,0x7a], # G 0x47 71
[0x00,0x7f,0x08,0x08,0x08,0x7f], # H 0x48 72
[0x00,0x00,0x41,0x7f,0x41,0x00], # I 0x49 73
[0x00,0x20,0x40,0x41,0x3f,0x01], # J 0x4a 74
[0x00,0x7f,0x08,0x14,0x22,0x41], # K 0x4b 75
[0x00,0x7f,0x40,0x40,0x40,0x40], # L 0x4c 76
[0x00,0x7f,0x02,0x0c,0x02,0x7f], # M 0x4d 77
[0x00,0x7f,0x04,0x08,0x10,0x7f], # N 0x4e 78
[0x00,0x3e,0x41,0x41,0x41,0x3e], # O 0x4f 79
[0x00,0x7f,0x09,0x09,0x09,0x06], # P 0x50 80
[0x00,0x3e,0x41,0x51,0x21,0x5e], # Q 0x51 81
[0x00,0x7f,0x09,0x19,0x29,0x46], # R 0x52 82
[0x00,0x46,0x49,0x49,0x49,0x31], # S 0x53 83
[0x00,0x01,0x01,0x7f,0x01,0x01], # T 0x54 84
[0x00,0x3f,0x40,0x40,0x40,0x3f], # U 0x55 85
[0x00,0x0f,0x30,0x40,0x30,0x0f], # V 0x56 86
[0x00,0x3f,0x40,0x30,0x40,0x3f], # W 0x57 87
[0x00,0x63,0x14,0x08,0x14,0x63], # X 0x58 88
[0x00,0x07,0x08,0x70,0x08,0x07], # Y 0x59 89
[0x00,0x61,0x51,0x49,0x45,0x43], # Z 0x5a 90
[0x00,0x3c,0x4a,0x49,0x29,0x1e], # [ 0x5b 91
[0x00,0x02,0x04,0x08,0x10,0x20], # \ 0x5c 92
[0x00,0x00,0x41,0x7f,0x00,0x00], # ] 0x5d 93
[0x00,0x04,0x02,0x01,0x02,0x04], # ^ 0x5e 94
[0x00,0x40,0x40,0x40,0x40,0x40], # _ 0x5f 95
[0x00,0x00,0x00,0x03,0x04,0x00], # ` 0x60 96
[0x00,0x20,0x54,0x54,0x54,0x78], # a 0x61 97
[0x00,0x7f,0x48,0x44,0x44,0x38], # b 0x62 98
[0x00,0x38,0x44,0x44,0x44,0x20], # c 0x63 99
[0x00,0x38,0x44,0x44,0x48,0x7f], # d 0x64 100
[0x00,0x38,0x54,0x54,0x54,0x18], # e 0x65 101
[0x00,0x08,0x7e,0x09,0x01,0x02], # f 0x66 102
[0x00,0x0c,0x52,0x52,0x52,0x3e], # g 0x67 103
[0x00,0x7f,0x08,0x04,0x04,0x78], # h 0x68 104
[0x00,0x00,0x44,0x7d,0x40,0x00], # i 0x69 105
[0x00,0x20,0x40,0x44,0x3d,0x00], # j 0x6a 106
[0x00,0x00,0x7f,0x10,0x28,0x44], # k 0x6b 107
[0x00,0x00,0x41,0x7f,0x40,0x00], # l 0x6c 108
[0x00,0x7c,0x04,0x18,0x04,0x78], # m 0x6d 109
[0x00,0x7c,0x08,0x04,0x04,0x78], # n 0x6e 110
[0x00,0x38,0x44,0x44,0x44,0x38], # o 0x6f 111
[0x00,0x7c,0x14,0x14,0x14,0x08], # p 0x70 112
[0x00,0x08,0x14,0x14,0x18,0x7c], # q 0x71 113
[0x00,0x7c,0x08,0x04,0x04,0x08], # r 0x72 114
[0x00,0x48,0x54,0x54,0x54,0x20], # s 0x73 115
[0x00,0x04,0x3f,0x44,0x40,0x20], # t 0x74 116
[0x00,0x3c,0x40,0x40,0x20,0x7c], # u 0x75 117
[0x00,0x1c,0x20,0x40,0x20,0x1c], # v 0x76 118
[0x00,0x3c,0x40,0x30,0x40,0x3c], # w 0x77 119
[0x00,0x44,0x28,0x10,0x28,0x44], # x 0x78 120
[0x00,0x0c,0x50,0x50,0x50,0x3c], # y 0x79 121
[0x00,0x44,0x64,0x54,0x4c,0x44], # z 0x7a 122
[0x00,0x00,0x08,0x36,0x41,0x41], # [ 0x7b 123
[0x00,0x00,0x00,0x7f,0x00,0x00], # | 0x7c 124
[0x00,0x41,0x41,0x36,0x08,0x00], # ] 0x7d 125
[0x00,0x04,0x02,0x04,0x08,0x04], # ~ 0x7e 126
[0x00,0x7f,0x6b,0x6b,0x6b,0x7f], # 0x7f 127
[0x00,0x00,0x7c,0x44,0x7c,0x00], # ¬ 0x80 128
[0x00,0x00,0x08,0x7c,0x00,0x00], # ? 0x81 129
[0x00,0x00,0x64,0x54,0x48,0x00], # 0x82 130
[0x00,0x00,0x44,0x54,0x28,0x00], # 0x83 131
[0x00,0x00,0x1c,0x10,0x78,0x00], # 0x84 132
[0x00,0x00,0x5c,0x54,0x24,0x00], #
0x85 133
[0x00,0x00,0x78,0x54,0x74,0x00], # 0x86 134
[0x00,0x00,0x64,0x14,0x0c,0x00], # 0x87 135
[0x00,0x00,0x7c,0x54,0x7c,0x00], # 0x88 136
[0x00,0x00,0x5c,0x54,0x3c,0x00], # 0x89 137
[0x00,0x78,0x24,0x26,0x25,0x78], # 0x8a 138
[0x00,0x78,0x25,0x26,0x24,0x78], # 0x8b 139
[0x00,0x70,0x2a,0x29,0x2a,0x70], # 0x8c 140
[0x00,0x78,0x25,0x24,0x25,0x78], # ? 0x8d 141
[0x00,0x20,0x54,0x56,0x55,0x78], # ] 0x8e 142
[0x00,0x20,0x55,0x56,0x54,0x78], # ? 0x8f 143
[0x00,0x20,0x56,0x55,0x56,0x78], # ? 0x90 144
[0x00,0x20,0x55,0x54,0x55,0x78], # 0x91 145
[0x00,0x7c,0x54,0x56,0x55,0x44], # 0x92 146
[0x00,0x7c,0x55,0x56,0x54,0x44], # 0x93 147
[0x00,0x7c,0x56,0x55,0x56,0x44], # 0x94 148
[0x00,0x7c,0x55,0x54,0x55,0x44], # 0x95 149
[0x00,0x38,0x54,0x56,0x55,0x18], # 0x96 150
[0x00,0x38,0x55,0x56,0x54,0x18], # 0x97 151
[0x00,0x38,0x56,0x55,0x56,0x18], # 0x98 152
[0x00,0x38,0x55,0x54,0x55,0x18], # 0x99 153
[0x00,0x00,0x44,0x7e,0x45,0x00], # 0x9a 154
[0x00,0x00,0x45,0x7e,0x44,0x00], # 0x9b 155
[0x00,0x00,0x46,0x7d,0x46,0x00], # 0x9c 156
[0x00,0x00,0x45,0x7c,0x45,0x00], # ? 0x9d 157
[0x00,0x00,0x48,0x7a,0x41,0x00], # ~ 0x9e 158
[0x00,0x00,0x49,0x7a,0x40,0x00], # 0x9f 159
[0x00,0x00,0x4a,0x79,0x42,0x00], # 0xa0 160
[0x00,0x00,0x49,0x78,0x41,0x00], # ¡ 0xa1 161
[0x00,0x38,0x44,0x46,0x45,0x38], # ¢ 0xa2 162
[0x00,0x38,0x45,0x46,0x44,0x38], # £ 0xa3 163
[0x00,0x38,0x46,0x45,0x46,0x38], # ¤ 0xa4 164
[0x00,0x38,0x45,0x44,0x45,0x38], # ¥ 0xa5 165
[0x00,0x30,0x48,0x4a,0x49,0x30], # ¦ 0xa6 166
[0x00,0x30,0x49,0x4a,0x48,0x30], # § 0xa7 167
[0x00,0x30,0x4a,0x49,0x4a,0x30], # ¨ 0xa8 168
[0x00,0x30,0x49,0x48,0x49,0x30], # © 0xa9 169
[0x00,0x3c,0x40,0x42,0x41,0x3c], # ª 0xaa 170
[0x00,0x3c,0x41,0x42,0x40,0x3c], # « 0xab 171
[0x00,0x3c,0x42,0x41,0x42,0x3c], # ¬ 0xac 172
[0x00,0x3c,0x41,0x40,0x41,0x3c], # 0xad 173
[0x00,0x3c,0x40,0x42,0x21,0x7c], # ® 0xae 174
[0x00,0x3c,0x41,0x42,0x20,0x7c], # ¯ 0xaf 175
[0x00,0x38,0x42,0x41,0x22,0x78], # ° 0xb0 176
[0x00,0x3c,0x41,0x40,0x21,0x7c], # ± 0xb1 177
[0x00,0x4e,0x51,0x71,0x11,0x0a], # ² 0xb2 178
[0x00,0x58,0x64,0x64,0x24,0x10], # ³ 0xb3 179
[0x00,0x7c,0x0a,0x11,0x22,0x7d], # ´ 0xb4 180
[0x00,0x78,0x12,0x09,0x0a,0x71], # µ 0xb5 181
[0x00,0x00,0x00,0x04,0x02,0x01], # ¶ 0xb6 182
[0x00,0x01,0x02,0x04,0x00,0x00], # · 0xb7 183
[0x00,0x00,0x02,0x00,0x02,0x00], # ¸ 0xb8 184
[0x00,0x30,0x48,0x45,0x40,0x20], # ¹ 0xb9 185
[0x00,0x00,0x00,0x7b,0x00,0x00], # º 0xba 186
[0x00,0x38,0x44,0x44,0x38,0x44], # » 0xbb 187
[0x00,0x40,0x3e,0x49,0x49,0x36], # ¼ 0xbc 188
[0x00,0x08,0x04,0x08,0x70,0x0c], # ½ 0xbd 189
[0x00,0x60,0x50,0x48,0x50,0x60], # ¾ 0xbe 190
[0x00,0x20,0x52,0x55,0x59,0x30], # ¿ 0xbf 191
[0x00,0x38,0x54,0x54,0x54,0x00], # À 0xc0 192
[0x00,0x00,0x00,0x7f,0x41,0x00], # Á 0xc1 193
[0x00,0x40,0x22,0x14,0x18,0x60], # Â 0xc2 194
[0x00,0x7c,0x20,0x20,0x1c,0x20], # Ã 0xc3 195
[0x00,0x44,0x3c,0x04,0x7c,0x44], # Ä 0xc4 196
[0x00,0x40,0x3c,0x12,0x12,0x0c], # Å 0xc5 197
[0x00,0x41,0x63,0x55,0x49,0x41], # Æ 0xc6 198
[0x00,0x38,0x44,0x44,0x3c,0x04], # Ç 0xc7 199
[0x00,0x08,0x04,0x3c,0x44,0x24], # È 0xc8 200
[0x00,0x08,0x14,0x7f,0x14,0x08], # É 0xc9 201
[0x00,0x4e,0x71,0x01,0x71,0x4e], # Ê 0xca 202
[0x00,0x45,0x29,0x11,0x29,0x45], # Ë 0xcb 203
[0x00,0x0d,0x51,0x51,0x51,0x3d], # Ì 0xcc 204
[0x00,0x00,0x00,0x05,0x02,0x05], # Í 0xcd 205
[0x00,0x40,0x00,0x40,0x00,0x40], # Î 0xce 206
[0x00,0x00,0x08,0x1c,0x3e,0x00], # Ï 0xcf 207
[0x00,0x1c,0x1c,0x1c,0x00,0x00], # Ð 0xd0 208
[0x00,0x00,0x70,0x08,0x07,0x00], # Ñ 0xd1 209
[0x00,0x00,0x08,0x08,0x08,0x00], # Ò 0xd2 210
[0x00,0x00,0x1d,0x15,0x17,0x00], # Ó 0xd3 211
[0x00,0x00,0x07,0x05,0x07,0x00], # Ô 0xd4 212
[0x00,0x00,0x11,0x15,0x0a,0x00], # Õ 0xd5 213
[0x00,0x00,0x00,0x00,0x00,0x00], # Ö 0xd6 214
[0x00,0x04,0x3c,0x41,0x20,0x00], # × 0xd7 215
[0x00,0x7c,0x16,0x15,0x16,0x08], # Ø 0xd8 216
[0x00,0x21,0x16,0x08,0x34,0x42], # Ù 0xd9 217
[0x00,0x7f,0x09,0x1d,0x01,0x03], # Ú 0xda 218
[0x00,0x38,0x54,0x54,0x14,0x08], # Û 0xdb 219
[0x00,0x00,0x00,0x7c,0x40,0x40], # Ü 0xdc 220
[0x00,0x7f,0x0e,0x1c,0x38,0x7f], # Ý 0xdd 221
[0x00,0x41,0x22,0x5d,0x22,0x1c], # Þ 0xde 222
[0x00,0x1c,0x3e,0x1c,0x08,0x00], # ß 0xdf 223
[0x00,0x7f,0x7f,0x7f,0x7f,0x7f], # à 0xe0 224
[0x00,0x77,0x7b,0x01,0x7b,0x77], # á 0xe1 225
[0x00,0x7f,0x43,0x75,0x43,0x7f], # â 0xe2 226
[0x00,0x7f,0x6f,0x55,0x43,0x7f], # ã 0xe3 227
[0x00,0x40,0x40,0x40,0x40,0x40], # ä 0xe4 228
[0x00,0x44,0x42,0x5f,0x42,0x44], # å 0xe5 229
[0x00,0x40,0x5e,0x45,0x5e,0x40], # æ 0xe6 230
[0x00,0x40,0x48,0x55,0x5e,0x40], # ç 0xe7 231
[0x00,0x00,0x04,0x08,0x10,0x20], # è 0xe8 232
[0x00,0x03,0x07,0x0e,0x1c,0x38], # é 0xe9 233
[0x00,0x01,0x03,0x07,0x0f,0x1f], # ê 0xea 234
[0x00,0x7c,0x78,0x70,0x60,0x40], # ë 0xeb 235
[0x00,0x08,0x08,0x1c,0x22,0x1c], # ì 0xec 236
[0x00,0x00,0x1c,0x22,0x1c,0x00], # í 0xed 237
[0x00,0x02,0x00,0x08,0x00,0x20], # î 0xee 238
[0x00,0x04,0x3e,0x3f,0x3e,0x04], # ï 0xef 239
[0x00,0x10,0x3e,0x7e,0x3e,0x10], # ð 0xf0 240
[0x00,0x55,0x2a,0x55,0x2a,0x55], # ñ 0xf1 241
[0x00,0x24,0x2a,0x7f,0x2a,0x12], # ò 0xf2 242
[0x00,0x04,0x1e,0x1f,0x1e,0x04], # ó 0xf3 243
[0x00,0x00,0x00,0x00,0x00,0x00], # ô 0xf4 244
[0x00,0x00,0x00,0x00,0x00,0x00], # õ 0xf5 245
[0x00,0x00,0x00,0x00,0x00,0x00], # ö 0xf6 246
[0x00,0x00,0x00,0x00,0x00,0x00], # ÷ 0xf7 247
[0x00,0x00,0x00,0x00,0x00,0x00], # ø 0xf8 248
[0x00,0x00,0x00,0x00,0x00,0x00], # ù 0xf9 249
[0x00,0x00,0x00,0x00,0x00,0x00], # ú 0xfa 250
[0x00,0x00,0x00,0x00,0x00,0x00], # û 0xfb 251
[0x00,0x00,0x00,0x00,0x00,0x00], # ü 0xfc 252
[0x00,0x00,0x00,0x00,0x00,0x00], # ý 0xfd 253
[0x00,0x00,0x00,0x00,0x00,0x00], # þ 0xfe 254
[0x00,0x00,0x00,0x00,0x00,0x00]) # ÿ 0xff 255
#DB0=18
#DB1=22
#DB2=23
#DB3=24
#DB4=25
#DB5=27
#DB6=30
#DB7=31
# GPIO numbers (BCM) for data lines, MSB to LSB
DATOS=[31,30,27,25,24,23,22,18]
#GPIO numbers (BCM) for control lines
RST=7
RD=8
RS=9
CS=10
WR=11
# LCD orientation (0,90º,180º,270º)
LCD_ORIENTATION0=0
LCD_ORIENTATION1=96
LCD_ORIENTATION2=160
LCD_ORIENTATION3=192
#ILI9163 commands
NOP=0x00
SOFT_RESET=0x01
GET_RED_CHANNEL=0x06
GET_GREEN_CHANNEL=0x07
GET_BLUE_CHANNEL=0x08
GET_PIXEL_FORMAT=0x0C
GET_POWER_MODE=0x0A
GET_ADDRESS_MODE=0x0B
GET_DISPLAY_MODE=0x0D
GET_SIGNAL_MODE=0x0E
GET_DIAGNOSTIC_RESULT=0x0F
ENTER_SLEEP_MODE=0x10
EXIT_SLEEP_MODE=0x11
ENTER_PARTIAL_MODE=0x12
ENTER_NORMAL_MODE=0x13
EXIT_INVERT_MODE=0x20
ENTER_INVERT_MODE=0x21
SET_GAMMA_CURVE=0x26
SET_DISPLAY_OFF=0x28
SET_DISPLAY_ON=0x29
SET_COLUMN_ADDRESS=0x2A
SET_PAGE_ADDRESS=0x2B
WRITE_MEMORY_START=0x2C
WRITE_LUT=0x2D
READ_MEMORY_START=0x2E
SET_PARTIAL_AREA=0x30
SET_SCROLL_AREA=0x33
SET_TEAR_OFF=0x34
SET_TEAR_ON=0x35
SET_ADDRESS_MODE=0x36
SET_SCROLL_START=0X37
EXIT_IDLE_MODE=0x38
ENTER_IDLE_MODE=0x39
SET_PIXEL_FORMAT=0x3A
WRITE_MEMORY_CONTINUE=0x3C
READ_MEMORY_CONTINUE=0x3E
SET_TEAR_SCANLINE=0x44
GET_SCANLINE=0x45
READ_ID1=0xDA
READ_ID2=0xDB
READ_ID3=0xDC
FRAME_RATE_CONTROL1=0xB1
FRAME_RATE_CONTROL2=0xB2
FRAME_RATE_CONTROL3=0xB3
DISPLAY_INVERSION=0xB4
SOURCE_DRIVER_DIRECTION=0xB7
GATE_DRIVER_DIRECTION=0xB8
POWER_CONTROL1=0xC0
POWER_CONTROL2=0xC1
POWER_CONTROL3=0xC2
POWER_CONTROL4=0xC3
POWER_CONTROL5=0xC4
VCOM_CONTROL1=0xC5
VCOM_CONTROL2=0xC6
VCOM_OFFSET_CONTROL=0xC7
WRITE_ID4_VALUE=0xD3
NV_MEMORY_FUNCTION1=0xD7
NV_MEMORY_FUNCTION2=0xDE
POSITIVE_GAMMA_CORRECT=0xE0
NEGATIVE_GAMMA_CORRECT=0xE1
GAM_R_SEL=0xF2
#GPIO initial setup
for x in range(0,8):
GPIO.setup(DATOS[x],GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(RST,GPIO.OUT,initial=GPIO.HIGH)
GPIO.setup(RD,GPIO.OUT,initial=GPIO.HIGH)
GPIO.setup(RS,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(CS,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(WR,GPIO.OUT,initial=GPIO.HIGH)
#function to pack 3 bytes rgb value in 2 bytes, R,G and B must be <=31
def decode_rgb(r,g,b):
return ((b<<11) | (g<<6) | (r))
#functions to translate x,y pixel coords. to text column,row
def textX(x):
return x*6
def textY(y):
return y*8
#initial LCD reset
def reset_LCD():
GPIO.output(RST,False)
sleep (0.05)
GPIO.output(RST,True)
sleep (0.12)
return
#write command to controller
def write_command(address):
GPIO.output(RS,False)
GPIO.output(CS,False)
for x in range(7,-1,-1): # sequence inverted to fill from LSB to MSB
GPIO.output(DATOS[x],(address & 1))
address>>=1
GPIO.output(WR,False)
GPIO.output(WR,True)
#write parameter after command
def write_parameter(parameter):
GPIO.output(RS,True)
GPIO.output(CS,False)
for x in range(7,-1,-1):
GPIO.output(DATOS[x],(parameter & 1))
parameter>>=1
GPIO.output(WR,False)
GPIO.output(WR,True)
# GPIO.output(CS,True)
#write data to frame memory, two-byte colour value
def write_data(dataByte1,dataByte2):
GPIO.output(RS,True)
GPIO.output(CS,False)
for x in range(7,-1,-1):
GPIO.output(DATOS[x],(dataByte1 & 1))
dataByte1>>=1
GPIO.output(WR,False)
GPIO.output(WR,True)
for x in range(7,-1,-1):
GPIO.output(DATOS[x],(dataByte2 & 1))
dataByte2>>=1
GPIO.output(WR,False)
GPIO.output(WR,True)
#-------------------------------------------
def iniciar_LCD(orientacion):
reset_LCD()
write_command(EXIT_SLEEP_MODE)
sleep(0.05)
write_command(SET_PIXEL_FORMAT)
write_parameter(0x05)
write_command(SET_GAMMA_CURVE)
write_parameter(0x04)
write_command(GAM_R_SEL)
write_parameter(0x01)
write_command(POSITIVE_GAMMA_CORRECT)
write_parameter(0x3f)
write_parameter(0x25)
write_parameter(0x1c)
write_parameter(0x1e)
write_parameter(0x20)
write_parameter(0x12)
write_parameter(0x2a)
write_parameter(0x90)
write_parameter(0x24)
write_parameter(0x11)
write_parameter(0x00)
write_parameter(0x00)
write_parameter(0x00)
write_parameter(0x00)
write_parameter(0x00)
write_command(NEGATIVE_GAMMA_CORRECT)
write_parameter(0x20)
write_parameter(0x20)
write_parameter(0x20)
write_parameter(0x20)
write_parameter(0x05)
write_parameter(0x00)
write_parameter(0x15)
write_parameter(0xa7)
write_parameter(0x3d)
write_parameter(0x18)
write_parameter(0x25)
write_parameter(0x2a)
write_parameter(0x2b)
write_parameter(0x2b)
write_parameter(0x3a)
write_command(FRAME_RATE_CONTROL1)
write_parameter(0x08)
write_parameter(0x08)
write_command(DISPLAY_INVERSION)
write_parameter(0x01)
write_command(POWER_CONTROL1)
write_parameter(0x0a)
write_parameter(0x02)
write_command(POWER_CONTROL2)
write_parameter(0x02)
write_command(VCOM_CONTROL1)
write_parameter(0x50)
write_parameter(0x5b)
write_command(VCOM_OFFSET_CONTROL)
write_parameter(0x40)
write_command(SET_COLUMN_ADDRESS)
write_parameter(0x00)
write_parameter(0x00)
write_parameter(0x00)
write_parameter(0x7f)
write_command(SET_PAGE_ADDRESS)
write_parameter(0x00)
write_parameter(0x00)
write_parameter(0x00)
write_parameter(0x7f)
write_command(SET_ADDRESS_MODE)
write_parameter(orientacion)
clear_display(decode_rgb(0,0,0))
write_command(SET_DISPLAY_ON)
# write_command(WRITE_MEMORY_START)
# clear display,writes same color pixel in all screen
def clear_display(color):
color_hi=color>>8 #requires two 1-byte writes
color_lo= color&(~(65280))
write_command(SET_COLUMN_ADDRESS)
write_parameter(0x00)
write_parameter(0x02)
write_parameter(0x00)
write_parameter(0x81)
write_command(SET_PAGE_ADDRESS)
write_parameter(0x00)
write_parameter(0x01)
write_parameter(0x00)
write_parameter(0x80)
write_command(WRITE_MEMORY_START)
for pixel in range (0,16384):
write_data(color_hi,color_lo)
# draw a dot in x,y with 'color' colour
def draw_dot(x,y,color):
color_hi=color>>8
color_lo= color&(~(65280))
write_command(SET_COLUMN_ADDRESS)
write_parameter(0x00)
write_parameter(x+2)
write_parameter(0x00)
write_parameter(x+3)
write_command(SET_PAGE_ADDRESS)
write_parameter(0x00)
write_parameter(y+1)
write_parameter(0x00)
write_parameter(y+2)
write_command(WRITE_MEMORY_START)
write_data(color_hi,color_lo)
# Bresenham's algorithm to draw a line with integers
# x0<=x1, y0<=y1
def draw_line(x0,y0,x1,y1,color):
dy=y1-y0
dx=x1-x0
if (dy<0):
dy=-dy
stepy=-1
else:
stepy=1
if (dx<0):
dx=-dx
stepx=-1
else:
stepx=1
dx <<=1
dy <<=1
draw_dot(x0,y0,color)
if (dx>dy):
fraccion=dy-(dx>>1)
while (x0!=x1):
if (fraccion>=0):
y0 +=stepy
fraccion -=dx
x0 +=stepx
fraccion +=dy
draw_dot(x0,y0,color)
else:
fraccion=dx-(dy>>1)
while (y0!=y1):
if (fraccion>=0):
x0 +=stepx
fraccion -=dy
y0 +=stepy
fraccion +=dx
draw_dot(x0,y0,color)
# draws hollow rectangle
# x0<=x1, y0<= y1
def draw_rectangle(x0,y0,x1,y1,color):
draw_line(x0,y0,x0,y1,color)
draw_line(x0,y1,x1,y1,color)
draw_line(x1,y0,x1,y1,color)
draw_line(x0,y0,x1,y0,color)
# draws filled rectangle, fills frame memory section with same pixel
# x0<=x1, y0<=y1
def draw_filled_rectangle(x0,y0,x1,y1,color):
color_hi=color>>8
color_lo= color&(~(65280))
x0+=2
y0+=1
x1+=2
y1+=1
write_command(SET_COLUMN_ADDRESS)
write_parameter(0x00)
write_parameter(x0)
write_parameter(0x00)
write_parameter(x1)
write_command(SET_PAGE_ADDRESS)
write_parameter(0x00)
write_parameter(y0)
write_parameter(0x00)
write_parameter(y1)
write_command(WRITE_MEMORY_START)
for pixels in range (0,(1+x1-x0)*(1+y1-y0)):
write_data(color_hi,color_lo)
#Bresenham's circle algorithm, circle can't pass screen boundaries
def draw_circle(x0,y0,radio,color):
error=1-radio
errorx=1
errory=-2*radio
y=radio
x=0
draw_dot(x0,y0+radio,color)
draw_dot(x0,y0-radio,color)
draw_dot(x0+radio,y0,color)
draw_dot(x0-radio,y0,color)
while (x<y):
if (error>=0):
y -=1
errory +=2
error +=errory
x +=1
errorx +=2
error +=errorx
draw_dot(x0+x,y0+y,color)
draw_dot(x0-x,y0+y,color)
draw_dot(x0+x,y0-y,color)
draw_dot(x0-x,y0-y,color)
draw_dot(x0+y,y0+x,color)
draw_dot(x0-y,y0+x,color)
draw_dot(x0+y,y0-x,color)
draw_dot(x0-y,y0-x,color)
# writes a character in graphic coordinates x,y, with
# foreground and background colours
def put_char(character,x,y,fgcolor,bgcolor):
fgcolor_hi=fgcolor>>8
fgcolor_lo= fgcolor&(~(65280))
bgcolor_hi=bgcolor>>8
bgcolor_lo= bgcolor&(~(65280))
write_command(SET_COLUMN_ADDRESS)
write_parameter(0x00)
write_parameter(x+2)
write_parameter(0x00)
write_parameter((x+7))
write_command(SET_PAGE_ADDRESS)
write_parameter(0x00)
write_parameter(y+1)
write_parameter(0x00)
write_parameter(y+8)
write_command(WRITE_MEMORY_START)
for row in range (0,8):
for column in range (0,6):
if (font5x8[ord(character)][column]) & (1<<row):
write_data(fgcolor_hi,fgcolor_lo)
else:
write_data(bgcolor_hi,bgcolor_lo)
# writes a string in graphic x,y coordinates, with
# foreground and background colours. If edge of screen is reached,
# it wraps to next text line to same starting x coord.
def put_string(cadena,x,y,fgcolor,bgcolor):
origen=x
for char_number in range (0,len(cadena)):
if (x>121):
x=origen
y +=8
if (y>120):
break
put_char(cadena[char_number],x,y,fgcolor,bgcolor)
x +=6
# defines scroll area, row1=lines in top fixed area,
#row2= lines in bottom fixed area
def scroll_area(row1,row2):
write_command(SET_COLUMN_ADDRESS)
write_parameter(0x00)
write_parameter(0x02)
write_parameter(0x00)
write_parameter(0x81)
write_command(SET_PAGE_ADDRESS)
write_parameter(0x00)
write_parameter(0x01)
write_parameter(0x00)
write_parameter(0x80)
x=row1+1
alto=128-(row1+row2)
y=row2+1
write_command(SET_SCROLL_AREA)
write_parameter(0x00)
write_parameter(x)
write_parameter(0x00)
write_parameter(alto)
write_parameter(0x00)
write_parameter(y)
print x,alto,y
# starts vertical scroll, line=how many lines from the start
# of the memory frame will be scrolled
def scroll_start(line):
write_command(SET_SCROLL_START)
write_parameter(0x00)
write_parameter(line)
def invert_screen():
write_command(ENTER_INVERT_MODE)
def normal_screen():
write_command(EXIT_INVERT_MODE)
#----------------------------------------------------------
iniciar_LCD(LCD_ORIENTATION0)
posx=0
posy=0
for i in range (32,220):
put_char(chr(i),posx,posy,decode_rgb(31,31,31),decode_rgb(0,0,0))
posx+=6
if posx>=121:
posx=0
posy+=8
for i in range (48,123):
put_char(chr(i),posx,posy,decode_rgb(0,0,0),decode_rgb(31,31,31))
posx+=6
if posx>=121:
posx=0
posy+=8
scroll_area(0,0)
for i in range (1,132):
scroll_start(i)
sleep(0.01)
for i in range (132,1,-1):
scroll_start(i)
sleep (0.01)
put_string("<<<PULSAR ENTER>>>",textX(2),textY(15),decode_rgb(31,31,0),decode_rgb(31,0,0))
raw_input("pulsar enter")
for i in range (0,5):
invert_screen()
sleep (0.5)
normal_screen()
sleep (0.5)
draw_filled_rectangle(0,0,128,64 ,decode_rgb(31,0,0))
draw_filled_rectangle(0,64,128,128,decode_rgb(0,0,0))
for i in range (4,32,4):
draw_rectangle(i,i,128-i,64-i,decode_rgb(i-1,i-1,i-1))
draw_line(0,0,128,128,decode_rgb(0,31,0))
draw_line(0,128,128,0,decode_rgb(0,31,0))
draw_circle(64,64,63,decode_rgb(0,0,31))
draw_circle(64,64,53,decode_rgb(0,0,31))
draw_circle(64,64,43,decode_rgb(0,0,31))
draw_circle(64,64,33,decode_rgb(0,0,31))
put_string("Hello,World!",28,28,decode_rgb(0,31,0),decode_rgb(0,0,31))
draw_filled_rectangle(0,64,128,128,decode_rgb(0,0,0))
draw_rectangle(0,64,127,127,decode_rgb(0,0,31))
# bat and ball animation
ballX=64
ballY=96
ballSpeed=1
xDir=ballSpeed
yDir=ballSpeed
while(1):
draw_filled_rectangle(ballX,ballY,ballX+2,ballY+2,decode_rgb(0,0,0))
draw_filled_rectangle(ballX-2,122,ballX+4,124,decode_rgb(0,0,0))
ballX +=xDir
ballY +=yDir
if (ballX>121):
xDir=-ballSpeed
if (ballX<4):
xDir=ballSpeed
if (ballY>120):
yDir=-ballSpeed
if (ballY<66):
yDir=ballSpeed
draw_filled_rectangle(ballX,ballY,ballX+2,ballY+2,decode_rgb(31,31,31))
draw_filled_rectangle(ballX-2,122,ballX+4,124,decode_rgb(31,31,31))
#GPIO.cleanup()