#include #include #include #include #include //----------------- 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 }