It's been a while since we published the last article.. Well we've been pretty busy those days but as a gift in this article I'll present you some of our lattest work : A library for the well known max7456 chip by Maxim.
As famous as it is, a little reminder won't be too much. max7456 is basically used to insert customized information in a given analogic video stream. This manip is called "OSD" (for On-Screen Display). A little picture to explain it :
We recently bought a wireless video system in order to do FPV (First Person Flying, you only look on a video send by a camera installed on the drone/plane). And the problem is that it's quite hard to pilot this way without additional informations about the flight. So we decided to make our own OSD system.
We decided to make a library for the max7456 because we didn't found one that fitted our needs. This library is pretty simple to use and comes with a complete documentation and example programs. This has been used with a PAL system, but the differences with NTSC are not really big (you have to init it an other way, refer to the datasheed of max7456 if you need to).
Here is the Hello World ! code :
#include "SPI.h"
#include "max7456.h"
Max7456 osd;
void setup()
{
SPI.begin(); //to be called before osd.init
osd.init(10); //CS on port 10
osd.setDisplayOffsets(60,18);
osd.setBlinkParams(_8fields, _BT_BT);
osd.activateOSD();
osd.print("Hello world : )",1,3);
}
void loop()
{
}
In order to make easier the process of entering new characters in the NVM (non-volatile memory) of the OSD, I made an program used to transform a bmp picture representing the OSD characters table into a single array you can use with the library (there is an example that shows the use of this array). Just lauch the executable with the options :
convertOSD.exe -i ".bmp picture" -head ".h containing array"
The bmp picture looks like this :
This represents the 256 characters to be insered into the NVM. So here's the deal : when you want to put your customized characters table into the NVM, you must write on a register in the max7456. The values to write on this special register are directly related to the character. To be quick, each pixel of a character is 2-bits coded, and the character is 12x18 pixels you'll need 54 bytes of data. There are 256 characters in the table so the array returned by the program is 13824 bytes long (approx. 13.5k) . This is much more than the Arduino's flash memory can handle (2k). But the program memory is sufficient to store such an array. Then we used a little trick to program the max7456 in one single operation : we simple store the array in the program memory with the instruction :
const prog_uchar tableOfAllCharacters[13824] PROGMEM = {0x55,0x55,0x55,0 // ....
Nothing really hard here : character at address 0x00 is represented by the 54 first bytes, character at address i is represented by the (54*i) next 54 characters. Note that all the 0xFF value has been replaced by "0x55". This is because af a tricky bug in the Arduino bootloader that causes the Arduino to be corrupted if too many 0xFF are sent on a row to the program memory. Therefore, this is the method to get the character i in the table "table" (we fill a special type "charact" which is in fact a 54 bytes array.
//-----------------------------------------------------------------------------
// Implements Max7456::getCARACFromProgMem
//-----------------------------------------------------------------------------
void Max7456::getCARACFromProgMem(const prog_uchar *table, byte i, charact car)
{
unsigned long index;
byte read;
index = i*54;
for(unsigned long j = 0 ; j < 54 ; j++)
{
read = pgm_read_byte_near(table +index+j );
car[j] = read;
if (car[j] == 0x55)
car[j] = 0xff;
}
}
Note that we experienced problems with the sparkfun max7456 package. This was caused by a chip overheat dued to insuficient copper pad under it. We solved the problem by adding a tiny RAM heat dissipator on it.
Ok, most important part now : the sources !



37 comments
Skip to comment form ↓
trisonic
January 23, 2013 at 8:45 pm (UTC 2) Link to this comment
hi
sorry for this email, but i really need your help
i have read your article about max7456 here: http://theboredengineers.com/2012/12/a-max7456-library-for-arduino/
i have a lot of problem, i have spent 2 days around it but it still not works.
i really dont know why it doesnt works, this is the wiring that i have used: http://localhostr.com/files/xFMs77Z/Uno and Max7456 C.jpg
this is a sketch that i have flashed: http://pastebin.com/aXieBpbM
but i dont see nothing on my display (pal tv color "mivar 16 p2").
i see only the image from a little cam that i have attached but no osd.
how can you help me?
regards
Ben
January 23, 2013 at 9:30 pm (UTC 2) Link to this comment
Hi trisonic,
I checked your sketch and it seems OK.
Your wiring seems good too, but you should try to tie LOS, HSYNC and VSYNC output to 5V with a 5K ou 10k resistor (same as RST). We had numerous problems caused by floating outputs.
Is the display easily disturbed (when you move it a little with your finger for instance) ?
Your max7456 seems OK too since the background is displayed.
Is it warm ? We had to add a heat sinker because after a few seconds the display disappeared.
trisonic
January 23, 2013 at 11:48 pm (UTC 2) Link to this comment
thanks for your reply!
i have wired it as you have wrote, i have used some trimpots adjusted at 7k... but nothing.
i see only the background image but no osd, no disturb, no strange effect, its not warm.
maybe the problem is on the offset?
osd.setDisplayOffsets(60,18);
osd.setBlinkParams(_8fields, _BT_BT);
Ben
January 24, 2013 at 12:02 am (UTC 2) Link to this comment
Hi again,
Did you upload into the OSD a new character table? if you did it using the sample program Max7456WriteTable.cpp your OSD memory has been overriden with 0xFFs (so all your characters are white). Can you try to invert colors on your osd.print("Hello world
",1,3); (just replace it with osd.print("Hello world
",1,3,0,1);. If so, you'll have to upload a non-empty table again.
trisonic
January 24, 2013 at 12:48 am (UTC 2) Link to this comment
uhm.... i didn't upload no character table! ;(
my osd is brand new and i didnt uploaded nothing, my mistake!!
...tomorrow i will fix it.
thanks so much ben
Ben
January 24, 2013 at 12:55 am (UTC 2) Link to this comment
Well actually it should work anyway : don't try it yet. There is a default chars table in the max, and some random characters should appear replacing the "Hello world" string. I'll try tomorow to upload the exact code you posted to see if it's a software problem. one thing you can do is to reset first the OSD (by connecting RST to ground and then put it back to 5V with resistor), and then reset the arduino after this (don't disconnect it, just push the reset button). What is the Arduino board you're working on?
trisonic
January 24, 2013 at 1:08 am (UTC 2) Link to this comment
Arduino UNO, and a regular duemilanove (with optiboot bootloader).
Do you think that my osd has a default table?
Could you populate Max7456WriteTable.h with a default table?
Maybe i can try to upload a new table.
What kind of benefit shoul i will have with resetting the osd?
regards
Ben
January 24, 2013 at 1:23 am (UTC 2) Link to this comment
resetting the chip will only restore its internal registers to a default value ; basically if the internal state of the max may have been somehow corrupted by something (lets say : rise up on the 5V ; states of the Arduino pins on startup,...). By the way can you tell me what version of the IDE you are using ? You could have to manually set the SPI pins to input and output states. But it's already done on the latest ones. one other problem you're pointing out is the bootloader that can somehow disturb the functionning of the max. those chips are quite sensitive so if you can for your tests I recommand you to get back to the original bootloader and therefore see if this is the source of the problem. If it still don't work, maybe you should try to upload a sample code for the max7456 (you can found it on the internet (http://f5mna.free.fr/Arduino.htm for exemple, it's in french but you can download a sample sketch at http://f5mna.free.fr/arduino/f5mna_8_phrases.zip ). Let us know if you find a solution to your problems.
Regards
andrea
January 24, 2013 at 10:52 am (UTC 2) Link to this comment
thanks for your suppor dude
i have tried to reset the osd but nothing on tv, im using ide 1.0.1.
i want to try to upload a new char table (im desperate!), is your code for arduino? i see a .cpp extension.
can you try modify it for a regular arduino + ide 1.0.1?
regards
Ben
January 24, 2013 at 11:57 am (UTC 2) Link to this comment
Hi Andrea,
I know this little device can be a pain in the ass
This is actually a code designed to be used in eclipse but chances are that you'll be able to open it in your arduino IDE by changing the extension to .ino. (If you often use arduino you should give a try to eclipse we wrote an article about it).
Also, the .h file that contains the characters table is filled with 0x55 (blanck characters).
You can try the program that we gave with the library (you have to open it with command lines -hope you know how to do this). It takes a bmp file as input and generate a .h which contains a table of 13.5k of data representing this bmp table into the max memory. You'll just have to copy it and replace the old 0x55 values in the initial.h. I tried your example and it works fine on me.
If it's an option to you, try to upgrade your IDE to 1.0.2, too..
Ben
January 24, 2013 at 12:15 pm (UTC 2) Link to this comment
Here is a data to copy if you can't use the generator
http://theboredengineers.com/WordPress3/wp-content/uploads/2013/01/table.h
andrea
January 24, 2013 at 1:16 pm (UTC 2) Link to this comment
i will modify your char loader...!
thanks a lot
Ben
January 24, 2013 at 1:41 pm (UTC 2) Link to this comment
No problem
I hope you'll eventually figure out what's the problem. Don't hesitate to comment again to share your experience.
Ben
andrea
January 24, 2013 at 3:18 pm (UTC 2) Link to this comment
Im converting your loader for working with arduino ide but i have some error messages such:
Max7456 *osd = NULL; //Pointer representing a max7456 .
In file included from Max7456WriteTable.ino:2:
Max7456WriteTable.h:25: error: expected constructor, destructor, or type conversion before '*' token
andrea
January 24, 2013 at 3:57 pm (UTC 2) Link to this comment
little update for your loader: https://gist.github.com/4622611
sketch_jan24b.ino: In function 'void setup()':
sketch_jan24b:303: error: no matching function for call to 'Max7456::getCARACFromProgMem(int&, byte [54])'
D:\arduino-1.0.3\libraries\max7456/max7456.h:228: note: candidates are: static void Max7456::getCARACFromProgMem(const prog_uchar*, byte, byte*)
sketch_jan24b:304: error: no matching function for call to 'Max7456::sendCharacter(byte [54], int&)'
D:\arduino-1.0.3\libraries\max7456/max7456.h:116: note: candidates are: void Max7456::sendCharacter(const byte*, byte, byte)
how can i solve it?
Ben
January 24, 2013 at 5:51 pm (UTC 2) Link to this comment
Ok for your first error you just have to add the name of the variable in progmem : tableOfAllCharacters as first argument. leave the other arguments as they are.
For the second, do this trick:
osd->sendCharacter(currentChar,i&0xF0, i&0xF0);
this is because we use it as low and high addresses and I forget to update the code sample, appologies
andrea
January 24, 2013 at 6:28 pm (UTC 2) Link to this comment
Thanks for your support
I have modified the sketch, the *final* version is this: https://gist.github.com/4625393.git
BUT... the two functions (osd.getCARACFromProgMem - osd.sendCharacter) will overflow the ram of my arduino uno....
I dont see nothing on the serial monitor but, If i will comment only this two functions it works!
What do you think?
andrea
January 24, 2013 at 6:30 pm (UTC 2) Link to this comment
Sorry, this is the link: https://gist.github.com/4625449
andrea
January 24, 2013 at 10:56 pm (UTC 2) Link to this comment
the problem is only in this function: osd.getCARACFromProgMem(tableOfAllCharacters,i,currentChar);
if i will comment only this, it will run (but it will write nothing).... maybe it take too much ram in run time.
what kind of trick can i use for upload a new table on the eeprom?
some people on internet, with my same issues, have solved it by uploading a new table.... maybe its blank.
Ben
January 24, 2013 at 11:12 pm (UTC 2) Link to this comment
Hi again,
One thing you can try is enable verbose mode for your compilation (file/preferences/check verbose). This can give you a better hint on what's happening. We had this problem but it was solved using the "prog_uchar... PROGMEM" pattern which write the big array into program memory of the chip. btw, what is your atmega version ? we did all our tests with a 328 but if you have a 168 it can be too short in memory (16kb of data from wich you must take the 13.5 from the array and 2k from the bootloader, which left almost nothing). If so, you should try to upload the 128 first characters only (divide the size of the array by 2 which free ~7k of memory) and then if it's ok go ahead with the 128 last characters.
andrea
January 24, 2013 at 11:22 pm (UTC 2) Link to this comment
sorry again
"myloader.ino: In function 'void setup()':
myloaderi.ino:17: warning: '__progmem__' attribute ignored"
line 17 is for: const prog_uchar tableOfAllCharacters[13824] PROGMEM = {
is it a big problem?
andrea
January 24, 2013 at 11:23 pm (UTC 2) Link to this comment
a regular arduino uno, 328p
Ben
January 24, 2013 at 11:32 pm (UTC 2) Link to this comment
OK this must be the problem : try to add the static keyword just after the const one.
If this does not do the trick, try to install a new version of Arduino. Some other dudes had the same problem solved by re-installing the entire chaintool.
andrea
January 24, 2013 at 11:42 pm (UTC 2) Link to this comment
i have solved the problem about the loader, the correct sketch for a regulare arduino ide 1.0.3 is this: https://gist.github.com/4628935
but.... still nothing on my tv!
i really dont know what is the problem....
Ben
January 24, 2013 at 11:50 pm (UTC 2) Link to this comment
There is a function in the library that allow reading characters from the max7456. Try to use it with one or two characters to see if the upload went well
andrea
January 25, 2013 at 1:00 am (UTC 2) Link to this comment
which function should i use? getCharacter?
i have made this but it doesnt works: https://gist.github.com/4629933
can you modify it?
thanks
Ben
January 25, 2013 at 2:04 pm (UTC 2) Link to this comment
Hi Andrea,
This is the right function. This code works with me. This seems to be a hardware problem : you can try to see if the SPI pins are correctly initialized (MISO as input for example). Maybe your max7456 is broken, too, but I can't really tell. If you can try with an other go for it. Did you try other examples around the internet ?
Ben
January 25, 2013 at 2:10 pm (UTC 2) Link to this comment
(Sorry I just made a typo : it's osd.getCharacter(currentChar,i&0x0F, i&0xF0), not i&0xF0, i&0xF0, but it should not affect the overall function.
andrea
January 25, 2013 at 3:04 pm (UTC 2) Link to this comment
I have modified both sketch with: i&0x0F, i&0xF0
getCharacter returns only 0
what it means? is the eeprom empty?!
andrea
January 28, 2013 at 5:30 pm (UTC 2) Link to this comment
hey ben!
i have bought a new one max7456... it works!
but i see a lot of strange characters, how can i fix it?
look:
http://localhostr.com/files/6oQSQ5Y/2013-01-28%2017.27.49.jpg
Ben
January 28, 2013 at 5:53 pm (UTC 2) Link to this comment
Hi Andrea that's great news (altought i'm sorry for your money
)
They are some things you can try out now you have a "running" max7456 :
- try to reset the OSD before to reset the arduino (do it manually)
- try to upload the whole new character table : the chinese chars you see come from the default table.
anyway you should get it to work soon
andrea
January 29, 2013 at 9:13 pm (UTC 2) Link to this comment
solved!
here the solution: http://arduino.cc/forum/index.php/topic,144493.msg1094963.html#msg1094963
Ben
January 30, 2013 at 12:03 am (UTC 2) Link to this comment
Ok that's nice for you ! Sorry you were not able to make it work with this library, have fun with OSD :p
Rick Eis
April 12, 2013 at 11:40 pm (UTC 2) Link to this comment
Hi Ben,
Very interested in what you have done here - It appears I have everything working except I'm having trouble bringing in your character set.
I'm not a programmer but hope you could walk me through using your little program ,"I made an program used to transform a bmp picture"
Thanks
Rick
Ben
April 17, 2013 at 12:55 pm (UTC 2) Link to this comment
Hi, this program basically translate a .bmp picture into a arduino-readable .h file that you can copy/past to the code that upload characters to the max7456. Where are you stuck with that ?
Simon
April 19, 2013 at 11:25 am (UTC 2) Link to this comment
Hijacking Rick's thread a bit, Yes. I understand that your little program reads a BMP of characters and converts them into a file (tableOSD.h) but what the line that then stuffs that in to the MAX7456.
I see the line
const prog_uchar tableOfAllCharacters[13824] PROGMEM = {0x55,0x55,0x55,0 //
and the
//-----------------------------------------------------------------------------
// Implements Max7456::getCARACFromProgMem
//-----------------------------------------------------------------------------
void Max7456::getCARACFromProgMem(const prog_uchar *table, byte i, charact car)
{
unsigned long index;
byte read;
index = i*54;
for(unsigned long j = 0 ; j < 54 ; j++)
{
read = pgm_read_byte_near(table +index+j );
car[j] = read;
if (car[j] == 0x55)
car[j] = 0xff;
}
}
Do I put
#include
at the start of my listing and then use the function Max7456?
Yours Simon M
Ben
April 24, 2013 at 3:05 pm (UTC 2) Link to this comment
Hey !
Basically all you need to do is replace all the characters (hexa values) in const prog_uchar tableOfAllCharacters[13824] PROGMEM = {0x55,0x55,0x55,0 //
by the freshly generated characters from the .h ; then upload the sketch to the arduino and use a terminal to update the characteres memory of the Max and it's done