olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
4.91k stars 1.03k forks source link

ST7920 parallel 8080 not working #2399

Open archwills opened 3 months ago

archwills commented 3 months ago

m working on a project that uses st7920 and atmega328p. Currently im trying to set up the st7920 lcd display in 8-bit parallel (8080) modifying the example code in the u8g2 library and trying to print something on to the screen. I've seen https://github.com/olikraus/u8g2/issues/90 and see that the CS has to set to U8x8_PIN_NONE, but a bit unsure how to do this as the post was from a few years ago and the library seems to have changed a lot. Any help apreaciated, thanks.

`#include <avr/io.h>

include

include <util/delay.h>

define DISPLAY_DATA_DIR DDRD

define DISPLAY_DATA_PORT PORTD

define DISPLAY_DATA_PIN0 0

define DISPLAY_DATA_PIN1 1

define DISPLAY_DATA_PIN2 2

define DISPLAY_DATA_PIN3 3

define DISPLAY_DATA_PIN4 4

define DISPLAY_DATA_PIN5 5

define DISPLAY_DATA_PIN6 6

define DISPLAY_DATA_PIN7 7

define DISPLAY_DC_DIR DDRB

define DISPLAY_DC_PORT PORTB

define DISPLAY_DC_PIN 2

define DISPLAY_RESET_DIR DDRB

define DISPLAY_RESET_PORT PORTB

define DISPLAY_RESET_PIN 0

define DISPLAY_E_DIR DDRB

define DISPLAY_E_PORT PORTB

define DISPLAY_E_PIN 5

define P_CPU_NS (1000000000UL / F_CPU)

u8g2_t u8g2;

uint8_t u8x8_avr_delay(u8x8_t u8x8, uint8_t msg, uint8_t arg_int, void arg_ptr) { uint8_t cycles;

switch(msg)
{
    case U8X8_MSG_DELAY_NANO:     // delay arg_int * 1 nano second
        // At 20Mhz, each cycle is 50ns, the call itself is slower.
        break;
    case U8X8_MSG_DELAY_100NANO:    // delay arg_int * 100 nano seconds
        // Approximate best case values...

define CALL_CYCLES 26UL

define CALC_CYCLES 4UL

define RETURN_CYCLES 4UL

define CYCLES_PER_LOOP 4UL

        cycles = (100UL * arg_int) / (P_CPU_NS * CYCLES_PER_LOOP);

        if(cycles > CALL_CYCLES + RETURN_CYCLES + CALC_CYCLES) 
            break;

        __asm__ __volatile__ (
        "1: sbiw %0,1" "\n\t" // 2 cycles
        "brne 1b" : "=w" (cycles) : "0" (cycles) // 2 cycles
        );
        break;
    case U8X8_MSG_DELAY_10MICRO:    // delay arg_int * 10 micro seconds
        for(int i=0 ; i < arg_int ; i++)
            _delay_us(10);
        break;
    case U8X8_MSG_DELAY_MILLI:      // delay arg_int * 1 milli second
        for(int i=0 ; i < arg_int ; i++)
            _delay_ms(1);
        break;
    default:
        return 0;
}
return 1;

}

uint8_t u8x8_avr_gpio_and_delay(u8x8_t u8x8, uint8_t msg, uint8_t arg_int, void arg_ptr) { // Re-use library for delays

switch(msg)
{
    case U8X8_MSG_GPIO_AND_DELAY_INIT:  // called once during init phase of u8g2/u8x8

        DISPLAY_DATA_DIR |= 0xFF;
        DISPLAY_DC_DIR |= 1<<DISPLAY_DC_PIN;
        DISPLAY_RESET_DIR |= 1<<DISPLAY_RESET_PIN;
        break;              // can be used to setup pins
    case U8X8_MSG_GPIO_D0:        // Clock pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN0);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN0);
        break;
    case U8X8_MSG_GPIO_D1:        // MOSI pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN1);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN1);
        break;
    case U8X8_MSG_GPIO_D2:        // MOSI pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN2);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN2);
        break;
    case U8X8_MSG_GPIO_D3:        // MOSI pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN3);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN3);
        break;  
    case U8X8_MSG_GPIO_D4:        // MOSI pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN4);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN4);
        break;
    case U8X8_MSG_GPIO_D5:        // MOSI pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN5);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN5);
        break;
    case U8X8_MSG_GPIO_D6:        // MOSI pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN6);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN6);
        break;
    case U8X8_MSG_GPIO_D7:        // MOSI pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN7);
        else
            DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN7);
        break;
    case U8X8_MSG_GPIO_E:
        if(arg_int)
            DISPLAY_E_PORT |= (1<<DISPLAY_E_PIN);
        else;
            DISPLAY_E_PORT &= ~(1<<DISPLAY_E_PIN);
        break;
    case U8X8_MSG_GPIO_DC:        // DC (data/cmd, A0, register select) pin: Output level in arg_int
        if(arg_int)
            DISPLAY_DC_PORT |= (1<<DISPLAY_DC_PIN);
        else
            DISPLAY_DC_PORT &= ~(1<<DISPLAY_DC_PIN);
        break;
    case U8X8_MSG_GPIO_RESET:     // Reset pin: Output level in arg_int
        if(arg_int)
            DISPLAY_RESET_PORT |= (1<<DISPLAY_RESET_PIN);
        else
            DISPLAY_RESET_PORT &= ~(1<<DISPLAY_RESET_PIN);
        break;
    default:
        if (u8x8_avr_delay(u8x8, msg, arg_int, arg_ptr))    // check for any delay msgs
            return 1;
        u8x8_SetGPIOResult(u8x8, 1);      // default return value
        break;
}
return 1;

}

int main(void) {

u8g2_Setup_st7920_p_128x64_f( &u8g2, U8G2_R0, u8x8_byte_8bit_8080mode, u8x8_avr_gpio_and_delay );
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);

u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2, u8g2_font_6x13_tf);
u8g2_DrawStr(&u8g2, 0, 16, "ENGG2800 Team Project 1");

while(1){
}

}`

olikraus commented 3 months ago

Maybe this helps: https://github.com/olikraus/u8g2/wiki/gallery#26-nov-2016-st7920-128x64-lcd-in-8080-parallel-mode

RW of the display has to be connected to GND, PSB has to be connected to 5V and I think the VarPot needs to be connected correctly.

Maybe you can post a wiring table for your display for crosscheck,