Terminal program for MailStation devices
1; vim:syntax=z8a:ts=8
2;
3; msTERM
4; parallel port routines
5;
6; Copyright (c) 2019 joshua stein <jcs@jcs.org>
7;
8; Permission to use, copy, modify, and distribute this software for any
9; purpose with or without fee is hereby granted, provided that the above
10; copyright notice and this permission notice appear in all copies.
11;
12; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19;
20
21 .module lpt
22
23 .include "mailstation.inc"
24
25 .equ CONTROL, #0x2c
26 .equ DATA, #0x2d
27 .equ STATUS, #0x21
28
29 .equ LPT_BUSY_IN, #0x40
30 .equ LPT_BUSY_OUT, #0x08
31 .equ LPT_STROBE_IN, #0x80
32 .equ LPT_STROBE_OUT, #0x10
33 .equ LPT_TRIB_MASK, #0x07
34 .equ LPT_DIB_MASK, #0x03
35
36 .area _CODE
37
38; receive a tribble byte from host, return h=1 l=0 on error, else h=0, l=(byte)
39lptrecv_tribble:
40 push bc
41 ld hl, #0 ; h will contain error, l result
42 xor a
43 out (DATA), a ; drop busy/ack, wait for strobe
44 ld b, #0xff ; try a bunch before bailing
45wait_for_strobe:
46 in a, (STATUS)
47 and #LPT_STROBE_IN ; inb(STATUS) & stbin
48 jr nz, got_strobe
49 djnz wait_for_strobe
50strobe_failed:
51 ld h, #1
52 ld l, #0
53 jr lptrecv_tribble_out
54got_strobe:
55 in a, (STATUS)
56 sra a
57 sra a
58 sra a
59 and #LPT_TRIB_MASK ; & tribmask
60 ld l, a
61 ld a, #LPT_BUSY_OUT ; raise busy/ack
62 out (DATA), a
63 ld b, #0xff ; retry 255 times
64wait_for_unstrobe:
65 in a, (STATUS)
66 and #LPT_STROBE_IN ; inb(STATUS) & stbin
67 jr z, lptrecv_tribble_out
68 djnz wait_for_unstrobe
69 ; if we never get unstrobe, that's ok
70lptrecv_tribble_out:
71 ld a, #LPT_BUSY_OUT ; raise busy/ack
72 out (DATA), a
73 pop bc
74 ret
75
76
77; unsigned char lptrecv(void)
78; receive a full byte from host in three parts
79; return h=1 l=0 on error, otherwise h=0, l=(byte)
80_lptrecv::
81 push bc
82 call lptrecv_tribble
83 ld a, h
84 cp #1
85 jr z, lptrecv_err ; bail early if h has an error
86 ld b, l
87 call lptrecv_tribble
88 ld a, h
89 cp #1
90 jr z, lptrecv_err
91 ld a, l
92 sla a
93 sla a
94 sla a
95 add b
96 ld b, a ; += tribble << 3
97 call lptrecv_tribble
98 ld a, h
99 cp #1
100 jr z, lptrecv_err
101 ld a, l
102 and #LPT_DIB_MASK ; dibmask
103 sla a
104 sla a
105 sla a
106 sla a
107 sla a
108 sla a
109 add b ; += (tribble & dibmask) << 6
110 ld h, #0
111 ld l, a
112lptrecv_out:
113 pop bc
114 ret
115lptrecv_err:
116 pop bc
117 ld hl, #0x0100
118 ret
119
120
121; send a tribble byte in register l to host, return l=0 on success
122lptsend_tribble:
123 push bc
124 ld h, #1
125 ld c, #0xff ; 255*255 tries before bailing
126wait_for_busy_drop_outer:
127 ld b, #0xff
128wait_for_busy_drop:
129 in a, (STATUS)
130 and #LPT_BUSY_IN ; inb(STATUS) & bsyin
131 jr z, got_busy_drop
132 djnz wait_for_busy_drop
133 dec c
134 ld a, c
135 cp #0
136 jr nz, wait_for_busy_drop_outer
137busy_drop_failed:
138 jr lptsend_tribble_out
139got_busy_drop:
140 ld a, l
141 and #LPT_TRIB_MASK
142 or #LPT_STROBE_OUT
143 out (DATA), a
144 ld c, #0xff ; try 255*255 tries before bailing
145wait_for_ack_outer:
146 ld b, #0xff
147wait_for_ack:
148 in a, (STATUS)
149 and #LPT_BUSY_IN ; inb(STATUS) & stbin
150 jr nz, lptsend_unstrobe
151 djnz wait_for_ack
152 dec c
153 ld a, c
154 cp #0
155 jr nz, wait_for_ack_outer
156 jr lptsend_tribble_out
157lptsend_unstrobe:
158 ld a, #1
159 out (DATA), a
160 ld h, #0 ; success
161lptsend_tribble_out:
162 ld a, #LPT_BUSY_OUT ; raise busy/ack
163 out (DATA), a
164 pop bc
165 ld l, h ; l=1 error, l=0 success
166 ld h, #0
167 ret
168
169
170; unsigned int lptsend(unsigned char b)
171; returns 0 on success
172_lptsend::
173 push ix
174 ld ix, #0
175 add ix, sp
176 ld l, 4(ix) ; char to send
177 push hl
178 call lptsend_tribble
179 ld a, l
180 pop hl
181 cp #0
182 jr z, tribble2
183 ld hl, #0x1
184 jr lptsend_error
185tribble2:
186 push hl
187 sra l
188 sra l
189 sra l ; b >> 3
190 call lptsend_tribble
191 ld a, l
192 pop hl
193 cp #0
194 jr z, tribble3
195 ld hl, #0x2
196 jr lptsend_error
197tribble3:
198 sra l
199 sra l
200 sra l
201 sra l
202 sra l
203 sra l ; b >> 6
204 call lptsend_tribble
205 ld a, l
206 cp #0
207 jr z, lptsend_out
208 ld hl, #0x3
209 jr lptsend_error
210lptsend_out:
211 ld hl, #0
212 ld sp, ix
213 pop ix
214 ret
215lptsend_error:
216 ld sp, ix
217 pop ix
218 ret
219
220
221; send pushed 16-bit as two bytes
222_lptsend16::
223 push ix
224 ld ix, #0
225 add ix, sp
226 push hl
227 ld h, #0
228 ld l, 5(ix)
229 push hl
230 call _lptsend
231 pop hl
232 ld l, 4(ix)
233 push hl
234 call _lptsend
235 pop hl
236 pop hl
237 ld sp, ix
238 pop ix
239 ret