6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Mon May 06, 2024 9:45 am

All times are UTC




Post new topic Reply to topic  [ 70 posts ]  Go to page Previous  1, 2, 3, 4, 5
Author Message
PostPosted: Tue Dec 27, 2016 9:19 pm 
Offline
User avatar

Joined: Mon May 25, 2015 2:25 pm
Posts: 632
Location: Gillies, Ontario, Canada
Yeah, the projects by Linus Åkesson are my kind of cool!
I like trying the single chip video demos.

Here is one I did when the XMega first came out.
This is a single XMega synthesizing NTSC all in software...

https://www.youtube.com/watch?v=CXFOTpM2Jn4

Everything is packed into the AVR memory.
Sound and images are RLE encoded.

I did this one because there were "doubters" out there that said color NTSC could not be synthesized on the fly in software to any decent degree.
I managed 256 colors... 16 shades of 16 colors as well as stereo 4 channel sound.

If I had not given myself a "DIP Only" rule for this project, I would have certianly used an XMega here.
I believe that the XMega is the absolute most powerful 8 bit uC ever conceived. It often beats a 32 bit ARM, and even kills any PIC32 for speed.
Sadly, it is not available in a DIP format, so it is not allowed here. At 64MHz, it would be easy to control a 6502.

I now have my 65C02 booting up, so this is a good step forward.
Because of the way I have to map the internal Flash / SRAM as ROM and RAM to the 6502, I may not get the clock speed initially intended.
Oh well, the goal here was just simplicity (minimal parts count and DIP format), so as long as the 6502 boots and runs code, it will be a success.
Once this project is working, I will try a PacMan clone to see if my 6502 assembly KungFu is up to par.

Brad


kakemoms wrote:
sark02 wrote:
Arlet wrote:
Here's a [single chip computer] nice one done by Linus Åkesson 8 years ago.
That's insane. It reminds me of the Atari ST demo scene from the 90s, and what those teams (mostly European) could make the machines do. Saying it's "very impressive" isn't even beginning to do it justice.


Quite impressive! So if we think of a 65C265 microcontroller with 65C02 built-in... a one-chip solution to this problem could be possible? :shock:


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 28, 2016 4:15 am 
Offline
User avatar

Joined: Mon May 25, 2015 2:25 pm
Posts: 632
Location: Gillies, Ontario, Canada
Wow, what a fun (and confusing) night of hacking away in my corner lab.

The ultra minimal 65C02 based multimedia computer is now alive and running 6502 assembly code!

It was really difficult to get all of the 6C502 timing correct while at the same time directing the different memory segments.
After some time (and wine), I finally managed to get the program from the 6502 assembler to load and execute.
I have some serious optimizing to do in the arbiter code, but I think this project will be usable enough for something decent.
Did I mention how much fun it was to make??

Here is how the Flash and SRAM inside the AVR is used by the 65C02 now...

Code:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 6502 ADDRESS SEGMENT      SEGMENT SIZE      SEGMENT DESCRIPTION      AVR MEMORY MAPPED LOCATION   
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   
// 00000 TO 00255         00256 BYTES      ZERO PAGE RAM         SRAM  FROM 00256 TO 00511
// 00256 TO 00511         00256 BYTES      HARDWARE STACK      SRAM  FROM 00512 TO 00767
// 00512 TO 13471         12960 BYTES      VIDEO MEMORY         SRAM  FROM 00768 TO 13727
// 13472 TO 16371         02900 BYTES      PROGRAM RAM         SRAM  FROM 13728 TO 16627
// 16372 TO 65529         49158 BYTES      PROGRAM ROM         FLASH MEMORY MAPPED
// 65530 TO 65531         00002 BYTES      NMI VECTOR         FLASH MEMORY MAPPED
// 65532 TO 65533         00002 BYTES      RESET VECTOR         FLASH MEMORY MAPPED
// 65534 TO 65535         00002 BYTES      BRK VECTOR         FLASH MEMORY MAPPED


To get a 6502 program up and running, the process is very quick and painless...

1) Code and assemble using your favorite PC program. I like the Kowalski Assembler.
2) Save a 64K Binary Image of your program.
3) Click on the 6502 to Data converter program I made.
4) Press the Load button in AVR Studio, and wait 3 seconds.

That's it. Right away, you get to see the results of your coding efforts.
Rapid coding with the ability to have instant feedback is the ultimate way to code. Forget debuggers man!

Here is an image being sent form the 6502 memory out to the simple Video generator memory mapped to address 12960...

Image
Video is 216x120 Resolution with 16 Colors.

This is the current state of the hardware now...

Image
A Vic-20 like Computer with 3 Chips and 10 Resistors.

There are 3 chips on the board : 65C02, AVR1284, and 74HC574.
The other black chip looking thing is the 25MHz oscillator.
There are also 10 resistors : 6 for the Video DAC and the rest for the 6502 pullups.

Here is a closeup of the ultra complex, super high quality Video DAC (AKA - 6 resistors)...

Image
The RGB+I DAC generates 16 colors : 8 hues with 2 intensity levels.

Now that I have the 6502 doing the heavy lifting, I will try some animation demos to see what it will do.
I don't expect to pull off too much here, since bytes have to be shoveled completely by the 6502.
If I can get even 1MHz of Pixel Bandwidth, than that would be just great.

Oh, and if you only want 4 levels of grey, this thing can be made with only 2 chips, but that's not cool.

It was cool to see the 6502 take over. A VIC-20 like computer made in 2 days using 3 chips on a breadboard!
Video timing was a bit intense, but that's where all the fun is at. I will post the entire project over the holidays.

Hope to get a few more days off over the next 2 weeks.
I must now give this project sound. Going to shoot for at least 2 voices capable of real music.

Cheers!
Radical Brad


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 28, 2016 8:20 am 
Offline
User avatar

Joined: Wed Feb 13, 2013 1:38 pm
Posts: 586
Location: Michigan, USA
Kind of like (grin);

1) Code and assemble using your favorite PC program.
2) Punch a set of cards of the Binary Image.
3) Read the set of cards into the AVR.
4) Watch the output of your program on the display.

Adding a keyboard would make it a lot more interactive. You'd be able to implement a Monitor program that would allow viewing/editing memory, support a dis-assembler and mini-assembler, single-step, etc. BASIC might be nice, too.

Actually, Geoff Graham's MX32 (DIP-28) video terminal chip is looking better and better to me. I could add it to my 2-chip design and have VGA video, Keyboard, and USB (serial) Terminal capability while running the 65C02 at 1-MHz. Adding Geoff's video terminal chip to my 3-chip design would produce a 64K system with expansion capability for 'classic' I/O (65C51, 65C22, etc.). Both systems (3-chip or 4-chip) would fit on your solderless breadboard quite nicely.

Anyway, nice demo'! Keep up the good work.

Cheerful regards, Mike


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 28, 2016 2:18 pm 
Offline
User avatar

Joined: Mon May 25, 2015 2:25 pm
Posts: 632
Location: Gillies, Ontario, Canada
Thanks!

Ironically, I actually considered making actual punch card hardware for my Vulcan-74 project!
I have the means to make such a device, and thought it would just be over-the-top retro.
It would be more of a "page reader" - using an 8.5x11 sheet that has been pixel coded and printed on laser.
The "reader" would feed the page, and read many bytes per line.
Perhaps another day, I am side tracked enough now.

The MX32 is a nice chip. I took the dive and learned MIPs assembly a few months ago. It was a bit "odd".
I will admit though, that the 8 bit XMega will run circles around the 32 bit PIC wen it comes to IO / SRAM speed!

Today is all about painting a cold storage room, so perhaps I will get some time on this project.
I will try to get a video of it doing some simple 6502 demo and post a schematic as well.
The graphics and speed are not spectacular, but I think I met my goal here...

The World's easiest to build and program breadboard based REAL 6502 multimedia computer.

Lofty claim, I know. There is always a smaller and faster fish out there someplace!

Brad


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 28, 2016 8:15 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10799
Location: England
Interesting project Brad, and impressive results with the video from the AVR. Did you share your code, or do you intend to?


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 28, 2016 11:18 pm 
Offline
User avatar

Joined: Mon May 25, 2015 2:25 pm
Posts: 632
Location: Gillies, Ontario, Canada
Thanks!
I will be posting everything as a final project once the code is optimized and commented.
Here is the code so far, without much optimizing and no sound routines...

Code:

////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// AVRCADE.COM - MINIMAL 6502 COMPUTER CHIPSET
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// TARGET : ATMEGA-1284 @ 25.175 MHZ
////////// VIDEO : 216 x 120 @ 16 COLORS
////////// AUDIO : TO BE COMPLETED
////////// HARDWARE AND CODING BY RADICAL BRAD
////////// VERSION DATE : DEC 28 2016
////////////////////////////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 25.175 MHZ TIMING FOR 640 X 480 @ 60 HZ VGA STANDARD
////////////////////////////////////////////////////////////////////////////////////////////////////////
// HSP : 096 FROM 0000 TO
// HBP : 048 FROM  TO
// HPX : 640 FROM  TO
// HFP : 016 FROM  TO
// TOT : 800
// VLN : 480 FROM 000 TO 479
// VFP : 011 FROM 480 TO 490
// VSP : 002 FROM 491 TO 492
// VBP : 032 FROM 493 TO 524
// TOT : 525




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 6502 AND AVR MEMORY MAPPING AND USAGE
////////////////////////////////////////////////////////////////////////////////////////////////////////
// 6502 ADDRESS SEGMENT      SEGMENT SIZE      SEGMENT DESCRIPTION      AVR MEMORY MAPPED LOCATION      
// 00000 TO 00255      00256 BYTES      ZERO PAGE RAM         SRAM  FROM 00256 TO 00511
// 00256 TO 00511      00256 BYTES      HARDWARE STACK         SRAM  FROM 00512 TO 00767
// 00512 TO 13471      12960 BYTES      VIDEO MEMORY         SRAM  FROM 00768 TO 13727
// 13472 TO 16371      02900 BYTES      PROGRAM RAM         SRAM  FROM 13728 TO 16627
// 16372 TO 65529      49158 BYTES      PROGRAM ROM         FLASH MEMORY MAPPED
// 65530 TO 65531      00002 BYTES      NMI VECTOR         FLASH MEMORY MAPPED
// 65532 TO 65533      00002 BYTES      RESET VECTOR         FLASH MEMORY MAPPED
// 65534 TO 65535      00002 BYTES      BRK VECTOR         FLASH MEMORY MAPPED




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// AVR DEDICATED REGISTERS
////////////////////////////////////////////////////////////////////////////////////////////////////////
// R2  : CONSTANT ZERO VALUE
// R3  : TEMP REGISTER TO SAVE DATA BUS
// R6  : TEMP REGISTER TO SWAP XL
// R7  : TEMP REGISTER TO SWAP XH
// R8  : TEMP REGISTER TO SWAP XL
// R9  : TEMP REGISTER TO SWAP XH
// R24 : 6502 VALID ADDRESS LO BYTE
// R25 : 6502 VALID ADDRESS HI BYTE
// XL  : VIDEO MEMORY POINTER LO BYTE
// XH  : VIDEO MEMORY POINTER HI BYTE
// YL  : VIDEO LINE COUNTER LO BYTE
// YH  : VIDEO LINE COUNTER HI BYTE
// ZL  : PROGRAM ROM POINTER LO BYTE
// ZH  : PROGRAM ROM POINTER HI BYTE




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// ATMEGA-1284 INITIALIZATION AND STARTUP
////////////////////////////////////////////////////////////////////////////////////////////////////////
.global main
main:

// ATMEGA-1284 INCLUDES ABD DEFINES
#include <avr/io.h>
#define __SFR_OFFSET 0


// SETUP PORT A
cbi DDRA,0; 6502 ADDRESS BIT 00
cbi DDRA,1; 6502 ADDRESS BIT 01
cbi DDRA,2; 6502 ADDRESS BIT 02
cbi DDRA,3; 6502 ADDRESS BIT 03
cbi DDRA,4; 6502 ADDRESS BIT 04
cbi DDRA,5; 6502 ADDRESS BIT 05
cbi DDRA,6; 6502 ADDRESS BIT 06
cbi DDRA,7; 6502 ADDRESS BIT 07

// SETUP PORT C
cbi DDRC,0; 6502 ADDRESS BIT 08 / PIXEL DATA BIT 0
cbi DDRC,1; 6502 ADDRESS BIT 09 / PIXEL DATA BIT 1
cbi DDRC,2; 6502 ADDRESS BIT 10 / PIXEL DATA BIT 2
cbi DDRC,3; 6502 ADDRESS BIT 11 / PIXEL DATA BIT 3
cbi DDRC,4; 6502 ADDRESS BIT 12 / PIXEL DATA BIT 4
cbi DDRC,5; 6502 ADDRESS BIT 13 / PIXEL DATA BIT 5
cbi DDRC,6; 6502 ADDRESS BIT 14 / PIXEL DATA BIT 6
cbi DDRC,7; 6502 ADDRESS BIT 15 / PIXEL DATA BIT 7

// SETUP PORT B
cbi DDRB,0; 6502 DATA BIT 0
cbi DDRB,1; 6502 DATA BIT 1
cbi DDRB,2; 6502 DATA BIT 2
cbi DDRB,3; 6502 DATA BIT 3
cbi DDRB,4; 6502 DATA BIT 4
cbi DDRB,5; 6502 DATA BIT 5
cbi DDRB,6; 6502 DATA BIT 6
cbi DDRB,7; 6502 DATA BIT 7

// SETUP PORT D
sbi DDRD,0; HORIZONTAL SYNC
sbi DDRD,1; VERTICAL SYNC
sbi DDRD,2; VIDEO BLANKING
sbi DDRD,3; AUDIO OUTPUT
sbi DDRD,4; 6502 CK
cbi DDRD,5; 6502 RW (LO:WRITE / HI:READ)
sbi DDRD,6; 6502 BE (LO:TRISTATE / HI:ACTIVE)
sbi DDRD,7; 6502 RS (LO:RESET / HI:RUN)

// SET TIMER 1 VIDEO INTERRUPT
ldi r16,(1<<CS10 | 1<<WGM12)
sts TCCR1B,r16

// SET TIMER1 MATCH INTERRUPT
ldi r16,(1<<OCIE1A)
sts TIMSK1,r16

// SET TIMER1 INTERRUPT TIME
ldi r16,hi8(800)
sts OCR1AH,r16
ldi r16,lo8(800)
sts OCR1AL,r16

// SET ALL PORTS LOW
clr r16
out PORTA,r16
out PORTB,r16
out PORTC,r16
out PORTD,r16




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 65C02 INITIALIZATION AND STARTUP
////////////////////////////////////////////////////////////////////////////////////////////////////////

// ENABLE 6502 BUS
sbi PORTD,6

// RESET 6502
cbi PORTD,7

// SEND CLOCK CYCLES
clr r16
RSCLK:
cbi PORTD,4
nop
nop
nop
nop
nop
nop
sbi PORTD,4
nop
nop
nop
nop
nop
nop
dec r16
brne RSCLK

// UNRESET 6502
sbi PORTD,7

// RESET DELAY
clr r16
RSDLY:
inc r16
brne RSDLY




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// SYSTEM INITIALIZATION AND STARTUP
////////////////////////////////////////////////////////////////////////////////////////////////////////

// CLEAR REGISTERS
clr r2
ser r16
mov r14,r16

ldi XL,lo8(768)
ldi XH,hi8(768)
movw r6,X

ldi XL,lo8(256)
ldi XH,hi8(256)
movw r10,X

ldi ZL,lo8(ProgMEM)
ldi ZH,hi8(ProgMEM)
movw r12,Z


// START VIDEO INTERRUPT
sei




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 65C02 CLOCK AND MEMORY ACCESS CONTROLLER
////////////////////////////////////////////////////////////////////////////////////////////////////////
RUN6502:

// 6502 CLOCK CYCLE
cbi PORTD,4
sbi PORTD,4

// READ ADDRESS FROM 6502
in r24,PINA
in r25,PINC

// CHECK RW STATUS
sbis PIND,5
rjmp WRITE6502




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 6502 READ REQUEST : RW HI
////////////////////////////////////////////////////////////////////////////////////////////////////////

// SET AVR DATA BUS FOR OUTPUT
out DDRB,r14

// CHECK FOR RAM MEMORY
cpi r24,lo8(16371) ; use movw
ldi r16,hi8(16371)
cpc r25,r16
brlo q1

// READ FROM ROM MEMORY
movw Z,r12
ldi r16,hh8(ProgMEM)
out RAMPZ,r16
add ZL,r24
adc ZH,r25
clr r16
brcc gg
inc r16
gg:
out RAMPZ,r16
elpm r16,Z
rjmp q2
q1:

// READ FROM RAM MEMORY
movw X,r10
add XL,r24
adc XH,r25
ld r16,X
q2:

// SEND DATA TO 6502
out PORTB,r16

// SET AVR DATA BUS FOR INPUT
out DDRB,r2

// END OF READ REQUEST
rjmp RUN6502




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 6502 WRITE REQUEST : RW LO
////////////////////////////////////////////////////////////////////////////////////////////////////////
WRITE6502:

// CHECK FOR RAM MEMORY
cpi r24,lo8(16371) ; use movw
ldi r16,hi8(16371)
cpc r25,r16
brlo b1

// WRITE TO PIXEL X REGISTER
cpi r24,lo8(32768)
ldi r16,hi8(32768)
cpc r25,r16
brne rr1
in r22,PINB
rr1:

// WRITE TO PIXEL Y REGISTER
cpi r24,lo8(32769)
ldi r16,hi8(32769)
cpc r25,r16
brne rr2
in r23,PINB
rr2:

// WRITE TO PIXEL COLOR REGISTER
cpi r24,lo8(32770)
ldi r16,hi8(32770)
cpc r25,r16
brne rr3
ldi XL,lo8(768)
ldi XH,hi8(768)
add XL,r22
adc XH,r2
ldi r16,108
mul r23,r16
add XL,r0
adc XH,r1
in r16,PINB
st X,r16
rr3:

// END OF GPU WRITE
rjmp RUN6502

// SET POINTER TO RAM
b1:
movw X,r10
add XL,r24
adc XH,r25

// WRITE DATA TO MEMORY
in r16,PINB
st X,r16

// END OF WRITE REQUEST
rjmp RUN6502




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// HORIZONTAL SYNC PULSE  = 96 CYCLES
////////////////////////////////////////////////////////////////////////////////////////////////////////
.global TIMER1_COMPA_vect
TIMER1_COMPA_vect:

// HORIZONTAL SYNC ON (2)
cbi PORTD,0 ;2

; SAVE REGISTERS (7)
push r16 ;2
in r16,SREG ;1
push r16 ;2
movw r8,X ;1
movw X,r6 ;1

; EQUALIZE INTERRUPT LATENCY (11)
#define fix 17
lds r16,TCNT1L ;2
cpi r16,fix+0 ;1
brlo FIX0 ;1/2
FIX0:
cpi r16,fix+1 ;1
brlo FIX1 ;1/2
FIX1:
cpi r16,fix+2 ;1
brlo FIX2 ;1/2
FIX2:

// VERTICAL SYNC FROM 492 TO 493 (16)
ldi r16,hi8(492) ;1
cpi YL,lo8(492) ;1
cpc YH,r16 ;1
brne AVRC_HSL1 ;1/2
cbi PORTD,1 ;2
AVRC_HSL1:
breq AVRC_HSL2 ;1/2
nop ;1
nop ;1
AVRC_HSL2:
ldi r16,hi8(494) ;1
cpi YL,lo8(494) ;1
cpc YH,r16 ;1
brne AVRC_HSH1 ;1/2
sbi PORTD,1 ;2
AVRC_HSH1:
breq AVRC_HSH2 ;1/2
nop ;1
nop ;1
AVRC_HSH2:

// LINE COUNTER WRAP AT 525 (13)
adiw YL,1 ;2
ldi r16,hi8(525) ;1
cpi YL,lo8(525) ;1
cpc YH,r16 ;1
brne AVRC_LWL ;1/2
clr YL ;1
AVRC_LWL:
brne AVRC_LWH ;1/2
clr YH ;1
AVRC_LWH:
brne AVRC_LCL ;1/2
ldi XL,lo8(768) ;1
AVRC_LCL:
brne AVRC_LCH ;1/2
ldi XH,hi8(768) ;1
AVRC_LCH:


// DELAY (48)
ldi r16,1
qq1:
dec r16
brne qq1

// DISABLE 6502 BUS
cbi PORTD,6

// ENABLE VIDEO BUS
ser r16
out DDRC,r16


// HORIZONTAL SYNC OFF (2)
sbi PORTD,0 ;2




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// HORIZONTAL BACK PORCH  = 40 CYCLES
////////////////////////////////////////////////////////////////////////////////////////////////////////

// BLANKING FROM 480 TO 524 (5)
ldi r16,hi8(480) ;1
cpi YL,lo8(480) ;1
cpc YH,r16 ;1
brcs AVRC_ACT ;1/2
rjmp AVRC_BLK ;2
AVRC_ACT:

// SET VIDEO MEMORY LINE (7)
mov r16,YL ;1
andi r16,3 ;1
cpi r16,0 ;1
breq AVRC_SV1 ;1/2
subi XL,108 ;1
AVRC_SV1:
breq AVRC_SV2 ;1/2
sbc XH,r2 ;1
AVRC_SV2:

// ENABLE PIXELS (3)
out PORTC,r2; 1
cbi PORTD,2 ;2




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// HORIZONTAL PIXEL LINE = 648 / 3 = 216 PIXELS / 8 = 27 CHARACTERS
////////////////////////////////////////////////////////////////////////////////////////////////////////

ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1
ld r16,X+ ;2
out PORTC,r16 ;1
swap r16 ;1
nop ;1
out PORTC,r16 ;1




////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// ////////// HORIZONTAL FRONT PORCH  = 16 CYCLES
////////////////////////////////////////////////////////////////////////////////////////////////////////
AVRC_HFP:

// HORIZONTAL BLANKING (4)
nop; 1
nop ;1
sbi PORTD,2 ;2
AVRC_BLK:

// DISABLE VIDEO BUS
out DDRC,r2

// ENABLE 6502 BUS
sbi PORTD,6

// restore data
//out PORTB,r3

// RESTORE REGISTERS (7)
movw r6,X ;1
movw X,r8 ;1
pop r16 ;2
out SREG,r16 ;1
pop r16 ;2

; RETURN FROM INTERRUPT
reti ;4



////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// ////////// INCLUDE 6502 ASSEMBLED 64K BINARY IMAGE
////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "6502MEM.s"




I am going to clean this up, add some sound, and then do a basic 6502 demo program.
The memory arbiter ate a LOT of cycles, so this isn't the fastest thing I have ever made.
Should just barely outperform a C64 for graphics speed.
Sound will be about as good as a VIC20.

Cheers,
Brad

BigEd wrote:
Interesting project Brad, and impressive results with the video from the AVR. Did you share your code, or do you intend to?


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 29, 2016 12:32 am 
Offline
User avatar

Joined: Mon May 25, 2015 2:25 pm
Posts: 632
Location: Gillies, Ontario, Canada
Anyone know of any good 6502 graphics code snippets?
I want to try out some code to see how this might compare to a VIC or C64.

Right now, I have routines that would expect the following...

6502 X Register : X Screen Location from 0 to 215
6502 Y Register : Y Screen Location from 0 to 119
6502 ZP Location 10 : Color of Pixel (0-15)

When the above information is set, I just do this to trigger a Pixel Draw...

Code:
 LDA 10 ; Get Pixel Color from ZP.10
 STX 32768 ; Set Pixel X Location
 STY 32769 ; Set Pixel Y Location
 STA 32770 ; Draw Pixel to VidMem


Other than following my memory map shown in previous posts, there are no limitations.
Even though memory at 32768+ is all ROM, the AVR (Kernal) takes that as a command to draw a pixel.
The 6502 could also just write directly to the Video Memory, but that requires some X/Y math.

Brad


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 29, 2016 2:11 pm 
Offline
User avatar

Joined: Mon May 25, 2015 2:25 pm
Posts: 632
Location: Gillies, Ontario, Canada
I tried to post this video yesterday, but it takes my internet almost 8 hours to upload a 300MB file!
Here is a basic proof of concept program running on the 6502...

Image
https://youtu.be/tunzcVP00J0

Sorry about the wiring mess, I have not cleaned anything up yet.
This test code checks the RW and access to RAM, ROM, Stack, and Zero Page.
Pixel drawing is slowed down 100 times by a loop so that drawing can be seen.

I did some cycle counting to see how fast the 6502 is actually running, but it is not that simple.
The 6502 clock is variable, and it depends on what is being accessed.
For Program ROM reads, I would say the 6502 runs at about 2.5 Mhz.
For SRAM reads (including ZP and Stack), it gets about 5MHz.
Writes are also highly variable, as it depends on the location.
To make an overall estimate, I would say 3MHz is the average 6502 speed here. Not bad.

For those messing with total control of a 65C02, I have made an observation on the clock.
You can speed it up beyond the posted limit by shrinking the low clock cycle.
Drop the clock low and then back high as fast as 20MHz, then keep it to the limit for the high cycle.
This works great here and on my FPGA project, where I am getting an easy 10 MHz+ out of a 6502.

I have also included several built in character sets (5x5 and 8x8). These are in memory above 64K.
This saves more room for actual 6502 code. To draw text, there are registers that can be written to.
I am also going to add some math functions (multiply, sin, cos, rand), and collision detection.
Of course, there will be a basic Blitter as well to help copy large blocks of graphics memory around!

Now that this experiment is a success, I will add sound and joystick input.
I plan on bus sharing one of the address ports to switch on the ADC during the active pixel time.
The 6502 is tri-stated at this time, so I can use all 8 ADC channels to read the joystick position.
This works great because I won't need a 4th chip (buffer) to isolate the joystick from the bus.
A direct connection would short address lines when moving diagonally due to the way 2 switched are active.
By using the ADC instead, I will just drive the bus bits from the joystick with 10K resistors.
Being pulled up weakly will have no effect on the bus when it is driven from the 6502.

Perhaps I will get time today to do a little bit of hacking while paint is drying!

Later,
Brad


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 29, 2016 4:48 pm 
Offline
User avatar

Joined: Wed Feb 13, 2013 1:38 pm
Posts: 586
Location: Michigan, USA
Can we double-check those 6502 speed estimates, please?

With a 25.175-MHz clock, isn't an AVR cycle about ~39.72-nS? That implies a "RUN6502" loop should take ~5 AVR cycles for a 5-MHz 6502 clock cycle or ~10 AVR cycles for a 2.5-MHz 6502 clock cycle. I'm not familiar with AVR but it seems the first few instructions in your "RUN6502" loop take four or five cycles just to copy the 16-bit address bus value and check the 6502 R/W line. What am I missing?

Cheerful regards, Mike


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 29, 2016 5:09 pm 
Offline
User avatar

Joined: Mon May 25, 2015 2:25 pm
Posts: 632
Location: Gillies, Ontario, Canada
I have reworked the code a lot since that post, but I probably did underestimate the cycle count through some of the memory access pathways.
I will do a proper count when it is all done, but at this point 1.25 MHz is probably the high end.
I will probably speed this up by using PWM for the 6502 clock and lookup tables later on.

It certainly won't be any kind of speed demon, that's for sure! Just a fun way to see code run on a real 6502.
Ironically, it would be faster if I just emulated a 6502 right inside the AVR! but that's not the goal here.

I have just figured out how to share the 8 channel ADC with the 6502 low address bus, so now I have joystick input.
Just to make it fun (and simple), I may use a potentiometer and 2 or 4 buttons for the joystick rather than the usual Atari style.
Having the analog + digital controller will make the hardware accessible to anyone. Those C64 joysticks are not easy to find these days!

Once I get the basic sound working, I will probably tune up my 6502 assembly skills on something very basic like a bad PacMan clone.

Cheers,
Brad

Michael wrote:
Can we double-check those 6502 speed estimates, please?
With a 25.175-MHz clock, isn't an AVR cycle about ~39.72-nS? That implies a "RUN6502" loop should take ~5 AVR cycles for a 5-MHz 6502 clock cycle or ~10 AVR cycles for a 2.5-MHz 6502 clock cycle. I'm not familiar with AVR but it seems the first few instructions in your "RUN6502" loop take four or five cycles just to copy the 16-bit address bus value and check the 6502 R/W line. What am I missing?
Cheerful regards, Mike


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 70 posts ]  Go to page Previous  1, 2, 3, 4, 5

All times are UTC


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: