This module provides a simple API to the Maxim MAX7456 on-screen display chip
Diff: MAX7456.cpp
- Revision:
- 0:d7cd54ad4c3d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAX7456.cpp Tue Nov 16 10:47:25 2010 +0000 @@ -0,0 +1,303 @@ +/* + 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); + } +} + + +