@@ -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
+ """Get the IR channel for message transmission"""
206
+ return self ._ir_channel
207
+
208
+ @ir_channel .setter
209
+ def ir_channel (self , channel = 1 ):
210
+ """
211
+ Set the IR channel for RC Tx
212
+
213
+ :param channel: 1-4 indicating the selected IR channel on the reciever
214
+ """
215
+ check_chan = channel
216
+ if check_chan > 4 :
217
+ check_chan = 4
218
+ elif check_chan < 1 :
219
+ check_chan = 1
220
+ # Internally: 0-3
221
+ self ._ir_channel = int (check_chan ) - 1
222
+
223
+ @property
224
+ def ir_address (self ):
225
+ """IR Address space of 0x0 for default PoweredUp or 0x1 for extra space"""
226
+ return self ._ir_address
227
+
228
+ def toggle_ir_toggle (self ):
229
+ """Toggle the IR toggle bit"""
230
+ # IYKYK, because the RC documents are not clear
231
+ if self ._ir_toggle :
232
+ self ._ir_toggle = 0x0
233
+ else :
234
+ self ._ir_toggle = 0x1
235
+ return self ._ir_toggle
236
+
237
+ def send_ir_sop (self , port , mode ):
238
+ """
239
+ Send an IR message via Power Functions RC Protocol in Single Output PWM mode
240
+
241
+ PF IR RC Protocol documented at https://www.philohome.com/pf/pf.htm
242
+
243
+ Port B is blue
244
+
245
+ Valid values for mode are:
246
+ 0x0: Float output
247
+ 0x1: Forward/Clockwise at speed 1
248
+ 0x2: Forward/Clockwise at speed 2
249
+ 0x3: Forward/Clockwise at speed 3
250
+ 0x4: Forward/Clockwise at speed 4
251
+ 0x5: Forward/Clockwise at speed 5
252
+ 0x6: Forward/Clockwise at speed 6
253
+ 0x7: Forward/Clockwise at speed 7
254
+ 0x8: Brake (then float v1.20)
255
+ 0x9: Backwards/Counterclockwise at speed 7
256
+ 0xA: Backwards/Counterclockwise at speed 6
257
+ 0xB: Backwards/Counterclockwise at speed 5
258
+ 0xC: Backwards/Counterclockwise at speed 4
259
+ 0xD: Backwards/Counterclockwise at speed 3
260
+ 0xE: Backwards/Counterclockwise at speed 2
261
+ 0xF: Backwards/Counterclockwise at speed 1
262
+
263
+ :param port: 'A' or 'B'
264
+ :param mode: 0-15 indicating the port's mode to set
265
+ """
266
+ escape_modeselect = 0x0
267
+ escape = escape_modeselect
268
+
269
+ ir_mode_single_output = 0x4
270
+ ir_mode = ir_mode_single_output
271
+
272
+ so_mode_pwm = 0x0
273
+ so_mode = so_mode_pwm
274
+
275
+ output_port_a = 0x0
276
+ output_port_b = 0x1
277
+
278
+ output_port = None
279
+ if port == 'A' or port == 'a' :
280
+ output_port = output_port_a
281
+ elif port == 'B' or port == 'b' :
282
+ output_port = output_port_b
283
+ else :
284
+ return False
285
+
286
+ ir_mode = ir_mode | (so_mode << 1 ) | output_port
287
+
288
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
289
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
290
+
291
+ # Mode range checked here
292
+ return self ._send_ir_nibbles (nibble1 , nibble2 , mode )
293
+
294
+ def send_ir_socstid (self , port , mode ):
295
+ """
296
+ Send an IR message via Power Functions RC Protocol in Single Output Clear/Set/Toggle/Increment/Decrement mode
297
+
298
+ PF IR RC Protocol documented at https://www.philohome.com/pf/pf.htm
299
+
300
+ Valid values for mode are:
301
+ 0x0: Toggle full Clockwise/Forward (Stop to Clockwise, Clockwise to Stop, Counterclockwise to Clockwise)
302
+ 0x1: Toggle direction
303
+ 0x2: Increment numerical PWM
304
+ 0x3: Decrement numerical PWM
305
+ 0x4: Increment PWM
306
+ 0x5: Decrement PWM
307
+ 0x6: Full Clockwise/Forward
308
+ 0x7: Full Counterclockwise/Backward
309
+ 0x8: Toggle full (defaults to Forward, first)
310
+ 0x9: Clear C1 (C1 to High)
311
+ 0xA: Set C1 (C1 to Low)
312
+ 0xB: Toggle C1
313
+ 0xC: Clear C2 (C2 to High)
314
+ 0xD: Set C2 (C2 to Low)
315
+ 0xE: Toggle C2
316
+ 0xF: Toggle full Counterclockwise/Backward (Stop to Clockwise, Counterclockwise to Stop, Clockwise to Counterclockwise)
317
+
318
+ :param port: 'A' or 'B'
319
+ :param mode: 0-15 indicating the port's mode to set
320
+ """
321
+ escape_modeselect = 0x0
322
+ escape = escape_modeselect
323
+
324
+ ir_mode_single_output = 0x4
325
+ ir_mode = ir_mode_single_output
326
+
327
+ so_mode_cstid = 0x1
328
+ so_mode = so_mode_cstid
329
+
330
+ output_port_a = 0x0
331
+ output_port_b = 0x1
332
+
333
+ output_port = None
334
+ if port == 'A' or port == 'a' :
335
+ output_port = output_port_a
336
+ elif port == 'B' or port == 'b' :
337
+ output_port = output_port_b
338
+ else :
339
+ return False
340
+
341
+ ir_mode = ir_mode | (so_mode << 1 ) | output_port
342
+
343
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
344
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
345
+
346
+ # Mode range checked here
347
+ return self ._send_ir_nibbles (nibble1 , nibble2 , mode )
348
+
349
+ def send_ir_combo_pwm (self , port_b_mode , port_a_mode ):
350
+ """
351
+ Send an IR message via Power Functions RC Protocol in Combo PWM mode
352
+
353
+ PF IR RC Protocol documented at https://www.philohome.com/pf/pf.htm
354
+
355
+ Valid values for the modes are:
356
+ 0x0 Float
357
+ 0x1 PWM Forward step 1
358
+ 0x2 PWM Forward step 2
359
+ 0x3 PWM Forward step 3
360
+ 0x4 PWM Forward step 4
361
+ 0x5 PWM Forward step 5
362
+ 0x6 PWM Forward step 6
363
+ 0x7 PWM Forward step 7
364
+ 0x8 Brake (then float v1.20)
365
+ 0x9 PWM Backward step 7
366
+ 0xA PWM Backward step 6
367
+ 0xB PWM Backward step 5
368
+ 0xC PWM Backward step 4
369
+ 0xD PWM Backward step 3
370
+ 0xE PWM Backward step 2
371
+ 0xF PWM Backward step 1
372
+
373
+ :param port_b_mode: 0-15 indicating the command to send to port B
374
+ :param port_a_mode: 0-15 indicating the command to send to port A
375
+ """
376
+ escape_combo_pwm = 0x1
377
+ escape = escape_combo_pwm
378
+
379
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
380
+
381
+ # Port modes are range checked here
382
+ return self ._send_ir_nibbles (nibble1 , port_b_mode , port_a_mode )
383
+
384
+ def send_ir_combo_direct (self , port_b_output , port_a_output ):
385
+ """
386
+ Send an IR message via Power Functions RC Protocol in Combo Direct mode
387
+
388
+ PF IR RC Protocol documented at https://www.philohome.com/pf/pf.htm
389
+
390
+ Valid values for the output variables are:
391
+ 0x0: Float output
392
+ 0x1: Clockwise/Forward
393
+ 0x2: Counterclockwise/Backwards
394
+ 0x3: Brake then float
395
+
396
+ :param port_b_output: 0-3 indicating the output to send to port B
397
+ :param port_a_output: 0-3 indicating the output to send to port A
398
+ """
399
+ escape_modeselect = 0x0
400
+ escape = escape_modeselect
401
+
402
+ ir_mode_combo_direct = 0x1
403
+ ir_mode = ir_mode_combo_direct
404
+
405
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
406
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
407
+
408
+ if port_b_output > 0x3 or port_a_output > 0x3 :
409
+ return False
410
+ if port_b_output < 0x0 or port_a_output < 0x0 :
411
+ return False
412
+
413
+ nibble3 = (port_b_output << 2 ) | port_a_output
414
+
415
+ return self ._send_ir_nibbles (nibble1 , nibble2 , nibble3 )
416
+
417
+ def send_ir_extended (self , mode ):
418
+ """
419
+ Send an IR message via Power Functions RC Protocol in Extended mode
420
+
421
+ PF IR RC Protocol documented at https://www.philohome.com/pf/pf.htm
422
+
423
+ Valid values for the mode are:
424
+ 0x0: Brake Port A (timeout)
425
+ 0x1: Increment Speed on Port A
426
+ 0x2: Decrement Speed on Port A
427
+
428
+ 0x4: Toggle Forward/Clockwise/Float on Port B
429
+
430
+ 0x6: Toggle Address bit
431
+ 0x7: Align toggle bit
432
+
433
+ :param mode: 0-2,4,6-7
434
+ """
435
+ escape_modeselect = 0x0
436
+ escape = escape_modeselect
437
+
438
+ ir_mode_extended = 0x0
439
+ ir_mode = ir_mode_extended
440
+
441
+ nibble1 = (self ._ir_toggle << 3 ) | (escape << 2 ) | self ._ir_channel
442
+ nibble2 = (self ._ir_address << 3 ) | ir_mode
443
+
444
+ if mode < 0x0 or mode == 0x3 or mode == 0x5 or mode > 0x7 :
445
+ return False
446
+
447
+ return self ._send_ir_nibbles (nibble1 , nibble2 , mode )
448
+
449
+ def send_ir_single_pin (self , port , pin , mode , timeout ):
450
+ """
451
+ Send an IR message via Power Functions RC Protocol in Single Pin mode
452
+
453
+ PF IR RC Protocol documented at 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 , nibble3 )
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