PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/target/devo7e/lcd.c

https://bitbucket.org/sunvsuv/deviationfor6810
C | 200 lines | 158 code | 14 blank | 28 comment | 17 complexity | 3ed8f794831603a1167ecebf4acac4ac MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /*
  2. This project is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. Deviation is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with Deviation. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #include <libopencm3/stm32/f1/gpio.h>
  14. #include <libopencm3/stm32/f1/rcc.h>
  15. #include <libopencm3/stm32/spi.h>
  16. #include "common.h"
  17. #include "gui/gui.h"
  18. #define CS_HI() gpio_set(GPIOB, GPIO0)
  19. #define CS_LO() gpio_clear(GPIOB, GPIO0)
  20. #define CMD_MODE() gpio_clear(GPIOC,GPIO5)
  21. #define DATA_MODE() gpio_set(GPIOC,GPIO5)
  22. //The screen is 129 characters, but we'll only expoise 128 of them
  23. #define PHY_LCD_WIDTH 129
  24. #define LCD_PAGES 8
  25. static u8 img[PHY_LCD_WIDTH * LCD_PAGES];
  26. static u8 dirty[PHY_LCD_WIDTH];
  27. static u16 xstart, xend; // After introducing logical view for devo10, the coordinate can be >= 5000
  28. static u16 xpos, ypos;
  29. static s8 dir;
  30. void LCD_Cmd(u8 cmd) {
  31. CMD_MODE();
  32. CS_LO();
  33. spi_xfer(SPI1, cmd);
  34. CS_HI();
  35. }
  36. void LCD_Data(u8 cmd) {
  37. DATA_MODE();
  38. CS_LO();
  39. spi_xfer(SPI1, cmd);
  40. CS_HI();
  41. }
  42. void lcd_display(uint8_t on)
  43. {
  44. LCD_Cmd(0xAE | (on ? 1 : 0));
  45. }
  46. void lcd_set_page_address(uint8_t page)
  47. {
  48. LCD_Cmd(0xB0 | (page & 0x07));
  49. }
  50. void lcd_set_column_address(uint8_t column)
  51. {
  52. LCD_Cmd(0x10 | ((column >> 4) & 0x0F)); //MSB
  53. LCD_Cmd(column & 0x0F); //LSB
  54. }
  55. void lcd_set_start_line(int line)
  56. {
  57. LCD_Cmd((line & 0x3F) | 0x40);
  58. }
  59. void LCD_Contrast(u8 contrast)
  60. {
  61. //int data = 0x20 + contrast * 0xC / 10;
  62. LCD_Cmd(0x81);
  63. int c = contrast * 12 + 76; //contrast should range from ~72 to ~200
  64. LCD_Cmd(c);
  65. }
  66. void LCD_Init()
  67. {
  68. //Initialization is mostly done in SPI Flash
  69. //Setup CS as B.0 Data/Control = C.5
  70. rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
  71. rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
  72. gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
  73. GPIO_CNF_OUTPUT_PUSHPULL, GPIO0);
  74. gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
  75. GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
  76. LCD_Cmd(0xE2); //Reset
  77. volatile int i = 0x8000;
  78. while(i) i--;
  79. LCD_Cmd(0xAE); //Display off
  80. LCD_Cmd(0xA6); //Normal display
  81. LCD_Cmd(0xA4); //All Points Normal
  82. LCD_Cmd(0xEA); //??
  83. LCD_Cmd(0xA0); //ADC Normal
  84. LCD_Cmd(0xC4); //Common Output Mode Scan Rate
  85. LCD_Cmd(0x2C); //Power Controller:Booster ON
  86. i = 0x8000;
  87. while(i) i--;
  88. LCD_Cmd(0x2E); //Power Controller: VReg ON
  89. i = 0x8000;
  90. while(i) i--;
  91. LCD_Cmd(0x2F); //Power Controller: VFollower ON
  92. i = 0x8000;
  93. while(i) i--;
  94. lcd_set_start_line(0);
  95. // Display data write (6)
  96. //Clear the screen
  97. for(int page = 0; page < 9; page++) {
  98. lcd_set_page_address(page);
  99. lcd_set_column_address(0);
  100. for(int col = 0; col < 129; col++)
  101. LCD_Data(0x00);
  102. }
  103. lcd_display(1);
  104. LCD_Contrast(5);
  105. memset(img, 0, sizeof(img));
  106. memset(dirty, 0, sizeof(dirty));
  107. }
  108. void LCD_Clear(unsigned int val)
  109. {
  110. int i,j;
  111. val = (val & 0xFF);
  112. for (i=0; i<LCD_PAGES; i++) {
  113. lcd_set_page_address(i);
  114. lcd_set_column_address(0);
  115. for (j=0;j<PHY_LCD_WIDTH;j++)
  116. LCD_Data(val ? 0xff : 0x00);
  117. }
  118. }
  119. void LCD_DrawStart(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, enum DrawDir _dir)
  120. {
  121. if (_dir == DRAW_SWNE) {
  122. ypos = y1; // bug fix: must do it this way to draw bmp
  123. dir = -1;
  124. } else {
  125. ypos = y0;
  126. dir = 1;
  127. }
  128. xstart = x0;
  129. xend = x1;
  130. xpos = x0;
  131. }
  132. /* Screen coordinates are as follows:
  133. * (128, 32) .... (0, 32)
  134. * ... .... ...
  135. * (128, 63) .... (0, 63)
  136. * (128, 0) .... (0, 0)
  137. * ... .... ...
  138. * (128, 31) .... (0, 31)
  139. */
  140. void LCD_DrawStop(void)
  141. {
  142. int col = 0;
  143. int p, c;
  144. for (p = 0; p < LCD_PAGES; p++) {
  145. int init = 0;
  146. for (c = 0; c < PHY_LCD_WIDTH; c++) {
  147. if(dirty[c] & (1 << p)) {
  148. if(! init) {
  149. lcd_set_page_address(p);
  150. lcd_set_column_address(c);
  151. } else if(col+1 != c) {
  152. lcd_set_column_address(c);
  153. }
  154. LCD_Data(img[p * PHY_LCD_WIDTH + c]);
  155. col = c;
  156. }
  157. }
  158. }
  159. memset(dirty, 0, sizeof(dirty));
  160. }
  161. void LCD_DrawPixel(unsigned int color)
  162. {
  163. int y = ypos;
  164. int x = xpos;
  165. int ycol = y / 8;
  166. int ybit = y & 0x07;
  167. if(color) {
  168. img[ycol * PHY_LCD_WIDTH + x] |= 1 << ybit;
  169. } else {
  170. img[ycol * PHY_LCD_WIDTH + x] &= ~(1 << ybit);
  171. }
  172. dirty[x] |= 1 << ycol;
  173. xpos++;
  174. if (xpos > xend) {
  175. xpos = xstart;
  176. ypos += dir;
  177. }
  178. }
  179. void LCD_DrawPixelXY(unsigned int x, unsigned int y, unsigned int color)
  180. {
  181. xpos = x;
  182. ypos = y;
  183. LCD_DrawPixel(color);
  184. }