Interface for Sharp LS012B7DD01 TFT-LCD

Dependents:   MAX32630FTHR_iButton_uSD_Logger

Sharp_LS012B7DD01.cpp

Committer:
j3
Date:
2016-11-22
Revision:
2:ccef06c5becf
Parent:
1:ea88fe2c73ed

File content as of revision 2:ccef06c5becf:

/*******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 j3
*
* Permission is hereby granted, free of charge, to any person obtaining a copy 
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights 
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in 
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
* SOFTWARE.
******************************************************************************/


#include "Sharp_LS012B7DD01.h"

//5x7 character bit map
static const uint8_t font_5x7[95][6] = {
	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //SPACE
	{0x00, 0x00, 0x00, 0xf2, 0x00, 0x00}, //!
	{0x00, 0x00, 0xe0, 0x00, 0xe0, 0x00}, //"
	{0x00, 0x28, 0xfe, 0x28, 0xfe, 0x28}, //#
	{0x00, 0x24, 0x54, 0xfe, 0x54, 0x48}, //$
	{0x00, 0xc4, 0xc8, 0x10, 0x26, 0x46}, //%
	{0x00, 0x6c, 0x92, 0xaa, 0x44, 0x0a}, //&
	{0x00, 0x00, 0xa0, 0xc0, 0x00, 0x00}, //'
	{0x00, 0x00, 0x38, 0x44, 0x82, 0x00}, //(
	{0x00, 0x00, 0x82, 0x44, 0x38, 0x00}, //)
	{0x00, 0x28, 0x10, 0x7c, 0x10, 0x28}, //*
	{0x00, 0x10, 0x10, 0x7c, 0x10, 0x10}, //+
	{0x00, 0x00, 0x0a, 0x0c, 0x00, 0x00}, //,
	{0x00, 0x10, 0x10, 0x10, 0x10, 0x10}, //-
	{0x00, 0x00, 0x06, 0x06, 0x00, 0x00}, //.
	{0x00, 0x04, 0x08, 0x10, 0x20, 0x40}, ///
	{0x00, 0x7c, 0x8a, 0x92, 0xa2, 0x7c}, //0
	{0x00, 0x00, 0x42, 0xfe, 0x02, 0x00}, //1
	{0x00, 0x42, 0x86, 0x8a, 0x92, 0x62}, //2
	{0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c}, //3
	{0x00, 0x18, 0x28, 0x48, 0xfe, 0x08}, //4
	{0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c}, //5
	{0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c}, //6
	{0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0}, //7
	{0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c}, //8
	{0x00, 0x60, 0x92, 0x92, 0x94, 0x78}, //9
	{0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00}, //:
	{0x00, 0x6a, 0x6c, 0x00, 0x00, 0x00}, //;
	{0x00, 0x10, 0x28, 0x44, 0x82, 0x00}, //<
	{0x00, 0x28, 0x28, 0x28, 0x28, 0x28}, //=
	{0x00, 0x00, 0x82, 0x44, 0x28, 0x10}, //>
	{0x00, 0x40, 0x80, 0x8a, 0x90, 0x60}, //?
	{0x00, 0x0c, 0x92, 0x9e, 0x82, 0x7c}, //@
	{0x00, 0x7e, 0x88, 0x88, 0x88, 0x7e}, //A
	{0x00, 0xfe, 0x92, 0x92, 0x92, 0x6c}, //B
	{0x00, 0x7c, 0x82, 0x82, 0x82, 0x44}, //C
	{0x00, 0xfe, 0x82, 0x82, 0x44, 0x38}, //D
	{0x00, 0xfe, 0x92, 0x92, 0x92, 0x82}, //E
	{0x00, 0xfe, 0x90, 0x90, 0x90, 0x80}, //F
	{0x00, 0x7c, 0x82, 0x92, 0x92, 0x5e}, //G
	{0x00, 0xfe, 0x10, 0x10, 0x10, 0xfe}, //H
	{0x00, 0x00, 0x82, 0xfe, 0x82, 0x00}, //I
	{0x00, 0x04, 0x02, 0x82, 0xfc, 0x80}, //J
	{0x00, 0xfe, 0x10, 0x28, 0x44, 0x82}, //K
	{0x00, 0xfe, 0x02, 0x02, 0x02, 0x02}, //L
	{0x00, 0xfe, 0x40, 0x30, 0x40, 0xfe}, //M
	{0x00, 0xfe, 0x20, 0x10, 0x08, 0xfe}, //N
	{0x00, 0x7c, 0x82, 0x82, 0x82, 0x7c}, //O
	{0x00, 0xfe, 0x90, 0x90, 0x90, 0x60}, //P
	{0x00, 0x7c, 0x82, 0x8a, 0x84, 0x7a}, //Q
	{0x00, 0xfe, 0x90, 0x98, 0x94, 0x62}, //R
	{0x00, 0x62, 0x92, 0x92, 0x92, 0x8c}, //S
	{0x00, 0x80, 0x80, 0xfe, 0x80, 0x80}, //T
	{0x00, 0xfc, 0x02, 0x02, 0x02, 0xfc}, //U
	{0x00, 0xf8, 0x04, 0x02, 0x04, 0xf8}, //V
	{0x00, 0xfc, 0x02, 0x0c, 0x02, 0xfc}, //W
	{0x00, 0xc6, 0x28, 0x10, 0x28, 0xc6}, //X
	{0x00, 0xe0, 0x10, 0x0e, 0x10, 0xe0}, //Y
	{0x00, 0x86, 0x8a, 0x92, 0xa2, 0xc2}, //Z
	{0x00, 0x00, 0xfe, 0x82, 0x82, 0x00}, //[
	{0x00, 0x40, 0x20, 0x10, 0x08, 0x04}, //backslash
	{0x00, 0x00, 0x82, 0x82, 0xfe, 0x00}, //]
	{0x00, 0x20, 0x40, 0x80, 0x40, 0x20}, //^
	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02}, //_
	{0x00, 0x00, 0x80, 0x40, 0x20, 0x00}, //`
	{0x00, 0x04, 0x2a, 0x2a, 0x2a, 0x1e}, //a
	{0x00, 0xfe, 0x0a, 0x12, 0x12, 0x0c}, //b
	{0x00, 0x1c, 0x22, 0x22, 0x22, 0x04}, //c
	{0x00, 0x1c, 0x22, 0x22, 0x12, 0xfe}, //d
	{0x00, 0x1c, 0x2a, 0x2a, 0x2a, 0x18}, //e
	{0x00, 0x10, 0x7e, 0x90, 0x80, 0x40}, //f
	{0x00, 0x30, 0x4a, 0x4a, 0x4a, 0x7c}, //g
	{0x00, 0xfe, 0x10, 0x20, 0x20, 0x1e}, //h
	{0x00, 0x00, 0x22, 0xbe, 0x02, 0x00}, //i
	{0x00, 0x04, 0x02, 0x22, 0xbc, 0x00}, //j
	{0x00, 0xfe, 0x08, 0x14, 0x22, 0x00}, //k
	{0x00, 0x00, 0x82, 0xfe, 0x02, 0x00}, //l
	{0x00, 0x1e, 0x20, 0x1a, 0x22, 0x1e}, //m
	{0x00, 0x3e, 0x10, 0x20, 0x20, 0x1e}, //n
	{0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c}, //o
	{0x00, 0x3e, 0x28, 0x28, 0x28, 0x10}, //p
	{0x00, 0x10, 0x28, 0x28, 0x18, 0x3e}, //q
	{0x00, 0x3e, 0x10, 0x20, 0x20, 0x10}, //r
	{0x00, 0x12, 0x2a, 0x2a, 0x2a, 0x04}, //s
	{0x00, 0x20, 0xfc, 0x22, 0x02, 0x04}, //t
	{0x00, 0x3c, 0x02, 0x02, 0x04, 0x3e}, //u
	{0x00, 0x38, 0x04, 0x02, 0x04, 0x38}, //v
	{0x00, 0x3c, 0x02, 0x0c, 0x02, 0x3c}, //w
	{0x00, 0x22, 0x14, 0x08, 0x14, 0x22}, //x
	{0x00, 0x30, 0x0a, 0x0a, 0x0a, 0x3c}, //y
	{0x00, 0x22, 0x26, 0x2a, 0x32, 0x22}, //z
	{0x00, 0x00, 0x10, 0x6c, 0x82, 0x00}, //{
	{0x00, 0x00, 0x00, 0xfe, 0x00, 0x00}, //|
	{0x00, 0x00, 0x82, 0x6c, 0x10, 0x00}, //}
	{0x00, 0x30, 0x40, 0x30, 0x08, 0x30}  //~
};

/*****************************************************************************/
SharpLS012B7DD01::SharpLS012B7DD01(PinName disp, PinName extcomin, PinName cs, SPI &spiBus)
:m_disp(disp, 0), m_extcomin(extcomin, 0), m_cs(cs, 0), m_spi(spiBus)
{
	update(SharpLS012B7DD01::ALL_CLEAR_MODE);
	m_disp = !m_disp;
	wait_us(30);
	m_extcominTicker.attach(callback(this, &SharpLS012B7DD01::toggle_extcomin), 0.016);
}


/*****************************************************************************/
SharpLS012B7DD01::~SharpLS012B7DD01()
{
}

/*****************************************************************************/
SharpLS012B7DD01::SharpCmdResult SharpLS012B7DD01::print_char(uint8_t ln, uint8_t pos, char c)
{
	SharpLS012B7DD01::SharpCmdResult rtnVal = SharpLS012B7DD01::Failure;
	
	uint8_t char_buff[6];
	memcpy(char_buff, &(font_5x7[c - 0x20][0]), 6);
	
	if((ln < 4) && (pos < 30))
	{
		ln = ((ln * 8) + 4);
		pos = ((pos * 6) + 2);
		
		uint8_t temp;
		for(uint8_t c_bit = 0; c_bit < 8; c_bit++)
		{
			temp = 0;
			for(uint8_t c_byte = 0; c_byte < 6; c_byte++)
			{
				if(((1 << (7 - c_bit)) & char_buff[c_byte]))
				{
					temp |= (1 << c_byte);
				}
			}
			
			//display is active low
			temp = ~temp;
			
			if((pos % 8) == 0)
			{
				if(pos)
				{
					m_data[ln + c_bit][pos/8] &= ~(0x3F);
					m_data[ln + c_bit][pos/8] |= temp;
				}
				else
				{
					m_data[ln + c_bit][0] &= ~(0x3F);
					m_data[ln + c_bit][0] |= temp;
				}
			}
			else
			{
				m_data[ln + c_bit][pos/8] &= ~(0x3F << (pos%8));
				m_data[ln + c_bit][pos/8] |= (temp << (pos%8));
				if((pos % 8) > 2)
				{
					uint8_t temp2 = 0;
					for(uint8_t idx = 0; idx < ((pos%8) -2); idx++)
					{
						temp2 |= (1 << idx);
					}
					m_data[ln + c_bit][(pos/8) + 1] &= ~temp2;
					m_data[ln + c_bit][(pos/8) + 1] |= (temp >> (8 - (pos%8)));
				}
			}
		}
		
		rtnVal = write_memory(m_data, 8, ln);
	}
	
	return rtnVal;
}


/*****************************************************************************/
SharpLS012B7DD01::SharpCmdResult SharpLS012B7DD01::print_str(uint8_t ln, uint8_t pos, const char *s)
{
	SharpLS012B7DD01::SharpCmdResult rtnVal = SharpLS012B7DD01::Failure;
	
	size_t len = strlen(s);
	
	if((ln < 4) && ((pos + (len - 1)) < 30))
	{
		for(size_t idx = 0; idx < len; idx++)
		{
			rtnVal = print_char(ln, (pos + idx), s[idx]);
		}
	}
	
	return rtnVal;
}


/*****************************************************************************/
void SharpLS012B7DD01::clear_display()
{
	update(SharpLS012B7DD01::ALL_CLEAR_MODE);
}


/*****************************************************************************/
SharpLS012B7DD01::SharpCmdResult SharpLS012B7DD01::write_memory(uint8_t data[][23], uint8_t lines, uint8_t offset)
{
	SharpLS012B7DD01::SharpCmdResult rtnVal = Failure;
	
	if((lines + offset) <= 38)
	{
		m_cs = !m_cs;
		//send mode
		m_spi.write(SharpLS012B7DD01::DATA_UPDATE_MODE);
		for(uint8_t idy = offset; idy < (lines + offset); idy++)
		{
			//send line adrs
			m_spi.write(rev_bit(idy + 1));
			for(uint8_t idx = 0; idx < 23; idx++)
			{
				m_spi.write(rev_bit(data[idy][idx]));
			}
			//dummy data required by datasheet
			m_spi.write(0);
			m_spi.write(0);
		}
		//last line requires 16 xfr clocks too
		m_spi.write(0);
		m_cs = !m_cs;
		
		rtnVal = Success;
	}
	
	return rtnVal;
}


/*****************************************************************************/
void SharpLS012B7DD01::update(const uint8_t mode)
{
	m_cs = !m_cs;
	//send mode
	m_spi.write(mode);
	m_spi.write(0);
	m_spi.write(0);
	m_cs = !m_cs;
	
	if(mode == SharpLS012B7DD01::ALL_CLEAR_MODE)
	{
		for(uint8_t idy = 0; idy < 38; idy++)
		{
			for(uint8_t idx = 0; idx < 23; idx ++)
			{
				m_data[idy][idx] = 0xFF;
			}
		}
	}
}


/*****************************************************************************/
uint8_t SharpLS012B7DD01::rev_bit(uint8_t data)
{
	uint8_t temp = 0;
	for(uint8_t idx = 0; idx < 8; idx++)
	{
		if((1 << idx) & data)
		{
			temp |= (0x80 >> idx);
		}
	}
	
	return temp;
}


/*****************************************************************************/
void SharpLS012B7DD01::toggle_extcomin()
{
	m_extcomin = !m_extcomin;
}