For square wave generation I would use the PWM unit with 50% duty cycle for lower frequencies, and the numerically controlled oscillator peripheral (NCO) for higher frequencies. You could even use a CLC to switch between them seamlessly. You don't want to waste time farting around with bit banging and instruction-bound delays. It takes a bit of reading and testing to use one, but then the updates to frequency are fast and simple, and you can spend processor cycles calculating the next update, servicing other routines, etc. On Wed, Jul 13, 2016 at 7:39 AM, Denny Esterline wrote: > I'm not an assembler guy, so I've been staying out of this. > > Looking at your specs, I think you're making this more complicated than i= t > needs to be. > Your fastest specified frequency at 2.65kHz gives a period of 377 uSec. > with 50% duty > cycle, that gives about 190 uSec between transitions. Now, you didn't > specify a clock > frequency for your PIC, but that one will run 20MHz -> 4e6 instructions p= er > second > Unless I forgot how to math last night, that's 950 instructions per > transition worst case. > Unless you have a bunch of other stuff for the PIC to be doing, that's > plenty of time > to toggle a couple pins and calculate the next delay time. To me this loo= ks > like this: > > Start loop: > DealWithOutputs() > calculate delay time > execute calculated delay > return to start of loop > > > Calculating delay times becomes a trickier bit, but... To me it looks lik= e > you could add > a loop counter and use the loop count variable to influence the delay > times. > Your sweep of 500Hz to 2.65kHz (-> 1mS to 190uS per transistion) gives us > delays > of 4,000 to 950 instruction times. The simplest form of this with a loop > variable > counting up from zero: > DelayTime =3D LongestDelayTime - (LoopCount * StepSize) > > In this example you calculate the constant beforehand with > StepSize =3D (LongestDelayTime - ShortestDelayTime) / NumberOfSteps > > Where "beforehand" could be pencil and paper before compile or in code > before > entering the loop. > > There's better ways to do this math, this is an intentionally simplified > example. > > > One of the problems with this approach is the processor is _always_ busy. > There's > no time left to handle other tasks. That might be Ok depending on your > application. > Or it might be a problem. i.e. if you send it commands via UART, you'll > have an audio > glitch while it handles that. > The solution here is to replace the busy loops with a timer interrupt. > Basically you > shove the body of the above code (not the loop part) into the interrupt a= nd > put a > calculated value into the timer to interrupt after the planned delay. Tim= er > math is a > little different, but it's basically the same shape. > > Another problem with the math of this example is your frequencies are goi= ng > to sweep > at an exponential rate. The changes happen at cycle rate, cycle rate gets > faster > during the sweep. More math can fix this if it's a problem, but 950 > instructions puts a > hard limit on how complex the math can be. > > So, to add the idea of a lookup table to this..... > Basically, you can precalculate a list of delay times. Store them as an > ordered list, > then use the loop count variable to index into the list to retrieve the > next delay time. > This is a classic engineering trade off, use more memory space to avoid t= he > run-time math. I don't think it's viable in the 16F1503 (2k FLASH) but it > might be > an option in the larger parts in the series. Personally, I don't think it= 's > justified > in this example, but, that's just me. > > A more elegant version of this might be to run two timers. One at a fixed > rate > that adjusts the delay time and the second to actually handle the output > pins. > Lots of ways to implement that, but the upside is you decouple the > frequency > change rate from the output frequency. That makes the "NumberOfSteps" a > lot easier to calculate. > > > There's also a worthwhile conversation to have about assembly vs > High-Level-Language > here, but life on the PICLIST has taught me that the conversation will > devolve > into a flame war in about 0.001 seconds. So, I'm gonna leave that alone. > > > > Let us know if that helps. > -Denny > -- > http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist > --=20 http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .