On Sun, 9 May 1999, erik wrote: > Hello all. > > I'm working on a project where I'm simulating a machine that we are > collecting a bunch of data from. > > The little gadget would have to be configurable via switches to output a > 50% duty cycle pulse at various > frequencies. > The maximum frequency would be about 71kHz. That means that I must > evaluate the configuration switches, > check a timer/counter, and turn on an output, plus execute the rest of > the program in about 72 instructions. > (that's if there are no jumps or gotos) > > It's becoming pretty clear that I just won't be able to do it. Why? > This output is to simulate an encoder and all other outputs must be "in > tune" with this encoder (machine speed) This requirment would seem to > rule out using 1 microcontroller for the encoder signals and another for > the rest. > > So, If I was to give an output pulse at say, 1/10th of the desired > frequency, is there a frequency multiplier of some sort that I could use > for an application like this? I'd like the PIC to output a 7.1kHz pulse, > and do a bunch of other neat stuff, and use another IC or circuit to > multiply the 7.1kHz signal by 10. Erik, You may wish to consider something like a 'co-routine'. Knuth discusses them at length in "The Art of Computer Programming" (though I don't recall which volume) and there was an article within the last year in 'Embedded Systems Programming'. But basically, a co-routine is like multitasking with just two tasks. It seems like you could divide the two tasks into 1) Frequency synthesis and 2) Everything else. For the frequency synthesis, I'd suggest phase accumulators. A sixteen-bit phase accumulator would be more then adequate for your application. I don't have time to think through the pic code, but this psuedo code should convey the idea: phase_accumalator = 0; // No phase initially clear_output(); loop1: read_switches(); phase_chunk = phase_given_switch_setting[switch_setting]; update_output(); switch(task_state) { task1: do_stuff1(); break; task2: do_stuff2(); break; task3: do_stuff3(); break; task4: do_stuff4(); break; } task_state = (task_state + 1) & 3; goto loop1; update_output() { phase_accumulator += phase_chunk; if(phase_accumulator rolled over) toggle the output; } The trick though is to break the tasks into equal sizes. In other words, the phase accumulator assumes that the time between phase adjustments is constant. But I think you were faced with a similar problem at the outset. I presume your running a pic with a 20Mhz clock (because (20MHz/4)/71kHz = 70.4 instructions per cycle). It only takes 8 (or 10) instructions to do the phase accumalation and bit-toggling: movf phase_chunk_lo,w addwf phase_accumulator_lo,f movf phase_chunk_hi,w skpnc incfsz phase_chunk_hi,w addwf phase_accumulator_hi,f rlf known_zero,w ;get the rollover sublw 0 andlw BIT_POSITION xorwf portx,f Or if you make the frequency output at the LSB (or MSB) of the I/O port, then this will work in place of the last 4 instructions: rlf known_zero,w ;get the rollover xorwf portx,f ;toggle output on rollover So if you adjusted your timing such that you ran the phase accumulator algorithm 4-times for the 71kHz period, then you would have about 70 - 32 or 38 cycles for looping, task switching, and task execution. Now, since the phase accumulator code is so short, you might as well repeat it whenever it is needed (saving 4 cycles for the call/return over head). The looping and task switching take at worst 10 cycles. That leaves 28 or so cycles for all of your mini-tasks. Challenging, but doable. Scott