Monday, November 8, 2010

Codec2 on Pic32: First Steps

In the dynamic field of digital ham radio projects, Codec2 just might be the most exciting one of all. A very low-bandwidth voice-to-digital codec has any number of uses: in fact, it is so important to future digital radio infrastructure that the D-Star architecture ended up using a proprietary codec for this purpose. Of course, D-Star's black-box chips are not most ham's style; we like to tinker; and in some contexts, like SDR radios and satellite communications, it's very difficult to work with locked-in hardware and code.

Enter David,  VK5DGR. He is  using his Ph.D. research to produce a patent-free voice codec for radio amateurs, with loud cheering from Bruce Perens, who has long championed this idea. The code is recently out in alpha , compressing to 2500 bps. It built quite happily on my Linux box, and the c2enc and c2dec applications will convert from and to 8000 bps, 16 bit signed RAW audio, producing very intelligible results.

Since I had a PIC32 chip on the bench, I decided to set aside work on the qrpTracker and see how far I could get in porting Codec2 to the PIC32. It isn't working yet, and I think we'll need integer math to get there, but I've made some progress.

The short story is that I can get the PIC32 to pass the tquant.c unit test (which I rewrote slightly to remove the need for a filesystem), and I can get it to produce decodes, but these are not the same as what is produced by my linux box. Moreover, the PIC32 stops decoding after about 8 7-byte frames, and I'm not sure why.

Finally, although my code is all ready to pipe the decodes to a speaker attached to a PWM output, I don't think the current implementation (which does all the math with floats) will be fast enough for real-time decoding at the PIC32 current maximum speed of 80 MHz. However, there is a PIC32 DSP library (integers) whose functions are very much like some that David bases his work on, so once David's architecture moves to 16 bit integers instead, we should see some great speed-ups.

Here, in no particular order, are some of the issues that I faced. First, the build process does some code generation, producing a 'codebook.c' file, which later gets compiled into the library. Thus, I needed to build the code on a linux box first, and copy over this file with the others. Second, the code does two malloc calls, and these need about 1200 bytes of stack. In PIC32, you need to tell the linker about this. Happily, David's code uses many asserts, which compile nicely and print out to UART2, so this was quite clear. Thirdly, I wasted a few hours trying to get this all to work on the PIC32 simulator and being beset by obscure errors which I'd ascribed to the heap and stack. After reading that the Sim was buggy, I decided to try the code on silicon, and sure enough none of the errors appeared (at least not in the first few decodes).

Lastly, since I'm using the CUI32 board, which has a PIC32 with 32kB of RAM, I'm terribly short on space. There's just enough to run the code alongside a serial port, interrupt and timer, so that some day we can make sounds. I'd started out hoping I could use a MMC/SD with filesystem, but I'd need at least 64kB for that. Because I'm so short on space, I can't compile in the debugger, making some of the issues above into little mysteries.

Still, the code does convert 7 byte frames into 160 16-bit signed integers, it just appears they are the wrong ones, and it does pass a unit test. I'm hoping some of the other unit tests will be rewritten so I can get closer to the issues, especially if they were to be rewritten with no need for a filesystem.

No comments:

Post a Comment