diff --git a/src/gpio.c b/src/gpio.c index b3143b7..74d9974 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -14,10 +14,7 @@ #define GLINE_BUTTON4 27 #define GLINE_BACKLIGHT 18 -#define STATE_BUTTON1 (1 << 0) -#define STATE_BUTTON2 (1 << 1) -#define STATE_BUTTON3 (1 << 2) -#define STATE_BUTTON4 (1 << 3) +#define PWM_BACKLIGHT 0 int Gpio_setup(void) { @@ -37,14 +34,23 @@ int Gpio_setup(void) bcm2835_gpio_set_pud(GLINE_BUTTON4, BCM2835_GPIO_PUD_UP); bcm2835_gpio_fsel(GLINE_BUTTON4, BCM2835_GPIO_FSEL_INPT); - /* TODO: other setup */ + /* configure the PWM for the backlight */ + bcm2835_gpio_set_pud(GLINE_BACKLIGHT, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BACKLIGHT, BCM2835_GPIO_FSEL_ALT5); + bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_2); + bcm2835_pwm_set_mode(PWM_BACKLIGHT, 1, 1); + bcm2835_pwm_set_range(PWM_BACKLIGHT, BACKLIGHT_MAX + 1); + bcm2835_pwm_set_data(PWM_BACKLIGHT, BACKLIGHT_MAX); return 0; } void Gpio_cleanup(void) { - /* TODO: additional cleanup may be required */ + /* close down the backlight lines */ + bcm2835_pwm_set_mode(PWM_BACKLIGHT, 1, 0); + bcm2835_gpio_set_pud(GLINE_BACKLIGHT, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BACKLIGHT, BCM2835_GPIO_FSEL_INPT); /* close down the button lines */ bcm2835_gpio_set_pud(GLINE_BUTTON1, BCM2835_GPIO_PUD_OFF); @@ -74,3 +80,10 @@ int Gpio_read_buttons(void) rc |= STATE_BUTTON4; return rc; } + +void Gpio_set_backlight(unsigned level) +{ + if (level > BACKLIGHT_MAX) + level = BACKLIGHT_MAX; + bcm2835_pwm_set_data(PWM_BACKLIGHT, level); +} diff --git a/src/gpio.h b/src/gpio.h index b70caf0..a46ef22 100644 --- a/src/gpio.h +++ b/src/gpio.h @@ -1,8 +1,16 @@ #ifndef __GPIO_H_INCLUDED #define __GPIO_H_INCLUDED +#define STATE_BUTTON1 (1 << 0) +#define STATE_BUTTON2 (1 << 1) +#define STATE_BUTTON3 (1 << 2) +#define STATE_BUTTON4 (1 << 3) + +#define BACKLIGHT_MAX 1023 + extern int Gpio_setup(void); extern void Gpio_cleanup(void); extern int Gpio_read_buttons(void); +extern void Gpio_set_backlight(unsigned level); #endif /* __GPIO_H_INCLUDED */ diff --git a/src/gpio_old.c b/src/gpio_old.c deleted file mode 100644 index eb332eb..0000000 --- a/src/gpio_old.c +++ /dev/null @@ -1,208 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "log.h" -#include "gpio.h" - -#define GLINE_BUTTON1 17 -#define GLINE_BUTTON2 22 -#define GLINE_BUTTON3 23 -#define GLINE_BUTTON4 27 -#define GLINE_BACKLIGHT 18 - -#define STATE_BUTTON1 (1 << 0) -#define STATE_BUTTON2 (1 << 1) -#define STATE_BUTTON3 (1 << 2) -#define STATE_BUTTON4 (1 << 3) - -#define INPUT 1 /* is really 0 for control register! */ -#define OUTPUT 0 /* is really 1 for control register! */ -#define ALT0 4 - -#define PUD_OFF 0 -#define PUD_DOWN 1 -#define PUD_UP 2 - -#define FSEL_OFFSET 0 -#define SET_OFFSET 7 -#define CLR_OFFSET 10 -#define PINLEVEL_OFFSET 13 -#define EVENT_DETECT_OFFSET 16 -#define RISING_ED_OFFSET 19 -#define FALLING_ED_OFFSET 22 -#define HIGH_DETECT_OFFSET 25 -#define LOW_DETECT_OFFSET 28 -#define PULLUPDN_OFFSET 37 -#define PULLUPDNCLK_OFFSET 38 - -#define PULLUPDN_OFFSET_2711_0 57 -#define PULLUPDN_OFFSET_2711_1 58 -#define PULLUPDN_OFFSET_2711_2 59 -#define PULLUPDN_OFFSET_2711_3 60 -#define PULLUPDN_2711_MAGIC 0x6770696F - -#define BLOCK_SIZE (4*1024) - -static int mem_fd = -1; -static volatile uint32_t *gpio_map = NULL; -static int is_2711 = 0; -static int last_state = 0; - -static void short_wait(void) -{ - int i; - - for (i=0; i<150; i++) - { /* wait 150 cycles */ - asm volatile("nop"); - } -} - -static int setup_the_memmap(void) -{ - if ((mem_fd = open("/dev/gpiomem", O_RDWR|O_SYNC)) > 0) - { - if ((gpio_map = (uint32_t *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0)) == MAP_FAILED) - { - gpio_map = NULL; - close(mem_fd); - Log(LFATAL, "Unable to map /dev/gpiomem (%d)", errno); - return -1; - } - } - - /* ignore the rest of the possibilities for now */ - return 0; -} - -static void set_pullupdn(int gpio, int pud) -{ - if (is_2711) - { /* method for RPi 4 */ - int pullreg = PULLUPDN_OFFSET_2711_0 + (gpio >> 4); - int pullshift = (gpio & 0xF) << 1; - uint32_t pullbits; - unsigned pull = 0; - switch (pud) - { - case PUD_OFF: pull = 0; break; - case PUD_UP: pull = 1; break; - case PUD_DOWN: pull = 2; break; - default: pull = 0; /* keep as "off" */ - } - pullbits = *(gpio_map + pullreg); - pullbits &= ~(3 << pullshift); - pullbits |= (pull << pullshift); - *(gpio_map + pullreg) = pullbits; - } - else - { /* method for older models */ - int clk_offset = PULLUPDNCLK_OFFSET + (gpio / 32); - int shift = gpio % 32; - - if (pud == PUD_DOWN) - { - *(gpio_map + PULLUPDN_OFFSET) = (*(gpio_map + PULLUPDN_OFFSET) & ~3) | PUD_DOWN; - } - else if (pud == PUD_UP) - { - *(gpio_map + PULLUPDN_OFFSET) = (*(gpio_map + PULLUPDN_OFFSET) & ~3) | PUD_UP; - } - else - { /* pud == PUD_OFF */ - *(gpio_map + PULLUPDN_OFFSET) &= ~3; - } - short_wait(); - *(gpio_map + clk_offset) = 1 << shift; - short_wait(); - *(gpio_map + PULLUPDN_OFFSET) &= ~3; - *(gpio_map + clk_offset) = 0; - } -} - -static void setup_gpio_line(int gpio, int direction, int pud) -{ - int offset = FSEL_OFFSET + (gpio / 10); - int shift = (gpio % 10) * 3; - - set_pullupdn(gpio, pud); - if (direction == OUTPUT) - *(gpio_map + offset) = (*(gpio_map + offset) & ~(7 << shift)) | (1 << shift); - else /* direction == INPUT */ - *(gpio_map + offset) = (*(gpio_map + offset) & ~(7 << shift)); -} - -static void setup_gpio_alt5(int gpio) -{ - int offset = FSEL_OFFSET + (gpio / 10); - int shift = (gpio % 10) * 3; - - set_pullupdn(gpio, PUD_OFF); - *(gpio_map + offset) = (*(gpio_map + offset) & ~(7 << shift)) | (2 << shift); -} - -static int gpio_input(int gpio) -{ - int offset, value, mask; - - offset = PINLEVEL_OFFSET + (gpio / 32); - mask = (1 << gpio % 32); - value = *(gpio_map + offset) & mask; - return value; -} - -int Gpio_setup(void) -{ - if (setup_the_memmap() != 0) - return -1; - - is_2711 = (*(gpio_map + PULLUPDN_OFFSET_2711_3) != PULLUPDN_2711_MAGIC); - - setup_gpio_line(GLINE_BUTTON1, INPUT, PUD_UP); - setup_gpio_line(GLINE_BUTTON2, INPUT, PUD_UP); - setup_gpio_line(GLINE_BUTTON3, INPUT, PUD_UP); - setup_gpio_line(GLINE_BUTTON4, INPUT, PUD_UP); - /* TODO: other setup */ - - last_state = 0; - return 0; -} - -void Gpio_cleanup(void) -{ - /* TODO: additional cleanup may be required */ - - setup_gpio_line(GLINE_BUTTON1, INPUT, PUD_OFF); - setup_gpio_line(GLINE_BUTTON2, INPUT, PUD_OFF); - setup_gpio_line(GLINE_BUTTON3, INPUT, PUD_OFF); - setup_gpio_line(GLINE_BUTTON4, INPUT, PUD_OFF); - - if (gpio_map) - { - munmap((void *)gpio_map, BLOCK_SIZE); - gpio_map = NULL; - } - if (mem_fd >= 0) - { - close(mem_fd); - mem_fd = -1; - } -} - -int Gpio_read_buttons(void) -{ - int rc = 0; - - if (gpio_input(GLINE_BUTTON1) == 0) - rc |= STATE_BUTTON1; - if (gpio_input(GLINE_BUTTON2) == 0) - rc |= STATE_BUTTON2; - if (gpio_input(GLINE_BUTTON3) == 0) - rc |= STATE_BUTTON3; - if (gpio_input(GLINE_BUTTON4) == 0) - rc |= STATE_BUTTON4; - return rc; -} diff --git a/src/main.c b/src/main.c index d474fc0..5702dec 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,16 @@ int main(int argc, char *argv[]) case WM_HWBUTTONUP: Log(LINFO, "Button %d was released.", (int)(msg.attrs[0])); + if (msg.attrs[0] == 1) + { + Log(LINFO, "Backlight ON."); + Gpio_set_backlight(BACKLIGHT_MAX); + } + if (msg.attrs[0] == 2) + { + Log(LINFO, "Backlight OFF."); + Gpio_set_backlight(0); + } if (msg.attrs[0] == 4) { Log(LINFO, "Quitting the message loop.");