|
@@ -32,12 +32,15 @@
|
32
|
32
|
limitations under the License.
|
33
|
33
|
*/
|
34
|
34
|
|
|
35
|
+#include <stdbool.h>
|
|
36
|
+
|
35
|
37
|
#include "ch.h"
|
36
|
38
|
#include "hal.h"
|
37
|
39
|
|
|
40
|
+/* PWM configuration for IR output */
|
38
|
41
|
static PWMConfig pwmcfg = {
|
39
|
|
- 380000, /* 1MHz PWM clock frequency. */
|
40
|
|
- 10, /* Initial PWM period 1ms. */
|
|
42
|
+ 380000, /* 380 kHz PWM clock frequency. */
|
|
43
|
+ 10, /* PWM period 10 clock cycles. */
|
41
|
44
|
NULL,
|
42
|
45
|
{
|
43
|
46
|
{PWM_OUTPUT_ACTIVE_HIGH, NULL},
|
|
@@ -49,6 +52,13 @@ static PWMConfig pwmcfg = {
|
49
|
52
|
0
|
50
|
53
|
};
|
51
|
54
|
|
|
55
|
+/* Timer configuration for IR output */
|
|
56
|
+static const GPTConfig gpt4cfg = {
|
|
57
|
+ 1000000, // 1 MHz timer clock.
|
|
58
|
+ NULL, // No callback
|
|
59
|
+ 0, 0
|
|
60
|
+};
|
|
61
|
+
|
52
|
62
|
/*
|
53
|
63
|
* Green LED blinker thread, times are in milliseconds.
|
54
|
64
|
*/
|
|
@@ -64,6 +74,44 @@ static THD_FUNCTION(Thread1, arg) {
|
64
|
74
|
}
|
65
|
75
|
}
|
66
|
76
|
|
|
77
|
+/*
|
|
78
|
+ * Synchronously send one bit for RC5
|
|
79
|
+ */
|
|
80
|
+void rc5_bit(bool bit)
|
|
81
|
+{
|
|
82
|
+ if (bit) {
|
|
83
|
+ pwmDisableChannel(&PWMD1, 0);
|
|
84
|
+ gptPolledDelay(&GPTD4, 889);
|
|
85
|
+ pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 5000));
|
|
86
|
+ gptPolledDelay(&GPTD4, 889);
|
|
87
|
+ } else {
|
|
88
|
+ pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 5000));
|
|
89
|
+ gptPolledDelay(&GPTD4, 889);
|
|
90
|
+ pwmDisableChannel(&PWMD1, 0);
|
|
91
|
+ gptPolledDelay(&GPTD4, 889);
|
|
92
|
+ }
|
|
93
|
+}
|
|
94
|
+
|
|
95
|
+/*
|
|
96
|
+ * Synchronously send a whole RC5 frame
|
|
97
|
+ */
|
|
98
|
+void rc5_frame(bool toggle, int addr, int data)
|
|
99
|
+{
|
|
100
|
+ /* Start */
|
|
101
|
+ rc5_bit(1);
|
|
102
|
+ rc5_bit(1);
|
|
103
|
+ /* Toggle */
|
|
104
|
+ rc5_bit(toggle);
|
|
105
|
+ /* Address */
|
|
106
|
+ for (int b = 0x10; b != 0; b >>= 1) {
|
|
107
|
+ rc5_bit(addr & b);
|
|
108
|
+ }
|
|
109
|
+ /* Data */
|
|
110
|
+ for (int b = 0x20; b != 0; b >>= 1) {
|
|
111
|
+ rc5_bit(data & b);
|
|
112
|
+ }
|
|
113
|
+}
|
|
114
|
+
|
67
|
115
|
/*
|
68
|
116
|
* Application entry point.
|
69
|
117
|
*/
|
|
@@ -84,14 +132,17 @@ int main(void) {
|
84
|
132
|
*/
|
85
|
133
|
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
|
86
|
134
|
|
|
135
|
+ /* Configure PWM */
|
87
|
136
|
pwmStart(&PWMD1, &pwmcfg);
|
88
|
137
|
palSetPadMode(GPIOA, 8, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
|
89
|
|
- pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 5000));
|
90
|
|
- /*
|
91
|
|
- * Normal main() thread activity, in this demo it does nothing except
|
92
|
|
- * sleeping in a loop and check the button state.
|
93
|
|
- */
|
|
138
|
+
|
|
139
|
+ /* Configure GPT */
|
|
140
|
+ gptStart(&GPTD4, &gpt4cfg);
|
|
141
|
+
|
|
142
|
+ /* Send a continuous stream of power off signals to the TV */
|
94
|
143
|
while (true) {
|
95
|
|
- chThdSleepMilliseconds(500);
|
|
144
|
+ rc5_frame(false, 0x00, 0x0C);
|
|
145
|
+
|
|
146
|
+ chThdSleepMilliseconds(90);
|
96
|
147
|
}
|
97
|
148
|
}
|