Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
osd/MAX7456.c@0:0a841b89d614, 2010-10-11 (annotated)
- Committer:
- AjK
- Date:
- Mon Oct 11 10:34:55 2010 +0000
- Revision:
- 0:0a841b89d614
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AjK | 0:0a841b89d614 | 1 | /**************************************************************************** |
AjK | 0:0a841b89d614 | 2 | * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd |
AjK | 0:0a841b89d614 | 3 | * |
AjK | 0:0a841b89d614 | 4 | * This file is part of the Satellite Observers Workbench (SOWB). |
AjK | 0:0a841b89d614 | 5 | * |
AjK | 0:0a841b89d614 | 6 | * SOWB is free software: you can redistribute it and/or modify |
AjK | 0:0a841b89d614 | 7 | * it under the terms of the GNU General Public License as published by |
AjK | 0:0a841b89d614 | 8 | * the Free Software Foundation, either version 3 of the License, or |
AjK | 0:0a841b89d614 | 9 | * (at your option) any later version. |
AjK | 0:0a841b89d614 | 10 | * |
AjK | 0:0a841b89d614 | 11 | * SOWB is distributed in the hope that it will be useful, |
AjK | 0:0a841b89d614 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
AjK | 0:0a841b89d614 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
AjK | 0:0a841b89d614 | 14 | * GNU General Public License for more details. |
AjK | 0:0a841b89d614 | 15 | * |
AjK | 0:0a841b89d614 | 16 | * You should have received a copy of the GNU General Public License |
AjK | 0:0a841b89d614 | 17 | * along with SOWB. If not, see <http://www.gnu.org/licenses/>. |
AjK | 0:0a841b89d614 | 18 | * |
AjK | 0:0a841b89d614 | 19 | * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $ |
AjK | 0:0a841b89d614 | 20 | * |
AjK | 0:0a841b89d614 | 21 | ***************************************************************************/ |
AjK | 0:0a841b89d614 | 22 | |
AjK | 0:0a841b89d614 | 23 | /* |
AjK | 0:0a841b89d614 | 24 | Design notes. |
AjK | 0:0a841b89d614 | 25 | The MAX7456 is connected to SSP1 on the Mbed. Additionally, the vertical sync |
AjK | 0:0a841b89d614 | 26 | is connected to Pxx, horizontal sync to Pxx, LOS to Pxx, RST to Pxx. These IO |
AjK | 0:0a841b89d614 | 27 | pins are setup and macros made available via gpio.c and the interrupts (vsync) |
AjK | 0:0a841b89d614 | 28 | via gpioirq.c so for information regarding those see those modules. |
AjK | 0:0a841b89d614 | 29 | */ |
AjK | 0:0a841b89d614 | 30 | |
AjK | 0:0a841b89d614 | 31 | #include "sowb.h" |
AjK | 0:0a841b89d614 | 32 | #include "gpio.h" |
AjK | 0:0a841b89d614 | 33 | #include "gpioirq.h" |
AjK | 0:0a841b89d614 | 34 | #include "utils.h" |
AjK | 0:0a841b89d614 | 35 | #include "user.h" |
AjK | 0:0a841b89d614 | 36 | #include "MAX7456.h" |
AjK | 0:0a841b89d614 | 37 | #include "MAX7456_chars.h" |
AjK | 0:0a841b89d614 | 38 | #include "debug.h" |
AjK | 0:0a841b89d614 | 39 | |
AjK | 0:0a841b89d614 | 40 | /* Forward local function prototypes. */ |
AjK | 0:0a841b89d614 | 41 | static void SSP1_init(void); |
AjK | 0:0a841b89d614 | 42 | |
AjK | 0:0a841b89d614 | 43 | /* Declare the custom character map (CM) definitions. |
AjK | 0:0a841b89d614 | 44 | See MAX7456_chars.c for more details. */ |
AjK | 0:0a841b89d614 | 45 | extern MAX7456_CUSTOM_CHAR custom_chars[]; |
AjK | 0:0a841b89d614 | 46 | |
AjK | 0:0a841b89d614 | 47 | /* Map ASCII table to the MAX7456 character map. |
AjK | 0:0a841b89d614 | 48 | Note, the MAX7456 in-built character map is no where near the ascii |
AjK | 0:0a841b89d614 | 49 | table mapping and very few characters are abailable to map. Where |
AjK | 0:0a841b89d614 | 50 | possible we create new characters for those we need that are missing |
AjK | 0:0a841b89d614 | 51 | from the MAX7456 that we want to use and also we create some special |
AjK | 0:0a841b89d614 | 52 | characters of our own that are not ASCII chars (crosshair for example). |
AjK | 0:0a841b89d614 | 53 | These additional character definitions are listed below the table. |
AjK | 0:0a841b89d614 | 54 | Character maps we have create can be found in MAX7456_chars.c */ |
AjK | 0:0a841b89d614 | 55 | const unsigned char MAX7456_ascii[256] = { |
AjK | 0:0a841b89d614 | 56 | |
AjK | 0:0a841b89d614 | 57 | /* Regular ASCII table. */ |
AjK | 0:0a841b89d614 | 58 | /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ |
AjK | 0:0a841b89d614 | 59 | /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 60 | /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 61 | /* 20 */ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x46, 0x3F, 0x40, 0x00, 0x4d, 0x45, 0x49, 0x41, 0x47, |
AjK | 0:0a841b89d614 | 62 | /* 30 */ 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x44, 0x43, 0x4A, 0x00, 0x4B, 0x42, |
AjK | 0:0a841b89d614 | 63 | /* 40 */ 0x4C, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, |
AjK | 0:0a841b89d614 | 64 | /* 50 */ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0X1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 65 | /* 60 */ 0x46, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, |
AjK | 0:0a841b89d614 | 66 | /* 70 */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 67 | |
AjK | 0:0a841b89d614 | 68 | /* Extended ASCII table. */ |
AjK | 0:0a841b89d614 | 69 | /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ |
AjK | 0:0a841b89d614 | 70 | /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 71 | /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 72 | /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 73 | /* B0 */ 0xB0, 0x00, 0x00, 0xB3, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, |
AjK | 0:0a841b89d614 | 74 | /* C0 */ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 75 | /* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 76 | /* E0 */ 0xe0, 0xe1, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
AjK | 0:0a841b89d614 | 77 | /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
AjK | 0:0a841b89d614 | 78 | }; |
AjK | 0:0a841b89d614 | 79 | |
AjK | 0:0a841b89d614 | 80 | /** MAX7456_map_char |
AjK | 0:0a841b89d614 | 81 | * |
AjK | 0:0a841b89d614 | 82 | * Convert the supplied ASCII character to a MAX7456 character. |
AjK | 0:0a841b89d614 | 83 | * Note, the MAX7456 does not support all ASCII chars. Those it |
AjK | 0:0a841b89d614 | 84 | * cannot convert are converted to spaces. Proceedure is a simple |
AjK | 0:0a841b89d614 | 85 | * table look-up. |
AjK | 0:0a841b89d614 | 86 | * |
AjK | 0:0a841b89d614 | 87 | * @See const unsigned char MAX7456_ascii |
AjK | 0:0a841b89d614 | 88 | * |
AjK | 0:0a841b89d614 | 89 | * @param unsigned char c The character to convert. |
AjK | 0:0a841b89d614 | 90 | * @return unsigned char The converted character. |
AjK | 0:0a841b89d614 | 91 | */ |
AjK | 0:0a841b89d614 | 92 | unsigned char MAX7456_map_char(unsigned char c) { |
AjK | 0:0a841b89d614 | 93 | return MAX7456_ascii[c]; |
AjK | 0:0a841b89d614 | 94 | } |
AjK | 0:0a841b89d614 | 95 | |
AjK | 0:0a841b89d614 | 96 | /** MAX7456_init |
AjK | 0:0a841b89d614 | 97 | */ |
AjK | 0:0a841b89d614 | 98 | void MAX7456_init(void) { |
AjK | 0:0a841b89d614 | 99 | |
AjK | 0:0a841b89d614 | 100 | /* Setup SSP1 to interface to the MAX7456 chip. */ |
AjK | 0:0a841b89d614 | 101 | SSP1_init(); |
AjK | 0:0a841b89d614 | 102 | |
AjK | 0:0a841b89d614 | 103 | DEBUG_INIT_START; |
AjK | 0:0a841b89d614 | 104 | |
AjK | 0:0a841b89d614 | 105 | /* Reset the MAX7456 device. */ |
AjK | 0:0a841b89d614 | 106 | MAX7456_RST_ASSERT; |
AjK | 0:0a841b89d614 | 107 | user_wait_ms_blocking(100); |
AjK | 0:0a841b89d614 | 108 | MAX7456_RST_DEASSERT; |
AjK | 0:0a841b89d614 | 109 | user_wait_ms_blocking(100); |
AjK | 0:0a841b89d614 | 110 | |
AjK | 0:0a841b89d614 | 111 | /* Write the custom CM map. */ |
AjK | 0:0a841b89d614 | 112 | MAX7456_write_byte(0, MAX7456_read_byte(0) & 0xF7); |
AjK | 0:0a841b89d614 | 113 | for (int index = 0; custom_chars[index].ascii != 0; index++) { |
AjK | 0:0a841b89d614 | 114 | MAX7456_write_char_map(custom_chars[index].ascii, custom_chars[index].map); |
AjK | 0:0a841b89d614 | 115 | } |
AjK | 0:0a841b89d614 | 116 | user_wait_ms_blocking(100); |
AjK | 0:0a841b89d614 | 117 | |
AjK | 0:0a841b89d614 | 118 | /* Change the vertical offset. */ |
AjK | 0:0a841b89d614 | 119 | MAX7456_write_byte(0x3, 0x16); |
AjK | 0:0a841b89d614 | 120 | |
AjK | 0:0a841b89d614 | 121 | /* Enable display of OSD image. */ |
AjK | 0:0a841b89d614 | 122 | MAX7456_write_byte(0x0, 0x48); |
AjK | 0:0a841b89d614 | 123 | |
AjK | 0:0a841b89d614 | 124 | DEBUG_INIT_END; |
AjK | 0:0a841b89d614 | 125 | } |
AjK | 0:0a841b89d614 | 126 | |
AjK | 0:0a841b89d614 | 127 | /** MAX7456_vsync_fall |
AjK | 0:0a841b89d614 | 128 | * |
AjK | 0:0a841b89d614 | 129 | * Interrupt handler for the vertical sync signal from the MAX7456 chip. |
AjK | 0:0a841b89d614 | 130 | * Note, this is called from gpioirq.c module which handles GPIO interrupts. |
AjK | 0:0a841b89d614 | 131 | */ |
AjK | 0:0a841b89d614 | 132 | void osd_vsync(void); |
AjK | 0:0a841b89d614 | 133 | void MAX7456_vsync_fall(void) { |
AjK | 0:0a841b89d614 | 134 | osd_vsync(); |
AjK | 0:0a841b89d614 | 135 | } |
AjK | 0:0a841b89d614 | 136 | |
AjK | 0:0a841b89d614 | 137 | /** MAX7456_vsync_rise |
AjK | 0:0a841b89d614 | 138 | * |
AjK | 0:0a841b89d614 | 139 | * Interrupt handler for the vertical sync signal from the MAX7456 chip. |
AjK | 0:0a841b89d614 | 140 | * Note, this is called from gpioirq.c module which handles GPIO interrupts. |
AjK | 0:0a841b89d614 | 141 | */ |
AjK | 0:0a841b89d614 | 142 | void MAX7456_vsync_rise(void) { |
AjK | 0:0a841b89d614 | 143 | // Does nothing. |
AjK | 0:0a841b89d614 | 144 | } |
AjK | 0:0a841b89d614 | 145 | |
AjK | 0:0a841b89d614 | 146 | /** MAX7456_write_byte |
AjK | 0:0a841b89d614 | 147 | * |
AjK | 0:0a841b89d614 | 148 | * Used to write a byte to a specific address. |
AjK | 0:0a841b89d614 | 149 | * This function also doubles up to allow a byte |
AjK | 0:0a841b89d614 | 150 | * to be written without an address (less than 0x80) |
AjK | 0:0a841b89d614 | 151 | * and this is used to make 16bit transfer from two |
AjK | 0:0a841b89d614 | 152 | * 8bit transfers or to construct continuous 8bit |
AjK | 0:0a841b89d614 | 153 | * transfer where the MAX7456 auto-increments an |
AjK | 0:0a841b89d614 | 154 | * internal location pointer on each write operation. |
AjK | 0:0a841b89d614 | 155 | * |
AjK | 0:0a841b89d614 | 156 | * Note, this function effectivly "blocks". However, the |
AjK | 0:0a841b89d614 | 157 | * speed of the SSP serial bus is pretty high to say the |
AjK | 0:0a841b89d614 | 158 | * least and experimentation has show it, so far, to have |
AjK | 0:0a841b89d614 | 159 | * had no adverse effects. |
AjK | 0:0a841b89d614 | 160 | * |
AjK | 0:0a841b89d614 | 161 | * @param unsigned char address The register address to write to. |
AjK | 0:0a841b89d614 | 162 | * @param unsigned char byte The byte to write to teh register. |
AjK | 0:0a841b89d614 | 163 | */ |
AjK | 0:0a841b89d614 | 164 | void MAX7456_write_byte(unsigned char address, unsigned char byte) { |
AjK | 0:0a841b89d614 | 165 | volatile int dev_null __attribute__((unused)); |
AjK | 0:0a841b89d614 | 166 | |
AjK | 0:0a841b89d614 | 167 | MAX7456_CS_ASSERT; |
AjK | 0:0a841b89d614 | 168 | |
AjK | 0:0a841b89d614 | 169 | /* MAX7456 addresses are always less than 0x80 so if the |
AjK | 0:0a841b89d614 | 170 | address is > 0x7F then the caller is requesting an direct |
AjK | 0:0a841b89d614 | 171 | 8bit data transfer. */ |
AjK | 0:0a841b89d614 | 172 | if (address < 0x80) { |
AjK | 0:0a841b89d614 | 173 | LPC_SSP1->DR = (uint32_t)(address & 0xFF); |
AjK | 0:0a841b89d614 | 174 | while(LPC_SSP1->SR & 0x10); |
AjK | 0:0a841b89d614 | 175 | dev_null = LPC_SSP1->DR; |
AjK | 0:0a841b89d614 | 176 | } |
AjK | 0:0a841b89d614 | 177 | |
AjK | 0:0a841b89d614 | 178 | LPC_SSP1->DR = (uint32_t)byte & 0xFF; |
AjK | 0:0a841b89d614 | 179 | while(LPC_SSP1->SR & 0x10); |
AjK | 0:0a841b89d614 | 180 | dev_null = LPC_SSP1->DR; |
AjK | 0:0a841b89d614 | 181 | |
AjK | 0:0a841b89d614 | 182 | MAX7456_CS_DEASSERT; |
AjK | 0:0a841b89d614 | 183 | } |
AjK | 0:0a841b89d614 | 184 | |
AjK | 0:0a841b89d614 | 185 | /** MAX7456_read_byte |
AjK | 0:0a841b89d614 | 186 | * |
AjK | 0:0a841b89d614 | 187 | * Read a byte from a specific address. |
AjK | 0:0a841b89d614 | 188 | * |
AjK | 0:0a841b89d614 | 189 | * Note, this function effectivly "blocks". However, the |
AjK | 0:0a841b89d614 | 190 | * speed of the SSP serial bus is pretty high to say the |
AjK | 0:0a841b89d614 | 191 | * least and experimentation has show it, so far, to have |
AjK | 0:0a841b89d614 | 192 | * had no adverse effects. |
AjK | 0:0a841b89d614 | 193 | * |
AjK | 0:0a841b89d614 | 194 | * @param unsigned char address The address of the register to read. |
AjK | 0:0a841b89d614 | 195 | * @return int data The value of the register addressed. |
AjK | 0:0a841b89d614 | 196 | */ |
AjK | 0:0a841b89d614 | 197 | int MAX7456_read_byte(unsigned char address) { |
AjK | 0:0a841b89d614 | 198 | int data; |
AjK | 0:0a841b89d614 | 199 | |
AjK | 0:0a841b89d614 | 200 | MAX7456_CS_ASSERT; |
AjK | 0:0a841b89d614 | 201 | |
AjK | 0:0a841b89d614 | 202 | LPC_SSP1->DR = (uint32_t)address & 0xFF; |
AjK | 0:0a841b89d614 | 203 | while(LPC_SSP1->SR & 0x10); |
AjK | 0:0a841b89d614 | 204 | data = LPC_SSP1->DR; /* Discarded. */ |
AjK | 0:0a841b89d614 | 205 | |
AjK | 0:0a841b89d614 | 206 | LPC_SSP1->DR = 0; |
AjK | 0:0a841b89d614 | 207 | while(LPC_SSP1->SR & 0x10); |
AjK | 0:0a841b89d614 | 208 | data = LPC_SSP1->DR & 0xFF; |
AjK | 0:0a841b89d614 | 209 | |
AjK | 0:0a841b89d614 | 210 | MAX7456_CS_DEASSERT; |
AjK | 0:0a841b89d614 | 211 | |
AjK | 0:0a841b89d614 | 212 | return data; |
AjK | 0:0a841b89d614 | 213 | } |
AjK | 0:0a841b89d614 | 214 | |
AjK | 0:0a841b89d614 | 215 | /** MAX7456_cursor |
AjK | 0:0a841b89d614 | 216 | * |
AjK | 0:0a841b89d614 | 217 | * Move the MAX7456 "cursor" (next display memory write) |
AjK | 0:0a841b89d614 | 218 | * to the specified position. |
AjK | 0:0a841b89d614 | 219 | * |
AjK | 0:0a841b89d614 | 220 | * @param int x The X position. |
AjK | 0:0a841b89d614 | 221 | * @param int y The Y position. |
AjK | 0:0a841b89d614 | 222 | */ |
AjK | 0:0a841b89d614 | 223 | void MAX7456_cursor(int x, int y) { |
AjK | 0:0a841b89d614 | 224 | int pos = (y * 30) + x; |
AjK | 0:0a841b89d614 | 225 | MAX7456_write_byte(0x05, (unsigned char)((pos >> 8) & 0xFF)); |
AjK | 0:0a841b89d614 | 226 | MAX7456_write_byte(0x06, (unsigned char)(pos & 0xFF)); |
AjK | 0:0a841b89d614 | 227 | } |
AjK | 0:0a841b89d614 | 228 | |
AjK | 0:0a841b89d614 | 229 | /** MAX7456_convert_string |
AjK | 0:0a841b89d614 | 230 | * |
AjK | 0:0a841b89d614 | 231 | * Convert the NULL terminated raw string to MAX7456 character set compat bytes. |
AjK | 0:0a841b89d614 | 232 | * Note, alters the string passed, doesn't make a copy of the string so cannot |
AjK | 0:0a841b89d614 | 233 | * be a const value. |
AjK | 0:0a841b89d614 | 234 | * |
AjK | 0:0a841b89d614 | 235 | * @param unisgned char *s A pointer to the string to convert. |
AjK | 0:0a841b89d614 | 236 | */ |
AjK | 0:0a841b89d614 | 237 | void MAX7456_convert_string(unsigned char *s) { |
AjK | 0:0a841b89d614 | 238 | while(*(s)) { |
AjK | 0:0a841b89d614 | 239 | *(s) = MAX7456_ascii[*(s)]; |
AjK | 0:0a841b89d614 | 240 | s++; |
AjK | 0:0a841b89d614 | 241 | } |
AjK | 0:0a841b89d614 | 242 | } |
AjK | 0:0a841b89d614 | 243 | |
AjK | 0:0a841b89d614 | 244 | /** MAX7456_string |
AjK | 0:0a841b89d614 | 245 | * |
AjK | 0:0a841b89d614 | 246 | * Send the NULL terminated ASCII string to the display memory. |
AjK | 0:0a841b89d614 | 247 | * |
AjK | 0:0a841b89d614 | 248 | * @param unisgned char *s A pointer to the ASCII string to write. |
AjK | 0:0a841b89d614 | 249 | */ |
AjK | 0:0a841b89d614 | 250 | void MAX7456_string(unsigned char *s) { |
AjK | 0:0a841b89d614 | 251 | MAX7456_write_byte(0x04, 0x01); /* Enable 8bit write */ |
AjK | 0:0a841b89d614 | 252 | while(*(s)) { |
AjK | 0:0a841b89d614 | 253 | MAX7456_write_byte(0x80, MAX7456_map_char(*s++)); |
AjK | 0:0a841b89d614 | 254 | } |
AjK | 0:0a841b89d614 | 255 | MAX7456_write_byte(0x80, 0xFF); |
AjK | 0:0a841b89d614 | 256 | } |
AjK | 0:0a841b89d614 | 257 | |
AjK | 0:0a841b89d614 | 258 | /** MAX7456_stringl |
AjK | 0:0a841b89d614 | 259 | * |
AjK | 0:0a841b89d614 | 260 | * Send the ASCII string to the display memory. A null will terminate the write. |
AjK | 0:0a841b89d614 | 261 | * |
AjK | 0:0a841b89d614 | 262 | * @param int x The X position to write the string to. |
AjK | 0:0a841b89d614 | 263 | * @param int y The Y position to write the string to. |
AjK | 0:0a841b89d614 | 264 | * @param unisgned char *s A pointer to the string to write. |
AjK | 0:0a841b89d614 | 265 | * @param int len The length of the string to send. |
AjK | 0:0a841b89d614 | 266 | */ |
AjK | 0:0a841b89d614 | 267 | void MAX7456_stringl(int x, int y, unsigned char *s, int len) { |
AjK | 0:0a841b89d614 | 268 | MAX7456_cursor(x, y); |
AjK | 0:0a841b89d614 | 269 | MAX7456_write_byte(0x04, 0x01); /* Enable 8bit write */ |
AjK | 0:0a841b89d614 | 270 | while(len--) { |
AjK | 0:0a841b89d614 | 271 | if (*s == '\0') break; |
AjK | 0:0a841b89d614 | 272 | MAX7456_write_byte(0x80, MAX7456_map_char(*s++)); |
AjK | 0:0a841b89d614 | 273 | } |
AjK | 0:0a841b89d614 | 274 | MAX7456_write_byte(0x80, 0xFF); |
AjK | 0:0a841b89d614 | 275 | } |
AjK | 0:0a841b89d614 | 276 | |
AjK | 0:0a841b89d614 | 277 | /** MAX7456_read_char_map |
AjK | 0:0a841b89d614 | 278 | * |
AjK | 0:0a841b89d614 | 279 | * Reads the 54byte character make-up bytes and stores them into a buffer. |
AjK | 0:0a841b89d614 | 280 | * |
AjK | 0:0a841b89d614 | 281 | */ |
AjK | 0:0a841b89d614 | 282 | void MAX7456_read_char_map(unsigned char address, unsigned char *data54) { |
AjK | 0:0a841b89d614 | 283 | MAX7456_write_byte(0x9, address); |
AjK | 0:0a841b89d614 | 284 | MAX7456_write_byte(0x8, 0x50); |
AjK | 0:0a841b89d614 | 285 | user_wait_ms_blocking(100); |
AjK | 0:0a841b89d614 | 286 | for (int index = 0; index < 54; index++) { |
AjK | 0:0a841b89d614 | 287 | MAX7456_write_byte(0xA, index); |
AjK | 0:0a841b89d614 | 288 | user_wait_ms_blocking(1); |
AjK | 0:0a841b89d614 | 289 | *(data54 + index) = MAX7456_read_byte(0xC0); |
AjK | 0:0a841b89d614 | 290 | } |
AjK | 0:0a841b89d614 | 291 | } |
AjK | 0:0a841b89d614 | 292 | |
AjK | 0:0a841b89d614 | 293 | /** MAX7456_write_char_map |
AjK | 0:0a841b89d614 | 294 | * |
AjK | 0:0a841b89d614 | 295 | * Used to write the 54bytes that make up a character into |
AjK | 0:0a841b89d614 | 296 | * the MAX7456 CM non-volatile memory. Note, it tests the |
AjK | 0:0a841b89d614 | 297 | * current non-v memory against the supplied buffer and only |
AjK | 0:0a841b89d614 | 298 | * writes the buffer out if they don't match. Used to ensure |
AjK | 0:0a841b89d614 | 299 | * we don't keep writing the same data into non-v memory which |
AjK | 0:0a841b89d614 | 300 | * has a "lifetime" associated with it. |
AjK | 0:0a841b89d614 | 301 | * |
AjK | 0:0a841b89d614 | 302 | * @param unsigned char address The character address we are writing. |
AjK | 0:0a841b89d614 | 303 | * @param unsigned char *data54 An array that contains the 54bytes of CM data. |
AjK | 0:0a841b89d614 | 304 | */ |
AjK | 0:0a841b89d614 | 305 | void MAX7456_write_char_map(unsigned char address, const unsigned char *data54) { |
AjK | 0:0a841b89d614 | 306 | unsigned char index, c, match = 1; |
AjK | 0:0a841b89d614 | 307 | |
AjK | 0:0a841b89d614 | 308 | MAX7456_write_byte(0x9, address); |
AjK | 0:0a841b89d614 | 309 | MAX7456_write_byte(0x8, 0x50); |
AjK | 0:0a841b89d614 | 310 | user_wait_ms_blocking(20); |
AjK | 0:0a841b89d614 | 311 | for (index = 0; index < 54; index++) { |
AjK | 0:0a841b89d614 | 312 | MAX7456_write_byte(0xA, index); |
AjK | 0:0a841b89d614 | 313 | c = MAX7456_read_byte(0xC0); |
AjK | 0:0a841b89d614 | 314 | if (c != data54[index]) { |
AjK | 0:0a841b89d614 | 315 | match = 0; |
AjK | 0:0a841b89d614 | 316 | break; |
AjK | 0:0a841b89d614 | 317 | } |
AjK | 0:0a841b89d614 | 318 | } |
AjK | 0:0a841b89d614 | 319 | |
AjK | 0:0a841b89d614 | 320 | if (!match) { |
AjK | 0:0a841b89d614 | 321 | MAX7456_write_byte(0x9, address); |
AjK | 0:0a841b89d614 | 322 | for (index = 0; index < 0x36; index++) { |
AjK | 0:0a841b89d614 | 323 | MAX7456_write_byte(0x0A, index); |
AjK | 0:0a841b89d614 | 324 | MAX7456_write_byte(0x0B, data54[index]); |
AjK | 0:0a841b89d614 | 325 | } |
AjK | 0:0a841b89d614 | 326 | MAX7456_write_byte(0x08, 0xA0); |
AjK | 0:0a841b89d614 | 327 | user_wait_ms_blocking(20); |
AjK | 0:0a841b89d614 | 328 | while ((MAX7456_read_byte(0xA0) & 0x20) != 0x00); |
AjK | 0:0a841b89d614 | 329 | } |
AjK | 0:0a841b89d614 | 330 | } |
AjK | 0:0a841b89d614 | 331 | |
AjK | 0:0a841b89d614 | 332 | /** SSP1_init |
AjK | 0:0a841b89d614 | 333 | */ |
AjK | 0:0a841b89d614 | 334 | static void SSP1_init(void) { |
AjK | 0:0a841b89d614 | 335 | |
AjK | 0:0a841b89d614 | 336 | DEBUG_INIT_START; |
AjK | 0:0a841b89d614 | 337 | |
AjK | 0:0a841b89d614 | 338 | /* The MAX7456 device is connected to SSP1 via the Mbed pins. |
AjK | 0:0a841b89d614 | 339 | So this init is about configuring just the SSP1, other |
AjK | 0:0a841b89d614 | 340 | MAX7456 signals (vsync, etc) are setup elsewhere although |
AjK | 0:0a841b89d614 | 341 | make call backs to this module as the "clearing house" for |
AjK | 0:0a841b89d614 | 342 | MAX7456 signals. */ |
AjK | 0:0a841b89d614 | 343 | |
AjK | 0:0a841b89d614 | 344 | /* Enable the SSP1 peripheral. */ |
AjK | 0:0a841b89d614 | 345 | LPC_SC->PCONP |= (1UL << 10); |
AjK | 0:0a841b89d614 | 346 | |
AjK | 0:0a841b89d614 | 347 | /* Select the clock required for SSP1. */ |
AjK | 0:0a841b89d614 | 348 | LPC_SC->PCLKSEL0 &= ~(3UL << 20); |
AjK | 0:0a841b89d614 | 349 | LPC_SC->PCLKSEL0 |= (3UL << 20); |
AjK | 0:0a841b89d614 | 350 | |
AjK | 0:0a841b89d614 | 351 | /* Select the GPIO pins for the SSP1 functions. */ |
AjK | 0:0a841b89d614 | 352 | /* SCK1 */ |
AjK | 0:0a841b89d614 | 353 | LPC_PINCON->PINSEL0 &= ~(3UL << 14); |
AjK | 0:0a841b89d614 | 354 | LPC_PINCON->PINSEL0 |= (2UL << 14); |
AjK | 0:0a841b89d614 | 355 | /* MISO1 */ |
AjK | 0:0a841b89d614 | 356 | LPC_PINCON->PINSEL0 &= ~(3UL << 16); |
AjK | 0:0a841b89d614 | 357 | LPC_PINCON->PINSEL0 |= (2UL << 16); |
AjK | 0:0a841b89d614 | 358 | /* MOSI1 */ |
AjK | 0:0a841b89d614 | 359 | LPC_PINCON->PINSEL0 &= ~(3UL << 18); |
AjK | 0:0a841b89d614 | 360 | LPC_PINCON->PINSEL0 |= (2UL << 18); |
AjK | 0:0a841b89d614 | 361 | |
AjK | 0:0a841b89d614 | 362 | /* Note, we don't use SSEL1 in our design, we just use a standard GPIO |
AjK | 0:0a841b89d614 | 363 | because a) the MAX7456 didn't really like the speed! and b) writing |
AjK | 0:0a841b89d614 | 364 | 16bit data is somewhat simpler than reconfiguring the SSP each time |
AjK | 0:0a841b89d614 | 365 | when all we need to do is hold CS low across 2 8bit operations. */ |
AjK | 0:0a841b89d614 | 366 | |
AjK | 0:0a841b89d614 | 367 | /* Setup the control registers for SSP1 */ |
AjK | 0:0a841b89d614 | 368 | LPC_SSP1->CR0 = 0x7; |
AjK | 0:0a841b89d614 | 369 | LPC_SSP1->CPSR = 0x2; |
AjK | 0:0a841b89d614 | 370 | LPC_SSP1->CR1 = 0x2; |
AjK | 0:0a841b89d614 | 371 | |
AjK | 0:0a841b89d614 | 372 | DEBUG_INIT_END; |
AjK | 0:0a841b89d614 | 373 | } |
AjK | 0:0a841b89d614 | 374 |