;*********************************************************************
;*
;*              Flash Routines for 29F160 (2 MB) Memory in 16-bit mode
;*
;*********************************************************************
;* FileName:        29F16016.ASM
;* Dependencies:    
;* Processor:       PIC18C601/801
;* Complier:        MPLAB 5.11.00
;* Company:         Microchip Technology, Inc.
;*
;* Software License Agreement
;*
;* The software supplied herewith by Microchip Technology Incorporated
;* (the Company) for its PICmicro Microcontroller is intended and
;* supplied to you, the Companys customer, for use solely and
;* exclusively on Microchip PICmicro Microcontroller products. The
;* software is owned by the Company and/or its supplier, and is
;* protected under applicable copyright laws. All rights are reserved.
;* Any use in violation of the foregoing restrictions may subject the
;* user to criminal sanctions under applicable laws, as well as to
;* civil liability for the breach of the terms and conditions of this
;* license.
;*
;* THIS SOFTWARE IS PROVIDED IN AN AS IS CONDITION. NO WARRANTIES,
;* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
;* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
;* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
;* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
;* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;*
;*
;* NOTE: This file must only use "bra" and "rcall" jump instructions.
;*       This code is "relocated" at run time and hence this
;*       restriction must be ovserved.
;*
;* Author               Date        Comment
;*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;* NKR                  1/30/01     Original (Rev. 1.0)
;********************************************************************/

#include <p18c801.inc>

#include "MEMRTNES.INC"



; Just a helpful macro to unlock and modify secured registers.
UNLOCK_N_MODIFY macro   @REG
    bsf     PSPCON, CMLK1                   ; 
    bsf     PSPCON, CMLK0
    movwf   @REG
    endm

DO_TBLWT_POSTINC macro
    tblwt*+
    endm
    
DO_TBLWT macro
    tblwt*
    endm

DO_TBLRD    macro
    tblrd*
    endm
    
DO_TBLRD_POSTDEC    macro   
    tblrd*-
    endm




; Any local/private data this programmer may have should go here.
ProgrammerData      UDATA_ACS

BufferedLSB     RES     01h

; Starting address of Programmer really does not matter at this
; stage.  Address 1000h is chosen just to make sure that it
; does not overlap with monitor software.
Programmer      CODE    1000h


JumpTable:
; Jump table for Memory routines - used by monitor/bootloader code.
    bra     Write           
    bra     Erase           

;***************************************************************************
; Function: WREG Write(DWORD Address, BYTE Byte, BYTE Flags)
;
; Input:    Address                     : 32-bit address to write to
;           Byte                        ; 8-bit data value to be written
;           Flags                       ; Special flags
;                               
;
; Output:   WERG                        : 0 if successful
;                                       ; Else error code
;
; Side Effects: Databank is changed
;
; Overview: 
;***************************************************************************
Write:
    rcall   _InitializeProgrammer       ; Setup appropriate Table Write mode
                                        ; This could be done only once based
                                        ; on flag.  We will do it later on..

    btfsc   Address, 0                  ; Is this odd address ?
    bra     Write_Flash
    movff   Byte, BufferedLSB           ; Remember LSB until we receive MSB
    retlw   00h
    
Write_Flash:
    rcall   UnlockFlash                 ; Write UNLOCK command

    movlw   0a0h                        ; Write Program SETUP command.
    movwf   TABLAT                        
    rcall   CommandFlash

    movff   Address, TBLPTRL            ; Write actual data.
    decf    TBLPTRL
    movff   Address+1, TBLPTRH
    movff   Address+2, TBLPTRU
    movff   BufferedLSB, TABLAT
    DO_TBLWT_POSTINC                    ; Write LSB

    movff   Byte, TABLAT
    DO_TBLWT                            ; Write MSB

    bcf     TBLPTRL, 0                  ; Interested in LSB only.

Write_Wait:                             ; Wait til it is written
    DO_TBLRD
    movf    TABLAT, W
    movwf   PRODL                       ; Save status value
    xorwf   BufferedLSB, W              ; Write is complete when
    btfss   WREG, 7                     ; DQ7 is same as D7 
    return                              ; If it is not, check for any error
    
    btfss   PRODL, 5                    ; Any error ?
    bra     Write_Wait                  ; No. Continue waiting...
    DO_TBLRD                            ; Re-read the LSB as per algorithm
    movf    TABLAT, W
    xorwf   BufferedLSB, W              ; Success if DQ7 = D7 or failed 
                                        ; otherwise
    return


;***************************************************************************
; Function: WREG Erase(void)
;
; Input:    None
;
; Output:   WERG                        : 0 if successful
;                                       ; Else error code
;
; Side Effects: Databank is changed
;
; Overview: 
;***************************************************************************
Erase:
    rcall   _InitializeProgrammer       ; Setup appropriate Table Write mode

    rcall   UnlockFlash                 ; Write UNLOCK sequence

    movlw   80h                         ; Write Erase Setup command
    movwf   TABLAT
    rcall   CommandFlash

    rcall   UnlockFlash                 ; One more UNLOCK command.

    movlw   10h                         ; Erase entire chip
    movwf   TABLAT
    rcall   CommandFlash

    bcf     TBLPTRL, 0                  ; Interested in LSB only.
Erase_Wait:                             ; Wait till Erase is complete
    DO_TBLRD
    movf    TABLAT, W 
    xorlw   0ffh
    bnz     Erase_Wait
    return


; Local Routines
UnlockFlash:
    movlw   0aah                        ; Write UNLOCK sequence
    movwf   TBLPTRL
    movwf   TABLAT
    movlw   0ah
    movwf   TBLPTRH
    clrf    TBLPTRU
    DO_TBLWT_POSTINC
    clrf    TABLAT
    DO_TBLWT

    movlw   054h                        ; Write SETUP sequence
    movwf   TBLPTRL
    movlw   05h
    movwf   TBLPTRH
    clrf    TBLPTRU
    movlw   55h
    movwf   TABLAT
    DO_TBLWT_POSTINC
    clrf    TABLAT
    DO_TBLWT
    return


; CommandFlash(TABLAT Command)
CommandFlash:
    movlw   0aah                          
    movwf   TBLPTRL
    movlw   0ah
    movwf   TBLPTRH
    clrf TBLPTRU
    DO_TBLWT_POSTINC
    clrf    TABLAT
    DO_TBLWT
    return




;***************************************************************************
; Function: void _InitializeProgrammer()
;
; Input:    None
;
; Output:   None
;
; Side Effects: Databank is changed
;
; Overview: Initialize all peripherals on board.
;***************************************************************************
_InitializeProgrammer:
    movf    MEMCON, W                   ; Set 16-bit Byte Write mode.
    bsf     WREG, WM1                   ; Select 16-bit Write Mode
    bcf     WREG, WM0
    bsf     WREG, 5
    bsf     WREG, 4
    UNLOCK_N_MODIFY MEMCON
    return

    END



