Tap Tempo LFO with PIC 16F684

Started by ElectricDruid, May 13, 2009, 05:22:13 AM

Previous topic - Next topic

3080

#100
Quote from: JKowalski on February 08, 2010, 01:03:19 PM
Quote from: 3080 on February 08, 2010, 01:01:32 PM
Quote from: JKowalski on February 08, 2010, 12:57:17 PM
Quote from: 3080 on February 08, 2010, 12:48:16 PM
Quote from: JKowalski on January 27, 2010, 01:48:16 PM
Another PWM output solution:

It's easy to change the 0-5V LFO output to any voltage range. For example, say you want a 0-9v Analog LFO output. You just put the PWM output into a CMOS buffer with 0/9v supply and filter the output of THAT. Now you have a 0-9v analog LFO after filtering. 5/-5v? Use a +5/-5 supply CMOS buffer (or anything very high gain)

If you want to get a... say 3-6V P-P LFO wave output, to get around the supply rail limitations for most op amp inputs (they cant go ALL the way to their supply rails) just put a potentiometer on the output of the CMOS buffer (or op amp) to divide the digital PWM signal down to the voltage range you need.

The PWM output is actually VERY versatile.

which CMOS you prefer?

Well it doesn't even have to be CMOS, just anything that can buffer a digital signal. It just has to be able to trigger on the 0-5V PWM and output a x-yV digital signal. I prefer CMOS digital chips because they are simple to use and they waste less power then other methods. Any ol' chip under the sun that can do the above (logic gates, inverters, digital buffers, hell even flip flops) would be usable. You just got to make sure the supply voltage ratings aren't exceeded.

i will try it with 40106...

That will work perfectly. Just remember though when you invert the PWM signal you invert the LFO, so if you want it back to the original you have to invert it again somewhere down the line. Or you can just use two inverters in series.

The VCLFO's Level control is working the same az the TAPLFO's?
If yes... then I need to invert it...
I'm going to do a phaser with this LFO... and I wanna add Start and Stop pots (something like on the new EHX Polyphase)...
So if it works az the TAPLFO's, then I will invert the PWM, and the Level pot will be the Stop...


bunnycat

Would somebody mind posting their schematic / pcb for this if they have it?  The ones that were previously posted seem to have disappeared.  I'd love to learn PIC programming and this seems like a great project!!

Taylor

If you look here:

http://www.diystompboxes.com/smfforum/index.php?topic=80407.120

a PCB will be available in a couple of weeks. It's a tap tempo trem, but if you just want a tap tempo LFO, the PCB can be used for that as well.

flo

Quote from: bunnycat on February 25, 2010, 09:12:41 PM
Would somebody mind posting their schematic / pcb for this if they have it?  The ones that were previously posted seem to have disappeared.  I'd love to learn PIC programming and this seems like a great project!!
See also:
Tap Tempo LFO (TAPLFO V2) - electricdruid
http://www.electricdruid.com/index.php?page=projects.taplfo

jakefuzz

I don't really want resurrect a dead topic but I have a question about this tap tempo chip. Does the clock output pin output the LFO frequency before or after the multiplier? I tried wading through the assembly code but that stuff is so far from C I don't know what I am looking at half the time. The reason I ask is because I am trying to send the clock output steps to a decade counter as a sequencer, but I want the counter steps to be the slowest base frequency of the LFO chip before and regardless of the multiplier. (so for 1 step on the decade counter the LFO goes (1 x multiplier) number of steps or output waveform periods).

And if it is post multiplier, how do I go about changing it?     

cloudscapes

Quote from: jakefuzz on November 15, 2010, 02:52:47 AM
I don't really want resurrect a dead topic but I have a question about this tap tempo chip. Does the clock output pin output the LFO frequency before or after the multiplier? I tried wading through the assembly code but that stuff is so far from C I don't know what I am looking at half the time. The reason I ask is because I am trying to send the clock output steps to a decade counter as a sequencer, but I want the counter steps to be the slowest base frequency of the LFO chip before and regardless of the multiplier. (so for 1 step on the decade counter the LFO goes (1 x multiplier) number of steps or output waveform periods).

And if it is post multiplier, how do I go about changing it?     

I dont think it outputs a clock signal. I think it outputs PWM (which is basically varying voltage). Not totally sure, though. I've not tried it.
~~~~~~~~~~~~~~~~~~~~~~
{DIY blog}
{www.dronecloud.org}

nelson

Quote from: jakefuzz on November 15, 2010, 02:52:47 AM
I don't really want resurrect a dead topic but I have a question about this tap tempo chip. Does the clock output pin output the LFO frequency before or after the multiplier? I tried wading through the assembly code but that stuff is so far from C I don't know what I am looking at half the time. The reason I ask is because I am trying to send the clock output steps to a decade counter as a sequencer, but I want the counter steps to be the slowest base frequency of the LFO chip before and regardless of the multiplier. (so for 1 step on the decade counter the LFO goes (1 x multiplier) number of steps or output waveform periods).

And if it is post multiplier, how do I go about changing it?     

If it does, you can always just tie the multiplier switch to also select pins on another decade counter, aswell as control the multiplier. Dividing it down by however much it is multiplied, to get back to 1x.

Breadboard the circuit and see!
My project site
Winner of Mar 2009 FX-X

JKowalski

#108
Quote from: jakefuzz on November 15, 2010, 02:52:47 AM
I don't really want resurrect a dead topic but I have a question about this tap tempo chip. Does the clock output pin output the LFO frequency before or after the multiplier? I tried wading through the assembly code but that stuff is so far from C I don't know what I am looking at half the time. The reason I ask is because I am trying to send the clock output steps to a decade counter as a sequencer, but I want the counter steps to be the slowest base frequency of the LFO chip before and regardless of the multiplier. (so for 1 step on the decade counter the LFO goes (1 x multiplier) number of steps or output waveform periods).

And if it is post multiplier, how do I go about changing it?      

The clock output is after the multiplier.

You can change the base multiplication (i.e. half or double or triple etc. the clock frequency compared to the PWM) of the clock output by changing one 6-bit number in the code. I found this useful to link multiple chips together, since the clock output needs to be 2x speed to clock another chip at the same frequency since the tap timer only reads negative going edges. (the act of reading a square wave as a tap tempo input acts like a frequency divider)

It's been a while since I have worked with the code but I can think of two things you can do.

1. Set up another phase accumulator, this one using RAW_INC instead of FREQ_INC. RAW_INC is the tap tempo frequency before multiplication. Toggle the clock based on this counter.

2. Depending on the multiplier setting, adjust the bit that the clock output toggles on. For example, if the multiplier is set to 2, toggle the clock every 2nd full cycle of the clock. If set to 0.5, toggle every half cycle. You'd have to set up come sort of counter, so that you can count how many clock cycles have passed.

The way the chip works when tapped in a very general sense is:

Tap input -> calculate timing interval in RAW_INC -> send to multiplication code and output to FREQ_INC

A timer runs in the background as the phase accumulator. This timer:

Adds current FREQ_INC to phase accumulator -> If bit 7 is on (end of phase accumulator cycle) toggle clock out

jakefuzz

Okay so for the first method. Just changing the phase clock variable, or do I have to change the phase variable as well because the clock output looks like it is evaluated from the phase clock variable.

; Increment the Clock Phase Accumulator (Provides non-distorted phase location)
IncrementPhaseClock:
   movfw   RAW_INC_LO   ; Add FREQ_INC_LO to PHASE_LO
   addwf   PHASE_LO_CLOCK, f
   
   movfw   FREQ_INC_MID   ; Add FREQ_INC_MID to PHASE_MID
   skpnc
   incfsz   FREQ_INC_MID, w
   addwf   PHASE_MID_CLOCK, f

   movfw   RAW_INC_HI   ; Add FREQ_INC_HI to PHASE_HI
   skpnc
   incfsz   RAW_INC_HI, w
   addwf   PHASE_HI_CLOCK, f
   
   ; If carry is set here, the Phase Accumulator has overflowed
   skpnc
   bsf   SEGMENT_END

; Deal with the Clock Output
   btfss   PHASE_HI_CLOCK, 7
   bsf   CLOCK_OUT      ; Glitch-free squarewave output
   btfsc   PHASE_HI_CLOCK, 7   ; Bit sets frequency multiple (below)
   bcf   CLOCK_OUT

; Bit 7=x1, Bit 6=x2, Bit 5=x4, and so on
; Use Bit6 for synching other TAPLFO chips since it measures the time between
; two pulses,  ; The output will also need inverting if it is to be used directly.

Can I do this and leave the rest of the phase accumulator intact? There is no RAW_INC_MID variable so I could probably just get rid of that central portion (and maybe even PHASE_MID_CLOCK). Also I just changed the phase clock increment routine, if I add a separate section to it preserving the old variable additions wont it add RAW_INC and FREQ_INC to the phase clock variable? I doesn't seem like the phase clock variable is used anywhere else so omitting the FREQ_INC additions wont change anything else but the clock output.

Nelson: interesting, I figured it would be only a few lines of code to change to get the clock output correct as opposed to adding more decade counters.

One more question, If I want to change the multipliers from (0.5, 1, 2, 3, 4...) to (1,2,3,4,6,8,16) Where 1 is the base frequency (RAW I guess) do I change the multiplier tables?

GetMultiplier:
        movwf   WAVETEMP
        movlw   HIGH MultiplierTable
        movwf   PCLATH
        movfw   WAVETEMP
        addlw   LOW MultiplierTable
        btfsc   CARRY
        incf   PCLATH, f
        movwf   PCL

MultiplierTable:
   retlw   D'1'   ; 1/2 note
   retlw   D'2'   ; 1/4 note
   retlw   D'3'   ; 1/4 note triplet
   retlw   D'4'   ; 1/8th note
   retlw   D'6'   ; 1/8th note triplet
   retlw   D'8'   ; 1/16th note
   retlw   D'2'   ; +2 dummy values for the top of the scale
   retlw   D'2'

I know for the majority of tremolo applications the latter multiples would seem redundant, but I wont lie, I am trying to build something that works like a Goatkeeper trem and for this the 1/2 multiple would be pointless and it would be nice to extend the range. 

jakefuzz

Ahhh, you know what, I am just going to use two divide by N chips (CD4018b) and a CD4011 to divide the existing output signal, this way I don't need to change any of the multipliers or the clock output and I can do hardware debugging rather than fiddle around with a language I don't know. Nelson has the right idea, but tying the pins together on a decade counter will limit the amount of denominators I can get out of a single CD4017 with minimal hardware. The best I can do is a 2P8T rotary switch for multipliers and one pole is going to changing the multiplier CV, that means I only have one pole to change the frequency divider for the sequencer clock.

JKowalski

Quote from: jakefuzz on November 15, 2010, 06:18:06 PM
Ahhh, you know what, I am just going to use two divide by N chips (CD4018b) and a CD4011 to divide the existing output signal, this way I don't need to change any of the multipliers or the clock output and I can do hardware debugging rather than fiddle around with a language I don't know. Nelson has the right idea, but tying the pins together on a decade counter will limit the amount of denominators I can get out of a single CD4017 with minimal hardware. The best I can do is a 2P8T rotary switch for multipliers and one pole is going to changing the multiplier CV, that means I only have one pole to change the frequency divider for the sequencer clock.

I can try to work something quick out for you if you'd like.

If you describe exactly what you are trying to make the chip do - what features you need/don't need. 

I'm working on a project that I might decide to start selling in pedal form (with permission from Tom), based on a modified version of this chip. If uses the PIC18F1320. It's basically the TAPLFO chip with a display output, 8 standard waveforms and then a switch to select 8 additional waveforms in memory - these waveforms can be customized, in the style of Cloudscape's tremolo design (where you draw out a waveshape with a knob). Also, the chip runs at 40mHz, enabling 10-bit PWM at 39kHz. I might fiddle with the tempo calculation to include averaging... Hardware multiplier simplifies the code a bit, too. If I complete this, I'll definitely post the code for you guys to play with as well. And if you guys think of anything interesting to add to the chip I am all ears!

jakefuzz

Sorry its been a while since i've visited. I am trying to make a goatkeeper like tremolo, essentially a sequenced tremolo with different waveforms. The problem with the current program is that to correctly sequence the counter clock (CD4017) you need the lowest frequency multiple (before it gets multiplied) as an output pin. I have been testing and experimenting with the code for the last couple of days, I have been able to add x5 and x16 multipliers and a post-multiplier clock pin out (instead of the next multiplier pin input).

The hardware design I am currently looking to build will send the pre-clock output (called half notes in the documentation) into the clock input pin of a CD4017 set up like a Zvex sequencer, these sequenced 5 volt pulses will run into a series of rotary switches (8 in total, one for each step of the sequence) and these will individually trigger the multiplier CV to whatever value is selected via the user on the rotary switches. So the multiplier will show a different value for each step of the sequence very similar to the goatkeeper.

I have also added a switchable NAND gate to the design in case the user wants to do a 90 degree phase shift on the clock output wave (mainly because the sine and triangle waveforms start high, but I thought it would also bee a cool feature to have)
Also unlike the goatkeeper the sequencer pulses and the post clock output are put through two quad AND gate chips to control each step led, showing the final frequency at the indicator for each step.



The problems I have been having so far:

I set up the phase_inc_clock timer to use the raw_inc increment rather than the freq_inc (post multiplier) increment, this makes the clock output independent of what multiplier is selected. The problem now is that clock out is about 100 times faster than the output waveform (at the lowest multiplier setting). I have tried everything I can think of to get the clock frequency back to the pwm waveform output frequency, no luck on this front.

The second issue is that the phases of the clock out and the waveform output are out of sync. I cannot see any defined relationship between the two and they start at different places almost every test run. For the post multiplier clock I was able to sync up the phases perfectly by triggering the clock output on a high 7th bit of the phase_hi variable rather than the phase_clock_hi variable. Works great, but the process to get here indicates that when I finally get the pre clock output working it wont likely be in phase with the wafeform output.   



I know it is kind of tough to explain, but I am confident if I can get the clock output to do what I want this would be a great design. Came up with the idea when someone asked about a diy goatkeeper over at the madbean pedals forum. If anyone else can figure this out that would be awesome, i will be working on it until I get it (no matter how long that takes!). I can draw up some paint pictures of the phase issue if anyone wants, i know that helps me to see what is going on. 

jakefuzz

That custom waveshape idea is awesome by the way. The new goatkeepers do that too I think, very, very cool. I would be very interested in that code.

jakefuzz

and if you don't mind me asking, how are you implementing hardware multiplication? Is it some sort of return loop to the microcontroller? or are you using a whole external clock section?

jakefuzz

   movlw   D'128'   
   movwf   TEMP2
   movfw   PHASE_HI
   subwf   TEMP2, w      
   btfsc           ZEROBIT      
   incf           PHASE2_COUNT, f
   movfw   MULTIPLIER
   subwf   PHASE2_COUNT, w   
   btfsc       ZEROBIT   
   bsf      CLOCK_OUT
   btfss           ZEROBIT
   bcf       CLOCK_OUT   
   btfsc           ZEROBIT
   clrf           PHASE2_COUNT

Ahh, why doesn't it work!!!!  >:(  This should count the number of times the output wave passes 1 whole cycle (PHASE_HI = 128) then compare that to the multiplier, when they are equal the clock will trigger high. Am I a retard cause this seems like it would work. It just gives me some funky random sputtering when the multiplier is set above 2.

JKowalski

Quote from: jakefuzz on December 04, 2010, 04:54:59 PM
and if you don't mind me asking, how are you implementing hardware multiplication? Is it some sort of return loop to the microcontroller? or are you using a whole external clock section?

The PIC18F series includes a hardware 8x8 bit -> 16 bit multiplier. This is used as another instruction, MULLW, MULWF. It's like the SUB and ADD instructions you are used to. The output is put into a special register for the low and high bytes.
Quote from: jakefuzz on December 05, 2010, 02:36:33 AM
   movlw   D'128'   
   movwf   TEMP2
   movfw   PHASE_HI
   subwf   TEMP2, w      
   btfsc           ZEROBIT      
   incf           PHASE2_COUNT, f
   movfw   MULTIPLIER
   subwf   PHASE2_COUNT, w   
   btfsc       ZEROBIT   
   bsf      CLOCK_OUT
   btfss           ZEROBIT
   bcf       CLOCK_OUT   
   btfsc           ZEROBIT
   clrf           PHASE2_COUNT

Ahh, why doesn't it work!!!!  >:(  This should count the number of times the output wave passes 1 whole cycle (PHASE_HI = 128) then compare that to the multiplier, when they are equal the clock will trigger high. Am I a retard cause this seems like it would work. It just gives me some funky random sputtering when the multiplier is set above 2.


I will have to check it out (and your previous message) tomorrow but I can tell you that you can count the wave cycles simply just by checking the high bit of the phase accumulator (when this bit is set, then the clock equals it's maximum value). The Clock_Out uses this method to trigger. Maybe simplifying will fix something.

jakefuzz

#117
Yeah, take your time, I have finals like a madman for the next couple of days. The way I understand (which very well may be incorrect) is that the phase accumulator high bit goes high when it reaches 1/2 of the cycle (=128) then it stays high until the remaining 1/2 cycle runs out (128-255). I just want it to increment my counter once for every one of these cycle changes so I evaluated just when the phase accumulator was at 128, I think if I triggered my counter from the high bit of the phase accumulator my counter would increment for every cycle in the last half of the phase accumulator (128-255) and trigger the clock far too many times. Sorry if my logic is just completely off about the way this works, this is like my crash course in assembly language programming.

jakefuzz

I got it to work using the raw_inc method (your first suggestion). Tom pointed out that raw_inc was 128 times faster than it should be so I bit shifted raw inc 7 times and it works!

I knew the phases wouldn't be in sync which is definitely a deal breaker for this method. Also the frequencies are just slightly off and over time will shift phases another big problem. I think the best method is to reference the wave directly, that way error wont accumulate in the phases.

jakefuzz

got it to finally work correctly using the following code! after a week of testing everything  :D

IncrementPhaseClock:


   btfsc   PHASE_HI, 7         ;Checking to see if the wave is onto the second half
   goto   skipper            ;if it is not then skip the increment section
   btfsc   OLD_COUNT, 0      ;if it is then check to see if there was a change from first to second half
   incf   PHASE3_COUNT, f      ;if there is a change increment the counter
   
   skipper:

   btfsc   PHASE_HI, 7         ;check the wave if it is the second half
   bsf      OLD_COUNT, 0      ;if it is set OLD_COUNT bit zero high
   btfss   PHASE_HI, 7         ;check the wave if it is the first half
   bcf      OLD_COUNT, 0      ;if it is set OLD_COUNT   bit zero low
   
   movfw   PHASE3_COUNT      
   subwf   MULTIPLIER, w      ;check if the cycle counter has reached the multiplier value
   btfsc   ZEROBIT            ;it has
   bsf      CLOCK_OUT         ;so turn on the clock
   btfsc   ZEROBIT            
   clrf   PHASE3_COUNT      ;also clear the counter to start over at this point
   
   btfss   PHASE_HI, 7         ;the wave is back to the first half so clear the clock
   bcf      CLOCK_OUT         ;this will make less than 50% duty cycle clock pulses, but it is the leading edge that counts (literally!)
   
   movfw   PHASE3_COUNT      
   addlw   D'127'            ;this section checks to see if the cycle counter has become larger than the multiplier
   movwf   BRAIN            ;this case will happen if the multiplier cv is rapidly changed
   movfw   MULTIPLIER         ;if it is larger then the counter needs to be reset
   subwf   BRAIN, f         ;if the counter isnt reset the counter will count to 255 until it resets itself
   btfsc   BRAIN, 7         ;which for out purposes (instant multiplier response) is not good
   clrf   PHASE3_COUNT


I think the multiplier change, reset section can be made better, but it all works! yay. now to make the triangle and sine waves start low b/c my clock invert function isn't going to work with a non 50% duty cycle clock. Thanks for all the help guys!