PDA

View Full Version : Elapsed timer not working as expected at 64MHz



Demon
- 22nd December 2014, 15:09
Has anyone else had problems using DT's Elapsed Timer at 64MHz?


When I run a 18F44K22 at 64MHz, 99 TICKS = .247 second.

7538


When I run at 16MHz, 99 TICKS = .988 second.

7539


It's as if the timer runs at a default 16MHz when the PIC is at 64MHz (exactly 1/4 speed).

Demon
- 22nd December 2014, 15:20
When I look at Elapsed Timer include, Darryl has adjusted it to run at any oscillator frequency.


'************************************************* **************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 *
'* Version : 1.2 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'************************************************* **************************
DISABLE DEBUG

; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)

Ticks VAR BYTE ; Counts timer Overflows
T1Post VAR BYTE ; Timer1 postscaler
Seconds VAR BYTE
Minutes VAR BYTE
Hours VAR BYTE
Days VAR WORD

SecondsChanged VAR BIT ; idicates that the value has changed
MinutesChanged VAR BIT
HoursChanged VAR BIT
DaysChanged VAR BIT

GOSUB ResetTime ; initialize the Elapsed Timer

Goto OverElapsed ; skip over the routines

' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value


; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm

; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm

; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM

' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
Ticks = Ticks + 1
IF Ticks = 100 THEN
Ticks = 0
T1Post = T1Post + 1
IF T1Post = T1PS THEN
T1Post = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt

'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------

StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN

; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN

; --------------------------------------------------------------------------
BitSave VAR BIT

ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
T1Post = 0 ; clear the postscaler
Ticks = 0
Seconds = 0
Minutes = 0
Hours = 0
Days = 0
SecondsChanged = 1 ; indicate everything has changed
MinutesChanged = 1 ; so that 00:00:00 is processed
HoursChanged = 1
DaysChanged = 1
RETURN


OverElapsed:
ENABLE DEBUG

The only thing that caught my eye was the TimerConst calculation. At 64MHz it is 160,000 on the first loop, well beyond the range of a WORD variable.

I don't have LONGs enabled right now. I can't seem to find the definition for TimerConst to see if it's a WORD or LONG.

It should be a WORD 'cause he ends up moving the high and low bytes.

HenrikOlsson
- 22nd December 2014, 17:33
Hi Robert,
The first piece of code is executed by the assembler at the time the code is built. It doesn't execute when the PIC actually runs so there's no WORD size limit at play as far as I know.

The second piece you've marked in red is of course run time code but by the TimerConst should be less than 65400 so no problem.

With that said something is apparently not working as expected. Darrels code, relies on you having DEFINE OSC xx correctly. It's easy enough to have a 16MHz clock with the corresponding DEFINE and then enable the PLL to get 64MHz but forget to change to DEFINE OSC 64.

/Henrik.

Demon
- 22nd December 2014, 20:56
I bet this is my Saleae probe biting me in the nose again; not being able to run it fast enough.

The interrupt is working faster, I'm probably missing signals.

7540

EDIT: And I notice I didn't align the marker the same way on Probe 1 - Port = 1 / 0, but it's the same interval as described in the WIDTH; 0.250uS, I just rechecked.



asm
; __CONFIG _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_OFF_1H & _PRICLKEN_OFF_1H & _FCMEN_ON_1H & _IESO_OFF_1H
__CONFIG _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_ON_1H & _PRICLKEN_OFF_1H & _FCMEN_ON_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRTEN_ON_2L & _BOREN_SBORDIS_2L & _BORV_285_2L
__CONFIG _CONFIG2H, _WDTEN_OFF_2H
__CONFIG _CONFIG3H, _CCP2MX_PORTC1_3H & _PBADEN_OFF_3H & _CCP3MX_PORTE0_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_EXTMCLR_3H
__CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
endasm

;DEFINE OSC 16
;OSCTUNE = %10000000

DEFINE OSC 64
OSCTUNE = %11000000

OSCCON = %01110000
OSCCON2 = %00000100
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
INCLUDE "ReEnterPBP-18LP.bas"
INCLUDE "Elapsed_INT-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
; INT_Handler RX1_INT, _RX1Interrupt, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_LIST_L macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ClockCount, PBP, yes
endm
INT_CREATE_L ; Creates the Low Priority interrupt processor
ENDASM
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
ADCON0 = %00000000
PMD0 = %10111110
PMD1 = %11011111
PMD2 = %00001111
DEFINE USE_LOWPRIORITY 1
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
pause 100
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
MainProgram:

PortD.2 = 1

if T1CON.0 = 0 then
GOSUB StartTimer ' Start the Elapsed Timer
PortD.3 = 1
endif

PortD.2 = 0

if ticks = 25 then
PortD.3 = 0
GOSUB StopTimer ' Stop the Elapsed Timer
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
endif

goto MainProgram
end


Switch bouncing becomes much more pronounced at 64MHz. I think I'm going to change approach and go the long way and use just a 0.1uF ceramic cap on each pin (I remember that helped somewhat on previous tests).

Master PIC @ 64MHz
LED Slave PIC @ 64MHz
Keypad Slave PIC at 16MHz

I start DT Timer on a keypress and ignore inputs during that interval. I just have to make tests to see how fast I can press the same button and tweak the delay.

I wanted to handle both the LEDs and Keypad on the same PIC, but it'll be a lot easier and reliable to just split them up.

Demon
- 22nd December 2014, 22:02
So I minimized the code:


asm
__CONFIG _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_ON_1H & _PRICLKEN_OFF_1H & _FCMEN_ON_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRTEN_ON_2L & _BOREN_SBORDIS_2L & _BORV_285_2L
__CONFIG _CONFIG2H, _WDTEN_OFF_2H
__CONFIG _CONFIG3H, _CCP2MX_PORTC1_3H & _PBADEN_OFF_3H & _CCP3MX_PORTE0_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_EXTMCLR_3H
__CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
endasm

DEFINE OSC 16
OSCCON = %01010000
' R/W 111 = HFINTOSC – (16 MHz)
' 110 = HFINTOSC/2 – (8 MHz)
' 101 = HFINTOSC/4 – (4 MHz)

OSCTUNE = %11000000
OSCCON2 = %00000100
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
INCLUDE "Elapsed_INT-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ClockCount, PBP, yes
endm
INT_CREATE
ENDASM
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
ADCON0 = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
pause 100
@ INT_ENABLE TMR1_INT
GOSUB ResetTime
MainProgram:

if T1CON.0 = 0 then
PortD.3 = 1
GOSUB StartTimer
endif

if ticks = 5 then
PortD.3 = 0
GOSUB StopTimer ' Stop the Elapsed Timer
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
endif

goto MainProgram
end

5 TICK Timer

OSC 16MHz (4MHz+PLL) 50ms
OSC 32MHz (8MHz+PLL) 25ms
OSC 64MHz (16MHz+PLL) 12.5ms

I can't help but feel I'm doing something wrong, it's just too proportional a variance. If the Saleae probe would miss pulses, there wouldn't be a regular pattern.

richard
- 22nd December 2014, 22:55
debug T1PS and TimerConst to see what's going on would be a good start

Demon
- 22nd December 2014, 23:23
Roger, oveur.

longpole001
- 22nd December 2014, 23:44
tips value will be 4 at 64mhz , i played a lot with this elasped timer code , for up down timer

longpole001
- 23rd December 2014, 00:04
for 64mhz
each tick should be 2.5ms , to confirm the internal osc trim i enable a i/o pin to check its pulse per tick rate , it not the best way but it showed me that the most the time the internal osc needed some adj to ensure that it was as close as possable to 2.5ms

here is a snip of modifed code for the timer, i left the asm as it stands, but cos i wanted the 100th sec reading and the same structure of code , i changed / removed the t1post varable and used the MOD





EL_Ticks = EL_Ticks + 1 ; each tick is 2.5ms
' IF LATG.0 = 0 THEN ' debug
' LATG.0 = 1
' ELSE
' LATG.0 = 0
' ENDIF
if EL_ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
' IF LATG.0 = 0 THEN ' debug
' LATG.0 = 1
' ELSE
' LATG.0 = 0
' ENDIF
EL_100th = EL_100th + 1
EL_100thChanged = 1
IF EL_100TH = 100 THEN
EL_100TH = 0
EL_Seconds = EL_Seconds + 1
EL_SecondsChanged = 1
IF EL_Seconds = 60 THEN
EL_Seconds = 0
EL_Minutes = EL_Minutes + 1
EL_MinutesChanged = 1
eNDIF
IF EL_Minutes = 60 THEN
EL_Minutes = 0
EL_Hours = EL_Hours + 1
EL_HoursChanged = 1
ENDIF
IF EL_Hours = 24 THEN
EL_Hours = 0
EL_Days = EL_Days + 1
EL_DaysChanged = 1
ENDIF
eNDIF
endif

longpole001
- 23rd December 2014, 00:14
each 100th is 10ms on the i/o debug section btw

longpole001
- 23rd December 2014, 00:16
OSCTUNE = %01000111 ' Bit 7 - INTSRC - internal LF Source Select 1 = 31.25 from 16Mhz Internal /512 HF-INTOSC ) 0 = Internal 31khz OSC
' Bit 6 - PLLEN - 1 PLL enabled , 0 = PLL disabled
' Bits 5-0 Frequancy callibaration 00000 = centre Frq - FREQ ADJ = 5-7 ( the higher the number the slower the osc timing )

Demon
- 23rd December 2014, 02:08
debug T1PS and TimerConst to see what's going on would be a good start

I started by making my version of the Elapsed include and adding 2 variables at the end of the timer calc:

...
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
; ---------------------------- DEBUG SCALER --------------------------------
DebugT1PS = T1PS
DebugTC = TimerConst
; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxx
...

Before Main of my program I added:

DebugT1PS CON EXT
DebugTC CON EXT

Right now I'm wiring up a LCD to display the 2 variables.

Am I on the right track to look at them?

I've never tried to display something from inside Darryl's includes before. My plan was to copy them into 2 words and then displaying the lower and upper bytes on the LCD.

richard
- 23rd December 2014, 02:40
Am I on the right track to look at them?
probably not if yours fails try this


DISABLE DEBUG

; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)

Ticks VAR BYTE ; Counts timer Overflows
T1Post VAR BYTE ; Timer1 postscaler
Seconds VAR BYTE
Minutes VAR BYTE
Hours VAR BYTE
Days VAR WORD
DebugT1PS var byte
DebugTCL var byte
DebugTCh var byte

SecondsChanged VAR BIT ; idicates that the value has changed
MinutesChanged VAR BIT
HoursChanged VAR BIT
DaysChanged VAR BIT

GOSUB ResetTime ; initialize the Elapsed Timer

Goto OverElapsed ; skip over the routines

' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
_DebugT1PS =T1PS
_DebugTCH=TimerConst /256
_DebugTCL = TimerConst - _DebugTCH*256

; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro

Demon
- 23rd December 2014, 03:09
Actually, it worked. :D

I deleted my debug include 'cause I can work without it.


...
;T1PS CON EXT ' Already defined in include
TimerConst CON EXT

varT1PS var word
varTC var word
varT1PS = T1PS
varTC = TimerConst

Lcdout $fe, 1, "Timer 1"
Lcdout $fe, $94, "PS:", BIN8 varT1PS.byte1, " ", BIN8 varT1PS.byte0
Lcdout $fe, $D4, "TC:", BIN8 varTC.byte1, " ", BIN8 varTC.byte0

MainProgram:

And I get:
PS:00000000 00000001
TC:01100011 11001000 <--- Dec=25544

EDIT: Woooops, still using OSC 16, BRB.

Demon
- 23rd December 2014, 03:15
OSC 64 (16 + PLL)

PS:00000000 00000100 <--- Dec=4
TC:01100011 11001000 <--- Dec=25544

I had same results manually this afternoon.

Robert

richard
- 23rd December 2014, 03:25
ok next whats in T1CON ?

Demon
- 23rd December 2014, 03:28
Looking at the datasheet for 18F44K22, timer 1 has a 2 bit prescaler.

4 (100) takes 3 bits.

Gonna try timer 2.


...
13.0 TIMER2/4/6 MODULE p.175
...
• 8-bit Timer and Period registers (TMRx and PRx,
respectively)
• Readable and writable (both registers)
• Software programmable prescaler (1:1, 1:4, 1:16)
• Software programmable postscaler (1:1 to 1:16)
...


EDIT: Darn, DT Elapsed include only has Timer1...

Robert

Demon
- 23rd December 2014, 03:35
Was looking at T1CON register and noticed this:


TxCKPS<1:0>: Timer1/3/5 Input Clock Prescale Select bits
11 = 1:8 Prescale value
10 = 1:4 Prescale value
01 = 1:2 Prescale value
00 = 1:1 Prescale value

So that is 2 bits.



bit 7-6 TMRxCS<1:0>: Timer1/3/5 Clock Source Select bits
11 =Reserved. Do not use.
10 =Timer1/3/5 clock source is pin or oscillator:
If TxSOSCEN = 0:
External clock from TxCKI pin (on the rising edge)
If TxSOSCEN = 1:
Crystal oscillator on SOSCI/SOSCO pins
01 =Timer1/3/5 clock source is system clock (FOSC)
00 =Timer1/3/5 clock source is instruction clock (FOSC/4)

bit 5-4 TxCKPS<1:0>: Timer1/3/5 Input Clock Prescale Select bits
11 = 1:8 Prescale value
10 = 1:4 Prescale value
01 = 1:2 Prescale value
00 = 1:1 Prescale value

bit 3 TxSOSCEN: Secondary Oscillator Enable Control bit
1 = Dedicated Secondary oscillator circuit enabled
0 = Dedicated Secondary oscillator circuit disabled

bit 2 TxSYNC: Timer1/3/5 External Clock Input Synchronization Control bit
TMRxCS<1:0> = 1X
1 = Do not synchronize external clock input
0 = Synchronize external clock input with system clock (FOSC)
TMRxCS<1:0> = 0X
This bit is ignored. Timer1/3/5 uses the internal clock when TMRxCS<1:0> = 1X.

bit 1 TxRD16: 16-Bit Read/Write Mode Enable bit
1 = Enables register read/write of Timer1/3/5 in one 16-bit operation
0 = Enables register read/write of Timer1/3/5 in two 8-bit operation

bit 0 TMRxON: Timer1/3/5 On bit
1 = Enables Timer1/3/5
0 = Stops Timer1/3/5
Clears Timer1/3/5 Gate flip-flop

T1CON=00000000

Robert

richard
- 23rd December 2014, 03:46
ITS NOT using the prescaler those bits need to be 00 ie 1:1
@64mhz with a preload of 25544 you get a tmr1 int every 2.5mS dt's int routine inc's the tips counter till its 4 then inc's the elapsed time clock I count ie once every 10mS

next step after confirming t1con is ok is to toggle a pin in the int routine as per what Sheldon suggested and verify 2.5mS ints are occurring

Demon
- 23rd December 2014, 03:47
In the Elapsed include:


...
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
...

Darryl talks about a post-scaler. Timers 1, 3 and 5 have none for a 18F44K22?

Neither does Timer 0, only Timers 2,4 and 6 have pre and post-scalers.

Robert

richard
- 23rd December 2014, 03:49
t1con looks good should be 0 or 1 (on or off) depending on what the int routine is up to

richard
- 23rd December 2014, 03:50
Darryl talks about a post-scaler. Timers 1, 3 and 5 have none for a 18F44K22?

Neither does Timer 0, only Timers 2,4 and 6 have pre and post-scalers

hence the T1PS VAR

longpole001
- 23rd December 2014, 03:54
for DT's elasped timer , i dont setup timer 1 at all




'Note: Programming the T1GCON prior to T1CON is recommended
T1GCON = %00000000 ' Timer 1 Gate Control bit7 0= counts regardless of gate 1 = gates in use , bit6 gate active when 1= High ,0=low
' bit5 0= toggle mode diabled 1= enabled bit4 single pulse mode 1- en 0= dis, bit 2 -status bit,1-0 - gate source sel
' 1
T1CON = %00000000 ' Timer 1 ,bit7-6 = TMR1 CLK source 00 = Instuction Clk(Fosc/4),01 =sys clk,10=ext clk,11=cap sense osc
' bit5-4 = TMR1 prescale 00= 1:1 ,bit3=0 LP off,bit2=1 no sync ext CLK ,bit1= 0 n/a,Bit0=0 Timer 1 on/off

TMR1H = 0 ' CLEAR TMR1H MODULE REGISTER
TMR1L = 0 ' CLEAR TMR1L MODULE REGISTER

richard
- 23rd December 2014, 04:07
I just noticed dt's ass code makes it impossible to stuff the t1con up it sets it to 0 anyway no matter what you may try to set it to . but worth checking anyway I suppose

Demon
- 23rd December 2014, 04:20
each 100th is 10ms on the i/o debug section btw

My output pin changes state every 2.5ms at 64MHz.



'************************************************* **************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 *
'* Version : 1.2 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'************************************************* **************************
DISABLE DEBUG

; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)

EL_Ticks VAR BYTE ; Counts timer Overflows
EL_100th VAR BYTE
;T1Post VAR BYTE ; Timer1 postscaler
EL_Seconds VAR BYTE
EL_Minutes VAR BYTE
EL_Hours VAR BYTE
EL_Days VAR WORD

EL_100thChanged VAR BIT
EL_SecondsChanged VAR BIT ; idicates that the value has changed
EL_MinutesChanged VAR BIT
EL_HoursChanged VAR BIT
EL_DaysChanged VAR BIT

GOSUB ResetTime ; initialize the Elapsed Timer

Goto OverElapsed ; skip over the routines

' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value


; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm

; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm

; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM

' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
EL_Ticks = EL_Ticks + 1 ; each tick is 2.5ms
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
if EL_ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
EL_100th = EL_100th + 1
EL_100thChanged = 1
IF EL_100TH = 100 THEN
EL_100TH = 0
EL_Seconds = EL_Seconds + 1
EL_SecondsChanged = 1
IF EL_Seconds = 60 THEN
EL_Seconds = 0
EL_Minutes = EL_Minutes + 1
EL_MinutesChanged = 1
eNDIF
IF EL_Minutes = 60 THEN
EL_Minutes = 0
EL_Hours = EL_Hours + 1
EL_HoursChanged = 1
ENDIF
IF EL_Hours = 24 THEN
EL_Hours = 0
EL_Days = EL_Days + 1
EL_DaysChanged = 1
ENDIF
eNDIF
endif
' Ticks = Ticks + 1
' IF Ticks = 100 THEN
' Ticks = 0
' T1Post = T1Post + 1
' IF T1Post = T1PS THEN
' T1Post = 0
' Seconds = Seconds + 1
' SecondsChanged = 1
' IF Seconds = 60 THEN
' Seconds = 0
' Minutes = Minutes + 1
' MinutesChanged = 1
' ENDIF
' IF Minutes = 60 THEN
' Minutes = 0
' Hours = Hours + 1
' HoursChanged = 1
' ENDIF
' IF Hours = 24 THEN
' Days = Days + 1
' DaysChanged = 1
' Hours = 0
' ENDIF
' ENDIF
' ENDIF
@ INT_RETURN ; Restore context and return from interrupt

'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------

StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN

; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN

; --------------------------------------------------------------------------
BitSave VAR BIT

ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
; T1Post = 0 ; clear the postscaler
EL_Ticks = 0
EL_100th = 0
EL_Seconds = 0
EL_Minutes = 0
EL_Hours = 0
EL_Days = 0
EL_100thChanged = 1
EL_SecondsChanged = 1 ; indicate everything has changed
EL_MinutesChanged = 1 ; so that 00:00:00 is processed
EL_HoursChanged = 1
EL_DaysChanged = 1
RETURN


OverElapsed:
ENABLE DEBUG

Demon
- 23rd December 2014, 04:21
each 100th is 10ms on the i/o debug section btw

My output pin changes state every 2.5ms at 64MHz.



'************************************************* **************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 *
'* Version : 1.2 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'************************************************* **************************
DISABLE DEBUG

; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)

EL_Ticks VAR BYTE ; Counts timer Overflows
EL_100th VAR BYTE
;T1Post VAR BYTE ; Timer1 postscaler
EL_Seconds VAR BYTE
EL_Minutes VAR BYTE
EL_Hours VAR BYTE
EL_Days VAR WORD

EL_100thChanged VAR BIT
EL_SecondsChanged VAR BIT ; idicates that the value has changed
EL_MinutesChanged VAR BIT
EL_HoursChanged VAR BIT
EL_DaysChanged VAR BIT

GOSUB ResetTime ; initialize the Elapsed Timer

Goto OverElapsed ; skip over the routines

' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value


; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm

; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm

; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM

' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
EL_Ticks = EL_Ticks + 1 ; each tick is 2.5ms
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
if EL_ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
EL_100th = EL_100th + 1
EL_100thChanged = 1
IF EL_100TH = 100 THEN
EL_100TH = 0
EL_Seconds = EL_Seconds + 1
EL_SecondsChanged = 1
IF EL_Seconds = 60 THEN
EL_Seconds = 0
EL_Minutes = EL_Minutes + 1
EL_MinutesChanged = 1
eNDIF
IF EL_Minutes = 60 THEN
EL_Minutes = 0
EL_Hours = EL_Hours + 1
EL_HoursChanged = 1
ENDIF
IF EL_Hours = 24 THEN
EL_Hours = 0
EL_Days = EL_Days + 1
EL_DaysChanged = 1
ENDIF
eNDIF
endif
' Ticks = Ticks + 1
' IF Ticks = 100 THEN
' Ticks = 0
' T1Post = T1Post + 1
' IF T1Post = T1PS THEN
' T1Post = 0
' Seconds = Seconds + 1
' SecondsChanged = 1
' IF Seconds = 60 THEN
' Seconds = 0
' Minutes = Minutes + 1
' MinutesChanged = 1
' ENDIF
' IF Minutes = 60 THEN
' Minutes = 0
' Hours = Hours + 1
' HoursChanged = 1
' ENDIF
' IF Hours = 24 THEN
' Days = Days + 1
' DaysChanged = 1
' Hours = 0
' ENDIF
' ENDIF
' ENDIF
@ INT_RETURN ; Restore context and return from interrupt

'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------

StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN

; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN

; --------------------------------------------------------------------------
BitSave VAR BIT

ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
; T1Post = 0 ; clear the postscaler
EL_Ticks = 0
EL_100th = 0
EL_Seconds = 0
EL_Minutes = 0
EL_Hours = 0
EL_Days = 0
EL_100thChanged = 1
EL_SecondsChanged = 1 ; indicate everything has changed
EL_MinutesChanged = 1 ; so that 00:00:00 is processed
EL_HoursChanged = 1
EL_DaysChanged = 1
RETURN


OverElapsed:
ENABLE DEBUG

Demon
- 23rd December 2014, 04:31
Yes, I'm an idiot.

T1CON becomes 00000001 once it is STARTED! D'OH!

Demon
- 23rd December 2014, 04:37
Sheldon,

It's not perfect, I'm missing some pulses on the Saleae probe, but it's sticking to a 2.5ms tick as you describe in your Elapsed include comment.

7541

EDIT: I just noticed that the skipped pulse happens at every 4 ticks.

And that skipped pulse is between 20-21uS.


EDIT SOME MORE: Got it, it's that 2nd LED toggle. I commented it out and now I have a regular 2.5ms pulse.

Robert

Demon
- 23rd December 2014, 04:52
each 100th is 10ms on the i/o debug section btw

Yup, I get 10ms if I comment out the 1st LED toggle.

7542

I understand quickly as long as you explain 10 times.

Robert

Demon
- 23rd December 2014, 05:03
Well that toggle from Sheldon confirms DT's is not working perfectly at 64MHz.

I get 2.5ms on each LED toggle.


T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
Ticks = Ticks + 1
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
IF Ticks = 100 THEN
Ticks = 0
T1Post = T1Post + 1
IF T1Post = T1PS THEN
T1Post = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt


Thanks a lot Sheldon for having figured this one out.

Robert



GAAAAA must not click on MeProg PROGRAM icon when I want to click on POST, it won't work.

richard
- 23rd December 2014, 05:16
now I'm confused

Well that toggle from Sheldon confirms DT's is not working perfectly at 64MHz.
or
Well that toggle from Sheldon confirms DT's is working perfectly at 64MHz.

ps

IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF

can be replaced with


latd.3=!latd.3


lets not have too much unnecessary overhead in the interrupt

Demon
- 23rd December 2014, 05:22
now I'm confused

or
Well that toggle from Sheldon confirms DT's is working perfectly at 64MHz.

DT's Elapsed include doesn't work perfectly at 64MHz (1 tick = 2.5ms), Sheldon's modified version does (1/100th = 10ms). Sheldon has added a new variable. I'm cleaning up the new include now to put it on the forum, somewhere.

Robert

Demon
- 23rd December 2014, 05:39
New version of Darrel Taylor's Elapsed include for 64MHz:


'************************************************* **************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 : Dec 23, 2014 *
'* Version : 1.3 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'* ver 1.3: will work with 64MHz thanks to Sheldon *
'* New field ONEHUNDRETH is now used instead of TICKS *
'************************************************* **************************
DISABLE DEBUG

; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)

Ticks VAR BYTE ; Counts timer Overflows
OneHundreth VAR BYTE ; New field for 64MHz
;T1Post VAR BYTE ; Timer1 postscaler
Seconds VAR BYTE
Minutes VAR BYTE
Hours VAR BYTE
Days VAR WORD

OneHundrethChanged VAR BIT ; New field for 64MHz
SecondsChanged VAR BIT ; idicates that the value has changed
MinutesChanged VAR BIT
HoursChanged VAR BIT
DaysChanged VAR BIT

GOSUB ResetTime ; initialize the Elapsed Timer

Goto OverElapsed ; skip over the routines

' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value


; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm

; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm

; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM

' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
Ticks = Ticks + 1 ; each tick is 2.5ms
' IF LATD.3 = 0 THEN ' used to debug to confirm 2.5ms
' LATD.3 = 1
' ELSE
' LATD.3 = 0
' ENDIF
if ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
' IF LATD.3 = 0 THEN ' used to debug to confirm 10ms
' LATD.3 = 1
' ELSE
' LATD.3 = 0
' ENDIF
OneHundreth = OneHundreth + 1 ; each 1/100th is 10ms
OneHundrethChanged = 1
IF OneHundreth = 100 THEN
OneHundreth = 0
' Ticks = Ticks + 1
' IF Ticks = 100 THEN
' Ticks = 0
' T1Post = T1Post + 1
' IF T1Post = T1PS THEN
' T1Post = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt

'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------

StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN

; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN

; --------------------------------------------------------------------------
BitSave VAR BIT

ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
; T1Post = 0 ; clear the postscaler
Ticks = 0
OneHundreth = 0
Seconds = 0
Minutes = 0
Hours = 0
Days = 0
OneHundrethChanged = 1
SecondsChanged = 1 ; indicate everything has changed
MinutesChanged = 1 ; so that 00:00:00 is processed
HoursChanged = 1
DaysChanged = 1
RETURN


OverElapsed:
ENABLE DEBUG

New field OneHundreth (10ms) replaces Tick (2.5ms at 64MHz).

7543

(Remove .TXT suffix)
7544

Robert

richard
- 23rd December 2014, 05:50
you may like to re-examine that I just tried it on a pic1845k20 @64 MHz and the int is @2.5mS as expected , sheldons mod just adds 100th capability doesn't it ?

the seconds inc on every 400th interrupt the ticks are not meant to be 10mS

Demon
- 23rd December 2014, 05:54
From http://web.archive.org/web/20120615160439/http://darreltaylor.com/DT_INTS-18/elapsed.html


The time is kept in the variables:
--------------------------------------------------------------------------------

Ticks var byte ' 1/100th of a second
Seconds var byte ' 0-59
Minutes var byte ' 0-59
Hours var byte ' 0-23
Days var word ' 0-65535

But a tick is not 2.5ms.

Robert

Demon
- 23rd December 2014, 05:59
you may like to re-examine that I just tried it on a pic1845k20 @64 MHz and the int is 2.5mS as expected , sheldons mod just adds 100th doesn't it

the ticks only inc on every 4th interrupt


What happens when you start/stop the timer after 5 ticks using the original include?

I get this using the new include:
7546


MainProgram:

if T1CON.0 = 0 then
PortD.3 = 1
GOSUB StartTimer
endif

if OneHundreth = 5 then
PortD.3 = 0
GOSUB StopTimer ' Stop the Elapsed Timer
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
endif

goto MainProgram

Robert

richard
- 23rd December 2014, 06:12
its a clock not a stopwatch , if you really need to measure wee small times like that there are better ways.
to get the fractional part of the seconds multiply t1post with ticks and / 4

longpole001
- 23rd December 2014, 06:20
ticks should be 2.5ms , 1/100 is 4 x tick = 10ms , 1 sec should be 100 x 1/100th or 400 tick = 1sec

longpole001
- 23rd December 2014, 06:27
i did version of DTs elapsed timer that shown at 1/1000 , assuming it does nothing else in life and you got a good xtl , it work ok up to 12 hours , when i tested it

also DT had a thing about showing code doing a countdown timer , so i never posted it as per his request

longpole001
- 23rd December 2014, 06:45
EL_Ticks VAR BYTE ; Ticks Up Counter -timer Overflows
EL_100th VAR BYTE ; value for 1/100s
EL_Seconds VAR BYTE ; value for seconds
EL_Minutes VAR byte
EL_Hours VAR BYTE
EL_Days VAR BYTE

longpole001
- 23rd December 2014, 06:55
also robert if your using the 18FxxK22 range of pics and DT ' ints you better to use his modified version of the specifically for the 18Fxxk22 range - as it allows for the changes in how the registers are used / accessed for some the supported functions in the k22 range , microchip changed how they are named / accessed from what i remember

Demon
- 23rd December 2014, 14:43
ticks should be 2.5ms , 1/100 is 4 x tick = 10ms , 1 sec should be 100 x 1/100th or 400 tick = 1sec

From my observations so far:

I think this is the core of the problem. With older PICs (I'm thinking up to 40MHz), a tick of 1/100 of a second was the smallest unit Darrel was able to attain. Now with newer PICs reaching 64MHz, a tick was now 4 times smaller. I can only guess that the old way of doing things in the background by Microchip was based on 16MHz processing, that would explain ticks becoming 4 times faster when using 64MHz.

As I mentionned in the chatbox last night, this is a PIC-specific issue. Sheldon mentionned that Darrel has released a 18FxxK22 version of the Elapsed Timer. I totally missed the release of this include. There's no mention of it in the archived web pages of Darrel's work (not surprising - they are old).

So I'll remove my modified version and leave people use Darrel's new version instead.

Robert

Charlie
- 23rd December 2014, 14:47
No need to remove it - there's nothing wrong with having more than one program that does the same thing!

Demon
- 23rd December 2014, 14:51
The problem with multiple versions is maintenance. If a problem is found in one version, it must also be corrected in the other - duplicating work. For example, when Microchip decides to change how things work in the background.


Right now I can't seem to find a post where Darrel released his Elapsed Timer for 18FxxK22 PICs. Has anyone else seen it?

Or was it possibly distributed through PM?

Robert

longpole001
- 23rd December 2014, 18:55
hi robbert
it was not released specifically for the elapsed timer , as that code uses timer 1 ,
and both versions must be maintained as the K22 version is specific to the registers that have changed for the K22 series

the ints-18_K22 version was on His site from memory


The modified version is used specifically on the 18fxxK22 ,for the following reasons

1. TMR4 - changed from PIR3 to PIR5 in K22 ver
2. TMR5 and TMR6 support added to support the addtional timers in the K22 series
3. ccp3 , ccp4,ccp5 - changed PIR3 to PIR4 in the K22 range


this is confirmed when comparing DT_INTS-18 AND dt_INTS-18_K22 of the code

the addtional / changed code in K22 version is as follows


regards

Sheldon



#define TMR4_INT PIR5, TMR4IF ;-- TMR4 to PR4 Match
#define TMR5_INT PIR5, TMR5IF ;-- TMR5 Overflow
#define TMR6_INT PIR5, TMR6IF ;-- TMR6 to PR6 Match



ccp3- ccp5 , uses PIR4 in the K22 , where other f18 use PIR3



#define CCP3_INT PIR4, CCP3IF ;-- CCP3
#define CCP4_INT PIR4, CCP4IF ;-- CCP4
#define CCP5_INT PIR4, CCP5IF ;-- CCP5



further support for the changed TMR4 and extra timers 5 and 6 in k22 range



ifdef TMR4IF ;----{ TMR4 Overflow Interrupt }------------[PIR5, TMR4IF]---
INT_Source PIR5,TMR4IF, PIE5,TMR4IE, IPR5,TMR4IP
endif

ifdef TMR5IF ;----{ TMR5 Overflow Interrupt }------------[PIR5, TMR5IF]---
INT_Source PIR5,TMR5IF, PIE5,TMR5IE, IPR5,TMR5IP
endif
ifdef TMR6IF ;----{ TMR6 Overflow Interrupt }------------[PIR5, TMR6IF]---
INT_Source PIR5,TMR6IF, PIE5,TMR6IE, IPR5,TMR6IP
endif



again further support of the changed interupt register from normal 18f pics ( PIR3) to that of the K22 (PIR4) for the CCP3-5



ifdef CCP3IF ;----{ CCP3 Interrupt Flag }----------------[PIR4, CCP3IF]---
INT_Source PIR4,CCP3IF, PIE4,CCP3IE, IPR4,CCP3IP
endif
ifdef CCP4IF ;----{ CCP4 Interrupt Flag }----------------[PIR4, CCP4IF]---
INT_Source PIR4,CCP4IF, PIE4,CCP4IE, IPR4,CCP4IP
endif
ifdef CCP5IF ;----{ CCP5 Interrupt Flag }----------------[PIR4, CCP5IF]---
INT_Source PIR4,CCP5IF, PIE4,CCP5IE, IPR4,CCP5IP
endif

Demon
- 23rd December 2014, 19:34
...this is confirmed when comparing DT_INTS-18 AND dt_INTS-18_K22 of the code...

Ok, so the K22 version is for the main DT_INTS-18 include, not the DT_Elapsed-18 include. I hadn't understood that.

Robert

longpole001
- 23rd December 2014, 19:42
yep there was no elapsed-18_k22

richard
- 23rd December 2014, 22:03
seems to me the easiest way to restore correct function for "ticks" when the post scaler is in use is to move the ticks loop inside the post scale loop , no extra vars no extra overhead


ClockCount:
@ RELOAD_TIMER ; Reload TIMER1

T1Post = T1Post + 1
IF T1Post = T1PS THEN
T1Post = 0
Ticks = Ticks + 1
IF Ticks = 100 THEN
Ticks = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt

Demon
- 24th December 2014, 01:59
I can only think that there was a reason why Darrel did it as he did. The dude could probably code this stuff while playing ping pong; the Bruce Lee of PBP and ASM.

There's more than one way to solve a problem, he probably took the one that worked for all PICs (until the K22 series came along). And even that he's solved the problem, it just wasn't widely known. I can only think he had greater concerns on his mind. Can you imagine how much of a headache it must have been tracking the new releases versus his routines? Makes me appreciate and miss him even more.

I now fear the day when Microchip releases a new product line. I love the K22 like I loved the 16F628 and 16F877, I'm not changing unless I'm forced to change.

Shoot, I might even stay on PBP 2.6. LOL

richard
- 24th December 2014, 02:12
it has nothing to do with the k22's its the problem exists whenever the T1PS value is >1 on any chip
its all to do with the way he implemented the post scaling , the loops are inside out . its no bigie to fix . its only apparent if you need to use "ticks" .
imho most of the time using ticks is pointless by the time you process the reading and then display it it's already meaningless and out of date . if you want to time events to such accuracy trigger times need to be allowed for and properly sync'ed , there are much better ways
ps
the k22 interrupt vagaries are a separate issue and unrelated to ticks not being 100th's of a sec

Demon
- 24th December 2014, 02:17
its only apparent if you understand what's going on .

There, fixed it for you. LOL

I never dealt with timer guts before. I always thought pre-scaling and post-scaling were what the fish looked like when my mom prepared them. :D

Oh and I don't like fish.

Robert

richard
- 24th December 2014, 02:29
you have to toggle your led at the correct place in the loop
the interrupt runs at 4x the speed required (because of high fosc not chip type ) for timing so the post scaler divides it by 4



ClockCount:
@ RELOAD_TIMER ; Reload TIMER1

T1Post = T1Post + 1
Robert toggle your pin here eg latd.0=!latd.0 for 2.5mS
IF T1Post = T1PS THEN
T1Post = 0
Ticks = Ticks + 1
Robert toggle your pin here eg latd.1=!latd.1 for 10mS
IF Ticks = 100 THEN
Ticks = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt

Demon
- 24th December 2014, 02:29
...imho most of the time using ticks is pointless by the time you process the reading and then display it it's already meaningless and out of date . if you want to time events to such accuracy trigger times need to be allowed for and properly sync'ed , there are much better ways
ps
the k22 interrupt vagaries are a separate issue and unrelated to ticks not being 100th's of a sec

I disagree. This is the first time I have a specialized need for a timer and it requires knowing how long a tick really is. I want to debounce using interrupts, so I press a button, look how long it takes for the contact to close and open again, take an arbitrary average and add maybe 25%, that's my debounce in mSeconds.

I know others use timers in what I consider a more complicated way, I have no clue how a preload value works and can never remember if the timer counts up or down from there (I have a hard time remembering little details like that). To them it's easier, I prefer the elapsed timer approach.

I turn a LED on and off, check the interval on the Saleae probe (I should get a commission every time I typed that), and that's it. Ticks=10mS is stuck in my brain ever since I first saw it on Darrel's include. I just count the ticks until I get my interval.

When you think about it, if we were that concerned with accuracy, we'd program in assembler.

Robert
:)

Demon
- 24th December 2014, 02:35
you have to toggle your led at the correct place in the loop
the interrupt runs at 4x the speed required (because of high fosc not chip type ) for timing so the post scaler divides it by 4

I know that now because I've spent 3 days on this. LOL

But ask me in a week and I won't remember, I'll spend another day running around my tail wondering why I get 4 times too many ticks at 64MHz.

I might eventually remember this long-term, if I do it for weeks. But I have sleep apnea that can't be treated completely, so what I experience during the day doesn't always get stored properly overnight in my sleep. Consider me as obsessive compulsive against my will. I can leave comments about quadruple ticking, but I'll glance over the comment and ignore it until it bites my face for a day or so. LOL

Shoot, my wife gave me $600 a month ago and I totally forgot.

Robert

Art
- 11th January 2015, 07:29
Hi Robert,
Getting to know the timer is fine, but that would be otherwise extreme for button debounce.
You can do a program timer to lock the button for a delay after being pushed.




dtimer var byte
dtimer = 0

main:

IF port.1 = 1 && dtimer = 0 then
dtimer = 200
gosub fire ‘oh no, he pushed the button, all hell is going to break loose.
endif


IF dtimer > 0 then
dtimer = dtimer-1
endif

goto main



If you needed interrupt driven buttons it would pay to set the timer in the ISR and
decrement the timer in your main program, and reenable interrupts when the timer reaches zero.

It’s good practice to keep interrupts for the thing that really needs it… like keeping real time is a good example :D

With regard to the speed, you can’t count to 400 in your Ticks byte,
but you can count to 240 Seconds (instead of 60 Seconds) to delay the time



IF Seconds = 240 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF


Now if you have to display the seconds anywhere just:



DisplaySeconds var byte

DisplaySeconds = Seconds / 4 ‘ divide by four
‘print Hours, Minutes, DisplaySeconds.



If you needed a high speed signal find and asm routine to rotate a byte with carry, and output bit.0 out a pin.
The benefit of that is ensuring it takes a constant period of time to run the check.
You might find in this code:




IF flag = 0 then
flag = 1
else
flag = 0
endif



once it’s decompiled it could take a cycle less to execute depending on the result.
So if you’re trying to produce a square wave it could be jagged.
These things are easier to do with HPWM of you have the hardware though.

Art
- 11th January 2015, 12:13
With the thing running exactly 4 times too fast I would have rotated this byte (with carry),
and read the value of bit0 each time:


%00001111