|
|
View previous topic :: View next topic |
Author |
Message |
orazio
Joined: 03 Sep 2010 Posts: 27
|
Problem Interfacing PIC18F8723 and MCP23016 |
Posted: Sun Oct 28, 2012 10:44 am |
|
|
Good Morning,
I'm using CCS 4.084 compiler and PIC 18F8723.
I have connected my PIC18F8723 with MCP23016 io expander by microchip, and i want to use it as output (all 16 channels).
I set MCP23016 address to 0x40.
As described in microchip AppNote AN245 i have followed the schematics "MCP23016 I/O EXPANDER SCHEMATIC (SHEET 1 OF 2)"
to interface MCP23016 to my PIC, apart following differences:
-PIN 14 (MCP23016 SCLK) was connect to PIN 64 (PIC18F8723 SCLK)
-PIN 15 (MCP23016 SDA) was connect to PIN 65 (PIC18F8723 SDA)
-Pull-ups both SDA and SCLK to +5V using a 2.7K resistor.
-PIN 16 (MCP23016 A0) was connect to PIN 68 (PIC18F8723 RD2)
-PIN 17 (MCP23016 A1) was connect to PIN 67 (PIC18F8723 SD3)
-PIN 18 (MCP23016 A2) was connect to PIN 68 (PIC18F8723 SD4)
This is my code:
Code: |
#include <18f8723.h>
#fuses HS,NOWDT,PROTECT,NOLVP,NOMCLR
#use delay(clock=25000000)
#use I2C(master, sda=PIN_D5, scl=PIN_D6, FORCE_HW)
#include <stdlib.h>
#include <string.h>
// COMMAND BYTE
#define GP0 0x00
#define GP1 0x01
#define OLAT0 0x02
#define OLAT1 0x03
#define IPOL0 0x04
#define IPOL1 0x05
#define IODIR0 0x06
#define IODIR1 0x07
#define INTCAP0 0x08
#define INTCAP1 0x09
#define IOCON0 0x0A
#define IOCON1 0x0B
void write_to_MCP(unsigned char WriteAddress, unsigned char cmdByte,unsigned char Data1, unsigned char Data2) {
i2c_start();
delay_us(20);
i2c_write(WriteAddress);
delay_us(20);
i2c_write(cmdByte);
delay_us(20);
i2c_write(Data1);
delay_us(20);
i2c_write(Data2);
delay_us(20);
i2c_stop();
delay_us(50);
}
void init_mcp23016(unsigned char MCP23016_Device_Address) {
write_to_MCP(MCP23016_Device_Address, IPOL0, 0x00, 0x00);
write_to_MCP(MCP23016_Device_Address, OLAT0, 0x00, 0x00);
write_to_MCP(MCP23016_Device_Address, IODIR0, 0x00, 0x00);
}
Init_All_Outputs() {
unsigned char ADR0_GP0= 0XFF;
unsigned char ADR0_GP1= 0XFF;
init_mcp23016(0x40);
write_to_MCP(0x40, OLAT0, ADR0_GP0, ADR0_GP1);
Delay_ms(10);
}
void main(){
delay_ms(1000);
output_low(PIN_D2); //Address mcp23016 000 => 0100 0000 = 40 Hex
output_low(PIN_D3);
output_low(PIN_D4);
output_float(PIN_D6);
output_float(PIN_D5);
Init_All_Outputs();
write_to_MCP(0x40, GP0, 0xFF, 0xFF);
while(true) {
write_to_MCP(0x40, GP0, 0x01, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x02, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x04, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x08, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x10, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x20, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x40, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x80, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x00, 0x01);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x00, 0x02);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x00, 0x04);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x00, 0x08);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0x00, 0x00);
delay_ms(1500);
write_to_MCP(0x40, GP0, 0xFF, 0xFF);
delay_ms(1500);
}
}
|
I have installed successfully the file firmware .hex in my PIC, but it doesn't work because i don't command the expander io. I see, always, all 16 channel of MCP23016 to 0 (ZERO).
Please can anyone help me ?
Thaks |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
Problem Interfacing PIC18F8723 and MCP23016 |
Posted: Sun Oct 28, 2012 1:04 pm |
|
|
Are you sure the PIC is running? If so, how?
If not, try putting output_toggle() commands in the code to
toggle LEDs and confirm it is even executing. Then you start
debugging the code. I would suspect, if the processor is running,
it may be hanging someplace.
Also, in the code library, there is a "MCP23016 simple driver" by PICoHolic
that you might look into.... _________________ Google and Forum Search are some of your best tools!!!! |
|
|
orazio
Joined: 03 Sep 2010 Posts: 27
|
Problem Interfacing PIC18F8723 and MCP23016 |
Posted: Sun Oct 28, 2012 2:36 pm |
|
|
Yes, I'm sure that PIC is running !
I have connected a led in RG3 Pin, and i have added output_bit(PIN_G3,1) in my code. When the PIC run i see the led ON.
As you proposed, I have found "MCP23016 simple driver" by PICoHolic.
So I have tried using following code:
Code: |
#include <18f8723.h>
#fuses HS,NOWDT,PROTECT,NOLVP,NOMCLR
#use delay(clock=25000000)
#use I2C(master, sda=PIN_D5, scl=PIN_D6, FORCE_HW)
#include <stdlib.h>
#include <string.h>
#ifndef MCP23016
#define MCP23016
#define MCP_write 0B01000000
#define MCP_read 0B01000001
#define GP0 0x00
#define GP1 0x01
#define OLAT0 0x02
#define OLAT1 0x03
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void InitMCP23016(int8 AddressSelect, int8 P0, int8 P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(IODIR0);
delay_us(20);
i2c_write(P0);
delay_us(20);
i2c_write(P1);
delay_us(20);
i2c_stop();
delay_us(20);
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(IOCON0);
delay_us(20);
i2c_write(0x01);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void GetGPx(int8 AddressSelect, int8 *P0, int8 *P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(GP0);
delay_us(20);
i2c_stop();
delay_us(50);
i2c_start();
delay_us(20);
i2c_write(MCP_read | (AddressSelect << 1));
delay_us(20);
*P0 = i2c_read();
delay_us(20);
*P1 = i2c_read(0);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void SetGPx(int8 AddressSelect, int8 P0, int8 P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(OLAT0);
delay_us(20);
i2c_write(P0);
delay_us(20);
i2c_write(P1);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void GetINTGPx(int8 AddressSelect, int8 *P0, int8 *P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(INTCAP0);
delay_us(20);
i2c_stop();
delay_us(50);
i2c_start();
delay_us(20);
i2c_write(MCP_read | (AddressSelect << 1));
delay_us(20);
*P0 = i2c_read();
delay_us(20);
*P1 = i2c_read(0);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void SetGPREG(int8 AddressSelect, int8 REG, int8 Data)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(REG);
delay_us(20);
i2c_write(Data);
delay_us(20);
i2c_stop();
delay_us(50);
}
#endif
void main(){
delay_ms(1000);
output_bit(PIN_G3,1);
output_low(PIN_D2); //Address mcp23016 000 => 0100 0000 = 40 Hex
output_low(PIN_D3);
output_low(PIN_D4);
output_float(PIN_D6);
output_float(PIN_D5);
delay_ms(2000);
InitMCP23016(0x40,0x00,0x00);
delay_ms(350);
SetGPx(0x40, 0xFF, 0xFF);
while(true) {
}
} |
I have installed the firmware in my PIC, but it doesn't work. I see the LED ON, but I see, always, all 16 channel of MCP23016 to 0 (ZERO).
Any suggestion will be appreciated.
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Sun Oct 28, 2012 3:13 pm |
|
|
Turning the LED 'on', doesn't prove the critical question - how fast it is going.
_Always_, start with a simple 'flash an LED' program, set to flash at (say) 1 second, and before trying to track down code problems, verify that your chip is running at the expected speed. Until this is right, your chip is not genuinely 'running', it is just waking up....
Why are you driving the chip's address lines from the PIC?. This is complex, and wastes pins on the PIC. The point of the address lines is they are meant to be 'hard wired' to specific patterns to allow multiple chips to be used on the same bus. It doesn't say in the data sheet, but on many chips like this the lines need to be setup _before_ the chip wakes up....
Best Wishes |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sun Oct 28, 2012 3:13 pm |
|
|
You are getting short with me because you think I'm asking a stupid
question. This situation crops up constantly and I don't assume anything
(you shouldn't either). The key to troubleshooting is to progress in steps
and prove each step before proceeding, where many people assume and
get into trouble.
Your routines may be hanging in the middle somewhere. I2C can (and will)
hang and stop executing if something is not right.
The output command you used doesn't tell you anything except the
processor executed the first few lines. The reason why I suggested
OUTPUT_TOGGLE is because you will know the entire loop is being
executed repeatedly if the LED toggles on and off. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
orazio
Joined: 03 Sep 2010 Posts: 27
|
Problem Interfacing PIC18F8723 and MCP23016 |
Posted: Sun Oct 28, 2012 3:47 pm |
|
|
Sorry, but i haven't understood your suggestion.
Ok Ttelmah, i have modified the code to flash LED ON/OFF each second.
But excuse me, what do you mean when you say "verify that your chip is running at the expected speed"? Can you explain better?
This is the code
Code: |
#include <18f8723.h>
#fuses HS,NOWDT,PROTECT,NOLVP,NOMCLR
#use delay(clock=25000000)
#use I2C(master, sda=PIN_D5, scl=PIN_D6, FORCE_HW)
#include <stdlib.h>
#include <string.h>
#ifndef MCP23016
#define MCP23016
#define MCP_write 0B01000000
#define MCP_read 0B01000001
#define GP0 0x00
#define GP1 0x01
#define OLAT0 0x02
#define OLAT1 0x03
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1
//////////////////////////////////////////////////////////////////////////////
int1 x =0x01;
//////////////////////////////////////////////////////////////////////////////
void InitMCP23016(int8 AddressSelect, int8 P0, int8 P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(IODIR0);
delay_us(20);
i2c_write(P0);
delay_us(20);
i2c_write(P1);
delay_us(20);
i2c_stop();
delay_us(20);
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(IOCON0);
delay_us(20);
i2c_write(0x01);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void GetGPx(int8 AddressSelect, int8 *P0, int8 *P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(GP0);
delay_us(20);
i2c_stop();
delay_us(50);
i2c_start();
delay_us(20);
i2c_write(MCP_read | (AddressSelect << 1));
delay_us(20);
*P0 = i2c_read();
delay_us(20);
*P1 = i2c_read(0);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void SetGPx(int8 AddressSelect, int8 P0, int8 P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(OLAT0);
delay_us(20);
i2c_write(P0);
delay_us(20);
i2c_write(P1);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void GetINTGPx(int8 AddressSelect, int8 *P0, int8 *P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(INTCAP0);
delay_us(20);
i2c_stop();
delay_us(50);
i2c_start();
delay_us(20);
i2c_write(MCP_read | (AddressSelect << 1));
delay_us(20);
*P0 = i2c_read();
delay_us(20);
*P1 = i2c_read(0);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void SetGPREG(int8 AddressSelect, int8 REG, int8 Data)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(REG);
delay_us(20);
i2c_write(Data);
delay_us(20);
i2c_stop();
delay_us(50);
}
#endif
void main(){
delay_ms(1000);
output_bit(PIN_G3,1);
output_low(PIN_D2); //Address mcp23016 000 => 0100 0000 = 40 Hex
output_low(PIN_D3);
output_low(PIN_D4);
output_float(PIN_D6);
output_float(PIN_D5);
delay_ms(2000);
InitMCP23016(0x40,0x00,0x00);
delay_ms(350);
SetGPx(0x40, 0xFF, 0xFF);
while(true) {
x=x^0x01;
output_bit(PIN_G3,x);
delay_ms(1000)
}
}
|
I see the LED flashing ON/OFF each second, but all 16 channel of MCP23016 are to 0 (ZERO).
I'm a developer. My electronic engineer project the board and he decides to drive the chip's address lines from the PIC; probably because the data sheet doesn't say that many chips like this the lines need to be setup _before_ the chip wakes up.
Do you think could be this the problem?
Thanks for your interest.
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Oct 28, 2012 5:12 pm |
|
|
Quote: | I'm a developer. My electronic engineer project the board and he decides to drive the chip's address lines from the PIC; probably because the data sheet doesn't say that many chips like this the lines need to be setup _before_ the chip wakes up.
Do you think could be this the problem? | Very well possible this is a problem. At least it is wasting I/O pins on your processor, it makes no sense to add an I/O-expander chip and then waste 3 pins like this.
You might be lucky there probably is a workaround for the power-up feature: the MCP23016 has a power-up timer of approximately 72ms. When you ensure your PIC wakes up faster and sets the I/O pins immediately it might work. Get rid of your initial delay routines and add the NOPUT fuse to disable the PIC's Power Up Timeout.
Disadvantage is that the NOPUT fuse will make your PIC less stable in starting up after power on. You might consider revising your hardware to comply to the Microchip advised design.
For reference here a link to the driver you used: http://www.ccsinfo.com/forum/viewtopic.php?t=29024
Just a few minor notes: Code: | InitMCP23016(0x40,0x00,0x00); | Your driver already adds the 0x40 offset so you should use the base register addresses (i.e. 0). Code: | InitMCP23016(0x00,0x00,0x00); | Fix also for your SetGPx() call.
Code: | x=x^0x01;
output_bit(PIN_G3,x); | Shorter and easier to read:
Code: | output_toggle(PIN_G3); |
Code: | #ifndef MCP23016
#define MCP23016 | This is not used in your program and can be removed.
Code: | output_float(PIN_D6);
output_float(PIN_D5); | This doesn't hurt, but isn't doing anything either as the D5 and D6 outputs were overruled by enabling the I2C module.
Last edited by ckielstra on Sun Oct 28, 2012 5:27 pm; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9240 Location: Greensville,Ontario
|
|
Posted: Sun Oct 28, 2012 5:26 pm |
|
|
Something else to try, is the I2C test program here from PCMprogrammer. It would verify that the PIC can communicate with the I2C device.
You might have a bad 23016 and no amount of good (ie working) code would actually run right. Or perhaps a bad wiring/solder connections ,etc.
sometimes hardware can be faulty...
hth
jay |
|
|
orazio
Joined: 03 Sep 2010 Posts: 27
|
|
Posted: Sun Oct 28, 2012 5:45 pm |
|
|
Thank you ckielstra. I have followed your suggestion and I have solved the problem.
This is the code
Code: |
#include <18f8723.h>
#fuses HS,NOWDT,PROTECT,NOLVP,NOMCLR,NOPUT
#use delay(clock=25000000)
#use I2C(master, sda=PIN_D5, scl=PIN_D6, FORCE_HW)
#include <stdlib.h>
#include <string.h>
#define MCP_write 0B01000000
#define MCP_read 0B01000001
#define GP0 0x00
#define GP1 0x01
#define OLAT0 0x02
#define OLAT1 0x03
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void InitMCP23016(int8 AddressSelect, int8 P0, int8 P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(IODIR0);
delay_us(20);
i2c_write(P0);
delay_us(20);
i2c_write(P1);
delay_us(20);
i2c_stop();
delay_us(20);
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(IOCON0);
delay_us(20);
i2c_write(0x01);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void GetGPx(int8 AddressSelect, int8 *P0, int8 *P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(GP0);
delay_us(20);
i2c_stop();
delay_us(50);
i2c_start();
delay_us(20);
i2c_write(MCP_read | (AddressSelect << 1));
delay_us(20);
*P0 = i2c_read();
delay_us(20);
*P1 = i2c_read(0);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void SetGPx(int8 AddressSelect, int8 P0, int8 P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(OLAT0);
delay_us(20);
i2c_write(P0);
delay_us(20);
i2c_write(P1);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void GetINTGPx(int8 AddressSelect, int8 *P0, int8 *P1)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(INTCAP0);
delay_us(20);
i2c_stop();
delay_us(50);
i2c_start();
delay_us(20);
i2c_write(MCP_read | (AddressSelect << 1));
delay_us(20);
*P0 = i2c_read();
delay_us(20);
*P1 = i2c_read(0);
delay_us(20);
i2c_stop();
delay_us(50);
}
//////////////////////////////////////////////////////////////////////////////
void SetGPREG(int8 AddressSelect, int8 REG, int8 Data)
{
i2c_start();
delay_us(20);
i2c_write(MCP_write | (AddressSelect << 1));
delay_us(20);
i2c_write(REG);
delay_us(20);
i2c_write(Data);
delay_us(20);
i2c_stop();
delay_us(50);
}
//#endif
void main(){
delay_ms(10);
output_low(PIN_D2); //Address mcp23016 000 => 0100 0000 = 40 Hex
output_low(PIN_D3);
output_low(PIN_D4);
delay_ms(2000);
InitMCP23016(0x00,0x00,0x00);
delay_ms(350);
SetGPx(0x00, 0xFF, 0xFF);
while(true) {
output_toggle(PIN_G3);
delay_ms(1000);
}
} |
Now the led flash and I can command the io expander output.
The solution is to put MCP 23016's A0,A1,A2 pins 'hard wired' to ground. ("massa")
My electronic enginner must revise the hardware.
Thanks to all. Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Mon Oct 29, 2012 2:11 am |
|
|
As you saw, I had a 'nasty feeling' that was the case...
It is true of a lot of I2C devices. They are not designed to be 'mobile' on the bus, but to be at fixed addresses that are set before the bus becomes active. The address pins allow multiples of the same device to be on the bus.
I had run into this before, on a system where we had a long I2C bus (with extenders), and wanted sub boards to have different addresses set in software. We had to add circuitry so the processor controlled the supply to the chip, set the address, and only then wake up the chip, to make it work. Again the data sheet did not 'say'....
Best Wishes |
|
|
|
|
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
|