diff --git a/MicroView.cpp b/MicroView.cpp index a54eb89..b10c361 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -2,36 +2,70 @@ #include #include +/* +Screen memory buffer 64 x 48 divided by 8 = 384 bytes +Screen memory buffer is required because in SPI mode, the host cannot read the GDRAM of the controller. This buffer serves as a scratch RAM for graphical functions. +*/ +static uint8_t screenmemory [] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xC0, + 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, + 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0x78, 0xF8, 0xBC, 0xFC, 0xDE, 0xDE, 0xCF, 0xCF, 0xC7, 0xC3, 0xC3, + 0xC7, 0x87, 0x8F, 0x0F, 0x1E, 0x1E, 0x3C, 0x78, 0x78, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xEF, 0xE7, 0xC7, + 0xC3, 0x83, 0x01, 0x01, 0x00, 0x0F, 0x1F, 0x3F, 0x71, 0x6E, 0xEE, 0xEF, 0xF3, 0xF7, 0xF6, 0xF9, + 0xFD, 0xDD, 0xEB, 0x7F, 0x7E, 0xBC, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF1, 0x79, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x1F, 0x1E, 0xFC, 0xFD, 0xF9, 0x7B, + 0xF3, 0xE7, 0xEF, 0xCF, 0xDE, 0x9E, 0xBC, 0x3C, 0x78, 0x78, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, + 0xBC, 0xFE, 0xFE, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x00, + 0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x1E, 0x3F, 0x3F, 0x3F, 0x1F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0x1F, 0x3F, 0x3F, 0x1F, 0x03, 0x07, + 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, + 0x0F, 0x07, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + void MICROVIEW::begin() { - // SPI - SPI.setClockDivider(SPI_CLOCK_DIV2); - SPI.begin(); + // Setting up SPI pins pinMode(MOSI, OUTPUT); pinMode(SCK, OUTPUT); pinMode(DC, OUTPUT); pinMode(RESET, OUTPUT); - pinMode(cs, OUTPUT); - digitalWrite(cs, HIGH); + pinMode(CS, OUTPUT); + digitalWrite(CS, HIGH); sckport = portOutputRegister(digitalPinToPort(SCK)); sckpinmask = digitalPinToBitMask(SCK); mosiport = portOutputRegister(digitalPinToPort(MOSI)); mosipinmask = digitalPinToBitMask(MOSI); - csport = portOutputRegister(digitalPinToPort(cs)); - cspinmask = digitalPinToBitMask(cs); + csport = portOutputRegister(digitalPinToPort(CS)); + cspinmask = digitalPinToBitMask(CS); dcport = portOutputRegister(digitalPinToPort(DC)); dcpinmask = digitalPinToBitMask(DC); digitalWrite(RESET, HIGH); - // VDD (3.3V) goes high at start, lets just chill for a ms - delay(1); + // VDD (3.3V) goes high at start, lets just chill for 5 ms + delay(5); // bring reset low digitalWrite(RESET, LOW); + + // Setup SPI frequency + SPI.setClockDivider(SPI_CLOCK_DIV2); + SPI.begin(); + // wait 10ms delay(10); // bring out of reset digitalWrite(RESET, HIGH); - // turn on VCC + // Init sequence for 64x48 OLED module command(DISPLAYOFF); // 0xAE @@ -52,10 +86,6 @@ void MICROVIEW::begin() { command(NORMALDISPLAY); // 0xA6 command(DISPLAYALLONRESUME); // 0xA4 - -// command(MEMORYMODE); // 0x20 -// command(0x00); // Horizontal Memory Addressing mode - command(SEGREMAP | 0x1); command(COMSCANDEC); @@ -105,14 +135,91 @@ void MICROVIEW::setColumnAddress(uint8_t add) { return; } -void MICROVIEW::clear(void) { - for (int i=0;i<8; i++) { - setPageAddress(i); - setColumnAddress(0); - for (int j=0; j<0x80; j++) { - data(0); + +/* + Clear GDRAM inside the LCD controller - mode = ALL + Clear screen page buffer - mode = PAGE +*/ +void MICROVIEW::clear(uint8_t mode) { + uint8_t page=6, col=0x40; + if (mode==ALL) { + + for (int i=0;i<8; i++) { + setPageAddress(i); + setColumnAddress(0); + for (int j=0; j<0x80; j++) { + data(0); + } } } + else + { + memset(screenmemory,0,384); // (64 x 48) / 8 = 384 + display(); + } +} + +void MICROVIEW::display(void) { + uint8_t i, j; + + for (i=0; i<6; i++) { + setPageAddress(i); + setColumnAddress(0); + for (j=0;j<0x40;j++) { + data(screenmemory[i*0x40+j]); + } + } +} + +void MICROVIEW::pixel(uint8_t x, uint8_t y, uint8_t color) { + if ((x<0) || (x>LCDWIDTH-1) || (y<0) || (y>LCDHEIGHT-1)) + return; + + if (color==WHITE) + screenmemory[x+ (y/8)*LCDWIDTH] |= _BV((y%8)); + else + screenmemory[x+ (y/8)*LCDWIDTH] &= ~_BV((y%8)); + + //display(); +} + +// bresenham's algorithm +void MICROVIEW::line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color) { + uint8_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + swap(x0, y0); + swap(x1, y1); + } + + if (x0 > x1) { + swap(x0, x1); + swap(y0, y1); + } + + uint8_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int8_t err = dx / 2; + int8_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1;} + + for (; x0