;#########################
;###     FLSUPPLY      ###
;#########################
;Version	 1.1
;Date:		 14 SEP 2005
;Filename:	 FLSUPPLY.ASM
;Support E-mail: info@astroma-spb.ru
;Target:	 ACM-801, ACM-811

;ПРОГРАММА УПРАВЛЕНИЯ СИСТЕМОЙ ПОДАЧИ МУКИ

.INCLUDE "m64def.inc"	;файл предоставляется компанией Atmel (www.atmel.com)
.INCLUDE "ACM-801.inc"	;файл предоставляется компанией Astroma Ltd. (www.astroma-spb.ru)

		.CSEG

.MACRO STATUS
	push	zl
	ldi	zl,@0
	sts	(FLSUPPLY_STATUS),zl
	pop	zl
.ENDMACRO

.MACRO	DELAY
	push	zl
	ldi	zl,low(@0)
	sts	(DELAY_TIME),zl
	ldi	zl,high(@0)
	sts	(DELAY_TIME+1),zl
	pop	zl
.ENDMACRO

		.org	0
;*****************************************
BEGIN:		clr	xl
		sts	(DELAY_TIME),xl
		sts	(DELAY_TIME+1),xl
		sts	(FLSUPPLY_STATUS),xl
		CALL	GetBaseAddress		;определить свой базовый адрес
		sts	(MY_BASE),xl
		sts	(MY_BASE+1),xh		;сохранить в SRAM
		mov	r5,xl
		mov	r6,xh
;установить обработчик прерывания INT0 ("FULL")
		ldi	r25,HOOK_INT0
		CALL	GetHookHandler		;сохранить прежний обработчик ловушки
		sts	(INT0_HANDLER),xl
		sts	(INT0_HANDLER+1),xh
		ldi	xl,low(FULL)
		ldi	xh,high(FULL)
		add	xl,r5
		adc	xh,r6
		CALL	SetHook			;установить новый обработчик
;установить обработчик прерывания INT1 ("EMPTY")
		ldi	r25,HOOK_INT1
		CALL	GetHookHandler		;сохранить прежний обработчик ловушки
		sts	(INT1_HANDLER),xl
		sts	(INT1_HANDLER+1),xh
		ldi	xl,low(EMPTY)
		ldi	xh,high(EMPTY)
		add	xl,r5
		adc	xh,r6
		CALL	SetHook			;установить новый обработчик
;активировать ловушку 200Hz
		ldi	r25,HOOK_SYS_TIME	;ловушка прерывания 200 Hz
		CALL	GetHookHandler		;сохранить прежний обработчик ловушки
		sts	(SYS_TIME_HANDLER),xl	;HOOK_SYS_TIME в переменной SYS_TIME_HANDLER
		sts	(SYS_TIME_HANDLER+1),xh
		lds	zl,(MY_BASE)		;базовый адрес
		lds	zh,(MY_BASE+1)
		ldi	xl,low(TIMER)		;адрес нового обработчика
		ldi	xh,high(TIMER)
		add	xl,zl
		adc	xh,zh
		CALL	SetHook			;установить новый обработчик
;настройка прерываний INT0 и INT1
		cli
		lds	xl,EICRA
		ori	xl,0b00001111		;INT0 и INT1 - прерывание только по фронту сигналов
		sts	EICRA,xl
		in	xl,EIMSK
		ori	xl,0b00000011
		out	EIMSK,xl
		sei
;проверка начального состояния датчиков
		in	r25,PIND		;прочитать состояние дискретных входов
		andi	r25,$03
		cpi	r25,$02			;FULL=0, EMPTY=1
		brne	EXIT
		cli
		rcall	EMPTY
		sei
EXIT:		ret
;*****************************************
;обработчик прерывания INT0 (емкость наполнена)
FULL:		lds	zl,(FLSUPPLY_STATUS)
		or	zl,zl
		breq	FULL_EXIT		;выход, если все выключено
		dec	zl
		brne	FULL_1
;статус системы 1 - включен компрессор
		STATUS	5
		rjmp	FULL_EXIT_1
FULL_1:		dec	zl
		brne	FULL_2
;статус системы 2 - включены компрессор и питатель
		STATUS	4
		rjmp	FULL_EXIT_1
FULL_2:		dec	zl
		brne	FULL_EXIT
;статус системы 3 - все включено
		lds	zh,(SILO_SELECT)
		or	zh,zh
		breq	V_1_OFF
V_2_OFF:	cbi	PORTB,4			;выход 4 - вибратор 2
		rjmp	V_OFF
V_1_OFF:	cbi	PORTB,2			;выход 2 - вибратор 1
V_OFF:		STATUS	4
		DELAY	15*200
		rjmp	FULL_EXIT
FULL_EXIT_1:	DELAY	1
FULL_EXIT:	lds	zl,(INT0_HANDLER)	;адрес прежнего обработчика INT0
		lds	zh,(INT0_HANDLER+1)
		ijmp				;переход к прежнему обработчику
;*****************************************
;обработчик прерывания INT1 (емкость пуста)
EMPTY:		lds	zl,(FLSUPPLY_STATUS)
		or	zl,zl			;проверить статус	
		brne	EMPTY_EXIT		;запуск возможен только при статусе 0
;начать заполение емкости
		sbi	PORTB,0			;включить компрессор
		STATUS	1			;установить статус 1		
		DELAY	10*200			;установить паузу 10 сек
EMPTY_EXIT:	lds	zl,(INT1_HANDLER)	;адрес прежнего обработчика INT1
		lds	zh,(INT1_HANDLER+1)
		ijmp				;переход к прежнему обработчику
;*****************************************
;обработчик прерывания 200Hz
TIMER:
		lds	zl,(DELAY_TIME)
		lds	zh,(DELAY_TIME+1)
		or	zh,zl
		breq	TIMER_EXIT
		lds	zl,(DELAY_TIME)
		lds	zh,(DELAY_TIME+1)
		sbiw	zh:zl,1
		sts	(DELAY_TIME),zl
		sts	(DELAY_TIME+1),zh
		brne	TIMER_EXIT
		lds	zl,(FLSUPPLY_STATUS)	;проверить статус
		or	zl,zl
		breq	TIMER_EXIT		;если 0 - ничего не делать
;пауза отработала
		dec	zl
		breq	STATUS_1
		dec	zl
		breq	STATUS_2
		dec	zl
		breq	STATUS_3
		dec	zl
		breq	STATUS_4
		dec	zl
		breq	STATUS_5
;*****************************************
;идет подача муки
STATUS_3:
TIMER_EXIT:	lds	zl,(SYS_TIME_HANDLER)	;адрес прежнего обработчика INT1
		lds	zh,(SYS_TIME_HANDLER+1)
		ijmp
;*****************************************
;компрессор включен, по истечении паузы 10 с включить питатель
STATUS_1:	in	zh,PIND
		andi	zh,0b00000100
		sts	(SILO_SELECT),zh
		or	zh,zh
		breq	BATCHER_1_ON
BATCHER_2_ON:	sbi	PORTB,3			;выход 3 - питатель 2
		rjmp	BATCHER_ON
BATCHER_1_ON:	sbi	PORTB,1			;выход 1 - питатель 1
BATCHER_ON:	STATUS	2			;установить состояние 2
		DELAY	3*200			;установить паузу 3 секунды
		rjmp	TIMER_EXIT
;*****************************************
;компрессор и питатель включены, по истечении паузы 3 с включить вибратор
STATUS_2:	lds	zh,(SILO_SELECT)
		or	zh,zh
		breq	VIBRATOR_1_ON
VIBRATOR_2_ON:	sbi	PORTB,4			;выход 4 - вибратор 2
		rjmp	VIBRATOR_ON
VIBRATOR_1_ON:	sbi	PORTB,2			;выход 2 - вибратор 1
VIBRATOR_ON:	STATUS	3			;установить состояние 3
		rjmp	TIMER_EXIT
;*****************************************
;вибратор выключен, по истечении 15 с выключить питатель
STATUS_4:	lds	zh,(SILO_SELECT)
		or	zh,zh
		breq	BATCHER_1_OFF
BATCHER_2_OFF:	cbi	PORTB,3
		rjmp	BATCHER_OFF
BATCHER_1_OFF:	cbi	PORTB,1
BATCHER_OFF:	STATUS	5			;установить состояние 5
		DELAY	15*200			;установить паузу 15 с
		rjmp	TIMER_EXIT
;*****************************************
;питатель выключен, по истечении 15 с выключить компрессор
STATUS_5:	cbi	PORTB,0
		STATUS	0			;установить состояние 0
		rjmp	TIMER_EXIT
;*****************************************
		.DSEG
		.org	$4000

FLSUPPLY_STATUS:	.byte	1		;состояние системы подачи муки
SILO_SELECT:		.byte	1		;выбранный силос
MY_BASE:		.byte	2		;базовый адрес программы
INT0_HANDLER:		.byte	2
INT1_HANDLER:		.byte	2
SYS_TIME_HANDLER:	.byte	2
DELAY_TIME:		.byte	2
