CPU16B Assembler v1.2  (C) Copyright 2010 John B. Stephensen
0 errors, 46 symbols used, 4070 instructions.

Line Addr  Inst Source
   1            ;
   2            ; Program Loader for DCP-3
   3            ; Z = reset memory address
   4            ; $ = load memory with data
   5            ; W = write to flash memory
   6            ; R = read from flash memory
   7            ; X = execute code at address 0
   8            ;
   9            	PRAM	4	; place in 4 block RAMs
  10            ;
  11            ; LED Control
  12            ;
  13            LEDON	EQU	$7E	; modified 2010-7-20
  14            LEDOFF	EQU	$7F
  15            ;
  16            ; UART
  17            ;
  18            UDATA	EQU	$20	; UART data FIFO
  19            UBAUD	EQU	$21	; UART baud rate divisor
  20            USTAT	EQU	$21	; UART status register
  21            URXR	EQU	0	; receiver ready bit (FIFO not empty)
  22            URXF	EQU	1	; receiver full
  23            UTXR	EQU	2	; transmitter ready (FIFO not full)
  24            UTXE	EQU	3	; transmitter empty
  25            ;
  26            ; Reset loads this program and starts execution here
  27            ;
  28 0000: 0F00 START:	CALL	INIT	; call loader (replaced when data laoded)
  29 0001: 0000 	DS	3839	; place loader at top of memory (0F00)
  30            ;
  31            ; Loader starts here
  32            ;
  33 0F00: 72A1 INIT:	MVI	R1,42	; divide by 43 for
  34 0F01: BA11 	OUT	R1,UBAUD ; 116.28 kbaud (+0.9%)
  35 0F02: 0F39 SPIN:	CALL	GETC	; decode commands
  36 0F03: 0F19 	CALL	ZERO
  37 0F04: 0F24 	CALL	DATA
  38 0F05: 0FC4 	CALL	WFLASH
  39 0F06: 0FD4 	CALL	RFLASH
  40 0F07: 0F10 	CALL	RUN
  41 0F08: 0F0A 	CALL	COMMENT
  42 0F09: 41F8 	JMP	SPIN
  43            ;
  44            ; Discard comment lines
  45            ;
  46            COMMENT:
  47 0F0A: 93B1 	CPI	R1,';'	; comment?
  48 0F0B: 5A00 	RNZ
  49 0F0C: 0F39 SKIP:	CALL	GETC
  50 0F0D: 90D1 	CPI	R1,13	; CR?
  51 0F0E: 4BFD 	JNZ	SKIP
  52 0F0F: 40D4 	JMP	DONE
  53            ;
  54            ; Execute program
  55            ;
  56 0F10: 9581 RUN:	CPI	R1,'X'	; execute program?
  57 0F11: 5A00 	RNZ
  58 0F12: 0F39 	CALL	GETC
  59 0F13: 90D1 	CPI	R1,13	; CR?
  60 0F14: 4ACE 	JNZ	ERROR
  61 0F15: 0000 	CALL	START	; start program
  62 0F16: 72A1 	LDL	R1,42	; divide by 43 for
  63 0F17: BA11 	OUT	R1,UBAUD ; 116.28 kbaud (+0.9%)
  64 0F18: 40CB 	JMP	DONE
  65            ;
  66            ; Reset Address and turn off error LED
  67            ; Call:	R1 = command
  68            ;
  69 0F19: 95A1 ZERO:	CPI	R1,'Z'	; set address?
  70 0F1A: 5A00 	RNZ
  71 0F1B: 0F39 	CALL	GETC
  72 0F1C: 90D1 	CPI	R1,13	; CR?
  73 0F1D: 4AC5 	JNZ	ERROR
  74 0F1E: AD0F 	LDA	R15,ADDR
     0F1F: 738F
  75 0F20: E311 	CLR	R1	; reset address
  76 0F21: B0F1 	WR	R1,R15
  77 0F22: BFFF 	OUT	R15,LEDOFF
  78 0F23: 40C0 	JMP	DONE
  79            ;
  80            ; Program Loader
  81            ; Call:	R1 = command
  82            ; Uses:	R1 = UART data/status
  83            ;	R2 = word assembly
  84            ;	R3 = checksum
  85            ;	R4 = address
  86            ;	R15 = temp
  87            ;
  88            ;   0   1  2  3  4   5       N  N+1     N+4 N+5
  89            ; +---+------------+----/ /----+-----------+---+
  90            ; | $ |    Data    |   Data    | Checksum  | CR|
  91            ; +---+------------+----/ /----+-----------+---+
  92            ;
  93            ; Checksum and data words are 4 hexidecomal digits each,
  94            ; transmitted most significant digit first. There may be
  95            ; 0-16 data words. The checksum is 0 minus the modulo-
  96            ; 65,536 sum of all words following '$'. 
  97            ;
  98 0F24: 9241 DATA:	CPI	R1,'$'	; load data?
  99 0F25: 5A00 	RNZ
 100 0F26: E333 	CLR	R3	; yes, clear checksum
 101 0F27: AD0F 	LDA	R15,ADDR
     0F28: 738F
 102 0F29: C8F4 	RD	R4,R15	; get next address
 103 0F2A: 0F4E DATA0:	CALL	GETWD	; get data
 104 0F2B: 4E03 	JNC	DATA1	; done if not hexidecimal number
 105 0F2C: B042 	WR	R2,R4	; store in memory
 106 0F2D: 8014 	INC	R4	; increment address
 107 0F2E: 41FB 	JMP	DATA0	; loop if hexidecimal
 108 0F2F: 8FF4 DATA1:	DEC	R4	; don't count checksum
 109 0F30: 90D1 	CPI	R1,13	; check for CR
 110 0F31: 4AB1 	JNZ	ERROR	; error if not CR
 111 0F32: 9003 	CPZ	R3	; test checksum
 112 0F33: 4AAF 	JNZ	ERROR	; error if checksum not zero
 113 0F34: AD0F 	LDA	R15,ADDR
     0F35: 738F
 114 0F36: B0F4 	WR	R4,R15	; save next address
 115 0F37: 40AC 	JMP	DONE
 116 0F38: 0000 ADDR:	DW	0
 117            ;
 118            ; Get character from UART and place in LSB of R1
 119            ;
 120 0F39: C211 GETC:	IN	R1,USTAT	; read status
 121 0F3A: AC01 	TST	R1,URXR		; and check for RXE=0
 122 0F3B: 4FFD 	JNC	GETC
 123 0F3C: C201 	IN	R1,UDATA	; get received byte
 124 0F3D: E471 	MASK	R1,7		; and remove top bit
 125 0F3E: 9001 	CPZ	R1
 126 0F3F: 49F9 	JZ	GETC		; ignore nulls
 127 0F40: 5000 	RET
 128            ;
 129            ; Get hexidecimal digit from UART and place binary in R1
 130            ; Returns characters less than '0' unaltered.
 131            ;
 132 0F41: 0F39 GETHEX:	CALL	GETC	; returns received character in R1
 133 0F42: 9301 	CPI	R1,'0'	; set carry if A >= B
 134 0F43: 5E00 	RNC		; return if less than '0'
 135 0F44: 8D01 	SBI	R1,'0'	; convert '0'-'9' to 0-9
 136 0F45: 709F 	LDL	R15,9
 137 0F46: AB1F 	CMP	R15,R1	; set carry if A >= B
 138 0F47: 5C00 	RC		; return if 0-9
 139 0F48: 8F91 	SBI	R1,7	; subtract 'A'-'9'-1
 140 0F49: 90A1 	CPI	R1,10	; set carry if A >= B
 141 0F4A: 5E00 	RNC		; return if between '9' and 'A'
 142 0F4B: 70FF 	LDL	R15,15	; compare to maximum
 143 0F4C: AB1F 	CMP	R15,R1	; set carry if A >= B
 144 0F4D: 5000 	RET		; carry set if 0-15
 145            ;
 146            ; Assemble 16-bit word from 4 hexidecimal digits and
 147            ; place in R2. Else return non-hex character in R1
 148            ; Also accumulate checksum in R3. Uses R14 and R15.
 149            ;
 150 0F4E: E322 GETWD:	CLR	R2	; clear accumulator
 151 0F4F: 704E 	MVI	R14,4	; get 4 digits
 152 0F50: 0F41 GETWD0:	CALL	GETHEX	; get next digit in R1
 153 0F51: 5E00 	RNC		; return if not 0-9 or A-F
 154 0F52: D222 	ADD	R2,R2	; shift left 1 digit
 155 0F53: D222 	ADD	R2,R2	; (4 bits)
 156 0F54: D222 	ADD	R2,R2
 157 0F55: D222 	ADD	R2,R2
 158 0F56: D212 	ADD	R2,R1	; add digit to word
 159 0F57: 8FFE 	DEC	R14	; check for last digit
 160 0F58: 4BF7 	JNZ	GETWD0	; loop if more digits
 161 0F59: D223 	ADD	R3,R2	; add to checksum
 162 0F5A: AE10 	STC
 163 0F5B: 5000 	RET
 164            ;
 165            ; SPI Registers
 166            ;
 167            SDATA	EQU	$8	; data I/O
 168            SSOFF	EQU	$A	; SS control
 169            SSON	EQU	$B
 170            ;
 171            ; Open flash memory for read
 172            ; Call:	R1 = page address
 173            ; Uses:	R2,3,4
 174            ;
 175 0F5C: 0F6D SREAD:	CALL	SSTAT	; check if ready
 176 0F5D: AC7F 	TST	R15,7
 177 0F5E: 4FFD 	JNC	SREAD	; wait if not ready
 178 0F5F: 70B3 	MVI	R3,$0B	; read command
 179 0F60: D014 	MOV	R4,R1	; page address
 180 0F61: 0F79 	CALL	SCMD	; send command and page address
 181 0F62: 4025 	JMP	SDUM	; send dummy byte
 182            ;
 183            ; Open flash memory for writing
 184            ; Call:	R1 = page address
 185            ; Uses:	R15 = temp.
 186            ;
 187 0F63: AD0F SWRITE:	LDA	R15,SPAGE ; initialize page counter
     0F64: 7C2F
 188 0F65: B0F1 	WR	R1,R15
 189 0F66: E311 	CLR	R1
 190 0F67: AD0F 	LDA	R15,SWORD ; initialize word counter
     0F68: 7C3F
 191 0F69: B0F1 	WR	R1,R15
 192 0F6A: 5000 	RET
 193            ;
 194            ; Close Flash Memory
 195            ;
 196 0F6B: B8AF SCLOSE:	OUT	R15,SSOFF
 197 0F6C: 5000 	RET
 198            ;
 199            ; Read Status
 200            ; Ret:	R15 = status
 201            ;	bit 0 = page size: 0 = natural (264/528), 1 = binary (256/512)
 202            ;	bit 1 = sector protection enabled (1) or disabled (0)
 203            ;	bit 6 = comparison result: match (0) or error (1)
 204            ;	bit 7 = ready (1) or busy (0)
 205            ;
 206 0F6D: B8BF SSTAT:	OUT	R15,SSON	; select flash memory
 207 0F6E: 7D7F 	MVI	R15,$D7		; status register read command
 208 0F6F: B88F 	OUT	R15,SDATA	; send command
 209 0F70: 6810 	REP	18		; wait 19 clock cycles
 210 0F71: E200 	NOP
 211 0F72: E3FF 	CLR	R15		; dummy byte
 212 0F73: B88F 	OUT	R15,SDATA
 213 0F74: 6811 	REP	19		; wait 19 clock cycles
 214 0F75: E200 	NOP
 215 0F76: C08F 	IN	R15,SDATA	; get status byte
 216 0F77: B8AF 	OUT	R15,SSOFF	; unselect flash memory
 217 0F78: 5000 	RET
 218            ;
 219            ; Send 4-byte command to flash memory (264B pages)
 220            ; Call:	R3 = command
 221            ;	R4 = page address
 222            ; Ret:	R3 zeroed
 223            ;	R4 unchanged
 224            ;
 225 0F79: B8BF SCMD:	OUT	R15,SSON	; enable memory
 226 0F7A: E200 	NOP
 227 0F7B: B883 	OUT	R3,SDATA	; send first byte
 228 0F7C: 680F 	REP	17		; wait 19 clock cycles
 229 0F7D: E200 	NOP
 230 0F7E: EFD4 	LSL	R4		; shift page address
 231 0F7F: EB44 	SWAP	R4		; get MSB
 232 0F80: B884 	OUT	R4,SDATA	; send second byte
 233 0F81: EB44 	SWAP	R4		; get LSB
 234 0F82: 6810 	REP	18		; wait 19 clock cycles
 235 0F83: E200 	NOP
 236 0F84: B884 	OUT	R4,SDATA	; send third byte
 237 0F85: EEC4 	LSR	R4
 238 0F86: 680F 	REP	17		; wait 19 clock cycles
 239 0F87: E200 	NOP
 240 0F88: E333 SDUM:	CLR	R3		; send fourth byte of command
 241 0F89: B883 	OUT	R3,SDATA	; or dummy byte
 242 0F8A: 6810 	REP	18		; wait 19 clock cycles
 243 0F8B: E200 	NOP
 244 0F8C: 5000 	RET
 245            ;
 246            ; Read multiple words from serial flash memory and deposit in RAM
 247            ; Call:	R1 = RAM address
 248            ;	R2 = number of words to transfer
 249            ; Uses:	R13 = even data bytes
 250            ;	R14 = odd data bytes
 251            ;	R15 = zero
 252            ; Ret:	R1 = one byte past end of memory used
 253            ;	R2 = 0
 254            ;
 255 0F8D: E3FF SGETM:	CLR	R15
 256 0F8E: B88F SGETM0:	OUT	R15,SDATA	; send 0 during read
 257 0F8F: 6811 	REP	19		; wait 19 clock cycles
 258 0F90: E200 	NOP
 259 0F91: C08D 	IN	R13,SDATA	; get LSB from flash
 260 0F92: B88F 	OUT	R15,SDATA	; send 0 during read
 261 0F93: 6811 	REP	19		; wait 19 clock cycles
 262 0F94: E200 	NOP
 263 0F95: C08E 	IN	R14,SDATA	; get MSB from flash
 264 0F96: EBEE 	SWAP	R14		; and put in MSB of register
 265 0F97: E2DE 	OR	R14,R13		; add LSB
 266 0F98: B01E 	WR	R14,R1		; write to memory
 267 0F99: 8011 	INC	R1		; increment memory address
 268 0F9A: 8FF2 	DEC	R2		; decrement word count
 269 0F9B: 4BF2 	JNZ	SGETM0		; repeat until all words read
 270 0F9C: 5000 	RET
 271            ;
 272            ; Write multiple words from RAM to serial flash memory
 273            ; Call:	R1 = memory address
 274            ;	R2 = number of words to transfer
 275            ; Uses:	R3 = command
 276            ;	R4 = page address
 277            ;	R5 = word count
 278            ;	R15 = temp.
 279            ; Ret:	R1 = one byte past end of memory used
 280            ;	R2 = 0
 281            ; This routine starts an erase/write when the word count is zero and
 282            ; terminates the command when 132 words have accumulated. The close
 283            ; routine terminates the command if the buffer is not completely full.
 284            ;
 285 0F9D: AD0F SPUTM:	LDA	R15,SWORD	; get word counter
     0F9E: 7C3F
 286 0F9F: C8F5 	RD	R5,R15
 287 0FA0: 9005 SPUTM0:	CPZ	R5		; start new write if buffer empty
 288 0FA1: 4A0E 	JNZ	SPUTM2
 289 0FA2: 0F6D SPUTM1:	CALL	SSTAT		; check if ready
 290 0FA3: AC7F 	TST	R15,7
 291 0FA4: 4FFD 	JNC	SPUTM1		; wait if not ready
 292 0FA5: AD0F 	LDA	R15,SPAGE	; get page address
     0FA6: 7C2F
 293 0FA7: C8F4 	RD	R4,R15
 294 0FA8: 7823 	MVI	R3,$82		; erase and write page command
 295 0FA9: 0F79 	CALL	SCMD		; send command and page address
 296 0FAA: 8014 	INC	R4		; increment page address
 297 0FAB: AD0F 	LDA	R15,SPAGE	; save page address
     0FAC: 7C2F
 298 0FAD: B0F4 	WR	R4,R15
 299 0FAE: AD00 	LOAD	R5,132		; initialize word counter
     0FAF: 7845
 300 0FB0: C81F SPUTM2:	RD	R15,R1		; read from RAM
 301 0FB1: 8011 	INC	R1		; increment RAM address
 302 0FB2: B88F 	OUT	R15,SDATA	; send LSB
 303 0FB3: 6810 	REP	18		; wait 19 clock cycles
 304 0FB4: E200 	NOP
 305 0FB5: EBFF 	SWAP	R15		; put MSB in LSB of register
 306 0FB6: B88F 	OUT	R15,SDATA	; send MSB
 307 0FB7: 680E 	REP	16		; wait 19 clock cycles until next out
 308 0FB8: E200 	NOP
 309 0FB9: 8FF5 	DEC	R5		; decrement words in page
 310 0FBA: 4A01 	JNZ	SPUTM3		; skip next if not zero
 311 0FBB: B8A1 	OUT	R1,SSOFF	; start write if buffer full
 312 0FBC: 8FF2 SPUTM3:	DEC	R2		; decrement word count
 313 0FBD: 4BE2 	JNZ	SPUTM0		; repeat until all words written
 314 0FBE: AD0F 	LDA	R15,SWORD	; save word counter
     0FBF: 7C3F
 315 0FC0: B0F5 	WR	R5,R15
 316 0FC1: 5000 	RET
 317            ;
 318            ; Write variables
 319            ;
 320 0FC2: 0000 SPAGE:	DW	0	; current page address
 321 0FC3: 0000 SWORD:	DW	0	; words left in flash memory buffer
 322            ;
 323            ; Write RAM to Flash Memory
 324            ; Call:	R1 = command
 325            ; Uses:	R1 = memory address
 326            ;	R2 = length
 327            ;	R15 = temp.
 328            ;
 329 0FC4: 9571 WFLASH:	CPI	R1,'W'	; write to flash?
 330 0FC5: 5A00 	RNZ
 331 0FC6: 0F4E 	CALL	GETWD	; yes, get page number
 332 0FC7: 4E1B 	JNC	ERROR	; return if error
 333 0FC8: 0F39 	CALL	GETC
 334 0FC9: 90D1 	CPI	R1,13	; CR?
 335 0FCA: 4A18 	JNZ	ERROR
 336 0FCB: D021 	MOV	R1,R2	; get page number
 337 0FCC: 0F63 	CALL	SWRITE	; open file
 338 0FCD: E311 	CLR	R1	; memory address
 339 0FCE: AD0F 	LDA	R15,ADDR ; length (words)
     0FCF: 738F
 340 0FD0: C8F2 	RD	R2,R15
 341 0FD1: 0F9D 	CALL	SPUTM	; write memory to file
 342 0FD2: 0F6B 	CALL	SCLOSE	; close file
 343 0FD3: 4010 	JMP	DONE
 344            ;
 345            ; Read Flash Memory into RAM
 346            ; Call:	R1 = command
 347            ; Uses:	R1 = memory address
 348            ;	R2 = length
 349            ;	R15 = temp.
 350            ;
 351 0FD4: 9521 RFLASH:	CPI	R1,'R'	; read from flash?
 352 0FD5: 5A00 	RNZ
 353 0FD6: 0F4E 	CALL	GETWD	; yes, get page number
 354 0FD7: 4E0B 	JNC	ERROR	; return if error
 355 0FD8: 0F39 	CALL	GETC
 356 0FD9: 90D1 	CPI	R1,13	; CR?
 357 0FDA: 4A08 	JNZ	ERROR
 358 0FDB: D021 	MOV	R1,R2	; get page number
 359 0FDC: 0F5C 	CALL	SREAD	; open file
 360 0FDD: E311 	CLR	R1	; memory address
 361 0FDE: AD0E 	LOAD	R2,3584	; length is memory below top 512 words
     0FDF: 7002
 362 0FE0: 0F8D 	CALL	SGETM	; write memory to file
 363 0FE1: 0F6B 	CALL	SCLOSE	; close file
 364 0FE2: 4001 	JMP	DONE
 365            ;
 366            ; Error - turn on LED
 367            ;
 368 0FE3: BFEF ERROR:	OUT	R15,LEDON
 369 0FE4: E311 DONE:	CLR	R1
 370 0FE5: 5000 	RET
 371            ; end

Sym  Type  Hex. Dec. Name
  0: UNDEF 0000    0 
  1: DATA  007E  126 LEDON
  2: DATA  007F  127 LEDOFF
  3: DATA  0020   32 UDATA
  4: DATA  0021   33 UBAUD
  5: DATA  0021   33 USTAT
  6: DATA  0000    0 URXR
  7: DATA  0001    1 URXF
  8: DATA  0002    2 UTXR
  9: DATA  0003    3 UTXE
 10: PADDR 0000    0 START
 11: PADDR 0F00 3840 INIT
 12: PADDR 0F02 3842 SPIN
 13: PADDR 0F39 3897 GETC
 14: PADDR 0F19 3865 ZERO
 15: PADDR 0F24 3876 DATA
 16: PADDR 0FC4 4036 WFLASH
 17: PADDR 0FD4 4052 RFLASH
 18: PADDR 0F10 3856 RUN
 19: PADDR 0F0A 3850 COMMENT
 20: PADDR 0F0C 3852 SKIP
 21: PADDR 0FE4 4068 DONE
 22: PADDR 0FE3 4067 ERROR
 23: PADDR 0F38 3896 ADDR
 24: PADDR 0F2A 3882 DATA0
 25: PADDR 0F4E 3918 GETWD
 26: PADDR 0F2F 3887 DATA1
 27: PADDR 0F41 3905 GETHEX
 28: PADDR 0F50 3920 GETWD0
 29: DATA  0008    8 SDATA
 30: DATA  000A   10 SSOFF
 31: DATA  000B   11 SSON
 32: PADDR 0F5C 3932 SREAD
 33: PADDR 0F6D 3949 SSTAT
 34: PADDR 0F79 3961 SCMD
 35: PADDR 0F88 3976 SDUM
 36: PADDR 0F63 3939 SWRITE
 37: PADDR 0FC2 4034 SPAGE
 38: PADDR 0FC3 4035 SWORD
 39: PADDR 0F6B 3947 SCLOSE
 40: PADDR 0F8D 3981 SGETM
 41: PADDR 0F8E 3982 SGETM0
 42: PADDR 0F9D 3997 SPUTM
 43: PADDR 0FA0 4000 SPUTM0
 44: PADDR 0FB0 4016 SPUTM2
 45: PADDR 0FA2 4002 SPUTM1
 46: PADDR 0FBC 4028 SPUTM3
