Mirics MSi3101MSi3101 is name of the reference design that consists of two parts, USB ADC and RF-tuner. Used USB ADC is MSi2500 and RF-tuner is MSi001. That designs was introduced somewhere in 2009 aimed for PCTV marked. It is the first and the only one SDR based PCTV solution, which unfortunately never becomes very popular.
|Mirics MSi3101 devices
If we compare traditional DTV USB solution and that software solution, we could see that kind of data paths in higher level:
HW, traditional, solution:
antenna => RF-tuner => HW demodulator => USB-interface => PC => TV-application
SW, SDR, solution:
antenna => RF-tuner => ADC => USB-interface => PC => SW demodulator => TV-application
The very first DTV USB ADCFirst of all, Mirics MSi2500 USB ADC is very interesting chip! It is very first plain USB ADC I have ever seen, designed for USB2.0 SDR based digital television. Requirements coming from the DTV terrestrial reception means that there must be sampling rates around 10Msps and sampling resolution 10-bit or more. These are hard requirements to meet as all the bits are transferred over rather slow speed USB2.0, which becomes quickly to bottleneck. To tackle that problem chip offers multiple stream format - for more you need sampling rate the less you has resolution and the other way round.
reverse-engineering USB ADC sampling rate formulaUnfortunately I was not able to get any needed register documentation for that chip, which forces me to jump reverse-engineering mode. Whilst I have done reverse-engineering quite a hell much, I don't like to do it as it is simply a waste of time... Fortunately ADCs are rather simply chips as there is not much moving parts, in a good luck only sampling rate. In that case there were mostly sampling rate and stream format which are needed to find out in order to operate chip somehow meaningful.
I thought some time how I could find out ADC sampling rate calculation formula and eventually ended up developing following method. It is mainly based of register value brute-force with sample rate calculation, but contains mixture of some other steps. I could imagine that same method could be useful later, when new USB ADC chips are arriving to market and documentation how to configure ADC sampling rate is not known.
- Prerequisites. You must have somehow working driver skeleton which streams ADC data. RF tuner functionality is not needed, but without the tuner step 2 could be hard to pass.
- Learn stream format. Implement some logic to driver which calculates all I/Q samples in given period. After the each period calculate sample rate (by driver) and output it to the debug log. I used 5 second period in my tests - more longer period you use, the more accurate sample rate calculation is.
- Find out registers involved to sampling rate setting. Sniffing and diffing... For example tune TV to 8 MHz channel, then 6 MHz and test even radio, depending on what app supports. Should not be very hard.
- Add "write_reg" V4L2 private control to your driver and some appropriate implementation for it. You could guess why and how - if not that method is not for you.
- Start streaming, eg.
cat /dev/video0 > /dev/null
- Brute force different values to sampling rate registers and see what driver reports as calculated sample rate.
v4l2-ctl -d /dev/video0 --set-ctrl=write_reg=0x1234503
|Fractional-N frequency synthesizer
Sample rates measuredBoth devices seems to perform very similarly on sampling rate test made. Sampling rate limits were between 1.21 Msps and 15 Msps. Smallest stable sampling rate is a little bit high what I expected, but not too high.
Sampling resolution & stream formatI found 4 different stream formats, all having different resolution. As a USB2.0 device there is direct relation between stream format and sampling resolution and indirect relation for sampling rate. Stream formats known currently supports 14-bit, 12-bit, 10+2-bit and 8-bit resolutions - at least sample bit count got is that, effective resolution (enob) could be a bit less...
I calculated following ~theoretical maximum sampling rates per stream format using assumption maximum USB2.0 effective throughput is 280 Mbit/s.
|8 613 281
|11 484 375
|13 125 000
|17 226 562
These results are very theoretical and not tested.
Btw. that stream format register didn't liked injection of new register values when streaming was ongoing :) Result was typically broken stream and it didn't get fixed until device was physically replugged. There could be still some more formats available and I suspect using own firmware you could implement your own formats. At least these are supported by default firmware.
There was also bits to select USB URB Isochronous micro frame size from one of the 1024/2048/3072. 3072 is maximum what USB2.0 supports and I don't see any idea to use smaller as bus datarate is so high in any case.
MSi2500 advertises on USB interface device descriptor that it has some more alternative settings to offer. That same register is likely place to configure those too.
USB device descriptor
RF-tunerRF tuner used for that design is Mirics MSi001. It supports both Zero-IF and Low-IF, which is very unusual nowadays as most tuners are just Zero-IF only.
Tuner supports multiple bands and wide range frequencies, starting from the 150 kHz and ending up to 2GHz. There is quite big gap between 260 - 410 MHz, but more bigger problem with devices planned for TV usage is unconnected LW/MW/SW and L-Band antennas. These unconnected antennas limits actual frequencies to 50 - 960 MHz. Modding should be possible, but how hard?
|testing tuner limits using RF generator
Here is the measured frequency ranges from two different devices I have.
|device / mode
|Mirics MSi3101 SDR Dongle
|Hauppauge WinTV 133559 LF
|52 - 132 MHz
|49 - 130 MHz
|103 - 263 MHz
|98 - 259 MHz
|413 - 960 MHz
|391 - 960 MHz
Staging qualityDeveloping that driver has been relatively big task for me. I started to looking it around one year ago but most of the implementation was done during this summer. There has been numerous new issues to resolve as that is first Linux Kernel USB SDR receiver driver. The fact is that my backgrounds are from the digital television side, DVB API, and that driver is implemented to V4L2 API. I didn't has any existing knowledge from V4L2, which put me position I was forced to learn lot of things. Now I can understand again why some "simple" DVB things could be so hard to implement for firstcomers :)
As there is still multiple unresolved issues that driver could not be mainlined yet. Biggest problem is no less than missing API. So I am putting driver to the Kernel staging which is right place to problematic stuff like that. That is something I will try to kick Mauro to get help as I have so little experience about V4L2 internals. Actually Mauro has already provided some SDR API related patches that are waiting for some discussion and review.
I collected Kernel SDR API requirement specification, which the implementation should follow in the mean it is reasonable possible to implement.
Here is the list of know issues, from critical to less critical. I think resolving API issues is enough to move that driver out from the staging.
- Kernel SDR API
- new V4L2 controls
- do not abuse video-device
- stream conversions (move to libv4l2?)
- implementation performance problems are ruled out
- GNU Radio plugin
- has performance problems (read => mmap)
- add more functionality
- stream conversions with the help of libv4l2
- separate USB ADC and RF-tuner logic to own drivers
- USB ADC main driver "msi2500"
- RF tuner to v4l2 subdev driver "msi001"
- tons of other changes!
- feel free to contribute I am open for any help
- hack hack hack!
Kernel driver development treeI will keep latest Kernel driver development tree:
GNU Radio use exampleInstall gr-kernel GNU Radio plugin:
Use LibV4L2 Source it provides.
|gr-kernel, LibV4L2 Source, FM radio
v4l2-ctl use exampleWhilst LibV4L2 Source in gr-kenel package is recommended application to use device, it is still possible to use it via standard v4l2-ctl tool. These commands will surely change without a any notification when API issues are implemented correctly, but at the time that blog post is written you could capture 94.3 MHz FM radio dump to file using following commands:
$ v4l2-ctl -d /dev/video0 --all
$ v4l2-ctl -d /dev/video0 --set-ctrl=sampling_rate=2000000
$ v4l2-ctl -d /dev/video0 --set-ctrl=tuner_bw=200000
$ v4l2-ctl -d /dev/video0 --set-ctrl=tuner_rf=94300000
$ cat /dev/video0 > ./my_fm_radio_record.bin