108 lines
2.1 KiB
C
108 lines
2.1 KiB
C
#include <time.h>
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include <errno.h>
|
|
|
|
#include <wiringPi.h>
|
|
|
|
#include "../include/logger.h"
|
|
#include "../include/ws2801.h"
|
|
|
|
#define WS2801_CLK_GPIO 17
|
|
#define WS2801_DAT_GPIO 18
|
|
|
|
// the interface rpi->ws2801 is active low
|
|
#define BUS_HIGH LOW
|
|
#define BUS_LOW HIGH
|
|
|
|
uint8_t *modRed = NULL;
|
|
uint8_t *modGreen = NULL;
|
|
uint8_t *modBlue = NULL;
|
|
uint8_t numModules;
|
|
|
|
void busy_wait(void)
|
|
{
|
|
static const struct timespec bitsleep = {0, 1000};
|
|
nanosleep(&bitsleep, NULL);
|
|
}
|
|
|
|
void send_bit(uint8_t value)
|
|
{
|
|
digitalWrite(WS2801_DAT_GPIO, (value ? BUS_HIGH : BUS_LOW));
|
|
|
|
digitalWrite(WS2801_CLK_GPIO, BUS_LOW);
|
|
busy_wait();
|
|
|
|
// rising edge at clock
|
|
digitalWrite(WS2801_CLK_GPIO, BUS_HIGH);
|
|
busy_wait();
|
|
}
|
|
|
|
void send_commit_condition(void)
|
|
{
|
|
digitalWrite(WS2801_DAT_GPIO, BUS_LOW);
|
|
digitalWrite(WS2801_CLK_GPIO, BUS_LOW);
|
|
}
|
|
|
|
void send_byte(uint8_t byte)
|
|
{
|
|
for(int i = 0; i <= 7; i++) {
|
|
send_bit(byte & 0x1);
|
|
byte >>= 1;
|
|
}
|
|
}
|
|
|
|
void send_colour(uint8_t red, uint8_t green, uint8_t blue)
|
|
{
|
|
send_byte(red);
|
|
send_byte(green);
|
|
send_byte(blue);
|
|
}
|
|
|
|
int ws2801_init(uint8_t nMod)
|
|
{
|
|
if(wiringPiSetupGpio() == -1) {
|
|
LOG(LVL_FATAL, "ws2801: wiringPi setup failed: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
numModules = nMod;
|
|
modRed = malloc(nMod * sizeof(uint8_t));
|
|
modGreen = malloc(nMod * sizeof(uint8_t));
|
|
modBlue = malloc(nMod * sizeof(uint8_t));
|
|
|
|
if(!modRed || !modGreen || !modBlue) {
|
|
LOG(LVL_ERR, "ws2801: could not allocate all colour arrays!");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ws2801_shutdown(void)
|
|
{
|
|
if(modRed != NULL) { free(modRed); modRed = NULL; }
|
|
if(modGreen != NULL) { free(modGreen); modGreen = NULL; }
|
|
if(modBlue != NULL) { free(modBlue); modBlue = NULL; }
|
|
}
|
|
|
|
void ws2801_set_colour(uint8_t module, uint8_t red, uint8_t green, uint8_t blue)
|
|
{
|
|
modRed[module] = red;
|
|
modGreen[module] = green;
|
|
modBlue[module] = blue;
|
|
}
|
|
|
|
void ws2801_send_update(void)
|
|
{
|
|
for(uint8_t i = 0; i < numModules; i++) {
|
|
send_colour(modRed[i], modGreen[i], modBlue[i]);
|
|
}
|
|
|
|
send_commit_condition();
|
|
|
|
static const struct timespec sleepval = {0, 550000};
|
|
nanosleep(&sleepval, NULL);
|
|
}
|
|
|