u8g2 icon indicating copy to clipboard operation
u8g2 copied to clipboard

Support for GP1294ai Display

Open StephiB opened this issue 1 year ago • 51 comments

Is it possible to add the GP1294AI VFD. I've tried to do it by myself but for some reason I can't get it to work. Datasheet: https://drive.google.com/file/d/1AG-xEty9XNawlXCaBtnWZ6uW1tDV3I1M/view?usp=drivesdk

Thanks in advance

StephiB avatar Jul 01 '23 06:07 StephiB

Can you do a test with the other GP12xx constructors? https://github.com/olikraus/u8g2/wiki/u8g2setupcpp#gp1287ai-256x50

What will you see? Which constructor works best? Could you sent an image?

olikraus avatar Jul 01 '23 23:07 olikraus

No function at all, the initial setting of the Gp1247/87 seems to be totally different. Gp1247ai : https://drive.google.com/file/d/1AvN5UNpLIzMM8QzgwikIQiSCDImiOtRc/view?usp=drivesdk Gp1287bi: https://drive.google.com/file/d/1AvAbVk_QmEUBSvrYXAyUfUIyaGBQaEKs/view?usp=drivesdk Gp1294ai: https://drive.google.com/file/d/1AG-xEty9XNawlXCaBtnWZ6uW1tDV3I1M/view?usp=drivesdk

StephiB avatar Jul 02 '23 19:07 StephiB

The main problem is: I am not the author of the GP12x7 displays... let's see...

olikraus avatar Jul 09 '23 13:07 olikraus

I had a deeper look into the specification, but to me it looks like that the documentation is kind of incomplete, for example the description for the 0xe0 cmd seems to be missing. Second problem is, that I am not able to read far east languages.

Maybe @izilzty can give better comments here...

olikraus avatar Jul 09 '23 15:07 olikraus

Hi olikraus, it looks like GP1294 doesn't use 0x0e cmd. I think only needs to modify the init_seq and display_info of GP1287 to make it compatible with GP1294. I'll try to add support for GP1294, if I have time this week.

The datasheet uploaded by @StephiB is not from Futaba, it should be made by someone else, because the display is a custom model, so there is no public datasheet, but the commands in it can still be referred to.

izilzty avatar Jul 09 '23 19:07 izilzty

I'll try to add support for GP1294, if I have time this week.

Thanks, if you could do the init sequence suggestion, then I can do the remaining code changes.

olikraus avatar Jul 09 '23 20:07 olikraus

Fortunately, there are few differences between GP1294 and GP1287, I have finished modifying the code and simply tested it on Arduino & STM32, everything looks fine. I'll open a pull request later.

IMG_0967

The init sequence of GP1294 is basically the same as that of GP1287, except for the commands 0xA0 (Dimming level Setting), 0x55 (Memory Map Clear) and 0xF0 (Display Data Write).

  • For GP1294, the parameter of command 0xA0 needs to send low bytes first.
  • For GP1294, there is no command 0x55 to clear the memory, it must be cleared manually during initialization, otherwise the last screen will be displayed for a short time after the display is only reset but not powered off.
  • For GP1294, the third parameter (Y length for return) of command 0xF0 only supports multiples of 8. If the input value plus 1 is not a multiple of 8, it will be automatically rounded up. For example, if the input value is 0x02, the actual applied parameter is 0x07. This works fine for the U8g2 library, no modification required.

izilzty avatar Jul 10 '23 16:07 izilzty

I can't express how much I'd love the GP1294 to be added to the list of supported displays. I have two of them that sellers sent me in error, that I can't get anything to work with.

The project I am trying is a VFD clock that works with the GP1287... but it does not work with the GP1294 (using the ESP code plus the u8g2 libraries and selecting a GP1287, I get nothing on the display at all.. So I'm really glad to see this brought up.

medtech1 avatar Jul 11 '23 23:07 medtech1

btw, if it helps.. I found some documentation on the GP1294AI and had it translated using google (and copied the html to my own site):

https://redhat.systems/GP1294AI%20256x48%20VFD%20Display%20Module%20%28UNL-200AP-C%29%20-%20Jiali%20Chuang%20EDA%20Open%20Source%20Hardware%20Platform.htm

Also, I noted there is some physical differences between the GP1287 and 1294... I noticed an added switching diode (A7W) on the 1294 just below R11 and to the left of the four capacitors.

medtech1 avatar Jul 11 '23 23:07 medtech1

Hi medtech1, This is an Arduino library I created while testing the PR#2222, which includes support for the GP1294AI. u8g2_arduino_2.35.2.zip You need to remove the current U8g2 library and install this zip library. But it should be noted that it is unofficial, when the official version supports GP1294AI, you can delete this library and reinstall the official version.

GP1294AI supports these constructors:

U8G2_GP1294AI_256X48_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8G2_GP1294AI_256X48_2_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);

U8G2_GP1294AI_256X48_1_2ND_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8G2_GP1294AI_256X48_2_2ND_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8G2_GP1294AI_256X48_F_2ND_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);

U8G2_GP1294AI_256X48_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/13, /* data=*/11, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8G2_GP1294AI_256X48_2_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/13, /* data=*/11, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8G2_GP1294AI_256X48_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/13, /* data=*/11, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);

U8X8_GP1294AI_256X48_4W_HW_SPI u8x8(/* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8X8_GP1294AI_256X48_2ND_4W_HW_SPI u8x8(/* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);
U8X8_GP1294AI_256X48_4W_SW_SPI u8x8(/* clock=*/13, /* data=*/11, /* cs=*/10, /* dc=*/U8X8_PIN_NONE, /* reset=*/8);

izilzty avatar Jul 12 '23 00:07 izilzty

Hi.. thank you!

In the code I was using this line for the GP1287

U8X8_GP1287AI_256X50_4W_SW_SPI u8x8(/* clock=/ 0, / data=/ 2, / cs=/ 14, / dc=/ 4, / reset=*/16);

I think this is the equiv for the GP1294: U8X8_GP1294AI_256X48_4W_SW_SPI u8x8(/* clock=/13, / data=/11, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=*/8);

I have to read the docs to see if the change in numbers is GPIO pin?

Thanks Michelle

On Tue, Jul 11, 2023, at 6:42 PM, izilzty wrote:

Hi medtech1, This is an Arduino library I created while testing the PR#2222 https://github.com/olikraus/u8g2/pull/2222, which includes support for the GP1294AI. u8g2_arduino_2.35.2.zip https://github.com/olikraus/u8g2/files/12022405/u8g2_arduino_2.35.2.zip You need to remove the current U8g2 library and install this zip library. But it should be noted that it is unofficial, when the official version supports GP1294AI, you can delete this library and reinstall the official version.

GP1294AI supports these constructors:

`U8G2_GP1294AI_256X48_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8G2_GP1294AI_256X48_2_4W_HW_SPI u8g2(U8G2_R0, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2(U8G2_R0, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=*/8);

U8G2_GP1294AI_256X48_1_2ND_4W_HW_SPI u8g2(U8G2_R0, /* cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8G2_GP1294AI_256X48_2_2ND_4W_HW_SPI u8g2(U8G2_R0, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8G2_GP1294AI_256X48_F_2ND_4W_HW_SPI u8g2(U8G2_R0, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=*/8);

U8G2_GP1294AI_256X48_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=/13, / data=/11, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8G2_GP1294AI_256X48_2_4W_SW_SPI u8g2(U8G2_R0, / clock=/13, / data=/11, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8G2_GP1294AI_256X48_F_4W_SW_SPI u8g2(U8G2_R0, / clock=/13, / data=/11, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=*/8);

U8X8_GP1294AI_256X48_4W_HW_SPI u8x8(/* cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8X8_GP1294AI_256X48_2ND_4W_HW_SPI u8x8(/ cs=/10, / dc=/U8X8_PIN_NONE, / reset=/8); U8X8_GP1294AI_256X48_4W_SW_SPI u8x8(/ clock=/13, / data=/11, / cs=/10, / dc=/U8X8_PIN_NONE, / reset=*/8); `

— Reply to this email directly, view it on GitHub https://github.com/olikraus/u8g2/issues/2213#issuecomment-1631687348, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADTWN2U2ID4SPJIWVFJSANDXPXXHVANCNFSM6AAAAAAZ2TTKJU. You are receiving this because you commented.Message ID: @.***>

medtech1 avatar Jul 12 '23 01:07 medtech1

Just like other constructor, you only need to change the pin number to the actual use. For example, you can use:

U8X8_GP1294AI_256X48_4W_SW_SPI u8x8(/* clock=*/ 0, /* data=*/ 2, /* cs=*/ 14, /* dc=*/ U8X8_PIN_NONE, /* reset=*/16);

GP1287, GP1247 and GP1294 did not use dc pin, using U8X8_PIN_NONE instead of pin number.

izilzty avatar Jul 12 '23 02:07 izilzty

Hey you rock.. it worked.

Thank you!!

On Tue, Jul 11, 2023, at 8:08 PM, izilzty wrote:

Just like other constructor, you only need to change the pin number to the actual use. For example, you can use:

U8X8_GP1294AI_256X48_4W_SW_SPI u8x8(/* clock=*/ 0, /* data=*/ 2, /* cs=*/ 14, /* dc=*/ U8X8_PIN_NONE, /* reset=*/16); GP1287, GP1247 and GP1294 did not use dc pin, using U8X8_PIN_NONE instead of pin number.

— Reply to this email directly, view it on GitHub https://github.com/olikraus/u8g2/issues/2213#issuecomment-1631742339, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADTWN2WWBEYJVQ2YHJ2UXW3XPYBJ3ANCNFSM6AAAAAAZ2TTKJU. You are receiving this because you commented.Message ID: @.***>

medtech1 avatar Jul 12 '23 02:07 medtech1

Hey izilzty How can I get your email address?

medtech1 avatar Jul 12 '23 02:07 medtech1

I don't know how to find the email address on github. Anyway, my email address is [email protected]

izilzty avatar Jul 12 '23 03:07 izilzty

I am impressed... looks like all is solved.... wow... and there is also a PR. Impressive.

olikraus avatar Jul 12 '23 04:07 olikraus

Yes, and thank you all.

medtech1 avatar Jul 12 '23 14:07 medtech1

Thanks again for the PR. Excellent work :-) I have created beta release 2.35.3

You can download the latest U8g2 beta release from here: https://github.com/olikraus/U8g2_Arduino/archive/master.zip Arduino IDE:

  1. Remove the existing U8g2_Arduino library (https://stackoverflow.com/questions/16752806/how-do-i-remove-a-library-from-the-arduino-environment)
  2. Install the U8g2_Arduino Zip file via Arduino IDE, add zip library menu (https://www.arduino.cc/en/Guide/Libraries).

PlatformIO: platformio.ini (https://docs.platformio.org/en/latest/projectconf/section_env_library.html#lib-deps) should include

lib_deps =
  u8g2=https://github.com/olikraus/U8g2_Arduino/archive/master.zip

olikraus avatar Jul 15 '23 18:07 olikraus

I'm currently having issues with this too and honestly I do not know how to fix this. I'm following this guide here: https://www.instructables.com/Simple-ESP8266-NTP-Clock-on-VFD-Display-VFD256x50-/ The VFD doesn't even power on. Is the pinout for GP1294AI much different than the GP1287? And yes I am using the new library you provided.

4b616c69 avatar Jul 15 '23 19:07 4b616c69

The pin-out on the NTP clock you are working with (per the URL you provided) is the same for both the GP1287 or GP1294:

Conn Pin Color Destination(ESP) CN7 1 Orange 3v3 (3.3v) CN7 2 Green D3 CN7 3 Yellow D5 CN7 4 Violet D4 CN7 5 Grey D0

CN6 1 Black GND CN6 2 White VIN (5v)

You just need to use:

For the GP1287AI use:

U8X8_GP1287AI_256X50_4W_SW_SPI u8x8(/* clock=*/ 0, /* data=*/ 2, /* cs=*/ 14, /* dc=*/ 4, /* reset=*/16);

For the GP1294AI use:

U8X8_GP1294AI_256X48_4W_SW_SPI u8x8(/* clock=*/ 0, /* data=*/ 2, /* cs=*/ 14, /* dc=*/ U8X8_PIN_NONE, /* reset=*/16);

Also, once you program the ESP8266, pull out the USB cable from it and use just the 5v DC (min 1 amp) barrel connector (center positive) to provide power to the VFD. You do not need to feed the ESP with power as shown in the url you provided. The VFD will provide power to the ESP8266 through the jumper wires.

Like this:

http://redhat.systems/vfd/vfd-wiring.png

btw, if the libraries aren't configured correctly it won't power on either. For instance, trying the GP1287AI library/constructs with the GP1294AI will just result in a non-responsive VFD.. it won't light up or anything. My GP1294AI worked right off using the construct above after removing the old library (that did not have GP1294 support) and installing the new one (with GP1294 support).

medtech1 avatar Jul 15 '23 20:07 medtech1

I did not see a pin mapping anywhere and duckduckgo brought me here, so I'm just mentioning it for future search engine enthusiasts:

Pins from the top to the bottom taken from this datasheet:

CN7 1: FILMENT_EN (Filament enable, active HIGH)
CN7 2: SPI CLOCK
CN7 3: SPI Chip Select (active LOW / CSN)
CN7 4: SPI DATA (COPI, LSB First)
CN7 5: RESET (active LOW)
CN7 6: Ground

CN6 1: Ground
CN6 2: 5V output
CN6 3: AINL (audio in left channel)
CN6 4: AINR (audio in right channel)
CN6 5: LII_SW (Light sensor, GL5506 Pull down)
CN6 6: Ground

ccoenen avatar Sep 21 '23 13:09 ccoenen

RESET (grey in the instructable) was tied to D0, which did not work for me. I tied it to 3V3 (or probably any "HIGH" level) and it worked beautifully. Basically, all you need to connect is

  • FILMENT_EN (any high level 3.3V/5V)
  • SPI CLOCK (preferably to the HW SPI of your microcontroller)
  • SPI Chip Select (oddly does not work by simply putting it on LOW level, needs to be connected to a pin as configured by the constructor)
  • SPI DATA (preferably to the HW SPI of your microcontroller)
  • RESET (tied to 3v3, as mentioned in the beginning)
  • Ground (probably any of the three grounds) must be connected as well

Additionally, to have the VFD supply your microcontroller, you can use CN6 pin 2 (5V output).

ccoenen avatar Sep 21 '23 14:09 ccoenen

SPI Chip Select

The chip select usually will put the SPI communication state machine into a defined state. So yes, usually it is required.

Thanks for the updates and notes :-)

duckduckgo brought me here

So, I hope you solved your problems with the help of u8g2

olikraus avatar Sep 21 '23 16:09 olikraus

For now, I'm just playing around with an interesting display. But without u8g2, this would have been much more work. So: Thanks, everyone! :-)

ccoenen avatar Sep 24 '23 18:09 ccoenen

Im also having issues getting this to run on the Pico W and at this point im kinda frustrated and im not sure if its a faulty module or me messing up constantly - anyway i hope someone can help me here and point out where i messed up

This is how i have wired the module up:

VFD PICO Pin 1 Pin 20 (3.3V High) Pin 2 Pin 4 (SCK) Pin 3 Pin 2 (CSn) Pin 4 Pin 5 (TX) Pin 5 Pin 20 (3.3V High) Pin 6 Pin 38 (GND)

And this is the code im using:

#include <sstream>
#include <stdio.h>

//#include "hardware/dma.h"
//#include "hardware/i2c.h"
#include "hardware/spi.h"
//#include "pico/multicore.h"
#include "pico/stdlib.h"
#include "pico/time.h"
#include "pico/util/queue.h"

#include "pico/cyw43_arch.h"

#include <u8g2.h>
//#include "Libraries/u8g2functions.h"


u8g2_t u8g2;
int displayWidth = 256;
int displayHeight = 48;

// ADD THE INIT DISPLAY 
#define PIN_RST 15

#define SPI_PORT spi0
#define PIN_MISO 1
#define PIN_CS 2
#define PIN_SCK 4
#define PIN_MOSI 5
#define SPI_SPEED 4000 * 1000

// Not needed i guess
#define PIN_DC 20

uint8_t u8x8_byte_pico_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
  uint8_t *data;
  switch (msg) {
  case U8X8_MSG_BYTE_SEND:
    data = (uint8_t *)arg_ptr;
    spi_write_blocking(SPI_PORT, data, arg_int);
    break;
  case U8X8_MSG_BYTE_INIT:
    u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
    break;
  case U8X8_MSG_BYTE_SET_DC:
    u8x8_gpio_SetDC(u8x8, arg_int);
    break;
  case U8X8_MSG_BYTE_START_TRANSFER:
    u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
    u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO,u8x8->display_info->post_chip_enable_wait_ns, NULL);
    break;
  case U8X8_MSG_BYTE_END_TRANSFER:
    u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO,
                            u8x8->display_info->pre_chip_disable_wait_ns, NULL);
    u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
    break;
  default:
    return 0;
  }
  return 1;
}

uint8_t u8x8_gpio_and_delay_pico(u8x8_t *u8x8, uint8_t msg,uint8_t arg_int, void *arg_ptr) {
  switch (msg) {
  case U8X8_MSG_GPIO_AND_DELAY_INIT: 
    spi_init(SPI_PORT, SPI_SPEED);
    gpio_set_function(PIN_CS, GPIO_FUNC_SIO);
    gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
    gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
    gpio_init(PIN_RST);
    gpio_init(PIN_DC);
    gpio_init(PIN_CS);
    gpio_set_dir(PIN_RST, GPIO_OUT);
    gpio_set_dir(PIN_DC, GPIO_OUT);
    gpio_set_dir(PIN_CS, GPIO_OUT);
    gpio_put(PIN_RST, 1);
    gpio_put(PIN_CS, 1);
    gpio_put(PIN_DC, 0);
    break;                  
  case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
    sleep_us(arg_int); // 1000 times slower, though generally fine in practice given rp2040 has no `sleep_ns()`
    break;
  case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
    sleep_us(arg_int);
    break;
  case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
    sleep_us(arg_int * 10);
    break;
  case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
    sleep_ms(arg_int);
    break;
  case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int
    gpio_put(PIN_CS, arg_int);
    break;
  case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level
    gpio_put(PIN_DC, arg_int);
    break;
  case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
    gpio_put(PIN_RST, arg_int);  // printf("U8X8_MSG_GPIO_RESET %d\n", arg_int);
    break;
  default:
    u8x8_SetGPIOResult(u8x8, 1); // default return value
    break;
  }
  return 1;
}

void draw_display() {
	char hey[12] = "Hello world";
	u8g2_ClearBuffer(&u8g2);
        u8g2_ClearDisplay(&u8g2);
	u8g2_SetDrawColor(&u8g2, 1);
        u8g2_SetFont(&u8g2, u8g2_font_t0_11_te);
        u8g2_DrawStr(&u8g2, 10, 10, hey);
        u8g2_UpdateDisplay(&u8g2);
}

void display_sequence(){
  u8g2_Setup_gp1294ai_256x48_f(&u8g2, U8G2_R0, u8x8_byte_pico_hw_spi, u8x8_gpio_and_delay_pico);
  u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
  u8g2_SetPowerSave(&u8g2, 0); 
  draw_display();
}



int main()
{
    stdio_init_all;
    sleep_ms(1000);

    // Need to initialize the WIFI Module for the LED to work
    if (cyw43_arch_init() != 0)
    {
        printf("WIFI Module Failed!");
    }

    //multicore_launch_core1(display_core);
    

    while(true)
    {
        //display_sequence();
        printf("MEOW\n");
        sleep_ms(1000);
        cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, true);
        sleep_ms(1000);
        cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, false);
    }
};

Niphoria avatar Oct 03 '23 08:10 Niphoria

Hi Niphoria, I have no experience with Pico, but I think it might be necessary to set the polarity and phase of the SPI. You can try adding the following code after spi_init(SPI_PORT, SPI_SPEED);

spi_set_format(SPI_PORT, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST); //SPI Mode 3

And check the VFD FILMENT_EN and RESET pins, they seem to be connected to the DC pins, which is incorrect. You need to make sure FILMENT_EN is high and connect RESET to the PIN_RST pin of Pico that you defined.

If FILMENT_EN is low, the filament will be turned off and nothing will be displayed on the screen. This is usually used to save power. If RESET is low, the screen enters reset state

izilzty avatar Oct 03 '23 09:10 izilzty

Hi izilzty, I applied your changes but sadly there is no sign of life on the VFD - is there any way i can test if the VFD module is even alive ? I have a power supply that can go up to 19V so i could apply it to the VFD display directly but i dont know if that would even be enough.

here are my code changes

#include <sstream>
#include <stdio.h>

//#include "hardware/dma.h"
//#include "hardware/i2c.h"
#include "hardware/spi.h"
//#include "pico/multicore.h"
#include "pico/stdlib.h"
#include "pico/time.h"
#include "pico/util/queue.h"

#include "pico/cyw43_arch.h"

#include <u8g2.h>
//#include "Libraries/u8g2functions.h"


u8g2_t u8g2;
int displayWidth = 256;
int displayHeight = 48;

// ADD THE INIT DISPLAY 
#define PIN_RST 22

#define SPI_PORT spi0
#define PIN_MISO 1
#define PIN_CS 2
#define PIN_SCK 4
#define PIN_MOSI 5
#define SPI_SPEED 4000 * 1000

// Not needed i guess
#define PIN_DC 20

//////////////////////////////////
// filament
#define FILAMENT 9
//////////////////////////////////

uint8_t u8x8_byte_pico_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
  uint8_t *data;
  switch (msg) {
  case U8X8_MSG_BYTE_SEND:
    data = (uint8_t *)arg_ptr;
    spi_write_blocking(SPI_PORT, data, arg_int);
    break;
  case U8X8_MSG_BYTE_INIT:
    u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
    break;
  case U8X8_MSG_BYTE_SET_DC:
    u8x8_gpio_SetDC(u8x8, arg_int);
    break;
  case U8X8_MSG_BYTE_START_TRANSFER:
    u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
    u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO,u8x8->display_info->post_chip_enable_wait_ns, NULL);
    break;
  case U8X8_MSG_BYTE_END_TRANSFER:
    u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO,
                            u8x8->display_info->pre_chip_disable_wait_ns, NULL);
    u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
    break;
  default:
    return 0;
  }
  return 1;
}

uint8_t u8x8_gpio_and_delay_pico(u8x8_t *u8x8, uint8_t msg,uint8_t arg_int, void *arg_ptr) {
  switch (msg) {
  case U8X8_MSG_GPIO_AND_DELAY_INIT: 
    spi_init(SPI_PORT, SPI_SPEED);
    //////////////////////////////////
    spi_set_format(SPI_PORT, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST); //SPI Mode 3
    //////////////////////////////////
    gpio_set_function(PIN_CS, GPIO_FUNC_SIO);
    gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
    gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
    gpio_init(PIN_RST);
    gpio_init(PIN_DC);
    gpio_init(PIN_CS);
    gpio_set_dir(PIN_RST, GPIO_OUT);
    gpio_set_dir(PIN_DC, GPIO_OUT);
    gpio_set_dir(PIN_CS, GPIO_OUT);
    gpio_put(PIN_RST, 1);
    gpio_put(PIN_CS, 1);
    gpio_put(PIN_DC, 0);
    break;                  
  case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
    sleep_us(arg_int); // 1000 times slower, though generally fine in practice given rp2040 has no `sleep_ns()`
    break;
  case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
    sleep_us(arg_int);
    break;
  case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
    sleep_us(arg_int * 10);
    break;
  case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
    sleep_ms(arg_int);
    break;
  case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int
    gpio_put(PIN_CS, arg_int);
    break;
  case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level
    gpio_put(PIN_DC, arg_int);
    break;
  case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
    gpio_put(PIN_RST, arg_int);  // printf("U8X8_MSG_GPIO_RESET %d\n", arg_int);
    break;
  default:
    u8x8_SetGPIOResult(u8x8, 1); // default return value
    break;
  }
  return 1;
}

void draw_display() {
	char hey[12] = "Hello world";
	u8g2_ClearBuffer(&u8g2);
        u8g2_ClearDisplay(&u8g2);
	u8g2_SetDrawColor(&u8g2, 1);
        u8g2_SetFont(&u8g2, u8g2_font_t0_11_te);
        u8g2_DrawStr(&u8g2, 10, 10, hey);
        u8g2_UpdateDisplay(&u8g2);
}

void display_sequence(){
  u8g2_Setup_gp1294ai_256x48_f(&u8g2, U8G2_R0, u8x8_byte_pico_hw_spi, u8x8_gpio_and_delay_pico);
  u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
  u8g2_SetPowerSave(&u8g2, 0); 
  draw_display();
}



int main()
{
    stdio_init_all;
    sleep_ms(1000);

    // Need to initialize the WIFI Module for the LED to work
    if (cyw43_arch_init() != 0)
    {
        printf("WIFI Module Failed!");
    }

    //multicore_launch_core1(display_core);

    //////////////////////////////////
    gpio_init(FILAMENT);
    gpio_set_dir(FILAMENT, GPIO_OUT);
    gpio_put(FILAMENT, 1);
    //////////////////////////////////
    display_sequence();

    while(true)
    {
        
        printf("MEOW\n");
        sleep_ms(1000);
        cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, true);
        sleep_ms(1000);
        cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, false);
    }
};

Niphoria avatar Oct 03 '23 10:10 Niphoria

After the program runs, if the filament in the display is dark red, it means that the power supply and FILMENT_EN pin are correct, and you may need to check the SPI wiring and program.

If you are not sure the display is alive, you can try running the example program using a 3.3V Arduino board, the example program on the Arduino board should be correct and you can concentrate on troubleshooting hardware issues.

izilzty avatar Oct 03 '23 11:10 izilzty

Helo,

I'm trying in vain to get this display to work with an ESP32 board. Use Arduino IDE to create programs. I think I'm connecting it incorrectly. I have the following board:

https://mischianti.org/2021/02/17/doit-esp32-dev-kit-v1-high-resolution-pinout-and-specs/

I haven't even managed to create a character yet. U8G2 is master installed

power-dodge avatar Oct 14 '23 17:10 power-dodge

Hi, I have this ESP32 board too, maybe you should check the wiring again or try this example:

Wiring:

ESP32 VFD Board
32 FILMENT_EN
18 CLOCK
25 CHIPSELECT
23 DATA
33 RESET
GND GND

Please connect the power supply of the VFD module and ESP32 by yourself, because our boards may be different.

Code:

/*

  U8g2Logo.ino

  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)

  Copyright (c) 2016, [email protected]
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  

*/

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

/*
  U8g2lib Example Overview:
    Frame Buffer Examples: clearBuffer/sendBuffer. Fast, but may not work with all Arduino boards because of RAM consumption
    Page Buffer Examples: firstPage/nextPage. Less RAM usage, should work with all Arduino boards.
    U8x8 Text Only Example: No RAM usage, direct communication with display controller. No graphics, 8x8 Text only.
    
  This is a frame buffer example.    
*/

// Please UNCOMMENT one of the contructor lines below
// U8g2 Contructor List (Frame Buffer)
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8g2setupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected

// U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/25, /* dc=*/U8X8_PIN_NONE, /* reset=*/33);
U8G2_GP1294AI_256X48_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/18, /* data=*/23, /* cs=*/25, /* dc=*/U8X8_PIN_NONE, /* reset=*/33);

// End of constructor list

//#define MINI_LOGO

void setup(void) {
  u8g2.begin();

  pinMode(32, OUTPUT);
  digitalWrite(32, HIGH); // Filament Enable
  // digitalWrite(32, LOW); // Filament Disable

  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH); // Turn on LED on board
}

void drawLogo(void)
{
    u8g2.setFontMode(1);	// Transparent
#ifdef MINI_LOGO

    u8g2.setFontDirection(0);
    u8g2.setFont(u8g2_font_inb16_mf);
    u8g2.drawStr(0, 22, "U");
    
    u8g2.setFontDirection(1);
    u8g2.setFont(u8g2_font_inb19_mn);
    u8g2.drawStr(14,8,"8");
    
    u8g2.setFontDirection(0);
    u8g2.setFont(u8g2_font_inb16_mf);
    u8g2.drawStr(36,22,"g");
    u8g2.drawStr(48,22,"\xb2");
    
    u8g2.drawHLine(2, 25, 34);
    u8g2.drawHLine(3, 26, 34);
    u8g2.drawVLine(32, 22, 12);
    u8g2.drawVLine(33, 23, 12);
#else

    u8g2.setFontDirection(0);
    u8g2.setFont(u8g2_font_inb24_mf);
    u8g2.drawStr(0, 30, "U");
    
    u8g2.setFontDirection(1);
    u8g2.setFont(u8g2_font_inb30_mn);
    u8g2.drawStr(21,8,"8");
        
    u8g2.setFontDirection(0);
    u8g2.setFont(u8g2_font_inb24_mf);
    u8g2.drawStr(51,30,"g");
    u8g2.drawStr(67,30,"\xb2");
    
    u8g2.drawHLine(2, 35, 47);
    u8g2.drawHLine(3, 36, 47);
    u8g2.drawVLine(45, 32, 12);
    u8g2.drawVLine(46, 33, 12);
    
#endif
}

void drawURL(void)
{
#ifndef MINI_LOGO
  u8g2.setFont(u8g2_font_4x6_tr);
  if ( u8g2.getDisplayHeight() < 59 )
  {
    u8g2.drawStr(89,20,"github.com");
    u8g2.drawStr(73,29,"/olikraus/u8g2");
  }
  else
  {
    u8g2.drawStr(1,54,"github.com/olikraus/u8g2");
  }
#endif
}

void loop(void) {
  u8g2.clearBuffer();
  drawLogo();
  drawURL();
  u8g2.sendBuffer();
  digitalWrite(2, !digitalRead(2));
  delay(1000);
}

After download and reset the ESP32, the VFD should show the U8g2 logo and the LED on the ESP32 board will flash.

izilzty avatar Oct 14 '23 19:10 izilzty