1 /*---------------------------------------------------------------------------*\
2
3 FILE........: sm1000_leds_switches.c
4 AUTHOR......: David Rowe
5 DATE CREATED: 18 July 2014
6
7 Functions for controlling LEDs and reading switches on the SM1000.
8
9 \*---------------------------------------------------------------------------*/
10
11 /*
12 Copyright (C) 2014 David Rowe
13
14 All rights reserved.
15
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU Lesser General Public License version 2.1, as
18 published by the Free Software Foundation. This program is
19 distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
22 License for more details.
23
24 You should have received a copy of the GNU Lesser General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 */
27
28 #define _CPTT GPIO_Pin_10
29 #define LED_PWR GPIO_Pin_12
30 #define LED_PTT GPIO_Pin_13
31 #define LED_RT GPIO_Pin_14
32 #define LED_ERR GPIO_Pin_15
33 #define SWITCH_PTT GPIO_Pin_7
34 #define SWITCH_SELECT GPIO_Pin_0
35 #define SWITCH_BACK GPIO_Pin_1
36 #define EXT_PTT GPIO_Pin_8
37
38 #include <stm32f4xx.h>
39 #include <stm32f4xx_gpio.h>
40 #include "sm1000_leds_switches.h"
41
sm1000_leds_switches_init(void)42 void sm1000_leds_switches_init(void) {
43 GPIO_InitTypeDef GPIO_InitStruct;
44
45 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
46
47 /* output pins */
48
49 GPIO_InitStruct.GPIO_Pin = LED_PWR | LED_PTT | LED_RT | LED_ERR | _CPTT;
50 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
51 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
52 GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
53 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
54 GPIO_Init(GPIOD, &GPIO_InitStruct);
55
56 /* input pins */
57
58 GPIO_InitStruct.GPIO_Pin = SWITCH_PTT | SWITCH_SELECT | SWITCH_BACK;
59 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
60 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
61 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; /* we have our own external pull ups */
62 GPIO_Init(GPIOD, &GPIO_InitStruct);
63
64 GPIO_InitStruct.GPIO_Pin = EXT_PTT;
65 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
66 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
67 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; /* use internal pull up */
68 GPIO_Init(GPIOD, &GPIO_InitStruct);
69
70
71 }
72
led_pwr(int state)73 void led_pwr(int state) {
74 if (state > 0)
75 GPIOD->ODR |= (1 << 12);
76 else if (state < 0)
77 GPIOD->ODR ^= (1 << 12);
78 else
79 GPIOD->ODR &= ~(1 << 12);
80 }
81
led_ptt(int state)82 void led_ptt(int state) {
83 if (state > 0)
84 GPIOD->ODR |= (1 << 13);
85 else if (state < 0)
86 GPIOD->ODR |= (1 << 13);
87 else
88 GPIOD->ODR &= ~(1 << 13);
89 }
90
led_rt(int state)91 void led_rt(int state) {
92 if (state > 0)
93 GPIOD->ODR |= (1 << 14);
94 else if (state < 0)
95 GPIOD->ODR ^= (1 << 14);
96 else
97 GPIOD->ODR &= ~(1 << 14);
98 }
99
led_err(int state)100 void led_err(int state) {
101 if (state > 0)
102 GPIOD->ODR |= (1 << 15);
103 else if (state < 0)
104 GPIOD->ODR ^= (1 << 15);
105 else
106 GPIOD->ODR &= ~(1 << 15);
107 }
108
not_cptt(int state)109 void not_cptt(int state) {
110 if (state)
111 GPIOD->ODR |= (1 << 10);
112 else
113 GPIOD->ODR &= ~(1 << 10);
114 }
115
switch_ptt(void)116 int switch_ptt(void) {
117 return GPIOD->IDR & (1 << 7);
118 }
119
switch_select(void)120 int switch_select(void) {
121 return GPIOD->IDR & (1 << 0);
122 }
123
switch_back(void)124 int switch_back(void) {
125 return GPIOD->IDR & (1 << 1);
126 }
127
ext_ptt(void)128 int ext_ptt(void) {
129 return GPIOD->IDR & (1 << 8);
130 }
131
132 /*
133 FUNCTION: ColorfulRingOfDeath()
134 AUTHOR..: xenovacivus
135
136 Colourful ring of death, blink LEDs like crazy forever if something
137 really nasty happens. Adapted from USB Virtual COM Port (VCP)
138 module adapted from code I found here:
139
140 https://github.com/xenovacivus/STM32DiscoveryVCP
141
142 Call this to indicate a failure. Blinks the STM32F4 discovery LEDs
143 in sequence. At 168Mhz, the blinking will be very fast - about 5
144 Hz. Keep that in mind when debugging, knowing the clock speed
145 might help with debugging.
146 */
147
148 int mycode; /* examine this with debugger if it dies */
149
ColorfulRingOfDeath(int code)150 void ColorfulRingOfDeath(int code) {
151 mycode = code;
152 uint16_t ring = 1;
153 while (1) {
154 uint32_t count = 0;
155 while (count++ < 5000000);
156
157 GPIOD->BSRRH = (ring << 12);
158 ring = ring << 1;
159 if (ring >= 1<<4) {
160 ring = 1;
161 }
162 GPIOD->BSRRL = (ring << 12);
163 }
164 }
HardFault_Handler(void)165 void HardFault_Handler(void) { ColorfulRingOfDeath(1); }
MemManage_Handler(void)166 void MemManage_Handler(void) { ColorfulRingOfDeath(2); }
BusFault_Handler(void)167 void BusFault_Handler(void) { ColorfulRingOfDeath(3); }
UsageFault_Handler(void)168 void UsageFault_Handler(void){ ColorfulRingOfDeath(4); }
169
170
switch_tick(struct switch_t * const sw)171 void switch_tick(struct switch_t* const sw)
172 {
173 if (sw->sw != sw->raw) {
174 /* State transition, reset timer */
175 if (sw->state == SW_STEADY)
176 sw->last = sw->sw;
177 sw->state = SW_DEBOUNCE;
178 sw->timer = DEBOUNCE_DELAY;
179 sw->sw = sw->raw;
180 } else if (sw->state == SW_DEBOUNCE) {
181 if (sw->timer > 0) {
182 /* Steady so far, keep waiting */
183 sw->timer--;
184 } else {
185 /* Steady state reached */
186 sw->state = SW_STEADY;
187 }
188 } else if (sw->sw) {
189 /* Hold state. Yes this will wrap, but who cares? */
190 sw->timer++;
191 }
192 }
193
switch_update(struct switch_t * const sw,uint8_t state)194 void switch_update(struct switch_t* const sw, uint8_t state)
195 {
196 sw->raw = state;
197 if (sw->raw == sw->sw)
198 return;
199
200 if (sw->state == SW_STEADY)
201 sw->last = sw->sw;
202 sw->timer = DEBOUNCE_DELAY;
203 sw->sw = sw->raw;
204 sw->state = SW_DEBOUNCE;
205 }
206
switch_pressed(const struct switch_t * const sw)207 uint32_t switch_pressed(const struct switch_t* const sw)
208 {
209 if ((sw->state == SW_STEADY) && sw->sw)
210 return sw->timer;
211 return 0;
212 }
213
switch_released(const struct switch_t * const sw)214 int switch_released(const struct switch_t* const sw)
215 {
216 if (sw->state != SW_STEADY)
217 return 0;
218 if (!sw->last)
219 return 0;
220 if (sw->sw)
221 return 0;
222 return 1;
223 }
224
switch_ack(struct switch_t * const sw)225 void switch_ack(struct switch_t* const sw)
226 {
227 if (sw->state == SW_STEADY)
228 sw->last = sw->sw;
229 }
230