Problem with Timer Interrupt

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
animo3d
Posts: 24
Joined: Sun Sep 18, 2011 6:02 am
Location: Monterrey Mexico

Problem with Timer Interrupt

Post by animo3d » Sun Nov 16, 2014 10:48 pm

Hello, I'm trying to drive a RGB led matrix using a pic18F25K22, for that matter I'm using the timer0 to interrupt every 1 ms, for multiplexing the matrix form a Buffer array with the display data, this is working well, the issue is that I have a Sub that modifies the buffer to set pixels on or off, and at random times it does not modify correctly the buffer, I assume is when it get interrupted by the Refresh Event, if I disable the interrupt at the SetPixel Sub it works correctly but due to the uneven multiplexing timming I see an Horrible flicker on the led matrix.

I'm lost on how to procede from here.. any help will be appreciated...

Code: Select all


Device = 18F25k22
Clock = 32

Config
    FOSC    = INTIO67,	    // HS Oscillator
    FCMEN	= OFF,		// Failsafe Clock Monitor Disabled
    IESO	= OFF,		// Int/Ext Oscillator Switch Over Disabled
    PWRTEN	= OFF,		// Power Up Timer Disabled
    BOREN	= OFF,		// Brownout Reset Disabled
    BORV    = 250,
    WDTEN   = OFF,		// Watchdog Timer Disabled
    MCLRE	= EXTMCLR,		// MCLR Enabled
    WDTPS   = 256,          // 15000 x 4mS  = 60 seconds
    LVP     = OFF,          // Low_Voltage Programming
    PBADEN  = OFF,           // PORTB Digital  
    CCP2MX  = PORTC1,
    CP0     = OFF,
    CP1     = OFF,
    CP2     = OFF,
    CP3     = OFF,
    CPB     = OFF,
    CPD     = OFF


Include "Timer0.bas"


' I/O setting
Dim PA As PORTA.0
Dim PB As PORTA.1
Dim PC As PORTA.2
Dim PD As PORTA.3

Dim R1 As PORTB.0
Dim G1 As PORTB.1
Dim B1 As PORTB.2
Dim R2 As PORTB.3
Dim G2 As PORTB.4
Dim B2 As PORTB.5

Dim CLK As PORTC.0
Dim LAT As PORTC.1
Dim OE As PORTC.2

Dim Led1 As PORTC.4
Dim Led2 As PORTC.5

' Ram Allocation
Dim BUF(513) As Byte
Dim A,B As Byte
Dim C As Byte
Dim Addr As Byte


' The RGB Matrix has 2 blocks of 16 lines each
' the First block (lines 0 to 15) uses Dalta Lines R1, G1 B1
' the Second block (lines 16 to 31) uses Dalta Lines R2, G2 B2
' PortA bits 0..3 selects the line to shift

Event Refresh()
  Dim x As Byte
  OE=1
  PORTA=Addr
  For x=0 To 31
   R1=BUF(Addr*32+x).0
   G1=BUF(Addr*32+x).1
   B1=BUF(Addr*32+x).2
   R2=BUF(Addr*32+x).4
   G2=BUF(Addr*32+x).5
   B2=BUF(Addr*32+x).6
   CLK=1
   CLK=0
  Next
  LAT=1
  LAT=0
  Inc(Addr)
  If Addr>15 Then 
   Addr=0
  EndIf 
  OE=0
End Event
 
 
Interrupt ISR()
     If Timer0.InterruptFlag =1 Then
        Timer0.SInterrupt()      
     EndIf
End Interrupt


' BUF(0..512) Memory Organization:
' Each byte corresponds to 2 pixels
' nibble0 for first block, nibble1 for second block

Sub SetPixel(x,y,d As Byte)
 Dim fdat As Byte
' Timer0.Disabled()
 If y<16 Then
  fdat=d And $0f
  BUF(y*32+x)=BUF(y*32+x) And $F0
  BUF(y*32+x)=BUF(y*32+x) Or fdat
 Else
  fdat=d<<4
  BUF((y-16)*32+x)=BUF((y-16)*32+x) And $0F
  BUF((y-16)*32+x)=BUF((y-16)*32+x) Or fdat
 EndIf
' Timer0.Enabled()
End Sub


Sub InitHardware()

  OSCCON=$60
  OSCTUNE.6=1

  CM1CON0=0
  CM2CON0=0

  ADCON0=0
  ADCON1= $0F
  ADCON2=0
  ANSELA=0
  ANSELB=0
  ANSELC=0

  Output(Led1)
  Output(Led2)
 
  Output(CLK)
  Output(LAT)
  Output(OE)
  
  Output(R1)
  Output(G1)
  Output(B1)
  
  Output(R2)
  Output(G2)
  Output(B2)

  Output(PA)
  Output(PB)
  Output(PC)
  Output(PD)

  PA=0
  PB=0
  PC=0
  PD=0
  R1=0
  G1=0
  B1=0
  R2=0
  G2=0
  B2=0
  CLK=0
  LAT=0
  OE=0
    
 Timer0.Initialize(Refresh)
 Timer0.SetPrescaler(Timer0.PS32) 'Timer0.PS2 99=prescaler disabled
 Timer0.EightBit = 1
 Timer0.Preload= 10
 Timer0.EnableInterrupt()
 Enable(ISR)

End Sub  

''''''''''  
' MAIN
''''''''''

InitHardware()
Addr=0

Clear(BUF)

Timer0.Enabled()
C=1
Repeat
 For A=0 To 31
  For B=0 To 31
   SetPixel(A,B,C)
  Next
   DelayMS(10)
 Next
 Inc(C)
 If C>7 Then
  C=0
 EndIf 
 
Until false 

User avatar
Coccoliso
Posts: 152
Joined: Mon Feb 17, 2014 10:34 am

Re: Problem with Timer Interrupt

Post by Coccoliso » Sun Nov 16, 2014 11:21 pm

Forgot "Timer0.bas" module but I suggest the module "ISRTimer.bas", if you've never used take a look to the help of SF but the use is very simple:

Code: Select all

Const Timer1 = 0    

Event OnTimer()
       ...
End Event

' ------------------ MAIN 
Timer.Initialize(1)

Timer.Items(Timer1).Interval = 10                // 10ms
Timer.Items(Timer1).OnTimer = @OnTimer   // timer event handler
Timer.Items(Timer1).Enabled = true

Timer.Start

...

animo3d
Posts: 24
Joined: Sun Sep 18, 2011 6:02 am
Location: Monterrey Mexico

Re: Problem with Timer Interrupt

Post by animo3d » Mon Nov 17, 2014 1:18 am

Thanks for the response, but I got the exact same result with ISRtimer I tried both, I sticked with timer0 because I can adjust the timming in smaller increments looking for better results in the multiplexing flicker,

the Timer0.bas library is here: http://www.sfcompiler.co.uk/wiki/pmwiki ... ser.Timer0

Thanks

User avatar
RangerBob
Posts: 152
Joined: Thu May 31, 2007 8:52 am
Location: Beds, UK

Re: Problem with Timer Interrupt

Post by RangerBob » Mon Nov 17, 2014 10:30 am

If this is all you are doing on the device, could you double buffer your display at the cost of another 513 or so bytes? The 18F25k22 has plenty of RAM.

Then you modify one buffer whilst the display updates from the other, then switch them over at the end, and so on.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Problem with Timer Interrupt

Post by Jerry Messina » Mon Nov 17, 2014 12:36 pm

There are a few things you could do that might help...

First, in Timer0.bas change Enable/DisableInterrupt() to inline

Code: Select all

Public inline Sub EnableInterrupt()
       FInterrupt=1
End Sub

Public inline Sub DisableInterrupt()
       FInterrupt=0
End Sub
Next, there are a lot of repetative expressions and array accesses in the code. If you compute these first, the code will be much faster
For example, the refresh event code could be changed to

Code: Select all

Event Refresh()
  Dim x As Byte
  dim b as byte
  dim ix as word

  OE=1
  PORTA=Addr
  ix = addr * 32
  For x=0 To 31
    b = buf(ix)
    ix = ix + 1
    R1=b.0
    G1=b.1
    B1=b.2
    R2=b.4
    G2=b.5
    B2=b.6
    CLK=1
    CLK=0
  Next
  LAT=1
  LAT=0
  Inc(Addr)
  If Addr>15 Then
   Addr=0
  EndIf
  OE=0
End Event
That will make it over 3x as fast (718us down to 176us). You can do the same thing to SetPixel.

Incorporating all of those together:

Code: Select all

Event Refresh()
  Dim x As Byte
  dim b as byte
  dim ix as word

  OE=1
  PORTA=Addr
  ix = addr * 32
  For x=0 To 31
    b = buf(ix)
    ix = ix + 1
    R1=b.0
    G1=b.1
    B1=b.2
    R2=b.4
    G2=b.5
    B2=b.6
    CLK=1
    CLK=0
  Next
  LAT=1
  LAT=0
  Inc(Addr)
  If Addr>15 Then
   Addr=0
  EndIf
  OE=0
End Event

Sub SetPixel(x,y,d As Byte)
  Dim fdat As Byte
  dim ix as word
  dim b as byte
  dim mask as byte

  If y<16 Then
    fdat = d And $0f
    mask = $F0
  Else
    fdat = d<<4
    y = y - 16
    mask = $0F
  EndIf
  ix = y*32 + x

  Timer0.DisableInterrupt()
  b = BUF(ix)
  b = b And mask
  BUF(ix) = b Or fdat
  Timer0.EnableInterrupt()
End Sub
I also changed Timer0.Disabled()/Enabled() to Disable/EnableInterrupt() since Enabled() was reloading the timer value.

With those changes the code is half the size of the original, but it's also MUCH faster (if I didn't screw anything up, that is).

See if that helps the flicker problem.
Last edited by Jerry Messina on Mon Nov 17, 2014 1:51 pm, edited 1 time in total.
Reason: remove useless DisplayBusy flag

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Problem with Timer Interrupt

Post by Jerry Messina » Mon Nov 17, 2014 1:54 pm

Strike what I said in the previous post about adding a DisplayBusy flag. I don't know what I was thinking when I wrote that, but I had the logic for it completely bass-ackwards. I editing the post to remove it.

I guess I need to wait for that first cup of coffee to kick in before I post. Luckily, the other statements still make some sense.

animo3d
Posts: 24
Joined: Sun Sep 18, 2011 6:02 am
Location: Monterrey Mexico

Re: Problem with Timer Interrupt

Post by animo3d » Mon Nov 17, 2014 8:54 pm

Thanks Jerry, I wil try it later today and post the results

Post Reply