Things used in this project

Hardware components:
Atmel Atmega 1284P
×1

Code

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

#define PS2_KC_BKSP    0x80
#define PS2_KC_UP      0x81
#define PS2_KC_DOWN    0x82
#define PS2_KC_LEFT    0x83
#define PS2_KC_RIGHT   0x84
#define PS2_KC_PGDN    0x85
#define PS2_KC_PGUP    0x86
#define PS2_KC_END     0x87
#define PS2_KC_HOME    0x88
#define PS2_KC_INS     0x89
#define PS2_KC_DEL     0x8A
#define PS2_KC_ESC     0x8B
#define PS2_KC_CLON    0x8C // caps_lock on
#define PS2_KC_CLOFF   0x8D // caps_lock off

const byte MSPIM_SCK = 0;

byte PROGMEM charROM [1024] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E,
0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E,
0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00,
0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00,
0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x7C, 0x38, 0x7C,
0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C,
0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,
0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF,
0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00,
0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF,
0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78,
0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0,
0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0,
0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99,
0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00,
0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00,
0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18,
0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00,
0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0xCC, 0x78,
0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00,
0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF,
0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00,
0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00,
0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00,
0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00,
0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00,
0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
0x30, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x30, 0x00,
0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00,
0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
0x00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
0x7C, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0x7C, 0x00,
0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00,
0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00,
0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00,
0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00,
0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00,
0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00,
0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00,
0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00,
0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00,
0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
0x78, 0xCC, 0x0C, 0x18, 0x30, 0x00, 0x30, 0x00,
0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x78, 0x00,
0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00,
0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00,
0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00,
0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00,
0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00,
0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00,
0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3E, 0x00,
0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00,
0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00,
0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00,
0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00,
0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00,
0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00,
0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
0x78, 0xCC, 0xCC, 0xCC, 0xDC, 0x78, 0x1C, 0x00,
0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00,
0x78, 0xCC, 0xE0, 0x70, 0x1C, 0xCC, 0x78, 0x00,
0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00,
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00,
0xC6, 0xC6, 0x6C, 0x38, 0x38, 0x6C, 0xC6, 0x00,
0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00,
0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00,
0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00,
0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00,
0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00,
0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
0x38, 0x6C, 0x60, 0xF0, 0x60, 0x60, 0xF0, 0x00,
0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00,
0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0x0C, 0x00, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78,
0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00,
0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xC6, 0x00,
0x00, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0,
0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0xF0, 0x00,
0x00, 0x00, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x00,
0x10, 0x30, 0x7C, 0x30, 0x30, 0x34, 0x18, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xFE, 0x6C, 0x00,
0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00,
0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00,
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00,
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00,
};


unsigned int scanline=0;
unsigned int videoptr=0;
volatile byte VBE=0;
byte xpos=0;
byte ypos=0;
byte txtback=0;
byte txtfore=255;

boolean ps2Keyboard_shift;     // indicates shift key is pressed
boolean ps2Keyboard_ctrl;      // indicates the ctrl key is pressed
boolean ps2Keyboard_alt;       // indicates the alt key is pressed
boolean ps2Keyboard_extend;    // remembers a keyboard extended char received
boolean ps2Keyboard_release;   // distinguishes key presses from releases
boolean ps2Keyboard_caps_lock; // remembers shift lock has been pressed

char videomem[8000];

void setup() {
  
  //Setup for NTSC with 14.318MHz Fcpu clock
  UBRR0 = 0; // must be zero before enabling the transmitter
  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;  // 7.16MHz pixel clock
  pinMode(15, OUTPUT); //Set PD7 as output for Sync
  pinMode(8, OUTPUT); //Set PD0 as output for video
  cli();
  //set timer0 interrupt at 15699Hz
  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 15699hz increments
  OCR0A = 113;// = (16*10^6) / (15699*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();
  
  //------------ PS/2 Keyboard setup ----------------------------
  
  // Enable receiver
  UCSR1B = 16 | 8;
  /* Set frame format: 1data, 1parity, 1stop bit */
  UCSR1C = 64 | 6;
  
  ps2Keyboard_shift         = false;
  ps2Keyboard_ctrl          = false;
  ps2Keyboard_alt           = false;
  ps2Keyboard_extend        = false;
  ps2Keyboard_release       = false;
  ps2Keyboard_caps_lock     = false;
  
  //----------------------------------------------------------------------------------------------
  
  for (int x=0; x <8000; x++){
     videomem[x]=B01010101;
  }
 
  


}

void TVdelay(unsigned int millisec) {
  unsigned long cnt=millisec*100L;
  for (unsigned long x=0; x < cnt; x++){  
  while (VBE==1) sleep_cpu();
  }
}

  




void loop() {
 TVdelay(100); //Dont use delay() to make delays, but TVdelay(millis) to do delays, there is no delay function.

 printstring("\x80\x87\fBambino BIOS v1.01\n\n\n"); //clear the screen with BGcolor black and FGcolor white.
 printstring("VideoBlaster v1.05\n");
  
  while(-1) {
    while (VBE==1) sleep_cpu();
    
    //If VBE=1 the CPU have to sleep for the video to be smooth.
    
    //put anything you like in this loop but make sure it returns before the next frame is painted.

    // Use printstring(string) to write an entier string to chrout.
    // Use chrout(char ascii) to write a singel char to the terminal screen. chr x80 - x87 sets BG and FG attributes.
    // Use chrin() to read a singel char from the keyboard.
    // use pset(x,y) to set a single dot on the 320x200 screen.
    // Use point(x,y,c) to set a color dot on the 320x200 screen (c is color 0-3).
    // All the other functions are used by the Bambino BIOS and wont remain the same in the future.
    // Dont touch the variables scanline and videoptr, they are not volatile on purpose because of speed reasons.

    
  }

}  
  
ISR(TIMER0_COMPA_vect){//timer0 interrupt
  asm("nop\n");
  byte p=40;
  UCSR0C = 192;
  UCSR0B = _BV(TXEN0);
  PORTD = 0;
      
  if ((scanline>2)&&(scanline<40)||(scanline>239)) {
    UCSR0B = 0;
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");  // Dont touch any of these NOPs
    asm("nop\n");  // They are all here for timing.
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");   
    PORTD =128;
    VBE=0;    
  }

 if (scanline<3) {
    UCSR0B = 0;
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");   
    PORTD =0;

    videoptr=0;   
  }  
  
  if ((scanline>39)&&(scanline<240)) {

    UDR0 = 0x00; //Load first byte
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    asm("nop\n");
    //asm("nop\n");   

    PORTD =128;
    VBE=1;
    //asm("nop\n");
    //asm("nop\n");


     //Color burst
     
     UDR0 = B00001010;

     UDR0 = B10101010;
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {}

     UDR0 = B10101000;
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {}
     UDR0 = B00000000;
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {}
      

     
     //Back porch 
     UCSR0C = 193; //This is the phasechange to the colorburst. If you put 192 here instead, you will get blue/green as colors.
     UDR0 = B00000000;
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {}
     UDR0 = B00000000;
     
     while ((UCSR0A & _BV (UDRE0)) == 0)
      {}
     
     
     
      
     //UDR0 = B00000000;
  
    
     //UCSR0C = 193;
     UDR0 = 0;

   

    
     
    
    while (p--) {
    while ((UCSR0A & _BV (UDRE0)) == 0)
     {}  
    UDR0 = videomem[videoptr++];
    }

  }
  UCSR0B = 0;
  scanline++;

  if (scanline>261) scanline=0;
   
}

void pset(unsigned int x,unsigned y) {
  unsigned int pixelbyte=videoptr+(y*40)+(x>>3);
  videomem[pixelbyte]=videomem[pixelbyte] | (128>>(x&7));
}

void point(unsigned int x,unsigned y,byte color) {
  x=x&510;
  color=((color<<6)&192)>>(x&7);
  unsigned int pixelbyte=videoptr+(y*40)+(x>>3);
  byte mask=255-(192>>(x&7));
  videomem[pixelbyte]=videomem[pixelbyte] & mask | color;
}

void screenclr(byte bgcolor) {
  bgcolor=bgcolor&3;
  bgcolor=bgcolor | (bgcolor<<2);
  bgcolor=bgcolor | (bgcolor<<4);
  for (int x=0; x <8000; x++){ 
   videomem[x]=bgcolor;
  }
  xpos=0;
  ypos=0;
}

void drawchar(byte x,byte y,byte ascii) {
 if ((x<40)&&(y<25)) { 
  for (byte i=0; i < 8; i++) {
   byte mask=(255-pgm_read_byte(&charROM[(ascii*8)+i]))&txtback;
   videomem[(y*320)+x+(i*40)]=(pgm_read_byte(&charROM[(ascii*8)+i])&txtfore)|mask;
  }  
 } 
}

void chrout(char ascii) {
  switch (ascii) {
    case 13:
      xpos=0;
      ypos++;
      if (ypos>24) {
       scrollscr(); 
       xpos=0;
       ypos=24;
      }
      break;
    case 10:
      xpos=0;
      ypos++;
      if (ypos>24) {
       scrollscr(); 
       xpos=0;
       ypos=24;
      }
      break;
    case 12:
      screenclr(txtback&3);
      xpos=0;
      ypos=0;
      break;      
    case 0x80:
      settxtBGcolor(0);
      break;
    case 0x81:
      settxtBGcolor(1);
      break;
    case 0x82:
      settxtBGcolor(2);
      break;
    case 0x83:
      settxtBGcolor(3);
      break;
    case 0x84:
      settxtFGcolor(0);
      break;
    case 0x85:
      settxtFGcolor(1);
      break;
    case 0x86:
      settxtFGcolor(2);
      break;
    case 0x87:
      settxtFGcolor(3);
      break;      
    default: 
    drawchar(xpos,ypos,ascii);
    xpos++;
    if (xpos>39) {
     xpos=0;
     ypos++;
     if (ypos>24) {
      scrollscr(); 
      xpos=0;
      ypos=24;
     }
    }
   }  
}

void scrollscr() {
  for (unsigned int i=320; i < 8000; i++) {
    videomem[i-320]=videomem[i];
  }
  for (unsigned int i=7680; i < 8000; i++) {
    videomem[i]=0;
  }  
}

void settxtBGcolor(byte color) {
  color=color&3;
  color=color | (color<<2);
  color=color | (color<<4);
  txtback=color;
}

void settxtFGcolor(byte color) {
  color=color&3;
  color=color | (color<<2);
  color=color | (color<<4);
  txtfore=color;
}

void printstring(char string[]) {
 byte i=0;
 while(string[i]) {
   chrout(string[i++]);
 }  
 
}

char chrin() {
 byte result=0;
 byte realkey=0; 
 if (UCSR1A&128) {
  result=UDR1;

    switch (result) {
    case 0xF0: { // key release char
      ps2Keyboard_release = true;
      ps2Keyboard_extend = false;
      result=0;
      break;
    }
    case 0xFA: { // command acknowlegde byte
      
      break;
    }
    case 0xE0: { // extended char set
      ps2Keyboard_extend = true;
      break;
    }
    case 0x12:   // left shift
    case 0x59: { // right shift
      ps2Keyboard_shift = ps2Keyboard_release? false : true;
      ps2Keyboard_release = false;
      result=0;
      break;
    }
    case 0x11: { // alt key (right alt is extended 0x11)
      ps2Keyboard_alt = ps2Keyboard_release? false : true;
      ps2Keyboard_release = false;
      result=0;
      break;
    }
    case 0x14: { // ctrl key (right ctrl is extended 0x14)
      ps2Keyboard_ctrl = ps2Keyboard_release? false : true;
      ps2Keyboard_release = false;
      break;
    }
    case 0x58: { // caps lock key
      if (!ps2Keyboard_release) {
	ps2Keyboard_caps_lock = ps2Keyboard_caps_lock? false : true;
      }
      else {
	ps2Keyboard_release = false;
      }
      result=0;
      break;
    }
    default: { // a real key
      if (ps2Keyboard_release) { // although ignore if its just released
        ps2Keyboard_release = false;
        result=0;
      }
      else { // real keys go into CharBuffer
        realkey=result;
      }
    }
    }

 switch (result) {
 
  case 0x1C: result = 'a'; break;
  case 0x32: result = 'b'; break;
  case 0x21: result = 'c'; break;
  case 0x23: result = 'd'; break;
  case 0x24: result = 'e'; break;
  case 0x2B: result = 'f'; break;
  case 0x34: result = 'g'; break;
  case 0x33: result = 'h'; break;
  case 0x43: result = 'i'; break;
  case 0x3B: result = 'j'; break;
  case 0x42: result = 'k'; break;
  case 0x4B: result = 'l'; break;
  case 0x3A: result = 'm'; break;
  case 0x31: result = 'n'; break;
  case 0x44: result = 'o'; break;
  case 0x4D: result = 'p'; break;
  case 0x15: result = 'q'; break;
  case 0x2D: result = 'r'; break;
  case 0x1B: result = 's'; break;
  case 0x2C: result = 't'; break;
  case 0x3C: result = 'u'; break;
  case 0x2A: result = 'v'; break;
  case 0x1D: result = 'w'; break;
  case 0x22: result = 'x'; break;
  case 0x35: result = 'y'; break;
  case 0x1A: result = 'z'; break;

    // note that caps lock only used on a-z
  case 0x41: result = ps2Keyboard_shift? ';' : ','; break;
  case 0x49: result = ps2Keyboard_shift? ':' : '.'; break;
  case 0x4A: result = ps2Keyboard_shift? '?' : '/'; break;
  case 0x54: result = ps2Keyboard_shift? '{' : '['; break;
  case 0x5B: result = ps2Keyboard_shift? '}' : ']'; break;
  case 0x4E: result = ps2Keyboard_shift? '_' : '-'; break;
  case 0x55: result = ps2Keyboard_shift? '+' : '='; break;
  case 0x29: result = ' '; break;

  case 0x45: result = ps2Keyboard_shift? '=' : '0'; break;
  case 0x16: result = ps2Keyboard_shift? '!' : '1'; break;
  case 0x1E: result = ps2Keyboard_shift? 0x22 : '2'; break;
  case 0x26: result = ps2Keyboard_shift? '#' : '3'; break;
  case 0x25: result = ps2Keyboard_shift? '$' : '4'; break;
  case 0x2E: result = ps2Keyboard_shift? '%' : '5'; break;
  case 0x36: result = ps2Keyboard_shift? '&' : '6'; break;
  case 0x3D: result = ps2Keyboard_shift? '/' : '7'; break;
  case 0x3E: result = ps2Keyboard_shift? '(' : '8'; break;
  case 0x46: result = ps2Keyboard_shift? ')' : '9'; break;

  case 0x0D: result = '\t'; break;
  case 0x5A: result = 13; break;
  case 0x66: result = PS2_KC_BKSP;  break;
  case 0x69: result = ps2Keyboard_extend? PS2_KC_END   : '1'; break;
  case 0x6B: result = ps2Keyboard_extend? PS2_KC_LEFT  : '4'; break;
  case 0x6C: result = ps2Keyboard_extend? PS2_KC_HOME  : '7'; break;
  case 0x70: result = ps2Keyboard_extend? PS2_KC_INS   : '0'; break;
  case 0x71: result = ps2Keyboard_extend? PS2_KC_DEL   : '.'; break;
  case 0x72: result = ps2Keyboard_extend? PS2_KC_DOWN  : '2'; break;
  case 0x73: result = '5'; break;
  case 0x74: result = ps2Keyboard_extend? PS2_KC_RIGHT : '6'; break;
  case 0x75: result = ps2Keyboard_extend? PS2_KC_UP    : '8'; break;
  case 0x76: result = PS2_KC_ESC; break;
  case 0x79: result = '+'; break;
  case 0x7A: result = ps2Keyboard_extend? PS2_KC_PGDN  : '3'; break;
  case 0x7B: result = '-'; break;
  case 0x7C: result = '*'; break;
  case 0x7D: result = ps2Keyboard_extend? PS2_KC_PGUP  : '9'; break;

  } // end switch(result)
 }
   if (((result>='a') && (result<='z')) &&
      ((ps2Keyboard_shift && !ps2Keyboard_caps_lock) ||
       (!ps2Keyboard_shift && ps2Keyboard_caps_lock))) {
    result = result + ('A'-'a');
   }
 
  return result;
}

Credits

Janne
Jan Ostman

I'm an embeddeds wizard that can turn any pile of electronic junk to something really great. Mc Gyver style.

Replications

Did you replicate this project? Share it!

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

OLED on the Cheap!
  • 8,422
  • 37

Full instructions

128x64 OLED displays are available for under $5 USD and are easily interfaced to Arduino AVR and STM32 boards such as the Maple Mini clone.

ATtiny85-powered programmable intervalometer for Canon DSLR
  • 2,135
  • 16

Full instructions

Some Canon DSLRs don't have a built-in intervalometer. Simple solution - make one yourself!

Infrared Dedicated Decoder
  • 9,026
  • 9

Full instructions

Offload IR decode to a dedicated Attiny85 for efficiency, simplicity, and reduced resources on the main microcontroller.

FastLED
  • 2,518
  • 16

Full instructions

FastLED is a fast, efficient, easy-to-use Arduino(ish) library for programming LED strips and pixels like WS2801, WS2811, LPD8806 and more!

DSP on 8-bit microcontroller
  • 5,044
  • 12

Full instructions

For 8-bit MCU, optimization of filtering requires tradeoffs between accuracy, ease of programming. and speed.

AVR Firmware Duplicator
  • 11,901
  • 12

Full instructions

Windows script to make an exact copy of AVR (Arduino) firmware including the bootloader, user program, fuses and EEPROM.

ProjectsCommunitiesContestsLiveAppsBetaFree StoreBlogAdd projectSign up / Login
Respect project
Feedback