;*************************************************************************
; FILE ..........: FMS_cbl.PIC
; AUTHOR ........: Vitaly Puzrin
; DESCRIPTION ...: Firmware for FMR interface cable
; NOTES .........:
; COPYRIGHT .....: Vitaly Puzrin, 2000    http://www.rcdesign.ru
; HISTORY .......: DATE		COMMENT
;                  ---------------------------------------------------
;                  25.11.2000	First version.
;*************************************************************************



	list p=12c508, f=inhx8m

	IFDEF	__12C508

#include	<p12c508.inc>
#define		TxBit	GPIO, 0		; Выход данных
#define		RAM_START	H'07'

	__CONFIG 	_MCLRE_OFF & _CP_ON & _WDT_ON & _WDT_ON & _IntRC_OSC

	ELSE

#include	<p16c84.inc>
#define		TxBit	PORTB, 2	; Выход данных
#define		RAM_START	H'0C'

	__CONFIG 	_CP_ON & _PWRTE_ON & _WDT_ON & _XT_OSC

	ENDIF

BAUD_1  	equ	D'15'		; 3 + 5 +3X = CLKOUT/Baud
BAUD_X  	equ	D'12'		; 11 + 5 + 3X = CLKOUT/Baud

;------------------------------------
; Регистровые переменные
;
	CBLOCK	RAM_START
		PktCnt		; счетчик байт в пакете
		TxData		; данные для передачи
		BitCnt		; считчик бит при передаче байта
		TimeCnt		; счетчик длительности импульса
		DelCnt		; счетчик задержки

		PktStart	; начало пакета данных
	ENDC

	org	0

;------------------------------------
; После сброса (HARDWARE или WDT)
; всегда шлем все FF
;
Reset:

	IFDEF	__12C508

	movwf	OSCCAL		; калибруем тактовый генератор

	ENDIF

	clrwdt
	movlw	B'00111010'	; таймер переключается по RA4
				; переключение по заднему фронту сигнала
				; предделитель подключен к WDT
				; период WDT - 20 * 4 мс
	option

	IFDEF	__12C508

	movlw	0FFh		; Настраиваем порты ввода-вывода
	movwf	GPIO
	bsf	TxBit
	movlw	B'00011110'	; весь GPIO на ввод, кроме GP0
	tris	GPIO

	ELSE

	movlw	0FFh		; Настраиваем порты ввода-вывода
	movwf	PORTA
	movwf	PORTB
	bsf	TxBit
	movlw	B'00010000'	; весь PORTA кроме PA4 на вывод
	tris	PORTA
	movlw	B'00000000'	; весь PORTB на вывод
	tris	PORTB

	ENDIF

	clrwdt			; Если сигнала нет, то будем иногда
				; сбрасываться и слать пустой пакет

	clrf	TMR0		; Подготавливаем таймер к переполнению

	clrf	PktCnt
	goto	send_pkt	; Шлем пустой пакет.
				;


;------------------------------------
;------------------------------------
; Ждем первый фронт.
; (!) При самом первом включение
; можем попасть не на начало пакета.
; Потом все синхронизируется по
; первой же паузе.
;
wait_first_front:
	movf	TMR0, W			; Ждем импульса на входе таймера
	btfsc	STATUS, Z
	goto	wait_first_front
;
	nop		; Выравниваем время измерения
	nop		; для первого канала
	nop		;
	nop		;
	nop		;
	nop		;

;------------------------------------
; Принимаем данные о 4-ех каналах.
; Если раньше времени наступает пауза,
; то передаем все FF
;
measure_channel:
;
	clrf	TMR0
	clrwdt

	movlw	D'143'				; Задержка на 715 мкс,
	movwf	DelCnt
DelLp:
	nop
	nop
	decfsz	DelCnt, F
	goto	DelLp

	nop
	nop

;
; Замеряем время до следующего импульса
;
	movlw	0FFh			; Подготавливаем
	movwf	TimeCnt			; счетчик времени
wait_front_loop:
	movf	TMR0, W			; Дискретность измерения -
	btfss	STATUS, Z		; 7 микросекунд.
	goto	save_measurement
	decfsz	TimeCnt, F		; Если пауза слишком большая
	goto	wait_front_loop		; (счетчик переполнился) то
					; начинаем искать данные
					; с самого начала
	goto	send_pkt

;------------------------------------
; Записываем измерянное значение
; длительности импульса
;
save_measurement:
	clrf	TMR0
	comf	TimeCnt, W		; (!) Инвертируем результат,
	movwf	INDF			; так как считали в обратном порядке
	incf	FSR, F
	incf	PktCnt,F
	goto	measure_channel

;------------------------------------
; Итак, тайм-аут. Конец фрейма
; нужно отправить пакет
;
send_pkt:
	movlw	PktStart
	movwf	FSR

	clrf	TxData
	decf	TxData,F
	call	tx_byte			; Отправляем заголовок пакета

	movlw	PktStart
	movwf	FSR

	movf	PktCnt, W
	btfsc	STATUS, Z
	goto	skip_data

pkt_loop:
	movf	INDF, W
	movwf	TxData
	call    tx_byte
	incf	FSR, F
	decfsz	PktCnt, F
	goto	pkt_loop

skip_data:

	clrf	PktCnt
	movlw	PktStart                ; (начиная с первого)
	movwf	FSR

	clrf	TMR0			; Подготавливаем таймер
					; к переполнению
	goto	wait_first_front	; Переходим к ожиданию
					; первого имепульса

;------------------------------------
;------------------------------------
; Передача 1 байта по последовательному
; интерфейсу. Скорость 19200 бод.
; Формат байта - 81N
;
tx_byte:
	movlw	8
	movwf	BitCnt
;
	bcf	TxBit			; Шлем старт-бит
	call	Delay1
tx_next_bit:
	bcf	STATUS,C
;
	rrf	TxData,F
;
	btfsc	STATUS,C
	bsf	TxBit
	btfss	STATUS,C
	bcf	TxBit
	call	DelayX
	decfsz	BitCnt,F
	goto	tx_next_bit
	bsf	TxBit		; Send Stop Bit
	call    Delay1
;
	retlw	0
;
; Задержки при передаче битов данных
;
DelayX  movlw   BAUD_X
	goto    save

Delay1  movlw   BAUD_1            ; 52 uS мкс на 19200 бод
	goto    save

save    movwf   DelCnt
redo_1  decfsz  DelCnt,F
	goto    redo_1

	retlw   0

	end
