Wednesday, July 27, 2005

SDR mini-itx project update

Here is an update on my mini-itx/SDR project:

I have been working out the details of the A/D – D/A board. I have decided to use the TI PCM4202 (24 bit, 192 kHz, stereo) for the RX A/D. For the TX A/D and RX/TX D/A I am going to use the TI TLV320AIC23B CODEC (24 bits, 8-98 kHz, stereo, with integrated mic amp and headphone driver). The PCM4204 will be dedicated to RX only. The TLV320AIC23B will handle the microphone input for TX as well as the IQ output for TX and the audio output for RX (in the stand alone configuration).

Both chips have digital audio interfaces (I2S, left, right justified, etc…) so I have the problem of getting that data into the PC via USB2.0. I looked at the Cypress EZ-USB FX2 CY7C68013 microcontroller for this but it cannot handle the transfer on its own. I decided to use a Xilinx FPGA in addition to the EZ USB FX2 for the I2S to parallel conversion (inspired by the USRP and SSRP projects of GnuRadio). The EZ USB FX2 will operate in slave FIFO mode to get the data/to from USB2.0. It seems a shame to waste all the I/O available with the FPGA so there will be general purpose parallel I/O, I2C, and SPI bus capability for future expansion*. In addition, since I already have the SPI/Microwire bus, I want to provide the ability to interface two AD9954 DDS chips to the FPGA. The AD9954 has a few dedicated I/O pins for synchronization between multiple chips as well as built in comparators that make it easy to generate a quadrature IQ clock up to 160 Mhz. The AD9954 has a 14 bit D/A so there should be less spurs.

The interface to the PCM4202 requires the digital audio interface lines (LRCK, BCK, DATA) and 3 sample rate select lines. The TLV320AIC23B requires the digital audio interface lines (LRCK, BCK, DIN, DOUT) and 3 wire SPI lines (for control) + /CS. The AD9954 requires 3 wire SPI lines for control and a /CS line. The SPI bus lines will be shared between the TLV320AIC23B and the two AD9954 DDS chips requiring 3 /CS lines, one for each chip.

Part of the parallel I/O will interface to the parallel connector on the SDR-1000 and the rest will be available for user defined I/O.

I will post more on my website as I make progress. Any input, suggestions, and criticisms are welcome.

Phil

*future expansion = high speed ( >=50MSPS) 14 bit A/D

Friday, July 22, 2005

Are you a computer simulation?

Someone emailed me about my webpage at: http://www.philcovington.com/comp.html to ask if I really believed we are living in a computer simulation. He was referring to the paper by Bostrom titled "Are You Living In A Computer Simulation? ". No, I do not believe we are living in a computer simulation. It is an interesting paper though.

I think that Ed Fredkin's Digital Philosophy (http://www.digitalphilosophy.org) is probably closer to what underlies reality.

Tuesday, July 19, 2005

SoftRock 40 & Reorganized website

SoftRock 40

I got Tony Park's SoftRock 40 playing today with Bill KD5TFD's modified PowerSDR console. It is amazing what can be done with such a small board. I want to revive the SharpDSP enabled console for use with the SoftRock 40. I will strip out all of the unneeded controls and functionality in the PowerSDR console to make it specific to the SoftRock 40. This will clear up some screen real estate so I can widen the Panadapter window to show all 48 or 96 kHz of bandwidth at once in the Panadapter.

When the PCM2900 codec boards become available I will modify SDRAudio to correct for the sample offset problem in the PCM2900.

Website

I reorganized my website today. The website notes were archived and links to the various software projects were rearranged to make it easier to find a specific item.

Monday, July 18, 2005

New SDR Project

A few people have mentioned in the past about
wanting to use a small motherboard like mini-itx or micro-atx to run
PowerSDR with the SDR-1000 to make a small self-contained unit
possibly using a small LCD panel display. That was one of the things
on my project list that I wanted to do also. Now that I have started
thinking about it again I decided to try a variant of this idea and
have had encouraging success so far just playing around with it.

I wanted to try to dedicate a mini-itx board to the DSP, CW keyer, and
hardware control of the SDR-1000 using real-time Linux (RTAI
http://www.rtai.org/). I am trying to see how feasible it is to run
the DSP (based on the DttSP code) and hardware control code in hard
real time under RTAI. The RTAI patched linux kernel with DSP and
hardware control code loads from a compact flash card to make it a
diskless system (I have it down to under 16 MB now). I'd also like to
come up with a A/D D/A add on board that will use a chip like the
Wolfson WM8786 24 bit, 192 khz stereo A/D or TI PCM4204 A/D and a
suitable 16 bit D/A instead of using a sound card. There recently has
been a new project released on SourceForge that adds real time USB
support to RTAI (USB4RT) that I am playing with now.

I would then like to use the 100baseT Ethernet on the itx board to
communicate with PowerSDR (minus portaudio, hardware control, DSP
code) so it handles the GUI only. Basically the itx board becomes the
"DSP processor" and the GUI is handled remotely on your home PC.
There are plenty of options for the hardware interfacing since the itx
board has parallel, serial, and USB ports (and I2C) and these ports
can be used in hard real time mode. This also would give the
possibility of running the SDR without the GUI by adding a front panel
with real knobs, switches, leds, etc… if so desired, to make a stand
alone unit without having to have a computer attached for GUI.

I am hoping this approach will eliminate the problems of trying to do
something that is inherently real-time on non-real time operating
systems like Windows and standard Linux. This should eliminate the
burps, braaaps, and buzzes in the DSP as well as give extremely low
latency to hardware interrupt I/O.

I will report on my progress periodically. With the current
improvements in 1.4.1 as well as the improvements to come, there may
be little need for this kind of dedicated hardware but I still would
like to have a stand alone unit that does not have to be connected to
the PC. I am also interested in any comments, suggestions, or
criticisms of this idea.

Sunday, July 17, 2005

vCOM on BerliOS Developer

The vCOM driver project is now hosted at:

http://developer.berlios.de/projects/n8vbvcomdriver/

Saturday, July 16, 2005

Update on Screen Capture Software

It turns out Microsoft offers a free download called Windows Media Encoder that will do screen recording. I have tried it and so far it looks good. It is not as jerky as CamStudio and creates smaller file sizes.

Monday, July 11, 2005

Screen Capture Software

I have been trying out various screen capture software that I hope can be used for software demonstations and tutorials. The first I looked at is Camtasia (http://www.techsmith.com). It is nice for creating software tutorials. Next I looked at Macromedia's Captivate (http://www.macromedia.com/software/robodemo/). It has a lot of avantages and I think I prefer it over Camtasia. Unfortunately it costs about twice what Camtasia costs, but I think it is worth it. I will post a test demo using Captivate to see how it plays with users. It saves files in Shockwave format.

I will probably do the software tutorials inside a VMWare Workstation 5 instance. My screen resolution is 1280x1040 so I need to do the demos within a smaller screen area... probably 1024x768 since this is the smallest common size on laptops as well as most desktops. I can also undo changes easily using VMWare's snapshot and cloning features. VMWare Workstation 5 also has a movie recorder mode where you can capture whatever is going on and save it as an AVI file. Unfortunately, I don't see any option to record audio narration in sync with whatever is happening on the screen. If it worked this way I would probably use it to create the software tutorials.

Saturday, July 09, 2005

vCOM Build 226 released

Build 226 of the vCOM virtual serial port driver is released.

As I said in an earlier note, I had two reports from two different users that the vCOM driver would cause intermittent system freezes. One one system it happened only a few times and on the other system it happened very often. The system that had frequent system hangs was a hyper-threaded box. There can be only a few causes of system freezes and deadlock is the most likely in multiprocessor and hyperthread systems. I had a race condition caused by excessive use of spinlocks resulting in a deadlock. The probablity of the deaklock happening is much higher in a multiprocessor/hyperthreaded system. This is corrected in build 226.

Important: You will need to edit the N8VBvCOM.inf file to match your current inf file before updating the driver. Once you have the inf edited you can run the update.bat file to update the driver.

Thursday, July 07, 2005

vCOM Build 224 released

Build 224 of the vCOM virtual serial port driver is released.

There were two reports by two different people that vCOM build 222 would hand their system. Not BSOD, but just freeze. I have adjusted the thread priorities in build 224 out of the real-time range where they were set in build 222. I think that perodically the threads priority would be boosted above the GUI's thread priority causing a deadlock.

Important: You will need to edit the N8VBvCOM.inf file to match your current inf file before updating the driver. Once you have the inf edited you can run the update.bat file to update the driver.

vSOUND progress - vCOM info

I overcame a major hurdle today in the development of the vSOUND virtual sound card driver. If you are familiar with WDM Audio drivers you know that the portcls.sys driver exposes functions for creating, registering, and managing WDM Audio drivers. Unfortunately for our application the PcXXX functions hide much of the internal workings of the audio driver. For our vSOUND virtual sound card driver we need to be able to send customs IOCTLs to read and write data to the driver's buffers that represent the virtual A/D input and D/A output of the sound card.

In the typical sound driver you will see something like this:

extern "C" NTSTATUS
DriverEntry
(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPathName
)
{
NTSTATUS ntStatus;

ntStatus =
PcInitializeAdapterDriver
(
DriverObject,
RegistryPathName,
AddDevice
);

return ntStatus;

}

The call to PcInitializeAdapterDriver() causes PortCls.sys to load pointers
to handlers for the certain IRPs like IRP_MJ_CREATE, IRP_MJ_DEVICE_CONTROL, etc… into the driver object. Without access to these handlers we cannot get at the buffers we need for our virtual driver. The question is - how do we intercept these handlers?

It turns out that PortCls provides a function call PcDispatchIrp() that we can use if we can get access to the handlers we need. To get access to the handlers we can override the pointers to the handlers that the call to PcInitializeAdapterDriver() installed:

extern "C" NTSTATUS
DriverEntry
(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPathName
)
{
NTSTATUS ntStatus;

ntStatus =
PcInitializeAdapterDriver
(
DriverObject,
RegistryPathName,
AddDevice
);

if (NT_SUCCESS(ntStatus))
{
DriverObject->
MajorFunction[IRP_MJ_DEVICE_CONTROL] = MSVASDeviceControl;
DriverObject->
MajorFunction[IRP_MJ_CREATE] = MSVADCreateDevice;
DriverObject->
MajorFunction[IRP_MJ_CLOSE] = MSVADCloseDevice;
}

return ntStatus;

}

In the code above we have installed our own handlers for the IOCTLs we are interested in. When our handler is called we can examine the IRP to determine whether the IRP is something we want to handle or pass along to the PortCls driver. We can do this by calling PcDispatchIrp() if we are not interested in the particular IRP.

That is all fine and dandy until you realize that you need to somehow call CreateFile() and DeviceIOControl() on the driver. We need a name that we can call in the CreateFile() function.

The MSVAD's AddDevice() looked like this:
extern "C" NTSTATUS
AddDevice
(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
NTSTATUS ntStatus;

ntStatus =
PcAddAdapterDevice
(
DriverObject,
PhysicalDeviceObject,
PCPFNSTARTDEVICE(StartDevice),
MAX_MINIPORTS,
0
);

return ntStatus;
}
The call to PcAddAdapterDevice() creates the device object, initializes the device context, and attaches the device object to the device stack. What we need to do is to create an additional FDO (Functional Device Object). If we create our own FDO we can create a symbolic link to it so Win32 user mode applications can open it and send IOCTLs to it.

Here is the solution:

extern "C" NTSTATUS
AddDevice
(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
NTSTATUS ntStatus;
PDEVICE_OBJECT deviceObject;
WCHAR NameBuffer[] = L
"\\Device\\vSOUND";
WCHAR DOSNameBuffer[] = L
"\\DosDevices\\vSOUND";
UNICODE_STRING uniNameString, uniDOSString;
PVSOUND_DEVICE_EXTENSION pDeviceExtension;


ntStatus =
PcAddAdapterDevice
(
DriverObject,
PhysicalDeviceObject,
PCPFNSTARTDEVICE(StartDevice),
MAX_MINIPORTS,
0
);

if (!NT_SUCCESS(ntStatus))
return ntStatus;

KdPrint((
"Success from PcAddAdapterDevice"));

RtlInitUnicodeString(&uniNameString, NameBuffer);
RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);

ntStatus = IoCreateDevice(DriverObject,
sizeof(VSOUND_DEVICE_EXTENSION),
&uniNameString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&deviceObject);

if(!NT_SUCCESS(ntStatus))
return ntStatus;

KdPrint((
"Success from IoCreateDevice"));

pDeviceExtension =
PVSOUND_DEVICE_EXTENSION)deviceObject->DeviceExtension;
pDeviceExtension-&id = 0x5000;

ntStatus = IoCreateSymbolicLink (&uniDOSString, &uniNameString);

if (!NT_SUCCESS(ntStatus)) //try to delete the symbolic link first
{
KdPrint((
"Failed IoCreateSymbolicLink... trying to delete it..."));
IoDeleteSymbolicLink(&uniDOSString);
ntStatus = IoCreateSymbolicLink(&uniDOSString, &uniNameString);
}

if (!NT_SUCCESS(ntStatus))
{
KdPrint((
"Failed IoCreateSymbolicLink"));
return ntStatus;
}

KdPrint((
"Success from IoCreateSymbolicLink"));

deviceObject-&Flags &= ~DO_DEVICE_INITIALIZING;

return ntStatus;

}
Like in a normal device driver, we create an additional functional device object using IoCreateDevice(). We then create a symbolic link to this FDO using IoCreateSymbolicLink(). If all goes well we can open a handle to the vSOUND driver by calling CreateFile("\\\\.\\vSOUND", ...). And this works... We can now intercept the IOCTLs being sent to the vSOUND driver which means we can define our own custom IOCTL codes to access the buffers we need to get the sound data in and out of the driver!

Unfortunately, because we are trying to do something very out of the ordinary none of this is documented in the DDK so it took a while to figure it out. But it is a major problem that we have overcome on the way to a workable virtual sound card driver for use with PowerSDR. Now someone who has experience in writing device drivers might wonder why I didn't use the WDM prefered method of registering a Device Interface instead of creating a new FDO with a NT sytle name - That is the approach I took initially and it did not work. Upon searching the web and newsgroups it seems that others have tried this approach and were not successful. The answer to why probably lies somewhere in ks.sys or PortCls.sys that we do not have the source code to.

vCOM:

There will be a new build of vCOM available soon. Two users have reported that they have gotten total system freezes while using the driver. They did not get BSODs - just a total system hang up. According to Windows Internals, Forth Edition by Mark E. Russinovich and David A. Solomon there are three things that can cause the system to hang or become unresponsive:

1. A device driver does not return from an ISR.

Since we are not servicing ISRs in the vCOM driver this is not the problem.

2. A high priority realtime thread prempts the windowing system driver's input threads.

3. A deadlock occurs in kernel mode.

I think that #2 is the culprit. In trying to squeeze maximum performance out of the driver I set the thread priorities to the real-time range in the vCOM driver. Obviously this is not a good idea. I will adjust the thread priorities to normal and release a new build. I am 95% sure this is the problem causing the hang on some systems. The threads only rarely run since I implemented the Fast read and Fast write functions in the vCOM driver for build 222. Occasionally these threads will run when data is not immediately available. This would explain the intermittency of the problem.

Tuesday, July 05, 2005

Ken, N9VV reported an error in PowerSDR 1.3.13 where opening a serial port after it had already been opened and then closed would cause an exception. The serial port will remain unavailable until PowerSDR is exited and then restarted.

Using PortMon, I immediately saw the error: I was trying to close the handle to the com port without first cancelling a WaitCommEvent(). The file handle to the com port would only be closed when PowerSDR exited.

The correction to the source code was pretty easy:

In SerialStream.cs line 1383, function FreeHandle needs to be changed to:




protected internal override void FreeHandle(IntPtr handle)
{
if (_ownsHandle)
{
//Important! Must cancel all events before closing file!!!
Win32API_Serial.SetCommMask(handle, 0);
//Now we can close the file handle
Win32API_Serial.CloseHandle(handle);
}
}


Calling SetCommMask() with a mask of 0 cancells the current WaitCommEvent() allowing the com port to be closed and correcting the problem.

Monday, July 04, 2005

My new blog

This is the first entry in my blog. I realized that I was basically blogging on my webpage in the Notes section. This caused people to have to search through all the notes for important installation and configuration information about the software. So, now all comments about what I am working on will be posted here and removed from the webpage. Check here for the current status of the vCOM driver, vSound driver, and any other PowerSDR code updates.

Currently I am working on a fix for a problem in the PowerSDR CAT serial code that causes an exception as reported by Ken, N9VV.

Also, I am working on the vSound virtual sound card driver. I will use choice #2 for the implementation as described on my webpage. This will avoid having to use PortAudio in PowerSDR to talk to the virtual sound card.