OS/src/skiller.c
2019-01-07 22:17:14 +01:00

192 lines
6.0 KiB
C

#include "skiller.h"
#include "utils.h"
#include <memory.h>
skillerctl_name_value_pair_t modesLUT[] = {
SK_MODE_WAVE , "wave",
SK_MODE_DRIFT , "drift",
SK_MODE_SWIRL , "swirl",
SK_MODE_CHANGE , "change",
SK_MODE_PULSATING, "pulsating",
SK_MODE_PERMAMENT, "permament",
SK_MODE_TRIGGER , "trigger",
SK_MODE_EXPLOSION, "explosion",
SK_MODE_BURST , "burst",
SK_MODE_CHAOS , "chaos",
SK_MODE_COSMIC , "cosmic",
SK_MODE_GRADIENT , "gradient",
SK_MODE_TIDE , "tide",
SK_MODE_LIGHTING , "lighting",
SK_MODE_MATRIX , "matrix",
SK_MODE_RICOCHET , "ricochet",
SK_MODE_RIPPLE , "ripple",
SK_MODE_CUSTOM , "custom",
};
skillerctl_packet_t* skillerctl_unpack(skillerctl_packet_t *packet, uint8_t *data, size_t length) {
if (*(unsigned char*)data != 0x04 || length < 1) {
return NULL;
}
packet->magic = *(uint8_t*)(data);
packet->checksum = *(uint16_t*)(data + 1);
packet->command = *(uint8_t*)(data + 3);
packet->length = *(uint8_t*)(data + 4);
packet->address = *(uint8_t*)(data + 5);
// 1 null byte
memcpy(packet->payload, data + 8, packet->length);
return packet;
}
void* skillerctl_pack(skillerctl_packet_t *packet, uint8_t *data) {
memcpy(data, &packet->magic, 1);
memcpy(data + 1, &packet->checksum, 2);
memcpy(data + 3, &packet->command, 1);
memcpy(data + 4, &packet->length, 1);
memcpy(data + 5, &packet->address, 2);
// 1 null byte
memcpy(data + 8, packet->payload, SK_MAX_PAYLOAD);
return packet;
}
void skillerctl_make_packet(skillerctl_packet_t *packet, uint8_t command, uint16_t address, void* payload, uint8_t size)
{
packet->magic = SK_MAGIC;
packet->address = address;
packet->command = command;
packet->length = size;
memset(packet->payload, 0, SK_MAX_PAYLOAD);
if (payload && size)
memcpy(packet->payload, payload, size);
packet->checksum = skillectl_packet_checksum(packet);
}
uint16_t skillectl_packet_checksum(skillerctl_packet_t *packet)
{
uint16_t checksum = 0;
checksum += (packet->command) & 0xFF;
checksum += (packet->address) & 0xFF;
checksum += (packet->address >> 8) & 0xFF;
checksum += (packet->length) & 0xFF;
for (int i = 0; i < packet->length; i++) {
checksum += packet->payload[i];
}
return checksum;
}
void skillerctl_color_command(skillerctl_packet_t *packet, skillerctl_keyaddr_t address, uint32_t color)
{
skillerctl_payload_color_t payload;
payload.color[0].r = (color >> 16) & 0xFF;
payload.color[0].g = (color >> 8) & 0xFF;
payload.color[0].b = color & 0xFF;
skillerctl_make_packet(packet, SK_CMD_SET_COLOR, address, &payload, 3);
}
void skillerctl_color_batch_command(skillerctl_packet_t *packet, skillerctl_keyaddr_t address, uint32_t *color, size_t n)
{
skillerctl_payload_color_t payload;
for (int i = 0; i < n; i++) {
payload.color[i].r = (color[i] >> 16) & 0xFF;
payload.color[i].g = (color[i] >> 8) & 0xFF;
payload.color[i].b = color[i] & 0xFF;
}
skillerctl_make_packet(packet, SK_CMD_SET_COLOR, address, &payload, 3*n);
}
void skillerctl_enable_led_command(skillerctl_packet_t *packet)
{
skillerctl_payload_color_t payload;
skillerctl_make_packet(packet, SK_CMD_ENABLE_LED, 0x0000, NULL, 0);
}
void skillerctl_disable_led_command(skillerctl_packet_t *packet)
{
skillerctl_payload_color_t payload;
skillerctl_make_packet(packet, SK_CMD_DISABLE_LED, 0x0000, NULL, 0);
}
void skillerctl_set_mode_command(skillerctl_packet_t *packet, uint8_t mode)
{
skillerctl_make_packet(packet, SK_CMD_SET_PROP, SK_PROP_MODE, &mode, 1);
}
void skillerctl_set_brightness_command(skillerctl_packet_t *packet, uint8_t brightness)
{
skillerctl_make_packet(packet, SK_CMD_SET_PROP, SK_PROP_BRIGHTNESS, &brightness, 1);
}
void skillerctl_set_direction_command(skillerctl_packet_t *packet, uint8_t direction)
{
skillerctl_make_packet(packet, SK_CMD_SET_PROP, SK_PROP_DIRECTION, &direction, 1);
}
void skillerctl_set_rgb_command(skillerctl_packet_t *packet, uint8_t rgb)
{
skillerctl_make_packet(packet, SK_CMD_SET_PROP, SK_PROP_RGB, &rgb, 1);
}
void skillerctl_set_speed_command(skillerctl_packet_t *packet, uint8_t speed)
{
skillerctl_make_packet(packet, SK_CMD_SET_PROP, SK_PROP_SPEED, &speed, 1);
}
void skillerctl_set_polling_command(skillerctl_packet_t *packet, uint8_t rate)
{
skillerctl_make_packet(packet, SK_CMD_SET_PROP, SK_PROP_POLLING, &rate, 1);
}
void skillerctl_set_base_color_command(skillerctl_packet_t *packet, uint32_t color)
{
skillerctl_payload_color_t payload;
payload.color[0].r = (color >> 16) & 0xFF;
payload.color[0].g = (color >> 8) & 0xFF;
payload.color[0].b = color & 0xFF;
skillerctl_make_packet(packet, SK_CMD_SET_PROP, SK_PROP_COLOR, &payload, 3);
}
char* skillerctl_modestr(skillerctl_mode_t mode)
{
switch (mode) {
case SK_MODE_WAVE: return "SK_MODE_WAVE";
case SK_MODE_DRIFT: return "SK_MODE_DRIFT";
case SK_MODE_SWIRL: return "SK_MODE_SWIRL";
case SK_MODE_CHANGE: return "SK_MODE_CHANGE";
case SK_MODE_PULSATING: return "SK_MODE_PULSATING";
case SK_MODE_PERMAMENT: return "SK_MODE_PERMAMENT";
case SK_MODE_TRIGGER: return "SK_MODE_TRIGGER";
case SK_MODE_EXPLOSION: return "SK_MODE_EXPLOSION";
case SK_MODE_BURST: return "SK_MODE_BURST";
case SK_MODE_CHAOS: return "SK_MODE_CHAOS";
case SK_MODE_COSMIC: return "SK_MODE_COSMIC";
case SK_MODE_GRADIENT: return "SK_MODE_GRADIENT";
case SK_MODE_TIDE: return "SK_MODE_TIDE";
case SK_MODE_LIGHTING: return "SK_MODE_LIGHTING";
case SK_MODE_MATRIX: return "SK_MODE_MATRIX";
case SK_MODE_RICOCHET: return "SK_MODE_RICOCHET";
case SK_MODE_RIPPLE: return "SK_MODE_RIPPLE";
case SK_MODE_CUSTOM: return "SK_MODE_CUSTOM";
}
return "SK_MODE_UNKNOWN";
}
skillerctl_mode_t skillerctl_strmode(const char *mode)
{
return skillerctl_lut_search(modesLUT, sizeof(modesLUT) / sizeof(skillerctl_name_value_pair_t), mode);
}