Community

Wiring and using the St7789 display in the Hack Kit

I just received my F7 Microv2.c board and I love it. I have so far gotten multiple LEDs working with a simple program using buttons to affect how they light. That’s just to give an idea of how far I have gotten with the device.

I am trying to use the St7789 display that I received in the kit. I believe I have it wired correctly, but all the examples I find are for the v1 boards. I try to clear and fill with a single color, and all I get are lines and bars.

If you have a good tool for drawing circuits I will draw mine out for you if you want, but it’s like this:

St7789<–>Meadow
gnd<–>gnd
VCC<–>3V3
SCL<–>SCK
SDA<–>COPI
RES<–>D00
DC<–>D01 (marked rx/com4/tx)

Edit: fixed my wiring… not sure why I got it all wrong at first

using Meadow;
using Meadow.Devices;
using Meadow.Foundation;
using Meadow.Foundation.Displays.TftSpi;
using Meadow.Foundation.Leds;
using Meadow.Hardware;
using System;
using System.Threading;

namespace MeadowApplication1
{
    // Change F7MicroV2 to F7Micro for V1.x boards
    public class MeadowApp : App<F7MicroV2, MeadowApp>
    {
        RgbPwmLed onboardLed;
        St7789 display;

        public MeadowApp()
        {
            Initialize();
            CycleColors(1000);
        }

        void Initialize()
        {
            Console.WriteLine("Initialize hardware...");

            onboardLed = new RgbPwmLed(device: Device,
                redPwmPin: Device.Pins.OnboardLedRed,
                greenPwmPin: Device.Pins.OnboardLedGreen,
                bluePwmPin: Device.Pins.OnboardLedBlue,
                3.3f, 3.3f, 3.3f,
                Meadow.Peripherals.Leds.IRgbLed.CommonType.CommonAnode);

            var config = new SpiClockConfiguration(new Meadow.Units.Frequency(6000), SpiClockConfiguration.Mode.Mode3);
            

            display = new St7789(
                  device: Device,
                  spiBus: Device.CreateSpiBus(
                      Device.Pins.SCK, Device.Pins.COPI, Device.Pins.CIPO, config),
                  chipSelectPin: Device.Pins.D02,
                  dcPin: Device.Pins.D01,
                  resetPin: Device.Pins.D00,
                  width: 240, height: 240);
        }   

        void CycleColors(int duration)
        {
            Console.WriteLine("Cycle colors...");
            while (true)
            {
                ShowColor(Color.Blue, duration);
                ShowColor(Color.Cyan, duration);
                ShowColor(Color.Green, duration);
                ShowColor(Color.GreenYellow, duration);
                ShowColor(Color.Yellow, duration);
                ShowColor(Color.Orange, duration);
                ShowColor(Color.OrangeRed, duration);
                ShowColor(Color.Red, duration);
                ShowColor(Color.MediumVioletRed, duration);
                ShowColor(Color.Purple, duration);
                ShowColor(Color.Magenta, duration);
                ShowColor(Color.Pink, duration);
            }

        }

        void ShowColor(Color color, int duration = 1000)
        {
            display.Clear();
            display.Fill(color);
            display.Show();
            Console.WriteLine($"Color: {color}");
            onboardLed.SetColor(color);
            Thread.Sleep(duration);
            onboardLed.Stop();
        }
    }
}

I modified the Hello Meadow example to start displaying colors on this display instead of just the onboard LED.

Any help would be appreciated. Thanks!

Domenic

I figured I would detail what I did to get past this. Bottom line, this is just an issue with the docs being slightly behind a team sprinting at top speed. I could have used MicroGraphics to draw shapes & display images.

Turns out I did have the board wired correctly, but the display must not support filling with a color. If I drew a rectangle that covered the whole screen, it worked fine. I had to tweak the clock numbers to get things moving quicker, too. Ultimately here’s the code I ended up with:

using Meadow;
using Meadow.Devices;
using Meadow.Foundation;
using Meadow.Foundation.Displays.TftSpi;
using Meadow.Foundation.Graphics;
using Meadow.Foundation.Leds;
using Meadow.Hardware;
using Meadow.Units;
using SimpleJpegDecoder;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;

namespace MeadowApplication1
{
    // Change F7MicroV2 to F7Micro for V1.x boards
    public class MeadowApp : App<F7MicroV2, MeadowApp>
    {
        RgbPwmLed onboardLed;
        St7789 display;
        MicroGraphics graphics;
        JpegDecoder decoder;
        Dictionary<string, byte[]> imgCache;

        public MeadowApp()
        {
            Initialize();
            CyicleJpgs();
        }

        void Initialize()
        {
            Console.WriteLine("Initialize hardware...");
            decoder = new JpegDecoder();
            imgCache = new Dictionary<string, byte[]>();
            onboardLed = new RgbPwmLed(device: Device,
                redPwmPin: Device.Pins.OnboardLedRed,
                greenPwmPin: Device.Pins.OnboardLedGreen,
                bluePwmPin: Device.Pins.OnboardLedBlue,
                3.3f, 3.3f, 3.3f,
                Meadow.Peripherals.Leds.IRgbLed.CommonType.CommonAnode);

            var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.ClockPolarity.Inverted, SpiClockConfiguration.ClockPhase.One);

            display = new St7789(Device, Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.COPI, Device.Pins.CIPO, config),
                null, Device.Pins.D01, Device.Pins.D00, 240, 240);

            graphics = new MicroGraphics(display);
            graphics.Rotation = RotationType._270Degrees;
            graphics.Clear();
        }

        void CyicleJpgs()
        {
            Console.WriteLine("Cycle pictures...");
            while (true)
            {
                ShowPic("pic1.jpg");
                ShowPic("pic2.jpg");
                ShowPic("pic3.jpg");
            }

        }

        private void ShowPic(string filename)
        {
            byte[] jpg = null;
            if (!imgCache.TryGetValue(filename, out jpg))
            {
                var jpegData = LoadResource(filename);
                Console.WriteLine("Decoding jpg");
                jpg = decoder.DecodeJpeg(jpegData);
                imgCache[filename] = jpg;
            }
            else
            {
                Console.WriteLine("Cache hit!");
            }
            Console.WriteLine($"Drawing {filename}");

            graphics.Clear(); 
            int x = 0; int y = 0; byte r, g, b;
            for (int i = 0; i < jpg.Length; i += 3)
            {
                r = jpg[i];
                g = jpg[i + 1];
                b = jpg[i + 2];
                graphics.DrawPixel(x, y, Color.FromRgb(r, g, b));
                x++; 
                if (x % decoder.Width == 0)
                {
                    y++; x = 0;
                }
            }
            display.Show();

            Thread.Sleep(10);
        }

        byte[] LoadResource(string filename)
        {
            var assembly = Assembly.GetExecutingAssembly(); 
            var resourceName = $"MeadowApplication1.{filename}";
            Console.WriteLine($"Loading {resourceName}");
            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
            {
                using (var ms = new MemoryStream())
                {
                    Console.WriteLine($"Creating memorystream from stream of size {stream.Length}");
                    stream.CopyTo(ms);
                    Console.WriteLine($"MemoryStream created... creating byte array");
                    return ms.ToArray();
                }
            }
        }
    }

}

So, maybe someone can benefit from this example now. Add the jpg files to your project and mark them as embedded resources in the properties window. The images themselves should be saved at the right size to match your display (mine was 240x240, so I resized the images accordingly). I scaled down the images too in order to make it faster to process. You don’t notice on such a small screen anyway.

Time to move on… if you’re reading this, thanks for being my postmortem rubber duck!

Edit: Credit is due to @Jorge_Ramirez and his tutorial at electromaker for providing the code to display images from jpgs loaded from embedded resources.