Audio over wireless serial
GaryT
Posts: 11
I've been working on sending audio from Prop to Prop for a while and with help from Mike, Peter, and Tim, I've had some success. I'm sending low (very low) quality voice data, "Watson, I need you"[noparse];)[/noparse] Thanks guys!
Then I thought it would be REALLY cool without a wire, so, I'm wondering if anyone has done anything with transmitting audio using the Propeller and some kind of wireless device? Wireless analog seems like it would be great for that, is there a digital option? Just doing some quick math, it seems like at a rate of 115K (typical Zigbee type rate, I think) transmission rate would be too slow to send the data stream I'm generating now, and it's very poor anyway. Would there be some kind of compression possible? A CODEC type IC that's made for this? Or am I so naive that I'm asking stupid questions?(please be gentle if the answer is that I'm stupid.)
Thanks for any help, and all the other very useful posts!
Gary
Then I thought it would be REALLY cool without a wire, so, I'm wondering if anyone has done anything with transmitting audio using the Propeller and some kind of wireless device? Wireless analog seems like it would be great for that, is there a digital option? Just doing some quick math, it seems like at a rate of 115K (typical Zigbee type rate, I think) transmission rate would be too slow to send the data stream I'm generating now, and it's very poor anyway. Would there be some kind of compression possible? A CODEC type IC that's made for this? Or am I so naive that I'm asking stupid questions?(please be gentle if the answer is that I'm stupid.)
Thanks for any help, and all the other very useful posts!
Gary
Comments
That's usually enough for *excellent* voice quality.
Even without any processing, 8 bit - 8Khz is good voice quality.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pull my finger!
The least complicated thing to do would be to replicate a simplified version of the S/PDIF interface (specified by the AES3-2003 document). Take a look at this wikipedia entry on biphase mark code. Basically you take a clock at 2x the data rate, and every time there is a "1" for the data bit there is a transition at each (rising/falling) clock edge, for a "0" there is only a transition for the rising edge of the clock. This makes clock recovery fairly easy, as there are only two possible edge delays (either half a clock period for a "1" or a full clock period for a "0"). The AES and S/PDIF interfaces use a "frame header" pattern that does not conform to the biphase mark encoding scheme - where there is always an edge at least every clock cycle, but with the headers (three unique patterns for AES and S/PDIF since it's a stereo interface, and needs to encode low-speed meta data) this is not the case. To make it not look like an encoded bit, use three bit periods (6 clock edges), but invert the output from the previous state for three edges and then invert it again for another three (instead of two or one for valid data). This will maintain the favorable zero-DC average (less noise) and polarity agnostic characteristics - this is great if you need to drive a fiber-optic LED with a low-side switch as that will not require inversion on the receive side, or if you use an RS-485 transmitter and get the polarity of the wires swapped at either end .
A header would be encoded as: invertstate-laststate-laststate-invertstate-laststate-laststate
A "0" would be encoded as: invertstate-laststate
A "1" would be encoded as: invertstate-invertstate
As an example:
if the previous bit was "0" the header would be 1-1-1-0-0-0
if the previous bit was "1" the header would be 0-0-0-1-1-1
if the previous bit was "0" a zero data bit be would be 1-1
if the previous bit was "1" a zero data bit be would be 0-0
if the previous bit was "0" a one data bit be would be 1-0
if the previous bit was "1" a one data bit be would be 0-1
On the receive side, you look for edges. When you find an edge, you start counting until the next edge. You are looking for three lengths, of "multiple" value (i.e.: 1x, 2x and 3x). When you have enough samples of each (I'd aim for at least four instances of a "header" to get the initial average), then you'd wait for the next "3x" ("header") pattern to arrive, and then start decoding bits and writing them into your output word. The data should not be considered "valid" until you successfully get the next "header" where it is expected to be (if you don't get the header where it should be, it's probably a safe bet that something is wrong with the link). Additionally you can add a checksum to the stream (at the cost of more bandwidth being required), but at least do a parity bit encoded as data for another "gut-check" on the receive-side. For example, you can "add" the bits together (i.e. for 4-bits: 1 + 1 + 0 + 1 = 3) and take the LSB of that addition and use it as a parity data bit. This way, if you sent the example four bits, but got a "0" for the parity - the receiver should not consider the data "valid". You can output the result of this parity check (1/0 or Valid/Invalid respectively) at the end of each pattern's receipt then logically "AND" that result with the check that ensures the new header arrived when expected (1/0 or correct-spacing/incorrect-spacing respectively). The result from that logical AND can be sent to an indicator LED as a fairly simple "link good" status indicator for your receiver.
For a 16-bit sample at 16kHz, which would sound about like a telephone, you'd need 20 bit periods (three for the header, one for the parity, and 16 for the data). This would necessitate a link that could support 640kpbs (320kbps for the data itself, but with the clock embedded it's 2x). This rate is very do-able with cheap RS-485 transmitters or fiber-optics.
-Tim
Post Edited (GreyBox Tim) : 11/22/2008 6:34:19 AM GMT
Thanks for any help,
Gary
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pull my finger!
Thanks,
Gary
Thanks again for the direction, if I have any luck I'll let you know.
Gary