On Thu, 23 Aug 2001, Olin Lathrop wrote: > > About PLL: > > I know that a PLL is used to lock on to a special freq > > but everyone here seems to agree on that it can be used > > to multipy by 8 ?!? > > A PLL (phased locked loop) locks the output of its own oscillator to an > incoming signal. It does this by adjusting the frequency of its own > oscillator from the phase error between the two signals. Now suppose the > oscillator was run thru a counter to divide its frequency by N before being > phase compared to the input signal. If oscillator/N is phase locked to the > input, then oscillator must be input * N. > > I've left out lots of details, especially regarding implementation and > limitations, but I'm sure there is LOTS of stuff on PLLs out there on the > web. Multiplication by 8 is especially easy. If I were to implement this in software I'd go about it like this: 1) Measure the time between rising edges of the ~50Hz signal. This will give you the period for one cycle. 2) Filter the measured period with a recursive low pass filter of the type that's been discussed before here. 3) Divide the filtered 50Hz period by 8 (i.e. shift right 3) and you'll have the period of the ~400Hz wave. Now, you'll actually want to divide by 16 instead of 8 so that you can obtain the time for the "half-period" and thus know how long the ~400hz wave is high/low. The challenge is to merge these three operation into one seamless (or seem less) isochronous algorithm. While I don't have time to fill in the details, I can suggest a few snippets: Capture rising edges: main_loop_start: ; last_state = last sampled value movf IOPORT,W ;sample ~50hz waveform andlw IOMASK ;get only the bit of interest xorwf last_state,W ;compare to last sample (W=1 if different) xorwf last_state,F ;save this sample as the old value andwf last_state,W ;If there's a difference and it's high ; then we found a rising edge skpnz goto L1 ; filter accumulated 50 hz period... ; clear 50 hz period counter ML1: ; re-entry point for isochronous delay ;main isochronous loop flow . . . goto main_loop_start L1: incf period_50Hz_low,f skpnz incf period_50Hz_high,f ; skpnz ;if 24 bit counter is needed then uncomment this ; incf period_50Hz_real_high,f ;delay an amount equal to the time required to filter ;the period. ... goto ML1 ;re-enter flow of isochronous loop ----------------- ; shift fperiod (filtered 50Hz period right 4) swapf fperiod_hi,W ;Shift high byte right 4 movwf p400_hi ;and put it into 400Hz period counter andlw 0xf0 ;but upper nibble goes into low byte movwf p400_lo xorwf p400_hi,f ;Clear upper nibble of high byte swapf fperiod_lo,W ;shift low byte right 4 andlw 0x0f ;put the high nibble into iorwf p400_lo,f ;the low nibble of p400 ; ; note that this will leave the upper nibble of p400_hi ; equal to zero and that the low nibble of fperiod is thrown away decrementing the 400hz period counter: ;------------- movlw 1 ;subtract 1 from the 400hz half-period subwf p400_lo,f ;counter. The carry gets cleared when skpnc ;count underflows. Note that this is subwf p400_hi,f ;an extra count that may have to ;be accounted for movwf IOPORT,w ;read current 400hz waveform state xorlw b400HZ_OUTPUT ;invert it skpc ; did counter reach zero? movwf IOPORT ;yep, so write new state. Out of time... Scott -- http://www.piclist.com#nomail Going offline? Don't AutoReply us! email listserv@mitvma.mit.edu with SET PICList DIGEST in the body