home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / MOUSE / GPIBLPT.ZIP / GPIB_C.ASM next >
Encoding:
Assembly Source File  |  1990-10-18  |  12.6 KB  |  677 lines

  1.     page    ,132
  2.     title    GPIB - GPIB Service Routines
  3.  
  4. ;*    General Purpose Interface Bus Service Routines.
  5. ;
  6. ;    Copyright 1990, Sydex.    All rights reserved.
  7. ;
  8. ;    These are simple 'C'-callable routines which, with the proper
  9. ;    cable, can drive most GPIB/HPIB/IEEE-488 devices.  Consult the
  10. ;    accompanying documentation for specific licensing rights and
  11. ;    descriptive information.
  12. ;
  13.  
  14.     .model    small,c
  15.  
  16.     .data
  17.  
  18. BasePort    dw    0        ; base port of parallel adapter
  19. Talker        db    0        ; talker address to use
  20. Start_Time    dw    0        ; time we started
  21. Tick_Time    dw    0        ; ticks to wait
  22.  
  23.     .code
  24.  
  25. ;    I/O port offsets from base for parallel printer adapter.
  26.  
  27. po_data equ    0            ; data
  28. po_ctl    equ    2            ; control
  29. po_sts    equ    1            ; status
  30.  
  31. ;    Control bits (output to pctl)
  32.  
  33. O_Input equ    020h            ; Input bit
  34. O_DAV    equ    001h            ; Data Available
  35. O_ATN    equ    002h            ; Attention
  36. O_RFD    equ    004h            ; Ready for Data (note inversion)
  37. O_NDAC    equ    008h            ; Not data accepted
  38.  
  39. ;    Input status bits (input from psts)
  40.  
  41. I_NIFC    equ    040h            ; not interface clear
  42. I_NREN    equ    020h            ; not remote enable
  43. I_NEOI    equ    010h            ; not EOI
  44. I_NSRQ    equ    008h            ; not Service request
  45.  
  46. ;    Specialized commands (pdata)
  47.  
  48. M_LIS    equ    020h            ; Listen
  49. M_UNL    equ    03fh            ; Unlisten
  50. M_TAL    equ    040h            ; Talk
  51. M_UNT    equ    05fh            ; Untalk
  52. M_SPE    equ    018h            ; Serial Poll Enable
  53. M_SPD    equ    019h            ; Serial Poll Disable
  54. M_DCL    equ    014h            ; Universal clear
  55.  
  56.     subttl    GPIB Service Routines
  57.     page
  58.  
  59. ;*    GPIB_Init - Initialize GPIB
  60. ;
  61. ;    int GPIB_Init( int io_port, int our_address)
  62. ;
  63. ;    Initialize GPIB interface.  "io_port" is the base port of the
  64. ;    printer adapter used.  "our_address" is the address that we
  65. ;    use as the controller/talker.
  66. ;
  67. ;    On exit, returns 0 if okay, -1 if error.
  68. ;
  69.  
  70. GPIB_Init    proc    ioport:word, us:word
  71.     mov    al,byte ptr (us)
  72.     mov    Talker,al        ; save the talker address
  73.     mov    dx,ioport        ; get the port
  74.     mov    BasePort,dx        ; save it
  75.     mov    al,not 0        ; set data to null
  76.     out    dx,al
  77.  
  78.     add    dx,po_ctl        ; to control port
  79.     mov    al,O_NDAC+O_Input    ; known state
  80.     out    dx,al            ; set it up
  81.  
  82.     mov    ah,M_DCL
  83.     call    SendAddr        ; send DCL out--use whatever status
  84.     call    ReduceStatus
  85.     ret                ; exit...
  86. GPIB_Init    endp
  87.  
  88. ;*    GPIB_Send - Send a character.
  89. ;
  90. ;    int GPIB_Send( int listen, char what)
  91. ;
  92. ;    The target device has address "listen"; "what" is sent.
  93. ;
  94. ;    On exit, returns 0 if okay, -1 if error.
  95. ;
  96.  
  97. GPIB_Send    proc    listen:word, what:byte
  98.     mov    ah,M_UNL
  99.     call    SendAddr    ; send an unlisten
  100.     jc    GPSend2        ; if error
  101.     mov    ah,Talker
  102.     or    ah,M_TAL
  103.     call    SendAddr    ; send ours as talker
  104.     jc    GPSend2        ; if error
  105.     mov    ah,byte ptr (listen)
  106.     or    ah,M_LIS    ; make it a listen
  107.     call    SendAddr    ; send address
  108.     jc    GPSend2        ; if error
  109.     mov    al,what
  110.     call    SendData    ; send data
  111.     jc    GPSend2        ; if timeout
  112.     mov    ah,M_UNL
  113.     call    SendAddr    ; send Unlisten
  114. GPSend2:
  115.     call    ReduceStatus
  116.     ret
  117. GPIB_Send    endp
  118.  
  119.  
  120. ;*    GPPutStr - Send a string to a device.
  121. ;
  122. ;    int GPIB_PutStr( int listen, char *string, int count)
  123. ;
  124. ;    "count" bytes of "string" are output to the listener address
  125. ;    "listen".
  126. ;
  127. ;    On exit, returns 0 if okay, -1 if error.
  128. ;
  129.  
  130. GPIB_PutStr    proc    uses si, listen:word, str:word, count:word
  131.     mov    ah,M_UNL
  132.     call    SendAddr    ; send an unlisten
  133.     jc    GPPutStr4    ; if error
  134.     mov    ah,Talker
  135.     or    ah,M_TAL
  136.     call    SendAddr    ; send ours as talker
  137.     jc    GPPutStr4    ; if error
  138.     mov    ah,byte ptr (listen)    ; save address
  139.     or    ah,M_LIS    ; make it a listen
  140.     call    SendAddr    ; send address
  141.     jc    GPPutStr4    ; if error
  142.     cld
  143.     mov    si,str
  144.     mov    cx,count
  145.     jcxz    GPPutStr3    ; if zero bytes
  146. GPPutStr2:
  147.     lodsb            ; get a byte
  148.     mov    ah,al
  149.     call    SendData    ; send it
  150.     jc    GPPutStr4    ; if error
  151.     loop    GPPutStr2    ; keep going
  152. GPPutStr3:
  153.     mov    ah,M_UNL    ; unlisten
  154.     call    SendAddr    ; end the transmission
  155. GPPutStr4:
  156.     call    ReduceStatus
  157.     ret            ; exit...
  158. GPIB_PutStr    endp
  159.  
  160. ;*    GPIB_Stat - Status - Return line status.
  161. ;
  162. ;    Returns: IFC REN EOI SRQ NDAC NRFD ATN DAV
  163. ;
  164. ;    int GPIB_Stat(void);
  165. ;
  166.  
  167. GPIB_Stat    proc
  168.     mov    dx,BasePort
  169.     add    dx,po_sts
  170.     in    al,dx            ; get upper
  171.     shl    al,1
  172.     and    al,0f0h
  173.     mov    ah,al
  174.     add    dx,po_ctl-po_sts
  175.     in    al,dx            ; get lower
  176.     and    al,0fh
  177.     or    al,ah
  178.     xor    al,11110100b        ; invert the proper bits
  179.     xor    ah,ah
  180.     ret
  181. GPIB_Stat    endp
  182.  
  183.  
  184. ;*    GPIB_Get - Get a character.
  185. ;
  186. ;    int GPIB_Get( int listen)
  187. ;
  188. ;    "listen" is target address.
  189. ;
  190. ;    Returns character or -1 if timeout.
  191. ;
  192.  
  193. GPIB_Get    proc    listen:word
  194.     mov    ah,M_UNL
  195.     call    SendAddr    ; send unlisten
  196.     jc    GPGet2        ; if error
  197.     mov    ah,byte ptr (listen)
  198.     or    ah,M_TAL    ; make it a talker
  199.     call    SendAddr    ; send address
  200.     jc    GPGet2        ; if error
  201.     mov    ah,Talker
  202.     or    ah,M_LIS    ; make us a listener
  203.     call    SendAddr
  204.     jc    GPGet2        ; if error
  205.     call    GetData        ; send data
  206.     jc    GPGet2        ; if timeout
  207.     push    ax
  208.     mov    ah,M_UNT
  209.     call    SendAddr    ; send Untalk
  210.     pop    ax
  211.     xor    ah,ah        ; clear out upper bits
  212.     ret
  213.  
  214. GPGet2:
  215.     mov    ax,-1        ; say error
  216.     ret
  217. GPIB_Get    endp
  218.  
  219.  
  220. ;*    GPIB_GetStr - Get a String.
  221. ;
  222. ;    int GPIB_GetStr( int listen, char *buf)
  223. ;
  224. ;    Returns count of bytes read or -1 if error.
  225. ;
  226.  
  227. GPIB_GetStr    proc    uses di,listen:word, buf:word
  228.     mov    ah,M_UNL
  229.     call    SendAddr    ; send unlisten
  230.     jc    GPGetStr4    ; if error
  231.     mov    ah,byte ptr (listen)
  232.     or    ah,M_TAL    ; make it a talker
  233.     call    SendAddr    ; send address
  234.     jc    GPGetStr4    ; if error
  235.     mov    ah,Talker
  236.     or    ah,M_LIS    ; make us a listener
  237.     call    SendAddr
  238.     jc    GPGetStr4    ; if error
  239.     mov    di,buf
  240.     cld
  241. GPGetStr2:
  242.     call    GetData        ; send data
  243.     jc    GPGetStr4    ; if timeout
  244.     jz    GPGetStr3    ; if end of data
  245.     stosb
  246.     loop    GPGetStr2    ; more data
  247. GPGetStr3:
  248.     mov    ah,M_UNT
  249.     call    SendAddr    ; send Untalk
  250.     mov    ax,di
  251.     sub    ax,buf
  252.     jmp    short GPGetStr6 ; just exit with count
  253.  
  254. GPGetStr4:
  255.     mov    ax,-1
  256. GPGetStr6:
  257.     ret
  258. GPIB_GetStr    endp
  259.  
  260. ;*    GPIB_SerPoll - Execute a serial poll.
  261. ;
  262. ;    int GPIB_SerPoll( int listen)
  263. ;
  264. ;    Returns serial poll status or -1 if error.
  265. ;
  266.  
  267. GPIB_SerPoll    proc    listen:word
  268.  
  269.     mov    ah,M_UNL
  270.     call    SendAddr        ; send unlisten
  271.     jc    GPSerPoll2
  272.     mov    ah,byte ptr (listen)
  273.     or    ah,M_TAL
  274.     call    SendAddr        ; send talk address
  275.     jc    GPSerPoll2
  276.  
  277.     mov    ah,Talker
  278.     or    ah,M_LIS
  279.     call    SendAddr        ; give us as listener
  280.     jc    GPSerPoll2
  281.  
  282.     mov    ah,M_SPE
  283.     call    SendAddr
  284.     jc    GPSerPoll2        ; if error
  285.     call    GetData            ; get data
  286.     jc    GPSerPoll2        ; if error
  287.     push    ax
  288.     mov    ah,M_UNT
  289.     call    SendAddr        ; say untalk
  290.     mov    ah,M_SPD
  291.     call    SendAddr        ; say serial poll disable
  292.     pop    ax
  293.     xor    ah,ah
  294.     jmp    GPSerPoll4
  295.  
  296. GPSerPoll2:
  297.     mov    ax,-1
  298. GPSerPoll4:
  299.     ret                ; exit...
  300. GPIB_SerPoll    endp
  301.  
  302. ;*    GPIB_PutAdd - Primitive - Put a byte in address mode.
  303. ;
  304. ;    int GPIB_PutAdd( char what)
  305. ;
  306. ;    returns 0 if success, -1 if error.
  307. ;
  308.  
  309. GPIB_PutAdd    proc    what:word
  310.     mov    ah,byte ptr (what)
  311.     call    SendAddr
  312.     call    ReduceStatus
  313.     ret            ; exit...
  314. GPIB_PutAdd       endp
  315.  
  316.  
  317. ;*    GPIB_PutData - Primitive - Put a byte in data mode.
  318. ;
  319. ;    int GPIB_PutData( char what)
  320. ;
  321. ;    returns 0 if success, -1 if error.
  322. ;
  323.  
  324. GPIB_PutData    proc    what:word
  325.     mov    ah,byte ptr (what)
  326.     call    SendData
  327.     call    ReduceStatus
  328.     ret            ; exit...
  329. GPIB_PutData    endp
  330.  
  331. ;*    GPIB_GetData - Primitive - Get a byte of data.
  332. ;
  333. ;    int GPIB_GetData();
  334. ;
  335. ;    Returns data or -1 if error.
  336. ;
  337.  
  338. GPIB_GetData    proc    near
  339.     call    GetData
  340.     mov    ah,0
  341.     jnc    GPGetData2
  342.     mov    ax,-1
  343. GPGetData2:
  344.     ret
  345. GPIB_GetData    endp
  346.  
  347.     subttl    Utility Subroutines
  348.     page
  349.  
  350. ;*    ReduceStatus - Reduce carry status to 0 or -1.
  351. ;
  352. ;    Used by most of the routines.
  353. ;
  354.  
  355. ReduceStatus    proc    near
  356.     mov    ax,0
  357.     jnc    ReduceStatus2
  358.     mov    ax,-1
  359. ReduceStatus2:
  360.     ret
  361. ReduceStatus    endp
  362.  
  363. ;*    StartTimer - Start a Countdown timer.
  364. ;
  365. ;    On entry, (ax) = number of 55 msec ticks to wait on.
  366. ;
  367.  
  368. StartTimer    proc    near
  369.     mov    Tick_Time,ax
  370.     push    dx
  371.     push    cx
  372.     mov    ah,0
  373.     int    1ah            ; get time of day
  374.     mov    Start_Time,dx
  375.     pop    cx
  376.     pop    dx
  377.     ret
  378. StartTimer    endp
  379.  
  380. ;*    TestTimer - Test the timer for expiration.
  381. ;
  382. ;    carry is set upon expired time limit.
  383. ;
  384.  
  385. TestTimer    proc    near
  386.     push    ax
  387.     push    dx
  388.     push    cx
  389.     mov    ah,0
  390.     int    1ah            ; time of day
  391.     sub    dx,Start_Time
  392.     cmp    dx,Tick_Time
  393.     cmc
  394.     pop    cx
  395.     pop    dx
  396.     pop    ax
  397.     ret
  398. TestTimer    endp
  399.  
  400. ;*    SendAddr - Send Device address.
  401. ;
  402. ;    On entry -
  403. ;        (ah) = address
  404. ;    On return -
  405. ;        (carry) - timeout
  406. ;
  407.  
  408. SendAddr    proc    near
  409.     push    bx
  410.     push    cx
  411.     push    dx
  412.     push    ax        ; save registers
  413.  
  414. ;    Wait for device ready - a long wait.
  415.  
  416.     mov    dx,BasePort
  417.     add    dx,po_ctl
  418.     mov    al,O_RFD
  419.     out    dx,al        ; set attention+ready for data
  420.     mov    ax,20*18
  421.     call    StartTimer
  422.     mov    dx,BasePort
  423.     add    dx,po_ctl
  424. SendAddr2:
  425.     in    al,dx        ; get status
  426.     test    al,O_RFD
  427.     jnz    SendAddr6    ; if RFD high
  428.     call    TestTimer
  429.     jnb    SendAddr2    ; keep trying...
  430.  
  431. ;    Timeout, set carry after going back to idle
  432.  
  433. SendAddr4:
  434.     mov    dx,BasePort
  435.     add    dx,po_ctl
  436.     mov    al,O_Input+O_RFD
  437.     out    dx,al        ; set not data accepted
  438.     stc
  439.     pop    ax
  440.     pop    dx
  441.     pop    cx
  442.     pop    bx
  443.     ret            ; back to main routine
  444.  
  445. ;    Send the talk address.
  446.  
  447. SendAddr6:
  448.     mov    al,O_RFD+O_ATN
  449.     out    dx,al        ; assert ATN
  450.     mov    al,ah
  451.     not    al
  452.     mov    dx,BasePort    ; for data
  453.     out    dx,al        ; set the inverse of the data
  454.     add    dx,po_ctl
  455.     mov    al,O_DAV+O_RFD+O_ATN
  456.     out    dx,al        ; say DAV
  457.  
  458. ;    Now, with DAV asserted, RFD should go low.  If not, we have
  459. ;    no devices connected.
  460.  
  461.     xor    cx,cx
  462. SendAddr8:
  463.     in    al,dx        ; wait for RFD low
  464.     test    al,O_RFD
  465.     jz    SendAddr9    ; if it did
  466.     loop    SendAddr8    ; keep trying
  467.     jmp    SendAddr4
  468.  
  469. ;    Wait for listener to release NDAC.
  470.  
  471. SendAddr9:
  472.     xor    cx,cx
  473. SendAddr10:
  474.     in    al,dx        ; get status
  475.     test    al,O_NDAC
  476.     jz    SendAddr12    ; if released
  477.     loop    SendAddr10    ; keep trying
  478.     jmp    SendAddr4    ; timeout
  479.  
  480. ;    Release DAV wait for RFD - may take a while.
  481.  
  482. SendAddr12:
  483.     mov    al,O_RFD+O_Input
  484.     out    dx,al            ; Return to input state
  485.     mov    ax,20*18
  486.     call    StartTimer
  487.     mov    dx,BasePort
  488.     add    dx,po_ctl
  489. SendAddr14:
  490.     in    al,dx
  491.     test    al,O_RFD
  492.     jnz    SendAddr16    ; if released
  493.     call    TestTimer
  494.     jnb    SendAddr14    ; loop for more
  495.     jmp    SendAddr4    ; timeout error
  496.  
  497. SendAddr16:
  498.     clc
  499.     pop    ax
  500.     pop    dx
  501.     pop    cx
  502.     pop    bx
  503.     ret                ; exit...
  504. SendAddr    endp
  505.  
  506.  
  507. ;*    SendData - Send Data.
  508. ;
  509. ;    On entry (ah) = data byte
  510. ;
  511. ;    On exit (carry) - timeout
  512. ;
  513.  
  514. SendData    proc    near
  515.     push    bx
  516.     push    cx
  517.     push    dx
  518.     push    ax
  519.  
  520. ;    Wait for quiet and ready.
  521.  
  522.     mov    dx,BasePort
  523.     add    dx,po_ctl
  524.     mov    al,O_RFD
  525.     out    dx,al        ; set ready for data
  526.     mov    ax,18*20
  527.     call    StartTimer
  528.     mov    dx,BasePort
  529.     add    dx,po_ctl
  530. SendData2:
  531.     in    al,dx        ; get status
  532.     test    al,O_RFD
  533.     jnz    SendData6    ; if RFD high
  534.     call    TestTimer
  535.     jnb    SendData2    ; loop if not timeout yet
  536.  
  537. ;    Timeout, set carry after going back to idle
  538.  
  539. SendData4:
  540.     mov    dx,BasePort
  541.     add    dx,po_ctl
  542.     mov    al,O_Input+O_RFD
  543.     out    dx,al        ; set ready for data
  544.     stc
  545.     pop    ax
  546.     pop    dx
  547.     pop    cx
  548.     pop    bx
  549.     ret            ; back to main routine
  550.  
  551. ;    Okay, Ready for Data..
  552.  
  553. SendData6:
  554.     mov    al,O_RFD
  555.     out    dx,al        ; keep RFD
  556.     pop    ax
  557.     push    ax
  558.     mov    al,ah
  559.     not    al
  560.     mov    dx,BasePort
  561.     out    dx,al        ; set the inverse of the data
  562.     add    dx,po_ctl
  563.     mov    al,O_DAV+O_RFD
  564.     out    dx,al        ; say DAV
  565.  
  566. ;    Now, with DAV asserted, RFD should go low.  If not, we have
  567. ;    no devices connected.
  568.  
  569.     xor    cx,cx
  570. SendData8:
  571.     in    al,dx        ; wait for RFD low
  572.     test    al,O_RFD
  573.     jz    SendData9    ; if it did
  574.     loop    SendData8    ; keep trying
  575.     jmp    SendData4
  576.  
  577. ;    Wait for listener to release NDAC.
  578.  
  579. SendData9:
  580.     xor    cx,cx
  581. SendData10:
  582.     in    al,dx        ; get status
  583.     test    al,O_NDAC
  584.     jz    SendData12    ; if released
  585.     loop    SendData10    ; keep trying
  586.     jmp    SendData4    ; timeout
  587.  
  588. ;    Release DAV and wait for RFD.
  589.  
  590. SendData12:
  591.     mov    al,O_RFD+O_Input
  592.     out    dx,al            ; Return to input state
  593.     mov    ax,18*20
  594.     call    StartTimer
  595.     mov    dx,BasePort
  596.     add    dx,po_ctl
  597. SendData14:
  598.     in    al,dx
  599.     test    al,O_RFD
  600.     jnz    SendData16    ; if released
  601.     call    TestTimer
  602.     jnb    SendData14
  603.     jmp    SendData4    ; timeout
  604.  
  605. SendData16:
  606.     clc
  607.     pop    ax
  608.     pop    dx
  609.     pop    cx
  610.     pop    bx
  611.     ret                ; exit...
  612. SendData    endp
  613.  
  614. ;*    GetData - Get a byte of data.
  615. ;
  616. ;    On return (carry) if timeout,
  617. ;    (al) = data read, (zero) if EOI encountered
  618. ;
  619.  
  620. GetData proc    near
  621.     push    dx
  622.     push    cx
  623.     mov    al,O_Input+O_RFD+O_NDAC        ; say not data accepted
  624.     mov    dx,BasePort
  625.     mov    dx,po_ctl
  626.     out    dx,al        ; set up as ready for data
  627.     xor    cx,cx
  628. GetData2:
  629.     in    al,dx        ; wait for DAV
  630.     test    al,O_DAV
  631.     jnz    GetData6    ; if got DAV
  632.     loop    GetData2    ; if error
  633. GetData4:
  634.     mov    al,O_Input+O_RFD
  635.     out    dx,al
  636.     stc
  637.     pop    cx
  638.     pop    dx
  639.     ret            ; timeout exit
  640.  
  641. GetData6:
  642.     mov    dx,BasePort
  643.     in    al,dx        ; get the data
  644.     not    al
  645.     mov    ah,al
  646.     add    dx,po_sts
  647.     in    al,dx        ; see about eoi
  648.     push    ax
  649.     add    dx,po_ctl-po_sts    ; back to control
  650.     mov    al,O_Input
  651.     out    dx,al        ; assert data accepted
  652.     xor    cx,cx
  653. GetData8:
  654.     in    al,dx
  655.     test    al,O_DAV
  656.     jz    GetData10    ; if DAV released
  657.     loop    GetData8    ; continue...
  658.     pop    ax
  659.     jmp    GetData4    ; error...
  660.  
  661. GetData10:
  662.     mov    al,O_Input+O_NDAC
  663.     out    dx,al        ; assert NDAC
  664.     jmp    GetData12
  665. GetData12:
  666.     mov    al,O_Input
  667.     out    dx,al        ; assert RFD, release NDAC
  668.     pop    ax
  669.     test    al,I_NEOI    ; if not EOI
  670.     mov    al,ah
  671.     pop    cx
  672.     pop    dx
  673.     ret            ; exit, zero flag indicates status
  674. GetData endp
  675.  
  676.     end
  677.