The VideoBlaster Hi Resolution TVout platform

Yes, I'll put the sourcecode up.

The colorsignal is generated by setting timer2 to divide by 29.
8000000/29 = 275862, 275862 x 13 = 3586206.

By temporarly changing the divide on a single cycle changes its phase compared to the burst.

275862 / 15750 = 17.5 changes/line.
We can modulate the clocksignal output by setting pin3 as input or output but to change phase?

It is going to need another pin for higher phasechange resolution.

janost:
We can modulate the clocksignal output by setting pin3 as input or output but to change phase?

Start the timer at different places in the horizontal blank?

fungus:

janost:
We can modulate the clocksignal output by setting pin3 as input or output but to change phase?

Start the timer at different places in the horizontal blank?

Yes, its all relative to the signal in the colorburst.

Some ideas what need to be done for NTSC color.

NTSC.bmp (1.26 MB)

NTSC2.bmp (1.23 MB)

fungus:
b) Do you think it's possible to set a color per video line?

I think it is very doable.

Now I know where the tearing and artifacts comes from.
It turns out the LCD-screen only has a vertical resolution of 240lines and that is an absolute physical.

I run it with over 250 visible lines and that creates line artifacts.

janost:
Now I know where the tearing and artifacts comes from.
It turns out the LCD-screen only has a vertical resolution of 240lines and that is an absolute physical.

I run it with over 250 visible lines and that creates line artifacts.

You're saying it can't accept an NTSC signal?

fungus:

janost:
Now I know where the tearing and artifacts comes from.
It turns out the LCD-screen only has a vertical resolution of 240lines and that is an absolute physical.

I run it with over 250 visible lines and that creates line artifacts.

You're saying it can't accept an NTSC signal?

Yes, it can but I'm running PAL with 288 visible lines.
Some lines drop out and some lines are doubled.

I have looked at adding a scart and a VGA port today.
With scart I can do 24x24 text in 16colors and the same with VGA.

Tiled 192x192, that is retro arcaderesolution.
It's a bit easier to get going than composite color.

To make color to work I need to make the pixel output gate the colorbits on D4-D7.
Either with diodes or with a 74LS08 Quad AND gate.

I'll include all 4 modes in the code.

Here is the code for 40x25 textmode B/W Composite output.
It contains some leftover junk so not all of it is required.

You can put your own calls in the loop() function but they cannot be blocking, i.e they have to return Before the next 200 lines are painted by the interrupt.

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

//CBM Textset1 ROM
const unsigned char charROM [8] [128] PROGMEM = { 0x1C , ... , 0xFF }; //Contains the PETSCII Font for characters 0-127

//const unsigned charROM [8] [128] PROGMEM = { 0x00 , ... , 0xFF }; // Contains the Block char font 2x3 blocks for the pset function.

char gameMAP[16] = { 0x20 , 0x20 , 0x4E , 0x20 , 0x20 , 0x4E , 0x20 , 0x20 , 0x4E , 0x20 , 0x20 , 0x20 , 0x45 , 0x45 , 0x45 , 0x4E };



const byte MSPIM_SCK = 4;
const byte MSPIM_SS = 5;

unsigned int scanline=0;
unsigned int videoptr=0;
byte row;
byte charcode;
byte border=0x00;
char videomem[1040];
unsigned int h=0;
unsigned int w=0;

void setup() {
  pinMode (MSPIM_SS, OUTPUT);   // SS
  // must be zero before enabling the transmitter
  UBRR0 = 0;
  UCSR0A = _BV (TXC0);  // any old transmit now complete
  pinMode (MSPIM_SCK, OUTPUT);   // set XCK pin as output to enable master mode
  UCSR0C = _BV (UMSEL00) | _BV (UMSEL01);  // Master SPI mode
  UCSR0B = _BV (TXEN0);  // transmit enable
  // must be done last, see page 206
  UBRR0 = 0;  // 4 Mhz clock rate
  pinMode(2, OUTPUT); //Set D2 as output for Sync
  cli();
  //set timer0 interrupt at 15625Hz
  TCCR0A = 0;// set entire TCCR0A register to 0
  TCCR0B = 0;// same for TCCR0B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 15625hz increments
  OCR0A = 133;// = (16*10^6) / (15625*8) - 1 (must be <256)
  //PAL OCR0A = 134;// = (16*10^6) / (15625*8) - 1 (must be <256)
  
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS01 and CS00 bits for 9 prescaler
  TCCR0B |= (1 << CS01) | (0 << CS00);   
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);
  set_sleep_mode (SLEEP_MODE_IDLE);
  sei();
  for (int x=0; x <40; x++) {
    videomem[x]=32;
  }
  for (int x=40; x <1040; x++){
     videomem[x]=pgm_read_byte(gameMAP+(x&3)+(((x/40)&3)<<2));
  }


}

void TVdelay(unsigned int millisec) {
  unsigned long cnt=millisec*500L;
  for (unsigned long x=0; x < cnt; x++){
  asm("nop\n\t");
  }
}


void drawgrid(unsigned int hh,unsigned int ww) {
  for (int x=40; x <1040; x++){
     videomem[x]=gameMAP[((x+hh)&3)+((((x/40)+ww)&3)<<2)];
  }  
}  




void loop() {
if ((scanline>55)&&(scanline<263)) sleep_mode ();
drawgrid(h++,w--);
TVdelay(100);
}  
  
ISR(TIMER0_COMPA_vect){//timer0 interrupt 
  byte c=3;
  byte p=40;
  // NTSC if ((scanline>3)&&(scanline<40)||(scanline>239)) {
    if ((scanline>3)&&(scanline<56)||(scanline>263)) {
    UCSR0B = _BV(TXEN0);
    PORTD = 0; //Hsync
    UDR0 = 0x00; //Load first byte
    while (c--); {  
     // wait for transmitter ready
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {} 
    // send pixelbyte
    UDR0 = 0x00;
    }
    while ((UCSR0A & _BV (UDRE0)) == 0)
      {}  
    if (border==0) UCSR0B = 0;
    PORTD =4;       
  }

 if (scanline<4) {
    c=3;
    UCSR0B = _BV(TXEN0);
    PORTD = 0; //Vsync
    UDR0 = 0x00;
    while (c--); {
    while ((UCSR0A & _BV (UDRE0)) == 0)
      {} 
    UDR0 = 0x00;
    }
    PORTD =0;
    UCSR0B = 0;
    videoptr=0;
    row=0;    
  }  
  
  //NTSC if ((scanline>39)&&(scanline<240)) {
  if ((scanline>55)&&(scanline<263)) {
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");

    UCSR0B = _BV(TXEN0);
    PORTD = 0; //Hsync
    UDR0 = 0x00; //Load first byte
    c=3;
    while (c--) {
     // wait for transmitter ready
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {} 
    // send pixelbyte
    UDR0 = 0x00;
    }
  
    while ((UCSR0A & _BV (UDRE0)) == 0)
      {} 
     //send colorburst
     UDR0 = B1011010;
     PORTD =0;
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {}
 
    const register byte * linePtr = &charROM [ row & 0x07 ] [0];
    register byte * messagePtr = (byte *) & videomem [videoptr] ;
     PORTD =4;

    UCSR0B = _BV(TXEN0); 
    
    c=3;
    while (c--) {
    //for (byte x=0; x < 3; x++){
     // wait for transmitter ready
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {} 
     // send pixelbyte
     UDR0 = 0x00;
    }
    c=7;
    while (c--) {
     // wait for transmitter ready
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {} 
    // send pixelbyte
    UDR0 = 0;
    }
    
    UDR0 = pgm_read_byte (linePtr + 32);
  
    while (p--) {  
    UDR0 = pgm_read_byte (linePtr + (* messagePtr++));
    }
  
    while ((UCSR0A & _BV (UDRE0)) == 0)
      {}
    UDR0 = border; //Front porch
    
    if (border==0) UCSR0B = 0;
    
    row++;
    videoptr=(row>>3)*40;
  }
  
  scanline++;
  if (scanline>311) scanline=0; 
}

void pset(byte x, byte y ,byte color) {  //This makes a plot routine in 80x100 when using the block font
  unsigned int c_add=(x>>1)+(y>>2)*40;
  char block=(1<<(x&1))<<((y&3)*2);
  if (color!=0) {
   videomem[c_add+40]=videomem[c_add+40]|block;
  }
  else {
   videomem[c_add+40]=videomem[c_add+40]&(255-block);
  }  
}

This is the best one can do (thanks, Nick) using only C.

I have looked into Assembler but its tough.
Inline assembly in the Arduino IDE is junk, it kills creativity.

I need to find a way to include pure AVR assembler into my functions.

Hi, I get this error -
const unsigned char charROM [8] [128] PROGMEM = { 0x1C , ... , 0xFF }; //Contains the PETSCII Font for characters 0-127

Expected primary-expression before '...' token

Thanks. Dave.

cosmicfrog:
Hi, I get this error -
const unsigned char charROM [8] [128] PROGMEM = { 0x1C , ... , 0xFF }; //Contains the PETSCII Font for characters 0-127

Expected primary-expression before '...' token

Thanks. Dave.

Because I cant include the copyrighted CBM ROM Font.

That line needs to contain 1024 bytedefinitions.

janost:
I need to find a way to include pure AVR assembler into my functions.

You'd have to use the command line.

I think Atmel studio would work, too.

Both of those make it very difficult to distribute code to Arduino users.

Another way would be to write a little program to convert ASM to Arduino-inline-style for compiling in the Arduino IDE. If you click the "Use External Editor" box in preferences you can change the files on disk and it will reload them when you hit 'compile'.

fungus:
Another way would be to write a little program to convert ASM to Arduino-inline-style for compiling in the Arduino IDE. If you click the "Use External Editor" box in preferences you can change the files on disk and it will reload them when you hit 'compile'.

I have though of that.

I have an 8MHz pixelclock.

31500Hz Hsync is 8000000/31500=254pixels/line.
254pixels on the line makes 31 characters/line and perhaps 24-26visible.

VGA is doable.

This is not about doing some elevator or 3-axis milling machine.
This is cycle hunting.

And C++ or any other compiler is not going to work.

cosmicfrog:
Hi, I get this error -
const unsigned char charROM [8] [128] PROGMEM = { 0x1C , ... , 0xFF }; //Contains the PETSCII Font for characters 0-127

Expected primary-expression before '...' token

Thanks. Dave.

The format is simple.
Put 128 bytes for the first row in all your characters and then the next 128 rows and so on.

I really cant put any copyright material here even if it is as simple as a font.

janost:
I really cant put any copyright material here even if it is as simple as a font.

Lots of 8x8 fonts here: Tileset repository - Dwarf Fortress Wiki

Can I use avrasm or wavrasm with ATmega328 and 644 or must I have AVR Studio 3000.0?
Am I going to strike on some mnemonics it doesnt support?

Doing AVR assembler is really fun without C and the bloated Arduino IDE.
I have based my future designs on the ATtiny85, ATmega328 and ATmega644.

But I need to know that I havent painted myself into a corner?

The codename for this is now AVR turbo.
I tried with the Italians to no avail.

Now its an 644 with the same footprint as an Uno but with video and selfprogramming without a PC.
It still runs on a 328, you have the code but I have to move on.

I'm discussing with Atmel.