; PWM LED Chaser Main state function code block
; Use with pwmc_main103.asm only
_idleState call _runState ; runs state code function
btfss flags, fTick ; test for timer tick flags set
goto _idleState ; idle if flag clear
bcf flags, fTick ; reset timer tick flag
; if switch held down and count reaches .128, we set State variable to 6 (run/setup state)
; otherwise we wait until switch is released, if it was held down long enough
; to debounce the switch but not long enough to enter run/setup state we
; set the fSwitch flag on release and let current state function handle switch
btfss PORTA, switch ; test if Switch is down
goto _swDown ; do switch down code if it was
incf swTimer,W ; test if swTimer == 255 by adding 1, result in W
skpnz ; skip next if result not 0 ( 255 + 1 = 0)
goto _resetSwTimer ; else we've just returned from a long hold so don't do debounce.
; value in W is swTimer + 1 from incf above
addlw -.4 ; add 251 to W
skpnc ; skip next if if W + 251 < 256 ( carry left clear)
bsf flags, fSwitch ; otherwise set fSwitch flag
_resetSwTimer clrf swTimer ; reset switch timer
goto _idleState ; and run idle loop
_swDown
incf swTimer,W ; increment timer while switch down
skpnz ; skip if timer increment doesn't rollover to 0
goto _idleState ; else hold timer at 255 until switch released
movwf swTimer ; load current value into W
xorlw .128 ; this test will set/clear Z flag in STATUS register
movlw .6 ; load W with state 6 (won't affect STATUS register)
skpnz ; skip if the XORLW .128 wasn't zero.
movwf state ; else set state to do long switch
goto _idleState
;
_runState ; run state selector code. Must reside in page 0 of program memory
clrf PCLATH ; reset PCLATH (expects code in page 0)
movfw state ; load state variable into W
addwf PCL,F ; add W to current PCL which jumps to one of the
; goto's in the list below to select the state function.
goto _S00 ; 0
goto _S01 ; 1
goto _S02 ; 2
goto _S03 ; 3
goto _S04 ; 4
goto _S05 ; 5
goto _S06 ; 6
goto _S07 ; 7
; Each state code function will either leave the state varaible unchanged or modify it before exiting
; to control the operation of the sequencer.
; State 0
;
_S00 incf state,F ; set State == 1
movfw seqMatch
call _countSeqIn ; find address of first sequence
bcf flags, fMirrorData ; clear mirror data flag
bcf flags, fMirrorNext ; clear mirror next flag
call _setIndex ; set sequence base address and repeat count
btfsc mode,modeRan ; test if we're in Random mode
goto _S00rndMir ; do random mirror
btfsc repeatCount, fMirrorData
bsf flags, fMirrorNext
call _Lookup ;
return
_S00rndMir btfss repeatCount, fMirrorData ; is canMirror bit set for this sequence?
return ; if not we're done
call _randNum ; get random number (use carry flag on return)
skpc ; skip if carry flag clear
bsf flags,fMirrorData ; and set MirrorData flag if it is set
call _Lookup
return
; State 1
_S01
; if switch pressed skip to next sequence. This happens in all auto/random and manual modes
btfss flags, fSwitch ; test switch flag
goto _S01auto ; do _S01auto if switch up
bcf flags, fSwitch ; clear switch flag
movlw .3 ; set State to 3
movwf state
movlw cSAVETIME
movwf saveModeTimerH
clrf saveModeTimerL
bsf flags, fSaveMode
return
_S01auto btfss flags, fHoldTimeout ; test hold timeout flag
return
movfw repeatCount ; read repeat count into W reg
andlw b'00011111' ; mask off bits in repeatCount
skpz ; skip next if repeatCount == 0
goto _Lookup ; else read next entry of current sequence
; the 'goto _Lookup' means we'll use its return to get back to the call
incf state,F ; change to next state
return
; State 2
_S02 incf state,F
btfss mode, modeMan ; test and skip next if mode is manual
return
call _setIndex ; set sequence base address and repeat count
call _Lookup
movlw .1 ; Set State back to 1
movwf state
return
; State 3
_S03 incf state,F
btfsc mode, modeRan ; don't check mirror state if Random mode on
return
btfss flags, fMirrorNext ; is 'canMirror' flag set for this sequence?
return
call _setIndex ; reset sequence base addess and repeat count
bcf flags,fMirrorNext ; clear fMirrorNext'flag
bsf flags,fMirrorData ; set the MirrorData flag table data gets mirrored
movlw .1 ; Set State back to 1
movwf state
return
; State 4
_S04 clrf state ; Set next State to 0
btfsc mode,modeRan ; test if Random mode
goto _getRandSeq
incf seqMatch,F ; increment sequence number pointer
movfw seqMatch ; load seqMatch into W
xorwf seqTotal,W ; test to see if this is the highest sequence
skpnz ; skip next if not
clrf seqMatch ; else reset to select first available sequence
return
_getRandSeq call _randNum
andwf RandMask,W ; mask off unwanted bits, result in W
movwf seqMatch ; save W to SeqMatch
movf seqTotal,W ; load W with SeqTotal
subwf seqMatch,W ; W = SeqMatch - SeqTotal
skpnc ; if SeqMatch < SeqTotal we're done
goto _getRandSeq ; else try another random number
return
; State 5
_S05 ; setup mode state
; Remain in this state until the Switch handler code detects a long switch press
; and changes state for us.
clrf loReload ; clear pwm reload counter low
movfw mode
movwf hiReload
btfss flags, fSwitch ; test if switch flag set
return ; do nothing if it is clear
bcf flags, fSwitch ; clear switch flag
; 76543210 3 = Sleep, 2 = Man, 1 = AutoRand, 0 = AutoSeq
clrc ; make sure carry flag is clear
movlw 1<<modeSeq ; load W with first mode bit set
; Mode 3 puts the PIC into a low power sleep mode, where it waits for the switch
; to be pressed for about 2-3 seconds when it will leave sleep mode and reset/restart.
; Not enabled in the web release of the code but if you swap the commented/uncommented
; btfss instructions around below it will enable it.
;
;btfss mode, modeSleep ; sleep mode not in webrelease
btfss mode, modeMan ; If this is the current mode then
; skip the rotate that follows
rlf mode,W ; shift bit to select next mode, result in W
movwf mode ; put W back in mode register
return
; State 6
; Long Switch test
_S06
movlw .7 ; preload W with state 7
btfss flags, fsetupRun ; skip if we're in run mode
movlw .5 ; reload W with state 5
movwf state ; set state to either run or setup
bcf flags, fSwitch ; clear switch flag
movlw 1<<fsetupRun
xorwf flags,F ; toggle fsetupRun mode flag
movlw .255 ; load Wreg with .255
movwf swTimer ; Wreg to swTimer var
btfss mode, modeSleep
return ; return
; sleep mode, PIC enters sleep state and is woken by the watchdog timer when it
; tests the switch input. If switch has been held down for about 2 seconds the PIC
; will restart the chaser by jumping to the reset vector, otherwise it goes back to sleep
; This code is fully functional but not enabled in the web release version
bcf INTCON, T0IE ; disable Timer 0 interrupts
bcf INTCON, T0IF ; clear Timer 0 interrupt flag
bcf INTCON, GIE ; disable global interrupts
clrwdt
clrf TMR0
bank1
movlw b'00001111'
movwf OPTION_REG
bank0
clrf PORTB ; turn off all LEDs outputs
_snooze clrf swTimer
_sleep sleep
clrwdt
btfsc PORTA, switch
goto _snooze
incf swTimer,F
movfw swTimer
xorlw .2
bnz _sleep
goto START
; State 7
_S07 ; return from setup to run mode
clrf loReload ; clear pwm reload counters (looks better if we do)
clrf hiReload ;
clrf state ; restart sequence by entering state 0
movlw cSAVETIME
movwf saveModeTimerH
clrf saveModeTimerL
bsf flags, fSaveMode
return
; PWM LED Chaser Reset and initialisation code block
; Use with pro481v207.asm
START clrwdt
clrf PORTB
ifdef CMCON
ifndef __16F88
movlw b'00000111' ; disable comparators by setting CM2:CM0 == 111
movwf CMCON ; See 16F628A datasheet section 10.0
endif
endif
bank1 ; set to register bank 1
; this is a pseudo instruction defined on earlier
ifdef OSCCON
movlw b'01100010' ; set OSCCON for internal RC oscillator
movwf OSCCON ; running at 4Mhz
endif
ifdef ANSEL ; 16F88
clrf ANSEL ; Set I/O ports for digital mode
endif
movlw 1<<switch | 1<<extClkIn ; set PORTA a I/O configuration
movwf TRISA
movlw 1<<clkSel
movwf TRISB ; set PORTB a I/O configuration
movlw b'00000000' ;setup option register
; ||||||||---- PS0 - Timer 0: Prescalar 1:256
; |||||||----- PS1
; ||||||------ PS2
; |||||------- PSA - Assign prescaler to Timer0
; ||||-------- TOSE - LtoH edge
; |||--------- TOCS - Timer0 uses IntClk
; ||---------- INTEDG - falling edge RB0
; |----------- RBPU - pull-ups enabled
movwf OPTION_REG
bank0 ; set to register bank 0
; this is a pseudo instruction defined on earlier
clrf PORTA ; set all unused outputs on PORTA to 0
; Initialise all GPR memory used by variables to 0
; This code block is very important. A number of functionns expect
; variables to be zet to zero on first use.
movlw firstGPR
movwf FSR
_clearGPR movlw lastGPR
clrf INDF
incf FSR,F
xorwf FSR,W
skpz
goto _clearGPR
movlw cTIMER ; load W with timer constant
movwf TMR0 ; preset timer
movlw cTICKS
movwf tick ; preset ticks
; find the number of sequences in the sequence data
; since this data is user defined we don't know how many there are.
movlw .255
call _countSeqIn ; find total individual sequences in data
; build a mask to AND the random number against so that the MSB of the mask
; is the same as the MSB of the highest sequence number. With all lower bits
; in the mask set, we can take 8 bit random number and mask off bits higher
; than the MSB of the highest sequence value which means random numbers are
; pre-conditioned to a similar range to the number of sequences.
; Since the sequences are user defined we have to calculate the mask rather
; than using a predefined constant.
_buildMask decf seqTotal,W ;
movwf save_W ; use save_W variable as temporary working var
clrf RandMask
movlw .8
_loopMask rlf save_W,F
movf RandMask,F
skpz
setc
rlf RandMask,F
addlw -.1
bnz _loopMask
clrf seqMatch ; make sure this is clear before entering state code
movlw .31 ; initialise PWM ramp variable
movwf pwm ; cosmetic really, LEDs will flash on power-up
; unless we set this here.
; *************************************************************************
; initialise mode control flags
; Code will start in auto-sequential mode
; If you want code to startup in a different mode, change flags here
;
call restore.opmode
movlw .1
movwf state
;
; *************************************************************************
bcf INTCON, T0IF ; clear TimerO interrupt flag
bcf INTCON, INTF ; clear RBO interrupt flag
bsf INTCON, T0IE ; enable TMR0 interrupt
bsf INTCON, GIE ; enable Global interrupts
goto _idleState ; start main state function code
I need to set a function up that lights all 8 LEDs if a Gnd is on one of the unused pins of the 628A.
I was hoping to simply set the duty cycle to 95% on all 8 LEDs while ever a switch is closed giving a Gnd onto one of the spare pins which are RA6 and RB1 which I would pull high with a 10k resistor.
geko the first code posted looks good I'm not downing you all i was saying is if they stack it up so you can read it inline it's easy to see what happening. You just made blocks that do each part nice job
But the way you did it i would use a hill a function for each block and loop in main your done
I would write it for what I want it do. Wouldn't You.Why would you want to take some code that was clearly not written do what you want, had a shed load of functionality
I'm not writing any code I said to read and see what's happening I stack it inline as called and it's easy to see how you planed it. That may help BigS have a look at it.
I want to use the original program with all the cool patterns but I need to be able to switch the LEDs to more or less solid on. The problem is that I want to use them on a car which is ok when the car is parked up but totally illegal when the car is moving. So I need to be able to use the LEDs as sidelights when the car is in motion ie not flashing in any way.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?