altos/stm32l0: Add casts to reduce -Wconversion warnings
[fw/altos] / src / stm32l0 / ao_exti_stm.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <ao.h>
20 #include <ao_exti.h>
21
22 static void     (*ao_exti_callback[16])(void);
23
24 uint32_t        ao_last_exti;
25
26 static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) {
27         uint16_t        pending = (uint16_t) (ao_last_exti = stm_exti.pr) & mask;
28         uint8_t         pin;
29         static uint16_t last_mask;
30         static uint8_t  last_pin;
31
32         if (pending == last_mask) {
33                 stm_exti.pr = last_mask;
34                 (*ao_exti_callback[last_pin])();
35                 return;
36         }
37         stm_exti.pr = pending;
38         for (pin = first; pin <= last; pin++)
39                 if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) {
40                         last_mask = (1 << pin);
41                         last_pin = pin;
42                         (*ao_exti_callback[pin])();
43                 }
44 }
45
46 void stm_exti1_0_isr(void) { ao_exti_range_isr(0, 1, 0x3); }
47 void stm_exti3_2_isr(void) { ao_exti_range_isr(2, 3, 0xc); }
48 void stm_exti15_4_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); }
49
50 void
51 ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
52         uint32_t        mask = 1 << pin;
53         uint8_t         irq;
54         uint8_t         prio;
55
56         ao_exti_callback[pin] = callback;
57
58         /* configure gpio to interrupt routing */
59         stm_exticr_set(gpio, pin);
60
61 #if 0
62         if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) {
63                 uint32_t        pupdr;
64                 /* configure pin as input, setting selected pull-up/down mode */
65                 stm_moder_set(gpio, pin, STM_MODER_INPUT);
66                 switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) {
67                 case 0:
68                 default:
69                         pupdr  = STM_PUPDR_NONE;
70                         break;
71                 case AO_EXTI_MODE_PULL_UP:
72                         pupdr = STM_PUPDR_PULL_UP;
73                         break;
74                 case AO_EXTI_MODE_PULL_DOWN:
75                         pupdr = STM_PUPDR_PULL_DOWN;
76                         break;
77                 }
78                 stm_pupdr_set(gpio, pin, pupdr);
79         }
80 #endif
81
82         /* Set interrupt mask and rising/falling mode */
83         stm_exti.imr &= ~mask;
84         if (mode & AO_EXTI_MODE_RISING)
85                 stm_exti.rtsr |= mask;
86         else
87                 stm_exti.rtsr &= ~mask;
88         if (mode & AO_EXTI_MODE_FALLING)
89                 stm_exti.ftsr |= mask;
90         else
91                 stm_exti.ftsr &= ~mask;
92
93         if (pin <= 1)
94                 irq = STM_ISR_EXTI1_0_POS;
95         else if (2 <= pin && pin <= 3)
96                 irq = STM_ISR_EXTI3_2_POS;
97         else
98                 irq = STM_ISR_EXTI15_4_POS;
99
100         /* Set priority */
101         prio = AO_STM_NVIC_MED_PRIORITY;
102         if (mode & AO_EXTI_PRIORITY_LOW)
103                 prio = AO_STM_NVIC_LOW_PRIORITY;
104         else if (mode & AO_EXTI_PRIORITY_HIGH)
105                 prio = AO_STM_NVIC_HIGH_PRIORITY;
106
107         stm_nvic_set_priority(irq, prio);
108         stm_nvic_set_enable(irq);
109 }
110
111 void
112 ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
113         (void) gpio;
114
115         uint32_t        mask = 1 << pin;
116
117         if (mode & AO_EXTI_MODE_RISING)
118                 stm_exti.rtsr |= mask;
119         else
120                 stm_exti.rtsr &= ~mask;
121         if (mode & AO_EXTI_MODE_FALLING)
122                 stm_exti.ftsr |= mask;
123         else
124                 stm_exti.ftsr &= ~mask;
125 }
126
127 void
128 ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)) {
129         (void) gpio;
130         ao_exti_callback[pin] = callback;
131 }
132
133 void
134 ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
135         uint32_t        mask = (1 << pin);
136         (void) gpio;
137         stm_exti.pr = mask;
138         stm_exti.imr |= mask;
139 }
140
141 void
142 ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
143         uint32_t        mask = (1 << pin);
144         (void) gpio;
145         stm_exti.imr &= ~mask;
146         stm_exti.pr = mask;
147 }
148
149 void
150 ao_exti_init(void)
151 {
152 }