Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX7456.c Source File

MAX7456.c

00001 /****************************************************************************
00002  *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
00003  *    
00004  *    This file is part of the Satellite Observers Workbench (SOWB).
00005  *
00006  *    SOWB is free software: you can redistribute it and/or modify
00007  *    it under the terms of the GNU General Public License as published by
00008  *    the Free Software Foundation, either version 3 of the License, or
00009  *    (at your option) any later version.
00010  *
00011  *    SOWB is distributed in the hope that it will be useful,
00012  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *    GNU General Public License for more details.
00015  *
00016  *    You should have received a copy of the GNU General Public License
00017  *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
00018  *
00019  *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
00020  *    
00021  ***************************************************************************/
00022 
00023 /*
00024     Design notes. 
00025     The MAX7456 is connected to SSP1 on the Mbed. Additionally, the vertical sync
00026     is connected to Pxx, horizontal sync to Pxx, LOS to Pxx, RST to Pxx. These IO
00027     pins are setup and macros made available via gpio.c and the interrupts (vsync)
00028     via gpioirq.c so for information regarding those see those modules.
00029 */
00030 
00031 #include "sowb.h"
00032 #include "gpio.h"
00033 #include "gpioirq.h"
00034 #include "utils.h"
00035 #include "user.h"
00036 #include "MAX7456.h"
00037 #include "MAX7456_chars.h"
00038 #include "debug.h"
00039 
00040 /* Forward local function prototypes. */
00041 static void SSP1_init(void);
00042 
00043 /* Declare the custom character map (CM) definitions.
00044    See MAX7456_chars.c for more details. */
00045 extern MAX7456_CUSTOM_CHAR custom_chars[];
00046 
00047 /* Map ASCII table to the MAX7456 character map.
00048    Note, the MAX7456 in-built character map is no where near the ascii
00049    table mapping and very few characters are abailable to map. Where 
00050    possible we create new characters for those we need that are missing
00051    from the MAX7456 that we want to use and also we create some special
00052    characters of our own that are not ASCII chars (crosshair for example).
00053    These additional character definitions are listed below the table. 
00054    Character maps we have create can be found in MAX7456_chars.c */
00055 const unsigned char MAX7456_ascii[256] = {
00056 
00057     /* Regular ASCII table. */
00058     /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
00059     /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00060     /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00061     /* 20 */ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x46,  0x3F, 0x40, 0x00, 0x4d, 0x45, 0x49, 0x41, 0x47, 
00062     /* 30 */ 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  0x08, 0x09, 0x44, 0x43, 0x4A, 0x00, 0x4B, 0x42,
00063     /* 40 */ 0x4C, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,  0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 
00064     /* 50 */ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0X1F, 0x20, 0x21,  0x22, 0x23, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 
00065     /* 60 */ 0x46, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,  0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
00066     /* 70 */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,  0x3C, 0x3D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 
00067     
00068     /* Extended ASCII table. */
00069     /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
00070     /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00071     /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00072     /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00073     /* B0 */ 0xB0, 0x00, 0x00, 0xB3, 0xB4, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF,   
00074     /* C0 */ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00075     /* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0xD9, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 
00076     /* E0 */ 0xe0, 0xe1, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
00077     /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00     
00078 };
00079 
00080 /** MAX7456_map_char
00081  *
00082  * Convert the supplied ASCII character to a MAX7456 character.
00083  * Note, the MAX7456 does not support all ASCII chars. Those it
00084  * cannot convert are converted to spaces. Proceedure is a simple
00085  * table look-up.
00086  *
00087  * @See const unsigned char MAX7456_ascii
00088  *
00089  * @param unsigned char c The character to convert.
00090  * @return unsigned char The converted character.
00091  */
00092 unsigned char MAX7456_map_char(unsigned char c) {
00093     return MAX7456_ascii[c];
00094 }
00095 
00096 /** MAX7456_init
00097  */
00098 void MAX7456_init(void) {
00099     
00100     /* Setup SSP1 to interface to the MAX7456 chip. */
00101     SSP1_init();
00102 
00103     DEBUG_INIT_START;
00104     
00105     /* Reset the MAX7456 device. */    
00106     MAX7456_RST_ASSERT;
00107     user_wait_ms_blocking(100);    
00108     MAX7456_RST_DEASSERT;
00109     user_wait_ms_blocking(100);
00110 
00111     /* Write the custom CM map. */
00112     MAX7456_write_byte(0, MAX7456_read_byte(0) & 0xF7);
00113     for (int index = 0; custom_chars[index].ascii != 0; index++) {
00114         MAX7456_write_char_map(custom_chars[index].ascii, custom_chars[index].map);
00115     }
00116     user_wait_ms_blocking(100);
00117 
00118     /* Change the vertical offset. */
00119     MAX7456_write_byte(0x3, 0x16);
00120     
00121     /* Enable display of OSD image. */
00122     MAX7456_write_byte(0x0, 0x48);
00123     
00124     DEBUG_INIT_END;
00125 }
00126 
00127 /** MAX7456_vsync_fall
00128  *
00129  * Interrupt handler for the vertical sync signal from the MAX7456 chip.
00130  * Note, this is called from gpioirq.c module which handles GPIO interrupts.
00131  */
00132 void osd_vsync(void);
00133 void MAX7456_vsync_fall(void) {
00134     osd_vsync();
00135 }
00136 
00137 /** MAX7456_vsync_rise
00138  *
00139  * Interrupt handler for the vertical sync signal from the MAX7456 chip.
00140  * Note, this is called from gpioirq.c module which handles GPIO interrupts.
00141  */
00142 void MAX7456_vsync_rise(void) {
00143     // Does nothing.
00144 }
00145 
00146 /** MAX7456_write_byte
00147  *
00148  * Used to write a byte to a specific address.
00149  * This function also doubles up to allow a byte
00150  * to be written without an address (less than 0x80)
00151  * and this is used to make 16bit transfer from two
00152  * 8bit transfers or to construct continuous 8bit
00153  * transfer where the MAX7456 auto-increments an 
00154  * internal location pointer on each write operation.
00155  *
00156  * Note, this function effectivly "blocks". However, the
00157  * speed of the SSP serial bus is pretty high to say the
00158  * least and experimentation has show it, so far, to have
00159  * had no adverse effects.
00160  *
00161  * @param unsigned char address The register address to write to.
00162  * @param unsigned char byte The byte to write to teh register.
00163  */
00164 void MAX7456_write_byte(unsigned char address, unsigned char byte) {
00165     volatile int dev_null __attribute__((unused));
00166     
00167     MAX7456_CS_ASSERT;
00168     
00169     /* MAX7456 addresses are always less than 0x80 so if the
00170        address is > 0x7F then the caller is requesting an direct
00171        8bit data transfer. */
00172     if (address < 0x80) {
00173         LPC_SSP1->DR = (uint32_t)(address & 0xFF);
00174         while(LPC_SSP1->SR & 0x10);     
00175         dev_null = LPC_SSP1->DR;            
00176     }
00177     
00178     LPC_SSP1->DR = (uint32_t)byte & 0xFF;
00179     while(LPC_SSP1->SR & 0x10); 
00180     dev_null = LPC_SSP1->DR;
00181             
00182     MAX7456_CS_DEASSERT;
00183 }
00184 
00185 /** MAX7456_read_byte
00186  *
00187  * Read a byte from a specific address.
00188  *
00189  * Note, this function effectivly "blocks". However, the
00190  * speed of the SSP serial bus is pretty high to say the
00191  * least and experimentation has show it, so far, to have
00192  * had no adverse effects.
00193  *
00194  * @param unsigned char address The address of the register to read.
00195  * @return int data The value of the register addressed.
00196  */
00197 int MAX7456_read_byte(unsigned char address) {
00198     int data;
00199 
00200     MAX7456_CS_ASSERT;
00201     
00202     LPC_SSP1->DR = (uint32_t)address & 0xFF;
00203     while(LPC_SSP1->SR & 0x10);
00204     data = LPC_SSP1->DR; /* Discarded. */
00205     
00206     LPC_SSP1->DR = 0;
00207     while(LPC_SSP1->SR & 0x10);
00208     data = LPC_SSP1->DR & 0xFF;
00209     
00210     MAX7456_CS_DEASSERT;
00211     
00212     return data;
00213 }
00214 
00215 /** MAX7456_cursor
00216  *
00217  * Move the MAX7456 "cursor" (next display memory write)
00218  * to the specified position.
00219  *
00220  * @param int x The X position.
00221  * @param int y The Y position.
00222  */
00223 void MAX7456_cursor(int x, int y) {
00224     int pos = (y * 30) + x;
00225     MAX7456_write_byte(0x05, (unsigned char)((pos >> 8) & 0xFF));
00226     MAX7456_write_byte(0x06, (unsigned char)(pos & 0xFF));
00227 }
00228 
00229 /** MAX7456_convert_string
00230  *
00231  * Convert the NULL terminated raw string to MAX7456 character set compat bytes.
00232  * Note, alters the string passed, doesn't make a copy of the string so cannot 
00233  * be a const value.
00234  *
00235  * @param unisgned char *s A pointer to the string to convert.
00236  */
00237 void MAX7456_convert_string(unsigned char *s) {
00238     while(*(s)) {
00239         *(s) = MAX7456_ascii[*(s)];
00240         s++;
00241     }
00242 }
00243 
00244 /** MAX7456_string
00245  *
00246  * Send the NULL terminated ASCII string to the display memory.
00247  *
00248  * @param unisgned char *s A pointer to the ASCII string to write.
00249  */
00250 void MAX7456_string(unsigned char *s) {
00251     MAX7456_write_byte(0x04, 0x01);  /* Enable 8bit write */
00252     while(*(s)) {
00253         MAX7456_write_byte(0x80, MAX7456_map_char(*s++));
00254     }
00255     MAX7456_write_byte(0x80, 0xFF);
00256 }
00257 
00258 /** MAX7456_stringl
00259  *
00260  * Send the ASCII string to the display memory. A null will terminate the write.
00261  *
00262  * @param int x The X position to write the string to.
00263  * @param int y The Y position to write the string to.
00264  * @param unisgned char *s A pointer to the string to write.
00265  * @param int len The length of the string to send.
00266  */
00267 void MAX7456_stringl(int x, int y, unsigned char *s, int len) {
00268     MAX7456_cursor(x, y);            
00269     MAX7456_write_byte(0x04, 0x01);  /* Enable 8bit write */
00270     while(len--) {
00271         if (*s == '\0') break;
00272         MAX7456_write_byte(0x80, MAX7456_map_char(*s++));
00273     }
00274     MAX7456_write_byte(0x80, 0xFF);
00275 }
00276 
00277 /** MAX7456_read_char_map
00278  *
00279  * Reads the 54byte character make-up bytes and stores them into a buffer.
00280  *
00281  */
00282 void MAX7456_read_char_map(unsigned char address, unsigned char *data54) {
00283     MAX7456_write_byte(0x9, address);
00284     MAX7456_write_byte(0x8, 0x50);
00285     user_wait_ms_blocking(100);
00286     for (int index = 0; index < 54; index++) {
00287         MAX7456_write_byte(0xA, index);
00288         user_wait_ms_blocking(1);
00289         *(data54 + index) = MAX7456_read_byte(0xC0);
00290     }
00291 }
00292 
00293 /** MAX7456_write_char_map
00294  *
00295  * Used to write the 54bytes that make up a character into
00296  * the MAX7456 CM non-volatile memory. Note, it tests the
00297  * current non-v memory against the supplied buffer and only
00298  * writes the buffer out if they don't match. Used to ensure
00299  * we don't keep writing the same data into non-v memory which
00300  * has a "lifetime" associated with it.
00301  *
00302  * @param unsigned char address The character address we are writing.
00303  * @param unsigned char *data54 An array that contains the 54bytes of CM data.
00304  */
00305 void MAX7456_write_char_map(unsigned char address, const unsigned char *data54) {
00306     unsigned char index, c, match = 1;
00307     
00308     MAX7456_write_byte(0x9, address);
00309     MAX7456_write_byte(0x8, 0x50);
00310     user_wait_ms_blocking(20);
00311     for (index = 0; index < 54; index++) {
00312         MAX7456_write_byte(0xA, index);
00313         c = MAX7456_read_byte(0xC0);
00314         if (c != data54[index]) {
00315             match = 0;            
00316             break;
00317         }
00318     }
00319     
00320     if (!match) {   
00321         MAX7456_write_byte(0x9, address);
00322         for (index = 0; index < 0x36; index++) {
00323             MAX7456_write_byte(0x0A, index);
00324             MAX7456_write_byte(0x0B, data54[index]);
00325         }
00326         MAX7456_write_byte(0x08, 0xA0);
00327         user_wait_ms_blocking(20);
00328         while ((MAX7456_read_byte(0xA0) & 0x20) != 0x00);    
00329     }
00330 }
00331 
00332 /** SSP1_init
00333  */
00334 static void SSP1_init(void) {
00335 
00336     DEBUG_INIT_START;
00337     
00338     /* The MAX7456 device is connected to SSP1 via the Mbed pins.
00339        So this init is about configuring just the SSP1, other
00340        MAX7456 signals (vsync, etc) are setup elsewhere although
00341        make call backs to this module as the "clearing house" for
00342        MAX7456 signals. */
00343     
00344     /* Enable the SSP1 peripheral. */
00345     LPC_SC->PCONP |= (1UL << 10);
00346 
00347     /* Select the clock required for SSP1. */    
00348     LPC_SC->PCLKSEL0  &= ~(3UL << 20);
00349     LPC_SC->PCLKSEL0  |=  (3UL << 20);
00350     
00351     /* Select the GPIO pins for the SSP1 functions. */
00352     /* SCK1 */
00353     LPC_PINCON->PINSEL0  &= ~(3UL << 14);
00354     LPC_PINCON->PINSEL0  |=  (2UL << 14);
00355     /* MISO1 */
00356     LPC_PINCON->PINSEL0  &= ~(3UL << 16);
00357     LPC_PINCON->PINSEL0  |=  (2UL << 16);
00358     /* MOSI1 */
00359     LPC_PINCON->PINSEL0  &= ~(3UL << 18);
00360     LPC_PINCON->PINSEL0  |=  (2UL << 18);
00361     
00362     /* Note, we don't use SSEL1 in our design, we just use a standard GPIO
00363        because a) the MAX7456 didn't really like the speed! and b) writing
00364        16bit data is somewhat simpler than reconfiguring the SSP each time
00365        when all we need to do is hold CS low across 2 8bit operations. */
00366     
00367     /* Setup the control registers for SSP1 */
00368     LPC_SSP1->CR0  = 0x7;
00369     LPC_SSP1->CPSR = 0x2;
00370     LPC_SSP1->CR1  = 0x2;
00371     
00372     DEBUG_INIT_END;
00373 }
00374