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