forked from Ho-Ro/ComponentTester
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIR_TX.c
1714 lines (1418 loc) · 53.8 KB
/
IR_TX.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* ************************************************************************
*
* IR remote control: sender
*
* (c) 2015-2021 by Markus Reschke
*
* ************************************************************************ */
/* local includes */
#include "config.h" /* global configuration */
#ifdef SW_IR_TRANSMITTER
/*
* local constants
*/
/* source management */
#define IR_TX_C
/*
* include header files
*/
/* local includes */
#include "common.h" /* common header file */
#include "variables.h" /* global variables */
#include "functions.h" /* external functions */
/*
* local constants
*/
/* IR protocols */
/* basic protocols */
#define IR_JVC 1 /* JVC C8D8 */
#define IR_KASEIKYO 2 /* Kaseikyo (Japanese Code) */
#define IR_MATSUSHITA 3 /* Matsushita (Panasonic) */
#define IR_MOTOROLA 4 /* Motorola */
#define IR_NEC_STD 5 /* NEC standard */
#define IR_NEC_EXT 6 /* NEC extended */
#define IR_PROTON 7 /* Proton (Mitsubishi) */
#define IR_RC5 8 /* RC-5 Standard */
#define IR_RC6 9 /* RC-6 Standard, Mode 0 */
#define IR_SAMSUNG 10 /* Samsung / Toshiba */
#define IR_SHARP 11 /* Sharp (Denon) */
#define IR_SIRC_12 12 /* Sony SIRC-12 */
#define IR_SIRC_15 13 /* Sony SIRC-15 */
#define IR_SIRC_20 14 /* Sony SIRC-20 */
/* extra protocols */
#define IR_THOMSON 15 /* Thomson */
#ifndef SW_IR_TX_EXTRA
#define IR_PROTO_MAX 14 /* number of basic protocols */
#else
#define IR_PROTO_MAX 15 /* number of all protocols */
#endif
/* code bit mode */
#define IR_LSB 1 /* LSB */
#define IR_MSB 2 /* MSB */
/* bi-phase modes (bitfield) */
#define IR_IEEE 0b00000001 /* IEEE bit encoding */
#define IR_THOMAS 0b00000010 /* Thomas bit encoding */
#define IR_PRE_PAUSE 0b00000100 /* heading pause */
/* signal types */
#define IR_PAUSE 0b00000001 /* pause */
#define IR_PULSE 0b00000010 /* pulse */
/*
* local variables
*/
/* key toggle feature */
uint8_t IR_Toggle = 0; /* key toggle flag */
/* ************************************************************************
* IR remote control tool (sender)
* ************************************************************************ */
/*
* send single pause/pulse
*
* requires:
* - type: IR_PAUSE or IR_PULSE
* - time: duration in µs
*/
void IR_Send_Pulse(uint8_t Type, uint16_t Time)
{
if (Type & IR_PULSE) /* create pulse */
{
/* enable output via OC1B pin */
TCCR1A = (1 << WGM11) | (1 << WGM10) | (1 << COM1B1);
/* start Timer1 for carrier frequency */
TCNT1 = 0; /* set counter to 0 */
/* enable Timer1 by setting prescaler 1:1 */
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
}
/*
* wait (delay loop)
* - loop (without NOPs) burns 7 cycles per run and 4 cycles for last run
* - total (without NOPs): 7 cycles * Time + 4 cycles
* - add NOPs for 1µs
* - don't care about missing cycles of last run
*/
#ifndef SW_IR_TX_ALTDELAY
while (Time > 0)
{
#if CPU_FREQ == 8000000
/* add 1 cycle (one cycle is 62.5ns) */
asm volatile("nop");
#elif CPU_FREQ == 16000000
/* add 9 cycles (one cycle is 62.5ns) */
asm volatile(
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
::
);
#elif CPU_FREQ == 20000000
/* add 13 cycles (one cycle is 50ns) */
asm volatile(
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
::
);
#else
#error <<< IR_Send_Pulse(): no supported MCU clock >>>
#endif
Time--;
}
#endif
/*
* alternative delay loop
* - provided by Vitaliy
*/
#ifdef SW_IR_TX_ALTDELAY
#include <util/delay.h>
while (Time >= 100) /* 100µs chunks */
{
_delay_us(100);
Time -= 100;
}
while (Time >= 10) /* 10µs chunks */
{
_delay_us(10);
Time -= 10;
}
while (Time > 0) /* 1µs chunks */
{
_delay_us(1);
Time--;
}
#endif
if (Type & IR_PULSE) /* create pulse */
{
/* stop Timer1 */
TCCR1B = (1 << WGM13) | (1 << WGM12); /* clear prescaler */
/* disable output via OC1B pin */
TCCR1A = (1 << WGM11) | (1 << WGM10);
}
}
/*
* send IR code using Bi-Phase modulation
* - similar to Manchester encoding
* - special case of BPSK (binary phase-shift keying)
*
* required:
* - Code: pointer to code data
* - Bits: number of bits in code data
* - Mode:
* IR_IEEE - IEEE
* IR_THOMAS - G.E. Thomas
* - tP: time units of pulse/pause in µs
*/
void IR_Send_BiPhase(uint8_t *Code, uint8_t Bits, uint8_t Mode, uint16_t tP)
{
uint8_t Count; /* bit counter */
uint8_t Byte; /* current code byte */
uint8_t One; /* type of first half for 0 */
uint8_t Zero; /* type of first half for 1 */
/*
* Bi-Phase Modulation:
* - fixed time slot for each bit
* - bit is encoded as a phase shift (H-L or L-H transition)
* - two encoding conventions
* - G.E. Thomas (Manchester II or Biphase-L)
* 0 -> pause - pulse
* 1 -> pulse - pause
* - IEEE 802.3
* 0 -> pulse - pause
* 1 -> pause - pulse
*/
if (Mode & IR_IEEE) /* IEEE */
{
Zero = IR_PULSE; /* 0 starts with pulse */
One = IR_PAUSE; /* 1 starts with pause */
}
else /* Thomas */
{
Zero = IR_PAUSE; /* 0 starts with pause */
One = IR_PULSE; /* 1 starts with pulse */
}
Count = 0; /* reset bit counter */
Byte = *Code; /* get first code byte */
while (Bits > 0) /* loop through bits */
{
if (Byte & 0b10000000) /* bit is 1 */
{
Mode = One; /* set type of first half for 1 */
}
else /* bit is 0 */
{
Mode = Zero; /* set type of first half for 0 */
}
IR_Send_Pulse(Mode, tP); /* send first half */
Mode = ~Mode; /* reverse type */
IR_Send_Pulse(Mode, tP); /* send second half */
Byte <<= 1; /* shift byte one step left */
Count++; /* another bit done */
if (Count == 8) /* complete byte done */
{
Code++; /* next code byte */
Byte = *Code; /* get new code byte */
Count = 0; /* reset bit counter */
}
Bits--; /* next bit */
}
}
/*
* send IR code using PWM
* - Pulse Width Modulation
*
* required:
* - Code: pointer to code data
* - Bits: number of bits in code data
* - tP: time units of pause in µs
* - t0: time units of pulse for 0 in µs
* - t1: time units of pulse for 1 in µs
*/
void IR_Send_PWM(uint8_t *Code, uint8_t Bits, uint16_t tP, uint16_t t0, uint16_t t1)
{
uint8_t Count; /* bit counter */
uint8_t Byte; /* current code byte */
/*
* PWM / pulse encoding:
* - fixed pause time
* - two different pulse times to encode 0/1
*/
Count = 0; /* reset bit counter */
Byte = *Code; /* get first code byte */
while (Bits > 0) /* loop through bits */
{
IR_Send_Pulse(IR_PAUSE, tP); /* send pause */
if (Byte & 0b10000000) /* bit is 1 */
{
IR_Send_Pulse(IR_PULSE, t1); /* send pulse for 1 */
}
else /* bit is 0 */
{
IR_Send_Pulse(IR_PULSE, t0); /* send pulse for 0 */
}
Byte <<= 1; /* shift byte one step left */
Count++; /* another bit done */
if (Count == 8) /* complete byte done */
{
Code++; /* next code byte */
Byte = *Code; /* get new code byte */
Count = 0; /* reset bit counter */
}
Bits--; /* next bit */
}
}
/*
* send IR code using PDM
* - Pulse Distance Modulation
*
* required:
* - Code: pointer to code data
* - Bits: number of bits in code data
* - tP: time units of pulse in µs
* - t0: time units of pause for 0 in µs
* - t1: time units of pause for 1 in µs
*/
void IR_Send_PDM(uint8_t *Code, uint8_t Bits, uint16_t tP, uint16_t t0, uint16_t t1)
{
uint8_t Count; /* bit counter */
uint8_t Byte; /* current code byte */
/*
* PDM / space encoding:
* - fixed pulse time
* - two different pause times to encode 0/1
* - last item is pulse (stop bit)
* required to indicate end of pause of last data bit
*/
Count = 0; /* reset bit counter */
Byte = *Code; /* get first code byte */
while (Bits > 0) /* loop through bits */
{
IR_Send_Pulse(IR_PULSE, tP); /* send pulse */
if (Byte & 0b10000000) /* bit is 1 */
{
IR_Send_Pulse(IR_PAUSE, t1); /* send pause for 1 */
}
else /* bit is 0 */
{
IR_Send_Pulse(IR_PAUSE, t0); /* send pause for 0 */
}
Byte <<= 1; /* shift byte one step left */
Count++; /* another bit done */
if (Count == 8) /* complete byte done */
{
Code++; /* next code byte */
Byte = *Code; /* get new code byte */
Count = 0; /* reset bit counter */
}
Bits--; /* next bit */
}
/* send a stop pulse (to signal end of last pause) */
IR_Send_Pulse(IR_PULSE, tP);
}
/*
* get code timing for PDM/PWM
* - max. time is 65ms
*
* required:
* - Code: pointer to code data
* - Bits: number of bits in code data
* - tP: time units of fixed pulse/pause in µs
* - t0: time units of pulse/pause for 0 in µs
* - t1: time units of pulse/pause for 1 in µs
*
* returns:
* - time in ms
*/
uint16_t CodeTime(uint8_t *Code, uint8_t Bits, uint16_t tP, uint16_t t0, uint16_t t1)
{
uint16_t Time = 0; /* time */
uint8_t Count; /* bit counter */
uint8_t Byte; /* current code byte */
Count = 0; /* reset bit counter */
Byte = *Code; /* get first code byte */
while (Bits > 0) /* loop through bits */
{
Time += tP; /* add time for fixed pulse/pause */
if (Byte & 0b10000000) /* bit is 1 */
{
Time += t1; /* add time for 1 */
}
else /* bit is 0 */
{
Time += t0; /* add time for 0 */
}
Byte <<= 1; /* shift byte one step left */
Count++; /* another bit done */
if (Count == 8) /* complete byte done */
{
Code++; /* next code byte */
Byte = *Code; /* get new code byte */
Count = 0; /* reset bit counter */
}
Bits--; /* next bit */
}
/* todo: for PDM we should add the end pulse */
return Time;
}
/*
* put bits into IR Code
*
* required:
* - Data: source data
* - Bits: number of bits to copy (1-16)
* - StartBit: start bit position in IR Code (1-?)
* - Mode: bit mode
* IR_LSB - LSB
* IR_MSB - MSB
*/
void PutBits(uint16_t Data, uint8_t Bits, uint8_t StartBit, uint8_t Mode)
{
uint8_t *Code; /* pointer to code data */
uint8_t Count; /* bit position in code byte */
uint8_t Byte; /* current code byte */
uint8_t Mask; /* bitmask */
uint8_t n; /* counter */
/*
* IR_Code: bits stored in sending order (bit #7 is first bit to be sent)
* IR_Code[0] is first byte
* LSB: bit #0 of Data goes to bit #7 of IR_Code
* bit #7 of Data goes to bit #0 of IR_Code
* MSB: bit #7 of Data goes to bit #7 of IR_Code
* bit #0 of Data goes to bit #0 of IR_Code
*/
/* determine start position in IR_Code */
StartBit--; /* align */
n = StartBit / 8; /* start byte (0-) */
Count = StartBit % 8; /* start bit in byte (0-7) */
Code = &IR_Code[n]; /* get start address */
Byte = *Code; /* get current code byte */
/* prepare Data for MSB */
if (Mode == IR_MSB) /* MSB mode */
{
n = 16 - Bits; /* unused bits */
Data <<= n; /* shift to left */
}
/* prepare mask */
Mask = 0b10000000; /* reset bitmask */
Mask >>= Count; /* shift 1 to position of start bit */
/* processing loop */
while (Bits > 0) /* loop through bits */
{
if (Mode == IR_LSB) /* LSB mode */
{
if (Data & 0b0000000000000001) /* bit set in data */
{
Byte |= Mask; /* set bit in code byte */
}
else /* bit not set in data */
{
Byte &= ~Mask; /* clear bit in code byte */
}
Data >>= 1; /* shift one bit right */
}
else /* MSB mode */
{
if (Data & 0b1000000000000000) /* bit set in data */
{
Byte |= Mask; /* set bit in code byte */
}
else /* bit not set in data */
{
Byte &= ~Mask; /* clear bit in code byte */
}
Data <<= 1; /* shift one bit left */
}
Mask >>= 1; /* shift one bit right */
Count++; /* next bit position */
Bits--; /* next bit */
if ((Count == 8) || (Bits == 0)) /* byte done or last bit */
{
*Code = Byte; /* save current code byte */
Code++; /* next byte in IR_Code[] */
Byte = *Code; /* get new code byte */
Count = 0; /* start at first bit again */
Mask = 0b10000000; /* reset bitmask */
}
}
}
/*
* send IR code
*
* required:
* - Proto: protocol ID
* - Data: pointer to array of data fields
*/
void IR_Send_Code(uint8_t Proto, uint16_t *Data)
{
uint16_t Temp; /* temporary value */
uint8_t n; /* counter */
/*
* JVC C8D8
* - start: pulse 8.44ms, pause 4.22ms
* - PDM: pulse 525µs, pause 0=525µs 1=1575µs
* - bit mode: LSB
* - stop: pulse 525µs
* - format: <start><address:8><command:8><stop>
* - repeat sequence format: <address:8><command:8><stop>
* - repeat sequence delay is 46.42ms (start to start)
*/
if (Proto == IR_JVC) /* JVC */
{
/* build code */
Temp = *Data; /* Data #0: address */
PutBits(Temp, 8, 1, IR_LSB); /* address, 8 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: command */
PutBits(Temp, 8, 17, IR_LSB); /* command, 8 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 8440); /* start */
IR_Send_Pulse(IR_PAUSE, 4220);
IR_Send_PDM(&IR_Code[0], 16, 525, 525, 1575);
}
/*
* Kaseikyo (Japanese Code)
* - start: pulse 3456µs, pause 1728µs
* - PDM: pulse 432µs, pause 0=432µs 1=1296µs
* - bit mode: LSB
* - stop: pulse 432µs
* - format (48 bits):
* <start><manufacturer code:16><parity:4><system:4><product:8><function:8><check:8><stop>
* - parity: 0000
* ?: <mc 0-3> ^ <mc 4-7> ^ <mc 8-11> ^ <mc 12-15>
* - check: <system:4><parity:4> ^ <product:8> ^ <function:8>
* ?: <system 0-3> + <product 0-3> + <product 4-7> + <function 0-3> + <function 4-7>
* - code becomes valid after sending it 2 (or 3) times
* code delay is 74.62ms (end to start)
* - repeat sequence format: <pulse 3456µs><pause 3456µs><pulse 432µs>
* - repeat delay is 42.2ms (end to start)
*/
else if (Proto == IR_KASEIKYO) /* Kaseikyo */
{
/* build code */
Temp = *Data; /* Data #0: manufacturer code */
PutBits(Temp, 16, 1, IR_LSB); /* manufacturer, 16 bits */
n = 0; /* 0000 */
PutBits(n, 4, 17, IR_LSB); /* parity, 4 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: system */
PutBits(Temp, 4, 21, IR_LSB); /* system, 4 bits */
n = Temp; /* use n for check value */
n <<= 4; /* check: <system><parity> */
Data++; /* next data field */
Temp = *Data; /* Data #2: product */
PutBits(Temp, 8, 25, IR_LSB); /* product, 8 bits */
n ^= (uint8_t)Temp; /* check: ^ <product> */
Data++; /* next data field */
Temp = *Data; /* Data #2: function */
PutBits(Temp, 8, 33, IR_LSB); /* function, 8 bits */
n ^= (uint8_t)Temp; /* check: ^ <function> */
PutBits(n, 8, 41, IR_LSB); /* check, 8 bits */
/* send code three times */
n = 3;
while (n > 0)
{
IR_Send_Pulse(IR_PULSE, 3456); /* start */
IR_Send_Pulse(IR_PAUSE, 1728);
IR_Send_PDM(&IR_Code[0], 48, 432, 432, 1296);
MilliSleep(74); /* delay for next packet */
n--; /* next run */
}
}
/*
* Matsushita (Panasonic, MN6014 C6D6)
* - start: pulse 3.5ms, pause 3.5ms
* - PDM: pulse 872µs, pause 0=872µs 1=2616µs
* - bit mode: LSB
* - stop: pulse 872µs
* - format:
* <start><custom code:6><data code:6><inverted custom code:6><inverted data code:6><stop>
* - repeat delay is 104.7ms (start to start) or 34ms (end to start)
*/
else if (Proto == IR_MATSUSHITA) /* Matsushita */
{
/* build code */
Temp = *Data; /* Data #0: custom code */
PutBits(Temp, 6, 1, IR_LSB); /* address, 6 bits */
Temp = ~Temp; /* invert address */
PutBits(Temp, 6, 13, IR_LSB); /* inverted address, 6 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: key data */
PutBits(Temp, 6, 7, IR_LSB); /* command, 6 bits */
Temp = ~Temp; /* invert command */
PutBits(Temp, 6, 19, IR_LSB); /* inverted command, 6 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 3500); /* start */
IR_Send_Pulse(IR_PAUSE, 3500);
IR_Send_PDM(&IR_Code[0], 24, 872, 872, 2616);
}
/*
* Motorola
* - start: pulse 512µs, pause 2560µs
* - Bi-Phase:
* 0: pause 512µs, pulse 512µs
* 1: pulse 512µs, pause 512µs
* - bit mode: LSB
* - a valid code consists of a start packet, one or more command packets
* and an end packet
* - command packets are repeated as long as key is pressed
* - start/end packet format: <start><start "1":1><all 1s:9>
* - command packet format: <start><start "1":1><command:9>
* - packet delay is 32.8ms (start to start) or 19.5ms (end to start) between
* command packets and 131ms (start to start) or 117.7ms (end to start) for
* start-command and command-end
*/
else if (Proto == IR_MOTOROLA) /* Motorola */
{
/* build code */
/* IR_Code[0] for command packet, IR_Code[2] for start/end packet */
Temp = 0b0000001111111111;
PutBits(Temp, 10, 17, IR_LSB); /* all 1s for start/end packet */
PutBits(Temp, 1, 1, IR_LSB); /* start bit, 1 bit */
Temp = *Data; /* Data #0: command */
PutBits(Temp, 9, 2, IR_LSB); /* command, 9 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 512); /* start */
IR_Send_Pulse(IR_PAUSE, 2560);
IR_Send_BiPhase(&IR_Code[2], 10, IR_THOMAS, 512); /* start packet */
MilliSleep(118); /* delay */
IR_Send_BiPhase(&IR_Code[0], 10, IR_THOMAS, 512); /* command packet */
MilliSleep(118); /* delay */
IR_Send_BiPhase(&IR_Code[2], 10, IR_THOMAS, 512); /* end packet */
}
/*
* NEC Standard (µPD6121/µPD6122)
* - start: pulse 9ms, pause 4.5ms
* - PDM: pulse 560µs, pause 0=560µs 1=1690µs
* - bit mode: LSB
* - format:
* <start><address:8><inverted address:8><command:8><inverted command:8><stop>
* - repeat sequence:
* <pulse 9ms><pause 2.25ms><stop>
* - repeat delay is 108ms (start to start)
*/
if (Proto == IR_NEC_STD) /* NEC Standard */
{
/* build code */
Temp = *Data; /* Data #0: address */
PutBits(Temp, 8, 1, IR_LSB); /* address, 8 bits */
Temp = ~Temp; /* invert address */
PutBits(Temp, 8, 9, IR_LSB); /* inverted address, 8 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: command */
PutBits(Temp, 8, 17, IR_LSB); /* command, 8 bits */
Temp = ~Temp; /* invert command */
PutBits(Temp, 8, 25, IR_LSB); /* inverted command, 8 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 9000); /* start */
IR_Send_Pulse(IR_PAUSE, 4500);
IR_Send_PDM(&IR_Code[0], 32, 560, 560, 1690);
}
/*
* NEC Extended (µPD6121/µPD6122)
* - start: pulse 9ms, pause 4.5ms
* - PDM: pulse 560µs, pause 0=560µs 1=1690µs
* - bit mode: LSB
* - format:
* <start><low address:8><high address:8><command:8><inverted command:8><stop>
* - repeat sequence:
* <pulse 9ms><pause 2.25ms><stop>
* - repeat delay is 108ms (start to start)
*/
else if (Proto == IR_NEC_EXT) /* NEC Extended */
{
/* build code */
Temp = *Data; /* Data #0: address */
PutBits(Temp, 16, 1, IR_LSB); /* address, 16 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: command */
PutBits(Temp, 8, 17, IR_LSB); /* command, 8 bits */
Temp = ~Temp; /* invert command */
PutBits(Temp, 8, 25, IR_LSB); /* inverted command, 8 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 9000); /* start */
IR_Send_Pulse(IR_PAUSE, 4500);
IR_Send_PDM(&IR_Code[0], 32, 560, 560, 1690);
}
/*
* Proton
* - also: Mitsubishi (M50560)
* - start: pulse 8ms, pause 4ms
* - sync/separator between address and command: pause 4ms
* - PDM: pulse 500µs, pause 0=500µs 1=1500µs
* - bit mode: LSB
* - stop: pulse 500µs
* - format: <start><address:8><stop><sync><command:8><stop>
* - code repeat delay is 60ms (start to start)
*/
else if (Proto == IR_PROTON) /* Proton */
{
/* build code */
Temp = *Data; /* Data #0: address */
PutBits(Temp, 8, 1, IR_LSB); /* address, 8 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: command */
PutBits(Temp, 8, 9, IR_LSB); /* command, 8 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 8000); /* start */
IR_Send_Pulse(IR_PAUSE, 4000);
IR_Send_PDM(&IR_Code[0], 8, 500, 500, 1500);
IR_Send_Pulse(IR_PAUSE, 4000); /* sync */
IR_Send_PDM(&IR_Code[1], 8, 500, 500, 1500);
}
/*
* Philips RC-5 Standard
* - 2 start bits: (889µs L) 889µs H, 889µs L (889µs H)
* - Bi-Phase (IEEE 802.3):
* 0: pulse 889µs, pause 889µs
* 1: pause 889µs, pulse 889µs
* - bit mode: MSB
* - format: <s1 "1":1><s2 "1":1><toggle:1><address:5><command:6>
* - toggle: inverted each time a key is pressed
* stays same when key is still pressed
* - repeat delay is 114ms (start to start) or 89ms (end to start)
*/
else if (Proto == IR_RC5) /* RC-5 Standard */
{
/* build code */
Temp = 0b0000000000000110; /* two start bits & cleared toggle bit */
Temp |= IR_Toggle; /* update toggle bit */
PutBits(Temp, 3, 1, IR_MSB); /* start & toggle, 3 bits */
Temp = *Data; /* Data #0: address */
PutBits(Temp, 5, 4, IR_MSB); /* address, 5 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: command */
PutBits(Temp, 6, 9, IR_MSB); /* command, 6 bits */
/* send code */
IR_Send_BiPhase(&IR_Code[0], 14, IR_IEEE, 889);
}
/*
* Philips RC-6 Standard (RC6-0-16)
* - start: pulse 2664µs, pause 888µs
* - Bi-Phase (Thomas):
* normal bit 0: pause 444µs, pulse 444µs
* normal bit 1: pulse 444µs, pause 444µs
* toggle bit 0: pause 888µs, pulse 888µs
* toggle bit 1: pulse 888µs, pause 888µs
* - bit mode: MSB
* - format (Mode 0, 16 bit):
* <start><start bit "1":1><mode:3><toggle:1><address:8><command:8>
* - mode: 000 for Mode 0
* - toggle: inverted each time a key is pressed
* stays the same when key is still pressed
* - delay between codes is 2.666ms (end to start)
*/
else if (Proto == IR_RC6) /* RC-6 Standard */
{
/* build code */
/* IR_Code[0] for start & mode, IR_Code[2] for address & command */
Temp = 0b0000000000001000; /* start bit & mode */
PutBits(Temp, 4, 1, IR_MSB); /* start & mode, 4 bits */
PutBits(IR_Toggle, 1, 7, IR_MSB); /* toggle bit */
Temp = *Data; /* Data #0: address */
PutBits(Temp, 8, 17, IR_MSB); /* address, 8 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: command */
PutBits(Temp, 8, 25, IR_MSB); /* command, 8 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 2664); /* start */
IR_Send_Pulse(IR_PAUSE, 888);
IR_Send_BiPhase(&IR_Code[0], 4, IR_THOMAS, 444); /* first part */
IR_Send_BiPhase(&IR_Code[1], 1, IR_THOMAS, 888); /* toggle bit */
IR_Send_BiPhase(&IR_Code[2], 16, IR_THOMAS, 444); /* second part */
}
/*
* Samsung / Toshiba (TC9012)
* - start: pulse 4.5ms, pause 4.5ms
* - PDM: pulse 560µs, pause 0=560µs 1=1690µs
* - bit mode: LSB
* - stop: pulse 560µs
* - format:
* <start><custom:8><copy of custom:8><data:8><inverted data:8><stop>
* - repeat sequence format:
* <start><inverted bit #0 of custom><stop>
* - repeat delay is 108ms (start to start)
*/
else if (Proto == IR_SAMSUNG) /* Samsung */
{
/* build code */
Temp = *Data; /* Data #0: custom */
PutBits(Temp, 8, 1, IR_LSB); /* custom, 8 bits */
PutBits(Temp, 8, 9, IR_LSB); /* copy of custom, 8 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: data */
PutBits(Temp, 8, 17, IR_LSB); /* data, 8 bits */
Temp = ~Temp; /* invert data */
PutBits(Temp, 8, 25, IR_LSB); /* inverted data, 8 bits */
/* send code */
IR_Send_Pulse(IR_PULSE, 4500); /* start */
IR_Send_Pulse(IR_PAUSE, 4500);
IR_Send_PDM(&IR_Code[0], 32, 560, 560, 1690);
}
/*
* Sharp (LR3715M)
* - also: Denon
* - no start / AGC burst
* - PDM: pulse 264µs, pause 0=786µs 1=1836µs
* - bit mode: LSB
* - stop: pulse 320µs
* - a valid code consists of two packets (#1 and #2)
* - format packet #1:
* <address:5><command:8><mask:1><type:1><stop>
* - format packet #2:
* <address:5><inverted command:8><inverted mask:1><inverted type:1><stop>
* - mask: 0, but also seen 1
* - type: indicater for packet (0 for first packet, 1 for second packet)
* - delay for second packet is 67.5ms (start to start),
* 40ms (end to start) could work too
*/
else if (Proto == IR_SHARP) /* Sharp */
{
/* build code */
/* IR_Code[0] for packet #1, IR_Code[2] for packet #2 */
Temp = *Data; /* Data #0: address */
PutBits(Temp, 5, 1, IR_LSB); /* address, 5 bits */
PutBits(Temp, 5, 17, IR_LSB); /* address, 5 bits (packet #2) */
Data++; /* next data field */
Temp = *Data; /* Data #1: command */
PutBits(Temp, 8, 6, IR_LSB); /* command, 8 bits */
Temp = ~Temp; /* invert command */
PutBits(Temp, 8, 22, IR_LSB); /* inverted command, 8 bits (packet #2) */
Data++; /* next data field */
Temp = *Data; /* Data #2: mask */
/* bit #1 should be 0 -> use as type bit */
PutBits(Temp, 2, 14, IR_LSB); /* mask & type, 2 bits */
Temp = ~Temp; /* invert mask & type */
PutBits(Temp, 2, 30, IR_LSB); /* inverted mask & type, 2 bits (packet #2) */
/* send code */
IR_Send_PDM(&IR_Code[0], 15, 264, 786, 1836); /* packet #1 */
MilliSleep(40); /* delay */
IR_Send_PDM(&IR_Code[2], 15, 264, 786, 1836); /* packet #2 */
}
/*
* Sony SIRC-12
* - start: pulse 2.4ms (pause 600µs)
* - PWM: pause 600µs, pulse 0=600µs 1=1200µs
* - bit mode: LSB
* - format: <start><command:7><address:5>
* - code becomes valid after sending it 3 times
* code delay is 45ms (start to start)
*/
else if (Proto == IR_SIRC_12) /* Sony SIRC 12 bits */
{
/* build code */
Temp = *Data; /* Data #0: command */
PutBits(Temp, 7, 1, IR_LSB); /* command, 7 bits */
Data++; /* next data field */
Temp = *Data; /* Data #1: address */
PutBits(Temp, 5, 8, IR_LSB); /* address, 5 bits */
/* calculate delay between code frames */
Temp = 45000 - 2400; /* time for start pulse */