; <<< START OF 89S8252 PRIMER >>>

; SFR definitions ***********************************************************
;
; The WMCON register is not bit-addressable, so Boolean operations are used
; to control functions and test bits.

WMCON   DATA 96H        ; watchdog and memory control register
EEMEN   EQU 00001000B   ; EEPROM access enable bit
EEMWE   EQU 00010000B   ; EEPROM write enable bit
WDTRST  EQU 00000010B   ; EEPROM RDY/BSY* bit
DPS     EQU 00000100B   ; data pointer select bit
WDTEN   EQU 00000001B   ; watchdog timer enable bit
PS0     EQU 00100000B   ; watchdog timer period select bits
PS1     EQU 01000000B   ;
PS2     EQU 10000000B   ;
                        ;
PCON    DATA 87H        ;
POF     EQU 00010000B   ; Power Off Flag bit
                        ;
;SP      DATA  81H       ;

; Define the new data pointer SFRs for a generic 8051 assembler.

DP0L    DATA 82H        ; data pointer 0
DP0H    DATA 83H        ;
DP1L    DATA 84H        ; data pointer 1
DP1H    DATA 85H        ;

;STACK **********************************************************************
	dseg at 03fh
STACK_START: ds 040h

;INTERRUPT TABLE ************************************************************
	CSEG AT 0
	AJMP XRESET
	ORG 003H
	AJMP UNDEFINED_ISR
	ORG 00BH
	AJMP UNDEFINED_ISR
	ORG 013H
	AJMP UNDEFINED_ISR
	ORG 01BH
	AJMP UNDEFINED_ISR
	ORG 023H
	AJMP UNDEFINED_ISR

;****************************************************************************
;START OF PROGRAM
;****************************************************************************
;
	SAMPLE_CODE segment code
	rseg 	SAMPLE_CODE

; Power Off Flag ************************************************************
;
; After reset, the controller begins executing code at program memory
; address 0000H. POF is tested to determine if the controller was reset by
; the application of power (cold start) or a high on RST (warm start).
; Code for the cold start and warm start routines is not shown.

 XRESET:                ; code for responding to reset
  MOV A, PCON           ; get Power Control register
  ANL A, #POF           ; test Power Off Flag
  JZ warm_start         ; POF=0 indicates reset from RST

  XRL PCON, #POF        ; clear POF for next time
  JMP cold_start        ; POF=1 indicates reset from power

 warm_start:
; do something needed only after warm start
  NOP                   ;
  JMP START             ;

 cold_start:
; do something needed only after cold start
  NOP                   ;
  JMP START             ;

START:
  mov SP,#STACK_START   ; initialize stack
; EEPROM ********************************************************************
;
; EEPROM read example.

  ORL WMCON, #EEMEN     ; enable EEPROM accesses
  MOV DPTR, #00H        ; address to read
  MOVX A, @DPTR         ; read EEPROM
  XRL WMCON, #EEMEN     ; disable EEPROM accesses

; EEPROM write example, utilizing RDY/BSY* to determine the end of
; the write cycle. Write is followed by verify (read and compare),
; but code to handle a verification failure is not shown.
; Needs a timeout to prevent a write error from causing an infinite loop.

  ORL WMCON, #EEMEN     ; enable EEPROM accesses
  ORL WMCON, #EEMWE     ; enable EEPROM writes

  MOV DPTR, #00H        ; address to write
  MOV A, #055H          ; data to write
  MOVX @DPTR, A         ; write EEPROM
 LOOP1:
  MOV A, WMCON          ; get EEPROM write status
  ANL A, #WDTRST        ; check RDY/BSY*
  JZ LOOP1              ; jump if busy

  MOVX A, @DPTR         ; read EEPROM
 CHECK:
  CJNE A, #055H,CHECK   ; lock up if data compare fails

  XRL WMCON, #EEMWE     ; disable EEPROM writes
  XRL WMCON, #EEMEN     ; disable EEPROM accesses

; EEPROM write example, utilizing DATA* Polling to determine the end of
; the write cycle. After data is loaded, the code loops on read until
; data is returned true. Write verification is implicit in this method.
; Needs a timeout to prevent a write error from causing an infinite loop.

  ORL WMCON, #EEMEN     ; enable EEPROM accesses
  ORL WMCON, #EEMWE     ; enable EEPROM writes

  MOV DPTR, #01H        ; address to write
  MOV A, #033H          ; data to write
  MOVX @DPTR, A         ; write EEPROM
 LOOP2:
  MOVX A, @DPTR         ; read EEPROM
  CJNE A, #033H, LOOP2  ; jump if data compare fails (busy)

  XRL WMCON, #EEMWE     ; disable EEPROM writes
  XRL WMCON, #EEMEN     ; disable EEPROM accesses

; Dual Data Pointers ********************************************************
;
; Copy block from program memory to external data memory.

  MOV R7, #4            ; block byte count
  MOV DPTR, #pgm_addr   ; pointer to program memory
  XRL WMCON, #DPS       ; switch data pointers
  MOV DPTR, #1000H      ; pointer to external data memory
 LOOP3:
  XRL WMCON, #DPS       ; switch data pointers
  CLR A                 ; read program memory
  MOVC A, @A+DPTR       ;
  INC DPTR              ; advance program memory pointer
  XRL WMCON, #DPS       ; switch data pointers
  MOVX @DPTR, A         ; write external data memeory
  INC DPTR              ; advance external data memory pointer
  DJNZ R7, LOOP3        ; continue until done

; Copy block from external data memory to on-chip EEPROM.
; Utilizes RDY/BSY* to determine the end of the EEPROM write cycle.
; Needs a timeout to prevent a write error from causing an infinite loop.

  ORL WMCON, #EEMEN     ; enable EEPROM accesses
  ORL WMCON, #EEMWE     ; enable EEPROM writes

  MOV R7, #4            ; block byte count
  MOV DPTR, #0000H      ; pointer to EEPROM
  XRL WMCON, #DPS       ; switch data pointers
  MOV DPTR, #01000H     ; pointer to external data memory
 COPY:
  MOVX A, @DPTR         ; read external data memory
  INC DPTR              ; advance external data memory pointer
  XRL WMCON, #DPS       ; switch data pointers
  MOVX @DPTR, A         ; write EEPROM
  INC DPTR              ; advance EEPROM pointer
  XRL WMCON, #DPS       ; switch data pointers
 WAIT:
  MOV A, WMCON          ; get EEPROM write status
  ANL A, #WDTRST        ; check RDY/BSY*
  JZ WAIT               ; jump if busy
  DJNZ R7, COPY         ; continue until done

  XRL WMCON, #EEMWE     ; disable EEPROM writes
  XRL WMCON, #EEMEN     ; disable EEPROM accesses

; IMPORTANT: The state of DPS affects ALL accesses to the data pointer SFRs
; (82H, 83H, 84H, 85H). Any machine instruction whose operand is one of the
; data pointer SFRs may produce unexpected results, as shown below. The user
; must exercise caution to avoid accessing the wrong SFRs.
;
  ORL WMCON, #DPS       ; set DPS
  PUSH DP0L             ; PUSHES DP1L !!!
  MOV 83H, A            ; COPIES ACCUMULATOR TO 85H !!!
  XRL WMCON, #DPS       ; clear DPS
  PUSH DP1H             ; PUSHES DP0H !!!
  MOV 84H, A            ; COPIES ACCUMULATOR TO 82H !!!

; Watchdog Timer ************************************************************
;
; Use the watchdog timer to regain control of the microcontroller if an
; operation takes longer than expected. The details of the operation are not
; shown. The operation is expected to take less than 30 mS to complete and
; the reset period chosen is 32 mS. Adequate margin must be allowed between
; the desired reset period and the selected period to allow for the excessive
; slop present in the timer.
; The WMCON register is not bit-addressable, so Boolean operations are used.

  ORL WMCON, #PS0       ; select 32 mS period
  ORL WMCON, #WDTEN     ; enable watchdog
 LOOP:
; Do something which normally takes less than 30 mS.
  NOP
  NOP
;
  ORL WMCON, #WDTRST    ; keep watchdog at bay
  JMP LOOP
; <<< END OF 89S8252 PRIMER >>>

pgm_addr:
  DB 011H,022H,033H,044H

UNDEFINED_ISR:
  clr EA
  sjmp $

END
