Added printing of data to the end of session not during session

Fork of SI1141_auto_sense by MF Doom

Committer:
mfillinois
Date:
Fri Jun 13 16:56:35 2014 +0000
Revision:
12:a7ec3a43a4a0
Parent:
11:f90ed8f6f38b
Added an array to store data (avoid bluetooth transfer) and print at the end of the session

Who changed what in which revision?

UserRevisionLine numberNew contents of line
GAT27 2:21381f11a5af 1 /**
GAT27 2:21381f11a5af 2 * @author Guillermo A Torijano
GAT27 2:21381f11a5af 3 *
GAT27 2:21381f11a5af 4 * @section LICENSE
GAT27 2:21381f11a5af 5 *
GAT27 2:21381f11a5af 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
GAT27 2:21381f11a5af 7 * of this software and associated documentation files (the "Software"), to deal
GAT27 2:21381f11a5af 8 * in the Software without restriction, including without limitation the rights
GAT27 2:21381f11a5af 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
GAT27 2:21381f11a5af 10 * copies of the Software, and to permit persons to whom the Software is
GAT27 2:21381f11a5af 11 * furnished to do so, subject to the following conditions:
GAT27 2:21381f11a5af 12 *
GAT27 2:21381f11a5af 13 * The above copyright notice and this permission notice shall be included in
GAT27 2:21381f11a5af 14 * all copies or substantial portions of the Software.
GAT27 2:21381f11a5af 15 *
GAT27 2:21381f11a5af 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
GAT27 2:21381f11a5af 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
GAT27 2:21381f11a5af 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
GAT27 2:21381f11a5af 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
GAT27 2:21381f11a5af 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
GAT27 2:21381f11a5af 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
GAT27 2:21381f11a5af 22 * THE SOFTWARE.
GAT27 2:21381f11a5af 23 *
GAT27 2:21381f11a5af 24 * @section DESCRIPTION
GAT27 2:21381f11a5af 25 *
GAT27 2:21381f11a5af 26 * Parallax SI1143 Gesture Sensor.
GAT27 2:21381f11a5af 27 *
GAT27 2:21381f11a5af 28 * Datasheet:
GAT27 2:21381f11a5af 29 *
GAT27 2:21381f11a5af 30 * http://www.silabs.com/Support%20Documents/TechnicalDocs/Si114x.pdf
GAT27 2:21381f11a5af 31 */
GAT27 2:21381f11a5af 32
GAT27 0:18ebb7348150 33 #include "SI1143.h"
GAT27 0:18ebb7348150 34
dmcohen24 10:a89555c4f62a 35 SI1143::SI1143(I2C* comm, PinName vcc, PinName enable, char offset)
GAT27 0:18ebb7348150 36 {
GAT27 0:18ebb7348150 37 wait_ms(30);
dmcohen24 10:a89555c4f62a 38
dmcohen24 10:a89555c4f62a 39 on = new DigitalOut(vcc);
dmcohen24 10:a89555c4f62a 40 en = new DigitalOut(enable);
GAT27 0:18ebb7348150 41
dmcohen24 10:a89555c4f62a 42 on->write(0);
dmcohen24 10:a89555c4f62a 43 en->write(0);
dmcohen24 10:a89555c4f62a 44 wait_ms(30);
dmcohen24 10:a89555c4f62a 45
dmcohen24 10:a89555c4f62a 46 adrs = IR_ADDRESS;
dmcohen24 10:a89555c4f62a 47 i2c_ = comm;
dmcohen24 10:a89555c4f62a 48
dmcohen24 10:a89555c4f62a 49 restart(offset);
GAT27 4:af8f820733e0 50 }
GAT27 4:af8f820733e0 51
dmcohen24 10:a89555c4f62a 52 void SI1143::restart(char offset)
dmcohen24 10:a89555c4f62a 53 {
dmcohen24 10:a89555c4f62a 54 DigitalOut l3(LED3);
dmcohen24 10:a89555c4f62a 55 l3 = 0;
dmcohen24 10:a89555c4f62a 56
dmcohen24 10:a89555c4f62a 57 wait_ms(30);
dmcohen24 10:a89555c4f62a 58 on->write(1);
dmcohen24 10:a89555c4f62a 59 wait_ms(30);
dmcohen24 10:a89555c4f62a 60 en->write(1);
GAT27 0:18ebb7348150 61 wait_ms(30);
GAT27 0:18ebb7348150 62
dmcohen24 10:a89555c4f62a 63 //printf("%d\r\n",adrs);
dmcohen24 10:a89555c4f62a 64
dmcohen24 10:a89555c4f62a 65 command(RESET);
dmcohen24 10:a89555c4f62a 66 l3 = 1;
dmcohen24 10:a89555c4f62a 67 wait_ms(30);
dmcohen24 8:70933bf445af 68 //Do this because you have to
GAT27 5:3fadc61598bc 69 write_reg(HW_KEY,HW_KEY_VAL0);
dmcohen24 10:a89555c4f62a 70 //Give new address
dmcohen24 10:a89555c4f62a 71 write_reg(PARAM_WR, adrs + offset);
dmcohen24 10:a89555c4f62a 72 //write_reg(PARAM_WR, ALS_IR_TASK + ALS_VIS_TASK + PS1_TASK + PS2_TASK + PS3_TASK);
dmcohen24 10:a89555c4f62a 73 command(PARAM_SET + (I2C_ADDR & 0x1F));
dmcohen24 10:a89555c4f62a 74
dmcohen24 10:a89555c4f62a 75 //set new address
dmcohen24 10:a89555c4f62a 76 command(BUSADDR);
dmcohen24 10:a89555c4f62a 77
dmcohen24 10:a89555c4f62a 78 adrs = adrs + offset;
dmcohen24 8:70933bf445af 79
dmcohen24 8:70933bf445af 80 // Setting up LED Power to FULL JUICE
dmcohen24 10:a89555c4f62a 81 write_reg(PS_LED21,0xCC); // Was 0x0A
dmcohen24 7:f1303b85db58 82 write_reg(PS_LED3,0x00);
dmcohen24 8:70933bf445af 83
dmcohen24 8:70933bf445af 84 //Activate ALS_IR, ALS_VIS, and PS1
dmcohen24 10:a89555c4f62a 85 write_reg(PARAM_WR, ALS_IR_TASK + ALS_VIS_TASK + PS1_TASK + PS2_TASK);
dmcohen24 8:70933bf445af 86 //write_reg(PARAM_WR, ALS_IR_TASK + ALS_VIS_TASK + PS1_TASK + PS2_TASK + PS3_TASK);
dmcohen24 8:70933bf445af 87 command(PARAM_SET + (CHLIST & 0x1F));
GAT27 0:18ebb7348150 88
dmcohen24 8:70933bf445af 89 /*
dmcohen24 8:70933bf445af 90 // Set PS_RANGE to high signal range
dmcohen24 8:70933bf445af 91 write_reg(PARAM_WR, 0x04); // 0x24 for high signal, 0x04 for normal
dmcohen24 8:70933bf445af 92 command(PARAM_SET + (PS_ADC_MISC & 0x1F));
dmcohen24 8:70933bf445af 93 */
dmcohen24 8:70933bf445af 94 //Set PS_ADC_COUNTER to lower time between ADC samples
dmcohen24 10:a89555c4f62a 95 write_reg(PARAM_WR, 0x07);
dmcohen24 8:70933bf445af 96 command(PARAM_SET + (PS_ADC_COUNTER & 0x1F));
dmcohen24 8:70933bf445af 97
dmcohen24 8:70933bf445af 98 //Turn up the juice on PS ACD GAIN!
dmcohen24 9:31d4e955ee92 99 write_reg(PARAM_WR, 0x00);
dmcohen24 8:70933bf445af 100 command(PARAM_SET + (PS_ADC_GAIN & 0x1F));
dmcohen24 8:70933bf445af 101
GAT27 0:18ebb7348150 102
dmcohen24 9:31d4e955ee92 103 write_reg(INT_CFG,0x01); // Configure Interrupts
mfillinois 11:f90ed8f6f38b 104 write_reg(IRQ_ENABLE,0x0C); // Enable PS1 (0x04) Enable PS1 & PS2 (0x0C)
GAT27 0:18ebb7348150 105 write_reg(IRQ_MODE1,0);
GAT27 0:18ebb7348150 106 write_reg(IRQ_MODE2,0);
dmcohen24 7:f1303b85db58 107
mfillinois 12:a7ec3a43a4a0 108 write_reg(MEAS_RATE,0xA0); //0x84 - wakes up every 10 ms
mfillinois 11:f90ed8f6f38b 109 write_reg(PS_RATE,0x08); //0x8 - wakes up every time measurement clock wakes up
dmcohen24 9:31d4e955ee92 110
dmcohen24 7:f1303b85db58 111 //write_reg(PS_ADC_MISC,0x24);
dmcohen24 7:f1303b85db58 112 //write_reg(PS1_ADCMUX,0x03);
GAT27 0:18ebb7348150 113 }
GAT27 0:18ebb7348150 114
GAT27 0:18ebb7348150 115 void SI1143::command(char cmd)
GAT27 0:18ebb7348150 116 {
GAT27 0:18ebb7348150 117 int val;
dmcohen24 10:a89555c4f62a 118 DigitalOut l2(LED2);
GAT27 0:18ebb7348150 119
GAT27 0:18ebb7348150 120 val = read_reg(RESPONSE,1);
GAT27 0:18ebb7348150 121 while(val!=0)
GAT27 0:18ebb7348150 122 {
GAT27 0:18ebb7348150 123 write_reg(COMMAND,NOP);
GAT27 0:18ebb7348150 124 val = read_reg(RESPONSE,1);
dmcohen24 10:a89555c4f62a 125 l2 = 1;
GAT27 0:18ebb7348150 126 }
dmcohen24 10:a89555c4f62a 127 l2 = 0;
GAT27 0:18ebb7348150 128 do{
GAT27 0:18ebb7348150 129 write_reg(COMMAND,cmd);
GAT27 0:18ebb7348150 130 if(cmd==RESET) break;
GAT27 0:18ebb7348150 131 val = read_reg(RESPONSE,1);
GAT27 0:18ebb7348150 132 }while(val==0);
GAT27 0:18ebb7348150 133 }
GAT27 0:18ebb7348150 134
GAT27 1:28beeb2f209b 135 char SI1143::read_reg(/*unsigned*/ char address, int num_data) // Read a register
GAT27 0:18ebb7348150 136 {
GAT27 0:18ebb7348150 137 char tx[1];
GAT27 0:18ebb7348150 138 char rx[1];
GAT27 0:18ebb7348150 139
GAT27 1:28beeb2f209b 140 //i2c_->start();
GAT27 0:18ebb7348150 141 tx[0] = address;
dmcohen24 10:a89555c4f62a 142 i2c_->write((adrs << 1) & 0xFE, tx, num_data);
GAT27 0:18ebb7348150 143 wait_ms(1);
GAT27 1:28beeb2f209b 144 //i2c_->stop();
GAT27 0:18ebb7348150 145
GAT27 1:28beeb2f209b 146 //i2c_->start();
dmcohen24 10:a89555c4f62a 147 i2c_->read((adrs << 1) | 0x01, rx, num_data);
GAT27 0:18ebb7348150 148 wait_ms(1);
GAT27 1:28beeb2f209b 149 //i2c_->stop();
GAT27 0:18ebb7348150 150
GAT27 0:18ebb7348150 151 return rx[0];
GAT27 0:18ebb7348150 152 }
GAT27 0:18ebb7348150 153
GAT27 1:28beeb2f209b 154 void SI1143::write_reg(char address, char num_data) // Write a resigter
GAT27 1:28beeb2f209b 155 {
GAT27 0:18ebb7348150 156 char tx[2];
GAT27 5:3fadc61598bc 157
GAT27 5:3fadc61598bc 158 //i2c_->start();
GAT27 0:18ebb7348150 159 tx[0] = address;
GAT27 0:18ebb7348150 160 tx[1] = num_data;
dmcohen24 10:a89555c4f62a 161 i2c_->write((adrs << 1) & 0xFE, tx, 2);
GAT27 0:18ebb7348150 162 wait_ms(1);
GAT27 1:28beeb2f209b 163 //i2c_->stop();
GAT27 0:18ebb7348150 164 }
GAT27 0:18ebb7348150 165
GAT27 5:3fadc61598bc 166 void SI1143::bias(int ready, int repeat)
GAT27 0:18ebb7348150 167 {
GAT27 5:3fadc61598bc 168 wait(ready);
dmcohen24 8:70933bf445af 169 //bias1 = get_ps1(repeat);
dmcohen24 8:70933bf445af 170 bias1 = 0;
dmcohen24 10:a89555c4f62a 171 bias2 = 0;
GAT27 5:3fadc61598bc 172 bias3 = get_ps3(repeat);
GAT27 0:18ebb7348150 173 }
GAT27 0:18ebb7348150 174
dmcohen24 9:31d4e955ee92 175 int SI1143::get_ps1(int repeat) // Read the data for the first LED (Used in forced mode)
GAT27 0:18ebb7348150 176 {
GAT27 5:3fadc61598bc 177 int stack = 0;
GAT27 5:3fadc61598bc 178
GAT27 0:18ebb7348150 179 command(PSALS_FORCE);
GAT27 0:18ebb7348150 180
GAT27 5:3fadc61598bc 181 for(int r=repeat; r>0; r=r-1)
GAT27 5:3fadc61598bc 182 {
GAT27 5:3fadc61598bc 183 LowB = read_reg(PS1_DATA0,1);
GAT27 5:3fadc61598bc 184 HighB = read_reg(PS1_DATA1,1);
GAT27 5:3fadc61598bc 185 stack = stack + (HighB * 256) + LowB;
GAT27 5:3fadc61598bc 186 }
GAT27 5:3fadc61598bc 187 PS1 = stack / repeat;
GAT27 0:18ebb7348150 188
GAT27 0:18ebb7348150 189 if(PS1 > bias1)
GAT27 0:18ebb7348150 190 PS1 = PS1 - bias1;
GAT27 0:18ebb7348150 191 else
GAT27 0:18ebb7348150 192 PS1 = 0;
GAT27 5:3fadc61598bc 193
GAT27 5:3fadc61598bc 194 return PS1;
GAT27 5:3fadc61598bc 195 }
GAT27 5:3fadc61598bc 196
dmcohen24 9:31d4e955ee92 197 void SI1143::start_ps_auto()
dmcohen24 9:31d4e955ee92 198 {
dmcohen24 9:31d4e955ee92 199 command(PS_AUTO);
dmcohen24 9:31d4e955ee92 200 }
dmcohen24 9:31d4e955ee92 201
dmcohen24 9:31d4e955ee92 202 int SI1143::read_ps1() // Read the data for the first LED (Used in autonomous mode)
dmcohen24 9:31d4e955ee92 203 {
dmcohen24 9:31d4e955ee92 204
dmcohen24 9:31d4e955ee92 205
dmcohen24 9:31d4e955ee92 206 LowB = read_reg(PS1_DATA0,1);
dmcohen24 9:31d4e955ee92 207 HighB = read_reg(PS1_DATA1,1);
dmcohen24 9:31d4e955ee92 208 PS1 = (HighB * 256) + LowB;
dmcohen24 9:31d4e955ee92 209
dmcohen24 9:31d4e955ee92 210 if(PS1 > bias1)
dmcohen24 9:31d4e955ee92 211 PS1 = PS1 - bias1;
dmcohen24 9:31d4e955ee92 212 else
dmcohen24 9:31d4e955ee92 213 PS1 = 0;
dmcohen24 9:31d4e955ee92 214
dmcohen24 9:31d4e955ee92 215 return PS1;
dmcohen24 9:31d4e955ee92 216 }
dmcohen24 9:31d4e955ee92 217
GAT27 5:3fadc61598bc 218 int SI1143::get_ps2(int repeat) // Read the data for the second LED
GAT27 5:3fadc61598bc 219 {
GAT27 5:3fadc61598bc 220 int stack = 0;
GAT27 5:3fadc61598bc 221
GAT27 5:3fadc61598bc 222 command(PSALS_FORCE);
GAT27 5:3fadc61598bc 223
GAT27 5:3fadc61598bc 224 for(int r=repeat; r>0; r=r-1)
GAT27 5:3fadc61598bc 225 {
GAT27 5:3fadc61598bc 226 LowB = read_reg(PS2_DATA0,1);
GAT27 5:3fadc61598bc 227 HighB = read_reg(PS2_DATA1,1);
GAT27 5:3fadc61598bc 228 stack = stack + (HighB * 256) + LowB;
GAT27 5:3fadc61598bc 229 }
GAT27 5:3fadc61598bc 230 PS2 = stack / repeat;
GAT27 5:3fadc61598bc 231
GAT27 0:18ebb7348150 232 if(PS2 > bias2)
GAT27 0:18ebb7348150 233 PS2 = PS2 - bias2;
GAT27 0:18ebb7348150 234 else
GAT27 0:18ebb7348150 235 PS2 = 0;
GAT27 5:3fadc61598bc 236
GAT27 5:3fadc61598bc 237 return PS2;
GAT27 5:3fadc61598bc 238 }
GAT27 5:3fadc61598bc 239
dmcohen24 10:a89555c4f62a 240 int SI1143::read_ps2() // Read the data for the first LED (Used in autonomous mode)
dmcohen24 10:a89555c4f62a 241 {
dmcohen24 10:a89555c4f62a 242
dmcohen24 10:a89555c4f62a 243 LowB = read_reg(PS2_DATA0,1);
dmcohen24 10:a89555c4f62a 244 HighB = read_reg(PS2_DATA1,1);
dmcohen24 10:a89555c4f62a 245 PS2 = (HighB * 256) + LowB;
dmcohen24 10:a89555c4f62a 246
dmcohen24 10:a89555c4f62a 247 if(PS2 > bias2)
dmcohen24 10:a89555c4f62a 248 PS2 = PS2 - bias2;
dmcohen24 10:a89555c4f62a 249 else
dmcohen24 10:a89555c4f62a 250 PS2 = 0;
dmcohen24 10:a89555c4f62a 251
dmcohen24 10:a89555c4f62a 252 return PS2;
dmcohen24 10:a89555c4f62a 253 }
dmcohen24 10:a89555c4f62a 254
GAT27 5:3fadc61598bc 255 int SI1143::get_ps3(int repeat) // Read the data for the third LED
GAT27 5:3fadc61598bc 256 {
GAT27 5:3fadc61598bc 257 int stack = 0;
GAT27 5:3fadc61598bc 258
GAT27 5:3fadc61598bc 259 command(PSALS_FORCE);
GAT27 5:3fadc61598bc 260
GAT27 5:3fadc61598bc 261 for(int r=repeat; r>0; r=r-1)
GAT27 5:3fadc61598bc 262 {
GAT27 5:3fadc61598bc 263 LowB = read_reg(PS3_DATA0,1);
GAT27 5:3fadc61598bc 264 HighB = read_reg(PS3_DATA1,1);
GAT27 5:3fadc61598bc 265 stack = stack + (HighB * 256) + LowB;
GAT27 5:3fadc61598bc 266 }
GAT27 5:3fadc61598bc 267 PS3 = stack / repeat;
GAT27 5:3fadc61598bc 268
GAT27 0:18ebb7348150 269 if(PS3 > bias3)
GAT27 0:18ebb7348150 270 PS3 = PS3 - bias3;
GAT27 0:18ebb7348150 271 else
GAT27 0:18ebb7348150 272 PS3 = 0;
GAT27 0:18ebb7348150 273
GAT27 5:3fadc61598bc 274 return PS3;
GAT27 0:18ebb7348150 275 }
GAT27 2:21381f11a5af 276
GAT27 5:3fadc61598bc 277 int SI1143::get_vis(int repeat) // Read the data for ambient light
GAT27 5:3fadc61598bc 278 {
GAT27 5:3fadc61598bc 279 int stack = 0;
GAT27 5:3fadc61598bc 280
GAT27 5:3fadc61598bc 281 command(PSALS_FORCE);
GAT27 5:3fadc61598bc 282
GAT27 5:3fadc61598bc 283 for(int r=repeat; r>0; r=r-1)
GAT27 5:3fadc61598bc 284 {
GAT27 5:3fadc61598bc 285 LowB = read_reg(ALS_VIS_DATA0,1);
GAT27 5:3fadc61598bc 286 HighB = read_reg(ALS_VIS_DATA1,1);
GAT27 5:3fadc61598bc 287 VIS = stack + (HighB * 256) + LowB;
GAT27 5:3fadc61598bc 288 }
GAT27 5:3fadc61598bc 289 VIS = stack / repeat;
GAT27 5:3fadc61598bc 290
GAT27 5:3fadc61598bc 291 return VIS;
GAT27 5:3fadc61598bc 292 }
GAT27 4:af8f820733e0 293
GAT27 5:3fadc61598bc 294 int SI1143::get_ir(int repeat) // Read the data for infrared light
GAT27 5:3fadc61598bc 295 {
GAT27 5:3fadc61598bc 296 int stack = 0;
GAT27 5:3fadc61598bc 297
GAT27 5:3fadc61598bc 298 command(PSALS_FORCE);
GAT27 5:3fadc61598bc 299
GAT27 5:3fadc61598bc 300 for(int r=repeat; r>0; r=r-1)
GAT27 5:3fadc61598bc 301 {
GAT27 5:3fadc61598bc 302 LowB = read_reg(ALS_IR_DATA0,1);
GAT27 5:3fadc61598bc 303 HighB = read_reg(ALS_IR_DATA1,1);
GAT27 5:3fadc61598bc 304 IR = stack + (HighB * 256) + LowB;
GAT27 5:3fadc61598bc 305 }
GAT27 5:3fadc61598bc 306 IR = stack / repeat;
GAT27 5:3fadc61598bc 307
GAT27 5:3fadc61598bc 308 return IR;
GAT27 5:3fadc61598bc 309 }
dmcohen24 9:31d4e955ee92 310
dmcohen24 9:31d4e955ee92 311 void SI1143::clear_int() // Clear Interrupt register when an interrupt occurs.
dmcohen24 9:31d4e955ee92 312 {
dmcohen24 9:31d4e955ee92 313 write_reg(IRQ_STATUS, 0x3F); // Writes one to every interrupt status, thereby clearing them
dmcohen24 10:a89555c4f62a 314 }
dmcohen24 10:a89555c4f62a 315
dmcohen24 10:a89555c4f62a 316 char SI1143::read_PSint() // Clear Interrupt register when an interrupt occurs.
dmcohen24 10:a89555c4f62a 317 {
dmcohen24 10:a89555c4f62a 318 char tmp;
dmcohen24 10:a89555c4f62a 319 char res;
dmcohen24 10:a89555c4f62a 320
dmcohen24 10:a89555c4f62a 321 DigitalOut led3a(LED3);
dmcohen24 10:a89555c4f62a 322 DigitalOut led4a(LED4);
dmcohen24 10:a89555c4f62a 323
dmcohen24 10:a89555c4f62a 324 tmp = read_reg(IRQ_STATUS, 1); // Reads iterrupt register
dmcohen24 10:a89555c4f62a 325 if( (tmp & 0x0C) == 0x0C ){
dmcohen24 10:a89555c4f62a 326 res = INT_PS12;
dmcohen24 10:a89555c4f62a 327 }
dmcohen24 10:a89555c4f62a 328 else if( (tmp & 0x0C) == 0x04 ){
dmcohen24 10:a89555c4f62a 329 res = INT_PS1;
dmcohen24 10:a89555c4f62a 330 }
dmcohen24 10:a89555c4f62a 331 else if( (tmp & 0x0C) == 0x08 ){
dmcohen24 10:a89555c4f62a 332 res = INT_PS2;
dmcohen24 10:a89555c4f62a 333 }
dmcohen24 10:a89555c4f62a 334 else {
dmcohen24 10:a89555c4f62a 335 res = 0;
dmcohen24 10:a89555c4f62a 336 }
dmcohen24 10:a89555c4f62a 337 return res;
dmcohen24 10:a89555c4f62a 338
dmcohen24 9:31d4e955ee92 339 }