#define F_CPU 8000000
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <avr/io.h>
#include <stdlib.h>
#include <string.h>
#include "logo.h"
#include "i2c.h"
#include "pcd8544.h"
#define LM75_ADDRIN 0b1001000
#define LM75_ADDROUT 0b1001111
#define LM75_REG_TEMP 0x00
unsigned char i,j,x,c,t;
int32_t voltread,v;
unsigned int temp;
char temp_H,temp_L,dst[2]; //I2C stuff buffer.
//////////////////////////////////////////////////////////////////////////////////////////
int i2c_write(char i2c_addr, char reg_addr, unsigned char *dat, char len) //Write data to I2C
{
unsigned char tmp[len+1];
tmp[0] = reg_addr & 0x1F;
memcpy(&tmp[1], dat, len);
return i2c_transaction(i2c_addr, len + 1, tmp, 0, NULL);
}
int i2c_read(char i2c_addr, char reg_addr, unsigned char *dst, char len) //Read data from I2C
{
unsigned char tmp;
tmp = reg_addr & 0x1F;
return i2c_transaction(i2c_addr, 1, &tmp, len, dst);
}
void error(void)
{
LcdStr(1,"ERROR");
_delay_ms(4);
LcdClear();
}
void clearscreen(void)
{
LcdClear();
}
void LcdNumber(unsigned int font_size, char c) {
char str[100];
int a;
itoa(c, (char *)str, 10);
for(a=0; a<strlen(str); a++)
{
LcdChr(1, str[a] );
}
}
void initHW(void)
{
LcdInit();
i2c_init();
// ADC config
//REFS1 REFS0 ADLAR – MUX3 MUX2 MUX1 MUX0
ADMUX = 0b01000000; //AVCC with external capacitor at AREF pin, ADC0= iejimas
//ADEN ADSC ADFR ADIF ADIE ADPS2 ADPS1 ADPS0
ADCSRA = 0b10000111; //ADC Enable, Free Running Select,Prescaler 128
DDRD=225;
MCUCR = 8; //ExtInterrupt0 triggered with external falling edge on INT0
GICR = 128; //Enable ExtInterrupt0 "interruption"
}
int adcread(void) // ADC nuskaitymo funkcija
{
ADCSRA |= (1 << ADSC); // Daroma pirmas nuskaitymas bet neisvedamas
while (ADCSRA & (1 << ADSC)); // Laukiama kol nuskaitys
ADCSRA |= (1 << ADSC); // Daromas nuskaitymas
while (ADCSRA & (1 << ADSC)); // Laukiama kol nuskaitys
return ADC; // Grazinama ADC reiksme (10 bit) nuo 0 iki 1024
}
void showlogo(void)
{
LcdClear();
LcdImage(waitImage);
LcdUpdate();
}
void color(unsigned char color)
{
switch(color)
{
case 0:PORTD=192; break; //Raudona
case 1:PORTD=128; break; //Geltona
case 2:PORTD=160; break; //Zalia
case 3:PORTD=32; break; //Zydra
case 4:PORTD=96; break; //Melyna
case 5:PORTD=64; break; //Violetine
case 6:PORTD=0; break; //Balta
case 7:PORTD=224; break; //OFF
}
}
void drawframe(void)
{
for(i=0;i<9;i++)
{
for(j=0;j<83;j++)
{
LcdPixel(j,i,2);
}
}
for(i=24;i<33;i++)
{
for(j=0;j<83;j++)
{
LcdPixel(j,i,2);
LcdPixel(j,47,2);
}
}
for(i=0;i<48;i++)
{
LcdPixel(0,i,1);
LcdPixel(83,i,1);
}
}
int main(void)
{
initHW();
color(2);
showlogo();
_delay_ms(200);
clearscreen();
sei();
while(1)
{
dst[0]=0;
dst[1]=0;
x = i2c_read(LM75_ADDRIN, LM75_REG_TEMP, &dst[0], 2);
if (x==0)
{
temp_H = dst[0];
temp_L = dst[1];
temp = (temp_H<<8)|temp_L;
temp = temp>>7;
LcdGotoXYFont(1,1);
LcdFStr(1, PSTR(" TEMPERATURE "));
LcdGotoXYFont(1,2);
LcdFStr(1, PSTR(" IN:"));
if(temp&0x100) //tikrinam ar neigiama temp
{
temp=(512-temp)>>1;
LcdFStr(1, PSTR("-"));
LcdNumber(1,temp);
if(temp_L&0x80) //tikrinam kas po kablelio
{
LcdFStr(1, PSTR("."));
LcdNumber(1,5);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
else
{
LcdFStr(1, PSTR("."));
LcdNumber(1,0);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
}
else
{
LcdNumber(1,temp_H);
if(temp_L & 0x80)
{
LcdFStr(1, PSTR("."));
LcdNumber(1,5);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
else
{
LcdFStr(1, PSTR("."));
LcdNumber(1,0);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
}
}
else
{
LcdFStr(FONT_1X, PSTR("ERROR"));
}
for (x=0;x<10;x++)
{
_delay_ms(20);
}
x = i2c_read(LM75_ADDROUT, LM75_REG_TEMP, &dst[0], 2);
if (x==0)
{
LcdGotoXYFont(1,3);
LcdFStr(FONT_1X, PSTR(" OUT:"));
temp_H = dst[0];
temp_L = dst[1];
temp = (temp_H<<8)|temp_L;
temp = temp>>7;
if(temp&0x100)
{
temp=(512-temp)>>1;
LcdFStr(1, PSTR("-"));
LcdNumber(1,temp);
if(temp_L&0x80)
{
LcdFStr(1, PSTR("."));
LcdNumber(1,5);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
else
{
LcdFStr(1, PSTR("."));
LcdNumber(1,0);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
}
else
{
LcdNumber(1,temp_H);
if(temp_L & 0x80)
{
LcdFStr(1, PSTR("."));
LcdNumber(1,5);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
else
{
LcdFStr(1, PSTR("."));
LcdNumber(1,0);
LcdChr(1, 0x7B);
LcdFStr(1, PSTR("C"));
}
}
}
else
{
LcdFStr(FONT_1X, PSTR("i2c_error"));
}
for (x=0;x<10;x++)
{
_delay_ms(20);
}
LcdGotoXYFont(1,4);
LcdFStr(FONT_1X, PSTR(" BATTERY "));
voltread = adcread();
voltread = (voltread*2000)/1023;
if(voltread<1000)
{
LcdGotoXYFont(2,5);
LcdNumber(1,voltread/100);
LcdFStr(FONT_1X, PSTR("."));
LcdNumber(1,voltread/10%10);
LcdNumber(1,voltread%10);
LcdFStr(FONT_1X, PSTR("V"));
}
else
{
LcdGotoXYFont(2,5);
LcdNumber(1,voltread/1000);
LcdNumber(1,voltread/100%10);
LcdFStr(FONT_1X, PSTR("."));
LcdNumber(1,voltread/10%10);
LcdNumber(1,voltread%10);
LcdFStr(FONT_1X, PSTR("V"));
}
//LcdGotoXYFont(2,5);
//LcdNumber(1,voltread/100);
//LcdFStr(FONT_1X, PSTR("."));
//LcdNumber(1,voltread/10%10);
//LcdNumber(1,voltread%10);
//LcdFStr(FONT_1X, PSTR("V"));
drawframe();
LcdUpdate();
_delay_ms(50);
clearscreen();
}
return 0;
}
ISR(INT1_vect)
{
cli();
_delay_ms(50);
while(!(PIND&PD5)){}
color(c);
c++;
c %= 8;
sei();
}
I2RlZmluZSAgICAgRl9DUFUgODAwMDAwMAoKCiNpbmNsdWRlIDxhdnIvaW50ZXJydXB0Lmg+CiNpbmNsdWRlIDxhdnIvcGdtc3BhY2UuaD4KI2luY2x1ZGUgPHV0aWwvZGVsYXkuaD4KI2luY2x1ZGUgPGF2ci9pby5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgImxvZ28uaCIKCiNpbmNsdWRlICJpMmMuaCIKI2luY2x1ZGUgInBjZDg1NDQuaCIKCiNkZWZpbmUgTE03NV9BRERSSU4gMGIxMDAxMDAwCiNkZWZpbmUgTE03NV9BRERST1VUIDBiMTAwMTExMQojZGVmaW5lIExNNzVfUkVHX1RFTVAJCTB4MDAKCgoKdW5zaWduZWQgY2hhciBpLGoseCxjLHQ7CmludDMyX3Qgdm9sdHJlYWQsdjsKdW5zaWduZWQgaW50IHRlbXA7CmNoYXIgdGVtcF9ILHRlbXBfTCxkc3RbMl07IC8vSTJDIHN0dWZmIGJ1ZmZlci4KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKCgppbnQgaTJjX3dyaXRlKGNoYXIgaTJjX2FkZHIsIGNoYXIgcmVnX2FkZHIsIHVuc2lnbmVkIGNoYXIgKmRhdCwgY2hhciBsZW4pIC8vV3JpdGUgZGF0YSB0byBJMkMKewoJdW5zaWduZWQgY2hhciB0bXBbbGVuKzFdOwoJdG1wWzBdID0gcmVnX2FkZHIgJiAweDFGOwoJbWVtY3B5KCZ0bXBbMV0sIGRhdCwgbGVuKTsKCXJldHVybiBpMmNfdHJhbnNhY3Rpb24oaTJjX2FkZHIsIGxlbiArIDEsIHRtcCwgMCwgTlVMTCk7Cn0KCmludCBpMmNfcmVhZChjaGFyIGkyY19hZGRyLCBjaGFyIHJlZ19hZGRyLCB1bnNpZ25lZCBjaGFyICpkc3QsIGNoYXIgbGVuKSAvL1JlYWQgZGF0YSBmcm9tIEkyQwp7Cgl1bnNpZ25lZCBjaGFyIHRtcDsKCXRtcCA9IHJlZ19hZGRyICYgMHgxRjsKCXJldHVybiBpMmNfdHJhbnNhY3Rpb24oaTJjX2FkZHIsIDEsICZ0bXAsIGxlbiwgZHN0KTsKfQoKCgoKdm9pZCBlcnJvcih2b2lkKQp7CglMY2RTdHIoMSwiRVJST1IiKTsKCV9kZWxheV9tcyg0KTsKCUxjZENsZWFyKCk7Cgp9CgoKCnZvaWQgY2xlYXJzY3JlZW4odm9pZCkKewoJTGNkQ2xlYXIoKTsKfQoKCgp2b2lkIExjZE51bWJlcih1bnNpZ25lZCBpbnQgZm9udF9zaXplLCBjaGFyIGMpIHsKCWNoYXIgc3RyWzEwMF07CglpbnQgYTsKCWl0b2EoYywgKGNoYXIgKilzdHIsIDEwKTsKCWZvcihhPTA7IGE8c3RybGVuKHN0cik7IGErKykKCXsKCQlMY2RDaHIoMSwgc3RyW2FdICk7Cgl9Cn0KCgoKdm9pZCBpbml0SFcodm9pZCkKewoJTGNkSW5pdCgpOwoJaTJjX2luaXQoKTsKCS8vIEFEQyBjb25maWcKCS8vUkVGUzEgUkVGUzAgQURMQVIg4oCTIE1VWDMgTVVYMiBNVVgxIE1VWDAKCUFETVVYID0gMGIwMTAwMDAwMDsgLy9BVkNDIHdpdGggZXh0ZXJuYWwgY2FwYWNpdG9yIGF0IEFSRUYgcGluLCBBREMwPSBpZWppbWFzCgkvL0FERU4gQURTQyBBREZSIEFESUYgQURJRSBBRFBTMiBBRFBTMSBBRFBTMAoJQURDU1JBID0gMGIxMDAwMDExMTsgLy9BREMgRW5hYmxlLCBGcmVlIFJ1bm5pbmcgU2VsZWN0LFByZXNjYWxlciAxMjgKCUREUkQ9MjI1OwoKCglNQ1VDUiA9IDg7IC8vRXh0SW50ZXJydXB0MCB0cmlnZ2VyZWQgd2l0aCBleHRlcm5hbCBmYWxsaW5nIGVkZ2Ugb24gSU5UMAoJR0lDUiA9IDEyODsgLy9FbmFibGUgRXh0SW50ZXJydXB0MCAiaW50ZXJydXB0aW9uIgoKfQoKCmludCBhZGNyZWFkKHZvaWQpICAgICAgICAgICAgICAgICAgICAgICAvLyBBREMgbnVza2FpdHltbyBmdW5rY2lqYQp7CglBRENTUkEgfD0gKDEgPDwgQURTQyk7ICAgICAgICAgICAgICAgICAvLyBEYXJvbWEgcGlybWFzIG51c2thaXR5bWFzIGJldCBuZWlzdmVkYW1hcwoJd2hpbGUgKEFEQ1NSQSAmICgxIDw8IEFEU0MpKTsgICAgICAgICAgLy8gTGF1a2lhbWEga29sIG51c2thaXR5cwoJQURDU1JBIHw9ICgxIDw8IEFEU0MpOyAgICAgICAgICAgICAgICAgLy8gRGFyb21hcyBudXNrYWl0eW1hcwoJd2hpbGUgKEFEQ1NSQSAmICgxIDw8IEFEU0MpKTsgICAgICAgICAgLy8gTGF1a2lhbWEga29sIG51c2thaXR5cwoJcmV0dXJuIEFEQzsgICAgIAkJCSAgICAgICAgICAgIC8vIEdyYXppbmFtYSBBREMgcmVpa3NtZSAoMTAgYml0KSBudW8gMCBpa2kgMTAyNAp9CgoKCnZvaWQgc2hvd2xvZ28odm9pZCkKewoJTGNkQ2xlYXIoKTsKCUxjZEltYWdlKHdhaXRJbWFnZSk7CglMY2RVcGRhdGUoKTsKfQoKdm9pZCBjb2xvcih1bnNpZ25lZCBjaGFyIGNvbG9yKQp7Cglzd2l0Y2goY29sb3IpCgl7CgkJY2FzZSAwOlBPUlREPTE5MjsgYnJlYWs7IC8vUmF1ZG9uYQoJCWNhc2UgMTpQT1JURD0xMjg7IGJyZWFrOyAvL0dlbHRvbmEKCQljYXNlIDI6UE9SVEQ9MTYwOyBicmVhazsgLy9aYWxpYQoJCWNhc2UgMzpQT1JURD0zMjsgIGJyZWFrOyAvL1p5ZHJhCgkJY2FzZSA0OlBPUlREPTk2OyAgYnJlYWs7IC8vTWVseW5hCgkJY2FzZSA1OlBPUlREPTY0OyAgYnJlYWs7IC8vVmlvbGV0aW5lCgkJY2FzZSA2OlBPUlREPTA7ICAgYnJlYWs7IC8vQmFsdGEKCQljYXNlIDc6UE9SVEQ9MjI0OyBicmVhazsgLy9PRkYKCX0KfQoKdm9pZCBkcmF3ZnJhbWUodm9pZCkKewoJZm9yKGk9MDtpPDk7aSsrKQoJewoJCWZvcihqPTA7ajw4MztqKyspCgkJewoJCQlMY2RQaXhlbChqLGksMik7CgkJfQoJfQoKCWZvcihpPTI0O2k8MzM7aSsrKQoJewoJCWZvcihqPTA7ajw4MztqKyspCgkJewoJCQlMY2RQaXhlbChqLGksMik7CgkJCUxjZFBpeGVsKGosNDcsMik7CgkJfQoJfQoKCWZvcihpPTA7aTw0ODtpKyspCgl7CgkJTGNkUGl4ZWwoMCxpLDEpOwoJCUxjZFBpeGVsKDgzLGksMSk7Cgl9Cn0KCgppbnQgbWFpbih2b2lkKQp7Cglpbml0SFcoKTsKCWNvbG9yKDIpOwoJc2hvd2xvZ28oKTsKCV9kZWxheV9tcygyMDApOwoJY2xlYXJzY3JlZW4oKTsKCglzZWkoKTsKCgoJd2hpbGUoMSkKCXsKCQlkc3RbMF09MDsKCQlkc3RbMV09MDsKCQl4ID0gaTJjX3JlYWQoTE03NV9BRERSSU4sIExNNzVfUkVHX1RFTVAsICZkc3RbMF0sIDIpOwoJCWlmICh4PT0wKQoJCXsKCQkJdGVtcF9IID0gZHN0WzBdOwoJCQl0ZW1wX0wgPSBkc3RbMV07CgkJCXRlbXAgPSAodGVtcF9IPDw4KXx0ZW1wX0w7CgkJCXRlbXAgPSB0ZW1wPj43OwoJCQlMY2RHb3RvWFlGb250KDEsMSk7CgkJCUxjZEZTdHIoMSwgUFNUUigiIFRFTVBFUkFUVVJFICAiKSk7CgkJCUxjZEdvdG9YWUZvbnQoMSwyKTsKCQkJTGNkRlN0cigxLCBQU1RSKCIgIElOOiIpKTsKCQkJaWYodGVtcCYweDEwMCkgICAgICAgICAgICAgICAvL3Rpa3JpbmFtIGFyIG5laWdpYW1hIHRlbXAKCQkJewoJCQkJdGVtcD0oNTEyLXRlbXApPj4xOwoJCQkJTGNkRlN0cigxLCBQU1RSKCItIikpOwoJCQkJTGNkTnVtYmVyKDEsdGVtcCk7CgkJCQlpZih0ZW1wX0wmMHg4MCkgICAgICAgICAgLy90aWtyaW5hbSBrYXMgcG8ga2FibGVsaW8KCQkJCXsKCQkJCQlMY2RGU3RyKDEsIFBTVFIoIi4iKSk7CgkJCQkJTGNkTnVtYmVyKDEsNSk7CgkJCQkJTGNkQ2hyKDEsIDB4N0IpOwoJCQkJCUxjZEZTdHIoMSwgUFNUUigiQyIpKTsKCQkJCX0KCQkJCWVsc2UKCQkJCXsKCQkJCQlMY2RGU3RyKDEsIFBTVFIoIi4iKSk7CgkJCQkJTGNkTnVtYmVyKDEsMCk7CgkJCQkJTGNkQ2hyKDEsIDB4N0IpOwoJCQkJCUxjZEZTdHIoMSwgUFNUUigiQyIpKTsKCQkJCX0KCQkJfQoJCQllbHNlCgkJCXsKCQkJCUxjZE51bWJlcigxLHRlbXBfSCk7CgkJCQlpZih0ZW1wX0wgJiAweDgwKQoJCQkJewoJCQkJCUxjZEZTdHIoMSwgUFNUUigiLiIpKTsKCQkJCQlMY2ROdW1iZXIoMSw1KTsKCQkJCQlMY2RDaHIoMSwgMHg3Qik7CgkJCQkJTGNkRlN0cigxLCBQU1RSKCJDIikpOwoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCUxjZEZTdHIoMSwgUFNUUigiLiIpKTsKCQkJCQlMY2ROdW1iZXIoMSwwKTsKCQkJCQlMY2RDaHIoMSwgMHg3Qik7CgkJCQkJTGNkRlN0cigxLCBQU1RSKCJDIikpOwoJCQkJfQoJCQl9CgkJfQoJCWVsc2UKCQl7CgkJCUxjZEZTdHIoRk9OVF8xWCwgUFNUUigiRVJST1IiKSk7CgkJfQoJCWZvciAoeD0wO3g8MTA7eCsrKQoJCXsKCQkJX2RlbGF5X21zKDIwKTsKCQl9CgoKCQl4ID0gaTJjX3JlYWQoTE03NV9BRERST1VULCBMTTc1X1JFR19URU1QLCAmZHN0WzBdLCAyKTsKCQlpZiAoeD09MCkKCQl7CgkJCUxjZEdvdG9YWUZvbnQoMSwzKTsKCQkJTGNkRlN0cihGT05UXzFYLCBQU1RSKCIgT1VUOiIpKTsKCQkJdGVtcF9IID0gZHN0WzBdOwoJCQl0ZW1wX0wgPSBkc3RbMV07CgkJCXRlbXAgPSAodGVtcF9IPDw4KXx0ZW1wX0w7CgkJCXRlbXAgPSB0ZW1wPj43OwoJCQlpZih0ZW1wJjB4MTAwKQoJCQl7CgkJCQl0ZW1wPSg1MTItdGVtcCk+PjE7CgkJCQlMY2RGU3RyKDEsIFBTVFIoIi0iKSk7CgkJCQlMY2ROdW1iZXIoMSx0ZW1wKTsKCQkJCWlmKHRlbXBfTCYweDgwKQoJCQkJewoJCQkJCUxjZEZTdHIoMSwgUFNUUigiLiIpKTsKCQkJCQlMY2ROdW1iZXIoMSw1KTsKCQkJCQlMY2RDaHIoMSwgMHg3Qik7CgkJCQkJTGNkRlN0cigxLCBQU1RSKCJDIikpOwoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCUxjZEZTdHIoMSwgUFNUUigiLiIpKTsKCQkJCQlMY2ROdW1iZXIoMSwwKTsKCQkJCQlMY2RDaHIoMSwgMHg3Qik7CgkJCQkJTGNkRlN0cigxLCBQU1RSKCJDIikpOwoJCQkJfQoJCQl9CgkJCWVsc2UKCQkJewoJCQkJTGNkTnVtYmVyKDEsdGVtcF9IKTsKCQkJCWlmKHRlbXBfTCAmIDB4ODApCgkJCQl7CgkJCQkJTGNkRlN0cigxLCBQU1RSKCIuIikpOwoJCQkJCUxjZE51bWJlcigxLDUpOwoJCQkJCUxjZENocigxLCAweDdCKTsKCQkJCQlMY2RGU3RyKDEsIFBTVFIoIkMiKSk7CgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJTGNkRlN0cigxLCBQU1RSKCIuIikpOwoJCQkJCUxjZE51bWJlcigxLDApOwoJCQkJCUxjZENocigxLCAweDdCKTsKCQkJCQlMY2RGU3RyKDEsIFBTVFIoIkMiKSk7CgkJCQl9CgkJCX0KCQl9CgkJZWxzZQoJCXsKCQkJTGNkRlN0cihGT05UXzFYLCBQU1RSKCJpMmNfZXJyb3IiKSk7CgkJfQoJCWZvciAoeD0wO3g8MTA7eCsrKQoJCXsKCQkJX2RlbGF5X21zKDIwKTsKCQl9CgkJTGNkR290b1hZRm9udCgxLDQpOwoJCUxjZEZTdHIoRk9OVF8xWCwgUFNUUigiICAgQkFUVEVSWSAgICAiKSk7CgoJCXZvbHRyZWFkID0gYWRjcmVhZCgpOwoJCXZvbHRyZWFkID0gKHZvbHRyZWFkKjIwMDApLzEwMjM7CgoKCQlpZih2b2x0cmVhZDwxMDAwKQoJCXsKCQkJTGNkR290b1hZRm9udCgyLDUpOwoJCQlMY2ROdW1iZXIoMSx2b2x0cmVhZC8xMDApOwoJCQlMY2RGU3RyKEZPTlRfMVgsIFBTVFIoIi4iKSk7CgkJCUxjZE51bWJlcigxLHZvbHRyZWFkLzEwJTEwKTsKCQkJTGNkTnVtYmVyKDEsdm9sdHJlYWQlMTApOwoJCQlMY2RGU3RyKEZPTlRfMVgsIFBTVFIoIlYiKSk7CgkJfQoJCWVsc2UKCQl7CgkJCUxjZEdvdG9YWUZvbnQoMiw1KTsKCQkJTGNkTnVtYmVyKDEsdm9sdHJlYWQvMTAwMCk7CgkJCUxjZE51bWJlcigxLHZvbHRyZWFkLzEwMCUxMCk7CgkJCUxjZEZTdHIoRk9OVF8xWCwgUFNUUigiLiIpKTsKCQkJTGNkTnVtYmVyKDEsdm9sdHJlYWQvMTAlMTApOwoJCQlMY2ROdW1iZXIoMSx2b2x0cmVhZCUxMCk7CgkJCUxjZEZTdHIoRk9OVF8xWCwgUFNUUigiViIpKTsKCQl9CgkJLy9MY2RHb3RvWFlGb250KDIsNSk7CgkJLy9MY2ROdW1iZXIoMSx2b2x0cmVhZC8xMDApOwoJCS8vTGNkRlN0cihGT05UXzFYLCBQU1RSKCIuIikpOwoJCS8vTGNkTnVtYmVyKDEsdm9sdHJlYWQvMTAlMTApOwoJCS8vTGNkTnVtYmVyKDEsdm9sdHJlYWQlMTApOwoJCS8vTGNkRlN0cihGT05UXzFYLCBQU1RSKCJWIikpOwoKCQlkcmF3ZnJhbWUoKTsKCQlMY2RVcGRhdGUoKTsKCQlfZGVsYXlfbXMoNTApOwoJCWNsZWFyc2NyZWVuKCk7Cgl9CglyZXR1cm4gMDsKfQoKCklTUihJTlQxX3ZlY3QpCnsKCWNsaSgpOwoJX2RlbGF5X21zKDUwKTsKd2hpbGUoIShQSU5EJlBENSkpe30KY29sb3IoYyk7CmMrKzsKYyAlPSA4OwpzZWkoKTsKfQoK