NanoPC T3 Plus, Android 5.1 with Newhaven IPS LCD | Home Automation Tech Blog

Fun with Embedded Electronics

NanoPC T3 Plus, Android 5.1 with Newhaven IPS LCD

Background

Having used the FriendlyArm Nano PC T3 Plus for some commercial projects, the system was let down by the poor display readability in sunlight in outdoor situations. I initially tried the 900 nits 800×480 display from Newhaven but the low resolution meant that the display in the taskbar area was almost unreadable and the viewing angles were also poor. I also had an issue in getting the display to be stable and had a few artifacts and extra lines appearing. Time to find a new solution.

Enter the Newhaven IPS LVDS display

Newhaven had released the NHD-7.0-1024600AF-LSXP-CTP, an IPS display with touch and giving some 900 nits brightness at 1024×600 resolution and claiming to be sunlight readable. The interface is LVDS so a new PCB would be needed to convert the RGB output from the Nano PC T3 Plus board. This was not as difficult as it appeared as FriendlyArm already did this with their HD702 display for use with the Nano PC boards. All I had to do was create the same mapping and use a similar LVDS encoder IC and it should just work.

I started with the RGB design that I had used for the 800×480 and added in the LVDS encoder IC, a DS90C385AMTX to convert the RGB signals to the LVDS required by the Newhaven display. Careful attention was paid to the mapping of the RGB and SYNC signals as this is not a straight 1 to 1 mapping to each of the LVDS 4 channels. There are 4 LVDS channels that carry the RGB and SYNC and 1 for the clock. Differential pairing was used in the layout of the LVDS signals although the tracks were quite short on the PCB so there was not a lot of concern with timing.

This image shows the LVDS encoder and the input signals. I’ve marked the RGB signals on this to make it clearer.

LVDS encoder

The connection from the Nano PC is RGB and some additional signals for the touch screen and 1-wire backlight control. More on this later.

Nano PC LCD Interface

To make this work with the existing kernel and the 1-wire bus for brightness and LCD control, an STM8S003 micro was added to the design and firmware HEX file from FriendlyArm was programmed into this IC. As I was unable to get them to supply me with a custom ID, I have had to had the u-boot and kernel, which will be detailed below. No the ideal solution and many attempts to get FriendlyArm to give me a custom HEX had failed so I am left with hacking u-boot and the kernel but it does work.

The final PCB has been designed to fit into a CNC machined acetal frame that is the same size as the HD702 from FriendlyArm, making this a drop-in replacement for the HD702 I was previously using.

Kernel and u-boot Hacking

As this LCD has different timing to any of the existing FriendlyArm LCD’s, it is required to edit the u-boot source code to add the timing and detection. u-boot then passes the LCD type via the command line when it runs the kernel. The kernel has the same timing settings along with other code to configure the display. So, to get this LCD working we must first edit the u-boot source and we locate this file:

board/s5p6818/nanopi3/lcds.c

Open this file and add the following code at the end of the existing structures but just before the HDMI timing structures.

static struct nxp_lcd wvga_axon = {
     .width = 1024,
     .height = 600,
     .p_width = 155,
     .p_height = 87,
     .bpp = 24,
     .freq = 60,
     .timing = {
        .h_fp = 160,
        .h_bp = 160,
        .h_sw = 48,
        .v_fp = 12,
        .v_fpe = 1,
        .v_bp = 23,
        .v_bpe = 1,
        .v_sw = 10,
     },
     .polarity = {
        .rise_vclk = 1,
        .inv_hsync = 0,
        .inv_vsync = 0,
        .inv_vden = 0,
     },
     .gpio_init = hd101_gpio_init,
};

Further down, before the function nanopi2_setup_lcd_by_id(), add the following to the structure called nanopi2_lcd_config. Note the position in the array that you placed this, as this will be what we use to select our LCD. later if we can get FriendlyArm to give us a unique code, we can change the 35 below and then remove the fixed hack we have to do here. 35 was selected to not be in conflict with the other ID’s used by the FriendlyArm LCD range. u-boot will pass the name field to the kernel during the boot sequence.

{  35, "AXONIPS7",&wvga_axon,  128, 1, LCD_RGB  },

Got to the first function in the code called nanopi2_setup_lcd_by_id() and change the code as follows:

int nanopi2_setup_lcd_by_id(int id)
{
    int i;for (i = 0; i < ARRAY_SIZE(nanopi2_lcd_config); i++) {
        if (nanopi2_lcd_config[i].id == id) {
            lcd_idx = i;
            break;
        }
    }
    /* Hard code our LCD at this point */

    lcd_idx = 19;
    i = 19;

    if (i >= ARRAY_SIZE(nanopi2_lcd_config)) {
        /* NOT found */
        return -19;
    }

    return nanopi2_lcd_config[i].id;
}

Note we need to use the index you selected when you inserted the text into the array.

We also need to add a line with lcd_idx=19; to the following function.

int nanopi2_setup_lcd_by_name(char *str)
{
    char *delim;
    int i;
    delim = strchr(str, ',');
    if (delim)
        *delim++ = '\0';

    if (!strncasecmp("HDMI", str, 4)) {
        struct hdmi_config *cfg = &nanopi2_hdmi_config[0];
        struct nxp_lcd *lcd;

        lcd_idx = ARRAY_SIZE(nanopi2_lcd_config) - 1;
        lcd = nanopi2_lcd_config[lcd_idx].lcd;

        for (i = 0; i < ARRAY_SIZE(nanopi2_hdmi_config); i++, cfg++) {
            if (!strcasecmp(cfg->name, str)) {
                lcd->width = cfg->width;
                lcd->height = cfg->height;
                nanopi2_lcd_config[lcd_idx].name = cfg->name;
                goto __ret;
            }
        }
    }

    for (i = 0; i < ARRAY_SIZE(nanopi2_lcd_config); i++) {
        if (!strcasecmp(nanopi2_lcd_config[i].name, str)) {
            lcd_idx = i;
            break;
        }
    }
    /* We have to hack our LCD for selection */
    lcd_idx = 19;

    __ret:
    return 0;
}

Now you can compile u-boot and update this to your board via ADB and fastboot. See the FriendlyArm Wiki on how to put the board into fastboot mode. You will need a serial cable connected to the NanoPC T3 Plus debug UART to do this. With Windows, the following command will copy u-boot to the NanoPC.

fastboot flash bootloader u-boot.bin

Kernel changes

Now we turn to the kernel and locate the same name file in:

arch/arm/plat-s5p6818/nanopi3/lcds.c

Open this file and add the following at the end of the structures and before HDMI as we did above.

static struct nxp_lcd wvga_axon = {
    .width = 1024,
    .height = 600,
    .p_width = 155,
    .p_height = 87,
    .bpp = 24,
    .freq = 60,
    .timing = {
        .h_fp = 160,
        .h_bp = 160,
        .h_sw = 48,
        .v_fp = 12,
        .v_fpe = 1,
        .v_bp = 23,
        .v_bpe = 1,
        .v_sw = 10,
    },
    .polarity = {
        .rise_vclk = 1,
        .inv_hsync = 0,
        .inv_vsync = 0,
        .inv_vden = 0,
    },
    .gpio_init = hd101_gpio_init,
};

Next, we need to add the following like to the same-named structure as before, nanopi2_lcd_config. The code will use the name

{ "AXONIPS7",    &wvga_axon,  CTP_FT5X06  },

We can now build the kernel. u-boot will pass in AXONIPS7 to the kernel and we can configure our display.

After you build the kernel, you need to update your board with this and you can do this from ADB. Boot the board into Android as normal and then using ADB, issue the following commands to copy the kernel to the board. Later you can copy the new uImage file to the Android build and include this as part of the build.

adb shell mount -t ext4 /dev/block/mmcblk0p1 /mnt/media_rw/sdcard1/

adb push uImage /mnt/media_rw/sdcard1/

DO NOT press reset at this point but use ADB reboot to restart the NanoPC or you will brick your board. Now your board should have the timing for the new IPS 1024×600 LCD and welcome to a high brightness display.

The image below shows the HD702 on the left, next to the IPS LCD. The 2 units are running the same software and you can clearly see that the IPS LCD is much brighter.

The image on the right appears blurred due to the higher brightness as I set the camera to adjust to the left display. The white frame is a test. The final builds are black.


Post a Comment