Terminal program for MailStation devices
at master 445 lines 8.9 kB view raw
1; vim:syntax=z8a:ts=8 2; 3; msTERM 4; modem routines for Rockwell RCV336DPFSP 5; https://github.com/jcs/mailstation-tools/blob/master/docs/modem-RCV336DPFSP.pdf 6; 7; Copyright (c) 2019 joshua stein <jcs@jcs.org> 8; 9; Permission to use, copy, modify, and distribute this software for any 10; purpose with or without fee is hereby granted, provided that the above 11; copyright notice and this permission notice appear in all copies. 12; 13; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20; 21 22 .module modem 23 24 .include "mailstation.inc" 25 .globl _new_mail 26 27 .area _DATA 28 29 ; modem msr 30_modem_curmsr:: 31 .db #0 32_modem_flowing:: 33 .db #0 34 35 .area _CODE 36 37_modem_isr:: 38 push af 39 push hl 40 push bc 41 ld l, #1 42 call _modem_iir ; read IIR to identify interrupt 43 bit #0, l 44 jr nz, modem_isr_out ; no interrupt, how did we get here? 45 ld a, l 46 and #0b00001111 ; mask off high 4 bits 47 ld l, a 48has_irq: 49 and #0b00000110 ; receiver line status, some error 50 jr nz, no_rls 51 push hl 52 call _modem_lsr ; what are we supposed to do with it? (FCR bit 1?) 53 pop hl 54 jr modem_isr_out 55no_rls: 56 ld a, l 57 and #0b00000100 ; received data available or timeout 58 jr z, modem_isr_out 59 ld b, #16 ; read 16 bytes at a time 60modem_read_loop: 61 push bc 62 push hl 63 call _modem_read 64 ld b, l 65 pop hl 66 ld hl, #_modem_buf 67 ld a, (_modem_buf_pos) 68 ld l, a ; 0xf600 + (modembufpos) 69 ld (hl), b 70 inc a 71 ld (_modem_buf_pos), a 72 pop bc 73 djnz check_for_more_bytes 74 jr modem_isr_out 75check_for_more_bytes: 76 call _modem_lsr 77 bit 0, l 78 jr nz, modem_read_loop 79modem_isr_out: 80 call _modem_msr ; modem status update 81 ld a, l 82 ld (_modem_curmsr), a 83 pop bc 84 pop hl 85 pop af 86 ret 87 88 89; void modem_init(void) 90_modem_init:: 91 push bc 92 push de 93 push hl 94 in a, (#SLOT_DEVICE) ; store old slot device 95 ld d, a 96 push de 97 ld a, #0 98 ld (_modem_buf_pos), a 99 call _modem_powerdown 100 ld a, #0x01 101 out (#0x26), a ; turn port 26 on 102 ld hl, #2000 103 push hl 104 call _delay ; delay 2 seconds 105 pop hl 106 ld a, #DEVICE_MODEM 107 out (#SLOT_DEVICE), a ; switch slot device to modem 108 ld a, #0b11000111 ; 14 byte FIFO 109 ld (#SLOT_ADDR + 0x2), a ; FCR = enable FIFO 110 ld a, #0b10000011 111 ld (#SLOT_ADDR + 0x3), a ; LCR = DLAB=1, 8n1 112 xor a 113 ld (#SLOT_ADDR + 0x1), a ; DLM = 0 114determine_dlab: 115dlab_57600: 116 ld hl, (_setting_modem_speed) 117 ld de, #57600 118 or a ; reset c 119 sbc hl, de 120 add hl, de 121 jr c, dlab_38400 122 ld a, #0x2 ; DLL = 2, baud rate = 57600 123 jp set_dlab 124dlab_38400: 125 ld hl, (_setting_modem_speed) 126 ld de, #38400 127 or a ; reset c 128 sbc hl, de 129 add hl, de 130 jr c, dlab_28800 131 ld a, #0x3 ; DLL = 3, baud rate = 38400 132 jr set_dlab 133dlab_28800: 134 ld hl, (_setting_modem_speed) 135 ld de, #28800 136 or a ; reset c 137 sbc hl, de 138 add hl, de 139 jr c, dlab_19200 140 ld a, #0x4 ; DLL = 4, baud rate = 28800 141 jr set_dlab 142dlab_19200: 143 ld hl, (_setting_modem_speed) 144 ld de, #19200 145 or a ; reset c 146 sbc hl, de 147 add hl, de 148 jr c, dlab_9600 149 ld a, #0x6 ; DLL = 6, baud rate = 19200 150 jr set_dlab 151dlab_9600: 152 ld hl, (_setting_modem_speed) 153 ld de, #9600 154 or a ; reset c 155 sbc hl, de 156 add hl, de 157 jr c, dlab_4800 158 ld a, #0x0c ; DLL = 0x0c, baud rate = 9600 159 jr set_dlab 160dlab_4800: 161 ld hl, (_setting_modem_speed) 162 ld de, #4800 163 or a ; reset c 164 sbc hl, de 165 add hl, de 166 jr c, dlab_2400 167 ld a, #0x18 ; DLL = 0x18, baud rate = 4800 168 jr set_dlab 169dlab_2400: 170 ld hl, (_setting_modem_speed) 171 ld de, #2400 172 or a ; reset c 173 sbc hl, de 174 add hl, de 175 jr c, dlab_1200 176 ld a, #0x30 ; DLL = 0x30, baud rate = 2400 177 jr set_dlab 178dlab_1200: 179 ld hl, (_setting_modem_speed) 180 ld de, #1200 181 or a ; reset c 182 sbc hl, de 183 add hl, de 184 jr c, dlab_300 185 ld a, #0x60 ; DLL = 0x60, baud rate = 1200 186 jr set_dlab 187dlab_300: 188 ld hl, (_setting_modem_speed) 189 ld de, #300 190 or a ; reset c 191 sbc hl, de 192 add hl, de 193 jr c, dlab_default 194 ld a, #0x01 195 ld (#SLOT_ADDR + 0x1), a ; DLM = 0x1 196 ld a, #0x80 ; DLL = 0x80, baud rate = 300 197 jr set_dlab 198dlab_default: 199 ld hl, #MODEM_DEFAULT_SPEED 200 ld (_setting_modem_speed), hl 201 jp determine_dlab ; run through the loop again 202set_dlab: 203 ld (#SLOT_ADDR), a ; DLL 204 ld a, #0b00000011 205 ld (#SLOT_ADDR + 0x3), a ; LCR = DLAB=0, 8n1 206 ld a, (#SLOT_ADDR + 0x4) ; read MCR 207 or #0b00001011 208 ld (#SLOT_ADDR + 0x4), a ; MCR = DTR, RTS, HINT 209; ld b, #0x01 210; ld c, #0x06 211; call 0x0a2f ; jp 0x1afb, do something with port 3 212; call 0x33ca ; init modem vars, activate interrupts 213 ld a, #0b00001001 ; IER = EDSSI, ERBFI 214 ld (#SLOT_ADDR + 0x1), a 215 ld a, (#SLOT_ADDR + 0x6) 216 ld (_modem_curmsr), a ; read and store MSR 217 pop de 218 ld a, d 219 out (#SLOT_DEVICE), a ; restore old slot device 220 pop hl 221 pop de 222 pop bc 223 ret 224 225 226; void modem_powerdown(void) 227; most of this is from 0x33f6 in v2.54 firmware 228_modem_powerdown:: 229 push bc 230 push de 231 push hl 232 call 0x3dbe ; disable caller id? 233 ld hl, (p3shadow) 234 ld a, (hl) 235 res 7, a ; disable caller id interrupt 236 ld (hl),a 237 out (#0x03), a 238 in a, (#0x29) ; XXX what is port 29? 239 or #0x0c 240 out (#0x29), a 241 ld hl, (p28shadow) 242 ld a, (hl) 243 set 2, a 244 res 3, a 245 ld (hl), a 246 out (#0x28), a ; XXX what is port 28? 247 xor a 248 ld (#0xe63b), a ; no idea what these shadow vars are 249 ld (#0xe63a), a 250 ld (#0xe64d), a 251 ld (#0xe638), a ; but init them all to 0 252; l33f8 253 ld a, #0x01 254 ld (#0xe638), a 255 in a, (#SLOT_DEVICE) ; store old slot device 256 ld d, a 257 push de 258 ld hl, (p2shadow) 259 ld a, (hl) ; read p2shadow 260 res 5, a ; turn off port 2.5 - modem power 261 ld (hl), a ; write p2shadow 262 out (#0x02), a ; also write it to port2 263 ld hl, #300 264 push hl 265 call _delay ; delay 300ms 266 pop hl 267 ld a, #0 268 out (#0x26), a ; turn port 26 off 269 ld hl, #100 270 push hl 271 call _delay ; delay 100ms 272 pop hl 273 pop de 274 ld a, d 275 out (#SLOT_DEVICE), a ; restore old slot device 276 pop hl 277 pop de 278 pop bc 279 ret 280 281 282; char modem_read(void) 283; return a byte in hl from the modem FIFO, from 0x3328 in v2.54 firmware 284_modem_read:: 285 ; use hl 286 in a, (#SLOT_ADDR) ; save old slot device 287 ld h, a ; into h 288 ld a, #DEVICE_MODEM 289 out (#SLOT_DEVICE), a ; slot device = modem 290 ld a, (#SLOT_ADDR) ; read byte from modem 291 ld l, a ; into l 292 ld a, h 293 out (#SLOT_DEVICE), a ; set old slot device 294 ld h, #0x00 295 ret ; return hl 296 297 298; void modem_write(char c) 299; write a byte to the modem TX FIFO, from 0x33b6 in v2.54 firmware 300_modem_write:: 301 push ix 302 ld ix, #0 303 add ix, sp 304 ld a, 4(ix) 305 ld l, a 306 in a, (#SLOT_DEVICE) 307 ld h, a 308 ld a, #DEVICE_MODEM 309 out (#SLOT_DEVICE), a 310 ld a, l 311 ld (#SLOT_ADDR), a 312 ld a, h 313 out (#SLOT_DEVICE), a 314 pop ix 315 ret 316 317 318; int modem_ier(void) 319; return modem IER register in hl, from 0x3339 in v2.54 firmware 320_modem_ier:: 321 in a, (#SLOT_DEVICE) 322 ld h, a 323 ld a, #DEVICE_MODEM 324 out (#SLOT_DEVICE), a 325 ld a, (#SLOT_ADDR + 0x1) ; read modem IER 326 ld l, a 327 ld a, h 328 out (#SLOT_DEVICE), a 329 ld h, #0x0 330 ret 331 332 333; int modem_iir(void) 334; return modem IIR register in hl, from 0x334a in v2.54 firmware 335_modem_iir:: 336 in a, (#SLOT_DEVICE) 337 ld h, a 338 ld a, #DEVICE_MODEM 339 out (#SLOT_DEVICE), a 340 ld a, (#SLOT_ADDR + 0x2) ; read modem IIR 341 ld l, a 342 ld a, h 343 out (#SLOT_DEVICE), a 344 ld h, #0x0 345 ret 346 347 348; int modem_lcr(void) 349; return modem LCR register in hl 350_modem_lcr:: 351 in a, (#SLOT_DEVICE) 352 ld h, a 353 ld a, #DEVICE_MODEM 354 out (#SLOT_DEVICE), a 355 ld a, (#SLOT_ADDR + 0x3) ; read LCR 356 ld l, a 357 ld a, h 358 out (#SLOT_DEVICE), a 359 ld h, #0x00 360 ret 361 362 363; int modem_lsr(void) 364; return modem LSR register in hl 365_modem_lsr:: 366 in a, (#SLOT_DEVICE) 367 ld h, a 368 ld a, #DEVICE_MODEM 369 out (#SLOT_DEVICE), a 370 ld a, (#SLOT_ADDR + 0x5) ; read LSR 371 ld l, a 372 ld a, h 373 out (#SLOT_DEVICE), a 374 ld h, #0x00 375 ret 376 377 378; int modem_msr(void) 379; return modem MSR register in hl 380_modem_msr:: 381 in a, (#SLOT_DEVICE) 382 ld h, a 383 ld a, #DEVICE_MODEM 384 out (#SLOT_DEVICE), a 385 ld a, (#SLOT_ADDR + 0x6) ; read modem MSR 386 ld (_modem_curmsr), a 387 ld l, a 388 ld a, h 389 out (#SLOT_DEVICE), a 390 ld h, #0x0 391 ret 392 393; void modem_hangup(void) 394; drop DTR to force a hangup 395_modem_hangup:: 396 push hl 397 in a, (#SLOT_DEVICE) 398 ld h, a 399 ld a, #DEVICE_MODEM 400 out (#SLOT_DEVICE), a 401 ld a, (#SLOT_ADDR + 0x4) ; read modem MCR 402 res 0, a ; drop DTR 403 ld (#SLOT_ADDR + 0x4), a 404 push af 405 push hl 406 ld hl, #500 407 push hl 408 call _delay ; sleep 500ms 409 pop hl 410 pop hl 411 pop af 412 set 0, a ; restore DTR 413 ld a, (#SLOT_ADDR + 0x6) 414 ld (_modem_curmsr), a 415 ld (#SLOT_ADDR + 0x4), a 416 ld a, (#SLOT_ADDR + 0x6) 417 ld (_modem_curmsr), a 418 ld a, h 419 out (#SLOT_DEVICE), a 420 pop hl 421 ret 422 423; void modem_pause(void) 424; send XOFF 425_modem_pause:: 426 push hl 427 ld l, #XOFF 428 push hl 429 call _modem_write 430 pop hl 431 pop hl 432 ld a, #0 433 ld (_modem_flowing), a 434 ret 435 436; void modem_unpause(void) 437; send XON 438_modem_unpause:: 439 push hl 440 ld l, #XON 441 push hl 442 call _modem_write 443 pop hl 444 pop hl 445 ret