⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lanc_if.asm

📁 修改DV内存的汇编源代码,在95/98下使用,使用时需仔细.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;=============================================================================
; (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 + -