/src/target/devo7e/lcd.c
C | 200 lines | 158 code | 14 blank | 28 comment | 17 complexity | 3ed8f794831603a1167ecebf4acac4ac MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
- /*
- This project is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Deviation is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Deviation. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <libopencm3/stm32/f1/gpio.h>
- #include <libopencm3/stm32/f1/rcc.h>
- #include <libopencm3/stm32/spi.h>
- #include "common.h"
- #include "gui/gui.h"
- #define CS_HI() gpio_set(GPIOB, GPIO0)
- #define CS_LO() gpio_clear(GPIOB, GPIO0)
- #define CMD_MODE() gpio_clear(GPIOC,GPIO5)
- #define DATA_MODE() gpio_set(GPIOC,GPIO5)
- //The screen is 129 characters, but we'll only expoise 128 of them
- #define PHY_LCD_WIDTH 129
- #define LCD_PAGES 8
- static u8 img[PHY_LCD_WIDTH * LCD_PAGES];
- static u8 dirty[PHY_LCD_WIDTH];
- static u16 xstart, xend; // After introducing logical view for devo10, the coordinate can be >= 5000
- static u16 xpos, ypos;
- static s8 dir;
- void LCD_Cmd(u8 cmd) {
- CMD_MODE();
- CS_LO();
- spi_xfer(SPI1, cmd);
- CS_HI();
- }
- void LCD_Data(u8 cmd) {
- DATA_MODE();
- CS_LO();
- spi_xfer(SPI1, cmd);
- CS_HI();
- }
- void lcd_display(uint8_t on)
- {
- LCD_Cmd(0xAE | (on ? 1 : 0));
- }
- void lcd_set_page_address(uint8_t page)
- {
- LCD_Cmd(0xB0 | (page & 0x07));
- }
- void lcd_set_column_address(uint8_t column)
- {
- LCD_Cmd(0x10 | ((column >> 4) & 0x0F)); //MSB
- LCD_Cmd(column & 0x0F); //LSB
- }
- void lcd_set_start_line(int line)
- {
- LCD_Cmd((line & 0x3F) | 0x40);
- }
- void LCD_Contrast(u8 contrast)
- {
- //int data = 0x20 + contrast * 0xC / 10;
- LCD_Cmd(0x81);
- int c = contrast * 12 + 76; //contrast should range from ~72 to ~200
- LCD_Cmd(c);
- }
- void LCD_Init()
- {
- //Initialization is mostly done in SPI Flash
- //Setup CS as B.0 Data/Control = C.5
- rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
- rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
- gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
- GPIO_CNF_OUTPUT_PUSHPULL, GPIO0);
- gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
- GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
- LCD_Cmd(0xE2); //Reset
- volatile int i = 0x8000;
- while(i) i--;
- LCD_Cmd(0xAE); //Display off
- LCD_Cmd(0xA6); //Normal display
- LCD_Cmd(0xA4); //All Points Normal
- LCD_Cmd(0xEA); //??
- LCD_Cmd(0xA0); //ADC Normal
- LCD_Cmd(0xC4); //Common Output Mode Scan Rate
- LCD_Cmd(0x2C); //Power Controller:Booster ON
- i = 0x8000;
- while(i) i--;
- LCD_Cmd(0x2E); //Power Controller: VReg ON
- i = 0x8000;
- while(i) i--;
- LCD_Cmd(0x2F); //Power Controller: VFollower ON
- i = 0x8000;
- while(i) i--;
- lcd_set_start_line(0);
- // Display data write (6)
- //Clear the screen
- for(int page = 0; page < 9; page++) {
- lcd_set_page_address(page);
- lcd_set_column_address(0);
- for(int col = 0; col < 129; col++)
- LCD_Data(0x00);
- }
- lcd_display(1);
- LCD_Contrast(5);
- memset(img, 0, sizeof(img));
- memset(dirty, 0, sizeof(dirty));
- }
- void LCD_Clear(unsigned int val)
- {
- int i,j;
- val = (val & 0xFF);
- for (i=0; i<LCD_PAGES; i++) {
- lcd_set_page_address(i);
- lcd_set_column_address(0);
- for (j=0;j<PHY_LCD_WIDTH;j++)
- LCD_Data(val ? 0xff : 0x00);
- }
- }
- void LCD_DrawStart(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, enum DrawDir _dir)
- {
- if (_dir == DRAW_SWNE) {
- ypos = y1; // bug fix: must do it this way to draw bmp
- dir = -1;
- } else {
- ypos = y0;
- dir = 1;
- }
- xstart = x0;
- xend = x1;
- xpos = x0;
- }
- /* Screen coordinates are as follows:
- * (128, 32) .... (0, 32)
- * ... .... ...
- * (128, 63) .... (0, 63)
- * (128, 0) .... (0, 0)
- * ... .... ...
- * (128, 31) .... (0, 31)
- */
- void LCD_DrawStop(void)
- {
- int col = 0;
- int p, c;
- for (p = 0; p < LCD_PAGES; p++) {
- int init = 0;
- for (c = 0; c < PHY_LCD_WIDTH; c++) {
- if(dirty[c] & (1 << p)) {
- if(! init) {
- lcd_set_page_address(p);
- lcd_set_column_address(c);
- } else if(col+1 != c) {
- lcd_set_column_address(c);
- }
- LCD_Data(img[p * PHY_LCD_WIDTH + c]);
- col = c;
- }
- }
- }
- memset(dirty, 0, sizeof(dirty));
- }
- void LCD_DrawPixel(unsigned int color)
- {
- int y = ypos;
- int x = xpos;
- int ycol = y / 8;
- int ybit = y & 0x07;
- if(color) {
- img[ycol * PHY_LCD_WIDTH + x] |= 1 << ybit;
- } else {
- img[ycol * PHY_LCD_WIDTH + x] &= ~(1 << ybit);
- }
- dirty[x] |= 1 << ycol;
- xpos++;
- if (xpos > xend) {
- xpos = xstart;
- ypos += dir;
- }
- }
- void LCD_DrawPixelXY(unsigned int x, unsigned int y, unsigned int color)
- {
- xpos = x;
- ypos = y;
- LCD_DrawPixel(color);
- }