@@ -27,11 +27,14 @@ PatriotViperController::PatriotViperController(i2c_smbus_interface* bus, viper_d
2727 led_count += 5 ;
2828 }
2929 }
30+
31+ keepalive_thread = NULL ;
32+ keepalive_thread_run = 1 ;
3033}
3134
3235PatriotViperController::~PatriotViperController ()
3336{
34-
37+ StopKeepaliveThread ();
3538}
3639
3740std::string PatriotViperController::GetDeviceName ()
@@ -92,26 +95,16 @@ void PatriotViperController::SetEffectColor(unsigned char red, unsigned char gre
9295
9396void PatriotViperController::SetAllColors (unsigned char red, unsigned char green, unsigned char blue)
9497{
95- ViperRegisterWrite (VIPER_REG_START, 0xFF , 0xFF , 0xFF );
96- ViperRegisterWrite (VIPER_REG_STATIC, 0x04 , 0x00 , 0x00 );
97-
98- ViperRegisterWrite (VIPER_REG_LED0_DIRECT_COLOR, red, blue, green);
99- ViperRegisterWrite (VIPER_REG_LED1_DIRECT_COLOR, red, blue, green);
100- ViperRegisterWrite (VIPER_REG_LED2_DIRECT_COLOR, red, blue, green);
101- ViperRegisterWrite (VIPER_REG_LED3_DIRECT_COLOR, red, blue, green);
102- ViperRegisterWrite (VIPER_REG_LED4_DIRECT_COLOR, red, blue, green);
103-
104- ViperRegisterWrite (VIPER_REG_APPLY, 0x01 , 0x00 , 0x00 );
98+ ViperRegisterWrite (VIPER_REG_LED0_EFFECT_COLOR, red, blue, green);
99+ ViperRegisterWrite (VIPER_REG_LED1_EFFECT_COLOR, red, blue, green);
100+ ViperRegisterWrite (VIPER_REG_LED2_EFFECT_COLOR, red, blue, green);
101+ ViperRegisterWrite (VIPER_REG_LED3_EFFECT_COLOR, red, blue, green);
102+ ViperRegisterWrite (VIPER_REG_LED4_EFFECT_COLOR, red, blue, green);
105103}
106104
107105void PatriotViperController::SetLEDColor (unsigned int led, unsigned char red, unsigned char green, unsigned char blue)
108106{
109- ViperRegisterWrite (VIPER_REG_START, 0xFF , 0xFF , 0xFF );
110- ViperRegisterWrite (VIPER_REG_STATIC, 0x04 , 0x00 , 0x00 );
111-
112- ViperRegisterWrite (VIPER_REG_LED0_DIRECT_COLOR + led, red, blue, green);
113-
114- ViperRegisterWrite (VIPER_REG_APPLY, 0x01 , 0x00 , 0x00 );
107+ ViperRegisterWrite (VIPER_REG_LED0_EFFECT_COLOR + led, red, blue, green);
115108}
116109
117110void PatriotViperController::SetLEDEffectColor (unsigned int led, unsigned char red, unsigned char green, unsigned char blue)
@@ -148,29 +141,198 @@ void PatriotViperController::SetLEDEffectColor(unsigned int /*slot*/, unsigned i
148141 ViperRegisterWrite (VIPER_REG_MODE, 0xFA , 0x00 , 0x00 );
149142}
150143
151- void PatriotViperController::SetMode (unsigned char new_mode, unsigned char new_speed)
144+ void PatriotViperController::SetMode (unsigned char new_mode, unsigned char new_speed, unsigned int color_mode )
152145{
146+ StopKeepaliveThread ();
153147 direct = false ;
154148 mode = new_mode;
155- speed = new_speed;
149+ if (mode_speed[mode] == -1 )
150+ {
151+ speed = new_speed;
152+ }
153+ else
154+ {
155+ speed = mode_speed[mode];
156+ }
156157
157- ViperRegisterWrite (VIPER_REG_START, 0xFF , 0xFF , 0xFF );
158- ViperRegisterWrite (VIPER_REG_STATIC, 0x04 , 0x00 , 0x00 );
159- ViperRegisterWrite (VIPER_REG_MODE, mode, 0x00 , speed);
160- ViperRegisterWrite (VIPER_REG_MODE, 0xAA , 0x00 , 0x00 );
161- ViperRegisterWrite (VIPER_REG_MODE, 0xFA , 0x00 , 0x00 );
158+ if (color_mode == 3 )
159+ {
160+ /* --------------------------------------------------------------------------------------------------*\
161+ | Reset previously set mode color, because we want RAM sticks to fall-back to automatic viper colors |
162+ | These are not just rainbowey, but they are affected differently with modes. |
163+ \*--------------------------------------------------------------------------------------------------*/
164+
165+ ViperRegisterWrite (VIPER_REG_START, 0xFF , 0xFF , 0xFF );
166+ ViperRegisterWrite (VIPER_REG_STATIC, 0x04 , 0x00 , 0x00 );
167+ ViperRegisterWrite (VIPER_REG_MODE, VIPER_MODE_DARK, 0x00 , 0x00 );
168+ ViperRegisterWrite (VIPER_REG_MODE, 0xAA , 0x00 , 0x00 );
169+ ViperRegisterWrite (VIPER_REG_MODE, 0xFA , 0x00 , 0x00 );
170+ }
171+
172+ if (mode_steps[mode] == -1 )
173+ {
174+ /* --------------------------------------------------------------------------------------------------*\
175+ | Based on a header file, if number of steps in mode is -1 it means mode is not synced, |
176+ | doesn't have steps and the Keepalive thread is not needed. Set the mode directly and leave it. |
177+ \*--------------------------------------------------------------------------------------------------*/
178+
179+ ViperRegisterWrite (VIPER_REG_START, 0xFF , 0xFF , 0xFF );
180+ ViperRegisterWrite (VIPER_REG_STATIC, 0x04 , 0x00 , 0x00 );
181+ ViperRegisterWrite (VIPER_REG_MODE, mode, 0x00 , speed);
182+ ViperRegisterWrite (VIPER_REG_MODE, 0xAA , 0x00 , 0x00 );
183+ ViperRegisterWrite (VIPER_REG_MODE, 0xFA , 0x00 , 0x00 );
184+ }
185+ else
186+ {
187+ /* ----------------------------------------------------------------*\
188+ | Reset step counters and fire up Keepalive thread. |
189+ | Thread will deal with changing the mode and everything else. |
190+ \*----------------------------------------------------------------*/
191+
192+ step = 0 ;
193+ sub_step = 0 ;
194+
195+ keepalive_thread = new std::thread (&PatriotViperController::KeepaliveThread, this );
196+ }
162197}
163198
164199void PatriotViperController::SetDirect ()
165200{
201+ StopKeepaliveThread ();
166202 direct = true ;
167203 ViperRegisterWrite (VIPER_REG_START, 0xFF , 0xFF , 0xFF );
168204 ViperRegisterWrite (VIPER_REG_STATIC, 0x04 , 0x00 , 0x00 );
169- ViperRegisterWrite (VIPER_REG_APPLY, 0x01 , 0x00 , 0x00 );
205+ ViperRegisterWrite (VIPER_REG_MODE, VIPER_MODE_DIRECT , 0x00 , 0x00 );
170206}
171207
172208void PatriotViperController::ViperRegisterWrite (viper_register reg, unsigned char val0, unsigned char val1, unsigned char val2)
173209{
174210 bus->i2c_smbus_write_byte_data (dev, reg, val0);
175211 bus->i2c_smbus_write_byte_data (dev, val2, val1);
176212}
213+
214+ void PatriotViperController::KeepaliveThread ()
215+ {
216+ while (keepalive_thread_run.load ())
217+ {
218+ int cur_step = step.load ();
219+ int cur_sub_step = sub_step.load ();
220+ if (cur_sub_step == 0 )
221+ {
222+ ViperRegisterWrite (VIPER_REG_MODE, mode, cur_step, speed);
223+ ViperRegisterWrite (VIPER_REG_MODE, 0xAA , 0x00 , cur_sub_step);
224+ }
225+ else
226+ {
227+ ViperRegisterWrite (VIPER_REG_MODE, 0xAA , 0x00 , cur_sub_step);
228+ }
229+
230+ if (cur_sub_step == mode_sub_steps[mode])
231+ {
232+ sub_step.store (0 );
233+
234+ if (cur_step == mode_steps[mode])
235+ {
236+ step.store (0 );
237+ }
238+ else
239+ {
240+ step.store (cur_step+1 );
241+ }
242+ }
243+ else
244+ {
245+ sub_step.store (cur_sub_step+1 );
246+ }
247+
248+ /* ---------------------------------------------------------------------------------------------------------*\
249+ | We have to use wait_for with condition_variable since some of the modes will keep the thread waiting for |
250+ | long time and we don't want to make user wait for mode change when in middle of waiting period. |
251+ \*---------------------------------------------------------------------------------------------------------*/
252+ int delay = GetDelay (mode, cur_step, cur_sub_step, cur_sub_step == mode_sub_steps[mode]);
253+ std::unique_lock<std::mutex> l (thread_ctrl_m);
254+ thread_ctrl.wait_for (l, std::chrono::milliseconds (delay));
255+ }
256+ }
257+
258+ void PatriotViperController::StopKeepaliveThread ()
259+ {
260+ if (keepalive_thread != NULL )
261+ {
262+ keepalive_thread_run = 0 ;
263+ thread_ctrl.notify_one ();
264+ keepalive_thread->join ();
265+ keepalive_thread = NULL ;
266+ keepalive_thread_run = 1 ;
267+ }
268+ }
269+
270+ unsigned int PatriotViperController::GetDelay (unsigned char mode, unsigned int step, unsigned int sub_step, bool loop_end)
271+ {
272+ if (loop_end)
273+ {
274+ if (mode == VIPER_MODE_VIPER)
275+ {
276+ return 7000 ;
277+ }
278+ else if (mode == VIPER_MODE_BREATHING)
279+ {
280+ return 3000 ;
281+ }
282+ else if (mode == VIPER_MODE_NEON)
283+ {
284+ return 600 ;
285+ }
286+ else if (mode == VIPER_MODE_AURORA)
287+ {
288+ return 300 ;
289+ }
290+ else
291+ {
292+ return 0 ;
293+ }
294+ }
295+
296+ if (sub_step == 0 )
297+ {
298+ if (mode == VIPER_MODE_VIPER)
299+ {
300+ return 3000 ;
301+ }
302+ else if (mode == VIPER_MODE_BREATHING)
303+ {
304+ return 3000 ;
305+ }
306+ else
307+ {
308+ return 0 ;
309+ }
310+ }
311+ else
312+ {
313+ if (sub_step == 4 && mode == VIPER_MODE_VIPER)
314+ {
315+ return 1000 ;
316+ }
317+ else if (sub_step == 5 && mode == VIPER_MODE_VIPER)
318+ {
319+ return 590 ;
320+ }
321+ else if (mode == VIPER_MODE_NEON)
322+ {
323+ return 600 ;
324+ }
325+ else if (mode == VIPER_MODE_HEARTBEAT)
326+ {
327+ return 100 ;
328+ }
329+ else if (mode == VIPER_MODE_MARQUEE)
330+ {
331+ return 300 ;
332+ }
333+ else
334+ {
335+ return 0 ;
336+ }
337+ }
338+ }
0 commit comments