?? lcd-color.cpp
字號:
/* LCD-color.cpp
*
* Class for controlling Spark Fun's 130x130 color LCD.
* The LCD requires 9-bit serial communication, which this
* code does via the SPI feature.
*
* Revisions:
* 07-13-06 included in LCDSample project
* 07-10-06 version 1 in master library
*
* Written by Cathy Saxton
* robotics@idleloop.com
*/
#include <stdio.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "Util.h"
#include "LCD-color.h"
#include "Fonts.h"
#include "Timer.h"
/* set up defines for using SPI registers */
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) \
|| defined(__AVR_ATmega32__) || defined(__AVR_ATmega128__)
#define regSPCR SPCR
#define regSPSR SPSR
#define regSPDR SPDR
#define bitSPE SPE
#define bitSPIF SPIF
#elif (defined(__AVR_ATmega644__))
#define regSPCR SPCR0
#define regSPSR SPSR0
#define regSPDR SPDR0
#define bitSPE SPE0
#define bitSPIF SPIF0
#else
#warning "unrecognized microcontroller (add/verify it)"
#endif
extern TIMER g_timer;
/* horiz: 0-129 (inclusive); vert: 2-131 */
/* Hungarian naming: xl and yl are x and y coordinates on LCD
(handling offset for visible pixels) */
static const uint xlMin = 0;
static const uint ylMin = 2;
static const uint xlMax = xlMin + dxLCDScreen;
static const uint ylMax = ylMin + dyLCDScreen;
static const uint xlMost = xlMin + dxLCDScreen - 1;
static const uint ylMost = ylMin + dyLCDScreen - 1;
static const uint dxLeading = 1; // spacing between chars
static const uint dyLeading = 1; // spacing between lines of text
static const uint dxMargin = 3; // margin to leave at left when drawing text
static const uint dyMargin = 2; // margin to leave at top when drawing text
enum // LCD Communication Type
{
lctCmd = 0, // command
lctData = 1, // data
};
/* Epson S1D15G10 Command Set */
#define DISON 0xaf
#define DISOFF 0xae
#define DISNOR 0xa6
#define DISINV 0xa7
#define COMSCN 0xbb
#define DISCTL 0xca
#define SLPIN 0x95
#define SLPOUT 0x94
#define PASET 0x75
#define CASET 0x15
#define DATCTL 0xbc
#define RGBSET8 0xce
#define RAMWR 0x5c
#define RAMRD 0x5d
#define PTLIN 0xa8
#define PTLOUT 0xa9
#define RMWIN 0xe0
#define RMWOUT 0xee
#define ASCSET 0xaa
#define SCSTART 0xab
#define OSCON 0xd1
#define OSCOFF 0xd2
#define PWRCTR 0x20
#define VOLCTR 0x81
#define VOLUP 0xd6
#define VOLDOWN 0xd7
#define TMPGRD 0x82
#define EPCTIN 0xcd
#define EPCOUT 0xcc
#define EPMWR 0xfc
#define EPMRD 0xfd
#define EPSRRD1 0x7c
#define EPSRRD2 0x7d
#define NOP 0x25
bool LCD::s_fInit = fFalse;
OUT *LCD::s_poutE;
OUT *LCD::s_poutSCK;
OUT *LCD::s_poutMOSI;
OUT *LCD::s_poutReset;
LCD::LCD(OUT *poutE, OUT *poutMOSI, OUT *poutSCK, OUT *poutReset,
const FONT *pfont, uchar clrBack, uchar clrFore)
: m_pfont(pfont),
m_clrBack(clrBack),
m_clrFore(clrFore),
m_x(0),
m_y(0)
{
if (!s_fInit)
{
s_poutE = poutE;
s_poutSCK = poutSCK;
s_poutMOSI = poutMOSI;
s_poutReset = poutReset;
poutE->SetHigh(); // signal is !ChipSelect; this disables it
poutSCK->SetLow(); // get ready for first send
Init();
}
SetPos(0, 1); // start at beginning of line 1
}
void LCD::Init() const
{
s_fInit = fTrue;
/* SPI setup:
SPI Control Register (SPCR): (0101 0001)
bit 7 SPIE (interrupt enable) 0 = not enabled
bit 6 SPE (enable) 1 = enable
bit 5 DORD (data order) 0 = MSB transmitted first
bit 4 MSTR (master sel.) 1 = master
bit 3 CPOL (clk polarity) 0 = idle low (leading edge is rising)
bit 2 CPHA (clock phase) 0 = sample data on leading edge of pulse
bit 1-0 SPR1/0 (clock rate) 00 = fOSC/4
But, we need to disable for starters... every command needs 9 bits,
so we'll send one manually, the use SPI for the next 8.
*/
regSPCR = 0x10; // 0001 0000
/* comms with LCD: longest write requirement is 90 ns
8 MHz uC executes one instruction every 125 ns */
/* give LCD a little time to react to power on */
g_timer.WaitMs(20);
/* send reset */
s_poutReset->SetLow();
/* reset pulse wants to be low for 350 ns (min) */
asm("nop");
asm("nop");
asm("nop");
#ifdef CLOCK_16M
asm("nop");
asm("nop");
asm("nop");
#endif
s_poutReset->SetHigh();
g_timer.WaitMs(2); // wait for reset to complete
WriteCommand(lctCmd, DISCTL); // Display Control
WriteCommand(lctData, 0x00); // default
WriteCommand(lctData, 0x20); // (32 + 1) * 4 = 132 lines (of which 130 are visible)
WriteCommand(lctData, 0x0a); // default
WriteCommand(lctCmd, COMSCN); // Common Scan
WriteCommand(lctData, 0x01); // COM1-80: 1->80; COM81-160: 160<-81 (otherwise bottom of screen is upside down)
WriteCommand(lctCmd, OSCON); // Oscillation On
WriteCommand(lctCmd, SLPOUT); // Sleep Out (exit sleep mode)
WriteCommand(lctCmd, VOLCTR); // Electronic Volume Control (brightness/contrast)
WriteCommand(lctData, 28);
WriteCommand(lctData, 3);
WriteCommand(lctCmd, TMPGRD);
WriteCommand(lctData, 0); // default
WriteCommand(lctCmd, PWRCTR); // Power Control Set
/* 0x0b = ref V / V reg + primary booster
0x0f = all on (0x0b + secondary booster)
(0x03, 0x07 don't work)
*/
// WriteCommand(lctData, 0x0b);
WriteCommand(lctData, 0x0f);
WriteCommand(lctCmd, DISINV); // Inverse Display
WriteCommand(lctCmd, PTLOUT); // Partial Out (no partial display)
#if 0 // unused feature
WriteCommand(lctCmd, ASCSET); // Area Scroll Set
WriteCommand(lctCmd, SCSTART); // Scroll Start Address Set
#endif
WriteCommand(lctCmd, DATCTL); // Data Control
WriteCommand(lctData, 0x00); // normal orientation; scan across cols, then rows
WriteCommand(lctData, 0x00); // RGB arrangement (RGB all rows/cols)
// WriteCommand(lctData, 0x04); // RGB arrangement (RGB row 1, BGR row 2)
WriteCommand(lctData, 0x01); // 8-color display
// WriteCommand(lctData, 0x02); // 16-color display
/* if 256-color mode, bytes represent RRRGGGBB; the following
maps to 4-bit color for each value in range (0-7 R/G, 0-3 B) */
WriteCommand(lctCmd, RGBSET8); // 256-color position set
WriteCommand(lctData, 0x00); // 000 RED
WriteCommand(lctData, 0x02); // 001
WriteCommand(lctData, 0x04); // 010
WriteCommand(lctData, 0x06); // 011
WriteCommand(lctData, 0x08); // 100
WriteCommand(lctData, 0x0a); // 101
WriteCommand(lctData, 0x0c); // 110
WriteCommand(lctData, 0x0f); // 111
WriteCommand(lctData, 0x00); // 000 GREEN
WriteCommand(lctData, 0x02); // 001
WriteCommand(lctData, 0x04); // 010
WriteCommand(lctData, 0x06); // 011
WriteCommand(lctData, 0x08); // 100
WriteCommand(lctData, 0x0a); // 101
WriteCommand(lctData, 0x0c); // 110
WriteCommand(lctData, 0x0f); // 111
WriteCommand(lctData, 0x00); // 00 BLUE
WriteCommand(lctData, 0x06); // 01
WriteCommand(lctData, 0x09); // 10
WriteCommand(lctData, 0x0f); // 11
/* clear screen */
FillRect(0, 0, dxLCDScreen, dyLCDScreen, m_clrBack);
g_timer.WaitMs(100);
WriteCommand(lctCmd, DISON); // Display On
}
/* prints given string on the specified line; unused portion of
line will be padded with background color by default; use a
1-based value for a specific line, or 0 for the current line;
line is updated after outputting text */
void LCD::Print(const char *psz, uchar line, bool fPad)
{
const char *pch;
uchar dy;
if (m_pfont == NULL)
return;
SetPos(0, line);
pch = psz;
while (*pch != 0)
WriteCh(*pch++);
dy = m_pfont->DyFont() + dyLeading;
if (fPad && m_clrBack != clrTransparent) // blank rest of line
{
FillRect(0, m_y, dxMargin, dy, m_clrBack);
FillRect(m_x, m_y, dxLCDScreen - m_x, dy, m_clrBack);
}
/* update default output position */
m_y += dy;
m_x = dxMargin;
}
/* sets current text output location to the specified position
(ich, 0-based) on the specified line; note that for proportional
fonts, horizontal position is an approximation (based on the
width of a space); using line=0 will leave line unchanged */
void LCD::SetPos(uchar ich, uchar line)
{
uchar dx;
uchar f;
if (m_pfont == NULL)
return;
if (line != 0)
m_y = dyMargin + (m_pfont->DyFont() + dyLeading) * (line - 1);
m_x = dxMargin;
if (ich > 0)
{
/* get width of space */
m_pfont->PbForCh(' ', &f, &dx);
m_x += ich * (dx + dxLeading);
}
}
/* writes a character at the current location, updates current location */
void LCD::WriteCh(char ch)
{
uchar dx, dy;
uint cpx;
uchar f;
uchar grf;
const uchar *pb;
if (m_pfont == NULL)
return;
dy = m_pfont->DyFont();
pb = m_pfont->PbForCh(ch, &f, &dx);
cpx = CpxSetAndValidateLCDRect(m_x, m_y, dx, dy);
if (cpx != (uint)dx * dy) // not enough room
return;
memcpy_P(&grf, pb, sizeof(uchar));
if (m_clrBack == clrTransparent)
{
uchar x, y;
/* just set desired bits manually */
for (y = m_y; y < m_y + dy; ++y)
{
for (x = m_x; x < m_x + dx; ++x)
{
if (grf & f)
ColorPixel(x, y, m_clrFore);
if ((f >>= 1) == 0)
{
memcpy_P(&grf, ++pb, sizeof(uchar));
f = 0x80;
}
}
}
/* update current position */
m_x += dx + dxLeading;
}
else
{
/* area set above; just fill in the pixels */
while (cpx-- > 0)
{
WriteCommand(lctData, (grf & f) ? m_clrFore : m_clrBack);
if ((f >>= 1) == 0)
{
memcpy_P(&grf, ++pb, sizeof(uchar));
f = 0x80;
}
}
/* fill in background for leading below text */
FillRect(m_x, m_y + dy, dx + dxLeading, dyLeading, m_clrBack);
/* update current position */
m_x += dx;
/* fill in background for leading after character */
FillRect(m_x, m_y, dxLeading, dy, m_clrBack);
m_x += dxLeading;
}
}
/* set the color of given pixel; note that pixels off screen will be ignored */
void LCD::ColorPixel(uchar x, uchar y, uchar clr) const
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -