Initial commit
This commit is contained in:
commit
c0def49827
|
@ -0,0 +1 @@
|
|||
*.swp
|
|
@ -0,0 +1,5 @@
|
|||
twinkl
|
||||
------
|
||||
|
||||
A simple multiclient network protocol for your blinkenlights.
|
||||
|
|
@ -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
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef _MESSAGE_H_
|
||||
#define _MESSAGE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _TWINKL_H_
|
||||
#define _TWINKL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
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
|
|
@ -0,0 +1,69 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue