113 lines
2.8 KiB
C
113 lines
2.8 KiB
C
/*
|
|
* vim: sw=2 ts=2 expandtab
|
|
*
|
|
* THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
|
|
* <cfr34k@tkolb.de> wrote this file. As long as you retain this notice you can
|
|
* do whatever you want with this stuff. If we meet some day, and you think
|
|
* this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "ws2801.h"
|
|
|
|
#define SET_COLOR 0
|
|
#define FADE_COLOR 1
|
|
#define ADD_COLOR 2
|
|
#define SET_FADESTEP 3
|
|
|
|
struct WS2801Packet {
|
|
uint8_t metadata;
|
|
uint8_t data[3];
|
|
};
|
|
|
|
int ws2801_socket = -1;
|
|
struct WS2801Packet packetQueue[50];
|
|
int queueIndex = 0;
|
|
|
|
// creates the socket needed for steering the LED strip
|
|
int ws2801_init(char *host, unsigned short port) {
|
|
struct addrinfo hints;
|
|
struct addrinfo *result;
|
|
char portstr[6];
|
|
|
|
memset(&hints, 0, sizeof(struct addrinfo));
|
|
hints.ai_family = AF_UNSPEC;
|
|
hints.ai_socktype = SOCK_DGRAM;
|
|
hints.ai_flags = 0;
|
|
hints.ai_protocol = 0;
|
|
|
|
sprintf(portstr, "%u", port);
|
|
|
|
if(getaddrinfo(host, portstr, &hints, &result) != 0) {
|
|
perror("getaddrinfo() failed");
|
|
return 1;
|
|
}
|
|
|
|
ws2801_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
|
if (ws2801_socket == -1) {
|
|
perror("socket() failed");
|
|
freeaddrinfo(result);
|
|
return 2;
|
|
}
|
|
|
|
if (connect(ws2801_socket, result->ai_addr, result->ai_addrlen) == -1) {
|
|
perror("connect() failed");
|
|
freeaddrinfo(result);
|
|
return 3;
|
|
}
|
|
|
|
freeaddrinfo(result);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ws2801_set_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b) {
|
|
packetQueue[queueIndex].metadata = (SET_COLOR << 6) | (module & 0x3F);
|
|
packetQueue[queueIndex].data[0] = r;
|
|
packetQueue[queueIndex].data[1] = g;
|
|
packetQueue[queueIndex].data[2] = b;
|
|
queueIndex++;
|
|
}
|
|
|
|
void ws2801_fade_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b) {
|
|
packetQueue[queueIndex].metadata = (FADE_COLOR << 6) | (module & 0x3F);
|
|
packetQueue[queueIndex].data[0] = r;
|
|
packetQueue[queueIndex].data[1] = g;
|
|
packetQueue[queueIndex].data[2] = b;
|
|
queueIndex++;
|
|
}
|
|
|
|
void ws2801_add_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b) {
|
|
packetQueue[queueIndex].metadata = (ADD_COLOR << 6) | (module & 0x3F);
|
|
packetQueue[queueIndex].data[0] = r;
|
|
packetQueue[queueIndex].data[1] = g;
|
|
packetQueue[queueIndex].data[2] = b;
|
|
queueIndex++;
|
|
}
|
|
|
|
void ws2801_set_fadestep(uint8_t fadestep) {
|
|
packetQueue[queueIndex].metadata = (SET_FADESTEP << 6);
|
|
packetQueue[queueIndex].data[0] = fadestep;
|
|
queueIndex++;
|
|
}
|
|
|
|
int ws2801_commit(void) {
|
|
if(send(ws2801_socket, packetQueue, queueIndex * sizeof(struct WS2801Packet), 0) == -1) {
|
|
return 1;
|
|
}
|
|
|
|
queueIndex = 0;
|
|
return 0;
|
|
}
|
|
|
|
void ws2801_shutdown() {
|
|
close(ws2801_socket);
|
|
}
|