Success with ST7735

Purchased some ST7735 TFT displays off of ebay. I got the ones without the SD card reader. I started with Brainpad code as Gus suggested to someone. I also used Bauland’s N18 code as a check. This link was useful for RoSchmi’s suggestion to use pullups- https://forums.ghielectronics.com/t/windows-iot-and-n18display/19991/12.
I should mention I was working with FEZ and TinyCLR.

It sure is fun when things work.

4 Likes

@Bill_Wyo - its not real without pictorial evidence :wink:

Used a 330 ohm resistor between backlight and power. 10K ohm pull resistors.
The blue object on the right is the backside of the display.
It is my wife’s birthday.

3 Likes

it’s her birthday, and you got the surprise ! (that the screen was so simple to make working) :wink:

1 Like

We have completely changed how graphics work with small displays. You are in for a big surprise in this coming release. So stay tuned and hold tight :sunglasses:

1 Like

Hello everybody
Some examples of student projects made with NetMF. TinyCLR OS is not yet in production in Lycée Pierre Emile Martin - Bourges. :roll_eyes: I can not wait to see TinyCLR OS 1.0.0 preview 2. :heart_eyes:

3 Likes

Hi guys i own (received today after 3 month because of shipping address - KOSOVO i have a difficulty of purchase anywhere except on Ebay) ST7735 and it looks like
image

please can anyone help me to wire this on brainpad or my nucleo f411 port

i tried to link (Nucleo port) but i’m missing something

LED = 3.3V (it seems was backlight)
SCK = D13 (SPI 2)
SDA = D11 (SPI 2 - MISO)
AO seems was DC too (D9 or i should link it to D12)
CS = D10
GND = GND
VCC = 5V

and from seller i’ve got this doc : http://tftdata.tjc1688.com/1.8_SPI/1.8_spi.rar

used GHI/Ardafruit driver and sample (But i could not managed it to work) because of error
Failed allocation for 962 blocks, 15392 bytes

Failed allocation for 962 blocks, 15392 bytes

#### Exception System.OutOfMemoryException - CLR_E_OUT_OF_MEMORY (1) ####
#### Message: 
#### GHIElectronics.TinyCLR.Drawing.BufferDrawTarget::.ctor [IP: 000f] ####
#### GHIElectronics.TinyCLR.Drawing.BufferDrawTargetRgb444::.ctor [IP: 0008] ####
#### TinyCLRApplication1.DrawTarget::.ctor [IP: 0012] ####
#### TinyCLRApplication1.Program::Main [IP: 0068] ####

Exception thrown: ‘System.OutOfMemoryException’ in GHIElectronics.TinyCLR.Drawing.dll
An unhandled exception of type ‘System.OutOfMemoryException’ occurred in GHIElectronics.TinyCLR.Drawing.dll

and tried with Bauland’s driver too but i can not make it work too.

attached code are (with GHI and Bauland example are)
https://drive.google.com/drive/folders/16e5ztcF4FJp-EVI69SvLlKZzVHgCpx0E?usp=sharing

1 Like

You need mosi not miso.

Before you draw to the display and have memory issues, initializing the display should show random pixels. If you do not see anything, it is not initialized correctly.

1 Like

i wrote by mistake MISO -
correct was MOSI (D11 on Nucleo)

but as far i seethere’s AO (DC) ,RESET and (BackLight) on Arduino Examples

and here for DC (i don’t know what to connect there)

since SCK is connected to (D13) like FEZ
SDA (MOSI) D11
CS was connected to D10
Reset was D8
BACKLIGHT (or any other pin with write high) directly to v3.3

all what i show with bouland code it WHITE Screen
but with GHI Code it do not display anything exept that error of memory exception …

(Edit : Arduino tests code work pretty well but i must find reason of not working on TinyCLR and how to use A0 - DC )

1 Like

Here is the code I have on the G30 dev board. I am using our nuget driver.

using GHIElectronics.TinyCLR.Devices.Display;
using GHIElectronics.TinyCLR.Devices.Display.Provider;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.Spi;
using GHIElectronics.TinyCLR.Drawing;
using GHIElectronics.TinyCLR.Pins;
using System;
using System.Drawing;
using System.Threading;
using GHIElectronics.TinyCLR.Drivers.Sitronix.ST7735;

namespace Display {
    public static class Program {
        public static void Main() {

            var spi = SpiController.FromName(G30.SpiBus.Spi2);
            var gpio = GpioController.GetDefault();
            var st7735 = new ST7735Controller(spi.GetDevice(ST7735Controller.GetConnectionSettings(SpiChipSelectType.Gpio, G30.GpioPin.PB1)), gpio.OpenPin(G30.GpioPin.PB0), gpio.OpenPin(G80.GpioPin.PB12));
            st7735.SetDataAccessControl(true, true, false, false);
            st7735.Enable();

            var disp = DisplayController.FromProvider(st7735);
            disp.SetConfiguration(new SpiDisplayControllerSettings { Width = 160, Height = 100 });

            var bl = gpio.OpenPin(G80.GpioPin.PA7);
            bl.Write(GpioPinValue.High);
            bl.SetDriveMode(GpioPinDriveMode.Output);

            var hdc = GraphicsManager.RegisterDrawTarget(new DrawTarget(disp));
            var screen = Graphics.FromHdc(hdc);

            var rnd = new Random();
            var x = 10;
            var y = 10;
            var vx = rnd.Next(20) - 10;
            var vy = rnd.Next(20) - 10;
            var color = new Pen(Color.Green);
            var teal = new SolidBrush(Color.Teal);

            // This is a special built-in font for simple SPI displays
            var font = new Font("GHIMono8x5", 8);

            while (true) {
                x += vx;
                y += vy;

                if (x >= disp.ActiveConfiguration.Width || x < 0) vx *= -1;
                if (y >= disp.ActiveConfiguration.Height || y < 0) vy *= -1;

                screen.Clear(Color.Black);
                screen.DrawString("Hello World!", font, teal, 40, 10);
                screen.DrawEllipse(color, x, y, 10, 10);
                screen.Flush();
                Thread.Sleep(10);
            }
        }
    }

    public sealed class DrawTarget : IDrawTarget {
        private readonly DisplayController parent;
        private readonly byte[] buffer;

        public DrawTarget(DisplayController parent) {
            this.parent = parent;

            this.Width = parent.ActiveConfiguration.Width;
            this.Height = parent.ActiveConfiguration.Height;

            this.buffer = new byte[this.Width * this.Height * 2];
        }

        public int Width { get; }
        public int Height { get; }

        public void Dispose() { }
        public byte[] GetData() => this.buffer;
        public Color GetPixel(int x, int y) => throw new NotSupportedException();

        public void Clear(Color color) => Array.Clear(this.buffer, 0, this.buffer.Length);

        public void Flush() => this.parent.DrawBuffer(0, 0, this.Width, this.Height, this.buffer, 0);

        public void SetPixel(int x, int y, Color color) {
            if (x < 0 || y < 0 || x >= this.Width || y >= this.Height) return;

            var idx = (y * this.Width + x) * 2;
            var clr = color.ToArgb();
            var red = (clr & 0b0000_0000_1111_1111_0000_0000_0000_0000) >> 16;
            var green = (clr & 0b0000_0000_0000_0000_1111_1111_0000_0000) >> 8;
            var blue = (clr & 0b0000_0000_0000_0000_0000_0000_1111_1111) >> 0;

            this.buffer[idx] = (byte)((red & 0b1111_1000) | ((green & 0b1110_0000) >> 5));
            this.buffer[idx + 1] = (byte)(((green & 0b0001_1100) << 3) | ((blue & 0b1111_1000) >> 3));
        }
    }
}
2 Likes

i can confirm work pretty well on BRAINPAD
and no issues (this cheap display) directly from NUGET as you said thanx a lot @Gus_Issa

on Nucleo STM32F411 show me error with buffer …

so now i need to try to recompile new firmware for Nucleo F411 - based on (Brainpad or G30)

source code that worked (or better @Gus_Issa code ) is used as below :

using GHIElectronics.TinyCLR.Devices.Display;
using GHIElectronics.TinyCLR.Devices.Display.Provider;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.Spi;
using GHIElectronics.TinyCLR.Drawing;
using GHIElectronics.TinyCLR.Pins;
using System;
using System.Drawing;
using System.Threading;
using GHIElectronics.TinyCLR.Drivers.Sitronix.ST7735;

namespace TinyCLRApplication1
{
public static class Program
{
public static void Main()
{

        var spi = SpiController.FromName(BrainPadBP2.SpiBus.Spi1);
        var gpio = GpioController.GetDefault();
        var st7735 = new ST7735Controller(spi.GetDevice(ST7735Controller.GetConnectionSettings(
                    SpiChipSelectType.Gpio,BrainPadBP2.GpioPin.PC3)),
                    gpio.OpenPin(BrainPadBP2.GpioPin.PB6),
                      gpio.OpenPin(BrainPadBP2.GpioPin.PA6)
                    ); //D8 on Nucleo F411

        st7735.SetDataAccessControl(true, true, false, false);
        st7735.Enable();

        var disp = DisplayController.FromProvider(st7735);
        disp.SetConfiguration(new SpiDisplayControllerSettings { Width = 160, Height = 100 });

        var bl = gpio.OpenPin(BrainPadBP2.GpioPin.PB7);
        bl.Write(GpioPinValue.High);
        bl.SetDriveMode(GpioPinDriveMode.Output);

        var hdc = GraphicsManager.RegisterDrawTarget(new DrawTarget(disp));
        var screen = Graphics.FromHdc(hdc);

        var rnd = new Random();
        var x = 10;
        var y = 10;
        var vx = rnd.Next(20) - 10;
        var vy = rnd.Next(20) - 10;
        var color = new Pen(Color.Green);
        var teal = new SolidBrush(Color.Teal);

        // This is a special built-in font for simple SPI displays
        var font = new Font("GHIMono8x5", 8);

        while (true)
        {
            x += vx;
            y += vy;

            if (x >= disp.ActiveConfiguration.Width || x < 0) vx *= -1;
            if (y >= disp.ActiveConfiguration.Height || y < 0) vy *= -1;

            screen.Clear(Color.Black);
            screen.DrawString("Hello World!", font, teal, 40, 10);
            screen.DrawEllipse(color, x, y, 10, 10);
            screen.Flush();
            Thread.Sleep(10);
        }
    }
}

public sealed class DrawTarget : IDrawTarget
{
    private DisplayController parent;
    private byte[] buffer;

    public DrawTarget(DisplayController parent)
    {
        this.parent = parent;

        this.Width = parent.ActiveConfiguration.Width;
        this.Height = parent.ActiveConfiguration.Height;

        this.buffer = new byte[this.Width * this.Height * 2];
    }

    public int Width { get; }
    public int Height { get; }

    public void Dispose() { }
    public byte[] GetData() => this.buffer;
    public Color GetPixel(int x, int y) => throw new NotSupportedException();

    public void Clear(Color color) => Array.Clear(this.buffer, 0, this.buffer.Length);

    public void Flush() => this.parent.DrawBuffer(0, 0, this.Width, this.Height, this.buffer, 0);

    public void SetPixel(int x, int y, Color color)
    {
        if (x < 0 || y < 0 || x >= this.Width || y >= this.Height) return;

        var idx = (y * this.Width + x) * 2;
        var clr = color.ToArgb();
        var red = (clr & 0b0000_0000_1111_1111_0000_0000_0000_0000) >> 16;
        var green = (clr & 0b0000_0000_0000_0000_1111_1111_0000_0000) >> 8;
        var blue = (clr & 0b0000_0000_0000_0000_0000_0000_1111_1111) >> 0;

        this.buffer[idx] = (byte)((red & 0b1111_1000) | ((green & 0b1110_0000) >> 5));
        this.buffer[idx + 1] = (byte)(((green & 0b0001_1100) << 3) | ((blue & 0b1111_1000) >> 3));
    }
}

}

ST7735 = BRAINPAD

LED = BrainPadBP2.GpioPin.PB7
SCK = SCK
SDA = MOSI
AO/DC = BrainPadBP2.GpioPin.PB6
RESET = BrainPadBP2.GpioPin.PA6
CS = BrainPadBP2.GpioPin.PC3
GND = GND
VCC = 5V

and schema url : http://files.ghielectronics.com/downloads/Schematics/FEZ/BrainPad%20BP2%20Schematic.pdf

video

thanx a lot

2 Likes

found problem on NUCLEO / PORT
- SPI2 (PA5 - SCK,PA6 - MISO , PA7 - MOSI) / not work
i don’t know reason, since i am not proficient on electronics and no way to make measurement but

- SPI1 (PB3 - SCK,PB4 - MISO , PB5 - MOSI) - work

but one thing i don’t understand is why nucleo with 128 kb ram is not able to run with more ram and this buffer because
it throw buffer exception: on above than
disp.SetConfiguration(new SpiDisplayControllerSettings { Width = 160, Height = 50});

**and G30 with 32kb less ram run with **
disp.SetConfiguration(new SpiDisplayControllerSettings { Width = 160, Height = 100});

or i should need to do changes on scatter file for this !!

1 Like

We have a zip library in our core to compress memory :slight_smile: plus we have some magical powers.

2 Likes

finally i run 160 x 128 - but i need to exclude some things [from Device.h]

//#define INCLUDE_STORAGE
//#define INCLUDE_SIGNALS
//#define INCLUDE_POWER
//#define INCLUDE_DEPLOYMENT

to be able to run this display at that resolutions

and SPI0 work this is used to connect screen but SPI1 do not work on Nucleo 411 (D13=PA5 SCK, D12=PA6 MISO, D11=PA7 MOSI)

if i compile with this declaration

#define INCLUDE_SPI
#define TOTAL_SPI_CONTROLLERS 2
#define STM32F4_SPI_PINS {/* MOSI MISO CLOCK*/
/SPI0/{ { PIN(B, 5), AF(5) }, { PIN(B, 4), AF(5) }, { PIN(B, 3) , AF(5) } },
/SPI1/{ { PIN(A, 7), AF(5) }, { PIN(A, 6), AF(5) }, { PIN(A, 5) , AF(5) } }
}

2 Likes