Example program for the Cidco MailStation Z80 computer
1; vim:syntax=z8a:ts=8
2;
3; WiFiStation parallel port routines
4; Copyright (c) 2019-2021 joshua stein <jcs@jcs.org>
5;
6; Permission to use, copy, modify, and distribute this software for any
7; purpose with or without fee is hereby granted, provided that the above
8; copyright notice and this permission notice appear in all copies.
9;
10; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17;
18
19 .module wifi
20
21 .include "mailstation.inc"
22
23 .area _CODE
24
25 .equ CONTROL_DIR, #0x0a
26 .equ CONTROL_DIR_OUT, #0xff
27 .equ CONTROL_DIR_IN, #0
28
29 .equ CONTROL_PORT, #0x9
30 .equ CONTROL_STATUS_MASK, #0xf0
31 .equ CONTROL_STROBE_BIT, #0
32 .equ CONTROL_STROBE, #(1 << CONTROL_STROBE_BIT)
33 .equ CONTROL_LINEFEED_BIT, #1
34 .equ CONTROL_LINEFEED, #(1 << CONTROL_LINEFEED_BIT)
35 .equ CONTROL_INIT, #(1 << 2)
36 .equ CONTROL_SELECT, #(1 << 3)
37
38 .equ DATA_DIR, #0x2c
39 .equ DATA_DIR_OUT, #0xff
40 .equ DATA_DIR_IN, #0
41 .equ DATA_PORT, #0x2d
42
43 .equ STATUS_PORT, #0x21
44 .equ STATUS_BUSY, #(1 << 7)
45 .equ STATUS_ACK, #(1 << 6)
46
47; void wifi_init(void);
48_wifi_init::
49 ; lower control lines
50 ld a, #CONTROL_DIR_OUT
51 out (#CONTROL_DIR), a
52 in a, (#CONTROL_PORT)
53 and #CONTROL_STATUS_MASK
54 out (#CONTROL_PORT), a
55 ret
56
57; at idle, lower all control lines
58; writer: reader:
59; raise strobe
60; see high strobe as high busy
61; raise linefeed
62; see high linefeed as high ack
63; write all data pins
64; lower strobe
65; see low strobe as low busy
66; read data
67; lower linefeed
68; see lower linefeed as high ack
69
70; int wifi_write(char); -1 on error, 0 on success
71_wifi_write::
72 push ix
73 ld ix, #0
74 add ix, sp
75 push bc
76 push de
77 ld c, 4(ix) ; char to send
78 ld a, #DATA_DIR_OUT
79 out (#DATA_DIR), a ; we're sending out
80 in a, (#CONTROL_PORT)
81 and #CONTROL_STATUS_MASK
82 set #CONTROL_STROBE_BIT, a
83 out (#CONTROL_PORT), a ; raise strobe
84 ld de, #0xffff
85wait_for_ack:
86 in a, (#STATUS_PORT)
87 and #STATUS_ACK ; is ack high?
88 jr nz, got_ack ; yes, break
89 dec de ; no, de--
90 ld a, d
91 cp #0
92 jr nz, wait_for_ack
93 ld a, e
94 cp #0
95 jr nz, wait_for_ack
96 jr abort_send ; de == 0, fail
97got_ack:
98 ld a, c
99 out (#DATA_PORT), a ; write data
100 xor a
101 in a, (#CONTROL_PORT)
102 and #CONTROL_STATUS_MASK
103 out (#CONTROL_PORT), a ; lower strobe
104 ld de, #0xffff
105wait_for_final_ack:
106 in a, (#STATUS_PORT)
107 and #STATUS_ACK ; is ack low?
108 jr z, got_final_ack ; yes, break
109 dec de ; no, de--
110 ld a, d
111 cp #0
112 jr nz, wait_for_final_ack
113 ld a, e
114 cp #0
115 jr nz, wait_for_final_ack
116got_final_ack:
117 pop de
118 pop bc
119 pop ix
120 ld hl, #0 ; return 0
121 ret
122abort_send:
123 in a, (#CONTROL_PORT)
124 and #CONTROL_STATUS_MASK
125 out (#CONTROL_PORT), a ; lower strobe
126 pop de
127 pop bc
128 pop ix
129 ld hl, #-1 ; return -1
130 ret
131
132
133; int wifi_read(void); -1 on nothing read, >= 0 on success returning char
134_wifi_read::
135 push ix
136 ld ix, #0
137 add ix, sp
138 push de
139 ld hl, #-1 ; return -1 unless we read something
140 in a, (#STATUS_PORT)
141 and #STATUS_BUSY ; is busy high?
142 jr z, recv_done ; no, bail
143 and #STATUS_ACK ; but is ack high too? probably bogus
144 jr nz, recv_done
145 ld a, #DATA_DIR_IN
146 out (#DATA_DIR), a ; we're reading in
147 in a, (#CONTROL_PORT)
148 and #CONTROL_STATUS_MASK
149 set #CONTROL_LINEFEED_BIT, a ; raise linefeed
150 out (#CONTROL_PORT), a
151 ld de, #0xffff
152wait_for_busy_ack:
153 in a, (#STATUS_PORT)
154 and #STATUS_BUSY ; is busy high?
155 jr z, read_data ; no, break
156 dec de ; no, de--
157 ld a, d
158 cp #0
159 jr nz, wait_for_busy_ack
160 ld a, e
161 cp #0
162 jr nz, wait_for_busy_ack
163 jr recv_done ; de == 0, fail
164read_data:
165 in a, (#DATA_PORT)
166 ld h, #0
167 ld l, a
168raise_lf:
169 in a, (#CONTROL_PORT)
170 and #CONTROL_STATUS_MASK
171 out (#CONTROL_PORT), a ; lower linefeed
172recv_done:
173 pop de
174 pop ix
175 ret