Cycling through effects with a switch on a pic

Thread Starter

vanaardep

Joined Apr 10, 2010
5
Hi there

I am coding in asm. I am currently trying to change the following code to cycle through the effects using one switch triggering RA1. ie. when power is put on the pic(16F627), no leds come on, but when the switch is clicked and let go it changes to effect 1, then when the switch is pressed again it goes to effect 2 and so on. I have no clue how to go about this can someone help please :confused:

;==========================================================================
; Variable Definition
;==========================================================================
;INPUTS
SW1 EQU H'00' ;SW1 is triggering RA0
SW2 EQU H'01' ;SW2 is triggering RA1
SW3 EQU H'02' ;SW3 is triggering RA2
SW4 EQU H'03' ;SW4 is triggering RA3
TIMER1 EQU H'20' ;Used in delay routine
TIMER2 EQU H'21' ; " " "
PATERN EQU H'22' ;Pattern data for effect's


ORG 0 ;Reset vector address
GOTO RESET ;goto RESET routine when boot.


; *********************************************
; * Example of a delay routine *
; *********************************************

DELAY_ROUTINE MOVLW D'10' ;54 Generate approx 10mS delay at 4Mhz CLK
MOVWF TIMER2
DEL_LOOP1 MOVLW D'10' ;60
MOVWF TIMER1
DEL_LOOP2 BTFSC PORTA,SW1
GOTO MENU
BTFSC PORTA,SW2
GOTO MENU
BTFSC PORTA,SW3
GOTO MENU
BTFSC PORTA,SW4
GOTO MENU
DECFSZ TIMER1,F
GOTO DEL_LOOP2
DECFSZ TIMER2,F
GOTO DEL_LOOP1
RETLW 0


; **********************************
; ** RESET : main boot routine **
; **********************************

RESET MOVLW B'00000111' ;Disable Comparator module's
MOVWF CMCON
;
BSF STATUS,RP0 ;Switch to register bank 1
;Disable pull-ups
;INT on rising edge
;TMR0 to CLKOUT
;TMR0 Incr low2high trans.
;Prescaler assign to Timer0
;Prescaler rate is 1:256
MOVLW B'11010111' ;Set PIC options (See datasheet).
MOVWF OPTION_REG ;Write the OPTION register.
;
CLRF INTCON ;Disable interrupts
MOVLW B'11000000'
MOVWF TRISB ;RB7 & RB6 are inputs.
;RB5...RB0 are outputs.
MOVLW B'11111111' ;all RA ports are inputs
MOVWF TRISA
BCF STATUS,RP0 ;Switch Back to reg. Bank 0
CLRF PORTB
GOTO EFFECT_4
;

MENU CLRF PORTB
;
BTFSC PORTA,SW1
GOTO EFFECT_1
BTFSC PORTA,SW2
GOTO EFFECT_2
BTFSC PORTA,SW3
GOTO EFFECT_3
BTFSC PORTA,SW4
GOTO EFFECT_4
GOTO MENU


EFFECT_1 BTFSC PORTA,SW1
GOTO EFFECT_1
E1 MOVLW B'00100001' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00010010' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00001100' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'11111111' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00001100' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00010010' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00100001' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00000000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00000000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00000000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
GOTO E1


EFFECT_2 BTFSC PORTA,SW2
GOTO EFFECT_2
E2 MOVLW B'00000001' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00000010' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00000100' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00001000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00010000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00100000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00010000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00001000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00000100' ;
MOVWF PORTB
CALL DELAY_ROUTINE
MOVLW B'00000010' ;
MOVWF PORTB
CALL DELAY_ROUTINE
GOTO E2

EFFECT_3 BTFSC PORTA,SW3
GOTO EFFECT_3
E3 MOVLW B'00000111' ;
MOVWF PORTB
CALL DELAY_ROUTINE
CALL DELAY_ROUTINE
MOVLW B'00111000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
CALL DELAY_ROUTINE
GOTO E3

EFFECT_4 BTFSC PORTA,SW4
GOTO EFFECT_4
E4 MOVLW B'11111111' ;
MOVWF PORTB
CALL DELAY_ROUTINE
CALL DELAY_ROUTINE
MOVLW B'00000000' ;
MOVWF PORTB
CALL DELAY_ROUTINE
CALL DELAY_ROUTINE
GOTO E4


END
 

Markd77

Joined Sep 7, 2009
2,806
You could do it with a main loop (this is pseodocode not real assembler)

loop
if state=1 call effect_1
if state=2 call effect_2
.
.
.
goto loop

You can have your switch detection in the delay routine which gets called pretty often (or use an interrupt) and just increases "state" until the max value then resets it.
To do this you need to put a "return" at the end of each effect routine so it goes through once then returns to the main loop.
The switch effect wouldn't be instant but I think the patterns are quite short so it would work pretty well.
 

MMcLaren

Joined Feb 14, 2010
861
Hi vanaardep (and gang),

I thought you might enjoy studying an example "FX Sequencer" program that uses a slightly different approach. Basically I built your 10-msec sequence interval timing into a simple sequencer loop. The loop grabs an output pattern byte from a table for the currently selected animation sequence and writes it to your LED port. Then it delays 10-msecs and samples the switch on RA0 (10-msecs is just about perfect for a debounce delay). A switch state latch variable and simple logic allows us to detect and act on a "new press" while ignoring the other switch states (no more waiting for a switch release). If a "new press" is detected we jump out of the sequencer loop and 'bump' the effect number variable and run the new effect sequence, otherwise we continue running the current sequence in the 10-msec sequencer loop. When the sequencer gets to the end of the current sequence pattern table it starts over at the beginning of that sequence. Here's an excerpt of the main program loop;

Rich (BB code):
;******************************************************************
;  main.loop                                                      *
;******************************************************************

fxbump
        clrf    PORTB           ; blank the LED outputs           |B0
        incf    fxnbr,F         ; increment effect number         |B0
        bcf     fxnbr,2         ; inclusive, 0..3                 |B0
        movf    fxnbr,W         ; W = effect number, 0..3         |B0
        addwf   fxnbr,W         ; W = effect number * 2           |B0
        addwf   fxnbr,W         ; W = effect number * 3           |B0
        addlw   low(fxtbl)      ; add to address table lo         |B0
        movwf   ptrl            ; setup table pointer lo          |B0
        movlw   high(fxtbl)     ; address table hi                |B0
        skpnc                   ; carry? no, skip, else           |B0
        addlw   1               ; account for carry               |B0
        movwf   ptrh            ; setup table pointer hi          |B0
        call    RdTable         ; get effect table addr lo        |B0
        movwf   begl            ; save "begin" table lo           |B0
        call    RdTable         ; get effect table addr hi        |B0
        movwf   begh            ; save "begin" table hi           |B0
        call    RdTable         ; get effect table length         |B0
        movwf   count           ; save length                     |B0
fxprep
        movf    begl,W          ; start/restart fx sequence       |B0
        movwf   ptrl            ; set table/array pointer lo      |B0
        movf    begh,W          ;                                 |B0
        movwf   ptrh            ; set table/array pointer hi      |B0
        movf    count,W         ;                                 |B0
        movwf   steps           ; set # steps in sequence         |B0
fxstep
        call    RdTable         ; get "pattern" byte              |B0
        movwf   PORTB           ; update port                     |B0
        DelayCy(10*msecs-27)    ; 10 msecs -27 cycle loop time    |B0
        movf    PORTA,W         ; sample active hi switches       |B0
        andlw   b'00000001'     ; on RA0 pin                      |B0
        xorwf   swold,W         ; W = changes, press or release   |B0
        xorwf   swold,F         ; update switch state latch       |B0
        andwf   swold,W         ; filter out "new release" bits   |B0
        bnz     fxbump          ; branch on a "new press", else   |B0
        decfsz  steps,F         ; sequence complete?              |B0
        goto    fxstep          ; no, branch (next step), else    |B0
        goto    fxprep          ; restart the sequence            |B0
;
The table read routines and FX sequence tables might look something like this (below). Each sequence pattern is displayed for 10-msecs so you would duplicate patterns for longer delays, or perhaps redesign the program with "pattern" and "duration" bytes for each sequence.

Rich (BB code):
;******************************************************************
;  table read routine and "fx" tables                             *
;******************************************************************

RdTable
        call    RdByte          ;                                 |B0
        incf    ptrl,F          ; bump pointer                    |B0
        skpnz                   ;                                 |B0
        incf    ptrh,F          ;                                 |B0
        return                  ;                                 |B0
RdByte
        movf    ptrh,W          ;                                 |B0
        movwf   PCLATH          ;                                 |B0
        movf    ptrl,W          ;                                 |B0
        movwf   PCL             ;                                 |B0
fxtbl
        dt      low(fx1)        ; fx1 array address lo            |B0
        dt      high(fx1)       ; fx1 array address hi            |B0
        dt      fx2-fx1         ; fx1 array length                |B0
        dt      low(fx2)        ; fx2 array address lo            |B0
        dt      high(fx2)       ; fx2 array address hi            |B0
        dt      fx3-fx2         ; fx2 array length                |B0
        dt      low(fx3)        ; fx3 array address lo            |B0
        dt      high(fx3)       ; fx3 array address hi            |B0
        dt      fx4-fx3         ; fx3 array length                |B0
        dt      low(fx4)        ; fx4 array address lo            |B0
        dt      high(fx4)       ; fx4 array address hi            |B0
        dt      fxx-fx4         ; fx4 array length                |B0
fx1
        dt      b'00100001'     ; effect 1 array                  |B0
        dt      b'00010010'     ;                                 |B0
        dt      b'00001100'     ;                                 |B0
        dt      b'11111111'     ;                                 |B0
        dt      b'00001100'     ;                                 |B0
        dt      b'00010010'     ;                                 |B0
        dt      b'00100001'     ;                                 |B0
        dt      b'00000000'     ;                                 |B0
        dt      b'00000000'     ;                                 |B0
        dt      b'00000000'     ;                                 |B0
fx2
        dt      b'00000001'     ; effect 2 array                  |B0
        dt      b'00000010'     ;                                 |B0
        dt      b'00000100'     ;                                 |B0
        dt      b'00001000'     ;                                 |B0
        dt      b'00010000'     ;                                 |B0
        dt      b'00100000'     ;                                 |B0
        dt      b'00010000'     ;                                 |B0
        dt      b'00001000'     ;                                 |B0
        dt      b'00000100'     ;                                 |B0
        dt      b'00000010'     ;                                 |B0
fx3
        dt      b'00000111'     ; effect 3 array                  |B0
        dt      b'00000111'     ;                                 |B0
        dt      b'00111000'     ;                                 |B0
        dt      b'00111000'     ;                                 |B0
fx4
        dt      b'11111111'     ; effect 4 array                  |B0
        dt      b'11111111'     ;                                 |B0
        dt      b'00000000'     ;                                 |B0
        dt      b'00000000'     ;                                 |B0
fxx
The complete "FX Sequencer" example program for 16F628A is attached below. Please let me know if it helps or if you have any questions.

Kind regards, Mike, K8LH
 

Attachments

Last edited:
Top