#include #include #include #include #include #include #include #ifdef DMALLOC #include #endif #define SPI_IOCTL 0x600 static int spidev; static unsigned char lastdata[LCD_H][LCD_W] = {{0}}; inline void spi_command(unsigned char command) { ioctl(spidev, SPI_IOCTL, &command); } void cursorxy(int x, int y) { spi_command(0x40 | (y & 0x07)); spi_command(0x80 | (x & 0x7f)); } void clearram() { unsigned char buf[LCD_BYTES] = {0}; cursorxy(0, 0); write(spidev, buf, LCD_BYTES); } /* Public functions */ int getticks() { struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); return tv.tv_sec * 1000 + tv.tv_usec / 1000; } void lcd_initialize() { spidev = open("/dev/spi", O_RDWR); spi_command(0x21); // Extended instruction set spi_command(0x80 | 70); // LCD contrast voltage spi_command(0x13); // LCD bias spi_command(0x20); // Normal instruction set spi_command(0x0C); // Display normal clearram(); } void lcd_update(unsigned char buf[LCD_H][LCD_W]) { int i, firstline = -1, lastline = 0; for (i = 0; i < LCD_H; i++) { if (memcmp(buf[i], lastdata[i], LCD_W) != 0) { firstline = i; break; } } for (i = firstline; i < LCD_H; i++) { if (memcmp(buf[i], lastdata[i], LCD_W) != 0) { lastline = i + 1; } } if (firstline < 0) // No changes return; cursorxy(0, firstline); write(spidev, &buf[firstline][0], (lastline - firstline) * LCD_W); memcpy(&lastdata[0][0], &buf[0][0], LCD_BYTES); } void lcd_scroll(unsigned char lbuf[LCD_H][LCD_W], unsigned char rbuf[LCD_H][LCD_W], int direction) { // 1 = right, 0 = left const int border = 2; unsigned char screen[LCD_H][LCD_W]; int pos, rpos, y; int ticks = getticks(), rticks; for (pos = 0; pos <= LCD_W + border; pos += 8) { if (direction) rpos = pos; else rpos = LCD_W + border - pos; for (y = 0; y < LCD_H; y++) { memcpy(&screen[y][0], &lbuf[y][rpos], LCD_W - rpos); if (rpos > 0 && rpos <= border) { memset(&screen[y][LCD_W - rpos], 0, rpos); } else if (rpos > border && rpos <= LCD_W) { memset(&screen[y][LCD_W - rpos], 0, border); } if (rpos > border) memcpy(&screen[y][LCD_W - rpos + border], &rbuf[y][0], rpos - border); } lcd_update(screen); ticks += 1000 / 50; rticks = ticks - getticks(); if (rticks > 0) usleep(rticks * 1000); } if (direction) lcd_update(rbuf); else lcd_update(lbuf); }