diff options
Diffstat (limited to 'source/sharp/Adafruit_SharpMem.cpp')
-rw-r--r-- | source/sharp/Adafruit_SharpMem.cpp | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/source/sharp/Adafruit_SharpMem.cpp b/source/sharp/Adafruit_SharpMem.cpp new file mode 100644 index 0000000..5e963ff --- /dev/null +++ b/source/sharp/Adafruit_SharpMem.cpp @@ -0,0 +1,315 @@ +/********************************************************************* +This is an Arduino library for our Monochrome SHARP Memory Displays + + Pick one up today in the adafruit shop! + ------> http://www.adafruit.com/products/1393 + +These displays use SPI to communicate, 3 pins are required to +interface + +Adafruit invests time and resources providing this open source code, +please support Adafruit and open-source hardware by purchasing +products from Adafruit! + +Written by Limor Fried/Ladyada for Adafruit Industries. +BSD license, check license.txt for more information +All text above, and the splash screen must be included in any redistribution +*********************************************************************/ + +#include "Adafruit_SharpMem.h" + +#ifndef _swap_int16_t +#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } +#endif +#ifndef _swap_uint16_t +#define _swap_uint16_t(a, b) { uint16_t t = a; a = b; b = t; } +#endif + +/************************************************************************** + Sharp Memory Display Connector + ----------------------------------------------------------------------- + Pin Function Notes + === ============== =============================== + 1 VIN 3.3-5.0V (into LDO supply) + 2 3V3 3.3V out + 3 GND + 4 SCLK Serial Clock + 5 MOSI Serial Data Input + 6 CS Serial Chip Select + 9 EXTMODE COM Inversion Select (Low = SW clock/serial) + 7 EXTCOMIN External COM Inversion Signal + 8 DISP Display On(High)/Off(Low) + + **************************************************************************/ + +#define SHARPMEM_BIT_WRITECMD (0x80) +#define SHARPMEM_BIT_VCOM (0x40) +#define SHARPMEM_BIT_CLEAR (0x20) +#define TOGGLE_VCOM do { _sharpmem_vcom = _sharpmem_vcom ? 0x00 : SHARPMEM_BIT_VCOM; } while(0); + +byte *sharpmem_buffer; + +/* ************* */ +/* CONSTRUCTORS */ +/* ************* */ +Adafruit_SharpMem::Adafruit_SharpMem(uint8_t clk, uint8_t mosi, uint8_t ss, uint16_t width, uint16_t height) : +Adafruit_GFX(width, height) { + _clk = clk; + _mosi = mosi; + _ss = ss; +} + +boolean Adafruit_SharpMem::begin(void) { + // Set pin state before direction to make sure they start this way (no glitching) + digitalWrite(_ss, HIGH); + digitalWrite(_clk, LOW); + digitalWrite(_mosi, HIGH); + + pinMode(_ss, OUTPUT); + pinMode(_clk, OUTPUT); + pinMode(_mosi, OUTPUT); + +#if defined(USE_FAST_PINIO) + clkport = portOutputRegister(digitalPinToPort(_clk)); + clkpinmask = digitalPinToBitMask(_clk); + dataport = portOutputRegister(digitalPinToPort(_mosi)); + datapinmask = digitalPinToBitMask(_mosi); +#endif + + // Set the vcom bit to a defined state + _sharpmem_vcom = SHARPMEM_BIT_VCOM; + + + sharpmem_buffer = (byte *)malloc((WIDTH * HEIGHT) / 8); + + if (!sharpmem_buffer) return false; + + setRotation(0); + + return true; +} + +/* *************** */ +/* PRIVATE METHODS */ +/* *************** */ + + +/**************************************************************************/ +/*! + @brief Sends a single byte in pseudo-SPI. +*/ +/**************************************************************************/ +void Adafruit_SharpMem::sendbyte(uint8_t data) +{ + uint8_t i = 0; + + // LCD expects LSB first + +#if defined(USE_FAST_PINIO) + for (i=0; i<8; i++) { + // Make sure clock starts low + *clkport &= ~clkpinmask; + if (data & 0x80) + *dataport |= datapinmask; + else + *dataport &= ~datapinmask; + + // Clock is active high + *clkport |= clkpinmask; + data <<= 1; + } + *clkport &= ~clkpinmask; +#else + for (i=0; i<8; i++) { + // Make sure clock starts low + digitalWrite(_clk, LOW); + if (data & 0x80) + digitalWrite(_mosi, HIGH); + else + digitalWrite(_mosi, LOW); + + // Clock is active high + digitalWrite(_clk, HIGH); + data <<= 1; + } + // Make sure clock ends low + digitalWrite(_clk, LOW); +#endif +} + +void Adafruit_SharpMem::sendbyteLSB(uint8_t data) +{ + uint8_t i = 0; + + // LCD expects LSB first +#if defined(USE_FAST_PINIO) + for (i=0; i<8; i++) { + // Make sure clock starts low + *clkport &= ~clkpinmask; + if (data & 0x01) + *dataport |= datapinmask; + else + *dataport &= ~datapinmask; + // Clock is active high + *clkport |= clkpinmask; + data >>= 1; + } + // Make sure clock ends low + *clkport &= ~clkpinmask; +#else + for (i=0; i<8; i++) + { + // Make sure clock starts low + digitalWrite(_clk, LOW); + if (data & 0x01) + digitalWrite(_mosi, HIGH); + else + digitalWrite(_mosi, LOW); + // Clock is active high + digitalWrite(_clk, HIGH); + data >>= 1; + } + // Make sure clock ends low + digitalWrite(_clk, LOW); +#endif +} + +/* ************** */ +/* PUBLIC METHODS */ +/* ************** */ + +// 1<<n is a costly operation on AVR -- table usu. smaller & faster +static const uint8_t PROGMEM + set[] = { 1, 2, 4, 8, 16, 32, 64, 128 }, + clr[] = { (uint8_t)~1 , (uint8_t)~2 , (uint8_t)~4 , (uint8_t)~8, + (uint8_t)~16, (uint8_t)~32, (uint8_t)~64, (uint8_t)~128 }; + +/**************************************************************************/ +/*! + @brief Draws a single pixel in image buffer + + @param[in] x + The x position (0 based) + @param[in] y + The y position (0 based) +*/ +/**************************************************************************/ +void Adafruit_SharpMem::drawPixel(int16_t x, int16_t y, uint16_t color) +{ + if((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return; + + switch(rotation) { + case 1: + _swap_int16_t(x, y); + x = WIDTH - 1 - x; + break; + case 2: + x = WIDTH - 1 - x; + y = HEIGHT - 1 - y; + break; + case 3: + _swap_int16_t(x, y); + y = HEIGHT - 1 - y; + break; + } + + if(color) { + sharpmem_buffer[(y * WIDTH + x) / 8] |= + pgm_read_byte(&set[x & 7]); + } else { + sharpmem_buffer[(y * WIDTH + x) / 8] &= + pgm_read_byte(&clr[x & 7]); + } +} + +/**************************************************************************/ +/*! + @brief Gets the value (1 or 0) of the specified pixel from the buffer + + @param[in] x + The x position (0 based) + @param[in] y + The y position (0 based) + + @return 1 if the pixel is enabled, 0 if disabled +*/ +/**************************************************************************/ +uint8_t Adafruit_SharpMem::getPixel(uint16_t x, uint16_t y) +{ + if((x >= _width) || (y >= _height)) return 0; // <0 test not needed, unsigned + + switch(rotation) { + case 1: + _swap_uint16_t(x, y); + x = WIDTH - 1 - x; + break; + case 2: + x = WIDTH - 1 - x; + y = HEIGHT - 1 - y; + break; + case 3: + _swap_uint16_t(x, y); + y = HEIGHT - 1 - y; + break; + } + + return sharpmem_buffer[(y * WIDTH + x) / 8] & + pgm_read_byte(&set[x & 7]) ? 1 : 0; +} + +/**************************************************************************/ +/*! + @brief Clears the screen +*/ +/**************************************************************************/ +void Adafruit_SharpMem::clearDisplay() +{ + memset(sharpmem_buffer, 0xff, (WIDTH * HEIGHT) / 8); + // Send the clear screen command rather than doing a HW refresh (quicker) + digitalWrite(_ss, HIGH); + sendbyte(_sharpmem_vcom | SHARPMEM_BIT_CLEAR); + sendbyteLSB(0x00); + TOGGLE_VCOM; + digitalWrite(_ss, LOW); +} + +/**************************************************************************/ +/*! + @brief Renders the contents of the pixel buffer on the LCD +*/ +/**************************************************************************/ +void Adafruit_SharpMem::refresh(void) +{ + uint16_t i, totalbytes, currentline, oldline; + totalbytes = (WIDTH * HEIGHT) / 8; + + // Send the write command + digitalWrite(_ss, HIGH); + sendbyte(SHARPMEM_BIT_WRITECMD | _sharpmem_vcom); + TOGGLE_VCOM; + + // Send the address for line 1 + oldline = currentline = 1; + sendbyteLSB(currentline); + + // Send image buffer + for (i=0; i<totalbytes; i++) + { + sendbyteLSB(sharpmem_buffer[i]); + currentline = ((i+1)/(WIDTH/8)) + 1; + if(currentline != oldline) + { + // Send end of line and address bytes + sendbyteLSB(0x00); + if (currentline <= HEIGHT) + { + sendbyteLSB(currentline); + } + oldline = currentline; + } + } + + // Send another trailing 8 bits for the last line + sendbyteLSB(0x00); + digitalWrite(_ss, LOW); +} |