108 lines
2.4 KiB
C
108 lines
2.4 KiB
C
#include <time.h>
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <linux/spi/spidev.h>
|
|
|
|
//#include <wiringPi.h>
|
|
|
|
#include "logger.h"
|
|
#include "ws2801.h"
|
|
|
|
static const char *spi_dev = "/dev/spidev0.0";
|
|
static const uint32_t spi_speed = 1000000; // clock freq in Hz
|
|
static const uint16_t spi_delay = 0; // us
|
|
static const uint8_t spi_bits = 8; // bits per word
|
|
|
|
uint32_t numModules;
|
|
uint8_t *message;
|
|
|
|
int spi_fd = 0;
|
|
|
|
void send_message(void)
|
|
{
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)message,
|
|
.rx_buf = (unsigned long)NULL,
|
|
.len = 3 * numModules,
|
|
.delay_usecs = spi_delay,
|
|
.speed_hz = spi_speed,
|
|
.bits_per_word = 8
|
|
};
|
|
|
|
if(ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr) < 0) {
|
|
LOG(LVL_ERR, "ws2801: could not send SPI message: %s", strerror(errno));
|
|
}
|
|
}
|
|
|
|
int ws2801_init(uint32_t nMod)
|
|
{
|
|
// Initialize SPI
|
|
// We need to have stable data at falling edge of the spi interface (this
|
|
// means rising edge at the led strip, as the signal is inverted.
|
|
uint8_t spi_mode = SPI_NO_CS; // | SPI_CPOL;
|
|
|
|
spi_fd = open(spi_dev, O_RDWR);
|
|
if(spi_fd < 0) {
|
|
LOG(LVL_ERR, "ws2801: cannot open %s: %s", spi_dev, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
if(ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode) == -1) {
|
|
LOG(LVL_ERR, "ws2801: cannot change SPI mode: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
if(ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits) == -1) {
|
|
LOG(LVL_ERR, "ws2801: cannot change SPI bits per word: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
if(ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) == -1) {
|
|
LOG(LVL_ERR, "ws2801: cannot change SPI speed: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
// create the message array
|
|
numModules = nMod;
|
|
message = malloc(3 * nMod * sizeof(uint8_t));
|
|
|
|
if(!message) {
|
|
LOG(LVL_ERR, "ws2801: could not allocate the message array!");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ws2801_shutdown(void)
|
|
{
|
|
close(spi_fd);
|
|
|
|
if(message != NULL) { free(message); message = NULL; }
|
|
}
|
|
|
|
void ws2801_set_colour(uint32_t module, uint8_t red, uint8_t green, uint8_t blue)
|
|
{
|
|
//message[3*module + 0] = ~red;
|
|
//message[3*module + 1] = ~green;
|
|
//message[3*module + 2] = ~blue;
|
|
message[3*module + 0] = red;
|
|
message[3*module + 1] = blue;
|
|
message[3*module + 2] = green;
|
|
}
|
|
|
|
void ws2801_send_update(void)
|
|
{
|
|
send_message();
|
|
|
|
static const struct timespec sleepval = {0, 550000};
|
|
nanosleep(&sleepval, NULL);
|
|
}
|
|
|