@@ -25,6 +25,9 @@ def __init__(self, port):
25
25
self .mode (6 )
26
26
self .avg_reads = 4
27
27
self ._old_color = None
28
+ self ._ir_channel = 0x0
29
+ self ._ir_address = 0x0
30
+ self ._ir_toggle = 0x0
28
31
29
32
def segment_color (self , r , g , b ):
30
33
"""Return the color name from HSV
@@ -197,6 +200,337 @@ def wait_for_new_color(self):
197
200
self .callback (None )
198
201
return self ._old_color
199
202
203
+ @property
204
+ def ir_channel (self ):
205
+ return self ._ir_channel
206
+
207
+ @ir_channel .setter
208
+ def ir_channel (self , channel = 1 ):
209
+ """
210
+ Set the IR channel for RC Tx
211
+
212
+ :param channel: 1-4 indicating the selected IR channel on the reciever
213
+ """
214
+ check_chan = channel
215
+ if check_chan > 4 :
216
+ check_chan = 4
217
+ elif check_chan < 1 :
218
+ check_chan = 1
219
+ # Internally: 0-3
220
+ self ._ir_channel = int (check_chan )- 1
221
+
222
+ @property
223
+ def ir_address (self ):
224
+ """
225
+ IR Address space of 0x0 for default PoweredUp or 0x1 for extra space
226
+ """
227
+ return self ._ir_address
228
+
229
+ def toggle_ir_toggle (self ):
230
+ """
231
+ Toggle the IR toggle bit
232
+
233
+ """
234
+ # IYKYK, because the RC documents are not clear
235
+ if self ._ir_toggle :
236
+ self ._ir_toggle = 0x0
237
+ else :
238
+ self ._ir_toggle = 0x1
239
+ return self ._ir_toggle
240
+
241
+ def send_ir_sop (self , port , mode ):
242
+ """
243
+ Send an IR message via Power Functions RC Protocol in Single Output PWM mode
244
+ https://www.philohome.com/pf/pf.htm
245
+
246
+ Port B is blue
247
+
248
+ Valid values for mode are:
249
+ 0x0: Float output
250
+ 0x1: Forward/Clockwise at speed 1
251
+ 0x2: Forward/Clockwise at speed 2
252
+ 0x3: Forward/Clockwise at speed 3
253
+ 0x4: Forward/Clockwise at speed 4
254
+ 0x5: Forward/Clockwise at speed 5
255
+ 0x6: Forward/Clockwise at speed 6
256
+ 0x7: Forward/Clockwise at speed 7
257
+ 0x8: Brake (then float v1.20)
258
+ 0x9: Backwards/Counterclockwise at speed 7
259
+ 0xA: Backwards/Counterclockwise at speed 6
260
+ 0xB: Backwards/Counterclockwise at speed 5
261
+ 0xC: Backwards/Counterclockwise at speed 4
262
+ 0xD: Backwards/Counterclockwise at speed 3
263
+ 0xE: Backwards/Counterclockwise at speed 2
264
+ 0xF: Backwards/Counterclockwise at speed 1
265
+
266
+ :param port: 'A' or 'B'
267
+ :param mode: 0-15 indicating the port's mode to set
268
+ """
269
+ escape_modeselect = 0x0
270
+ escape = escape_modeselect
271
+
272
+ ir_mode_single_output = 0x4
273
+ ir_mode = ir_mode_single_output
274
+
275
+ so_mode_pwm = 0x0
276
+ so_mode = so_mode_pwm
277
+
278
+ output_port_a = 0x0
279
+ output_port_b = 0x1
280
+
281
+ output_port = None
282
+ if port == 'A' or port == 'a' :
283
+ output_port = output_port_a
284
+ elif port == 'B' or port == 'b' :
285
+ output_port = output_port_b
286
+ else :
287
+ return False
288
+
289
+ ir_mode = ir_mode | (so_mode << 1 ) | output_port
290
+
291
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
292
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
293
+
294
+ # Mode range checked here
295
+ return self ._send_ir_nibbles (nibble1 , nibble2 , mode )
296
+
297
+ def send_ir_socstid (self , port , mode ):
298
+ """
299
+ Send an IR message via Power Functions RC Protocol in Single Output Clear/Set/Toggle/Increment/Decrement mode
300
+ https://www.philohome.com/pf/pf.htm
301
+
302
+ Valid values for mode are:
303
+ 0x0: Toggle full Clockwise/Forward (Stop to Clockwise, Clockwise to Stop, Counterclockwise to Clockwise)
304
+ 0x1: Toggle direction
305
+ 0x2: Increment numerical PWM
306
+ 0x3: Decrement numerical PWM
307
+ 0x4: Increment PWM
308
+ 0x5: Decrement PWM
309
+ 0x6: Full Clockwise/Forward
310
+ 0x7: Full Counterclockwise/Backward
311
+ 0x8: Toggle full (defaults to Forward, first)
312
+ 0x9: Clear C1 (C1 to High)
313
+ 0xA: Set C1 (C1 to Low)
314
+ 0xB: Toggle C1
315
+ 0xC: Clear C2 (C2 to High)
316
+ 0xD: Set C2 (C2 to Low)
317
+ 0xE: Toggle C2
318
+ 0xF: Toggle full Counterclockwise/Backward (Stop to Clockwise, Counterclockwise to Stop, Clockwise to Counterclockwise)
319
+
320
+ :param port: 'A' or 'B'
321
+ :param mode: 0-15 indicating the port's mode to set
322
+ """
323
+
324
+ escape_modeselect = 0x0
325
+ escape = escape_modeselect
326
+
327
+ ir_mode_single_output = 0x4
328
+ ir_mode = ir_mode_single_output
329
+
330
+ so_mode_cstid = 0x1
331
+ so_mode = so_mode_cstid
332
+
333
+ output_port_a = 0x0
334
+ output_port_b = 0x1
335
+
336
+ output_port = None
337
+ if port == 'A' or port == 'a' :
338
+ output_port = output_port_a
339
+ elif port == 'B' or port == 'b' :
340
+ output_port = output_port_b
341
+ else :
342
+ return False
343
+
344
+ ir_mode = ir_mode | (so_mode << 1 ) | output_port
345
+
346
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
347
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
348
+
349
+ # Mode range checked here
350
+ return self ._send_ir_nibbles (nibble1 , nibble2 , mode )
351
+
352
+ def send_ir_combo_pwm (self , port_b_mode , port_a_mode ):
353
+ """
354
+ Send an IR message via Power Functions RC Protocol in Combo PWM mode
355
+ https://www.philohome.com/pf/pf.htm
356
+
357
+ Valid values for the modes are:
358
+ 0x0 Float
359
+ 0x1 PWM Forward step 1
360
+ 0x2 PWM Forward step 2
361
+ 0x3 PWM Forward step 3
362
+ 0x4 PWM Forward step 4
363
+ 0x5 PWM Forward step 5
364
+ 0x6 PWM Forward step 6
365
+ 0x7 PWM Forward step 7
366
+ 0x8 Brake (then float v1.20)
367
+ 0x9 PWM Backward step 7
368
+ 0xA PWM Backward step 6
369
+ 0xB PWM Backward step 5
370
+ 0xC PWM Backward step 4
371
+ 0xD PWM Backward step 3
372
+ 0xE PWM Backward step 2
373
+ 0xF PWM Backward step 1
374
+
375
+ :param port_b_mode: 0-15 indicating the command to send to port B
376
+ :param port_a_mode: 0-15 indicating the command to send to port A
377
+ """
378
+
379
+ escape_combo_pwm = 0x1
380
+ escape = escape_combo_pwm
381
+
382
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
383
+
384
+ # Port modes are range checked here
385
+ return self ._send_ir_nibbles (nibble1 , port_b_mode , port_a_mode )
386
+
387
+ def send_ir_combo_direct (self , port_b_output , port_a_output ):
388
+ """
389
+ Send an IR message via Power Functions RC Protocol in Combo Direct mode
390
+ https://www.philohome.com/pf/pf.htm
391
+
392
+ Valid values for the output variables are:
393
+ 0x0: Float output
394
+ 0x1: Clockwise/Forward
395
+ 0x2: Counterclockwise/Backwards
396
+ 0x3: Brake then float
397
+
398
+ :param port_b_output: 0-3 indicating the output to send to port B
399
+ :param port_a_output: 0-3 indicating the output to send to port A
400
+ """
401
+ escape_modeselect = 0x0
402
+ escape = escape_modeselect
403
+
404
+ ir_mode_combo_direct = 0x1
405
+ ir_mode = ir_mode_combo_direct
406
+
407
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
408
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
409
+
410
+ if port_b_output > 0x3 or port_a_output > 0x3 :
411
+ return False
412
+ if port_b_output < 0x0 or port_a_output < 0x0 :
413
+ return False
414
+
415
+ nibble3 = (port_b_output << 2 ) | port_a_output
416
+
417
+ return self ._send_ir_nibbles (nibble1 , nibble2 , nibble3 )
418
+
419
+ def send_ir_extended (self , mode ):
420
+ """
421
+ Send an IR message via Power Functions RC Protocol in Extended mode
422
+ https://www.philohome.com/pf/pf.htm
423
+
424
+ Valid values for the mode are:
425
+ 0x0: Brake Port A (timeout)
426
+ 0x1: Increment Speed on Port A
427
+ 0x2: Decrement Speed on Port A
428
+
429
+ 0x4: Toggle Forward/Clockwise/Float on Port B
430
+
431
+ 0x6: Toggle Address bit
432
+ 0x7: Align toggle bit
433
+
434
+ :param mode: 0-2,4,6-7
435
+ """
436
+ escape_modeselect = 0x0
437
+ escape = escape_modeselect
438
+
439
+ ir_mode_extended = 0x0
440
+ ir_mode = ir_mode_extended
441
+
442
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
443
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
444
+
445
+ if mode < 0x0 or mode == 0x3 or mode == 0x5 or mode > 0x7 :
446
+ return False
447
+
448
+ return self ._send_ir_nibbles (nibble1 , nibble2 , mode )
449
+
450
+ def send_ir_single_pin (self , port , pin , mode , timeout ):
451
+ """
452
+ Send an IR message via Power Functions RC Protocol in Single Pin mode
453
+ https://www.philohome.com/pf/pf.htm
454
+
455
+ Valid values for the mode are:
456
+ 0x0: No-op
457
+ 0x1: Clear
458
+ 0x2: Set
459
+ 0x3: Toggle
460
+
461
+ Note: The unlabeled IR receiver (vs the one labeled V2) has a "firmware bug in Single Pin mode"
462
+ https://www.philohome.com/pfrec/pfrec.htm
463
+
464
+ :param port: 'A' or 'B'
465
+ :param pin: 1 or 2
466
+ :param mode: 0-3 indicating the pin's mode to set
467
+ :param timeout: True or False
468
+ """
469
+ escape_mode = 0x0
470
+ escape = escape_mode
471
+
472
+ ir_mode_single_continuous = 0x2
473
+ ir_mode_single_timeout = 0x3
474
+ ir_mode = None
475
+ if timeout :
476
+ ir_mode = ir_mode_single_timeout
477
+ else :
478
+ ir_mode = ir_mode_single_continuous
479
+
480
+ output_port_a = 0x0
481
+ output_port_b = 0x1
482
+
483
+ output_port = None
484
+ if port == 'A' or port == 'a' :
485
+ output_port = output_port_a
486
+ elif port == 'B' or port == 'b' :
487
+ output_port = output_port_b
488
+ else :
489
+ return False
490
+
491
+ if pin != 1 and pin != 2 :
492
+ return False
493
+ pin_value = pin - 1
494
+
495
+ if mode > 0x3 or mode < 0x0 :
496
+ return False
497
+
498
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
499
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
500
+ nibble3 = (output_port << 3 ) | (pin_value << 3 ) | mode
501
+
502
+ return self ._send_ir_nibbles (nibble1 , nibble2 , mode )
503
+
504
+ def _send_ir_nibbles (self , nibble1 , nibble2 , nibble3 ):
505
+
506
+ # M7 IR Tx SI = N/A
507
+ # format count=1 type=1 chars=5 dp=0
508
+ # RAW: 00000000 0000FFFF PCT: 00000000 00000064 SI: 00000000 0000FFFF
509
+
510
+ mode = 7
511
+ self .mode (mode )
512
+
513
+ # The upper bits of data[2] are ignored
514
+ if nibble1 > 0xF or nibble2 > 0xF or nibble3 > 0xF :
515
+ return False
516
+ if nibble1 < 0x0 or nibble2 < 0x0 or nibble3 < 0x0 :
517
+ return False
518
+
519
+ byte_two = (nibble2 << 4 ) | nibble3
520
+
521
+ data = bytearray (3 )
522
+ data [0 ] = (0xc << 4 ) | mode
523
+ data [1 ] = byte_two
524
+ data [2 ] = nibble1
525
+
526
+ # print(" ".join('{:04b}'.format(nibble1)))
527
+ # print(" ".join('{:04b}'.format(nibble2)))
528
+ # print(" ".join('{:04b}'.format(nibble3)))
529
+ # print(" ".join('{:08b}'.format(n) for n in data))
530
+
531
+ self ._write1 (data )
532
+ return True
533
+
200
534
def on (self ):
201
535
"""Turn on the sensor and LED"""
202
536
self .reverse ()
0 commit comments