;====================================================================
; Main.asm file generated by New Project wizard
;
; Created:   Чт дек 4 2014
; Processor: ATtiny2313
; Compiler:  AVRASM (Proteus)
;====================================================================

;====================================================================
; DEFINITIONS
;====================================================================

;====================================================================
; VARIABLES
;====================================================================

;====================================================================
; RESET and INTERRUPT VECTORS
;====================================================================

      ; Reset Vector
      

;====================================================================
; CODE SEGMENT
;====================================================================

;Start:
      ;*************************************************************************
;* Термостат на базе микроконтроллера AT90S2313 *
;* с использованием микросхемы термодатчика DS1620 *
;*************************************************************************
;*************************************************************************
;* Название:		Цифровой регулятор температуры
;* Объект: 		AVR микроконтроллер AT90S2313 и термостат DS1620 
;* 
;*
;*************************************************************************

.include "2313def.inc"

;***** Константы
.equ preset=192	;T/C0 Preset constant (256-64) 
.def result=r10	;Result and intermediate data
.def temp=r11	;временный регистр
.def temp1=r2	;временный регистр
.def temp2=r3	;временный регистр
.def temp3=r4	;временный регистр
.def ramsize=r5	;размер блока
.def tmode=r6	;Регистр режима
.def key=r20		;Регистр нажатой клавиши
.def keyc=r21	;Счетчик для прграммы обработки нажатия клавиши
.def	TMIN=r22	;ячейка с содержимым минимальной температуры термостата
.def	TMINL=r23	;младший
.def	TMINH=r24	;старший
.def	TMAX=r25	;ячейка с содержимым максимальной температуры термостата
.def	TMAXL=r7	;младший
.def	TMAXH=r8	;старший
.def	TNORM=r9	;ячейка с содержимым текущей температуры термостата
.def	TNORML=r12	;младший
.def	TNORMH=r13	;старший
.equ	DLCD=$66	;стартовый адрес SRAM для буфера индикатора
;маладшая ячейка соответствует левому символу
;на дисплее
.def fbinL =r15;двоичное значение, младший байт
.def fbinH =r16;двоичное значение, старший байт
;биты портов
.equ K1	=3	;бит первой кнопки
.equ K2	=4	;бит второй кнопки
.equ K3	=5	;бит третьей кнопки
.equ WR1	=5	;бит WR1
.equ WR2	=6	;бит WR2
.equ A0	=7	;бит A0
.equ DQ	=0	;бит DQ канал данных термостата
.equ CLK	=1	;бит CLK канал синхронизации данных

;*************************************************************************
;*
;* PROGRAM START - программа начинает выполняться с этого места
;*
;*************************************************************************
;.cseg

.org $0000
;rjmp  Start
rjmp hhh

RETI
RETI
RETI
RETI
RETI
RETI
RETI
RETI
RETI
RETI
.org $0020
;*************************************************************************
; настройка констант
SETCONST:
ldi	temp,20
mov	TMINL,temp
ldi	temp,0
mov	TMINH,temp
ldi	temp,25
mov	TMAXL,temp
ldi	temp,0
mov	TMAXH,temp
ret
;*************************************************************************
; передача констант
OUTCONST:
mov	temp,TMINl
mov	temp1,TMINH
ldi	temp2,2		;запись нижней температуры
rcall	TERMOUT2
mov	temp,TMAXL
mov	temp1,TMAXH
ldi	temp2,1		;запись нижней температуры
rcall	TERMOUT2
ldi	temp1,0xee	; инициализация термостата
rcall	TERMOUT1
ret	
;*************************************************************************
; Натройка портов ввода вывода
port_set:
ldi result,$ff	;PORTB настраивается на вывод
out DDRB,result	;для работы с индикатором
ldi result,$00	;все биты устанавливаются в ноль
out PORTB,result;PORTD настраивается для работы 
ldi result,0b01000011	; с клавиатурой и
out DDRD,result	;микросхемой термометра
ldi result,0b11111001	; с клавиатурой и
out PORTD,result	;микросхемой термометра
ret
;*************************************************************************
;*	очистка буфера ЖКИ
CLRLCD:
ldi	ramsize,10	;очистка буфера индикатора
ldi	temp,0
ldi	ZH,high(DLCD)
ldi	ZL,low(DLCD)
clrlcdloop:
st	Z+,temp
dec	ramsize
brne	clrlcdloop	;если не закончили повторить
rjmp	LCDOUT
;*************************************************************************
; Вывод содержимого буфера на индикатор
LCDOUT:
ldi	temp,low(DLCD)	;установить Z как указатель на буфер
mov	ZL,temp	;индикатора
ldi	temp,high(DLCD)
mov	ZH,temp
ldi	ramsize,10
LCDOUT1:
mov	temp,ramsize	;запись в индикатор адреса символа
andi	temp,0b00001111
out	PORTB,temp
cbi	PORTB,A0
sbi	PORTB,WR1
cbi	PORTB,WR1

ld	temp1,Z+	; получить байт из DLCD
mov	temp,temp1
andi	temp,0b00001111	;получить младшую тетраду
sbrs	temp,A0
out	PORTB,temp
sbi	PORTB,WR1
cbi	PORTB,WR1

mov	temp,temp1
swap	temp
andi	temp,0b00001111	;получить старшую тетраду
sbrs	temp,A0
out	PORTB,temp
sbi	PORTB,WR1
cbi	PORTB,WR1
dec	ramsize		;
brne	LCDOUT1		;если не закончили повторить
ret
;*************************************************************************
;*	вывод готовой строки в буфер и вывод буфера на ЖКИ
;* temp - номер строки
;* ramsize - количество выводимых символов
STRLCDD:
ldi	YH,high(tcstr)
ldi	YL,low(tcstr)
add	temp,temp
add	temp,temp
add	YL,temp
ldi	ramsize,4
;*************************************************************************
;*	вывод готовой строки в буфер и вывод буфера на ЖКИ
;* Y - указатель на строку temp - положение 
;* ramsize - количество выводимых символов
STRLCD:
ldi	ZH,high(DLCD)
ldi	ZL,low(DLCD)
strtolcdloop:
ld	temp,Y+
st	Z+,temp
dec	ramsize
brne	strtolcdloop	;если не закончили повторить
rjmp	LCDOUT
;*************************************************************************
;* получение данных из термостата
;* temp2 - команда temp - первые 8 бит temp1 - 9-ый бит
TERMIN:
ldi	ramsize,8
terminloop:
sbi	PIND,DQ
sbrc	temp2,0
cbi	PIND,DQ
sbi	PIND,CLK
cbi	PIND,CLK
ror	temp2
dec	ramsize
brne	terminloop		;если не закончили повторить
ldi	ramsize,0x8
sbi	DDRD,DQ
termindloop:
sbi	PIND,DQ
sbrc	temp,0
cbi	PIND,DQ
sbi	PIND,CLK
cbi	PIND,CLK
ror	temp2
dec	ramsize
brne	termindloop		;если не закончили повторить
sbi	PIND,DQ
sbrc	temp1,0
cbi	PIND,DQ
sbi	PIND,CLK
cbi	PIND,CLK
cbi	DDRD,DQ
ret

;*************************************************************************
;*	передача одного байта данных на термостат
;* temp2 - команда 
TERMOUT1:
ldi	ramsize,8
termout1loop:
sbi	PIND,DQ
sbrc	temp2,0
cbi	PIND,DQ
sbi	PIND,CLK
cbi	PIND,CLK
ror	temp2
dec	ramsize
brne	termout1loop		;если не закончили повторить
ldi	ramsize,0x8
ret
;*************************************************************************
;*	передача одного байта данных на термостат и 9 бит
;* temp2 - команда temp - первые 8 бит temp1 - 9-ый бит
TERMOUT2:
ldi	ramsize,8
termout2loop:
sbi	PIND,DQ
sbrc	temp2,0
cbi	PIND,DQ
sbi	PIND,CLK
cbi	PIND,CLK
ror	temp2
dec	ramsize
brne	termout2loop		;если не закончили повторить
ldi	ramsize,0x8
termout2loopdat:
clc
sbi	PIND,CLK
sbic	PIND,DQ
sec
cbi	PIND,CLK
ror	temp2
dec	ramsize
brne	termout2loopdat		;если не закончили повторить
ldi	temp1,0
sbi	PIND,CLK
sbic	PIND,DQ
ldi	temp1,1
cbi	PIND,CLK
cbi	DDRD,DQ
ret
;*************************************************************************
;*	получение кода нажатой клавиши если она нажата более 20 мс
;* код кнопки находится в регистре key если сброшен бит Z
KEYPRESS:
ldi	temp1,20	;количество попыток для гашения
;дребезга контактов
keyloop:
in	temp,PIND
andi	temp,0b00111000
breq	keynopress
sbic	PIND,K1
ldi	key,1
sbic	PIND,K2
ldi	key,2
sbic	PIND,K3
ldi	key,3
dec	temp1
brne	keyloop		;если не закончили повторить
keynopress:
and	key,key
ret

;*************************************************************************
;*	ожидание отпускания клавиши
KEYUP:
ldi	temp1,20	;количество попыток для гашения
;дребезга контактов
keyuloop:
in	temp,PIND
andi	temp,0b001110000
breq	unpress
dec	temp1
brne	KEYUP		;если не закончили повторить
unpress:
and	key,key
ret

;*************************************************************************
; программа переводит температуру в зависимости от режима
; и выводит на индикатор для индикации
; calckterm
outTmax:
mov	fbinL,TMAXL
mov	fbinH,TMAXH
rjmp	outterm
outTmin:
mov	fbinL,TMAXL
mov	fbinH,TMAXH
rjmp	outterm
calckterm:
mov	temp,tmode
rcall	STRLCD
mov	fbinL,TNORML
mov	fbinH,TNORMH
cpi	tmode,1
breq	outTmin
cpi	tmode,2	
breq	outTmax
ldi	temp,0xb
outterm:
ldi	ZH,high(DLCD+5)
ldi	ZL,low(DLCD+5)
ldi	temp2,0xb
sbrs	fbinH,0		
ldi	temp2,0x10
;		ldi	temp3,0
;		sub	temp3,temp2
;		ror	temp3
st	Z+,temp2
inc	ZL
inc	ZL
ldi	temp2,5
sbrs	fbinL,0
ldi	temp2,0
st	Z+,temp2
ldi	fbinH,0
clc
ror	fbinL
rcall	bin16BCD5
mov	temp3,fbinH
mov	temp2,fbinL
swap	temp2
andi	temp3,0xf
andi	temp2,0xf
andi	temp,0xf
rcall	getcod
mov	temp1,temp
set
bst	temp1,4
mov	temp,temp2
rcall	getcod
mov	temp2,temp
mov	temp,temp3
rcall	getcod
mov	temp3,temp
ldi	ZH,high(DLCD+6)
ldi	ZL,low(DLCD+6)
st	Z+,temp3
st	Z+,temp2
st	Z+,temp1
rcall	LCDOUT
;*************************************************************************
; программа возвращает код символа для индикатора
; значение temp заменяется на значение необходимое для отображения на 
; индикаторе и оно помещается назад в ячейку temp	
getcod:
ldi	ZH,high(LCDCG*2)
ldi	ZL,low(LCDCG*2);init Z-pointer
add	ZL,temp
lpm			;get constant
mov	temp,r0
ret
;*************************************************************************
; данные для отображения на индикаторе
LCDCG:			;тип		код
.DB 0xEE		;число 	0
.DB 0x60		;число 	1	
.DB 0x2F		;число 	2
.DB 0x6D		;число 	3
.DB 0xE1		;число 	4
.DB 0xCD		;число 	5
.DB 0xCF		;число 	6
.DB 0x68		;число 	7
.DB 0xEF		;число 	8
.DB 0xED		;число 	9
.DB 0x10		;символ. 	a
.DB 0x01		;символ - 	b
.DB 0x87		;символ t c
.DB 0x46		;символ u d
.DB 0x67		;символ d e
.DB 0x07		;символ c f
.DB 0x00		;символ blanck 10	 пустой символ
;строка tc-
tcstr:
.DB 0x0c,0x0f,0x0b,0x10
;строка tu-
tustr:
.DB 0x0c,0x0d,0x0b,0x10
;cтрока td-
tdstr:
.DB 0x0c,0x0e,0x0b,0x10
;*************************************************************************
;*
;* PROGRAM RESET - главная программа
;*
;*************************************************************************

hhh:
ldi	temp,low(RAMEND)
out	SPL,temp	; настройка стека на верх памяти данных
rcall port_set	; настроить порты
rcall	CLRLCD
;*************************************************************************
;*
;* mainloop - главный цикл программы
;*
;*************************************************************************
mainloop:
ldi	temp1,250
mov	r5,temp1
mainloop1:
rcall	KEYPRESS	;определения нажатия кнопки
brne	keyis		; переход если хотябы одна кнопка нажата
rjmp	returnin	;возврат к основному цыклу
keyis:
ldi	temp1,250
mov	r5,temp1
cpi	temp,1
rcall	key1press
cpi	temp,2
rcall	key2press
cpi	temp,3
rcall	key3press
returnin:
ldi	temp1,0xaa	; чтениее текущей температуры термостата
rcall	TERMIN
ldi	temp2,0xaa	; инициализация термостата
rcall	TERMIN
mov	TNORML,temp
mov	TNORMH,temp1
rcall	calckterm	; расчет температуры
dec	r5
brne	mainloop1	; после ожиданжжия в течении минуты
ldi	tmode,0	; возвратиться в основной режим
rjmp	mainloop
;*************************************************************************
;* обработка клавиши режима
key1press:
and	tmode,tmode
brne	k1setmax
dec	tmode
rjmp	keyret
k1setmax:
ldi	temp,2
mov	tmode,temp
keyret:
rcall	calckterm
rjmp	KEYUP
;*************************************************************************
;* обработка клавиши изменения значения вверх
key2press:	
cpi	tmode,1
brne	key2min
cpi	tmode,2
brne	key2max
rjmp	keyret
key2min:
sbrs	TMINH,0
rjmp	key2minm
inc	TMINL
brmi	key2mins
rjmp	keyret
key2mins:
ldi	TMINH,0
rjmp	keyret
key2minm:
cpi	TMINL,0xfa
brmi	keyret
inc	TMINL
rjmp	keyret
key2max:
sbrs	TMAXH,0
rjmp	key2maxm
inc	TMINL
brmi	key2maxs
rjmp	keyret
key2maxs:
ldi	TMAXH,0
rjmp	keyret
key2maxm:
cpi	TMAXL,0xfa
brmi	keyret
inc	TMAXL
rjmp	keyret

;*************************************************************************
;* обработка клавиши изменения значения вниз
key3press:	
cpi	tmode,1
brne	key3min
cpi	tmode,2
brne	key3max
rjmp	keyret
key3min:
sbrc	TMINH,0
rjmp	key3minm
dec	TMINL
brmi	key3mins
rjmp	keyret
key3mins:
ldi	TMINH,1
rjmp	keyret
key3minm:
cpi	TMINL,0x92
brmi	keyret
dec	TMINL
rjmp	keyret
key3max:
sbrc	TMAXH,0
rjmp	key3maxm
dec	TMAXL
brmi	key3maxs
rjmp	keyret
key3maxs:
ldi	TMAXH,1
rjmp	keyret
key3maxm:
cpi	TMAXL,0x92
brmi	keyret
dec	TMAXL
rjmp	keyret

;*************************************************************************
;1. Текст программы "bin16BCD5"- преобразование 16-битного двоичного
;значения в упакованный BCD формат
;*************************************************************************
;* Количество слов кода:25 + возврат
;* Количество циклов:25/176 (Мин/Макс) + возврат
;* Использованные младшие регистры:нет
;* Использованные старшие регистры:4(fbinL,fbinH/tBCD0,tBCD1,tBCD2)
;* Использованные указатели:нет
;*************************************************************************
;***** Регистровые переменные подпрограммы
;.def fbinL =r15;двоичное значение, младший байт
;.def fbinH =r16;двоичное значение, старший байт
.def tBCD0 =r17;BCD значение, цифры 1 и 0
.def tBCD1 =r18;BCD значение, цифры 3 и 2
.def tBCD2 =r19;BCD значение, цифра 4
;Примечание: Переменные fbinH и tBCD0 должны размещаться в одном
;регистре.
;***** Код
;*************************************************************************
bin16BCD5:
ldi tBCD2, -1
bin16BCD5_loop_1:
inc tBCD2
subi fbinL, low(10000)
sbci fbinH, high(10000)
brsh bin16BCD5_loop_1
subi fbinL, low(-10000)
sbci fbinH, high(-10000)
ldi tBCD1, -0x11
bin16BCD5_loop_2:
subi tBCD1, -0x10
subi fbinL, low(1000)
sbci fbinH, high(1000)
brsh bin16BCD5_loop_2
subi fbinL, low(-1000)
sbci fbinH, high(-1000)
bin16BCD5_loop_3:
inc tBCD1
subi fbinL, low(100)
sbci fbinH, high(100)
brsh bin16BCD5_loop_3
subi fbinL, -100
ldi tBCD0, -0x10
bin16BCD5_loop_4:
subi tBCD0, -0x10
subi fbinL, 10
brsh bin16BCD5_loop_4
subi fbinL, -10
add tBCD0, fbinL
ret
;*************************************************************************

Loop:
      rjmp  Loop

;====================================================================
