* Examples: Generic LCD procedures

This commit is contained in:
Vovanium 2021-09-22 15:59:56 +03:00
parent 59d3143be5
commit b6f651b2bd
7 changed files with 222 additions and 239 deletions

View File

@ -0,0 +1,96 @@
with Ada.Real_Time;
use Ada.Real_Time;
package body Board.LCD.Generic_IO is
type Unsigned_8_Array is array (Integer range <>) of Interfaces.Unsigned_8;
procedure Write_Command (Command : ILI9341.Command; Data_1 : Interfaces.Unsigned_8) is
begin
Write_Command (Command);
Write_Data (Data_1);
end;
procedure Write_Command (Command : ILI9341.Command; Data : Unsigned_8_Array) is
begin
Write_Command (Command);
for I of Data loop
Write_Data (I);
end loop;
end;
procedure Initialize_Controller is
Now : Time := Clock;
begin
-- Initialization procedure per
-- https://github.com/mongoose-os-libs/ili9341-spi
-- released under Apache licence
Write_Command (ILI9341.SWRESET);
Now := Clock + Milliseconds (5);
delay until Now;
Write_Command (ILI9341.Power_Control_A, (16#39#, 16#2C#, 16#00#, 16#34#, 16#02#));
-- Vcore = 1.6, DDVDH = 5.6 (default)
Write_Command (ILI9341.Power_Control_B, (16#00#, 16#C1#, 16#30#));
-- PCEQ = 1, DRV_ena = 0, Power_Control = 0, DRV_vml = 0, DRV_vmh = 0, DC_ena = 1
--Command (ILI9341.Undocumented_EF, 16#03#, 16#80#, 16#02#);
Write_Command (ILI9341.Driver_Timing_Control_A, (16#85#, 16#00#, 16#78#));
-- NOW = 1, EQ = 0, CR = 0, precharge = 2unit
Write_Command (ILI9341.Driver_Timing_Control_B, (16#00#, 16#00#));
-- T1 = 0, T2 = 0, T3 = 0, T3 = 0
Write_Command (ILI9341.Power_On_Sequence_Control, (16#64#, 16#03#, 16#12#, 16#81#));
-- CP1 = 1frame, CP23 = 3frame, En_vcl = 1st, En_ddvdh = 4th, En_vgh = 2nd, En_vgl = 3rd, DDVDH = En
Write_Command (ILI9341.Pump_Ratio_Control, (16#20#));
-- DDVDH = 2xVCI
Write_Command (ILI9341.PWCTRL1, (16#23#));
-- GVDD level = 4.45 V
Write_Command (ILI9341.PWCTRL2, (16#10#));
-- VGH = VCIx7, VGL = VCIx4
Write_Command (ILI9341.VMCTRL1, (16#3E#, 16#28#));
-- VCOMH = 4.250, VCOML = -1.500
Write_Command (ILI9341.VMCTRL2, (16#86#));
-- nVM = 1, VCOMH = VMH - 58
Write_Command (ILI9341.MADCTL, (16#48#));
-- MY = 0, MX = 1, MV = 0, ML = 0, BGR = 1, MH = 0
Write_Command (ILI9341.PIXSET, (16#66#));
-- RGB = 18bpp, MCU = 18bpp
Write_Command (ILI9341.DINVOFF);
Write_Command (ILI9341.FRMCTR1, (16#00#, 16#13#));
-- DivA = fosc, RTNA = 19 clocks
Write_Command (ILI9341.DISCTRL, (16#08#, 16#82#, 16#27#, 16#00#));
-- PTG Intervalscan, PT = V63/V0/VCOMH/L, REV = White, ISC = 5 fr, GS = G1>G320,W, NL = 320, Fosc = DOTCLK/2
Write_Command (ILI9341.PTLAR, (16#00#, 16#00#, 16#01#, 16#3F#));
-- SR = 0, ER = 319
Write_Command (ILI9341.Enable_3G, (16#02#));
-- 3G = disable
Write_Command (ILI9341.GAMSET, (16#01#));
-- Curve = G2.2
Write_Command (ILI9341.PGAMCTRL, (16#0F#, 16#31#, 16#2B#, 16#0C#, 16#0E#,
16#08#, 16#4E#, 16#F1#, 16#37#, 16#07#, 16#10#, 16#03#, 16#0E#, 16#09#, 16#00#));
Write_Command (ILI9341.NGAMCTRL, (16#00#, 16#0E#, 16#14#, 16#03#, 16#11#,
16#07#, 16#31#, 16#C1#, 16#48#, 16#08#, 16#0F#, 16#0C#, 16#31#, 16#36#, 16#0F#));
Now := Clock + Milliseconds (120);
delay until Now;
Write_Command (ILI9341.SLPOUT);
Write_Command (ILI9341.DISPON);
end Initialize_Controller;
procedure Plot_24 (X, Y, R, G, B: Integer) is
-- Draw a pixel;
begin
Write_Command (ILI9341.CASET, (
Interfaces.Unsigned_8 (X / 256),
Interfaces.Unsigned_8 (X mod 256),
Interfaces.Unsigned_8 ((X + 1) / 256),
Interfaces.Unsigned_8 ((X + 1) mod 256)));
Write_Command (ILI9341.PASET, (
Interfaces.Unsigned_8 (Y / 256),
Interfaces.Unsigned_8 (Y mod 256),
Interfaces.Unsigned_8 ((Y + 1) / 256),
Interfaces.Unsigned_8 ((Y + 1) mod 256)));
Write_Command (ILI9341.RAMWR, (
Interfaces.Unsigned_8 (G),
Interfaces.Unsigned_8 (B),
Interfaces.Unsigned_8 (R)));
end;
end Board.LCD.Generic_IO;

View File

@ -0,0 +1,10 @@
with ILI9341;
with Interfaces;
generic
with procedure Write_Command (Command : ILI9341.Command);
with procedure Write_Data (Data : Interfaces.Unsigned_8);
package Board.LCD.Generic_IO is
procedure Initialize_Controller;
procedure Plot_24 (X, Y, R, G, B: Integer);
end Board.LCD.Generic_IO;

View File

@ -1,202 +0,0 @@
with Ada.Unchecked_Conversion;
with Ada.Real_Time; use Ada.Real_Time;
with Board.SPI.IO;
use Board;
package body Board.LCD.IO is
procedure Initialize_SPI is
begin
-- First initialize SPI to communicate onboard controller
SPI_RCC_EN := True;
SPI_RCC_RST := True;
SPI_RCC_RST := False;
declare
R : STM32.SPI.Control_Register_1 := SPI_Module.CR1;
begin
R.BR := STM32.SPI.PCLK_DIV_16;
R.CPHA := STM32.SPI.Late_Clock;
R.CPOL := STM32.SPI.Positive_Clock;
R.DFF := STM32.SPI.Frame_8_Bit;
R.LSBFIRST := False;
R.SSM := True;
R.SSI := True;
R.MSTR := STM32.SPI.Master;
R.SPE := True;
R.RXONLY := False;
R.BIDIMODE := STM32.SPI.Unidirectional;
R.BIDIOE := True;
R.CRCEN := False;
R.CRCNEXT := False;
SPI_Module.CR1 := R;
end;
declare
R : STM32.SPI.Control_Register_2 := SPI_Module.CR2;
begin
R.FRF := STM32.SPI.Motorola_Mode;
SPI_Module.CR2 := R;
end;
-- Enabling pins
RCC.AHB1ENR (Index.GPIOC) := True;
RCC.AHB1ENR (Index.GPIOD) := True;
RCC.AHB1ENR (Index.GPIOF) := True;
CSX.Set_MODER (STM32.GPIO.Output_Mode);
CSX.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
CSX.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
CSX.Set (True);
DCX.Set_MODER (STM32.GPIO.Output_Mode);
DCX.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
DCX.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
DCX.Set (True);
SCL_Port.AFR (SCL_Bit) := STM32.GPIO.Alternate_Functions.SPI5;
SCL.Set_MODER (STM32.GPIO.Alternate_Mode);
SCL.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
SCL.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
SCL.Set_PUPDR (STM32.GPIO.Pull_Up);
SDA_Port.AFR (SDA_Bit) := STM32.GPIO.Alternate_Functions.SPI5;
SDA.Set_MODER (STM32.GPIO.Alternate_Mode);
SDA.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
SDA.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
SDA.Set_PUPDR (STM32.GPIO.Pull_Up);
end;
procedure Enter is
begin
CSX.Set (False);
end;
procedure Leave is
begin
CSX.Set (True);
end;
procedure Command (Command : ILI9341.Command) is
function To_Unsigned_8 is new Ada.Unchecked_Conversion (ILI9341.Command, Interfaces.Unsigned_8);
begin
DCX.Set(False);
SPI.IO.Transmit (LCD.SPI_Module, To_Unsigned_8 (Command));
end;
procedure Command (Command : ILI9341.Command; Data_1 : Interfaces.Unsigned_8) is
begin
IO.Command (Command);
DCX.Set (True);
SPI.IO.Transmit (LCD.SPI_Module, Data_1);
end;
procedure Data (Data : Interfaces.Unsigned_8) is
begin
DCX.Set (True);
SPI.IO.Transmit (LCD.SPI_Module, Data);
end;
procedure Data (Data : Unsigned_8_Array) is
begin
DCX.Set (True);
for D of Data loop
SPI.IO.Transmit (LCD.SPI_Module, D);
end loop;
end;
procedure Command (Command : ILI9341.Command; Data : Unsigned_8_Array) is
begin
IO.Command (Command);
IO.Data (Data);
end;
procedure Initialize_Controller is
Now : Time := Clock;
begin
Enter;
-- Initialization procedure per
-- https://github.com/mongoose-os-libs/ili9341-spi
-- released under Apache licence
Command (ILI9341.SWRESET);
Now := Clock + Milliseconds (5);
delay until Now;
Command (ILI9341.Power_Control_A, (16#39#, 16#2C#, 16#00#, 16#34#, 16#02#));
-- Vcore = 1.6, DDVDH = 5.6 (default)
Command (ILI9341.Power_Control_B, (16#00#, 16#C1#, 16#30#));
-- PCEQ = 1, DRV_ena = 0, Power_Control = 0, DRV_vml = 0, DRV_vmh = 0, DC_ena = 1
--Command (ILI9341.Undocumented_EF, 16#03#, 16#80#, 16#02#);
Command (ILI9341.Driver_Timing_Control_A, (16#85#, 16#00#, 16#78#));
-- NOW = 1, EQ = 0, CR = 0, precharge = 2unit
Command (ILI9341.Driver_Timing_Control_B, (16#00#, 16#00#));
-- T1 = 0, T2 = 0, T3 = 0, T3 = 0
Command (ILI9341.Power_On_Sequence_Control, (16#64#, 16#03#, 16#12#, 16#81#));
-- CP1 = 1frame, CP23 = 3frame, En_vcl = 1st, En_ddvdh = 4th, En_vgh = 2nd, En_vgl = 3rd, DDVDH = En
Command (ILI9341.Pump_Ratio_Control, (16#20#));
-- DDVDH = 2xVCI
Command (ILI9341.PWCTRL1, (16#23#));
-- GVDD level = 4.45 V
Command (ILI9341.PWCTRL2, (16#10#));
-- VGH = VCIx7, VGL = VCIx4
Command (ILI9341.VMCTRL1, (16#3E#, 16#28#));
-- VCOMH = 4.250, VCOML = -1.500
Command (ILI9341.VMCTRL2, (16#86#));
-- nVM = 1, VCOMH = VMH - 58
Command (ILI9341.MADCTL, (16#48#));
-- MY = 0, MX = 1, MV = 0, ML = 0, BGR = 1, MH = 0
Command (ILI9341.PIXSET, (16#66#));
-- RGB = 18bpp, MCU = 18bpp
Command (ILI9341.DINVOFF);
Command (ILI9341.FRMCTR1, (16#00#, 16#13#));
-- DivA = fosc, RTNA = 19 clocks
Command (ILI9341.DISCTRL, (16#08#, 16#82#, 16#27#, 16#00#));
-- PTG Intervalscan, PT = V63/V0/VCOMH/L, REV = White, ISC = 5 fr, GS = G1>G320,W, NL = 320, Fosc = DOTCLK/2
Command (ILI9341.PTLAR, (16#00#, 16#00#, 16#01#, 16#3F#));
-- SR = 0, ER = 319
Command (ILI9341.Enable_3G, (16#02#));
-- 3G = disable
Command (ILI9341.GAMSET, (16#01#));
-- Curve = G2.2
Command (ILI9341.PGAMCTRL, (16#0F#, 16#31#, 16#2B#, 16#0C#, 16#0E#,
16#08#, 16#4E#, 16#F1#, 16#37#, 16#07#, 16#10#, 16#03#, 16#0E#, 16#09#, 16#00#));
Command (ILI9341.NGAMCTRL, (16#00#, 16#0E#, 16#14#, 16#03#, 16#11#,
16#07#, 16#31#, 16#C1#, 16#48#, 16#08#, 16#0F#, 16#0C#, 16#31#, 16#36#, 16#0F#));
Now := Clock + Milliseconds (120);
delay until Now;
Command (ILI9341.SLPOUT);
Command (ILI9341.DISPON);
LCD.IO.Leave;
end Initialize_Controller;
procedure Plot_24 (X, Y, R, G, B: Integer) is
begin
-- Draw a pixel;
Enter;
Command (ILI9341.CASET, (
Interfaces.Unsigned_8 (X / 256),
Interfaces.Unsigned_8 (X mod 256),
Interfaces.Unsigned_8 ((X + 1) / 256),
Interfaces.Unsigned_8 ((X + 1) mod 256)));
Command (ILI9341.PASET, (
Interfaces.Unsigned_8 (Y / 256),
Interfaces.Unsigned_8 (Y mod 256),
Interfaces.Unsigned_8 ((Y + 1) / 256),
Interfaces.Unsigned_8 ((Y + 1) mod 256)));
Command (ILI9341.RAMWR, (
Interfaces.Unsigned_8 (G),
Interfaces.Unsigned_8 (B),
Interfaces.Unsigned_8 (R)));
Leave;
end;
begin
Initialize_SPI;
Initialize_Controller;
end Board.LCD.IO;

View File

@ -1,34 +0,0 @@
with Interfaces;
with STM32.GPIO.Ports; use STM32.GPIO.Ports;
with ILI9341;
package Board.LCD.IO is
package CSX is new GPIO_Port_Boolean (LCD.CSX_Port, LCD.CSX_Bit);
package DCX is new GPIO_Port_Boolean (LCD.DCX_Port, LCD.DCX_Bit);
package SCL is new GPIO_Port_Boolean (LCD.SCL_Port, LCD.SCL_Bit);
package SDA is new GPIO_Port_Boolean (LCD.SDA_Port, LCD.SDA_Bit);
procedure Initialize_SPI;
procedure Enter;
procedure Leave;
procedure Command (Command : ILI9341.Command);
-- These LCD_Command's are for convenience
procedure Command (Command : ILI9341.Command; Data_1 : Interfaces.Unsigned_8);
procedure Data (Data : Interfaces.Unsigned_8);
type Unsigned_8_Array is array (Integer range <>) of Interfaces.Unsigned_8;
procedure Data (Data : Unsigned_8_Array);
procedure Command (Command : ILI9341.Command; Data : Unsigned_8_Array);
procedure Initialize_Controller;
procedure Plot_24 (X, Y, R, G, B: Integer);
end Board.LCD.IO;

View File

@ -0,0 +1,108 @@
with Ada.Unchecked_Conversion;
with Board.SPI.IO;
with Board.LCD.Generic_IO;
use Board;
with ILI9341;
with Interfaces;
with STM32.GPIO.Ports;
use STM32.GPIO.Ports;
package body Board.LCD.SPI_IO is
package CSX is new GPIO_Port_Boolean (LCD.CSX_Port, LCD.CSX_Bit);
package DCX is new GPIO_Port_Boolean (LCD.DCX_Port, LCD.DCX_Bit);
package SCL is new GPIO_Port_Boolean (LCD.SCL_Port, LCD.SCL_Bit);
package SDA is new GPIO_Port_Boolean (LCD.SDA_Port, LCD.SDA_Bit);
procedure Initialize_SPI is
begin
-- First initialize SPI to communicate onboard controller
SPI_RCC_EN := True;
SPI_RCC_RST := True;
SPI_RCC_RST := False;
declare
R : STM32.SPI.Control_Register_1 := SPI_Module.CR1;
begin
R.BR := STM32.SPI.PCLK_DIV_16;
R.CPHA := STM32.SPI.Late_Clock;
R.CPOL := STM32.SPI.Positive_Clock;
R.DFF := STM32.SPI.Frame_8_Bit;
R.LSBFIRST := False;
R.SSM := True;
R.SSI := True;
R.MSTR := STM32.SPI.Master;
R.SPE := True;
R.RXONLY := False;
R.BIDIMODE := STM32.SPI.Unidirectional;
R.BIDIOE := True;
R.CRCEN := False;
R.CRCNEXT := False;
SPI_Module.CR1 := R;
end;
declare
R : STM32.SPI.Control_Register_2 := SPI_Module.CR2;
begin
R.FRF := STM32.SPI.Motorola_Mode;
SPI_Module.CR2 := R;
end;
-- Enabling pins
RCC.AHB1ENR (Index.GPIOC) := True;
RCC.AHB1ENR (Index.GPIOD) := True;
RCC.AHB1ENR (Index.GPIOF) := True;
CSX.Set_MODER (STM32.GPIO.Output_Mode);
CSX.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
CSX.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
CSX.Set (True);
DCX.Set_MODER (STM32.GPIO.Output_Mode);
DCX.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
DCX.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
DCX.Set (True);
SCL_Port.AFR (SCL_Bit) := STM32.GPIO.Alternate_Functions.SPI5;
SCL.Set_MODER (STM32.GPIO.Alternate_Mode);
SCL.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
SCL.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
SCL.Set_PUPDR (STM32.GPIO.Pull_Up);
SDA_Port.AFR (SDA_Bit) := STM32.GPIO.Alternate_Functions.SPI5;
SDA.Set_MODER (STM32.GPIO.Alternate_Mode);
SDA.Set_OSPEEDR (STM32.GPIO.Very_High_Speed);
SDA.Set_OTYPER (STM32.GPIO.Push_Pull_Type);
SDA.Set_PUPDR (STM32.GPIO.Pull_Up);
end;
procedure Command (Command : ILI9341.Command) is
function To_Unsigned_8 is new Ada.Unchecked_Conversion (ILI9341.Command, Interfaces.Unsigned_8);
begin
CSX.Set (False);
DCX.Set(False);
SPI.IO.Transmit (LCD.SPI_Module, To_Unsigned_8 (Command));
CSX.Set (True);
end;
procedure Data (Data : Interfaces.Unsigned_8) is
begin
CSX.Set (False);
DCX.Set (True);
SPI.IO.Transmit (LCD.SPI_Module, Data);
CSX.Set (True);
end;
package IO is new LCD.Generic_IO(Command, Data);
procedure Initialize_Controller renames IO.Initialize_Controller;
procedure Plot_24 (X, Y, R, G, B: Integer) renames IO.Plot_24;
begin
Initialize_SPI;
Initialize_Controller;
end Board.LCD.SPI_IO;

View File

@ -0,0 +1,5 @@
package Board.LCD.SPI_IO is
procedure Plot_24 (X, Y, R, G, B: Integer);
end Board.LCD.SPI_IO;

View File

@ -1,7 +1,7 @@
with Interfaces;
with Ada.Real_Time; use Ada.Real_Time;
with Chip.Units; use Chip.Units;
with Board.LCD.IO;
with Board.LCD.SPI_IO;
use Board;
with ILI9341;
@ -60,9 +60,9 @@ begin
N := N + 1;
end loop;
if N = 256 then
LCD.IO.Plot_24 (X, Y, 0, 0, 0);
LCD.SPI_IO.Plot_24 (X, Y, 0, 0, 0);
else
LCD.IO.Plot_24 (X, Y, 255 - N, N, 255 - N);
LCD.SPI_IO.Plot_24 (X, Y, 255 - N, N, 255 - N);
end if;
end loop;
end loop;