Some interesting (?) updates

I am writing this post in order to provide a quick update on all open fronts of the project. These are (a) the readers’ possibility of obtaining a development board/DIY kit in order to help in advancing the project, (b) the dongle board and its issues and (c) the “channel driver vs. dahdi-compatibility” saga. There’s news in all of these fronts — but don’t hold your breath, I am not going to announce anything really spectacular.

First, let me finish off with the poll (that I have once more included above). I have now set a closing date on it, which is by the end of the current week (March 28th at noon in my timezone). As of today, there are already twelve replies. Wow, a team of twelve prospective developers/testers is already a small army! After the poll closes, I will try to (no promises yet) do all that is required to give to the readers who are interested to help the possibility to order a prototype at the bare cost of materials+p/p+assembly (the latter only for ready-made boards). Details on this will follow, as I need to check my options: for example, if I can convince a local e-shop to run an errand for me, I might make prototypes/DIY kits available through their web site, otherwise I could use eBay and PayPal — but I ‘ll announce more on that later on.

My second piece of news is that I have debugged (well, somewhat…) the situation with the heat dissipation issue in my dongle board. By means of the popular among electronics enthusiasts “touch-n-burn-your-fingers” technique, I was able to trace the heat source. And — surprise! — although the 3210 gets hot, it is not the primary source of heat as I had thought. It is the line driver chip (Si3201), which is mounted on the bottom side of the board, that dissipates the most heat. The 3201 gets hot quickly, and its proximity to the 3210 makes the latter get hot quickly as well. Why didn’t this show up on my large-form boards? Because there, the hotty 3201 is relatively isolated from the other sources of heat dissipation (PIC, 3210) and has also a very good heat sink — a large ground-level copper area on the bottom side of the board (this is the large-form one I am talking about).

Back to the dongle, I am not a specialist in computing the thermal resistance of PCBs, however I think I can do a couple of things to redesign the dongle in order to fix the problem. The first thing to try is to relocate the line driver chip and place it as far away as possible from the 3210. The second is to use a four-layer board and to make the medium two layers into heat sinks. This would work by adding a large-hole “via” underneath the 3201, connected to the thermal pad which is already there. A generous blob of solder would serve as a thermal conductor between the thermal pad and the middle layers. Then, I could use the same method (thermal connection between layers through large-hole vias) to create “heat egress points” to the two surface layers of the board, onto some ground areas located as far away as possible from the 3210.

Other ideas include (i) an adhesive heat sink mounted on the Si3201 (see picture on the left — it’s not very expensive, but it will defeat the low-profile design of the bottom-side of the board) and (ii) redesigning the circuit and the board so as to revert to the discrete transistor-based output stage, as shown in the Silabs reference design. I tend to flirt with the idea (ii), since it might reduce the cost of the board. However, it is quite a lot of work, plus it is a challenge to fit another twelve or so components onto the tiny dongle board, so I really don’t know for now — maybe later…

Note: all the above babbling means that if you choose to manufacture your own dongle before I devise, test and publish some of the above thermal fixes, you risk working with two hot chips, and this may end up in these chips working unreliably or even burning. Probably the quickest patch here is using a heat sink, so I ‘ll try this ASAP and report back the results.

That having been said, let me now get to the dahdi-driver-versus-channel-driver saga.

The last few days I have been recap’ing my reading of the Dahdi drivers. As it turned out, after having written my own device driver for the board (or a first attempt thereof whatsoever), I was able to understand much easier what is going on in the Dahdi world. [Note, since the structure of the older predecessor of Dahdi, Zaptel, is very similar, for the rest of this discussion I ‘ll go on with Dahdi and assume that the same things more or less hold for Zaptel as well.]

So, I studied a bit wctdm.c at first. This is the source code of a Linux module implementing a device driver for a family of Digium PCI-based FXS and FXO cards which use Si3210. Some readers may remember that I have, ahem, “borrowed” some initialization values for the chip’s indirect registers in my test code from this very source. Modulo a few changes in register values (e.g., 1 instead of 0 for the TXS/RXS direct registers, different values for the indirect registers that monitor line output transistor power level, etc.), the code that handles the 3210 in this file could just as well manage my board too. On the other hand, this is a PCI driver, while mine is a USB one. I ‘ll come back to that in a few paragraphs.

Then, there is another kernel module, dahdi-base.c. In terms of the Linux module hierarchy, this module exports symbols for a set of common functions used by all other hardware-dependent device drivers. For example, and unlike what I have done with my “openusbfxs” driver, the fops (file operations) section that includes open(), release(), read(), write() and friends is implemented in dahdi-base and not on hardware-dependent device drivers like wctdm.c.

Now what I found very interesting is that the only functions that are triggered by userland requests and need to make it through to the hardware-dependent device drivers are ioctls. Read(), write(), poll() and friends are implemented entirely in dahdi-base.c and do not require any sort of “hooks” in the device drivers. As for read() and write(), there is a totally asynchronous interface between the hardware-dependent drivers and dahdi-base. Here is how I think this works.

Each hardware device driver like wctdm.c implements a dahdi-compliant device structure, which in turn contains a set of channel sub-structures, with one such sub-structure for each actual device that a card implements (remember that a card may implement e.g. four or eight FXS or FXO interfaces — I won’t discuss trunk cards, like E1/T1 for now). The hardware device driver implements a h/w  interrupt-level automaton (for example, in the case of wctdm.c this is triggered by PCI IRQs) that inputs and outputs audio data at the pace of the hardware. The device driver reads and writes data to some buffers in the device structure and then invokes two functions, dahdi_send() and dahdi_receive().

These latter functions implement a smart circular structure, made out of a set of buffers. The read() and write() syscalls that are implemented in dahdi-base.c read data from / place data to, respectively, these same buffers which are alternated between dahdi-base and the hardware device driver. This buffer structure  does not really require locking between the device driver and dahdi-base, because buffer “ownership” is only modified by the device driver, and this happens only at interrupt level (when the device is ready to read or write more data), by invoking dahdi_send()/dahdi_receive().

This looks very similar to the way that that my openusbfxs device driver works! The main difference in my current openusbfxs driver is that data are not pushed to or pulled from an “upper-layer” driver like dahdi-base, but are instead interfaced directly to the read() and write() syscalls. Because however of the fine-grain locking involved, it may turn out that my driver is imposing some overhead that dahdi does not have. In other words it seems that, as an amateur device driver writer, I may have introduced far too much complexity into my design and things could become considerably faster by avoiding locking altogether, like Dahdi does.

Hmmm… Presumably, with my experience from writing the “openusbfxs” driver, I could utilize much of the code in wctdm.c, substituting the PCI interface with the USB core interface, and removing much of the fine-grain locking that my driver is based on. Since making my h/w driver visible to the Linux filesystem level is not needed, I could remove the fops section altogether. For I/O, all I would need to do is invoke dahdi-send() and dahdi-receive() as soon as a URB arrives or is ready to ship, respectively. Finally, I would need to implement the ioctls with their Dahdi names (excluding some LED/lamp flashing device-specific ioctls) — and that’s largely all there is to it! [OK, there is also the echo cancellation that I need to take care of, but I think this won’t be very hard to add a posteriori].

Which means that, unless there is something big that I am really missing here, I think that rewriting my device driver for Dahdi is much, much easier than writing a channel driver from scratch, especially taking into account that there are tons of functionality already implemented in the Dahdi channel driver that I would need to repeat.

So, the next few days I am going to start in this course, and report as I progress through some major steps (e.g., basic module, USB working, board initialization, Dahdi registration and Dahdi I/O). I certainly hope that the results will be faster than in my previous attempt, but if I were you, I would not hold my breath. I have tried things in the wrong direction before (and this blog is the very proof of that, just check some of the older posts) and it is not unlikely that things go wrong this time as well.

As usually, I ‘ll be updating this post as I go on, so you may want to re-check this post periodically to see (if and) how work is progressing.

Update, March 29: The poll is now closed. The results are on the top of this page. I have not yet decided how exactly I should proceed, but I ‘ll let readers know really soon. If anyone intended to participate to the poll but have missed the closing date (or has just found out about it past the closing date), no worries: if I produce boards or kits, I am going to leave some headroom and make larger quantities available.

Besides that, I am redesigning the output state of the dongle, to make room for on-board heat sink areas for the 3201, as far away from the 3210 as possible. Here is the current stage of the redesign:

As you can see, the chip is now placed underneath a relatively empty top-side area, which will be covered by the GND fill polygon. Hopefully, this area will conduct much of the generated heat to the air surrounding the board. Moreover, all this area is near the RJ11 plug, and hence close to an opening in the dongle’s case, that will provide some ventilation if needed. Finally, since now the top PCB side near the hot chip is almost clear of components (there are still some remaining ones that I need to move away), a normal external heat sink could be mounted directly on the top side GND copper area if needed.

BTW, the Dahdi-compatible kernel module is also underway. Currently, it just loads but doesn’t do anything useful yet (not even invoke dahdi-base functions). Finishing my next dongle design attempt, I ‘ll definitely get more active on that — stay tuned…

Update, March 31: the heat-revised dongle design is now ready. Here is what it looks like: 

As you can see, I have placed a lot of “free copper” on the top side of the “hot area” of the board, in the hope that this will be enough. In addition, I have removed the solder mask from the most part of this area in order to ease heat radiation. If all this proves to be insufficient, there is also enough room to add two adhesive heat-sinks (this is mainly why I have removed the solder mask). I hope all these will suffice, but in order to be sure, I ‘ll order and assemble one or two prototype PCBs. If these prove to work OK, then I ‘ll be ready to go on with ordering the necessary parts for DIY kits or ready-made boards.

Update, April 6: In the dongle front, I have ordered a set of two/three prototypes for my new design (shown above) and am waiting for them to arrive. Salva has provided a very useful startup version of project shopping basket in (see his comment in this post for more information). In the driver front, I am now rewriting some of the initialization stuff and doing a lot of thinking about other parts of the code. Here is a question if anyone knows: when I get notified of a urb completion which means that I have received some (typically, four or eight) 1-millisecond chunks, should I call dahdi_receive repetitvely to deliver all the received data to dahdi-base (or, contrarily, should I deliver one 1-millisecond chunk per system “tick”)? In the meantime, if you are really interested in the dahdi driver, a very useful resource is Tzafrir Cohen’s page on Dahdi-Linux and especially the low-level drivers section. It seems that many of my questions throughout writing my new module will find answers there.

Update, April 8: I had forgotten to upload all my changes including statistics gathering, modifications to test programs to display statistics, SOF profiling, and the fix to tmr1_isr.asm that synchronizes the board’s clock to the USB SOF. They are all now uploaded to the project’s Google code page. Please note that by now the changes to the openusbfxs kernel module are in a sense obsolete, since the focus of the project has now moved into creating a dahdi-compliant kernel module; however, I am going to use nearly everything from my old module, so it’s a good idea to review the changes if you are actively interested in the code. In the new module front, I have stumbled upon this bug (I am developing on a 2.6.26 kernel and kbuild environment) but have found two workarounds: (1) compile from the top dahdi directory, having the new module in a subdir of $(TOP_DAHDI)/drivers/dahdi and adding the env variable SUBDIRS_EXTRA, and (2) copying the Module.symvers file that is generated in $(TOP_DAHDI)/drivers/dahdi after compiling dahdi into my own module’s directory and issuing a “make” in that directory. So, I am now able to insmod my new module. In a matter of days, I am going to report on my first tests (and crashes, if any :-)).

Update (same day, later on): the new module recognizes the board (as expected) and registers itself successfully with dahdi-base. Here is what dahdi_scan reports:

description=DAHDI_DUMMY/1 (source: HRtimer) 1
devicetype=DAHDI Dummy Timing
description=Open USB FXS board 0
manufacturer=Angelos Varvitsiotis
devicetype=Open USB FXS
location=USB ??? - FIXME

Not bad at all, is it? Probably, to be consistent with Dahdi numbering, some ‘0’s should read ‘1’. Also, location “??? FIXME” is printed because what is expected there is that the driver report the USB path of the attached device, but I haven’t put the necessary effort to fix that yet.

Update, April 9: My new prototype dongle boards (3 of them) have arrived and look OK. I am now refreshing my BOM and going to order some parts that I am missing.

Update, April 13: The board initialization with the new driver is now complete (well, almost: the initial URB submissions to get the isochronous engine rolling aren’t yet in place, but I ‘ll add that soon). I have implemented two new module parameters taken from wctdm.c. The “reversepolarity” does what it says, i.e., causes the driver to use reverse-active linefeed mode (Si3210 direct register 64). The “lowpower” parameter instructs the 3210 to work with an on-hook voltage of 24V and a ringer peak voltage of 50V, as originally hinted by Edwin in his comment (see also my last reply to that comment). BTW, it seems that the low-power mode indeed results in less heat dissipation on the 3201 — thanks for the hint, Edwin! Now probably I can work somewhat longer with my (un-revised) dongle without fearing that it will burn on me. I have left out the tx- and rx-gain parameters for the time, as I have also done with all the MWVI code and module parameters (MWVI stands for “Message Waiting Visual Indication”, and is used to flash a light bulb on a phone with such a bulb installed when a voice message is waiting; I guess I could use the board’s LED for a similar visual indication, but I ‘m not going to do this right now, maybe later…).

Update, April 14: I have now ordered materials for three rev-b dongle prototypes. I guess that my first rev-b prototype will be assembled by the end of this week (will it work though? fingers crossed…). In the dahdi driver front, I am ready to write the code for the isochronous engine. It still bugs me that I am not sure how often I need to tick dahdi_send()/dahdi_receive(). Theoretically, these two should be ticked once every millisecond. However, in dahdy_dymmy.c (the HR-timer based dahdi timing module), the code seems to tick dahdi_send/receive four consecutive times every four milliseconds. So, presumably, I could do the same, by calling the two functions N times at each URB completion time  without incurring too much inaccuracy [it might help to remind that in isochronous USB it makes sense to transfer N (N ≥ 4) packets per URB, so I get a completion callback only once per N milliseconds].  Thus, I ‘ll make my first attempt along these lines, and I ‘ll report on how good it will work.


14 Responses to “Some interesting (?) updates”

  1. Alok Says:

    Can we make the casing of the Dongle itself as Heat sink.probably it help in making low profile dongle for final finished product.A four layer would increase the cost

  2. Angelos Varvitsiotis Says:

    Hi Alok,

    Sure, you are right about the higher cost of a four-layer PCB. Using the case as a heat sink is also a viable solution, provided however that the case is metallic and not plastic. Note however that a metallic case would also be more expensive than a plastic one. I ‘ve been trying to think of other solutions as well. For example, a metallic screw could be fitted into the hole underneath the 3201 (that is, on the top side of the board) and heated until it would be soldered to the chip’s thermal pad. Then, a heat sink could be fitted on that screw, only this time the heat sink would sit on the top side of the board, which doesn’t need to keep a low profile like the bottom side. Yet all these things are hard to mass-produce automatically, and thus they would also raise the final cost. Maybe the cheapest solution is the discretes, only it requires much work and validation.



  3. dazza Says:

    Maybe you can conduct the heat onto the USB connector itself.
    Solder a strip of copper to the metal shield of the USB plug, and then build a heat bridge to the hot chip.

    You can easily insulate the exposed copper with a strip of sticky tape or industry standard Kapton tape to avoid short circuits.

    This can be used in conjunction with the 4 layer PCB heatsink.

  4. Angelos Varvitsiotis Says:

    Hi Dazza,

    Thanks for your suggestion. It’s a good idea, and it may work alright. For the time, I have already started to redesign the output stage of the dongle board, so that the hot 3201 is placed almost underneath the RJ11 plug and as far away as possible from the other two chips. I ‘ll try to leave a large contiguous area without any components on the opposite (top) side of the board, and connect the thermal pad of the 3201 to that area using a “via” with a wide enough hole, so that I can connect thermally the two areas via a blob of solder. I guess that will do much better than the current board. I ‘ll post a part of this new PCB design (unfinished, as it is now) in an update to my latest post for you to see what I mean. Anyway, thanks again for the suggestion, I may use it anyhow in conjunction with the changes I am making.



  5. edwin Says:

    What is the voltage you need for the RJ11 port? we use the 3201 in the fxs module also in the ip04 design. If a 24v output is ok with most of the case ( a short rj11 line, a plain regular phone , a pbx that don’t need ringging), then you can set the chip to low power mode. it will dramatically reduce the heat.


  6. Angelos Varvitsiotis Says:

    Hi Edwin,

    Thanks a lot for your comment — a very useful suggestion indeed. I am not sure how exactly one can set the 3201 to “low power mode”, nor how one does lower the voltage on the chip’s output. Maybe by lowering the VBAT voltage on the respective input pin of the chip? If so, are you suggesting that I could lower VBAT to 24V or something like that? Currently, I am using VBAT=65V. I would be grateful if you could supply some additional details.

    On the other hand, I think that it will be nice if the Open USB FXS dongle board can support a “regular” FXS line as well. The current setup in Open USB FXS should be able to support a line of 2000 ft max., with one phone set (NREN=1), so that, say, people in a community could lay cable from a central facility to a somewhat distant location. [Caution, fellows, the circuit as it is now does not include surge protection for an outdoor application like this, but one could supply an small external add-on circuit to remedy that]. Anyway, saving power is always a good idea, so I would definitely like to know more details re. your suggestion — so, even if I come up with a better heat-sink PCB design, if not anything else, I could provide a “low-power” alternative setup for a typical indoor application like the one you are describing.

    Thanks again for this very useful comment!



  7. Dazza Says:


    Considering you are trying to free up as much space as possible, it maybe worthy to migrate the current PIC from a 28-Pin SOIC PC18F2550 to its smaller cousin the 44_Pin-TQFP PIC18F4550 (0.5mm pitch)

    This would save you PCB space, allowing you to build a smaller board or providing you with more room for heatsink space.
    Soldering a TQFP is a little bit more challenging, but not too difficult. Just use lots of flux, and start with opposite corners first to align the TQFP.

    Also, as for placing “hot” 3201 ICs under PCBs may not be such a good idea, because heat naturally rises.
    There are only three ways to get rid of heat: “Conduction, Convection, Radiation (Black body)”
    So the heat (and the heated air) may just linger around the chip, only allowing primarily for heat conduction via the PCB to draw the heat away.

    Is it possible to place the Si3201 on top of the board?

    I feel that by placing the hottest chip on the bottom may reduce the ability to “convect” the heat away. Plus putting an upward facing heatsink will provide better heat removal, as opposed to a downward facing one.

  8. Angelos Varvitsiotis Says:

    Hi Dazza,

    Thanks for your suggestion and your extensive explanations.

    Yes, I have considered the QFP PIC package and may switch to that in a later revision. I haven’t done so yet, mainly because I did not want to use a higher-price PIC (4550), in order to keep the cost of the board as low as possible.

    About the 3201, there is one minor point worth discussing: the chip has a thermal pad underneath it, which must be soldered to a copper area of equal size. Thus, placing the 3201 (turned upside down, of course) on the bottom PCB side means that the hottest side of the chip will be actually facing upwards! When hand-soldering, the only way to solder the thermal pad is through a hole. In my first version of the dongle, this was a plain hole (not a “via”, which is plated), and that hole led to an area on the top side which was close to the other chip (3210) and densely populated by other SMD components. It’s natural that both the other SMD components and the 3210 became hot as well, because the densely populated area simply did not contain a contiguous surface with enough copper on it to radiate/abduct the heat away.

    Now, in my second PCB design attempt, I have used a “via” instead of a plain hole (so as to connect the thermal pad of the chip to the top side) and have left an empty copper area on the top side. I will also leave part of this copper area exposed without a solder mask, so that an (upwards-facing) heat sink can be soldered or otherwise fitted directly on that area if need be. I hope that all this will cure much of the problem, but if it doesn’t, I ‘ll make sure to consider flipping sides and placing the chip on the top side.



  9. sal Says:

    angelos i started to put some devices in the basket from mouser. You can check and continue if you like! I make all the stuff modifiable

  10. Angelos Varvitsiotis Says:

    Hi Salva,

    This is great, thanks! Currently I ‘m a bit disconnected (replying from my mobile). It ‘s the Orthodox Easter, and at the place where I am, it ‘s hard to get me a decent Internet connection. I ‘ll be able to catch up from next Tuesday.

    Thanks again for helping out!



  11. Angelos Varvitsiotis Says:

    Hi Salva,

    I have now checked the project materials basket that you have created in It’s great, only it still needs some work in order to complete the full BOM. You are welcome to go on with it, since it will be a great help to anyone wishing to order materials directly.



  12. sal Says:

    Hi angelos did you refreshed your bom? So i can check and continue to add to mouser. Cheers salva

  13. Angelos Varvitsiotis Says:

    Hi Salva,

    There are not any tremendous changes in the BOM. The phrase “refreshing my BOM” that I wrote in my last update means checking out the quantities of parts that I have stashed from previous orders, not altering the actual BOM. There are a few changes, though: I have now included a 2×3 pinhead connector instead of the board edge one; I noted that I have used a through-hole USB Type-A plug in my board, so I have changed the SMD part with a through-hole one (Farnell #1696544); and I have made a note to check Kingbright side-view LEDs (e.g. Farnell #8530335) instead of the plain 1206-type ones I have been using so far, because this is actually needed in order for the LED to be visible from the side of the dongle. Other than that, the posted BOM is fully up-to-date.

    One thing that you need to watch for is part availability at Mouser. In your Mouser basket I have noted that some items are in back-order status, which means that Mouser have ordered them, but currently do not have them in stock. Including these may delay your order until Mouser receives all back-ordered parts. Probably there are other equivalent in-stock parts that you can select instead of the back-ordered ones, or else it’s probably best not to include back-order items at all, especially if it’s for easy-to-find ones, such as capacitors and the like.

    Keep up the good work!



  14. Angelos Varvitsiotis Says:


    Please ignore my previous reply. I found the code within wctdm.c that implements “low power” mode. It sets direct register 72 of the Si3210 (on-hook voltage) to a lower value (24V instead of my 48V) and indirect register 21 (ring peak voltage) to 50V. This is indeed much lower than the default values. I have implemented the code in my new driver and will check to see how it does with the heat.

    Thanks again!



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: