363 lines
9.0 KiB
C
363 lines
9.0 KiB
C
/*
|
|
* lcd.c
|
|
*
|
|
* Created on: May 27, 2022
|
|
* Author: Keith.Lloyd
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <arm_math.h>
|
|
|
|
#include "fsl_gpio.h"
|
|
|
|
#include "spi.h"
|
|
#include "lcd.h"
|
|
#include "display.h"
|
|
#include "timer.h"
|
|
#include "mode.h"
|
|
#include "Graphics/graphicsLibrary.h"
|
|
#include "Fonts/fontLibrary.h"
|
|
#include "Graphics/testIconsMono.h"
|
|
#include "Graphics/icons.h"
|
|
#include "adc.h"
|
|
#include "main.h"
|
|
#include "ports.h"
|
|
#include "utils.h"
|
|
//Overview:
|
|
// LCD control / data line normally stays in the data state.
|
|
// Any function that changes to control MUST change the line back to data before exiting
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
//Backlight GPIO
|
|
#define LCD_BL_PORT 2 //ToDo: Update this for LPC
|
|
#define LCD_BL_GPIO_PIN 30 //ToDo: Update this for LPC
|
|
//#define LCD_CD_PORT 0 //ToDo: Update this for LPC Port0 || Port1 208002
|
|
//#define LCD_CD_GPIO_PIN 6 //ToDo: Update this for LPC Bit position 208002
|
|
|
|
#define LCD_CD_PORT 1 //ToDo: Update this for LPC Port0 || Port1 208004
|
|
#define LCD_CD_GPIO_PIN 8 //ToDo: Update this for LPC Bit position 208004
|
|
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
// Frame buffer
|
|
//uint16_t mFrameBuffer[LCD_HEIGHT_PIXELS][LCD_WIDTH_PIXELS/16]; //y,x
|
|
//uint8_t mFrameBuffer[LCD_WIDTH_PIXELS][LCD_HEIGHT_PIXELS / 8]; //x,y
|
|
uint8_t mFrameBuffer[LCD_HEIGHT_PIXELS/8][LCD_WIDTH_PIXELS]; //x,y
|
|
extern uint8_t Power_Level, Over_Voltage_Flag, Task,Error;
|
|
extern uint8_t tempString[];
|
|
extern uint8_t frequency, Cur_Mode, Safe_Mode;
|
|
extern uint8_t Dds_Pot_Val[];
|
|
extern uint8_t Port_State[];
|
|
extern uint8_t Diag_Flag;
|
|
extern uint16_t Display_warning_tmr;
|
|
/*******************************************************************************
|
|
* Static Function Declarations
|
|
******************************************************************************/
|
|
static void SetBacklightPower(uint8_t state);
|
|
static void SetCommandDataLine(LCD_CDLINE_t state);
|
|
static void SendLcdCommand(uint8_t command, uint8_t data);
|
|
|
|
|
|
/*******************************************************************************
|
|
* Static Functions
|
|
******************************************************************************/
|
|
|
|
//Set Backlight GPIO to 'state'
|
|
static void SetBacklightPower(uint8_t state)
|
|
{
|
|
//ToDo This function Note backlight is now on Serial expander
|
|
GPIO_PinWrite(GPIO, LCD_BL_PORT, LCD_BL_GPIO_PIN, state);
|
|
|
|
}
|
|
|
|
//Set CD line GPIO high for LCD_CDLINE_DATA or low for LCD_CDLINE_CONTROL
|
|
static void SetCommandDataLine(LCD_CDLINE_t state)
|
|
{
|
|
//ToDo This function Done !!
|
|
GPIO_PinWrite(GPIO, LCD_CD_PORT, LCD_CD_GPIO_PIN, state);
|
|
}
|
|
|
|
//command is the #defined command
|
|
//data is optional arguments > zero if not used!
|
|
static void SendLcdCommand(uint8_t command, uint8_t data)
|
|
{
|
|
SetCommandDataLine(LCD_CDLINE_CONTROL);
|
|
|
|
uint8_t sendData = command | data;
|
|
SPI3_SendBytes(&sendData, 1); //send one byte via SPI
|
|
|
|
SetCommandDataLine(LCD_CDLINE_DATA);
|
|
}
|
|
|
|
//dedicated function for setting LCD gain and pot values
|
|
static void SetGainAndPot(uint8_t data)
|
|
{
|
|
SetCommandDataLine(LCD_CDLINE_CONTROL);
|
|
|
|
uint8_t sendData[2];
|
|
sendData[0] = LCD_SET_GAIN_AND_POT;
|
|
sendData[1] = data;
|
|
|
|
SPI3_SendBytes(&sendData[0], 2); //send one byte via SPI
|
|
|
|
SetCommandDataLine(LCD_CDLINE_DATA);
|
|
}
|
|
|
|
static void TestLCD(void)
|
|
{
|
|
//Alternate setting all pixels black, then white
|
|
while(1)
|
|
{
|
|
SendLcdCommand(LCD_SET_ALL_PIXELS, 1);
|
|
|
|
uint32_t delay = 50000000;
|
|
while(delay--);
|
|
|
|
SendLcdCommand(LCD_SET_ALL_PIXELS, 0);
|
|
|
|
delay = 50000000;
|
|
while(delay--);
|
|
|
|
// Delay_Ticks(500);
|
|
}
|
|
}
|
|
|
|
static void TestLCD2(void)
|
|
{
|
|
|
|
|
|
while(1)
|
|
{
|
|
//Draw vertical stripes in frameBuffer and output to LCD
|
|
for(uint32_t y = 0; y < LCD_HEIGHT_PIXELS; y++)
|
|
{
|
|
for(uint32_t x = 0; x < LCD_WIDTH_PIXELS / 16; x++)
|
|
{
|
|
|
|
mFrameBuffer[y][x] = 0xF0;
|
|
|
|
}
|
|
}
|
|
|
|
LCD_Update();
|
|
|
|
uint32_t delay = 50000000;
|
|
while(delay--);
|
|
|
|
//Draw horizontal striped in frameBuffer and output to LCD
|
|
for(uint32_t y = 0; y < LCD_HEIGHT_PIXELS; y++)
|
|
{
|
|
for(uint32_t x = 0; x < LCD_WIDTH_PIXELS / 16; x++)
|
|
{
|
|
if(y % 1 == 0) //every other row
|
|
{
|
|
mFrameBuffer[y][x] = 0xF0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
LCD_Update();
|
|
|
|
delay = 50000000;
|
|
while(delay--);
|
|
|
|
}
|
|
}
|
|
|
|
void LCD_Init(void)
|
|
{
|
|
|
|
SendLcdCommand(0, 0); // SET COLUMN LSB
|
|
SendLcdCommand(0b00010000, 0); // SET COLUMN MSB
|
|
SendLcdCommand(0b01000000, 0); // SET START LINE
|
|
SendLcdCommand(0b00100100, 0); // SET MUX & TEMP. COMPENSATION
|
|
SendLcdCommand(0b00101101, 0); // SET POWER CONTROL
|
|
SendLcdCommand(0b10000001, 0); // SET GAIN & POTENTIOMETER
|
|
SendLcdCommand(0b10000000, 0); // SET GAIN & POTENTIOMETER (second part)
|
|
SendLcdCommand(0b10001001, 0); // RAM CONTROL
|
|
SendLcdCommand(0b10100100, 0); // ALL PIX OFF
|
|
SendLcdCommand(0b10100100, 0); // ALL PIX OFF
|
|
SendLcdCommand(0b10101111, 0); // SLEEP MODE OFF
|
|
SendLcdCommand(0b11001000, 0); // MY=1 MX=0 MSF=0
|
|
// SendLcdCommand(0b11101010, 0); // BIAS=12 D1,D0 = BR[1:0]
|
|
SendLcdCommand(0b11101010, 0); // BIAS=12 D1,D0
|
|
SendLcdCommand(0b10010000, 0); // fixed line
|
|
|
|
}
|
|
|
|
|
|
|
|
void Display_Update(void)
|
|
{
|
|
|
|
LCD_Clear(); //clear the frameBuffer
|
|
|
|
Display_USB_Status();
|
|
|
|
LCD_Update();
|
|
|
|
}
|
|
|
|
|
|
void LCD_PowerOff(void)
|
|
{
|
|
//TODO: UC1608 Power down requirements: (see datasheet page 33)
|
|
//Reset command
|
|
//Wait 2mS
|
|
//Turn off VDD
|
|
}
|
|
|
|
/* Output frameBuffer data to LCD
|
|
*
|
|
*/
|
|
|
|
void LCD_Update(void)
|
|
{
|
|
SendLcdCommand(LCD_SET_COLUMN_LSB, 0);
|
|
SendLcdCommand(LCD_SET_COLUMN_MSB, 0);
|
|
SendLcdCommand(LCD_SET_PAGE_ADDRESS, 0);
|
|
|
|
//output framebuffer data via SPI
|
|
SPI3_SendBytes((uint8_t *)mFrameBuffer, sizeof(mFrameBuffer));
|
|
|
|
}
|
|
|
|
//Clear mFrameBuffer
|
|
void LCD_Clear(void)
|
|
{
|
|
//Clear Screen
|
|
memset(mFrameBuffer, 0, sizeof(mFrameBuffer));
|
|
}
|
|
|
|
//Write a pixel to the framebuffer in the specified location
|
|
void LCD_DrawPixel(int16_t x, int16_t y, LCD_DRAWMODE_t mode)
|
|
{
|
|
//ignore if outside LCD area
|
|
if(x < 0 || x > LCD_X_MAX)
|
|
return;
|
|
if(y < 0 || y > LCD_Y_MAX)
|
|
return;
|
|
|
|
//Flip LCD 180*
|
|
x = LCD_X_MAX - x;
|
|
y = LCD_Y_MAX - y;
|
|
|
|
//8-bit data in frameBuffer to read > modify > write
|
|
|
|
uint16_t page = y / LCD_Y_BITS_PER_PAGE;
|
|
uint8_t bitPosition = y%8;
|
|
uint8_t bitMask = 1 << bitPosition;
|
|
|
|
//Draw the pixel
|
|
switch(mode)
|
|
{
|
|
case LCD_DRAW_SET:
|
|
mFrameBuffer[page][x] |= bitMask;
|
|
break;
|
|
case LCD_DRAW_CLEAR:
|
|
mFrameBuffer[page][x] &= bitMask;
|
|
break;
|
|
case LCD_DRAW_XOR:
|
|
mFrameBuffer[page][x] ^= bitMask;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
//get a pixel from the framebuffer at the specified location
|
|
//returns 1 if pixel set, 0 otherwise
|
|
uint8_t LCD_GetPixel(int16_t x, int16_t y)
|
|
{
|
|
//Flip LCD 180*
|
|
x = LCD_X_MAX - x;
|
|
y = LCD_Y_MAX - y;
|
|
|
|
|
|
uint16_t page = y / LCD_Y_BITS_PER_PAGE;
|
|
uint8_t bitPosition = y%8;
|
|
uint8_t bitMask = 1 << bitPosition;
|
|
|
|
uint8_t byte = mFrameBuffer[page][x];
|
|
return (byte >> bitPosition) & 0x01; // right shift the bit of interest to the ones position, then mask
|
|
}
|
|
|
|
|
|
#if 0 //UC1608
|
|
/****************************************************************************/
|
|
/*** uc1608 ***/
|
|
/****************************************************************************/
|
|
|
|
/**
|
|
* uc1608_send send chunk over SPI
|
|
* @param spi config
|
|
* @param command or data array ptr
|
|
* @param size of command or data to send
|
|
* @param command or data mode
|
|
* @param io pin for data/cmd mode
|
|
* @author Matthieu Barreteau
|
|
* @date 04/26/2014
|
|
*/
|
|
int uc1608_send(struct spi_config *config,unsigned char *data, int len,uint8_t mode,uint8_t cmdPin)
|
|
{
|
|
delayMicroseconds(10);
|
|
if(mode == UC1608_DATA) {
|
|
GPIO_SET = 1<<cmdPin; // ToDo
|
|
} else {
|
|
GPIO_CLR = 1<<cmdPin; //ToDo
|
|
}
|
|
delayMicroseconds(75);
|
|
|
|
if(spi_write_data(config, data, len) == -1) {
|
|
fprintf (stderr, "Unable to send over SPI : %s\n", strerror (errno)) ;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* uc1608_setup screen setup
|
|
* @param spi config
|
|
* @param io pin for data/cmd mode
|
|
* @author Matthieu Barreteau
|
|
* @date 04/26/2014
|
|
*/
|
|
void uc1608_setup(struct spi_config *config,uint8_t cmdPin)
|
|
{
|
|
unsigned char cmdToSend[14];
|
|
|
|
cmdToSend[0] = 0b11100010; // SYSTEM RESET
|
|
uc1608_send(config, cmdToSend, 1, UC1608_CMD, cmdPin) ;
|
|
delay(300);
|
|
cmdToSend[0] = 0b00000000; // SET COLUMN LSB
|
|
cmdToSend[1] = 0b00010000; // SET COLUMN MSB
|
|
cmdToSend[2] = 0b01000000; // SET START LINE
|
|
cmdToSend[3] = 0b00100100; // SET MUX & TEMP. COMPENSATION
|
|
cmdToSend[4] = 0b00101101; // SET POWER CONTROL
|
|
cmdToSend[5] = 0b10000001; // SET GAIN & POTENTIOMETER
|
|
cmdToSend[6] = 0b10000000; // SET GAIN & POTENTIOMETER (second part)
|
|
cmdToSend[7] = 0b10001001; // RAM CONTROL
|
|
cmdToSend[8] = 0b10100100; // ALL PIX OFF
|
|
cmdToSend[9] = 0b10100100; // ALL PIX OFF
|
|
cmdToSend[10] = 0b10101111; // SLEEP MODE OFF
|
|
cmdToSend[11] = 0b11001100; // MY=1 MX=1 MSF=0
|
|
cmdToSend[12] = 0b11101010; // BIAS=12
|
|
cmdToSend[13] = 0b10010000; // fixed line
|
|
uc1608_send(config, cmdToSend, 14, UC1608_CMD, cmdPin) ;
|
|
}
|
|
/* EOF */
|
|
#endif
|
|
|