00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <cfg/arch.h>
00058 #include <cfg/arch/gpio.h>
00059 #include <cfg/lcd.h>
00060
00061 #include <stdlib.h>
00062 #include <string.h>
00063
00064 #include <sys/nutconfig.h>
00065 #include <dev/st7036.h>
00066 #include <dev/term.h>
00067 #include <sys/timer.h>
00068
00069 #ifndef LCD_ROWS
00070 #define LCD_ROWS 2
00071 #endif
00072
00073 #ifndef LCD_COLS
00074 #define LCD_COLS 16
00075 #endif
00076
00077 #ifndef LCD_SHORT_DELAY
00078 #define LCD_SHORT_DELAY 100
00079 #endif
00080
00081 #ifndef LCD_LONG_DELAY
00082 #define LCD_LONG_DELAY 1000
00083 #endif
00084
00085
00086 #ifdef LCD_CS_BIT
00087 #define LCD_CS _BV(LCD_CS_BIT)
00088 #if LCD_CS_PIO_ID == PIOA_ID
00089 #define LCD_CS_SET() { outr(PIOA_PER, LCD_CS); outr(PIOA_SODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00090 #define LCD_CS_CLR() { outr(PIOA_PER, LCD_CS); outr(PIOA_CODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00091 #elif LCD_CS_PIO_ID == PIOB_ID
00092 #define LCD_CS_SET() { outr(PIOB_PER, LCD_CS); outr(PIOB_SODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00093 #define LCD_CS_CLR() { outr(PIOB_PER, LCD_CS); outr(PIOB_CODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00094 #elif LCD_CS_PIO_ID == PIOC_ID
00095 #define LCD_CS_SET() { outr(PIOC_PER, LCD_CS); outr(PIOC_SODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00096 #define LCD_CS_CLR() { outr(PIOC_PER, LCD_CS); outr(PIOC_CODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00097 #else
00098 #define LCD_CS_SET() { outr(PIO_PER, LCD_CS); outr(PIO_SODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00099 #define LCD_CS_CLR() { outr(PIO_PER, LCD_CS); outr(PIO_CODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00100 #endif
00101 #else
00102 #define LCD_CS_SET()
00103 #define LCD_CS_CLR()
00104 #endif
00105
00106 #ifdef LCD_RS_BIT
00107 #define LCD_RS _BV(LCD_RS_BIT)
00108 #if LCD_RS_PIO_ID == PIOA_ID
00109 #define LCD_RS_SET() { outr(PIOA_PER, LCD_RS); outr(PIOA_SODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00110 #define LCD_RS_CLR() { outr(PIOA_PER, LCD_RS); outr(PIOA_CODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00111 #elif LCD_RS_PIO_ID == PIOB_ID
00112 #define LCD_RS_SET() { outr(PIOB_PER, LCD_RS); outr(PIOB_SODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00113 #define LCD_RS_CLR() { outr(PIOB_PER, LCD_RS); outr(PIOB_CODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00114 #elif LCD_RS_PIO_ID == PIOC_ID
00115 #define LCD_RS_SET() { outr(PIOC_PER, LCD_RS); outr(PIOC_SODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00116 #define LCD_RS_CLR() { outr(PIOC_PER, LCD_RS); outr(PIOC_CODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00117 #else
00118 #define LCD_RS_SET() { outr(PIO_PER, LCD_RS); outr(PIO_SODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00119 #define LCD_RS_CLR() { outr(PIO_PER, LCD_RS); outr(PIO_CODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00120 #endif
00121 #else
00122 #define LCD_RS_SET()
00123 #define LCD_RS_CLR()
00124 #endif
00125
00126 #ifdef LCD_CLK_BIT
00127 #define LCD_CLK _BV(LCD_CLK_BIT)
00128 #if LCD_CLK_PIO_ID == PIOA_ID
00129 #define LCD_CLK_SET() { outr(PIOA_PER, LCD_CLK); outr(PIOA_SODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00130 #define LCD_CLK_CLR() { outr(PIOA_PER, LCD_CLK); outr(PIOA_CODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00131 #elif LCD_CLK_PIO_ID == PIOB_ID
00132 #define LCD_CLK_SET() { outr(PIOB_PER, LCD_CLK); outr(PIOB_SODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00133 #define LCD_CLK_CLR() { outr(PIOB_PER, LCD_CLK); outr(PIOB_CODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00134 #elif LCD_CLK_PIO_ID == PIOC_ID
00135 #define LCD_CLK_SET() { outr(PIOC_PER, LCD_CLK); outr(PIOC_SODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00136 #define LCD_CLK_CLR() { outr(PIOC_PER, LCD_CLK); outr(PIOC_CODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00137 #else
00138 #define LCD_CLK_SET() { outr(PIO_PER, LCD_CLK); outr(PIO_SODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00139 #define LCD_CLK_CLR() { outr(PIO_PER, LCD_CLK); outr(PIO_CODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00140 #endif
00141 #else
00142 #define LCD_CLK_SET()
00143 #define LCD_CLK_CLR()
00144 #endif
00145
00146 #ifdef LCD_MOSI_BIT
00147 #define LCD_MOSI _BV(LCD_MOSI_BIT)
00148 #if LCD_MOSI_PIO_ID == PIOA_ID
00149 #define LCD_MOSI_SET() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_SODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00150 #define LCD_MOSI_CLR() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_CODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00151 #elif LCD_MOSI_PIO_ID == PIOB_ID
00152 #define LCD_MOSI_SET() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_SODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00153 #define LCD_MOSI_CLR() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_CODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00154 #elif LCD_MOSI_PIO_ID == PIOC_ID
00155 #define LCD_MOSI_SET() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_SODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00156 #define LCD_MOSI_CLR() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_CODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00157 #else
00158 #define LCD_MOSI_SET() { outr(PIO_PER, LCD_MOSI); outr(PIO_SODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00159 #define LCD_MOSI_CLR() { outr(PIO_PER, LCD_MOSI); outr(PIO_CODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00160 #endif
00161 #else
00162 #define LCD_MOSI_SET()
00163 #define LCD_MOSI_CLR()
00164 #endif
00165
00170
00181 static void LcdDelay(unsigned int cycles)
00182 {
00183 while (cycles--) {
00184 _NOP(); _NOP(); _NOP(); _NOP();
00185 _NOP(); _NOP(); _NOP(); _NOP();
00186 _NOP(); _NOP(); _NOP(); _NOP();
00187 _NOP(); _NOP(); _NOP(); _NOP();
00188 _NOP(); _NOP(); _NOP(); _NOP();
00189 _NOP(); _NOP(); _NOP(); _NOP();
00190 _NOP(); _NOP(); _NOP(); _NOP();
00191 _NOP(); _NOP(); _NOP(); _NOP();
00192 _NOP(); _NOP(); _NOP(); _NOP();
00193 _NOP(); _NOP(); _NOP(); _NOP();
00194 _NOP(); _NOP(); _NOP(); _NOP();
00195 _NOP(); _NOP(); _NOP(); _NOP();
00196 }
00197 }
00198
00199 #if 0
00200 static void INLINE LcdSetBits(unsigned int mask)
00201 {
00202 outr(LCD_PIO_SOD_REG, mask);
00203 outr(LCD_PIO_OE_REG, mask);
00204 }
00205
00206 static void INLINE LcdClrBits(unsigned int mask)
00207 {
00208 outr(LCD_PIO_COD_REG, mask);
00209 outr(LCD_PIO_OE_REG, mask);
00210 }
00211 #endif
00212
00213 static void LcdWaitReady(unsigned int delay)
00214 {
00215 while (delay--) {
00216 _NOP();
00217 }
00218 }
00219
00225 static void LcdWriteByte(unsigned int data)
00226 {
00227 uint8_t msk = 0x80;
00228
00229 while (msk) {
00230 LCD_CLK_CLR();
00231 if (data & msk) {
00232 LCD_MOSI_SET();
00233 } else {
00234 LCD_MOSI_CLR();
00235 }
00236 LCD_CLK_SET();
00237 msk >>= 1;
00238 LcdDelay(1);
00239 }
00240 LcdWaitReady(LCD_LONG_DELAY);
00241 }
00242
00248 static void LcdWriteCmd(uint8_t cmd)
00249 {
00250
00251 LCD_CS_CLR();
00252 LcdDelay(LCD_SHORT_DELAY);
00253 LCD_RS_CLR();
00254 LcdDelay(LCD_SHORT_DELAY);
00255 LcdWriteByte(cmd);
00256 LcdDelay(LCD_SHORT_DELAY);
00257 LCD_RS_SET();
00258 LcdDelay(LCD_SHORT_DELAY);
00259 LCD_CS_SET();
00260 LcdDelay(LCD_SHORT_DELAY);
00261 }
00262
00263 static void LcdWriteInstruction(uint8_t cmd, uint8_t xt)
00264 {
00265 LcdWriteCmd(cmd);
00266 }
00267
00273 static void LcdWriteData(uint8_t data)
00274 {
00275
00276 LCD_CS_CLR();
00277 LcdDelay(LCD_SHORT_DELAY);
00278 LCD_RS_SET();
00279 LcdDelay(LCD_SHORT_DELAY);
00280 LcdWriteByte(data);
00281 LcdDelay(LCD_SHORT_DELAY);
00282 LCD_CS_SET();
00283 LcdDelay(LCD_SHORT_DELAY);
00284 }
00285
00286 static void LcdSetCursor(uint8_t pos)
00287 {
00288 uint8_t offset[] = {
00289 0x00, 0x40, 0x10, 0x50
00290 };
00291
00292 pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00293 LcdWriteCmd(0x80 | pos);
00294 }
00295
00296 static void LcdCursorHome(void)
00297 {
00298 LcdWriteCmd(0x02);
00299 LcdDelay(10 * LCD_LONG_DELAY);
00300 }
00301
00302 static void LcdCursorLeft(void)
00303 {
00304 LcdWriteCmd(0x10);
00305 }
00306
00307 static void LcdCursorRight(void)
00308 {
00309 LcdWriteCmd(0x14);
00310 }
00311
00312 static void LcdClear(void)
00313 {
00314 LcdWriteCmd(0x01);
00315 LcdDelay(10 * LCD_LONG_DELAY);
00316 }
00317
00318 static void LcdCursorMode(uint8_t on)
00319 {
00320 if (on) {
00321 LcdWriteCmd(0x0D);
00322 } else {
00323 LcdWriteCmd(0x0C);
00324 }
00325 LcdDelay(10 * LCD_LONG_DELAY);
00326 }
00327
00328 static int LcdInit(NUTDEVICE * dev)
00329 {
00330 #if defined(PMC_PCER)
00331 unsigned int pcer = 0;
00332 #if defined(LCD_CS_PIO_ID)
00333 pcer = _BV(LCD_CS_PIO_ID);
00334 #endif
00335 #if defined(LCD_RS_PIO_ID)
00336 pcer |= _BV(LCD_RS_PIO_ID);
00337 #endif
00338 #if defined(LCD_CLK_PIO_ID)
00339 pcer |= _BV(LCD_CLK_PIO_ID);
00340 #endif
00341 #if defined(LCD_MOSI_PIO_ID)
00342 pcer |= _BV(LCD_MOSI_PIO_ID);
00343 #endif
00344 outr(PMC_PCER, pcer);
00345 #endif
00346
00347
00348 LCD_CS_SET();
00349 LCD_RS_SET();
00350 LCD_CLK_SET();
00351 LCD_MOSI_SET();
00352
00353
00354 NutSleep(50);
00355
00356 LCD_RS_CLR();
00357 LCD_CS_CLR();
00358
00359 LcdWriteCmd(0x38);
00360 NutSleep(2);
00361 LcdWriteCmd(0x39);
00362 NutSleep(2);
00363 LcdWriteCmd(0x14);
00364 NutSleep(1);
00365 LcdWriteCmd(0x55);
00366 NutSleep(1);
00367 LcdWriteCmd(0x6D);
00368 NutSleep(1);
00369 LcdWriteCmd(0x78);
00370 NutSleep(1);
00371 LcdWriteCmd(0x0F);
00372 NutSleep(1);
00373 LcdWriteCmd(0x01);
00374 NutSleep(1);
00375 LcdWriteCmd(0x06);
00376 NutSleep(1);
00377
00378 LCD_CS_SET();
00379 LCD_RS_SET();
00380
00381
00382 LcdClear();
00383
00384 LcdCursorHome();
00385
00386 return 0;
00387 }
00388
00392 static TERMDCB dcb_term = {
00393 LcdInit,
00394 LcdWriteData,
00395 LcdWriteInstruction,
00396 LcdClear,
00397 LcdSetCursor,
00398 LcdCursorHome,
00399 LcdCursorLeft,
00400 LcdCursorRight,
00401 LcdCursorMode,
00402 0,
00403 0,
00404 LCD_ROWS,
00405 LCD_COLS,
00406 LCD_COLS,
00407 0,
00408 0,
00409 0
00410 };
00411
00415 NUTDEVICE devSbiLcd = {
00416 0,
00417 {'s', 'b', 'i', 'l', 'c', 'd', 0, 0, 0},
00418 IFTYP_STREAM,
00419 0,
00420 0,
00421 0,
00422 &dcb_term,
00423 TermInit,
00424 TermIOCtl,
00425 0,
00426 TermWrite,
00427 TermOpen,
00428 TermClose,
00429 0
00430 };
00431