Files
SyncHome/trunk/Arduino/Single_Chip_VIC20/Single_Chip_VIC20.ino
2023-03-17 11:40:49 +00:00

180 lines
11 KiB
C++

#include <EEPROM.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
//----------------- VideoBlaster definitions -----------------
#define DOTCLK 1 // Pixel clock (0 for 8MHz, 1 for 4MHz)
#define HSYNC 132 // Hsync frequency (divided from Fcpu)
#define LINES 261 // Lines per field -1 (261 for NTSC, 311 for PAL)
#define SYNCPIN 4 // Pin in PORTD that rhat is connected for sync
#define INTERLACE 0 // 0 for interlace, 1 for non interlace Running with interlaced video gives more cycles to the application
volatile byte VBE=0; // Video blanking status. If this is not zero you should sleep to keep the video smooth
#define WAIT_VBE while (VBE==1) sleep_cpu();
unsigned int scanline=0; // Dont touch, not volatile
unsigned int videoptr=0; // Dont touch, not volatile
byte row; // Dont touch, not volatile
byte lace; // Dont touch, not volatile
// This is the video character ROM (8x8 font definition)
const unsigned char charROM [8] [128] PROGMEM = { 0x1C , 0x18 , 0x7C , 0x1C , 0x78 , 0x7E , 0x7E , 0x1C , 0x42 , 0x1C , 0xE , 0x42 , 0x40 , 0x42 , 0x42 , 0x18 , 0x7C , 0x18 , 0x7C , 0x3C , 0x3E , 0x42 , 0x42 , 0x42 , 0x42 , 0x22 , 0x7E , 0x42 , 0x42 , 0x18 , 0x0 , 0x0 , 0x0 , 0x8 , 0x24 , 0x24 , 0x8 , 0x0 , 0x30 , 0x4 , 0x4 , 0x20 , 0x8 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3C , 0x8 , 0x3C , 0x3C , 0x4 , 0x7E , 0x1C , 0x7E , 0x3C , 0x3C , 0x0 , 0x0 , 0xE , 0x0 , 0x70 , 0x3C , 0x0 , 0x8 , 0x10 , 0x0 , 0x0 , 0x0 , 0x0 , 0x20 , 0x4 , 0x0 , 0x8 , 0x8 , 0x80 , 0x80 , 0x1 , 0xFF , 0xFF , 0x0 , 0x0 , 0x36 , 0x40 , 0x0 , 0x81 , 0x0 , 0x8 , 0x2 , 0x8 , 0x8 , 0xA0 , 0x8 , 0x0 , 0xFF , 0x0 , 0xF0 , 0x0 , 0xFF , 0x0 , 0x80 , 0xAA , 0x1 , 0x0 , 0xFF , 0x3 , 0x8 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x8 , 0x0 , 0x8 , 0xC0 , 0xE0 , 0x7 , 0xFF , 0xFF , 0x0 , 0x1 , 0x0 , 0xF , 0x8 , 0xF0 , 0xF0 , 0x22 , 0x24 , 0x22 , 0x22 , 0x24 , 0x40 , 0x40 , 0x22 , 0x42 , 0x8 , 0x4 , 0x44 , 0x40 , 0x66 , 0x62 , 0x24 , 0x42 , 0x24 , 0x42 , 0x42 , 0x8 , 0x42 , 0x42 , 0x42 , 0x42 , 0x22 , 0x2 , 0x18 , 0x18 , 0x24 , 0x8 , 0x0 , 0x0 , 0x8 , 0x24 , 0x24 , 0x1E , 0x62 , 0x48 , 0x8 , 0x8 , 0x10 , 0x2A , 0x8 , 0x0 , 0x0 , 0x0 , 0x2 , 0x42 , 0x18 , 0x42 , 0x42 , 0xC , 0x40 , 0x20 , 0x42 , 0x42 , 0x42 , 0x0 , 0x0 , 0x18 , 0x0 , 0x18 , 0x42 , 0x0 , 0x1C , 0x10 , 0x0 , 0x0 , 0xFF , 0x0 , 0x20 , 0x4 , 0x0 , 0x8 , 0x8 , 0x80 , 0x40 , 0x2 , 0x80 , 0x1 , 0x3C , 0x0 , 0x7F , 0x40 , 0x0 , 0x42 , 0x3C , 0x1C , 0x2 , 0x1C , 0x8 , 0x50 , 0x8 , 0x0 , 0x7F , 0x0 , 0xF0 , 0x0 , 0x0 , 0x0 , 0x80 , 0x55 , 0x1 , 0x0 , 0xFE , 0x3 , 0x8 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x8 , 0x0 , 0x8 , 0xC0 , 0xE0 , 0x7 , 0xFF , 0xFF , 0x0 , 0x1 , 0x0 , 0xF , 0x8 , 0xF0 , 0xF0 , 0x4A , 0x42 , 0x22 , 0x40 , 0x22 , 0x40 , 0x40 , 0x40 , 0x42 , 0x8 , 0x4 , 0x48 , 0x40 , 0x5A , 0x52 , 0x42 , 0x42 , 0x42 , 0x42 , 0x40 , 0x8 , 0x42 , 0x42 , 0x42 , 0x24 , 0x22 , 0x4 , 0x24 , 0x24 , 0x3C , 0x1C , 0x10 , 0x0 , 0x8 , 0x24 , 0x7E , 0x28 , 0x64 , 0x48 , 0x10 , 0x10 , 0x8 , 0x1C , 0x8 , 0x0 , 0x0 , 0x0 , 0x4 , 0x46 , 0x28 , 0x2 , 0x2 , 0x14 , 0x78 , 0x40 , 0x4 , 0x42 , 0x42 , 0x8 , 0x8 , 0x30 , 0x7E , 0xC , 0x2 , 0x0 , 0x3E , 0x10 , 0x0 , 0xFF , 0x0 , 0x0 , 0x20 , 0x4 , 0x0 , 0x8 , 0x8 , 0x80 , 0x20 , 0x4 , 0x80 , 0x1 , 0x7E , 0x0 , 0x7F , 0x40 , 0x0 , 0x24 , 0x42 , 0x2A , 0x2 , 0x3E , 0x8 , 0xA0 , 0x8 , 0x1 , 0x3F , 0x0 , 0xF0 , 0x0 , 0x0 , 0x0 , 0x80 , 0xAA , 0x1 , 0x0 , 0xFC , 0x3 , 0x8 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x8 , 0x0 , 0x8 , 0xC0 , 0xE0 , 0x7 , 0x0 , 0xFF , 0x0 , 0x1 , 0x0 , 0xF , 0x8 , 0xF0 , 0xF0 , 0x56 , 0x7E , 0x3C , 0x40 , 0x22 , 0x78 , 0x78 , 0x4E , 0x7E , 0x8 , 0x4 , 0x70 , 0x40 , 0x5A , 0x4A , 0x42 , 0x7C , 0x42 , 0x7C , 0x3C , 0x8 , 0x42 , 0x24 , 0x5A , 0x18 , 0x1C , 0x18 , 0x42 , 0x42 , 0x42 , 0x2A , 0x20 , 0x0 , 0x8 , 0x0 , 0x24 , 0x1C , 0x8 , 0x30 , 0x0 , 0x10 , 0x8 , 0x3E , 0x3E , 0x0 , 0x7E , 0x0 , 0x8 , 0x5A , 0x8 , 0xC , 0x1C , 0x24 , 0x4 , 0x7C , 0x8 , 0x3C , 0x3E , 0x0 , 0x0 , 0x60 , 0x0 , 0x6 , 0xC , 0x0 , 0x7F , 0x10 , 0xFF , 0x0 , 0x0 , 0x0 , 0x20 , 0x4 , 0x0 , 0x4 , 0x10 , 0x80 , 0x10 , 0x8 , 0x80 , 0x1 , 0x7E , 0x0 , 0x7F , 0x40 , 0x0 , 0x18 , 0x42 , 0x77 , 0x2 , 0x7F , 0x8 , 0x50 , 0x8 , 0x3E , 0x1F , 0x0 , 0xF0 , 0x0 , 0x0 , 0x0 , 0x80 , 0x55 , 0x1 , 0x0 , 0xF8 , 0x3 , 0x8 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x8 , 0x0 , 0x8 , 0xC0 , 0xE0 , 0x7 , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0xF , 0x8 , 0xF0 , 0xF0 , 0x4C , 0x42 , 0x22 , 0x40 , 0x22 , 0x40 , 0x40 , 0x42 , 0x42 , 0x8 , 0x4 , 0x48 , 0x40 , 0x42 , 0x46 , 0x42 , 0x40 , 0x4A , 0x48 , 0x2 , 0x8 , 0x42 , 0x24 , 0x5A , 0x24 , 0x8 , 0x20 , 0x7E , 0x42 , 0x7E , 0x8 , 0x7F , 0x0 , 0x0 , 0x0 , 0x7E , 0xA , 0x10 , 0x4A , 0x0 , 0x10 , 0x8 , 0x1C , 0x8 , 0x0 , 0x0 , 0x0 , 0x10 , 0x62 , 0x8 , 0x30 , 0x2 , 0x7E , 0x2 , 0x42 , 0x10 , 0x42 , 0x2 , 0x0 , 0x0 , 0x30 , 0x7E , 0xC , 0x10 , 0xFF , 0x7F , 0x10 , 0x0 , 0x0 , 0x0 , 0x0 , 0x20 , 0x4 , 0xE0 , 0x3 , 0xE0 , 0x80 , 0x8 , 0x10 , 0x80 , 0x1 , 0x7E , 0x0 , 0x3E , 0x40 , 0x3 , 0x18 , 0x42 , 0x2A , 0x2 , 0x3E , 0xFF , 0xA0 , 0x8 , 0x54 , 0xF , 0x0 , 0xF0 , 0xFF , 0x0 , 0x0 , 0x80 , 0xAA , 0x1 , 0xAA , 0xF0 , 0x3 , 0xF , 0xF , 0xF , 0xF8 , 0x0 , 0xF , 0xFF , 0xFF , 0xF8 , 0xC0 , 0xE0 , 0x7 , 0x0 , 0x0 , 0x0 , 0x1 , 0xF0 , 0x0 , 0xF8 , 0x0 , 0xF , 0x20 , 0x42 , 0x22 , 0x22 , 0x24 , 0x40 , 0x40 , 0x22 , 0x42 , 0x8 , 0x44 , 0x44 , 0x40 , 0x42 , 0x42 , 0x24 , 0x40 , 0x24 , 0x44 , 0x42 , 0x8 , 0x42 , 0x18 , 0x66 , 0x42 , 0x8 , 0x40 , 0x42 , 0x24 , 0x42 , 0x8 , 0x20 , 0x0 , 0x0 , 0x0 , 0x24 , 0x3C , 0x26 , 0x44 , 0x0 , 0x8 , 0x10 , 0x2A , 0x8 , 0x8 , 0x0 , 0x18 , 0x20 , 0x42 , 0x8 , 0x40 , 0x42 , 0x4 , 0x44 , 0x42 , 0x10 , 0x42 , 0x4 , 0x8 , 0x8 , 0x18 , 0x0 , 0x18 , 0x0 , 0x0 , 0x1C , 0x10 , 0x0 , 0x0 , 0x0 , 0xFF , 0x20 , 0x4 , 0x10 , 0x0 , 0x0 , 0x80 , 0x4 , 0x20 , 0x80 , 0x1 , 0x7E , 0x0 , 0x1C , 0x40 , 0x4 , 0x24 , 0x42 , 0x8 , 0x2 , 0x1C , 0x8 , 0x50 , 0x8 , 0x14 , 0x7 , 0x0 , 0xF0 , 0xFF , 0x0 , 0x0 , 0x80 , 0x55 , 0x1 , 0x55 , 0xE0 , 0x3 , 0x8 , 0xF , 0x0 , 0x8 , 0x0 , 0x8 , 0x0 , 0x8 , 0x8 , 0xC0 , 0xE0 , 0x7 , 0x0 , 0x0 , 0xFF , 0x1 , 0xF0 , 0x0 , 0x0 , 0x0 , 0xF , 0x1E , 0x42 , 0x7C , 0x1C , 0x78 , 0x7E , 0x40 , 0x1C , 0x42 , 0x1C , 0x38 , 0x42 , 0x7E , 0x42 , 0x42 , 0x18 , 0x40 , 0x1A , 0x42 , 0x3C , 0x8 , 0x3C , 0x18 , 0x42 , 0x42 , 0x8 , 0x7E , 0x42 , 0x18 , 0x42 , 0x8 , 0x10 , 0x0 , 0x8 , 0x0 , 0x24 , 0x8 , 0x46 , 0x3A , 0x0 , 0x4 , 0x20 , 0x8 , 0x0 , 0x8 , 0x0 , 0x18 , 0x40 , 0x3C , 0x3E , 0x7E , 0x3C , 0x4 , 0x38 , 0x3C , 0x10 , 0x3C , 0x38 , 0x0 , 0x8 , 0xE , 0x0 , 0x70 , 0x10 , 0x0 , 0x3E , 0x10 , 0x0 , 0x0 , 0x0 , 0x0 , 0x20 , 0x4 , 0x8 , 0x0 , 0x0 , 0x80 , 0x2 , 0x40 , 0x80 , 0x1 , 0x3C , 0xFF , 0x8 , 0x40 , 0x8 , 0x42 , 0x3C , 0x8 , 0x2 , 0x8 , 0x8 , 0xA0 , 0x8 , 0x14 , 0x3 , 0x0 , 0xF0 , 0xFF , 0x0 , 0x0 , 0x80 , 0xAA , 0x1 , 0xAA , 0xC0 , 0x3 , 0x8 , 0xF , 0x0 , 0x8 , 0xFF , 0x8 , 0x0 , 0x8 , 0x8 , 0xC0 , 0xE0 , 0x7 , 0x0 , 0x0 , 0xFF , 0x1 , 0xF0 , 0x0 , 0x0 , 0x0 , 0xF , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x10 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x10 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x10 , 0x0 , 0x0 , 0x0 , 0x0 , 0x20 , 0x4 , 0x8 , 0x0 , 0x0 , 0xFF , 0x1 , 0x80 , 0x80 , 0x1 , 0x0 , 0x0 , 0x0 , 0x40 , 0x8 , 0x81 , 0x0 , 0x0 , 0x2 , 0x0 , 0x8 , 0x50 , 0x8 , 0x0 , 0x1 , 0x0 , 0xF0 , 0xFF , 0x0 , 0xFF , 0x80 , 0x55 , 0x1 , 0x55 , 0x80 , 0x3 , 0x8 , 0xF , 0x0 , 0x8 , 0xFF , 0x8 , 0x0 , 0x8 , 0x8 , 0xC0 , 0xE0 , 0x7 , 0x0 , 0x0 , 0xFF , 0xFF , 0xF0 , 0x0 , 0x0 , 0x0 , 0xF };
#define SYNCDELAY // This makes up the sync pulse low time delay
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); \
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); \
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); \
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); \
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); \
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); \
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); \
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
const byte MSPIM_SCK = 4; // This is needed for the hardware to work
const byte MSPIM_SS = 5; // This is needed for the hardware to work
//--------------------------------------------------------------
char videomem[528];
char basicram[512];
uint8_t RAM[832];
extern "C" {
void exec6502();
void reset6502();
void writeEEPROM(unsigned int eeaddress, byte data ) {
if ((eeaddress>7679)&&(eeaddress<8192)) {
videomem[eeaddress-7680+22]=data;
return;
}
if ((eeaddress>1023)&&(eeaddress<2048)) {
digitalWrite(13,HIGH);
EEPROM.write(eeaddress&0x3FF, data);
digitalWrite(13,LOW);
return;
}
if ((eeaddress>2047)&&(eeaddress<7680)) {
basicram[eeaddress&0x1FF]=data;
return;
}
return;
}
byte readEEPROM(unsigned int eeaddress ) {
if ((eeaddress>7679)&&(eeaddress<8192)) {
return videomem[eeaddress-7680+22];
}
if ((eeaddress>1023)&&(eeaddress<2048)) {
return EEPROM.read(eeaddress&0x3FF);
}
if ((eeaddress>2047)&&(eeaddress<7680)) {
return basicram[eeaddress&0x1FF];
}
return 0xFF;
}
}
ISR(TIMER0_COMPA_vect){ //Video interrupt. This is called at every line in the frame.
byte c=8; //Back porch
byte d=4; //Left Blank
byte p=22; //Chars per row
PORTD=0;
if ((scanline>2)&&(scanline<40)||(scanline>231)) {
SYNCDELAY
PORTD = SYNCPIN;
VBE=0;
}
if (scanline<3) {
SYNCDELAY
PORTD =0;
videoptr=0;
row=0;
}
if ((scanline>39)&&(scanline<232)) {
SYNCDELAY
PORTD = SYNCPIN;
if (lace&1|INTERLACE) {
const register byte * linePtr = &charROM [ row & 0x07 ] [0];
register byte * messagePtr = (byte *) & videomem [videoptr] ;
while (c--) {
asm("nop\n");
asm("nop\n");
}
UCSR0B = _BV(TXEN0);
while (d--) {
while ((UCSR0A & _BV (UDRE0)) == 0) {}
UDR0 = 0;
}
while (p--) {
UDR0 = pgm_read_byte (linePtr + (* messagePtr++));
while ((UCSR0A & _BV (UDRE0)) == 0)
{}
}
while ((UCSR0A & _BV (UDRE0)) == 0)
{}
UCSR0B = 0;
row++;
videoptr=(row>>3)*22;
VBE=1;
}
}
scanline++;
if (scanline>LINES) {
scanline=0;
lace++;
}
}
void setup () {
pinMode (MSPIM_SS, OUTPUT); //A must for MSMSPI VIDEO to work
pinMode (MSPIM_SCK, OUTPUT); //A must for MSMSPI VIDEO to work
pinMode(2, OUTPUT); //Set D2 as output for Sync. A must for MSMSPI VIDEO to work
UBRR0 = 0;
UCSR0A = _BV (TXC0);
UCSR0C = _BV (UMSEL00) | _BV (UMSEL01);
UCSR0B = _BV (TXEN0);
UBRR0 = DOTCLK;
cli();
TCCR0A = 0;
TCCR0B = 0;
TCNT0 = 0;
OCR0A = HSYNC;// = (16*10^6) / (15625*8) - 1 (must be <256)
TCCR0A |= (1 << WGM01);
TCCR0B |= (1 << CS01) | (0 << CS00);
TIMSK0 |= (1 << OCIE0A);
set_sleep_mode (SLEEP_MODE_IDLE);
sei();
pinMode(13, OUTPUT);
digitalWrite(13,LOW);
pinMode(1, OUTPUT); //A must for MSMSPI VIDEO to work
digitalWrite(1,LOW); //A must for MSMSPI VIDEO to work
reset6502();
for (int i=0;i<528;i++) {
videomem[i]=32;
}
}
void loop () {
WAIT_VBE
exec6502();
RAM[55]=0; //POKE55,0
RAM[56]=0x0A; //POKE56,10 lower top of mem to 0x0A
}