Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
u8g_dev_ssd1327_96x96_gr.c
00001 /* 00002 00003 u8g_dev_ssd1327_96x96_gr.c 00004 00005 2-Bit (graylevel) Driver for SSD1327 Controller (OLED Display) 00006 Tested with Seedstudio 96x96 Oled (LY120) 00007 http://www.seeedstudio.com/wiki/index.php?title=Twig_-_OLED_96x96 00008 00009 Universal 8bit Graphics Library 00010 00011 Copyright (c) 2012, olikraus@gmail.com 00012 All rights reserved. 00013 00014 Redistribution and use in source and binary forms, with or without modification, 00015 are permitted provided that the following conditions are met: 00016 00017 * Redistributions of source code must retain the above copyright notice, this list 00018 of conditions and the following disclaimer. 00019 00020 * Redistributions in binary form must reproduce the above copyright notice, this 00021 list of conditions and the following disclaimer in the documentation and/or other 00022 materials provided with the distribution. 00023 00024 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 00025 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 00026 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00027 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00028 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 00029 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00030 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00031 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00032 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00033 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00034 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00035 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 00036 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 00038 SSD130x Monochrom OLED Controller 00039 SSD131x Character OLED Controller 00040 SSD132x Graylevel OLED Controller 00041 SSD1331 Color OLED Controller 00042 00043 */ 00044 00045 #include "u8g.h" 00046 00047 #define WIDTH 96 00048 #define HEIGHT 96 00049 #define XOFFSET 8 00050 00051 /* 00052 http://www.seeedstudio.com/wiki/index.php?title=Twig_-_OLED_96x96 00053 */ 00054 static const uint8_t u8g_dev_ssd1327_2bit_96x96_init_seq[] PROGMEM = { 00055 U8G_ESC_DLY(10), /* delay 10 ms */ 00056 U8G_ESC_CS(0), /* disable chip */ 00057 U8G_ESC_ADR(0), /* instruction mode */ 00058 U8G_ESC_RST(1), /* do reset low pulse with (1*16)+2 milliseconds */ 00059 U8G_ESC_CS(1), /* enable chip */ 00060 0x0fd, 0x012, /* unlock display, usually not required because the display is unlocked after reset */ 00061 0x0ae, /* display off, sleep mode */ 00062 0x0a8, 0x05f, /* multiplex ratio: 0x05f * 1/64 duty */ 00063 0x0a1, 0x000, /* display start line */ 00064 0x0a2, 0x060, /* display offset, shift mapping ram counter */ 00065 //0x0a2, 0x04c, /* NHD: display offset, shift mapping ram counter */ 00066 0x0a0, 0x046, /* remap configuration, vertical address increment, enable nibble remap (upper nibble is left) */ 00067 //0x0a0, 0x056, /* NHD: remap configuration, vertical address increment, enable nibble remap (upper nibble is left) */ 00068 0x0ab, 0x001, /* Enable internal VDD regulator (RESET) */ 00069 0x081, 0x053, /* contrast, brightness, 0..128, Newhaven: 0x040, LY120 0x053, 0x070 seems also ok */ 00070 0x0b1, 0x051, /* phase length */ 00071 0x0b3, 0x001, /* set display clock divide ratio/oscillator frequency */ 00072 0x0b9, /* use linear lookup table */ 00073 #if 0 00074 0x0b8, /* set gray scale table */ 00075 //0x01, 0x011, 0x022, 0x032, 0x043, 0x054, 0x065, 0x076, 00076 0x01, 0x011, 0x022, 0x032, 0x043, 0x054, 0x077, 0x077, // 4L mode uses 0, 2, 4, 7 00077 #endif 00078 0x0bc, 0x008, /* pre-charge voltage level */ 00079 0x0be, 0x007, /* VCOMH voltage */ 00080 0x0b6, 0x001, /* second precharge */ 00081 0x0d5, 0x062, /* enable second precharge, internal vsl (bit0 = 0) */ 00082 00083 #if 0 00084 // the following commands are not used by the SeeedGrayOLED sequence */ 00085 0x0ad, 0x002, /* master configuration: disable embedded DC-DC, enable internal VCOMH */ 00086 0x086, /* full current range (0x084, 0x085, 0x086) */ 00087 0x0b2, 0x051, /* frame frequency (row period) */ 00088 0x0b4, 0x002, /* set pre-charge compensation level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */ 00089 0x0b0, 0x028, /* enable pre-charge compensation (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */ 00090 0x0bf, 0x002|0x00d, /* VSL voltage level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */ 00091 #endif 00092 00093 0x0a5, /* all pixel on */ 00094 //0x02e, /* no scroll (according to SeeedGrayOLED sequence) */ 00095 0x0af, /* display on */ 00096 U8G_ESC_DLY(100), /* delay 100 ms */ 00097 0x0a4, /* normal display mode */ 00098 U8G_ESC_DLY(100), /* delay 100 ms */ 00099 0x0a5, /* all pixel on */ 00100 0x0af, /* display on */ 00101 U8G_ESC_DLY(100), /* delay 100 ms */ 00102 0x0a4, /* normal display mode */ 00103 00104 0x015, /* column address... */ 00105 0x008, /* start at column 8, special for the LY120 ??? */ 00106 0x037, /* end at column 55, note: there are two pixel in one column */ 00107 00108 0x075, /* row address... */ 00109 0x008, 00110 0x05f, 00111 00112 U8G_ESC_ADR(1), /* data mode */ 00113 0x000f, 0x000f, 0x0000, 0x0000, 0x000f,0x000f,0x0000,0x0000, 00114 0x000f, 0x000f, 0x0000, 0x0000, 0x000f,0x000f,0x0000,0x0000, 00115 0x000f, 0x000f, 0x0000, 0x0000, 0x000f,0x000f,0x0000,0x0000, 00116 0x000f, 0x000f, 0x0000, 0x0000, 0x000f,0x000f,0x0000,0x0000, 00117 00118 U8G_ESC_CS(0), /* disable chip */ 00119 U8G_ESC_END /* end of sequence */ 00120 }; 00121 00122 static const uint8_t u8g_dev_ssd1327_2bit_96x96_prepare_page_seq[] PROGMEM = { 00123 U8G_ESC_ADR(0), /* instruction mode */ 00124 U8G_ESC_CS(1), /* enable chip */ 00125 0x015, /* column address... */ 00126 XOFFSET, /* start at column 8, special for the LY120 ??? */ 00127 0x037, /* end at column 55, note: there are two pixel in one column */ 00128 0x075, /* row address... */ 00129 U8G_ESC_END /* end of sequence */ 00130 }; 00131 00132 00133 static void u8g_dev_ssd1327_2bit_prepare_page(u8g_t *u8g, u8g_dev_t *dev) 00134 { 00135 uint8_t page = ((u8g_pb_t *)(dev->dev_mem))->p.page; 00136 00137 u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1327_2bit_96x96_prepare_page_seq); 00138 00139 page <<= 2; 00140 u8g_WriteByte(u8g, dev, page); /* start at the selected page */ 00141 page += 3; 00142 u8g_WriteByte(u8g, dev, page); /* end within the selected page */ 00143 00144 u8g_SetAddress(u8g, dev, 1); /* data mode */ 00145 } 00146 00147 static void u8g_dev_ssd1327_2bit_2x_prepare_page(u8g_t *u8g, u8g_dev_t *dev, uint8_t is_odd) 00148 { 00149 uint8_t page = ((u8g_pb_t *)(dev->dev_mem))->p.page; 00150 00151 u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1327_2bit_96x96_prepare_page_seq); 00152 00153 page <<= 1; 00154 page += is_odd; 00155 00156 page <<= 2; 00157 u8g_WriteByte(u8g, dev, page); /* start at the selected page */ 00158 page += 3; 00159 u8g_WriteByte(u8g, dev, page); /* end within the selected page */ 00160 00161 u8g_SetAddress(u8g, dev, 1); /* data mode */ 00162 } 00163 00164 /* assumes row autoincrement and activated nibble remap */ 00165 static void u8g_dev_ssd1327_2bit_write_4_pixel(u8g_t *u8g, u8g_dev_t *dev, uint8_t left, uint8_t right) 00166 { 00167 uint8_t d, tmp, cnt; 00168 static uint8_t buf[4]; 00169 buf[0] = 0; 00170 buf[1] = 0; 00171 buf[2] = 0; 00172 buf[3] = 0; 00173 cnt = 0; 00174 do 00175 { 00176 if ( left == 0 && right == 0 ) 00177 break; 00178 d = left; 00179 d &= 3; 00180 d <<= 4; 00181 tmp = right; 00182 tmp &= 3; 00183 d |= tmp; 00184 d <<= 2; 00185 buf[cnt] = d; 00186 left >>= 2; 00187 right >>= 2; 00188 cnt++; 00189 }while ( cnt < 4 ); 00190 u8g_WriteSequence(u8g, dev, 4, buf); 00191 } 00192 00193 static void u8g_dev_ssd1327_2bit_write_buffer(u8g_t *u8g, u8g_dev_t *dev) 00194 { 00195 uint8_t cnt, left, right; 00196 uint8_t *ptr; 00197 u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); 00198 00199 cnt = pb->width; 00200 cnt >>= 1; 00201 ptr = pb->buf; 00202 do 00203 { 00204 left = *ptr++; 00205 right = *ptr++; 00206 u8g_dev_ssd1327_2bit_write_4_pixel(u8g, dev, left, right); 00207 cnt--; 00208 } while( cnt > 0 ); 00209 } 00210 00211 static void u8g_dev_ssd1327_2bit_2x_write_buffer(u8g_t *u8g, u8g_dev_t *dev, uint8_t is_odd) 00212 { 00213 uint8_t cnt, left, right; 00214 uint8_t *ptr; 00215 u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); 00216 00217 ptr = pb->buf; 00218 cnt = pb->width; 00219 if ( is_odd ) 00220 ptr += cnt; 00221 cnt >>= 1; 00222 do 00223 { 00224 left = *ptr++; 00225 right = *ptr++; 00226 u8g_dev_ssd1327_2bit_write_4_pixel(u8g, dev, left, right); 00227 cnt--; 00228 } while( cnt > 0 ); 00229 } 00230 00231 uint8_t u8g_dev_ssd1327_96x96_gr_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) 00232 { 00233 switch(msg) 00234 { 00235 case U8G_DEV_MSG_INIT: 00236 u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); 00237 u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1327_2bit_96x96_init_seq); 00238 break; 00239 case U8G_DEV_MSG_STOP: 00240 break; 00241 case U8G_DEV_MSG_PAGE_NEXT: 00242 { 00243 u8g_dev_ssd1327_2bit_prepare_page(u8g, dev); 00244 u8g_dev_ssd1327_2bit_write_buffer(u8g, dev); 00245 u8g_SetChipSelect(u8g, dev, 0); 00246 } 00247 break; 00248 case U8G_DEV_MSG_CONTRAST: 00249 u8g_SetChipSelect(u8g, dev, 1); 00250 u8g_SetAddress(u8g, dev, 0); /* instruction mode */ 00251 u8g_WriteByte(u8g, dev, 0x081); 00252 u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 1); 00253 u8g_SetChipSelect(u8g, dev, 0); 00254 return 1; 00255 } 00256 return u8g_dev_pb8v2_base_fn(u8g, dev, msg, arg); 00257 } 00258 00259 uint8_t u8g_dev_ssd1327_96x96_2x_gr_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) 00260 { 00261 switch(msg) 00262 { 00263 case U8G_DEV_MSG_INIT: 00264 u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); 00265 u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1327_2bit_96x96_init_seq); 00266 break; 00267 case U8G_DEV_MSG_STOP: 00268 break; 00269 case U8G_DEV_MSG_PAGE_NEXT: 00270 { 00271 u8g_dev_ssd1327_2bit_2x_prepare_page(u8g, dev, 0); 00272 u8g_dev_ssd1327_2bit_2x_write_buffer(u8g, dev, 0); 00273 u8g_dev_ssd1327_2bit_2x_prepare_page(u8g, dev, 1); 00274 u8g_dev_ssd1327_2bit_2x_write_buffer(u8g, dev, 1); 00275 u8g_SetChipSelect(u8g, dev, 0); 00276 } 00277 break; 00278 case U8G_DEV_MSG_CONTRAST: 00279 u8g_SetChipSelect(u8g, dev, 1); 00280 u8g_SetAddress(u8g, dev, 0); /* instruction mode */ 00281 u8g_WriteByte(u8g, dev, 0x081); 00282 u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 1); 00283 u8g_SetChipSelect(u8g, dev, 0); 00284 return 1; 00285 } 00286 return u8g_dev_pb16v2_base_fn(u8g, dev, msg, arg); 00287 } 00288 00289 U8G_PB_DEV(u8g_dev_ssd1327_96x96_gr_sw_spi , WIDTH, HEIGHT, 4, u8g_dev_ssd1327_96x96_gr_fn, U8G_COM_SW_SPI); 00290 U8G_PB_DEV(u8g_dev_ssd1327_96x96_gr_hw_spi , WIDTH, HEIGHT, 4, u8g_dev_ssd1327_96x96_gr_fn, U8G_COM_HW_SPI); 00291 U8G_PB_DEV(u8g_dev_ssd1327_96x96_gr_i2c , WIDTH, HEIGHT, 4, u8g_dev_ssd1327_96x96_gr_fn, U8G_COM_SSD_I2C); 00292 00293 #define DWIDTH (2*WIDTH) 00294 uint8_t u8g_dev_ssd1327_96x96_2x_buf[DWIDTH] U8G_NOCOMMON ; 00295 u8g_pb_t u8g_dev_ssd1327_96x96_2x_pb = { {8, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_ssd1327_96x96_2x_buf}; 00296 u8g_dev_t u8g_dev_ssd1327_96x96_2x_gr_sw_spi = { u8g_dev_ssd1327_96x96_2x_gr_fn, &u8g_dev_ssd1327_96x96_2x_pb, U8G_COM_SW_SPI }; 00297 u8g_dev_t u8g_dev_ssd1327_96x96_2x_gr_hw_spi = { u8g_dev_ssd1327_96x96_2x_gr_fn, &u8g_dev_ssd1327_96x96_2x_pb, U8G_COM_HW_SPI }; 00298 u8g_dev_t u8g_dev_ssd1327_96x96_2x_gr_i2c = { u8g_dev_ssd1327_96x96_2x_gr_fn, &u8g_dev_ssd1327_96x96_2x_pb, U8G_COM_SSD_I2C }; 00299 00300
Generated on Tue Jul 12 2022 17:30:57 by
1.7.2