diff options
Diffstat (limited to 'lib/chibios-contrib/testhal/KINETIS/FRDM-KL26Z/PWM/main.c')
-rw-r--r-- | lib/chibios-contrib/testhal/KINETIS/FRDM-KL26Z/PWM/main.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/lib/chibios-contrib/testhal/KINETIS/FRDM-KL26Z/PWM/main.c b/lib/chibios-contrib/testhal/KINETIS/FRDM-KL26Z/PWM/main.c new file mode 100644 index 000000000..740471a54 --- /dev/null +++ b/lib/chibios-contrib/testhal/KINETIS/FRDM-KL26Z/PWM/main.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * (c) 2015 flabbergast <[email protected]> | ||
3 | * Based on ChibiOS 3.0.1 demo code, license below. | ||
4 | * Licensed under the Apache License, Version 2.0. | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio | ||
9 | * | ||
10 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
11 | * you may not use this file except in compliance with the License. | ||
12 | * You may obtain a copy of the License at | ||
13 | * | ||
14 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
15 | * | ||
16 | * Unless required by applicable law or agreed to in writing, software | ||
17 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
19 | * See the License for the specific language governing permissions and | ||
20 | * limitations under the License. | ||
21 | */ | ||
22 | |||
23 | #include "ch.h" | ||
24 | #include "hal.h" | ||
25 | |||
26 | /* | ||
27 | * on FRDM-KL26Z: | ||
28 | * red LED on PTE29/TPM0_CH2 (AF3) | ||
29 | * green LED on PTE31/TPM0_CH4 (AF3) | ||
30 | * blue LED on PTD5/TPM0_CH5 (AF4) | ||
31 | */ | ||
32 | |||
33 | #define PWM_DRIVER PWMD1 | ||
34 | |||
35 | /* PWM config structure */ | ||
36 | /* Note: the PWM clock frequency must be so that | ||
37 | * SYSCLK / FREQ is a power of 2 between 1 and 128. | ||
38 | */ | ||
39 | static const PWMConfig pwmcfg = { | ||
40 | 750000, /* 750kHz PWM clock frequency. */ | ||
41 | 1000, /* PWM period is 1000 cycles. */ | ||
42 | /* meaning PWM resolution is 750 */ | ||
43 | NULL, /* no callback */ | ||
44 | { | ||
45 | {PWM_OUTPUT_DISABLED, NULL}, /* ch0: mode, no callback */ | ||
46 | {PWM_OUTPUT_DISABLED, NULL}, /* ch1: mode, no callback */ | ||
47 | {PWM_OUTPUT_ACTIVE_LOW, NULL}, /* ch2: mode, no callback */ | ||
48 | {PWM_OUTPUT_DISABLED, NULL}, /* ch3: mode, no callback */ | ||
49 | {PWM_OUTPUT_ACTIVE_LOW, NULL}, /* ch4: mode, no callback */ | ||
50 | {PWM_OUTPUT_ACTIVE_LOW, NULL} /* ch5: mode, no callback */ | ||
51 | }, | ||
52 | }; | ||
53 | |||
54 | #define BREATHE_STEP 16 /* ms; = 4000ms/TABLE_SIZE */ | ||
55 | |||
56 | /* Breathing Sleep LED brighness(PWM On period) table | ||
57 | * | ||
58 | * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63 | ||
59 | * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i } | ||
60 | */ | ||
61 | /* ruby -e "a = ((0..255).map{|x| Math.exp(Math.cos(Math::PI+(2*x*(Math::PI)/255)))-Math.exp(-1) }); m = a.max; a.map\!{|x| (10000*x/m).to_i}; p a" */ | ||
62 | #define TABLE_SIZE 256 | ||
63 | static const uint16_t breathing_table[TABLE_SIZE] = { | ||
64 | 0, 0, 1, 4, 7, 11, 17, 23, 30, 38, 47, 58, 69, 81, 94, 109, 124, 141, 159, 177, 197, 218, 241, 264, 289, 315, 343, 372, 402, 433, 466, 501, 537, 574, 613, 654, 696, 741, 786, 834, 883, 935, 988, 1043, 1100, 1159, 1220, 1283, 1349, 1416, 1486, 1558, 1632, 1709, 1788, 1870, 1954, 2040, 2129, 2220, 2314, 2411, 2510, 2611, 2715, 2822, 2932, 3044, 3158, 3275, 3395, 3517, 3641, 3768, 3897, 4028, 4162, 4298, 4436, 4576, 4717, 4861, 5006, 5152, 5300, 5449, 5600, 5751, 5903, 6055, 6208, 6361, 6513, 6666, 6818, 6970, 7120, 7269, 7417, 7563, 7708, 7850, 7990, 8127, 8261, 8391, 8519, 8643, 8762, 8878, 8989, 9095, 9196, 9293, 9383, 9469, 9548, 9622, 9689, 9750, 9805, 9853, 9895, 9930, 9957, 9978, 9992, 9999, 10000, 9992, 9978, 9957, 9930, 9895, 9853, 9805, 9750, 9689, 9622, 9548, 9469, 9383, 9293, 9196, 9095, 8989, 8878, 8762, 8643, 8519, 8391, 8261, 8127, 7990, 7850, 7708, 7563, 7417, 7269, 7120, 6970, 6818, 6666, 6513, 6361, 6208, 6055, 5903, 5751, 5600, 5449, 5300, 5152, 5006, 4861, 4717, 4576, 4436, 4298, 4162, 4028, 3897, 3768, 3641, 3517, 3395, 3275, 3158, 3044, 2932, 2822, 2715, 2611, 2510, 2411, 2314, 2220, 2129, 2040, 1954, 1870, 1788, 1709, 1632, 1558, 1486, 1416, 1349, 1283, 1220, 1159, 1100, 1043, 988, 935, 883, 834, 786, 741, 696, 654, 613, 574, 537, 501, 466, 433, 402, 372, 343, 315, 289, 264, 241, 218, 197, 177, 159, 141, 124, 109, 94, 81, 69, 58, 47, 38, 30, 23, 17, 11, 7, 4, 1, 0, 0 | ||
65 | }; | ||
66 | |||
67 | uint16_t table_pos = 0; | ||
68 | uint8_t active_led = 0; | ||
69 | |||
70 | static THD_WORKING_AREA(waBreatheThread, 128); | ||
71 | static THD_FUNCTION(BreatheThread, arg) { | ||
72 | (void)arg; | ||
73 | chRegSetThreadName("breatheThread"); | ||
74 | |||
75 | while(true) { | ||
76 | switch(active_led) { | ||
77 | case 0: /* red LED */ | ||
78 | pwmEnableChannel(&PWM_DRIVER, 2, PWM_PERCENTAGE_TO_WIDTH(&PWM_DRIVER,breathing_table[table_pos])); | ||
79 | break; | ||
80 | case 1: /* green LED */ | ||
81 | pwmEnableChannel(&PWM_DRIVER, 4, PWM_PERCENTAGE_TO_WIDTH(&PWM_DRIVER,breathing_table[table_pos])); | ||
82 | break; | ||
83 | case 2: /* blue LED */ | ||
84 | pwmEnableChannel(&PWM_DRIVER, 5, PWM_PERCENTAGE_TO_WIDTH(&PWM_DRIVER,breathing_table[table_pos])); | ||
85 | break; | ||
86 | } | ||
87 | table_pos++; | ||
88 | if(table_pos == TABLE_SIZE) { | ||
89 | table_pos = 0; | ||
90 | active_led = (active_led+1) % 3; | ||
91 | } | ||
92 | chThdSleepMilliseconds(BREATHE_STEP); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Check button thread | ||
98 | */ | ||
99 | static THD_WORKING_AREA(waButtonThread, 128); | ||
100 | static THD_FUNCTION(ButtonThread, arg) { | ||
101 | (void)arg; | ||
102 | chRegSetThreadName("buttonThread"); | ||
103 | |||
104 | uint8_t newstate, state = PAL_HIGH; | ||
105 | |||
106 | while(true) { | ||
107 | if(palReadLine(LINE_BUTTON) != state) { | ||
108 | chThdSleepMilliseconds(20); /* debounce */ | ||
109 | newstate = palReadLine(LINE_BUTTON); | ||
110 | if(newstate != state) { | ||
111 | state = newstate; | ||
112 | if(newstate == PAL_LOW) { | ||
113 | table_pos = (table_pos + 120)%TABLE_SIZE; | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | chThdSleepMilliseconds(20); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Application entry point. | ||
123 | */ | ||
124 | int main(void) { | ||
125 | /* | ||
126 | * System initializations. | ||
127 | * - HAL initialization, this also initializes the configured device drivers | ||
128 | * and performs the board-specific initializations. | ||
129 | * - Kernel initialization, the main() function becomes a thread and the | ||
130 | * RTOS is active. | ||
131 | */ | ||
132 | halInit(); | ||
133 | chSysInit(); | ||
134 | |||
135 | /* | ||
136 | * Turn off the RGB LED. | ||
137 | */ | ||
138 | palSetLine(LINE_LED_RED); /* red */ | ||
139 | palSetLine(LINE_LED_GREEN); /* green */ | ||
140 | palSetLine(LINE_LED_BLUE); /* blue */ | ||
141 | |||
142 | /* | ||
143 | * Create the button check thread. | ||
144 | */ | ||
145 | chThdCreateStatic(waButtonThread, sizeof(waButtonThread), NORMALPRIO, ButtonThread, NULL); | ||
146 | |||
147 | /* | ||
148 | * Start the PWM driver, route TPM0 output to PTE29, PTE31, PTD5. | ||
149 | * Enable channels now to avoid a blink later. | ||
150 | */ | ||
151 | pwmStart(&PWM_DRIVER, &pwmcfg); | ||
152 | palSetLineMode(LINE_LED_RED, PAL_MODE_ALTERNATIVE_3); | ||
153 | palSetLineMode(LINE_LED_GREEN, PAL_MODE_ALTERNATIVE_3); | ||
154 | palSetLineMode(LINE_LED_BLUE, PAL_MODE_ALTERNATIVE_4); | ||
155 | pwmEnableChannel(&PWM_DRIVER, 2, 0); | ||
156 | pwmEnableChannel(&PWM_DRIVER, 4, 0); | ||
157 | pwmEnableChannel(&PWM_DRIVER, 5, 0); | ||
158 | |||
159 | /* | ||
160 | * Create the breathe thread. | ||
161 | */ | ||
162 | chThdCreateStatic(waBreatheThread, sizeof(waBreatheThread), NORMALPRIO, BreatheThread, NULL); | ||
163 | |||
164 | /* | ||
165 | * Normal main() thread activity, in this demo it does nothing except | ||
166 | * sleeping in a loop and check the button state, when the button is | ||
167 | * pressed ... nothing happens. | ||
168 | */ | ||
169 | while(true) { | ||
170 | chThdSleepMilliseconds(500); | ||
171 | } | ||
172 | } | ||