226 lines
4.7 KiB
C
226 lines
4.7 KiB
C
/**
|
|
* lcd.c: lcd menuing and support functions
|
|
* 2014 by true
|
|
*
|
|
* ----
|
|
*
|
|
* $Id: lcd.c 327 2015-02-18 04:43:42Z true $
|
|
*
|
|
**/
|
|
|
|
#include <pirate.h>
|
|
|
|
#include "lcd.h"
|
|
|
|
#include "../interface/i2c.h"
|
|
#include "../interface/gpio.h"
|
|
|
|
|
|
// led backlight
|
|
uint16_t lcd_led_level = 0;
|
|
uint16_t lcd_led_level_set = 0;
|
|
uint8_t lcd_led_rate;
|
|
uint8_t lcd_led_upd;
|
|
|
|
// lcd control
|
|
uint8_t lcd_height;
|
|
uint8_t lcd_cursor_pos;
|
|
uint8_t lcd_cursor_type;
|
|
uint8_t (*lcd_cgram)[8];
|
|
uint8_t lcd_cgram_len;
|
|
|
|
// lcd display
|
|
char lcd_line[2][9];
|
|
|
|
// lcd hardware
|
|
const tGPIO lcd_led_pin = {GPIOA, GPIO_Pin_6, 6};
|
|
|
|
|
|
/* functions */
|
|
void lcd_init()
|
|
{
|
|
static const uint8_t cmd_init[] = {
|
|
0x38, // set to i2c
|
|
0x39, // set to i2c
|
|
0x1d, // 1/4 bias, osc ~220hz
|
|
0x78, // contrast low 4 bits
|
|
0x5d, // icon enable, voltage boost enable, contrast high 2 bits
|
|
0x6d, // internal follower enable,
|
|
0x0c, // display on
|
|
0x01, // clear display
|
|
0x06 //
|
|
};
|
|
|
|
uint8_t *cmdptr = (uint8_t *)cmd_init;
|
|
|
|
I2C_WriteTransfer(LCD_I2C_ADDR, cmdptr, 9, LCD_CMD, 1);
|
|
|
|
// set stored contrast
|
|
lcd_set_contrast(settings.contrast);
|
|
}
|
|
|
|
void lcd_led_init()
|
|
{
|
|
TIM_TimeBaseInitTypeDef tim_tb;
|
|
TIM_OCInitTypeDef tim_oc;
|
|
GPIO_InitTypeDef gpio;
|
|
|
|
// enable clocks
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
|
|
|
|
// set up with 250 levels of brightness, with a bit of empty
|
|
tim_tb.TIM_Prescaler = 5 - 1; // 6.4MHz
|
|
tim_tb.TIM_Period = 320 - 1; // 25KHz PWM
|
|
tim_tb.TIM_ClockDivision = 0;
|
|
tim_tb.TIM_CounterMode = TIM_CounterMode_Up;
|
|
TIM_TimeBaseInit(LCD_LED_TIMER, &tim_tb);
|
|
|
|
// configure outputs as pwm
|
|
tim_oc.TIM_OCMode = TIM_OCMode_PWM1;
|
|
tim_oc.TIM_OutputState = TIM_OutputState_Enable;
|
|
tim_oc.TIM_Pulse = 0;
|
|
tim_oc.TIM_OCPolarity = LCD_LED_OC_POLARITY;
|
|
TIM_OC1Init(LCD_LED_TIMER, &tim_oc);
|
|
TIM_OC1PreloadConfig(LCD_LED_TIMER, TIM_OCPreload_Enable);
|
|
|
|
TIM_ARRPreloadConfig(LCD_LED_TIMER, ENABLE);
|
|
TIM_Cmd(LCD_LED_TIMER, ENABLE);
|
|
|
|
// configure output pin as timer AF
|
|
GPIO_StructInit(&gpio);
|
|
gpio.GPIO_Mode = GPIO_Mode_AF;
|
|
gpio.GPIO_Speed = GPIO_Speed_2MHz;
|
|
gpio.GPIO_Pin = lcd_led_pin.pin;
|
|
GPIO_Init(lcd_led_pin.port, &gpio);
|
|
|
|
GPIO_PinAFConfig(lcd_led_pin.port, lcd_led_pin.pinsource, GPIO_AF_TIM10);
|
|
}
|
|
|
|
void lcd_print(uint8_t pos, uint8_t *msg, uint8_t msg_len)
|
|
{
|
|
uint8_t len;
|
|
|
|
// which line/pos to print to?
|
|
I2C_WriteTransfer(LCD_I2C_ADDR, &pos, 1, LCD_CMD, 1);
|
|
|
|
// length to print
|
|
len = msg_len < LCD_MAX_LINE_LENGTH ? msg_len : LCD_MAX_LINE_LENGTH;
|
|
|
|
// send it
|
|
I2C_WriteTransfer(LCD_I2C_ADDR, msg, len, LCD_DATA, 1);
|
|
}
|
|
|
|
void lcd_linebuf_send()
|
|
{
|
|
lcd_print(LCD_LINE_1, (uint8_t *)lcd_line[0], 8);
|
|
|
|
if (lcd_get_height() != LCD_CMD_DOUBLEHEIGHT) {
|
|
lcd_print(LCD_LINE_2, (uint8_t *)lcd_line[1], 8);
|
|
}
|
|
}
|
|
|
|
|
|
void lcd_cmd(uint8_t cmd)
|
|
{
|
|
I2C_WriteTransfer(LCD_I2C_ADDR, &cmd, 1, LCD_CMD, 1);
|
|
// pirate_delay(1);
|
|
}
|
|
|
|
void lcd_set_contrast(uint8_t level) {
|
|
settings.contrast = level & 0x3f;
|
|
}
|
|
|
|
void lcd_apply_contrast()
|
|
{
|
|
// contrast is 6 bits; can be between 0 and 63
|
|
uint8_t cmd[2] = {0};
|
|
|
|
// form command
|
|
cmd[0] = 0x5c | (settings.contrast >> 4);
|
|
cmd[1] = 0x70 | (settings.contrast & 0x0f);
|
|
|
|
I2C_WriteTransfer(LCD_I2C_ADDR, cmd, 2, LCD_CMD, 1);
|
|
}
|
|
|
|
void lcd_set_height(uint8_t height)
|
|
{
|
|
if (height)
|
|
lcd_height = height;
|
|
}
|
|
|
|
uint8_t lcd_get_height()
|
|
{
|
|
return lcd_height;
|
|
}
|
|
|
|
void lcd_set_cursor(uint8_t pos, uint8_t type)
|
|
{
|
|
if (pos)
|
|
lcd_cursor_pos = pos;
|
|
|
|
if (type)
|
|
lcd_cursor_type = type;
|
|
}
|
|
|
|
uint8_t lcd_get_cursor_pos()
|
|
{
|
|
return lcd_cursor_pos;
|
|
}
|
|
|
|
uint8_t lcd_get_cursor_type()
|
|
{
|
|
return lcd_cursor_type;
|
|
}
|
|
|
|
void lcd_set_cgram_load(const uint8_t (*cgram)[8], const uint8_t len)
|
|
{
|
|
lcd_cgram = (uint8_t (*)[8])cgram;
|
|
lcd_cgram_len = (uint8_t)len;
|
|
}
|
|
|
|
void lcd_led_set_level(uint8_t level, uint8_t ramp_speed)
|
|
{
|
|
lcd_led_level_set = level;
|
|
lcd_led_rate = ramp_speed;
|
|
lcd_led_upd = LCD_LED_UPD_RATE;
|
|
|
|
// force an update now
|
|
lcd_led_update();
|
|
}
|
|
|
|
void lcd_led_update()
|
|
{
|
|
if (lcd_led_upd) {
|
|
lcd_led_upd--;
|
|
if (!lcd_led_upd) {
|
|
// are we done?
|
|
if (lcd_led_level == lcd_led_level_set) {
|
|
return;
|
|
}
|
|
// nope, check and see if we are increasing level
|
|
if (lcd_led_level_set > lcd_led_level) {
|
|
lcd_led_level += lcd_led_rate;
|
|
// level higher than target? then force to target
|
|
if (lcd_led_level > lcd_led_level_set) {
|
|
lcd_led_level = lcd_led_level_set;
|
|
}
|
|
}
|
|
// nope, check and see if we are decreasing level
|
|
if (lcd_led_level_set < lcd_led_level) {
|
|
// rate lower than target? if so, force to target
|
|
if ((lcd_led_level - lcd_led_level_set) > lcd_led_rate) {
|
|
lcd_led_level = lcd_led_level_set;
|
|
} else {
|
|
lcd_led_level -= lcd_led_rate;
|
|
}
|
|
}
|
|
|
|
// set OC
|
|
LCD_LED_TIMER->CCR1 = lcd_led_level;
|
|
|
|
// and reset countdown timer
|
|
lcd_led_upd = LCD_LED_UPD_RATE;
|
|
}
|
|
}
|
|
}
|