I'm sure John meant this to go to the list and not to just me. Return-Path: Received: from Kitten.mcs.com (Kitten.mcs.com [192.160.127.90]) by unix.sri.com (8.8.8/8.8.5) with ESMTP id TAA17083 for ; Thu, 29 Jan 1998 19:52:47 -0800 (PST) Received: from Jupiter.Mcs.Net (supercat@Jupiter.mcs.net [192.160.127.88]) by Kitten.mcs.com (8.8.7/8.8.2) with ESMTP id VAA01855 for ; Thu, 29 Jan 1998 21:54:57 -0600 (CST) Received: (from supercat@localhost) by Jupiter.Mcs.Net (8.8.7/8.8.2) id VAA18854 for sdattalo@unix.sri.com; Thu, 29 Jan 1998 21:54:57 -0600 (CST) From: John Payson Message-Id: <199801300354.VAA18854@Jupiter.Mcs.Net> Subject: Re: frequency noise ? To: sdattalo@unix.sri.com Date: Thu, 29 Jan 1998 21:54:56 -0600 (CST) In-Reply-To: <34CFF3BE.6336@unix.sri.com> from "Scott Dattalo" at Jan 28, 98 07:13:02 pm X-Mailer: ELM [version 2.4 PL24] Content-Type: text X-Status: > Now what's neat about this, is that we can handle all eight > inputs simultaneously. In other words, we can allocate/name > a PIC register 'D' and let it hold all 8 of the LSB's, let > 'C' hold the next LSB etc. I call these vertical counters > (although there may be a more appropriate name) because if > you view the RAM they occupy as a stack, then the counter > bits are grouped vertically instead of the more familiar > horizontal-single-register way. I've used this technique as well. It has some advantages over the more conventional techniques: [1] It's faster than conventional routines if you need to count on all eight inputs, and if the counts are less than or more than 8-bits long. Note that down-counters are faster to code than up-counters: ; Assuming inputs to this stage are in W xorwf StageN,f andwf StageN,w Two cycles per stage to handle all eight inputs, regardless of the number of stages. [2] It's straightforward to have the counters operate with a modulus other than 2^N (i.e. they wrap after some other number of counts). Just use some xorwf's on specific stages with the carry out of the last stage (or, if desired, the carry from intermediate stages). [3] It may require less memory to store the counts than conventional meth- ods. For example, storing eight 6-bit counts would require six bytes rather than eight, and storing eight 10-bit counts would require ten bytes instead of sixteen. [4] It interfaces well with certain other count- or frequency-generation methods. For example: [1] You wish to generate output pulses whose frequency is (FreqN/4096) times the rate at which a subroutine is called. You can use code like this: movf Freq0,w addwf Phase0,f rrf Temp,f movf Freq1,w addwf Phase1,f rrf Temp,f ... movf Freq7,w addwf Phase7,f rrf Temp,w xorwf TopPhase0,f andwf TopPhase0,w xorwf TopPhase1,f andwf TopPhase1,w xorwf TopPhase2,f andwf TopPhase2,w xorwf TopPhase3,f At this point, TopPhase3 contains the desired eight square waves. The total time [including the omitted portion] is 31 cycles. There is no way to even come close to that by purely conventional means. A second useful frequency-generation method is to have the least-sig- nificant N bits of the desired frequency stored in Freq_L0 through Freq_LN [with Freq_LN being the most significant of that group], and then use: incf Count,f movlw 0 btfss Count,3 ; However many bits you have... movlw Freq_L0 btfss Count,2 movlw Freq_L1 btfss Count,1 movlw Freq_L2 btfss Count,0 movlw Freq_L3 movwf FSR movf IND,w and then use the resulting value in W as input to the sideways count routine given above. Note that this code is faster than conventional addition and also DOES NOT REQUIRE ANY RAM other than the "number of times called" counter which may be useful for other things. The one important caveat, though, is that the output waveform from this rou- tine won't be very clean; if you feed it through several counting or addition stages, though, it should be okay. [5] For frequency generation, it's possible to use a technique analagous to sideways counters to do sideways addition. The code for this ends up being very fast (3 cycles/stage) but also rather cryptic; some of the bits in the accumulating registers will be "normal" while others will be inverted. Since the item of interest is the carry-out, the meaning of the other bits doesn't matter, but working them out can be an interesting challenge. For those who want to try it, the repeated sequence is: ; Carry-ins are in W xorlw [constant] xorwf StageN,f andwf StageN,w ; or iorwf... the next constant will be ; different if the latter, but if iorwf ; happens to make the next constant zero ; then use it and save a cycle. This routine works very nicely with the technique in [4]; you may use the technique in [4] to handle the LSB's of the frequencies while using this technique for the MSB's. Using the tricks of vertical addition, it is possible to detect DTMF tones reliably on a 16C622's comparator (7200Hz sampling rate, 11.052KHz crystal, about 60% CPU utilization). Frankly, I'm not sure such a thing would even be really possible without such tricks.