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.
Fork of Smoothie by
ST7565.cpp
00001 /* 00002 * ST7565.cpp 00003 * 00004 * Created on: 21-06-2013 00005 * Author: Wulfnor 00006 */ 00007 00008 #include "ST7565.h" 00009 #include "ST7565/glcdfont.h" 00010 #include "Kernel.h" 00011 #include "platform_memory.h" 00012 00013 //definitions for lcd 00014 #define LCDWIDTH 128 00015 #define LCDHEIGHT 64 00016 #define LCDPAGES (LCDHEIGHT+7)/8 00017 #define FB_SIZE LCDWIDTH*LCDPAGES 00018 #define FONT_SIZE_X 6 00019 #define FONT_SIZE_Y 8 00020 00021 #define panel_checksum CHECKSUM("panel") 00022 #define spi_channel_checksum CHECKSUM("spi_channel") 00023 #define spi_cs_pin_checksum CHECKSUM("spi_cs_pin") 00024 #define spi_frequency_checksum CHECKSUM("spi_frequency") 00025 #define encoder_a_pin_checksum CHECKSUM("encoder_a_pin") 00026 #define encoder_b_pin_checksum CHECKSUM("encoder_b_pin") 00027 #define click_button_pin_checksum CHECKSUM("click_button_pin") 00028 #define up_button_pin_checksum CHECKSUM("up_button_pin") 00029 #define down_button_pin_checksum CHECKSUM("down_button_pin") 00030 #define contrast_checksum CHECKSUM("contrast") 00031 #define reverse_checksum CHECKSUM("reverse") 00032 #define rst_pin_checksum CHECKSUM("rst_pin") 00033 #define a0_pin_checksum CHECKSUM("a0_pin") 00034 00035 #define CLAMP(x, low, high) { if ( (x) < (low) ) x = (low); if ( (x) > (high) ) x = (high); } while (0); 00036 #define swap(a, b) { uint8_t t = a; a = b; b = t; } 00037 00038 ST7565::ST7565() { 00039 //SPI com 00040 00041 // select which SPI channel to use 00042 int spi_channel = THEKERNEL->config->value(panel_checksum, spi_channel_checksum)->by_default(0)->as_number(); 00043 PinName mosi; 00044 PinName sclk; 00045 if(spi_channel == 0){ 00046 mosi= P0_18; sclk= P0_15; 00047 }else if(spi_channel == 1){ 00048 mosi= P0_9; sclk= P0_7; 00049 }else{ 00050 mosi= P0_18; sclk= P0_15; 00051 } 00052 00053 this->spi= new mbed::SPI(mosi,NC,sclk); 00054 this->spi->frequency(THEKERNEL->config->value(panel_checksum, spi_frequency_checksum)->by_default(1000000)->as_number()); //4Mhz freq, can try go a little lower 00055 00056 //chip select 00057 this->cs.from_string(THEKERNEL->config->value( panel_checksum, spi_cs_pin_checksum)->by_default("0.16")->as_string())->as_output(); 00058 cs.set(1); 00059 00060 //lcd reset 00061 this->rst.from_string(THEKERNEL->config->value( panel_checksum, rst_pin_checksum)->by_default("nc")->as_string())->as_output(); 00062 if(this->rst.connected()) rst.set(1); 00063 00064 //a0 00065 this->a0.from_string(THEKERNEL->config->value( panel_checksum, a0_pin_checksum)->by_default("2.13")->as_string())->as_output(); 00066 a0.set(1); 00067 00068 this->up_pin.from_string(THEKERNEL->config->value( panel_checksum, up_button_pin_checksum )->by_default("nc")->as_string())->as_input(); 00069 this->down_pin.from_string(THEKERNEL->config->value( panel_checksum, down_button_pin_checksum )->by_default("nc")->as_string())->as_input(); 00070 00071 this->click_pin.from_string(THEKERNEL->config->value( panel_checksum, click_button_pin_checksum )->by_default("nc")->as_string())->as_input(); 00072 this->encoder_a_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_a_pin_checksum)->by_default("nc")->as_string())->as_input(); 00073 this->encoder_b_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_b_pin_checksum)->by_default("nc")->as_string())->as_input(); 00074 00075 // contrast, mviki needs 0x018 00076 this->contrast= THEKERNEL->config->value(panel_checksum, contrast_checksum)->by_default(9)->as_number(); 00077 // reverse display 00078 this->reversed= THEKERNEL->config->value(panel_checksum, reverse_checksum)->by_default(false)->as_bool(); 00079 00080 framebuffer= (uint8_t *)AHB0.alloc(FB_SIZE); // grab some memoery from USB_RAM 00081 if(framebuffer == NULL) { 00082 THEKERNEL->streams->printf("Not enough memory available for frame buffer"); 00083 } 00084 } 00085 00086 ST7565::~ST7565() { 00087 delete this->spi; 00088 AHB0.dealloc(framebuffer); 00089 } 00090 00091 //send commands to lcd 00092 void ST7565::send_commands(const unsigned char* buf, size_t size){ 00093 cs.set(0); 00094 a0.set(0); 00095 while(size-- >0){ 00096 spi->write(*buf++); 00097 } 00098 cs.set(1); 00099 } 00100 00101 //send data to lcd 00102 void ST7565::send_data(const unsigned char* buf, size_t size){ 00103 cs.set(0); 00104 a0.set(1); 00105 while(size-- >0){ 00106 spi->write(*buf++); 00107 } 00108 cs.set(1); 00109 a0.set(0); 00110 } 00111 00112 //clearing screen 00113 void ST7565::clear(){ 00114 memset(framebuffer, 0, FB_SIZE); 00115 this->tx=0; 00116 this->ty=0; 00117 } 00118 00119 void ST7565::send_pic(const unsigned char* data){ 00120 for (int i=0; i<LCDPAGES; i++) 00121 { 00122 set_xy(0, i); 00123 send_data(data + i*LCDWIDTH, LCDWIDTH); 00124 } 00125 } 00126 00127 // set column and page number 00128 void ST7565::set_xy(int x, int y) 00129 { 00130 CLAMP(x, 0, LCDWIDTH-1); 00131 CLAMP(y, 0, LCDPAGES-1); 00132 unsigned char cmd[3]; 00133 cmd[0] = 0xb0 | (y & 0x07); 00134 cmd[1] = 0x10 | (x >> 4); 00135 cmd[2] = 0x00 | (x & 0x0f); 00136 send_commands(cmd, 3); 00137 } 00138 00139 void ST7565::setCursor(uint8_t col, uint8_t row){ 00140 this->tx=col*6; 00141 this->ty=row*8; 00142 } 00143 00144 void ST7565::home(){ 00145 this->tx=0; 00146 this->ty=0; 00147 } 00148 00149 void ST7565::display(){ 00150 ///nothing 00151 } 00152 00153 void ST7565::init(){ 00154 const unsigned char init_seq[] = { 00155 0x40, //Display start line 0 00156 (unsigned char)(reversed?0xa0:0xa1), // ADC 00157 (unsigned char)(reversed?0xc8:0xc0), // COM select 00158 0xa6, //Display normal 00159 0xa2, //Set Bias 1/9 (Duty 1/65) 00160 0x2f, //Booster, Regulator and Follower On 00161 0xf8, //Set internal Booster to 4x 00162 0x00, 00163 0x27, //Contrast set 00164 0x81, 00165 this->contrast, //contrast value 00166 0xac, //No indicator 00167 0x00, 00168 0xaf, //Display on 00169 }; 00170 //rst.set(0); 00171 if(this->rst.connected()) rst.set(1); 00172 send_commands(init_seq, sizeof(init_seq)); 00173 clear(); 00174 } 00175 int ST7565::drawChar(int x, int y, unsigned char c, int color){ 00176 int retVal=-1; 00177 if(c=='\n'){ 00178 this->ty+=8; 00179 retVal= -tx; 00180 } 00181 if(c=='\r'){ 00182 retVal= -tx; 00183 } 00184 else{ 00185 for (uint8_t i =0; i<5; i++ ) { 00186 if(color==0){ 00187 framebuffer[x + (y/8*128) ] = ~(glcd_font[(c*5)+i]<< y%8); 00188 if(y+8<63){ 00189 framebuffer[x + ((y+8)/8*128) ] = ~(glcd_font[(c*5)+i] >>(8-(y%8))); 00190 } 00191 } 00192 if(color==1){ 00193 framebuffer[x + ((y)/8*128) ] = glcd_font[(c*5)+i] <<(y%8); 00194 if(y+8<63){ 00195 framebuffer[x + ((y+8)/8*128) ] = glcd_font[(c*5)+i] >>(8-(y%8)); 00196 } 00197 } 00198 x++; 00199 } 00200 retVal= 6; 00201 this->tx+=6; 00202 } 00203 00204 return retVal; 00205 } 00206 00207 //write single char to screen 00208 void ST7565::write_char(char value){ 00209 drawChar(this->tx, this->ty,value,1); 00210 } 00211 00212 void ST7565::write(const char* line, int len){ 00213 for (int i = 0; i < len; ++i) { 00214 write_char(line[i]); 00215 } 00216 } 00217 //refreshing screen 00218 00219 void ST7565::on_refresh(bool now){ 00220 static int refresh_counts = 0; 00221 refresh_counts++; 00222 // 10Hz refresh rate 00223 if(now || refresh_counts % 2 == 0 ){ 00224 send_pic(framebuffer); 00225 } 00226 } 00227 00228 //reading button state 00229 uint8_t ST7565::readButtons(void) { 00230 uint8_t state= 0; 00231 state |= (this->click_pin.get() ? BUTTON_SELECT : 0); 00232 if(this->up_pin.connected()) { 00233 state |= (this->up_pin.get() ? BUTTON_UP : 0); 00234 state |= (this->down_pin.get() ? BUTTON_DOWN : 0); 00235 } 00236 return state; 00237 } 00238 00239 int ST7565::readEncoderDelta() { 00240 static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; 00241 static uint8_t old_AB = 0; 00242 if(this->encoder_a_pin.connected()) { 00243 // mviki 00244 old_AB <<= 2; //remember previous state 00245 old_AB |= ( this->encoder_a_pin.get() + ( this->encoder_b_pin.get() * 2 ) ); //add current state 00246 return enc_states[(old_AB&0x0f)]; 00247 00248 }else{ 00249 return 0; 00250 } 00251 } 00252 00253 void ST7565::bltGlyph(int x, int y, int w, int h, const uint8_t *glyph, int span, int x_offset, int y_offset) { 00254 if(x_offset == 0 && y_offset == 0 && span == 0) { 00255 // blt the whole thing 00256 renderGlyph(x, y, glyph, w, h); 00257 00258 }else{ 00259 // copy portion of glyph into g where x_offset is left byte aligned 00260 // Note currently the x_offset must be byte aligned 00261 int n= w/8; // bytes per line to copy 00262 if(w%8 != 0) n++; // round up to next byte 00263 uint8_t g[n*h]; 00264 uint8_t *dst= g; 00265 const uint8_t *src= &glyph[y_offset*span + x_offset/8]; 00266 for (int i = 0; i < h; ++i) { 00267 memcpy(dst, src, n); 00268 dst+=n; 00269 src+= span; 00270 } 00271 renderGlyph(x, y, g, w, h); 00272 } 00273 } 00274 00275 void ST7565::renderGlyph(int x, int y, const uint8_t *g, int w, int h) { 00276 CLAMP(x, 0, LCDWIDTH-1); 00277 CLAMP(y, 0, LCDHEIGHT-1); 00278 CLAMP(w, 0, LCDWIDTH - x); 00279 CLAMP(h, 0, LCDHEIGHT - y); 00280 00281 for(int i=0; i<w; i++){ 00282 for(int j=0; j<h; j++){ 00283 pixel(x+i,y+j,g[(i/8)+ j*((w-1)/8 +1)] & (1<<(7-i%8))); 00284 } 00285 } 00286 } 00287 00288 void ST7565::pixel(int x, int y, int colour) 00289 { 00290 int page = y / 8; 00291 unsigned char mask = 1<<(y%8); 00292 unsigned char *byte = &framebuffer[page*LCDWIDTH + x]; 00293 if ( colour == 0 ) 00294 *byte &= ~mask; // clear pixel 00295 else 00296 *byte |= mask; // set pixel 00297 }
Generated on Tue Jul 12 2022 20:09:02 by
1.7.2
