Author Topic: Help Me Continue My I2C  (Read 17263 times)

0 Members and 1 Guest are viewing this topic.

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #25 on: August 02, 2014, 10:57:45 pm »
Bingo600

Thanks for the advice and reminding me that I do have a 5V Arduino board..

 I've been looking a few ARM 3.3V MCU's and I forget the ATMEG2560 was a 5V device.

What do you use software and hardware breadboard wise to work with ARM?

Can you actually say that you have found something as easy to use, reliable, as bug-free as PIC chips, a competent IDE that allows easy compiling, chip programming, compared to PIC.. as easy to use?
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26891
  • Country: nl
    • NCT Developments
Re: Help Me Continue My I2C
« Reply #26 on: August 03, 2014, 12:16:28 am »
Most NXP ARM controllers are 5V tolerant even though they use a 3.3V supply. The documentation is good and judging from the comments from others the LPCExpresso software is easy to use.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #27 on: August 03, 2014, 03:02:57 am »
Thanks again 22swg!
Yes I have a very steady hand.

I am a little uncertain on how to continue with the PIC16F886 based idea, my code uses now, compiled 90% of the 8k available and I can see that I am not getting anywhere troubleshooting the i2c problem. I got to reread the i2C interfacing again to catch what is wrong. The Master--->Slave dialog is only succeeding if getting a complete byte transfer burst only once in approx.  any 10-seconds of operation which is entirely,  to put it simply, goofy.

I have the option, if not perhaps the good sense, to try to use PIC16F887's and use my own 4-wire communication protocol which I have already spent weeks perfecting several years ago. Having a two I/O pins for irq trigger and dedicated state machine control signals for handshake dialog and then the other two other pins, Serial Data/Serial clock pins makes the communication job much easier and independent of interrupt complications and there is then no handshake ambiguity or uncertainty of which byte or bit is which and what direction they are going in.

I can see the advantage of using a single chip, but the idea of remotely locating the individual chips right near the motors is much more compact and sensible for the large currents, sensors and drivers involved, but I still embrace my goal and like the idea of a  centralized MCU Master-Slaves type of operation and control.

I can see it will be some while before I catch up with the robotic work being done in Japan or even the sleep I've lost.
« Last Edit: August 03, 2014, 03:32:08 am by SuzyC »
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Help Me Continue My I2C
« Reply #28 on: August 03, 2014, 08:21:26 am »
The distributed intelligence , for even 'simple' robots would be the way I would go, perhaps I2C is not the method , dare I ask if you looked at SPI , not been there but has higher speed and 4 wires...  Dogged persistence must be in EE blood...  :-+



 
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26891
  • Country: nl
    • NCT Developments
Re: Help Me Continue My I2C
« Reply #29 on: August 03, 2014, 10:24:32 am »
I wouldn't use SPI. I2C is a bit more rugged in noisy environments.

@SuzyC: I'd start with a single controller. Creating a distributed system requires careful partitioning of a system. You'll find you often have to share much more data than you initially think which increases the amount of communication between various CPUs.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Help Me Continue My I2C
« Reply #30 on: August 03, 2014, 11:17:08 am »
Quote
Can you actually say that you have found something as easy to use,

Ease of use is highly personal, and in the case of PIC, I would argue that on some respect it is quite difficult to use, but its simplicity (primitive?) helps.

Quote
reliable, as bug-free as PIC chips,

Its simplicity.

Quote
a competent IDE that allows easy compiling, chip programming, compared to PIC.. as easy to use?

I would argue that either MPLAB or MPLAB X is the opposite of a competent IDE. Because of that, I don't use PIC18 (for a lack of good IDE). For 10/12/16 chips, I use hi-tide, and for 24f chips, I use emBlocks.

Going to an avr would add no meaningful value.

Going to an arm offers you more flexibility, better IDEs (CoIDE or either Keil / IAR), more hardware debugging capabilities and an upward path. However, it is considerably more complex to code than an 8-bit chip.

As to your trouble, I do not know of a i2c slave that is not coded via a state machine. NXP used to have lots of examples for their LPC21xx chips that demonstrated how that can be done - those code pieces are directly portable to a PIC. If you look at most of the I2C hardware implementations, you will see a state machine in them - STM8 / STM32F for example.

A centralized one-chip solution doesn't fit your application so you have to figure this (I2C slave) out. No way around it.
================================
https://dannyelectronics.wordpress.com/
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Help Me Continue My I2C
« Reply #31 on: August 03, 2014, 12:49:54 pm »
My little grey cells have been pondering during a spell down the allotment....  :-+   , take the I2C comms away from the slave PIC (where the bottle neck is ) and put in an I2C port expander   ... I have used a MCP23008     >:D  ( 8 hard wired  address possible )  lots of possibilities if you increase the wires to 5 ,.,., logic 5V, Gnd , clock, data, interrupt (to master)  TX as many bytes as you like, read the slaves data pins (may be a bit tiresome ), give you back some memory ... 
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Offline senso

  • Frequent Contributor
  • **
  • Posts: 951
  • Country: pt
    • My AVR tutorials
Re: Help Me Continue My I2C
« Reply #32 on: August 04, 2014, 12:52:46 am »
But Microchip has like a million different parts, you can throw a dsPIC in DIP-40 and have a much faster core, lots of timers, pwm, fast ADC, and a LOT of goodies, the compilers might be or not crap, but they are free-ish, download them and buy a PIC designed in this century.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26891
  • Country: nl
    • NCT Developments
Re: Help Me Continue My I2C
« Reply #33 on: August 04, 2014, 10:38:30 am »
Going to an arm.... However, it is considerably more complex to code than an 8-bit chip.
Nonsense. It is just as easy or difficult. An ARM microcontroller is just like any microcontroller: a CPU, memory and peripherals. There is nothing magical about it and no high wall to climb. And you know it (LPC21xx are ARM microcontrollers after all):
Quote
NXP used to have lots of examples for their LPC21xx chips that demonstrated how that can be done - those code pieces are directly portable to a PIC.
« Last Edit: August 04, 2014, 10:40:52 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #34 on: August 04, 2014, 02:30:40 pm »
Ok, I've go this code to work half the time. The other time the first test byte sent by Master is not  acknowledged *ack =0
but Addr is *ack=0 and so Slave address match has been detected ok.

 I know when it works and when it's not working, I can see it clearly on the scope.

//And I don't have a clue whatsamatta


//----------------------------------------------------------------------MASTER----------------------------------------------------------------
main()  //most initialization code of chip no shown, not the problem
i2creset();
  i2cinit();  //Sets SSPEN i2c lock TRIS's cbit3,cbit4 as inputs Clk is set on upon setting SSPCON to Master Mode = 0x38
   HmS1=0;
  SSt=Init;
  i2cwrite(); //Master sends bytes to Slave with this routine
start:; //---------------------  START  ------------------------------
  if(SSt==i2cerr) //Alas, most often the case!
   { SSPEN=0;
     i2creset();
     i2cinit();
     SSt=Init;
    HmS1=0;
    i2cwrite();
   }

 else if (SSt==SlvUpDtd) //if everything went well
  { if(HmS1>9) //restarts every second
      {
        SSt=Init;
        HmS1=0;
        i2cwrite();
      }
  }
  goto start;


void WaitMSSP()  //Antifreeze test for SSPIF.     this routine code exactly the same in both Slave and Master
{int k1=0;
  W4IF:
   if(!SSPIF) // while SSPIF=0 stay here else exit the loop
    { if(k1<65535)
       { k1++;
         goto W4IF;
       }
      else
       { SSt=i2cerr;
       }
    }
   SSPIF=0;       // operation completed clear the flag
}

void i2cwrite()
{
wait4ClkHi:

 if(cbit3==0)goto wait4ClkHi; //Wait first for Slave Clk to be ready

 if(SSt==Init) //it is always Init when called by main()
  {
    SEN=1;               // Send i2C Start Condition first
    WaitMSSP();       // A start bit sets SSPIF
    if(SSt==i2cerr)goto i2cWXit; //anti-freezeup
                              //Slave Addr = 0x12
    SSPBUF=Addr;   //0x12 WRITE Sent to Slave Address+WriteCmd


Wait4Ack:
    WaitMSSP();      //Wait for Ack
    if(SSt==i2cerr)goto i2cWXit;
    if(ACKSTAT !=0) goto Wait4Ack; //ACKSTAT=0 if Nack=0(ok) sent by slave

    SSPBUF=0xAA;  //test byte

Wait4Ack1:
    WaitMSSP();
    if(SSt==i2cerr)goto i2cWXit;
    if(ACKSTAT !=0) goto Wait4Ack1;

    SSPBUF=0x55; //test byte

w4b3:
   WaitMSSP();
    if(SSt==i2cerr)goto i2cWXit;
   if(ACKSTAT != 0)goto w4b3;


   for(i=0;i<4;i++)  //4 bytes sent to slave
    {
      if(i==3)
       { SSPBUF=0xA5; //Always the last byte sent to Slave to verify sequence of bytes completed ok
       }
      else SSPBUF=i;  //Just a test byte at this point
w4b4:
      WaitMSSP();
      if(SSt==i2cerr)goto i2cWXit;

      if(ACKSTAT !=0) goto w4b4;

    }
   PEN=1;         // Send stop bit
   WaitMSSP();
   SSt=SlvUpDtd;
  }
goto i2cWExit;

i2cWXit:;
SSPEN=0;  //Error in Master to Slave Session, Reset the whole thing!
SSPCON=0;

i2cWExit:;
}
//--------------------------------------------------MASTER Code Ends -----------------------------------------------------------------------------

//--------------------------------------------------Slave Code Begins (located inside inside ISR)---------------------------------------------

interrupt int_server(void)   
{
T0irq:
if (T0IF)      // TMR0 overflow flag, if set triggers IRQ  TMR0Clk=Clk/2
 { TMR0=17;    //Comp needed to calibrates timer for exactly .1uS/IRQ.
   T0IF=0;       
   pt1_mSec++;
   pt1_mSec1++;
   pt1_mSec2++;   
//---etc code to udate ten_mSec, Hun_mSec counters ...code not shown here
XitTimer:;
 } //------------------------------------------------End of TMR0 ISR--------------------------------------------

if(SSPIF) //set by ADDRESS MATCH, Start or Stop  Start Bit Detected
 {           //CPK is set high by main()
              //Should sends Ack=0 to Master and Sets SSPIF  twice on Master, (once already set by start bit)
   if( (SSt==Idle) ) //always set by main()  to Idle to start i2c conversation
    {
      if( (SSPBUF & 0xFE)==Addr) //*Ack =0 always set by slave if Addr match  Addr = 0x12
       {           
         SSPIF=0;
         BF=0;
         SSt=TxRx;  //After an i2c Addr match 6 bytes follow to be received by this Slave code
         Din[5]=0;  //Must ==0xA5 as a check for valid reception of all bytes sent by Master
         bn=0;       //reset incoming byte counter bn
       }
    }

RecMore:

   if(SSt==TxRx)
    {   
         CKP=1;     //enable reception
W4B0:
         WaitMSSP();  //SSPIF set when buffer is full, Slaves expects a byte
         if(SSt==i2cerr)goto i2cerrxit;
         if(BF==1)    //Byte has been received so SPPBUF is full
          {
            Din[bn]=SSPBUF; //grab the byte and save it in a small array
            CKP=0;          //stretch the clock b4 acknowldege
            if(bn<5)bn++;
            if (bn==5)
             { if ( Din[bn] != 0xA5) //Check for valid transmission sequence
                { CKP=0;
                  SSt=i2cerr;
                  goto i2cerrxit;
                }
               else
                { CKP=0;
                  SSt=Begun; ///Correct Master-Slave session so set SSPI state to Begun = Success
                }
             }                 
          }

         if(SSt==TxRx)
          { CKP=1; //Re-enable SClk
             
          }

    }
goto Xiti2c;

i2cerrxit:  //no error management code yet.  Main just retries again from the start

Xiti2c:
   SSPIF=0;   //No code for Start Condition, just trying to catch the Addr match and work from there
   goto ExitISR;
 }

ExitISR:;
}
« Last Edit: August 04, 2014, 04:53:05 pm by SuzyC »
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #35 on: August 04, 2014, 02:41:21 pm »
Here is the Slave main() for the code above
.......etc
 SSt=Idle;
 CKP=1;      //enable clock line
 SSPIE=1;    //enable SSPI irqs on start stop buffer full
 SSPEN=1;    //Enable i2c
  Sec1=0;   
  HmS1=0;
start:; //--------------------- SLAVE START  ------------------------------
  if(SSt==Begun) //if there only was such a thing as success
   { blink=1; //Fast Blink LED means ok session
     CKP=0;
     SSPIE=0;
     SSPIF=0;
     if(HmS1>20)
      { HmS1=0;
        CKP=1;
        blink=2;
        SSt=Idle;
         SSPIE=1;   //do it again and again
      }
   }
 
  else if(SSt==i2cerr)
   {HmS1=0;
     SSPOV=0;  //Else error   Take it from the top again
     SSPIF=0;
     CKP=1;
     SSPIE=1;
     SSt=Idle;
   }
goto start;
« Last Edit: August 04, 2014, 03:38:39 pm by SuzyC »
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Help Me Continue My I2C
« Reply #36 on: August 04, 2014, 04:19:34 pm »
"half the time "  Thats better than it was  :)  ... I found in I2C asm  the "state machine" made life easier , each interrupt .. start , buffer full, read , write, restart , stop , had a sub to process the data ,
Am i wrong but you seem to enter the ISR for the whole I2C  packet ... anyway  I started to look at my asm code and move it to XC8 , (new to me) to see where Slave problems arise..  I have got to where the ISR fires up on a start ....   


 

   
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #37 on: August 04, 2014, 04:32:11 pm »
Thanks again 22swg!

The code has a if(SSt=TxRx) that is entered initially after an address match and so gets the first byte and thereafter only on an IRQ from SSPIF.

I have an LCD readout on the Master and I kept score.  Each pass on the main() loop the i2cwrite()  (Master to Slave) is invoked with either success or failure and I got 278 good results 1003 failures over 6.5 minutes, i2cwrite() gets a hit every loop that shows a result of the last ry and it gets invoked about 3 times a second in main().
« Last Edit: August 04, 2014, 05:50:04 pm by SuzyC »
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26891
  • Country: nl
    • NCT Developments
Re: Help Me Continue My I2C
« Reply #38 on: August 04, 2014, 05:02:26 pm »
What happens if you lower the data rate of the I2C master to 1kHz? If the communication works perfectly at a much lower rate you can conclude that your software is too slow. Or there might be a hardware problem due to the I2C signals getting distorted by a pull-up resistor which is too large.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #39 on: August 04, 2014, 05:11:29 pm »
Thank you DannyF for your advice!

I can't help but compare to PIC, offering DIP packaging, on serial in-circuit programming, so plugging it in/into a programmer is a snap.

I have not found powerful ARM NX chips on a tiny PCB header to plug right into a project or that can be easily wired for use with a breadboard so common to get that is offering just the basics, the chip with bleed-out for all pins and a place for the clock xtal and caps and programming the chip. For me, In Situ, socketed chips or module On-chip programming is also a must.  The IDE/compiler software you recommend is probably expensive? Needs Linix?

license (£3,349.14 = $ 5412) of KEIL MDK500 for code size >32KB

....Found this comment on a forum also:
The SoftDevice stack is precompiled so it does not count into the 32k limit of the free version of Keil. Most applications will actually fit inside 32k because of the architecture and SDK that Nordic provides. If you need more than 32k, there is always Eclipse and GCC.
Some fellow named Bastiaan (Nov 20 '13)


And would not so much ARM power have a steep learning curve to understand how the chip works (or doesn't in gotchas)?
« Last Edit: August 04, 2014, 08:08:59 pm by SuzyC »
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #40 on: August 04, 2014, 05:31:06 pm »
Thanks for your help ntcnico!

The question is, what is the max. latency in i2c specs for the i2c receiver to respond before the transmitter(Master) 9th i2c clock is going to  go hi? and make a go/no go decision?
My scope shows i2c clock and data rise/fall times of approx 10nS or better. Besides the Addr match always works and sends *Ack.

As I have stated in a previous post, I have tried Master clock speeds as slow as approx many uSec for each hi and lo period using the i2c formula i2c Baud=FOSC/4 (SPPADD+1)  setting SPPADD=0x44) and it did not make any difference at the time.

In fact the approx i2c 1.5uSec clock (SPPADD=4) yielding  a clock hi and lo period of approx 1.5 uSec  seems to work just as well as any other slower clk I have yet tried.

I haven't had the good sense yet to try even snail so slow clock speeds to troubleshoot the problem yet.

I know the Slave ISR can respond to a SSPI IRQ in <15 uSecs and the scope shows that the i2c byte was Tx'd correctly to the slave. If there were no response from the slave once the i2c byte fills the Slave SSPBUF buffer, that would be the problem, but the i2c firmware automatically clears ACK once the buffer is full after and Addr match and then after the Slave buffer is filled again with an incoming byte.

The fact is that the i2c always sends a correct Addr match *Ack, it does this automatically, now immediately after getting the SSPIF set and reset, the Master sends a byte and my Master code WaitMSSP() has a loop that waits up to 65535 iterations of an integer k1++; goto incl., just waiting checking for the SSPIF flag to be set before calling off the game(at least >.1 second before the referee yells Foul!).

Doesn't this code mean that there is a very patient Master waiting for an Ack=0 after a byte sent to the Slave?
« Last Edit: August 04, 2014, 06:52:33 pm by SuzyC »
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #41 on: August 04, 2014, 06:06:11 pm »
SPPADD=0x4;

Latest score:   Successes: 5300   Failures: 17536

Now I'm going to see if slowing the clock speed with my changed code.

"The hurrier I go, the behinder I get!" might apply here.
« Last Edit: August 04, 2014, 06:54:09 pm by SuzyC »
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #42 on: August 04, 2014, 06:15:25 pm »
 :) ;) :)Changed SSPADD for setting i2d clock from 0x4 to 0x8

Score Failures: 55 Success: 38

Changed SSPADD to 0x10

Score Failures: 42 Success: 103

Changed SSPADD to 0x20

Score Failures: 1 Success: 25000  //the one and only error occurred at startup but takes 800uSec for 6-bytes!

Now to find the sweet spot!

Changed SSPADD to 0x18
Score Failures: 6 Success: 50000  //Some errors occur after startup with several seconds between them

Still same SSPADD, 0x18 but just Reset Master and the Slave processor, test 2
Score Failures: 0 Success: 50000  //Just no errors
Still same SSPADD, but just Reset Master and the Slave processor, test 3
Score Failures: 4 Success: 65000  //Just a few errors

Changed SSPADD to 0x14
Score Failures: 20 Success: 1698  //Some errors occur after startup with fractional seconds between them

Changed SSPADD to 0x16
Score Failures: 10 Success: 9363  //Some errors occur after startup with fractional seconds between them

Changed SSPADD to 0x17
Score Failures: 4 Success: 10000  //Some errors occur after startup with fractional seconds between them

//seems to be a pattern here.

And this years IgNobel Prize for Code and i2c Troubleshooting goes to   nctnico  thanx!
 :)  ;) ;) :-+ :-+ :-DMM :-DMM :scared: :scared:
« Last Edit: August 04, 2014, 07:46:12 pm by SuzyC »
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #43 on: August 04, 2014, 06:29:17 pm »
Thanks to everyone!

Now I gotta figure out how to get the Slave to send back the bytes I need to the Master!
I hope it will be easier.
« Last Edit: August 04, 2014, 07:01:19 pm by SuzyC »
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Help Me Continue My I2C
« Reply #44 on: August 04, 2014, 07:57:02 pm »
As a matter of interest what pullup value are you using on clk and data ? 
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #45 on: August 04, 2014, 08:11:03 pm »
22swg:   Thanks Again for your great help and encouragement!

I am using 1 k for both Clk and Data
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Help Me Continue My I2C
« Reply #46 on: August 04, 2014, 09:27:19 pm »
-seems to be a pattern here-

I tend to think that it is a lot more important to know why some numbers worked better than others, not just that some worked better than others.
================================
https://dannyelectronics.wordpress.com/
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Help Me Continue My I2C
« Reply #47 on: August 04, 2014, 09:49:24 pm »
I would consider that too low , normally I use minimum 2k2  ...    this what clk baud should be   • I2C Master mode, clock = OSC/4 (SSPADD +1)
« Last Edit: August 04, 2014, 09:56:02 pm by 22swg »
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Offline SuzyCTopic starter

  • Frequent Contributor
  • **
  • Posts: 792
Re: Help Me Continue My I2C
« Reply #48 on: August 04, 2014, 10:06:04 pm »
If the problem is with pull-up resistors, then 1k should be better for high frequency performance than 1K, unless the problem is not risetime to slow but risetime too fast with overshoot so 2.2K resistors may benefit to lower risetime while not affecting groundbounce.

BTW, I have been looking at 24FV processors and notice that only 3 PWM's per chip. Leaves me with one PWM missing. Otherwise the 32K program mem, 2k RAM 12bit A2D and multiple timers, 16MIPS 5V operation  etc and price seem attractive, but the BOB is perhaps more costly than the PIC for each instantiation.
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Help Me Continue My I2C
« Reply #49 on: August 04, 2014, 10:14:45 pm »
I believe it will take longer to switch 5 milliamps  1k :  than 2 miliamps 2k2 ?    some would recommend 4K7 as pullups especially for 400 khz   
« Last Edit: August 04, 2014, 10:17:21 pm by 22swg »
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf