77#include <pthread.h>
88#include <stdlib.h>
99#include <time.h>
10+ #include <unistd.h>
1011
11-
12- void sleep (double t ) {
13- /** Sleep for a specified amount of seconds */
14- clock_t start = clock ();
15- while (((double ) (clock () - start )) / CLOCKS_PER_SEC < t );
16- }
12+ #define LIBMKC_DEBUG
1713
1814
1915LibMK_Controller * libmk_create_controller (LibMK_Handle * handle ) {
@@ -27,13 +23,17 @@ LibMK_Controller* libmk_create_controller(LibMK_Handle* handle) {
2723 pthread_mutex_init (& controller -> exit_flag_lock , NULL );
2824 pthread_mutex_init (& controller -> instr_lock , NULL );
2925 pthread_mutex_init (& controller -> error_lock , NULL );
26+ controller -> instr = NULL ;
27+ controller -> state = LIBMK_STATE_PRESTART ;
28+ controller -> exit_flag = false;
29+ controller -> wait_flag = false;
3030 return controller ;
3131}
3232
3333
3434LibMK_Controller_State libmk_get_controller_state (LibMK_Controller * c ) {
3535 /** Return whether the given controller is running (active) */
36- pthread_mutex_lock (& c -> state_lock );
36+ pthread_mutex_lock (& ( c -> state_lock ) );
3737 LibMK_Controller_State b = c -> state ;
3838 pthread_mutex_unlock (& c -> state_lock );
3939 return b ;
@@ -42,9 +42,9 @@ LibMK_Controller_State libmk_get_controller_state(LibMK_Controller* c) {
4242
4343LibMK_Result libmk_get_controller_error (LibMK_Controller * c ) {
4444 /** Return an error if the controller has one set */
45- pthread_mutex_lock (& c -> error_lock );
45+ pthread_mutex_lock (& ( c -> error_lock ) );
4646 LibMK_Result r = c -> error ;
47- pthread_mutex_unlock (& c -> error_lock );
47+ pthread_mutex_unlock (& ( c -> error_lock ) );
4848 return r ;
4949}
5050
@@ -80,69 +80,83 @@ LibMK_Result libmk_start_controller(LibMK_Controller* controller) {
8080
8181void libmk_run_controller (LibMK_Controller * controller ) {
8282 /** Execute instructions on a LibMK_Controller in a separate thread */
83- bool exit_flag ;
83+ pthread_mutex_lock (& (controller -> state_lock ));
84+ controller -> state = LIBMK_STATE_ACTIVE ;
85+ pthread_mutex_unlock (& (controller -> state_lock ));
86+ bool exit_flag , wait_flag ;
8487 while (true) {
85- pthread_mutex_lock (& controller -> exit_flag_lock );
88+ pthread_mutex_lock (& ( controller -> exit_flag_lock ) );
8689 exit_flag = controller -> exit_flag ;
87- pthread_mutex_unlock (& controller -> exit_flag_lock );
90+ wait_flag = controller -> wait_flag ;
91+ pthread_mutex_unlock (& (controller -> exit_flag_lock ));
8892 if (exit_flag )
8993 break ;
90-
91- if (controller -> instr == NULL )
94+ pthread_mutex_lock (& (controller -> instr_lock ));
95+ if (controller -> instr == NULL ) {
96+ pthread_mutex_unlock (& (controller -> instr_lock ));
97+ if (wait_flag )
98+ break ;
99+ usleep (1000 );
92100 continue ;
101+ }
93102 LibMK_Result r = (LibMK_Result ) libmk_exec_instruction (
94103 controller -> handle , controller -> instr );
95104 if (r != LIBMK_SUCCESS ) {
96105 libmk_set_controller_error (controller , r );
106+ pthread_mutex_unlock (& (controller -> instr_lock ));
97107 break ;
98108 }
99- // Sleep
100- struct timespec delay ;
101- delay .tv_nsec = controller -> instr -> duration ;
102- nanosleep (& delay , NULL );
109+ usleep (controller -> instr -> duration );
103110 // Move on to next instruction
104111 LibMK_Instruction * old = controller -> instr ;
105112 controller -> instr = controller -> instr -> next ;
106113 libmk_free_instruction (old );
114+ pthread_mutex_unlock (& (controller -> instr_lock ));
107115 }
108116 int r = libmk_disable_control (controller -> handle );
109117 if (r != LIBMK_SUCCESS ) {
110118 libmk_set_controller_error (controller , (LibMK_Result ) r );
111119 }
120+ pthread_mutex_lock (& (controller -> state_lock ));
121+ controller -> state = LIBMK_STATE_STOPPED ;
122+ pthread_mutex_unlock (& (controller -> state_lock ));
112123}
113124
114125
115126void libmk_set_controller_error (LibMK_Controller * c , LibMK_Result e ) {
116127 /** Set an error in the controller struct if one has not been set */
117- pthread_mutex_lock (& c -> error_lock );
128+ pthread_mutex_lock (& ( c -> error_lock ) );
118129 if (c -> error == LIBMK_SUCCESS )
119130 c -> error = e ;
120- pthread_mutex_unlock (& c -> error_lock );
131+ pthread_mutex_unlock (& ( c -> error_lock ) );
121132}
122133
123134
124- int libmk_exec_instruction (LibMK_Handle * h , LibMK_Instruction * i ) {
135+ LibMK_Result libmk_exec_instruction (LibMK_Handle * h , LibMK_Instruction * i ) {
125136 /** Execute a single instruction on the keyboard controlled */
126137 if (i == NULL )
127138 return libmk_send_control_packet (h );
128- else if (i -> colors != NULL ) {
139+ else if (i -> type == LIBMK_INSTR_ALL ) {
129140 return libmk_set_all_led_color (h , i -> colors );
130- } else {
131- unsigned char colors [LIBMK_MAX_ROWS ][LIBMK_MAX_COLS ][3 ];
132- for (unsigned char r = 0 ; r < LIBMK_MAX_ROWS ; r ++ )
133- for (unsigned char c = 0 ; c < LIBMK_MAX_COLS ; c ++ )
134- for (unsigned char k = 0 ; k < 3 ; k ++ )
135- colors [r ][c ][k ] = i -> color [k ];
136- return libmk_set_all_led_color (h , (unsigned char * ) colors );
141+ } else if (i -> type == LIBMK_INSTR_FULL ) {
142+ return libmk_set_full_color (h , i -> color [0 ], i -> color [1 ], i -> color [2 ]);
137143 }
138144}
139145
140146
141147void libmk_stop_controller (LibMK_Controller * controller ) {
142148 /** Stop a LibMK_Controller running in a separate thread */
143- pthread_mutex_lock (& controller -> exit_flag_lock );
149+ pthread_mutex_lock (& ( controller -> exit_flag_lock ) );
144150 controller -> exit_flag = true;
145- pthread_mutex_unlock (& controller -> exit_flag_lock );
151+ pthread_mutex_unlock (& (controller -> exit_flag_lock ));
152+ }
153+
154+
155+ void libmk_wait_controller (LibMK_Controller * controller ) {
156+ /** Set the flag to wait for the controller to finish scheduled instr */
157+ pthread_mutex_lock (& (controller -> exit_flag_lock ));
158+ controller -> wait_flag = true;
159+ pthread_mutex_unlock (& (controller -> exit_flag_lock ));
146160}
147161
148162
@@ -153,11 +167,11 @@ LibMK_Controller_State libmk_join_controller(
153167 clock_t t = clock ();
154168 double elapsed ;
155169 while (true) {
156- pthread_mutex_lock (& controller -> state_lock );
170+ pthread_mutex_lock (& ( controller -> state_lock ) );
157171 s = controller -> state ;
158- pthread_mutex_unlock (& controller -> state_lock );
159- // if (s != LIBMK_STATE_ACTIVE)
160- // break;
172+ pthread_mutex_unlock (& ( controller -> state_lock ) );
173+ if (s != LIBMK_STATE_ACTIVE )
174+ break ;
161175 elapsed = ((double ) (clock () - t )) / CLOCKS_PER_SEC ;
162176 if (elapsed > timeout )
163177 return LIBMK_STATE_JOIN_ERR ;
@@ -168,6 +182,7 @@ LibMK_Controller_State libmk_join_controller(
168182
169183void libmk_free_instruction (LibMK_Instruction * i ) {
170184 /** Free the memory allocated for an executed instruction */
185+ fflush (stdout );
171186 if (i -> colors != NULL )
172187 free (i -> colors );
173188 free (i );
@@ -180,6 +195,9 @@ LibMK_Instruction* libmk_create_instruction() {
180195 (LibMK_Instruction * ) malloc (sizeof (LibMK_Instruction ));
181196 i -> duration = 0 ;
182197 i -> id = 0 ;
198+ i -> type = -1 ;
199+ i -> next = NULL ;
200+ i -> colors = NULL ;
183201 return i ;
184202}
185203
@@ -189,6 +207,7 @@ LibMK_Instruction* libmk_create_instruction_full(unsigned char c[3]) {
189207 LibMK_Instruction * i = libmk_create_instruction ();
190208 for (unsigned char j = 0 ; j < 3 ; j ++ )
191209 i -> color [j ] = c [j ];
210+ i -> type = LIBMK_INSTR_FULL ;
192211 return i ;
193212}
194213
@@ -203,14 +222,43 @@ LibMK_Instruction* libmk_create_instruction_all(
203222 for (unsigned char col = 0 ; col < LIBMK_MAX_COLS ; col ++ )
204223 for (unsigned char j = 0 ; j < 3 ; j ++ )
205224 i -> colors [row * LIBMK_MAX_COLS + j ] = c [row ][col ][j ];
225+ i -> type = LIBMK_INSTR_ALL ;
226+ return i ;
227+ }
228+
229+
230+ LibMK_Instruction * libmk_create_instruction_flash (
231+ unsigned char c [3 ], unsigned int delay , unsigned char n ) {
232+ unsigned char color [3 ] = {0 };
233+ LibMK_Instruction * i = libmk_create_instruction_full (color );
234+ LibMK_Instruction * k = i ;
235+ LibMK_Instruction * l ;
236+ for (unsigned char j = 0 ; j < n ; j ++ ) {
237+ color [0 ] = ((double ) j / (double ) n ) * c [0 ];
238+ color [1 ] = ((double ) j / (double ) n ) * c [1 ];
239+ color [2 ] = ((double ) j / (double ) n ) * c [2 ];
240+ l = libmk_create_instruction_full (color );
241+ l -> duration = delay ;
242+ k -> next = l ;
243+ k = l ;
244+ }
245+ for (unsigned char j = n ; j > 0 ; j -- ) {
246+ color [0 ] = ((double ) j / (double ) n ) * c [0 ];
247+ color [1 ] = ((double ) j / (double ) n ) * c [1 ];
248+ color [2 ] = ((double ) j / (double ) n ) * c [2 ];
249+ l = libmk_create_instruction_full (color );
250+ l -> duration = delay ;
251+ k -> next = l ;
252+ k = l ;
253+ }
206254 return i ;
207255}
208256
209257
210258LibMK_Result libmk_sched_instruction (
211259 LibMK_Controller * c , LibMK_Instruction * i ) {
212260 /** Schedule a single instruction for execution on the controller */
213- pthread_mutex_lock (& c -> instr_lock );
261+ pthread_mutex_lock (& ( c -> instr_lock ) );
214262 if (c -> instr == NULL ) {
215263 c -> instr = i ;
216264 c -> instr -> id = 1 ;
@@ -225,14 +273,23 @@ LibMK_Result libmk_sched_instruction(
225273 t = t -> next ;
226274 }
227275 }
228- pthread_mutex_unlock (& c -> instr_lock );
276+ if (i -> next != NULL ) {
277+ LibMK_Instruction * k = i -> next ;
278+ unsigned int id = i -> id ;
279+ while (k != NULL ) {
280+ id += 1 ;
281+ k -> id = id ;
282+ k = k -> next ;
283+ }
284+ }
285+ pthread_mutex_unlock (& (c -> instr_lock ));
229286 return LIBMK_SUCCESS ;
230287}
231288
232289
233290LibMK_Result libmk_cancel_instruction (LibMK_Controller * c , unsigned int id ) {
234291 /** Cancel a scheduled instruction from executing */
235- pthread_mutex_lock (& c -> instr_lock );
292+ pthread_mutex_lock (& ( c -> instr_lock ) );
236293 LibMK_Instruction * prev = NULL ;
237294 LibMK_Instruction * curr = c -> instr ;
238295 while (curr != NULL ) {
@@ -248,6 +305,6 @@ LibMK_Result libmk_cancel_instruction(LibMK_Controller* c, unsigned int id) {
248305 prev = curr ;
249306 curr = curr -> next ;
250307 }
251- pthread_mutex_unlock (& c -> instr_lock );
308+ pthread_mutex_unlock (& ( c -> instr_lock ) );
252309 return LIBMK_SUCCESS ;
253310}
0 commit comments