OpenCores
URL https://opencores.org/ocsvn/rf6809/rf6809/trunk

Subversion Repositories rf6809

[/] [rf6809/] [trunk/] [software/] [boot/] [xmodem.asm] - Rev 21

Compare with Previous | Blame | View Log

; ============================================================================
;        __
;   \\__/ o\    (C) 2022  Robert Finch, Waterloo
;    \  __ /    All rights reserved.
;     \/_//     robfinch<remove>@opencores.org
;       ||
;  
;
; BSD 3-Clause License
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;
; 1. Redistributions of source code must retain the above copyright notice, this
;    list of conditions and the following disclaimer.
;
; 2. Redistributions in binary form must reproduce the above copyright notice,
;    this list of conditions and the following disclaimer in the documentation
;    and/or other materials provided with the distribution.
;
; 3. Neither the name of the copyright holder nor the names of its
;    contributors may be used to endorse or promote products derived from
;    this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;                                                                          
; ============================================================================
;
; Xmodem variables
;
xm_timer                                EQU             $FFC020
xm_protocol                     EQU             $9F5
xm_flag                                 EQU             $9F6
xm_checksum                     EQU             $9F7
xm_tmp2                                 EQU             $9F8
xm_packetnum            EQU             $9FA
xm_tmp                                  EQU             $9FC
xm_crc                                  EQU             $9FE
xm_ibuf                                 EQU             $A00    ; to $A7F
xm_obuf                                 EQU             $A80    ; to $AFF

; ------------------------------------------------------------------------------
; Send data using XModem.
; ------------------------------------------------------------------------------

xm_SendStart:
        lbsr    GetRange
        ldx             mon_r1+2                                ; x = buffer address
        tfr             x,u
        ldb             #1                                                      ; packet numbers start at one
        stb             xm_packetnum+1
        ; Wait for receiver to send a NAK
xm_send:                                                        
        ldd             #-1                                                     ; select blocking input
        swi
        fcb             MF_INCH
        cmpb    #NAK                                            ; should have got a NAK
        beq             xm_send5
        cmpb    #'C'                                            ; or a 'C'
        bne             xm_send
xm_send5:
        stb             xm_protocol
xm_send4:
        ldb             #SOH                                            ; send start
        swi
        fcb             OUTCH                   
        ldb             xm_packetnum+1  ; send packet number
        swi
        fcb             MF_OUTCH
        comb                                                                    ; one's complement
        swi
        fcb             MF_OUTCH                                ; send packet number complement
        clra                                                                    ; acca = byte count
        tfr             x,u                                                     ; u = buffer address
xm_send1:
        ldb             ,u+                                                     ; grab a byte from the buffer
        swi
        fcb             MF_OUTCH                                ; send it out
        inca
        cmpa    #128                                            ; number of bytes in payload
        blo             xm_send1
        ldb             xm_protocol
        cmpb    #'C'                                            ; CRC protocol?
        bne             xm_send2
        bsr             xm_calc_crc                     ; compute CRC
        ldd             xm_crc                                  ; get crc
        lsra                                                                    ; transfer high eight bits first, so
        rorb                                                                    ; right shift D by eight
        lsra
        rorb
        lsra
        rorb
        lsra
        rorb
        lsra
        rorb
        lsra
        rorb
        lsra
        rorb
        lsra
        rorb
        swi
        fcb             MF_OUTCH                                ; send out the byte
        ldd             xm_crc                                  ; get back CRC
        swi                                                                     
        fcb             MF_OUTCH                                ; and send out low byte
        bra             xm_send3
xm_send2:
        bsr             xm_calc_checksum
        ldb             xm_checksum
        swi
        fcb             MF_OUTCH
xm_send3:
        swi
        ldd             #-1                                                     ; block until input is present
        fcb             MF_INCH
        cmpb    #ACK
        bne             xm_send4                                ; not an ACK then resend the record
        inc             xm_packetnum            ; increment packet number
        leax    128,x                                           ; advance buffer pointer
        cmpx    mon_r2+2
        blo             xm_send4                                ; go send next record
        ldb             #EOT                                            ; send end of transmission
        swi
        fcb             MF_OUTCH
        swi
        fcb             MF_OUTCH
        swi
        fcb             MF_OUTCH
        rts

; ------------------------------------------------------------------------------
; Get a byte, checking for a receive timeout.
;
; Returns:
;               accb = byte (0 to 255) or -1 if timed out
; ------------------------------------------------------------------------------

xm_getbyte:
xm_gb1:
        tst             xm_timer                ; check the timeout - 2048 ticks (3 seconds approx.)
        bmi             xm_gb2
        clra                                                    ; non-blocking
        clrb
        swi     
        fcb             MF_INCH                 ; try and get a character
        bmi             xm_gb1                  ; if no character, try again
        bsr             xm_outbyteAsHex
        rts
xm_gb2:
        ldb             #-1
        rts

; ------------------------------------------------------------------------------
; XModem Receive
;
; Parameters:
;               none
; Modifies:
;               All
;       Returns:
;               none
; ------------------------------------------------------------------------------

xm_ReceiveStart:
        lbsr    Delay3s                         ; give a little bit of time for sender
        lbsr    Delay3s
        lbsr    Delay3s
        lbsr    GetNumber                       ; Get the transfer address
        tstb                                                            ; Make sure we got a value
        lbeq    Monitor
        ldx             mon_numwka+2    ; X = transfer address
        clr             xm_packetnum    ; initialize
        lda             #'C'                                    ; try for CRC first
        sta             xm_protocol
xm_receive:
        lda             #2                                              ; number of times to retry -1
xm_rcv5:
        ldb             xm_protocol             ; indicate we want a transfer (send protocol byte)
        swi
        fcb             MF_SerialPutchar
xm_rcv4:
        clr             xm_timer                ; clear the timeout
xm_rcv1:
        bsr             xm_getbyte
        tstb
        bmi             xm_retry1               ; timeout on protocol id?
        cmpb    #SOH                            ; it should be start of a transfer
        beq             xm_SOH
        cmpb    #EOT
        beq             xm_EOT                  ; or end of transfer (EOT)
        cmpb    #CAN
        beq             xm_receive      ; might be a cancel
        cmpb    #ETB
        beq             xm_EOT
xm_rcv_nak:                                     ; wasn't a valid start so
        ldb             #NAK                            ; send a NAK
        swi
        fcb             MF_SerialPutchar        ; and try again
        bra             xm_rcv4
xm_SOH:
        bsr             xm_getbyte      ; get packet number
        bmi             xm_rcv_to1
        stb             xm_packetnum+1
        pshs    b                                               ; save it
        bsr             xm_getbyte      ; get complement of packet number
        bmi             xm_rcv_to2
        addb    ,s                                      ; add the two values
        andb    #$FF                            ; the sum should be $FF
        subb    #$FF
        stb             xm_flag                 ; should be storing a zero if there is no error
        ldy             #0                                      ; y = payload byte counter
        tfr             x,u
xm_rcv2:
        bsr             xm_getbyte
        bmi             xm_rcv_to1
        stb             ,u+                                     ; store the byte to memory
        iny
        cmpy    #128                            ; 128 bytes per payload
        blo             xm_rcv2
        bsr             xm_getbyte      ; get checksum or CRC byte
        bmi             xm_rcv_to1
        stb             xm_tmp                  ; stuff checksum/CRC byte
        ldb             xm_protocol
        cmpb    #'C'
        bne             xm_rcv_chksum
        bsr             xm_getbyte      ; get low order CRC byte
        bmi             xm_rcv_to1
        lda             xm_tmp                  ; get the high byte
        aslb                                                    ; prepare to combine high and low order
        aslb
        aslb
        aslb
        lsra                                                    ; shift low nybble of acca into accb
        rorb
        lsra
        rorb
        lsra
        rorb
        lsra
        rorb
        anda    #$00F                                   ; mask off any extra bits
        std     xm_tmp2
        bsr             xm_calc_crc             ; compute the CRC-16 for the received data
        ldd             xm_crc                          ; and compare to received value
        cmpd    xm_tmp2
        bra             xm_rcv3
xm_rcv_chksum:
        bsr             xm_calc_checksum
        ldb             xm_checksum
        cmpb    xm_tmp                          ; where we stuffed the byte
xm_rcv3:
        bne             xm_rcv_nak              ; if not the same, NAK
        tst             xm_flag
        bne             xm_rcv_nak              ; bad packet number?
        ldb             #ACK                                    ; packet recieved okay, send back an ACK
        swi
        fcb             MF_SerialPutchar
        ldb             xm_packetnum+1  ; did we receive the same packet
        cmpb    xm_packetnum
        beq             xm_rcv4                         ; same packet received, dont update buffer pointer
        stb             xm_packetnum    ; update last seen packet number
        leax    128,x                                   ; increment buffer pointer
        bra             xm_rcv4                         ; and go back for next packet
xm_rcv_to2:
        leas    1,s                                             ; get rid of stacked byte
xm_rcv_to1:
        ldd             #msgXmTimeout
        swi
        fcb             MF_DisplayString
        lbra    Monitor
xm_EOT:                                                         ; end of transmission received, return
        ldb             #ACK                                    ; ACK the EOT
        swi
        fcb             MF_SerialPutchar
        lbra    Monitor
xm_retry1:
        deca
        bpl             xm_rcv5
        lda             xm_protocol
        cmpa    #NAK                                    ; are we already lowered down to checksum protocol?
        beq             xm_noTransmitter        ; did we try both checksum and CRC?
        lda             #NAK
        sta             xm_protocol
        bra             xm_receive
xm_noTransmitter:
        ldd             #msgXmNoTransmitter
        swi
        fcb             MF_DisplayString
        lbra    Monitor 

msgXmTimeout:
        fcb             "Xmodem: timed out",CR,LF,0
msgXmNoTransmitter:
        fcb             "XModem: transmitter not responding",CR,LF,0

; ------------------------------------------------------------------------------
; Calculate checksum value. The checksum is simply the low order eight bits of
; the sum of all the bytes in the payload area.
;
; Stack space:
;               two words
;       Modifies:
;               xm_checksum             contains the checksum value for the record
; Parameters:
;               X = buffer address
;       Returns:
;               none
; ------------------------------------------------------------------------------

xm_calc_checksum:
        pshs    d,x
        clra
        clrb
xm_cs1:
        addb    ,x+
        inca
        cmpa    #128
        blo             xm_cs1
        andb    #$FF
        stb             xm_checksum
        puls    d,x,pc

; ------------------------------------------------------------------------------
; Compute CRC-16 of buffer.
;
;int calcrc(char *ptr, int count)
;{
;    int  crc;
;    char i;
;    crc = 0;
;    while (--count >= 0)
;    {
;        crc = crc ^ (int) (*ptr++ << 8);
;        i = 8;
;        do
;        {
;            if (crc & 0x8000)
;                crc = crc << 1 ^ 0x1021;
;            else
;                crc = crc << 1;
;        } while(--i);
;    }
;    return (crc);
;}
;
; Modifies:
;               xm_crc variable
; Parameters:
;               u = buffer address
; Returns:
;               none
; ------------------------------------------------------------------------------

xm_calc_crc:
        pshs    d,x,y,u
        clr             xm_crc
        clr             xm_crc+1        
        ldu             #0                                      ; u = byte count
xm_crc1:
        ldb             ,x+                                     ; get byte
        clr             xm_tmp                  ; save in temp
        stb             xm_tmp+1
        asl             xm_tmp+1                ; shift temp eight bits to left         
        rol             xm_tmp
        asl             xm_tmp+1
        rol             xm_tmp
        asl             xm_tmp+1
        rol             xm_tmp
        asl             xm_tmp+1
        rol             xm_tmp
        asl             xm_tmp+1
        rol             xm_tmp
        asl             xm_tmp+1
        rol             xm_tmp
        asl             xm_tmp+1
        rol             xm_tmp
        asl             xm_tmp+1
        rol             xm_tmp
        ldd             xm_crc          ; crc = crc ^ tmp
        eora    xm_tmp
        eorb    xm_tmp+1
        std             xm_crc
        ldy             #0
xm_crc4:
        ldb             xm_crc          ; get high byte
        bitb    #$8                             ; check for $8000
        beq             xm_crc2         ; no? then just go shift
        ldd             xm_crc          ; load
        aslb                                            ; shift
        rola
        eorb    #$021                   ; and xor
        eora    #$001
        std             xm_crc          ; store it back
        bra             xm_crc3
xm_crc2:
        ldd             xm_crc          ; load
        aslb                                            ; shift
        rola
        std             xm_crc          ; and store
xm_crc3:
        iny
        cmpy    #8                              ; repeat eight times
        blo             xm_crc4
        leau    1,u                             ; increment byte count
        cmpu    #128
        ldd             xm_crc          ; we want only a 16-bit CRC
        anda    #$0F
        std             xm_crc
        blo             xm_crc1
        puls    d,x,y,u,pc

xm_outbyteAsHex:
        pshs    d
        ldd             CharOutVec                                              ; get current char out vector
        pshs    d                                                                                       ; save it
        ldd             #ScreenDisplayChar              ; set output vector to screen display
        std             CharOUtVec
        ldd             2,s                                                                             ; get passed data
        lbsr    DispByteAsHex                                   ; and display on-screen
        ldb             #' '
        lbsr    ScreenDisplayChar
        puls    d                                                                                       ; get back old char out vector
        std             CharOutVec                                              ; and restore it
        puls    d                                                                                       ; restore input arguments
        rts

        

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.