MAX7456 OSD video overlay code

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
User avatar
madinventions
Posts: 11
Joined: Tue Jan 06, 2009 9:13 pm
Location: Suffolk, England

MAX7456 OSD video overlay code

Post by madinventions » Mon Jun 29, 2009 3:02 pm

I've been playing around with the MAX7456 OSD video IC in a project to overlay GPS data onto a video stream, and I'd like to share the beta code with other users. With a bit of refinement maybe this could be made into a fully functional module?

So far it allows you to write strings of text to any position on the screen. Missing functions at the moment include custom-generated characters, and reading data back from the display data although these aren't essential for me at the moment.

So, hopefully someone will find this code useful? Let me know if you do.

Module code

Code: Select all

{
*****************************************************************************
*  Name    : MAX7456.BAS                                                   *
*  Author  : Ed Williamson-Brown                                            *
*  Notice  : Copyright (c) 2009 MadInventions                               *
*          : All Rights Reserved                                            *
*  Date    : 25/06/2009                                                     *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
Module MAX7456
Include "string.bas"
Include "SPI.bas" 

Const MAXREG_VM0 = $0
Const MAXREG_VM1 = $1
Const MAXREG_HOS = $2
Const MAXREG_VOS = $3
Const MAXREG_DMM = $4
Const MAXREG_DMAH =$5
Const MAXREG_DMAL = $6
Const MAXREG_DMDI = $7
Const MAXREG_CMM = $8
Const MAXREG_CMAH = $9
Const MAXREG_CMAL = $A
Const MAXREG_CMDI = $B
Const MAXREG_OSDM = $C
Const MAXREG_RB0 = $10
Const MAXREG_RB1 = $11
Const MAXREG_RB2 = $12
Const MAXREG_RB3 = $13
Const MAXREG_RB4 = $14
Const MAXREG_RB5 = $15
Const MAXREG_RB6 = $16
Const MAXREG_RB7 = $17
Const MAXREG_RB8 = $18
Const MAXREG_RB9 = $19
Const MAXREG_RB10 = $1A
Const MAXREG_RB11 = $1B
Const MAXREG_RB12 = $1C
Const MAXREG_RB13 = $1D
Const MAXREG_RB14 = $1E
Const MAXREG_RB15 = $1F
Const MAXREG_OSDBL = $6C

//Read only registers
Const MAXREG_STAT = $A0
Const MAXREG_DMDO = $B0
Const MAXREG_CMDO = $C0

Const CharTable() As Char = 
(
    " ","1","2","3","4","5","6","7","8","9","0",
    "A","B","C","D","E","F","G","H","I","J","K",
    "L","M","N","O","P","Q","R","S","T","U","V",
    "W","X","Y","Z","a","b","c","d","e","f","g",
    "h","i","j","k","l","m","n","o","p","q","r",
    "s","t","u","v","w","x","y","z","(",")",".",
    "?",";",":",",",$27,"/","'","-","<",">","@" )

Const char_to_char_code_table() As Byte =
(
    $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,
    $0B,$0C,$0D,$0E,$0F,$10,$11,$12,$13,$14,$15,
    $16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F,$20,
    $21,$22,$23,$24,$25,$26,$27,$28,$29,$2A,$2B,
    $2C,$2D,$2E,$2F,$30,$31,$32,$33,$34,$35,$36,
    $37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F,$40,$41,
    $42,$43,$44,$45,$46,$47,$48,$49,$4A,$4B,$4C)

//*****************************************************************************
Sub init_SPI() 
    SPI.SetAsMaster(spiOscDiv16) 
    SPI.SetSample(spiSampleMiddle) 
    SPI.SetClock(spiIdleHigh,spiRisingEdge ) 
    SPI.Enabled = true 
End Sub 

Sub select_Max() 
    PORTC.0=0 
    DelayUS(1) 
End Sub 

Sub deselect_Max() 
    PORTC.0=1 
    DelayUS(1) 
End Sub 
//*****************************************************************************
// MAX7456 low level code
Sub MAXWrite(addr As Byte, data As Byte)
    select_Max()
    SPI.WriteByte(addr)
    DelayUS(1)
    SPI.WriteByte(data)
    deselect_Max()
End Sub
//-----------------------------------------------------
sub ResetMAX7456()
	maxwrite(MAXREG_VM0,%01000110) // Software reset
	delayms(1)
end sub
//-----------------------------------------------------
Sub EnableMAX7456()
    MAXWrite(MAXREG_VM0,%01000100) // PAL, autosync, OSD off, VSYNC, buffer enabled
End Sub
//-----------------------------------------------------
Sub DisableMAX7456()
    MAXWrite(MAXREG_VM0,%01000101) // PAL, disabled
End Sub
//-----------------------------------------------------
Sub EnableMAX7456_with_OSD()
    MAXWrite(MAXREG_VM0,%01001100) // PAL, enabled with OSD enabled
End Sub

//-----------------------------------------------------
Function Get_Charcode_From_Table(c As String) As Byte
    Dim count As Byte
    Dim rv_char As Byte
    
    rv_char=0
    count = 0
    For count=0 To Bound(CharTable)
        If c = CharTable(count) Then
           rv_char = char_to_char_code_table(count)        
           Break	
        End If
    Next
    If count=Bound(CharTable) Then 
       rv_char=1 //Should be '0' later...
    End If
    Get_Charcode_From_Table =  rv_char
End Function
//-----------------------------------------------------
Sub InitAutoIncrement()
	MAXWrite(MAXREG_DMM,%00000001)
End Sub
//-----------------------------------------------------
Sub OffAutoIncrement()
	MAXWrite(MAXREG_DMM,0)
End Sub
//-----------------------------------------------------
Sub SendStopAutoAddressIncrementData()
	select_Max()
	SPI.WriteByte($ff)
	deselect_Max()
End Sub
//-----------------------------------------------------
Sub WriteText(txt As String)
    Dim data As Byte
    Dim i As Byte
    
    i=0
    InitAutoIncrement()
    
    While txt(i) <> null
        data = Get_Charcode_From_Table(mid(txt,i,1)) 
        select_Max()
        SPI.WriteByte(data)  
        deselect_Max()
        i=i+1
    Wend
    
    SendStopAutoAddressIncrementData()
    OffAutoIncrement()
End Sub
//-----------------------------------------------------
Sub SetCursor(x As Byte, y As Byte)
    Dim msb As Byte
    Dim lsb As Byte
    Dim temp_line_num As Integer
    
    If (x>30 Or  x=0 Or  y>30 Or  y=0) Then
       lsb=4
       msb=0
    Else 
       temp_line_num = ((y-1)*30)+x
       lsb = temp_line_num And 255
       temp_line_num = temp_line_num >> 8
       msb = temp_line_num And 255
       msb=msb And 1 //Ensure we're writing to the Data memory...
    End If    
    select_Max()
    MAXWrite(MAXREG_DMAH,msb)
    MAXWrite(MAXREG_DMAL,lsb)
    deselect_Max()        
End Sub
//-----------------------------------------------------

//*****************************************************************************
// MAX7456 high level code

//*****************************************************************************
// public routines
Public Sub Init_MAX7456()
       init_SPI()
       DelayMS(1)
       ResetMAX7456()
       delayms(1)
       EnableMAX7456()
       DelayMS(1)
       DisableMAX7456()
       DelayMS(1)
       EnableMAX7456()
       DelayMS(1)
       EnableMAX7456_with_OSD()
       DelayMS(1)
End Sub
//-----------------------------------------------------
Public Sub SetXY(x As Byte, y As Byte)
       SetCursor(x,y)
End Sub
//-----------------------------------------------------
Public Sub Print(text As String)
//       DisableMAX7456()
       WriteText(text)
//       EnableMAX7456()
End Sub
//-----------------------------------------------------
Public Sub Clearline(y As Byte)
       SetCursor(0,y)
       //         123456789012345678901234567890
       WriteText("                              ")
End Sub
//-----------------------------------------------------
// initialise module
//Initialize
Please note that the /CS signal to the MAX7456 is currently hard coded to PORTC.0 although this could be made into an #option fairly easily.

To use the module, use the following code in your main bas file (note that I'm using a PIC18F2610)




Ed.

Code: Select all

{
*****************************************************************************
*  Name    : GPS_OBD.BAS                                                   *
*  Author  : Ed Williamson-Brown                                            *
*  Notice  : Copyright (c) 2009 MadInventions                               *
*          : All Rights Reserved                                            *
*  Date    : 25/06/2009                                                     *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
// device and clock
Device = 18F2610
Clock = 8

Config osc = INTIO67, WDT = OFF, MCLRE = ON , PWRT = off

#option ICD = false
 // import modules...
Include "ICD_debug.bas"
Include "MAX7456.bas"
Include "Convert.bas"

// local variables
Dim counter As Integer

OSCCON = %01110010
counter=0

Output (PORTC.0)
Output (PORTC.1)
PORTC.0=1

Init_MAX7456()
DelayMS(1)
SetXY(9,2)
Print("MadInventions!")

While True

   SetXY(1,15)
   Print("Count = " + DecToStr(counter)+"  ")

   counter=counter+1

   If counter<25 Then 
   		PORTC.1=1 
   		setxy(20,15)
   		print ("LED ON ")
   Else 
   		PORTC.1=0 
   		setxy(20,15)
   		print ("LED OFF")
   End If

   If counter>50 Then counter = 1  End If

   DelayMS(100)

Wend
Although the essential parts of this are:

Code: Select all

Include "MAX7456.bas"
Output (PORTC.0)
PORTC.0=1
Init_MAX7456()
DelayMS(1)
SetXY(9,2)
Print("MadInventions!")

wirecut
Posts: 3
Joined: Sun Sep 27, 2009 5:11 pm
Location: Milano

Post by wirecut » Wed Sep 30, 2009 9:35 am

Hi madinventions,

do you use a specific hardware for the MAX7456 like

http://thesiliconhorizon.com/store/alam ... -p-78.html

or Maxim DevKit?

Regards

Leo

User avatar
madinventions
Posts: 11
Joined: Tue Jan 06, 2009 9:13 pm
Location: Suffolk, England

Post by madinventions » Wed Sep 30, 2009 10:26 am

Hi Leo,

I got the ICs as samples directly from Maxim and soldered one down to a SMD-to-DIL adaptor and I then used a good old fashioned breadboard to do the prototyping as there really aren't very many connections to make. I've since made this into a more permanent design using stripboard and I may end up with a PCB design at some point.

I've always found that dev kits are either a bit limited in what they allow you to do or vastly more complicated than they need to be. Also, they do tend to be expensive so I generally end up making up something myself.

If your soldering is up to it then I'd say go the DIY route - the SMD to DIL adaptor cost about £3 from eBay and the rest was from the spares box. The kit you mention is a quick and easy way to get started but you'll still need to link up a PIC somehow aswell...

I'll see if I can find a photo of the breadboard lashup and post it up here.

Ed. :D

wirecut
Posts: 3
Joined: Sun Sep 27, 2009 5:11 pm
Location: Milano

Post by wirecut » Sat Oct 03, 2009 4:11 pm

Hi Ed,

Do you have see the strange character set address of the MAX7456?

I'm thinking to generate a new character set respecting the ASCII code/position and update the OSD character memory area chip trough serial port.

What is your opinion about that?

Ciao

Leo


PS. I have sent to you a PM; do you have read it?

wirecut
Posts: 3
Joined: Sun Sep 27, 2009 5:11 pm
Location: Milano

Post by wirecut » Sun Oct 04, 2009 5:47 am

Hi Ed,

I have found here
http://mysite.verizon.net/res12f4fa/index.html
from Arduino forum. The file contain the mcm character memory with ASCII layout.

Bye

Leo

User avatar
madinventions
Posts: 11
Joined: Tue Jan 06, 2009 9:13 pm
Location: Suffolk, England

Post by madinventions » Mon Oct 05, 2009 3:47 pm

Hi Leo,

Yes, the character set is a bit strange on the MAX7456, but I got around this by using the 'GetCharCodeFromTable()' routine. The font files on the Arduino forum look like an easy way to get around the problem!

On my system, I have defined some custom characters using the MCM and MDM utilities to create the character codes and some PIC code to write it into the MAX. I'll see if I can dig out the code I wrote to do this and post it up later.

Best regards,
Ed. :)

JAComms
Posts: 3
Joined: Sat Nov 28, 2009 5:01 am
Location: Goulburn, AUSTRALIA

Post by JAComms » Sat Nov 28, 2009 5:09 am

Hi Madinventions

Nice job with the above code. This is my 1st play with SF Compiler up untill now Ive been using mirkoBasic and proton prior to that. I googleed the MAX7456 and found this code. Ive poped it into my EasyPIC4, I only had a PIC18F4685 handy to test with but am unable to get text to the screen. Can you please let me know your Port C to Pin config for the SPI Im sure I have read your code correct but still no luck.

Oh yeh ......AWSOME Compiler.....well done guys!!!

Justin

JAComms
Posts: 3
Joined: Sat Nov 28, 2009 5:01 am
Location: Goulburn, AUSTRALIA

Post by JAComms » Sat Nov 28, 2009 5:32 am

Sorry I forgot to add my config

PIC MAX
RC0 - Reset
RC1 - C/S
RC3 - SCK
RC4 - SO
RC5 - SI


Thanks again

Justin

JAComms
Posts: 3
Joined: Sat Nov 28, 2009 5:01 am
Location: Goulburn, AUSTRALIA

Post by JAComms » Sat Nov 28, 2009 12:57 pm

Hi all

Well after another play and a quick change in my code its all happy.... This is an awsome module. Well done!!

Will post final code when finished.

:-)

yllis
Posts: 10
Joined: Wed Feb 23, 2011 10:18 am
Location: Finland

Re: MAX7456 OSD video overlay code

Post by yllis » Tue Sep 27, 2016 11:14 am

Hi all

In the code the 'GetCharCodeFromTable()' routine was used.
How would you use the existing character set of the MAX7456 in Swordfish?
If I was to use custom characters, I would first have to make and load them to the memory of the MAX7456 chip (I am not asking how to do it, as there are tutorials for this). But then I would need a way to call these characters in Swordfish and the 'GetCharCodeFromTable()' routine needs to be replaced for this...

Best regards,
Antti

Jerry Messina
Swordfish Developer
Posts: 1235
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: MAX7456 OSD video overlay code

Post by Jerry Messina » Wed Sep 28, 2016 12:29 am

How would you use the existing character set of the MAX7456 in Swordfish?
The code shown in the first post DOES use the internal character set of the MAX7456.

Post Reply