Avisos
Vaciar todo

Nanocom fabricado en casa

89 Respuestas
27 Usuarios
0 Reacciones
12.5 K Visitas
(@garmen)
Maestro LandRovero Socio
Registrado: hace 15 años
Respuestas: 2099
Iniciador del debate  

Buenos días caballeros,

Al no haber subforo de guerra electrónica, lo posteo aquí.

Estoy haciéndome una copia del Nanocom, utilizando un Arduino Mega 2560, he conseguido que me funcione, pero me faltan bastantes opciones.

He utilizado el Arduino Mega 2650, y un lector de tarjetas SD, para guardar en este la tabla para poder autentificarse ante la ECU. La pantalla es una gráfica 128x64

He aquí el vídeo:

www.youtube.com/watch?v=0-HRKtRTEmw

Y aquí el código fuente, provisional, sin comentar y sin pulir:

/*
Rx connected to pin 4
Tx connected to pin 5, it is inverted, driving a transistor
bit wide is 96,15 microseconds @10400kbs

 */

byte rx=5;
byte tx=4;
unsigned long time,time2;
byte bool1=0;
int int1=0;
byte i, tosend, k;
byte arraya[150];
byte temp1;
int RPM, coolant;
float print_glcd;

#include 
#include 

#include 
#include 

File myFile;

byte init1[] = {0x81, 0x13, 0xF7, 0x81, 0x0C};
byte init2[] = {0x02, 0x10, 0xA0, 0xB2};
byte init_seed_req[] = {0x02, 0x27, 0x01, 0x2A};
byte fuelling_req[] = {0x02, 0x21, 0x02, 0x43};
byte rpm_req[] = {0x02, 0x21, 0x09, 0x2C};
byte speed_req[] = {0x02, 0x21, 0x0D, 0x30};
byte temp_req[] = {0x02, 0x21, 0x1A, 0x3D};

 int displayInt;






byte response[50];

void print_intro()
{
  GLCD.ClearScreen();
  GLCD.SelectFont(Cooper19);
  
  GLCD.CursorToXY(1,2);
  GLCD.print("GarmenCom"); 
  
  GLCD.SelectFont(System5x7);
  GLCD.CursorToXY(2,20);
  GLCD.print("Rev 0.02 ");
  GLCD.println("2015-08-25");
}

void setup()  
{
  GLCD.Init();
  print_intro();
  
  pinMode(16,OUTPUT);
   
  digitalWrite(16, HIGH);    //Start signal
  
  // Open serial communications and wait for port to open:
  Serial.begin(57600);
  
  if (!SD.begin(53)) {
    Serial.println("SD initialization failed!");
    GLCD.println("SD Init FAIL");
  }
  else
  {
    Serial.println("SD initialization done.");
    GLCD.println("SD Init OK");
  }

  Serial.println("GarmenCom V.0.01!");
  
  time=micros();
  

  // set the data rate for the SoftwareSerial port
  //mySerial.println("Hello, world?");
}
void sniff()
{
  while (true)
  {
  
  if (Serial3.available() > 0) {
                    
		// read the incoming byte:
                tosend = Serial3.read();

                // say what you got:
                if (tosend<16)
		{
		  Serial.print(0);
		}
		Serial.print(tosend,HEX);
		Serial.print(" ");
		time=micros();
  }
  
  }
  
}

void get_ans(byte *received, byte ignore, byte ans_size)
{
  byte count=0,count2=0;
  byte first_round=1;
  Serial.println();
  Serial.print("Sent: ");
  
  while (count 0) {
                
		
		// read the incoming byte:
                temp1 = Serial2.read();
		
		
                // say what you got:
		if (count>=(ignore))
		{
		  if (first_round)
		  {
		    first_round=0;
		    Serial.println();
		    Serial.print("Received: ");
		  }
		  received[count2]=temp1;
		  if (temp1<16)
		  {
		    Serial.print(0);
		  }
		  Serial.print(temp1,HEX);
		  Serial.print(" ");
		  count2++;
		}
		
		else
		{
		  if (temp1<16)
		  {
		    Serial.print(0);
		  }
		  Serial.print(temp1,HEX);
		  Serial.print(" ");		  
		}
		
		count++;
   }
   }
   
  
}

void get_ans_silent(byte *received, byte ignore, byte ans_size)
{
  byte count=0,count2=0;
  byte first_round=1;
  //Serial.println();
  //Serial.print("Sent: ");
  
  while (count 0) {
                
		
		// read the incoming byte:
                temp1 = Serial2.read();
		
		
                // say what you got:
		if (count>=(ignore))
		{
		  if (first_round)
		  {
		    first_round=0;
		    //Serial.println();
		    //Serial.print("Received: ");
		  }
		  received[count2]=temp1;
		  if (temp1<16)
		  {
		    //Serial.print(0);
		  }
		  //Serial.print(temp1,HEX);
		  //Serial.print(" ");
		  count2++;
		}
		
		else
		{
		  if (temp1<16)
		  {
		    //Serial.print(0);
		  }
		  //Serial.print(temp1,HEX);
		  //Serial.print(" ");		  
		}
		
		count++;
   }
   }
   
  
}

void init_frame()
{
   long temp1,temp2,temp3,temp4,temp5,modulo;
   uint16_t seed, seed_answer;
   
   digitalWrite(16, HIGH);    //Start signal
   delay(1000);              
   digitalWrite(16, LOW);    
   delay(25);
   digitalWrite(16, HIGH);    
   delay(150); 
   
   Serial.println("Initializing...");
   GLCD.println("Initing...");
   
   Serial2.begin(10400);
   
   delay(25); 
   Serial2.write(init1, sizeof(init1));
   
   int x=0;
   
   get_ans(response,5,5);
   
   delay(10);
   
   Serial2.write(init2, sizeof(init2));
   
   get_ans(response,4,3);
   
   delay(10);
   
   Serial2.write(init_seed_req, sizeof(init_seed_req));
   
   get_ans(response,4,6);
   
   seed=response[3];
   seed=seed*256;
   seed=seed+response[4];
   
   Serial.println();
   Serial.print("Seed is: ");
   
   Serial.println(seed,HEX);
   
   GLCD.print("Seed is: ");
   GLCD.println(seed,HEX);
   
   long k=0;
   // re-open the file for reading:
  myFile = SD.open("key.txt");
  if (myFile) {
   
    // read from the file until there's nothing else in it:
    while (k<=seed) {
        temp1=myFile.read();
	temp2=myFile.read();
	temp3=myFile.read();
	temp4=myFile.read();
	temp5=myFile.read();
	k++;
	
    }
    
    

    // close the file:
    myFile.close();
    
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening key.txt");
    GLCD.println("error opening key.txt");
  }
   
   Serial.print("Seed answer is: ");
   
   Serial.write(temp1);
   Serial.write(temp2);
   Serial.write(temp3);
   Serial.write(temp4);
   
   Serial2.write(0x04);
   Serial2.write(0x27);
   Serial2.write(0x02);
   
   if (temp1<60)
     temp1=temp1-48;
   else
     temp1=temp1-55;
   
   if (temp2<60)
     temp2=temp2-48;
   else
     temp2=temp2-55;
   
   if (temp3<60)
     temp3=temp3-48;
   else
     temp3=temp3-55;
   
   if (temp4<60)
     temp4=temp4-48;
   else
     temp4=temp4-55;
   
   Serial2.write( (temp1 * 16) + temp2 );
    
   Serial2.write( (temp3 * 16) + temp4 );
   
   modulo = (0x04 + 0x27 + 0x02 + ( (temp1 * 16) + temp2 ) + ( (temp3 * 16) + temp4 ) )%256;
   
   Serial2.write(modulo);
   
   get_ans(response,6,4);
   
   if (response[0]==0x02 && response[1]==0x67 && response[2]==0x02 && response[3]==0x6B)
   {
     Serial.println("Authentification OK!");
     GLCD.println("Auth OK!");
     delay(250);
   }
   else
   {
     Serial.println("Auth FAIL!");
     delay(1000);
   }
   
   
   /*displayInt = pgm_read_word_near(seed_table1+20);
   displayInt = pgm_read_word_near(seed_table2);
   displayInt = pgm_read_word_near(seed_table3);
   displayInt = pgm_read_word_near(seed_table4);
   displayInt = pgm_read_word_near(seed_table5);
   displayInt = pgm_read_word_near(seed_table6);
   displayInt = pgm_read_word_near(seed_table7);
   displayInt = pgm_read_word_near(seed_table8);
   
    Serial.println(displayInt);*/
   //Serial.println(seed_table[seed],HEX);
   
   x=0;
   
  
}


void loop() // run over and over
{
  
  
  
  init_frame();  
  
  delay(10);
  
  GLCD.ClearScreen();
  
  GLCD.SelectFont(Cooper19);
  GLCD.CursorToXY(10,10);
  GLCD.EraseTextLine();
  GLCD.print("RPM: ");
  GLCD.print(RPM);
  
  //Serial2.write(fuelling_req, sizeof(fuelling_req));
   
  //get_ans(response,4,8);
  
  while (true)
  {
    delay(50);
      
    Serial2.write(rpm_req, sizeof(rpm_req));
   
    get_ans_silent(response,4,6);
    
    RPM = response[3];
    RPM = RPM*256;
    RPM = RPM+response[4];
    
    Serial.print("RPM: ");
    Serial.println(RPM);
    GLCD.CursorToXY(10,10);
    GLCD.EraseTextLine();
    GLCD.print("RPM: ");
    GLCD.println(RPM);
    
    delay(50);
    
    /*
    Serial2.write(speed_req, sizeof(speed_req));
   
    get_ans(response,4,5);
    
    
    Serial.print("Km/h: ");
    Serial.print(response[3]);   
    GLCD.CursorToXY(10,30);
    GLCD.EraseTextLine();
    GLCD.print("Km/h: ");
    GLCD.print(response[3]);
    */
    
    Serial2.write(temp_req, sizeof(temp_req));
   
    get_ans(response,4,20);
    
    coolant = response[3];
    coolant = coolant*256;
    coolant = coolant+response[4];
    coolant=coolant;
    
    GLCD.CursorToXY(10,30);
    GLCD.EraseTextLine();
    print_glcd=coolant;
    GLCD.print("T1: ");
    GLCD.print((print_glcd/10)-272.7);
    
    Serial.print("T1: ");
    Serial.println(coolant);
    
    coolant = response[7];
    coolant = coolant*256;
    coolant = coolant+response[8];
    coolant=coolant;
    
    Serial.print("T2: ");
    Serial.println(coolant);
    
    coolant = response[11];
    coolant = coolant*256;
    coolant = coolant+response[12];
    coolant=coolant;
    
    Serial.print("T3: ");
    Serial.println(coolant);
    
    coolant = response[15];
    coolant = coolant*256;
    coolant = coolant+response[16];
    coolant=coolant;
    
    Serial.print("T4: ");
    Serial.println(coolant);
    

    
  }
  
  
}

Aquí el zip con el código y el archivo key.txt:
http://www.mediafire.com/download/h54wp2n1wfhh5ch/GarmenCom.zip



   
Citar
(@saltamontes)
Dr. LandRovero Socio
Registrado: hace 21 años
Respuestas: 5187
 

Buenas tardes, eres una makina !!!!! No se de donde sacas el tiempo jeje siempre estás liado



   
ResponderCitar
(@salvaje)
Dr. H. C. LR Socio
Registrado: hace 22 años
Respuestas: 19378
 

Vaya tela...



   
ResponderCitar
(@RXquattro)
Registrado: hace 13 años
Respuestas: 358
 

Esto les va a interesar a @nanotec y @griyao 😀



   
ResponderCitar
(@griyao)
Iniciado en LR Socio
Registrado: hace 13 años
Respuestas: 318
 

datos, datos, mas datos, quiero info que me hare uno igual o peor.....



   
ResponderCitar
(@griyao)
Iniciado en LR Socio
Registrado: hace 13 años
Respuestas: 318
 

le he estado hechando un vistazo al codigo, interesante, bastante interesante, asi que si puedes pasarme la info que tengas, conjugandola con la que tengo yo podemos ahorrarnos una pasta.....



   
ResponderCitar
(@garmen)
Maestro LandRovero Socio
Registrado: hace 15 años
Respuestas: 2099
Iniciador del debate  

Griyao,

Aquí tienes todo lo que tengo del tema:

Incluso tienes el programa que hizo Luca, para hacer esto mismo, aunque yo he seguido otro camino para hacer lo mismo.

Mañana mas y mejor



   
ResponderCitar
(@garmen)
Maestro LandRovero Socio
Registrado: hace 15 años
Respuestas: 2099
Iniciador del debate  

Griyao, mirate el programa de Luca, está bien, pero haría que documentarlo y clarificarlo un poco, digo yo.



   
ResponderCitar
(@nanotec)
Registrado: hace 13 años
Respuestas: 187
 

Esto les va a interesar a @nanotec y @griyao 😀

"pues no entiendo por qué, si yo no estoy interesado en ningún P38".
Ups!
;D



   
ResponderCitar
(@griyao)
Iniciado en LR Socio
Registrado: hace 13 años
Respuestas: 318
 

le he estado hechando un vistazo y es un poco lioso,  ver si puedo montarlo en un rato y veo resultdos en general, pero es muy interesante .....



   
ResponderCitar
(@Disco_300)
Registrado: hace 11 años
Respuestas: 1052
 

Buff madre mia no se como haceis esos inventos cada dia me sorprendo mas de la informacion i gente con muchos conocimientos i experiencias que hay en este foro



   
ResponderCitar
(@xiscorp)
Iniciado en LR Registered
Registrado: hace 13 años
Respuestas: 521
 

Nivelazo que hay por el Foro.

Siendo la base un Arduino supongo que sería una grandísima idea añadirle un BT y poder manejarlo/visualizarlo todo desde un Android.

Uno de los problemas que le veo a mi Nanocom (que por otro lado me encanta y ya me ha salvado el culo a mí y a varios compis suficientes veces como para considerarlo amortizado!), es que en modo cuadro de mandos, no te deja organizar los datos a visualizar, y tiene separados algunos que yo considero interesantes verlos a la vez.

Grandísimo proyecto!
Me lo pongo para recibir actualizaciones del mismo.



   
ResponderCitar
(@griyao)
Iniciado en LR Socio
Registrado: hace 13 años
Respuestas: 318
 

estoy dandole vueltas al codigo y...

tanto puerto serie abierto, supongo que sera uno para leer por la linea k, otro para la pantalla aunque tambien utilizas los bit de datos, por lo que no lo entiendo y el tercero tambien para leer, ya me has dejado hundido, podrias comentar las lineas un poco mas??????, a ver si lo modifico un poco que yo no tengo la misma pantalla que tu, y asi poder verlo.



   
ResponderCitar
(@garmen)
Maestro LandRovero Socio
Registrado: hace 15 años
Respuestas: 2099
Iniciador del debate  

Griyao, el codigo estaba sin limpiar.

Aquí el 0.03 un poquito mas limpio.

El puerto Serial se utiliza para comunicarse con el PC.
El puerto Serial2 para comunicarse con la ECU.

/*
GarmenCom Ver 0.03
by EA2EGA

This sketch is designed to be used on a Arduino MEGA 2560

Serial Port 2 must be wired in this way:

K-line      12 Volt   5 Volt           Serial2.RX    Serial2.TX
  |           |           |                 |            |
  |--2K2------|           |   (Reduce       |            |
  |                       |   signal        |            |
  |--22K--------1N1484->--|   to 0-5 Volt)  |            |
  |        |                                |            |
  |        |----------2K2-------------------|            |
  |                                                      |
  |                                                      |
  |     2N2222A              (Invert again and Power)    |
  |     C  B  E                                          |
  |     |  |  |-------GND                                |
  |------  |                                             |
           |                                             |
           |--------|                                    |
                    |                                    |
       5 Volt       |  2N2222A      (Inverter)           |
          |-----2K2----C  B  E                           |
                          |  |----- GND                  |
                          |                              |
                          |------------------2K2---------|



 */

unsigned long time,time2;
byte bool1=0;
int int1=0;
byte i, tosend, k;
byte arraya[150];
byte temp1;
int RPM, coolant;
float print_glcd;

#include 
#include 

#include 
#include 

File myFile;

/* Codes to get the params from the ECU
 * 
 */

byte init1[] = {0x81, 0x13, 0xF7, 0x81, 0x0C};
byte init2[] = {0x02, 0x10, 0xA0, 0xB2};
byte init_seed_req[] = {0x02, 0x27, 0x01, 0x2A};
byte fuelling_req[] = {0x02, 0x21, 0x02, 0x43};
byte rpm_req[] = {0x02, 0x21, 0x09, 0x2C};
byte speed_req[] = {0x02, 0x21, 0x0D, 0x30};
byte temp_req[] = {0x02, 0x21, 0x1A, 0x3D};

 int displayInt;






byte response[50];

void print_intro()
{
  GLCD.ClearScreen();
  GLCD.SelectFont(Cooper19);
  
  GLCD.CursorToXY(1,2);
  GLCD.print("GarmenCom"); 
  
  GLCD.SelectFont(System5x7);
  GLCD.CursorToXY(2,20);
  GLCD.print("Rev 0.03 ");
  GLCD.println("2015-08-25");
}

void setup()  
{
  GLCD.Init();
  print_intro();
  
  pinMode(16,OUTPUT);	     //Set Serial2.TX at HIGH		
  digitalWrite(16, HIGH);    //Start signal
  
  // Serial port 0 is used for comunicating with the Computer
  Serial.begin(57600);
  
  if (!SD.begin(53)) {
    Serial.println("SD initialization failed!");
    GLCD.println("SD Init FAIL");
  }
  else
  {
    Serial.println("SD initialization done.");
    GLCD.println("SD Init OK");
  }

  Serial.println("GarmenCom V.0.01!");

}
void sniff()  //Sniff all data in the K-Line and Send to the USB Serial Port
{
  while (true)
  {
  
  if (Serial2.available() > 0) {
                    
		// read the incoming byte:
                tosend = Serial2.read();

                // say what you got:
                if (tosend<16)		//Add 0, for showing 0x6 as 0x06, for example
		{
		  Serial.print(0);
		}
		Serial.print(tosend,HEX);
		Serial.print(" ");
  }
  
  }
  
}

void get_ans(byte *received, byte ignore, byte ans_size)
{
  byte count=0,count2=0;
  byte first_round=1;
  Serial.println();
  Serial.print("Sent: ");
  
  while (count 0) {
                
		
		// read the incoming byte:
                temp1 = Serial2.read();
		
		
                // say what you got:
		if (count>=(ignore))
		{
		  if (first_round)
		  {
		    first_round=0;
		    Serial.println();
		    Serial.print("Received: ");
		  }
		  received[count2]=temp1;
		  if (temp1<16)
		  {
		    Serial.print(0);
		  }
		  Serial.print(temp1,HEX);
		  Serial.print(" ");
		  count2++;
		}
		
		else
		{
		  if (temp1<16)
		  {
		    Serial.print(0);
		  }
		  Serial.print(temp1,HEX);
		  Serial.print(" ");		  
		}
		
		count++;
   }
   }
   
  
}

void get_ans_silent(byte *received, byte ignore, byte ans_size)
{
  byte count=0,count2=0;
  
  while (count 0) {
		// read the incoming byte:
                temp1 = Serial2.read();
                // say what you got:
		if (count>=(ignore))
		{
		  received[count2]=temp1;
		  count2++;
		}
		else
		{  
		}
		count++;
   }
   }

}

void init_frame()
{
   long temp1,temp2,temp3,temp4,temp5,modulo;
   uint16_t seed, seed_answer;
   
   digitalWrite(16, HIGH);    //Start signal, send to Serial2.TX
   delay(1000);              
   digitalWrite(16, LOW);    
   delay(25);
   digitalWrite(16, HIGH);    
   delay(150); 
   
   Serial.println("Initializing...");
   GLCD.println("Initing...");
   
   Serial2.begin(10400);	//Serial2 is used to comunicate with the ECU
   
   delay(25); 
   Serial2.write(init1, sizeof(init1));
   
   int x=0;
   
   get_ans(response,5,5);
   
   delay(10);
   
   Serial2.write(init2, sizeof(init2));
   
   get_ans(response,4,3);
   
   delay(10);
   
   Serial2.write(init_seed_req, sizeof(init_seed_req));
   
   get_ans(response,4,6);
   
   seed=response[3];
   seed=seed*256;
   seed=seed+response[4];
   
   Serial.println();
   Serial.print("Seed is: ");
   
   Serial.println(seed,HEX);
   
   GLCD.print("Seed is: ");
   GLCD.println(seed,HEX);
   
   long k=0;
   // re-open the file for reading:
  myFile = SD.open("key.txt");
  if (myFile) {
   
    // read bytes until the desired line 
    while (k<=seed) {
        temp1=myFile.read();
	temp2=myFile.read();
	temp3=myFile.read();
	temp4=myFile.read();
	temp5=myFile.read();
	k++;
	
    }
    
    

    // close the file:
    myFile.close();
    
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening key.txt");
    GLCD.println("error opening key.txt");
  }
   
   Serial.print("Seed answer is: ");
   
   Serial.write(temp1);
   Serial.write(temp2);
   Serial.write(temp3);
   Serial.write(temp4);
   
   Serial2.write(0x04);
   Serial2.write(0x27);
   Serial2.write(0x02);
   
   if (temp1<60)
     temp1=temp1-48;
   else
     temp1=temp1-55;
   
   if (temp2<60)
     temp2=temp2-48;
   else
     temp2=temp2-55;
   
   if (temp3<60)
     temp3=temp3-48;
   else
     temp3=temp3-55;
   
   if (temp4<60)
     temp4=temp4-48;
   else
     temp4=temp4-55;
   
   Serial2.write( (temp1 * 16) + temp2 );
    
   Serial2.write( (temp3 * 16) + temp4 );
   
   modulo = (0x04 + 0x27 + 0x02 + ( (temp1 * 16) + temp2 ) + ( (temp3 * 16) + temp4 ) )%256;
   
   Serial2.write(modulo);
   
   get_ans(response,6,4);
   
   if (response[0]==0x02 && response[1]==0x67 && response[2]==0x02 && response[3]==0x6B)
   {
     Serial.println("Authentification OK!");
     GLCD.println("Auth OK!");
     delay(250);
   }
   else
   {
     Serial.println("Auth FAIL!");
     delay(1000);
   }
   x=0;
}


void loop() // run over and over
{
  init_frame();  
  
  delay(10);
  
  GLCD.ClearScreen();
  
  GLCD.SelectFont(Cooper19);
  GLCD.CursorToXY(10,10);
  GLCD.EraseTextLine();
  GLCD.print("RPM: ");
  GLCD.print(RPM);
  
  //Serial2.write(fuelling_req, sizeof(fuelling_req));
   
  //get_ans(response,4,8);
  
  while (true)
  {
    delay(50);
      
    Serial2.write(rpm_req, sizeof(rpm_req));
   
    get_ans_silent(response,4,6);
    
    RPM = response[3];
    RPM = RPM*256;
    RPM = RPM+response[4];
    
    Serial.print("RPM: ");
    Serial.println(RPM);
    GLCD.CursorToXY(10,10);
    GLCD.EraseTextLine();
    GLCD.print("RPM: ");
    GLCD.println(RPM);
    
    delay(50);
    
    /*
    Serial2.write(speed_req, sizeof(speed_req));
   
    get_ans(response,4,5);
    
    
    Serial.print("Km/h: ");
    Serial.print(response[3]);   
    GLCD.CursorToXY(10,30);
    GLCD.EraseTextLine();
    GLCD.print("Km/h: ");
    GLCD.print(response[3]);
    */
    
    Serial2.write(temp_req, sizeof(temp_req));
   
    get_ans(response,4,20);
    
    coolant = response[3];
    coolant = coolant*256;
    coolant = coolant+response[4];
    coolant=coolant;
    
    GLCD.CursorToXY(10,30);
    GLCD.EraseTextLine();
    print_glcd=coolant;
    GLCD.print("T1: ");
    GLCD.print((print_glcd/10)-272.7);
    
    Serial.print("T1: ");
    Serial.println(coolant);
    
    coolant = response[7];
    coolant = coolant*256;
    coolant = coolant+response[8];
    coolant=coolant;
    
    Serial.print("T2: ");
    Serial.println(coolant);
    
    coolant = response[11];
    coolant = coolant*256;
    coolant = coolant+response[12];
    coolant=coolant;
    
    Serial.print("T3: ");
    Serial.println(coolant);
    
    coolant = response[15];
    coolant = coolant*256;
    coolant = coolant+response[16];
    coolant=coolant;
    
    Serial.print("T4: ");
    Serial.println(coolant);
    

    
  }
  
  
}

A ver si me hago un blog o una página y lo explico bien bien bien.



   
ResponderCitar
(@LSmalaga)
Registrado: hace 16 años
Respuestas: 2549
 

😮 😮 😮 jooo no dejáis de sorprenderle, que maquinon Garmen...



   
ResponderCitar
Página 1 / 6
Compartir: