summaryrefslogtreecommitdiff
path: root/src/stm
diff options
context:
space:
mode:
Diffstat (limited to 'src/stm')
-rw-r--r--src/stm/ao_debounce.c187
-rw-r--r--src/stm/ao_fast_timer.c120
-rw-r--r--src/stm/ao_fast_timer.h34
-rw-r--r--src/stm/stm32l.h5
4 files changed, 159 insertions, 187 deletions
diff --git a/src/stm/ao_debounce.c b/src/stm/ao_debounce.c
deleted file mode 100644
index 22cdf230..00000000
--- a/src/stm/ao_debounce.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao.h>
-#include <ao_debounce.h>
-
-static uint8_t ao_debounce_initialized;
-static uint8_t ao_debounce_running;
-static struct ao_debounce *ao_debounce;
-
-static void
-ao_debounce_on(void)
-{
- stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
- (0 << STM_TIM67_CR1_OPM) |
- (1 << STM_TIM67_CR1_URS) |
- (0 << STM_TIM67_CR1_UDIS) |
- (1 << STM_TIM67_CR1_CEN));
-}
-
-static void
-ao_debounce_off(void)
-{
- stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
- (0 << STM_TIM67_CR1_OPM) |
- (1 << STM_TIM67_CR1_URS) |
- (0 << STM_TIM67_CR1_UDIS) |
- (0 << STM_TIM67_CR1_CEN));
-}
-
-static void
-_ao_debounce_set(struct ao_debounce *debounce, uint8_t value)
-{
- if (value != debounce->value) {
- debounce->value = value;
- debounce->_set(debounce, value);
- }
- _ao_debounce_stop(debounce);
-}
-
-/*
- * Get the current value, set the result when we've
- * reached the debounce count limit
- */
-static void
-_ao_debounce_check(struct ao_debounce *debounce)
-{
- if (debounce->_get(debounce)) {
- if (debounce->count < 0)
- debounce->count = 0;
- if (debounce->count < debounce->hold) {
- if (++debounce->count == debounce->hold)
- _ao_debounce_set(debounce, 1);
- }
- } else {
- if (debounce->count > 0)
- debounce->count = 0;
- if (debounce->count > -debounce->hold) {
- if (--debounce->count == -debounce->hold)
- _ao_debounce_set(debounce, 0);
- }
- }
-}
-
-/*
- * Start monitoring one pin
- */
-void
-_ao_debounce_start(struct ao_debounce *debounce)
-{
- if (debounce->running)
- return;
- debounce->running = 1;
-
- /* Reset the counter */
- debounce->count = 0;
-
- /* Link into list */
- debounce->next = ao_debounce;
- ao_debounce = debounce;
-
- /* Make sure the timer is running */
- if (!ao_debounce_running++)
- ao_debounce_on();
-
- /* And go check the current value */
- _ao_debounce_check(debounce);
-}
-
-/*
- * Stop monitoring one pin
- */
-void
-_ao_debounce_stop(struct ao_debounce *debounce)
-{
- struct ao_debounce **prev;
- if (!debounce->running)
- return;
-
- debounce->running = 0;
-
- /* Unlink */
- for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) {
- if (*prev == debounce) {
- *prev = debounce->next;
- break;
- }
- }
- debounce->next = NULL;
-
- /* Turn off the timer if possible */
- if (!--ao_debounce_running)
- ao_debounce_off();
-}
-
-void stm_tim6_isr(void)
-{
- struct ao_debounce *debounce, *next;
- if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) {
- stm_tim6.sr = 0;
-
- /* Walk the current list, allowing the current
- * object to be removed from the list
- */
- for (debounce = ao_debounce; debounce; debounce = next) {
- next = debounce->next;
- _ao_debounce_check(debounce);
- }
- }
-}
-
-/*
- * According to the STM clock-configuration, timers run
- * twice as fast as the APB1 clock *if* the APB1 prescaler
- * is greater than 1.
- */
-
-#if AO_APB1_PRESCALER > 1
-#define TIMER_23467_SCALER 2
-#else
-#define TIMER_23467_SCALER 1
-#endif
-
-#define TIMER_100kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 100000)
-
-void
-ao_debounce_init(void)
-{
- if (ao_debounce_initialized)
- return;
- ao_debounce_initialized = 1;
-
- stm_nvic_set_enable(STM_ISR_TIM6_POS);
- stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY);
-
- /* Turn on timer 6 */
- stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
-
- stm_tim6.psc = TIMER_100kHz;
- stm_tim6.arr = 9;
- stm_tim6.cnt = 0;
-
- /* Enable update interrupt */
- stm_tim6.dier = (1 << STM_TIM67_DIER_UIE);
-
- /* Poke timer to reload values */
- stm_tim6.egr |= (1 << STM_TIM67_EGR_UG);
-
- stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS);
-
- /* And turn it off (for now) */
- ao_debounce_off();
-}
diff --git a/src/stm/ao_fast_timer.c b/src/stm/ao_fast_timer.c
new file mode 100644
index 00000000..d61b40c9
--- /dev/null
+++ b/src/stm/ao_fast_timer.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <ao.h>
+#include <ao_fast_timer.h>
+
+static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
+static uint8_t ao_fast_timer_count;
+static uint8_t ao_fast_timer_users;
+
+static void
+ao_fast_timer_enable(void)
+{
+ stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
+ (0 << STM_TIM67_CR1_OPM) |
+ (1 << STM_TIM67_CR1_URS) |
+ (0 << STM_TIM67_CR1_UDIS) |
+ (1 << STM_TIM67_CR1_CEN));
+}
+
+static void
+ao_fast_timer_disable(void)
+{
+ stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
+ (0 << STM_TIM67_CR1_OPM) |
+ (1 << STM_TIM67_CR1_URS) |
+ (0 << STM_TIM67_CR1_UDIS) |
+ (0 << STM_TIM67_CR1_CEN));
+}
+
+void
+ao_fast_timer_on(void (*callback)(void))
+{
+ ao_fast_timer_callback[ao_fast_timer_count] = callback;
+ if (!ao_fast_timer_count++)
+ ao_fast_timer_enable();
+}
+
+void
+ao_fast_timer_off(void (*callback)(void))
+{
+ uint8_t n;
+
+ for (n = 0; n < ao_fast_timer_count; n++)
+ if (ao_fast_timer_callback[n] == callback) {
+ for (; n < ao_fast_timer_count-1; n++) {
+ ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
+ }
+ if (!--ao_fast_timer_count)
+ ao_fast_timer_disable();
+ break;
+ }
+}
+
+void stm_tim6_isr(void)
+{
+ uint8_t i;
+ if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) {
+ stm_tim6.sr = 0;
+
+ for (i = 0; i < ao_fast_timer_count; i++)
+ (*ao_fast_timer_callback[i])();
+ }
+}
+
+/*
+ * According to the STM clock-configuration, timers run
+ * twice as fast as the APB1 clock *if* the APB1 prescaler
+ * is greater than 1.
+ */
+
+#if AO_APB1_PRESCALER > 1
+#define TIMER_23467_SCALER 2
+#else
+#define TIMER_23467_SCALER 1
+#endif
+
+#define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000)
+
+void
+ao_fast_timer_init(void)
+{
+ if (!ao_fast_timer_users) {
+ stm_nvic_set_enable(STM_ISR_TIM6_POS);
+ stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY);
+
+ /* Turn on timer 6 */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
+
+ stm_tim6.psc = TIMER_10kHz;
+ stm_tim6.arr = 9;
+ stm_tim6.cnt = 0;
+
+ /* Enable update interrupt */
+ stm_tim6.dier = (1 << STM_TIM67_DIER_UIE);
+
+ /* Poke timer to reload values */
+ stm_tim6.egr |= (1 << STM_TIM67_EGR_UG);
+
+ stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS);
+ ao_fast_timer_disable();
+ }
+ if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
+ ao_panic(AO_PANIC_FAST_TIMER);
+ ao_fast_timer_users++;
+}
+
diff --git a/src/stm/ao_fast_timer.h b/src/stm/ao_fast_timer.h
new file mode 100644
index 00000000..90fb3930
--- /dev/null
+++ b/src/stm/ao_fast_timer.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FAST_TIMER_H_
+#define _AO_FAST_TIMER_H_
+
+void
+ao_fast_timer_init(void);
+
+#ifndef AO_FAST_TIMER_MAX
+#define AO_FAST_TIMER_MAX 2
+#endif
+
+void
+ao_fast_timer_on(void (*callback)(void));
+
+void
+ao_fast_timer_off(void (*callback)(void));
+
+#endif /* _AO_FAST_TIMER_H_ */
diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h
index 63bde0f8..1868468f 100644
--- a/src/stm/stm32l.h
+++ b/src/stm/stm32l.h
@@ -171,6 +171,11 @@ stm_gpio_get(struct stm_gpio *gpio, int pin) {
return (gpio->idr >> pin) & 1;
}
+static inline uint16_t
+stm_gpio_get_all(struct stm_gpio *gpio) {
+ return gpio->idr;
+}
+
extern struct stm_gpio stm_gpioa;
extern struct stm_gpio stm_gpiob;
extern struct stm_gpio stm_gpioc;