diff --git a/components/src/io_expander/pcf8574/pcf8574.adb b/components/src/io_expander/pcf8574/pcf8574.adb new file mode 100644 index 000000000..ea6424c1c --- /dev/null +++ b/components/src/io_expander/pcf8574/pcf8574.adb @@ -0,0 +1,63 @@ +------------------------------------------------------------------------------ +-- -- +-- Copyright (C) 2022, AdaCore -- +-- -- +-- Redistribution and use in source and binary forms, with or without -- +-- modification, are permitted provided that the following conditions are -- +-- met: -- +-- 1. Redistributions of source code must retain the above copyright -- +-- notice, this list of conditions and the following disclaimer. -- +-- 2. Redistributions in binary form must reproduce the above copyright -- +-- notice, this list of conditions and the following disclaimer in -- +-- the documentation and/or other materials provided with the -- +-- distribution. -- +-- 3. Neither the name of the copyright holder nor the names of its -- +-- contributors may be used to endorse or promote products derived -- +-- from this software without specific prior written permission. -- +-- -- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- +-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- +-- -- +------------------------------------------------------------------------------ + +package body PCF8574 is + + ----------- + -- Get -- + ----------- + + function Get (This : PCF8574_Module) return UInt8 + is + Val : I2C_Data (1 .. 1); + Status : I2C_Status; + begin + This.Port.Master_Receive (This.Addr, Val, Status); + return Val (1); + end Get; + + procedure Get (This : PCF8574_Module; Data : out UInt8) + is begin + Data := Get (This); + end Get; + + ----------- + -- Set -- + ----------- + + procedure Set (This : PCF8574_Module; Data : UInt8) + is + Status : I2C_Status; + begin + This.Port.Master_Transmit (This.Addr, (1 => Data), Status); + end Set; + +end PCF8574; diff --git a/components/src/io_expander/pcf8574/pcf8574.ads b/components/src/io_expander/pcf8574/pcf8574.ads new file mode 100644 index 000000000..04b4054a9 --- /dev/null +++ b/components/src/io_expander/pcf8574/pcf8574.ads @@ -0,0 +1,63 @@ +------------------------------------------------------------------------------ +-- -- +-- Copyright (C) 2022, AdaCore -- +-- -- +-- Redistribution and use in source and binary forms, with or without -- +-- modification, are permitted provided that the following conditions are -- +-- met: -- +-- 1. Redistributions of source code must retain the above copyright -- +-- notice, this list of conditions and the following disclaimer. -- +-- 2. Redistributions in binary form must reproduce the above copyright -- +-- notice, this list of conditions and the following disclaimer in -- +-- the documentation and/or other materials provided with the -- +-- distribution. -- +-- 3. Neither the name of the copyright holder nor the names of its -- +-- contributors may be used to endorse or promote products derived -- +-- from this software without specific prior written permission. -- +-- -- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- +-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- +-- -- +------------------------------------------------------------------------------ + +with HAL; use HAL; +with HAL.I2C; use HAL.I2C; + +-- I2C 8-bit IO expander with quasi bidirectional I/O, no data +-- direction, no latch + +package PCF8574 is + + subtype PCF8574_Address is I2C_Address range 16#40# .. 16#5F#; + + type PCF8574_Module (Port : not null Any_I2C_Port; + Addr : I2C_Address) is tagged limited private; + + type Any_PCF8574_Module is access all PCF8574_Module'Class; + + + procedure Set (This : PCF8574_Module; Data : UInt8); + + function Get (This : PCF8574_Module) return UInt8; + procedure Get (This : PCF8574_Module; Data : out UInt8); + -- when reading the input from keys (buttons) carefully read the + -- datasheet. The input line should be set high before reading. + -- E.g. if all lines are key input: + -- M.Set (16#FF#); + -- Keys := M.Get; + +private + + type PCF8574_Module (Port : not null Any_I2C_Port; + Addr : I2C_Address) is tagged limited null record; + +end PCF8574; diff --git a/components/src/screen/lcd/lcd_hd44780-custom_characters.ads b/components/src/screen/lcd/lcd_hd44780-custom_characters.ads new file mode 100644 index 000000000..555675053 --- /dev/null +++ b/components/src/screen/lcd/lcd_hd44780-custom_characters.ads @@ -0,0 +1,70 @@ +------------------------------------------------------------------------------ +-- -- +-- Copyright (C) 2022, AdaCore -- +-- -- +-- Redistribution and use in source and binary forms, with or without -- +-- modification, are permitted provided that the following conditions are -- +-- met: -- +-- 1. Redistributions of source code must retain the above copyright -- +-- notice, this list of conditions and the following disclaimer. -- +-- 2. Redistributions in binary form must reproduce the above copyright -- +-- notice, this list of conditions and the following disclaimer in -- +-- the documentation and/or other materials provided with the -- +-- distribution. -- +-- 3. Neither the name of the copyright holder nor the names of its -- +-- contributors may be used to endorse or promote products derived -- +-- from this software without specific prior written permission. -- +-- -- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- +-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- +-- -- +------------------------------------------------------------------------------ + +-- sample definitions for custom characters + +package LCD_HD44780.Custom_Characters is + + -- + -- Sample Custom Characters + -- + + Filled_Heart : constant Custom_Character_Definition := + (2#00000#, + 2#00000#, + 2#01010#, + 2#11111#, + 2#11111#, + 2#11111#, + 2#01110#, + 2#00100#); + + Open_Heart : constant Custom_Character_Definition := + (2#00000#, + 2#00000#, + 2#01010#, + 2#10101#, + 2#10001#, + 2#10001#, + 2#01010#, + 2#00100#); + + Thermometer : constant Custom_Character_Definition := + (2#00100#, + 2#01010#, + 2#01010#, + 2#01010#, + 2#01010#, + 2#10001#, + 2#10001#, + 2#01110#); + +end LCD_HD44780.Custom_Characters; diff --git a/components/src/screen/lcd/lcd_hd44780-pcf8574.adb b/components/src/screen/lcd/lcd_hd44780-pcf8574.adb new file mode 100644 index 000000000..5b0e0b7ba --- /dev/null +++ b/components/src/screen/lcd/lcd_hd44780-pcf8574.adb @@ -0,0 +1,206 @@ +------------------------------------------------------------------------------ +-- -- +-- Copyright (C) 2022, AdaCore -- +-- -- +-- Redistribution and use in source and binary forms, with or without -- +-- modification, are permitted provided that the following conditions are -- +-- met: -- +-- 1. Redistributions of source code must retain the above copyright -- +-- notice, this list of conditions and the following disclaimer. -- +-- 2. Redistributions in binary form must reproduce the above copyright -- +-- notice, this list of conditions and the following disclaimer in -- +-- the documentation and/or other materials provided with the -- +-- distribution. -- +-- 3. Neither the name of the copyright holder nor the names of its -- +-- contributors may be used to endorse or promote products derived -- +-- from this software without specific prior written permission. -- +-- -- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- +-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- +-- -- +------------------------------------------------------------------------------ + +-- driver for text based LCDs connected via I2C port expander PCF8574 + +pragma Restrictions (No_Allocators); +pragma Restrictions (No_Implicit_Heap_Allocations); + +package body LCD_HD44780.PCF8574 is + + type Shadow_Bits is array (Bit_Number) of Boolean + with Pack, Size => 8; + + I2C_Shadow : Shadow_Bits; + + procedure Write_Shadow (This : LCD_PCF8574) + with Inline; + + ------------ + -- Create -- + ------------ + + function Create (Display_Width : Char_Position; + Display_Height : Line_Position; + Time : not null HAL.Time.Any_Delays; + Expander : Standard.PCF8574.Any_PCF8574_Module; + Mapping : Bit_Mapping := Standard_Mapping) return LCD_PCF8574 + is + begin + I2C_Shadow := (others => False); + return L : LCD_PCF8574 (Display_Width, Display_Height, Time) do + L.I2C_Driver := Expander; + L.Pins := Mapping; + end return; + end Create; + + ------------------ + -- Write_Shadow -- + ------------------ + + procedure Write_Shadow (This : LCD_PCF8574) + is + Shadow_As_Byte : UInt8 + with Address => I2C_Shadow'Address; + begin + This.I2C_Driver.Set (Shadow_As_Byte); + end Write_Shadow; + + ------------------- + -- Set_Backlight -- + ------------------- + + overriding + procedure Set_Backlight (This : in out LCD_PCF8574; + Is_On : Boolean := True) + is + Bl : Boolean renames I2C_Shadow (This.Pins (Backlight)); + begin + Bl := Is_On; + This.Write_Shadow; + end Set_Backlight; + + ------------------- + -- Toggle_Enable -- + ------------------- + + overriding + procedure Toggle_Enable (This : LCD_PCF8574) + is + Bit : constant Bit_Number := This.Pins (Enable); + En : Boolean renames I2C_Shadow (Bit); + begin + En := True; + This.Write_Shadow; + En := False; + This.Write_Shadow; + This.Time.Delay_Microseconds (280); + end Toggle_Enable; + + ------------ + -- Output -- + ------------ + + overriding + procedure Output (This : LCD_PCF8574; + Cmd : UInt8; + Is_Data : Boolean := False) + is + RW_Bit : constant Bit_Number := This.Pins (ReadWrite); + RS_Bit : constant Bit_Number := This.Pins (RegSel); + B0_Bit : constant Bit_Number := This.Pins (D0); + B1_Bit : constant Bit_Number := This.Pins (D1); + B2_Bit : constant Bit_Number := This.Pins (D2); + B3_Bit : constant Bit_Number := This.Pins (D3); + RW : Boolean renames I2C_Shadow (RW_Bit); + RS : Boolean renames I2C_Shadow (RS_Bit); + P0 : Boolean renames I2C_Shadow (B0_Bit); + P1 : Boolean renames I2C_Shadow (B1_Bit); + P2 : Boolean renames I2C_Shadow (B2_Bit); + P3 : Boolean renames I2C_Shadow (B3_Bit); + begin + -- control pins + RW := False; + RS := Is_Data; + -- write data + -- high nibble first + P0 := (Cmd and 16#10#) /= 0; + P1 := (Cmd and 16#20#) /= 0; + P2 := (Cmd and 16#40#) /= 0; + P3 := (Cmd and 16#80#) /= 0; + + This.Toggle_Enable; + + P0 := (Cmd and 16#01#) /= 0; + P1 := (Cmd and 16#02#) /= 0; + P2 := (Cmd and 16#04#) /= 0; + P3 := (Cmd and 16#08#) /= 0; + + This.Toggle_Enable; + + This.Time.Delay_Microseconds (50); + end Output; + + -------------------- + -- Init_4bit_Mode -- + -------------------- + + overriding + procedure Init_4bit_Mode (This : LCD_PCF8574) + is + RW_Bit : constant Bit_Number := This.Pins (ReadWrite); + RS_Bit : constant Bit_Number := This.Pins (RegSel); + En_Bit : constant Bit_Number := This.Pins (Enable); + B0_Bit : constant Bit_Number := This.Pins (D0); + B1_Bit : constant Bit_Number := This.Pins (D1); + B2_Bit : constant Bit_Number := This.Pins (D2); + B3_Bit : constant Bit_Number := This.Pins (D3); + RW : Boolean renames I2C_Shadow (RW_Bit); + RS : Boolean renames I2C_Shadow (RS_Bit); + En : Boolean renames I2C_Shadow (En_Bit); + P0 : Boolean renames I2C_Shadow (B0_Bit); + P1 : Boolean renames I2C_Shadow (B1_Bit); + P2 : Boolean renames I2C_Shadow (B2_Bit); + P3 : Boolean renames I2C_Shadow (B3_Bit); + begin + I2C_Shadow := (others => False); + + -- all control lines low + RS := False; + En := False; + RW := False; + -- write 1 into pins 0 and 1 + P0 := True; + P1 := True; + P2 := False; + P3 := False; + This.Write_Shadow; + + This.Toggle_Enable; + This.Time.Delay_Milliseconds (5); + + -- send last command again (is still in register, just toggle E) + This.Toggle_Enable; + This.Time.Delay_Milliseconds (5); + + -- send last command a third time + This.Toggle_Enable; + + This.Time.Delay_Microseconds (150); + + -- set 4 bit mode, clear data bit 0 + P0 := False; + + This.Toggle_Enable; + + end Init_4bit_Mode; + +end LCD_HD44780.PCF8574; diff --git a/components/src/screen/lcd/lcd_hd44780-pcf8574.ads b/components/src/screen/lcd/lcd_hd44780-pcf8574.ads new file mode 100644 index 000000000..939704722 --- /dev/null +++ b/components/src/screen/lcd/lcd_hd44780-pcf8574.ads @@ -0,0 +1,93 @@ +------------------------------------------------------------------------------ +-- -- +-- Copyright (C) 2022, AdaCore -- +-- -- +-- Redistribution and use in source and binary forms, with or without -- +-- modification, are permitted provided that the following conditions are -- +-- met: -- +-- 1. Redistributions of source code must retain the above copyright -- +-- notice, this list of conditions and the following disclaimer. -- +-- 2. Redistributions in binary form must reproduce the above copyright -- +-- notice, this list of conditions and the following disclaimer in -- +-- the documentation and/or other materials provided with the -- +-- distribution. -- +-- 3. Neither the name of the copyright holder nor the names of its -- +-- contributors may be used to endorse or promote products derived -- +-- from this software without specific prior written permission. -- +-- -- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- +-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- +-- -- +------------------------------------------------------------------------------ + +-- driver for text based LCDs connected via I2C port expander PCF8574 + +with HAL.Time; +with PCF8574; + +package LCD_HD44780.PCF8574 is + + -- Describe the internal wiring between the PCF8574 output pins + -- and the HD44780 input pins. The PCF8574 pins are the bit numbers. + + type Bit_Number is range 0 .. 7; + + type Bit_Mapping is array (HD44780_4bit_Pins) of Bit_Number; + + Standard_Mapping : constant Bit_Mapping := + (Enable => 2, + ReadWrite => 1, + RegSel => 0, + Backlight => 3, + D0 => 4, + D1 => 5, + D2 => 6, + D3 => 7); + + type LCD_PCF8574 (Display_Width : Char_Position; + Display_Height : Line_Position; + Time : not null HAL.Time.Any_Delays) + is limited new LCD_Module with private; + + function Create (Display_Width : Char_Position; + Display_Height : Line_Position; + Time : not null HAL.Time.Any_Delays; + Expander : Standard.PCF8574.Any_PCF8574_Module; + Mapping : Bit_Mapping := Standard_Mapping) return LCD_PCF8574; + + overriding + procedure Set_Backlight (This : in out LCD_PCF8574; + Is_On : Boolean := True); + +private + + type LCD_PCF8574 (Display_Width : Char_Position; + Display_Height : Line_Position; + Time : not null HAL.Time.Any_Delays) + is limited new LCD_Module (Display_Width, Display_Height, Time) with + record + I2C_Driver : Standard.PCF8574.Any_PCF8574_Module; + Pins : Bit_Mapping; + end record; + + overriding + procedure Toggle_Enable (This : LCD_PCF8574); + + overriding + procedure Output (This : LCD_PCF8574; + Cmd : UInt8; + Is_Data : Boolean := False); + + overriding + procedure Init_4bit_Mode (This : LCD_PCF8574); + +end LCD_HD44780.PCF8574; diff --git a/components/src/screen/lcd/lcd_hd44780.adb b/components/src/screen/lcd/lcd_hd44780.adb new file mode 100644 index 000000000..234bec781 --- /dev/null +++ b/components/src/screen/lcd/lcd_hd44780.adb @@ -0,0 +1,184 @@ +------------------------------------------------------------------------------ +-- -- +-- Copyright (C) 2022, AdaCore -- +-- -- +-- Redistribution and use in source and binary forms, with or without -- +-- modification, are permitted provided that the following conditions are -- +-- met: -- +-- 1. Redistributions of source code must retain the above copyright -- +-- notice, this list of conditions and the following disclaimer. -- +-- 2. Redistributions in binary form must reproduce the above copyright -- +-- notice, this list of conditions and the following disclaimer in -- +-- the documentation and/or other materials provided with the -- +-- distribution. -- +-- 3. Neither the name of the copyright holder nor the names of its -- +-- contributors may be used to endorse or promote products derived -- +-- from this software without specific prior written permission. -- +-- -- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- +-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- +-- -- +------------------------------------------------------------------------------ + +-- +-- From the Hitachi HD44780U data sheet: +-- +-- The HD44780U has two 8-bit registers, an instruction register (IR) +-- and a data register (DR). +-- +-- The IR stores instruction codes, such as display clear and cursor +-- shift, and address information for display data RAM (DDRAM) and +-- character generator RAM (CGRAM). The IR can only be written from +-- the MPU. +-- +-- The DR temporarily stores data to be written into DDRAM or CGRAM +-- and temporarily stores data to be read from DDRAM or CGRAM. Data +-- written into the DR from the MPU is automatically written into +-- DDRAM or CGRAM by an internal operation. The DR is also used for +-- data storage when reading data from DDRAM or CGRAM. When address +-- information is written into the IR, data is read and then stored +-- into the DR from DDRAM or CGRAM by an internal operation. Data +-- transfer between the MPU is then completed when the MPU reads the +-- DR. After the read, data in DDRAM or CGRAM at the next address is +-- sent to the DR for the next read from the MPU. By the register +-- selector (RS) signal, these two registers can be selected + +package body LCD_HD44780 is + + ---------------- + -- Initialize -- + ---------------- + + procedure Initialize (This : in out LCD_Module) is + Dispatch : constant Any_LCD_Module := This'Unchecked_Access; + begin + Dispatch.Init_4bit_Mode; + + -- now we can use the standard Command routine for set up + Dispatch.Command (Commands.Display_On); -- implies blink off and cursor off + This.Clear_Screen; + Dispatch.Command (Commands.Entry_Inc); + end Initialize; + + --------- + -- Put -- + --------- + + -- output at the current cursor location + procedure Put (This : in out LCD_Module; C : Character) is + Dispatch : constant Any_LCD_Module := This'Unchecked_Access; + begin + Dispatch.Output (Character'Pos (C), Is_Data => True); + end Put; + + -- output at the current cursor location + procedure Put (This : in out LCD_Module; Text : String) is + begin + for C of Text loop + This.Put (C); + end loop; + end Put; + + -- output at the specified cursor location + procedure Put (This : in out LCD_Module; + X : Char_Position; + Y : Line_Position; + Text : String) + is + begin + This.Goto_XY (X, Y); + This.Put (Text); + end Put; + + ------------- + -- Command -- + ------------- + + -- output the command code Cmd to the display + procedure Command (This : in out LCD_Module; Cmd : Command_Type) is + Dispatch : constant Any_LCD_Module := This'Unchecked_Access; + begin + Dispatch.Output (UInt8 (Cmd), Is_Data => False); + end Command; + + ------------------ + -- Clear_Screen -- + ------------------ + + -- clear display and move cursor to home position + procedure Clear_Screen (This : in out LCD_Module) is + begin + This.Command (Commands.Clear); + This.Time.Delay_Microseconds (1_500); + end Clear_Screen; + + ---------- + -- Home -- + ---------- + + -- move cursor to home position + procedure Home (This : in out LCD_Module) is + begin + This.Command (16#02#); + end Home; + + ------------- + -- Goto_XY -- + ------------- + + -- move cursor into line Y and before character position X. Lines + -- are numbered 1 to 2 (or 1 to 4 on big displays). The left most + -- character position is Y = 1. The right most position is + -- defined by Lcd.Display.Width; + procedure Goto_XY (This : in out LCD_Module; + X : Char_Position; + Y : Line_Position) + is + begin + if X > This.Display_Width then return; end if; + if Y > This.Display_Height then return; end if; + case Y is + when 1 => Command (This, 16#80# + Command_Type (X) - 1); + when 2 => Command (This, 16#C0# + Command_Type (X) - 1); + when 3 => Command (This, 16#80# + Command_Type (X + This.Display_Width) - 1); + when 4 => Command (This, 16#C0# + Command_Type (X + This.Display_Width) - 1); + end case; + end Goto_XY; + + ----------------------------- + -- Create_Custom_Character -- + ----------------------------- + + procedure Create_Custom_Character (This : in out LCD_Module; + Position : Custom_Character_Index; + Definition : Custom_Character_Definition) + is + Start_Address : constant := 16#40#; + Dispatch : constant Any_LCD_Module := This'Unchecked_Access; + begin + Dispatch.Output (UInt8 (Start_Address + 8 * Position), Is_Data => False); + for Line of Definition loop + Dispatch.Output (UInt8 (Line), Is_Data => True); + end loop; + end Create_Custom_Character; + + ----------------- + -- Custom_Char -- + ----------------- + + function Custom_Char (From_Index : Custom_Character_Index) return Character + is + begin + return Character'Val (From_Index); + end Custom_Char; + +end LCD_HD44780; diff --git a/components/src/screen/lcd/lcd_hd44780.ads b/components/src/screen/lcd/lcd_hd44780.ads new file mode 100644 index 000000000..84a3360ea --- /dev/null +++ b/components/src/screen/lcd/lcd_hd44780.ads @@ -0,0 +1,145 @@ +------------------------------------------------------------------------------ +-- -- +-- Copyright (C) 2022, AdaCore -- +-- -- +-- Redistribution and use in source and binary forms, with or without -- +-- modification, are permitted provided that the following conditions are -- +-- met: -- +-- 1. Redistributions of source code must retain the above copyright -- +-- notice, this list of conditions and the following disclaimer. -- +-- 2. Redistributions in binary form must reproduce the above copyright -- +-- notice, this list of conditions and the following disclaimer in -- +-- the documentation and/or other materials provided with the -- +-- distribution. -- +-- 3. Neither the name of the copyright holder nor the names of its -- +-- contributors may be used to endorse or promote products derived -- +-- from this software without specific prior written permission. -- +-- -- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- +-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- +-- -- +------------------------------------------------------------------------------ + +-- driver for text based LCDs in the typical sizes of 8x1, 16x2 or 20x4 + +with HAL; use HAL; +with HAL.Time; + +package LCD_HD44780 is + + subtype Char_Position is UInt8 range 1 .. 40; + subtype Line_Position is UInt8 range 1 .. 4; + + -- typical display formats are: + -- 8x1 16x1 20x1 + -- 8x2 12x2 16x2 20x2 24x2 40x2 + -- 16x4 20x4 40x4 + + type LCD_Module (Display_Width : Char_Position; + Display_Height : Line_Position; + Time : not null HAL.Time.Any_Delays) + is abstract tagged limited private; + + type Any_LCD_Module is access all LCD_Module'Class; + + procedure Initialize (This : in out LCD_Module); + + procedure Put (This : in out LCD_Module; C : Character) with Inline; + procedure Put (This : in out LCD_Module; Text : String); + -- output at the current cursor location + + procedure Put (This : in out LCD_Module; + X : Char_Position; + Y : Line_Position; + Text : String); + -- output at the specified cursor location + + procedure Clear_Screen (This : in out LCD_Module); + -- clear display and move cursor to home position + + procedure Home (This : in out LCD_Module); + -- move cursor to home position + + procedure Goto_XY (This : in out LCD_Module; X : Char_Position; Y : Line_Position); + -- move cursor into line Y and before character position X. Lines + -- are numbered 1 to 2 (or 1 to 4 on big displays). The left most + -- character position is Y = 1. The right most position is + -- defined by Display_Width; + + procedure Set_Backlight (This : in out LCD_Module; + Is_On : Boolean := True) is abstract; + + type HD44780_Pins is (Enable, ReadWrite, RegSel, Backlight, D0, D1, D2, D3, D4, D5, D6, D7); + subtype HD44780_4bit_Pins is HD44780_Pins range Enable .. D3; + + -- + -- Custom Characters + -- + type Custom_Character_Definition is array (1 .. 8) of UInt5; + subtype Custom_Character_Index is Integer range 0 .. 7; + procedure Create_Custom_Character (This : in out LCD_Module; + Position : Custom_Character_Index; + Definition : Custom_Character_Definition); + function Custom_Char (From_Index : Custom_Character_Index) return Character; + + + type Command_Type is new UInt8; + procedure Command (This : in out LCD_Module; Cmd : Command_Type) + with Inline; + -- send the command code Cmd to the display + + package Commands is + Clear : constant Command_Type := 16#01#; + Home : constant Command_Type := 16#02#; + + -- interface data width and number of lines + Mode_4bit_1line : constant Command_Type := 16#20#; + Mode_4bit_2line : constant Command_Type := 16#28#; + Mode_8bit_1line : constant Command_Type := 16#30#; + Mode_8bit_2line : constant Command_Type := 16#38#; + + -- display on/off, cursor on/off, blinking char at cursor position + Display_Off : constant Command_Type := 16#08#; + Display_On : constant Command_Type := 16#0C#; + Display_On_Blink : constant Command_Type := 16#0D#; + Display_On_Cursor : constant Command_Type := 16#0E#; + Display_On_Cursor_Blink : constant Command_Type := 16#0F#; + + -- entry mode + Entry_Inc : constant Command_Type := 16#06#; + Entry_Dec : constant Command_Type := 16#04#; + Entry_Shift_Inc : constant Command_Type := 16#07#; + Entry_Shift_Dec : constant Command_Type := 16#05#; + + -- cursor/shift display + Move_Cursor_Left : constant Command_Type := 16#10#; + Move_Cursor_Right : constant Command_Type := 16#14#; + Move_Display_Left : constant Command_Type := 16#18#; + Move_Display_Right : constant Command_Type := 16#1C#; + end Commands; + +private + + type LCD_Module (Display_Width : Char_Position; + Display_Height : Line_Position; + Time : not null HAL.Time.Any_Delays) + is abstract tagged limited null record; + + procedure Toggle_Enable (This : LCD_Module) is null; + + procedure Output (This : LCD_Module; + Cmd : UInt8; + Is_Data : Boolean := False) is null; + + procedure Init_4bit_Mode (This : LCD_Module) is null; + +end LCD_HD44780;