180 lines
11 KiB
C++
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
|
|
}
|
|
|