PIC Programming: Program Construct

Status
Not open for further replies.
Joel Rainville said:
Ok, now that it's clear what the algorithm is used for :lol:, my code isn't any faster than Nigel's suggestion of decrementing then testing.

And it is still one instruction more than not using the DECFSZ instruction.

Code:
;Code by Joel, 11 instructions

   movf   SEC, w
   btfsc   STATUS, Z
   goto    sec_zero
   decfsz   SEC, f
   goto    next_1
sec_zero:   
   movf   MIN, w
   btfsc    STATUS, Z ; <MIN != 0>?
   goto next_1
   decf   MIN, f
   movlw   D'59'
   movwf   SEC
next_1:

;Code by EBLC, 10 instructions

   movf SEC,F
   btfss STATUS,Z
   goto next_0
   movf MIN,F
   btfsc STATUS,Z
   goto next_1
   decf MIN,F
   movlw D'60'
   movwf SEC
next_0:
   decf SEC,F
next_1:
 
Hey, you're cheating!

Why do you "goto next_1" which is located at the end of the routine? Where you put "goto next_1" in my code, it should be a return from the call.

While I agree that your code conforms exactly to the diagram posted, in a real world situation, your code would either need a return after next_1, or at least a goto for the next iteration... Maybe the return would be located at the very end of your program, separated from the "timer code" by thousands of lines, but you still need it to enter the timer logic more than once. My code integrates that "return".

I agree that nowhere does it ask for reentry in the diagram , but come on!...

Ok, you win, but not by much.

Edit : on closer inspection, your version does nothing when the "timer" reaches 0, while mine returns (2nd goto next_1 in what you posted), that's what explains the 1 instruction difference, but I must admit that your version looks somewhat cleaner than mine
 
If it's of any interest?, here's some clock code I used, this routine counts up (as a clock needs to), using regular 1mS interrupts.

Code:
; *********************************************
;       Timer 2 Interrupt handler.
;       Timer 2 has overflowed
;
Timer2
        incf    MSecs,F		; increment milli second counter
        movlw   d'100'          ; Is MSecs 100 yet?
        subwf   MSecs,W
        btfss   STATUS,Z        ; If MSecs is not 100, don't flash.
        goto    EndTimer2Interrupt
        movlw   H'FF'
        movwf   flagsecs
; Reinitialize Secs
        clrf    MSecs

        incf    Secs,F		; increment 10 second counter
        movlw   d'60'           ; Is Secs 60 yet?
        subwf   Secs,W
        btfss   STATUS,Z        ; If Secs is not 60, don't flash.
        goto    EndTimer2Interrupt
        movlw   H'FF'
        movwf   flag10s
; Reinitialize Secs
        clrf    Secs

        incf    Mins,F		; increment 60 second counter
        movlw   d'60'           ; Is Mins 60 yet?
        subwf   Mins,W
        btfss   STATUS,Z        ; If Mins is not 60, don't flash.
        goto    EndTimer2Interrupt
        movlw   H'FF'
        movwf   flag60s
; Reinitialize Mins
        clrf    Mins

        incf    Hours,F		; increment hour counter
        movlw   d'24'           ; Is Mins 24 yet?
        subwf   Hours,W
        btfss   STATUS,Z        ; If Hours is not 24, don't flash.
        goto    EndTimer2Interrupt
        movlw   H'FF'
        movwf   flag60s
; Reinitialize Hours
        clrf    Hours

EndTimer2Interrupt

        BCF PIR1,TMR2IF 	; Clear flag and continue.
        return
 
Joel Rainville said:
Ok, you win, but not by much.

My point is DECFSZ doesn't offer more advantage over test and DECF because its always something need to done, not skip over, when a value reaches zero.

Does DECFSNZ makes more sense?
 

...unless you're decrementing a value blindingly fast and nothing else needs to be done :lol:


eblc1388 said:
Does DECFSNZ makes more sense?

Yes, but we're on a PIC16, not a PIC18 right? Right? :lol: BTW, my PIC18 instruction set reference says DCFSNZ. Is it a typo?
 
Nigel Goodwin said:
If it's of any interest?, here's some clock code I used, this routine counts up (as a clock needs to), using regular 1mS interrupts.

Hi Nigel, why are you "incf Secs" every 100mS in your code? Should the Secs be incremented at 1000mS instead?
 

Sorry, minor typo! - the interrupts occur every 10mS not every mS, so the clock has 10mS resolution.
 

There is a problem for me to use a "return" as you have mentioned. As you might probably have guessed, this routine is placed inside an interrupt service routine, executed only after a millisecond counter has "overflowed" to indicate passage of one second. I have chosen to use the T0 timer giving me a 1.6384ms interrupt period, but then I have both T1 and T2 timer free for my other usage.

The code is almost the same as the code structure in Nigel's code. This additional routine is used to decrement the countdown period timer to zero. I still have to code for other tasks before I can truely "return" to the interrupted main program.
 
Code:
	movlw	D'60'
	decfsz SEC,f
	goto	EXIT
	movwf	SEC
;
	decfsz MIN,f
	goto	EXIT
	movwf	MIN
EXIT:
 
motion said:
Code:
	movlw	D'60'
	decfsz SEC,f
	goto	EXIT
	movwf	SEC
;
	decfsz MIN,f
	goto	EXIT
	movwf	MIN
EXIT:

Nice try, but it's gonna fail if SEC is 0, and MIN > 0, as in 2m00s, which would have to be initialized as "1m60s" to work with your code.
 

It's really no big deal to put the ff. code in the initializing routine:

Code:
        movlw D'60'
        movwf SEC
        movwf MIN

You only have to do this once, versus having to separately check if they are zero and then have to decement evertime.
 
You're right, but if we're allowed to do this, why not just go all out and simply convert everything to seconds and save a few more instructions?

I mean, you have a better solution to a real world problem than what eblc and me posted, but our little "contest" was to see how to implement the logic *exactly* as in the diagram in as few instructions as possible, and verify if BTFSS and BTFSC might offer an advantage over the other, which was later extended to include DECFSZ because of my initial claim that it would be faster... which it really isn't in that particular case.

You probably skipped over the first page of the thread... and I wouldn't blame you for that :lol:
 
I failed to see how the code posted by motion can work.

The required code is supposed to do nothing, after both SEC and MIN variable have reached zero. The above code just keeps on decrement SEC and MIN and when they reached zero, then reload them with 60.

It is not supposed to be a clock in reverse but a countdown timer which stops at zero.
 

That is easy to fix. However now that you have enlightened me on the objective, I would like to point out that your flow chart has one serious bug. As soon as the SEC variable counts down to zero, it is not reloaded and at every succeeding pass to the routine, the MIN variable immediately decrements.

Code:
   movf   MIN,w
   SKPZ
   decfsz SEC,f 
   goto   EXIT 
;
   movlw   D'60' 
   movwf   SEC 
   decf   MIN,f 
EXIT:
 
motion said:
I would like to point out that your flow chart has one serious bug. As soon as the SEC variable counts down to zero, it is not reloaded and at every succeeding pass to the routine, the MIN variable immediately decrements.

Which of the flowchart(s) has the bug you mentioned? :shock:

motion said:
That is easy to fix.

Code:
   movf   MIN,w
   SKPZ
   decfsz SEC,f
   goto   EXIT
;
   movlw   D'60'
   movwf   SEC
   decf   MIN,f
EXIT:

It's getting worse. You now check for zero in MIN and exit routine if it is zero, so the routine cannot be used for countdown a period of less than 60 seconds.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…