Scott Dattalo says
Speaking of mixing tones, during my hiatus I wrote a cute little twist routine. While primarily intended for adjusting the twist in DTMF generated signals, it has applications elsewhere too. It would work here to mix two arbitrary waves. You could cascade calls to this routine for mixing more than two tones. For N tones you'd need N1 calls. That's not terribly efficient, but at least you'd have a way of combining fixed waveforms with non 2^k weighted coefficients.The purpose of this routine is to evaluate:
A*x + B*y  A + BSuch that A+B = 2^N
This formula is useful for several applications. For example, DTMF generartors sometimes need to weight the individual sine waves differently. The term used to describe the difference in amplitudes is 'twist'. It's the ratio of the amplitudes in dB.
Another application of this formulation is for lowpass filtering. If 'x' is the current filtered value, and 'y' is the latest sample, then this equation will be a recursive lowpass filter. ztransforms may be used to calculate the frequency response, but that's beyond the scope of this simple description. An intui tive way to look at it is as weighted averages. If A is made large relative to B, then more emphasis is placed on the average. If B is large then the latest samples are given more weight.
Algorithm:
This algorithm exploits the relationship: A + B = 2^N. For example, consider N=4. Then the (A,B) pairs are:
(1,15), (2,14), (3,13), (4,12), (5,11), (6,10), (7,9), (8,8) i.e. B = 2^N  A , and , A = 2^N  BUpon closer examination, it's observed that the (A,B) pairs are two's complements of one another (modulo 2^N). E.g., the 2's complement of 1 mod 16 is 15. In general:
B = (~A + 1) % 2^NSubstituting this into the twist formula yields:
A*x + ((~A + 1) % 2^N)*y  2^NA modulo N operation means that only the lower N bits are significant. So dropping the notation and keeping this observation in mind we can simplify this equation:
A*x + (~A + 1)*y A*x + ~A*y + y  =  2^N 2^NWhich can be evaluated in psuedoC:
int A; /* initialized somewhere's else */ int twist ( int x, int y) { int num = y; num += (A & 0x01) ? x : y; num >>= 1 num += (A & 0x02) ? x : y; num >>= 1 num += (A & 0x04) ? x : y; num >>= 1 num += (A & 0x08) ? x : y; num >>= 1 /* etc. for N>4 */ return num; }Excution time: 1 + 5*N cycles (e.g. 21cycles for A+B=16=2^4)
twist: movf y,w movwf num btfsc A,0 movf x,w addwf num,f rrf num,f movf y,w ;A macro would work well here... btfsc A,1 ;All we're doing is an unrolled movf x,w ;multiplication. If a bit in 'A' is addwf num,f ;set, we add 'y' to the running sum rrf num,f ;otherwise we add 'x'. In either case ;we divide by 2. movf y,w btfsc A,2 movf x,w addwf num,f rrf num,f movf y,w btfsc A,3 movf x,w addwf num,f rrf num,f return
See also:
file: /Techref/microchip/dttwist.htm, 4KB, , updated: 2005/10/11 16:54, local time: 2021/4/11 09:11,

©2021 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://techref.massmind.org/techref/microchip/dttwist.htm"> Scott Dattalos' Dual Tone Digital Twist for the PIC</A> 
Did you find what you needed? 
Welcome to massmind.org! 
Welcome to techref.massmind.org! 
.