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.

233 lines
8.6 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 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. with Ada.Text_IO;
  25. use Ada.Text_IO;
  26. package body st7565lcd is
  27. procedure io_init is
  28. begin
  29. bcm2835_gpio_fsel(pin => LCD_CS, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  30. bcm2835_gpio_fsel(pin => LCD_RST, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  31. bcm2835_gpio_fsel(pin => LCD_A0, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  32. bcm2835_gpio_fsel(pin => LCD_CLK, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  33. bcm2835_gpio_fsel(pin => LCD_SI, mode => unsigned_char(BCM2835_GPIO_FSEL_OUTP));
  34. end io_init;
  35. procedure lcd_init is
  36. begin
  37. -- reset
  38. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(HIGH));
  39. bcm2835_delayMicroseconds(unsigned_long_long(1));
  40. bcm2835_gpio_write(pin => LCD_RST, on => unsigned_char(LOW));
  41. bcm2835_delayMicroseconds(unsigned_long_long(1));
  42. bcm2835_gpio_write(pin => LCD_RST, on => unsigned_char(HIGH));
  43. bcm2835_delayMicroseconds(unsigned_long_long(1));
  44. -- init routine
  45. for index in lcd_init_data'range loop
  46. lcd_transfer_data(value => lcd_init_data(index), si => false);
  47. end loop;
  48. lcd_clear;
  49. end lcd_init;
  50. -- display strings on the lcd at a given position
  51. -- data is a string with any allowed range
  52. -- for strings not beginning at 0 we have to decrement the index
  53. -- variable for xpos by the value of the range begin, so we get
  54. -- for xpos a range from (xpos + 0 .. xpos + number of char in string)
  55. procedure lcd_ascii57_string (xpos : natural; ypos : natural; data : string) is
  56. begin
  57. for index in data'range loop
  58. lcd_ascii57(xpos => xpos + (index - data'first) * 6, ypos => ypos, data => character'val(character'pos(data(index))));
  59. end loop;
  60. end lcd_ascii57_string;
  61. procedure lcd_ascii57 (xpos : natural; ypos : natural; data : character) is
  62. begin
  63. lcd_set_page(page => ypos, column => xpos);
  64. -- write one 5x7 char
  65. for index in 0..4 loop
  66. lcd_transfer_data(value => font_5x7(character'pos(data))(index), si => true);
  67. end loop;
  68. -- one free column between chars
  69. lcd_transfer_data(value => 16#00#, si => true);
  70. end lcd_ascii57;
  71. procedure lcd_picture (xpos : natural; ypos: natural; picture : t_lcd_array) is
  72. begin
  73. for outdex in 0..7 loop
  74. lcd_set_page(page => ypos + outdex, column => xpos);
  75. for index in (128 * outdex) .. (128 * (outdex + 1) - 1) loop
  76. lcd_transfer_data(value => picture(index), si => true);
  77. end loop;
  78. end loop;
  79. end lcd_picture;
  80. procedure lcd_clear is
  81. begin
  82. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(LOW));
  83. for outdex in 0..7 loop
  84. lcd_set_page(page => outdex, column => 0);
  85. for index in 0..128 loop
  86. lcd_transfer_data(value => 16#00#, si => true);
  87. end loop;
  88. end loop;
  89. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(HIGH));
  90. end lcd_clear;
  91. procedure lcd_transfer_data (value : byte; si : boolean) is
  92. begin
  93. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(LOW));
  94. bcm2835_gpio_write(pin => LCD_CLK, on => unsigned_char(HIGH));
  95. if si then
  96. bcm2835_gpio_write(pin => LCD_A0, on => unsigned_char(HIGH));
  97. else
  98. bcm2835_gpio_write(pin => LCD_A0, on => unsigned_char(LOW));
  99. end if;
  100. lcd_byte(value);
  101. bcm2835_gpio_write(pin => LCD_CS, on => unsigned_char(HIGH));
  102. end lcd_transfer_data;
  103. procedure lcd_set_page (page : natural; column : natural) is
  104. lsb : byte := byte(column + 1) and 16#0f#;
  105. msb : byte := byte(column + 1) and 16#f0#;
  106. page_int : byte := byte(page) or 16#b0#;
  107. begin
  108. msb := Shift_Right(msb, 4);
  109. msb := msb or 16#10#;
  110. lcd_transfer_data(value => page_int, si => false);
  111. lcd_transfer_data(value => msb, si => false);
  112. lcd_transfer_data(value => lsb, si => false);
  113. null;
  114. end lcd_set_page;
  115. procedure lcd_byte (data : byte) is
  116. data_int : byte := data;
  117. begin
  118. for index in 0..7 loop
  119. bcm2835_delayMicroseconds(unsigned_long_long(1));
  120. bcm2835_gpio_write(pin => LCD_CLK, on => unsigned_char(LOW));
  121. if (data_int and 16#80#) = 16#80# then
  122. bcm2835_gpio_write(pin => LCD_SI, on => unsigned_char(HIGH));
  123. else
  124. bcm2835_gpio_write(pin => LCD_SI, on => unsigned_char(LOW));
  125. end if;
  126. data_int := Shift_Left(data_int, 1);
  127. bcm2835_delayMicroseconds(unsigned_long_long(1));
  128. bcm2835_gpio_write(pin => LCD_CLK, on => unsigned_char(HIGH));
  129. end loop;
  130. end lcd_byte;
  131. function bmp_to_lcd (bmp_picture : t_bmp_picture) return t_lcd_array is
  132. lcd : t_lcd_array := (others => 16#00#);
  133. logic : byte;
  134. begin
  135. for aussen in 0 .. 7 loop
  136. logic := 16#01#;
  137. for outdex in 0 .. 7 loop
  138. for index in 0 .. 127 loop
  139. if ((bmp_picture.data(aussen * 1024 + outdex * 128 + index)(which_byte(bmp_picture.mask.red)) or
  140. bmp_picture.data(aussen * 1024 + outdex * 128 + index)(which_byte(bmp_picture.mask.green)) or
  141. bmp_picture.data(aussen * 1024 + outdex * 128 + index)(which_byte(bmp_picture.mask.blue))) < 16#88#) then
  142. lcd(aussen * 128 + index) := lcd(aussen * 128 + index) or logic;
  143. end if;
  144. end loop;
  145. logic := Shift_Left(logic, 1);
  146. end loop;
  147. end loop;
  148. return lcd;
  149. end bmp_to_lcd;
  150. function which_byte (data : dword) return integer is
  151. begin
  152. case data is
  153. when 16#000000FF# =>
  154. return 0;
  155. when 16#0000FF00# =>
  156. return 1;
  157. when 16#00FF0000# =>
  158. return 2;
  159. when 16#FF000000# =>
  160. return 3;
  161. when others =>
  162. raise mask_exception;
  163. end case;
  164. end which_byte;
  165. -- read_bmp : read a bmp file in t_bmp_picture record
  166. procedure read_bmp (file : in Ada.Streams.Stream_IO.File_Type;
  167. file_access : access Ada.Streams.Root_Stream_Type'Class;
  168. bmp_picture : in out t_bmp_picture) is
  169. begin
  170. -- read header
  171. t_bmp_header'Read(file_access, bmp_picture.header);
  172. -- check for valid header
  173. if (abs bmp_picture.header.biHeight /= 64 or bmp_picture.header.biWidth /= 128 or
  174. (bmp_picture.header.biCompression /= 0 and bmp_picture.header.biCompression /= 3) or
  175. bmp_picture.header.biBitCount /= 32) then
  176. raise bmp_exception;
  177. end if;
  178. -- get color map if existing
  179. if bmp_picture.header.biCompression = 3 then
  180. t_color_mask'Read(file_access, bmp_picture.mask);
  181. end if;
  182. -- read in image data
  183. if bmp_picture.header.biHeight < 0 then
  184. -- top-down pixel matrix
  185. for index in bmp_picture.data'range loop
  186. if not Ada.Streams.Stream_IO.End_Of_File(file) then
  187. t_byte_array'Read(file_access, bmp_picture.data(index));
  188. end if;
  189. end loop;
  190. else
  191. -- bottom-top pixel matrix
  192. for row in reverse 0 .. 63 loop
  193. for column in 0 .. 127 loop
  194. if not Ada.Streams.Stream_IO.End_Of_File(file) then
  195. t_byte_array'Read(file_access, bmp_picture.data(row * 128 + column));
  196. end if;
  197. end loop;
  198. end loop;
  199. end if;
  200. end read_bmp;
  201. end st7565lcd;