Multiple displays using threads
This commit is contained in:
parent
e0f5bc1af3
commit
289a9a1e34
|
@ -1376,6 +1376,11 @@ void u8g2_SetBufferCurrTileRow(u8g2_t *u8g2, uint8_t row) U8G2_NOINLINE;
|
|||
void u8g2_FirstPage(u8g2_t *u8g2);
|
||||
uint8_t u8g2_NextPage(u8g2_t *u8g2);
|
||||
|
||||
// Add ability to set buffer pointer
|
||||
#if defined(__ARM_LINUX__) || defined(unix) || defined(__unix__) || defined(__unix)
|
||||
#define U8G2_USE_DYNAMIC_ALLOC
|
||||
#endif
|
||||
|
||||
#ifdef U8G2_USE_DYNAMIC_ALLOC
|
||||
#define u8g2_SetBufferPtr(u8g2, buf) ((u8g2)->tile_buf_ptr = (buf));
|
||||
#define u8g2_GetBufferSize(u8g2) ((u8g2)->u8x8.display_info->tile_width * 8 * (u8g2)->tile_buf_height)
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
# 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
|
||||
|
||||
# IP Address of your PI
|
||||
PI=pi@raspberrypi.local
|
||||
|
||||
TARGET=u8g2_sw_i2c_thread
|
||||
IDIR= -I ../../../drivers -I ../../../../../csrc -I ../../../port
|
||||
SRCDIR=../../../../../csrc
|
||||
OBJDIR=../../../obj
|
||||
OUTDIR=../../../bin
|
||||
LDIR= -L ../../../lib
|
||||
LIBS= -lm -lpthread
|
||||
|
||||
CFLAGS= $(IDIR) -W -Wall -D __ARM_LINUX__
|
||||
|
||||
OBJ+=u8g2_sw_i2c_thread.o\
|
||||
../../../port/u8g2port.o\
|
||||
../../../drivers/gpio.o\
|
||||
../../../drivers/spi.o\
|
||||
../../../drivers/i2c.o\
|
||||
|
||||
OBJ+=$(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o, $(wildcard $(SRCDIR)/*.c))
|
||||
|
||||
all: directories $(TARGET)
|
||||
|
||||
directories:
|
||||
@mkdir -p $(OBJDIR)
|
||||
@mkdir -p $(OUTDIR)
|
||||
|
||||
$(TARGET):$(OBJ)
|
||||
@echo Generating $(TARGET) ...
|
||||
@$(CC) -o $(OUTDIR)/$@ $(OBJ) $(LDIR) $(LIBS)
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.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)
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Run three displays drawing random lines. This proves you can use U8g2 to run
|
||||
* multiple displays in a thread safe way.
|
||||
*/
|
||||
|
||||
#include "u8g2port.h"
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <errno.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* do_display(void *arg) {
|
||||
display_t disp = *((display_t*) arg);
|
||||
pthread_t id = pthread_self();
|
||||
uint8_t h, w, y1, y2;
|
||||
uint8_t *buf;
|
||||
|
||||
printf("Thread %lu start\n", id);
|
||||
u8g2_t u8g2;
|
||||
// Initialization
|
||||
u8g2_Setup_ssd1306_i2c_128x32_univision_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c,
|
||||
u8x8_arm_linux_gpio_and_delay);
|
||||
// We need unique buffer for each display in order to be thread friendly
|
||||
buf = (uint8_t*)malloc(u8g2_GetBufferSize(&u8g2));
|
||||
u8g2_SetBufferPtr(&u8g2, buf);
|
||||
init_i2c_sw(&u8g2, disp.gpio_chip, disp.scl, disp.sda, disp.res,
|
||||
disp.delay);
|
||||
u8g2_InitDisplay(&u8g2);
|
||||
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;
|
||||
y2 = rand() % h;
|
||||
u8g2_DrawLine(&u8g2, 0, y1, w - 1, y2);
|
||||
u8g2_SendBuffer(&u8g2);
|
||||
sleep_ms(50);
|
||||
}
|
||||
u8g2_SetPowerSave(&u8g2, 1);
|
||||
// Close and deallocate GPIO resources
|
||||
done_user_data(&u8g2);
|
||||
free(buf);
|
||||
printf("Thread %lu end\n", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
pthread_t id_1;
|
||||
pthread_t id_2;
|
||||
pthread_t id_3;
|
||||
|
||||
void *retval_1;
|
||||
void *retval_2;
|
||||
void *retval_3;
|
||||
|
||||
display_t display_1 = { 0, 14, 13, U8X8_PIN_NONE, 0 };
|
||||
display_t display_2 = { 0, 15, 16, U8X8_PIN_NONE, 0 };
|
||||
display_t display_3 = { 0, 198, 199, U8X8_PIN_NONE, 0 };
|
||||
|
||||
pthread_create(&id_1, NULL, &do_display, &display_1);
|
||||
pthread_create(&id_2, NULL, &do_display, &display_2);
|
||||
pthread_create(&id_3, NULL, &do_display, &display_3);
|
||||
|
||||
pthread_join(id_1, (void**) &retval_1);
|
||||
pthread_join(id_2, (void**) &retval_2);
|
||||
pthread_join(id_3, (void**) &retval_3);
|
||||
printf("Done\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* This code should support multiple displays since GPIO pin handles have been
|
||||
* This code supports multiple displays since GPIO pin handles have been
|
||||
* moved into user_data_struct. I2C and SPI handles are global since they can be
|
||||
* shared by multiple devices (think I2C with different address sharing bus).
|
||||
*
|
||||
* So far I have tested this with 3 software I2C displays. See examples.
|
||||
*/
|
||||
|
||||
#include "u8g2port.h"
|
||||
|
|
Loading…
Reference in New Issue