Subversion Repositories svn.mios

Rev

Blame | Last modification | View Log | RSS feed

; $Id: tia_sysex.inc bdupeyron.tech@gmail.com(Antichambre)
;
; MIDIbox TIA SysEx Parser
;
; ==========================================================================
;
;  Copyright 1998-2006 Thorsten Klose (tk@midibox.org)
;  Licensed for personal non-commercial use only.
;  All other rights reserved.
; 
; ==========================================================================

TIA_SYSEX_STATE_MYSYSEX     EQU 7
TIA_SYSEX_STATE_ACTION      EQU 6

TIA_SYSEX_STATE_PRESET_RECEIVED EQU 5   ; used by Action PATCH_[Read/Write]
TIA_SYSEX_STATE_BANK_RECEIVED   EQU 4   ; used by Action PATCH_[Read/Write]
TIA_SYSEX_STATE_TYPE_RECEIVED   EQU 3   ; used by Action PATCH_[Read/Write]
TIA_SYSEX_STATE_WAIT_CHECKSUM   EQU 2   ; used by Action PATCH_Write

TIA_SYSEX_STATE_AH_RECEIVED EQU 5   ; used by Action PAR_[Read/Write]
TIA_SYSEX_STATE_AL_RECEIVED EQU 4   ; used by Action PAR_[Read/Write]
TIA_SYSEX_STATE_D_RECEIVED  EQU 3   ; used by Action PAR_[Write]

TIA_SYSEX_STATE_A_RECEIVED  EQU 5   ; used by Action CFG_[Read/Write]
TIA_SYSEX_STATE_DH_RECEIVED EQU 4   ; used by Action CFG_[Read/Write]
TIA_SYSEX_STATE_DL_RECEIVED EQU 3   ; used by Action CFG_[Read/Write]

;; --------------------------------------------------------------------------
;;  This sysex parser waits for the TIA Header 
;; --------------------------------------------------------------------------
TIA_SYSEX_SysExCheck
    ;; store received byte in TIA_SYSEX_IN
    movwf   TIA_SYSEX_IN

    ;; ignore realtime messages
    movlw   0xf8
    cpfslt  TIA_SYSEX_IN, ACCESS
    return

    ;; check sysex state
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_MYSYSEX, ACCESS, TIA_SYSEX_Handler

    movf    TIA_SYSEX_STATE, W
    rcall   TIA_SYSEX_SysExHeaderGet
    cpfseq  TIA_SYSEX_IN, ACCESS
    rgoto TIA_SYSEX_SysExCheckFailed
    incf    TIA_SYSEX_STATE, F
    movf    TIA_SYSEX_STATE, W
    andlw   0x07
    xorlw   0x06    ; wait for 6 bytes (f0 00 00 7E 46 <device-id>)
    bnz TIA_SYSEX_SysExCheckOk

    ;; SysEx ID received, lets go
    movlw   (1 << TIA_SYSEX_STATE_MYSYSEX)
    movwf   TIA_SYSEX_STATE
    call    MIOS_MPROC_MergerDisable
    rgoto   TIA_SYSEX_SysExCheckOk

TIA_SYSEX_SysExCheckFailed
    ;; reset the sysex counter and action ID
    rcall   TIA_SYSEX_ActionInvalid
TIA_SYSEX_SysExCheckOk

TIA_SYSEX_SysExCheck_End
    return

; ==========================================================================

;; --------------------------------------------------------------------------
;;  Returns expected MIDI bytes from SysEx header
;; --------------------------------------------------------------------------
TIA_SYSEX_SysExHeaderGet
    andlw   0x07
    JUMPTABLE_2BYTES_UNSECURE
    retlw   0xf0
    retlw   0x00        ; Vendor ID
    retlw   0x00
    retlw   0x7e
    retlw   0x51        ; MIDIbox TIA ID (51 - the ultimative number + 4)
    movf    TIA_MIDI_DEVICE, W
    return

;; --------------------------------------------------------------------------
;;  Action Invalid will be invoked when receiving an invalid sequence
;; --------------------------------------------------------------------------
TIA_SYSEX_ActionInvalid

;; --------------------------------------------------------------------------
;;  Action finished will be invoked when midi action is done
;; --------------------------------------------------------------------------
TIA_SYSEX_ActionFinished
    clrf    TIA_SYSEX_STATE
    clrf    TIA_SYSEX_ACTION
#if DEFAULT_TIA_DEBUG_ON == 1 
    bsf TIA_DEBUG_EE_REGA, TIA_DEBUG_EE_SYX
    call    TIA_Debug_EE_Do
    bsf TIA_DEBUG_BS_REGA, TIA_DEBUG_EE_SYX
    call    TIA_Debug_BS_Do
#endif
    ;; reinit patch if engine has been disabled during upload
    bcf TIA_STAT, TIA_STAT_ENGINE_DISABLE
    
    call    MIOS_MPROC_MergerEnable
    rgoto   TIA_SYSEX_SysExCheck_End


;; --------------------------------------------------------------------------
;;  MIDI Check action: perform a sysex action
;; --------------------------------------------------------------------------
TIA_SYSEX_Handler
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_ACTION, ACCESS, TIA_SYSEX_Handler_DoAction

    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_ACTION

    movff   TIA_SYSEX_IN, TIA_SYSEX_ACTION  ; store action ID
    rcall   TIA_SYSEX_Handler_InitAction    ; initialize the action
    rgoto   TIA_SYSEX_SysExCheck_End    ; branch to the end

    ;; ---

TIA_SYSEX_Handler_DoAction
    ;; branch to end if status byte (i.e. F7)
    BRA_IFSET TIA_SYSEX_IN, 7, ACCESS, TIA_SYSEX_Handler_EndAction

    ;; branch depending on current action ID
    movf    TIA_SYSEX_ACTION, W
    JUMPTABLE_2BYTES 16 ; 16 entries
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_Action_PRESET_Read
    rgoto   TIA_SYSEX_Action_PRESET_Write
    rgoto   TIA_SYSEX_Action_BANK_Read
    rgoto   TIA_SYSEX_Action_BANK_WriteName
    rgoto   TIA_SYSEX_Action_PAR_Read
    rgoto   TIA_SYSEX_Action_PAR_Write
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_Action_BANK_Sel
    rgoto   TIA_SYSEX_Action_CFG_Read
    rgoto   TIA_SYSEX_Action_CFG_Write
    rgoto   TIA_SYSEX_Action_RequestCC
    rgoto   TIA_SYSEX_Action_Ping


;; --------------------------------------------------------------------------
;;  Initialize an action depending on TIA_SYSEX_ACTION
;; --------------------------------------------------------------------------
TIA_SYSEX_Handler_InitAction
    movf    TIA_SYSEX_ACTION, W
    JUMPTABLE_2BYTES 16 ; 16 entries
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_Init_PRESET_Read
    rgoto   TIA_SYSEX_Init_PRESET_Write
    rgoto   TIA_SYSEX_Init_BANK_Read
    rgoto   TIA_SYSEX_Init_BANK_WriteName
    rgoto   TIA_SYSEX_Init_PAR_Read
    rgoto   TIA_SYSEX_Init_PAR_Write
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_Init_BANK_Sel
    rgoto   TIA_SYSEX_Init_CFG_Read
    rgoto   TIA_SYSEX_Init_CFG_Write
    rgoto   TIA_SYSEX_Init_RequestCC
    rgoto   TIA_SYSEX_Init_Ping

    
;; --------------------------------------------------------------------------
;;  Finish an action depending on TIA_SYSEX_ACTION
;; --------------------------------------------------------------------------
TIA_SYSEX_Handler_EndAction
    ;; if sysex footer (F7) has not been received here, action is invalid!
    movlw   0xf7
    xorwf   TIA_SYSEX_IN, W
    bnz TIA_SYSEX_ActionInvalid

    ;; else finish action
    movf    TIA_SYSEX_ACTION, W
    JUMPTABLE_2BYTES 16 ; 16 entries
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_End_PRESET_Read
    rgoto   TIA_SYSEX_End_PRESET_Write
    rgoto   TIA_SYSEX_End_BANK_Read
    rgoto   TIA_SYSEX_End_BANK_WriteName
    rgoto   TIA_SYSEX_End_PAR_Read
    rgoto   TIA_SYSEX_End_PAR_Write
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_ActionInvalid
    rgoto   TIA_SYSEX_End_BANK_Sel
    rgoto   TIA_SYSEX_End_CFG_Read
    rgoto   TIA_SYSEX_End_CFG_Write
    rgoto   TIA_SYSEX_End_RequestCC
    rgoto   TIA_SYSEX_End_Ping

;; --------------------------------------------------------------------------
;;  MIDI Action: Patch Read
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_PRESET_Read
    return

TIA_SYSEX_Action_PRESET_Read
    ;; receive <type> <bank> <patch> F7
TIA_SYSEX_Action_PRESET_Read_T
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED, ACCESS, TIA_SYSEX_Action_PRESET_Read_B
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED
    movff   TIA_SYSEX_IN, TIA_SYSEX_ADDRESS     ; load preset type
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_PRESET_Read_B
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED, ACCESS, TIA_SYSEX_Action_PRESET_Read_P
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED    
    movff   TIA_SYSEX_IN, TIA_BANK      ; load bank
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
    
TIA_SYSEX_Action_PRESET_Read_P
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_PRESET_RECEIVED, ACCESS, TIA_SYSEX_Action_PRESET_ReadStall
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_PRESET_RECEIVED
    movff   TIA_SYSEX_IN, TIA_PRESET        ; load preset
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
            
TIA_SYSEX_Action_PRESET_ReadStall
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_PRESET_Read
    ;; action invalid if patch number has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_PRESET_RECEIVED, ACCESS, TIA_SYSEX_ActionInvalid

    movff   TIA_BANK, TMP2  ;; store relative bank
    movf    TIA_SYSEX_ADDRESS, W
    rcall   TIA_SYSEX_Hlp_GetAbsoluteBank      ; set bank to absolute
    movwf   TIA_SYSEX_ERROR
    bnz     TIA_SYSEX_End_PRESET_Read_Cont
    
    movf    TIA_PRESET, W
    bz      TIA_SYSEX_End_PRESET_Read_Cont    
    movf    TIA_BANK, W
    call    TIA_BANK_GetBankStickReady
    skpz
    rgoto   TIA_SYSEX_End_PRESET_Read_Size
    ;; BS not ready Error #3
    movlw   0x03
    movwf   TIA_SYSEX_ERROR
    rgoto   TIA_SYSEX_End_PRESET_Read_Cont
TIA_SYSEX_End_PRESET_Read_Size    
    call    TIA_BANK_GetBankStickSize
    bnz     TIA_SYSEX_End_PRESET_Read_Cont

    btfsc   TIA_PRESET, 6
    clrf    TIA_PRESET

TIA_SYSEX_End_PRESET_Read_Cont

    ;; send SysEx header
    rcall   TIA_SYSEX_Send_SysExHeader

    ;; Send PRESET_Read ID
    movlw   0x01
    call    MIOS_MIDI_TxBufferPut

    ;; send requested preset type number
    movf    TIA_SYSEX_ADDRESS, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    
    ;; send requested relative bank number
    movf    TMP2, W
    andlw   0x1f
    call    MIOS_MIDI_TxBufferPut
    
    ;; send requested preset number
    movf    TIA_PRESET, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    
    movf    TIA_SYSEX_ERROR, W
    bz      TIA_SYSEX_End_PRESET_Read_Cont_Ok
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    rgoto   TIA_SYSEX_End_PRESET_Read_Footer
    
TIA_SYSEX_End_PRESET_Read_Cont_Ok 
    ;; clear checksum
    clrf    TIA_SYSEX_CHECKSUM

    ;movf   TIA_SYSEX_ADDRESS, W
    ;rcall   TIA_SYSEX_Hlp_GetAbsoluteBank     ; set bank to absolute
    ;; send patch (128 bytes)
    rcall   TIA_SYSEX_Hlp_SendPreset    

    ;; send checksum
    movf    TIA_SYSEX_CHECKSUM, W
    sublw   0x80
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut

TIA_SYSEX_End_PRESET_Read_Footer
    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rcall   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished

;; --------------------------------------------------------------------------
;;  MIDI Action: Patch Write
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_PRESET_Write
    ;; disable TIA engine until end of transfer (will be requested by ActionFinished)
    bsf TIA_STAT, TIA_STAT_ENGINE_DISABLE
    call    TIA_TUNE_Note_Off
    return

TIA_SYSEX_Action_PRESET_Write
    ;; receive <type> <bank> <patch> <128 bytes> F7
TIA_SYSEX_Action_PRESET_WriteT
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED, ACCESS, TIA_SYSEX_Action_PRESET_WriteB
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED
    movff   TIA_SYSEX_IN, TIA_SYSEX_ADDRESS     ; load preset type
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_PRESET_WriteB
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED, ACCESS, TIA_SYSEX_Action_PRESET_WriteP
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED
    movff   TIA_SYSEX_IN, TIA_BANK      ; load bank
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
    
TIA_SYSEX_Action_PRESET_WriteP
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_PRESET_RECEIVED, ACCESS, TIA_SYSEX_Action_PRESET_WriteC
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_PRESET_RECEIVED
    movff   TIA_SYSEX_IN, TIA_PRESET        ; load preset 
    
    clrf    TIA_SYSEX_CHECKSUM      ; clear checksum
    clrf    EEADR                   ; clear address
    clrf    TIA_SYSEX_ERROR      ; clear reply error
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
    
TIA_SYSEX_Action_PRESET_WriteC
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_WAIT_CHECKSUM, ACCESS, TIA_SYSEX_Action_PRESET_WriteChk

    lfsr    FSR0, BANKSTICK_FORMAT_BEGIN            ; init pointer to upload buffer
    movff   EEADR, FSR0L

    ;; store received byte in upload buffer
    movf    TIA_SYSEX_IN, W
    movwf   INDF0

    ;; add to checksum
    andlw   0x7f
    addwf   TIA_SYSEX_CHECKSUM, F
    
    ;; increment address
    incf    EEADR, F

    ;; if FSR0L is zero, go into WAIT_CHECKSUM state
    movlw   0x80
    cpfslt  EEADR, ACCESS
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_WAIT_CHECKSUM

    ;; wait for next byte
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_Action_PRESET_WriteChk
    ;; store received byte in checksum (using TIA_SYSEX_ADDRESS as store register)
    movff   TIA_SYSEX_IN, EEADR

    ;; wait for next byte
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_PRESET_Write
    ;; action invalid if checksum has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_WAIT_CHECKSUM, ACCESS, TIA_SYSEX_ActionInvalid

    ;; calc final checksum
    movf    TIA_SYSEX_CHECKSUM, W
    sublw   0x80
    andlw   0x7f

    ;; compare with received checksum
    xorwf   EEADR, W

    ;; if not equal jump to ActionInvalid
    skpz
    rgoto   TIA_SYSEX_End_PRESET_Write_Reply_ChksumErr
    
    movf    TIA_SYSEX_ADDRESS, W
    rcall   TIA_SYSEX_Hlp_GetAbsoluteBank
    movwf   TIA_SYSEX_ERROR
    bnz     TIA_SYSEX_End_PRESET_Write_Reply
    
    movf    TIA_PRESET, W
    bz      TIA_SYSEX_End_PRESET_Write_Cont    
    movf    TIA_BANK, W
    call    TIA_BANK_GetBankStickReady
    skpnz
    rgoto   TIA_SYSEX_End_PRESET_Write_Reply_NotReady
     
    call    TIA_BANK_GetBankStickSize
    bnz     TIA_SYSEX_End_PRESET_Write_Cont

    btfsc   TIA_PRESET, 6
    rgoto   TIA_SYSEX_End_PRESET_Write_Reply_32k

TIA_SYSEX_End_PRESET_Write_Cont
    ;; write buffer to EEPROM
    lfsr    FSR1, BANKSTICK_FORMAT_BEGIN    ; init pointer to upload buffer
    movlw   EEPROM_PATCH & 0xff
    movwf   EEADR
    movlw   (EEPROM_PATCH >> 8) & 0xff
    movwf   EEADRH
        
TIA_SYSEX_End_PRESET_WritePages
    clrwdt          ; feed watchdog
    call    TIA_BANK_WritePage      ; write a 64 bytes page to EEPROM
    ;; increment FSR1 by 0x40
    movlw   0x40
    addwf   FSR1L, F
    clrwdt          ; feed watchdog
    call    TIA_BANK_WritePage      ; write a 64 bytes page to EEPROM
    rgoto   TIA_SYSEX_End_PRESET_Write_Reply
    ;; to do... bank num in command and set patch/kit/WT +init if BANK==xBANK/ PRESET==xPRESET

TIA_SYSEX_End_PRESET_Write_Reply_ChksumErr
    ;; CheckSum Error #5
    movlw   0x05
    movwf   TIA_SYSEX_ERROR
    rgoto   TIA_SYSEX_End_PRESET_Write_Reply
    
TIA_SYSEX_End_PRESET_Write_Reply_NotReady
    ;; BS not ready Error #3
    movlw   0x03
    movwf   TIA_SYSEX_ERROR
    rgoto   TIA_SYSEX_End_PRESET_Write_Reply

TIA_SYSEX_End_PRESET_Write_Reply_32k
    ;; BS 32k 64 presets max Error #4
    movlw   0x04
    movwf   TIA_SYSEX_ERROR
    ;;rgoto   TIA_SYSEX_End_PRESET_Write_Reply
        
TIA_SYSEX_End_PRESET_Write_Reply
    ;; send SysEx header
    rcall   TIA_SYSEX_Send_SysExHeader

    ;; Send PRESET_Write ID
    movlw   0x02
    call    MIOS_MIDI_TxBufferPut

    ;; send requested preset type number
    rcall   TIA_SYSEX_Hlp_GetRelativeBank
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    
    ;; send requested bank number
    movf    TIA_BANK, W
    andlw   0x1f
    call    MIOS_MIDI_TxBufferPut
    
    ;; send requested preset number
    movf    TIA_PRESET, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut

    ;; send error status
    movf    TIA_SYSEX_ERROR, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut

    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rcall   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished

TIA_SYSEX_End_PRESET_Write_STR
    STRING  20, 0x00, "Patch A  1 uploaded "

;; --------------------------------------------------------------------------
;;  MIDI Action: All Patch Read
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_BANK_Read
    ;; disable TIA engine until end of transfer (will be requested by ActionFinished)
    bsf TIA_STAT, TIA_STAT_ENGINE_DISABLE
    call    TIA_TUNE_Note_Off
    return

TIA_SYSEX_Action_BANK_Read
    ;; receive <type> <bank> F7
TIA_SYSEX_Action_BANK_Read_T
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED, ACCESS, TIA_SYSEX_Action_BANK_Read_B
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED
    movff   TIA_SYSEX_IN, TIA_SYSEX_ADDRESS     ; load preset type
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_BANK_Read_B    
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED, ACCESS, TIA_SYSEX_Action_BANK_ReadStall
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED
    movff   TIA_SYSEX_IN, TIA_BANK      ; load bank
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
            
TIA_SYSEX_Action_BANK_ReadStall
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_BANK_Read
    ;; action invalid if patch number has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED, ACCESS, TIA_SYSEX_ActionInvalid
    
    movff   TIA_BANK, TMP2  ;; store relative bank
    movf    TIA_SYSEX_ADDRESS, W
    rcall   TIA_SYSEX_Hlp_GetAbsoluteBank   ; set bank to absolute
    movwf   TIA_SYSEX_ERROR
    bnz     TIA_SYSEX_End_BANK_Read_Cont
    
    movf    TIA_PRESET, W
    bz      TIA_SYSEX_End_BANK_Read_Cont    
    movf    TIA_BANK, W
    call    TIA_BANK_GetBankStickReady
    skpz
    rgoto   TIA_SYSEX_End_BANK_Read_Cont
    ;; BS not ready Error #3
    movlw   0x03
    movwf   TIA_SYSEX_ERROR
    rgoto   TIA_SYSEX_End_BANK_Read_Cont

TIA_SYSEX_End_BANK_Read_Cont

    ;; send SysEx header
    rcall   TIA_SYSEX_Send_SysExHeader

    ;; send PTCHES_Write ID
    movlw   0x03
    call    MIOS_MIDI_TxBufferPut
    
    ;; send requested preset type number
    movf    TIA_SYSEX_ADDRESS, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    
    ;; send requested bank number
    movf    TMP2, W
    andlw   0x1f
    call    MIOS_MIDI_TxBufferPut

    ;movf   TIA_SYSEX_ADDRESS, W
    ;rcall   TIA_SYSEX_Hlp_GetAbsoluteBank   ; set bank to absolute    
    movf    TIA_BANK, W
    call    TIA_BANK_GetBankStickReady
    ;; send requested bank size
    call    TIA_BANK_GetBankStickSize
    call    MIOS_MIDI_TxBufferPut
    
    movf    TIA_SYSEX_ERROR, W
    bz      TIA_SYSEX_End_BANK_Read_Cont_Ok
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    rgoto   TIA_SYSEX_End_BANK_Read_Footer
    
TIA_SYSEX_End_BANK_Read_Cont_Ok 

    ;; clear checksum
    clrf    TIA_SYSEX_CHECKSUM

#if 1    
    ;; send bank informations 
    call    TIA_BANK_SetBankStickAddressMagic
TIA_SYSEX_End_BANK_Read_Cont_Name_Loop
    call    MIOS_BANKSTICK_Read     ; read content, inc MIOS_PARAMETER12
    movwf   TABLAT              ; store data in TABLAT
    
    movf    MIOS_PARAMETER1, W
    andlw   0xf0
    xorlw   0x10
    bnz     TIA_SYSEX_End_BANK_Read_Cont_Name_Jump
    movlw   0x20
    cpfslt  TABLAT, ACCESS      ; ensure that patch name doesn't contain characters < 0x20
    rgoto   TIA_SYSEX_End_BANK_Read_Cont_Name_Jump
    movwf   TABLAT
TIA_SYSEX_End_BANK_Read_Cont_Name_Jump
    movf    TABLAT, W
    andlw   0x7f
    addwf   TIA_SYSEX_CHECKSUM, F
    call    MIOS_MIDI_TxBufferPut
    btfss   MIOS_PARAMETER1, 7            ; until == 0x20 send 16 bytes
    rgoto   TIA_SYSEX_End_BANK_Read_Cont_Name_Loop

    ;; 127 patches to send(1-127), TIA_PRESET used as counter
    movlw   0x01
    movwf   TIA_PRESET
#else
    
    ;; 128 patches to send, TIA_PRESET used as counter
    clrf    TIA_PRESET
#endif    
    
TIA_SYSEX_End_BANK_Read_OL  ; outer loop
    clrwdt                      ; feed the watchdog
    rcall   TIA_SYSEX_Hlp_SendPreset    ; send 128 bytes

    incf    TIA_PRESET, F       ; loop 64/128 times depends on BS Size
    call    TIA_BANK_GetBankStickSize
    movlw   128-1
    skpnz
    movlw   64-1
    cpfsgt  TIA_PRESET, ACCESS
    rgoto TIA_SYSEX_End_BANK_Read_OL

    ;; send checksum
    movf    TIA_SYSEX_CHECKSUM, W
    sublw   0x80
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut

TIA_SYSEX_End_BANK_Read_Footer
    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rcall   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished


;; --------------------------------------------------------------------------
;;  MIDI Action: Bank Write Name
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_BANK_WriteName
    ;; disable TIA engine until end of transfer (will be requested by ActionFinished)
    ;;bsf   TIA_STAT, TIA_STAT_ENGINE_DISABLE
    return

TIA_SYSEX_Action_BANK_WriteName
    ;; receive <type> <bank> <16 bytes> F7
TIA_SYSEX_Action_BANK_WriteNameT
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED, ACCESS, TIA_SYSEX_Action_BANK_WriteNameB
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_TYPE_RECEIVED
    movff   TIA_SYSEX_IN, TIA_SYSEX_ADDRESS     ; load preset type
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_BANK_WriteNameB
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED, ACCESS, TIA_SYSEX_Action_BANK_WriteNameC
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_BANK_RECEIVED
    movff   TIA_SYSEX_IN, TIA_BANK      ; load bank
    
    clrf    EEADR                       ; clear address
    clrf    TIA_SYSEX_ERROR             ; clear reply error
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byt
        
TIA_SYSEX_Action_BANK_WriteNameC
    lfsr    FSR0, BANKSTICK_FORMAT_BEGIN            ; init pointer to upload buffer
    movff   EEADR, FSR0L

    ;; store received byte in upload buffer
    movf    TIA_SYSEX_IN, W
    movwf   INDF0

    ;; increment address
    incf    EEADR, F

    ;; if FSR0L is zero, go into WAIT_CHECKSUM state
    movlw   0x10
    cpfslt  EEADR, ACCESS
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_PRESET_RECEIVED
    
    ;; wait for next byte
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_BANK_WriteName
    ;; action invalid if checksum has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_PRESET_RECEIVED, ACCESS, TIA_SYSEX_ActionInvalid

    movf    TIA_SYSEX_ADDRESS, W
    rcall   TIA_SYSEX_Hlp_GetAbsoluteBank
    movwf   TIA_SYSEX_ERROR
    bnz     TIA_SYSEX_End_BANK_WriteName_Reply
  
    movf    TIA_BANK, W
    call    TIA_BANK_GetBankStickReady
    skpnz
    rgoto   TIA_SYSEX_End_BANK_WriteName_Reply_NotReady

TIA_SYSEX_End_BANK_WriteName_Cont
    lfsr    FSR1, BANKSTICK_FORMAT_BEGIN    ; init pointer to upload buffer
    ;; add name offset to MP1 start @0x10
    call    TIA_BANK_SetBankStickAddressMagic  
    movlw   0x10
    addwf   MIOS_PARAMETER1, F
    
TIA_SYSEX_End_BANK_WriteName_Loop 
    clrwdt          ; feed watchdog
    movlw   0x20
    cpfslt  INDF1, BANKED      ; ensure that patch name doesn't contain characters < 0x20
    movwf   INDF1
TIA_SYSEX_End_BANK_WriteName_Loop_Jump 
    movf    POSTINC1, W
    call    MIOS_BANKSTICK_Write     ; write byte to EEPROM
    bnz     TIA_SYSEX_End_BANK_WriteName_Reply_WError

    ;; if FSR0L is zero, go into WAIT_CHECKSUM state
    movlw   0x20
    cpfslt  MIOS_PARAMETER1, ACCESS
    rgoto   TIA_SYSEX_End_BANK_WriteName_Reply
    rgoto   TIA_SYSEX_End_BANK_WriteName_Loop

TIA_SYSEX_End_BANK_WriteName_Reply_WError
    ;; BS write byte Error #8
    movlw   0x08
    movwf   TIA_SYSEX_ERROR
    rgoto   TIA_SYSEX_End_BANK_WriteName_Reply       

TIA_SYSEX_End_BANK_WriteName_Reply_NotReady
    ;; BS not ready Error #3
    movlw   0x03
    movwf   TIA_SYSEX_ERROR
    rgoto   TIA_SYSEX_End_BANK_WriteName_Reply
        
TIA_SYSEX_End_BANK_WriteName_Reply
    ;; send SysEx header
    rcall   TIA_SYSEX_Send_SysExHeader

    ;; Send PRESET_WriteName ID
    movlw   0x04
    call    MIOS_MIDI_TxBufferPut

    ;; send requested preset type number
    rcall   TIA_SYSEX_Hlp_GetRelativeBank
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    
    ;; send requested bank number
    movf    TIA_BANK, W
    andlw   0x1f
    call    MIOS_MIDI_TxBufferPut

    ;; send error status
    movf    TIA_SYSEX_ERROR, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut

    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rcall   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished

;; --------------------------------------------------------------------------
;;  MIDI Action: Parameter Read
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_PAR_Read
    return

TIA_SYSEX_Action_PAR_Read
    ;; receive <AH> <AL> F7
TIA_SYSEX_Action_PAR_ReadAH
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_AH_RECEIVED, ACCESS, TIA_SYSEX_Action_PAR_ReadAL
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_AH_RECEIVED
    clrf    TIA_SYSEX_ADDRESS       ; clear register and set TIA_SYSEX_ADDRESS[7] if IN[0] is set
    btfsc   TIA_SYSEX_IN, 0
    bsf TIA_SYSEX_ADDRESS, 7
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
    
TIA_SYSEX_Action_PAR_ReadAL
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_AL_RECEIVED, ACCESS, TIA_SYSEX_Action_PAR_ReadStall
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_AL_RECEIVED
    movf    TIA_SYSEX_IN, W         ; OR TIA_SYSEX_ADDRESS with low-byte
    andlw   0x7f
    iorwf   TIA_SYSEX_ADDRESS, F
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_PAR_ReadStall
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_PAR_Read
    ;; action invalid if low-byte of address has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_AL_RECEIVED, ACCESS, TIA_SYSEX_ActionInvalid

    ;; send SysEx header
    rcall   TIA_SYSEX_Send_SysExHeader

    ;; send PAR_Write ID
    movlw   0x06
    call    MIOS_MIDI_TxBufferPut

    ;; send AH
    movlw   0x00
    btfsc   TIA_SYSEX_ADDRESS, 7
    movlw 0x01
    call    MIOS_MIDI_TxBufferPut

    ;; send AL
    movf    TIA_SYSEX_ADDRESS, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut

    ;; get corresponding CC parameter from address
    movf    TIA_SYSEX_ADDRESS, W
    call    TIA_SYSEX_TABLE_Get

    ;; branch if EEPROM value should be sent
    BRA_IFSET WREG, 7, ACCESS, TIA_SYSEX_Action_PAR_Read_EE

TIA_SYSEX_Action_PAR_Read_RAM
    ;; get CC value from RAM
    call    TIA_CCOUT_Get
    rgoto   TIA_SYSEX_Action_PAR_Read_Cont
TIA_SYSEX_Action_PAR_Read_EE
    ;; read value from EEPROM
    movff   TIA_SYSEX_ADDRESS, EEADR
    call    TIA_BANK_Read
TIA_SYSEX_Action_PAR_Read_Cont
    ;; send value
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    
    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rcall   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished

;; --------------------------------------------------------------------------
;;  MIDI Action: Parameter Write
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_PAR_Write
    return

TIA_SYSEX_Action_PAR_Write
    ;; receive <AH> <AL> <value> F7
TIA_SYSEX_Action_PAR_WriteAH
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_AH_RECEIVED, ACCESS, TIA_SYSEX_Action_PAR_WriteAL
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_AH_RECEIVED
    clrf    TIA_SYSEX_ADDRESS       ; clear register and set TIA_SYSEX_ADDRESS[7] if IN[0] is set
    btfsc   TIA_SYSEX_IN, 0
    bsf TIA_SYSEX_ADDRESS, 7
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
    
TIA_SYSEX_Action_PAR_WriteAL
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_AL_RECEIVED, ACCESS, TIA_SYSEX_Action_PAR_WriteD
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_AL_RECEIVED
    movf    TIA_SYSEX_IN, W         ; OR TIA_SYSEX_ADDRESS with low-byte
    andlw   0x7f
    iorwf   TIA_SYSEX_ADDRESS, F
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_PAR_WriteD
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_D_RECEIVED, ACCESS, TIA_SYSEX_Action_PAR_WriteStall
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_D_RECEIVED 
    movff   TIA_SYSEX_IN, TIA_SYSEX_CHECKSUM; store byte in TIA_SYSEX_CHECKSUM (used as write buffer here)
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_PAR_WriteStall
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_PAR_Write
    ;; action invalid if data has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_D_RECEIVED, ACCESS, TIA_SYSEX_ActionInvalid

    ;; get corresponding CC parameter from address
    movf    TIA_SYSEX_ADDRESS, W
    call    TIA_SYSEX_TABLE_Get
    movwf   TMP1

    ;; branch if value should be saved in EEPROM
    BRA_IFSET TMP1, 7, ACCESS, TIA_SYSEX_Action_PAR_Write_EE

TIA_SYSEX_Action_PAR_Write_RAM
    ;; write CC value to RAM
    movff   TIA_SYSEX_CHECKSUM, MIOS_PARAMETER1 ; byte has been stored in _CHECKSUM
    call    TIA_CCIN_Set
    rgoto   TIA_SYSEX_Action_PAR_Write_Cont
TIA_SYSEX_Action_PAR_Write_EE
    ;; if split parameter, redirect to TIA_Vx_SPLIT_xxx
    movf    TMP1, W
    andlw   0xf0
    xorlw   0x90
    bnz TIA_SYSEX_Action_PAR_Write_EEC
TIA_SYSEX_Action_PAR_Write_EES
    movf    TMP1, W
    call    TIA_PATCH_GetSplitPointer
    movff   TIA_SYSEX_CHECKSUM, PLUSW1
    rgoto   TIA_SYSEX_Action_PAR_Write_Cont

TIA_SYSEX_Action_PAR_Write_EEC
    ;; write value to EEPROM
    movff   TIA_SYSEX_ADDRESS, EEADR
    movf    TIA_SYSEX_CHECKSUM, W; byte has been stored in _CHECKSUM
    call    TIA_BANK_Write
TIA_SYSEX_Action_PAR_Write_Cont

    ;; send acknowledge
    call    TIA_SYSEX_Send_Acknowledge

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished

;; --------------------------------------------------------------------------
;;  MIDI Action: Switch Bank
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_BANK_Sel
    clrf    TIA_SYSEX_ADDRESS
    return

TIA_SYSEX_Action_BANK_Sel
    ;; store bank in TIA_SYSEX_ADDRESS
    movff   TIA_SYSEX_IN, TIA_SYSEX_ADDRESS
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_End_BANK_Sel
    ;; check if BankStick available
    movlw   0x0f
    cpfslt  TIA_SYSEX_ADDRESS, ACCESS
    rgoto TIA_SYSEX_End_BANK_SelInv
    movf    TIA_SYSEX_ADDRESS, W
    call    MIOS_HLP_GetBitORMask
    andwf   TIA_BANKSTICK_STAT, W
    bz  TIA_SYSEX_End_BANK_SelInv

    ;; change to bank immediately
    movff   TIA_SYSEX_ADDRESS, TIA_PBANK
    rcall   TIA_SYSEX_ChangeMPatch

    ;;  rgoto   TIA_SYSEX_End_BANK_Cont

    ;; don't select new bankstick
TIA_SYSEX_End_BANK_SelInv

TIA_SYSEX_End_BANK_Cont
    ;; send acknowledge with bank number
    rcall   TIA_SYSEX_Send_SysExHeader

    movlw   0x0f        ; (acknowledge ID)
    call    MIOS_MIDI_TxBufferPut

    movf    TIA_PBANK, W
    call    MIOS_MIDI_TxBufferPut

    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rcall   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished

;; --------------------------------------------------------------------------
;;  MIDI Action: Configuration Write
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_CFG_Read
    return
TIA_SYSEX_Action_CFG_Read    
    ;; send <A> <DH> <DL> F7
TIA_SYSEX_Action_CFG_ReadA
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_A_RECEIVED, ACCESS, TIA_SYSEX_Action_CFG_ReadStall
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_A_RECEIVED
    movff   TIA_SYSEX_IN, TIA_SYSEX_ADDRESS ; store address in TIA_SYSEX_ADDRESS
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_CFG_ReadStall
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End
    
TIA_SYSEX_End_CFG_Read
    ;; action invalid if low-byte of address has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_A_RECEIVED, ACCESS, TIA_SYSEX_ActionInvalid
_TIA_SYSEX_End_CFG_Read
    ;; send SysEx header
    rcall   TIA_SYSEX_Send_SysExHeader

    ;; send CFG_Read ID
    movlw   0x0c
    call    MIOS_MIDI_TxBufferPut

    ;; send A
    movf    TIA_SYSEX_ADDRESS, W
    call    MIOS_MIDI_TxBufferPut
    
        ;; branch depending on current action ID
    movf    TIA_SYSEX_ADDRESS, W
    JUMPTABLE_2BYTES 16 ; 16 entries
    rgoto   TIA_SYSEX_End_CFG_Read_EEPROM
    rgoto   TIA_SYSEX_End_CFG_Read_EEPROM
    rgoto   TIA_SYSEX_End_CFG_Read_EEPROM
    rgoto   TIA_SYSEX_End_CFG_Read_Bank
    rgoto   TIA_SYSEX_End_CFG_Read_Patch
    rgoto   TIA_SYSEX_End_CFG_Read_BSInfo
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    rgoto   TIA_SYSEX_End_CFG_Read_All
    
    
    ;BRA_IFSET TIA_SYSEX_ADDRESS, 2, ACCESS, TIA_SYSEX_End_CFG_Read_All
    
TIA_SYSEX_End_CFG_Read_EEPROM    
    ;; calc resulting EEADR
    movf    TIA_SYSEX_ADDRESS, W
    andlw   0x03
    addlw   EEPROM_CFG_BASE & 0xff
    movwf   EEADR

    ;; read value from EEPROM
    call    MIOS_EEPROM_Read
    movwf   TIA_SYSEX_CHECKSUM  ; (value is stored in TIA_SYSEX_CHECKSUM)    
    
    ;; send DH
    movlw   0x00
    btfsc   TIA_SYSEX_CHECKSUM, 7
    movlw   0x01
    call    MIOS_MIDI_TxBufferPut

    ;; send DL
    movf    TIA_SYSEX_CHECKSUM, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
    rgoto   TIA_SYSEX_End_CFG_Read_Cont
    
TIA_SYSEX_End_CFG_Read_Bank   
    ;; send current bank number
    movf    TIA_PBANK, W
    call    MIOS_MIDI_TxBufferPut

#if 0    
    ;; send bank type
    call    TIA_BANK_SetBankStickAddressMagic
    incf    MIOS_PARAMETER1, F
    call    MIOS_BANKSTICK_Read
    movwf   TIA_SYSEX_CHECKSUM
    movlw   BANKSTICK_MAGIC1
    subwf   TIA_SYSEX_CHECKSUM, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut  
#endif

    ;; send bank name    
    call    TIA_BANK_SetBankStickAddressMagic
    movlw   0x10
    addwf   MIOS_PARAMETER1, F
TIA_SYSEX_End_CFG_Read_Bank_NameLoop
    call    MIOS_BANKSTICK_Read
    movwf   TIA_SYSEX_CHECKSUM
    movlw   0x20
    cpfslt  TIA_SYSEX_CHECKSUM
    movf    TIA_SYSEX_CHECKSUM, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut  
    btfss   MIOS_PARAMETER1, 5
    rgoto   TIA_SYSEX_End_CFG_Read_Bank_NameLoop
    rgoto   TIA_SYSEX_End_CFG_Read_Cont
    
TIA_SYSEX_End_CFG_Read_Patch
    ;; send current patch number
    movf    TIA_PATCH, W
    call    MIOS_MIDI_TxBufferPut
    rgoto   TIA_SYSEX_End_CFG_Read_Cont
    
        
TIA_SYSEX_End_CFG_Read_All
    ;; calc resulting EEADR
    movlw   EEPROM_CFG_BASE & 0xff
    movwf   EEADR

    ;; read value from EEPROM
    call    MIOS_EEPROM_Read
    movwf   TIA_SYSEX_CHECKSUM  ; (v2 ch is stored in TIA_SYSEX_CHECKSUM)    

    ;; send v2 ch
    movf    TIA_SYSEX_CHECKSUM, W
    call    MIOS_MIDI_TxBufferPut

    ;; read value from EEPROM
    call    MIOS_EEPROM_Read
    movwf   TIA_SYSEX_CHECKSUM  ; (v1 ch is stored in TIA_SYSEX_CHECKSUM)    

    ;; send v1 ch
    movf    TIA_SYSEX_CHECKSUM, W
    call    MIOS_MIDI_TxBufferPut

    ;; read value from EEPROM
    call    MIOS_EEPROM_Read
    movwf   TIA_SYSEX_CHECKSUM  ; (v1 ch is stored in TIA_SYSEX_CHECKSUM) 
        
    ;; send DH/DL (device ID)
    movlw   0x00
    btfsc   TIA_SYSEX_CHECKSUM, 7
    movlw   0x01
    call    MIOS_MIDI_TxBufferPut
    movf    TIA_SYSEX_CHECKSUM, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
     
    ;; send current bank number
    movf    TIA_PBANK, W
    call    MIOS_MIDI_TxBufferPut
    
    ;; send current patch number
    movf    TIA_PATCH, W
    call    MIOS_MIDI_TxBufferPut
    

TIA_SYSEX_End_CFG_Read_BSInfo
    ;; send DH/DL (bank status)
    movlw   0x00
    btfsc   TIA_BANKSTICK_RDY, 7
    movlw   0x01
    call    MIOS_MIDI_TxBufferPut
    movf    TIA_BANKSTICK_RDY, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut    

    ;; send DH/DL (bank size)
    movlw   0x00
    btfsc   TIA_BANKSTICK_SIZE, 7
    movlw   0x01
    call    MIOS_MIDI_TxBufferPut
    movf    TIA_BANKSTICK_SIZE, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut 
    
    ;; send Kit/WT start Id
    movlw   DEFAULT_BS_KBANK_ID
    call    MIOS_MIDI_TxBufferPut   
            

TIA_SYSEX_End_CFG_Read_Cont  
    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rcall   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished
    
;; --------------------------------------------------------------------------
;;  MIDI Action: Configuration Write
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_CFG_Write
    ;; disable TIA engine until end of transfer (will be requested by ActionFinished)
    bsf TIA_STAT, TIA_STAT_ENGINE_DISABLE
    return

TIA_SYSEX_Action_CFG_Write
    ;; receive <A> <DH> <DL> F7
TIA_SYSEX_Action_CFG_WriteA
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_A_RECEIVED, ACCESS, TIA_SYSEX_Action_CFG_WriteDH
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_A_RECEIVED
    movff   TIA_SYSEX_IN, TIA_SYSEX_ADDRESS ; store address in TIA_SYSEX_ADDRESS
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte
    
TIA_SYSEX_Action_CFG_WriteDH
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_DH_RECEIVED, ACCESS, TIA_SYSEX_Action_CFG_WriteDL
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_DH_RECEIVED
    swapf   TIA_SYSEX_IN, W         ; store high-nibble in TIA_SYSEX_CHECKSUM (used as data buffer here)
    andlw   0xf0
    movwf   TIA_SYSEX_CHECKSUM
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_CFG_WriteDL
    BRA_IFSET TIA_SYSEX_STATE, TIA_SYSEX_STATE_DL_RECEIVED, ACCESS, TIA_SYSEX_Action_CFG_WriteStall
    bsf TIA_SYSEX_STATE, TIA_SYSEX_STATE_DL_RECEIVED
    movf    TIA_SYSEX_IN, W         ; store low-nibble in TIA_SYSEX_CHECKSUM (used as data buffer here)
    iorwf   TIA_SYSEX_CHECKSUM, F
    rgoto   TIA_SYSEX_SysExCheck_End    ; wait for next byte

TIA_SYSEX_Action_CFG_WriteStall
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_CFG_Write
    ;; action invalid if data has not been received
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_DL_RECEIVED, ACCESS, TIA_SYSEX_ActionInvalid

    ;; calc resulting EEADR
    movf    TIA_SYSEX_ADDRESS, W
    andlw   0x03
    addlw   EEPROM_CFG_BASE & 0xff
    movwf   EEADR

    ;; write value to EEPROM
    movf    TIA_SYSEX_CHECKSUM, W   ; (value has been stored in TIA_SYSEX_CHECKSUM)
    call    MIOS_EEPROM_Write
    
    ;; send response
    rcall   TIA_SYSEX_Send_SysExHeader

    ;; send CFG_Write ID
    movlw   0x0d
    call    MIOS_MIDI_TxBufferPut

    ;; send A
    movf    TIA_SYSEX_ADDRESS, W
    call    MIOS_MIDI_TxBufferPut

    ;; send DH
    movlw   0x00
    btfsc   TIA_SYSEX_CHECKSUM, 7
    movlw   0x01
    call    MIOS_MIDI_TxBufferPut

    ;; send DL
    movf    TIA_SYSEX_CHECKSUM, W
    andlw   0x7f
    call    MIOS_MIDI_TxBufferPut
            
    ;; send of SysEx footer
    movlw   0x01        ; (independent from merger state)
    rgoto   TIA_SYSEX_Send_SysExFooter

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished

;; --------------------------------------------------------------------------
;;  MIDI Action: CC Request
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_RequestCC
    return

TIA_SYSEX_Action_RequestCC
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_RequestCC
    ;; request CC dump (handled by tia_ccout.inc)
    bsf TIA_STAT, TIA_STAT_CC_DUMP_REQ

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished


;; --------------------------------------------------------------------------
;;  MIDI Action: Ping
;; --------------------------------------------------------------------------
TIA_SYSEX_Init_Ping
    return

TIA_SYSEX_Action_Ping
    ;; do nothing until sysex footer (F7) has been received
    rgoto   TIA_SYSEX_SysExCheck_End

TIA_SYSEX_End_Ping
    ;; send Acknowledge
    rcall   TIA_SYSEX_Send_Acknowledge

    ;; finish Action
    rgoto   TIA_SYSEX_ActionFinished



;; --------------------------------------------------------------------------
;;  MIDI Send Acknowledge (Util function)
;; --------------------------------------------------------------------------
TIA_SYSEX_Send_Acknowledge
    rcall   TIA_SYSEX_Send_SysExHeader

    movlw   0x0f        ; (acknowledge ID)
    call    MIOS_MIDI_TxBufferPut

    ;; send of SysEx footer
    movlw   0x01        ; (independend from merger state)
    rgoto   TIA_SYSEX_Send_SysExFooter

;; --------------------------------------------------------------------------
;;  Send TIA SysEx Header (Util function)
;; --------------------------------------------------------------------------
TIA_SYSEX_Send_SysExHeader
    ;; if TIA_SYSEX_SYXSTATE > 0, check merger flag to allow propper sysex merging
    BRA_IFCLR TIA_SYSEX_STATE, TIA_SYSEX_STATE_MYSYSEX, ACCESS, TIA_SYSEX_Send_SysExHeader_Skp
    call    MIOS_MIDI_MergerGet
    andlw   0x01
    bz  TIA_SYSEX_Send_SysExHeader_Skp
    movlw   0x05        ; send only DEVICE_ID
    movwf   TMP1
    rgoto   TIA_SYSEX_Send_SysExHeaderLoop
TIA_SYSEX_Send_SysExHeader_Skp

    clrf    TMP1
TIA_SYSEX_Send_SysExHeaderLoop
    movf    TMP1, W
    rcall   TIA_SYSEX_SysExHeaderGet
    call    MIOS_MIDI_TxBufferPut
    incf    TMP1, F
    movlw   0x06
    cpfseq  TMP1, ACCESS
    rgoto TIA_SYSEX_Send_SysExHeaderLoop
    return

;; --------------------------------------------------------------------------
;;  MIDI Send SysEx Footer (Util function)
;; --------------------------------------------------------------------------
TIA_SYSEX_Send_SysExFooter
    ;; if WREG[0]=1: send F7 regardless of the merger state
    BRA_IFSET WREG, 0, ACCESS, TIA_SYSEX_Send_SysExFooter_Force
    ;; send footer only if merger has been enabled
    ;; to ensure a proper MIDI protocol
    call    MIOS_MIDI_MergerGet
    andlw   0x01
    skpnz
    return

TIA_SYSEX_Send_SysExFooter_Force
    movlw   0xf7
    goto    MIOS_MIDI_TxBufferPut


;; --------------------------------------------------------------------------
;;  Changes the TIA Master patch
;;  IN: patch number in TIA_PATCH
;;      bank number in TIA_PBANK
;; --------------------------------------------------------------------------
TIA_SYSEX_ChangeMPatch
    return


;; --------------------------------------------------------------------------
;;  Sends a patch
;;  IN: patch number in TIA_PATCH
;;      bank number in TIA_PBANK
;;      TIA_SYSEX_CHECKSUM should be cleared if required
;;  OUT: 256 bytes will be sent
;;       checksum in TIA_SYSEX_CHECKSUM
;; --------------------------------------------------------------------------
TIA_SYSEX_Hlp_SendPreset
    movlw   (EEPROM_PATCH >> 8) & 0xff
    movwf   EEADRH
    clrf    EEADR           ; 0x80 bytes to send, use EEADR as counter
    ;;rgoto   TIA_SYSEX_Hlp_SendPresetLoop
TIA_SYSEX_Hlp_SendPresetLoop
    call    TIA_BANK_Read   ; read patch content (EEADR will be incremented)
    movwf   TABLAT      ; store data in TABLAT

    movlw   0x10+1      ; ensure that patch name doesn't contain characters < 0x20
    cpfslt  EEADR, ACCESS
    rgoto TIA_SYSEX_Hlp_SendPresetLoop_NoN
TIA_SYSEX_Hlp_SendPresetLoop_N
    movlw   0x20
    cpfslt  TABLAT, ACCESS
    rgoto TIA_SYSEX_Hlp_SendPresetLoop_NoN
    movwf   TABLAT
TIA_SYSEX_Hlp_SendPresetLoop_NoN
    movf    TABLAT, W
    andlw   0x7f        ; add to checksum
    addwf   TIA_SYSEX_CHECKSUM, F

    call    MIOS_MIDI_TxBufferPut; send byte

    btfss   EEADR, 7
    rgoto   TIA_SYSEX_Hlp_SendPresetLoop    ; loop 128 times

    return
    
    
    
;; --------------------------------------------------------------------------
;;  This function returns the absolute BANK # from relative xBANK #
;;  IN: Relative Bank in TIA_BANK, preset type in WREG
;;  OUT: Abslolute Bank in TIA_BANK, Error in WREG
;; --------------------------------------------------------------------------
TIA_SYSEX_Hlp_GetAbsoluteBank
    movwf   TMP1
    BRA_IFCLR  TMP1, 0, ACCESS, TIA_SYSEX_Hlp_GetAbsoluteBank_P
TIA_SYSEX_Hlp_GetAbsoluteBank_K
    movlw   16-(DEFAULT_BS_KBANK_ID*2)
    cpfslt  TIA_BANK, ACCESS
    rgoto   TIA_SYSEX_Hlp_GetAbsoluteBank_Err
    movf    TIA_BANK, W
    andlw   0x06
    rlncf   WREG, W
    btfsc   TIA_BANK, 0
    incf    WREG, W
    addlw   DEFAULT_BS_KBANK_ID*4
    BRA_IFSET  TMP1, 1, ACCESS, TIA_SYSEX_Hlp_GetAbsoluteBank_WT
    movwf   TIA_BANK
    movlw   0x00
    rgoto   TIA_SYSEX_Hlp_GetAbsoluteBank_End
    
TIA_SYSEX_Hlp_GetAbsoluteBank_WT
    addlw   0x02
    movwf   TIA_BANK   
    movlw   0x00
    rgoto   TIA_SYSEX_Hlp_GetAbsoluteBank_End
    
TIA_SYSEX_Hlp_GetAbsoluteBank_P
    ;; Saturate to max Patch banks (DEFAULT_BS_KBANK_ID*4-1)
    movlw   DEFAULT_BS_KBANK_ID*4
    cpfslt  TIA_BANK, ACCESS
    rgoto   TIA_SYSEX_Hlp_GetAbsoluteBank_Err
    movlw   0x00
    rgoto   TIA_SYSEX_Hlp_GetAbsoluteBank_End
    
TIA_SYSEX_Hlp_GetAbsoluteBank_Err
    movlw   0x06 ;; not valid xBANK
    
TIA_SYSEX_Hlp_GetAbsoluteBank_End
    return

;; --------------------------------------------------------------------------
;;  This function returns the absolute BANK # from relative xBANK #
;;  IN:  Abslolute Bank in TIA_BANK
;;  OUT: Relative Bank in TIA_BANK, preset type in WREG
;; --------------------------------------------------------------------------
TIA_SYSEX_Hlp_GetRelativeBank
    ;; Saturate to 32 absolute banks
    movlw   0x1f
    cpfslt  TIA_BANK, ACCESS
    movwf   TIA_BANK
    movlw   DEFAULT_BS_KBANK_ID*4
    subwf   TIA_BANK, W
    movwf   TMP1
    bnn     TIA_SYSEX_Hlp_GetRelativeBank_K
TIA_SYSEX_Hlp_GetRelativeBank_P   
    movlw   0x00
    rgoto   TIA_SYSEX_Hlp_GetRelativeBank_End
TIA_SYSEX_Hlp_GetRelativeBank_K
    BRA_IFSET  TMP1, 1, ACCESS, TIA_SYSEX_Hlp_GetRelativeBank_WT 
    incf    WREG, W
    rrncf   WREG, W
    movwf   TIA_BANK
    movlw   0x01
    rgoto   TIA_SYSEX_Hlp_GetRelativeBank_End
TIA_SYSEX_Hlp_GetRelativeBank_WT
    decf    WREG, W
    btfsc   WREG, 7
    movlw   0x00
    rrncf   WREG, W
    movwf   TIA_BANK
    movlw   0x03
TIA_SYSEX_Hlp_GetRelativeBank_End
    return

Generated by GNU enscript 1.6.4.