Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

10/02/2013 #1


Mensaje corrido en lcd con ccs
hola a todos,
tengo una duda lo que pasa es que estoy tratando de hacer un programa en ccs que consiste en que tiene que aparecer un mensaje en la pantalla pero letra por letra y he tratado de hacerlo de muchas maneras pero al probarlo en proteus no funciona. aqui esta el codigo que utilice

#include <16f84a.h>
#fuses xt,nowdt,noprotect
#use delay(clock=4m)
#use standard_io(a)
#use standard_io(b)
#define use_portb_lcd true
#include <lcd.c>
byte const mensaje[4]="hola";
int i=0;
int dato=0;
void main(){

delay_ms(100);

for (i=0;i<4;i++)
lcd_init();
lcd_gotoxy(1,1);
Printf(lcd_putc,mensaje[i]);

}
10/02/2013 #2

Avatar de Moyano Jonathan

he tratado de hacerlo de muchas maneras pero al probarlo en proteus no funciona
Probalo en el circuito real...

Yo tengo una función que realiza el desplazamiento del texto a lo largo del display.

Código:
void lcd_cursor_shift_right(){
lcd_send_byte(0,0x10|0x08|0x04);
}

void lcd_cursor_shift_left(void){
lcd_send_byte(0,0x10|0x08|0x00);
}

void lcd_clear(void)
{
   lcd_send_byte(0,0x01);
   delay_ms(250);
}
La última función limpia el LCD. El modo de usarlas es simple, cada vez que llamas a la función de desplazamiento...desplaza 1 vez el cursor y el texto. Si realizar un bucle for, con 4 iteraciones como tenés en tu código, el cursor y por ende el texto, se desplazará 4 posiciones.
Si querés borrar la pantalla, realizas una llamada a la última función.

Las funciones que te adjunté, funcionan con la librería LCD de CCS, por lo tanto tendrías que agregar las funciones a la librería.

Saludos !
10/02/2013 #3


muchas gracias por responder me gustaria que me explicaras un poco mas esta parte lcd_send_byte(0,0x10|0x08|0x00); se que lcd_send_byte envia valores pero en este ejemplo no entiendo lo que esta en parentesis y otra cosa cuando se utiliza un mensaje muy extenso creo que es recomendable mejor el for y quisiera saber como hacerlo con dicha funcion
10/02/2013 #4

Avatar de Moyano Jonathan

no entiendo lo que esta en parentesis y otra cosa cuando se utiliza un mensaje muy extenso creo que es recomendable mejor el for y quisiera saber como hacerlo con dicha funcion
No es complejo, es un comando para desplazar el cursor. Si lees la hoja de datos del controlador HD44780 (LCD 2x16, 4x20, etc controlador de hitachi) te vas a dar cuenta de lo que te digo. La función se utiliza con un bucle for de la siguiente manera:

for (i=0;i<4;i++)

lcd_cursor_shift_left(); // Desplaza 4 lugares a la izquierda, el texto que se encuentre en el LCD.

}

PD: Tu código está mal, es de la siguiente manera:

Código:
#include <16f84a.h>
#fuses xt,nowdt,noprotect
#use delay(clock=4m)
#use standard_io(a)
#use standard_io(b)
#define use_portb_lcd true
#include <lcd.c>

int i=0;

void main(){
lcd_init();
lcd_gotoxy(1,1);
Printf(lcd_putc,mensaje[i]);

for (i=0;i<4;i++){
lcd_cursor_shift_left();
}
 }
11/02/2013 #5


muchas gracias de nuevo, y despues de tanto probar me di cuenta que tenia que colocar unos retardos para poder visualizar caracter por caracter y ya me volvi un duro manejando lcds jjajajajaja muchas gracias
12/04/2013 #6

Avatar de kapotik

Hola Moyano, estoy tratando de hacer que se desplaze el texto de la primera linea hacia la izquierda y aga un scroll, tipo marquesina, e hestado intentando como as descripto mas arriba pero no me sale,
podrias poner el codigo completo con algun texto ejemplo para poder entenderlo mejor?

gracias
saludos
12/04/2013 #7

Avatar de Moyano Jonathan

Hola como estás.

Mirá te dejo mi librería para el LCD, ahí te vas a dar cuenta como están desarrolladas las funciones.

Código:
/*

LCD_2x16_.c

Programador: Moyano Jonathan.

Año: 2012.

Descripción: Librería de control para un LCD de 2 líneas * 16 caracteres.

*/

// Declaramos las funciones.

// Convierte un dato de 8 bits en booleano y le envía el dato al LCD.

void lcd_send_nibble(int8 nibble); 

// Le envía un byte al LCD, puede ser dato o comando.

void lcd_send_byte(int8 address, int8 n);

// Inicializa al LCD.

void lcd_init(void);

// Situa al cursor en la posición (X,Y), dentro de la pantalla del LCD.

void lcd_gotoxy(int8 x, int8 y);

// Escribe un caracter en el LCD.

void lcd_putc(char c);

// Desplaza el cursor hacia la derecha.

void lcd_cursor_shift_right(void);

// Desplaza el cursor hacia la izquierda.

void lcd_cursor_shift_left(void);

// Borra el LCD.

void lcd_clear(void);

// Borra el LCD con un retardo de 2 segundos.

void lcd_time_clear(void);


////////////////////////////////////////////////////////////////////////////////

// Definimos pines del LCD.
// Definición de pines para la plantilla del PIC18F4550.

#define LCD_DB4   PIN_D3 
#define LCD_DB5   PIN_D2 
#define LCD_DB6   PIN_D1 
#define LCD_DB7   PIN_D0 

#define LCD_RS    PIN_C6  
#define LCD_E     PIN_C7 

// Definimos la dirección de cada línea del LCD.

#define LCD_LINE_1_ADDRESS 0x00 
#define LCD_LINE_2_ADDRESS 0x40 

// Constantes del LCD.

#define lcd_tipo 2   // 0=5x7, 1=5x10, 2=2 Líneas o más de caracteres.

int8 lcd_line; 

int8 const LCD_INIT_STRING[4] = 
{ 
 0x20 | (lcd_tipo << 2),  // Modo: 4-bits, 2+ líneas, 5x8 puntos. 
 0xc,                     // Encendido del display. 
 1,                       // Limpia display. 
 6                        // Incrementa cursor. 
 }; 

void lcd_send_nibble(int8 nibble) { 

 output_bit(LCD_DB4, !!(nibble & 1)); 
 output_bit(LCD_DB5, !!(nibble & 2));  
 output_bit(LCD_DB6, !!(nibble & 4));    
 output_bit(LCD_DB7, !!(nibble & 8));    

 delay_cycles(1); 
 output_high(LCD_E); 
 delay_us(2); 
 output_low(LCD_E); 
} 

void lcd_send_byte(int8 address, int8 n){ 

output_low(LCD_RS); 

delay_us(60);

if(address)
   output_high(LCD_RS); 
else 
   output_low(LCD_RS); 
      
 delay_cycles(1); 
 
output_low(LCD_E); 

lcd_send_nibble(n >> 4); 
lcd_send_nibble(n & 0xf); 

} 

void lcd_init(void) 
{ 

int8 i; 

lcd_line = 1; 

output_low(LCD_RS); 

output_low(LCD_E);

delay_ms(35);          

for(i=0 ;i < 3; i++) 
   { 
    lcd_send_nibble(0x03); 
    delay_ms(5); 
   } 

lcd_send_nibble(0x02); 

for(i=0; i < sizeof(LCD_INIT_STRING); i++) 
   { 
    lcd_send_byte(0, LCD_INIT_STRING[i]); 
    
    delay_ms(5); 
    
   } 

} 

void lcd_gotoxy(int8 x, int8 y){ 

int8 address; 

switch(y) 
  { 
   case 1: 
     address = LCD_LINE_1_ADDRESS; 
     break; 
   case 2: 
     address = LCD_LINE_2_ADDRESS; 
     break; 
   default: 
     address = LCD_LINE_1_ADDRESS; 
     break;      
  } 

address += x-1; 
lcd_send_byte(0, 0x80 | address); 

} 

void lcd_putc(char c) 
{ 
 switch(c) 
   { 
    case '\f': 
      lcd_send_byte(0,1); 
      delay_ms(2); 
      break; 
    case '\n'   : lcd_gotoxy(1, ++lcd_line); 
       break; 
    case '\b'   : lcd_send_byte(0,0x10); 
       break; 
    case '\t'   : lcd_send_byte(0,0x14);
       break;
    case '\r'   : lcd_send_byte(0,0x18);
       break;
    case '\v'   : lcd_send_byte(0,0x1C);
       break;
    default     : lcd_send_byte(1,c);
                   break; 
   } 
}

void lcd_cursor_shift_right(){
lcd_send_byte(0,0x10|0x08|0x04);
}

void lcd_cursor_shift_left(void){
lcd_send_byte(0,0x10|0x08|0x00);
}

void lcd_clear(void)
{
   lcd_send_byte(0,0x01);
   delay_ms(250);
}

void lcd_time_clear(void)
{
   delay_ms(2000);
   lcd_send_byte(0,0x01);
   
}
El ejemplo se muestra más arriba, por favor armá una aplicación REAL, no simulada para poder probar si funciona. Caso contrario poné tus dudas, colocando la aplicación que armaste.

Saludos !
13/04/2013 #8

Avatar de kapotik

Gracias Moyano por responder y por la libreria, pero recien hace unos dias que he empesado a meterme en el lenguaje C, ( yo vengo del assembler), y la verdad que no logro darme cuenta como lo implementas, y el codigo que sale mas arriba no me compila me da error, por eso te pedia si podias poner algun codigo a modo ejemplo para poder entenderlo mejor.

Gracias
saludos
14/04/2013 #9

Avatar de Moyano Jonathan

Sinceramente no tengo ningún ejemplo donde solo pruebe esa funcionalidad que vos necesitas. La librería si funciona por lo que no vas a tener problemas con eso...pero si recién empezas a programar en C, te recomiendo aprender primero como usar el LCD en ese leguaje y luego utilizar mi librería. Te vas a dar cuenta que su uso es muy sencillo.

Saludos !
28/02/2014 #10


Buenas noches desde Madrid: Perdón por reabrir este viejo enlace pero no soy capaz de sacar el simple "Hola" en mi LCD con la versíón adaptada del programa de Moyano. Con LCD.C sí que me funciona todo pero quiero ver las letras "moviéndose". Adjunto el sencillo programa de prueba y mi adaptación al 16F628A del programa de Moyano. No sé si es que no se puede adaptar al 16F628 o es que me falta algo más por cambiar. Creo que entiendo el programa y lo único que he cambiado ha sido la asignación de los pines del pic al lcd. Si solo se puede hacer con Pics superiores con puerto C y/o D os pido que me lo confirméis porque ni en el foro ni por Google he encontrado una solución. Un saludo y gracias anticipadas por las respuestas.
Archivos Adjuntos
Tipo de Archivo: rar Lcd con 16F628A.rar (1,5 KB (Kilobytes), 119 visitas)
01/03/2014 #11

Avatar de Moyano Jonathan

Los pasos a seguir:

1º - Primero armar bien tu hardware y determinar que todo está conectado correctamente.
2º - Configurar que pines del PIC están conectados al LCD.

Código:
////////////////////////////////////////////////////////////////////////////////

// Definimos pines del LCD.
// Definición de pines para la plantilla del PIC18F4550.

#define LCD_DB4   PIN_D3 
#define LCD_DB5   PIN_D2 
#define LCD_DB6   PIN_D1 
#define LCD_DB7   PIN_D0 

#define LCD_RS    PIN_C6  
#define LCD_E     PIN_C7
3º - El código de prueba es el siguiente:

Código:
void main(){
lcd_init();
lcd_gotoxy(1,1);
Printf(lcd_putc,"Hola mundo !");

for (i=0;i<4;i++){
lcd_cursor_shift_left();
}
 }
PD: Configurá bien los fusibles.
02/03/2014 #12


Un cordial saludo y muchas gracias por la respuesta: tengo la lcd montada en un protoboard y funciona con la libreria lcd.c. Perdón por repetirme pero, ¿solo con cambiar la asignación de pines se puede usar tu libreria en un pic 16F628/A o tiene que ser uno superior como el 18Fxxxx que mencionas?. Repito que con lcd.c y mi 16F628A sí funciona, puedo leer el mensaje que grabo.
02/03/2014 #13

Avatar de Moyano Jonathan

¿solo con cambiar la asignación de pines se puede usar tu libreria en un pic 16F628/A
Si, solo asignando los pines correctamente podés usar mi librería con tu proyecto. Saludos !
23/09/2016 #14


Hola, amigos. Les cuento, estoy desarrollando un programa en picc compiler, en lenguaje C en el que tengo una función que lo que hace, es que hasta que no se presione la tecla ok, haya una leyenda que diga "presione -ok-" que corra por el display de derecha a izquierda.

El problema que se me presenta es el siguiente:
Al pasar la leyenda de derecha a izquierda, la parte final de este texto no llega a desaparecer por completo de la pantalla.
Quedaría así: "e -ok-"
Luego vuelve a aparecer la leyenda por la derecha y va pisando a lo que quedó en pantalla.
("e -ok-presione -"), pero esa parte final de la leyenda nunca desaparece.

Es como si el lcd 16x2 sólo permitiera el movimiento de 7 caracteres hacia la izquierda, lo que supera a eso lo deja fijo en pantalla.

¿Cómo puedo hacer para que el texto se mueva completo?
Que desaparezca por completo por la izquierda y aparezca por la derecha.

Les paso el código que yo estoy usando.
Código PHP:
void leyenda_en _movimiento(void

   
int s=1;      //creamos el entero S que es el que me va a permitir el movimiento en pantalla 
   
while(bit_test(porta,1))     // mientras no se presione la tecla ok correrá el siguiente programa 
      

        
lcd_gotoxy(s,1);      // me ubica en la columna 1, porque &quot;s&quot; es 1, y en la fila 1 (parte superior del display) 
        
printf(lcd_putc,"PRESIONE -OK-");      // imprime la leyenda &quot; PRESIONE -OK- &quot; .
        
delay_ms(180);       // retraso de 180 mili-segundos, tiempo de movimiento de la leyenda. 
        
s=s-1;       // S resta 1 por cada vez que el programa pasa por acá. 
        
if(s==-15)       // si S es igual a -15 (o sea que 15 caracteres pasaron hacia la izq o desaparecieron del display) 
         

           
s=16;      // me coloca la leyenda justo en el margen derecho del display para que vuelvan a caminar hacia la izq. 
         

     } 

En el simulador PROTEUS funciona perfecto, pero en la realidad ocurre lo que les expliqué al principio.

Espero su ayuda para saber qué es lo que estoy haciendo mal.

Gracias, amigos.
24/09/2016 #15

Avatar de roberttorres

jairotev dijo: Ver Mensaje

El problema que se me presenta es el siguiente:
Al pasar la leyenda de derecha a izquierda, la parte final de este texto no llega a desaparecer por completo de la pantalla.
Quedaría así: "e -ok-"
Luego vuelve a aparecer la leyenda por la derecha y va pisando a lo que quedó en pantalla.
("e -ok-presione -"), pero esa parte final de la leyenda nunca desaparece.

¿Cómo puedo hacer para que el texto se mueva completo?
Que desaparezca por completo por la izquierda y aparezca por la derecha.
Buenas.
El rastro que va quedando es porque no estas limpiando la pantalla, prueba de esta forma:

Código:
void leyenda_en _movimiento(void) 
{ 
   int s=1;      //creamos el entero S que es el que me va a permitir el movimiento en pantalla 
   while(bit_test(porta,1))     // mientras no se presione la tecla ok correrá el siguiente programa 
      { 
        lcd_gotoxy(s,1);      // me ubica en la columna 1, porque &quot;s&quot; es 1, y en la fila 1 (parte superior del display) 
        printf(lcd_putc,"PRESIONE -OK-");      // imprime la leyenda &quot; PRESIONE -OK- &quot; .
        delay_ms(180);       // retraso de 180 mili-segundos, tiempo de movimiento de la leyenda. 
        printf(lcd_putc,"\f");//LIMPIAR PANTALLA
        s=s-1;       // S resta 1 por cada vez que el programa pasa por acá. 
        if(s==-17)       // si S es igual a -15 (o sea que 15 caracteres pasaron hacia la izq o desaparecieron del display) 
         { 
           s=16;      // me coloca la leyenda justo en el margen derecho del display para que vuelvan a caminar hacia la izq. 
         } 
     } 
}
18/01/2017 #16


Hola. Soy medio novato en programación.
Estoy tratando de hacer una función en la librería del lcd para ir colocando letra por letra alguna frase.

Por ejemplo:
funcion desplazar("foros electronica",300 ms de retardo x letra);
Pero no sé cómo hacer para colocar los datos en la función de forma correcta.

Lo probé y funcionó correctamente, pero con una frase definida en la variable; const int frase
Aquí el código que hice:
Código PHP:
#include <16f877a.h>
#fuses xt,nowdt,put,nobrownout,nocpd
#use delay(clock=4000000)
#define LCD_DB4 PIN_B2
#define LCD_DB5 PIN_B3
#define LCD_DB6 PIN_B4
#define LCD_DB7 PIN_B5
#define LCD_RS PIN_D3
#define LCD_RW PIN_D2
#define LCD_E PIN_B1
#include <lcd1.c>
#define ms delay_ms
void desplazar(const int letras,int tiempo);//prototipo funcion
void main(){
lcd_init();//inicio libreria lcd
while(1)
{
desplazar(oracion a desplazar,300);//funcion en bucle while
}
}
void desplazar(const int letras,int tiempo){//funcion (frase a desplazar:letras, tiempo de retardo por letra: tiempo)
int y=1;//posicion y lcd
int x=1;//posicion x lcd
const int frase[]={letras};//no se que hacer aqui para que la variable frase tome las letras introducidas a la funcion
for(int i=1;i<sizeof(frase);i++)//bucle for para colocar letra por letra
{
lcd_gotoxy(x,y);//posicion lcd
lcd_putc(frase[i-1]);//que letra se colocara
ms(tiempo);//retardo por letra, dato introducido desde la funcion desplazar
x++;//aumento posicion "X" del lcd
if((x>16)&&(y==1)){//si la posicion "X" alcanza los 16 cuadros que continue la frase desde x=1,y=2
y=2;
x=1;
}
if((
x>16)&&(y==2))//Si alcanza los 16 cuadros de arriba y abajo, que limpie lcd y continue escribiendo desde x=1,y=1
{
lcd_putc("\f");
x=1;
y=1;
}
if(
i==sizeof(frase)-1)//que limpie lcd cuando termine la frase y vuelva a comenzar
{
lcd_putc("\f");
}
}

22/01/2017 #17

Avatar de Saint_

hola dierma, te comento que hay algunos errores de conceptos en tu programa pero en general la idea esta bien. Este un pequeño ajuste (CCS 5.061).

Código:
#include <16F877A.h>
#device PASS_STRINGS=IN_RAM   //Importante

#FUSES PUT                      //Power Up Timer
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOPROTECT                //Code not protected from reading

#use delay(crystal=4MHz)

//!#define LCD_DB4 PIN_B2
//!#define LCD_DB5 PIN_B3
//!#define LCD_DB6 PIN_B4
//!#define LCD_DB7 PIN_B5
//!#define LCD_RS PIN_D3
//!#define LCD_RW PIN_D2
//!#define LCD_E PIN_B1

#define LCD_ENABLE_PIN  PIN_B1
#define LCD_RS_PIN      PIN_D3
#define LCD_RW_PIN      PIN_D2
#define LCD_DATA4       PIN_B2
#define LCD_DATA5       PIN_B3
#define LCD_DATA6       PIN_B4
#define LCD_DATA7       PIN_B5 


#include <lcd.c>
#include <string.h>
void desplazar(char *p,unsigned int16 tiempo)
{
   unsigned int8 y=1;//posicion y lcd
   unsigned int8 x=1;//posicion x lcd
   unsigned int8 i=0;
   char  letras[64]; ///tamaño maximo de de el mensaje
   
   do{letras[i++]=*p++;}while(*p!=0);//transfiere la cadena de texto a la variable temporal letras
   
   for(i=0;i<strlen(letras);i++)//bucle for para colocar letra por letra
   {
      lcd_gotoxy(x,y);//posicion lcd
      lcd_putc(letras[i]);//que letra se colocara
      delay_ms(tiempo);//retardo por letra, dato introducido desde la funcion desplazar
      x++;//aumento posicion "X" del lcd
      if((x>16)&&(y==1))
      {//si la posicion "X" alcanza los 16 cuadros que continue la frase desde x=1,y=2
         y=2;
         x=1;
      }
      if((x>16)&&(y==2))//Si alcanza los 16 cuadros de arriba y abajo, que limpie lcd y continue escribiendo desde x=1,y=1
      {
         lcd_putc("\f");
         x=1;
         y=1;
      }
   }
}
/****************************************************************************/
void main() 
{
   lcd_init();
   while(true)
   {
      lcd_putc("\f");
      desplazar("Oracion a desplazar",300);//funcion en bucle while
      delay_ms(300);
   }
}
23/01/2017 #18


Saint_ muchas gracias por responder y enviar un código con los problemas resueltos
mi error fue no haber colocado #device PASS_STRINGS=IN_RAM y cambie sizeof por strlen entre otras
cositas ) gracias por tu astucia, una preguntita, para que nos sirve el "!" en !#define LCD_E PIN_B1?
24/01/2017 #19

Avatar de Saint_

Si te refieres a //!#device...
Es solo un comentario nada mas
04/03/2017 #20


Error a la hora de compilar
Soy nuevo. Una pregunta.
¿Por qué trato de cargar el código y me marca un error en: desplazar("Oracion a desplazar",300);?
Es el único error que me marca y no me deja compilarlo.
Yo utilizo otro PIC y ya lo tengo configurado para ese PIC.
Código PHP:
#include <18f4550.h>
//#fuses HSPDLL, NOWDT, NOBROWNOUT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,MCLR,NOP,BADEN,WRTB,CPB
#use delay(clock=48000000) //frecuencia para trabajar con el puerto usb y del pic
#build(reset=0x02000,interrupt=0x02008) //aqui estan los vectores para el reset y el boot (exclusivo del bootloader)
#org 0x0000, 0x1FFF {} //que el compilador no va a escribir nada aqui (aqui esta el bootloader), exclusivas del bootloader

//----------------------------------------------

#define LCD_ENABLE_PIN  PIN_b2
#define LCD_RS_PIN      PIN_b0
#define LCD_RW_PIN      PIN_b1
#define LCD_DATA4       PIN_B4
#define LCD_DATA5       PIN_B5
#define LCD_DATA6       PIN_B6
#define LCD_DATA7       PIN_B7 


#include <lcd.c>
#include <string.h>
void desplazar(char *p,unsigned int16 tiempo)
{
   
unsigned int8 y=1;//posicion y lcd
   
unsigned int8 x=1;//posicion x lcd
   
unsigned int8 i=0;
   
char  letras[64]; ///tamaño maximo de de el mensaje
   
   
do{letras[i++]=*p++;}while(*p!=0);//transfiere la cadena de texto a la variable temporal letras
   
   
for(i=0;i<strlen(letras);i++)//bucle for para colocar letra por letra
   
{
      
lcd_gotoxy(x,y);//posicion lcd
      
lcd_putc(letras[i]);//que letra se colocara
      
delay_ms(tiempo);//retardo por letra, dato introducido desde la funcion desplazar
      
x++;//aumento posicion "X" del lcd
      
if((x>16)&&(y==1))
      {
//si la posicion "X" alcanza los 16 cuadros que continue la frase desde x=1,y=2
         
y=2;
         
x=1;
      }
      if((
x>16)&&(y==2))//Si alcanza los 16 cuadros de arriba y abajo, que limpie lcd y continue escribiendo desde x=1,y=1
      
{
         
lcd_putc("\f");
         
x=1;
         
y=1;
      }
   }
}
/****************************************************************************/
void main() 
{
   
lcd_init();
   while(
true)
   {
      
lcd_putc("\f");
      
desplazar("Oracion a desplazar",300);//funcion en bucle while
      
delay_ms(300);
   }

¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.