Being able to overlay text on video has a number of uses. I needed this ability while building a couple of different SMPTE timecode readers. While there were a selection of inexpensive OSD chips, for use in VHS and TV sets, that market seems to dried up lately. Luckily Maxim has just come out with new OSD chip.
This is a platform for experimenting with the MAX7456 OSD chip. It is a surface mount chip and is more easily used if attached to breakout board.
The shield wiring is pretty straight forward, +5, ground some .1 bypass caps, however you can get it all to fit the best. Please see the schematic.
Schematic
Parts you will need:
5 .1uf caps
2 75 ohm resistors
1 10K ohm resistor
1 100uf cap
1 22uf cap
1 27Mhx crystal
1 SparkFun 28 pin SSOP to DIP Adapter
1 NKC proto shield
1 28 DIP socket
The OSD accepts commands from the Arduino over the SPI bus. I did comment the code, more then I normally do anyway. So I hope is easy to follow. Once you get the board setup you can issue serial commands from the sketch serial monitor, or HyperTerm. You can also create a text file and download it into the overlay.
Part 1
#include <EEPROM.h> //Needed to access eeprom read/write functions
#define DATAOUT 11//MOSI
#define DATAIN 12//MISO
#define SPICLOCK 13//sck
#define MAX7456SELECT 10//ss
#define VSYNC 2// INT0
//MAX7456 opcodes
#define DMM_reg 0x04
#define DMAH_reg 0x05
#define DMAL_reg 0x06
#define DMDI_reg 0x07
#define VM0_reg 0x00
#define VM1_reg 0x01
//MAX7456 commands
#define CLEAR_display 0x04
#define CLEAR_display_vert 0x06
#define END_string 0xff
// with NTSC
#define ENABLE_display 0x08
#define ENABLE_display_vert 0x0c
#define MAX7456_reset 0x02
#define DISABLE_display 0x00
// with PAL
// all VM0_reg commands need bit 6 set
//#define ENABLE_display 0x48
//#define ENABLE_display_vert 0x4c
//#define MAX7456_reset 0x42
//#define DISABLE_display 0x40
#define WHITE_level_80 0x03
#define WHITE_level_90 0x02
#define WHITE_level_100 0x01
#define WHITE_level_120 0x00
// with NTSC
#define MAX_screen_size 390
#define MAX_screen_rows 13
// with PAL
//#define MAX_screen_size 480
//#define MAX_screen_rows 16
#define EEPROM_address_hi 510
#define EEPROM_address_low 511
#define EEPROM_sig_hi 'e'
#define EEPROM_sig_low 's'
volatile byte screen_buffer[MAX_screen_size];
volatile byte writeOK;
volatile byte valid_string;
volatile byte save_screen;
volatile int incomingByte;
volatile int count;
//
//##############################
//# 30 characters per line #
//# 13 lines per screen #
//# start'[' end ']' 390 chars #
//# add '~' if front of '[' to #
//# force write to eeprom #
//# '~[]' to zero out eeprom #
//##############################
//
//[
//
//
// THIS IS A TEST
//
// Arduino / MAX7456-OSD
//
// ABCDEFGHIJKLMNOPQRSTUVWXYZ
// 0123456789
//]
//
//////////////////////////////////////////////////////////////
void setup()
{
byte spi_junk, eeprom_junk;
int x;
Serial.begin(9600);
Serial.flush();
pinMode(MAX7456SELECT,OUTPUT);
digitalWrite(MAX7456SELECT,HIGH); //disable device
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(VSYNC, INPUT);
// SPCR = 01010000
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 rate (4 meg)
SPCR = (1<<SPE)|(1<<MSTR);
spi_junk=SPSR;
spi_junk=SPDR;
delay(250);
// force soft reset on Max7456
digitalWrite(MAX7456SELECT,LOW);
spi_transfer(VM0_reg);
spi_transfer(MAX7456_reset);
digitalWrite(MAX7456SELECT,HIGH);
delay(500);
// set all rows to same charactor white level, 90%
digitalWrite(MAX7456SELECT,LOW);
for (x = 0; x < MAX_screen_rows; x++)
{
spi_transfer(x + 0x10);
spi_transfer(WHITE_level_90);
}
// make sure the Max7456 is enabled
spi_transfer(VM0_reg);
spi_transfer(ENABLE_display);
digitalWrite(MAX7456SELECT,HIGH);
// clear the array
for (x = 0; x < MAX_screen_size; x++)
{
screen_buffer[x] = 0x00;
}
writeOK = false;
valid_string = false;
save_screen = false;
incomingByte = 0;
count = 0;
// check to see if we have a default screen stored in eeprom
eeprom_junk = EEPROM.read(EEPROM_address_hi);
if (eeprom_junk == EEPROM_sig_hi)
{
eeprom_junk = EEPROM.read(EEPROM_address_low);
if (eeprom_junk == EEPROM_sig_low)
{
for (x = 0; x < MAX_screen_size; x++)
{
screen_buffer[x] = EEPROM.read(x);
}
writeOK = true;
count = MAX_screen_size;
}
}
Serial.println("Ready for text file download");
Serial.println("");
delay(100);
}
Arduino with MAX7456 Shield
**
[this is a test] prints on line one upper left screen
**
[
this is a test] prints on the third line center of the screen
**
[] erases the video overlay
**
~[this is a test] writes the text to eeprom memory and displays it at boot time
**
~[] zeros out the eeprom
Output