base:xmodem-send
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | base:xmodem-send [2015-04-17 04:34] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== XMODEM/CRC send ====== | ||
+ | < | ||
+ | ; XMODEM/CRC Sender for the 65C02 | ||
+ | ; | ||
+ | ; By Daryl Rictor Aug 2002 | ||
+ | ; | ||
+ | ; A simple file transfer program to allow upload from the SBC to a | ||
+ | ; console device utilizing the x-modem/CRC transfer protocol. | ||
+ | ; under 1k of either RAM or ROM, 132 bytes of RAM for the receive buffer, | ||
+ | ; and 8 bytes of zero page RAM for variable storage. | ||
+ | ; | ||
+ | ; | ||
+ | ; This implementation of XMODEM/CRC does NOT conform strictly to the | ||
+ | ; XMODEM protocol standard in that it (1) does not accurately time character | ||
+ | ; reception or (2) fall back to the Checksum mode. | ||
+ | |||
+ | ; (1) For timing, it uses a crude timing loop to provide approximate | ||
+ | ; delays. | ||
+ | ; found that CPU clock speed of up to 5MHz also work but may not in | ||
+ | ; every case. Windows HyperTerminal worked quite well at both speeds! | ||
+ | ; | ||
+ | ; (2) Most modern terminal programs support XMODEM/CRC which can detect a | ||
+ | ; wider range of transmission errors so the fallback to the simple checksum | ||
+ | ; calculation was not implemented to save space. | ||
+ | ; | ||
+ | ; | ||
+ | ; Files uploaded via XMODEM-CRC will have the load address contained in | ||
+ | ; the first two bytes in little-endian format: | ||
+ | ; FIRST BLOCK | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; Subsequent blocks | ||
+ | ; | ||
+ | ; | ||
+ | ; One note, XMODEM send 128 byte blocks. | ||
+ | ; you wish to save is smaller than the 128 byte block boundary, then | ||
+ | ; the last block will be padded with zeros. | ||
+ | ; data will be written back to the original location. | ||
+ | ; padded zeros WILL also be written into RAM, which could overwrite other | ||
+ | ; data. | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; zero page variables (adjust these to suit your needs) | ||
+ | ; | ||
+ | ; | ||
+ | lastblk = $35 ; | ||
+ | blkno = $36 ; | ||
+ | errcnt = $37 ; | ||
+ | |||
+ | crc = $38 ; | ||
+ | crch = $39 ; | ||
+ | |||
+ | ptr = $3a ; | ||
+ | ptrh = $3b ; | ||
+ | |||
+ | eofp = $3c ; | ||
+ | eofph = $3d ; | ||
+ | |||
+ | retry = $3e ; | ||
+ | retry2 = $3f ; | ||
+ | |||
+ | ; | ||
+ | ; | ||
+ | ; non-zero page variables and buffers | ||
+ | ; | ||
+ | ; | ||
+ | Rbuff = $0300 | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; tables and constants | ||
+ | ; | ||
+ | ; | ||
+ | ; The crclo & crchi labels are used to point to a lookup table to calculate | ||
+ | ; the CRC for the 128 byte data blocks. | ||
+ | ; tables. | ||
+ | ; file) and the other is to build them at run-time. | ||
+ | ; then these two labels will need to be un-commented and declared in RAM. | ||
+ | ; | ||
+ | ; | ||
+ | ;crchi = $7E00 | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; XMODEM Control Character Constants | ||
+ | SOH = $01 ; | ||
+ | EOT = $04 ; | ||
+ | ACK = $06 ; | ||
+ | NAK = $15 ; | ||
+ | CAN = $18 ; | ||
+ | CR = $0d ; | ||
+ | LF = $0a ; | ||
+ | ESC = $1b ; | ||
+ | |||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; Xmodem/CRC download routine | ||
+ | ; By Daryl Rictor, August 8, 2002 | ||
+ | ; | ||
+ | ; v0.1 code creation | ||
+ | ; | ||
+ | ; | ||
+ | *= $7800 ; Start of program (adjust to your needs) | ||
+ | ; | ||
+ | ; Enter this routine with the beginning address stored in the zero page address | ||
+ | ; pointed to by ptr & ptrh and the ending address stored in the zero page address | ||
+ | ; pointed to by eofp & eofph. | ||
+ | ; | ||
+ | ; | ||
+ | XModem jsr PrintMsg ; | ||
+ | lda # | ||
+ | sta errcnt ; | ||
+ | sta lastblk ; | ||
+ | lda # | ||
+ | sta blkno ; | ||
+ | Wait4CRC lda # | ||
+ | sta retry2 ; | ||
+ | jsr GetByte ; | ||
+ | bcc Wait4CRC ; | ||
+ | cmp #" | ||
+ | beq SetstAddr ; | ||
+ | cmp # | ||
+ | bne Wait4CRC ; | ||
+ | jmp PrtAbort ; | ||
+ | SetstAddr ldy # | ||
+ | ldx # | ||
+ | lda # | ||
+ | sta Rbuff ; | ||
+ | lda # | ||
+ | sta Rbuff+1 ; | ||
+ | lda ptr ; | ||
+ | sta Rbuff+2 ; | ||
+ | lda ptrh ; | ||
+ | sta Rbuff+3 ; | ||
+ | jmp Ldbuff1 ; | ||
+ | |||
+ | LdBuffer lda Lastblk ; | ||
+ | beq LdBuff0 ; | ||
+ | jmp Done ; yes, we're done | ||
+ | LdBuff0 ldx # | ||
+ | ldy # | ||
+ | inc Blkno ; | ||
+ | lda Blkno ; | ||
+ | sta Rbuff ; | ||
+ | eor # | ||
+ | sta Rbuff+1 ; | ||
+ | |||
+ | LdBuff1 lda (ptr), | ||
+ | sta Rbuff, | ||
+ | LdBuff2 sec ; | ||
+ | lda eofp ; | ||
+ | sbc ptr ; | ||
+ | bne LdBuff4 ; | ||
+ | lda eofph ; | ||
+ | sbc ptrh ; | ||
+ | bne LdBuff4 ; | ||
+ | inc LastBlk ; | ||
+ | LdBuff3 inx ; | ||
+ | cpx # | ||
+ | beq CalcCRC ; | ||
+ | lda # | ||
+ | sta Rbuff, | ||
+ | beq LdBuff3 ; | ||
+ | |||
+ | LdBuff4 inc ptr ; | ||
+ | bne LdBuff5 ; | ||
+ | inc ptrh ; | ||
+ | LdBuff5 inx ; | ||
+ | cpx # | ||
+ | bne LdBuff1 ; | ||
+ | |||
+ | CalcCRC lda # | ||
+ | sta crc ; | ||
+ | sta crch ; | ||
+ | ldy # | ||
+ | CalcCRC1 lda Rbuff, | ||
+ | jsr UpdCRC ; | ||
+ | iny ; | ||
+ | cpy # | ||
+ | bne CalcCRC1 ; | ||
+ | lda crch ; | ||
+ | sta Rbuff, | ||
+ | iny ; | ||
+ | lda crc ; | ||
+ | sta Rbuff, | ||
+ | Resend ldx # | ||
+ | lda # | ||
+ | jsr Put_Chr ; | ||
+ | SendBlk lda Rbuff, | ||
+ | jsr Put_chr ; | ||
+ | inx ; | ||
+ | cpx # | ||
+ | bne SendBlk ; | ||
+ | lda # | ||
+ | sta retry2 ; | ||
+ | jsr GetByte ; | ||
+ | bcc Seterror ; | ||
+ | cmp # | ||
+ | beq LdBuffer ; | ||
+ | cmp # | ||
+ | beq Seterror ; | ||
+ | cmp # | ||
+ | beq PrtAbort ; | ||
+ | ; fall through to error counter | ||
+ | Seterror inc errcnt ; | ||
+ | lda errcnt ; | ||
+ | cmp # | ||
+ | bne Resend ; | ||
+ | PrtAbort jsr Flush ; | ||
+ | jmp Print_Err ; | ||
+ | Done Jmp Print_Good ; | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; subroutines | ||
+ | ; | ||
+ | ; ; | ||
+ | GetByte lda # | ||
+ | sta retry ; | ||
+ | StartCrcLp jsr Get_chr ; | ||
+ | bcs GetByte1 ; | ||
+ | dec retry ; | ||
+ | bne StartCrcLp ; | ||
+ | dec retry2 ; | ||
+ | bne StartCrcLp ; | ||
+ | clc ; if loop times out, CLC, else SEC and return | ||
+ | GetByte1 rts ; | ||
+ | ; | ||
+ | Flush lda # | ||
+ | sta retry2 ; | ||
+ | Flush1 jsr GetByte ; | ||
+ | bcs Flush ; | ||
+ | rts ; else done | ||
+ | ; | ||
+ | PrintMsg ldx # | ||
+ | PrtMsg1 lda | ||
+ | beq PrtMsg2 | ||
+ | jsr Put_Chr | ||
+ | inx | ||
+ | bne PrtMsg1 | ||
+ | PrtMsg2 rts | ||
+ | Msg .byte " | ||
+ | .BYTE | ||
+ | | ||
+ | ; | ||
+ | Print_Err ldx # | ||
+ | PrtErr1 lda | ||
+ | beq PrtErr2 | ||
+ | jsr Put_Chr | ||
+ | inx | ||
+ | bne PrtErr1 | ||
+ | PrtErr2 rts | ||
+ | ErrMsg .byte " | ||
+ | .BYTE | ||
+ | .byte 0 | ||
+ | ; | ||
+ | Print_Good ldx # | ||
+ | Prtgood1 lda | ||
+ | beq Prtgood2 | ||
+ | jsr Put_Chr | ||
+ | inx | ||
+ | bne Prtgood1 | ||
+ | Prtgood2 rts | ||
+ | GoodMsg .byte EOT, | ||
+ | .byte " | ||
+ | .BYTE | ||
+ | .byte 0 | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; I/O Device Specific Routines | ||
+ | ; | ||
+ | ; Two routines are used to communicate with the I/O device. | ||
+ | ; | ||
+ | ; " | ||
+ | ; return without waiting with the Carry flag CLEAR if no character is | ||
+ | ; present or return with the Carry flag SET and the character in the " | ||
+ | ; register if one was present. | ||
+ | ; | ||
+ | ; " | ||
+ | ; if this routine waits for the port to be ready. | ||
+ | ; character was send upon return from this routine. | ||
+ | ; | ||
+ | ; Here is an example of the routines used for a standard 6551 ACIA. | ||
+ | ; You would call the ACIA_Init prior to running the xmodem transfer | ||
+ | ; routine. | ||
+ | ; | ||
+ | ACIA_Data = $7F70 ; | ||
+ | ACIA_Status = $7F71 ; | ||
+ | ACIA_Command = $7F72 ; | ||
+ | ACIA_Control = $7F73 ; | ||
+ | |||
+ | ACIA_Init | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ; | ||
+ | ; input chr from ACIA (no waiting) | ||
+ | ; | ||
+ | Get_Chr clc ; | ||
+ | | ||
+ | | ||
+ | beq Get_Chr2 ; | ||
+ | | ||
+ | | ||
+ | Get_Chr2 | ||
+ | ; | ||
+ | ; output to OutPut Port | ||
+ | ; | ||
+ | Put_Chr | ||
+ | Put_Chr1 | ||
+ | and # | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; CRC subroutines | ||
+ | ; | ||
+ | ; | ||
+ | UpdCrc eor crc+1 ; Quick CRC computation with lookup tables | ||
+ | | ||
+ | lda crc ; with the byte send in the " | ||
+ | eor CRCHI,X | ||
+ | sta crc+1 | ||
+ | lda CRCLO,X | ||
+ | sta crc | ||
+ | rts | ||
+ | ; | ||
+ | ; Alternate solution is to build the two lookup tables at run-time. | ||
+ | ; be desirable if the program is running from ram to reduce binary upload time. | ||
+ | ; The following code generates the data for the lookup tables. | ||
+ | ; un-comment the variable declarations for crclo & crchi in the Tables and Constants | ||
+ | ; section above and call this routine to build the tables before calling the | ||
+ | ; " | ||
+ | ; | ||
+ | ; | ||
+ | ; ldx #$00 | ||
+ | ; LDA #$00 | ||
+ | ; | ||
+ | ; sta crchi,x | ||
+ | ; inx | ||
+ | ; | ||
+ | ; ldx #$00 | ||
+ | ;fetch txa | ||
+ | ; | ||
+ | ; | ||
+ | ; ldy #$08 | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; eor #$10 | ||
+ | ; | ||
+ | ; | ||
+ | ; eor #$21 | ||
+ | ; | ||
+ | ; | ||
+ | ; | ||
+ | ; inx | ||
+ | ; | ||
+ | ; rts | ||
+ | ; | ||
+ | ; The following tables are used to calculate the CRC for the 128 bytes | ||
+ | ; in the xmodem data blocks. | ||
+ | ; store this program in ROM. If you choose to build them at run-time, | ||
+ | ; then just delete them and define the two labels: crclo & crchi. | ||
+ | ; | ||
+ | ; low byte CRC lookup table (should be page aligned) | ||
+ | *= $7c00 | ||
+ | crclo | ||
+ | .byte $00, | ||
+ | .byte $31, | ||
+ | .byte $62, | ||
+ | .byte $53, | ||
+ | .byte $C4, | ||
+ | .byte $F5, | ||
+ | .byte $A6, | ||
+ | .byte $97, | ||
+ | .byte $88, | ||
+ | .byte $B9, | ||
+ | .byte $EA, | ||
+ | .byte $DB, | ||
+ | .byte $4C, | ||
+ | .byte $7D, | ||
+ | .byte $2E, | ||
+ | .byte $1F, | ||
+ | |||
+ | ; hi byte CRC lookup table (should be page aligned) | ||
+ | *= $7d00 | ||
+ | crchi | ||
+ | .byte $00, | ||
+ | .byte $12, | ||
+ | .byte $24, | ||
+ | .byte $36, | ||
+ | .byte $48, | ||
+ | .byte $5A, | ||
+ | .byte $6C, | ||
+ | .byte $7E, | ||
+ | .byte $91, | ||
+ | .byte $83, | ||
+ | .byte $B5, | ||
+ | .byte $A7, | ||
+ | .byte $D9, | ||
+ | .byte $CB, | ||
+ | .byte $FD, | ||
+ | .byte $EF, | ||
+ | ; | ||
+ | ; | ||
+ | ; End of File | ||
+ | ; | ||
+ | </ |
base/xmodem-send.txt · Last modified: 2015-04-17 04:34 by 127.0.0.1