#include "includes.h"

// 是否自检屏状态
u8 self_check_state = 0;

// 显示缓冲区
TVideoBuf VideoBuf = {0};
TVideoBuf Last_VideoBuf = {0};

// 定义7段字库编码
//  |-A-|
//  F   B
//  |-G-|
//  E   C
//  |-D-|

typedef struct
{
	unsigned A : 1;
	unsigned B : 1;
	unsigned C : 1;
	unsigned D : 1;
	unsigned E : 1;
	unsigned F : 1;
	unsigned G : 1;
	unsigned : 1;
} TChar;

// 字库，不带小数点或单位
const TChar CLib[] = 
{
	{0, 0, 0, 0, 0, 0, 0}, // ' '
	{0, 0, 0, 0, 0, 0, 1}, // '-'
	{0, 1, 1, 0, 0, 0, 1}, // '+' = '-|'
	{1, 0, 0, 0, 0, 0, 0}, // '^'
	
	{1, 1, 1, 0, 1, 1, 1}, // 'A'
	{0, 0, 1, 1, 1, 1, 1}, // 'b'
	{0, 0, 0, 1, 1, 0, 1}, // 'c'
	{0, 1, 1, 1, 1, 0, 1}, // 'd'
	{1, 0, 0, 1, 1, 1, 1}, // 'E'
	{1, 0, 0, 0, 1, 1, 1}, // 'F'
	{1, 0, 1, 1, 1, 1, 0}, // 'G'
	{0, 0, 1, 0, 1, 1, 1}, // 'h'
	{0, 0, 0, 0, 1, 1, 0}, // 'I'
	{0, 1, 1, 1, 0, 0, 0}, // 'J'
	{0, 0, 0, 1, 0, 0, 0}, // 'K' = '_'
	{0, 0, 0, 1, 1, 1, 0}, // 'L'
	{0, 0, 0, 1, 0, 0, 0}, // 'M' = '_'
	{0, 0, 1, 0, 1, 0, 1}, // 'n'
	{0, 0, 1, 1, 1, 0, 1}, // 'o'
	{1, 1, 0, 0, 1, 1, 1}, // 'P'
	{1, 1, 1, 0, 0, 1, 1}, // 'q'
	{0, 0, 0, 0, 1, 0, 1}, // 'r'
	{1, 0, 1, 1, 0, 1, 1}, // 'S'
	{0, 0, 1, 0, 0, 0, 1}, // 't'
	{0, 1, 1, 1, 1, 1, 0}, // 'U'
	{0, 1, 0, 0, 1, 1, 1}, // 'V'
	{0, 0, 0, 1, 0, 0, 0}, // 'W' = '_'
	{0, 0, 0, 1, 0, 0, 0}, // 'X' = '_'
	{0, 1, 1, 1, 0, 1, 1}, // 'y'
	{0, 0, 0, 1, 0, 0, 0}, // 'Z' = '_'
	
	{1, 1, 1, 1, 1, 1, 0}, // '0'
	{0, 1, 1, 0, 0, 0, 0}, // '1'
	{1, 1, 0, 1, 1, 0, 1}, // '2'
	{1, 1, 1, 1, 0, 0, 1}, // '3'
	{0, 1, 1, 0, 0, 1, 1}, // '4'
	{1, 0, 1, 1, 0, 1, 1}, // '5'
	{1, 0, 1, 1, 1, 1, 1}, // '6'
	{1, 1, 1, 0, 0, 0, 0}, // '7'
	{1, 1, 1, 1, 1, 1, 1}, // '8'
	{1, 1, 1, 1, 0, 1, 1}, // '9'
};

// 字符在字库中的编码
typedef enum 
{
	CODE_SPACE, CODE_MINUS, CODE_PLUS, CODE_EXP,
	CODE_A, CODE_B, CODE_C, CODE_D, CODE_E, CODE_F, CODE_G, 
	CODE_H, CODE_I, CODE_J, CODE_K, CODE_L, CODE_M, CODE_N,
	CODE_O, CODE_P, CODE_Q, CODE_R, CODE_S, CODE_T,
	CODE_U, CODE_V, CODE_W, CODE_X, CODE_Y, CODE_Z,
  	CODE_0, CODE_1, CODE_2, CODE_3, CODE_4, CODE_5, CODE_6, CODE_7, CODE_8, CODE_9
} TCode;

TCode HT1621_Char2Code(char c)
{
	if(c >= '0' && c <= '9')
		return CODE_0 + (c - '0');
	
	if(c >= 'a' && c <= 'z')
		return CODE_A + (c - 'a');
	
	if(c >= 'A' && c <= 'Z')
		return CODE_A + (c - 'A');
	
	if(c == '-')
		return CODE_MINUS;
	
	if(c == '+')
		return CODE_PLUS;
	
	if(c == '^')
		return CODE_EXP;
	
	return CODE_SPACE;
}

// pin_no: 1~32
// com_no: 1~4
void HT1621_WriteBuf(u16 pin_com, u8 bit_val)
{
	uint8_t byte_index, bit_index;
	uint8_t pin_no = pin_com / 10;
	uint8_t com_no = pin_com % 10;
	
	if(pin_no < 1 || pin_no > 25)
		return;
	if(com_no < 1 || com_no > 6)
		return;
		
	byte_index = pin_no - 1;
	bit_index = com_no - 1; 		// COM6高位，COM1低位
	if(bit_val)
		VideoBuf.buf[byte_index] |= (1 << bit_index);
	else
		VideoBuf.buf[byte_index] &= ~(1 << bit_index);
}
	
// 写一个七段码字符
// pin_comA = (A段的pin_no) * 10 + (A段的com_no)
void HT1621_WriteChar(char c, u16 pin_comA, u16 pin_comB, u16 pin_comC, u16 pin_comD, u16 pin_comE, u16 pin_comF, u16 pin_comG)
{
	TCode code = HT1621_Char2Code(c);
	   
	HT1621_WriteBuf(pin_comA, CLib[code].A);
	HT1621_WriteBuf(pin_comB, CLib[code].B);
	HT1621_WriteBuf(pin_comC, CLib[code].C);
	HT1621_WriteBuf(pin_comD, CLib[code].D);
	HT1621_WriteBuf(pin_comE, CLib[code].E);
	HT1621_WriteBuf(pin_comF, CLib[code].F);
	HT1621_WriteBuf(pin_comG, CLib[code].G);
}

// 写一个七段码数据
// pin_comA = (A段的pin_no) * 10 + (A段的com_no)
void HT1621_Write7Seg(u8 val, u16 pin_comA, u16 pin_comB, u16 pin_comC, u16 pin_comD, u16 pin_comE, u16 pin_comF, u16 pin_comG)
{
	HT1621_WriteBuf(pin_comA, val & 1);
	val >>= 1;
	HT1621_WriteBuf(pin_comB, val & 1);
	val >>= 1;
	HT1621_WriteBuf(pin_comC, val & 1);
	val >>= 1;
	HT1621_WriteBuf(pin_comD, val & 1);
	val >>= 1;
	HT1621_WriteBuf(pin_comE, val & 1);
	val >>= 1;
	HT1621_WriteBuf(pin_comF, val & 1);
	val >>= 1;
	HT1621_WriteBuf(pin_comG, val & 1);
}

///////////////////////////////////////////////////////////////////////////////////
// 以下定义适用于HT16L23驱动芯片
//命令
#define  WRITE_LCD       0x80
#define  DRIVE_MODE_CMD  0x82
#define  SYS_MODE_CMD    0x84
#define  FRQ_CMD         0x86
#define  BLINK_FRQ_CMD   0x88
#define  VOL_SET_CMD     0x8a

//参数定义
#define  BIAS_LCD        0x34  // 驱动模式 SEG40*8com显示段位模式  1/8duty  1/3bias
#define  SYS_MODE_LCD    0x03  //显示和内部晶振都打开
#define  FRQ_LCD         0x02  //3--128HZ  2--64
#define  BLINK_FRQ_LCD   0x00  //blinking off
#define  VOL_LCD         0x02  //1--内部V  电压3.3v
///////////////////////////////////////////////////////////////////////////////////

void HT1621_Delay()
{
	__NOP();
}

// 通讯定义
#define   HT1621_CS_EN() \
	{ \
		LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_12); \
		HT1621_Delay(); \
	}
	
#define   HT1621_CS_DIS() \
    { \
		LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_12); \
		HT1621_Delay(); \
    }
   	
#define   HT1621_CLK_LOW() \
	{ \
		LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_13); \
		HT1621_Delay(); \
	}   
	
#define   HT1621_CLK_HIGH() \
   	{ \
 		LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_13); \
		HT1621_Delay(); \
   	}

#define   HT1621_DATA_1() \
	{ \
		LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_14); \
		HT1621_Delay(); \
	}	
	
#define   HT1621_DATA_0() \
	{ \
		LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_14); \
		HT1621_Delay(); \
	}	

// 写 1 bit
void HT1621_Bit(u8 b1)
{
	HT1621_CLK_LOW();
	if(b1)
	{
		HT1621_DATA_1();
	}
	else
	{
		HT1621_DATA_0();
	}
	HT1621_CLK_HIGH();
}

// 写多个bits
void HT1621_Bits(u8 byte, u8 num)
{
	while(num--)
	{
		HT1621_Bit(byte & 0x80);
		byte <<= 1;
	}		
}

// 写命令
void HT1621_Cmd(u8 cmd, u8 val)
{
	// 片选
    HT1621_CS_EN();

	HT1621_Bits(cmd, 8);
	HT1621_Bits(val, 8);
		
	// 取消片选
	HT1621_CS_DIS();
}

// 设置参数
void HT1621_SetParams()
{
	HT1621_Cmd(DRIVE_MODE_CMD, BIAS_LCD);
	HT1621_Cmd(VOL_SET_CMD, VOL_LCD);    //使用内部振荡器
	HT1621_Cmd(FRQ_CMD, FRQ_LCD);
	HT1621_Cmd(BLINK_FRQ_CMD, BLINK_FRQ_LCD);
	HT1621_Cmd(SYS_MODE_CMD, SYS_MODE_LCD);
}

// 刷新整个显示屏内容
void HT1621_Refresh()
{
	u8 i;
	
	// 比较显示内容和标志位，如无改变则不操作
	if(memcmp(&VideoBuf, &Last_VideoBuf, sizeof(VideoBuf)) == 0)
		return;

	// 保存显示内容和标志位
	Last_VideoBuf = VideoBuf;
	
	// 处理闪烁，根据标志位临时改变显示内容
	if(!self_check_state && !VideoBuf.blink_visible)
	{
		// 隐藏数字（显示界面）
		if(VideoBuf.fld1_blink)			// 显示1
		{
			Disp_Fld1Text("    ");
			Disp_Fld1PointOff();
		}
		if(VideoBuf.fld2_blink)			// 显示2
		{
			Disp_Fld2Text("   ");
			Disp_Fld2PointOff();
		}
		if(VideoBuf.fld3_blink)			// 显示3
		{
			Disp_Fld3Text("    ");
			Disp_Fld3PointOff();
		}
		if(VideoBuf.fld4_blink)			// 显示4
		{
			Disp_Fld4Text("    ");
			Disp_Fld4PointOff();
		}
		if(VideoBuf.battery_blink) 		// 电池
			Disp_WriteBattery(0);
		
		// 光标闪烁（配置界面）
		for(i = 0; i < VideoBuf.cursor_width; i++)
			Disp_DispChar(VideoBuf.cursor_pos + i, ' ');
	}
	
	// 片选
    HT1621_CS_EN();
	
	HT1621_Bits(WRITE_LCD, 8); // cmd
	HT1621_Bits(0, 8);		   // addr
	for(i = 0; i < sizeof(VideoBuf.buf); i++)
		HT1621_Bits(VideoBuf.buf[i], 8);	
		
	// 取消片选
	HT1621_CS_DIS();

	// 恢复显示内容和标志位
	VideoBuf = Last_VideoBuf;
}	

// 整个屏幕全熄灭
void HT1621_AllOff()
{
	self_check_state = 1;
	memset(VideoBuf.buf, 0x00, sizeof(VideoBuf.buf)); // 不影响最后的状态
	HT1621_Refresh();
	self_check_state = 0;
}
	
// 整个屏幕全点亮
void HT1621_AllOn()
{
	self_check_state = 1;
	memset(VideoBuf.buf, 0xFF, sizeof(VideoBuf.buf)); // 不影响最后的状态
	HT1621_Refresh();
	self_check_state = 0;
}

void LCD_Init()
{
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);

  /**/
  LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_11|LL_GPIO_PIN_12|LL_GPIO_PIN_13|LL_GPIO_PIN_14);

  /**/
  GPIO_InitStruct.Pin = LL_GPIO_PIN_11|LL_GPIO_PIN_12|LL_GPIO_PIN_13|LL_GPIO_PIN_14;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
 
void LCD_MyOpen()
{
	HT1621_SetParams();
}
