I have now finished with the code for the hook debouncing and for invoking the echo canceller. The latter is still largely untested, but I might be able to set up a test maybe even today. One could say that the code is more or less ready now. The only thing that has not yet been ported from the old driver is the code that counts USB packet-level statistics (missing sequence numbers, incorrectly received USB frames and the like). At this point in time though, I feel that these are not really urgent, since I have kind of resolved the issues for which these statistics were needed. So, I am going to update the SVN tree soon with the latest version of the driver (and will place an update to this post as soon as I do that).
One thing that I need to do is to write some compiling instructions on how to best compile the module on various popular Linux distros. When trying to compile the driver, one’s mileage may vary depending on the distro/kernel/Kbuild environment. To give an example: because of a bug (mentioned in an older post of mine), in Debian lenny one has to either issue a “make EXTRADIRS=oufxs” at the top-level dahdi directory, or else the Module.symvers file has to be copied manually for an isolated “make” to work inside the oufxs directory. On ubuntu, “make” inside the oufxs directory fails altogether with a syntax error (?) message; plus, in order to install the driver via the dkms facility, one needs to fiddle with the dkms.conf file found in the top-level dahdi directory. I have not the slightest idea what the situation is on other distros like Red-Hat ones.
I have managed to bring the failed board mentioned in item #6 of my previous post back to life! The problem was that the 3201 had not been soldered to the thermal pad and thus had burnt after some time of continuous operation. I suspected the 3201 because of the following symptoms: the board would not make the phone ring at all; nothing was heard on the earphone when the card switched to forward active mode (a click is normally heard); and, the DC-DC converter was producing correctly 65V on powerup, but the voltage fell to 9V when the card switched to forward active mode. All these indications suggested an issue beyond the 3210, at the output stage. Replacing the 3201 with a new one — which I tried to make sure is now tightly soldered to its thermal pad — resolved the problem and the card is now alive and kicking.
My third and last dongle-version-2 prototype card remains out-of-order. The indications there suggest a problem in the 3210 or in the PCM bus between that and the PIC. I need to spend some time using an oscilloscope in order to debug this further, and I don’t know if it is really worth the trouble at this stage of the project. I might do it later on.
I have to note down that I owe to try out the pull-down resistor suggested by Gabor in this comment. The truth is that I am having some noise, which I have been overlooking all this time. Probably, as the fix by Gabor suggests, the cause is that the 3210’s PCM bus driver, when outputting a logical zero on the DTX line, does not offer that a good GND-level surge for the noise caught by the transmission line between the 3210 and the PIC. Thus, unless the fix with the pull-down resistor is applied, noise can possibly make it into the audio path. Another issue is the noise induced into the analog audio path, mainly from the DC-DC converter. Fortunately, the 3210 contains a squelch filter for that, however the filter takes some time to adapt after changes in the linefeed mode (direct register 64), during which a high-frequency hum is audible. Probably the solution there is to find out which indirect register(s) are related with the squelch, save their values and re-apply that after every change in DR 64’s value. Anyway, just in case I am to adopt Gabor’s fix, I have checked the PCB design and it is easy to add the pull-down, near the “via” for the DTX signal, with no major changes.
Another piece of good news is that I cannot seem to reproduce the DTMF dialing intermittent failures on a native Linux. The issue still remains on the VMWare-hosted Asterisk, which by now is well known to starve from CPU and I/O resources. Probably the failures are due to a CPU-starved Asterisk missing samples and thus being unable to decode correctly DTMF. This is a great relief, in that DTMF recognition intermittency was a scary, scary bug, at least to me.
Perhaps the most important piece of news in this post is that I have now got on in an agreement with a local company owned by some good old friends, in order to set forth the production of a limited quantity of prototypes (in both an assembled board and a DIY kit flavor). This involves a number of steps, too, and I am going to spend some time discussing these steps.
A quick inspection and review of my board by some hardware assembly specialists revealed to me that there is substantial room for improvement in the choice and placement of components in order to ease the mechanized assembly and thus reduce the cost of the board. To name one, I had better change all components into SMD ones (my board still has a number of through-hole components: two electrolytic capacitors, a tantalum capacitor, a crystal, and the USB and RJ11 plugs). In PCB assembly production lines, placement of through-hole components slows down the process and costs more.
Another area of improvement is that, because the board has components on both sides, it normally requires a second baking round in a reflow oven, and bottom-side components must be glued to the PCB, or else they will fall off the board during the second bake phase. This raises the cost of assembly. However, if components are all oriented alike, the bottom soldering can be done in a solder bath, which is much cheaper than baking in a reflow oven. So, if I am to go into mass production, I had better redesign the bottom side of the board to orient all components west-to-east (the PIC cannot change orientation, so it will make the rule for the others).
Finally, there are lots of components, mainly on the top side, which are too close to one another. Mechanized assembly tools like pick-and-place machines tend to complain or even fail in such cases. Some examples where I should allow components more headroom between them can be found around L1 (mainly the power transistor and the crystal).
The good news are that this redesign step, otherwise time-consuming, will probably be unnecessary for the production of prototypes. Because of the limited number of prototypes, we may go for a manual assembly production, without this incurring any substantial higher cost (the cost for the setup of a mechanized assembly production line is high anyway). The only possibly required redesign of my PCB at this stage involves the DTX pull-down resistor mentioned earlier.
This means that, during the next few weeks, I might be able to give out some more-or-less concrete dates for the availability of assembled prototypes. However, please bear in mind that things are now getting a bit more complicated, since more people and at least two companies are involved. So, please be patient if planned dates shift a bit. For the time, the only planned date is next week, when I think I ‘ll be able to give out some first timeplan. In any case, the important piece of news is that there is now sort of a commitment to produce and give out prototypes at a nominal price. The dates will follow.
I will make sure to include a shot of an assembled v2-dongle in this post, just to make it livelier. Other updates may follow as I get done with the echo tests and as the prototype production is progressing.
Update, May 15: The driver code with the hook debouncing and the invocation of the echo canceller has now been uploaded to the project’s Google code page. Also, I have patched a board of mine with a pull-down resistor in the DTX line as suggested by Gabor in his comment. However, I saw — or, to be exact, I heard — no obvious difference. I also ran a few more tests by setting the 3210 to several loopback modes. I tried both ALM1 and ALM2, and was happy to find that there were no audio quality issues at all — at least no issues that my ear could perceive. Similarly, I ran a DLM test by generating a 1-kHz tone, sending that to the board and collecting it back from loopback. Apart from lost packets (on VMWare), this did not show any issues either. However, I will run these tests again, carefully comparing a patched versus an unpatched version of the board, to make sure that the pull-down resistor patch is not really needed. This is very important because it proves that the firmware (including the receipt and transmission of data via the digital DTX/DRX loop) is working perfectly OK, and any potential audio issues can be isolated in the USB layer and up (including the USB communication between the firmware and the host, the driver, and Asterisk). Hey, this is a test I should have run months ago… Anyway… Finally, here is another great piece of news: I am about to place an order for materials for a bunch of 50 prototypes! Without making any promises yet, prototypes should now be available soon!
Update, May 23: It may seem that I am inactive these days, since I am not posting much. This is not at all the case. The reason I am not posting is that I am doing is a very, very mundane and dull job: I am trying to optimize the cost of my BOM, by looking around at several online electronics shops and retailers. To give an example, a quantity of 50 USB Type A solder-on-board plugs costs about 75 EUR on Digi-Key (Molex), about 100 EUR on mouser (Molex) and about 25 EUR from Farnell. Moreover, in my location, I have to calculate import taxes for merchandise bought from Digi-key. Anyway, in this case Farnell is the clear winner, however this is a very lengthy (and tiresome) work. So far, my per-board BOM cost for 50 prototypes is somewhere between 20 and 30 EUR (this cost does not include assembly and P&P). A friend at a retail shop is currently helping me out to reduce this even further, but I feel the BOM cost won’t drop below 20 EUR/brd. That’s not awfully bad for such a small quantity, and it can drop dramatically at higher quantities. Moreover, there are other optimizations one can make. To give an example, the 0.22uF/100V caps at the output stage cost more than twice as much in a 1812 package than in a 1206 one. I don’t really know why Silabs suggest a 1812 package (I should ask them BTW, or if any reader has gone through this already, a word of advice would be greatly appreciated). As of now, I have decided not to touch the PCB design and to just try finding the best price for the existing list of materials. Anyway, I am to finalize and place my orders the forthcoming week; until then, probably there are not many news to expect.
Besides hardware, I am also contemplating an optimization for the driver. Here are some details: the driver tends to spend long periods of time in a non-interruptible (IRQ?-)context inside the USB completion callback routines, packetizing and de-packetizing audio data. With the current defaults, this occurs once every four milliseconds for OUT packets plus at the same frequency for IN packets. Ideally, this would occur once every two milliseconds, alternating between OUT and IN callbacks. However, nothing really guarantees this optimal alternating scheduling: the initial submissions that trigger callbacks are executed asynchronously, and it might just as well occur that both IN and OUT callbacks get ready to execute at the exact same millisecond. If more than one boards are plugged, four (or more) callbacks might occur at the same millisecond, and each of those must consume a non-negligible amount of time to packetize/de-packetize data. This might starve the (userspace) Asterisk process from real-time CPU resources and result in “lost” samples (samples that arrive too late) or to bad sound quality. Optimizations include the following: (a) try a preemptive kernel (I am not expecting much there, besides numerous bugs that might show up, both in my and in other people’s code); (b) invoke schedule() at times while doing (de-)packetization and (c) decouple (de-)packetization from the completion callbacks, by adding tasklets to perform the lengthier jobs. I trust that some of the options (a) to (c) above (or a combination thereof) will peform much better than the current driver. Notice that my VMWare testing environment is very demanding anyway in that performance issues show up that would never exist in a native Linux environment. Once I am clear with hardware orders, I might try these optimizations and see what happens. Again, readers who might advise me on the subject are more than welcome!