Author Topic: Reverse engineering FNIRSI-5012H  (Read 109999 times)

0 Members and 1 Guest are viewing this topic.

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Reverse engineering FNIRSI-5012H
« on: October 06, 2019, 05:32:04 am »
Source code is now available here https://github.com/ataradov/open-5012h

I've recently got FNIRSI-5012H, and it is a very neat device. Once again, I would not use it as a primary scope, but it is a nice addition to the multimeter.
It has a fast boot time and, finally, sane and intuitive controls from the keyboard.

But there are some minor annoyances, which would be nice to fix. For example it does not remember settings for volts/div, time/div, 1x/10x, AC/DC.
Some of the controls could be improved.

So I decided to reverse engineer the board to see if there is any possibility of making open firmware for that thing. It only took a day to completely describe the board. My findings are below.

Note that there are two models of the PCB. The first revision has 4 mechanical relays. The second revision has only one mechanical relay.
The text below only applies to the second revision.

Main components on the board:
GD32F407VET6 - MCU (Cortex-M4, 512 KB Flash, 192 KB SRAM)
AD9288 (probably a clone, no markings) - ADC
TP4056 - Li-lon Battery Charger
TLV70033DDCR - 3.3 V LDO
PC817 - Photocoupler
CPC1002N - Optically coupled solid state relay
SN74HC148 - 8-line to 3-line priority encoder
SS8550 - PNP transistor
HFD4 - Mechanical relay
OPA356 - 200 MHz, CMOS OpAmp
W25Q64JV - 64 Mbit SPI Flash
TFT Display - Based on ST7789S

The MCU is locked (can't even erase), but it does not really matter, since there is zero value to having the original binary.
New MCUs are available for $5 from LCSC. Unfortunately a chip replacement is the only way to go, unless we can find a way to exploit GigaDevice MCUs, which is unlikely.

The ADC is pin-compatible with AD9288, but there are a couple of pins in the original that are marked NC, but bypassed to ground with capacitors in this design.
It also has a hemispherical dimple for first pin marker. The original has a flat bottom dimple. So it is possibly a knock-off, but fully pin-compatible.
But they have a few NC pins on the MCU bypassed to ground as well, so may be they just know more about those devices.

There are two LDOs in the system. One is the main LDO powering all the components. The other one is dedicated to the LCD backlight. The brightness is controlled by PWMing the enable signal.
Note that the LDO inputs are always supplied by the battery. The power switch only controls enable pin of the main LDO.

The display controller type is unknown, but the 20-pin connector pinout matches commonly available LCDs, so it should not be too hard to figure out the type once we get to the ID registers.

The USB connector actually has SWDIO/SWCLK on the data pins, so this connector is used for initial programming during the manufacturing process.
There is no way to get USB working without hardware modification. Although modification would be relatively easy to do. USB FS data pins are located right next to the programming pins.
But I'm not really sure of value of the USB on this device.

CPC1002N is used for shorting the AC/DC capacitor.
SS8550 are used to control PC817s and a mechanical relay.
OPA356 is a buffer right before the ADC.
W25Q64JV is used for waveform storage (and possibly settings, but not the firmware).
SN74HC148 are used to read the keyboard. Each IC handles 8 buttons and two buttons are connected directly to the MCU pins (for a total of 18 buttons).

Allocation of keys to priority encoders (PE):
PE0.0 - STOP
PE0.1 - F1
PE0.2 - EDGE
PE0.3 - AC/DC
PE0.4 - UP
PE0.5 - RIGHT
PE0.6 - MODE
PE0.7 - AUTO

PE1.0 - 50%
PE1.1 - TRIG DOWN
PE1.2 - TRIG UP
PE1.3 - TRIG
PE1.4 - MENU
PE1.5 - SAVE
PE1.6 - LEFT
PE1.7 - DOWN

F2 and 1X10X are connected directly to the MCU pins.

It is an interesting way to reduce the number of pins required for the keyboard, but obviously only one key from the group can be detected at a time, even if multiple keys are pressed.

As to the claim of 500 MHz real time sampling, I could not confirm it in any way.
The fastest sampling rate is with 6 ns/div - 200 ns/div. In this mode both channels of the ADC are used and the clock supplied to the ADCs is 125 MHz. So at best it is a 250 MSPS scope.
With slower settings only one channel is used and the sampling rate drops to 25 MHz, 12 MHz or 5 MHz, and in some cases to 27.8 MHz. In some cases there are also periodic single clock pulses following at a rate of about 30 kHz. Not sure what that is about.
The clock is only supplied when the samples are read, so the ADCs are not clocked significant potion of the time. This can't be good for their performance. I assume they discard the first few samples.

Attenuation is set though the 7 transistors (controlling optocouplers and a relay). I number the transistors Q0-Q6 starting from the one closest to the BNC connector.
Each volts/div setting enables one transistor:
10 V/div - Q4
5 V/div - Q5
2 V/div - Q6
1 V/div - Q1
500 mV/div - Q0
200 mV/div - Q2
100 mV/div and 50 mV/div - Q3

50 and 100 mV/div are not different on the hardware level, so the amplitude is just changed in the software.
This is also the only range that is controlled using a mechanical relay.

And finally, the full pinout of the MCU:
PD0  - ADC B D0
PD1  - ADC B D1
PD2  - ADC B D2
PD3  - ADC B D3
PD4  - ADC B D4
PD5  - ADC B D5
PD6  - ADC B D6
PD7  - ADC B D7
PD8  - ADC A D7
PD9  - ADC A D6
PD10 - ADC A D5
PD11 - ADC A D4
PD12 - ADC A D3
PD13 - ADC A D2
PD14 - ADC A D1
PD15 - ADC A D0
PA8  - ADC A CLK
PA9  - ADC B CLK

PC6  - LCD_RESET
PB0  - LCD_BL_EN
PB3  - LCD_RD
PB4  - LCD_WR
PB5  - LCD_RS
PB6  - LCD_CS
PE0  - LCD_D0
PE1  - LCD_D1
PE2  - LCD_D2
PE3  - LCD_D3
PE4  - LCD_D4
PE5  - LCD_D5
PE6  - LCD_D6
PE7  - LCD_D7

PB9  - Q0
PB8  - Q1
PB7  - Q2
PC12 - Q3
PC11 - Q4
PC10 - Q5
PA15 - Q6
PC15 - AC/DC
PA4  - Offset (DAC output)

PE13 - PE0.A0
PB14 - PE0.A1
PB13 - PE0.A2
PE14 - PE0.GS
PE15 - PE1.A0
PB12 - PE1.A1
PB11 - PE1.A2
PB10 - PE1.GS
PE12 - BTN_1X10X
PE11 - BTN_F2

PA3  - FLASH_CS
PA5  - FLASH_CLK
PA6  - FLASH_MISO
PA7  - FLASH_MOSI

PB15 - CHARGE
PB1  - VBAT_SENSE (Vbat / 2)
PH0 / PH1 - 20 MHz crystal
PA13 - SWDIO
PA14 - SWCLK
« Last Edit: January 27, 2020, 02:43:24 am by ataradov »
Alex
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #1 on: October 06, 2019, 05:33:35 am »
I have a few GD32F407VET6 on a way and another scope just in case.

I have not tried to think though the actual data capture, but I assume it is DMA triggered by the same timer that generates the clock signal. Hopefully it will not be a problem.

« Last Edit: October 06, 2019, 06:14:10 am by ataradov »
Alex
 
The following users thanked this post: argg

Offline BravoV

  • Super Contributor
  • ***
  • Posts: 7547
  • Country: 00
  • +++ ATH1
Re: Reverse engineering FNIRSI-5012H
« Reply #2 on: October 06, 2019, 06:09:30 am »
Subbed and thanks for sharing & your effort.  :-+ :clap:

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #3 on: October 07, 2019, 07:21:37 am »
I've made a breakout board for GD32F407V to make initial project bring up easier - https://github.com/ataradov/breakout-boards/tree/master/gd32f407v PcbWay is currently making them.
The same board may be used to poke around the security locks. ST chips have some issues there, so may be there is a way to unlock the device.

Given the annoying triggering bug (https://www.eevblog.com/forum/testgear/daniu-ads5012h-100mhz-500-mss-portable-scope-for-$80-usd/msg2727270/#msg2727270) and no ability to update the regular firmware, making a new firmware is actually the only way to make this thing usable.
« Last Edit: October 07, 2019, 07:23:24 am by ataradov »
Alex
 
The following users thanked this post: amspire, mikerj, Kilrah, girishv

Offline abyrvalg

  • Frequent Contributor
  • **
  • Posts: 824
  • Country: es
Re: Reverse engineering FNIRSI-5012H
« Reply #4 on: October 09, 2019, 08:20:34 am »
Why custom breakout board? Isn’t this GD32 just a clone of STM32F407VET6? There are lots of VET6 boards for sale.
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #5 on: October 09, 2019, 05:17:32 pm »
Why custom breakout board? Isn’t this GD32 just a clone of STM32F407VET6? There are lots of VET6 boards for sale.
There are a few reasons:
1. I always do a breakout board for the new to me MCU. This ensures that I have correct CAD symbols/footprints for when the device goes into a real project. Plus I have a chance to work out any gotchas on a custom design. This does not really matter here, but a process is a process.
2. I hate standard dev kits with a bunch of peripherals on them. I never use any of that stuff and it is always in a way.
3. I do not like ST-Link. I much prefer a standard CMSIS-DAP programmer/debugger. I have lots of custom tools for working with that.
4. It only took half a day and I had PcbWay order going out anyway, so time and money investment are minimal.
5. Custom board will also let me poke around the original locked chip, may be try to do some power glitching to see how it compares to ST devices in that respect.

It is also not a perfect clone, just a register set compatible implementation. There are differences between them, and I'd rater use the same exact device.
Alex
 
The following users thanked this post: 001, msliva, dave528

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #6 on: November 02, 2019, 11:15:01 pm »
Parts finally arrived after a long time sitting at LAX customs. No Idea why, some packages I ordered later actually came first.

I swapped the chip and now I can program the device in my scope and I can blink the backlight and read a button state. The next order of business is to figure out the display type.

I must say, I rather like having SWD interface on the external connector. This lets me debug the hardware while having it all assembled.

I also saved the original chip and soldered it onto one of the breakout boards. I quickly poked at it, and it does appear to be locked. But if I hold the chip in reset, the debug interface actually responds, and I can read and write debug registers. Any attempt to read any other registers result in zeros being read, but no faults or errors. Writes seem to be ignored, but who knows. I will have a more detailed look at that later.

As a bonus, here is a picture of the board under the GD32. I don't think this exists anywhere else on the internet.

PS: While debugging some of this hardware, I tried to use this scope as is, and it is basically unusable in its current form. Without a decent firmware it is a total junk.
« Last Edit: November 02, 2019, 11:38:01 pm by ataradov »
Alex
 
The following users thanked this post: BravoV, uer166, jhpadjustable

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #7 on: November 03, 2019, 01:51:44 am »
The display is based on the ST7789S controller. I have not tried to output an actual image yet, but the device ID register matches the datasheet for that controller.

EDIT: I can now display an image. Tomorrow will be a fun day.
« Last Edit: November 03, 2019, 04:29:58 am by ataradov »
Alex
 
The following users thanked this post: jhpadjustable

Online splin

  • Frequent Contributor
  • **
  • Posts: 999
  • Country: gb
Re: Reverse engineering FNIRSI-5012H
« Reply #8 on: November 03, 2019, 07:44:55 pm »
.
Main components on the board:
GD32F407VET6 - MCU (Cortex-M4, 512 KB Flash, 192 KB SRAM)
AD9288 (probably a clone, no markings) - ADC
...
As to the claim of 500 MHz real time sampling, I could not confirm it in any way.
The fastest sampling rate is with 6 ns/div - 200 ns/div. In this mode both channels of the ADC are used and the clock supplied to the ADCs is 125 MHz. So at best it is a 250 MSPS scope.

Interesting info - thanks for sharing.

I guess the only way the MCU could keep up with the ADC data would be through the FSMC -  DMA GPIO to memory is 1/4 CPU clock or 42MHz max on the ST version of the processor whereas the FSMC can manage approx twice that. That would suggest that the GD32F407 is being overclocked from 168MHz to 250MHz to be able to read 125MSPs which seems quite a stretch. Maybe the clone version is different but I doubt it.

The 500MSPs claim seems totally bogus.  I'm curious as to the motivation behind the claim.  I can't believe they thought it wouldn't be uncovered soon enough so perhaps they assume that most potential buyers don't care or perhaps even expect the specs to be wildly exaggerated - so would assume it to be a 62.5MSPs  scope if they stated 125MSPs!  :-//
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #9 on: November 03, 2019, 07:52:59 pm »
This is actually the only puzzling thing about this while design. ADCs are hooked up to regular pins, so they must be sampling them as regular GPIOs, but I don't see how this would work either. I will have to experiment.

ADC clocks are connected to the timer outputs. In this case to generate 125 MHz, the timer would have to be running at 250 MHz. This is indeed somewhat overclocked :). Unless I've missed something about those timers.

And I guess the data is read as normal GPIO by the DMA triggered by the TC.

There is nothing inherently wrong with overclocking, I did it many times for my projects.  Usually overclocking starts to cause troubles at extreme voltages and temperatures. But in this case we can assume stable 3.3 V supply and around operation at a room temperature.
« Last Edit: November 03, 2019, 07:55:20 pm by ataradov »
Alex
 

Online splin

  • Frequent Contributor
  • **
  • Posts: 999
  • Country: gb
Re: Reverse engineering FNIRSI-5012H
« Reply #10 on: November 03, 2019, 10:17:27 pm »
Must be a difference in implementation between the STM32 and the GD32 versions, the latter having more efficient bus matrix arbitration/synchronisation or whatever.  As to the almost 50% overclock it could be down to conservative ratings for the GD32 - they may prefer to emphasize the similarity to, and hence its compatability with the ST parts rather than highlight the differences even though being faster (if it actually is) would normally be a significant marketing advantage.

Are the two ADCs clocked with different timers to allow interlacing interleaving? That would make the GPIO read timings interesting - both ADCs will be read simultaneously with an 8ns clock cycle the ADC's output data will be offset by 4ns from each other leading to some hairy setup time and hold time margins!

[EDIT] typo
« Last Edit: November 04, 2019, 10:29:37 am by splin »
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #11 on: November 03, 2019, 10:32:36 pm »
The ADC clocks are out of phase (when both channels are used), but the ADC itself has a data align setting, which makes data from both channels available on the rising edge of the channel A clock. So from the MCU point of view it looks like 16-bit samples coming in at 125 MHz rate.
Alex
 

Offline BravoV

  • Super Contributor
  • ***
  • Posts: 7547
  • Country: 00
  • +++ ATH1
Re: Reverse engineering FNIRSI-5012H
« Reply #12 on: November 04, 2019, 08:40:45 am »
I also saved the original chip and soldered it onto one of the breakout boards. I quickly poked at it, and it does appear to be locked. But if I hold the chip in reset, the debug interface actually responds, and I can read and write debug registers. Any attempt to read any other registers result in zeros being read, but no faults or errors. Writes seem to be ignored, but who knows. I will have a more detailed look at that later.

 :popcorn: ... again thanks for your effort, time & energy spent.  :-+

Offline dave j

  • Regular Contributor
  • *
  • Posts: 127
  • Country: gb
Re: Reverse engineering FNIRSI-5012H
« Reply #13 on: November 04, 2019, 10:53:33 am »
Quote
An analog watchdog block can be used to detect the channels which are required to remain within a specific threshold window
(page 44).

Surely that's what they use for the trigger?

It's using an external ADC (AD9288 or clone) not the ones in the MCU. Alex's investigation shows it's not even routing the analog signal to the MCU.

Part of the reason for the triggering problems with this scope is because it doesn't appear to be checking for a trigger as the samples come in. It appears to be doing:

1. Read a buffer full of samples.
2. Check for a trigger occurring somewhere in that buffer using software.
3. Repeat if haven't found a trigger.

The problem with this is it isn't reading samples whilst doing step 2 which means triggers can occur that aren't detected.

It's possible to check for triggers using software surprisingly quickly (see here). I think Alex's plan is to do something like that so it can check samples continuously rather than have gaps where triggers can be missed.
I'm not David L Jones. Apparently I actually do have to point this out.
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #14 on: November 04, 2019, 05:51:57 pm »
Yes, then only  thing internal ADCs are used for is the battery voltage measurement.

The only way I can think of to avoid dead time would require additional hardware, e.g. a small-ish fpga piggybacked on top of the ADC sniffing d0..7 :-)
Adding FPGA would complicate the design, and potentially increase the price. And at the highest sampling rate it would be D[15:0], since both channels are used.

My goal would be to optimize things so that I can guarantee that at some sampling rate, I look at every single sample. And at a higher rate there will be dead windows.

In a single and normal modes there is no need to update the display, so most of the CPU time can be spent looking at samples and scanning the keyboard. And in auto mode missed triggers are not that big of a deal anyway.

I spent entire day yesterday figuring out ways to put the stuff on the screen efficiently. I will try to make the simple naive version first and then optimize based on the profiled bottlenecks.
Alex
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #15 on: November 04, 2019, 06:19:30 pm »
I will after I have more pieces in place. At this stage there is not a whole lot to look at. And the code is not in the publishable shape.

The thing still runs from the internal RC oscillator, I have not tried to switch to the PLL yet.
Alex
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #16 on: November 05, 2019, 06:49:22 pm »
I've got the device to run at 250 MHz and the simple application seems to run without any immediate issue. With that I configured timers to output 125 MHz on the clock pins.

I'm now trying to figure out how to configure DMA to receive the data. And I'm not sure I understand how their DMA works. Typically you configure source address, destination address and the trigger event (for P2M transfers). But in this case I see no way to configure the trigger. So far the way I rad the datasheet the trigger is inferred from the peripheral address that you configure in the DMA registers.

The issue is that I need to transfer the data from the GPIO based on the timer/counter event.

I will obviously need to do more reading of the sample code and documentation, but if someone knows this, I would appreciate the hints.

Also, the GD32 already bumps the maximum frequencies of the buses to 200 MHz, so 250 MHz is much less of an overclock than it would be with ST devices.
Alex
 

Offline dave j

  • Regular Contributor
  • *
  • Posts: 127
  • Country: gb
Re: Reverse engineering FNIRSI-5012H
« Reply #17 on: November 05, 2019, 07:29:41 pm »
It looks like it's done by setting the PERIEN field in the DMA_CHxCTL registers. See section 10.4.1 Peripheral handshake starting on page 198 which contains two tables that map peripherals to the channels'  PERIEN fields.
I'm not David L Jones. Apparently I actually do have to point this out.
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #18 on: November 05, 2019, 07:36:21 pm »
Thanks! That's it.

I was looking for a bigger field. But it looks like in this device different peripherals are spread over fixed channels with up to 7 peripherals assigned to a channel.

Boy, this is primitive, but I guess functional enough.
Alex
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #19 on: November 06, 2019, 03:49:51 am »
Ok, I've got the whole capture setup working in a very non-optimized way. But there is one more wrinkle to the performance. My original pinout was slightly wrong - PD8  is actually ADC A D7 and PD15 is ADC A D0, which means that samples from one of the channels will have to be bit-reversed before processing.

ARMv7-M has "rbit" instruction, but moving the data around will take additional processing time.

And the original firmware uses ADC A in cases when only one channel is necessary.  So I guess they just like to reverse things, since simply using channel B would have no other side effects.
« Last Edit: November 06, 2019, 03:51:47 am by ataradov »
Alex
 
The following users thanked this post: mikerj

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3237
  • Country: gb
Re: Reverse engineering FNIRSI-5012H
« Reply #20 on: November 07, 2019, 11:38:09 am »
Ok, I've got the whole capture setup working in a very non-optimized way. But there is one more wrinkle to the performance. My original pinout was slightly wrong - PD8  is actually ADC A D7 and PD15 is ADC A D0, which means that samples from one of the channels will have to be bit-reversed before processing.

I suppose this was done to ease layout?
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #21 on: November 07, 2019, 03:24:32 pm »
I suppose this was done to ease layout?
Correct. This way it is a bunch of short parallel traces going from the ADC to the MCU.
Alex
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Reverse engineering FNIRSI-5012H
« Reply #22 on: November 08, 2019, 06:04:45 am »
I was playing with the original device to see how locked it really is, and I noticed that it generated a lot of traffic on the SPI flash pins. The traffic turned out to be just repeated attempts to read the device ID (and failing, since the chip is on an empty breakout board).

But that gave me an idea to actually read the flash. I don't think I used any store functions on this device, so the flash should be in its factory state.

The majority of the device is empty (0xff). The first data starts at address 0x007da000. Then there is a small chunk at 0x007df000, then one byte at 0x007e4000, and then a long (8.5K) block at 0x007ee000.

I'm attaching the binary dump starting from 0x007da000.

I have not tried to interpret any of this data yet. I assume from of it is calibration information.
Alex
 

Offline EEVblog

  • Administrator
  • *****
  • Posts: 37717
  • Country: au
    • EEVblog
Re: Reverse engineering FNIRSI-5012H
« Reply #23 on: November 08, 2019, 12:48:21 pm »
I didn't know about this thread.
I just did a review video. The bandwidth is only 10MHz, not 100MHz.
Triggering is pretty horrible.

 

Offline thinkfat

  • Supporter
  • ****
  • Posts: 2150
  • Country: de
  • This is just a hobby I spend too much time on.
    • Matthias' Hackerstübchen
Re: Reverse engineering FNIRSI-5012H
« Reply #24 on: November 08, 2019, 01:05:04 pm »
I also saved the original chip and soldered it onto one of the breakout boards. I quickly poked at it, and it does appear to be locked. But if I hold the chip in reset, the debug interface actually responds, and I can read and write debug registers. Any attempt to read any other registers result in zeros being read, but no faults or errors. Writes seem to be ignored, but who knows. I will have a more detailed look at that later.

You cannot do a lot with the debug unit while the chip is in reset, but you can program the flash and you can also read it, if you want to extract the original firmware. This is the usual trick to recover a chip if you messed something up and used the SWD lines for some other purpose (accidentally or deliberately).
Everybody likes gadgets. Until they try to make them.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf