DANI-I 6502 Microcomputer

Let's talk about anything related to the 6502 microprocessor.
ChaseHQ85
Posts: 38
Joined: 21 Feb 2017

DANI-I 6502 Microcomputer

Post by ChaseHQ85 »

Hello everyone! My name is Craig, an avid electronics hobbyist. I'm brand new to the 6502 scene and have been working on the following project for the last 3-4 weeks. The DANI-I 6502 Microcomputer (named after my wife Danneille). Without further ado - here are the pictures with some explanations.
IMG_6764.JPG
From left to right
Xilinx Spartan 3A - Used as the custom made VGA Controller - Called DANI-I VGA
Output is VGA @ 640x480 60Hz - but the pixel area is 320x240 or a 40x30 tile display of 8x8 tiles, with 16 sprites. 6bit Resistor DAC (64 Displayable colors) 2 Colors per 8x8 tile (for time being)
The the Right of that on bottom is 32Kb of Video RAM, it holds all the Tile and Sprite Data. Above that is the screen Index buffer and VGA command register which is 4k of Dual Port Ram. The Left port is accessed by the FPGA at 25mhz and Right side is accessed by the 6502 at 4mhz. During HSYNC optional commands can be sent to the VGA controller for storing or retrieving tile and sprite data, screen data can be accessed at any time.
In the middle is the address bus and data bus (I know im gonna get hate for doing this on a breadboard, but hey - it's what i had :) )
Next starting on the bottom is the main system SRAM Chip, 32Kb of it - above it is some address decoding and glue logic.
In the next column we have a reset circuit on top - it consists of a Hex Inverter and a 555 circuit for reset.
Below the Hex Inverter is the 6502! (So glad I went with this chip - it's been amazing) Below the 6502 is the ROM it's 32Kb but only 16Kb of it is accessible.
On the far right is nothing special yet... it's just glue logic for the additional IC's i will be adding this week, including the 6522.
IMG_6754.JPG
This is a line debugger I created to watch the address and data lines to debug issues.
IMG_6765.JPG
My homemade EEPROM programmer

And Finally - the thing that made everything worth it this weekend - the DANI-I 6502 first test of actual code!
IMG_6763.JPG
The Memory map -

Code: Select all

$0000 - $7FFF => SRAM    32k b0.xxxxxxxxxxxxxxx 
$8000 - $8FFF => VRAM    04k b1000.xxxxxxxxxxxx
$9000 - $90FF => ACIA     1b b10010000.xxxxxxxx
$9100 - $91FF => VIA      1b b10010001.xxxxxxxx
$9200 - $92FF => PIA      1b b10010010.xxxxxxxx
$C000 - $FFFF => ROM     16k b11.xxxxxxxxxxxxxx
The initial ROM System Code -

Code: Select all

;-------------------------------------------------
;-------------DANI-I-SYSTEM-ROM-------------------
;-------------------------------------------------

;-------------EQUATES-----------------------------
VRAM:            .SET $8000
VRAM_CMD:        .SET VRAM + $F00
VRAM_CHARSLOC:   .SET VRAM + $F10
VRAM_CHARSBUF:   .SET VRAM + $F20
CURSOR_LOC:      .SET $80            ; Cursor Location ZP: 40
;-------------EO-EQUATES--------------------------

    .ORG $C000
RESET:
    LDX #$FF            ; Initialize the Stack Pointer
    TXS                 ; Transfer X to Stack
START:
    JSR SYS_INIT        ; Initialize the System
    LDA #<S_HelloWorld
    STA $10
    LDA #>S_HelloWorld
    STA $11
    JSR DVGA_PUTS       ; Print out String
HALT:
    JMP HALT       ; Done: "halt" in an infinite loop

;----------SUB-ROUTINES---------------------------

;----------System Initialization -----------------
;-- Parameters - VOID
;-------------------------------------------------
SYS_INIT:
    LDX #<[CHAR_ROM+$400-8]    ; Store Low Byte of Char ROM (Last Character) in ZP 05
    STX $40
    LDX #>[CHAR_ROM+$400-8]    ; Store High Byte of Char ROM (Last Character) in ZP 06
    STX $41
    LDX #$7F                 ; Set X counter to 127 (128 total)
.loop
    STX $20                 ; Set Location of this character
    LDA $40                 ; Set Address of Char Rom in ZP 40
    STA $10
    LDA $41
    STA $11
    JSR DVGA_STORECHAR      ; Put Address of Character in ZP 10 and Location you want it stored in ZP 20
    LDA #$08                ; Put 8 bytes of dec
    STA $10                 ; Store it in param (ZP10)
    JSR MEM_SAFE_ZP40_DEC
    DEX                     ; deduct 1 from the location
    BPL .loop               ; loop until we hit go through 0 to FF
    JSR DVGA_BLANKSCREEN    ; Blank the Screen
    RTS
    
;----------Safe Memory Decrement -----------------
;-- Parameters - ZP10 = Amount to Dec ZP 40 by
;-------------------------------------------------
MEM_SAFE_ZP40_DEC:
    PHA                      ; Store A
    TXA			     ; 
    PHA			     ; Push X to Stack
    LDX $10                  ; Get the amount we want to dec by
.loop
    DEC $40                  ; Deduct from Memaddress 40
    LDA $40                  ; Test A
    CMP #$FF
    BEQ .deduct41            ; If we hit FF, make sure we deduct from 41
.cont
    DEX			     ; Decrease X Counter
    BNE .loop	             ; Loop if we arent at 0 yet
    PLA                      ; Restore X
    TAX
    PLA                      ; Restore A
    RTS			     ; Return from Sub
.deduct41
    DEC $41		     ; Deduct from High Byte
    JMP .cont		     ; Go Back

;----------DVGA Store Character ------------------
;-- Parameters - ZP10 = Address of Character
;-- Paramaters - ZP20 = Location that you want to store charater in
;-------------------------------------------------
DVGA_STORECHAR:              ;-- ptr to Character in ZP 10, stored in LDA, Location is in ZP 20
    PHA			     ; Push A To Stack
    TYA
    PHA			     ; Push Y To Stack
    LDY #$07                 ; Set up counter - put 7
.loop:                       ; Start of Loop
    LDA ($10),Y              ; Get StoreChar Byte
    STA VRAM_CHARSBUF,Y      ; Store it in VRAM
    DEY                      ; Decrement Y
    BPL .loop                ; Continue to loop until it wraps
    LDA $20                  ; Load location value
    STA VRAM_CHARSLOC        ; Store it in Vram Char location
    LDA #$01                 ; Set Store Command
    STA VRAM_CMD             ; in the VGA command location
.chkcmd:
;    LDA VRAM_CMD             ; Check to see if it was loaded in
;    BNE .chkcmd              ; It was? Okay were good
    PLA
    TAY			     ; Restore Y
    PLA  		     ; Restore A
    RTS                      ; Return from subroutine
    
;----------DVGA Blank Screen ---------------------
;-- Parameters - VOID
;-------------------------------------------------
DVGA_BLANKSCREEN:
    LDA #<VRAM               ; Load Low Byte of VRAM address
    STA $40                  ; Store it in Zero Page 40
    LDY #$B0                 ; Last page + 1 only partially filled
    LDA #$00                 ; Set Accu To 0 (fill byte)
    LDX #>VRAM+4             ; Init X to last VRAM page number
.loop_outer:
    STX $41       	     ; Store it in Zero Page 41
.loop_inner:
    DEY             	     ; (filling high to low is more efficient)
    STA ($40),Y     	     ; Store the fill byte
    BNE .loop_inner 	     ; ... down to the bottom of the page
    DEX               	     ; Prepare to fill next-lower page
    CPX #>VRAM       	     ; Is X < VRAM_H?
    BCS .loop_outer 	     ; No: fill the next page
    LDA #<VRAM               ; Set Cursor Location to 0
    STA CURSOR_LOC           ; Store it into Cursor Location
    LDA #>VRAM
    STA CURSOR_LOC+1
    RTS			     ; Return from Subroutine

;---------DVGA-Put-String--------------------------
;-- Parameters - ZP10 - Ptr to String to Put on Scr
;-- Desc: Puts String on Screen at Cursor Location
;--------------------------------------------------
DVGA_PUTS:
    TYA                       ; Save Y
    PHA                       ; Push Y on stack
    TXA                       ; Save X
    PHA                       ; Push X on Stack
    LDY #$00                  ; Set Y To Zero
.loop
    LDA ($10),Y               ; Load Byte of String
    BEQ .stringDone           ; If this is a NULL character We are done with string
    STA (CURSOR_LOC)          ; Store this character into Cursor Location
    INC CURSOR_LOC            ; Increase Cursor Location
    BMI .increaseCursorH
    LDA CURSOR_LOC
    CMP #$B0
    BEQ .checkCursor          ; Check to see if we are at 1200
.continueLoop
    INY                       ; Increase Y
    BMI .stringDone           ; Y Overflowed to 00 - String is over 256 Characers, Exit
    JMP .loop
.increaseCursorH
    INC CURSOR_LOC+1
    JMP .continueLoop
.checkCursor
    LDA CURSOR_LOC+1
    CMP #$84
    BNE .continueLoop
    LDA #$80
    STA CURSOR_LOC+1
    LDA #$00
    STA CURSOR_LOC
    JMP .loop
.stringDone
    PLA                       ; Grab X From Stack
    TAX                       ; Restore X
    PLA                       ; Grab Y from Stack
    TAY                       ; Restore Y
    RTS

;--------------------------------------------------
;---------Static STRINGS---------------------------
;--------------------------------------------------

S_HelloWorld:	.db "Hello World!", $00

;--------------------------------------------------
;---------BUILT IN ROM CHARS-----------------------
;--------------------------------------------------
CHAR_ROM:                    ; ASCII encoded - 128 Chars
	.BYTE @00000000
	.BYTE @00000000
	.BYTE @00000000
	.BYTE @00000000
	.BYTE @00000000
	.BYTE @00000000
	.BYTE @00000000
	.BYTE @00000000
	
  	.BYTE @00000000
  	.BYTE @00111110
  	.BYTE @01000001
  	.BYTE @01010101
  	.BYTE @01000001
  	.BYTE @01010101
  	.BYTE @01001001
  	.BYTE @00111110

  	.BYTE @00000000
  	.BYTE @00111110
  	.BYTE @01111111
  	.BYTE @01101011
  	.BYTE @01111111
  	.BYTE @01101011
  	.BYTE @01110111
  	.BYTE @00111110

  	.BYTE @00000000
  	.BYTE @00100010
  	.BYTE @01110111
  	.BYTE @01111111
  	.BYTE @01111111
  	.BYTE @00111110
  	.BYTE @00011100
  	.BYTE @00001000

  	.BYTE @00000000
  	.BYTE @00001000
  	.BYTE @00011100
  	.BYTE @00111110
  	.BYTE @01111111
  	.BYTE @00111110
  	.BYTE @00011100
  	.BYTE @00001000

  	.BYTE @00000000
  	.BYTE @00001000
  	.BYTE @00011100
  	.BYTE @00101010
  	.BYTE @01111111
  	.BYTE @00101010
  	.BYTE @00001000
  	.BYTE @00011100

  	.BYTE @00000000
  	.BYTE @00001000
  	.BYTE @00011100
  	.BYTE @00111110
  	.BYTE @01111111
  	.BYTE @00111110
  	.BYTE @00001000
  	.BYTE @00011100

  	.BYTE @00000000
  	.BYTE @00000000
  	.BYTE @00011100
  	.BYTE @00111110
  	.BYTE @00111110
  	.BYTE @00111110
  	.BYTE @00011100
  	.BYTE @00000000

  	.BYTE @11111111
  	.BYTE @11111111
  	.BYTE @11100011
  	.BYTE @11000001
  	.BYTE @11000001
  	.BYTE @11000001
  	.BYTE @11100011
  	.BYTE @11111111

  	.BYTE @00000000
  	.BYTE @00000000
  	.BYTE @00011100
  	.BYTE @00100010
  	.BYTE @00100010
  	.BYTE @00100010
  	.BYTE @00011100
  	.BYTE @00000000

; I removed the rest of the Characters to shorten post - you get the idea

;---------VECTORS----------------------------------
VECTORS:
    .ORG $FFFA           ; 6502 Starts reading its vectors here
    .word HALT     ; NMI
    .word RESET    ; RESET
    .word HALT     ; BRK
   
   .END
This is the first time ive written 6502 code or built such a project - but it has been absolutely amazing so far. Let me know your thoughts! I will continue to post as it evolves!
ChaseHQ85
Posts: 38
Joined: 21 Feb 2017

Re: DANI-I 6502 Microcomputer

Post by ChaseHQ85 »

And of course all the pictures are upside down... :evil:
User avatar
KC9UDX
Posts: 246
Joined: 07 Dec 2013
Location: The Kettle Moraine

Re: DANI-I 6502 Microcomputer

Post by KC9UDX »

Not here, they're not.
Klaus2m5
Posts: 442
Joined: 28 Jul 2012
Location: Wiesbaden, Germany

Re: DANI-I 6502 Microcomputer

Post by Klaus2m5 »

ChaseHQ85 wrote:
And of course all the pictures are upside down... :evil:
It seems to depend on the browser. Edge displays both preview and magnified image upside down. In Firefox only the preview is upside down and the magnified image is correctly oriented.

EXIF Orientation should be top left. There is no EXIF with the preview, so it cannot be corrected.
Attachments
EXIF.png
6502 sources on GitHub: https://github.com/Klaus2m5
ChaseHQ85
Posts: 38
Joined: 21 Feb 2017

Re: DANI-I 6502 Microcomputer

Post by ChaseHQ85 »

The pics work well in chrome as well. Hey Mike B, or anyone can I get a code review pretty please? :mrgreen: it's my first real attempt at writing 6502 code id like to keep.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: DANI-I 6502 Microcomputer

Post by barrym95838 »

I have to go to work right now, but I'll try to take a peek at your source this weekend and give you a friendly critique.

Mike B.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: DANI-I 6502 Microcomputer

Post by GARTHWILSON »

Welcome.

I don't know if this is a bit premature, but I'd like to nudge you to look into macros as soon as you're ready. Your first loop there for example,

Code: Select all

SYS_INIT:
    LDX #<[CHAR_ROM+$400-8]    ; Store Low Byte of Char ROM (Last Character) in ZP 05
    STX $40
    LDX #>[CHAR_ROM+$400-8]    ; Store High Byte of Char ROM (Last Character) in ZP 06
    STX $41
    LDX #$7F                 ; Set X counter to 127 (128 total)
.loop
    STX $20                 ; Set Location of this character
    LDA $40                 ; Set Address of Char Rom in ZP 40
    STA $10
    LDA $41
    STA $11
    JSR DVGA_STORECHAR      ; Put Address of Character in ZP 10 and Location you want it stored in ZP 20
    LDA #$08                ; Put 8 bytes of dec
    STA $10                 ; Store it in param (ZP10)
    JSR MEM_SAFE_ZP40_DEC
    DEX                     ; deduct 1 from the location
    BPL .loop               ; loop until we hit go through 0 to FF
    JSR DVGA_BLANKSCREEN    ; Blank the Screen
    RTS
can be shortened to:

Code: Select all

SYS_INIT:  PUT2  CHAR_ROM+$400-8, INTO, $40  ; The PUT2 macro uses A instead of X; but you re-init A and X below anyway.
           FOR_X  $7F, DOWN_TO, NEG_NRs      ; Set X counter to 127 (128 total, dropping through when X dec's to $FF)
               STX   $20                     ; Set Location of this character
               COPY2 $40, TO, $10            ; Set Address of Char Rom in ZP 40
               JSR   DVGA_STORECHAR          ; Put addr of Char in ZP 10 and Location you want it stored in ZP 20
               PUT   8, INTO, $10            ; Put 8 bytes of dec and Store it in param (ZP10)
               JSR   MEM_SAFE_ZP40_DEC
           NEXT_X                            ; NEXT_X assembles DEX, BPL because that's what FOR_X and its parameters dictated.
           JMP  DVGA_BLANKSCREEN             ; Blank the Screen (Combine JSR, RTS, saving one byte and 9 clocks.
and this last version brings a slight improvement in both performance and memory. The macros offload some of your work to the assembler, work that you were doing by hand before. You're still in total control since you write the macros (or adapt others' macros) and you know what they do; but you don't have to look at the mundane innards every time anymore. You become more productive, and since you can see what you're doing better, you get fewer bugs to fix.

The first small change is that "PUT2" uses LDA# instead of LDX# which I figured is no problem because you re-initialize both A and X right below anyway, without re-using what's in either of them. If you really had to have it use X, you could write another version of PUT2, or re-write the existing one to use a parameter telling which register to use. The other change is that I removed your RTS by replacing your last JSR with JMP, using the RTS at the end of subroutine DVGA_BLANKSCREEN to return to the right place. The only time you can't do that is when passing parameters on the hardware stack, since the routines need a consistent number of return addresses on the stack above the data so they can find the data where it's expected. (Passing parameters on the hardware stack (or even on a virtual stack) can remove the need for a lot of variables though. This is covered in my stack treatise, especially section 6.)

If you don't feel ready for the macros yet, no problem. Just keep it in the back of your mind for later.

If you have a 65c02, you can shorten things up further. A couple of key things that pop out at me right away in your code is that LDA#0, STA can be replaced with just STZ (STore Zero) which is shorter and does not disturb any registers; and the 65c02 can push and pull the index registers without going through A. I have a list of the differences between the CMOS and NMOS 6502 here.

If your assembler can handle lots of bytes on each .BYTE line, you can shorten up your source code a lot there, too. The part at the end becomes:

Code: Select all

CHAR_ROM:                    ; ASCII encoded - 128 Chars
     .BYTE  @00000000, @00000000, @00000000, @00000000, @00000000, @00000000, @00000000, @00000000
     .BYTE  @00000000, @00111110, @01000001, @01010101, @01000001, @01010101, @01001001, @00111110
     .BYTE  @00000000, @00111110, @01111111, @01101011, @01111111, @01101011, @01110111, @00111110
     .BYTE  @00000000, @00100010, @01110111, @01111111, @01111111, @00111110, @00011100, @00001000
     .BYTE  @00000000, @00001000, @00011100, @00111110, @01111111, @00111110, @00011100, @00001000
     .BYTE  @00000000, @00001000, @00011100, @00101010, @01111111, @00101010, @00001000, @00011100
     .BYTE  @00000000, @00001000, @00011100, @00111110, @01111111, @00111110, @00001000, @00011100
     .BYTE  @00000000, @00000000, @00011100, @00111110, @00111110, @00111110, @00011100, @00000000
     .BYTE  @11111111, @11111111, @11100011, @11000001, @11000001, @11000001, @11100011, @11111111
     .BYTE  @00000000, @00000000, @00011100, @00100010, @00100010, @00100010, @00011100, @00000000
instead of the 90 or so lines you had.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
EugeneNine
Posts: 59
Joined: 01 Nov 2016

Re: DANI-I 6502 Microcomputer

Post by EugeneNine »

you made an eprom programmer with a pickit3?
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: DANI-I 6502 Microcomputer

Post by BigEd »

Great project Craig - thanks for posting about it!
leepivonka
Posts: 167
Joined: 15 Apr 2016

Re: DANI-I 6502 Microcomputer

Post by leepivonka »

Here's a version with assorted changes - pick & choose the parts you like.

Code: Select all

;-------------------------------------------------
;-------------DANI-I-SYSTEM-ROM-------------------
;-------------------------------------------------

;-------------Memory locations-----------------------------

Temp1:		.SET $10	;unpreserved scratch
Temp2:		.set $12	;unpreserved scratch

DVGA_Cursor:	.SET $80	;Cursor Location - ptr to VRAM



					;$0000 - $7FFF => SRAM    32k b0.xxxxxxxxxxxxxxx 
VRAM:            .SET $8000		;$8000 - $8FFF => VRAM    04k b1000.xxxxxxxxxxxx
VRAM_CMD:        .SET VRAM + $F00
VRAM_CHARSLOC:   .SET VRAM + $F10
VRAM_CHARSBUF:   .SET VRAM + $F20

					;$9000 - $90FF => ACIA     1b b10010000.xxxxxxxx
					;$9100 - $91FF => VIA      1b b10010001.xxxxxxxx
					;$9200 - $92FF => PIA      1b b10010010.xxxxxxxx
					;$C000 - $FFFF => ROM     16k b11.xxxxxxxxxxxxxx


;-------------ROM--------------------------

	.ORG $C000
RESET:
	LDX #$FF		; Initialize the Stack Pointer
	TXS
	CLD

	JSR DVGA_Init		; Initialize DVGA
	LDA #<S_HelloWorld	; Print out String on DVGA
	LDY #>S_HelloWorld
	JSR DVGA_Put_String
.HALT:	JMP .HALT		; Done: "halt" in an infinite loop


S_HelloWorld:   .db "Hello World!", 0


;============== DVGA ======================================

DVGA_Put_Char: ;---------------------------------------------
; Puts char on Screen at Cursor Location
; Parameters - A = char to Put on Scr
; Registers X & Y preserved, A destroyed, preserves Temp1

;	cmp #$20		; ASCII control char?
;	bcc .ctl
	STA (DVGA_Cursor)	; Store the character
	INC 0+DVGA_Cursor	; Increment DVGA_Cursor
	BNE .inc9
	INC 1+DVGA_Cursor
.inc9
	LDA 0+DVGA_Cursor	; if DVGA_Cursor = VRAM+1200
	CMP #>[VRAM+1200]
	BNE .cmp9
	LDA 1+DVGA_Cursor
	CMP #<[VRAM+1200]
	BNE .cmp9
	LDA #>VRAM		;    DVGA_Cursor = VRAM
	STA 0+DVGA_Cursor
	LDA #<VRAM
	STA 1+DVGA_Cursor
.cmp9

.cur	; display cursor???

	RTS

;.ctl	cmp #$0d		; carriage return?
;	beq .cr
;	cmp #$0a		; line feed?
;	beq .lf
;	cmp #$08		; backspace?
;	beq .bs
;	rts

;.cr	;move cursor to begin of current line???
;	bra .cur

;.lf	;move cursor to next line???
;	bra .cur

;.bs	;move cursor back 1 char???
;	bra .cur


DVGA_Put_String: ;-------------------------------------------
; Puts String on Screen at Cursor Location
; Parameters - YA - Ptr to String to Put on Scr
; Registers X preserved, A & Y destroyed, Temp1 set to YA

	STA 0+Temp1
    	STY 1+Temp1

	LDY #0
.loop
	LDA (Temp1),Y		; Load Byte of String
	BEQ .Done		; If this is a NULL character We are done with string
	JSR DVGA_Put_Char	; type it
	INY
	BNE .loop		; if Y not Overflowed to 0 then loop
.Done
	RTS


DVGA_STORECHAR: ;---------------------------------
; Parameters - Y & A = Address of Character
; Paramaters - X= Location that you want to store charater in
; Registers X preserved, A & Y destroyed, Temp1 set to YA

	STA 0+Temp1
	STY 1+Temp1

	LDY #7			; for(X=7; X>=0; X--)
.loop:
	LDA (Temp1),Y		;   move char pattern byte
	STA VRAM_CHARSBUF,Y
	DEY			;   next X
	BPL .loop

	STX VRAM_CHARSLOC	; Set Vram Char location
	LDA #$01		; Start Store command
	STA VRAM_CMD
.chkcmd:
;	LDA VRAM_CMD		; Check to see if it was loaded in
;	BNE .chkcmd		; It was? Okay were good
	RTS


DVGA_Init: ;---------------------------------------
; Parameters - VOID
; All registers destroyed, Temp1 destroyed

	; load character generator patterns
	LDA #<[CHAR_ROM+$400-8]	; YA=&CHAR_ROM[127]
	LDY #>[CHAR_ROM+$400-8]
	LDX #$7F		; for(X=127; x>=0; x--)
.loop
	JSR DVGA_STORECHAR	;   load the char pattern from (YA) into DVGA at X

	LDY 1+Temp1		;   YA=Temp1-8
	LDA 0+Temp1
	SEC
	SBC #8
	BCS .sub9
	DEY
.sub9
	DEX			;   next X
	BPL .loop

;	BRA DVGA_BlankScreen	; Blank the Screen & RTS


DVGA_BlankScreen: ;---------------------------------
; Clear VRAM
; Parameters - none
; Register X perserved, A & Y destroyed

	lda #0			; fill value
	ldy #240		; 240 is 1200/5
.loop
	sta 0*240+VRAM-1,Y
	sta 1*240+VRAM-1,Y
	sta 2*240+VRAM-1,Y
	sta 3*240+VRAM-1,Y
	sta 4*240+VRAM-1,Y
	dey
	bne .loop

;	bra DVGA_Home		; Home the cursor & RTS


DVGA_Home: ;------------------------------------------
; Move the cursor to the start of VRAM
; Parameters - none
	LDA #<VRAM		; DVGA_Cursor = VRAM
	STA 0+DVGA_Cursor
	LDA #>VRAM
	STA 1+DVGA_Cursor

	RTS
    

;--------------------------------------------------
;---------BUILT IN ROM CHARS-----------------------
;--------------------------------------------------
CHAR_ROM:                    ; ASCII encoded - 128 Chars
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   .BYTE @00000000
   
     .BYTE @00000000
     .BYTE @00111110
     .BYTE @01000001
     .BYTE @01010101
     .BYTE @01000001
     .BYTE @01010101
     .BYTE @01001001
     .BYTE @00111110

     .BYTE @00000000
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @01101011
     .BYTE @01111111
     .BYTE @01101011
     .BYTE @01110111
     .BYTE @00111110

     .BYTE @00000000
     .BYTE @00100010
     .BYTE @01110111
     .BYTE @01111111
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00001000

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00001000

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00101010
     .BYTE @01111111
     .BYTE @00101010
     .BYTE @00001000
     .BYTE @00011100

     .BYTE @00000000
     .BYTE @00001000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @01111111
     .BYTE @00111110
     .BYTE @00001000
     .BYTE @00011100

     .BYTE @00000000
     .BYTE @00000000
     .BYTE @00011100
     .BYTE @00111110
     .BYTE @00111110
     .BYTE @00111110
     .BYTE @00011100
     .BYTE @00000000

     .BYTE @11111111
     .BYTE @11111111
     .BYTE @11100011
     .BYTE @11000001
     .BYTE @11000001
     .BYTE @11000001
     .BYTE @11100011
     .BYTE @11111111

     .BYTE @00000000
     .BYTE @00000000
     .BYTE @00011100
     .BYTE @00100010
     .BYTE @00100010
     .BYTE @00100010
     .BYTE @00011100
     .BYTE @00000000

; I removed the rest of the Characters to shorten post - you get the idea

;---------VECTORS----------------------------------
VECTORS:
    .ORG $FFFA           ; 6502 Starts reading its vectors here
    .word HALT     ; NMI
    .word RESET    ; RESET
    .word HALT     ; BRK
   
   .END
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: DANI-I 6502 Microcomputer

Post by BigDumbDinosaur »

leepivonka wrote:
Here's a version with assorted changes - pick & choose the parts you like.
Which assembler are you using?
x86?  We ain't got no x86.  We don't NEED no stinking x86!
ChaseHQ85
Posts: 38
Joined: 21 Feb 2017

Re: DANI-I 6502 Microcomputer

Post by ChaseHQ85 »

Wow I really appreciate all the suggestions, examples and rewrites leading me to faster and more efficient code!

Thanks, this has been great!
ChaseHQ85
Posts: 38
Joined: 21 Feb 2017

Re: DANI-I 6502 Microcomputer

Post by ChaseHQ85 »

BigDumbDinosaur wrote:
leepivonka wrote:
Here's a version with assorted changes - pick & choose the parts you like.
Which assembler are you using?
Yes... Which assembler is this for?

Thanks!
ChaseHQ85
Posts: 38
Joined: 21 Feb 2017

Re: DANI-I 6502 Microcomputer

Post by ChaseHQ85 »

EugeneNine wrote:
you made an eprom programmer with a pickit3?
Yes but im sure it's not what you think. I use a PIC18f with 64k of programming memory. So i turn the ROM in to a C style const in a rom.h header and have the uController program the ROM. I use the debugging feature of the PICKit3 to ensure that all the bytes are checked and verified.
leepivonka
Posts: 167
Joined: 15 Apr 2016

Re: DANI-I 6502 Microcomputer

Post by leepivonka »

Quote:
Which assembler are you using?
I was trying to match the syntax of your original post.
For other projects I've been using CA65 from http://cc65.github.io/cc65/ - it supports several 6502 variants and the 65816 too.
If you haven't already looked at the 65816, it's interesting. Its a 6502 + more instructions + more addressing modes + 16bit operations + 24bit addresses.

Here's the result of modifying it some more & assembling with CA65:

Code: Select all

ca65 V2.15
Main file   : dani_65c02.txt
Current file: dani_65c02.txt

000000r 1               ;-------------------------------------------------
000000r 1               ;-------------DANI-I-SYSTEM-ROM-------------------
000000r 1               ;-------------------------------------------------
000000r 1               
000000r 1               	.list on
000000r 1               	.listbytes unlimited
000000r 1               	.pc02	;select 65c02 CPU - I assume you do have this CPU
000000r 1               
000000r 1               ;-------------Memory locations-----------------------------
000000r 1               	.org 0 ; direct page
000000  1  xx xx        Temp1:	.res 2	;unpreserved scratch
000002  1               ;Temp2:	.res 2	;unpreserved scratch
000002  1  xx xx        DVGA_Cursor: .res 2	;Cursor Location - ptr to VRAM
000004  1               
000004  1               
000004  1               DVGA_DimX = 40	;X display dimension
000004  1               DVGA_DimY = 30	;Y display dimension
000004  1               
000004  1               				;$0000 - $7FFF => SRAM	32k b0.xxxxxxxxxxxxxxx
000004  1               VRAM		= $8000		;$8000 - $8FFF => VRAM  04k b1000.xxxxxxxxxxxx
000004  1               VRAM_E		= DVGA_DimX*DVGA_DimY + VRAM ; end of display chars
000004  1               VRAM_CMD	= VRAM + $F00
000004  1               VRAM_CHARSLOC	= VRAM + $F10
000004  1               VRAM_CHARSBUF	= VRAM + $F20
000004  1               
000004  1               ACIA1		= $9000		;$9000 - $90FF => ACIA	 2b b10010000.xxxxxxxx
000004  1               VIA1		= $9100		;$9100 - $91FF => VIA	16b b10010001.xxxxxxxx
000004  1               PIA1		= $9200		;$9200 - $92FF => PIA	 4b b10010010.xxxxxxxx
000004  1               	.org $c000		;$C000 - $FFFF => ROM	16k b11.xxxxxxxxxxxxxx
00C000  1               
00C000  1               RESET:
00C000  1  A2 FF        	LDX #$FF		; Initialize the Stack Pointer
00C002  1  9A           	TXS
00C003  1  D8           	CLD
00C004  1               
00C004  1  20 AC C0     	JSR DVGA_Init		; Initialize DVGA
00C007  1  A9 10        	LDA #<S_HelloWorld	; Print string on DVGA
00C009  1  A0 C0        	LDY #>S_HelloWorld
00C00B  1  20 84 C0     	JSR DVGA_Put_String
00C00E  1  80 FE        HALT:	bra HALT		; "halt" in an infinite loop
00C010  1               
00C010  1               
00C010  1  48 65 6C 6C  S_HelloWorld: .byte "Hello World!", 0
00C014  1  6F 20 57 6F  
00C018  1  72 6C 64 21  
00C01C  1  00           
00C01D  1               
00C01D  1               
00C01D  1               ;============== DVGA ======================================
00C01D  1               
00C01D  1               DVGA_Put_Char: ;---------------------------------------------
00C01D  1               ; Puts char on Screen at Cursor Location
00C01D  1               ; Parameters - A = char to Put on Scr
00C01D  1               ; Registers X & Y preserved, A destroyed, preserves Temp1
00C01D  1               
00C01D  1  5A           	phy			;save callers Y
00C01E  1  A4 03        	ldy 1+DVGA_Cursor
00C020  1  C9 20        	cmp #$20		; ASCII control char?
00C022  1  90 20        	bcc @ctl
00C024  1  92 02        	sta (DVGA_Cursor)	; Store the character
00C026  1  A5 02        	lda 0+DVGA_Cursor	;YA=DVGA_Cursor
00C028  1  1A           	ina			;YA+=1
00C029  1  D0 01        	bne @inc9
00C02B  1  C8           	iny
00C02C  1               @inc9:
00C02C  1  C0 84        @wrap:	cpy #>VRAM_E		; if(YA>=VRAM_E)
00C02E  1  90 0E        	bcc @cur
00C030  1  D0 04        	bne @sub
00C032  1  C9 B0        	cmp #<VRAM_E
00C034  1  90 08        	bcc @cur
00C036  1  E9 B0        @sub:	sbc #<(DVGA_DimX*DVGA_DimY) ;   YA-=DVGA_DimX*DVGA*DimY
00C038  1  48           	pha
00C039  1  98           	tya
00C03A  1  E9 04        	sbc #>(DVGA_DimX*DVGA_DimY)
00C03C  1  A8           	tay
00C03D  1  68           	pla
00C03E  1               
00C03E  1  85 02        @cur:	sta 0+DVGA_Cursor	;DVGA_Cursor=YA
00C040  1  84 03        	sty 1+DVGA_Cursor
00C042  1               
00C042  1               	; display cursor???
00C042  1               
00C042  1  7A           	ply			;restore Y
00C043  1  60           	rts
00C044  1               
00C044  1  C9 0D        @ctl:	cmp #$0d		; carriage return?
00C046  1  F0 0A        	beq @cr
00C048  1  C9 0A        	cmp #$0a		; line feed?
00C04A  1  F0 1E        	beq @lf
00C04C  1  C9 08        	cmp #$08		; backspace?
00C04E  1  F0 24        	beq @bs
00C050  1  80 EC        	bra @cur
00C052  1               
00C052  1               @cr:	;move cursor to begin of current line
00C052  1  A9 B0        	lda #<VRAM_E		;YA=VRAM_E
00C054  1  A0 84        	ldy #>VRAM_E
00C056  1               @cr2:				;do
00C056  1  38           	sec			;  YA-=DVGA_DimX
00C057  1  E9 28        	sbc #DVGA_DimX
00C059  1  B0 01        	bcs @cr3
00C05B  1  88           	dey
00C05C  1               @cr3:
00C05C  1  C4 03        	cpy 1+DVGA_Cursor	;  while(YA>DVGA_Cursor)
00C05E  1  90 DE        	bcc @cur
00C060  1  D0 F4        	bne @cr2
00C062  1  C5 02        	cmp 0+DVGA_Cursor
00C064  1  90 D8        	bcc @cur
00C066  1  D0 EE        	bne @cr2
00C068  1  80 D4        	bra @cur
00C06A  1               
00C06A  1               @lf:	;move cursor to next line
00C06A  1  A5 02        	lda 0+DVGA_Cursor	;YA=DVGA_Cursor
00C06C  1  18           	clc			;YA+=DVGA_DimX
00C06D  1  69 28        	adc #DVGA_DimX
00C06F  1  90 01        	bcc @lf1
00C071  1  C8           	iny
00C072  1               @lf1:
00C072  1  80 B8        	bra @wrap
00C074  1               
00C074  1               @bs:	;move cursor back 1 char
00C074  1  A5 02        	lda 0+DVGA_Cursor	;YA=DVGA_Cursor
00C076  1  D0 01        	bne @bs1		;YA-=1
00C078  1  88           	dey
00C079  1  3A           @bs1:	dea
00C07A  1  C0 80        	cpy #>VRAM		;if(YA<VRAM)
00C07C  1  B0 C0        	bcs @cur
00C07E  1  A9 AF        	lda #<(VRAM_E-1)	;  YA=VRAM_E-1
00C080  1  A0 84        	ldy #>(VRAM_E-1)
00C082  1  80 BA        	bra @cur
00C084  1               
00C084  1               
00C084  1               DVGA_Put_String: ;-------------------------------------------
00C084  1               ; Puts String on Screen at Cursor Location
00C084  1               ; Parameters - YA - Ptr to String to Put on Scr
00C084  1               ; Registers X preserved, A & Y destroyed, Temp1 set to YA
00C084  1               
00C084  1  85 00        	STA 0+Temp1
00C086  1  84 01        	STY 1+Temp1
00C088  1               
00C088  1  A0 00        	LDY #0
00C08A  1               @loop:
00C08A  1  B1 00        	LDA (Temp1),Y		; Load Byte of String
00C08C  1  F0 06        	BEQ @Done		; If this is a NULL character We are done with string
00C08E  1  20 1D C0     	JSR DVGA_Put_Char	; type it
00C091  1  C8           	INY
00C092  1  D0 F6        	BNE @loop		; if Y not Overflowed to 0 then loop
00C094  1               @Done:
00C094  1  60           	RTS
00C095  1               
00C095  1               
00C095  1               DVGA_STORECHAR: ;---------------------------------------------
00C095  1               ; Parameters - Y & A = Address of Character
00C095  1               ; Parameters - X= Location that you want to store character in
00C095  1               ; Registers X preserved, A & Y destroyed, Temp1 set to YA
00C095  1               
00C095  1  85 00        	STA 0+Temp1
00C097  1  84 01        	STY 1+Temp1
00C099  1               
00C099  1  A0 07        	LDY #7			; for(X=7; X>=0; X--)
00C09B  1               @loop:
00C09B  1  B1 00        	LDA (Temp1),Y		; move char pattern byte
00C09D  1  99 20 8F     	STA VRAM_CHARSBUF,Y
00C0A0  1  88           	DEY			; next X
00C0A1  1  10 F8        	BPL @loop
00C0A3  1               
00C0A3  1  8E 10 8F     	STX VRAM_CHARSLOC	; Set Vram Char location
00C0A6  1  A9 01        	LDA #$01		; Start Store command
00C0A8  1  8D 00 8F     	STA VRAM_CMD
00C0AB  1               @chkcmd:
00C0AB  1               ;	LDA VRAM_CMD		; Check to see if it was loaded in
00C0AB  1               ;	BNE @chkcmd		; It was? Okay were good
00C0AB  1  60           	RTS
00C0AC  1               
00C0AC  1               
00C0AC  1               DVGA_Init: ;---------------------------------------
00C0AC  1               ; Parameters - VOID
00C0AC  1               ; All registers destroyed, Temp1 destroyed
00C0AC  1               
00C0AC  1               ; load character generator patterns
00C0AC  1  A9 D9        	LDA #<(CHAR_ROM+$400-8)	; YA=&CHAR_ROM[127]
00C0AE  1  A0 C4        	LDY #>(CHAR_ROM+$400-8)
00C0B0  1  A2 7F        	LDX #$7F		; for(X=127; x>=0; x--)
00C0B2  1               @loop:
00C0B2  1  20 95 C0     	JSR DVGA_STORECHAR	;load the char pattern from (YA) into DVGA at X
00C0B5  1               
00C0B5  1  A4 01        	LDY 1+Temp1		;YA=Temp1-8
00C0B7  1  A5 00        	LDA 0+Temp1
00C0B9  1  38           	SEC
00C0BA  1  E9 08        	SBC #8
00C0BC  1  B0 01        	BCS @sub9
00C0BE  1  88           	DEY
00C0BF  1               @sub9:
00C0BF  1  CA           	DEX			;  next X
00C0C0  1  10 F0        	BPL @loop
00C0C2  1               
00C0C2  1               ;	BRA DVGA_BlankScreen	; Blank the Screen & RTS
00C0C2  1               
00C0C2  1               
00C0C2  1               DVGA_BlankScreen: ;---------------------------------
00C0C2  1               ; Clear VRAM
00C0C2  1               ; Parameters - none
00C0C2  1               ; Register X preserved, A & Y destroyed
00C0C2  1               
00C0C2  1               	.assert DVGA_DimX*DVGA_DimY=1200, error, "Assumes 1200 bytes"
00C0C2  1  A9 00        	lda #0		; fill value
00C0C4  1  A0 F0        	ldy #240	; 240 is 1200/5
00C0C6  1               @loop:
00C0C6  1  99 FF 7F     	sta 0*240+VRAM-1,Y
00C0C9  1  99 EF 80     	sta 1*240+VRAM-1,Y
00C0CC  1  99 DF 81     	sta 2*240+VRAM-1,Y
00C0CF  1  99 CF 82     	sta 3*240+VRAM-1,Y
00C0D2  1  99 BF 83     	sta 4*240+VRAM-1,Y
00C0D5  1  88           	dey
00C0D6  1  D0 EE        	bne @loop
00C0D8  1               
00C0D8  1               ;	bra DVGA_Home	; Home the cursor & RTS
00C0D8  1               
00C0D8  1               
00C0D8  1               DVGA_Home: ;------------------------------------------
00C0D8  1               ; Move the cursor to the start of VRAM
00C0D8  1               ; Parameters - none
00C0D8  1  A9 00        	LDA #<VRAM	; DVGA_Cursor = VRAM
00C0DA  1  85 02        	STA 0+DVGA_Cursor
00C0DC  1  A9 80        	LDA #>VRAM
00C0DE  1  85 03        	STA 1+DVGA_Cursor
00C0E0  1               
00C0E0  1  60           	RTS
00C0E1  1               
00C0E1  1               ;--------------------------------------------------
00C0E1  1               ;---------BUILT IN ROM CHARS-----------------------
00C0E1  1               ;--------------------------------------------------
00C0E1  1               CHAR_ROM: ; ASCII encoded - 128 Chars
00C0E1  1  00           	.BYTE %00000000
00C0E2  1  00           	.BYTE %00000000
00C0E3  1  00           	.BYTE %00000000
00C0E4  1  00           	.BYTE %00000000
00C0E5  1  00           	.BYTE %00000000
00C0E6  1  00           	.BYTE %00000000
00C0E7  1  00           	.BYTE %00000000
00C0E8  1  00           	.BYTE %00000000
00C0E9  1               
00C0E9  1  00           	.BYTE %00000000
00C0EA  1  3E           	.BYTE %00111110
00C0EB  1  41           	.BYTE %01000001
00C0EC  1  55           	.BYTE %01010101
00C0ED  1  41           	.BYTE %01000001
00C0EE  1  55           	.BYTE %01010101
00C0EF  1  49           	.BYTE %01001001
00C0F0  1  3E           	.BYTE %00111110
00C0F1  1               
00C0F1  1  00           	.BYTE %00000000
00C0F2  1  3E           	.BYTE %00111110
00C0F3  1  7F           	.BYTE %01111111
00C0F4  1  6B           	.BYTE %01101011
00C0F5  1  7F           	.BYTE %01111111
00C0F6  1  6B           	.BYTE %01101011
00C0F7  1  77           	.BYTE %01110111
00C0F8  1  3E           	.BYTE %00111110
00C0F9  1               
00C0F9  1  00           	.BYTE %00000000
00C0FA  1  22           	.BYTE %00100010
00C0FB  1  77           	.BYTE %01110111
00C0FC  1  7F           	.BYTE %01111111
00C0FD  1  7F           	.BYTE %01111111
00C0FE  1  3E           	.BYTE %00111110
00C0FF  1  1C           	.BYTE %00011100
00C100  1  08           	.BYTE %00001000
00C101  1               
00C101  1  00           	.BYTE %00000000
00C102  1  08           	.BYTE %00001000
00C103  1  1C           	.BYTE %00011100
00C104  1  3E           	.BYTE %00111110
00C105  1  7F           	.BYTE %01111111
00C106  1  3E           	.BYTE %00111110
00C107  1  1C           	.BYTE %00011100
00C108  1  08           	.BYTE %00001000
00C109  1               
00C109  1  00           	.BYTE %00000000
00C10A  1  08           	.BYTE %00001000
00C10B  1  1C           	.BYTE %00011100
00C10C  1  2A           	.BYTE %00101010
00C10D  1  7F           	.BYTE %01111111
00C10E  1  2A           	.BYTE %00101010
00C10F  1  08           	.BYTE %00001000
00C110  1  1C           	.BYTE %00011100
00C111  1               
00C111  1  00           	.BYTE %00000000
00C112  1  08           	.BYTE %00001000
00C113  1  1C           	.BYTE %00011100
00C114  1  3E           	.BYTE %00111110
00C115  1  7F           	.BYTE %01111111
00C116  1  3E           	.BYTE %00111110
00C117  1  08           	.BYTE %00001000
00C118  1  1C           	.BYTE %00011100
00C119  1               
00C119  1  00           	.BYTE %00000000
00C11A  1  00           	.BYTE %00000000
00C11B  1  1C           	.BYTE %00011100
00C11C  1  3E           	.BYTE %00111110
00C11D  1  3E           	.BYTE %00111110
00C11E  1  3E           	.BYTE %00111110
00C11F  1  1C           	.BYTE %00011100
00C120  1  00           	.BYTE %00000000
00C121  1               
00C121  1  FF           	.BYTE %11111111
00C122  1  FF           	.BYTE %11111111
00C123  1  E3           	.BYTE %11100011
00C124  1  C1           	.BYTE %11000001
00C125  1  C1           	.BYTE %11000001
00C126  1  C1           	.BYTE %11000001
00C127  1  E3           	.BYTE %11100011
00C128  1  FF           	.BYTE %11111111
00C129  1               
00C129  1  00           	.BYTE %00000000
00C12A  1  00           	.BYTE %00000000
00C12B  1  1C           	.BYTE %00011100
00C12C  1  22           	.BYTE %00100010
00C12D  1  22           	.BYTE %00100010
00C12E  1  22           	.BYTE %00100010
00C12F  1  1C           	.BYTE %00011100
00C130  1  00           	.BYTE %00000000
00C131  1               
00C131  1               ; I removed the rest of the Characters to shorten post - you get the idea
00C131  1               
00C131  1               ;---------VECTORS----------------------------------
00C131  1               	.ORG $FFFA		; 6502 Starts reading its vectors here
00FFFA  1  0E C0        	.word HALT		; NMI
00FFFC  1  00 C0        	.word RESET		; RESET
00FFFE  1  0E C0        	.word HALT		; BRK
010000  1               
010000  1               	.END
Post Reply