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

MAX7456.cpp

Committer:
AjK
Date:
2010-11-16
Revision:
0:d7cd54ad4c3d

File content as of revision 0:d7cd54ad4c3d:

/*
    Copyright (c) 2010 Andy Kirkham
 
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
 
    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.
 
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

#include "mbed.h"
#include "MAX7456.h"

#ifdef MAX7456_DEBUG
#include "IOMACROS.h"
extern Serial pc;
#endif

#define CS_ASSERT   _cs->write(0)
#define CS_DEASSERT _cs->write(1)

// This header should only be included once here in this
// file as it compiles inline directly. Include within
// the library namespace.
#include "MAX7456CHARS.h"

/* Map ASCII table to the MAX7456 character map.
   Note, the MAX7456 in-built character map is no where near the ascii
   table mapping and very few characters are available to map. Where 
   possible we create new characters for those we need that are missing
   from the MAX7456 that we want to use and also we create some special
   characters of our own that are not ASCII chars (crosshair for example).
   These additional character definitions are listed below the table. 
   Character maps we have create can be found in MAX7456CHARS.h */
const unsigned char MAX7456_ascii[256] = {

    /* Regular ASCII table. */
    /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
    /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* 20 */ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x46,  0x3F, 0x40, 0x00, 0x4d, 0x45, 0x49, 0x41, 0x47, 
    /* 30 */ 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  0x08, 0x09, 0x44, 0x43, 0x4A, 0x00, 0x4B, 0x42,
    /* 40 */ 0x4C, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,  0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 
    /* 50 */ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,  0x22, 0x23, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* 60 */ 0x46, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,  0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
    /* 70 */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,  0x3C, 0x3D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 
    
    /* Extended ASCII table. */
    /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
    /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* B0 */ 0xB0, 0x00, 0x00, 0xB3, 0xB4, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF,   
    /* C0 */ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0xD9, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* E0 */ 0xe0, 0xe1, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00     
};

MAX7456::MAX7456(PinName mosi, PinName miso, PinName sclk, const char *name, PinName cs, PinName rst, PinName vsync)
{
    init(mosi, miso, sclk, name, cs, rst, vsync);
}

MAX7456::MAX7456(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName vsync)
{
    init(mosi, miso, sclk, NULL, cs, rst, vsync);
}

MAX7456::~MAX7456()
{
    delete(_ssp);
    delete(_cs);
    delete(_rst);
    delete(_vsync);
}

void
MAX7456::init(PinName mosi, PinName miso, PinName sclk, const char *name, PinName cs, PinName rst, PinName vsync)
{
    _ssp = new SPI(mosi, miso, sclk, name);
    _cs  = new DigitalOut(cs);
    _rst = new DigitalOut(rst);    
    if (vsync != NC) {
        _vsync = new InterruptIn(vsync);
        _vsync->fall(this, &MAX7456::vsync_isr);   
    }
    
    // Set default output signals.
    CS_DEASSERT;
    _rst->write(1);
   
    // Setup the SSP.
    _ssp->format(8,0);
    _ssp->frequency(25000000);
    
    // Reset the MAX7456
    reset();
    
    /* Write the custom CM map. */
    write(0, read(0) & 0xF7);
    for (int index = 0; custom_chars[index].ascii != 0; index++) {
        write_char_map(custom_chars[index].ascii, custom_chars[index].map);
    }
    
    wait_us(100000);
    
    /* Change the vertical offset. */
    vos(0x16);
    
    /* Set the blink rate. */
    //vm1((3 << 2) | 3);
    
    /* Enable display of OSD image. */
    vm0(0x48);
}

void 
MAX7456::write(unsigned char address, unsigned char byte) 
{
    CS_ASSERT;
 
    /* MAX7456 addresses are always less than 0x80 so if the
       address is > 0x7F then the caller is requesting an direct
       8bit data transfer. */
    if (address < 0x80) { _ssp->write(address); }
    
    _ssp->write(byte);
    CS_DEASSERT;
}

int 
MAX7456::read(unsigned char address) 
{
    int data;
    address |= 0x80;
    CS_ASSERT;
    _ssp->write(address);
    data = _ssp->write(0xFF);
    CS_DEASSERT;
    return data;
}

void
MAX7456::reset(void)
{
    _rst->write(0); 
    wait_us(100000);
    _rst->write(1);  
    wait_us(100000);
}

void
MAX7456::clear_display(void)
{
    dmm(1 << 2);
    while(dmm() & (1 << 2));
}

void 
MAX7456::cursor(int x, int y) 
{
    uint16_t pos = (y * 30) + x;
    dmah((pos >> 8) & 0x1);
    dmal(pos & 0xFF);    
}

void 
MAX7456::convert_string(char *s) 
{
    while(*(s)) {
        *(s) = MAX7456_ascii[*(s)];
        s++;
    }
}

int
MAX7456::string(char *s) 
{
    int len = 0;
    dmm(1 | (1 << 6)); /* Enable 8bit write */    
    while(*(s)) {
        write(0x80, MAX7456_ascii[*s++]);        
        len++;
    }
    write(0x80, 0xFF);
    return len;
}

void
MAX7456::attributes_xyl(int x, int y, char *s, int len)
{
    uint16_t pos = (y * 30) + x;
    dmah(((pos >> 8) & 0x1) | (1 << 1));
    dmdi(pos & 0xFF);    
    dmm(1 | (1 << 6)); /* Enable 8bit write */    
    while (len--) {
        write(0x80, *s++);
    }
    write(0x80, 0xFF);
}

int
MAX7456::stringxy(int x, int y, char *s) 
{
    cursor(x, y);
    return string(s);
}

int
MAX7456::stringxy(int x, int y, char *s, uint8_t a) 
{
    char *q = NULL;
    int len;
    cursor(x, y);
    len = string(s);
    q = (char *)malloc(len);
    if (!q) {
        return -1;
    }
    memset(q, a, len);
    attributes_xyl(x, y, q, len);
    free(q);
    return len;
}

int
MAX7456::stringxy(int x, int y, char *s, char *a) 
{
    int len;
    cursor(x, y);
    len = string(s);
    attributes_xyl(x, y, a, 30);
    return len;
}

void 
MAX7456::stringl(int x, int y, char *s, int len) 
{
    cursor(x, y);            
    dmm(1); /* Enable 8bit write */    
    while(len--) {
        if (*s == '\0') break;
        write(0x80, MAX7456_ascii[*s++]);
    }
    write(0x80, 0xFF);
}

void 
MAX7456::read_char_map(unsigned char address, unsigned char *data54) 
{
    cmah((uint8_t)address);
    cmm(0x50);
    for (uint8_t index = 0; index < 54; index++) {
        cmal(index);
        wait_us(1000);        
        *(data54 + index) = read(0xC0);
    }
}

void 
MAX7456::write_char_map(unsigned char address, const unsigned char *data54) 
{
    unsigned char index, c, match = 1;
    
    write(CMAH, address);
    write(CMM, 0x50);
    wait_us(20000);
    for (index = 0; index < 54; index++) {
        write(CMAL, index);
        c = read(0xC0);
        if (c != data54[index]) {
            match = 0;            
            break;
        }
    }
    
    if (!match) {   
        write(CMAH, address);
        for (index = 0; index < 0x36; index++) {
            write(CMAL, index);
            write(CMDI, data54[index]);
        }
        write(CMM, 0xA0);
        wait_us(20000);
        while ((read(0xA0) & 0x20) != 0x00);    
    }
}