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 #include <cfg/arch.h>
00054 #include <cfg/arch/gpio.h>
00055 #include <cfg/lcd.h>
00056
00057 #include <stdlib.h>
00058 #include <string.h>
00059
00060 #include <sys/nutconfig.h>
00061 #include <dev/st7036.h>
00062 #include <dev/term.h>
00063 #include <sys/timer.h>
00064
00065 #ifndef LCD_ROWS
00066 #define LCD_ROWS 2
00067 #endif
00068
00069 #ifndef LCD_COLS
00070 #define LCD_COLS 16
00071 #endif
00072
00073 #ifndef LCD_SHORT_DELAY
00074 #define LCD_SHORT_DELAY 100
00075 #endif
00076
00077 #ifndef LCD_LONG_DELAY
00078 #define LCD_LONG_DELAY 1000
00079 #endif
00080
00081
00082 #ifdef LCD_CS_BIT
00083 #define LCD_CS _BV(LCD_CS_BIT)
00084 #if LCD_CS_PIO_ID == PIOA_ID
00085 #define LCD_CS_SET() { outr(PIOA_PER, LCD_CS); outr(PIOA_SODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00086 #define LCD_CS_CLR() { outr(PIOA_PER, LCD_CS); outr(PIOA_CODR, LCD_CS); outr(PIOA_OER, LCD_CS); }
00087 #elif LCD_CS_PIO_ID == PIOB_ID
00088 #define LCD_CS_SET() { outr(PIOB_PER, LCD_CS); outr(PIOB_SODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00089 #define LCD_CS_CLR() { outr(PIOB_PER, LCD_CS); outr(PIOB_CODR, LCD_CS); outr(PIOB_OER, LCD_CS); }
00090 #elif LCD_CS_PIO_ID == PIOC_ID
00091 #define LCD_CS_SET() { outr(PIOC_PER, LCD_CS); outr(PIOC_SODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00092 #define LCD_CS_CLR() { outr(PIOC_PER, LCD_CS); outr(PIOC_CODR, LCD_CS); outr(PIOC_OER, LCD_CS); }
00093 #else
00094 #define LCD_CS_SET() { outr(PIO_PER, LCD_CS); outr(PIO_SODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00095 #define LCD_CS_CLR() { outr(PIO_PER, LCD_CS); outr(PIO_CODR, LCD_CS); outr(PIO_OER, LCD_CS); }
00096 #endif
00097 #else
00098 #define LCD_CS_SET()
00099 #define LCD_CS_CLR()
00100 #endif
00101
00102 #ifdef LCD_RS_BIT
00103 #define LCD_RS _BV(LCD_RS_BIT)
00104 #if LCD_RS_PIO_ID == PIOA_ID
00105 #define LCD_RS_SET() { outr(PIOA_PER, LCD_RS); outr(PIOA_SODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00106 #define LCD_RS_CLR() { outr(PIOA_PER, LCD_RS); outr(PIOA_CODR, LCD_RS); outr(PIOA_OER, LCD_RS); }
00107 #elif LCD_RS_PIO_ID == PIOB_ID
00108 #define LCD_RS_SET() { outr(PIOB_PER, LCD_RS); outr(PIOB_SODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00109 #define LCD_RS_CLR() { outr(PIOB_PER, LCD_RS); outr(PIOB_CODR, LCD_RS); outr(PIOB_OER, LCD_RS); }
00110 #elif LCD_RS_PIO_ID == PIOC_ID
00111 #define LCD_RS_SET() { outr(PIOC_PER, LCD_RS); outr(PIOC_SODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00112 #define LCD_RS_CLR() { outr(PIOC_PER, LCD_RS); outr(PIOC_CODR, LCD_RS); outr(PIOC_OER, LCD_RS); }
00113 #else
00114 #define LCD_RS_SET() { outr(PIO_PER, LCD_RS); outr(PIO_SODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00115 #define LCD_RS_CLR() { outr(PIO_PER, LCD_RS); outr(PIO_CODR, LCD_RS); outr(PIO_OER, LCD_RS); }
00116 #endif
00117 #else
00118 #define LCD_RS_SET()
00119 #define LCD_RS_CLR()
00120 #endif
00121
00122 #ifdef LCD_CLK_BIT
00123 #define LCD_CLK _BV(LCD_CLK_BIT)
00124 #if LCD_CLK_PIO_ID == PIOA_ID
00125 #define LCD_CLK_SET() { outr(PIOA_PER, LCD_CLK); outr(PIOA_SODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00126 #define LCD_CLK_CLR() { outr(PIOA_PER, LCD_CLK); outr(PIOA_CODR, LCD_CLK); outr(PIOA_OER, LCD_CLK); }
00127 #elif LCD_CLK_PIO_ID == PIOB_ID
00128 #define LCD_CLK_SET() { outr(PIOB_PER, LCD_CLK); outr(PIOB_SODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00129 #define LCD_CLK_CLR() { outr(PIOB_PER, LCD_CLK); outr(PIOB_CODR, LCD_CLK); outr(PIOB_OER, LCD_CLK); }
00130 #elif LCD_CLK_PIO_ID == PIOC_ID
00131 #define LCD_CLK_SET() { outr(PIOC_PER, LCD_CLK); outr(PIOC_SODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00132 #define LCD_CLK_CLR() { outr(PIOC_PER, LCD_CLK); outr(PIOC_CODR, LCD_CLK); outr(PIOC_OER, LCD_CLK); }
00133 #else
00134 #define LCD_CLK_SET() { outr(PIO_PER, LCD_CLK); outr(PIO_SODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00135 #define LCD_CLK_CLR() { outr(PIO_PER, LCD_CLK); outr(PIO_CODR, LCD_CLK); outr(PIO_OER, LCD_CLK); }
00136 #endif
00137 #else
00138 #define LCD_CLK_SET()
00139 #define LCD_CLK_CLR()
00140 #endif
00141
00142 #ifdef LCD_MOSI_BIT
00143 #define LCD_MOSI _BV(LCD_MOSI_BIT)
00144 #if LCD_MOSI_PIO_ID == PIOA_ID
00145 #define LCD_MOSI_SET() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_SODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00146 #define LCD_MOSI_CLR() { outr(PIOA_PER, LCD_MOSI); outr(PIOA_CODR, LCD_MOSI); outr(PIOA_OER, LCD_MOSI); }
00147 #elif LCD_MOSI_PIO_ID == PIOB_ID
00148 #define LCD_MOSI_SET() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_SODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00149 #define LCD_MOSI_CLR() { outr(PIOB_PER, LCD_MOSI); outr(PIOB_CODR, LCD_MOSI); outr(PIOB_OER, LCD_MOSI); }
00150 #elif LCD_MOSI_PIO_ID == PIOC_ID
00151 #define LCD_MOSI_SET() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_SODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00152 #define LCD_MOSI_CLR() { outr(PIOC_PER, LCD_MOSI); outr(PIOC_CODR, LCD_MOSI); outr(PIOC_OER, LCD_MOSI); }
00153 #else
00154 #define LCD_MOSI_SET() { outr(PIO_PER, LCD_MOSI); outr(PIO_SODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00155 #define LCD_MOSI_CLR() { outr(PIO_PER, LCD_MOSI); outr(PIO_CODR, LCD_MOSI); outr(PIO_OER, LCD_MOSI); }
00156 #endif
00157 #else
00158 #define LCD_MOSI_SET()
00159 #define LCD_MOSI_CLR()
00160 #endif
00161
00166
00177 static void LcdDelay(u_int cycles)
00178 {
00179 while (cycles--) {
00180 _NOP(); _NOP(); _NOP(); _NOP();
00181 _NOP(); _NOP(); _NOP(); _NOP();
00182 _NOP(); _NOP(); _NOP(); _NOP();
00183 _NOP(); _NOP(); _NOP(); _NOP();
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 }
00193 }
00194
00195 #if 0
00196 static void INLINE LcdSetBits(u_int mask)
00197 {
00198 outr(LCD_PIO_SOD_REG, mask);
00199 outr(LCD_PIO_OE_REG, mask);
00200 }
00201
00202 static void INLINE LcdClrBits(u_int mask)
00203 {
00204 outr(LCD_PIO_COD_REG, mask);
00205 outr(LCD_PIO_OE_REG, mask);
00206 }
00207 #endif
00208
00209 static void LcdWaitReady(u_int delay)
00210 {
00211 while (delay--) {
00212 _NOP();
00213 }
00214 }
00215
00221 static void LcdWriteByte(u_int data)
00222 {
00223 uint8_t msk = 0x80;
00224
00225 while (msk) {
00226 LCD_CLK_CLR();
00227 if (data & msk) {
00228 LCD_MOSI_SET();
00229 } else {
00230 LCD_MOSI_CLR();
00231 }
00232 LCD_CLK_SET();
00233 msk >>= 1;
00234 LcdDelay(1);
00235 }
00236 LcdWaitReady(LCD_LONG_DELAY);
00237 }
00238
00244 static void LcdWriteCmd(uint8_t cmd)
00245 {
00246
00247 LCD_CS_CLR();
00248 LcdDelay(LCD_SHORT_DELAY);
00249 LCD_RS_CLR();
00250 LcdDelay(LCD_SHORT_DELAY);
00251 LcdWriteByte(cmd);
00252 LcdDelay(LCD_SHORT_DELAY);
00253 LCD_RS_SET();
00254 LcdDelay(LCD_SHORT_DELAY);
00255 LCD_CS_SET();
00256 LcdDelay(LCD_SHORT_DELAY);
00257 }
00258
00259 static void LcdWriteInstruction(uint8_t cmd, uint8_t xt)
00260 {
00261 LcdWriteCmd(cmd);
00262 }
00263
00269 static void LcdWriteData(uint8_t data)
00270 {
00271
00272 LCD_CS_CLR();
00273 LcdDelay(LCD_SHORT_DELAY);
00274 LCD_RS_SET();
00275 LcdDelay(LCD_SHORT_DELAY);
00276 LcdWriteByte(data);
00277 LcdDelay(LCD_SHORT_DELAY);
00278 LCD_CS_SET();
00279 LcdDelay(LCD_SHORT_DELAY);
00280 }
00281
00282 static void LcdSetCursor(uint8_t pos)
00283 {
00284 uint8_t offset[] = {
00285 0x00, 0x40, 0x10, 0x50
00286 };
00287
00288 pos = offset[(pos / LCD_COLS) % LCD_ROWS] + pos % LCD_COLS;
00289 LcdWriteCmd(0x80 | pos);
00290 }
00291
00292 static void LcdCursorHome(void)
00293 {
00294 LcdWriteCmd(0x02);
00295 LcdDelay(10 * LCD_LONG_DELAY);
00296 }
00297
00298 static void LcdCursorLeft(void)
00299 {
00300 LcdWriteCmd(0x10);
00301 }
00302
00303 static void LcdCursorRight(void)
00304 {
00305 LcdWriteCmd(0x14);
00306 }
00307
00308 static void LcdClear(void)
00309 {
00310 LcdWriteCmd(0x01);
00311 LcdDelay(10 * LCD_LONG_DELAY);
00312 }
00313
00314 static void LcdCursorMode(uint8_t on)
00315 {
00316 if (on) {
00317 LcdWriteCmd(0x0D);
00318 } else {
00319 LcdWriteCmd(0x0C);
00320 }
00321 LcdDelay(10 * LCD_LONG_DELAY);
00322 }
00323
00324 static void LcdInit(NUTDEVICE * dev)
00325 {
00326 #if defined(PMC_PCER)
00327 u_int pcer = 0;
00328 #if defined(LCD_CS_PIO_ID)
00329 pcer = _BV(LCD_CS_PIO_ID);
00330 #endif
00331 #if defined(LCD_RS_PIO_ID)
00332 pcer |= _BV(LCD_RS_PIO_ID);
00333 #endif
00334 #if defined(LCD_CLK_PIO_ID)
00335 pcer |= _BV(LCD_CLK_PIO_ID);
00336 #endif
00337 #if defined(LCD_MOSI_PIO_ID)
00338 pcer |= _BV(LCD_MOSI_PIO_ID);
00339 #endif
00340 outr(PMC_PCER, pcer);
00341 #endif
00342
00343
00344 LCD_CS_SET();
00345 LCD_RS_SET();
00346 LCD_CLK_SET();
00347 LCD_MOSI_SET();
00348
00349
00350 NutSleep(50);
00351
00352 LCD_RS_CLR();
00353 LCD_CS_CLR();
00354
00355 LcdWriteCmd(0x38);
00356 NutSleep(2);
00357 LcdWriteCmd(0x39);
00358 NutSleep(2);
00359 LcdWriteCmd(0x14);
00360 NutSleep(1);
00361 LcdWriteCmd(0x55);
00362 NutSleep(1);
00363 LcdWriteCmd(0x6D);
00364 NutSleep(1);
00365 LcdWriteCmd(0x78);
00366 NutSleep(1);
00367 LcdWriteCmd(0x0F);
00368 NutSleep(1);
00369 LcdWriteCmd(0x01);
00370 NutSleep(1);
00371 LcdWriteCmd(0x06);
00372 NutSleep(1);
00373
00374 LCD_CS_SET();
00375 LCD_RS_SET();
00376
00377
00378 LcdClear();
00379
00380 LcdCursorHome();
00381 }
00382
00386 static TERMDCB dcb_term = {
00387 LcdInit,
00388 LcdWriteData,
00389 LcdWriteInstruction,
00390 LcdClear,
00391 LcdSetCursor,
00392 LcdCursorHome,
00393 LcdCursorLeft,
00394 LcdCursorRight,
00395 LcdCursorMode,
00396 0,
00397 0,
00398 LCD_ROWS,
00399 LCD_COLS,
00400 LCD_COLS,
00401 0,
00402 0,
00403 0
00404 };
00405
00409 NUTDEVICE devSbiLcd = {
00410 0,
00411 {'s', 'b', 'i', 'l', 'c', 'd', 0, 0, 0},
00412 IFTYP_STREAM,
00413 0,
00414 0,
00415 0,
00416 &dcb_term,
00417 TermInit,
00418 TermIOCtl,
00419 0,
00420 TermWrite,
00421 TermOpen,
00422 TermClose,
00423 0
00424 };
00425