Driving an ‘Adafruit ST7565 Negative LCD Display’ with a Netduino

 I have been waiting for an excuse to use a Nyan Cat in a blog post and the ‘ST7565 Negative LCD Display’ released by Adafruit being equipped with RGB LED backlights was the perfect occasion. After all, RGB LEDs can create a ‘rainbow’, right? All that’s needed is a cat to go with it and Voila!

Since Nyan Cat needed some friends, Hello Kitty and a Space Invader joined in. Eventually, Darth Vader was called in to scare the Nyan Cat away. But I digress…

Connecting the Adafruit ST7565 to the Netduino

The breakout board supporting the LCD display won’t accommodate a standard 0.1″ header unfortunately, so I had to build my own adapter to use it on a breadboard. No big deal but it’s time consuming.

No, really, this is not a squid.

The back of the connector.

The ST7565 is hooked up to the Netduino, ready for development.

The length of the wires that I used for this test were a bit long and limited the communication on the SPI bus to 22 MHz. With shorter connections, this display is capable of supporting much higher speeds, even though the LCD refresh rate can’t keep up at such high speeds and creates ghosting effects between frames.

Pin Connection Map

Here’s the pin mapping I chose from the LCD connector to the Netduino:

  • LCD B-: Netduino D5 (PWM) (LED Blue)
  • LCD G-: Netduino D6 (PWM) (LED Green)
  • LCD A+: Netduino 3.3v (LED anode)
  • LCD R-: Netduino D9 (PWM) (LED Red)
  • LCD GND: Netduino GND
  • LCD VDD: Netduino 3.3v
  • LCD SID: Netduino D11 (SPI MOSI)
  • LCD SCLK: Netduino D13 (SPI CLK)
  • LCD A0: Netduino D7 (Data / Command)
  • LCD /RST: Netduino D4
  • LCD /CS: Netduino D10 (SPI CS) or us Netduino D8 if D10 used for the SD card CS pin

Using the Netduino’s PWM pins is not a requirement: the B-, G- and R- LCD pins can just be connected to the Netduino’s GND pin instead, which results in a bright white backlight.

The C# driver

As always, reading the datasheet for the LCD module is a must before starting on the driver details which is part of the netduino helpers library as usual.

According to the datasheet, the Display Memory Map is divided into 8 pages of 128 bytes each, laid out like this:

There are 2 implications of this memory organization on the Netduino:

  1. The page that needs to be updated must be selected prior to sending a block of 128 bytes over SPI. This requires switching the LCD A0 pin between Command and Data mode constantly, which is limited to ~8.1KHz on the Netduino.
  2. In addition, because SPI.Write() only takes a byte[] or a ushort[] argument, it is necessary to copy the 128 bytes of the page to an intermediate buffer usable by SPI from the buffer actually storing the 128×64 image bitmap. It would be very useful to add relative buffer addressing capability to SPI.Write() in a future version of the .Net MF to avoid shuffling data around like this.

As it turned out, the display frames still get refreshed quickly.

Sex, Lies and Datasheets

In practice, the Display Memory Map pages are not organized as the datasheet describes. Instead, this is how the pages are actually organized:

  • Line zero is in the middle of the display, where page zero starts
  • The image wraps at the bottom of page 3 and continues displaying from the top in page 4
This wacky display memory layout requires maintaining a logical to physical mapping of the pages. Here’s what the final display refresh function looks like:

Re-using the Netduino SSD1306 driver code

The ST7565 Netduino driver is very similar to the SSD1306 Netduino driver: except for the Display Memory Map layout, they’re both monochrome displays and have the same resolutions, therefore it was natural to re-use all the existing drawing routines previously written for the SSD1306. The significant differences are in the Initialize() and Refresh() functions.
In addition, the Netduino ST7565 driver supports these functions:
  • PowerSaveMode(): which places the display in a mode where its current draw is minimal. It is recommended in the datasheet to enter power save mode before switching the display’s power off. A call to Initialize() is required to get out of the power save mode.
  • SetContrast(): adjusts the contrasts of the LCD display.
    • The driver provides three constants to set the contrast to High, Medium and Low
    • Medium is the default

Controlling the backlight

In order to manage the RGB backlight easily, a new RGBLed class was also added to the netduino helpers library. It can be configured to work with RGB LEDs that have a common anode or common cathode configuration as indicated in the constructor of the RGBLed class. To use it, simply call SetColor() with a hex RGB value and an optional delay expressed in milliseconds before the function returns. The class also defines 12 handy common color constants, which is particularly useful in ‘Nyan Cat Animation’ scenarios 😉


The Adafruit ST7565 is a beautiful, crisp, graphic display with pixels large enough to be seen without a magnifying glass (I’m looking at you, SSD1306…) and small enough to display images or multiple lines of text. The built-in RGB LED backlight makes for an effective method of communicating application status conditions at a glance and from a good distance, without having to read text. The screen appears to be made out of thin glass and is fragile, so be sure to handle the display with care: I inadvertently put a small dent in mine while soldering the connector and did not notice it until I turned the display on. My only wish is for the breakout board to support the common 0.1″ header pitch. Finally, because it only takes ~1.1KB to manage the display buffer, it is very usable for Netduino Plus applications without jumping through hoops.

Driving an AdaFruit ST7735 TFT display with a netduino

Color Flow

AdaFruit recently released a sweet little TFT display that I was dying to hook up to a netduino: the display features a resolution of 128*160 pixels, is capable of showing 18-bit colors and has a microSD card reader on the back of the breakout board. As usual, Limor wrote a nicely detailed Arduino tutorial showing how to connect the display and how to write sketches to drive it.

The Arduino driver relies on the ability of the Atmega168/368 to toggle digital lines extremely fast, which does not work well on the netduino due to the latency introduced by the .Net Micro Framework: even when configured to use hardware SPI, the Arduino driver constantly toggles a data/command output line, rspin below, which would be unbearably slow on the netduino if the same method were applied.

You can see an example of this in the drawPixel function:

void ST7735::drawPixel(uint8_t x, uint8_t y,uint16_t color) {
  if ((x >= width) || (y >= height)) return;
  // setup for data
  *portOutputRegister(rsport) |= rspin;
  *portOutputRegister(csport) &= ~ cspin;
  spiwrite(color >> 8);
  *portOutputRegister(csport) |= cspin;

Driving the ST7735 on the netduino

The  netduino has one advantage over the Arduino: it has plenty of RAM. So, instead of toggling I/O lines slowly all the time and using next to zero RAM, the netduino driver allocates a 40K buffer corresponding to the resolution of the display in 12-bit depth colors (16 bits per pixel) and leaves the ST7735 in ‘data’ mode upon initialization.

Drawing always happens on the internal buffer first. Then, whenever the actual display needs refreshing, the display I/O operations are performed using hardware SPI, blasting the entire 40K buffer. It may sound crazy but using this method on the netduino is faster than refreshing a single pixel while toggling an I/O line!

Take a look at the following netduino code to see how this works, compared to the Arduino driver drawPixel funtion above:

private void Initialize() {

Write((byte)LcdCommand.NORON);  // normal display on

SetAddressWindow(0, 0, Width - 1, Height - 1);


private void SetPixel(int x, int y, ushort color) {

if ((x < 0) || (x >= Width) || (y < 0) || (y >= Height)) return;
var index = ((y * Width) + x) * sizeof(ushort);
SpiBuffer[index] = (byte) (color >> 8);
SpiBuffer[++index] = (byte)(color);
public void Refresh() {

The caveat is that allocating a 40K buffer on the netduino does not leave room for much object allocation afterwards. In fact, memory is so tight that OutOfMemory exceptions will be common if not careful and planning your application accordingly.

Before going any further, let’s look at the display in action on the netduino. Please forgive the quality of the video as the camera on my phone doesn’t do justice to the display.

Pretty zippy, huh?

Some hacking required…

As I was trying to get the ST7735 display to work with the netduino, I discovered that the display would stop communicating when configuring SPI to run @ 10 MHz or above.

This is a huge issue for a couple reasons: the speed of the SPI bus determines the display frame rate on the netduino and secondly, mounting a microSD card on the netduino configures SPI to run @ 10 MHz minimum. No matter what. This meant that I could either use the display or the microSD card but never together, preventing scenarios such as loading pictures from the microSD card for display for instance.

Based on previous experience, I began suspecting that the CD4050B logic level-shifter on the ST7735 breakout board was the root cause of the issue and decided to take it out of the equation altogether by shorting out its pins so that it would no longer convert signals. Since the netduino works at a 3.3v logic level, there was no risk of damaging the display driver.

CD4050B - Before hack
CD4050B – Before hack
CD4050B - Before hack
CD4050B – After hack

Sure enough, eliminating the logic-level shifter allowed me to initialize SPI @ 40MHz on the netduino as well as using the the microSD card reader without any issues.

Connecting the AdaFruit ST7735 display to the netduino

  • netduino GND -> ST7735 GND
  • netduino Vcc (3.3v or 5.0v) -> ST7735 Vcc
  • netduino D8 (or other Dx pin) -> ST7735 RESET
  • netduino D7 (or other Dx pin) -> ST7735 D/C
  • netduino D10 -> ST7735 CARD_CS
  • netduino D9 (or other Dx pin) ->ST7735 TFT_CS
  • netduino D11 -> ST7735 MOSI
  • netduino D13 -> ST7735 SCK
  • netduino D12 -> ST7735 MISO

Note that the ST7735 LITE pin can be connected to netduino Vcc (3.3v or 5.0v) or any of the netduino’s PWM pins if you’d like to control the intensity of the display’s back light.

As always, you can find the code as part of the netduino.helpers library.


The AdaFruit ST7735 TFT is a fast, bright and convenient all-in-one display and microSD reader:

Using it on the netduino is sub-optimal for the time being due to the memory requirements involved in making the display work at a decent frame rate but, if used carefully, it is possible to achieve very cool results with it right now. Keep in mind that the memory requirement will eventually go away once the netduino starts supporting native ARM code with .Net Micro Framework 4.2, letting applications toggle I/O lines super fast.

Finally, my only wish is for AdaFruit Industries to consider producing versions of their products without built-in logic level-shifters as they can negatively impact some micro controllers such as the netduino.

Happy hacking!

Color Flow image courtesy of Bartelme Design


Update on 08/23/2011: here’s the same hack applied to the stand-alone version on the adafruit microSD card reader, this time with a 10K resistor between Vcc and Gnd to ensure that the electrical behavior of the chip remains stable.





Using a MAX7219/MAX7221 LED display driver with a netduino

LED Matrix Glow

In a previous post, I described how to drive an LED matrix relying on persistence of vision. While beautifully minimalist, this method has drawbacks: it requires 11 digital pins on the netduino and takes constant CPU cycles to refresh the matrix. This can potentially put tough resource constraints on the rest of the application.

This is where a chip like the MAX7219/MAX7221 LED display driver comes in handy: all you need to do is to send it the data that you want to display over SPI and it will drive LEDs without further involvement from the micro controller.

The chip offers 2 display modes: ‘Decode Mode’ is intended to manage 7 segment displays (plus a dot) and another which displays raw bitmaps instead, perfect for controlling an 8×8 LED matrix.

Multiple MAX72xx chips can be daisy-chained together to form larger displays as well.

Being a popular chip, a great deal has been written about the Max7219 and after you familiarize yourself with the datasheet, you should check out this article on the Arduino Playground and come back here when you’re done.

Connecting the MAX72xx to the netduino

Here are the hardware components that you’ll need:

  • 1 Max72xx chip
  • 1 monochrome LED matrix (for example)
  • 1 Logic-level shifter (DigiKey) (optional: see note below)
  • 1 10K resistor minimum
  • 1 100 uF capacitor
  • 1 0.1 uF ceramic capacitor
  • many hookup wires (as short as possible)

Note: The MAX72xx requires 3.5 volt logic levels minimum and because the netduino uses 3.3 volt logic level on its digital output pins, you may need to place a logic-level shifter between the netduino SPI interface and the Max72xx SPI interface. Check out this article if you’re not sure how this works.

While the Max72xx SPI clock can go up to 10 MHz based,  I was unable to get stable communications above 2 MHz when using the MAX7219 with a logic-level shifter. Without the shifter, SPI @ 10 MHz works flawlessly but because this is out of the chip’s specifications, so your mileage may vary.

The following summarizes the connections. It doesn’t matter which pins you choose on the logic-level shifter provided that they’re matching low-level input/high-level output pins.

  • SPI CLK: netduino pin 13 -> Logic-level shifter -> Max72xx pin 13 (CLK)
  • SPI MOSI: netduino pin 11 -> Logic-level shifter -> Max72xx pin 1 (DIN)
  • SPI CS: netduino pin 10 -> Logic-level shifter -> Max72xx pin 12 (LOAD/CS)

Note: the MAX72xx is extremely sensitive to EMI and power fluctuations. So, be sure to:

  • Place the capacitors as close as possible to the V+ and GND pins of the chip
  • Connect both GND pins to ground
  • Use the shortest possible hookup wires

If EMI is an issue, reducing the speed for the SPI bus and/or using shorter hookup wires may help. If you still have EMI issues, the MAX7221 is likely the right alternative.

Connecting the Max72xx to the LED matrix

The LED matrix that I’m using is wired like this:

LED matrix

Connecting it to the MAX72xx is straight forward:

  • The MAX72xx’s SEG pins correspond to the columns of the LED matrix
  • The MAX72xx’s DIG pins correspond to the rows on the LED matrix

Max72xx -> LED matrix Wiring

Using the netduino.helpers Max72xx C# driver

The C# driver attempts to stick to the Max72xx datasheet as closely as possible. It presents properties matching the various registers of the chip and a simple overloaded ‘Display’ method. Be sure to check out the unit tests in the /Samples for usage details.

Max72xx C# Interface

Action shot

Happy hacking!


Driving an AdaFruit SSD1306 OLED display with a netduino [reloaded]

neduino ssd1306 driver

I ported adapted the Arduino driver written by Limor Fried for the SSD1306 monochrome OLED display to the netduino last week back in January.

At the time, I could not figure out why I was unable to communicate with the display over hardware SPI and had resorted to bit banging data, which was quite slow as you can see:

Last night, I revisited the driver and figured out the issue I had in January. I overhauled the code which now works properly @ 40 MHz using hardware SPI.

Here’s a video of the new driver in action:

Connecting the display to the netduino

SSD1306 VDD ->netduino 3.3 volts power

SSD1306 VBAT ->netduino 3.3 volts power

SSD1306 CS -> netduino D10 (or other Dx pin)

SSD1306 RESET -> netduino D9 (or other Dx pin)

SSD1306 D/C -> netduino D8 (or other Dx pin)

SSD1306 CLK -> netduino D13

SSD1306 DAT -> netduino D11

The driver and the sample code is located at http://netduinohelpers.codeplex.com/

Happy hacking!

Post edited on June 1st 2011.