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;
}