00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00027 #include <avr/io.h>
00028 #include <avr/interrupt.h>
00029 #include <avr/pgmspace.h>
00030 #include <inttypes.h>
00031 #include "main/lcd.h"
00032 #include "main/rom.h"
00033 #include "delay.h"
00034 #include "utils.h"
00035
00036 #define WBF_MASTER 0x04
00037 #define WBF_SLAVE 0x02
00038 #define WBF_MODE_DATA 0x01
00039 #define WBF_MODE_CMD 0x00
00040
00041 #define CMD_DISPLAY_ON 0x3f
00042 #define CMD_DISPLAY_OFF 0x3e
00043 #define CMD_SET_START 0xC0
00044 #define CMD_SET_PAGE 0xB8
00045 #define CMD_SET_COLUMN 0x40
00046
00047 #define send_cmd(a, b) write_byte(a, b | WBF_MODE_CMD)
00048 #define send_all_cmd(a) send_cmd(a, WBF_MASTER | WBF_SLAVE)
00049
00050
00051 #define RES_PORT PORTC
00052 #define RES_BIT PC5
00053 #define RS_PORT PORTE
00054 #define RS_BIT PE3
00055 #define RW_PORT PORTE
00056 #define RW_BIT PE4
00057 #define E_PORT PORTE
00058 #define E_BIT PE5
00059 #define CS1_PORT PORTC
00060 #define CS1_BIT PC7
00061 #define CS2_PORT PORTC
00062 #define CS2_BIT PC6
00063 #define LED_PORT PORTD
00064 #define LED_BIT PD7
00065
00072 static void write_byte(uint8_t value, uint8_t flags)
00073 {
00074 DDRA = 0xff;
00075 PORTA = value;
00076 if (flags & WBF_MODE_DATA) sbi(RS_PORT, RS_BIT); else cbi(RS_PORT, RS_BIT);
00077 cbi(RW_PORT, RW_BIT);
00078 nop();
00079 if (flags & WBF_MASTER) sbi(CS1_PORT, CS1_BIT);
00080 if (flags & WBF_SLAVE) sbi(CS2_PORT, CS2_BIT);
00081 nop(); nop();
00082 sbi(E_PORT, E_BIT);
00083 nop(); nop(); nop();
00084 cbi(E_PORT, E_BIT);
00085 nop(); nop();
00086 cbi(CS1_PORT, CS1_BIT);
00087 cbi(CS2_PORT, CS2_BIT);
00088 PORTA = 0x00;
00089 DDRA = 0x00;
00090 delay(3);
00091 }
00092
00102 static uint8_t read_byte(uint8_t flags)
00103 {
00104 uint8_t result;
00105
00106
00107 if (flags & WBF_MODE_DATA) sbi(RS_PORT, RS_BIT); else cbi(RS_PORT, RS_BIT);
00108 sbi(RW_PORT, RW_BIT);
00109 if (flags & WBF_MASTER) {
00110 sbi(CS1_PORT, CS1_BIT);
00111 } else {
00112 if (flags & WBF_SLAVE) sbi(CS2_PORT, CS2_BIT);
00113 }
00114
00115 nop(); nop();
00116 sbi(E_PORT, E_BIT);
00117 nop(); nop(); nop();
00118 result = PINA;
00119 cbi(E_PORT, E_BIT);
00120 nop();
00121 cbi(CS1_PORT, CS1_BIT);
00122 cbi(CS2_PORT, CS2_BIT);
00123 delay(3);
00124
00125 return result;
00126 }
00127
00131 uint8_t lcd_str_width(uint8_t *text)
00132 {
00133 uint8_t chr, cnt;
00134 uint8_t result = 0;
00135 uint16_t charset;
00136
00137 while ((chr = *text++) != 0x00) {
00138 charset = ((uint16_t)(&i_small_charset)) + ((uint16_t)chr * SMALL_CHAR_SIZE) + 2;
00139 for (cnt=0; cnt<8; cnt++) {
00140 chr = pgm_read_byte(charset);
00141 charset++;
00142 result++;
00143 if (chr == 0x00) break;
00144 }
00145 }
00146 return result;
00147 }
00148
00154 void lcd_print(uint8_t x, uint8_t y, uint8_t inverted, char *text)
00155 {
00156 uint8_t chip, chr, cnt;
00157 uint16_t charset;
00158
00159 if (x > 127) return;
00160
00161
00162 send_all_cmd(CMD_SET_PAGE | (y >> 3));
00163 if (x < 64) {
00164 chip = WBF_MASTER;
00165 send_cmd(CMD_SET_COLUMN | x, WBF_MASTER);
00166 send_cmd(CMD_SET_COLUMN | 0, WBF_SLAVE);
00167 } else {
00168 chip = WBF_SLAVE;
00169 send_cmd(CMD_SET_COLUMN | (x-64), WBF_SLAVE);
00170 }
00171
00172 while ((chr = *text++) != 0x00) {
00173
00174 charset = ((uint16_t)(&i_small_charset)) + ((uint16_t)chr * SMALL_CHAR_SIZE) + 2;
00175
00176
00177 for (cnt=0; cnt<8; cnt++) {
00178
00179 if (x == 64) chip = WBF_SLAVE;
00180
00181 chr = pgm_read_byte(charset);
00182 charset++;
00183 write_byte((inverted)?~chr:chr, chip | WBF_MODE_DATA);
00184 x++;
00185
00186 if (chr == 0x00) break;
00187 }
00188 }
00189 }
00190
00194 void lcd_v_line(uint8_t x, uint8_t y1, uint8_t y2)
00195 {
00196 uint8_t chip, cnt, chr;
00197 uint8_t buffer[8];
00198
00199 if (x > 63) {
00200 x-=64;
00201 chip = WBF_SLAVE;
00202 } else {
00203 chip = WBF_MASTER;
00204 }
00205
00206
00207
00208
00209 for (cnt=0; cnt<8; cnt++) buffer[cnt] = 0;
00210 for (cnt=y1; cnt<=y2; cnt++) buffer[cnt >> 3] |= 1 << (cnt & 0x07);
00211
00212
00213 for (cnt=0; cnt<8; cnt++) {
00214 send_cmd(CMD_SET_PAGE | cnt, chip);
00215 send_cmd(CMD_SET_COLUMN | x, chip);
00216 read_byte(chip | WBF_MODE_DATA);
00217 chr = read_byte(chip | WBF_MODE_DATA);
00218 send_cmd(CMD_SET_COLUMN | x, chip);
00219 write_byte(chr | buffer[cnt], chip | WBF_MODE_DATA);
00220 }
00221 }
00222
00226 void lcd_h_line(uint8_t x1, uint8_t x2, uint8_t y)
00227 {
00228 uint8_t chip, posi, mask, chr;
00229
00230 mask = 1 << (y & 0x07);
00231 send_all_cmd(CMD_SET_PAGE | (y >> 3));
00232 if (x1 < 64) {
00233 chip = WBF_MASTER;
00234 posi = x1;
00235 send_cmd(CMD_SET_COLUMN | 0, WBF_SLAVE);
00236 } else {
00237 chip = WBF_SLAVE;
00238 posi = x1-64;
00239 }
00240 send_cmd(CMD_SET_COLUMN | posi, chip);
00241
00242 while (x1 <= x2) {
00243 if (x1 == 64) {
00244 chip = WBF_SLAVE;
00245 posi = 0;
00246 }
00247 send_cmd(CMD_SET_COLUMN | x1, chip);
00248 read_byte(chip | WBF_MODE_DATA);
00249 chr = read_byte(chip | WBF_MODE_DATA);
00250 send_cmd(CMD_SET_COLUMN | x1, chip);
00251 write_byte(chr | mask, chip | WBF_MODE_DATA);
00252 posi++;
00253 x1++;
00254 }
00255 }
00256
00262 void lcd_put_image(uint8_t x, uint8_t y, PGM_P image)
00263 {
00264 uint8_t chip, cnt, posi, w;
00265 uint8_t width, height;
00266
00267 y = y >> 3;
00268 width = PRG_RDB(image++);
00269 height = PRG_RDB(image++);
00270
00271 for (cnt=0; cnt<height; cnt++) {
00272 posi = x;
00273
00274 if (posi < 64) {
00275 chip = WBF_MASTER;
00276 send_cmd(CMD_SET_COLUMN | posi, WBF_MASTER);
00277 send_cmd(CMD_SET_COLUMN | 0, WBF_SLAVE);
00278 } else {
00279 chip = WBF_SLAVE;
00280 send_cmd(CMD_SET_COLUMN | (posi-64), WBF_SLAVE);
00281 }
00282 send_all_cmd(CMD_SET_PAGE | (y+cnt));
00283
00284 w = width;
00285 while (w--) {
00286 if (posi == 64) chip = WBF_SLAVE;
00287 write_byte(pgm_read_byte(image++), chip | WBF_MODE_DATA);
00288 posi++;
00289 }
00290 }
00291 }
00292
00296 void lcd_clear_line(uint8_t x1, uint8_t x2, uint8_t y)
00297 {
00298 uint8_t chip;
00299
00300 send_all_cmd(CMD_SET_PAGE | (y >> 3));
00301 if (x1 < 64) {
00302 chip = WBF_MASTER;
00303 send_cmd(CMD_SET_COLUMN | x1, WBF_MASTER);
00304 send_cmd(CMD_SET_COLUMN | 0, WBF_SLAVE);
00305 } else {
00306 chip = WBF_SLAVE;
00307 send_cmd(CMD_SET_COLUMN | (x1-64), WBF_SLAVE);
00308 }
00309
00310 while (x1 <= x2) {
00311 if (x1 == 64) chip = WBF_SLAVE;
00312 x1++;
00313 write_byte(0, chip | WBF_MODE_DATA);
00314 }
00315 }
00316
00320 void lcd_clear(void)
00321 {
00322 uint8_t page_cnt, col_cnt;
00323
00324 for (page_cnt = 0; page_cnt < 8; page_cnt++) {
00325 send_all_cmd(CMD_SET_PAGE | page_cnt);
00326 send_all_cmd(CMD_SET_COLUMN | 0);
00327 for (col_cnt = 0; col_cnt < 64; col_cnt++)
00328 write_byte(0x00, WBF_MASTER | WBF_SLAVE | WBF_MODE_DATA);
00329 }
00330 }
00331
00335 void lcd_init(void)
00336 {
00337
00338 sbi(RES_PORT, RES_BIT);
00339 delay(1000);
00340 cbi(RES_PORT, RES_BIT);
00341 delay(1000);
00342 sbi(RES_PORT, RES_BIT);
00343 delay(1000);
00344
00345 lcd_clear();
00346 }
00347
00351 void lcd_activate(void)
00352 {
00353 sbi(LED_PORT, LED_BIT);
00354 send_all_cmd(CMD_DISPLAY_ON);
00355 }
00356
00360 void lcd_deactivate(void)
00361 {
00362 cbi(LED_PORT, LED_BIT);
00363 send_all_cmd(CMD_DISPLAY_OFF);
00364 }
00365
00369 void lcd_enable_backlight(void)
00370 {
00371 sbi(LED_PORT, LED_BIT);
00372 }
00373
00377 void lcd_disable_backlight(void)
00378 {
00379 cbi(LED_PORT, LED_BIT);
00380 }