Initial commit

This commit is contained in:
Thomas Kolb 2013-04-08 23:55:01 +02:00
commit 2437c7b18d
6 changed files with 449 additions and 0 deletions

79
Makefile Normal file
View file

@ -0,0 +1,79 @@
# --- START OF CONFIG ---------------------------------------------------
# Edit the following variables for your own needs
# toolchain configuration
CXX=gcc
LD=gcc
# default build configuration
# "make BUILD=release" does a release build
BUILD:=release
# basic build flags configuration
CFLAGS+=-std=c99 -Wall -pedantic -Wno-long-long -D_POSIX_C_SOURCE=20120607L -D_FILE_OFFSET_BITS=64
LIBS+=-lm
# library specific flags
# wiringPi
CFLAGS+=
LIBS+=-lwiringPi
# build type specific flags
CFLAGS_debug=-O0 -ggdb -DDEBUG
LIBS_debug=
CFLAGS_release=-Os -pipe -march=armv6zk -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard
LIBS_release=
# target configuration
TARGET := ws2801d
VERSION := 0.0.0
VCSVERSION := $(shell git rev-parse --short HEAD)
# source files for the project
SOURCE := $(shell find src/ -name '*.c')
INCLUDES := $(shell find include/ -name '*.h')
# --- END OF CONFIG -----------------------------------------------------
OBJ1=$(patsubst %.c, %.o, $(SOURCE))
OBJ=$(patsubst src/%, obj/$(BUILD)/%, $(OBJ1))
VERSIONSTR="\"$(VERSION)-$(VCSVERSION)\""
CFLAGS+=-Iinclude -DVERSION=$(VERSIONSTR)
TARGETFILE := bin/$(BUILD)/$(TARGET)
all: $(TARGET)
CFLAGS+=$(CFLAGS_$(BUILD))
LIBS+=$(LIBS_$(BUILD))
.PHONY show_cflags:
@echo --- Build parameters: ------------------------------------------
@echo CFLAGS\=$(CFLAGS)
@echo LIBS\=$(LIBS)
@echo SOURCE\=$(SOURCE)
@echo -----------------------------------------------------------------
$(TARGET): show_cflags $(TARGETFILE)
@echo ">>> $(BUILD) build complete."
$(TARGETFILE): $(OBJ) $(INCLUDES) Makefile
@echo Linking $@ ...
@mkdir -p $(shell dirname $@)
@$(LD) -o $(TARGETFILE) $(OBJ) $(LIBS)
obj/$(BUILD)/%.o: src/%.c $(INCLUDES) Makefile
@echo Compiling $< ...
@mkdir -p $(shell dirname $@)
@$(CXX) -c $(CFLAGS) -o $@ $<
doc:
doxygen doxygen.conf
clean:
rm -f $(TARGETFILE)
rm -f $(OBJ)

37
include/logger.h Normal file
View file

@ -0,0 +1,37 @@
/*
* vim: sw=2 ts=2 expandtab
*
* "THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
* Thomas Kolb <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
*/
#ifndef LOGGER_H
#define LOGGER_H
#include <semaphore.h>
#include <stdarg.h>
static const int LVL_FATAL = 0; /*!< Fatal message level */
static const int LVL_ERR = 5; /*!< Error message level */
static const int LVL_WARN = 50; /*!< Warning message level */
static const int LVL_INFO = 100; /*!< Information message level */
static const int LVL_DEBUG = 200; /*!< Debug message level */
static const int LVL_DUMP = 500; /*!< Dump message level */
extern sem_t logger_semaphore;
extern int logger_verbosity;
extern int logger_use_colors;
void logger_init(void);
void logger_shutdown(void);
void logger_enable_colors(int enable);
void logger_set_verbosity(int verbosity);
void logger_log(int level, const char *format, ...);
#define LOG(level, ...) logger_log(level, __VA_ARGS__)
#endif // LOGGER_H

11
include/ws2801.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef WS2801_H
#define WS2801_H
#include <stdint.h>
int ws2801_init(uint8_t num_modules);
void ws2801_shutdown(void);
void ws2801_set_colour(uint8_t module, uint8_t red, uint8_t green, uint8_t blue);
void ws2801_send_update(void);
#endif // WS2801_H

161
src/logger.c Normal file
View file

@ -0,0 +1,161 @@
/*
* vim: sw=2 ts=2 expandtab
*
* "THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
* Thomas Kolb <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 <stdio.h>
#include <malloc.h>
#include <time.h>
#include <sys/time.h>
#include "logger.h"
// define constants
const char *LOGGER_STR_FATAL = "FATAL";
const char *LOGGER_STR_ERR = "ERROR";
const char *LOGGER_STR_WARN = "WARN ";
const char *LOGGER_STR_INFO = "INFO ";
const char *LOGGER_STR_DEBUG = "DEBUG";
const char *LOGGER_STR_DUMP = "DUMP ";
const char *LOGGER_COLOR_FATAL = "\033[1;31m";
const char *LOGGER_COLOR_ERR = "\033[1;31m";
const char *LOGGER_COLOR_WARN = "\033[1;33m";
const char *LOGGER_COLOR_INFO = "\033[1;32m";
const char *LOGGER_COLOR_DEBUG = "\033[1m";
const char *LOGGER_COLOR_DUMP = "\033[1;30m";
const char *LOGGER_COLOR_NONE = "\033[0m";
// global variables
sem_t logger_semaphore;
int logger_verbosity;
int logger_use_colors;
void logger_init(void) {
// Initialize the semaphore
sem_init(&logger_semaphore, 0, 1);
logger_verbosity = 2147483647;
logger_use_colors = 1;
}
void logger_shutdown(void) {
sem_destroy(&logger_semaphore);
}
void logger_enable_colors(int enable) {
logger_use_colors = enable;
}
void logger_set_verbosity(int verbosity) {
logger_verbosity = verbosity;
}
void logger_debug_message(const char *prefix, const char *fmt, va_list ap) {
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p, *np;
va_list internal_ap;
if ((p = (char*)malloc(size)) == NULL) {
fprintf(stderr, "[%s] FATAL: Cannot allocate string buffer while processing arguments.\n", LOGGER_STR_ERR);
return;
}
while (1) {
/* Try to print in the allocated space. */
va_copy(internal_ap, ap);
n = vsnprintf(p, size, fmt, internal_ap);
va_end(internal_ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
break;
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((np = (char*)realloc (p, size)) == NULL) {
free(p);
fprintf(stderr, "[%s] FATAL: Cannot reallocate string buffer while processing arguments.\n", LOGGER_STR_ERR);
return;
} else {
p = np;
}
}
sem_wait(&logger_semaphore);
fprintf(stderr, "%s %s\n", prefix, p);
sem_post(&logger_semaphore);
free(p);
}
void logger_log(int level, const char *format, ...) {
va_list argptr;
char timebuf[32];
char timebuf2[32];
char prefixbuf[64];
const char *prefixcolor = "", *prefixtext = "";
if(level > logger_verbosity)
return;
struct timeval tv;
gettimeofday(&tv, NULL);
strftime(timebuf, 32, "%Y-%M-%d %H:%M:%S.%%03d", localtime(&(tv.tv_sec)));
snprintf(timebuf2, 32, timebuf, tv.tv_usec/1000);
if(level >= LVL_DUMP) {
if(logger_use_colors)
prefixcolor = LOGGER_COLOR_DUMP;
prefixtext = LOGGER_STR_DUMP;
} else if(level >= LVL_DEBUG) {
if(logger_use_colors)
prefixcolor = LOGGER_COLOR_DEBUG;
prefixtext = LOGGER_STR_DEBUG;
} else if(level >= LVL_INFO) {
if(logger_use_colors)
prefixcolor = LOGGER_COLOR_INFO;
prefixtext = LOGGER_STR_INFO;
} else if(level >= LVL_WARN) {
if(logger_use_colors)
prefixcolor = LOGGER_COLOR_WARN;
prefixtext = LOGGER_STR_WARN;
} else if(level >= LVL_ERR) {
if(logger_use_colors)
prefixcolor = LOGGER_COLOR_ERR;
prefixtext = LOGGER_STR_ERR;
} else {
if(logger_use_colors)
prefixcolor = LOGGER_COLOR_FATAL;
prefixtext = LOGGER_STR_FATAL;
}
if(logger_use_colors) {
sprintf(prefixbuf, "%s [%s%s%s]", timebuf2, prefixcolor, prefixtext, LOGGER_COLOR_NONE);
} else {
sprintf(prefixbuf, "%s [%s]", timebuf2, prefixtext);
}
va_start(argptr, format);
logger_debug_message(prefixbuf, format, argptr);
va_end(argptr);
}

54
src/main.c Normal file
View file

@ -0,0 +1,54 @@
#include <math.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include "../include/ws2801.h"
#include "../include/logger.h"
#define PI 3.141592654f
void set_all(uint8_t r, uint8_t g, uint8_t b)
{
for(uint8_t i = 0; i < 20; i++) {
ws2801_set_colour(i, r, g, b);
}
}
float sin_off(float phase)
{
return 255 * (0.5f + 0.5f * sin(phase));
}
int main(void)
{
float phase = 0;
logger_init();
if(ws2801_init(20) == -1) {
LOG(LVL_FATAL, "Could not initialize WS2801 library.");
return 1;
}
while(1) {
//phase += PI/1000;
for(uint8_t i = 0; i < 20; i++) {
ws2801_set_colour(i, sin_off(i * PI / 10 + phase), sin_off(i * PI / 10 + 1.241*phase), sin_off(i * PI / 10 + 1.537*phase));
}
ws2801_send_update();
static const struct timespec sleepval = {0, 40000000};
nanosleep(&sleepval, NULL);
}
ws2801_shutdown();
return 0;
}

107
src/ws2801.c Normal file
View file

@ -0,0 +1,107 @@
#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);
}