Author Topic: Reading out the LIS302DL by STmicro  (Read 11314 times)

0 Members and 1 Guest are viewing this topic.

Offline Torrentula

  • Regular Contributor
  • *
  • Posts: 91
  • Country: de
    • My blog
Reading out the LIS302DL by STmicro
« on: September 29, 2012, 04:22:17 pm »
Hello again!

I am currently trying to get the LIS302DL (Datasheet) on my STM32F4 Discovery board up and running but it just refuses to send any response.
I am not using the STM32F4 Firmware library by ST. I have already had a look at it but it's not very helpful because it seems to do exactly what I do as well, with the exception that it works with the STM32F4 Discovery demo application so I know the device is working perfectly fine  ;)

I have set up SPI1 in SPI mode 3, meaning that SCK is high when idle and the data is sampled at the second clock transition (low to high). I have already had a look at the communication lines with an oscilloscope and the SCK, CS and MOSI lines look alright but the LIS302DL will just not send it's data on the MISO line and I don't know why.  >:(

It even refuses to send back it's ID from the WHO_AM_I register...

I set the following bits:
The BOOT bit in CTRL_REG2
The PD, Zen, Yen, Xen bits in the CTRL_REG1

Here are the relevant parts of my code:

The SPI1 routines:

Code: [Select]
void SPI1_init(void){

// configure the SPI1 I/O pins
// used pins on GPIOA
RCC->AHB1ENR |= (1<<0); // enable clock for GPIOA

GPIOA->MODER |= (1<<15) | (1<<13) | (1<<11);    // set PA7 (MOSI), PA6 (MISO) and PA5 (SCK) to Alternate Function (AF)
GPIOA->OTYPER &= ~( (1<<7) | (1<<6) | (1<<5) ); // set PA7, PA6 and PA5 to push pull mode
GPIOA->OSPEEDR |= (1<<15) | (1<<13) | (1<<11);  // set PA7, PA6 and PA5 speed to 50MHz fast speed
GPIOA->PUPDR |= (1<<14) | (1<<12) | (1<<10);    // enable pull-ups on PA7, PA6 and PA5

GPIOA->AFR[0] |= (1<<30) | (1<<28); // connect PA7 to AF5 via AFRL
GPIOA->AFR[0] |= (1<<26) | (1<<24); // connect PA6 to AF5 via AFRL
GPIOA->AFR[0] |= (1<<22) | (1<<20); // connect PA5 to AF5 via AFRL

// used pins on GPIOE
RCC->AHB1ENR |= (1<<4); // enable clock for GPIOE

GPIOE->MODER |= (1<<4);   // set PE2 to GPIO
GPIOE->OTYPER &= ~(1<<2); // set PE2 to push-pull ouput type
GPIOE->OSPEEDR |= (1<<5); // set PE2 speed to 50MHz fast speed
GPIOE->PUPDR |= (1<<4);   // enable pull-up on PE2

// configure SPI1
RCC->APB2ENR |= (1<<12); // enable clock for SPI1

SPI1->CR1 |= (1<<4) | (1<<3); // set SPI clock to F_PCLK / 16
SPI1->CR1 |= (1<<9) | (1<<8) | (1<<2); // set NSS management to internal and set the internal NSS to high, set MSTR bit
SPI1->CR1 |= (1<<1) | (1<<0); // set CPOL high = idle high, set CPHA high = second clock transition is data sample edge
SPI1->CR1 |= (1<<6);          // enable the SPI
}

int8_t SPI1_send(uint16_t data){
SPI1->DR = data; // write value to transmit into the data register
while( !(SPI1->SR & (1<<1)) ); // wait until TXE flag is set --> transmit buffer empty

while( SPI1->SR & (1<<7) );    // wait until SPI1 is not busy anymore

while( !(SPI1->SR & (1<<0)) ); // wait until RXE flag is set --> receive buffer not empty

return SPI1->DR; // read received data from data register and return it
}

Routines and defines for the LIS302DL:

Code: [Select]
// LIS302DL register map
#define LIS302DL_WHO_AM_I 0x0F

#define LIS302DL_CTRL_REG1 0x20
#define LIS302DL_CTRL_REG2 0x21
#define LIS302DL_CTRL_REG3 0x22

#define LIS302DL_STATUS_REG 0x27

#define LIS302DL_OUT_X 0x29
#define LIS302DL_OUT_Y 0x2B
#define LIS302DL_OUT_Z 0x2D

// LIS302DL bits
// communication
#define DUMMY_BYTE 0x00
#define LIS302DL_R 0x80
#define LIS302DL_W 0x00
#define LIS302DL_M 0x40
#define LIS302DL_S 0x00

// CTRL_REG1
#define LIS302DL_XEN 0x01
#define LIS302DL_YEN 0x02
#define LIS302DL_ZEN 0x04
#define LIS302DL_STM 0x08
#define LIS302DL_STP 0x10
#define LIS302DL_FS  0x20
#define LIS302DL_PD  0x40
#define LIS302DL_DR  0x80

// CTRL_REG2
#define LIS302DL_HP_COEFF1 0x01
#define LIS302DL_HP_COEFF2 0x02
#define LIS302DL_HP_FF_WU1 0x04
#define LIS302DL_HP_FF_WU2 0x08
#define LIS302DL_FDS 0x10
#define LIS302DL_BOOT      0x40
#define LIS302DL_SIM 0x80

void LIS302DL_init(void){
uint8_t whoami;

// configure LIS302DL
// A = address bits, D = data bits
//          AADD
GPIOE->BSRRH |= (1<<2); // set PE2 (CS) low
SPI1_send(LIS302DL_CTRL_REG2); // CTRL_REG2 @ 21h,
SPI1_send(LIS302DL_W | LIS302DL_BOOT); // bits BOOT set, R/W and M/S not set
GPIOE->BSRRL |= (1<<2); // set PE2 (CS) high

GPIOE->BSRRH |= (1<<2); // set PE2 (CS) low
SPI1_send(LIS302DL_CTRL_REG1); // CTRL_REG1 @ 20h
SPI1_send(LIS302DL_W | LIS302DL_PD | LIS302DL_ZEN | LIS302DL_YEN | LIS302DL_XEN);   // bits PD, Zen, Yen, Xen, R/W and M/S not set
GPIOE->BSRRL |= (1<<2); // set PE2 (CS) high

Delay(0xFFFF);

GPIOE->BSRRH |= (1<<2);  // set PE2 (CS) low
SPI1_send(LIS302DL_R | LIS302DL_WHO_AM_I); // WHO_AM_I @ 0F, R bit set
whoami = SPI1_send(DUMMY_BYTE); // bits PD, Zen, Yen, Xen, R/W and M/S not set
GPIOE->BSRRL |= (1<<2);  // set PE2 (CS) high

if(whoami == 0x3B){
GPIOD->BSRRH |= (1<<14); // set PD14 low
GPIOD->BSRRL |= (1<<12); // set PD12 high
}
else{
GPIOD->BSRRH |= (1<<12); // set PD12 low
GPIOD->BSRRL |= (1<<14); // set PD14 high
}
}

void LIS302DL_read(void){
GPIOE->BSRRH |= (1<<2);  // set PE2 (CS) low
SPI1_send(LIS302DL_R | LIS302DL_OUT_X); // X_OUT @ 29h, R bit set, M/S not set
accel_x = SPI1_send(DUMMY_BYTE);
GPIOE->BSRRL |= (1<<2);  // set PE2 (CS) high

GPIOE->BSRRH |= (1<<2);  // set PE2 (CS) low
SPI1_send(LIS302DL_R | LIS302DL_OUT_Y);         // Y_OUT @ 2Bh, R bit set, M/S not set
accel_y = SPI1_send(DUMMY_BYTE);
GPIOE->BSRRL |= (1<<2);  // set PE2 (CS) high

GPIOE->BSRRH |= (1<<2);  // set PE2 (CS) low
SPI1_send(LIS302DL_R | LIS302DL_OUT_Z);         // Z_OUT @ 2Dh, R bit set, M/S not set
accel_z = SPI1_send(DUMMY_BYTE);
GPIOE->BSRRL |= (1<<2);  // set PE2 (CS) high
}

Has someone else experienced this problem before?
I really appreciate your help!
« Last Edit: September 29, 2012, 04:26:56 pm by Torrentula »
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 7405
  • Country: us
    • SiliconValleyGarage
Re: Reading out the LIS302DL by STmicro
« Reply #1 on: September 29, 2012, 04:58:45 pm »
do you use the ST bootcode ?

some chips contain hardware discrepancies in relation to the spec . the boot code solves these
the boot code in the ST project is typically a small piece of assembly that is run prior to entering the main function.
check that one out. there may be a patch in there for something spi related ..
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline Torrentula

  • Regular Contributor
  • *
  • Posts: 91
  • Country: de
    • My blog
Re: Reading out the LIS302DL by STmicro
« Reply #2 on: September 29, 2012, 05:22:57 pm »
My project does have the file "startup_stm32f4xx.s" which contains the startup code, it's the one shipped with Keil IDE. I don't think it has to do with the SPI peripheral because sending the data looks perfectly fine on the oscilloscope but the accelerometer actually seems to refuse to answer...

Maybe it's some simple config bit I'm missing out but I have been trying this pretty much all day and now I just can't find anything anymore... I have searched the net already but they all did it the way I do so I really don't know what the problem is right now.

Thanks!
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: us
Re: Reading out the LIS302DL by STmicro
« Reply #3 on: September 29, 2012, 08:45:54 pm »
I've got an FDisco board blinking at me right now. :-) See if you can find a working accelerometer demo program and flash that onto the board. There are a couple that come with ChibiOS (an RTS with good STM32 support), but you can probably get one from ST too. Once you've got it running, scope *that* program and see what the signals should look like.

I've got a project that uses STM32 SPI to talk to a LCD display. The lower levels are all handled by a hardware abstraction layer, but once you get the configurations right, it's pretty simple. One thing that had me scratching my head was the slave select. My code toggles it explicitly, but that may be because I'm using DMA instead of a byte-by-byte spin-wait.

If you've got a good clock on the scope and your chip select is doing the right thing, maybe the initialization sequence for the '302 is off somehow?
 

Offline Torrentula

  • Regular Contributor
  • *
  • Posts: 91
  • Country: de
    • My blog
Re: Reading out the LIS302DL by STmicro
« Reply #4 on: September 30, 2012, 08:07:36 am »
Ok now I feel dumb... should've checked this in the first place.

The the STM32F4 Discovery documentation shows on page 28 that the CS pin of the LIS302DL is connected to PE2.
The library uses PE3 as the CS pin, and what do you know? It actually works fine with PE3 being CS!

Again another day of work wasted due to crappy ST documentation but now it works at least...


EDIT: Now it's only turning out random or no data. The data is all over the place without even touching / moving it... I have no clue what's wrong this time but it has become touchy to get it working with the demo as well so I might have fried the chip...
« Last Edit: September 30, 2012, 01:09:14 pm by Torrentula »
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: us
Re: Reading out the LIS302DL by STmicro
« Reply #5 on: September 30, 2012, 04:29:49 pm »
Seems unlikely that you could have fried anything unless you were making physical changes to the board.
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2018
  • Country: nl
Re: Reading out the LIS302DL by STmicro
« Reply #6 on: October 10, 2012, 05:10:39 pm »
Thanks for the code snippets. After changing PE2 to PE3 it worked straight away. :)


The the STM32F4 Discovery documentation shows on page 28 that the CS pin of the LIS302DL is connected to PE2.
The library uses PE3 as the CS pin, and what do you know? It actually works fine with PE3 being CS!

Indeed. Incidentally, on page 36 the schematic does correctly show PE3 being used for CS.Probably a last minute revision that didn't quite make it to the written docs.



 

Offline Torrentula

  • Regular Contributor
  • *
  • Posts: 91
  • Country: de
    • My blog
Re: Reading out the LIS302DL by STmicro
« Reply #7 on: October 14, 2012, 03:07:25 pm »
Yep seems like it just wasn't picked up by the documentation guy or just forgotten (we all make mistakes, right?) - annoying but I'm glad it works now :)
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2018
  • Country: nl
Re: Reading out the LIS302DL by STmicro
« Reply #8 on: October 14, 2012, 05:03:47 pm »
Yep seems like it just wasn't picked up by the documentation guy or just forgotten (we all make mistakes, right?) -

Indeed. It's just a bit unfortunate that documentation guys at ST are more prone to such mistakes than some other companies. ;-) Or maybe we should just blame the non-quality assurance department. :P

Anyways, about this bit of code ...

Code: [Select]
// configure the SPI1 I/O pins
// used pins on GPIOA
RCC->AHB1ENR |= (1<<0); // enable clock for GPIOA

GPIOA->MODER |= (1<<15) | (1<<13) | (1<<11);    // set PA7 (MOSI), PA6 (MISO) and PA5 (SCK) to Alternate Function (AF)
GPIOA->OTYPER &= ~( (1<<7) | (1<<6) | (1<<5) ); // set PA7, PA6 and PA5 to push pull mode
GPIOA->OSPEEDR |= (1<<15) | (1<<13) | (1<<11);  // set PA7, PA6 and PA5 speed to 50MHz fast speed
GPIOA->PUPDR |= (1<<14) | (1<<12) | (1<<10);    // enable pull-ups on PA7, PA6 and PA5

GPIOA->AFR[0] |= (1<<30) | (1<<28); // connect PA7 to AF5 via AFRL
GPIOA->AFR[0] |= (1<<26) | (1<<24); // connect PA6 to AF5 via AFRL
GPIOA->AFR[0] |= (1<<22) | (1<<20); // connect PA5 to AF5 via AFRL

Any particular reason to use that style of coding? No right or wrong here, just curious. It works, so no arguments there. I personally just find it less readible. Certainly because I am an stm32 n00b, so I don't know all the funky bit locations in the registers. So right now I use something like this:

Code: [Select]
GPIO_InitTypeDef  GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

/* Configure PA5, PA6, PA7 in alternate function push-pull mode */
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5 | GPIO_Pin_6| GPIO_Pin_7;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP; // maybe use GPIO_PuPd_NOPULL ?
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); // SCK
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); // MISO
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); // MOSI

That does the same as your code snippet, but for me this is a bit easier to maintain. Mostly when I want to use the same code snippet, but then for say SPI2. I don't know the bit locations in the AFR registers without checking a datasheet. But changing GPIO_AF_SPI1 to GPIO_AF_SPI2 I think I can manage without too much chance of introducing an error. ;-)

So I was wondering if there was any specific reason to use the GPIOA->AFR[0] |= (1<<30) | (1<<28); code style? All I can think of is maybe smaller code size and faster execution... While that is nice, personally I favor code that is maintainable and less error prone. Certainly for initialization code that runs only once.

Anyways, just wondering if there's a particular reason... :)
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: us
Re: Reading out the LIS302DL by STmicro
« Reply #9 on: October 14, 2012, 10:31:13 pm »
Any particular reason to use that style of coding? No right or wrong here, just curious.
It may be a matter (again) of documentation. Sometimes the hardware datasheets are much easier to deal with than OEM firmware documentation. The register info in the datasheet is all about bit fields and that leads to the "(x << y)" type of code.
 

Offline Torrentula

  • Regular Contributor
  • *
  • Posts: 91
  • Country: de
    • My blog
Re: Reading out the LIS302DL by STmicro
« Reply #10 on: October 15, 2012, 09:57:38 am »
Quote
Any particular reason to use that style of coding? No right or wrong here, just curious.

No it doens' really matter how you do it and yes your code is probably easier to maintain, the only reason I do this is that I wanted to get the thing up and running with the Keil IDE and I could't seem to figure out how to get the peripheral lib by ST to get compiled into that project.

The maintainability is a good argument and I would prefer to use that style as well, the problem is that I just don't want to always turn on my laptop in order to use the toolchain built for Linux.

I am still looking for some good explanation on how to get Keil to use the ST peripheral lib so if you have any information on how to set up Keil correctly then I'd appreciate it ;) 
 

Online andersm

  • Super Contributor
  • ***
  • Posts: 1149
  • Country: fi
Re: Reading out the LIS302DL by STmicro
« Reply #11 on: October 15, 2012, 11:58:45 am »
So I was wondering if there was any specific reason to use the GPIOA->AFR[0] |= (1<<30) | (1<<28); code style?
ST's library code at least used to be miserably slow. Doesn't matter for initialization code, but on one project some bit-banging code ran probably an order of magnitude faster after switching to accessing the GPIO port registers directly.

I am still looking for some good explanation on how to get Keil to use the ST peripheral lib so if you have any information on how to set up Keil correctly then I'd appreciate it
It's been a while since I used Keil, but does't it set up that automatically when you create a new project? If you want to use an external copy of the library, the download should come with some example projects or you could adapt one of ST's sample projects from their website.

Offline Torrentula

  • Regular Contributor
  • *
  • Posts: 91
  • Country: de
    • My blog
Re: Reading out the LIS302DL by STmicro
« Reply #12 on: October 15, 2012, 02:37:17 pm »
Yep Keil includes it's own peripheral lib but I just figured out how to set this thing up after about an hour of checking build commmands etc.
The thing with the lib specifically provided for the STM32F4 Discovery is that it also includes functions for the LIS302DL and the onboard Cirrus Logic audio DAC.

I wouldn't bother with using functions to do such simple tasks as setting a bit in an output data register like so:
Code: [Select]
GPIOD->BSRRL |= (1<<15); // set PD15 high
GPIOD->BSRRH |=  (1<<14); // set PD14 low
GPIOD->ODR |= (1<<13); // set PD13 high
GPIOD->ODR &= ~(1<<12); // set PD12 low

Calling a function to do this would be a waste of execution time because in the given application you will know which pins you are using for bit banging.

Initializing a peripheral is different though because much more bits have to be set and that's where the library comes in handy and does all the non time-critical initialization stuff for you.

OT: Does anyone know of a good screen recording software for Windows? What does Dave use? I might do a video on how to get this thing to work.
« Last Edit: October 15, 2012, 02:42:15 pm by Torrentula »
 

Offline OndraSter

  • Contributor
  • Posts: 40
  • Country: cz
Re: Reading out the LIS302DL by STmicro
« Reply #13 on: October 17, 2012, 11:06:26 pm »
Not sure how about Dave, but I use Microsoft's Expression Encoder http://www.microsoft.com/expression/products/EncoderPro_Overview.aspx - I have done few recordings without any issues - just install and use.
XBoard coco. When Arduino is not enough!

(Website + first sampled boards coming in August.)
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2018
  • Country: nl
Re: Reading out the LIS302DL by STmicro
« Reply #14 on: October 18, 2012, 12:50:35 am »
No it doens' really matter how you do it and yes your code is probably easier to maintain, the only reason I do this is that I wanted to get the thing up and running with the Keil IDE and I could't seem to figure out how to get the peripheral lib by ST to get compiled into that project.
...
I am still looking for some good explanation on how to get Keil to use the ST peripheral lib so if you have any information on how to set up Keil correctly then I'd appreciate it ;)

The toolchain situation would be a good enough reason, yes. ;)

No explanations on Keil from me I'm afraid.... Under linux I use the obligatory eclipse + arm-none-eabi combo. And on windoze I use Atollic, which is based on eclipse. That way I can use inspiration gleaned from the atollic install on the linux install. Out of sheer frustration I caved in and installed atollic, which at least worked out of the box. Then when I slowly got the hang of it I moved to linux again...

I guess my point is, you could try Atollic. That worked straight away without any crazy library setup required. You can install the Lite version (making sure to [X] check the ST-Link install). After that you can do Import => Example from Teh Internets => your fav demo board => Blinkenlights, etc. That got me up and running fairly quick.

As for this code snippet:
Code: [Select]
GPIOD->BSRRL |= (1<<15); // set PD15 high
GPIOD->BSRRH |=  (1<<14); // set PD14 low

You may want to do this:
Code: [Select]
GPIOD->BSRRL = (1<<15); // set PD15 low
GPIOD->BSRRH =  (1<<14); // set PD14 high

Note that the low/high situation is precisely opposed to what was in your comments. You probably grabbed some random googled code, but just so you know. In case you didn't know, then this serves as a nice example of "optimization" vs "the illusion of optimization". Because even the crappy ST lib results in something faster than the inadvertent |= based code. Your code with the bit-wise or results in a read-modify-write, which results in waaay too many instructions. The above does it's thing in 4 instructions as you'd expect.

Personally I am still perfectly happy to use this equivalent:
Code: [Select]
GPIO_ResetBits(GPIOD, GPIO_Pin_15 | GPIO_Pin_14);
GPIO_SetBits(GPIOD, GPIO_Pin_13 | GPIO_Pin_12);

... certainly for non-critical things as blink-the-led.

The rationale for using the GPIOx->ODR notation for bit-banging is only partially rational IMO. One of the reasons why I picked the stm32f4 is because it has a nice set of peripherals, precisely so I would not have to do any bit-banging to do trivial mundane boring stuff like i2c or spi.

All the stuff I've used so far on it could either be handled by the onboard peripherals, OR was slow enough that I didn't really care too much about optimizing it to the ns.

Incidentally, if you are going the optimization route you might as well do this for the previous bit of code:
Code: [Select]
*((__IO uint32_t *)&GPIOD->BSRRL) = 0xC0003000; // PD15=PD14 = 0 , PD13=PD12=1

That does a 32-bit write to the BSRRL and BSRRH registers in one go. I was curious if the BSRR register accepts 32-bit writes, and indeed it does. It even gives the right result. ;) I just checked it on my discovery board and 1) the leds go blinkie as intended, and 2) the resulting asm for it is 3 instructions. Two for the constant loads, and one for the write. That's with -O1 optimization.

And no, I don't advocate using that code. But if you want to optimize like that, might as well go all the way and shave of 25% of your execution time. :P
 

Online andersm

  • Super Contributor
  • ***
  • Posts: 1149
  • Country: fi
Re: Reading out the LIS302DL by STmicro
« Reply #15 on: October 18, 2012, 01:12:11 am »
The BSRR register (bit set reset register register?) also has the nice property that the "set" bit has precedence over the "reset" bit, so you can have the "reset" part be a constant mask of all the GPIO pins and put the actual data in the "set" bits. Much nicer than having to do the read-modify-write dance.

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2018
  • Country: nl
Re: Reading out the LIS302DL by STmicro
« Reply #16 on: October 18, 2012, 01:59:08 pm »
Yeah, I noticed that as well. Very handy feature, that.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: us
Re: Reading out the LIS302DL by STmicro
« Reply #17 on: October 18, 2012, 02:12:48 pm »
... code with the bit-wise or results in a read-modify-write, which results in waaay too many instructions.
And if you *really* need to flip a single bit in one instruction, there's always bit banding. I've never had a need for it though.
 

Offline Javier Revilla

  • Newbie
  • Posts: 1
Re: Reading out the LIS302DL by STmicro
« Reply #18 on: August 16, 2013, 06:31:03 pm »
Dear Torrentula,

Thank you for your code for configuration and usage of the STM32F4 accelerometer (LIS302DL).

You say that PE3 is used as the CS pin, instead of PE2.

Please, could you post a new version of your code taking this correction into consideration ?
I am really a newbie and I do not know how to adapt your code for PE3, instead of PE2.

Thanks.

Best regards,
Javier Revilla
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf