Files
bacnet_stack/apps/blinkt/blinkt.c
T
2024-11-01 10:40:53 -05:00

227 lines
5.4 KiB
C

/**
* @file
* @brief API for Blinkt! daughter board for Raspberry Pi
*
* SPDX-License-Identifier: MIT
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "blinkt.h"
#define BLINKT_DEFAULT_BRIGHTNESS 7
#define BLINKT_NUM_LEDS 8
/* GPIO pin numbers */
#define BLINKT_MOSI 23
#define BLINKT_SCLK 24
/* RGBb data for each LED */
static uint32_t Blinkt_LED[BLINKT_NUM_LEDS];
/* handle to the pigpiod */
static int Blinkt_Pi;
#ifdef BUILD_PIPELINE
#define PI_OUTPUT 1
#define gpio_write(a, b, c) printf("gpio_write(%d, %d, %d)\n", a, b, c)
#define set_mode(a, b, c) printf("set_mode(%d, %d, %d)\n", a, b, c)
#define pigpio_start(a, b) printf("pigpio_start(%p, %p)\n", a, b)
#define pigpio_stop(a) printf("pigpio_stop(%d)\n", a)
#else
#include <pigpiod_if2.h>
#endif
/**
* @brief Get the number of LEDS
* @return Number of LEDs
*/
uint8_t blinkt_led_count(void)
{
return BLINKT_NUM_LEDS;
}
/**
* @brief Set all the LEDS to default brightness (7/31)
*/
void blinkt_clear(void)
{
int x;
for (x = 0; x < BLINKT_NUM_LEDS; x++) {
Blinkt_LED[x] = BLINKT_DEFAULT_BRIGHTNESS;
}
}
/**
* @brief Set one LED to specific RGB color
* @param led index 0..#BLINKT_NUM_LEDS
* @param r color red from 0..255
* @param g color green from 0..255
* @param b color blue from 0..255
*/
void blinkt_set_pixel(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
{
if (led >= BLINKT_NUM_LEDS) {
return;
}
Blinkt_LED[led] = blinkt_rgbb(r, g, b, Blinkt_LED[led] & 0x1F);
}
/**
* @brief Set one LED to specific intensity
* @param led index 0..#BLINKT_NUM_LEDS
* @param brightness intensity from 0..31, 0=OFF, 1=dimmest, 31=brightest
*/
void blinkt_set_pixel_brightness(uint8_t led, uint8_t brightness)
{
if (led >= BLINKT_NUM_LEDS) {
return;
}
Blinkt_LED[led] = (Blinkt_LED[led] & 0xFFFFFF00) | (brightness & 0x1F);
}
/**
* @brief Set one LED to RGB color and brightness
* @param led index 0..#BLINKT_NUM_LEDS
* @param color encoded as 32-bit RGBb (red | green | blue | brightness)
*/
void blinkt_set_pixel_uint32(uint8_t led, uint32_t color)
{
if (led >= BLINKT_NUM_LEDS) {
return;
}
Blinkt_LED[led] = color;
}
/**
* @brief Encode RGB color and brightness into 32-bit RGBb
* @param r color red from 0..255
* @param g color green from 0..255
* @param b color blue from 0..255
* @param brightness intensity from 0..31, 0=OFF, 1=dimmest, 31=brightest
* @return color encoded as 32-bit RGBb (red | green | blue | brightness)
*/
uint32_t blinkt_rgbb(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness)
{
uint32_t result = 0;
result = (brightness & 0x1F);
result |= ((uint32_t)r << 24);
result |= ((uint32_t)g << 16);
result |= ((uint16_t)b << 8);
return result;
}
/**
* @brief Encode RGB color at default brightness into 32-bit RGBb
* @param r color red from 0..255
* @param g color green from 0..255
* @param b color blue from 0..255
* @return color encoded as 32-bit RGBb (red | green | blue | brightness)
*/
uint32_t blinkt_rgb(uint8_t r, uint8_t g, uint8_t b)
{
return blinkt_rgbb(r, g, b, BLINKT_DEFAULT_BRIGHTNESS);
}
/**
* @brief Write a byte via shift register to LEDs
* @param byte to be written
*/
inline static void write_byte(uint8_t byte)
{
int n;
for (n = 0; n < 8; n++) {
gpio_write(Blinkt_Pi, BLINKT_MOSI, (byte & (1 << (7 - n))) > 0);
gpio_write(Blinkt_Pi, BLINKT_SCLK, 1);
gpio_write(Blinkt_Pi, BLINKT_SCLK, 0);
}
}
/**
* @brief Shift LED values to the actual LEDs via shift registers
*/
void blinkt_show(void)
{
int x;
write_byte(0);
write_byte(0);
write_byte(0);
write_byte(0);
for (x = 0; x < BLINKT_NUM_LEDS; x++) {
write_byte(0xE0 | (Blinkt_LED[x] & 0x1F));
write_byte((Blinkt_LED[x] >> 8) & 0xFF);
write_byte((Blinkt_LED[x] >> 16) & 0xFF);
write_byte((Blinkt_LED[x] >> 24) & 0xFF);
}
write_byte(0xff);
}
/**
* @brief Disable the GPIO hardware to the Blinkt! board
*/
void blinkt_stop(void)
{
/* Disconnect from local Pi. */
pigpio_stop(Blinkt_Pi);
printf("PiGPIO stopped\n");
}
/**
* @brief Initialize the GPIO hardware for the Blinkt! board
*/
int blinkt_init(void)
{
char *optHost = NULL;
char *optPort = NULL;
/* Connect to local Pi. */
Blinkt_Pi = pigpio_start(optHost, optPort);
if (Blinkt_Pi < 0) {
perror("PiGPIO failed to start!");
return -1;
}
set_mode(Blinkt_Pi, BLINKT_MOSI, PI_OUTPUT);
gpio_write(Blinkt_Pi, BLINKT_MOSI, 0);
set_mode(Blinkt_Pi, BLINKT_SCLK, PI_OUTPUT);
gpio_write(Blinkt_Pi, BLINKT_SCLK, 0);
blinkt_clear();
printf("PiGPIO started\n");
return 0;
}
static int test_column = 0;
static int test_z, test_y;
/**
* @brief Test the Blinkt! board with a simple changing pattern
*/
void blinkt_test_task(void)
{
for (test_z = 0; test_z < BLINKT_NUM_LEDS; test_z++) {
switch (test_column) {
case 0:
blinkt_set_pixel_uint32(test_z, blinkt_rgb(test_y, 0, 0));
break;
case 1:
blinkt_set_pixel_uint32(test_z, blinkt_rgb(0, test_y, 0));
break;
case 2:
blinkt_set_pixel_uint32(test_z, blinkt_rgb(0, 0, test_y));
break;
default:
break;
}
}
blinkt_show();
test_y += 1;
if (test_y > 254) {
test_column++;
}
test_column %= 3;
test_y %= 255;
}