Код: Выделить всё
SPL = 0x3d
SPH = 0x3e
SREG = 0x3f
PORTD = 0x12
DDRD = 0x11
PIND = 0x10
SLPORT = PORTD
SLPIN = PIND
SLDDR = DDRD
SLBIT = 0
.globl w1sInit
.globl w1sTry
.section .text
;void w1sInit();
w1sInit:
; Бит на вход с резитором.
cbi SLDDR, SLBIT
sbi SLPORT, SLBIT
ret
; r2 - состояние. 0 - сток (игнорировать всё), 1 - начало (чтение команды), 2 - передача кода, 0xff - допуск.
; r3 - осталось битов
; r4 - команда (0) или остаток байт (2)
; Y - текущий байт кода.
auotomatonReset:
ldi r18, 1
mov r2, r18
ldi r18, 8
mov r3, r18
eor r4, r4
push r28
push r29
ldi r18, 8
1: lpm r0, z+
st y+, r0
dec r18
brne 1b
pop r29
pop r28
ret
auotomatonBit:
tst r2 ; 1
breq 9f ; 1
mov r18, r2
cpi r18, 0xff
breq 255f
dec r2 ; 1
brne 2f ; 1
inc r2 ; 1
; чтение команды
; Ждать 15 мкс
ldi r24, 27 ; 1
ldi r25, 0 ; 1
rcall cwait ; 112
;120 считать бит
in r0, SLPIN ; 1
bst r0, SLBIT ; 1
lsr r4 ; 1
bld r4, 7 ; 1
dec r3 ; 1
breq fullcmd ; 1
; если не все биты считаны
;480 выйти
ldi r24, 88 ;1
ldi r25, 0 ; 1
rcall cwait ; ~360
ret
fullcmd: ; 1
mov r18, r4 ; 1
cpi r18, 0x33 ; 1
brne 9f ; 1
; если всё биты считаны и если команда == 0x33
; перейти в состояние 2
inc r2 ; 1
ldi r18, 8 ; 1
mov r4, r18 ; 1
mov r3, r18 ; 1
;480 выйти
ldi r24, 85 ;1
ldi r25, 0 ; 1
rcall cwait ; ~360
ret
2: inc r2 ; 1
; Взять текущий бит
ld r18, Y
andi r18, 1
brne one
; Бит на выход и передать ноль.
sbi SLDDR, SLBIT
cbi SLPORT, SLBIT
one: ; ждать 60 мкс (480)
ldi r24, 120
ldi r25, 0
rcall cwait
; Бит на вход
cbi SLDDR, SLBIT
sbi SLPORT, SLBIT
; Следующий бит
dec r3
brne set
; Следующий байт
ldi r18, 8
mov r3, r18
adiw r28, 1
dec r4
; готово
breq 255f
ret
set: ld r18, Y
lsr r18
st Y, r18
ret
; перейти в состояние 0
9: eor r2, r2
ret
255: eor r2, r2
dec r2
ret
; unsigned int w1sTry(unsigned int pgm_addr);
w1sTry:
push r2
push r3
push r4
push r28
push r29
; прерываний нет
in r28, SPL
in r29, SPH
sbiw r28, 8
out SPL, r28
out SPH, r29
adiw r28, 1
mov r30, r24
mov r31, r25
sbi SLPORT, SLBIT
; Если на входе 1, вернуть 1
sbic SLPIN, SLBIT
rjmp 11f
; Если ноль, ждать единицы.
reset:
rcall auotomatonReset
1: sbis SLPIN, SLBIT
rjmp 1b
; Ждать ~40 мкс (~320)
ldi r25, hi8(80)
ldi r24, lo8(80)
rcall cwait
; Выдать ноль и ждать 150-200 мкс (~1500)
sbi SLDDR, SLBIT
cbi SLPORT, SLBIT
ldi r25, hi8(325)
ldi r24, lo8(325)
rcall cwait
; r23::r20 - счетчик. Время порядка 0,5 с (2^19 * 8 = 2^22 тактов).
3: ldi r20, 0
ldi r21, 0
ldi r22, 8
ldi r23, 0
; Бит на вход.
cbi SLDDR, SLBIT
sbi SLPORT, SLBIT
; Ждать нуля
1: subi r20, 1 ; 1
sbci r21, 0 ; 1
sbci r22, 0 ; 1
sbci r23, 0 ; 1
brcs 12f ; 1 слишком долго
sbic SLPIN, SLBIT ; 1
rjmp 1b ; 2
; Ноль.
rcall auotomatonBit
mov r18, r2
cpi r18, 0xff
; конец связи
breq 3f
cpi r18, 0
; неправильно что-то
breq 13f
rjmp 3b
3: eor r24, r24
eor r25, r25
rjmp 100f
11: eor r25, r25
ldi r24, 1
rjmp 100f
12: eor r25, r25
ldi r24, 2
rjmp 100f
13: eor r25, r25
ldi r24, 3
; прерываний нет
100: in r28, SPL
in r29, SPH
adiw r28, 8
out SPL, r28
out SPH, r29
pop r29
pop r28
pop r3
pop r4
pop r2
ret


