; Micro-SCI / Franklin "Technician Mode" firmware ; ; Thanks to S.Elliott@AppleFritter for comments/analysis .setcpu "6502" .org $c600 A2L := $3e SLOTx16 := $fd ; motherboard IO ports KBD := $C000 KBDSTRB := $C010 ; DEVSEL ports, accessed via SLOTx16 in X reg STEPOFF := $C080 STEPON := $C081 MOTOROFF := $C088 MOTORON := $C089 Q6OFF := $C08C Q6ON := $C08D Q7OFF := $C08E Q7ON := $C08F MON_WAIT := $FCA8 GETLNZ := $FD67 BELL := $FF3A IORTS := $FF58 GETNUM := $FFA7 KEY_POUND := $A3 KEY_S := $EC KEY_W := $F0 KEY_Z := $F3 KEY_M := $06 KEY_R := $EB KEY_X := $F1 KEY_Q := $EA lda #KEY_POUND sta $33 ; set input-prompt character to '#' LC604: jsr BELL LC607: jsr GETLNZ ; start new line and take input lda #$00 sta $F2 PARSER: sta KBDSTRB ; clear keyboard strobe sta $F3 ldy $F2 jsr GETNUM ; parse hex into A2, A has last char xor $b0 ; plus $89 sty $F2 cmp #$C6 ; $C6 from $8D (return) beq LC607 ; no more input, go prompt for new input cmp #KEY_S ; 'S' beq CMD_S cmp #KEY_W ; 'W' beq CMD_W cmp #KEY_Z ; 'Z' beq CMD_Z ldy #$7F cmp #KEY_M ; 'M' beq CMD_MX cmp #KEY_R ; 'R' beq CMD_R ldx #$06 stx $F3 cmp #KEY_X ; 'X' beq CMD_MX cmp #KEY_Q ; 'Q' bne LC604 ; BEEP and prompt for new input brk ; 'Q' exits out ; 'R': recalibrate by seeking track 0 from track 80 CMD_R: lda #80 ; set starting track sta $FC ; store accumulator as 'current' track at $FC txa ; set accumulator to 0 adc #$00 ; inc A (carry still set from CMP #$EB) sta $F3 ; set ($F3)=01 lda #$00 ; pass target track 0 through accumulator beq LC651 ; branch to end of 'S' command to finish ; 'S': seek logical-track index in A2L ('22S' seeks logical track $22) CMD_S: lda A2L ; load logical track-index from A2L asl a ; convert to physical track-index LC651: sta $F0 ; store accumulator as target track at $F0 ldy #$FF ; value to be stored at $09 = #$FF bne CMD_MX ; branch to 'M' command for next step ; 'Z': seek logical-track index in A2L (eg: "22Z" seeks logical track $22) CMD_Z: lda A2L ; load logical track-index from A2L asl a ; convert to physical track-index sta $F1 ; store as target track in $F1 ldy #$00 ; value to stored at $09 = #$00 beq CMD_MX ; branch to 'M' command for next step ; temporarily stop motor, then branch to turn it on again STOP_MOTOR: lda #$50 jsr MON_WAIT sta MOTOROFF,x ldy A2L LC66A: jsr MON_WAIT dey bpl LC66A bmi LC68E ; EXIT THRU GIFT SHOP, current command finished, go back to parser DONE: lda #$00 beq PARSER ; 'W' command, write nibble-pattern in A2L (eg: "96W" writes 96 96 96...) CMD_W: lda A2L ; pattern to write sta $FF ldy #$0F ; 'M' command while Y=#7F and X=#00 ; 'X' command while Y=#7F and X=#06 and ($f3)=#06 CMD_MX: sty $09 ; preserve actual command jsr IORTS ; put our address on stack tsx lda $0100,x ; derive our DEVSEL index asl a asl a asl a asl a sta SLOTx16 ; save DEVSEL index for future IO adc $F3 tax LC68E: sta MOTORON,x lda $09 beq LC6BA ; Y=00, branch for 'Z' bmi LC6BA ; Y=FF, branch for 'S' asl a bmi LC6AC sta Q7ON,x ; start writing/erasing LC69D: lda $09 ; [3 cycles] reload saved Y byte asl a ; [2] shift-left to test second bit bmi STOP_MOTOR ; [2] branch to stop motor for M/X/S commands nop nop lda $FF ; byte value to be written sta Q6ON,x ; store into data register ; (wrong timing for Disk II, it would probably ; write $DD instead) cmp Q6OFF,x ; [4] shift data-out LC6AC: lda KBD ; get keypress eor #$9B ; ESC? bne LC69D ; if not, continue loop ldx SLOTx16 sta Q7OFF,x LC6B8: beq DONE ; all done, branch to branch-to-parser LC6BA: ldx SLOTx16 sta MOTORON,x LC6BF: ldy $FC LC6C1: cpy $F0 ; compare track index in Y to target track (result in carry flag) bne LC6E3 ; track doesn't match, go to stepper routine lda $F0 ; load current track into A (why not tya?) sta $FC ; store current track lda $09 bne DONE ; Y=00, branch for 'Z' lda $F0 ; exchange target track indexes in $F0 vs $F1 ldy $F1 sta $F1 sty $F0 lda KBD ; read current key value eor #$9B ; $9B = beq LC6B8 ; if current key is then branch lda #$73 jsr MON_WAIT ; delay for mechanical seek time bcs LC6BF LC6E3: bcs LC6E7 ; track numbers increasing or decreasing? iny ; increment track number in Y reg iny ; decrement track number in Y reg LC6E7: dey tya and #$03 ; mask track to just 4 low bits, numbers 00-01-02-03 asl a ; shift left, convert to stepper-motor phases 02-04-06-08 ora SLOTx16 ; bitwise-OR for DEVSEL-relative IO address tax ; move it into X for IO lsr a ; shift right to make track number again lsr a ; shift low-bit into carry flag (odd vs even) sta STEPON,x ; turn on stepper motor phase indicated in X nop ; dead code nop lda #$56 jsr MON_WAIT ; wait stepper delay (returns A=00, carry set) sta STEPOFF,x ; turn off stepper motor phase indicated in X bcs LC6C1 ; branch always