lcd_32122a_avr.c
Go to the documentation of this file.00001
00045 #include "lcd_32122a_avr.h"
00046
00047 #include "cfg/cfg_lcd.h"
00048
00049 #include <cfg/macros.h>
00050 #include <cfg/debug.h>
00051 #include <cfg/module.h>
00052
00053 #include <gfx/gfx.h>
00054 #include <drv/timer.h>
00055
00056 #include <cpu/irq.h>
00057 #include <cpu/types.h>
00058
00059 #include <avr/io.h>
00060
00061 #include <stdbool.h>
00062 #include <inttypes.h>
00063
00064 #warning TODO:Refactor this module. Split code to hw file.
00065
00066
00067 #if !defined(CONFIG_LCD_SOFTINT_REFRESH) || (CONFIG_LCD_SOFTINT_REFRESH != 0 && CONFIG_LCD_SOFTINT_REFRESH != 1)
00068 #error CONFIG_LCD_SOFTINT_REFRESH must be defined to either 0 or 1
00069 #endif
00070 #if !defined(CONFIG_LCD_SOFTINT_REFRESH) || (CONFIG_LCD_SOFTINT_REFRESH != 0 && CONFIG_LCD_SOFTINT_REFRESH != 1)
00071 #error CONFIG_LCD_SOFTINT_REFRESH must be defined to either 0 or 1
00072 #endif
00073
00074
00075 #if CONFIG_LCD_SOFTINT_REFRESH
00076
00078 # define LCD_REFRESH_INTERVAL 20
00079
00080 #endif
00081
00083 #define LCD_PAGES 4
00084
00086 #define LCD_PAGESIZE (LCD_WIDTH / 2)
00087
00092 #define LCD_PF_DB0 PF4
00093 #define LCD_PF_DB1 PF5
00094 #define LCD_PF_DB2 PF6
00095 #define LCD_PF_DB3 PF7
00096 #define LCD_PD_DB4 PD4
00097 #define LCD_PD_DB5 PD5
00098 #define LCD_PD_DB6 PD6
00099 #define LCD_PD_DB7 PD7
00100 #define LCD_PB_A0 PB0
00101 #define LCD_PE_RW PE7
00102 #define LCD_PE_E1 PE2
00103 #define LCD_PE_E2 PE6
00104
00110 #define LCD_DATA_HI_PORT PORTD
00111 #define LCD_DATA_HI_PIN PIND
00112 #define LCD_DATA_HI_DDR DDRD
00113 #define LCD_DATA_HI_SHIFT 0
00114 #define LCD_DATA_HI_MASK 0xF0
00115
00121 #define LCD_DATA_LO_PORT PORTF
00122 #define LCD_DATA_LO_PIN PINF
00123 #define LCD_DATA_LO_DDR DDRF
00124 #define LCD_DATA_LO_SHIFT 4
00125 #define LCD_DATA_LO_MASK 0xF0
00126
00132 #define LCD_CLR_A0 (PORTB &= ~BV(LCD_PB_A0))
00133 #define LCD_SET_A0 (PORTB |= BV(LCD_PB_A0))
00134 #define LCD_CLR_RD (PORTE &= ~BV(LCD_PE_RW))
00135 #define LCD_SET_RD (PORTE |= BV(LCD_PE_RW))
00136 #define LCD_CLR_E1 (PORTE &= ~BV(LCD_PE_E1))
00137 #define LCD_SET_E1 (PORTE |= BV(LCD_PE_E1))
00138 #define LCD_CLR_E2 (PORTE &= ~BV(LCD_PE_E2))
00139 #define LCD_SET_E2 (PORTE |= BV(LCD_PE_E2))
00140 #define LCD_SET_E(x) (PORTE |= (x))
00141 #define LCD_CLR_E(x) (PORTE &= ~(x))
00142
00148 #define LCDF_E1 (BV(LCD_PE_E1))
00149 #define LCDF_E2 (BV(LCD_PE_E2))
00150
00153 #define LCD_READ ( \
00154 ((LCD_DATA_LO_PIN & LCD_DATA_LO_MASK) >> LCD_DATA_LO_SHIFT) | \
00155 ((LCD_DATA_HI_PIN & LCD_DATA_HI_MASK) >> LCD_DATA_HI_SHIFT) \
00156 )
00157
00159 #define LCD_WRITE(d) \
00160 do { \
00161 LCD_DATA_LO_PORT = (LCD_DATA_LO_PORT & ~LCD_DATA_LO_MASK) | (((d)<<LCD_DATA_LO_SHIFT) & LCD_DATA_LO_MASK); \
00162 LCD_DATA_HI_PORT = (LCD_DATA_HI_PORT & ~LCD_DATA_HI_MASK) | (((d)<<LCD_DATA_HI_SHIFT) & LCD_DATA_HI_MASK); \
00163 } while (0)
00164
00166 #define LCD_DB_OUT \
00167 do { \
00168 LCD_DATA_LO_DDR |= LCD_DATA_LO_MASK; \
00169 LCD_DATA_HI_DDR |= LCD_DATA_HI_MASK; \
00170 } while (0)
00171
00173 #define LCD_DB_IN \
00174 do { \
00175 LCD_DATA_LO_DDR &= ~LCD_DATA_LO_MASK; \
00176 LCD_DATA_HI_DDR &= ~LCD_DATA_HI_MASK; \
00177 } while (0)
00178
00180 #define LCD_DELAY_WRITE \
00181 do { \
00182 NOP; \
00183 NOP; \
00184 } while (0)
00185
00187 #define LCD_DELAY_READ \
00188 do { \
00189 NOP; \
00190 NOP; \
00191 NOP; \
00192 } while (0)
00193
00194
00199 #define LCD_CMD_DISPLAY_ON 0xAF
00200 #define LCD_CMD_DISPLAY_OFF 0xAE
00201 #define LCD_CMD_STARTLINE 0xC0
00202 #define LCD_CMD_PAGEADDR 0xB8
00203 #define LCD_CMD_COLADDR 0x00
00204 #define LCD_CMD_ADC_LEFT 0xA1
00205 #define LCD_CMD_ADC_RIGHT 0xA0
00206 #define LCD_CMD_STATIC_OFF 0xA4
00207 #define LCD_CMD_STATIC_ON 0xA5
00208 #define LCD_CMD_DUTY_32 0xA9
00209 #define LCD_CMD_DUTY_16 0xA8
00210 #define LCD_CMD_RMW_ON 0xE0
00211 #define LCD_CMD_RMW_OFF 0xEE
00212 #define LCD_CMD_RESET 0xE2
00213
00215 MOD_DEFINE(lcd)
00216
00217
00218
00219 #define LCDF_BUSY BV(7)
00220
00221 #if CONFIG_LCD_WAIT
00222
00235 #define WAIT_LCD \
00236 do { \
00237 uint8_t status; \
00238 LCD_DB_IN; \
00239 do { \
00240 LCD_SET_RD; \
00241 LCD_CLR_A0; \
00242 LCD_SET_E1; \
00243 LCD_DELAY_READ; \
00244 status = LCD_READ; \
00245 LCD_CLR_E1; \
00246 LCD_SET_A0; \
00247 LCD_CLR_RD; \
00248 } while (status & LCDF_BUSY); \
00249 LCD_DB_OUT; \
00250 } while (0)
00251
00252 #else
00253
00254 #define WAIT_LCD do {} while(0)
00255
00256 #endif
00257
00258
00265 DECLARE_WALL(wall_before_raster, WALL_SIZE)
00266 static uint8_t lcd_raster[RAST_SIZE(LCD_WIDTH, LCD_HEIGHT)];
00267 DECLARE_WALL(wall_after_raster, WALL_SIZE)
00268
00270 struct Bitmap lcd_bitmap;
00271
00272
00273 #if CONFIG_LCD_SOFTINT_REFRESH
00274
00276 static Timer *lcd_refresh_timer;
00277
00278 #endif
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 static inline void lcd_32122_cmd(uint8_t cmd, uint8_t chip)
00305 {
00306 WAIT_LCD;
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 LCD_WRITE(cmd);
00318
00319 LCD_CLR_A0;
00320 LCD_SET_E(chip);
00321 LCD_DELAY_WRITE;
00322 LCD_CLR_E(chip);
00323 LCD_SET_A0;
00324
00325 }
00326
00327
00328 static inline uint8_t lcd_32122_read(uint8_t chip)
00329 {
00330 uint8_t data;
00331
00332 WAIT_LCD;
00333
00347 LCD_DB_IN;
00348
00349 LCD_SET_RD;
00350 LCD_SET_E(chip);
00351 LCD_DELAY_READ;
00352 data = LCD_READ;
00353 LCD_CLR_E(chip);
00354 LCD_CLR_RD;
00355
00356 LCD_DB_OUT;
00357
00358 return data;
00359 }
00360
00361 static inline void lcd_32122_write(uint8_t c, uint8_t chip)
00362 {
00363 WAIT_LCD;
00364
00378 LCD_WRITE(c);
00379
00380
00381 LCD_SET_E(chip);
00382 LCD_DELAY_WRITE;
00383 LCD_CLR_E(chip);
00384
00385
00386 }
00387
00388 static void lcd_32122_clear(void)
00389 {
00390 uint8_t page, j;
00391
00392 for (page = 0; page < LCD_PAGES; ++page)
00393 {
00394 lcd_32122_cmd(LCD_CMD_COLADDR | 0, LCDF_E1 | LCDF_E2);
00395 lcd_32122_cmd(LCD_CMD_PAGEADDR | page, LCDF_E1 | LCDF_E2);
00396 for (j = 0; j < LCD_PAGESIZE; j++)
00397 lcd_32122_write(0, LCDF_E1 | LCDF_E2);
00398 }
00399 }
00400
00401
00402 static void lcd_32122_writeRaster(const uint8_t *raster)
00403 {
00404 uint8_t page, rows;
00405 const uint8_t *right_raster;
00406
00407 CHECK_WALL(wall_before_raster);
00408 CHECK_WALL(wall_after_raster);
00409
00410 for (page = 0; page < LCD_PAGES; ++page)
00411 {
00412 lcd_32122_cmd(LCD_CMD_PAGEADDR | page, LCDF_E1 | LCDF_E2);
00413 lcd_32122_cmd(LCD_CMD_COLADDR | 0, LCDF_E1 | LCDF_E2);
00414
00415
00416 right_raster = raster + LCD_PAGESIZE;
00417 rows = LCD_PAGESIZE;
00418 do
00419 {
00420 lcd_32122_write(*raster++, LCDF_E1);
00421 lcd_32122_write(*right_raster++, LCDF_E2);
00422 }
00423 while (--rows);
00424 raster = right_raster;
00425 }
00426 }
00427
00428 #if CONFIG_LCD_SOFTINT_REFRESH
00429
00430 static void lcd_32122_refreshSoftint(void)
00431 {
00432 lcd_blit_bitmap(&lcd_bitmap);
00433 timer_add(lcd_refresh_timer);
00434 }
00435
00436 #endif
00437
00441 void lcd_32122_setPwm(int duty)
00442 {
00443 ASSERT(duty >= LCD_MIN_PWM);
00444 ASSERT(duty <= LCD_MAX_PWM);
00445
00446 OCR3C = duty;
00447 }
00448
00452 void lcd_32122_blitBitmap(Bitmap *bm)
00453 {
00454 MOD_CHECK(lcd);
00455 lcd_32122_writeRaster(bm->raster);
00456 }
00457
00458
00465 void lcd_32122_init(void)
00466 {
00467 MOD_CHECK(timer);
00468
00469
00470 cpu_flags_t flags;
00471 IRQ_SAVE_DISABLE(flags);
00472
00473 PORTB |= BV(LCD_PB_A0);
00474 DDRB |= BV(LCD_PB_A0);
00475
00476 PORTE &= ~(BV(LCD_PE_RW) | BV(LCD_PE_E1) | BV(LCD_PE_E2));
00477 DDRE |= BV(LCD_PE_RW) | BV(LCD_PE_E1) | BV(LCD_PE_E2);
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 LCD_DB_OUT;
00494
00495
00496 IRQ_ENABLE;
00497 timer_delay(20);
00498 IRQ_SAVE_DISABLE(flags);
00499
00500 lcd_32122_cmd(LCD_CMD_RESET, LCDF_E1 | LCDF_E2);
00501 lcd_32122_cmd(LCD_CMD_DISPLAY_ON, LCDF_E1 | LCDF_E2);
00502 lcd_32122_cmd(LCD_CMD_STARTLINE | 0, LCDF_E1 | LCDF_E2);
00503
00504
00505 INIT_WALL(wall_before_raster);
00506 INIT_WALL(wall_after_raster);
00507
00508 IRQ_RESTORE(flags);
00509
00510 lcd_32122_clear();
00511 lcd_32122_setPwm(LCD_DEF_PWM);
00512
00513 gfx_bitmapInit(&lcd_bitmap, lcd_raster, LCD_WIDTH, LCD_HEIGHT);
00514 gfx_bitmapClear(&lcd_bitmap);
00515
00516 #if CONFIG_LCD_SOFTINT_REFRESH
00517
00518
00519 lcd_refresh_timer = timer_new();
00520 ASSERT(lcd_refresh_timer != NULL);
00521 INITEVENT_INT(&lcd_refresh_timer->expire, (Hook)lcd_refresh_softint, 0);
00522 lcd_refresh_timer->delay = LCD_REFRESH_INTERVAL;
00523 timer_add(lcd_refresh_timer);
00524
00525 #endif
00526
00527 MOD_INIT(lcd);
00528 }
00529