.TITLE KERMIT-65 Hayes micro modem .SBTTL 6502 version - Ted Medin ; Version 1.0 ; Based on the KERMIT Protocol. ; $Header: apphmm.m65,v 1.8 90/10/15 14:23:32 medin Locked $ .SBTTL Define start address for assembly .=$1003 ;[39] Start assembly at hex 1003 .SBTTL Revision History ; ; Edit # Description ; ------ ----------- ; ;$Log: apphmm.m65,v $ Revision 1.8 90/10/15 14:23:32 medin new org of $7f00 for 3.87 version 1.8 ;Revision 1.7 88/12/22 09:26:51 medin ;use the time constant for the wait routine ;Revision 1.6 88/02/06 21:41:04 medin ; Correct bug in checking status for output ready. Happens only when ;host has asked us to stop flow. ;Change output routine to check for input ch ready before exiting. ;Revision 1.5 88/01/15 08:41:26 medin ;New origin for 3.81 ;Revision 1.4 87/06/29 10:39:29 medin ; Change wait routine to use apple rom wait, change org to work with 3.78. ;Revision 1.3 87/05/13 18:11:36 medin ; Change org to correspond with 3.76 ;Revision 1.2 87/02/21 00:01:58 medin ;Put the version in the hearld so we can keep track of the com drivers ;also. Thanks Rhoda. ;DONT FORGET TO UPDATE THE VERSION ;Revision 1.1 86/10/28 10:32:10 medin ;Initial revision ; ; ; Vector for com cards starts here ; location $1003 for data ; location $1020 for routine jumps ; location $1040 for main routines ; sscdbd: .blkb 1 ;[54]contains baud index(ala super serial card) used by init ; 6 - 300 baud ; 7 - 600 ; etc .blkb 1 ; crdnam: .word herld ;[54] null terminated string of who we are kersli: .blkb 1 ;[54] com slot $n0 kerins: .blkb 1 ;[54] force initialization flag-when 0 endker: .blkb 2 ;[54] address of end of main kermit flowfg: .blkb 1 ;flow control (xon xoff) flag true when hi bit set tl0end .word endcom ;[1.5] end of this routine timect .blkb 1 ;[1.7] 1 ms of delay via rom wait rtn .=sscdbd+29 ;[54] future expansion jmp tl2int ;[54] initialize com card jmp tl2cmd ;[54] command for ACIA in A ; ; 0 - hang up ; $0b - set baud ; $0c - set break on the line ; $91 - xon ; $93 - xoff ; ;[54] routine will return false(0) if unable jmp tl2cp ;[54] check for input ch ready-0 false jmp tl2gpc ;[54] get input ch jmp tl2ppc ;[54] put output character jmp tl2exi ;[54] reset card and restore initialized .=sscdbd+29+32 ;[54] futures ;[1.4]wait: .blkb 3 ;[54] wait routine-a reg contains milliseconds wait: .blkb 3 ;[1.4] apple rom wait rtn 220=125ms,206=108ms,25=2ms prstr: .blkb 3 ;[54] print string-x=lsb,y=msb of null terminated string urdkey: .blkb 3 ;[54] read keyboard prcrlf: .blkb 3 ;[54] print cr and lf telcnc .blkb 3 ;check for keyboard character telspa .blkb 3 ;set character parity ;[1.4] .=$7200 ;[54] place to start com card assembly .=$7f00 ;[1.8][1.5] place to start com card assembly start = . ;need a label at begining kr0pch = $c087 ;[12] Base for port char location (DC Hayes) kr0pst = $c086 ;[12] Base for port strobe locations (DC Hayes) kr0pcr = $c086 ;[41] Base for prot control register (DC Hayes) kr0pcc = $c085 ;[48] Modem control port kbd = $c000 ; Keyboard character input location cr = $d ; apinc1 = 3 ;[48] first init char for 6850 acia apinc2 = $11 ;[48] second init (8-bits) hctrlq = $91 ;^Q with high bit set hctrls = $93 ;^S " hctrlz = $9a ;^Z " ctrlq = $11 ;[59] ^Q ctrls = $13 ;[59] ^S setio2 = $fe93 ; place for pr#0 cswl = $36 cswh = $37 rdkey = $fd0c ; read a ch from current input device cout = $fded ; print a ch to current output device kwrk01 .byte ;[1.7] temp .byte ;[48] work space for dial pinptr .byte ; input buffer pointer inptr .byte ; input buffer pointer for get poutpt .byte ;[59] output buffer pointer outptr .byte ;[59] " " " for put ksli .byte ; com slot $0n dch.cr = $7f8 ;[41] Save area for Control register herld nasc 1 ;tell who we are bad nasc 1 dialms: nasc 1 ;[48] dialm2: nasc 1 ;[48] dialm3: nasc 1 ;[48] dialm4 nasc 1 ; ; D. C. Hayes I/O Device support - These routines support the ; D. C. Hayes Micromodem. ; tlini9: lda #1 ;[59] give true return rts ;[48] only way to reach this tl2int: lda #start^ cmp endker+1 ;are we loaded above main beq dontno ;cant tell yet bcc trble ;yes we are in trouble bcs setnm ;ok dontno lda #start\ ;well lets check 16 bits cmp endker beq setnm ;whee just exactly right bcs setnm ;ok trble ldx #bad\ ;got to tell someone ldy #bad^ jsr prstr ;print the message jsr prcrlf ;and terminate it properly setnm: init0: tlinit: ;[48] ldx kersli ;[48] get device slot lda kr0pch,x ;[48] access data lda kr0pst,x ;[48] now for the status and #4 ;[48] do we have a carrier? beq tlini9 ;[48] yes,carry on txa ; calculate $0n from $n0 lsr a lsr a lsr a lsr a sta ksli ; now we have $0slot ldx #dialm4\ ; tell about the delay ldy #dialm4^ jsr prstr jsr prcrlf ;and make it look nice lda cswl ; save output hooks pha lda cswh pha lda ksli ; now make it pr#slot jsr setio2+2 lda #hctrlq ; ^q starts dialing jsr cout lda #cr+$80 ; ^m end of dialing wait for carrier jsr cout lda #hctrlz ; ^z hang up jsr cout ;[1.4] lda #10 lda #20 ;[1.4] sta temp ; wait for 2.5 sec, slow phone co ;[1.4]tlini0 lda #250 ;[1.4] jsr wait ; .250 sec at a time ;[1.7]tlini0 lda #220 ;[1.4] 125 ms tlini0 lda #125 ;[1.7] 125 ms sta kwrk01 ;[1.7] tlinii lda timect ;[1.7] 1 ms at a time jsr wait ;[1.4] dec kwrk01 ;[1.7] bne tlinii ;[1.7] dec temp bne tlini0 pla ; we are now thru so restore output sta cswh pla sta cswl lda #$8d ;[48] go offhook to dial ldx kersli ;[48] get slot again and again and again ... sta kr0pcc,x ;[48] lda #apinc1 ;[48] init acia ch 1 sta kr0pch,x ;[48] lda #apinc2 ;[48] init acia ch 2 sta kr0pch,x ;[48] ;[1.4] lda #10 ;[48] now to wait 2.5 sec lda #20 ;[1.4] now to wait 2.5 sec 125ms at a time sta temp ;[48] ;[1.4]tlini2: lda #250 ;[48] 250 ms. ;[1.7]tlini2: lda #220 ;[1.4] 125 ms. tlini2: lda #125 ;[1.7] 125 ms. ;[1.4] jsr wait ;[48] there goes x again sta kwrk01 ;[1.7] 1 ms at a time tlinih lda timect ;[1.7] jsr wait ;[1.4] dec kwrk01 ;[1.7] bne tlinih ;[1.7] dec temp ;[48] bne tlini2 ;[48] all 2.5 sec? no ldx #dialms\ ;[48] now for the dial message ldy #dialms^ ;[48] jsr prstr ;[48] print it tlini5: jsr rdkey ;[48] get a ch from keyboard jsr cout ; and print it and #$7f ;[48] drop high bit cmp #'0 ;[48] you can never tell what one types bmi notnum ;[48] its not in the number range fro ascii cmp #$3a ;[48] well it may be a number bpl notnum ;[48] no, its too big and #$f ;[48] get the digits bne tlini3 ;[48] is it a zero lda #10 ;[48] yes, thats 10 pulses tlini3: sta temp ;[48] thats the count of pulses tlini4: lda #$d ;[48] go on hook ldx kersli ;[48] the slot again sta kr0pcc,x ;[48] tell the chip ;[1.4] lda #61 ;[48] this is a 61 ms delay ;[1.7] lda #154 ;[1.4] this is a 61 ms delay lda #61 ;[1.7] this is a 61 ms delay sta kwrk01 ;[1.7] tlinib lda timect ;[1.7] 1 ms at a time jsr wait ;[48] dec kwrk01 ;[1.7] bne tlinib ;[1.7] lda #$8d ;[48] off hook ldx kersli ;[48] you know what this is by now sta kr0pcc,x ;[48] tell ;[1.4] lda #39 ;[48] now for a 39 ms delay ;[1.7] lda #123 ;[1.4] now for a 39 ms delay lda #39 ;[1.7] now for a 39 ms delay sta kwrk01 ;[1.7] tlinif lda timect ;[1.7] 1 ms at a time jsr wait ;[48] dec kwrk01 ;[1.7] bne tlinif ;[1.7] dec temp ;[48] all the pulses ? bne tlini4 ;[48] no, keep on ;[1.4] lda #3 ;[48] wait for 600 ms lda #6 ;[1.4] wait for 600 ms sta temp ;[48] ;[1.4]tlini6: lda #200 ;[48] ;[1.7]tlini6: lda #198 ;[48] 100ms tlini6: lda #100 ;[1.7] 100ms sta kwrk01 ;[1.7] tlinig lda timect ;[1.7] 1 ms at a tiime jsr wait ;[48] dec kwrk01 ;[1.7] bne tlinig ;[1.7] dec temp ;[48] bne tlini6 ;[48] jmp tlini5 ;[48] get the next number notnum: cmp #cr ;[48] is this the end bne tlini5 ;[48] nope try for a number jsr prcrlf ;[48] make the screen look nice ldx #dialm2\ ;[48] now for the waiting msg ldy #dialm2^ ;[48] jsr prstr ;[48] print it ldx kersli ;[48] the slot again tlini8: bit kbd ;[48] do we have a ch from the keyboard bpl tlini7 ;[48] no, try for carrier jsr rdkey ; lets do this right lda #0 ;[48] ldx kersli ;[48] the slot again sta kr0pcc,x ;[48] hang up and give up lda #0 ; give a false return (0) rts ;[48]give a false return (0) tlini7: lda kr0pch,x ;[48] the data lda kr0pst,x ;[48] and now the status and #4 ;[48] carrier? bne tlini8 ;[48] not yet try again lda #$8f ;[48] originate mode+ap300+apoffh sta kr0pcc,x ;[48] tell jsr prcrlf ;[48] ldx #dialm3\ ;[48] tell we got carrier ldy #dialm3^ ;[48] jsr prstr ;[48] jsr prcrlf ;[48] lda #0 ;start the buffer at 0 sta pinptr sta inptr sta poutpt ;[59] " sta outptr ;[59] " lda #1 ; give a true return (non 0) rts ;[48] finally tl2cp: ldx kersli ;[12] Offset into I/O locations tl0cp1: lda kr0pst,x ;[12] Try for a character and #$01 ;[12] Check for receive register full beq tl0cp7 lda kr0pch,x ; get ch ldy pinptr ; get place to store sta inbuf,y ; in buf inc pinptr ; ready for next bit flowfg ;[59] how about flow control bpl tl0cp7 ;[59] no lda inbuf,y ;[59] get input ch and #$7f ;[59] drop parity etc ; bvc tl2cp4 ;[59] yes,how about ^S received?, no cmp #ctrlq ;[59] is this continue(start up outputing) bne tl2cp4 ;[59] no, check for ^S lda flowfg ;[59] tattle about the continue and #$bf ;[59] sta flowfg ;[59] dec pinptr ;[59] forget about this character tl2cp2 ldy outptr ;[59] see if any to output cpy poutpt ;[59] well? beq tl0cp7 ;[59] no more we have put all tl2cp3 lda kr0pst,x ;[59] check status for output ;[1.6] and #$10 ;[59] ready? and #2 ;[1.6] ready? beq tl2cp3 ;[59] no, spin lda outbuf,y ;[59] output ch sta kr0pch,x ;[59] bye inc outptr ;[59] ready for next jmp tl2cp2 ;[59] tl2cp4 cmp #ctrls ;[59] is this stop? bne tl0cp7 ;[59] no lda #$40 ;[59] yes, tattle ora flowfg ;[59] sta flowfg ;[59] now everyone knows dec pinptr ;[59] forget about the ^S character tl0cp7: lda pinptr cmp inptr ;[12] No character, return false(zero) ;[12] Successful return, return true(non 0) rts ;[12] ... tl2gpc: ldx inptr ;get where the ch is lda inbuf,x ;get ch inc inptr tl0rtc: rts ;[12] and return tl2ppc: pha ;[12] Hold the byte to send ldx kersli ;[12] Get I/O location offset tl0pp1: lda kr0pst,x ;[12] Get the status byte and #$02 ;[12] Isolate the flag we want (TRE) beq tl0pp2 ;[12] Transmit register is NOT empty, try again bit flowfg ;[59] flow control? bpl tl2pp0 ;[59] no bvc tl2pp0 ;[59] should we stop outputing?,no ldy poutpt ;[59] yes, save this ch in buffer pla ;[59] sta outbuf,y ;[59] inc poutpt ;[59] tell how many ;[1.6] rts ;[59] thats all jmp tl0cp1 ;[1.6] check for input and return tl2pp0 ;[59] pla ;[12] Fetch the data byte off the stack sta kr0pch,x ;[12] Stuff it at the proper loc to send it ;[1.6] rts ;[59] thats all jmp tl0cp1 ;[1.6] check for input and return tl0pp2: jsr tl0cp1 ;go check for an input ch jmp tl0pp1 ;try output again tl2exi: lda #0 ;tell we did this ldx kersli ;[47] get slot number sta kr0pcc,x ;shut it down exit9: rts tl2cmd: ;find out what command beq tl0drp ;its drop line cmp #$0c beq break ;its a break command cmp #$0b beq tl2rts ;its a set baud command and we cant cmp #hctrlq beq tl2sac ;its a xon command cmp #hctrls beq tl2sac ;its a xoff command tl2fls: lda #0 ;unknown command tl2rts: rts ;que passo ? return false(0) tl2sac: ldx flowfg ;do we have flow control bpl tl2fls ;no return false and #$7f ;drop high bit jsr telspa ;set parity jsr tl2ppc ;output the ch lda #1 ;return a true rts tl0drp: ldx kersli ;[47] get slot number sta kr0pcc,x ;shut it down lda #1 ;[54] true return rts break: ldy kersli ;[41] Get slot index,form = $n0 ldx ksli ; and $0n where n = slot lda dch.cr,x ;[41] Get saved Control Register ora #$60 ;[41] Set appropriate flags for break sta kr0pcr,y ;[41] Start break signal ;[1.4] lda #233 ;[41] Wait for 233 ms. ;[1.4] jsr wait ;[41] Do it, say goodby to x ;[1.7] lda #220 ;[1.4] Wait for 125 ms. lda #233 ;[1.7] Wait for 233 ms. sta kwrk01 ;[1.7] break3 lda timect ;[1.7] 1 ms at a time jsr wait ;[1.4] dec kwrk01 ;[1.7] bne break3 ;[1.7] ;[1.7] lda #206 ;[1.4] Wait for 108 ms a total of 233ms. ;[1.7] jsr wait ;[1.4] ;[1.7] ldx ksli ; restore x lda dch.cr,x ;[41] Get saved Control reg and #$9f ;[41] Reset flags ;[1.7] ldy kersli ;[41] Get slot index sta kr0pcr,y ;[41] Stop break signal rts ;[41] and return inbuf .blkb 256 ;input buffer outbuf .blkb 256 ;[59] output " endcom ;[1.5]