• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ISR Overlap - Code Optimize Help

Suraj143

Active Member
Thread starter #1
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
Spread_Up_Fast    clrf        W_Height
                movwf        P1
Spread_Up_Fast_A    
                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
Spread_Fast_Loop    
                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
                goto        Spread_Fast_Loop
                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
Most Helpful Member
#2
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..
 

Suraj143

Active Member
Thread starter #4
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
#5
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
Most Helpful Member
#6
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?.
 
Thread starter #7
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.
 
#8
*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:
Thread starter #9
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:

Latest threads

EE World Online Articles

Loading

 
Top