Skip to content

Commit

Permalink
CTRL (arm_atsam) support user-defined LED instructions (#2)
Browse files Browse the repository at this point in the history
* CTRL (arm_atsam) support user-defined LED instructions

* ok, layer matching works now

* Bitwise LED ID to reduce number of instructions (performance)

* Use 32-bit ints to be more compatible with generation in JS

* TYpo
  • Loading branch information
just-another-jxliu authored Sep 14, 2018
1 parent 1a907a1 commit 5fb9b45
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 65 deletions.
14 changes: 13 additions & 1 deletion keyboards/massdrop/ctrl/keymaps/default/keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,16 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
default:
return true; //Process all other keycodes normally
}
}
}

led_instruction_t led_instructions[] = {
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 10, .id1 = 9, .r = 255, .g = 0, .b = 0 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_PATTERN, .id0 = 4, .id1 = 0, .pattern_id = 8 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 8, .id1 = 0, .r = 0, .g = 255, .b = 0 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_PATTERN, .id = 16, .id1 = 0, .pattern_id = 9 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 32, .id1 = 0, .r = 0, .g = 0, .b = 255 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN, .id0 = 64, .id1 = 0},
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_ROTATE_PATTERN, .id0 = 262144, .id1 = 0, .layer = 0 },
// { .flags = LED_FLAG_MATCH_ID | LED_FLAG_MATCH_LAYER | LED_FLAG_USE_ROTATE_PATTERN, .id = 16777216, .id1 = 0, .layer = 1 },
{ .end = 1 }
};
202 changes: 138 additions & 64 deletions tmk_core/protocol/arm_atsam/led_matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,87 @@ issi3733_led_t *led_cur;
uint8_t led_per_run = 15;
float breathe_mult;

void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo) {
float px;

uint8_t fcur = 0;
uint8_t fmax = 0;

//Frames setup
while (f[fcur].end != 1)
{
fcur++; //Count frames
}

fmax = fcur; //Store total frames count

for (fcur = 0; fcur < fmax; fcur++)
{
px = led_cur->px;
float pxmod;
pxmod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;

//Add in any moving effects
if ((!led_animation_direction && f[fcur].ef & EF_SCR_R) || (led_animation_direction && (f[fcur].ef & EF_SCR_L)))
{
pxmod *= 100.0f;
pxmod = (uint32_t)pxmod % 10000;
pxmod /= 100.0f;

px -= pxmod;

if (px > 100) px -= 100;
else if (px < 0) px += 100;
}
else if ((!led_animation_direction && f[fcur].ef & EF_SCR_L) || (led_animation_direction && (f[fcur].ef & EF_SCR_R)))
{
pxmod *= 100.0f;
pxmod = (uint32_t)pxmod % 10000;
pxmod /= 100.0f;
px += pxmod;

if (px > 100) px -= 100;
else if (px < 0) px += 100;
}

//Check if LED's px is in current frame
if (px < f[fcur].hs) continue;
if (px > f[fcur].he) continue;
//note: < 0 or > 100 continue

//Calculate the px within the start-stop percentage for color blending
px = (px - f[fcur].hs) / (f[fcur].he - f[fcur].hs);

//Add in any color effects
if (f[fcur].ef & EF_OVER)
{
*ro = (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
*go = (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
*bo = (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
else if (f[fcur].ef & EF_SUBTRACT)
{
*ro -= (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
*go -= (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
*bo -= (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
else
{
*ro += (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
*go += (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
*bo += (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
}
}

__attribute__((weak))
led_instruction_t led_instructions[] = { { .end = 1 } };

void led_matrix_run(led_setup_t *f)
{
float ro;
float go;
float bo;
float px;
uint8_t led_this_run = 0;

if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing
Expand All @@ -289,17 +364,6 @@ void led_matrix_run(led_setup_t *f)
}
}

uint8_t fcur = 0;
uint8_t fmax = 0;

//Frames setup
while (f[fcur].end != 1)
{
fcur++; //Count frames
}

fmax = fcur; //Store total frames count

while (led_cur < lede && led_this_run < led_per_run)
{
ro = 0;
Expand All @@ -320,62 +384,72 @@ void led_matrix_run(led_setup_t *f)
}
else
{
//Act on LED
for (fcur = 0; fcur < fmax; fcur++)
{
px = led_cur->px;
float pxmod;
pxmod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
led_instruction_t *led_cur_instruction;
led_cur_instruction = led_instructions;

//Add in any moving effects
if ((!led_animation_direction && f[fcur].ef & EF_SCR_R) || (led_animation_direction && (f[fcur].ef & EF_SCR_L)))
{
pxmod *= 100.0f;
pxmod = (uint32_t)pxmod % 10000;
pxmod /= 100.0f;

px -= pxmod;

if (px > 100) px -= 100;
else if (px < 0) px += 100;
}
else if ((!led_animation_direction && f[fcur].ef & EF_SCR_L) || (led_animation_direction && (f[fcur].ef & EF_SCR_R)))
{
pxmod *= 100.0f;
pxmod = (uint32_t)pxmod % 10000;
pxmod /= 100.0f;
px += pxmod;

if (px > 100) px -= 100;
else if (px < 0) px += 100;
}
//Act on LED
if (led_cur_instruction->end) {
// If no instructions, use normal pattern
led_run_pattern(f, &ro, &go, &bo);
} else {
uint8_t skip;

while (!led_cur_instruction->end) {
skip = 0;

if (led_cur_instruction->flags & LED_FLAG_MATCH_ID) {
if (
led_cur_instruction->id0 == 0 &&
led_cur_instruction->id1 == 0 &&
led_cur_instruction->id2 == 0 &&
led_cur_instruction->id3 == 0 &&
led_cur->id == 0
) {
//
} else if (
(0 <= led_cur->id && led_cur->id <= 31) &&
(~led_cur_instruction->id0 & ((uint32_t) 1UL << led_cur->id))
) {
skip = 1;
} else if (
(32 <= led_cur->id && led_cur->id <= 63) &&
(~led_cur_instruction->id1 & ((uint32_t) 1UL << (led_cur->id - 32)))
) {
skip = 1;
} else if (
(64 <= led_cur->id && led_cur->id <= 95) &&
(~led_cur_instruction->id2 & ((uint32_t) 1UL << (led_cur->id - 64)))
) {
skip = 1;
} else if (
(96 <= led_cur->id && led_cur->id <= 127) &&
(~led_cur_instruction->id3 & ((uint32_t) 1UL << (led_cur->id - 96)))
) {
skip = 1;
}
}

//Check if LED's px is in current frame
if (px < f[fcur].hs) continue;
if (px > f[fcur].he) continue;
//note: < 0 or > 100 continue
if (led_cur_instruction->flags & LED_FLAG_MATCH_LAYER) {
if (layer_state == 0 && led_cur_instruction->layer == 0) {
//
} else if (~layer_state & (1UL << led_cur_instruction->layer)) {
skip = 1;
}
}

//Calculate the px within the start-stop percentage for color blending
px = (px - f[fcur].hs) / (f[fcur].he - f[fcur].hs);
if (!skip) {
if (led_cur_instruction->flags & LED_FLAG_USE_RGB) {
ro = led_cur_instruction->r;
go = led_cur_instruction->g;
bo = led_cur_instruction->b;
} else if (led_cur_instruction->flags & LED_FLAG_USE_PATTERN) {
led_run_pattern(led_setups[led_cur_instruction->pattern_id], &ro, &go, &bo);
} else if (led_cur_instruction->flags & LED_FLAG_USE_ROTATE_PATTERN) {
led_run_pattern(f, &ro, &go, &bo);
}
}

//Add in any color effects
if (f[fcur].ef & EF_OVER)
{
ro = (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
go = (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
bo = (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
else if (f[fcur].ef & EF_SUBTRACT)
{
ro -= (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
go -= (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
bo -= (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
}
else
{
ro += (px * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
go += (px * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
bo += (px * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
led_cur_instruction++;
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions tmk_core/protocol/arm_atsam/led_matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,28 @@ typedef struct led_setup_s {
uint8_t end; //Set to signal end of the setup
} led_setup_t;

//LED Extra Instructions
#define LED_FLAG_NULL 0x00
#define LED_FLAG_MATCH_ID 0x01
#define LED_FLAG_MATCH_LAYER 0x02
#define LED_FLAG_USE_RGB 0x10
#define LED_FLAG_USE_PATTERN 0x20
#define LED_FLAG_USE_ROTATE_PATTERN 0x40

typedef struct led_instruction_s {
uint16_t flags; // Bitfield for LED instructions
uint32_t id0; // Bitwise id, IDs 0-31
uint32_t id1; // Bitwise id, IDs 32-63
uint32_t id2; // Bitwise id, IDs 64-95
uint32_t id3; // Bitwise id, IDs 96-127
uint8_t layer;
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t pattern_id;
uint8_t end;
} led_instruction_t;

extern issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];

extern uint8_t gcr_desired;
Expand All @@ -130,6 +152,9 @@ extern uint8_t breathe_dir;
extern const uint8_t led_setups_count;

extern void *led_setups[];
extern led_instruction_t led_instructions[];

extern uint32_t layer_state;

extern issi3733_led_t *led_cur;
extern issi3733_led_t *lede;
Expand Down

0 comments on commit 5fb9b45

Please sign in to comment.