Refactor to allow sysfs or charater device for GPIO
This commit is contained in:
parent
8d38070847
commit
a7b8883bc3
|
@ -0,0 +1,29 @@
|
|||
![Title](images/title.png)
|
||||
|
||||
[U8g2 for arm-linux](https://github.com/wuhanstudio/u8g2-arm-linux) has been modified to use
|
||||
[c-periphery](https://github.com/vsergeev/c-periphery) userspace library.
|
||||
* Deprecated sysfs method is no longer used for GPIO thus increasing speed and stability.
|
||||
* GPIO pins can be unallocated which is useful for testing multiple times.
|
||||
* I2C and SPI also use c-periphery.
|
||||
|
||||
## Download U8g2 project
|
||||
* `cd ~/`
|
||||
* `git clone --depth 1 https://github.com/olikraus/u8g2`
|
||||
|
||||
## Modify source as needed
|
||||
Currently GPIO device, I2C and SPI buses are hard coded in u8g2port.c.
|
||||
* Change values as needed
|
||||
* `nano ~/u8g2/sys/arm-linux/port/u8g2port.c`
|
||||
* 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`
|
||||
* Change the DC and RESET as needed (NanoPi Duo here using tx1 and rx1)
|
||||
* `#define OLED_SPI_PIN_RES 199`
|
||||
* `#define OLED_SPI_PIN_DC 198`
|
||||
|
||||
## Build source with GPIO character device
|
||||
* `cd ~/u8g2/sys/arm-linux`
|
||||
* `make CPPFLAGS=-DPERIPHERY_GPIO_CDEV_SUPPORT=1 CC=gcc CXX=g++`
|
||||
|
||||
## Build source with GPIO sysfs
|
||||
* `cd ~/u8g2/sys/arm-linux`
|
||||
* `make CC=gcc CXX=g++`
|
|
@ -34,6 +34,9 @@ int main(void)
|
|||
u8g2_SendBuffer(&u8g2);
|
||||
|
||||
printf("Initialized ...\n");
|
||||
|
||||
sleep_ms(5000);
|
||||
u8g2_SetPowerSave(&u8g2, 1);
|
||||
// Deallocate GPIO pins
|
||||
done_pins();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,13 +9,49 @@ static const char spi_bus[] = "/dev/spidev0.0";
|
|||
static const char gpio_device[] = "/dev/gpiochip0";
|
||||
|
||||
// c-periphery GPIO pins
|
||||
gpio_t *pins[U8X8_PIN_CNT];
|
||||
gpio_t *pins[U8X8_PIN_CNT] = { };
|
||||
|
||||
/**
|
||||
* Initialize pin if not set to U8X8_PIN_NONE.
|
||||
*/
|
||||
void init_pin(u8x8_t *u8x8, int pin) {
|
||||
pins[pin] = gpio_new();
|
||||
if (u8x8->pins[pin] != U8X8_PIN_NONE) {
|
||||
pins[pin] = gpio_new();
|
||||
// Support character device
|
||||
#if PERIPHERY_GPIO_CDEV_SUPPORT
|
||||
if (gpio_open(pins[pin], gpio_device, u8x8->pins[pin], GPIO_DIR_OUT_HIGH)
|
||||
< 0) {
|
||||
fprintf(stderr, "gpio_open(): %s\n", gpio_errmsg(pins[pin]));
|
||||
fprintf(stderr, "gpio_open(): pin %d, %s\n", pin, gpio_errmsg(pins[pin]));
|
||||
}
|
||||
// Support deprecated sysfs
|
||||
#else
|
||||
if (gpio_open_sysfs(pins[pin], u8x8->pins[pin], GPIO_DIR_OUT_HIGH)
|
||||
< 0) {
|
||||
fprintf(stderr, "gpio_open_sysfs(): pin %d, %s\n", pin,
|
||||
gpio_errmsg(pins[pin]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close and free gpio_t.
|
||||
*/
|
||||
void done_pins() {
|
||||
for (int i = 0; i < U8X8_PIN_CNT; ++i) {
|
||||
if (pins[i] != NULL) {
|
||||
gpio_close(pins[i]);
|
||||
gpio_free(pins[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write pin if not set to U8X8_PIN_NONE.
|
||||
*/
|
||||
void write_pin(u8x8_t *u8x8, int pin, int value) {
|
||||
if (u8x8->pins[pin] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[pin], value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,54 +92,26 @@ uint8_t u8x8_arm_linux_gpio_and_delay(u8x8_t *u8x8, uint8_t msg,
|
|||
// printf("SDA:%d, SCL:%d\n", u8x8->pins[U8X8_PIN_I2C_DATA], u8x8->pins[U8X8_PIN_I2C_CLOCK]);
|
||||
|
||||
// SPI Pins
|
||||
if (u8x8->pins[U8X8_PIN_SPI_CLOCK] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_SPI_CLOCK);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_SPI_DATA] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_SPI_DATA);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_CS] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_CS);
|
||||
}
|
||||
init_pin(u8x8, U8X8_PIN_SPI_CLOCK);
|
||||
init_pin(u8x8, U8X8_PIN_SPI_DATA);
|
||||
init_pin(u8x8, U8X8_PIN_CS);
|
||||
|
||||
// 8080 mode
|
||||
// D0 --> spi clock
|
||||
// D1 --> spi data
|
||||
if (u8x8->pins[U8X8_PIN_D2] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_D2);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_D3] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_D3);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_D4] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_D4);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_D5] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_D5);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_D6] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_D6);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_D7] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_D7);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_E] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_E);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_RESET] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_RESET);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_DC] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_DC);
|
||||
}
|
||||
init_pin(u8x8, U8X8_PIN_D2);
|
||||
init_pin(u8x8, U8X8_PIN_D3);
|
||||
init_pin(u8x8, U8X8_PIN_D4);
|
||||
init_pin(u8x8, U8X8_PIN_D5);
|
||||
init_pin(u8x8, U8X8_PIN_D6);
|
||||
init_pin(u8x8, U8X8_PIN_D7);
|
||||
init_pin(u8x8, U8X8_PIN_E);
|
||||
init_pin(u8x8, U8X8_PIN_RESET);
|
||||
init_pin(u8x8, U8X8_PIN_DC);
|
||||
|
||||
// I2c pins
|
||||
if (u8x8->pins[U8X8_PIN_I2C_DATA] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_I2C_DATA);
|
||||
}
|
||||
if (u8x8->pins[U8X8_PIN_I2C_CLOCK] != U8X8_PIN_NONE) {
|
||||
init_pin(u8x8, U8X8_PIN_I2C_CLOCK);
|
||||
}
|
||||
init_pin(u8x8, U8X8_PIN_I2C_DATA);
|
||||
init_pin(u8x8, U8X8_PIN_I2C_CLOCK);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -114,96 +122,68 @@ uint8_t u8x8_arm_linux_gpio_and_delay(u8x8_t *u8x8, uint8_t msg,
|
|||
//case U8X8_MSG_GPIO_SPI_DATA:
|
||||
|
||||
case U8X8_MSG_GPIO_D2: // D2 pin: Output level in arg_int
|
||||
if (u8x8->pins[U8X8_PIN_D2] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_D2], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_D2, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_D3: // D3 pin: Output level in arg_int
|
||||
if (u8x8->pins[U8X8_PIN_D3] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_D3], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_D3, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_D4: // D4 pin: Output level in arg_int
|
||||
if (u8x8->pins[U8X8_PIN_D4] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_D4], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_D4, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_D5: // D5 pin: Output level in arg_int
|
||||
if (u8x8->pins[U8X8_PIN_D5] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_D5], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_D5, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_D6: // D6 pin: Output level in arg_int
|
||||
if (u8x8->pins[U8X8_PIN_D6] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_D6], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_D6, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_D7: // D7 pin: Output level in arg_int
|
||||
if (u8x8->pins[U8X8_PIN_D7] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_D7], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_D7, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_E: // E/WR pin: Output level in arg_int
|
||||
if (u8x8->pins[U8X8_PIN_E] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_E], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_E, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
// arg_int=0: Output low at I2C clock pin
|
||||
// arg_int=1: Input dir with pullup high for I2C clock pin
|
||||
if (u8x8->pins[U8X8_PIN_I2C_CLOCK] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_I2C_CLOCK], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_I2C_CLOCK, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
// arg_int=0: Output low at I2C data pin
|
||||
// arg_int=1: Input dir with pullup high for I2C data pin
|
||||
if (u8x8->pins[U8X8_PIN_I2C_DATA] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_I2C_DATA], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_I2C_DATA, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_SPI_CLOCK:
|
||||
//Function to define the logic level of the clockline
|
||||
if (u8x8->pins[U8X8_PIN_SPI_CLOCK] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_SPI_CLOCK], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_SPI_CLOCK, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_SPI_DATA:
|
||||
//Function to define the logic level of the data line to the display
|
||||
if (u8x8->pins[U8X8_PIN_SPI_DATA] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_SPI_DATA], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_SPI_DATA, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_CS:
|
||||
// Function to define the logic level of the CS line
|
||||
if (u8x8->pins[U8X8_PIN_CS] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_CS], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_CS, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_DC:
|
||||
//Function to define the logic level of the Data/ Command line
|
||||
if (u8x8->pins[U8X8_PIN_DC] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_DC], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_DC, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_RESET:
|
||||
//Function to define the logic level of the RESET line
|
||||
if (u8x8->pins[U8X8_PIN_RESET] != U8X8_PIN_NONE) {
|
||||
gpio_write(pins[U8X8_PIN_RESET], arg_int);
|
||||
}
|
||||
write_pin(u8x8, U8X8_PIN_RESET, arg_int);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -263,7 +243,7 @@ uint8_t u8x8_byte_arm_linux_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
|
|||
|
||||
while (arg_int > 0) {
|
||||
// printf("%.2X ", (uint8_t)*data);
|
||||
tx[0] = (uint8_t) * data;
|
||||
tx[0] = (uint8_t) *data;
|
||||
struct spi_ioc_transfer tr = { .tx_buf = (unsigned long) tx,
|
||||
.rx_buf = (unsigned long) rx, .len = 1, .delay_usecs = 0,
|
||||
.speed_hz = 500000, .bits_per_word = 8, };
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "spi.h"
|
||||
|
||||
void init_pin(u8x8_t *u8x8, int pin);
|
||||
void done_pins();
|
||||
void write_pin(u8x8_t *u8x8, int pin, int value);
|
||||
uint8_t u8x8_arm_linux_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_byte_arm_linux_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_byte_arm_linux_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
|
Loading…
Reference in New Issue