This module provides a simple API to the Maxim MAX7456 on-screen display chip

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX7456.cpp Source File

MAX7456.cpp

00001 /*
00002     Copyright (c) 2010 Andy Kirkham
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021 */
00022 
00023 #include "mbed.h"
00024 #include "MAX7456.h"
00025 
00026 #ifdef MAX7456_DEBUG
00027 #include "IOMACROS.h"
00028 extern Serial pc;
00029 #endif
00030 
00031 #define CS_ASSERT   _cs->write(0)
00032 #define CS_DEASSERT _cs->write(1)
00033 
00034 // This header should only be included once here in this
00035 // file as it compiles inline directly. Include within
00036 // the library namespace.
00037 #include "MAX7456CHARS.h"
00038 
00039 /* Map ASCII table to the MAX7456 character map.
00040    Note, the MAX7456 in-built character map is no where near the ascii
00041    table mapping and very few characters are available to map. Where 
00042    possible we create new characters for those we need that are missing
00043    from the MAX7456 that we want to use and also we create some special
00044    characters of our own that are not ASCII chars (crosshair for example).
00045    These additional character definitions are listed below the table. 
00046    Character maps we have create can be found in MAX7456CHARS.h */
00047 const unsigned char MAX7456_ascii[256] = {
00048 
00049     /* Regular ASCII table. */
00050     /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
00051     /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00052     /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00053     /* 20 */ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x46,  0x3F, 0x40, 0x00, 0x4d, 0x45, 0x49, 0x41, 0x47, 
00054     /* 30 */ 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  0x08, 0x09, 0x44, 0x43, 0x4A, 0x00, 0x4B, 0x42,
00055     /* 40 */ 0x4C, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,  0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 
00056     /* 50 */ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,  0x22, 0x23, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 
00057     /* 60 */ 0x46, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,  0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
00058     /* 70 */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,  0x3C, 0x3D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 
00059     
00060     /* Extended ASCII table. */
00061     /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
00062     /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00063     /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00064     /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00065     /* B0 */ 0xB0, 0x00, 0x00, 0xB3, 0xB4, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF,   
00066     /* C0 */ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00067     /* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0xD9, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 
00068     /* E0 */ 0xe0, 0xe1, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00069     /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00     
00070 };
00071 
00072 MAX7456::MAX7456(PinName mosi, PinName miso, PinName sclk, const char *name, PinName cs, PinName rst, PinName vsync)
00073 {
00074     init(mosi, miso, sclk, name, cs, rst, vsync);
00075 }
00076 
00077 MAX7456::MAX7456(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName vsync)
00078 {
00079     init(mosi, miso, sclk, NULL, cs, rst, vsync);
00080 }
00081 
00082 MAX7456::~MAX7456()
00083 {
00084     delete(_ssp);
00085     delete(_cs);
00086     delete(_rst);
00087     delete(_vsync);
00088 }
00089 
00090 void
00091 MAX7456::init(PinName mosi, PinName miso, PinName sclk, const char *name, PinName cs, PinName rst, PinName vsync)
00092 {
00093     _ssp = new SPI(mosi, miso, sclk, name);
00094     _cs  = new DigitalOut(cs);
00095     _rst = new DigitalOut(rst);    
00096     if (vsync != NC) {
00097         _vsync = new InterruptIn(vsync);
00098         _vsync->fall(this, &MAX7456::vsync_isr);   
00099     }
00100     
00101     // Set default output signals.
00102     CS_DEASSERT;
00103     _rst->write(1);
00104    
00105     // Setup the SSP.
00106     _ssp->format(8,0);
00107     _ssp->frequency(25000000);
00108     
00109     // Reset the MAX7456
00110     reset();
00111     
00112     /* Write the custom CM map. */
00113     write(0, read(0) & 0xF7);
00114     for (int index = 0; custom_chars[index].ascii != 0; index++) {
00115         write_char_map(custom_chars[index].ascii, custom_chars[index].map);
00116     }
00117     
00118     wait_us(100000);
00119     
00120     /* Change the vertical offset. */
00121     vos(0x16);
00122     
00123     /* Set the blink rate. */
00124     //vm1((3 << 2) | 3);
00125     
00126     /* Enable display of OSD image. */
00127     vm0(0x48);
00128 }
00129 
00130 void 
00131 MAX7456::write(unsigned char address, unsigned char byte) 
00132 {
00133     CS_ASSERT;
00134  
00135     /* MAX7456 addresses are always less than 0x80 so if the
00136        address is > 0x7F then the caller is requesting an direct
00137        8bit data transfer. */
00138     if (address < 0x80) { _ssp->write(address); }
00139     
00140     _ssp->write(byte);
00141     CS_DEASSERT;
00142 }
00143 
00144 int 
00145 MAX7456::read(unsigned char address) 
00146 {
00147     int data;
00148     address |= 0x80;
00149     CS_ASSERT;
00150     _ssp->write(address);
00151     data = _ssp->write(0xFF);
00152     CS_DEASSERT;
00153     return data;
00154 }
00155 
00156 void
00157 MAX7456::reset(void)
00158 {
00159     _rst->write(0); 
00160     wait_us(100000);
00161     _rst->write(1);  
00162     wait_us(100000);
00163 }
00164 
00165 void
00166 MAX7456::clear_display(void)
00167 {
00168     dmm(1 << 2);
00169     while(dmm() & (1 << 2));
00170 }
00171 
00172 void 
00173 MAX7456::cursor(int x, int y) 
00174 {
00175     uint16_t pos = (y * 30) + x;
00176     dmah((pos >> 8) & 0x1);
00177     dmal(pos & 0xFF);    
00178 }
00179 
00180 void 
00181 MAX7456::convert_string(char *s) 
00182 {
00183     while(*(s)) {
00184         *(s) = MAX7456_ascii[*(s)];
00185         s++;
00186     }
00187 }
00188 
00189 int
00190 MAX7456::string(char *s) 
00191 {
00192     int len = 0;
00193     dmm(1 | (1 << 6)); /* Enable 8bit write */    
00194     while(*(s)) {
00195         write(0x80, MAX7456_ascii[*s++]);        
00196         len++;
00197     }
00198     write(0x80, 0xFF);
00199     return len;
00200 }
00201 
00202 void
00203 MAX7456::attributes_xyl(int x, int y, char *s, int len)
00204 {
00205     uint16_t pos = (y * 30) + x;
00206     dmah(((pos >> 8) & 0x1) | (1 << 1));
00207     dmdi(pos & 0xFF);    
00208     dmm(1 | (1 << 6)); /* Enable 8bit write */    
00209     while (len--) {
00210         write(0x80, *s++);
00211     }
00212     write(0x80, 0xFF);
00213 }
00214 
00215 int
00216 MAX7456::stringxy(int x, int y, char *s) 
00217 {
00218     cursor(x, y);
00219     return string(s);
00220 }
00221 
00222 int
00223 MAX7456::stringxy(int x, int y, char *s, uint8_t a) 
00224 {
00225     char *q = NULL;
00226     int len;
00227     cursor(x, y);
00228     len = string(s);
00229     q = (char *)malloc(len);
00230     if (!q) {
00231         return -1;
00232     }
00233     memset(q, a, len);
00234     attributes_xyl(x, y, q, len);
00235     free(q);
00236     return len;
00237 }
00238 
00239 int
00240 MAX7456::stringxy(int x, int y, char *s, char *a) 
00241 {
00242     int len;
00243     cursor(x, y);
00244     len = string(s);
00245     attributes_xyl(x, y, a, 30);
00246     return len;
00247 }
00248 
00249 void 
00250 MAX7456::stringl(int x, int y, char *s, int len) 
00251 {
00252     cursor(x, y);            
00253     dmm(1); /* Enable 8bit write */    
00254     while(len--) {
00255         if (*s == '\0') break;
00256         write(0x80, MAX7456_ascii[*s++]);
00257     }
00258     write(0x80, 0xFF);
00259 }
00260 
00261 void 
00262 MAX7456::read_char_map(unsigned char address, unsigned char *data54) 
00263 {
00264     cmah((uint8_t)address);
00265     cmm(0x50);
00266     for (uint8_t index = 0; index < 54; index++) {
00267         cmal(index);
00268         wait_us(1000);        
00269         *(data54 + index) = read(0xC0);
00270     }
00271 }
00272 
00273 void 
00274 MAX7456::write_char_map(unsigned char address, const unsigned char *data54) 
00275 {
00276     unsigned char index, c, match = 1;
00277     
00278     write(CMAH, address);
00279     write(CMM, 0x50);
00280     wait_us(20000);
00281     for (index = 0; index < 54; index++) {
00282         write(CMAL, index);
00283         c = read(0xC0);
00284         if (c != data54[index]) {
00285             match = 0;            
00286             break;
00287         }
00288     }
00289     
00290     if (!match) {   
00291         write(CMAH, address);
00292         for (index = 0; index < 0x36; index++) {
00293             write(CMAL, index);
00294             write(CMDI, data54[index]);
00295         }
00296         write(CMM, 0xA0);
00297         wait_us(20000);
00298         while ((read(0xA0) & 0x20) != 0x00);    
00299     }
00300 }
00301 
00302 
00303