From c0def498277b9cae690a95fb2495d77dadafd09b Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Wed, 2 Sep 2015 21:48:07 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + README.md | 5 ++++ include/config.h | 23 ++++++++++++++++ include/message.h | 62 ++++++++++++++++++++++++++++++++++++++++++ include/twinkl.h | 17 ++++++++++++ include/util.h | 9 +++++++ twinkl.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ util.c | 11 ++++++++ 8 files changed, 197 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 include/config.h create mode 100644 include/message.h create mode 100644 include/twinkl.h create mode 100644 include/util.h create mode 100644 twinkl.c create mode 100644 util.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/README.md b/README.md new file mode 100644 index 0000000..34c9112 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +twinkl +------ + +A simple multiclient network protocol for your blinkenlights. + diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..c945190 --- /dev/null +++ b/include/config.h @@ -0,0 +1,23 @@ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +/* + * Here be Configuration + */ + +// Number of channels +#define TWINKL_CHANNEL_COUNT 512 + +// Number of priority levels +#define TWINKL_LEVEL_COUNT 8 + + +/* + * Only automagic below this point + */ + +// ceil(TWINKL_CHANNEL_COUNT / 8) +#define TWINKL_MASK_BYTES ((TWINKL_CHANNEL_COUNT + 7) / 8) + + +#endif diff --git a/include/message.h b/include/message.h new file mode 100644 index 0000000..3df34bc --- /dev/null +++ b/include/message.h @@ -0,0 +1,62 @@ +#ifndef _MESSAGE_H_ +#define _MESSAGE_H_ + +#include + +#include "config.h" +#include "util.h" + +struct twinkl_message { + + // Channel values from 0 to 255 + uint8_t values[TWINKL_CHANNEL_COUNT]; + + /* + * Mask bits + * + * If the value of channel X should be set, + * set bit X % 8 in byte X / 8. + */ + uint8_t mask[TWINKL_MASK_BYTES]; + + // Priority of this message. + uint8_t priority; +}; + + +/* + * Static helper functions for messages + */ +static inline void twinkl_init_message(struct twinkl_message *msg) { + twinkl_memset(msg->values, 0, TWINKL_CHANNEL_COUNT); + twinkl_memset(msg->mask, 0, TWINKL_MASK_BYTES); + msg->priority = 0; +} + +static inline void twinkl_set_value(struct twinkl_message *msg, uint16_t chan, uint8_t value) { + if(chan < TWINKL_CHANNEL_COUNT) { + msg->values[chan] = value; + + uint16_t byte = chan / 8; + uint8_t bit = chan % 8; + msg->mask[byte] |= (1 << bit); + } +} + +static inline void twinkl_unset_value(struct twinkl_message *msg, uint16_t chan) { + if(chan < TWINKL_CHANNEL_COUNT) { + msg->values[chan] = 0; + + uint16_t byte = chan / 8; + uint8_t bit = chan % 8; + msg->mask[byte] &= ~(1 << bit); + } +} + +static inline void twinkl_set_priority(struct twinkl_message *msg, uint8_t priority) { + if(priority < TWINKL_LEVEL_COUNT) { + msg->priority = priority; + } +} + +#endif diff --git a/include/twinkl.h b/include/twinkl.h new file mode 100644 index 0000000..9b92080 --- /dev/null +++ b/include/twinkl.h @@ -0,0 +1,17 @@ +#ifndef _TWINKL_H_ +#define _TWINKL_H_ + +#include + +#include "message.h" + +void twinkl_init(void); + +void twinkl_process_message(struct twinkl_message* msg); + +uint8_t twinkl_has_changes(void); + +void twinkl_render(uint8_t *channels); + + +#endif diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..4be054c --- /dev/null +++ b/include/util.h @@ -0,0 +1,9 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include + +void* __attribute__((weak)) twinkl_memset(void *ptr, int value, size_t num); +void* __attribute__((weak)) twinkl_memcpy(void * destination, const void * source, size_t num); + +#endif diff --git a/twinkl.c b/twinkl.c new file mode 100644 index 0000000..0114a0b --- /dev/null +++ b/twinkl.c @@ -0,0 +1,69 @@ +#include + +#include "config.h" +#include "util.h" +#include "twinkl.h" + + +uint8_t twinkl_channels[TWINKL_LEVEL_COUNT][TWINKL_CHANNEL_COUNT]; +uint8_t twinkl_masks[TWINKL_LEVEL_COUNT][TWINKL_MASK_BYTES]; + +uint8_t twinkl_has_changed; + + +void twinkl_init() { + twinkl_memset(twinkl_channels, 0, TWINKL_LEVEL_COUNT * TWINKL_CHANNEL_COUNT); + twinkl_memset(twinkl_masks, 0, TWINKL_LEVEL_COUNT * TWINKL_MASK_BYTES); + + twinkl_has_changed = 0; +} + + +void twinkl_process_message(struct twinkl_message *msg) { + if(msg->priority < TWINKL_LEVEL_COUNT) { + twinkl_memcpy(twinkl_channels[msg->priority], msg->values, TWINKL_CHANNEL_COUNT); + twinkl_memcpy(twinkl_masks[msg->priority], msg->mask, TWINKL_MASK_BYTES); + + twinkl_has_changed = 1; + } +} + + +uint8_t twinkl_has_changes() { + return twinkl_has_changed; +} + + +uint8_t get_mask_bit(uint8_t level, uint16_t channel) { + if(level >= TWINKL_LEVEL_COUNT && channel >= TWINKL_CHANNEL_COUNT) { + return 0; + } + + uint16_t byte = channel / 8; + uint8_t bit = channel % 8; + + if((twinkl_masks[level][byte] & (1 << bit)) != 0) { + return 1; + } + else { + return 0; + } +} + + +void twinkl_render(uint8_t *channels) { + uint16_t chan; + uint8_t level; + + for(chan = 0; chan < TWINKL_CHANNEL_COUNT; chan++) { + for(level = 0; level < TWINKL_LEVEL_COUNT; level++) { + if(get_mask_bit(level,chan)) { + channels[chan] = twinkl_channels[level][chan]; + break; + } + } + } + + twinkl_has_changed = 0; +} + diff --git a/util.c b/util.c new file mode 100644 index 0000000..dcb118b --- /dev/null +++ b/util.c @@ -0,0 +1,11 @@ +#include + +#include "util.h" + +void* twinkl_memset(void *ptr, int value, size_t num) { + return memset(ptr, value, num); +} + +void* twinkl_memcpy(void *destination, const void *source, size_t num) { + return memcpy(destination, source, num); +}