This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

lcd.c

Committer:
Clemo
Date:
2014-10-28
Revision:
1:8ae4ab73ca6a
Parent:
0:cb80470434eb

File content as of revision 1:8ae4ab73ca6a:

/**
* @file
* Implementation of a portable LCD driver.
*
* You have to provide two functions to interface this driver
* to the actual hardware:
*
* void lcd_4bit_write_port(uint8_t value);
*
* uint8_t lcd_4bit_read_port(void);
*
* void lcd_backlight(uint8_t on);
*
* Author: Clemens Valens
* License: GNU General Public License
*
* History
* 2011.04.11  ver 1.00    Preliminary version, first release
*/

#include "lcd.h"
#include "systick.h"
#include "string.h"


const uint8_t custom_characters[8][8] =
{
	/*{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f },
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f },
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f },
	{ 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f },
	{ 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f },
	{ 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f },
	{ 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f },
	{ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }*/
	{ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 },
	{ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04 },
	{ 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04 },
	{ 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04 },
	{ 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04 },
//	{ 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04 },
	{ 0x04, 0x04, 0x04, 0x0e, 0x0e, 0x1f, 0x1f, 0x04 },
	{ 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 },
	{ 0x1f, 0x1f, 0x0e, 0x0e, 0x04, 0x04, 0x04, 0x04 }
};

typedef uint8_t I2C_ID_T;
#define I2C0  (0)

// State machine handler for I2C0 and I2C1.
static void i2c_state_handling(I2C_ID_T id)
{
	/*if (Chip_I2C_IsMasterActive(id))
	{
		Chip_I2C_MasterStateHandler(id);
	}
	else
	{
		Chip_I2C_SlaveStateHandler(id);
	}*/
}


void I2C_IRQHandler(void)
{
	i2c_state_handling(I2C0);
}


void st7032i_write_byte(uint8_t cmd_or_data, uint8_t value)
{
	// buffer must be static because the I2C engine does not copy the data,
	// but uses a pointer to buffer.
	//static uint8_t buffer[2];
	//buffer[0] = cmd_or_data;
	//buffer[1] = value;
	//Chip_I2C_MasterSend(I2C0,LCD_I2C_ADDRESS,buffer,2);
}


void st7032i_write_data(uint8_t value)
{
	// Bit 6 (the RS bit) must be set (1) in order to write the Data Register (DR).
	// With bit 7 cleared (the Co bit) only one control byte can be sent.
	st7032i_write_byte(0x40,value);
}


void st7032i_write_command(uint8_t cmd, uint8_t value)
{
	// Bit 6 (the RS bit) must be cleared (0) in order to write the Instruction Register (IR).
	// With bit 7 cleared (the Co bit) only one control byte can be sent.
	st7032i_write_byte(0x00,cmd|value);
}


uint8_t lcd_putc(char ch)
{
	st7032i_write_data(ch);
	return 1;
}


uint8_t lcd_puts(char *p_str)
{
	uint8_t result = 0;

	while (*p_str!=0)
	{
		st7032i_write_data(*p_str++);
		result += 1;
	}

	return result;
}


void lcd_clear(void)
{
	st7032i_write_command(ST7032_CMD_CLEAR,0);
	SysTick_Delay(2);
}


void lcd_cursor(uint8_t line, uint8_t column)
{
	st7032i_write_command(ST7032_CMD_DDRAM_ADDRESS,(line==0?0:0x40)+column);
	lcd_display_cursor_blink(1,0,0);
}


void lcd_display_cursor_blink(uint8_t display, uint8_t cursor, uint8_t blink)
{
	uint8_t cmd = 0;
	if (display!=0) cmd |= ST7032_DISPLAY_ON;
	// Beware of auto-increment. If you don't see the cursor, maybe it fell off the screen?
	if (cursor!=0) cmd |= ST7032_CURSOR_ON;
	if (blink!=0) cmd |= ST7032_BLINK_ON;
	st7032i_write_command(ST7032_CMD_ON_OFF,cmd);
}


void lcd_clear_to_eol(int line, int column)
{
	uint8_t i;
	lcd_cursor(line,column);
	for (i=column; i<BOARD_LCD_CHARS_PER_LINE; i++)
	{
		lcd_putc(' ');
	}
	lcd_cursor(line,column);
}


void lcd_contrast(uint8_t contrast)
{
	// Set contrast low bits.
	st7032i_write_command(ST7032_CMD_CONTRAST_LO,contrast&ST7032_CONTRAST_LO_MASK);
	// Set contrast high bits.
	// When LCD is powered from 3V the booster must be on.
	st7032i_write_command(ST7032_CMD_POWER_ICON_CONTRAST,ST7032_BOOSTER_ON|((contrast>>4)&ST7032_CONTRAST_HI_MASK));
}


void lcd_font(uint8_t font)
{
	st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_EXTENDED|(font&ST7032_FUNC_HEIGHT_DOUBLE));
}


void lcd_set_custom_character(uint8_t index, const uint8_t *p_data)
{
	int i;
	// Up to 8 custom characters may be defined.
	// Select function table 0.
	st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_NORMAL);
	// Set CGRAM address.
	st7032i_write_command(ST7032_CMD_CGRAM_ADDRESS,(8*index)&0x3f);
	// 8 bytes per character.
	for (i=0; i<7; i++)
	{
		st7032i_write_data(p_data[i]&0x1f);
	}
}


void lcd_bar_graph(uint8_t position, uint8_t value, uint8_t value_max)
{
	//st7032i_write_command(ST7032_CMD_ON_OFF,ST7032_DISPLAY_ON|ST7032_CURSOR_OFF|ST7032_BLINK_OFF);
	uint16_t v = value;
	v = 14*v/value_max; // map [1,255] to 14 possibilities, 0 is possibility 15.
	lcd_cursor(1,position);
	if (v<=6)
	{
		if (value==0)
		{
			v = 5; //'0';
		}
		else
		{
			v += 1;
			if (v==5) v = 0x11;
			else if (v==7) v = 'T';
		}
		lcd_putc(v);
		lcd_cursor(0,position);
		lcd_putc(0);
	}
	else
	{
		lcd_putc(0);
		lcd_cursor(0,position);
		v -= 6;
		if (v==5) v = 0x11;
		else if (v==7) v = 'T';
		else if (v>7) v = 7; //'M';
		lcd_putc(v);
	}
}


void lcd_init(void)
{
	int i;

	Board_LCD_SetBacklight(true);
	// Liberate LCD.
	SysTick_Delay(10);
	Board_LCD_ResetDeassert();
	SysTick_Delay(ST7032_RESET_RECOVERY_TIME);

	// Setup I2C port.
//	Chip_SYSCTL_DeassertPeriphReset(RESET_I2C0);
//	Chip_I2C_Init(I2C0);
//	Chip_I2C_SetClockRate(I2C0,400000); // ST7032 can handle 400 kHz.
//	Chip_I2C_SetMasterEventHandler(I2C0,Chip_I2C_EventHandler);
	// Enable I2C interrupts.
//	NVIC_EnableIRQ(I2C0_IRQn);
	// Low interrupt priority.
//	NVIC_SetPriority(I2C0_IRQn,7);

	// Initialize LCD module.
	// Set custom characters.
	for (i=0; i<8; i++)
	{
		lcd_set_custom_character(i,(const uint8_t *)&custom_characters[i]);
	}
	// Set our default config and enable extended functions.
	st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_EXTENDED);
	// Set internal oscillator.
	st7032i_write_command(ST7032_CMD_BIAS_OSC,ST7032_BIAS_020|4);
	// Set contrast. 4 is a good value for 3V displays.
	lcd_contrast(4);
	// Follower on, amplifier max. (Why? From the Midas datasheet)
	st7032i_write_command(ST7032_CMD_FOLLOWER,ST7032_FOLLOWER_ON|7);
	// A 200 ms delay is recommended for the power to stabilize.
	SysTick_Delay(200);
	// Display on.
	//st7032i_write_command(ST7032_CMD_ON_OFF,ST7032_DISPLAY_ON|ST7032_CURSOR_OFF|ST7032_BLINK_OFF);
	lcd_display_cursor_blink(1,0,0);
	// Clear display.
	lcd_clear();

	// Check custom characters.
	/*lcd_display_cursor_blink(1,1,0);
	for (i=0; i<8; i++)
	{
		lcd_putc((char)i);
	}
	SysTick_Delay(5000);*/
}