Various projects using Raspberry Pi
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
6.9 KiB

11 years ago
  1. -- raspilcd, a simple tool to display bmp pictures & text on a ST7565 LCD
  2. -- Copyright (C) 2014 Torsten Meissner
  3. --
  4. -- This program is free software: you can redistribute it and/or modify
  5. -- it under the terms of the GNU General Public License as published by
  6. -- the Free Software Foundation, either version 3 of the License, or
  7. -- (at your option) any later version.
  8. --
  9. -- This program is distributed in the hope that it will be useful,
  10. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. -- GNU General Public License for more details.
  13. --
  14. -- You should have received a copy of the GNU General Public License
  15. -- along with this program. If not, see http://www.gnu.org/licenses/.
  16. with Interfaces;
  17. use Interfaces;
  18. with Interfaces.C;
  19. use Interfaces.C;
  20. with Interfaces.C.extensions;
  21. use Interfaces.C.extensions;
  22. with bcm2835_h;
  23. use bcm2835_h;
  24. package body st7565lcd is
  25. procedure io_init is
  26. begin
  27. bcm2835_gpio_fsel(pin => LCD_CS, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  28. bcm2835_gpio_fsel(pin => LCD_RST, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  29. bcm2835_gpio_fsel(pin => LCD_A0, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  30. bcm2835_gpio_fsel(pin => LCD_CLK, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  31. bcm2835_gpio_fsel(pin => LCD_SI, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  32. end io_init;
  33. procedure lcd_init is
  34. begin
  35. -- reset
  36. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(HIGH));
  37. bcm2835_delayMicroseconds(unsigned_long_long(1));
  38. bcm2835_gpio_write(pin => LCD_RST, on => unsigned_char(LOW));
  39. bcm2835_delayMicroseconds(unsigned_long_long(1));
  40. bcm2835_gpio_write(pin => LCD_RST, on => unsigned_char(HIGH));
  41. bcm2835_delayMicroseconds(unsigned_long_long(1));
  42. -- init routine
  43. for index in lcd_init_data'range loop
  44. lcd_transfer_data(value => lcd_init_data(index), si => false);
  45. end loop;
  46. lcd_clear;
  47. end lcd_init;
  48. -- display strings on the lcd at a given position
  49. -- data is a string with any allowed range
  50. -- for strings not beginning at 0 we have to decrement the index
  51. -- variable for xpos by the value of the range begin, so we get
  52. -- for xpos a range from (xpos + 0 .. xpos + number of char in string)
  53. procedure lcd_ascii57_string (xpos : natural; ypos : natural; data : string) is
  54. begin
  55. for index in data'range loop
  56. lcd_ascii57(xpos => xpos + (index - data'first) * 6, ypos => ypos, data => character'val(character'pos(data(index))));
  57. end loop;
  58. end lcd_ascii57_string;
  59. procedure lcd_ascii57 (xpos : natural; ypos : natural; data : character) is
  60. begin
  61. lcd_set_page(page => ypos, column => xpos);
  62. -- write one 5x7 char
  63. for index in 0..4 loop
  64. lcd_transfer_data(value => font_5x7(character'pos(data))(index), si => true);
  65. end loop;
  66. -- one free column between chars
  67. lcd_transfer_data(value => 16#00#, si => true);
  68. end lcd_ascii57;
  69. procedure lcd_picture (xpos : natural; ypos: natural; picture : t_lcd_array) is
  70. begin
  71. for outdex in 0..7 loop
  72. lcd_set_page(page => ypos + outdex, column => xpos);
  73. for index in (128 * outdex) .. (128 * (outdex + 1) - 1) loop
  74. lcd_transfer_data(value => picture(index), si => true);
  75. end loop;
  76. end loop;
  77. end lcd_picture;
  78. procedure lcd_clear is
  79. begin
  80. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(LOW));
  81. for outdex in 0..7 loop
  82. lcd_set_page(page => outdex, column => 0);
  83. for index in 0..128 loop
  84. lcd_transfer_data(value => 16#00#, si => true);
  85. end loop;
  86. end loop;
  87. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(HIGH));
  88. end lcd_clear;
  89. procedure lcd_transfer_data (value : byte; si : boolean) is
  90. begin
  91. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(LOW));
  92. bcm2835_gpio_write(pin => LCD_CLK, on => unsigned_char(HIGH));
  93. if si then
  94. bcm2835_gpio_write(pin => LCD_A0, on => unsigned_char(HIGH));
  95. else
  96. bcm2835_gpio_write(pin => LCD_A0, on => unsigned_char(LOW));
  97. end if;
  98. lcd_byte(value);
  99. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(HIGH));
  100. end lcd_transfer_data;
  101. procedure lcd_set_page (page : natural; column : natural) is
  102. lsb : byte := byte(column + 1) and 16#0f#;
  103. msb : byte := byte(column + 1) and 16#f0#;
  104. page_int : byte := byte(page) or 16#b0#;
  105. begin
  106. msb := Shift_Right(msb, 4);
  107. msb := msb or 16#10#;
  108. lcd_transfer_data(value => page_int, si => false);
  109. lcd_transfer_data(value => msb, si => false);
  110. lcd_transfer_data(value => lsb, si => false);
  111. null;
  112. end lcd_set_page;
  113. procedure lcd_byte (data : byte) is
  114. data_int : byte := data;
  115. begin
  116. for index in 0..7 loop
  117. bcm2835_delayMicroseconds(unsigned_long_long(1));
  118. bcm2835_gpio_write(pin => LCD_CLK, on => unsigned_char(LOW));
  119. if (data_int and 16#80#) = 16#80# then
  120. bcm2835_gpio_write(pin => LCD_SI, on => unsigned_char(HIGH));
  121. else
  122. bcm2835_gpio_write(pin => LCD_SI, on => unsigned_char(LOW));
  123. end if;
  124. data_int := Shift_Left(data_int, 1);
  125. bcm2835_delayMicroseconds(unsigned_long_long(1));
  126. bcm2835_gpio_write(pin => LCD_CLK, on => unsigned_char(HIGH));
  127. end loop;
  128. end lcd_byte;
  129. function bmp_to_lcd (bmp : t_bmp_array; color_mask : t_color_mask) return t_lcd_array is
  130. lcd : t_lcd_array := (others => 16#00#);
  131. logic : byte;
  132. begin
  133. for aussen in 0 .. 7 loop
  134. logic := 16#01#;
  135. for outdex in 0 .. 7 loop
  136. for index in 0 .. 127 loop
  137. if ((bmp(aussen * 1024 + outdex * 128 + index)(which_byte(color_mask.red)) or
  138. bmp(aussen * 1024 + outdex * 128 + index)(which_byte(color_mask.green)) or
  139. bmp(aussen * 1024 + outdex * 128 + index)(which_byte(color_mask.blue))) < 16#77#) then
  140. lcd(aussen * 128 + index) := lcd(aussen * 128 + index) or logic;
  141. end if;
  142. end loop;
  143. logic := Shift_Left(logic, 1);
  144. end loop;
  145. end loop;
  146. return lcd;
  147. end bmp_to_lcd;
  148. function which_byte (data : dword) return integer is
  149. begin
  150. case data is
  151. when 16#000000FF# =>
  152. return 0;
  153. when 16#0000FF00# =>
  154. return 1;
  155. when 16#00FF0000# =>
  156. return 2;
  157. when 16#FF000000# =>
  158. return 3;
  159. when others =>
  160. return -1;
  161. end case;
  162. end which_byte;
  163. end st7565lcd;