Erik, Roland's approach sounds probably easier for you to do then. (Beware, girlfriend's interrupting me a lot today so I'd rather scream & run, I think. I may look a little more distracted than average, here...) To build a real time operating system like this, the usual approach is to do this (Time-Slicing Real Time OS idea; Pseudo-Code warning ): Setup_Task1(); Setup_Task2(); Setup_Task3(); Main_Loop: Do_Part_of_Task1(); Do_Part_of_Task2(); Do_Part_of_Task3(); Do_Short_Delay(); goto Main_Loop; The main idea here is to split each task into little tiny "time slice" pieces - i.e. the first time you call Do_Part_of_Task1(), for example, it just does one small part of it's job - the next time through it does the next part of it's job, and so on. Something like: Proc Do_Part_of_Task1() { Static Int WhichSlice1=0; /* Initialize only at startup, not with each call to this procedure */ Const n = 3; /* number of total time slices for this task, arbitrarily 3 here. */ WhichSlice1 = (WhichSlice1 + 1) mod n; Case WhichSlice of { 1: Do_Task1_TinyPart1(); break; 2: Do_Task1_TinyPart2(); break; 3: Do_Task1_TinyPart3(); } }; Task1TinyPart1 could do the first half of a math calculation, part 2 could do the next half, part 3 could do a comparison to check & see if it's time to flip an output bit - for something somewhat specific here. Do feel free to use more than 3 slices, too! (In avionics, for example, you commonly test ALL CPU instructions, regularly, so TinyPart1 might test a register increment instruction, TinyPart2 a register assign, TinyPart3 a register decrement, TinyPart4 a Jump instruction, and so on and on, probably 100 slices or more Task 1 could be "check if it's time to flip the 43uSec pulser". Task 2 could be some other pulser. Task 3 could be "see if the paper roll's turned another turn", and could gradually increase or decrease the Paper Roll Diameter variable, to suit the radius of the paper roll. The problem can be figuring out how to do things just right, the first time You can also do this in two ways, "Isochronously" or "Synchronously"; The first means you have routines that take different numbers clock cycles to run through, so you need a synchronizing delay loop in Do_ShortDelay() to sync everything up to the (Timer) heartbeat; The second would be needed if you're way low on CPU resources, you make sure that whatever happens your program takes the exact same number of cpu cycles to do it's job, then you don't have any delay loop; Harder to do, but if you need the cycles to all do processing not overhead, you need it. There is no "Wrong" way to do something like this, so long as your code works, it's "right". Do it the way that makes sense to you! Mark erik wrote: > > Roland, > I've been giving this alot of thought but don't think I can do things > entirely with an interrupt on > TMR0 rollover. I would like to simulate a printing press running at > 3000 ft/min which would require a pulse > once every 43usec with a 2500 pulse encoder. There are other signals > whose frequency is directly > proportional to the press speed. I could have TMR0 overflow at 43usec > and in the ISR I would turn on the > "encoder output". Three switches would be used to set the "press speed" > and would directly correlate > to the prescaler bits. This way, if all timing was based on the TMR0, > the whole "machine" would slow > down. > > My problem is: that on some machines (and therefore my simulator) there > are 2500 and 1200 pulse per rev encoders and > either a 2:1 or 4:1 shaft to encoder ratio. To facilitate this > functionality I think I would need a routine > independent of the interrupt that determines if it is time to turn on > the "encoder output" based on the > "machine configuration" ie. configuration switches. > > My original intent was to have TMR0 interrupt every 1 msec as a means of > incrementing a "global timer register". The various routines in the > program would then check with the "global timer" to see if it was > time for an output. The "global timer" could easily be slowed down and > all the machine functions would > slow as well. Unfortunately I've found that with a press speed of > 3000ft/min with a 4:1 1200 pulse encoder > I'll need to output an encoder pulse once every 23 usec. At 20MHz OSC I > could load the TMR0 with 141 so that > 115 cycles would generate an interrupt at 23 usec. Now keeping track of > the machine speed has become more > difficult. There is a once per revolution pulse from paper roll that > obviously is dependent on the machine > speed but also has to increase in frequency as the paper roll gets > smaller. That part is easy enough if I can > establish a "metronome" or "heart beat" of the machine. I'm just not > sure how I'd do that if my "heart beat" > changes with different encoder configurations. > > 23usec pulse at [(1200 pulse/rev)*4] and > 43usec pulse at [(2500 pulse/rev)*1] > both = 3000ft/min > depending on which machine configuration I'd like to simulate. > i.e. while the encoder output pulse changes with the configuration > switches, the other signals must not. > All this said, am I correct in thinking that I cannot manipulate the > "global timer"/"heartbeat". Instead I must establish a "heartbeat" and > change the encoder frequency for different configurations. > > Maybe I'm just not thinking sneaky enough. I'm still very new at this. > > And Mark, > Thanks for the URLs. I'm pretty sure I've no idea what you were talking > about. :) I've never worked with... > well, I've never worked with lots of stuff. I'll take a look at them and > see if I can figure it out. Thanks. > > Erik > > Roland Andrag wrote: > > > > Eric, I don't know which pic you are using, but you should be able to run > > Timer0 (I think) to generate an interrupt whenever your output has to change > > from high to low. This means that your frequency generating code will run in > > the background, driven by the interrupt, leaving you clear to run your other > > code in the foreground. > > > > Otherwise you are probably looking at implementing a phase locked loop to be > > able to multiply the frequency, which gets a little tricky. > > > > Your interrupt routine would basically do the following: > > 1. Save registers etc. > > 2. Change output state of pin to generate frequency. > > 3. Reset interrupt flag(s) > > 4. Reset timer0 so that it will generate the next interrupt when the signal > > needs to change again > > 5. Restore registers etc > > 6. Return > > > > Steps 2 to 4 can be shuffled to suit you. Perhaps put step 4 where step 2 > > is - makes timing easier to calculate. > > > > Using the interrupt has the advantage that you don't have to 'tune' your > > code to achieve the correct delay - only the interrupt routine. You should > > be able to get within 1 clock cycle of the required delay. The only > > limitation is that the interrupt routine should be finished by the time the > > next interrupt occurs. > > > > Hope that helps (scream if you need more info) > > > > Cheers > > Roland > > -----Original Message----- > > From: erik > > To: PICLIST@MITVMA.MIT.EDU > > Date: 09 May 1999 19:14 > > Subject: Frequency Multiplier > > > > >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. > > > > > >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 > > >