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