Raspberry Pi Pico - i2c on SunFounder IIC I2C TWI Serial 2004 20x4 LCD Module Shield

I’m using Jeremy Grosser’s Raspberry Pi RP2040 Pico Ada code mentioned in the following blog:

https://pico-doc.synack.me/

I’m converting some working C code that uses the Raspberry Pi C SDK that allows me to connect to the 20x4 LCD module. I’ve got most of it converted, but it looks like it uses:

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/hardware_i2c/i2c.c

And, in the working C code it uses the routines:

i2c_write_blocking and i2c_read_blocking

Can anyone help me figure out what to use in place of these 2 routines? I will be glad to post up all of the working C code and the Ada code I have converted.

The Master_Transmit and Master_Receive procedures in the HAL.I2C interface.

With rp2040_hal, RP.Device.I2CM_0 and RP.Device.I2CM_1 implement this interface.

Here’s a driver that uses these procedures

You’d instantiate it like this:

RTC : DS3231.DS3231_Device :=
   (I2C_Port    => RP.Device.I2CM_0'Access,
    I2C_Address => DS3231.Default_Address);

OK. I’ll look at this and see if I can implement for what I’m trying to do. Most of my microcontroller programming has been done via the Arduino IDE. So, I always had libraries to just use (or the C SDK). I’ve never programmed down at the hardware level. So, this may take some time. Thanks.

When you talk about a 20x4 LCD it is most probably based on the hd44780 LCD driver. The mentioned SunFounder board uses the I2C based I/O port expander PCF8574 connected to the HD44780 as far as I can see.

If that is the case have a look at the Ada_Drivers_Library Ada_Drivers_Library/components/src/screen/lcd/lcd_hd44780.ads at 69b17f612784850f9d661f81a51d9f21fe15f9dc · AdaCore/Ada_Drivers_Library · GitHub and Ada_Drivers_Library/components/src/screen/lcd/lcd_hd44780-pcf8574.ads at 69b17f612784850f9d661f81a51d9f21fe15f9dc · AdaCore/Ada_Drivers_Library · GitHub in components/src/screen/lcd

I once had a sample program somewhere on my computer. If you need it I will have to search more seriously…

Yeah, this looks similar to what I wrote up (but, programmed better). The part I don’t see, which is what I’m having difficulty with is the I2C part. I’ve ordered a debug module, so I can attach it to my pico and debug it remotely.

It is one of the nice features of the Arduino IDE that you can monitor your printfs (or Put, Put_Line) via the built-in Serial monitor. So, you don’t have to do SWD debugging if all you’re after is to see “print” in your code. Let me know if you know how to do this via Ada. I guess it would be like opening a serial stream for Ada to write to.

Anyway, thanks for this code. It gives me a decent example of creating a Class.

Frank

OK. In the C SDK for the Pico, I see the following code:

    i2c_init(i2c_default, 100 * 1000);
    gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
    gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
    
    -- Make the I2C pins available to picotool
    bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));

How do I translate these using the Jeremy’s Ada Pico code?

Frank

OK. I finally got my debug probe from Adafruit and have it working with code via C/C++ SDK. So far, no luck via Ada (btw - I’m doing everything via VS Code on Mint Linux running on

System:
  Kernel: 6.8.0-57-generic arch: x86_64 bits: 64 compiler: gcc v: 13.3.0 clocksource: tsc
  Desktop: Xfce v: 4.18.1 tk: Gtk v: 3.24.41 wm: xfwm4 v: 4.18.0 with: xfce4-panel
    tools: light-locker vt: 7 dm: LightDM v: 1.30.0 Distro: Linux Mint 22.1 Xia
    base: Ubuntu 24.04 noble
Machine:
  Type: Portable System: Dell product: Inspiron 3531 v: A00 serial: <superuser required>
  Mobo: Dell model: 00FTTX v: A00 serial: <superuser required> part-nu: Inspiron 3531
    uuid: <superuser required> UEFI-[Legacy]: Dell v: A00 date: 04/11/2014

So, I decided to post the C code that I know works. All I need is the i2c part to work in Ada and the rest will fall into place. So, if someone could just look at the two sets of code - focusing on the I2C part - maybe someone can help me get this working. My goal is to get this project printed up in the official Raspberry Pi magazine. So, it’d give Ada some exposure.

This is lcd_2004_i2c.c

#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "lcd_2004_i2c.h"

// I2C reserves some addresses for special purposes. We exclude these from the scan.
// These are any addresses of the form 000 0xxx or 111 1xxx
static bool reserved_addr(uint8_t addr) {
    return (addr & 0x78) == 0 || (addr & 0x78) == 0x78;
}

static void i2c_write_byte(i2c_inst_t *i2c, uint8_t addr, uint8_t val) {
    i2c_write_blocking(i2c, addr, &val, 1, false);
}

static int lcd_check_available(struct lcd_device *lcd)
{
    uint8_t rxdata;
    if (reserved_addr(lcd->addr))
        return false;
    
    return i2c_read_blocking(lcd->i2c, lcd->addr, &rxdata, 1, false) < 0 ? false : true;
}

static void lcd_toggle_enable(struct lcd_device *lcd, uint8_t val) {
    sleep_us(ENABLE_DELAY_US);
    i2c_write_byte(lcd->i2c, lcd->addr, val | LCD_ENABLE_BIT);
    sleep_us(ENABLE_DELAY_US);
    i2c_write_byte(lcd->i2c, lcd->addr, val & ~LCD_ENABLE_BIT);
    sleep_us(ENABLE_DELAY_US);
}

static void lcd_send_byte(struct lcd_device *lcd, uint8_t val, int mode) {
    uint8_t high = mode | (val & 0xF0) | LCD_BACKLIGHT;
    uint8_t low = mode | ((val << 4) & 0xF0) | LCD_BACKLIGHT;

    // The data can be sent before or after sending RS and RW signals.
    // But data should be available before toggling LCD enable pin.
    i2c_write_byte(lcd->i2c, lcd->addr, high);
    lcd_toggle_enable(lcd, high);

    i2c_write_byte(lcd->i2c, lcd->addr, low);
    lcd_toggle_enable(lcd, low);
}

static void inline lcd_char(struct lcd_device *lcd, char val) {
    lcd_send_byte(lcd, val, LCD_CHARACTER);
}

static void lcd_home(struct lcd_device *lcd) {
    lcd_send_byte(lcd, LCD_RETURNHOME, LCD_COMMAND);
}

void lcd_clear(struct lcd_device *lcd) {
    lcd_send_byte(lcd, LCD_CLEARDISPLAY, LCD_COMMAND);
}

void lcd_set_cursor(struct lcd_device *lcd, int line, int position) {
    int val;
	switch(line) {
		case 0:
			val = LCD_ROW0;
			break;
		case 1:
			val = LCD_ROW1;
			break;
		case 2:
			val = LCD_ROW2;
			break;
		case 3:
			val = LCD_ROW3;
			break;
	}
    val += position;
    lcd_send_byte(lcd, val, LCD_COMMAND);
}

void lcd_string(struct lcd_device *lcd, const char *s) {
    while (*s) {
        lcd_char(lcd, *s++);
    }
}

bool lcd_init(struct lcd_device *lcd) {
    if(!lcd_check_available(lcd))
        return false;

    // please check the initialization flow from https://cdn-shop.adafruit.com/datasheets/TC2004A-01.pdf    
    lcd_send_byte(lcd, 0x03, LCD_COMMAND);
    lcd_send_byte(lcd, 0x03, LCD_COMMAND);
    lcd_send_byte(lcd, 0x03, LCD_COMMAND);
    lcd_send_byte(lcd, 0x02, LCD_COMMAND);

    lcd_send_byte(lcd, LCD_ENTRYMODESET | LCD_ENTRYLEFT, LCD_COMMAND);
    lcd_send_byte(lcd, LCD_FUNCTIONSET | LCD_2LINE, LCD_COMMAND);
    lcd_send_byte(lcd, LCD_DISPLAYCONTROL | LCD_DISPLAYON, LCD_COMMAND);
    lcd_clear(lcd);
    lcd_home(lcd);

    return true;
}

This is lcd_2004_i2c.h

#ifndef LCD2004_I2C_H
#define LCD2004_I2C_H

#include <stdlib.h>

// commands
#define LCD_CLEARDISPLAY         0x01
#define LCD_RETURNHOME           0x02
#define LCD_ENTRYMODESET         0x04
#define LCD_DISPLAYCONTROL       0x08
#define LCD_CURSORSHIFT          0x10
#define LCD_FUNCTIONSET          0x20
#define LCD_SETCGRAMADDR         0x40
#define LCD_SETDDRAMADDR         0x80

// flags for display entry mode
#define  LCD_ENTRYSHIFTINCREMENT 0x01
#define  LCD_ENTRYLEFT           0x02

// flags for display and cursor control
#define  LCD_BLINKON             0x01
#define  LCD_CURSORON            0x02
#define  LCD_DISPLAYON           0x04

// flags for display and cursor shift
#define  LCD_MOVERIGHT           0x04
#define  LCD_DISPLAYMOVE         0x08

// flags for function set
#define  LCD_5x10DOTS            0x04
#define  LCD_2LINE               0x08
#define  LCD_8BITMODE            0x10

// flag for backlight control
#define  LCD_BACKLIGHT           0x08

#define  LCD_ENABLE_BIT          0x04

// Modes for lcd_send_byte
#define LCD_CHARACTER   1
#define LCD_COMMAND     0

#define MAX_LINES       4
#define MAX_CHARS       20

#define LCD_ROW0        0x80
#define LCD_ROW1        0xC0
#define LCD_ROW2        0x94
#define LCD_ROW3        0xD4
#define ENABLE_DELAY_US 666

struct lcd_device
{
  uint8_t addr;
  i2c_inst_t *i2c;
};

bool lcd_init(struct lcd_device *lcd);
void lcd_string(struct lcd_device *lcd, const char *s);
void lcd_set_cursor(struct lcd_device *lcd, int line, int position);
void lcd_clear(struct lcd_device *lcd);

#endif

Here’s the main program

#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/i2c.h"
#include "lcd_2004_i2c.h"

static char *message[] =
            {
                    "Cherie Hsieh",
                    "Software Engineer", "at PUFsecurity",
                    "Golang", "Community",
                    "GDG Group", "Thank You",
            };

int main() {
    //struct lcd_device lcd = {.i2c = i2c_default, .addr = 0x3F};
    struct lcd_device lcd = {.i2c = i2c_default, .addr = 0x27};
    size_t message_len;

    i2c_init(lcd.i2c, 100 * 1000);
    //gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
    gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
    bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));

    if (!lcd_init(&lcd))
    {
        printf("failed to init LCD device\n");
        return 1;
    }

    message_len = sizeof(message) / sizeof(message[0]);

    while (true) {
        for (int m = 0; m < message_len; m += MAX_LINES) {
            for (int line = 0; line < MAX_LINES && (m + line) < message_len; line++) {
                lcd_set_cursor(&lcd, line, (MAX_CHARS / 2) - strlen(message[m + line]) / 2);
                lcd_string(&lcd, message[m + line]);
            }
            sleep_ms(5000);
            lcd_clear(&lcd);
        }
    }
    return 0;
}

Here’s my Ada specification - hd44780lcd.ads

with Ada.Strings; use Ada.Strings;
with Interfaces;  use Interfaces;
with RP.GPIO;     use RP.GPIO;
with RP.i2c;
with RP.I2C_Master;
with RP.Device;
with RP.Clock;
with HAL;     use HAL;
with HAL.I2C; use HAL.I2C;



package hd44780lcd is

   SDA : GPIO_Point := (Pin => 4);
   SCL : GPIO_Point := (Pin => 5);
   Addr_HAL : constant HAL.I2C.I2C_Address := 16#37#;
   Port : RP.i2c.I2C_Port renames RP.Device.I2C_0;
   Status : RP.I2C.I2C_Status;



   subtype Unsigned_Byte is HAL.UInt8;

   -- commands
   LCD_CLEARDISPLAY   : constant Unsigned_Byte := 16#01#;
   LCD_RETURNHOME     : constant Unsigned_Byte := 16#02#;
   LCD_ENTRYMODESET   : constant Unsigned_Byte := 16#04#;
   LCD_DISPLAYCONTROL : constant Unsigned_Byte := 16#08#;
   LCD_CURSORSHIFT    : constant Unsigned_Byte := 16#10#;
   LCD_FUNCTIONSET    : constant Unsigned_Byte := 16#20#;
   LCD_SETCGRAMADDR   : constant Unsigned_Byte := 16#40#;
   LCD_SETDDRAMADDR   : constant Unsigned_Byte := 16#80#;

   -- flags for display entry mode
   LCD_ENTRYSHIFTINCREMENT : constant Unsigned_Byte := 16#01#;
   LCD_ENTRYLEFT           : constant Unsigned_Byte := 16#02#;

   -- flags for display and cursor control
   LCD_BLINKON   : constant Unsigned_Byte := 16#01#;
   LCD_CURSORON  : constant Unsigned_Byte := 16#02#;
   LCD_DISPLAYON : constant Unsigned_Byte := 16#04#;

   -- flags for display and cursor shift
   LCD_MOVERIGHT   : constant Unsigned_Byte := 16#04#;
   LCD_DISPLAYMOVE : constant Unsigned_Byte := 16#08#;

   -- flags for function set
   LCD_5x10DOTS : constant Unsigned_Byte := 16#04#;
   LCD_2LINE    : constant Unsigned_Byte := 16#08#;
   LCD_8BITMODE : constant Unsigned_Byte := 16#10#;

   -- flag for backlight control
   LCD_BACKLIGHT : constant Unsigned_Byte := 16#08#;

   LCD_ENABLE_BIT : constant Unsigned_Byte := 16#04#;

   -- Modes for lcd_send_byte
   LCD_CHARACTER : constant Unsigned_Byte := 1;
   LCD_COMMAND   : constant Unsigned_Byte := 0;

   MAX_LINES : constant Unsigned_Byte := 4;
   MAX_CHARS : constant Unsigned_Byte := 20;

   LCD_ROW0        : constant Unsigned_Byte := 16#80#;
   LCD_ROW1        : constant Unsigned_Byte := 16#C0#;
   LCD_ROW2        : constant Unsigned_Byte := 16#94#;
   LCD_ROW3        : constant Unsigned_Byte := 16#D4#;
   ENABLE_DELAY_US : constant Integer       := 666;

   --struct lcd_device
   --{
   --  uint8_t addr;
   --  i2c_inst_t *i2c;
   --};

   --bool lcd_init(struct lcd_device *lcd);
   --void lcd_string(struct lcd_device *lcd, const char *s);
   --void lcd_set_cursor(struct lcd_device *lcd, int line, int position);
   --void lcd_clear(struct lcd_device *lcd);
   function reserved_addr return Boolean;
   procedure i2c_write_byte (val : Unsigned_Byte);
   function lcd_check_available return Boolean;
   procedure lcd_toggle_enable (val : Unsigned_Byte);
   procedure lcd_send_byte (val : Unsigned_Byte; mode : Unsigned_Byte);
   procedure lcd_char (val : Unsigned_Byte);
   procedure lcd_home;
   procedure lcd_clear;
   procedure lcd_set_cursor (line : Unsigned_Byte; position : Unsigned_Byte);
   procedure lcd_string (s : String);
   function lcd_init return Boolean;
   procedure rp_i2c_init;

end hd44780lcd;

Here’s my hd44780lcd.adb

with HAL.GPIO;
with Interfaces;
with Interfaces.C;
with RP;       use RP;
with RP.GPIO;  use RP.GPIO;
with HAL.GPIO; use HAL.GPIO;
with RP.I2C_Master;
with RP.Device;
with RP.Clock;
with HAL.I2C;  use HAL;
with Pico;

with hd44780lcd; use hd44780lcd;

package body hd44780lcd is
   -- I2C reserves some addresses for special purposes. We exclude these from the scan.
   -- These are any addresses of the form 000 0xxx or 111 1xxx
   function reserved_addr return Boolean is
      temp1 : Unsigned_Byte;
      ret   : Boolean;
   begin
      --return (addr & 0x78) == 0 || (addr & 0x78) == 0x78;
      temp1 := UInt8 (Addr_HAL) and 16#78#;
      if ((temp1 = 0) or (temp1 = 16#78#)) then
         ret := True; -- true
      else
         ret := False;
      end if;

      return ret;
   end reserved_addr;

   procedure i2c_write_byte (val : Unsigned_Byte) is
      use HAL.I2C;
   begin
      null;
      -- i2c_write_blocking(i2c, addr, &val, 1, false);
      Port.Write
        (Data     => val, 
        Status => Status);
      --Port.Master_Transmit
      --  (Addr    => Addr_HAL, Data => Data, Status => Status,
      --   Timeout => 1);
      --Port.Master_Transmit (Default_Address, Data, Status);
   end i2c_write_byte;

   function lcd_check_available return Boolean is
      use RP.I2C;
      ret    : Boolean;
      Data   : UInt8;
   begin
      --if (reserved_addr(lcd->addr))
      --    return false;

      -- return i2c_read_blocking(lcd->i2c, lcd->addr, &rxdata, 1, false) < 0 ? false : true;

      if (reserved_addr) then
         ret := False;  -- false
      else
         --i2c_read_blocking(lcd->i2c, lcd->addr, &rxdata, 1, false)
         Port.Read
           (Data     => Data,
            Status   =>    Status);


         if (Status = Ok) then
            ret := False;  --false
         else
            ret := True;  --true
         end if;
      end if;

      return ret;
   end lcd_check_available;

   procedure lcd_toggle_enable (val : Unsigned_Byte) is
   begin
      RP.Device.Timer.Delay_Microseconds (ENABLE_DELAY_US);
      --i2c_write_byte(lcd->i2c, lcd->addr, val | LCD_ENABLE_BIT);
      i2c_write_byte (val or LCD_ENABLE_BIT);
      RP.Device.Timer.Delay_Microseconds (ENABLE_DELAY_US);
      --i2c_write_byte(lcd->i2c, lcd->addr, val & ~LCD_ENABLE_BIT);
      i2c_write_byte (val and not LCD_ENABLE_BIT);
   end lcd_toggle_enable;

   procedure lcd_send_byte (val : Unsigned_Byte; mode : Unsigned_Byte) is
      high, low, temp : Unsigned_Byte;
      Status          : HAL.I2C.I2C_Status;
   begin
      high := mode or (val and 16#F0#) or LCD_BACKLIGHT;
      temp := Unsigned_Byte'Value (Unsigned_Byte'Image (Shift_Left (val, 4)));
      low  := mode or (temp and 16#F0#) or LCD_BACKLIGHT;
      -- The data can be sent before or after sending RS and RW signals.
      -- But data should be available before toggling LCD enable pin.
      --i2c_write_byte(lcd->i2c, lcd->addr, high);
      --lcd_toggle_enable(lcd, high);
      i2c_write_byte (high);
      lcd_toggle_enable (high);

      --i2c_write_byte(lcd->i2c, lcd->addr, low);
      --lcd_toggle_enable(lcd, low);
      i2c_write_byte (low);
      lcd_toggle_enable (low);

   end lcd_send_byte;

   procedure lcd_char (val : Unsigned_Byte) is
   begin
      lcd_send_byte (val, LCD_CHARACTER);
   end lcd_char;

   procedure lcd_home  is
   begin
      lcd_send_byte (LCD_RETURNHOME, LCD_COMMAND);
   end lcd_home;

   procedure lcd_clear is
   begin
      lcd_send_byte (LCD_CLEARDISPLAY, LCD_COMMAND);
   end lcd_clear;

   procedure lcd_set_cursor (line : Unsigned_Byte; position : Unsigned_Byte) is
      val : Unsigned_Byte;
   begin
      case line is
         when 0 =>
            val := LCD_ROW0;
         when 1 =>
            val := LCD_ROW1;
         when 2 =>
            val := LCD_ROW2;
         when 3 =>
            val := LCD_ROW3;
         when others =>
            val := LCD_ROW0;
      end case;

      val := val + position;
      lcd_send_byte (val, LCD_COMMAND);
   end lcd_set_cursor;

   procedure lcd_string (s : String) is
      i : Integer;
   begin
      -- while (*s) {
      --    lcd_char(lcd, *s++);
      --}
      for i in 1 .. s'Length loop
         -- null;
         -- need correct conversion
         -- lcd_char (Character'Pos (s (i)));
         lcd_char (41); --letter A
      end loop;
   end lcd_string;

   function lcd_init return Boolean is
      ret : Boolean;
   begin
      if (lcd_check_available) then
         ret := False;  --false
      else
         -- please check the initialization flow from https://cdn-shop.adafruit.com/datasheets/TC2004A-01.pdf
         lcd_send_byte (16#03#, LCD_COMMAND);
         lcd_send_byte (16#03#, LCD_COMMAND);
         lcd_send_byte (16#03#, LCD_COMMAND);
         lcd_send_byte (16#02#, LCD_COMMAND);

         lcd_send_byte (LCD_ENTRYMODESET or LCD_ENTRYLEFT, LCD_COMMAND);
         lcd_send_byte (LCD_FUNCTIONSET or LCD_2LINE, LCD_COMMAND);
         lcd_send_byte (LCD_DISPLAYCONTROL or LCD_DISPLAYON, LCD_COMMAND);
         lcd_clear;
         lcd_home;
         ret := True; --true
      end if;

      return ret;
   end lcd_init;

   procedure rp_i2c_init is
   begin
      SDA.Configure (Output, Pull_Up, RP.GPIO.I2C, Schmitt => True);
      SCL.Configure (Output, Pull_Up, RP.GPIO.I2C, Schmitt => True);

      Port.Configure ((Role => RP.I2C.Target, others => <>));
      Port.Set_Address (Addr_HAL);
      Port.Enable;
      
      --Port.Set_Address := Default_Address;
      --Port.enable

      -- This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico)
      --   i2c_init(i2c_default, 100 * 1000);
      --   gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
      --   gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
      --   gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
      --   gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);

      --   -- Make the I2C pins available to picotool
      --   bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));

   end rp_i2c_init;

end hd44780lcd;

Here’s my main - hd44780lcd_test.adb

with Ada.Text_IO;             use Ada.Text_IO;
with System.Unsigned_Types;   use System.Unsigned_Types;
with Ada.Characters.Handling; use Ada.Characters.Handling;
with Interfaces;              use Interfaces;
with RP.GPIO;                 use RP.GPIO;
with RP.I2C_Master;
with RP.Device;
with RP.Clock;
with HAL.I2C;
with Pico;

--with lcd_2004_i2c; use lcd_2004_i2c;
with hd44780lcd; use hd44780lcd;

procedure hd44780lcd_test is
   Status : Boolean;
   -- struct lcd_device lcd = {.i2c = i2c_default, .addr = 0x27};
begin
   -- null;
   --  i2c_init(lcd.i2c, 100 * 1000);
   -- i2c_init (lcd.i2c, 100 * 1_000);

   -- need to replace the following 5 lines with Ada equivalent
   --
   --gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
   --gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
   --gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
   --gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
   --bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
   --   if (!lcd_init(&lcd))
   --      {
   --          printf("failed to init LCD device\n");
   --          return 1;
   --      }

   --      message_len = sizeof(message) / sizeof(message[0]);

   --      while (true) {
   --          for (int m = 0; m < message_len; m += MAX_LINES) {
   --              for (int line = 0; line < MAX_LINES && (m + line) < message_len; line++) {
   --                  lcd_set_cursor(&lcd, line, (MAX_CHARS / 2) - strlen(message[m + line]) / 2);
   --                  lcd_string(&lcd, message[m + line]);
   --              }
   --              sleep_ms(5000);
   --              lcd_clear(&lcd);
   --          }
   --      }
   --      return 0;

   rp_i2c_init;

   Status := lcd_init;
   Put_Line (Status'Image);
   if (Status) then
      Put_Line ("failed to init LCD device");
   else

      lcd_clear;
      --length := Unsigned_Byte(message'Length);
      --for m in 1 .. length loop
      lcd_set_cursor (0, 0);
      lcd_char (65);
      --lcd_string ("Hello World");
      --end loop;

   end if;
end hd44780lcd_test;
1 Like