;**** Программная реализация SPI для микроконтроллера AT90S1200 **********
;*
;* Интерфейс SPI реализуется программно для подключения АЦП TLV1572.
;*
;* Тактовая частота микроконтроллеров AVR: 4 МГц (стандарт STK200)
;* 
;***************************************************************************
.nolist
.include "1200def.inc"
.list

.equ	sck	= PD2	; Shift-Clock = порт D / разряд 2
.equ	nss	= PD3	; /SS = порт D / разряд 3
.equ	mosi	= PD4	; MOSI = порт D / разряд 4
.equ	miso	= PD5	; MISO = порт D / разряд 5

.def	spi_lo	= r14	; Младший байт результата АЦ преобразования
.def	spi_hi	= r15	; Старший байт результата АЦ преобразования
.def	temp	= r16	; Рабочий регистр

Reset:
rjmp  Init_SPI

Read_Write_SPI:		; Запись/чтение 16 бит через SPI
cbi   PortD,nss	; /CS АЦП 1572 = активный (лог. 0)
ldi   temp,16		; Инициализируем счетчик цикла числом 16
spi_loop:
lsl   spi_lo		; Сдвиг влево млад. байта, D0=лог.0, D7->C
rol   spi_hi		; Сдвиг влево старш. байта, C->D8, D15->C
brcc  low_mosi	; Переход, если выводимый бит = лог. 0
sbi   PortD,mosi	; MOSI = лог. 1
rjmp  sck_high	; На этом завершается высокий уровень SCK
low_mosi:
cbi   PortD,mosi	; MOSI = лог. 0
nop	; Задержка, пока бит не станет стабильным
sck_high:
sbi   PortD,sck	; Нарастающий фронт SCK 
nop	; Задержка
sck_low:
cbi   PortD,sck	; Ниспадающий фронт SCK
nop	; Теперь бит данных на входе MISO стабилен
sbic  PinD,miso	; Пропускаем следующую команду, если бит MISO = лог. 0
inc   spi_lo	; Когда D0=0 (lsl), устан. "inc spi_lo" D0
dec   temp	; Счетчик цикла – 1
brne  spi_loop	; Следующий бит, если temp не равно 0
sbi   PortD,mosi	; MOSI переходит в состояние покоя (лог.1)
sbi   PortD,nss	; /SS = неактивный (лог. 1)
ret

Auswertung:			; Вывод результата
lsr   spi_hi	; Сдвиг вправо старшего байта, D15 = лог.0, D8->C
ror   spi_lo	; Сдвиг вправо младш. байта, C->D7, D0->C
cbi   PortD,6	; Младший разряд результата – в порт D, разряд 6 = 0
brcc  Auswert1	; Переход, если младший разряд действительно = лог. 0
sbi   PortD,6	; Младший разряд результата – в порт D, разряд 6 = 1
Auswert1:
out   DDRB,spi_lo	; Разряды 1...8 результата – в порт B
lsr   spi_hi	; Сдвиг вправо старшего байта, D15 = лог. 0, MSB->C
cbi   PortD,0	; Старший разряд результата – в порт D, разряд 0 = 0
brcc  Auswert2	; Переход, если старший разряд действительно = лог. 0
sbi   PortD,0	; Старший разряд результата – в порт D, разряд 0 = 1
Auswert2:
ret

Init_SPI:	; CPHA = 1, CPOL = 0
ldi   temp,$00	; Все разряды = 0
out   PortB,temp	; Все выводы порта B – низкий уровень
out   DDRB,temp	; Выводы драйвера B – все высокоомные
ldi   temp,$38	; Разряды 3...5 = 1, остальные = 0
out   PortD,temp	; /SS,MOSI,MISO = лог.1, SCK,ост. = лог.0
ldi   temp,$DF	; Разряд 5 = 0, остальные = 1
out   DDRD,temp	; PD5 (MISO) = вход, остальные = выходы
Haupt:
ldi   temp,$65	; Условно для выводимого слова
mov   spi_lo,temp	; Инициализируем млад. байт вых. регистра
mov   spi_hi,temp	; Инициализируем старш. байт вых. регистра
rcall Read_Write_SPI	; Ввод/вывод 16 бит через SPI
rcall Auswertung	; Обрабатываем результат АЦ преобразования
rjmp  Haupt

