📄 lanc_if.asm
字号:
;=============================================================================
; (C) 1999 by Helge Wagner
;
; FILE: LANC_IF.ASM
;
; DESC: Sony LANC Protocol low level interface
;
; BY: H.Wagner, mailto:<H.Wagner@sbs-or.de>
; DATE: 04.03.1999
;
; NOTE: Tab width=4
;=============================================================================
; Rev Date Author Description
;-----------------------------------------------------------------------------
; 1.01 08.12.1999 H.Wagner -Changed to easy adapt to other interfaces.
;=============================================================================
.MODEL SMALL,SYSCALL
PAGE 60,132
TITLE LANC_IF.ASM
OPTION PROC:private
.nolist
include lanc_if.inc
include lanc_if.inp
.list
;IRDEO_LANC_INTERFACE EQU
PARPORT_LANC_INTERFACE EQU
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;%
;% MAIN MODULE
;%
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; this is for IRdeo
IFDEF IRDEO_LANC_INTERFACE
SEND_PORT TEXTEQU <ser_port_lcr>
RECEIVE_PORT TEXTEQU <ser_port_msr>
SEND_HIGH EQU 01000011b
SEND_LOW EQU 00000011b
RECV_MASK EQU 10h
RECV_HIGH EQU 10h
RECV_LOW EQU 00h
ENDIF ;IFDEF IRDEO_LANC_INTERFACE
; this is for the parallel port LANC (Pins 15,17,18)
IFDEF PARPORT_LANC_INTERFACE
SEND_PORT TEXTEQU <par_port_controlreg>
RECEIVE_PORT TEXTEQU <par_port_statusreg>
SEND_HIGH EQU 00h
SEND_LOW EQU 08h
RECV_MASK EQU 08h
RECV_HIGH EQU 00h
RECV_LOW EQU 08h
ENDIF ;IFDEF PARPORT_LANC_INTERFACE
SET_DS MACRO
push ax
mov ax, cs:ds_reg
.if (ax == 0)
pop ax
mov al, E__LANC_NOT_INITIALIZED
ret
.endif
mov ds, ax
pop ax
ENDM
PRG_DATA_SEGM SEGMENT PARA PUBLIC 'DATA' USE16
; program state variables
calibrated byte 0
opened byte 0
; LANC variables
lanc_channel byte -1 ; -1=not specified yet, 0-2 on IRdeo for X1(=0), X2(=1) and X3(=2)
; serial port variables
com_port byte -1 ; -1=not specified yet, 0=COM1, 1=COM2, 2=COM3, 3=COM4
IFDEF IRDEO_LANC_INTERFACE
ser_port_addr word ?
ser_port_lcr word ?
ser_port_mcr word ?
ser_port_msr word ?
ENDIF ;IFDEF IRDEO_LANC_INTERFACE
IFDEF PARPORT_LANC_INTERFACE
; parallel port variables
par_port_addr word ?
par_port_statusreg word ?
par_port_controlreg word ?
ENDIF ;IFDEF PARPORT_LANC_INTERFACE
; receive data variables
recv_data byte 16 dup (?)
bytes_recvd byte 0 ; bytes in recv_data - buffer
send_byte_recvd byte 0 ; bytes received from the send_byte function
;calibration values
loops_per_bit dword ?
loops_per_halfbit dword ?
PRG_DATA_SEGM ENDS
CONST SEGMENT PARA USE16 PUBLIC 'CODE'
com1_string byte "/COM1", 0
com2_string byte "/COM2", 0
com3_string byte "/COM3", 0
com4_string byte "/COM4", 0
x1_string byte "/X1", 0
x2_string byte "/X2", 0
x3_string byte "/X3", 0
CONST ENDS
CODEVAR SEGMENT PARA USE16 PUBLIC 'CODE'
ds_reg word 0
CODEVAR ENDS
CODEGROUP GROUP CONST, CODEVAR, MYCODE
MYCODE SEGMENT PARA PUBLIC 'CODE' USE16
.386p
assume ds:PRG_DATA_SEGM
IODELAY MACRO
out 0E1h, ax
ENDM
;in: ecx=microseconds to wait
;out: nothing
delay proc uses ax ecx
.repeat
.repeat ; wait for 1->0 transition
in al, 61h
IODELAY
.until !(al & 00010000b)
.repeat ; wait for 0->1 transition
in al, 61h
IODELAY
.until (al & 00010000b)
sub ecx, 30
.until (carry?)
ret
delay endp
;IN: BL Value to compare with.
; BH Mask to apply to value read from port.
; ECX Amount of time to wait (in ticks at 14,318/12 MHz)
; DX Port to read from.
;OUT: carry set Timeout
; carry clear Read OK
wait_port_ticks proc uses ax ecx
.repeat
in al, dx
and al, bh
.break .if (al == bl)
.repeat ; wait for 1->0 transition
in al, 61h
IODELAY
.until !(al & 00010000b)
.repeat ; wait for 0->1 transition
in al, 61h
IODELAY
.until (al & 00010000b)
sub ecx, 2*18
.until (carry?)
ret
wait_port_ticks endp
;in: ecx loops to perform
;out: nothing
loop_delay proc uses ecx
inc ecx
.repeat
dec ecx
.until (ecx == 0)
ret
loop_delay endp
;in: nothing
;out: nothing
init_comport proc uses ax dx
; get serial port address from com port number
push es
push bx
mov ax, 40h
mov es, ax
IFDEF IRDEO_LANC_INTERFACE
movzx bx, com_port
.if (bx > 3) ; must be 0-3 for COM1-COM4
pop bx
pop es
ret
.endif
shl bx, 1
mov ax, es:[bx]
mov ser_port_addr, ax
ENDIF ;IFDEF IRDEO_LANC_INTERFACE
; this is for the parallel port LANC (Pins 15,17,18)
IFDEF PARPORT_LANC_INTERFACE
mov bx, 8
mov ax, es:[bx]
mov par_port_addr, ax
inc ax
mov par_port_statusreg, ax
inc ax
mov par_port_controlreg, ax
ENDIF ;IFDEF PARPORT_LANC_INTERFACE
pop bx
pop es
IFDEF IRDEO_LANC_INTERFACE
mov ax, ser_port_addr
mov bx, LCR
add bx, ax
mov ser_port_lcr, bx
mov bx, MCR
add bx, ax
mov ser_port_mcr, bx
mov bx, MSR
add bx, ax
mov ser_port_msr, bx
mov dx, ser_port_mcr
mov al, 1 ; LANC-channel X0 on IRdeo
out dx, al
ENDIF ;IFDEF IRDEO_LANC_INTERFACE
mov dx, SEND_PORT
mov al, SEND_LOW
out dx, al
ret
init_comport endp
;in: al byte to send
;out: al byte received
byte_out proc uses bx ecx dx si
push ax
mov ah, al
xor bx, bx
mov si, 9 ; 8 bits per byte + stop bit
mov ecx, loops_per_halfbit
; wait for startbit to occur
mov dx, RECEIVE_PORT
.repeat
in al, dx
and al, RECV_MASK
.until (al == RECV_HIGH)
; send out bit per bit
mov dx, SEND_PORT
.repeat
;;
;;ecx is still loaded:
;;
;; mov ecx, loops_per_halfbit
call loop_delay
; receive the bit
mov dx, RECEIVE_PORT
in al, dx
and al, RECV_MASK
shr bx, 1
.if (al == RECV_HIGH)
or bx, 80h
.endif
call loop_delay
.if (ah & 1)
mov al, SEND_HIGH ; send logical high
.else
mov al, SEND_LOW ; send logical low
.endif
mov dx, SEND_PORT
out dx, al
shr ah, 1
dec si
.until (si == 0)
call loop_delay
pop ax
mov al, bl
ret
byte_out endp
comment ~
;in: al byte to send
;out: nothing
byte_out proc uses ax ecx dx si
mov ah, al
mov si, 9 ; 8 bits per byte + stop bit
mov ecx, loops_per_bit
; wait for startbit to occur
mov dx, RECEIVE_PORT
.repeat
in al, dx
and al, RECV_MASK
.until (al == RECV_HIGH)
; send out bit per bit
mov dx, SEND_PORT
.repeat
;;
;;ecx is still loaded:
;;
;; mov ecx, loops_per_bit
call loop_delay
.if (ah & 1)
mov al, SEND_HIGH ; send logical high
.else
mov al, SEND_LOW ; send logical low
.endif
out dx, al
shr ah, 1
dec si
.until (si == 0)
ret
byte_out endp
endcomment ~
;in: nothing
;out: al received byte
; ebx time to start receiving
byte_in proc uses ecx dx si
; wait for startbit to occur
xor ebx, ebx
mov dx, RECEIVE_PORT
.repeat
in al, dx
and al, RECV_MASK
inc ebx
.until (al == RECV_HIGH)
mov ecx, loops_per_halfbit
call loop_delay
mov ecx, loops_per_bit
mov si, 8 ; 8 bits per byte
; receive bit per bit
xor ah, ah
mov dx, RECEIVE_PORT
.repeat
;;
;;ecx is still loaded:
;;
;; mov ecx, loops_per_bit
call loop_delay
in al, dx
and al, RECV_MASK
shr ah, 1
.if (al == RECV_HIGH)
or ah, 80h
.endif
dec si
.until (si == 0)
call loop_delay ; wait for the stop bit to occur
mov al, ah
ret
byte_in endp
GATE_LOW EQU 0Ch
GATE_HIGH EQU 0Dh
OP_MUL EQU 0
OP_DIV EQU 1
OP_ADD EQU 0
OP_SUB EQU 1
;in: ax ticks to calibrate the loop for
;out: ecx loops for given ticks
calibrate_loop proc uses ax bx edx
; register usage:
; ax=temp
; bl=operation for the corrector (div or mul)
; bh=operation for the loop counter (add or sub)
; ecx= loop counter
; edx= corrector
pushf
cli
mov bx, ax
; init timer
mov al, GATE_LOW
out 61h, al
mov al, 10110010b ; timer 2, write 16 bit value, mode 1, binary
out 43h, al
mov ax, bx
out 42h, al
IODELAY
mov al, ah
out 42h, al
mov ecx, 1024
mov edx, ecx
shr edx, 1
mov bl, OP_MUL
.repeat
; trigger the timer...
mov al, GATE_HIGH
out 61h, al
; ..and wait for OUT to go low
.repeat
in al, 61h
.until !(al & 20h)
; do the loops
call loop_delay
; did the timer count to 0?
in al, 61h
.if (al & 20h)
mov bl, OP_DIV
mov bh, OP_SUB
.else
mov bh, OP_ADD
.endif
.if (bl == OP_DIV)
shr edx, 1
.else
shl edx, 1
.endif
.if (bh == OP_ADD)
add ecx, edx
.else
sub ecx, edx
.endif
; disable gate
mov al, GATE_LOW
out 61h, al
.until (edx == 1)
popf
ret
calibrate_loop endp
public send_calibrate
send_calibrate proc far uses ax ecx
mov ax, TICKS_PER_SEC/9600
call calibrate_loop
mov loops_per_bit, ecx
mov ax, TICKS_PER_SEC/(9600*2)
call calibrate_loop
mov loops_per_halfbit, ecx
ret
send_calibrate endp
set_defaults proc uses ax
mov al, lanc_channel
.if (al == -1)
mov lanc_channel, 0 ; = X1 on IRdeo
.endif
mov al, com_port
.if (al == -1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -