This commit is contained in:
kraus 2021-11-22 07:56:27 +01:00
commit 0c82f8cc5e
9 changed files with 158 additions and 12 deletions

View File

@ -4,6 +4,8 @@
* GPIO, I2C and SPI can be closed and unallocated.
* Overall performance should be better.
* Run as non-root user.
* Thread safe and multiple display capable.
* For Java check out [Java U8g2](https://github.com/sgjava/java-u8g2) which uses arm-linux port.
## Non-root access
If you want to access devices without root do the following (you can try udev
@ -25,7 +27,7 @@ chmod -R ug+rw /dev/spidev*</code></pre>
## Modify source as needed
* Change example (SPI 4 wire hardware for instance)
* `nano ~/u8g2/sys/arm-linux/examples/c-examples/u8g2_4wire_hw_spi\u8g2_4wire_hw_spi.c`
* `nano ~/u8g2/sys/arm-linux/examples/c-examples/u8g2_4wire_hw_spi/u8g2_4wire_hw_spi.c`
* Change the GPIO chip number (0 uses /dev/gpiochip0)
* `#define GPIO_CHIP_NUM 0`
* Change the SPI bus number (0x10 uses /dev/spidev1.0)
@ -43,3 +45,12 @@ chmod -R ug+rw /dev/spidev*</code></pre>
* `cd ~/u8g2/sys/arm-linux`
* `make clean`
* `make CC=gcc CXX=g++`
## Multiple display example using pthreads
After building U8g2 using instructions above.
* `nano ~/u8g2/sys/arm-linux/examples/c-examples/u8g2_sw_i2c_thread/u8g2_sw_i2c_thread.c`
* Change display_1, display_2 and display_3 variables. Obviously you can have only two displays, so modify the code accordingly. This uses software I2C since most SBCs will not have three hardware I2C controllers and changing addresses on displays usually required soldering resistor.
* `cd ~/u8g2/sys/arm-linux`
* `make CPPFLAGS=-DPERIPHERY_GPIO_CDEV_SUPPORT=1 CC=gcc CXX=g++`
* `cd bin`
* `./u8g2_sw_i2c_thread`

View File

@ -29,7 +29,7 @@ void* do_display(void *arg) {
printf("Thread %lu start\n", id);
u8g2_t u8g2;
// Initialization
// CHange setup function call as needed to support your display
u8g2_Setup_ssd1306_i2c_128x32_univision_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c,
u8x8_arm_linux_gpio_and_delay);
init_i2c_sw(&u8g2, disp.gpio_chip, disp.scl, disp.sda, disp.res,
@ -38,7 +38,6 @@ void* do_display(void *arg) {
h = u8g2_GetDisplayHeight(&u8g2);
w = u8g2_GetDisplayWidth(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr);
for (int i = 1; i < 200; ++i) {
u8g2_ClearBuffer(&u8g2);
y1 = rand() % h;

View File

@ -0,0 +1,72 @@
# Chosse proper compiler for your PI
# NanoPi: arm-linux-gnueabi-gcc
# Raspberry Pi Zero: arm-linux-gnueabi-gcc
# Raspberry Pi 2: arm-linux-gnueabihf-gcc
# OrangePi Zero: arm-linux-gnueabihf-gcc
# NanoPi NEO: arm-linux-gnueabihf-gcc
# NanoPi NEO Plus 2: arm-linux-gnueabihf-gcc
# C-SKY Linux: csky-linux-gcc
CC=arm-linux-gnueabi-gcc
CXX=arm-linux-gnueabi-g++
# IP Address of your PI
PI=pi@raspberrypi.local
TARGET=u8g2_sw_i2c_thread_cpp
IDIR= -I ../../../drivers -I ../../../../../csrc -I ../../../port
CSRCDIR=../../../../../csrc
CXXSRCDIR=../../../port
OBJDIR=../../../obj
OUTDIR=../../../bin
LDIR= -L ../../../lib
LIBS= -lm -lpthread
CFLAGS= $(IDIR) -W -Wall -D __ARM_LINUX__
OBJ+=u8g2_sw_i2c_thread.cpp.o\
../../../port/u8g2port.o\
../../../drivers/gpio.o\
../../../drivers/spi.o\
../../../drivers/i2c.o\
$(OBJDIR)/Print.cpp.o\
$(OBJDIR)/U8x8lib.cpp.o\
$(OBJDIR)/U8g2lib.cpp.o\
OBJ+=$(patsubst $(CSRCDIR)/%.c,$(OBJDIR)/%.o, $(wildcard $(CSRCDIR)/*.c))
all: directories $(TARGET)
directories:
@mkdir -p $(OBJDIR)
@mkdir -p $(OUTDIR)
$(TARGET):$(OBJ)
@echo Generating $(TARGET) ...
@$(CXX) -o $(OUTDIR)/$@ $(OBJ) $(LDIR) $(LIBS)
u8g2_sw_i2c_thread.cpp.o: u8g2_sw_i2c_thread.cpp
$(CXX) -c -o $@ $< $(CFLAGS) $(LDIR) $(LIBS)
$(OBJDIR)/%.cpp.o: $(CXXSRCDIR)/%.cpp
$(CXX) -c -o $@ $< $(CFLAGS) $(LDIR) $(LIBS)
$(OBJDIR)/%.o: $(CSRCDIR)/%.c
$(CC) -c -o $@ $< $(CFLAGS) $(LDIR) $(LIBS)
clean:
@echo RM -rf $(OBJDIR)/
@rm -rf $(OBJ)
@rm -rf $(OBJDIR)
@echo RM -rf $(OUTDIR)/
@rm -rf $(OUTDIR)
upload:
scp $(OUTDIR)/$(TARGET) $(PI):~/
run:
ssh $(PI)

View File

@ -0,0 +1,67 @@
#include <U8g2lib.h>
#include <pthread.h>
// Encapsulate each thread's info
struct display {
uint8_t gpio_chip;
uint8_t scl;
uint8_t sda;
uint8_t res;
unsigned long delay;
};
typedef struct display display_t;
/*
* Draw random lines with 50 ms delay.
*/
void * doDisplay(void *arg) {
display_t disp = *((display_t*) arg);
pthread_t id = pthread_self();
uint8_t h, w, y1, y2;
printf("Thread %lu start\n", id);
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, disp.scl, disp.sda,
U8X8_PIN_NONE);
u8g2.initI2cSw(disp.gpio_chip, disp.scl, disp.sda, disp.res, disp.delay);
u8g2.begin();
h = u8g2.getDisplayHeight();
w = u8g2.getWidth();
for (int i = 1; i < 200; ++i) {
u8g2.clearBuffer();
y1 = rand() % h;
y2 = rand() % h;
u8g2.drawLine(0, y1, w - 1, y2);
u8g2.sendBuffer();
u8g2.sleepMs(50);
}
u8g2.sleepOn();
u8g2.doneUserData();
printf("Thread %lu end\n", id);
return NULL;
}
int main(void) {
pthread_t id1;
pthread_t id2;
pthread_t id3;
void *retVal1;
void *retVal2;
void *retVal3;
display_t display1 = { 0, 14, 13, U8X8_PIN_NONE, 0 };
display_t display2 = { 0, 15, 16, U8X8_PIN_NONE, 0 };
display_t display3 = { 0, 198, 199, U8X8_PIN_NONE, 0 };
pthread_create(&id1, NULL, &doDisplay, &display1);
pthread_create(&id2, NULL, &doDisplay, &display2);
pthread_create(&id3, NULL, &doDisplay, &display3);
pthread_join(id1, (void**) &retVal1);
pthread_join(id2, (void**) &retVal2);
pthread_join(id3, (void**) &retVal3);
printf("Done\n");
return 0;
}

View File

@ -209,11 +209,10 @@ public:
u8g2_SetDisplayRotation(&u8g2, u8g2_cb);
}
bool begin(void) {
void begin(void) {
initDisplay();
clearDisplay();
setPowerSave(0);
return 1;
sleepOff();
}
void beginSimple(void) {
@ -224,7 +223,7 @@ public:
#ifdef U8X8_USE_PINS
/* use U8X8_PIN_NONE if a pin is not required */
bool begin(uint8_t menu_select_pin, uint8_t menu_next_pin,
void begin(uint8_t menu_select_pin, uint8_t menu_next_pin,
uint8_t menu_prev_pin, uint8_t menu_up_pin = U8X8_PIN_NONE,
uint8_t menu_down_pin = U8X8_PIN_NONE, uint8_t menu_home_pin =
U8X8_PIN_NONE) {
@ -234,7 +233,7 @@ public:
setMenuUpPin(menu_up_pin);
setMenuDownPin(menu_down_pin);
setMenuHomePin(menu_home_pin);
return begin();
begin();
}
#endif
@ -615,16 +614,14 @@ public:
}
/* connect to u8g2, draw to u8g2 whenever required */
bool begin(class U8G2 &u8g2, uint8_t width, uint8_t height, uint8_t *buf) {
void begin(class U8G2 &u8g2, uint8_t width, uint8_t height, uint8_t *buf) {
u8log_Init(&u8log, width, height, buf);
u8log_SetCallback(&u8log, u8log_u8g2_cb, u8g2.getU8g2());
return true;
}
/* disconnected version, manual redraw required */
bool begin(uint8_t width, uint8_t height, uint8_t *buf) {
void begin(uint8_t width, uint8_t height, uint8_t *buf) {
u8log_Init(&u8log, width, height, buf);
return true;
}
void setLineHeightOffset(int8_t line_height_offset) {