;***********************************************************************************
; LISTING NO.: 1
;
; FILE NAME: FPQB.ASM
; PURPOSE: To provide a FLASH erase, program and verify program
; TARGET DEVICE: HC908QT1/2/4/QY1/2/4
;
; MEMORY USAGE - RAM: 1A0H BYTES
;			ROM: 280H BYTES
;
; ASSEMBLER: CASM08
; VERSION: 1.02
;
; PROGRAM DESCRIPTION:
; This program loads a RAM routine with instructions/data
; located in FLASH memory that:
;	Receives data over the SCI or Port A, bit 0
;	Row-erases FLASH block if necessary
;	Programs FLASH with received data
;	Dumps specified row out comm port
;	Bulk erases device upon command
;
; The program has assembler directives to be able to program in
; both user and monitor modes. In monitor mode, the generated S-record
; file will contain all of the necessary programming routines in RAM. It
; will not have any code that would reside out of RAM. In user mode, load
; routines are incorporated so that it could be contained in a user's
; application. The load routines load the programming routines into RAM and
; from there it looks just like the RAM routine executed in monitor mode.
;
;
; AUTHOR: Grant Whitacre
; LOCATION: Austin, Texas
;
; UPDATE HISTORY:
; REV	AUTHOR		DATE		DESCRIPTION OF CHANGE
; ===	============	========	=====================
; 0.0	GRANT WHITACRE	03/04/98	INITIAL VERSION
; 0.1	GRANT WHITACRE	04/15/98	SECOND VERSION (FP2.ASM)-
;					LOADS ALL RTNS INTO RAM
;					SO RE-ENTRY INTO FLASH IS
;					NOT NECESSARY. ALLOWS
;					REPROGRAMMING OF ENTIRE
;					FLASH ARRAY.
; 0.2	GRANT WHITACRE	06/22/98	CONSOLIDATES PROGRAM TO
;					ALLOW BOTH USER MODE AND
;					MONITOR MODE PROGRAMMING
;					SELECTABLE BY ASSEMBLER
;					DIRECTIVES
;
;
; GENERAL CODING NOTES:
; Bit names are labeled with <port name><bit number> and are
; used in the commands that operate on individual bits, such
; as BSET and BCLR. A bit name followed by a dot indicates
; a label that will be used to form a bit mask.
;
; FOR TESTING, HAD TO ADD AN ASSEMBLER SWITCH (TESTMOD) TO
; KEEP FROM TRIPPING ON AN ILLEGAL MEMORY WRITE BREAK IN
; THE DEBUGGER. OTHER SWITCHES ARE INSTALLED FOR EASE OF
; TESTING.
;
;***********************************************************************************
; ASSEMBLER DIRECTIVES
; (INCLUDES, BASE, MACROS, SETS, CONDITIONS, RAM DEFS, ETC.)
;***********************************************************************************
	       .radix	D		;DEFAULT TO BASE 10 NUMBER DESIGNATION
						        ;Remember: ACTIVE LOW!!!!!!!!!!!!!!!!!!
;***********************************************************************************
; PORT AND I/O REGISTER EQUATES
;***********************************************************************************
PORTA		=	$$00			;I/O PORT A
;***********************************************************************************
; APPLICATION-SPECIFIC MEMORY AND I/O EQUATES
;***********************************************************************************
; ABS. ADDRESS OF MONITOR ROUTINES COMMENTED OUT IN TEST VERSION
GETBYTE         = $$2800        ;GETS A BYTE WITHOUT ECHO - QB/QT/QY
PUT_BYTE  		= $$280F        ;SEND A BYTE OUT PTA0 - QB
;
RDVRRNG         = $$2803        ;QT/QY/QB RDVRRNG jump address
ERARNGE         = $$2806        ;QT/QY/QB ERARNGE jump address
PRGRNGE         = $$2809        ;QY/QY/QB PRGRNGE jump address
;
RAMSTART		=  $$80			;FIRST ADDRESS OF RAM - QT1/2/4 QT1/2/4 QB4 (anche QB8)
;***********************************************************************************
; VARIABLE DEFINITIONS & RAM SPACE USAGE
;***********************************************************************************
;
;           Table 5. Data Structure Location and Content
; Location          Variable Name            Size              Description
; RAM + $08            CTRLBYT              1 byte  Control byte setting erase size
;                                                  CPU speed passed as 4 × fop
; RAM + $09            CPUSPD               1 byte
; RAM + $0A             LADDR              2 bytes  Last address for read a range
; RAM + $0B                                         and program a range
; RAM + $0C              DATA              Variable Variable number of bytes of
;                                                  passed data for programming or
;                                                  verifying a block
; $$88		TRANSFER SIZE			( 1 BYTE)
; $$89-$8A	FIRST ADDRESS TO BE PROGRAMMED( 2 BYTES)
; $$8B		DATA SIZE (DATASIZ)		( 1 BYTE)
; $$8C-$AB	DATA ARRAY			( 32 BYTES)
; $$AC-$EF	RAM PROGRAM			( 72 BYTES)
; $$F0-$FF	STACK				( 16 BYTES)
;
; $$FA      STACK (QT/QY initial value)
; - Call DumpROW/PGM        2 byte (F8)
; - Call DELNUS (from pgm)  2 byte (F6)
            .area	RAMPGM	(ABS)
		    .org	RAMSTART
		    .blkb 	6     		; Spare ...
FRSADDRT: 	.blkb 	2     		; Temporary start address
RXBLOCK:              			; Address of received block (receive)
XFRSIZE:	       				;NUMBER OF BYTES TO BE TRANSFERRED (receive)
CTRLBYT:  	.blkb 	1     		; 88 - Control byte setting erase size
FRSTADR:	            		;FIRST ADDR TO BE PROGRAMMED (receive)
CPUSPD:   	.blkb 	1     		; 89 - CPU speed passed as 4 × fop
FRSTADRLO:            			;FIRSR ADDR TO BE PROGRAMMED (LO)
LADDR:    	.blkb 	1     		; 8A Last address for read a range
                      			;    and program a range
LADDRLO:              			; 8B Last address (lo)                      
DATASIZ:	.blkb	1			;NUMBER OF BYTES TO PROGRAM (receive)
DATARAY:	            		;RESERVE 32 BYTES FOR DATA (receive)
DATA:     	.blkb 	32    		; 8C Variable Variable number of bytes of
                      			;    passed data for programming or
                      			;    verifying a block
;
;***********************************************************************************
;	Program Algorithm (User Mode Programming)
;	1.	Initialize all variables and ports, PLL (if selected) and
;		SCI.
;	2.	Monitor SCI port for input of block of data to be
;		programmed and the start address. Load RAM with the data
;		array (up to 64 bytes), the start address and length of
;		data array.
;	3.	Transfer the following subroutines to
;		RAM at address RAMPRG
;		A.	LDDATA
;		B.	MAINPRG
;		C.	ERABLK
;		D.	DELNUS
;		E.	PROGRAM
;	4.	Jump to first byte of main RAM program (RAMPRG).
;	5	Execute RAM program MAINPRG and then return to SCI
;		port monitoring loop in RAM.
;
;	Program Algorithm - Monitor Mode Programming
;	1.	Monitor PTA0 for input of block of data to be
;		programmed and the start address. Load RAM with the data
;		array (up to 64 bytes), the start address and length of
;		data array.
;	2.	Execute RAM program MAINPRG and then return to PTA0
;		monitoring loop in RAM.
;***********************************************************************************
;
; START OF PROGRAM
;***********************************************************************************
; START OF THE MONITOR PROGRAM WHICH WE'LL .org IN RAM
START:
;***********************************************************************************
; NAME: LDDATA
; PURPOSE: LOAD RAM WITH USER'S DATA AND START ADDRESS VIA THE SCI;
;          PROGRAMS AND THEN DUMPS DATA THAT IS DOWNLOADED; ONLY DUMPS DATA
;          IN ROW SPECIFIED IF NUMBER OF BYTES TO BE PROGRAMMED (DATASIZ) IS 0.
; ENTRY CONDITIONS:
; EXIT CONDITIONS:
; SUBROUTINES CALLED: PRGFLSH, DUMPROW
; EXTERNAL VARIABLES USED:
; DESCRIPTION: EXECUTED OUT OF RAM
; THE STRUCTURE OF THE DATA RECEIVED IS AS FOLLOWS:
;	LOCATION	DESCRIPTION				RAM LOC.
;	========	==================================	========
;	1		COUNT OF THE TOTAL NUMBER OF		$$40
;			BYTES TO BE SENT (INCL. THAT BYTE)
;	2-3		THE FIRST ADDRESS WHERE THE		$$41-$42
;			FOLLOWING DATA IS TO BE PROGRAMMED
;	4		NUMBER OF BYTES TO BE PROGRAMMED	$$43
;	5-68		ARRAY SPACE FOR DATA TO BE PROGRAMMED	$$44-$83
;
; IF A COUNT IS USED THAT IS GREATER THAN (PROGRAM LENGTH + 1)
; THEN THE ROUTINE WILL HANG AFTER THE LAST PROGRAM BYTE IS SENT.
; CONTINUOUSLY LOOPS LOOKING FOR NEW DATA ON THE SCI. MUST RESET
; AFTER THE LAST ROW DOWNLOAD.
; IF A DATA ARRAY IS RECEIVED WITH A NUMBER OF BYTES TO BE PROGRAMMED OF >= $$80
; THEN PROGRAM WILL CONSTRUE THIS AS A SIGNAL TO ERASE THE ENTIRE ARRAY. THIS
; WAS THE MOST CONVENIENT WAY TO IMPLEMENT BULK ERASE WITHOUT HAVING TO HAVE
; A COMMAND BYTE IN THE DATA STRUCTURE.
;***********************************************************************************
LDDATA:
      	  CLRH
          CLRA
          LDX     #XFRSIZE      ;POINT TO START OF RAM
WAITRX:
          jsr     GETBYTE		; Reads a byte from Debug serial
CHKCHK:	  CPX     #RXBLOCK      ;IF VALUE OF 1ST BYTE IS ZERO, THEN
          BNE     STORNOW       ;BAD START - KEEP LOOPING FOR NON-
          TSTA                  ;ZERO FIRST BYTE
          BEQ     WAITRX
STORNOW:  STA     ,X            ;STORE THE DATA IN RAM
          jsr     PUT_BYTE		; Echoes back the read byte
          INCX                  ;MOVE TO NEXT RAM LOCATION
          DBNZ    *RXBLOCK,WAITRX ;DEC. PROG SIZE CNTR (1st BYTE)
						        ;IF ENTIRE PROG NOT LODED, CONT.
; **********************************************************************************
; Block completely read - continue with programming
; **********************************************************************************
          LDA     *DATASIZ      ;IF SIZE OF DATA TO BE PROGRAMMED
          LDHX    FRSTADR
          STHX    FRSADDRT      ; copies received start in temporary location
          DEC     A             ; decrement count (to address last byte)
          ADD     *FRSTADRLO    ; adds start address (lo)
          STA     LADDRLO       ; stores in routine's data struc
          LDA     #0
          ADC     *FRSTADR      ; hi byte sum
          STA     *LADDR        ; stores in routine's data struc
          ldhx    FRSADDRT      ;Load beginning address of range
          mov     #$$0A,CPUSPD  ;2.45 MHZ OPER. FREQ. * 4 -> 10
          mov     #$$40,CTRLBYT ;Select Mass erase operation
          jsr     ERARNGE       ;Call ERARNGE routine (jumps into)
          bclr    #0,*PORTA     ;0,$PORTA   ; PTA     ;Initialize data bit to zero PTA0=0
          ldhx    FRSADDRT      ;Load beginning address of range
                                ; to H:X
          clra                  ;A=0 to select send-out option
          jsr     RDVRRNG       ;Call RDVRRNG routine
                                ; A contains a checksum value
          BRA     LDDATA        ;Waits for other commands
