please dont rip this site

IO Stepper Linistep LINI_ASM_V21

; ******

************************************************************************
;
;  LiniStepper v2
;  PIC 16F84 / 16F628 / 16F628A code (updated 628A June 2007)
;  Copyright Aug 2002 - Nov 2009 - Roman Black   http://www.romanblack.com
;
;  PIC assembler code for the LiniStepper stepper motor driver board.
;  200/400/1200/3600 steps
;
;  v2.0	New version 2.0; 2nd Nov 2009.
;		* modified v1 source to work with new Lini v2 PCB.
;		* STEP and DIR are the same, but POWER is now "ENABLE" (active LOW)
;		  (so the POWER pin function is inverted in Lini v2) 
;  v2.1   Updated 16th Nov 2010.
;		Now incorporates update suggested by Brian D Freeman; improves
;         performance by skipping the current calculation on the hi-lo
;         transition of the step input.
;
;  (set mplab TABS to 5 for best viewing this .asm file)
;******************************************************************************


;==============================================================================
; mplab settings

	ERRORLEVEL -224		; suppress annoying message because of option/tris
	ERRORLEVEL -302		; suppress message because of bank select in setup ports

	LIST b=5, n=97, t=ON, st=OFF		;
	; absolute listing tabs=5, lines=97, trim long lines=ON, symbol table=OFF

;==============================================================================
; processor defined

	;include <p16f84A.inc>
	;include <p16f628.inc>
	include <p16f628A.inc>

; processor config

	IFDEF __16F84A
		__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
	ENDIF
	IFDEF __16F628
		__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _MCLRE_ON & _BODEN_OFF & _LVP_OFF
	ENDIF
	IFDEF __16F628A
		__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _MCLRE_ON & _BODEN_OFF & _LVP_OFF
	ENDIF


;==============================================================================
; Variables here

	;-------------------------------------------------
	IFDEF __16F84A
		#define RAM_START	0x0C
		#define RAM_END	RAM_START+d'68' 		; 16F84 has only 68 ram
	ENDIF
	IFDEF __16F628
		#define RAM_START	0x20	
		#define RAM_END	RAM_START+d'96' 		; F628 has 96 ram
	ENDIF
	IFDEF __16F628A
		#define RAM_START	0x20	
		#define RAM_END	RAM_START+d'96' 		; F628A has 96 ram
	ENDIF
	;-------------------------------------------------
	CBLOCK 	RAM_START

		status_temp		; used for int servicing
		w_temp			; used for int servicing

		step				; (0-71) ustep position!
		steptemp			; for calcs

		phase			; stores the 4 motor phase pins 0000xxxx
		current1			; for current tween pwm
		current2			; for current tween pwm

		inputs			; stores new input pins
		inputs_last		; stores last states of input pins

	ENDC

	;-------------------------------------------------
	; PIC input pins for porta

	#define 	STEP			0		; / = move 1 step, \=do nothing
	#define 	DIR			1		; lo= cw,  hi=ccw
	#define 	POWER		2		; lo=full power, hi=half power
			; (Note! POWER pin was inverted for v2 !!!)
	;-------------------------------------------------
	; Custom instructions!

	#define	skpwne		skpnz			; after subxx, uses zero
	#define	skpweq		skpz				; after subxx, uses zero
	#define	skpwle		skpc				; after subxx, uses carry
	#define	skpwgt		skpnc			; after subxx, uses carry

;==============================================================================
; CODE GOES HERE

	org 0x0000 			; Set program memory base at reset vector 0x00
reset
	goto main				;



;==============================================================================
; INTERRUPT vector here
	org 0x0004 			; interrupt routine must start here
int_routine

	;-------------------------------------------------
						; first we preserve w and status register

	movwf w_temp      		; save off current W register contents
	movf	STATUS,w          	; move status register into W register
	movwf status_temp       	; save off contents of STATUS register
	;-------------------------------------------------
						; we get here every 256 timer0 ticks  3900Hz
						; int body code here if you want

	;-------------------------------------------------
						; finally we restore w and status registers and
						; clear TMRO int flag now we are finished.
int_exit
	bcf INTCON,T0IF		; reset the tmr0 interrupt flag
	movf status_temp,w     	; retrieve copy of STATUS register
	movwf STATUS            	; restore pre-isr STATUS register contents
	swapf w_temp,f
	swapf w_temp,w          	; restore pre-isr W register contents
	retfie				; return from interrupt
	;-------------------------------------------------

;==============================================================================




;******************************************************************************
; MOVE MOTOR  		  sets 8 portb output pins to control motor
;******************************************************************************
; NOTE!! var step is used for sequencing the 0-71 steps
; uses tables! so keep it first in the code and set PCLATH to page 0

;------------------
move_motor				; goto label
;------------------

	;-------------------------------------------------
	; this code controls the phase sequencing and current
	; settings for the motor.

	; there are always 72 steps (0-71)

	; we can split the main table into 2 halves, each have identical
	; current sequencing. That is only 12 entries for hardware current.

	; Then can x3 the table to get 36 table entries which cover all 72 steps.
	; the 36 entries jump to 36 code pieces, which set the current values
	; for the 2 possible tween steps... We need 2 current values, one
	; for the x2 value and one for the x1 value.
	;-------------------------------------------------
	; PHASE SEQUENCING (switch the 4 coils)

	; there are 4 possible combinations for the phase switching:
	; each have 18 steps, total 72 steps:

	;	A+ B+	range 0		step 0-17
	;	A- B+	range 1		18-35
	;	A- B-	range 2		36-53
	;	A+ B-	range 3		54-71

	;-------------------------------------------------
						; find which of the 4 ranges we are in
	movf step,w			; get step
	movwf steptemp			; store as working temp

	movf steptemp,w		;
	sublw d'35'			; sub to test
	skpwle				;
	goto half_hi			; wgt, steptemp is 36-71 (upper half)

	;-------------------------
half_low					; wle, steptemp is 0-35

	movf steptemp,w		;
	sublw d'17'			; sub to test
	skpwle				;
	goto range1			; wgt
	
range0					; wle
	movlw b'00000101'		; 0101 = A+ B+
	goto phase_done		;

range1
	movlw b'00001001'		; 1001 = A- B+
	goto phase_done		;

	;-------------------------
half_hi					; steptemp is 36-71
						; NOTE! must subtract 36 from steptemp, so it
						; will become 0-35 and ok with table later!
	movlw d'36'			; subtract 36 from steptemp,
	subwf steptemp,f		; (now steptemp is 0-35)

						; now find the range
	movf steptemp,w		;
	sublw d'17'			; sub to test
	skpwle				;
	goto range3			; wgt
	
range2					; wle
	movlw b'00001010'		; 1010 = A- B-
	goto phase_done		;

range3
	movlw b'00000110'		; 0110 = A+ B-

phase_done				; note! steptemp is always 0-35 by here
	movwf phase			; store phase values

	;-------------------------------------------------
	; at this point we have the phasing done and stored as the last
	; 4 bits in var phase; 0000xxxx
	
	; now we have 36 possible current combinations, which we can do
	; by separate code fragments, from a jump table.

	; as we have 2 power modes; full and low power, we
	; need 2 tables.

	;-------------------------------------------------

	btfsc inputs,POWER		; select table to use
	goto table_lowpower		;

	;-------------------------------------------------
	; HIGH POWER TABLE
	;-------------------------------------------------

table_highpower			;

	movf steptemp,w		; add steptemp to the PCL
	addwf PCL,f			; 
						; here are the 36 possible values;
	;-------------------------
	goto st00				; * (hardware 6th steps)
	goto st01				;   (pwm tween steps)
	goto st02				;   (pwm tween steps)
	goto st03				; *
	goto st04				; 
	goto st05				; 

	goto st06				; *
	goto st07				;
	goto st08				;
	goto st09				; *
	goto st10				;
	goto st11				;

	goto st12				; *
	goto st13				;
	goto st14				;
	goto st15				; *
	goto st16				;
	goto st17				;

	goto st18				; *
	goto st19				;
	goto st20				;
	goto st21				; *
	goto st22				;
	goto st23				;

	goto st24				; *
	goto st25				;
	goto st26				;
	goto st27				; *
	goto st28				;
	goto st29				;

	goto st30				; *
	goto st31				;
	goto st32				;
	goto st33				; *
	goto st34				;
	goto st35				;

	;-------------------------------------------------
	; LOW POWER TABLE
	;-------------------------------------------------
	; as low power mode is for wait periods we don't need to
	; maintain the full step precision and can wait on the
	; half-step (400 steps/rev). This means much easier code tables.
	; The nature of the board electronics is not really suited
	; for LOW power microstepping, but it could be programmed here
	; if needed.

	; NOTE!! uses my hi-torque half stepping, not normal half step.

	;  doing half stepping with the 55,25 current values gives;
	; 55+25 = 80
	; max current 100+100 = 200
	; typical (high) current 100+50 = 150
	; so low power is about 1/2 the current of high power mode,
	; giving about 1/4 the motor heating and half the driver heating.

	; for now it uses only half-steps or 8 separate current modes.
	; we only have to use 4 actual current modes as
	; the table is doubled like the table_highpower is.

	; NOTE!! I have left the table full sized so it can be modified
	; to 1200 or 3600 steps if needed.
	;-------------------------------------------------

table_lowpower				;

	movf steptemp,w		; add steptemp to the PCL
	addwf PCL,f			; 
						; here are the 36 possible values;
	;-------------------------
						; A+ B+ (A- B-)

	goto lp00				;
	goto lp00				;
	goto lp00				;
	goto lp00				;
	goto lp00				;	55,25 (100,45) current low (high)
	goto lp00				;
	goto lp00				;
	goto lp00				;
	goto lp00				;

	goto lp09				;
	goto lp09				;
	goto lp09				;
	goto lp09				;
	goto lp09				;	25,55 (45,100)
	goto lp09				;
	goto lp09				;
	goto lp09				;
	goto lp09				;

	;-------------------------
						; A- B+ (A+ B-)

	goto lp18				;
	goto lp18				;
	goto lp18				;
	goto lp18				;
	goto lp18				;	25,55 (45,100)
	goto lp18				;
	goto lp18				;
	goto lp18				;
	goto lp18				;

	goto lp27				;
	goto lp27				;
	goto lp27				;
	goto lp27				;
	goto lp27				;	55,25 (100,45)
	goto lp27				;
	goto lp27				;
	goto lp27				;
	goto lp27				;

	;-------------------------------------------------
	; all tables done, no more tables after this point!
	;-------------------------------------------------
	; next are the 36 code fragments for the high power table.

	; CURRENT INFO.
	; hardware requires that we send the entire 8 bits to the motor
	; at one time, to keep pwm fast.

	; ----xxxx,  where xxxx is the coils on/off phasing (done)
	; xxxx----,  where xxxx is the current settings for the A and B phases;
	; xx------,  where xx is current for A phase
	; --xx----,  where xx is current for B phase

	; hardware currents for 6th stepping have 4 possible values;
	; 00  =  0% current
	; 01  =  25% current
	; 10  =  55% current
	; 11  =  100% current

	;-------------------------------------------------
	; PWM INFO.
	; hardware gives us 6th steps, or 1200 steps/rev.
	; to get 3600 steps/rev we need TWO more
	; "tween" steps between every proper hardware 6th step.

	; to do this we set 2 currents, current1 and current2.
	; then we do FAST pwm, with 2 time units at current2,
	; and 1 time unit at current1.
	; this gives a current which is between the two currents,
	; proportionally closer to current2. (2/3 obviously)
	; this gives the ability to get 2 evenly spaced "tween" currents
	; between our hardware 6th step currents, and go from 1200 to 3600.

	; the next 36 code fragments set the 2 currents desired, then
	; we goto a fast-pwm loop (same loop used for all currents)
	; which modulates between the 2 currents and gives final
	; output current.
	;-------------------------------------------------

st00						; (6th step)
	movf phase,w			; get coil phasing (is 0000xxxx)
	iorlw b'11000000'		; set currents; 100,0 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st01						; (tween step)
	movf phase,w			; get coil phasing
	iorlw b'11000000'		; set 100,0 
	movwf current2			;
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current1			;
	goto pwm				;

st02						; (tween step)
	movf phase,w			; get coil phasing
	iorlw b'11010000'		; set 100,25 
	movwf current2			;
	movf phase,w			;
	iorlw b'11000000'		; set 100,0 
	movwf current1			;
	goto pwm				;

	;-------------------------

st03						; (6th step)
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st04						;
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current2			;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current1			;
	goto pwm				;

st05						;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current2			;
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current1			;
	goto pwm				;

	;-------------------------

st06						; (6th step)
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st07						;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current2			;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current1			;
	goto pwm				;

st08						;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100
	movwf current2			;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current1			;
	goto pwm				;

	;-------------------------

st09						; (6th step)
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st10						;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current2			;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current1			;
	goto pwm				;

st11						;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100
	movwf current2			;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current1			;
	goto pwm				;

	;-------------------------

st12						; (6th step)
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st13						;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current2			;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current1			;
	goto pwm				;

st14						;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100
	movwf current2			;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current1			;
	goto pwm				;

	;-------------------------
st15						; (6th step)
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st16						;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current2			;
	movf phase,w			;
	iorlw b'00110000'		; set 0,100 
	movwf current1			;
	goto pwm				;

st17						;
	movf phase,w			;
	iorlw b'00110000'		; set 0,100
	movwf current2			;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current1			;
	goto pwm				;

	;-------------------------
	;-------------------------

st18						; (6th step)
	movf phase,w			;
	iorlw b'00110000'		; set 0,100 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st19						;
	movf phase,w			;
	iorlw b'00110000'		; set 0,100 
	movwf current2			;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current1			;
	goto pwm				;

st20						;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100
	movwf current2			;
	movf phase,w			;
	iorlw b'00110000'		; set 0,100 
	movwf current1			;
	goto pwm				;

	;-------------------------

st21						; (6th step)
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st22						;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current2			;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current1			;
	goto pwm				;

st23						;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100
	movwf current2			;
	movf phase,w			;
	iorlw b'01110000'		; set 25,100 
	movwf current1			;
	goto pwm				;

	;-------------------------

st24						; (6th step)
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st25						;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current2			;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current1			;
	goto pwm				;

st26						;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100
	movwf current2			;
	movf phase,w			;
	iorlw b'10110000'		; set 55,100 
	movwf current1			;
	goto pwm				;

	;-------------------------

st27						; (6th step)
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st28						;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current2			;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current1			;
	goto pwm				;

st29						;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55
	movwf current2			;
	movf phase,w			;
	iorlw b'11110000'		; set 100,100 
	movwf current1			;
	goto pwm				;

	;-------------------------

st30						; (6th step)
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st31						;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current2			;
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current1			;
	goto pwm				;

st32						;
	movf phase,w			;
	iorlw b'11010000'		; set 100,25
	movwf current2			;
	movf phase,w			;
	iorlw b'11100000'		; set 100,55 
	movwf current1			;
	goto pwm				;

	;-------------------------

st33						; (6th step)
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current2			;
	movwf current1			;
	goto pwm				;

st34						;
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current2			;
	movf phase,w			;
	iorlw b'11000000'		; set 100,0 
	movwf current1			;
	goto pwm				;

st35						;
	movf phase,w			;
	iorlw b'11000000'		; set 100,0
	movwf current2			;
	movf phase,w			;
	iorlw b'11010000'		; set 100,25 
	movwf current1			;
	goto pwm				;
						; high power table done!


	;-------------------------------------------------
	; next are the 4 code fragments for the low power table.
	; (no PWM is used)
	;-------------------------------------------------

lp00						;
	movf phase,w			;
	iorlw b'10010000'		; set 55,25 
	movwf current2			;
	movwf current1			;
	goto pwm				;

lp09						;
	movf phase,w			;
	iorlw b'01100000'		; set 25,55 
	movwf current2			;
	movwf current1			;
	goto pwm				;

lp18						;
	movf phase,w			;
	iorlw b'01100000'		; set 25,55 
	movwf current2			;
	movwf current1			;
	goto pwm				;

lp27						;
	movf phase,w			;
	iorlw b'10010000'		; set 55,25
	movwf current2			;
	movwf current1			;
	goto pwm				;

	;-------------------------------------------------


;------------------------------------------------------------------------------




;******************************************************************************
;  Main 
;******************************************************************************
;
;------------------
main						; goto label
;------------------

	;---------------------------------------------
						; do initial setup for ports and ints and stuff
	call setup			; this is our only proper call...
						; it is called only once, and does not really need
						; to be a function.
	;---------------------------------------------
	; main operating loop is here.
	;---------------------------------------------

	goto move_motor		; will set the motor to step 0,
						; and loop permanently from there

	;---------------------------------------------
	goto main				; safe loop, should never get here anyway.

;==============================================================================




;******************************************************************************
; NEW INPUTS   input change was detected
;******************************************************************************
;
;------------------
new_inputs				; goto tag
;------------------

	;-------------------------------------------------
	; when we enter here:
	; * one or more PORTA inputs have just changed
	; * inputs_last	contains last PORTA inputs values
	; * inputs		contains new PORTA inputs values
	;-------------------------------------------------
	; must first detect which input pins changed.

	; ---x----	RA4	* mode bit1	   ( 00=200 step	01=400 step
	; ----x---	RA3	* mode bit0		10=1200 step	11=3600 step )
	; -----x--	RA2	* power  (Lini v2; now 0 = full power!)
	; ------x-	RA1	* direction
	; -------x	RA0	* step

	; if step went hi, we move the step (step++ or step--)

	; if step went low, ignore
	; ignore change in direction pin
	; ignore change in power pin
	; ignore change in mode pins
	; (all pins besides step are handled automatically in move_motor)
	;-------------------------------------------------

	movf inputs,w			; xor to compare new inputs with last values
	xorwf inputs_last,f		; now inputs_last has the diff.

	btfss inputs_last,STEP	; test if step input changed
	goto ni_end			; 

						; step input changed!
	btfsc inputs,STEP		; test if change was lo-hi or hi-lo
	goto trans_hi			; lo-hi, so process a step!

						; hi-lo, so ignore this transition
	bcf inputs_last,STEP	; record new state of step pin
	goto pwm				; fast exit back to pwm()

	;-------------------------------------------------
	; step input changed lo-hi!
	; now must make a step forward or back, based
	; on the state of the dir pin.

	; here it gets complex as we have 4 operating modes,
	; determined by the state of the 2 input pins RA4 and RA3;

	; ---00---	200 steps
	; ---01---	400 steps
	; ---10---	1200 steps
	; ---11---	3600 steps

	; there are 4 separate code systems to handle stepping 
	; in the 4 modes;
	;-------------------------------------------------
trans_hi
						; find which of the 4 modes we are in
	btfss inputs,4			; test hi bit
	goto mode_lo			;

mode_hi					; must be 1200 or 3600

	btfss inputs,3			; test lo bit
	goto mode_1200			;

	;-------------------------------------------------
mode_3600					; 3600 mode (72/1)
						; each step is 1

	btfss inputs,DIR		; test direction input
	goto m36_up			;

m36_down
	decf step,f			; step--
	btfss step,7			; test for roll under <0
	goto ni_end			; ok
						; rolled under!
	movlw d'71'			; force to top step (72-1)
	movwf step			;
	goto ni_end			;

m36_up
	incf step,f			; step++
	movf step,w			; test for roll over >71
	sublw d'71'			; sub to test
	skpwle				;
	clrf step				; wgt, rolled over so force to step 0

	goto ni_end			;
	;-------------------------------------------------
mode_1200					; 1200 mode (72/3)
						; each step is mod 3 (0,3,6,9,12 - 66, 69 etc)

	btfss inputs,DIR		; test direction input
	goto m12_up			;

m12_down
	movlw d'3'			; amount to subtract
	subwf step,f			; step-=3
	btfss step,7			; test for roll under <0
	goto ni_end			; ok
						; rolled under!
	movlw d'69'			; force to top step (72-3)
	movwf step			;
	goto ni_end			;

m12_up
	movlw d'3'			; amount to add
	addwf step,f			; step+=3
						;
	movf step,w			; test for roll over >69
	sublw d'69'			; sub to test
	skpwle				;
	clrf step				; wgt, rolled over so force to step 0

	goto ni_end			;
	;-------------------------------------------------
mode_lo					; must be 200 or 400
	btfss inputs,3			; test lo bit
	goto mode_200			;

	;-------------------------------------------------
mode_400					; 400 mode (72/9)
						; note! we do special half stepping here.
						; there are ONLY 8 valid steps:
						; 4, 13, 22, 31, 40, 49, 58, 67
						; these steps give 100,45 and 35,100 combos, good
						; enough for now. (should average 100,41)

	btfss inputs,DIR		; test direction input
	goto m4_up			;

m4_down
	movlw d'9'			; amount to subtract
	subwf step,f			; step-=9
	btfss step,7			; test for roll under <0
	goto ni_end			; ok
						; rolled under!
	movlw d'67'			; force to top (full) step 
	movwf step			;
	goto ni_end			;

m4_up
	movlw d'9'			; amount to add
	addwf step,f			; step+=9
						;
	movf step,w			; test for roll over
	sublw d'67'			; sub to test
	skpwgt				;
	goto ni_end			; wle, is ok

	movlw d'4'			; wgt, rolled over so force to bottom step 5
	movwf step			;

	goto ni_end			;
	;-------------------------------------------------
mode_200					; 200 mode (72/18)
						; NOTE!! this has special needs as we can't use
						; step 0, we need to stay on the "2 steps on" steps.
						; there are ONLY 4 valid steps;  9, 27, 45, 63

	btfss inputs,DIR		; test direction input
	goto m2_up			;

m2_down
	movlw d'18'			; amount to subtract
	subwf step,f			; step-=18
	btfss step,7			; test for roll under <0
	goto ni_end			; ok
						; rolled under!
	movlw d'63'			; force to top (full) step (72-(18/2))
	movwf step			;
	goto ni_end			;

m2_up
	movlw d'18'			; amount to add
	addwf step,f			; step+=18
						;
	movf step,w			; test for roll over
	sublw d'63'			; sub to test
	skpwgt				;
	goto ni_end			; wle, is ok

	movlw d'9'			; wgt, rolled over so force to bottom step 9
	movwf step			;

	goto ni_end			;

	;-------------------------------------------------
ni_end
	movf inputs,w			; save a copy of the inputs
	movwf inputs_last		;

	goto move_motor		; go and make it all happen

;------------------------------------------------------------------------------




;******************************************************************************
; PWM		is the fast pwm loop
;******************************************************************************
; NOTE!! we enter the code in the middle of the loop!

	;-------------------------------------------------
	; the 2 target currents were set in the move_motor code.

	; what this function does is spend 2 time units at current2,
	; and 1 time unit at current1.
	; actual is 8 clocks at current2
	; and 4 clocks at current 1
	; total 12 cycles, so 333 kHz with 16MHz resonator.

	; this gives an average pwm current of 2/3 the way between
	; current2 and current1.

	; the routine is kept short to keep pwm frequency high, so it
	; is easy to smooth in hardware by the ramping caps.

	; IMPORTANT! is timed by clock cycles, don't change this code!
	; it also checks for any change in input pins here

	; the 8/4 code seen here was supplied by Eric Bohlman (thanks!)
	;-------------------------------------------------
pwm_loop
						; first output current1 to motor
	movf current1,w		; get currents and phase switching
	movwf PORTB			; send to motor!

	nop					; timing delay
	nop					;
						; (4 cycles)
	;-------------------------
pwm						; main entry!
						; better to enter at current2 for motor power.

						; now output current2
	movf current2,w		;
	movwf PORTB			; send to motor!
	nop					; safe wait 250nS

						; now test input pins
	movf PORTA,w			; get pin values from port

	xorwf inputs_last,w		; xor to compare new inputs with last values
	skpnz
	goto pwm_loop			; z, inputs not changed, so keep looping
						; (8 cycles)
	;-------------------------------------------------
						; nz, one or more input pins have changed!
	xorwf inputs_last,w		; restore xored value back to the orig inputs value
	movwf inputs			;

	goto new_inputs		; 
	;-------------------------------------------------

;------------------------------------------------------------------------------






;******************************************************************************
;  SETUP   sets port directions and interrupt stuff etc,
;******************************************************************************
; NOTE!! is the only proper funtion, is done before other activity

;------------------
setup					; routine tag
;------------------

	;-------------------------------------------------
	; Note! there are added bits for the 16F628!
	; here we set up peripherals and port directions.
	; this will need to be changed for different PICs.
	;-------------------------------------------------
						; OPTION setup
	movlw b'10000010'		;
		;  x-------		; 7, 0=enable, 1=disable, portb pullups
		;  -x------		; 6, 1=/, int edge select bit
		;  --x-----		; 5, timer0 source, 0=internal clock, 1=ext pin.
		;  ---x----		; 4, timer0 ext edge, 1=\
		;  ----x---		; 3, prescaler assign, 1=wdt, 0=timer0
		;  -----x--		; 2,1,0, timer0 prescaler rate select
		;  ------x-		;   000=2, 001=4, 010=8, 011=16, etc.
		;  -------x		; 
						;
	banksel OPTION_REG		; go proper reg bank
	movwf OPTION_REG		; load data into OPTION_REG
	banksel 0				;
	;-------------------------------------------------
	; note! check for 16F628 (and A) and do extra setup for it.

	IFDEF  __16F628
		banksel VRCON		; do bank 1 stuff
		clrf VRCON		; disable Vref
		clrf PIE1			; disable pi etc
		banksel 0			;

		clrf T1CON		; disable timer1
		clrf T2CON		; disable timer2
		clrf CCP1CON		; disable CCP module

		movlw b'00000111'	; disable comparators
		movwf CMCON		;
	ENDIF
	IFDEF  __16F628A
		banksel VRCON		; do bank 1 stuff
		clrf VRCON		; disable Vref
		clrf PIE1			; disable pi etc
		banksel 0			;

		clrf T1CON		; disable timer1
		clrf T2CON		; disable timer2
		clrf CCP1CON		; disable CCP module

		movlw b'00000111'	; disable comparators
		movwf CMCON		;
	ENDIF
	;-------------------------------------------------
						; PORTB pins direction setup
						; 1=input, 0=output
	clrf PORTB			;
						;
	movlw b'00000000'		; all 8 portb are outputs
						;
	banksel TRISB			; go proper reg bank
	movwf TRISB			; send mask to portb
	banksel 0				;
	;-------------------------------------------------

						; PORTA pins direction setup
						; 1=input, 0=output
	clrf PORTA			;

						; NOTE!! all 5 PORTA pins are inputs
	movlw b'00011111'		;
		;  ---x----		; RA4
		;  ----x---		; RA3
		;  -----x--		; RA2
		;  ------x-		; RA1
		;  -------x		; RA0

	banksel TRISA			; go proper reg bank
	movwf TRISA			; send mask to porta
	banksel 0				;
	;-------------------------------------------------

	movlw 0x00			; set up PCLATH for all jump tables on page 0
	movwf PCLATH			; (all tables are in move_motor)
	;-------------------------------------------------

						; CLEAR RAM! for lower bank
	movlw RAM_START		; first byte of ram
	movwf FSR				; load pointer
ram_clear_loop
	clrf INDF				; clear the ram we pointed to
	incf FSR,f			; inc pointer to next ram byte
	movf FSR,w			; get copy of pointer to w
	sublw RAM_END			; test if PAST the last byte now
	skpweq				;
	goto ram_clear_loop		;

	;-------------------------------------------------
						; here we can set the user variables and output pins

	movlw 0x00			; for step 0 of 0-71
	movwf step			; loaded ready for jump table

	movf PORTA,w			; get initial value for inputs
	movwf inputs			;
	movwf inputs_last		;

	;-------------------------------------------------
						; set up INTCON register last
	movlw b'00000000'		; set the bit value 

		;  x-------		; bit7 	GIE global int enable, 1=enabled
		;  -x------		; bit6	EE write complete enable, 1=en
		;  --x-----		; bit5 	TMR0 overflow int enable, 1=en
		;  ---x----		; bit4 	RB0/INT enable, 1=en
		;  ----x---		; bit3	RB port change int enable, 1=en
		;  -----x--		; bit2	TMR0 int flag bit, 1=did overflow and get int
		;  ------x-		; bit1	RB0/INT flag bit, 1=did get int
		;  -------x		; bit0	RB port int flag bit, 1=did get int

	movwf INTCON			; put in INTCON register
	;-------------------------------------------------
	return				;
;------------------------------------------------------------------------------





;==============================================================================
	; this code is only to display 1k of the memory usage chart
	; in the absolute listing!

	; page 0 256 byte block--------------------
	;org 0x40-2
	;nop
	;org 0x80-1
	;nop
	;org 0xC0-1
	;nop
	;org 0x100-1
	;nop

	; page 1 256 byte block--------------------
	;org 0x140-2
	;nop
	;org 0x180-1
	;nop
	;org 0x1C0-1
	;nop
	;org 0x200-1
	;nop

	; page 2 256 byte block--------------------
	org 0x240-2
	nop
	org 0x280-1
	nop
	org 0x2C0-1
	nop
	org 0x300-1
	nop

	; page 3 256 byte block--------------------
	org 0x340-2
	nop
	org 0x380-1
	nop
	org 0x3C0-1
	nop
	org 0x400-1
	nop


	IFDEF __16F628A
		; page 4 256 byte block--------------------
		org 0x440-2
		nop
		org 0x480-1
		nop
		org 0x4C0-1
		nop
		org 0x500-1
		nop

		; page 5 256 byte block--------------------
		org 0x540-2
		nop
		org 0x580-1
		nop
		org 0x5C0-1
		nop
		org 0x600-1
		nop

		; page 6 256 byte block--------------------
		org 0x640-2
		nop
		org 0x680-1
		nop
		org 0x6C0-1
		nop
		org 0x700-1
		nop

		; page 7 256 byte block--------------------
		org 0x740-2
		nop
		org 0x780-1
		nop
		org 0x7C0-1
		nop
		org 0x800-1
		nop
	ENDIF

	;-------------------------------------------------------------------------
	end
	;-------------------------------------------------------------------------

;==============================================================================
;==============================================================================
;==============================================================================



	;-------------------------------------------------
	; NOTE!! example! below is the original (non-pwm) table for the
	; 24x hardware 6th steps.
	; this will be useful to code a minimum-rom microstepper
	; if you don't need 3600 and can make do with 1200 steps.

	; same system as the main code;
	; ----xxxx	are the phase sequencing
	; xxxx----	are the current values

	; (this code table has been used and tested!)
	;-------------------------------------------------
	; COMMENTED OUT!

		;movlw b'11000101'		; 0,		100,0 	A+ B+	00=0		01=25
		;movlw b'11010101'		; 1,		100,25	A+ B+	10=55	11=100
		;movlw b'11100101'		; 2, 	100,55 	A+ B+
		;movlw b'11110101'		; 3, 	100,100	A+ B+
		;movlw b'10110101'		; 4, 	55,100	A+ B+
		;movlw b'01110101'		; 5, 	25,100	A+ B+
	;-------------------------
		;movlw b'00111001'		; 6, 	0,100	A- B+
		;movlw b'01111001'		; 7, 	25,100	A- B+
		;movlw b'10111001'		; 8, 	55,100	A- B+
		;movlw b'11111001'		; 9, 	100,100	A- B+
		;movlw b'11101001'		; 10, 	100,55	A- B+
		;movlw b'11011001'		; 11, 	100,25	A- B+
	;-------------------------
		;movlw b'11001010'		; 12, 	100,0	A- B-
		;movlw b'11011010'		; 13, 	100,25	A- B-
		;movlw b'11101010'		; 14, 	100,55	A- B-
		;movlw b'11111010'		; 15, 	100,100	A- B-
		;movlw b'10111010'		; 16, 	55,100	A- B-
		;movlw b'01111010'		; 17, 	25,100	A- B-
	;-------------------------
		;movlw b'00110110'		; 18, 	0,100	A+ B-
		;movlw b'01110110'		; 19, 	25,100	A+ B-
		;movlw b'10110110'		; 20, 	55,100	A+ B-
		;movlw b'11110110'		; 21, 	100,100	A+ B-
		;movlw b'11100110'		; 22, 	100,55	A+ B-
		;movlw b'11010110'		; 23, 	100,25	A+ B-



	EXAMPLE! full table example here, 0-71 steps showing every step...

	;-------------------------
	0	100,0 	A+ B+
	1	 100,8   (pwm tween)
	2	 100,17  (pwm tween)
	3	100,25	A+ B+
	4	 100,35  (pwm tween)
	5	 100,45  (pwm tween)
	6	100,55 	A+ B+
	7	 100,70  (pwm tween)	
	8	 100,85  (pwm tween)
	9	100,100	A+ B+	(rest of table is same, tweens not shown)
	10
	11
	12	55,100	A+ B+
	13
	14
	15	25,100	A+ B+
	16
	17
	;-------------------------
	18	0,100	A- B+
	19
	20
	21	25,100	A- B+
	22
	23
	24	55,100	A- B+
	25
	26
	27	100,100	A- B+
	28
	29
	30	100,55	A- B+
	31
	32
	33	100,25	A- B+
	34
	35
	;-------------------------
	36	100,0	A- B-
	37
	38
	39	100,25	A- B-
	40
	41
	42	100,55	A- B-
	43
	44
	45	100,100	A- B-
	46
	47
	48	55,100	A- B-
	49
	50
	51	25,100	A- B-
	52
	53
	;-------------------------
	54	0,100	A+ B-
	55
	56
	57	25,100	A+ B-
	58
	59
	60	55,100	A+ B-
	61
	62
	63	100,100	A+ B-
	64
	65
	66	100,55	A+ B-
	67
	68
	69	100,25	A+ B-
	70
	71
	;-------------------------------------------------
	




file: /Techref/io/stepper/linistep/Lini_asm_v21.asm, 36KB, , updated: 2012/12/29 00:37, local time: 2017/8/22 17:57,
TOP NEW HELP FIND: 
54.166.168.243:LOG IN

 ©2017 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE! / 

<A HREF="http://www.piclist.com/techref/io/stepper/linistep/Lini_asm_v21.asm"> io stepper linistep Lini_asm_v21</A>

Did you find what you needed?

 
Stepper motors CAN be smooth!
And stepper controllers can be strong and cheap. Roman Black's Linistep stepper controller kits:
o 18th microstep
o Linear smoothing
  o Open source
o Full kit $25!
 

Welcome to www.piclist.com!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .