# ISR Overlap - Code Optimize Help

Status
Not open for further replies.

#### Suraj143

##### Active Member
I'm doing a LED pattern design.ISR does the multiplexing part.Patterns feeding in Main loop.
My oscillator is 8Mhz, Every 600uS I get an interrupt & update the display.

For below pattern I need to call two subroutines which takes total 710uS which is ovelapping ISR (Because I get inteerupts on every 600uS).So everytime I have to disable interrupts before calling this subroutines (Which I don't like).I need to optimize my subroutines within 600uS.

Note: It does not need two subroutines, any how I need to optimize....

Any Help
Thanks

Code:
                ;Bank2 RAM
cblock    110h
D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,D12,D13,D14,D15,D16                ; 16 10-1Fh
D17,D18,D19,D20,D21,D22,D23,D24,D25,D26,D27,D28,D29,D30,D31,D32        ; 32 20-2Fh
D33,D34,D35,D36,D37,D38,D39,D40,D41,D42,D43,D44,D45,D46,D47,D48        ; 48 30-3Fh
D49,D50,D51,D52,D53,D54,D55,D56,D57,D58,D59,D60,D61,D62,D63,D64        ; 64 40-4Fh
D65,D66,D67,D68,D69,D70,D71,D72,D73,D74,D75,D76,D77,D78,D79,D80        ; 80 50-5Fh
D81,D82,D83,D84,D85,D86,D87,D88,D89,D90,D91,D92,D93,D94,D95,D96        ; 96 60-6Fh
endc

Pat_Loop        bcf            INTCON,GIE
lcall        Full_Rotate_CCW        ;Rotate Pattern CCW
pagesel    $movlw b'11000000' ;Feed new Pattern Data lcall Spread_Up_Fast ;Pattern Shift Up pagesel$
bsf            INTCON,GIE
lcall        Del_80mS
pagesel    \$
goto        Pat_Loop

;This Routine Takes 320uS
movwf        P1
movf        P1,W
movwf        R1
movwf        R2
movwf        R3
movwf        R4
movwf        R5
movwf        R6
bsf            STATUS,IRP
movlw        .48
movwf        Columns
movlw        10h
movwf        FSR
rlf            R6,F
rlf            R5,F
rlf            R4,F
rlf            R3,F
rlf            R2,F
rlf            R1,F
rlf            INDF,F
incf        FSR,F
rlf            INDF,F
incf        FSR,F
decfsz        Columns,F
bcf            STATUS,IRP
return

;This routine Takes 390uS
Full_Rotate_CCW    bsf            STATUS,IRP
movlw          .48
movwf          Temp
movlw          70h
movwf         FSR
bsf            STATUS,RP1
movf        D1,W
bcf            STATUS,RP1
;
Full_R_CCW_Loop1
decf           FSR,F
decf           FSR,F
xorwf          INDF,W
xorwf          INDF,F
xorwf          INDF,W
decfsz         Temp,F
goto           Full_R_CCW_Loop1
;
movlw          .48
movwf          Temp
movlw          71h
movwf         FSR
bsf            STATUS,RP1
movf          D2,W
bcf            STATUS,RP1
;
Full_R_CCW_Loop2
decf           FSR,F
decf           FSR,F
xorwf          INDF,W
xorwf          INDF,F
xorwf          INDF,W
decfsz         Temp,F
goto           Full_R_CCW_Loop2
bcf            STATUS,IRP
return

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Interrupts on the mid range do not overlap... One has to finish before the other starts... Even on the high end pics they can be prioritised..

However! That said... You only need to "Flag" the interrupt has happened and the rotate should be done outside the interrupt.. Again with the display.. Once the interrupt occurs set a flag and update the display outside..

Your problem I should imagine is the rotation is taking place and you want live data on the screen.. I would use the delay between rotations to update the small amount of the screen ( 80mS is a long time ) If you update the display in this time just switch on / off the interrupt in this period..

#### Pommie

##### Well-Known Member
Can you explain what the code is doing? And, what the hardware is.

Mike.

#### Suraj143

##### Active Member
Hi,
I have only one interrupt.I do multiplex part in the interrupt.

Overlaping means while I'm in the main loop ( calling the above pattern) the interrupt occurs.Because the subroutine processing time is more than the interrupt time.

The above code is in the main routine.

I need to optimize the subroutines processing time less than the interrupt time (600uS).

I have shown the processing time for each subroutines.

#### Mike - K8LH

##### Well-Known Member
If you could provide a bit more information we might be able to help more.

It looks like you're driving a 16x48 display (16 rows & 48 columns) and probably lighting a single 16 bit column at a time at 600-us interrupt intervals from a 48 element 16-bit D[0..47] array/buffer (1/48th duty cycle & ~34-Hz refresh rate). If so, then you're probably maintaining a 0-47 'column' counter in your ISR to index the array and load the row drivers during each interrupt. If that's the case then you might consider making the D[0..47] array/buffer a "circular" buffer and using a set of pointer variables to speed up the "scroll left" and/or "scroll right" operations. That is, instead of shifting the entire 48 element array to the left or right in your main program, you'd simply increment or decrement a "display_start" variable (0..47) and stuff new column data, if needed, at the 'head' or 'tail' of the array. You'd still maintain a 'column' variable (0..47) in your ISR but you'd add it to the 'display_start' variable modulo 48 plus the array start address to index the correct element of the D[0..47] array during each interrupt (not as complicated as it sounds).

If you have an opportunity, please tell us a little more about what your doing and I'm sure we can offer more detailed suggestions.

Regards...

Last edited:

#### Nigel Goodwin

##### Super Moderator
Hi,
I have only one interrupt.I do multiplex part in the interrupt.

Overlaping means while I'm in the main loop ( calling the above pattern) the interrupt occurs.Because the subroutine processing time is more than the interrupt time.

The above code is in the main routine.

I need to optimize the subroutines processing time less than the interrupt time (600uS).

I have shown the processing time for each subroutines.
As has already been said, ISR's should be short and fast - and you shouldn't be calling sub-routines from within them.

Do you even need such a fast multiplexing rate?.

#### Suraj143

##### Active Member
If you could provide a bit more information we might be able to help more.

It looks like you're driving a 16x48 display (16 rows & 48 columns) and probably lighting a single 16 bit column at a time at 600-us interrupt intervals from a 48 element 16-bit D[0..47] array/buffer (1/48th duty cycle & ~34-Hz refresh rate). If so, then you're probably maintaining a 0-47 'column' counter in your ISR to index the array and load the row drivers during each interrupt. If that's the case then you might consider making the D[0..47] array/buffer a "circular" buffer and using a set of pointer variables to speed up the "scroll left" and/or "scroll right" operations. That is, instead of shifting the entire 48 element array to the left or right in your main program, you'd simply increment or decrement a "display_start" variable (0..47) and stuff new column data, if needed, at the 'head' or 'tail' of the array. You'd still maintain a 'column' variable (0..47) in your ISR but you'd add it to the 'display_start' variable modulo 48 plus the array start address to index the correct element of the D[0..47] array during each interrupt (not as complicated as it sounds).

If you have an opportunity, please tell us a little more about what your doing and I'm sure we can offer more detailed suggestions.

Regards...
Hi Thanks for the detail info.You are correct.The only change I do is my Display RAM assignment is vertical than horizontal.See the attached RAM assignment of my matrix.

I get TMR2 interrupt on every 600uS, I feed the particular 48 bits row data on each interrupt.So I get 1/16th duty cycle design with a 104Hz refresh rate.

In my entire design I have two subroutines.
1) "Shift_up" - This will shift up the entire display RAM from one bit up by feeding the "new data" to the bottom Row1.
2)"Rotate CCW" or "Roate CW" - Roatate entire display RAM to 1 bit left or right (Circular rotate).

*I need speed subroutines which does not exceed the interrupt timings.
*Does it speed up the process by placing DIsplay RAM horizontally than vertical?

I use PIC16F886 with 8MHz Assembly code.

#### Mike - K8LH

##### Well-Known Member
*I need speed subroutines which does not exceed the interrupt timings.
Not necessarily. If you needed to run those subroutines between each interrupt, then yes, you'd be in trouble. However, it looks like you may be running them once every 80-ms and if that's correct, the routines in their present form could be interrupted once or twice while updating the buffer but I suspect you might not notice the partially updated display buffer because the entire display is refreshed every 9.8 milliseconds.

As I mentioned before, you might consider implementing a "circular" buffer to reduce the overhead for scroll left and scroll right operations. However, unless you somehow synchronize your update routines to the ISR, your routines could still be interrupted.
*Does it speed up the process by placing DIsplay RAM horizontally than vertical?
That depends entirely on how you drive the display and how you want to manipulate data in the buffer. Both vertical and horizontal formats will have advantages and disadvantages. For example, your vertical format makes it much easier to place text or graphic images into the buffer starting at any X position (0..47) and to scroll the buffer left or right by implementing a "circular" buffer. However, since you're refreshing rows of 48 bits, your ISR needs to extract a single bit from each of the 48 column elements to drive the 48 columns and this might take a lot of work and might be considered a disadvantage.

I'm curious about your ISR "row" driver code and how much time it uses out of each 600-us interrupt interval?

Regards. Mike

Last edited:

#### Suraj143

##### Active Member
Hi K8LH

Isn't that "Full_Rotate_CCW" subroutine (in my 1st post) is a circular buffer?That code is also I got from you

I'm curious about your ISR "row" driver code and how much time it uses out of each 600-us interrupt interval?
It takes 240uS time to display part in interrupt routine out of 600uS.

Last edited:
Status
Not open for further replies.