This is the David Smart RA8875 Library with mods for working with FRDM-K64F
RA8875_Touch_GSL1680.cpp@193:74f80834d59d, 2019-11-25 (annotated)
- Committer:
- WiredHome
- Date:
- Mon Nov 25 19:55:17 2019 +0000
- Revision:
- 193:74f80834d59d
- Parent:
- 182:8832d03a2a29
- Child:
- 197:853d08e2fb53
Improve debouncing of resistive touch.; Minor format changes for easier maintenance.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 166:53fd4a876dac | 1 | /// |
WiredHome | 166:53fd4a876dac | 2 | /// Support for Touch Controller GSL1680 |
WiredHome | 166:53fd4a876dac | 3 | /// |
WiredHome | 166:53fd4a876dac | 4 | /// Information is quite scarce for the SiLead GSL1680 Capacitive Touch controller. |
WiredHome | 166:53fd4a876dac | 5 | /// Further, this controller hosts a 32-bit micro, but is without flash memory, so |
WiredHome | 166:53fd4a876dac | 6 | /// after power-up, the program must be installed into the chip. This is done through |
WiredHome | 166:53fd4a876dac | 7 | /// the I2C interface. |
WiredHome | 166:53fd4a876dac | 8 | /// |
WiredHome | 182:8832d03a2a29 | 9 | /// @attention To make it a bit more complicated, I cannot find any source |
WiredHome | 166:53fd4a876dac | 10 | /// for this micro, only "bytestream", which one has to hope is defect free. |
WiredHome | 166:53fd4a876dac | 11 | /// |
WiredHome | 182:8832d03a2a29 | 12 | /// @attention To make it even more complicated, I do not have a display with this |
WiredHome | 166:53fd4a876dac | 13 | /// controller in it, so this body of work is the collective merge of what I've |
WiredHome | 166:53fd4a876dac | 14 | /// found and interpreted and interface converted to align with this library. |
WiredHome | 166:53fd4a876dac | 15 | /// |
WiredHome | 182:8832d03a2a29 | 16 | /// @attention It is probably clear that this represents a work in process, and is |
WiredHome | 170:7e26d51bc48b | 17 | /// an attempt to make a working driver. |
WiredHome | 166:53fd4a876dac | 18 | /// |
WiredHome | 166:53fd4a876dac | 19 | /// http://linux-sunxi.org/GSL1680 has some useful information, a bit of which |
WiredHome | 166:53fd4a876dac | 20 | /// is replicated here in case that site changes/disappears. |
WiredHome | 166:53fd4a876dac | 21 | /// |
WiredHome | 166:53fd4a876dac | 22 | /// To read from the chip, just write a single byte with the register number to |
WiredHome | 166:53fd4a876dac | 23 | /// start to read, and then do as many reads as registers to read. |
WiredHome | 166:53fd4a876dac | 24 | /// |
WiredHome | 166:53fd4a876dac | 25 | /// The known registers are: |
WiredHome | 166:53fd4a876dac | 26 | /// * 0x00-0x7F: these registers are used to load portions of the firmware. |
WiredHome | 166:53fd4a876dac | 27 | /// * 0x80: contains the number of touches in the screen. |
WiredHome | 166:53fd4a876dac | 28 | /// ** If zero, the user isn't touching the screen; |
WiredHome | 166:53fd4a876dac | 29 | /// ** if one, only one finger is on the screen; |
WiredHome | 166:53fd4a876dac | 30 | /// ** if two, there are two fingers; and so on. |
WiredHome | 166:53fd4a876dac | 31 | /// * 0x84-0x87: contains the coordinates for the first touch. |
WiredHome | 166:53fd4a876dac | 32 | /// * 0x88-0x8B: contains the coordinates for the second touch. |
WiredHome | 166:53fd4a876dac | 33 | /// * 0x8C-0xAB: contains the coordinates for the third, fourth, and so on |
WiredHome | 166:53fd4a876dac | 34 | /// ** (up to five in some devices, up to ten in other), touches, |
WiredHome | 166:53fd4a876dac | 35 | /// in the same format than the previous ones (four bytes for each touch). |
WiredHome | 166:53fd4a876dac | 36 | /// * 0xE0: STATUS register |
WiredHome | 166:53fd4a876dac | 37 | /// * 0xE4, 0xBC-0xBF: some kind of control registers. Needed for uploading |
WiredHome | 166:53fd4a876dac | 38 | /// the firmware and soft resetting the chip |
WiredHome | 166:53fd4a876dac | 39 | /// (there's not more data available about them). |
WiredHome | 166:53fd4a876dac | 40 | /// * 0xF0: PAGE register. Contains the memory page number currently mapped |
WiredHome | 166:53fd4a876dac | 41 | /// in the 0x00-0x7F registers. |
WiredHome | 166:53fd4a876dac | 42 | /// |
WiredHome | 166:53fd4a876dac | 43 | /// Touch coordinates format |
WiredHome | 166:53fd4a876dac | 44 | /// The four bytes of each group of coordinates contains the X and Y values, |
WiredHome | 166:53fd4a876dac | 45 | /// and also the finger. |
WiredHome | 166:53fd4a876dac | 46 | /// |
WiredHome | 166:53fd4a876dac | 47 | /// * The first two bytes contains, in little endian format, |
WiredHome | 166:53fd4a876dac | 48 | /// ** the X coordinate in the 12 lower bits. |
WiredHome | 166:53fd4a876dac | 49 | /// * The other two bytes contains, in little endian format, |
WiredHome | 166:53fd4a876dac | 50 | /// ** the Y coordinate in the 12 lower bits. |
WiredHome | 166:53fd4a876dac | 51 | /// ** The 4 upper bits in the Y coordinate contains the finger identifier. |
WiredHome | 166:53fd4a876dac | 52 | /// |
WiredHome | 166:53fd4a876dac | 53 | /// Example: |
WiredHome | 166:53fd4a876dac | 54 | /// Let's say that the user touches the screen with one finger. The register 0x80 |
WiredHome | 166:53fd4a876dac | 55 | /// will contain 1, and registers 0x84 to 0x87 will contain the X and Y coordinates, |
WiredHome | 166:53fd4a876dac | 56 | /// and the finger identifier will be 1. |
WiredHome | 166:53fd4a876dac | 57 | /// |
WiredHome | 166:53fd4a876dac | 58 | /// Now the user, without removing the first finger, touches the screen with a second finger. |
WiredHome | 166:53fd4a876dac | 59 | /// The register 0x80 will contain 2. Registers 0x84 to 0x87 will contain the |
WiredHome | 166:53fd4a876dac | 60 | /// X and Y coordinates of the first touch and the finger identifier in them will be 1. |
WiredHome | 166:53fd4a876dac | 61 | /// Registers 0x88 to 0x8B will contain the X and Y coordinates of the second touch |
WiredHome | 166:53fd4a876dac | 62 | /// and the finger identifier in them will be 2. |
WiredHome | 166:53fd4a876dac | 63 | /// |
WiredHome | 166:53fd4a876dac | 64 | /// Now the user removes the first finger, keeping the second one. The register 0x80 |
WiredHome | 166:53fd4a876dac | 65 | /// will contain 1. Registers 0x84 to 0x87 will contain the X and Y coordinates, |
WiredHome | 166:53fd4a876dac | 66 | /// but the finger identifier will be 2, because that's the finger that remains |
WiredHome | 166:53fd4a876dac | 67 | /// in the screen. |
WiredHome | 165:695c24cc5197 | 68 | |
WiredHome | 165:695c24cc5197 | 69 | #include "RA8875.h" |
WiredHome | 166:53fd4a876dac | 70 | #include "RA8875_Touch_GSL1680_Firmware.h" |
WiredHome | 165:695c24cc5197 | 71 | |
WiredHome | 171:f92c0f1f6db4 | 72 | //#define DEBUG "RAGL" |
WiredHome | 168:37a0c4d8791c | 73 | // ... |
WiredHome | 168:37a0c4d8791c | 74 | // INFO("Stuff to show %d", var); // new-line is automatically appended |
WiredHome | 168:37a0c4d8791c | 75 | // |
WiredHome | 168:37a0c4d8791c | 76 | #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) |
WiredHome | 168:37a0c4d8791c | 77 | #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 168:37a0c4d8791c | 78 | #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 168:37a0c4d8791c | 79 | #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 193:74f80834d59d | 80 | static void HexDump(const char * title, const uint8_t * p, int count) { |
WiredHome | 168:37a0c4d8791c | 81 | int i; |
WiredHome | 168:37a0c4d8791c | 82 | char buf[100] = "0000: "; |
WiredHome | 168:37a0c4d8791c | 83 | |
WiredHome | 168:37a0c4d8791c | 84 | if (*title) |
WiredHome | 168:37a0c4d8791c | 85 | INFO("%s", title); |
WiredHome | 168:37a0c4d8791c | 86 | for (i=0; i<count; ) { |
WiredHome | 168:37a0c4d8791c | 87 | sprintf(buf + strlen(buf), "%02X ", *(p+i)); |
WiredHome | 168:37a0c4d8791c | 88 | if ((++i & 0x0F) == 0x00) { |
WiredHome | 168:37a0c4d8791c | 89 | INFO("%s", buf); |
WiredHome | 168:37a0c4d8791c | 90 | if (i < count) |
WiredHome | 168:37a0c4d8791c | 91 | sprintf(buf, "%04X: ", i); |
WiredHome | 168:37a0c4d8791c | 92 | else |
WiredHome | 168:37a0c4d8791c | 93 | buf[0] = '\0'; |
WiredHome | 168:37a0c4d8791c | 94 | } |
WiredHome | 168:37a0c4d8791c | 95 | } |
WiredHome | 168:37a0c4d8791c | 96 | if (strlen(buf)) |
WiredHome | 168:37a0c4d8791c | 97 | INFO("%s", buf); |
WiredHome | 168:37a0c4d8791c | 98 | } |
WiredHome | 168:37a0c4d8791c | 99 | #else |
WiredHome | 168:37a0c4d8791c | 100 | #define INFO(x, ...) |
WiredHome | 168:37a0c4d8791c | 101 | #define WARN(x, ...) |
WiredHome | 168:37a0c4d8791c | 102 | #define ERR(x, ...) |
WiredHome | 168:37a0c4d8791c | 103 | #define HexDump(a, b, c) |
WiredHome | 168:37a0c4d8791c | 104 | #endif |
WiredHome | 168:37a0c4d8791c | 105 | |
WiredHome | 168:37a0c4d8791c | 106 | |
WiredHome | 166:53fd4a876dac | 107 | #if 0 |
WiredHome | 165:695c24cc5197 | 108 | // Translate from GSL1680 Event Flag to Touch Code to API-match the |
WiredHome | 165:695c24cc5197 | 109 | // alternate resistive touch screen driver common in the RA8875 |
WiredHome | 165:695c24cc5197 | 110 | // displays. |
WiredHome | 165:695c24cc5197 | 111 | static const TouchCode_t GSL1680_EventFlagToTouchCode[4] = { |
WiredHome | 165:695c24cc5197 | 112 | touch, // 00b Put Down |
WiredHome | 165:695c24cc5197 | 113 | release, // 01b Put Up |
WiredHome | 165:695c24cc5197 | 114 | held, // 10b Contact |
WiredHome | 165:695c24cc5197 | 115 | no_touch // 11b Reserved |
WiredHome | 165:695c24cc5197 | 116 | }; |
WiredHome | 166:53fd4a876dac | 117 | #endif |
WiredHome | 165:695c24cc5197 | 118 | |
WiredHome | 165:695c24cc5197 | 119 | RetCode_t RA8875::GSL1680_Init() { |
WiredHome | 165:695c24cc5197 | 120 | RetCode_t r = noerror; |
WiredHome | 165:695c24cc5197 | 121 | uint8_t buf[5] = {0}; // addr + up to 4 Bytes data |
WiredHome | 165:695c24cc5197 | 122 | unsigned int source_line = 0; |
WiredHome | 165:695c24cc5197 | 123 | unsigned int source_len; |
WiredHome | 165:695c24cc5197 | 124 | const struct fw_data *ptr_fw; |
WiredHome | 165:695c24cc5197 | 125 | |
WiredHome | 168:37a0c4d8791c | 126 | INFO("GSL1680_Init()"); |
WiredHome | 165:695c24cc5197 | 127 | // Wake it |
WiredHome | 165:695c24cc5197 | 128 | m_wake->write(false); |
WiredHome | 165:695c24cc5197 | 129 | wait_ms(20); |
WiredHome | 165:695c24cc5197 | 130 | m_wake->write(true); |
WiredHome | 165:695c24cc5197 | 131 | wait_ms(20); |
WiredHome | 165:695c24cc5197 | 132 | |
WiredHome | 165:695c24cc5197 | 133 | // Clear reg |
WiredHome | 165:695c24cc5197 | 134 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 135 | buf[1] = 0x88; |
WiredHome | 165:695c24cc5197 | 136 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 137 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 138 | buf[0] = 0x80; |
WiredHome | 165:695c24cc5197 | 139 | buf[1] = 0x03; |
WiredHome | 165:695c24cc5197 | 140 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 141 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 142 | buf[0] = 0xe4; |
WiredHome | 165:695c24cc5197 | 143 | buf[1] = 0x04; |
WiredHome | 165:695c24cc5197 | 144 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 145 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 146 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 147 | buf[1] = 0x00; |
WiredHome | 165:695c24cc5197 | 148 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 149 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 150 | |
WiredHome | 165:695c24cc5197 | 151 | // Reset |
WiredHome | 165:695c24cc5197 | 152 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 153 | buf[1] = 0x88; |
WiredHome | 165:695c24cc5197 | 154 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 155 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 156 | buf[0] = 0xe4; |
WiredHome | 165:695c24cc5197 | 157 | buf[1] = 0x04; |
WiredHome | 165:695c24cc5197 | 158 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 159 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 160 | buf[0] = 0xbc; |
WiredHome | 165:695c24cc5197 | 161 | buf[1] = 0x00; |
WiredHome | 165:695c24cc5197 | 162 | buf[2] = 0x00; |
WiredHome | 165:695c24cc5197 | 163 | buf[3] = 0x00; |
WiredHome | 165:695c24cc5197 | 164 | buf[4] = 0x00; |
WiredHome | 165:695c24cc5197 | 165 | m_i2c->write(m_addr, (char *)buf, 5); |
WiredHome | 165:695c24cc5197 | 166 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 167 | |
WiredHome | 165:695c24cc5197 | 168 | // Load Firmware |
WiredHome | 165:695c24cc5197 | 169 | ptr_fw = GSLX680_FW; |
WiredHome | 165:695c24cc5197 | 170 | source_len = ARRAY_SIZE(GSLX680_FW); |
WiredHome | 165:695c24cc5197 | 171 | for (source_line = 0; source_line < source_len; source_line++) |
WiredHome | 193:74f80834d59d | 172 | |
WiredHome | 165:695c24cc5197 | 173 | { |
WiredHome | 165:695c24cc5197 | 174 | /* init page trans, set the page val */ |
WiredHome | 193:74f80834d59d | 175 | if (0xf0 == ptr_fw[source_line].offset) { |
WiredHome | 165:695c24cc5197 | 176 | buf[0] = 0xf0; |
WiredHome | 165:695c24cc5197 | 177 | buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff); |
WiredHome | 168:37a0c4d8791c | 178 | INFO("GSL1680 Firmware set page: %02X", buf[1]); |
WiredHome | 165:695c24cc5197 | 179 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 193:74f80834d59d | 180 | } else { |
WiredHome | 165:695c24cc5197 | 181 | buf[0] = ptr_fw[source_line].offset; |
WiredHome | 165:695c24cc5197 | 182 | buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff); |
WiredHome | 165:695c24cc5197 | 183 | buf[2] = (uint8_t)((ptr_fw[source_line].val & 0x0000ff00) >> 8); |
WiredHome | 165:695c24cc5197 | 184 | buf[3] = (uint8_t)((ptr_fw[source_line].val & 0x00ff0000) >> 16); |
WiredHome | 165:695c24cc5197 | 185 | buf[4] = (uint8_t)((ptr_fw[source_line].val & 0xff000000) >> 24); |
WiredHome | 168:37a0c4d8791c | 186 | //INFO("GSL1680 Firmware write[%02X] = %08X", ptr_fw[source_line].offset, ptr_fw[source_line].val); |
WiredHome | 165:695c24cc5197 | 187 | m_i2c->write(m_addr, (char *)buf, 5); |
WiredHome | 165:695c24cc5197 | 188 | } |
WiredHome | 165:695c24cc5197 | 189 | } |
WiredHome | 165:695c24cc5197 | 190 | |
WiredHome | 165:695c24cc5197 | 191 | // Startup chip |
WiredHome | 165:695c24cc5197 | 192 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 193 | buf[1] = 0x00; |
WiredHome | 165:695c24cc5197 | 194 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 195 | wait_ms(100); |
WiredHome | 165:695c24cc5197 | 196 | |
WiredHome | 165:695c24cc5197 | 197 | return r; |
WiredHome | 165:695c24cc5197 | 198 | } |
WiredHome | 165:695c24cc5197 | 199 | |
WiredHome | 165:695c24cc5197 | 200 | uint8_t RA8875::GSL1680_ReadRegU8(uint8_t reg, uint8_t * buf, int count) { |
WiredHome | 165:695c24cc5197 | 201 | uint8_t lbuf[1]; |
WiredHome | 165:695c24cc5197 | 202 | |
WiredHome | 165:695c24cc5197 | 203 | if (buf == NULL) { |
WiredHome | 165:695c24cc5197 | 204 | buf = lbuf; |
WiredHome | 165:695c24cc5197 | 205 | count = 1; |
WiredHome | 165:695c24cc5197 | 206 | } |
WiredHome | 165:695c24cc5197 | 207 | m_i2c->write(m_addr, (char *)®, 1); |
WiredHome | 165:695c24cc5197 | 208 | m_i2c->read(m_addr, (char *)buf, count); |
WiredHome | 165:695c24cc5197 | 209 | return buf[0]; |
WiredHome | 165:695c24cc5197 | 210 | } |
WiredHome | 165:695c24cc5197 | 211 | |
WiredHome | 165:695c24cc5197 | 212 | |
WiredHome | 165:695c24cc5197 | 213 | uint8_t RA8875::GSL1680_TouchPositions(void) { |
WiredHome | 166:53fd4a876dac | 214 | // [80] = # touch points |
WiredHome | 166:53fd4a876dac | 215 | // [81] not used |
WiredHome | 166:53fd4a876dac | 216 | // [82] not used |
WiredHome | 166:53fd4a876dac | 217 | // [83] not used |
WiredHome | 166:53fd4a876dac | 218 | // [84] --+ Touch # 1 info |
WiredHome | 166:53fd4a876dac | 219 | // [85] | |
WiredHome | 166:53fd4a876dac | 220 | // [86] | |
WiredHome | 166:53fd4a876dac | 221 | // [87] --+ |
WiredHome | 166:53fd4a876dac | 222 | // [88] --+ Touch # 2 info |
WiredHome | 166:53fd4a876dac | 223 | // [89] | |
WiredHome | 166:53fd4a876dac | 224 | // [8A] | |
WiredHome | 166:53fd4a876dac | 225 | // [8B] --+ |
WiredHome | 166:53fd4a876dac | 226 | // ... |
WiredHome | 193:74f80834d59d | 227 | |
WiredHome | 166:53fd4a876dac | 228 | #define TD_SPACE (4 + 4 * GSL1680_TOUCH_POINTS) |
WiredHome | 170:7e26d51bc48b | 229 | if (m_irq->read() == 0) { |
WiredHome | 166:53fd4a876dac | 230 | uint8_t touch_data[TD_SPACE]; |
WiredHome | 165:695c24cc5197 | 231 | |
WiredHome | 166:53fd4a876dac | 232 | GSL1680_ReadRegU8(0x80, touch_data, TD_SPACE); |
WiredHome | 165:695c24cc5197 | 233 | numberOfTouchPoints = touch_data[0]; |
WiredHome | 165:695c24cc5197 | 234 | gesture = FT5206_GEST_ID_NO_GESTURE; // no gesture support |
WiredHome | 165:695c24cc5197 | 235 | |
WiredHome | 168:37a0c4d8791c | 236 | INFO("GSL1680 Touch %d points", numberOfTouchPoints); |
WiredHome | 166:53fd4a876dac | 237 | int tNdx = GSL1680_TOUCH_POINTS - 1; |
WiredHome | 166:53fd4a876dac | 238 | int dNdx = TD_SPACE - 1; |
WiredHome | 166:53fd4a876dac | 239 | for ( ; tNdx >= 0; tNdx--, dNdx -= 4) { |
WiredHome | 182:8832d03a2a29 | 240 | uint16_t fingerAndY, AndX; |
WiredHome | 166:53fd4a876dac | 241 | fingerAndY = (uint16_t)(touch_data[dNdx-0])<<8 | (uint16_t)touch_data[dNdx-1]; |
WiredHome | 166:53fd4a876dac | 242 | AndX = (uint16_t)(touch_data[dNdx-2])<<8 | (uint16_t)touch_data[dNdx-3]; |
WiredHome | 166:53fd4a876dac | 243 | touchInfo[tNdx].coordinates.y = fingerAndY & 0x0FFF; |
WiredHome | 166:53fd4a876dac | 244 | touchInfo[tNdx].coordinates.x = AndX & 0x0FFFF; |
WiredHome | 166:53fd4a876dac | 245 | touchInfo[tNdx].touchID = (fingerAndY >> 12); |
WiredHome | 168:37a0c4d8791c | 246 | touchInfo[tNdx].touchCode = (numberOfTouchPoints > tNdx) ? touch : no_touch; |
WiredHome | 168:37a0c4d8791c | 247 | //INFO(" Code %d, Finger %d, xy (%4d,%4d)", |
WiredHome | 168:37a0c4d8791c | 248 | // touchInfo[tNdx].touchCode, touchInfo[tNdx].touchID, |
WiredHome | 168:37a0c4d8791c | 249 | // touchInfo[tNdx].coordinates.x, touchInfo[tNdx].coordinates.y); |
WiredHome | 166:53fd4a876dac | 250 | } |
WiredHome | 165:695c24cc5197 | 251 | } else { |
WiredHome | 165:695c24cc5197 | 252 | numberOfTouchPoints = 0; |
WiredHome | 170:7e26d51bc48b | 253 | ERR("GSL1680 Touch - else path, unexpected."); |
WiredHome | 165:695c24cc5197 | 254 | } |
WiredHome | 165:695c24cc5197 | 255 | return numberOfTouchPoints; |
WiredHome | 165:695c24cc5197 | 256 | } |