Driving 4 NOKIA 3310 LCD ( PCD8544) c example



  • Hi,

    Final project will show a couple of temperature/humidity on each screen.
    ( I have 4 little ESP8266 with DHT12 and an Openhab server ).
    First attempt with python and SPI ( hard and bitbanging ) is not working, I do not know why....
    Second attempt with python and direct gpio access were working but very very very slow !
    Final attempt coding in C and direct memory access for gpio works but it takes me times to search and find all these informations. ( example is working for gpio number < 32, other gpio have another base address ).

    So I think this example can perhaps be helpful for someone and can save some times !

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <time.h>
    
    #define GPIO_ADDR 0x10000000 // base address
    #define GPIO_BLOCK 0x6AC // memory block size
    
    #define RST 19
    #define CE1 16
    #define CE2 5
    #define CE3 4
    #define CE4 15
    #define DC 2
    #define DIN 3
    #define CLK 18
    
    unsigned int ASCII[][5] =
    {
         {0x00, 0x00, 0x00, 0x00, 0x00} // 0
        ,{0x00, 0x00, 0x5f, 0x00, 0x00} // 1 !
        ,{0x00, 0x07, 0x00, 0x07, 0x00} // 2 "
        ,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 3 #
        ,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 4 $
        ,{0x23, 0x13, 0x08, 0x64, 0x62} // 5 %
        ,{0x36, 0x49, 0x55, 0x22, 0x50} // 6 &
        ,{0x00, 0x05, 0x03, 0x00, 0x00} // 7 '
        ,{0x00, 0x1c, 0x22, 0x41, 0x00} // 8 (
        ,{0x00, 0x41, 0x22, 0x1c, 0x00} // 9 )
        ,{0x14, 0x08, 0x3e, 0x08, 0x14} // 10 *
        ,{0x08, 0x08, 0x3e, 0x08, 0x08} // 11 +
        ,{0x00, 0x50, 0x30, 0x00, 0x00} // 12 ,
        ,{0x08, 0x08, 0x08, 0x08, 0x08} // 13 -
        ,{0x00, 0x60, 0x60, 0x00, 0x00} // 14 .
        ,{0x20, 0x10, 0x08, 0x04, 0x02} // 15 /
        ,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 16 0
        ,{0x00, 0x42, 0x7f, 0x40, 0x00} // 17 1
        ,{0x42, 0x61, 0x51, 0x49, 0x46} // 18 2
        ,{0x21, 0x41, 0x45, 0x4b, 0x31} // 19 3
        ,{0x18, 0x14, 0x12, 0x7f, 0x10} // 20 4
        ,{0x27, 0x45, 0x45, 0x45, 0x39} // 21 5
        ,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 22 6
        ,{0x01, 0x71, 0x09, 0x05, 0x03} // 23 7
        ,{0x36, 0x49, 0x49, 0x49, 0x36} // 24 8
        ,{0x06, 0x49, 0x49, 0x29, 0x1e} // 25 9
        ,{0x00, 0x36, 0x36, 0x00, 0x00} // 26 :
        ,{0x00, 0x56, 0x36, 0x00, 0x00} // 27 ;
        ,{0x08, 0x14, 0x22, 0x41, 0x00} // 28 <
        ,{0x14, 0x14, 0x14, 0x14, 0x14} // 29 =
        ,{0x00, 0x41, 0x22, 0x14, 0x08} // 30 >
        ,{0x02, 0x01, 0x51, 0x09, 0x06} // 31 ?
        ,{0x32, 0x49, 0x79, 0x41, 0x3e} // 32 @
        ,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 33 A
        ,{0x7f, 0x49, 0x49, 0x49, 0x36} // 34 B
        ,{0x3e, 0x41, 0x41, 0x41, 0x22} // 35 C
        ,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 36 D
        ,{0x7f, 0x49, 0x49, 0x49, 0x41} // 37 E
        ,{0x7f, 0x09, 0x09, 0x09, 0x01} // 38 F
        ,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 39 G
        ,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 40 H
        ,{0x00, 0x41, 0x7f, 0x41, 0x00} // 41 I
        ,{0x20, 0x40, 0x41, 0x3f, 0x01} // 42 J
        ,{0x7f, 0x08, 0x14, 0x22, 0x41} // 43 K
        ,{0x7f, 0x40, 0x40, 0x40, 0x40} // 44 L
        ,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 45 M
        ,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 46 N
        ,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 47 O
        ,{0x7f, 0x09, 0x09, 0x09, 0x06} // 48 P
        ,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 49 Q
        ,{0x7f, 0x09, 0x19, 0x29, 0x46} // 50 R
        ,{0x46, 0x49, 0x49, 0x49, 0x31} // 51 S
        ,{0x01, 0x01, 0x7f, 0x01, 0x01} // 52 T
        ,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 53 U
        ,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 54 V
        ,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 55 W
        ,{0x63, 0x14, 0x08, 0x14, 0x63} // 56 X
        ,{0x07, 0x08, 0x70, 0x08, 0x07} // 57 Y
        ,{0x61, 0x51, 0x49, 0x45, 0x43} // 58 Z
        ,{0x00, 0x7f, 0x41, 0x41, 0x00} // 59 [
        ,{0x02, 0x04, 0x08, 0x10, 0x20} // 60 ¥
        ,{0x00, 0x41, 0x41, 0x7f, 0x00} // 61 ]
        ,{0x04, 0x02, 0x01, 0x02, 0x04} // 62 ^
        ,{0x40, 0x40, 0x40, 0x40, 0x40} // 63 _
        ,{0x00, 0x01, 0x02, 0x04, 0x00} // 64 `
        ,{0x20, 0x54, 0x54, 0x54, 0x78} // 65 a
        ,{0x7f, 0x48, 0x44, 0x44, 0x38} // 66 b
        ,{0x38, 0x44, 0x44, 0x44, 0x20} // 67 c
        ,{0x38, 0x44, 0x44, 0x48, 0x7f} // 68 d
        ,{0x38, 0x54, 0x54, 0x54, 0x18} // 69 e
        ,{0x08, 0x7e, 0x09, 0x01, 0x02} // 70 f
        ,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 71 g
        ,{0x7f, 0x08, 0x04, 0x04, 0x78} // 72 h
        ,{0x00, 0x44, 0x7d, 0x40, 0x00} // 73 i
        ,{0x20, 0x40, 0x44, 0x3d, 0x00} // 74 j
        ,{0x7f, 0x10, 0x28, 0x44, 0x00} // 75 k
        ,{0x00, 0x41, 0x7f, 0x40, 0x00} // 76 l
        ,{0x7c, 0x04, 0x18, 0x04, 0x78} // 77 m
        ,{0x7c, 0x08, 0x04, 0x04, 0x78} // 78 n
        ,{0x38, 0x44, 0x44, 0x44, 0x38} // 79 o
        ,{0x7c, 0x14, 0x14, 0x14, 0x08} // 80 p
        ,{0x08, 0x14, 0x14, 0x18, 0x7c} // 81 q
        ,{0x7c, 0x08, 0x04, 0x04, 0x08} // 82 r
        ,{0x48, 0x54, 0x54, 0x54, 0x20} // 83 s
        ,{0x04, 0x3f, 0x44, 0x40, 0x20} // 84 t
        ,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 85 u
        ,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 86 v
        ,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 87 w
        ,{0x44, 0x28, 0x10, 0x28, 0x44} // 88 x
        ,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 89 y
        ,{0x44, 0x64, 0x54, 0x4c, 0x44} // 90 z
        ,{0x00, 0x08, 0x36, 0x41, 0x00} // 91 {
        ,{0x00, 0x00, 0x7f, 0x00, 0x00} // 92 |
        ,{0x00, 0x41, 0x36, 0x08, 0x00} // 93 }
        ,{0x10, 0x08, 0x08, 0x10, 0x08} // 94 ←
        ,{0x00, 0x06, 0x09, 0x09, 0x06} // 95 →
        ,{0x55, 0xaa, 0x55, 0xaa, 0x55} // 96  rectangle a moitié rempli
        ,{0xff, 0xff, 0xe7, 0xff, 0xff} // 97  rectangle rempli
        ,{0xff, 0x01, 0xfd, 0x05, 0x05} // 98  coin haut gauche double
        ,{0x05, 0x05, 0xfd, 0x01, 0xff} // 99  coin haut droit double
        ,{0xff, 0x80, 0xbf, 0xa0, 0xa0} // 100  coin bas gauche double
        ,{0xa0, 0xa0, 0xbf, 0x80, 0xff} // 101 coin bas droit double
        ,{0x05, 0x05, 0x05, 0x05, 0x05} // 102 ligne haut horizontal double
        ,{0xa0, 0xa0, 0xa0, 0xa0, 0xa0} // 103 ligne bas horizontal double
        ,{0xff, 0x00, 0xff, 0x00, 0x00} // 104 ligne gauche vertical double
        ,{0x00, 0x00, 0xff, 0x00, 0xff} // 105 ligne droit vertical double
        ,{0x7e, 0xdb, 0xdf, 0xdb, 0x7e} // 106 smiley plein
        ,{0x66, 0xef, 0xfb, 0x7e, 0x34} // 107 piaf
        ,{0x00, 0x18, 0x3c, 0x18, 0x00} // 108 piece plein
        ,{0x00, 0x18, 0x24, 0x18, 0x00} // 109 piece vide
        ,{0x18, 0x24, 0x48, 0x24, 0x18} // 110 coeur vide
        ,{0x18, 0x3c, 0x78, 0x3c, 0x18} // 111 coeur plein
        ,{0x80, 0x00, 0x00, 0x00, 0x00} // 112 pixel haut gauche
    };
    
    volatile unsigned long *gpioAddress;
    volatile unsigned char CE[4]={CE1,CE2,CE3,CE4};
    
    int gpioSetup()
    {
        int  m_mfd;
        if ((m_mfd = open("/dev/mem", O_RDWR)) < 0)
        {
            return -1;
        }
        gpioAddress = (unsigned long*)mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, m_mfd, GPIO_ADDR);
        close(m_mfd);
    
        if (gpioAddress == MAP_FAILED)
        {
            return -2;
        }
    
        return 0;
    }
    
    void gpioDirection(int gpio, int direction)
    {
        unsigned long value = *(gpioAddress + 384 + 0); // obtain current settings
        if (direction == 1)
        {
            value |= (1 << gpio); // set bit to 1
        }
        else
        {
            value &= ~(1 << gpio); // clear bit
        }
        *(gpioAddress + 384 + 0) = value;
    }
    
    void gpioSet(int gpio, int value)
    {
        if (value == 0)
        {
            *(gpioAddress + 400 ) = (1 << gpio);
        }
        else
        {
            *(gpioAddress + 396 ) = (1 << gpio);
        }
    }
    
    int gpioRead(int gpio)
    {
        unsigned long value = *(gpioAddress + 392);
        return (value & (1 << gpio));
    }
    
    void spi(unsigned char screen,unsigned char c)
    {
    	gpioSet(CE1,1);
    	gpioSet(CE2,1);
    	gpioSet(CE3,1);
    	gpioSet(CE4,1);
    	gpioSet(CE[screen],0);
    	for (int i=0;i<8;i++)
    	{
    		gpioSet(DIN,(c & (1<< (7-i)))>0);
    		/*if ((c & (1 << (7-i))) > 0)
    				gpioSet(DIN,1);
    		else
    				gpioSet(DIN,0);*/
    		gpioSet(CLK,0);
    		gpioSet(CLK,1);
    	}
    }
    
    void lcd_cmd(unsigned char screen,unsigned char c)
    {
    	gpioSet(DC,0);
    	spi(screen,c);
    }
    
    void lcd_data(unsigned char screen,unsigned char c)
    {
    	gpioSet(DC,1);
    	spi(screen,c);
    }
    
    void gotoXY(unsigned char screen,int x, int y)
    {
    	lcd_cmd(screen,0x80|x);
    	lcd_cmd(screen,0x40|y);
    }
    
    void lcd_character(unsigned char screen,unsigned char c)
    {
    	lcd_data(screen,0x00);
    	for (int i=0;i<5;i++)
    		{
    		lcd_data(screen,ASCII[c-0x20][i]);
    		}
    	lcd_data(screen,0x00);
    }
    
    void init_lcd(unsigned char screen)
    {
    
    
    	lcd_cmd(screen,0x21); // extended mode
    	//lcd_cmd(screen,0xB4); // contrast
    	if (screen==3) lcd_cmd(screen,0xBA); // contrast
    	if (screen==2) lcd_cmd(screen,0xB0); // contrast
    	if (screen==1) lcd_cmd(screen,0xB4); // contrast
    	if (screen==0) lcd_cmd(screen,0xB4); // contrast
    	lcd_cmd(screen,0x05); // start position
    	lcd_cmd(screen,0x40); // start position
    	lcd_cmd(screen,0x14); // bias mode
    	lcd_cmd(screen,0x20); // clear
    	lcd_cmd(screen,0x0C); // normal mode	
    }
    
    void lcd_clear(unsigned char screen)
    {
    	lcd_cmd(screen,0x24);
    	gotoXY(screen,0,0);
    	for (int i=0;i<504;i++)
    		lcd_data(screen,0x00);	
    	lcd_cmd(screen,0x20);
    }
    	
    
    void setup()
    {
    gpioDirection(RST,1);
    gpioDirection(DC,1);
    gpioDirection(CE1,1);
    gpioDirection(CE2,1);
    gpioDirection(CE3,1);
    gpioDirection(CE4,1);
    gpioDirection(DIN,1);
    gpioDirection(CLK,1);
    	
    }
    
     int main()
     {
        system("omega2-ctrl gpiomux set i2c gpio");
    	system("omega2-ctrl gpiomux set uart1 gpio");
    	printf("Hello World!\n");
        printf("We're running a C program on the Omega2!\n");
    	printf("gpiosetup :%d \n",gpioSetup());
    	setup();
    	gpioSet(RST,0);
    	usleep(1000);
    	gpioSet(RST,1);	
    	init_lcd(0);
    	init_lcd(1);
    	init_lcd(2);
    	init_lcd(3);
    	lcd_clear(0);
    	lcd_clear(1);
    	lcd_clear(2);
    	lcd_clear(3);
    	for (int i=0;i<60;i++)
    		{
    		lcd_character(0,0x20+i);
    		lcd_character(1,0x21+i);
    		lcd_character(2,0x22+i);
    		lcd_character(3,0x23+i);
    		}
    
        return 0;
     }
    


Looks like your connection to Community was lost, please wait while we try to reconnect.