list    p=p16f873
        radix   dec
;
;	Test EEPROM and FLASH program single byte reads and writes.
;	on 16f873 which uses wide mode

  __config _WDT_OFF

	include "p16f873.inc"
        include <coff.inc>              ; Grab some useful macros


  cblock        0x20	; bank 0 and 2
        adr_cnt
        data_cnt
        status_temp
	datah
	datal
	ee_int
  endc

    ; W shadowing for interrupts
    ; When an interrupt occurs, we don't know what the current bank settings
    ; are. The solution here is to declare two temporaries that have the
    ; same base address. That way we don't need to worry about the bank setting.

  cblock        0x70
        w_temp          ; W is stored here during interrupts if the
                        ; bank bits point to bank 0 or 2
  endc
  cblock        0xf0
        w_temp_shadow   ; W is stored here during interrupts if the
                        ; bank bits point to bank 0 or 2
  endc

;;========================================================================
;;========================================================================
;
;       Start 
;
        org     0

        goto    start

        org     4

    ;;************** 
    ;; Interrupt
    ;;*************

        movwf   w_temp
        swapf   STATUS,W
        clrf    STATUS          ;Bank 0
        movwf   status_temp

	btfss	PIR2,EEIF
        goto   check

;;; eeprom has interrupted
	bcf	PIR2,EEIE
	incf	ee_int,F
	goto	i_ret

check:
  .assert "\"***  FAILED wide EEPROM unexpected interrupt\""
	nop

i_ret:
        clrf    STATUS          ;bank 0
        swapf   status_temp,W
        movwf   STATUS
        swapf   w_temp,F
        swapf   w_temp,W
        retfie
    ;;*************
    ;; end of interrupt
    ;;*************
     

start:  
        clrf    STATUS          ;Point to Bank 0
        clrf    adr_cnt
        clrf    data_cnt
 ;       bsf     INTCON,EEIE
        bsf     INTCON,PEIE
        bsf     INTCON,GIE
	bsf	STATUS,RP0	;Bank 1
	bsf	PIR2,EEIE
	bcf	STATUS,RP0	;Bank 0
;
;	write to EEPROM starting at EEPROM address 0
;	value of address as data using interrupts to
;	determine write complete. 
;	read and verify data

l1:     
	bcf	PIR2,EEIF
        movf    adr_cnt,W
	clrf	ee_int
        bcf     STATUS,RP0
        bsf     STATUS,RP1	;Bank 2
        movwf   EEADR ^ 0x100
        movf    data_cnt,W
        movwf   EEDATA ^ 0x100

        bcf     INTCON,GIE      ;Disable interrupts while enabling write

        bsf     STATUS,RP0	; Bank 3
        bcf     (EECON1 ^ 0x180),EEPGD   ;Point to data Memory
        bsf     (EECON1 ^ 0x180),WREN    ;Enable eeprom writes

        movlw   0x55            ;Magic sequence to enable eeprom write
        movwf   (EECON2 ^ 0x180)
        movlw   0xaa
        movwf   (EECON2 ^ 0x180)

        bsf     (EECON1 ^ 0x180),WR      ;Begin eeprom write

        bsf     INTCON,GIE      ;Re-enable interrupts
        
        clrf    STATUS          ; Bank 0
        movf   ee_int,W
	skpnz
        goto   $-2
;
;	read what we just wrote
;
	
        movf    adr_cnt,W

	bsf	STATUS,RP1
	bcf	STATUS,RP0      ; Bank 2
	movwf   EEADR
	bsf	STATUS,RP0      ; Bank 3
	bcf	EECON1,EEPGD	; point ot data memory
	bsf	EECON1,RD	; start read operation
	bcf	STATUS,RP0      ; Bank 2
	movf	EEDATA,W	; Read data
	clrf	STATUS		; Bank 0

	xorwf	data_cnt,W	; did we read what we wrote ?
	skpz
	goto fail

        incf    adr_cnt,W
        andlw   0x7f
        movwf   adr_cnt
	movwf	data_cnt

        skpz
         goto   l1
	
	goto flash

fail:
  .assert  "\"***  FAILED wide EEPROM Compare written and read\""
        goto    $

;
;	test program FLASH read and writes
;	    read low program memory (0x00XX)  
;	    write to higher memory (0x01XX)
;	    read and compare higher memory (0x1XX)

flash:

	bsf	STATUS,RP1
	bcf	STATUS,RP0      ; Bank 2
loop_prg:     
;
;	read low memory 0x00XX
;
	bsf	STATUS,RP1
	bcf	STATUS,RP0      ; Bank 2
	movwf	adr_cnt
	movwf   EEADR
	clrf	EEADRH
	bsf	STATUS,RP0      ; Bank 3
	bsf	EECON1,EEPGD	; point to program memory
	bsf	EECON1,RD	; start read operation
	nop
	nop
	bcf	STATUS,RP0      ; Bank 2
	movf	EEDATA,W	; save read data
	movwf	datal
	movf	EEDATH,W
	movwf	datah
;
;  Write to High address (0x01XX) data alredy in EEDATA, EEDATAH
;
	movlw	0x01
	movwf	EEADRH
	movf	adr_cnt,W
        movwf   EEADR ^ 0x100

        bcf     INTCON,GIE      ;Disable interrupts while enabling write
        bsf     STATUS,RP0	; Bank 3
        bsf     (EECON1 ^ 0x180),EEPGD   ;Point to program Memory
        bsf     (EECON1 ^ 0x180),WREN    ;Enable eeprom writes
        movlw   0x55            ;Magic sequence to enable write
        movwf   (EECON2 ^ 0x180)
        movlw   0xaa
        movwf   (EECON2 ^ 0x180)

        bsf     (EECON1 ^ 0x180),WR      ;Begin write
	nop
	nop

        bsf     INTCON,GIE      ;Re-enable interrupts
        bcf     (EECON1 ^ 0x180),WREN    ;Disable writes
        
        btfsc   (EECON1 & 0x7f),WR
         goto   $-1
;
;	read what we just wrote
;

	bcf	STATUS,RP0      ; Bank 2
        movf    adr_cnt,W
	movwf   EEADR
	movlw	0x01
	movwf	EEADRH
	bsf	STATUS,RP0      ; Bank 3
	bsf	EECON1,EEPGD	; point to program memory
	bsf	EECON1,RD	; start read operation
	bcf	STATUS,RP0      ; Bank 2
	movf	EEDATA,W	; Read data
	xorwf	datal,W
	skpz
	goto	fail_prog	; low byte does not match
	movf	EEDATH,W	; Read data
	xorwf	datah,W
	skpz
	goto	fail_prog	; low byte does not match
	nop
	nop

        incf    adr_cnt,W
        andlw   0x3f
        movwf   adr_cnt
        skpz
         goto   loop_prg

  .assert  "\"*** PASSED wide EEPROM and program FLASH read-write test\""
        goto    $

fail_prog:
  .assert  "\"***  FAILED wide program FLASH Compare written and read\""
        goto    $


        org     0x2100
	de	"0123456789ABCDEF"
        de      "Linux is cool!",0
        de      0xaa,0x55,0xf0,0x0f
        de      'g','p','s','i','m'

   end


syntax highlighted by Code2HTML, v. 0.9.1