I did get it working Ryan and as you have there was a lot of hair pulling.
I will see if I can dig up what I did, I can't seem to find it right now.
Code: Select all
[quote]
[color=#7E7E7E]/*[/color]
[color=#7E7E7E] MAX7456 OSD Display Test Program for Arduino[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E] Hobbytronics.co.uk[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E] Nov-2013[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E] Setup is for PAL but NTSC settings are shown in the program.[/color]
[color=#7E7E7E] Displays text on the screen in to following format (30 chars x 16 lines)[/color]
[color=#7E7E7E] The program is completely self contained and requires no library files[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E] '------------------------------`[/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | Hobbytronics.co.uk OSD |[/color]
[color=#7E7E7E] | Test |[/color]
[color=#7E7E7E] | | [/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | | [/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | | [/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | |[/color]
[color=#7E7E7E] | #### 00:00:00 | <- Clock counts up from boot [/color]
[color=#7E7E7E] | | [/color]
[color=#7E7E7E] '------------------------------`[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E]*/[/color]
[color=#7E7E7E]// SPI pins[/color]
#define DATAOUT 11 [color=#7E7E7E]//MOSI[/color]
#define DATAIN 12 [color=#7E7E7E]//MISO [/color]
#define SPICLOCK 13 [color=#7E7E7E]//sck[/color]
#define MAX7456SELECT 10 [color=#7E7E7E]//ss[/color]
[color=#7E7E7E]//MAX7456 opcodes[/color]
#define MAX_DMM_REG 0x04
#define MAX_DMAH_REG 0x05
#define MAX_DMAL_REG 0x06
#define MAX_DMDI_REG 0x07
#define MAX_VM0_REG 0x00
#define MAX_VM1_REG 0x01
#define MAX_CMAH_REG 0x09
#define MAX_CMM_REG 0x08
[color=#7E7E7E]//MAX7456 commands[/color]
#define MAX_CLEAR_DISPLAY 0x04
#define MAX_CLEAR_DISPLAY_VERT 0x06
#define MAX_END_STRING 0xFF
[color=#7E7E7E]// PAL[/color]
[color=#7E7E7E]// all VM0_reg commands need bit 6 set[/color]
#define MAX_ENABLE_DISPLAY 0x48
#define MAX_ENABLE_DISPLAY_VERT 0x4C
#define MAX_RESET 0x42
#define MAX_DISABLE_DISPLAY 0x40
#define MAX_SCREEN_SIZE 480
#define MAX_SCREEN_WIDTH 30
#define MAX_SCREEN_ROWS 16
[color=#7E7E7E]// NTSC[/color]
[color=#7E7E7E]//#define MAX_ENABLE_DISPLAY 0x08[/color]
[color=#7E7E7E]//#define MAX_ENABLE_DISPLAY_VERT 0x0C[/color]
[color=#7E7E7E]//#define MAX_RESET 0x02[/color]
[color=#7E7E7E]//#define MAX_DISABLE_DISPLAY 0x00[/color]
[color=#7E7E7E]//#define MAX_SCREEN_SIZE 390[/color]
[color=#7E7E7E]//#define MAX_SCREEN_WIDTH 30[/color]
[color=#7E7E7E]//#define MAX_SCREEN_ROWS 13[/color]
volatile [color=#CC6600]byte[/color] osd_buffer[MAX_SCREEN_SIZE+1];
volatile [color=#CC6600]byte[/color] osd_writeOK;
[color=#7E7E7E]// Variables for counting time and displaying bar[/color]
#define BAR_LENGTH 15
[color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] counter=0;
[color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] currentTime;
[color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] cloopTime;
[color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] bloopTime;
[color=#CC6600]unsigned[/color] [color=#CC6600]char[/color] barsize=0;
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color]()
{
[color=#CC6600]byte[/color] spi_junk;
[color=#CC6600]int[/color] x;
[color=#CC6600]pinMode[/color](MAX7456SELECT,[color=#006699]OUTPUT[/color]);
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]HIGH[/color]); [color=#7E7E7E]//disable device[/color]
[color=#CC6600]pinMode[/color](DATAOUT, [color=#006699]OUTPUT[/color]);
[color=#CC6600]pinMode[/color](DATAIN, [color=#006699]INPUT[/color]);
[color=#CC6600]pinMode[/color](SPICLOCK,[color=#006699]OUTPUT[/color]);
[color=#7E7E7E]// SPCR = 01010000[/color]
[color=#7E7E7E]//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,[/color]
[color=#7E7E7E]//sample on leading edge of clk,system clock/4 rate (4 meg)[/color]
SPCR = (1<<SPE)|(1<<MSTR);
spi_junk=SPSR;
spi_junk=SPDR;
[color=#7E7E7E]// force soft reset on Max7456[/color]
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]LOW[/color]);
spi_send_byte(MAX_VM0_REG, MAX_RESET);
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]HIGH[/color]);
[color=#CC6600]delay[/color](200);
[color=#7E7E7E]// osd_create_block_char(); // Run this once only as data is stored in eeprom[/color]
[color=#7E7E7E]// make sure the Max7456 is enabled[/color]
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]LOW[/color]);
spi_send_byte(MAX_VM0_REG, MAX_ENABLE_DISPLAY);
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]HIGH[/color]);
[color=#7E7E7E]// clear the data array[/color]
[color=#CC6600]for[/color] (x = 0; x <= MAX_SCREEN_SIZE; x++)
{
osd_buffer[x] = 0x00;
}
osd_writeOK = [color=#CC6600]false[/color];
[color=#7E7E7E]// Setup default data to display[/color]
[color=#7E7E7E]// 30 chars x 16 lines for PAL[/color]
[color=#7E7E7E]// Line 1 = bytes 1-30, Line2 = bytes 31-60 etc up to 480[/color]
osd_print(2,2,[color=#006699]"Well Hi There"[/color]);
osd_print(2,25,[color=#006699]"OSD"[/color]);
osd_print(3,24,[color=#006699]"Test"[/color]);
currentTime = [color=#CC6600]millis[/color]();
cloopTime = currentTime;
bloopTime = currentTime;
osd_writeOK = [color=#CC6600]true[/color];
osd_clear_screen();
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color]()
{
[color=#CC6600]int[/color] i;
[color=#CC6600]unsigned[/color] [color=#CC6600]char[/color] hours, mins, secs;
currentTime = [color=#CC6600]millis[/color]();
[color=#CC6600]if[/color](currentTime >= (cloopTime + 1000))
{
[color=#7E7E7E]// This loop runs once a second and display the time [/color]
[color=#7E7E7E]// in the bottom right corner[/color]
[color=#7E7E7E]// Increment counter every second and display time since bootup[/color]
cloopTime = currentTime; [color=#7E7E7E]// Updates cloopTime [/color]
hours = counter / 3600;
mins = (counter % 3600) / 60;
secs = counter % 60;
[color=#CC6600]char[/color] ascii_str[10];
sprintf(ascii_str,[color=#006699]"%0.2d:%0.2d:%0.2d"[/color],hours,mins,secs);
[color=#CC6600]for[/color](i=0;i<8;i++)
{
osd_buffer[440+i] = convert_ascii(ascii_str[i]);
}
counter++;
[color=#7E7E7E]// Update line 15 only[/color]
osd_write_line(15);
}
[color=#CC6600]if[/color](currentTime >= (bloopTime + 200))
{
[color=#7E7E7E]// This loop runs every 200mS and simply uses the block character[/color]
[color=#7E7E7E]// we created to display a bar across the screen[/color]
[color=#7E7E7E]// Increment bar display[/color]
[color=#7E7E7E]// Bar displayed at line 15 col 2 = (14*30)+2[/color]
bloopTime = currentTime; [color=#7E7E7E]// Updates cloopTime [/color]
[color=#CC6600]for[/color](i=0;i<BAR_LENGTH;i++)
{
[color=#CC6600]if[/color](i<barsize) osd_buffer[(14*30)+2+i] = 0xC0;
[color=#CC6600]else[/color] osd_buffer[(14*30)+2+i] = convert_ascii([color=#006699]' '[/color]);;
}
barsize++;
[color=#CC6600]if[/color](barsize>=BAR_LENGTH) barsize=0;
[color=#7E7E7E]// Update line 15[/color]
osd_write_line(15);
}
[color=#CC6600]if[/color] (osd_writeOK)
{
[color=#7E7E7E]// if osd_writeOK is set then rewrite full screen[/color]
osd_writeOK = [color=#CC6600]false[/color];
osd_write_screen();
}
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#7E7E7E]// Print a string to position row/col[/color]
[color=#7E7E7E]// Places the text into the correct location in the display buffer[/color]
[color=#CC6600]void[/color] osd_print([color=#CC6600]unsigned[/color] [color=#CC6600]int[/color] osd_line, [color=#CC6600]unsigned[/color] [color=#CC6600]int[/color] osd_col, [color=#CC6600]const[/color] [color=#CC6600]String[/color] &s){
[color=#CC6600]for[/color] ([color=#CC6600]int[/color] i = 0; i < s.length(); i++) {
osd_buffer[((osd_line-1)*MAX_SCREEN_WIDTH)+osd_col+i] = convert_ascii(([color=#CC6600]byte[/color]) s[i]);
}
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]byte[/color] spi_send_byte([color=#CC6600]byte[/color] address, volatile [color=#CC6600]byte[/color] data)
{
SPDR = address; [color=#7E7E7E]// Start the transmission[/color]
[color=#CC6600]while[/color] (!(SPSR & (1<<SPIF))) {}; [color=#7E7E7E]// Wait the end of the transmission [/color]
SPDR = data; [color=#7E7E7E]// Start the transmission[/color]
[color=#CC6600]while[/color] (!(SPSR & (1<<SPIF))) {}; [color=#7E7E7E]// Wait the end of the transmission[/color]
[color=#CC6600]return[/color] SPDR; [color=#7E7E7E]// return the received byte[/color]
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]byte[/color] convert_ascii ([color=#CC6600]int[/color] character)
{
[color=#7E7E7E]// for some reason the MAX7456 does not follow ascii letter[/color]
[color=#7E7E7E]// placement, so you have to have this odd lookup table[/color]
[color=#CC6600]byte[/color] lookup_char;
[color=#CC6600]if[/color] (character == 32)
lookup_char = 0x00; [color=#7E7E7E]// blank space[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 48)
lookup_char = 0x0a; [color=#7E7E7E]// 0[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] ((character > 48) && (character < 58))
lookup_char = (character - 48); [color=#7E7E7E]// 1-9[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] ((character > 64) && (character < 90))
lookup_char = (character - 54); [color=#7E7E7E]// A-Z[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] ((character > 96) && (character < 123))
lookup_char = (character - 60); [color=#7E7E7E]// a-z[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 34)
lookup_char = 0x48; [color=#7E7E7E]// "[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 39)
lookup_char = 0x46; [color=#7E7E7E]// '[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 40)
lookup_char = 0x3f; [color=#7E7E7E]// ([/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 41)
lookup_char = 0x40; [color=#7E7E7E]// )[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 44)
lookup_char = 0x45; [color=#7E7E7E]// ,[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 45)
lookup_char = 0x49; [color=#7E7E7E]// -[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 46)
lookup_char = 0x41; [color=#7E7E7E]// .[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 47)
lookup_char = 0x47; [color=#7E7E7E]// /[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 58)
lookup_char = 0x44; [color=#7E7E7E]// :[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 59)
lookup_char = 0x43; [color=#7E7E7E]// ;[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 60)
lookup_char = 0x4a; [color=#7E7E7E]// <[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 62)
lookup_char = 0x4b; [color=#7E7E7E]// >[/color]
[color=#CC6600]else[/color] [color=#CC6600]if[/color] (character == 63)
lookup_char = 0x42; [color=#7E7E7E]// ?[/color]
[color=#CC6600]else[/color]
lookup_char = 0x00; [color=#7E7E7E]// out of range, blank space[/color]
[color=#CC6600]return[/color] (lookup_char);
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]void[/color] osd_create_block_char()
{
[color=#7E7E7E]// Create a solid White block char at character location 0xC0[/color]
[color=#7E7E7E]// This function only need to be called once as the character[/color]
[color=#7E7E7E]// is stored in the MAX7456 eeprom[/color]
[color=#7E7E7E]// Check out https://sites.google.com/site/qeewiki/projects/q-s-max7456-img-gen/QMIG_v1.10.rar?attredirects=0[/color]
[color=#7E7E7E]// for a free character creation tool for the MAX7456[/color]
[color=#CC6600]unsigned[/color] [color=#CC6600]char[/color] i;
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]LOW[/color]);
[color=#7E7E7E]// disable display [/color]
spi_send_byte(MAX_VM0_REG, MAX_DISABLE_DISPLAY);
[color=#7E7E7E]// Create Character at 0xC0 - See MAX7456 datasheet for character locations[/color]
spi_send_byte(MAX_CMAH_REG, 0xC0); [color=#7E7E7E]// Write to address 0xC0[/color]
[color=#7E7E7E]// We need to send 54 bytes of data to store the character. Our 'block' character[/color]
[color=#7E7E7E]// is all the same, so we can loop here[/color]
[color=#CC6600]for[/color](i=0;i<54;i++)
{
spi_send_byte(0x0A, i);
spi_send_byte(0x0B, 0b10101010);
}
spi_send_byte(MAX_CMM_REG,0xA0);
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]HIGH[/color]);
[color=#CC6600]delay[/color](200);
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]void[/color] osd_clear_screen()
{
[color=#7E7E7E]// clear the screen[/color]
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]LOW[/color]);
spi_send_byte(MAX_DMM_REG,MAX_CLEAR_DISPLAY);
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]HIGH[/color]);
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]void[/color] osd_write_line([color=#CC6600]unsigned[/color] [color=#CC6600]int[/color] linenum)
{
[color=#7E7E7E]// Instead of redrawing the whole screen, we may only need to [/color]
[color=#7E7E7E]// change one or more lines. [/color]
[color=#CC6600]unsigned[/color] [color=#CC6600]int[/color] x, local_count, start_address;
[color=#CC6600]byte[/color] char_address_hi, char_address_lo;
[color=#CC6600]byte[/color] osd_char;
local_count = MAX_SCREEN_WIDTH;
start_address = (linenum-1) * MAX_SCREEN_WIDTH;
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]LOW[/color]);
spi_send_byte(MAX_DMM_REG,0x01); [color=#7E7E7E]//16 bit trans w/o background[/color]
spi_send_byte(MAX_DMAH_REG,([color=#CC6600]unsigned[/color] [color=#CC6600]char[/color])(start_address>>8)); [color=#7E7E7E]// set start address high[/color]
spi_send_byte(MAX_DMAL_REG,([color=#CC6600]unsigned[/color] [color=#CC6600]char[/color])(start_address)); [color=#7E7E7E]// set start address low[/color]
x = 0;
[color=#CC6600]while[/color](local_count) [color=#7E7E7E]// write out full screen[/color]
{
osd_char = osd_buffer[((linenum-1)*MAX_SCREEN_WIDTH)+x];
spi_send_byte(MAX_DMDI_REG,osd_char);
x++;
local_count--;
}
spi_send_byte(MAX_DMDI_REG,MAX_END_STRING);
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]HIGH[/color]);
}
[color=#7E7E7E]//////////////////////////////////////////////////////////////[/color]
[color=#CC6600]void[/color] osd_write_screen()
{
[color=#7E7E7E]// Change the data for the whole screen[/color]
[color=#CC6600]int[/color] x, local_count;
[color=#CC6600]byte[/color] char_address_hi, char_address_lo;
[color=#CC6600]byte[/color] osd_char;
local_count = MAX_SCREEN_SIZE;
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]LOW[/color]);
spi_send_byte(MAX_DMM_REG,0x01); [color=#7E7E7E]//16 bit trans w/o background[/color]
spi_send_byte(MAX_DMAH_REG,0x00); [color=#7E7E7E]// set start address high[/color]
spi_send_byte(MAX_DMAL_REG,0x00); [color=#7E7E7E]// set start address low[/color]
x = 0;
[color=#CC6600]while[/color](local_count) [color=#7E7E7E]// write out full screen[/color]
{
osd_char = osd_buffer[x];
spi_send_byte(MAX_DMDI_REG,osd_char);
x++;
local_count--;
}
spi_send_byte(MAX_DMDI_REG,MAX_END_STRING);
[color=#CC6600]digitalWrite[/color](MAX7456SELECT,[color=#006699]HIGH[/color]);
}
[/quote]