|
|
View previous topic :: View next topic |
Author |
Message |
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
Problem when clear Graphic LCD 192x64 |
Posted: Tue Jul 28, 2015 7:53 pm |
|
|
Hi all.
I have a project with graphics lcd using KS0108 display controller.
I also using a driver get from our forum, but i have a problem when using glcd_fillScreen function to clear screen, it make the GLCD flash when I'm inputting data from keypad to GLCD.
Because i want to only clear some position on this GLCD, not all screen, so that i need a helping to solve this problem.
In my project using PIC18F4680, CCSC compiler ver 5.044
Here is the driver i'm using:
Code: |
/////////////////////////////////////////////////////////////////////////
//// HDM64GS192.c ////
//// ////
//// This file has been modified to handle the 192 x 64 display ////
//// ////
//// ////
//// This file contains drivers for using a Hantronix HDM64GS12 with ////
//// a KS0108 display controller. The HDM64GS12 is 128 by 64 pixels. ////
//// The driver treats the upper left pixel as (0,0). ////
//// ////
//// Use #define FAST_GLCD if the target chip has at least 1k of RAM ////
//// to decrease the time it takes to update the display. ////
//// glcd_update() must then be called to update the display after ////
//// changing the pixel information. ////
//// See ex_glcd.c for suggested usage. ////
//// See KS0108.c for controlling a single 64 by 64 display ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// LCD Pin connections: ////
//// (These can be changed as needed in the following defines). ////
//// * 1: VSS is connected to GND ////
//// * 2: VDD is connected to +5V ////
//// * 3: V0 - LCD operating voltage (Contrast adjustment) ////
//// * 4: R/S - Data or Instruction is connected to B2 ////
//// * 5: R/W - Read or Write is connected to B4 ////
//// * 6: Enable is connected to B5 ////
//// *7-14: Data Bus 0 to 7 is connected to port d ////
//// *15: Chip Select 1 is connected to B0 ////
//// *16: Chip Select 2 is connected to B1 ////
//// *17: Reset is connected to C0 ////
//// *18: Negative voltage is also connected to the 20k Ohm POT ////
//// *19: Positive voltage for LED backlight is connected to +5V ////
//// *20: Negative voltage for LED backlight is connected to GND ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// glcd_init(mode) ////
//// * Must be called before any other function. ////
//// - mode can be ON or OFF to turn the LCD on or off ////
//// ////
//// glcd_pixel(x,y,color) ////
//// * Sets the pixel to the given color. ////
//// - color can be ON or OFF ////
//// ////
//// glcd_fillScreen(color) ////
//// * Fills the entire LCD with the given color. ////
//// - color can be ON or OFF ////
//// ////
//// glcd_update() ////
//// * Write the display data stored in RAM to the LCD ////
//// * Only available if FAST_GLCD is defined ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996, 2004 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
#define LARGE_LCD
#ifndef HDM64GS192
#define HDM64GS192
#ifndef GLCD_WIDTH
#define GLCD_WIDTH 192
#endif
#ifndef GLCD_CS1
#define GLCD_CS1 PIN_A3 // Chip Selection 1
#endif
#ifndef GLCD_CS2
#define GLCD_CS2 PIN_A1 // Chip Selection 2
#endif
#ifndef GLCD_CS3
#define GLCD_CS3 PIN_A0 // Chip Selection 3
#endif
#ifndef GLCD_DI
#define GLCD_DI PIN_E0 // Data or Instruction input
#endif
#ifndef GLCD_RW
#define GLCD_RW PIN_E1 // Read/Write
#endif
#ifndef GLCD_E
#define GLCD_E PIN_E2 // Enable
#endif
#ifndef GLCD_RST
#define GLCD_RST PIN_A2 // Reset
#endif
#define GLCD_LEFT 0
#define GLCD_MID 1
#define GLCD_RIGHT 2
#ifndef ON
#define ON 1
#endif
#ifndef OFF
#define OFF 0
#endif
/////////////////////////////////////////////////////////////////////////
// Function Prototypes
/////////////////////////////////////////////////////////////////////////
void glcd_update();
void glcd_init(int1 mode);
void glcd_pixel(unsigned int8 x, unsigned int8 y, int1 color);
void glcd_fillScreen(int1 color);
void glcd_writeByte(int8 side, BYTE data);
BYTE glcd_readByte(int8 side);
//void glcd_update();
/////////////////////////////////////////////////////////////////////////
#ifdef FAST_GLCD
struct
{
unsigned int8 left[512];
unsigned int8 right[512];
unsigned int8 mid[512];
} displayData;
#endif
//=============================================================================
// Purpose: Initialize the LCD.
// Call before using any other LCD function.
// Inputs: OFF - Turns the LCD off
// ON - Turns the LCD on
void glcd_init(int1 mode)
{
// Initialize some pins
output_high(GLCD_RST);
output_low(GLCD_E);
output_high(GLCD_CS1);
output_high(GLCD_CS2);
output_high(GLCD_CS3);
output_low(GLCD_DI); // Set for instruction
glcd_writeByte(GLCD_LEFT, 0xC0); // Specify first RAM line at the top
glcd_writeByte(GLCD_RIGHT, 0xC0); // of the screen
glcd_writeByte(GLCD_MID, 0xC0);
glcd_writeByte(GLCD_LEFT, 0x40); // Set the column address to 0
glcd_writeByte(GLCD_RIGHT, 0x40);
glcd_writeByte(GLCD_MID, 0x40);
glcd_writeByte(GLCD_LEFT, 0xB8); // Set the page address to 0
glcd_writeByte(GLCD_RIGHT, 0xB8);
glcd_writeByte(GLCD_MID, 0xB8);
if(mode == ON)
{
glcd_writeByte(GLCD_LEFT, 0x3F); // Turn the display on
glcd_writeByte(GLCD_MID, 0x3F);
glcd_writeByte(GLCD_RIGHT, 0x3F);
}
else
{
glcd_writeByte(GLCD_LEFT, 0x3E); // Turn the display off
glcd_writeByte(GLCD_MID, 0x3E);
glcd_writeByte(GLCD_RIGHT, 0x3E);
}
glcd_fillScreen(OFF); // Clear the display
#ifdef FAST_GLCD
glcd_update();
#endif
}
//==================================================================================
// Purpose: Update the LCD with data from the display arrays
#ifdef FAST_GLCD
void glcd_update()
{
unsigned int8 i, j;
unsigned int8 *p1, *p2, *p3;
p1 = displayData.left;
p2 = displayData.right;
p3 = displayData.mid;
// Loop through the vertical pages
for(i = 0; i < 8; ++i)
{
output_low(GLCD_DI); // Set for instruction
glcd_writeByte(GLCD_LEFT, 0x40); // Set horizontal address to 0
glcd_writeByte(GLCD_RIGHT, 0x40);
glcd_writeByte(GLCD_MID, 0x40);
glcd_writeByte(GLCD_LEFT, i | 0xB8); // Set page address
glcd_writeByte(GLCD_RIGHT, i | 0xB8);
glcd_writeByte(GLCD_MID, i | 0xB8);
output_high(GLCD_DI); // Set for data
// Loop through the horizontal sections
for(j = 0; j < 64; ++j)
{
glcd_writeByte(GLCD_LEFT, *p1++); // Turn pixels on or off
glcd_writeByte(GLCD_RIGHT, *p2++); // Turn pixels on or off
glcd_writeByte(GLCD_MID, *p3++); // Turn pixels on or off
}
}
}
#endif
//===================================================================================
// Purpose: Turn a pixel on a graphic LCD on or off
// Inputs: 1) x - the x coordinate of the pixel
// 2) y - the y coordinate of the pixel
// 3) color - ON or OFF
void glcd_pixel(unsigned int8 x, unsigned int8 y, int1 color)
#ifdef FAST_GLCD
{
unsigned int8* p;
unsigned int16 temp;
temp = y/8;
temp *= 64;
temp += x;
if((x>63)&&(x<128))
{
p = displayData.mid + temp - 64;
}
else if(x>127)
{
p = displayData.right + temp-128;
}
else if((x>=0)&&(x<4))
{
p = displayData.left+temp;
if(color)
{
bit_set(*p, y%8);
}
else
{
bit_clear(*p, y%8);
}
}
#else
{
BYTE data;
int8 side = GLCD_LEFT; // Stores which chip to use on the LCD
if((x>63)&&(x<128)) // Check for first or second display area
{
x -= 64;
side = GLCD_MID;
}
else if ((x>127)&&(x<192))
{
x -=128;
side=GLCD_RIGHT;
}
else
{
side=GLCD_LEFT;
}
output_low(GLCD_DI); // Set for instruction
bit_clear(x,7); // Clear the MSB. Part of an instruction code
bit_set(x,6); // Set bit 6. Also part of an instruction code
glcd_writeByte(side, x); // Set the horizontal address
glcd_writeByte(side, (y/8 & 0xBF) | 0xB8); // Set the vertical page address
output_high(GLCD_DI); // Set for data
glcd_readByte(side); // Need two reads to get data
data=glcd_readByte(side); // at new address
if(color == ON)
bit_set(data, y%8); // Turn the pixel on
else // or
bit_clear(data, y%8); // turn the pixel off
output_low(GLCD_DI); // Set for instruction
glcd_writeByte(side, x); // Set the horizontal address
output_high(GLCD_DI); // Set for data
glcd_writeByte(side, data); // Write the pixel data
}
#endif
//=============================================================================================
// Purpose: Fill the LCD screen with the passed in color
// Inputs: ON - turn all the pixels on
// OFF - turn all the pixels off
void glcd_fillScreen(int1 color)
#ifdef FAST_GLCD
{
unsigned int8 data;
unsigned int8 *p1, *p2, *p3;
unsigned int16 i;
p1 = displayData.left;
p2 = displayData.right;
p3 = displayData.mid;
data = 0xFF * color;
for(i=0; i<512; ++i)
{
*p1++ = data;
*p2++ = data;
*p3++ = data;
}
}
#else
{
unsigned int8 i, j;
// Loop through the vertical pages
for(i = 0; i < 8; ++i)
{
output_low(GLCD_DI); // Set for instruction
glcd_writeByte(GLCD_LEFT, 0b01000000); // Set horizontal address to 0
glcd_writeByte(GLCD_RIGHT, 0b01000000);
glcd_writeByte(GLCD_MID, 0b01000000);
glcd_writeByte(GLCD_LEFT, i | 0b10111000);// Set page address
glcd_writeByte(GLCD_RIGHT, i | 0b10111000);
glcd_writeByte(GLCD_MID, i | 0b10111000);
output_high(GLCD_DI); // Set for data
// Loop through the horizontal sections
for(j = 0; j < 64; ++j)
{
glcd_writeByte(GLCD_LEFT, 0xFF*color); // Turn pixels on or off
glcd_writeByte(GLCD_MID, 0xFF*color); // Turn pixels on or off
glcd_writeByte(GLCD_RIGHT, 0xFF*color); // Turn pixels on or off
}
}
}
#endif
//==================================================================================
// Purpose: Write a byte of data to the specified chip
// Inputs: 1) chipSelect - which chip to write the data to
// 2) data - the byte of data to write
void glcd_writeByte(int8 side, BYTE data)
{
set_tris_d(0x00);
output_low(GLCD_RW); // Set for writing
if(side==0) // Choose which side to write to
{
output_low(GLCD_CS1);
output_high(GLCD_CS2);
output_high(GLCD_CS3);
}
else if(side==1)
{
output_low(GLCD_CS2);
output_high(GLCD_CS1);
output_high(GLCD_CS3);
}
else
{
output_low(GLCD_CS3);
output_high(GLCD_CS2);
output_high(GLCD_CS1);
}
delay_us(1);
output_d(data); // Put the data on the port
delay_us(1);
output_high(GLCD_E); // Pulse the enable pin
delay_us(5);
output_low(GLCD_E);
output_high(GLCD_CS1); // Reset the chip select lines
output_high(GLCD_CS2);
output_high(GLCD_CS3);
}
//===============================================================================
// Purpose: Reads a byte of data from the specified chip
// Ouputs: A byte of data read from the chip
BYTE glcd_readByte(int8 side)
{
BYTE data; // Stores the data read from the LCD
set_tris_d(0xFF); // Set port d to input
output_high(GLCD_RW); // Set for reading
if(side==0) // Choose which side to write to
{
output_low(GLCD_CS1);
output_high(GLCD_CS2);
output_high(GLCD_CS3);
}
else if(side==1)
{
output_low(GLCD_CS2);
output_high(GLCD_CS1);
output_high(GLCD_CS3);
}
else
{
output_low(GLCD_CS3);
output_high(GLCD_CS2);
output_high(GLCD_CS1);
}
delay_us(1);
output_high(GLCD_E); // Pulse the enable pin
delay_us(4);
data = input_d(); // Get the data from the display's output register
output_low(GLCD_E);
output_high(GLCD_CS1); // Reset the chip select lines
output_high(GLCD_CS2);
output_high(GLCD_CS3);
return data; // Return the read data
}
#endif
|
Please show me way to fix it if you can, thank so much! _________________ Begin Begin Begin !!! |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Thu Jul 30, 2015 11:45 pm |
|
|
Hi all.
I tried to write null character to clear GLCD but not success.
It still have a character of the last.
Please show me way to solve this.
Thanks you! _________________ Begin Begin Begin !!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Aug 01, 2015 3:06 pm |
|
|
Quote: |
I have a problem when using glcd_fillScreen function to clear screen,
it make the GLCD flash when I'm inputting data from keypad to GLCD. |
The glcd_fillscreen() routine will be slow. Look at the driver. It takes a
lot of instruction cycles to clear the screen.
Post a test program that shows the problem. The program should be
small, but complete (compiles with no errors).
Also, we'll be interested to see in your test program if you are using
FAST_GLCD. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sat Aug 01, 2015 5:41 pm |
|
|
I don't use that display but
query: does it not have a cmd for cls/home like the 2x16 char. LCD modules? If so it might be faster than the 512 count loop.
query: initially p1=0, p2=1,p3=2. during the 'loop' does this not happen
p1=0,p2=1,p3=2
p1=1,p2=2,p3=3
p1=2,p2=3,p3=4
It looks like they are overlapping and that +3 in the counter might increment the operation 3X faster. mind you I haven't read the data sheet but it does 'look' wrong , or at least not efficient.
If the 'displayData' is really a linear block of 512 *3 bytes, might it not be faster to do for (i=0;I<1536;++i) ?
just ideas to consider?
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sun Aug 02, 2015 1:22 am |
|
|
He specifically says:
"i want to only clear some position on this GLCD, not all screen".
PCM_programmer has raised the critical question, whether he is using FAST_GLCD or not?.
Key is to understand that if you want to fill a block on such a screen, the code has to read the byte containing each bit to change, change the bit, and write it back. Very slow. With FAST_GLCD selected, the CPU keeps a copy of the screen contents 'locally', does the changes to this, and then writes this back. Much faster, Downside, it requires 1536 bytes of RAM on the processor.
It's very different from the text LCD, with these screens you are looking at I/O for every individual pixel, versus just one byte for a whole character. A lot of work. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sun Aug 02, 2015 5:02 am |
|
|
yeah I re read the OP and got stuck on this line...
....but i have a problem when using glcd_fillScreen function to clear screen, so I looked at the 'fillscreen' function...
kinda forgot about the next line.....
Mr. T's right about when you only want to 'update' just a portion of the whole screen. It is a complicated process of reading in the pixel at the location, changing it to the new data, writing the new data back and it does involve hundreds if not thousands of operations.
One possible 'speedup' would be to run the PIC at maximum speed, though I assume you're already doing this ?
Another possibility would be to rewrite the driver itself. As I said I don't use GLCD or this driver but it may be possible to 'tweak' out better performance using different algorithms or 'fine tuning' the current code.
Jay |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sun Aug 02, 2015 11:48 pm |
|
|
Thanks for your support.
Really, I want to modify program to reduce time clear screen because it make GLCD flash, it's difficult to see when press keypad.
Now, in my program, I can't using FAST_GLCD define because i tried but can't see anythings on GLCD.
About maximum speed for PIC, I also am using PLL to increase frequency to from crystal 10MHZ to 40MHZ.
In my program, I am using disp_runing function update data on lcd when keypass press, because I can't clear some position to update data, so that i must clear all GLCD, and it make flashing.
Here is my program for processing and display data on GLCD.
Code: |
void disp_runing(void) // hien thi giao dien sau khi setup xong
{
glcd_fillScreen(OFF);
glcd_rect(0, 0, 191, 15, NO, ON); // Outline the bar
glcd_rect(0, 17,191, 63, NO, ON); // Outline the bar
glcd_line(38, 0,38, 63, ON);
glcd_line(92, 0,92, 63, ON);
glcd_line(150,0,150, 63, ON);
//! sprintf(str_demo1, "%u", count_left_right_push);
glcd_text57(5, 4, str_demo1, 1, ON);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHANNEL 1
//! if(count_enter_push==1 || count_enter_push==2 || power_up==1)
//! {
ch1_off_num = ch1_off[5]*100000 + ch1_off[4]*10000 + ch1_off[3]*1000 + ch1_off[2]*100 + ch1_off[1]*10 + ch1_off[0];
if (ch1_off_num >999999) ch1_off_num=0;
ch1_on_num = ch1_on[5]*100000 + ch1_on[4]*10000 + ch1_on[3]*1000 + ch1_on[2]*100 + ch1_on[1]*10 + ch1_on[0];
if (ch1_on_num >999999) ch1_on_num=0;
sprintf(ch1_off_disp, "%06Lu", ch1_off_num);
sprintf(ch1_on_disp, "%06Lu", ch1_on_num);
glcd_text57(5,20, str_l1_ch1, 1, ON);
glcd_text57(50,20,clr_scr,1,OFF); delay_ms(10);
glcd_text57(50,20,ch1_on_disp,1,ON);
glcd_text57(105,20,clr_scr,1,OFF);
glcd_text57(105,20,ch1_off_disp,1,ON);
//! }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHANNEL 2
//! if(count_enter_push==3 || count_enter_push==4 || power_up==1)
//! {
ch2_off_num = ch2_off[5]*100000 + ch2_off[4]*10000 + ch2_off[3]*1000 + ch2_off[2]*100 + ch2_off[1]*10 + ch2_off[0];
if( ch2_off_num >999999) ch2_off_num=0;
ch2_on_num = ch2_on[5]*100000 + ch2_on[4]*10000 + ch2_on[3]*1000 + ch2_on[2]*100 + ch2_on[1]*10 + ch2_on[0];
if( ch2_on_num >999999) ch2_on_num=0;
sprintf(ch2_off_disp, "%06Lu", ch2_off_num);
sprintf(ch2_on_disp, "%06Lu", ch2_on_num);
glcd_text57(5,31, str_l2_ch2, 1, ON); // hien thi chu "MODEL:" co dinh
glcd_text57(50,31,ch2_on_disp,1,ON);
glcd_text57(105,31,ch2_off_disp,1,ON);
//! }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//! if( count_enter_push==5 || count_enter_push==6 || power_up==1)
//! {
ch3_off_num = ch3_off[5]*100000 + ch3_off[4]*10000 + ch3_off[3]*1000 + ch3_off[2]*100 + ch3_off[1]*10 + ch3_off[0];
if( ch3_off_num >999999) ch3_off_num=0;
ch3_on_num = ch3_on[5]*100000 + ch3_on[4]*10000 + ch3_on[3]*1000 + ch3_on[2]*100 + ch3_on[1]*10 + ch3_on[0];
if( ch3_on_num >999999) ch3_on_num=0;
sprintf(ch3_off_disp, "%06Lu", ch3_off_num); // CHANNEL 3
sprintf(ch3_on_disp, "%06Lu", ch3_on_num);
glcd_text57(5,42, str_l3_ch3, 1, ON); // hien thi chu "LOT:" co dinh
glcd_text57(50,42,ch3_on_disp,1,ON);
glcd_text57(105,42,ch3_off_disp,1,ON);
//! }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//! if( count_enter_push==7 || count_enter_push==8 || power_up==1)
//! {
ch4_off_num = ch4_off[5]*100000 + ch4_off[4]*10000 + ch4_off[3]*1000 + ch4_off[2]*100 + ch4_off[1]*10 + ch4_off[0];
if( ch4_off_num >999999) ch4_off_num=0;
ch4_on_num = ch4_on[5]*100000 + ch4_on[4]*10000 + ch4_on[3]*1000 + ch4_on[2]*100 + ch4_on[1]*10 + ch4_on[0];
if( ch4_on_num >999999) ch4_on_num=0;
sprintf(ch4_off_disp, "%06Lu", ch4_off_num); // CHANNEL 4
sprintf(ch4_on_disp, "%06Lu", ch4_on_num);
glcd_text57(5,53, str_l4_ch4, 1, ON);
glcd_text57(50,53,ch4_on_disp,1,ON);
glcd_text57(105,53,ch4_off_disp,1,ON);
power_up=0;
//! }
if( count_enter_push==1 || count_enter_push==2) { pos_under_line_y=22;}
else if( count_enter_push==3 || count_enter_push==4) { pos_under_line_y=33;}
else if( count_enter_push==5 || count_enter_push==6) { pos_under_line_y=44;}
else if( count_enter_push==7 || count_enter_push==8) { pos_under_line_y=55;}
if(count_enter_push !=0)
{
glcd_text57(pos_under_line_x, pos_under_line_y, under_line, 1, ON);
glcd_rect(150, 17, 191, 63, yes, on);
}
else
{
if ( stt_ch1==0) glcd_text57(160,20,stt_off_disp,1,ON);
else glcd_text57(160,20,stt_on_disp,1,ON);
if ( stt_ch2==0) glcd_text57(160,31,stt_off_disp,1,ON);
else glcd_text57(160,31,stt_on_disp,1,ON);
if ( stt_ch3==0) glcd_text57(160,42,stt_off_disp,1,ON);
else glcd_text57(160,42,stt_on_disp,1,ON);
if ( stt_ch4==0) glcd_text57(160,53,stt_off_disp,1,ON);
else glcd_text57(160,53,stt_on_disp,1,ON);
}
}
|
Please help me if you can, thanks yours ! _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Aug 03, 2015 1:30 pm |
|
|
Little key thing to understand. If using FAST_GLCD, you have to tell the display to redraw after you make the changes.
"//// Use #define FAST_GLCD if the target chip has at least 1k of RAM ////
//// to decrease the time it takes to update the display. ////
//// glcd_update() must then be called to update the display after ////
//// changing the pixel information. ////
//// See ex_glcd.c for suggested usage. "
Unless you call glcd_update, nothing will be displayed.
It is 'read the notes and example' stuff..... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|