#include "skiller.h" #include "utils.h" #include 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); }