;**************************************************************************
; DMX84.ASM
;	Heater control software for dmx84 heating doll.
;	(c) 2003 doku@newon.org
;**************************************************************************

        LIST P=16F84, R=DEC

	#include	"16cxx.h"

RamTop   EQU     0x10

;--------------------------------------------------------------------------
;	Variables
;--------------------------------------------------------------------------

;
;	pointers
;
RamTop		EQU	0x10

wk0		EQU	RamTop+0x0
wk1		EQU	RamTop+0x1
wk2		EQU	RamTop+0x2

TimCnt		EQU	RamTop+0x3

SyncFlg		EQU	RamTop+0x5

TimCnt0		EQU	RamTop + 0x6
TimCnt1		EQU	TimCnt0 + 0x1
TimCnt2		EQU	TimCnt0 + 0x2
TimCnt3		EQU	TimCnt0 + 0x3

PB		EQU	RamTop+0xb

PwmCnt		EQU	RamTop+0xc

DrvCnt		EQU	RamTop + 0xd
DrvRat		EQU	RamTop + 0xe
;
;	Bits
;
#define		MonBit	_porta,4

;
;	values
;
SkpCnt		EQU	9
TimSet		EQU	0xFF - 100

;--------------------------------------------------------------------------
; Program Code
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
;   Set the reset vector here.  If you are using a PIC16C5X device, use:
;               ORG     <last program memory location>
;   Otherwise, use:
;               ORG     0
;--------------------------------------------------------------------------

		ORG     0       
		GOTO    Init

;--------------------------------------------------------------------------
; Interrupt Program
;--------------------------------------------------------------------------
		ORG	4
Interrupt
		movwf	wk0		;w -> wk0
		swapf	wk0,F		;sawp(wk0) -> wk0

		swapf	_status,w	;swap(status) -> w
		movwf	wk1		;wk1 <- w

		movf	_fsr,w		;fsw -> w
		movwf	wk2		;w -> wk2

;	reset interrupt source
		bcf	_rtif		;0 -> rtif
		
;	increment time counter
		decfsz	TimCnt,f
;	if TimCnt != 0 then skip count up TimCnt0-3 and Sync
		goto	NoSync
;	else reset TimCnt and count up TimCnt0-3

;--------------------------------------------------------------------------
;	COUNT UP and SYNC 	

;	reset skip counter
		movlw	SkpCnt
		movwf	TimCnt

;	increment time counter
		incfsz	TimCnt0,f
		goto	IncEnd
		incfsz	TimCnt1,f
		goto	IncEnd
		incfsz	TimCnt2,f
		goto	IncEnd
		incf	TimCnt3,f
IncEnd

;	set sync flag
		bsf	SyncFlg,0	;1 -> SuncFlag

;--------------------------------------------------------------------------

NoSync

		incf	PwmCnt,f

;	PwmOut1
		movf	PwmCnt,w
		subwf	TimCnt0,w
		btfss	_c
		bcf	_porta,0
		btfsc	_c
		bsf	_porta,0

;	PwmOut1
		movf	PwmCnt,w
		subwf	TimCnt1,w
		btfss	_c
		bcf	_porta,1
		btfsc	_c
		bsf	_porta,1

;	PwmOut2
		movf	PwmCnt,w
		subwf	DrvCnt,w
		btfss	_c
		bcf	_porta,2
		btfsc	_c
		bsf	_porta,2

;	PwmOut3
		movf	PwmCnt,w
		subwf	DrvRat,w
		btfss	_c
		bcf	_porta,3
		btfsc	_c
		bsf	_porta,3

;	reset timer
		movlw	TimSet
		movwf	_tmr0

;	restore registors
		movf	wk2,w		;wk2 -> w
		movwf	_fsr		;w -> fsr

		swapf	wk1,w		;wk1 -> w
		movwf	_status		;w -> status

		swapf	wk0,w		;wk0 -> w

;	end of interrupt
		retfie	

;--------------------------------------------------------------------------
; Main Program
;--------------------------------------------------------------------------

                ORG     H'50'

;--------------------------------------------------------------------------
Init
;--------------------------------------------------------------------------


;--------------------------------------------------------------------------
;	init memory
;	clear all memory
;--------------------------------------------------------------------------
		movlw	RamTop
		movwf	_fsr
clrloop		clrf	_indf
		incf	_fsr,f
		movf	_fsr,w
		sublw	RamTop + 0x30
		btfss	_z
		goto	clrloop

;	init clock
		movlw	TimSet
		movwf	_tmr0

;--------------------------------------------------------------------------
;	init register
;--------------------------------------------------------------------------

;	set bank 1 
		bcf	_irp
		bcf	_rp1
		bsf	_rp0

;	I/O Location
;
;	port	I/O
;	---------------------
;	A0	OUT	of A3
;	A1	OUT	of A2
;	A2	IN
;	A3	IN
;	B0	IN
;	B1	IN
;	B2	IN
;	B3	IN
;	B4	OUT	of B3
;	B5	OUT	of B2
;	B6	OUT	of B1
;	B7	OUT	of B0	

;	A4	OUT	Power Control


;	set port a I/O mode (0 for out)
		movlw	11100000B
		movwf	_trisa

;	set port b I/O mode (0 for out)
		movlw	00001111B
		movwf	_trisb

;	set up timer
		movlw	11000000B	;tmr0 active PS 1/1 devide
		movwf	_option		;set them

;	set bank 0 
		bcf	_rp0

;	set up interrupt
		movlw	00100000B	;tmr0 int enable
		movwf	_intcon

;	enable interrupt
		bsf	_gie		

;	init value
		movlw	SkpCnt
		movwf	TimCnt

;	Full Drive!
		movlw	0xFF
		movwf	DrvRat
;--------------------------------------------------------------------------
;	main loop
;--------------------------------------------------------------------------
Start
;	Is now for Obserb Drive Counter?
		movlw	255
		subwf	TimCnt1,W
		btfss	_z
		goto	Main1

;	Obserb Drive Countor		
		call	Obserb
		goto	WLoop
		
;	Drive a Heater
Main1
		call	Sync

		call 	Lat

		call	Sync

		call	OffDrv
		call 	Drv

;	Wait for Next Time BLOCK (not a time slot)
WLoop		call	Sync
		movlw	0
		subwf	TimCnt0,W
		btfss	_z
		goto	WLoop
		
		GOTO    Start

;--------------------------------------------------------------------------
;	obserbing drive ratio
;--------------------------------------------------------------------------
Obserb
;	if ODD turn then return
		btfsc	TimCnt2,0
		goto	Obs1
		clrf	DrvCnt
		return

Obs1
;	if EVEN turn then Clear 
;	Save Drive Ratio
		movf	DrvCnt,W
		movwf	DrvRat	
		clrf	DrvCnt
		return 

;--------------------------------------------------------------------------
;	Off output drive
;	all heaters are off and bridge sensing is enabled
;--------------------------------------------------------------------------
OffDrv		bcf	_portb,4
		bcf	_portb,5
		bcf	_portb,6
		bcf	_portb,7
		return

;--------------------------------------------------------------------------
;	Latch senser input and drive due to input status
;--------------------------------------------------------------------------
Lat		movf	_portb,w	;get port b
		movwf	PB	;save port b
		return

;--------------------------------------------------------------------------
;	Latch senser input and drive due to input status
;--------------------------------------------------------------------------
Drv		BTFSS	PB,3	;if compalator is HIGH (temp is LOW) then skip
		BsF	_portb,4	;else off the heater

		BTFSS	PB,2	;if compalator is HIGH (temp is LOW) then skip
		BsF	_portb,5	;else off the heater

		BTFSS	PB,1	;if compalator is HIGH (temp is LOW) then skip
		BsF	_portb,6	;else off the heater

		BTFSS	PB,0	;if compalator is HIGH (temp is LOW) then skip
		BsF	_portb,7	;else off the heater

		BTFSS	PB,0	;if compalator is HIGH (temp is LOW) then skip
		incf	DrvCnt	;One up Drive Counter

		return

;--------------------------------------------------------------------------
;	Sync
;--------------------------------------------------------------------------
Sync	
SyncLoop
;	Wait for next time slot(loop while sync flag  <> 0)
		btfss	SyncFlg,0	;check sync flag
		goto	SyncLoop
		
;	reset sync flag
		bcf	SyncFlg,0

		return
		
;--------------------------------------------------------------------------
;	end of program
;--------------------------------------------------------------------------
                END


