Hi Mike,
sounds interesting - explain away
Andrew
Hi Andrew,
The disadvantage of this particular method is that you need a PIC with lots of RAM, something like an 18F2620, for the 1024 byte toggle array. If this is a one-off project then perhaps that may not be a big deal.
The PrepArray() routine builds the following (abbreviated) toggle[] array from the pulse[] array values and the Output() routine uses those values to update LATB as shown below;
Code:interval ^ LATB 0000-usecs toggle[ 0] = 0b00001111 0b00001111 RB3..RB0 toggled on 0001-usecs toggle[ 1] = 0b00000000 0b00001111 .... 0043-usecs toggle[ 43] = 0b00000000 0b00001111 0044-usecs toggle[ 44] = 0b00000010 0b00001101 RB1 toggled off 0045-usecs toggle[ 45] = 0b00000100 0b00001001 RB2 toggled off 0046-usecs toggle[ 46] = 0b00000000 0b00001001 .... 0119-usecs toggle[ 119] = 0b00000000 0b00001001 0120-usecs toggle[ 120] = 0b00000001 0b00001000 RB0 toggled off 0121-usecs toggle[ 121] = 0b00000000 0b00001000 .... 1000-usecs toggle[1000] = 0b00000000 0b00001000 1001-usecs toggle[1001] = 0b00001000 0b00000000 RB3 toggled off ....
The advantage of using a "toggle" data array and XOR'ing the values with LATB over using an "output" data array and simply writing the values to LATB is that the "toggle" array only requires inserting eight "toggle" bits into the array. An "output" data array would require inserting many many "output" bits into the array.
The Do-While loop in the Output() routine compiles to the following 5-cycle instruction sequence (by the BoostC compiler) for perfect 1-usec intervals (with a 20-MHz clock);
In your program you would edit the pulse array values for the outputs and then call the PrepArray() routine to build the toggle array. Then I suspect you would wait for some "trigger" event before calling the Output() routine.Code:loop: movf _postinc0,W ; xorwf _latb,F ; btfss _fsr0h,3 ; bra loop ;
Any of this make sense Sir? I'm rather pressed for time and that tends to make my rushed explanations rather useless to most people. Sorry...
Regards, Mike
Last edited by Mike, K8LH; - 17th October 2009 at 01:04.
More or less makes sense.
As I'm only juggling three outputs, I think I'll just sort the outputs into increasing time, calculate the incremental time between trailing edges, put them all on together and then pull them back down sequentially with PAUSEUS delays.
Thanks for taking the time to answer
Andrew
Last edited by AndrewC; - 17th October 2009 at 08:23. Reason: spelling :(
This last post made me to put on my thinking capI do this stuff within an ISR usually, but your case doesn't need it.
How about something like this. BEWARE : untested code
Code:Out1 var PORTB.0 Out2 var PORTB.1 Out3 var PORTB.2 AllOn con %00000111 ' all three outputs on Delay1 var word ' turn off delay for output1 Delay2 var word ' and 2 Delay3 var word ' surely this has to be for 3 RunDelay var word ' this is the running timer ' set all outputs on together TRISB = 0 Delay1 = 1000 ' in units of PAUSE time Delay2 = 2000 Delay3 = 3000 Loop: PORTB = AllOn for RunDelay = 0 to 65535 ' or whatever is the maximum you want ' this would be your cycle / repeat time if RunDelay > Delay1 then Out1 = 0 endif if RunDelay > Delay2 then Out2 = 0 endif if RunDelay > Delay3 then Out3 = 0 endif pauseus 10 ' this is the resolution of your delays next goto Loop
Hi Jerson,
I agree that ISR code isn't necessary or even desirable in this case because of the high resolution required and the ISR context save/restore 'overhead'.
Andrew mentioned in his first post that the pulse width range could be several microseconds up to about one millisecond.
I believe the pulse width resolution for your example would be the loop code 'overhead' plus the 16-bit compare code 'overhead' plus the delay. The 16-bit compare code 'overhead' may well be the biggest limiting factor affecting resolution and the delay may not be necessary. Have you checked to see how many cycles are used for 1 loop cycle in your example Sir?
Regards, Mike
Last edited by Mike, K8LH; - 17th October 2009 at 16:13.
Hey Andrew,
Once I figure out how to force an address for the toggle array in Swordfish BASIC I suspect my method might look something like this BASIC example, which I hope makes more sense than my previous pseudo C example.
Kind regards, Mike
Code:Dim Tgl(1024) As Byte ' ??? force to $400..$7FF ??? Dim Pulse(3) As Word Dim LastElement As FSR0H.booleans(3) ' Pulse(0) = 3 ' RB0 pulse, 0..1023 usecs Pulse(1) = 11 ' RB1 pulse, 0..1023 usecs Pulse(2) = 12 ' RB2 pulse, 0..1023 usecs ' ' clear the 1024 element toggle array ' FSR0 = AddressOf(Tgl) ' indirect for Tgl(0) Repeat ' clear toggle array POSTINC0 = 0 ' clear 0x400..0x7FF Until LastElement ' ' ' insert 3 output toggle bits into our 1024 interval toggle array ' Tgl(Pulse(0)) = Tgl(Pulse(0)) Or 1 ' insert RB0 toggle bit Tgl(Pulse(1)) = Tgl(Pulse(1)) Or 2 ' insert RB1 toggle bit Tgl(Pulse(2)) = Tgl(Pulse(2)) Or 4 ' insert RB2 toggle bit Tgl(0) = Tgl(0) Xor $FF ' prep Tgl(0) element ' ' implement a button press or some other trigger before falling into ' the output routine (1024 1-usec intervals with 20-MHz clock) ' FSR0 = AddressOf(Tgl) ' Tgl(0..1023), 0x400..0x7FF Repeat ' toggle outputs from toggle array LATB = LATB Xor POSTINC0 ' at 1-usec (5 cycle) intervals Until LastElement ' until end-of-array (0x800)
Last edited by Mike, K8LH; - 18th October 2009 at 16:45.
Bookmarks