Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Could someone who knows ASM please add something to a prog please?

Status
Not open for further replies.

bigal_scorpio

Active Member
Hi to all,

I have been trying to understand a program but it is in ASM and I only know PicBasic.

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.

Does anyone fancy having a go at doing it please?

I will post the full zip file with the ASM in it and all the rest as I am not sure how the ASM works and which parts are needed to be changed.

Thanks, Al
 
If you need all 8 LEDs to be driven at same duty cycle, could you not just generate a single PWM on one output and connect the 8 LEDs to it via a transistor of some type?

Would be far simpler to do and you could make use of the hardware PWM in the 16F628A
 
Hi Pete,

That may work mate but I would need extra parts and still need to change the PICs code even then.

Al
 
Problem with the code you posted is that most of it is not needed and the bit you do need won't generate the 95% PWM you want because it was hard coded to four specific duty cycles.

The code you posted needs the PWM function rewritting, extra code to detect the input and modification to disable all the stuff you don't need so I think it would be better to use say a transistor for the LEDs, a smaller PIC like a 12F683 and a simple bit of code to use the hardware PWM, which you could probably do in PIC basic.
 
Hi Pete,

I was thinking that all it needed was a bit of code to detect the Gnd on the chosen pin and then tell the prog to jump to one single pattern (which I could simply edit to be on full all the time) and stay on that pattern.

Wish I could understand ASM and then I could test out my thoughts but I have had numerous tries and never got any of it into my "ROM" :(

Al
 
Well I see your thinking but it's not that simple to do.

I wrote the code and I wouldn't even try it.

Based on the functionality in your initial post I'd probably go with the 12F683/transistor/hardware PWM I think.

Even if I stuck with the 8 outputs on a 16F628A I'd just write a bit of code from scratch.
 
Last edited:
Hi Al,
I had a look at the code thinking I might be able to help, though it's written with so many 'INC' files (that looked like nonsense when I opened them) that I had no idea where to start. I was thinking along your lines in as much as a simple interrupt to a routine would have what you want done and dusted. Sadly, not the case. :(
 
Last edited:
Hi Guys,

Hmmm, I didn't think it would be so complex, but I quite understand.

HouseOFwax, if it looks like nonsense to you just imagine how it looks to me. ;)

Maybe I can find a similar program and someone may understand it, I will try anyway.

Back to the drawing board. (well google for now) ;)

Thanks, Al
 
The code would be very simple but I'm just on my way out. I may get time later or tomorrow if you're not in too much of a rush.

Mike.
 
If I was going to use that many INC files I think I'd spend my time learning a Hill But you could pile the code as it is listed and figure it out better
Like this
Code:
; 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 write my code to do something, not as a tutorial for programming and I say as much on my web site.

I split the code into include files so I'm not trawling through miles of code in a single asm file.

The code is only split into four bits
startup
interrupt
main state code
functions
 
Last edited:
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.

Here's some code (14 instructions of it) for a 16F628A that generates a 95% PWM on all PORTB outputs.

When PORTA RA4 input is low PWM is 95%, when RA4 is high PWM is 0% (off)
All other PORTA pins are set as output

It does exactly that, no more, no less.
 
Last edited:
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
 
Last edited:
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

Thing about the code is that it 'evolved' so by my own admission if I started again from scratch it would be cleaner shall we say.

However, it does work as I intended and because you can edit the sequence data I have to make the whole source code available to reassemble it.
 
Last edited:
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.

Why would you want to take some code that was clearly not written do what you want, had a shed load of functionality
I would write it for what I want it do. Wouldn't You.

And Not use something that's not made to do what I want
 
Last edited:
Hi Pete,

Sorry mate but I think you have the wrong idea.

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.

Mike, I am in no great hurry and would be very grateful if you could make the addition. PS My good mate Martin Connelly moved to your part of the world about 5 years ago now and he is loving it and doing very well for himself! He is a refridgeration engineer and is now teaching the trade and flies all over Oz to do so. I can't believe some of the distances he travels. Some of his flights are many hours (I think he said seven was the longest so far), you can virtually cross Britain in a car in that time! BIG place.

Bill, No matter how the ASM is laid out it is still nonsense to me with its bsf's and mov's. I can only just manage basic. ;)

Al
 
Last edited:
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.

That was kind of how your initial post should have started.... rather changes things.

You know when you say 'more or less solid on' do you mean solid on? Because that makes a huge difference as to how easy it would be to modify the code.

As it stands the code doesn't do 95% duty, it does:
0/31 off 0%
1/31 dim 3%
8/31 bright 25%
31/31 very bright 100%
 
Hi Pete,

100% on would be fine. I somehow had the idea that PWM couldn't be 100% thats why I said 95%. I probably got hold of some iffy info on PWM knowing me! ;)

Al
 
Okay, so what you want is

When RB1 input is high it runs the original PWM LED chaser function
When RB1 input is pulled low it sets all 8 outputs to 'on'
 
Status
Not open for further replies.

Latest threads

Back
Top