
VERSIONSTRING equ "Motor v1.00"

!
! Filename:     motor.asm
! Module name:  Motor
! Description:  stepper motor driver
!
! Commands:
!   string QueryVersion () - retrieve version string
!   SetStep (byte stepnum) - set the stepper motor pattern directly
!   SetSpeed (word speed) - set the turn speed
!   StepLeft () - move one step to the left
!   StepRight () - move one step to the right
!   TurnLeft (word numsteps) - turn numsteps to the left
!   TurnRight (word numsteps) - turn numsteps to the right
!   Stop () - stop turning
!   Release () - turn off current to the motor
!
! IPC:
!   none
!
! Timers:
!   TIMER_Motor - timer for turning
!
! Hooks:
!   none
!
! Comments:
!   none :)
!
! Hardware notes:
!   Simply write the stepper motor pattern to PORT_Motor.
!
! History:
!   bv 5/11/99	- initial revision
!   bv 7/26/99	- converted to cokeOS v3 module
!   bv 5/28/99	- converted to cokeOS v3 module

	include <coke/coke.inc>

; constants

DEFAULTMOTORSPEED	equ $18
NUMSTEPS		equ $8


; EntryPoint

EntryPoint	subroutine
	cmpa	#IPC_Coke_Hello
	beq	.init
	cmpa	#IPC_Coke_Goodbye
	beq	.free
	sec
	rts
.init
	ldx	#CommandTable	; install command table
	jsr	Coke_InstallCommandTable
	ldaa	#ID_Doodad	; register IPC
	ldx	#EntryPoint
	jsr	Coke_RegisterIPC
	jsr	InitMotor	; init stuff
	clc
	rts		
.free
	ldx	#CommandTable	; remove commands
	jsr	Coke_RemoveCommandTable
	ldaa	#TIMER_Motor	; remove timer
	jsr	Coke_RemoveTimer
	ldaa	#ID_Doodad	; remove IPC
	jsr	Coke_UnregisterIPC
	clc
	rts



; InitMotor turns off the motor so we don't waste power

InitMotor	subroutine
	clra
	staa	PORT_Motor
	staa	motor_stepnum
	staa	motor_portout
	ldd	#DEFAULTMOTORSPEED
	std	motor_speed
	rts


; StepLeft steps the motor to the left
	
StepLeft subroutine
	pshb
	ldab	motor_stepnum
	incb
	cmpb	#NUMSTEPS
	bne	.dostep
	clrb
.dostep
	jsr	DoStep
	pulb
	rts


; StepRight steps the motor to the right

StepRight subroutine
	pshb
	ldab	motor_stepnum
	decb
	bpl	.dostep
	ldab	#NUMSTEPS-1
.dostep
	jsr	DoStep
	pulb
	rts


; DoStep sets the motor pattern.
; stepnum in b

DoStep subroutine
	pshb
	pshx

	stab	motor_stepnum
	ldx	#StepTable
	abx

	ldab	motor_portout
	andb	#$f0
	orab	0,x
	stab	motor_portout
	stab	PORT_Motor

	pulx
	pulb
	rts


; Command_SetStep (byte stepnum)

Command_SetStep subroutine
	jsr	Coke_GetChar	; get param
	cmpa	#NUMSTEPS	; check if it's too big
	bhs	.badstep	; if so, fail
	tab			; if good, put code in b
	jsr	DoStep		; do the step
	ldaa	#COKE_ACK	; we cool, fool
	rts
.badstep
	ldab	#ERROR_Motor_BadStepNumber
	ldaa	#COKE_FAIL
	rts


; Command_SetSpeed (word speed)

Command_SetSpeed subroutine
	jsr	Coke_GetChar	; get lobyte
	tab
	jsr	Coke_GetChar	; get hibyte
	std	motor_speed	; set the variable
	ldaa	#COKE_ACK
	rts


; Command_StepLeft ()

Command_StepLeft subroutine
	jsr	StepLeft	; step left
	ldaa	#COKE_ACK
	rts


; Command_StepRight ()

Command_StepRight subroutine
	jsr	StepRight	; step right
	ldaa	#COKE_ACK
	rts


; Command_TurnLeft (word numsteps)

Command_TurnLeft subroutine
	jsr	Coke_GetChar	; lobyte
	tab
	jsr	Coke_GetChar	; hibyte
	std	motor_stepcount	; store it

	ldaa	#TIMER_Motor	; set the timer
	ldab	#0		; turn left
	ldx	#TurnTimerFunction
	ldy	motor_speed
	jsr	Coke_SetTimer
.done
	ldaa	#COKE_ACK	; and we're off!
	rts


; Command_TurnRight (word numsteps)

Command_TurnRight subroutine
	jsr	Coke_GetChar	; lobyte
	tab
	jsr	Coke_GetChar	; hibyte
	std	motor_stepcount	; store it

	ldaa	#TIMER_Motor	; set the timer
	ldab	#1		; turn right
	ldx	#TurnTimerFunction
	ldy	motor_speed
	jsr	Coke_SetTimer
.done
	ldaa	#COKE_ACK	; and we're off!
	rts


; Command_Stop ()

Command_Stop subroutine
	ldaa	#TIMER_Motor	; remove the timer function
	jsr	Coke_RemoveTimer
	ldaa	#COKE_ACK
	rts


; Command_Release ()

Command_Release subroutine
	ldaa	#TIMER_Motor	; remove the timer function
	jsr	Coke_RemoveTimer

	ldab	motor_portout	; clear the motor bits
	andb	#$f0
	stab	motor_portout
	stab	PORT_Motor

	ldaa	#COKE_ACK
	rts


; TurnTimerFunction is the timer function for turning
; direction is in param in a.

TurnTimerFunction subroutine
	pshx

	ldx	motor_stepcount	; get the counter
	beq	.turn		; if zero, we're counting forever
	dex			; decrement
	stx	motor_stepcount	; store it
	bne	.turn		; was it zero?
	psha			
	ldaa	#TIMER_Motor	; if so, remove this timer function
	jsr	Coke_RemoveTimer
	pula
.turn
	tsta			; turning left or right?
	bne	.right
	jsr	StepLeft	; step left
	bra	.done
.right
	jsr	StepRight	; step right
.done
	pulx
	rts


; StepTable is the pattern table for half-stepping

StepTable subroutine
	dc.b	%00000101
	dc.b	%00000001
	dc.b	%00000011
	dc.b	%00000010
	dc.b	%00001010
	dc.b	%00001000
	dc.b	%00001100
	dc.b	%00000100


; version stuff

	_versionstuff

; command table

CommandTable subroutine
	dc.b	CMD_Motor_QueryVersion
	dc.w	Command_QueryVersion
	dc.b	CMD_Motor_SetStep
	dc.w	Command_SetStep
	dc.b	CMD_Motor_SetSpeed
	dc.w	Command_SetSpeed
	dc.b	CMD_Motor_StepLeft
	dc.w	Command_StepLeft
	dc.b	CMD_Motor_StepRight
	dc.w	Command_StepRight
	dc.b	CMD_Motor_TurnLeft
	dc.w	Command_TurnLeft
	dc.b	CMD_Motor_TurnRight
	dc.w	Command_TurnRight
	dc.b	CMD_Motor_Stop
	dc.w	Command_Stop
	dc.b	CMD_Motor_Release
	dc.w	Command_Release

	dc.b	0


; data segment

motor_stepnum	ds 1
motor_portout	ds 1
motor_stepcount	ds 2
motor_speed	ds 2
