#include #include #include #include #include #include #include #include "led_info.h" #include "gradient.h" void refresh_strip(ws2811_t *ledstring, segment_t *segments, unsigned int segment_amount) { unsigned int s = 0; unsigned int led = 0; for(; s < segment_amount; s++) { for(; led < segments[s].size; led++) { ledstring->channel[0].leds[led] = segments[s].color; } } if(led < (LED_COUNT - 1)) { for(; led < LED_COUNT; led++) { ledstring->channel[0].leds[led] = segments[s].color; } } ws2811_render(ledstring); } unsigned int find_starting_pos(segment_t *segments, unsigned int index) { unsigned int position = 0; for(int i = 0; i < position; i++) position += segments[i].size; return(position); } int main() { initscr(); clear(); noecho(); cbreak(); keypad(stdscr, TRUE); ws2811_return_t ret; if((ret = ws2811_init(&ledstring)) != WS2811_SUCCESS) { printf("Error initilizing ws8211 strip: %s\n", ws2811_get_return_t_str(ret)); return(ret); } segment_t *segments = malloc(sizeof(segment_t)); //just start with one segments[0].size = LED_COUNT - 1; segments[0].color = 0; int prev_program_state = EXITED; int program_state = VIEW_MODE; int ui_selection = 0; unsigned int i = 0; unsigned int starting_pos; unsigned int segment_selection = 0; unsigned int segment_quanity = 1; int selection_state = 0; //just for asthetics int user_key; char *main_msg = "Press the arrow keys to select the segment, and enter to edit it.\nTo create new segments, select the segment you want to divide.\n"; char *modification_menu[7] = { "Change red", "Change green", "Change blue", "Change size", "Subdivide (create segment)", "Delete", "Go back" }; int modification_menu_items = 7; for(;;) { //prev_program_state = program_state; if(prev_program_state != program_state) { switch(program_state) { case MODIFY_MODE: clear(); for(i = 0; i < modification_menu_items; i++) { cbreak(); if(ui_selection == i) attron(A_STANDOUT); printw("%s, %i, %i\n", modification_menu[i], ui_selection, user_key); if(ui_selection == i) attroff(A_STANDOUT); } refresh(); break; case MODIFY_R: printw("Modifying red value.\n"); refresh_strip(&ledstring, segments, segment_quanity); refresh(); break; case MODIFY_G: printw("Modifying green value.\n"); refresh_strip(&ledstring, segments, segment_quanity); refresh(); break; case MODIFY_B: printw("Modifying blue value.\n"); refresh_strip(&ledstring, segments, segment_quanity); refresh(); break; case MODIFY_SIZE: printw("Modifying size.\n"); refresh_strip(&ledstring, segments, segment_quanity); refresh(); break; case VIEW_MODE: clear(); refresh_strip(&ledstring, segments, segment_quanity); printw("%s\n", main_msg); cbreak(); break; case SELECT_MODE: clear(); printw("Press enter to modify segment %i, or [q] to return.\n", segment_selection); halfdelay(10); break; case EXITED: for(i = 0; i < LED_COUNT; i++) { ledstring.channel[0].leds[i] = 0; } ws2811_render(&ledstring); ws2811_fini(&ledstring); clear(); endwin(); printf("goodbye\n"); return 0; break; default: break; } } if((user_key = getch()) != ERR) { switch(user_key) { case KEY_UP: case KEY_LEFT: switch(program_state) { case VIEW_MODE: program_state = SELECT_MODE; segment_selection = segment_quanity; break; case SELECT_MODE: if(segment_selection < segment_quanity) segment_selection++; break; case MODIFY_MODE: if(ui_selection < modification_menu_items) ui_selection++; break; case MODIFY_R: if ((segments[segment_selection].color >> 16) < 0xff) segments[segment_selection].color += 0x10000; break; case MODIFY_G: if ((segments[segment_selection].color >> 8 & 0xff) < 0xff) segments[segment_selection].color += 0x100; break; case MODIFY_B: if ((segments[segment_selection].color & 0xff) < 0xff) segments[segment_selection].color += 1; break; case MODIFY_SIZE: if(find_starting_pos(segments, segment_quanity - 1) < LED_COUNT - 1) segments[segment_selection].size++; break; default: break; } break; case KEY_DOWN: case KEY_RIGHT: switch(program_state) { case VIEW_MODE: program_state = SELECT_MODE; segment_selection = 0; break; case SELECT_MODE: if(segment_selection > 0) segment_selection--; break; case MODIFY_MODE: if(ui_selection > 0) ui_selection--; case MODIFY_R: if (!(segments[segment_selection].color >> 16)) segments[segment_selection].color -= 0x10000; break; case MODIFY_G: if (!(segments[segment_selection].color >> 8 & 0xff)) segments[segment_selection].color -= 0x100; break; case MODIFY_B: if (!(segments[segment_selection].color & 0xff)) segments[segment_selection].color -= 1; break; case MODIFY_SIZE: if(segments[segment_selection].size >= 4) segments[segment_selection].size--; break; default: break; } break; case 10: switch(program_state) { case VIEW_MODE: program_state = SELECT_MODE; break; case SELECT_MODE: program_state = MODIFY_MODE; break; case MODIFY_MODE: switch(ui_selection) { case 0: program_state = MODIFY_R; break; case 1: program_state = MODIFY_G; break; case 2: program_state = MODIFY_B; break; case 3: program_state = MODIFY_SIZE; break; case 4: //create new segment //TODO: prevent user stupidity program_state = MODIFY_MODE; segments[segment_selection].size = segments[segment_selection].size / 2; segment_quanity++; segments = realloc(segments, sizeof(segment_t) * segment_quanity); memmove(&segments[segment_selection + 2], &segments[segment_selection] + sizeof(segment_t), &segments[segment_quanity - 1] - &segments[segment_selection + 1]); memcpy(&segments[segment_selection + 1], &segments[segment_selection], sizeof(segment_t)); segment_selection++; break; case 5: program_state = VIEW_MODE; segments[segment_selection + 1].size += segments[segment_selection].size; memmove(&segments[segment_selection], &segments[segment_selection + 1], &segments[segment_quanity] - &segments[segment_selection + 1]); segment_quanity--; segments = realloc(&segments, &segments[segment_quanity] - &segments[0]); break; case 6: program_state = VIEW_MODE; break; default: break; } break; case MODIFY_R: case MODIFY_G: case MODIFY_B: case MODIFY_SIZE: program_state = MODIFY_MODE; break; default: break; } break; case 'q': switch(program_state) { case VIEW_MODE: program_state = EXITED; break; case SELECT_MODE: program_state = VIEW_MODE; break; case MODIFY_MODE: program_state = SELECT_MODE; break; case MODIFY_R: case MODIFY_G: case MODIFY_B: case MODIFY_SIZE: program_state = MODIFY_MODE; default: break; } break; default: break; } } else if(program_state = SELECT_MODE) { starting_pos = find_starting_pos(segments, segment_selection); for(i = starting_pos; i <= starting_pos + segments[segment_selection].size; i++) { ledstring.channel[0].leds[i] = (selection_state ? (i % 2) : ((i+1) % 2)) ? 0xffffff : 0; } selection_state = selection_state ? 0 : 1; ws2811_render(&ledstring); } } return 0; }