note description : "[ HD44780 custom character generator. A HD44780 can support upto 8 custom characters from indexes 0 to 8, for displays using 5x7 font sizes. Due to the Character Generator RAM (CGRAM) 5-bit addressing this custom character limit is reduced to only 6 characters for displays using font sizes of 5x10. ]" legal : "See notice at end of class." status : "See notice at end of class."; author : "Paul Bates (paul.a.bates@gmail.com)" date : "$Date$" revision: "$Revision$" class HD44780_CHARACTER_GENERATOR inherit HD44780_CONTROLLER_OPERATOR export {NONE} all end USABLE_I inherit {NONE} SHARED_HD44780_OP_CODES export {NONE} all end HD44780_CHARACTER_UTILITY create make feature {NONE} -- Initialization make (a_controller: like controller) -- Initializes character generator for display controller `a_controller'. -- -- `a_controller': A HD44780 display controller to manipulate CGRAM on. require a_controller_attached: attached a_controller a_controller_is_interface_usable: a_controller.is_interface_usable do controller := a_controller ensure controller_set: controller = a_controller end feature -- Access pixel_height: NATURAL_8 -- Character pixel height. require is_interface_usable: is_interface_usable do inspect controller.font.item when {HD44780_FONT}.font_5x7 then Result := 7 when {HD44780_FONT}.font_5x10 then Result := 10 end ensure result_big_enough: Result > 0 end pixel_width: NATURAL_8 -- Character pixel width. require is_interface_usable: is_interface_usable do Result := 5 ensure result_big_enough: Result > 0 end feature {NONE} -- Access controller: HD44780_CONTROLLER -- Controller to modify character graphic data on. feature -- Status report is_interface_usable: BOOLEAN -- do Result := controller.is_interface_usable ensure then controller_is_interface_usable: Result implies controller.is_interface_usable end feature -- Basic Operation set_character (a_index: NATURAL_8; a_char_map: ARRAY [NATURAL_8]) -- Sets a custom character map at a given character index. -- -- `a_index': Zero-based custom character slot index. -- `a_char_map': 5-bit Integer vertical bitmap. -- -- Note: Changing the contents of the CGRAM will affect any same indexed character currently -- diplayed. require is_interface_usable: is_interface_usable a_index_is_valid_index: is_valid_index (a_index) a_char_map_attached: attached a_char_map a_char_map_is_valid_character_map: is_valid_character_map (a_char_map) local l_controller: like controller l_height: like pixel_height l_write_mode: HD44780_BUFFER_SELECT_MODE l_char: NATURAL_8 l_upper, i: INTEGER l_mask: NATURAL_8 do l_mask := ((2 ^ pixel_width) - 1).truncated_to_integer.to_natural_8 l_controller := controller l_height := pixel_height l_write_mode := l_controller.buffer_write_mode -- Write character data to the controller l_controller.buffer_write_mode := {HD44780_BUFFER_SELECT_MODE}.graphic_data l_controller.load_instruction (op_codes.set_cgram_address_op (cgram_address_for_index (a_index))) from i := a_char_map.lower l_upper := a_char_map.upper until i > l_height loop if i <= l_upper then l_char := (a_char_map[i]) & l_mask else l_char := 0 end l_controller.load_data (l_char) i := i + 1 end l_controller.buffer_write_mode := l_write_mode ensure controller_mode_unchanged: controller.buffer_write_mode = old controller.buffer_write_mode end feature -- Query is_valid_index (a_index: NATURAL_8): BOOLEAN -- Determines if the a character index is valid given the controller's font. -- -- `a_index': Zero-based character index. -- `Result': True if the index is valid; False otherwise. require is_interface_usable: is_interface_usable do inspect controller.font.item when {HD44780_FONT}.font_5x7 then Result := a_index < 8 when {HD44780_FONT}.font_5x10 then Result := a_index < 11 end end is_valid_character_map (a_char_map: ARRAY [NATURAL_8]): BOOLEAN -- Determines if the a character map is valid given the controller's font. -- -- `a_char_map': Linear character bitmap. -- `Result': True if the character map is valid; False otherwise. require is_interface_usable: is_interface_usable a_char_map_attached: a_char_map /= Void local l_upper, i: INTEGER l_mask: NATURAL_8 do l_mask := ((2 ^ pixel_width) - 1).truncated_to_integer.to_natural_8 Result := a_char_map.count <= pixel_height if Result then from i := a_char_map.lower l_upper := a_char_map.upper until i > l_upper or not Result loop -- Must be 5 bits Result := (a_char_map[i] & l_mask) = a_char_map[i] i := i + 1 end end end feature {NONE} -- Query cgram_address_for_index (a_index: NATURAL_8): NATURAL_8 -- Retrieve CGRAM address for character at `a_index'. -- -- `a_index': Character index to retrieve bit address for. -- `Result': A CGRAM address. require is_interface_usable: is_interface_usable a_index_is_valid_index: is_valid_index (a_index) do -- The controller may have a cursor bar, under a character matrix, which needs to be accounted for. -- This is why the result address is a_index * (height + 1) inspect controller.font.item when {HD44780_FONT}.font_5x7 then Result := a_index * 8 when {HD44780_FONT}.font_5x10 then Result := a_index * 11 end ensure result_is_valid_cgram_address: (Result & {HD44780_OP_CODES}.cgram_address_mask) = Result end invariant controller_attached: attached controller end