Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
authorBdale Garbee <bdale@gag.com>
Tue, 30 Jul 2013 06:15:06 +0000 (00:15 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 30 Jul 2013 06:15:06 +0000 (00:15 -0600)
28 files changed:
src/Makefile
src/cc1111/ao_adc.c
src/core/ao.h
src/core/ao_debounce.c [new file with mode: 0644]
src/core/ao_debounce.h [new file with mode: 0644]
src/core/ao_ignite.c
src/core/ao_pyro.c
src/core/ao_pyro.h
src/drivers/ao_74hc165.c [new file with mode: 0644]
src/drivers/ao_74hc165.h [new file with mode: 0644]
src/drivers/ao_button.c
src/drivers/ao_event.c
src/drivers/ao_event.h
src/drivers/ao_pad.c
src/drivers/ao_quadrature.c
src/stm-demo/Makefile
src/stm-demo/ao_demo.c
src/stm/ao_fast_timer.c [new file with mode: 0644]
src/stm/ao_fast_timer.h [new file with mode: 0644]
src/stm/stm32l.h
src/telefire-v0.2/Makefile [new file with mode: 0644]
src/telefire-v0.2/ao_pins.h [new file with mode: 0644]
src/telefire-v0.2/ao_telefire.c [new file with mode: 0644]
src/telelco-v0.2/Makefile
src/telelco-v0.2/ao_lco.c
src/telelco-v0.2/ao_pins.h
src/telemega-v0.1/ao_pins.h
src/telemega-v0.3/ao_pins.h

index 7ffc52d6431d9b90d9621668f12226f849a0a37d..ee76c32579af451cd4d0ebd33e40fde6876315b8 100644 (file)
@@ -16,17 +16,14 @@ include Version
 
 SDCCDIRS=\
        telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \
-       teledongle-v0.2 teledongle-v0.1 \
-       telemini-v1.0 telenano-v0.1 \
+       teledongle-v0.2 \
+       telemini-v1.0 \
        telebt-v1.0 \
-       telemetrum-v0.1-sky telemetrum-v0.1-sirf \
-       telelaunch-v0.1 tidongle test \
        teleterra-v0.2 teleshield-v0.1 \
-       telefire-v0.1 \
-       spiradio-v0.1
+       telefire-v0.1 telefire-v0.2
 
 AVRDIRS=\
-       telescience-v0.1 telescience-pwm telepyro-v0.1 micropeak
+       telescience-v0.1 telescience-pwm micropeak
 
 ARMDIRS=\
        telemega-v0.1 telemega-v0.1/flash-loader \
index ed76179b5ebeec1813edad23b2f10dc8a6e6624c..4a58023d50474270d017167ef09240e99184775a 100644 (file)
@@ -144,7 +144,7 @@ ao_adc_isr(void) __interrupt 1
        }
 #endif /* telemini || telenano */
 
-#ifdef TELEFIRE_V_0_1
+#if defined(TELEFIRE_V_0_1) || defined(TELEFIRE_V_0_2)
        a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence - AO_ADC_FIRST_PIN);
        a[0] = ADCL;
        a[1] = ADCH;
index 7f344736b8f0a7bd19c5d204b09be34a0b2f62a7..caa0ec195e59f6fea2774eaefed84c3ef3517931 100644 (file)
@@ -75,6 +75,7 @@ typedef AO_PORT_TYPE ao_port_t;
 #define AO_PANIC_CRASH         14      /* Processor crashed */
 #define AO_PANIC_BUFIO         15      /* Mis-using bufio API */
 #define AO_PANIC_EXTI          16      /* Mis-using exti API */
+#define AO_PANIC_FAST_TIMER    17      /* Mis-using fast timer API */
 #define AO_PANIC_SELF_TEST_CC1120      0x40 | 1        /* Self test failure */
 #define AO_PANIC_SELF_TEST_HMC5883     0x40 | 2        /* Self test failure */
 #define AO_PANIC_SELF_TEST_MPU6000     0x40 | 3        /* Self test failure */
@@ -703,6 +704,8 @@ struct ao_ignition {
        uint8_t firing;
 };
 
+extern __code char * __code ao_igniter_status_names[];
+
 extern __xdata struct ao_ignition ao_ignition[2];
 
 enum ao_igniter_status
diff --git a/src/core/ao_debounce.c b/src/core/ao_debounce.c
new file mode 100644 (file)
index 0000000..b9d6772
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * 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>
+#include <ao_fast_timer.h>
+
+static uint8_t                 ao_debounce_initialized;
+static uint8_t                 ao_debounce_running;
+static struct ao_debounce      *ao_debounce;
+
+static uint8_t values[64];
+static uint8_t n;
+
+#define d_step(n)      (((n) + 1) & 63)
+
+static void
+_ao_debounce_set(struct ao_debounce *debounce, uint8_t value)
+{
+       if (value != debounce->value) {
+               values[n] = value;
+               n = (n + 1) & 63;
+               debounce->value = value;
+               debounce->_set(debounce, value);
+       }
+       _ao_debounce_stop(debounce);
+}
+
+void
+ao_debounce_dump(void)
+{
+       uint8_t s;
+
+       for (s = 0; s < n; s++) {
+               printf ("%d: %d\n",
+                       s, values[s]);
+       }
+       n = 0;
+}
+
+/*
+ * Get the current value, set the result when we've
+ * reached the debounce count limit
+ */
+static void
+_ao_debounce_check(struct ao_debounce *debounce)
+{
+       uint8_t next = debounce->_get(debounce);
+
+       if (next == debounce->current) {
+               if (debounce->count < debounce->hold) {
+                       if (++debounce->count == debounce->hold)
+                               _ao_debounce_set(debounce, debounce->current);
+               }
+       } else {
+               debounce->count = 0;
+               debounce->current = next;
+       }
+}
+
+static void
+_ao_debounce_isr(void)
+{
+       struct ao_debounce *debounce, *next;
+
+       for (debounce = ao_debounce; debounce; debounce = next) {
+               next = debounce->next;
+               _ao_debounce_check(debounce);
+       }
+}
+
+static void
+ao_debounce_on(void)
+{
+       ao_fast_timer_on(_ao_debounce_isr);
+}
+
+static void
+ao_debounce_off(void)
+{
+       ao_fast_timer_off(_ao_debounce_isr);
+}
+
+/*
+ * Start monitoring one pin
+ */
+void
+_ao_debounce_start(struct ao_debounce *debounce)
+{
+       uint32_t        m;
+
+       m = ao_arch_irqsave();
+       if (!debounce->running) {
+               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);
+       }
+       ao_arch_irqrestore(m);
+}
+
+/*
+ * Stop monitoring one pin
+ */
+void
+_ao_debounce_stop(struct ao_debounce *debounce)
+{
+       struct ao_debounce **prev;
+       uint32_t m;
+
+       m = ao_arch_irqsave();
+       if (debounce->running) {
+               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();
+       }
+       ao_arch_irqrestore(m);
+}
+
+void
+ao_debounce_init(void)
+{
+       if (ao_debounce_initialized)
+               return;
+       ao_debounce_initialized = 1;
+       ao_fast_timer_init();
+}
diff --git a/src/core/ao_debounce.h b/src/core/ao_debounce.h
new file mode 100644 (file)
index 0000000..19c620f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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_DEBOUNCE_H_
+#define _AO_DEBOUNCE_H_
+
+struct ao_debounce {
+       struct ao_debounce      *next;
+
+       /* time that pin value must be stable before accepting */
+       uint8_t                 hold;
+
+       /* last value reported to app; don't report it twice */
+       uint8_t                 value;
+
+       /* current value received from pins */
+       uint8_t                 current;
+
+       /* current count of intervals pin value has been stable */
+       uint8_t                 count;
+
+       /* This pin is running */
+       uint8_t                 running;
+
+       /* Get the current pin value */
+       uint8_t                 (*_get)(struct ao_debounce *debounce);
+
+       /* The stable value has changed */
+       void                    (*_set)(struct ao_debounce *debounce, uint8_t value);
+};
+
+static inline void
+ao_debounce_config(struct ao_debounce *debounce,
+                  uint8_t (*_get)(struct ao_debounce *debounce),
+                  void (*_set)(struct ao_debounce *debounce, uint8_t value),
+                  uint8_t hold)
+{
+       debounce->next = 0;
+       debounce->hold = hold;
+       debounce->value = 0xff;
+       debounce->current = 0xff;
+       debounce->count = 0;
+       debounce->running = 0;
+       debounce->_get = _get;
+       debounce->_set = _set;
+}
+
+void
+_ao_debounce_start(struct ao_debounce *debounce);
+
+void
+_ao_debounce_stop(struct ao_debounce *debounce);
+
+void
+ao_debounce_init(void);
+
+void
+ao_debounce_dump(void);
+
+#endif /* _AO_DEBOUNCE_H_ */
index 74bd0c5aea021a55a4e7f16d45300f9fcb97bebe..9f2ec0a7afc98a972ff020a5ec09df0a80890ac8 100644 (file)
 
 #include "ao.h"
 #include <ao_data.h>
+#if AO_PYRO_NUM
+#include <ao_pyro.h>
+#endif
 
+#if HAS_IGNITE
 __xdata struct ao_ignition ao_ignition[2];
 
 void
@@ -150,6 +154,8 @@ ao_igniter(void)
        }
 }
 
+#endif
+
 void
 ao_ignite_manual(void)
 {
@@ -157,33 +163,50 @@ ao_ignite_manual(void)
        if (!ao_match_word("DoIt"))
                return;
        ao_cmd_white();
-       if (ao_cmd_lex_c == 'm') {
-               if(ao_match_word("main"))
-                       ao_igniter_fire(ao_igniter_main);
-       } else {
-               if(ao_match_word("drogue"))
-                       ao_igniter_fire(ao_igniter_drogue);
+#if HAS_IGNITE
+       if (ao_cmd_lex_c == 'm' && ao_match_word("main")) {
+               ao_igniter_fire(ao_igniter_main);
+               return;
+       }
+       if (ao_cmd_lex_c == 'd' && ao_match_word("drogue")) {
+               ao_igniter_fire(ao_igniter_drogue);
+               return;
+       }
+#endif
+#if AO_PYRO_NUM
+       if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') {
+               ao_pyro_manual(ao_cmd_lex_c - '0');
+               return;
        }
+#endif
+       ao_cmd_status = ao_cmd_syntax_error;
 }
 
-static __code char * __code igniter_status_names[] = {
+__code char * __code ao_igniter_status_names[] = {
        "unknown", "ready", "active", "open"
 };
 
+#if HAS_IGNITE
 void
 ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant
 {
        enum ao_igniter_status status = ao_igniter_status(igniter);
        printf("Igniter: %6s Status: %s\n",
               name,
-              igniter_status_names[status]);
+              ao_igniter_status_names[status]);
 }
+#endif
 
 void
 ao_ignite_test(void)
 {
+#if HAS_IGNITE
        ao_ignite_print_status(ao_igniter_drogue, "drogue");
        ao_ignite_print_status(ao_igniter_main, "main");
+#endif
+#if AO_PYRO_NUM
+       ao_pyro_print_status();
+#endif
 }
 
 __code struct ao_cmds ao_ignite_cmds[] = {
@@ -192,6 +215,7 @@ __code struct ao_cmds ao_ignite_cmds[] = {
        { 0,    NULL },
 };
 
+#if HAS_IGNITE
 __xdata struct ao_task ao_igniter_task;
 
 void
@@ -200,11 +224,14 @@ ao_ignite_set_pins(void)
        ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, 0);
        ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, 0);
 }
+#endif
 
 void
 ao_igniter_init(void)
 {
+#if HAS_IGNITE
        ao_ignite_set_pins();
-       ao_cmd_register(&ao_ignite_cmds[0]);
        ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
+#endif
+       ao_cmd_register(&ao_ignite_cmds[0]);
 }
index 39f40dfa44986c62fc225150bf8c8ff39ee03174..531e1f5003118228c05969ef5b8f4d8de956730e 100644 (file)
 
 #define ao_lowbit(x)   ((x) & (-x))
 
+#ifndef AO_FLIGHT_TEST
+enum ao_igniter_status
+ao_pyro_status(uint8_t p)
+{
+       __xdata struct ao_data packet;
+       __pdata int16_t value;
+
+       ao_arch_critical(
+               ao_data_get(&packet);
+               );
+
+       value = (AO_IGNITER_CLOSED>>1);
+       value = AO_SENSE_PYRO(&packet, p);
+       if (value < AO_IGNITER_OPEN)
+               return ao_igniter_open;
+       else if (value > AO_IGNITER_CLOSED)
+               return ao_igniter_ready;
+       else
+               return ao_igniter_unknown;
+}
+
+void
+ao_pyro_print_status(void)
+{
+       uint8_t p;
+
+       for(p = 0; p < AO_PYRO_NUM; p++) {
+               enum ao_igniter_status status = ao_pyro_status(p);
+               printf("Igniter: %d Status: %s\n",
+                      p, ao_igniter_status_names[status]);
+       }
+}
+#endif
+
 uint16_t       ao_pyro_fired;
 
 /*
@@ -441,25 +475,17 @@ ao_pyro_set(void)
        _ao_config_edit_finish();
 }
 
-static void
-ao_pyro_manual(void)
+void
+ao_pyro_manual(uint8_t p)
 {
-       ao_cmd_white();
-       if (!ao_match_word("DoIt"))
+       printf ("ao_pyro_manual %d\n", p);
+       if (p >= AO_PYRO_NUM) {
+               ao_cmd_status = ao_cmd_syntax_error;
                return;
-       ao_cmd_white();
-       ao_cmd_decimal();
-       if (ao_cmd_lex_i < 0 || AO_PYRO_NUM <= ao_cmd_lex_i)
-               return;
-       ao_pyro_pins_fire(1 << ao_cmd_lex_i);
-
+       }
+       ao_pyro_pins_fire(1 << p);
 }
 
-const struct ao_cmds ao_pyro_cmds[] = {
-       { ao_pyro_manual,       "P DoIt <n>\0Fire igniter" },
-       { 0, NULL }
-};
-
 void
 ao_pyro_init(void)
 {
@@ -487,7 +513,6 @@ ao_pyro_init(void)
 #if AO_PYRO_NUM > 7
        ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0);
 #endif
-       ao_cmd_register(&ao_pyro_cmds[0]);
        ao_add_task(&ao_pyro_task, ao_pyro, "pyro");
 }
 #endif
index 1f8385426753cde410c533b00f516a810c64f2eb..0c5642d6ea91f2ff12e76c6b1321ff69882b3a4c 100644 (file)
@@ -74,4 +74,10 @@ ao_pyro_show(void);
 void
 ao_pyro_init(void);
 
+void
+ao_pyro_manual(uint8_t p);
+
+void
+ao_pyro_print_status(void);
+
 #endif
diff --git a/src/drivers/ao_74hc165.c b/src/drivers/ao_74hc165.c
new file mode 100644 (file)
index 0000000..f24fce3
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+/*
+ * 74HC165 driver.
+ * Reads a single byte from the shift register
+ */
+
+#include <ao.h>
+#include <ao_74hc165.h>
+
+uint8_t
+ao_74hc165_read(void)
+{
+       static __xdata state;
+       ao_mutex_get(&ao_spi_mutex);
+       ao_spi_set_speed(AO_SPI_SPEED_FAST);
+       AO_74HC165_CS = 1;
+       ao_spi_recv(&state, 1, AO_74HC165_SPI_BUS);
+       AO_74HC165_CS = 0;
+       ao_mutex_put(&ao_spi_mutex);
+       return state;
+}
+
+static void
+ao_74hc165_cmd(void)
+{
+       uint8_t v;
+
+       v = ao_74hc165_read();
+       printf ("Switches: 0x%02x\n", v);
+}
+
+static const struct ao_cmds ao_74hc165_cmds[] = {
+       { ao_74hc165_cmd, "L\0Show 74hc165" },
+       { 0, NULL }
+};
+
+void
+ao_74hc165_init(void)
+{
+       ao_enable_output(AO_74HC165_CS_PORT, AO_74HC165_CS_PIN, AO_74HC165_CS, 0);
+       ao_cmd_register(&ao_74hc165_cmds[0]);
+}
diff --git a/src/drivers/ao_74hc165.h b/src/drivers/ao_74hc165.h
new file mode 100644 (file)
index 0000000..3ae5135
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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_74HC165_H_
+#define _AO_74HC165_H_
+
+uint8_t
+ao_74hc165_read(void);
+
+void
+ao_74hc165_init(void);
+
+#endif /* _AO_74HC165_H_ */
index a507c909ea0248d80032a0739a67f0e4a8b05819..25c0cd5cea66b753813cd566102ce5ba6f7c9da9 100644 (file)
@@ -18,6 +18,7 @@
 #include <ao.h>
 #include <ao_button.h>
 #include <ao_exti.h>
+#include <ao_debounce.h>
 #if AO_EVENT
 #include <ao_event.h>
 #define ao_button_queue(b,v)   ao_event_put_isr(AO_EVENT_BUTTON, b, v)
 #define ao_button_queue(b,v)
 #endif
 
-static uint8_t         ao_button[AO_BUTTON_COUNT];
-static AO_TICK_TYPE    ao_button_time[AO_BUTTON_COUNT];
+#define AO_BUTTON_DEBOUNCE_HOLD        10
 
-#define AO_DEBOUNCE    AO_MS_TO_TICKS(20)
+static struct ao_debounce      ao_button_debounce[AO_BUTTON_COUNT];
 
 #define port(q)        AO_BUTTON_ ## q ## _PORT
 #define bit(q) AO_BUTTON_ ## q
 #define pin(q) AO_BUTTON_ ## q ## _PIN
 
-static void
-ao_button_do(uint8_t b, uint8_t v)
-{
-       /* Debounce */
-       if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE)
-               return;
-
-       /* pins are inverted */
-       v = !v;
-       if (ao_button[b] != v) {
-               ao_button[b] = v;
-               ao_button_time[b] = ao_tick_count;
-               ao_button_queue(b, v);
-               ao_wakeup(&ao_button[b]);
-       }
-}
+/* pins are inverted */
+#define ao_button_value(b)     !ao_gpio_get(port(b), bit(b), pin(b))
 
-#define ao_button_update(b)    ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
-
-static void
-ao_button_isr(void)
+static uint8_t
+_ao_button_get(struct ao_debounce *debounce)
 {
+       uint8_t b = debounce - ao_button_debounce;
+
+       switch (b) {
 #if AO_BUTTON_COUNT > 0
-       ao_button_update(0);
+       case 0: return ao_button_value(0);
 #endif
 #if AO_BUTTON_COUNT > 1
-       ao_button_update(1);
+       case 1: return ao_button_value(1);
 #endif
 #if AO_BUTTON_COUNT > 2
-       ao_button_update(2);
+       case 2: return ao_button_value(2);
 #endif
 #if AO_BUTTON_COUNT > 3
-       ao_button_update(3);
+       case 3: return ao_button_value(3);
 #endif
 #if AO_BUTTON_COUNT > 4
-       ao_button_update(4);
+       case 4: return ao_button_value(4);
 #endif
+       }
+}
+
+static void
+_ao_button_set(struct ao_debounce *debounce, uint8_t value)
+{
+       uint8_t b = debounce - ao_button_debounce;
+
+       ao_button_queue(b, value);
+}
+
+
+#define ao_button_update(b)    ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
+
+static void
+ao_button_debounce_init(struct ao_debounce *debounce) {
+       ao_debounce_config(debounce,
+                          _ao_button_get,
+                          _ao_button_set,
+                          AO_BUTTON_DEBOUNCE_HOLD);
+}
+
+static void
+ao_button_isr(void)
+{
+       uint8_t b;
+
+       for (b = 0; b < AO_BUTTON_COUNT; b++)
+               _ao_debounce_start(&ao_button_debounce[b]);
 }
 
 #define init(b) do {                                                   \
+               ao_button_debounce_init(&ao_button_debounce[b]);        \
                ao_enable_port(port(b));                                \
                                                                        \
                ao_exti_setup(port(b), bit(b),                          \
@@ -91,4 +108,14 @@ ao_button_init(void)
 #if AO_BUTTON_COUNT > 1
        init(1);
 #endif
+#if AO_BUTTON_COUNT > 2
+       init(2);
+#endif
+#if AO_BUTTON_COUNT > 3
+       init(3);
+#endif
+#if AO_BUTTON_COUNT > 4
+       init(4);
+#endif
+       ao_debounce_init();
 }
index 440ef2de6d0ecd9f89a2359ce5387a9dcfd1e820..c428125d0760771b73e7264fe3211dc632256676 100644 (file)
 #define ao_event_queue_empty() (ao_event_queue_insert == ao_event_queue_remove)
 #define ao_event_queue_full()  (ao_event_queue_next(ao_event_queue_insert) == ao_event_queue_remove)
 
-/*
- * Whether a sequence of events from the same device should be collapsed
- */
-#define ao_event_can_collapse(type)    ((type) == AO_EVENT_QUADRATURE)
-
 struct ao_event ao_event_queue[AO_EVENT_QUEUE];
 uint8_t                ao_event_queue_insert;
 uint8_t                ao_event_queue_remove;
@@ -48,17 +43,9 @@ ao_event_get(struct ao_event *ev)
 
 /* called with interrupts disabled */
 void
-ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value)
+ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value)
 {
        if (!ao_event_queue_full()) {
-
-               if (ao_event_can_collapse(type) && !ao_event_queue_empty()) {
-                       uint8_t prev = ao_event_queue_prev(ao_event_queue_insert);
-
-                       if (ao_event_queue[prev].type == type &&
-                           ao_event_queue[prev].unit == unit)
-                               ao_event_queue_insert = prev;
-               }
                ao_event_queue[ao_event_queue_insert] = (struct ao_event) {
                        .type = type,
                        .unit = unit,
@@ -71,7 +58,7 @@ ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value)
 }
 
 void
-ao_event_put(uint8_t type, uint8_t unit, uint32_t value)
+ao_event_put(uint8_t type, uint8_t unit, int32_t value)
 {
        ao_arch_critical(ao_event_put_isr(type, unit, value););
 }
index 25c49c3574b7f0f629d9deeef7b6eaaa5c125bf1..ed9a743329a49dc2cda65fa3b55b38b8fb225f9a 100644 (file)
@@ -26,16 +26,16 @@ struct ao_event {
        uint8_t         type;
        uint8_t         unit;
        uint16_t        tick;
-       uint32_t        value;
+       int32_t         value;
 };
 
 uint8_t
 ao_event_get(struct ao_event *ev);
 
 void
-ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value);
+ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value);
 
 void
-ao_event_put(uint8_t type, uint8_t unit, uint32_t value);
+ao_event_put(uint8_t type, uint8_t unit, int32_t value);
 
 #endif /* _AO_EVENT_H_ */
index 6cec98ab6e52bcc22ce3d68ee21d8579ae521973..e205f99b5e26a1b360cac76a6f821dd305e565a9 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <ao.h>
 #include <ao_pad.h>
-#include <ao_74hc497.h>
+#include <ao_74hc165.h>
 #include <ao_radio_cmac.h>
 
 static __xdata uint8_t ao_pad_ignite;
@@ -182,10 +182,7 @@ ao_pad_monitor(void)
 
                if (ao_pad_armed) {
                        ao_strobe(1);
-                       if (sample & 2)
-                               ao_siren(1);
-                       else
-                               ao_siren(0);
+                       ao_siren(1);
                        beeping = 1;
                } else if (query.arm_status == AO_PAD_ARM_STATUS_ARMED && !beeping) {
                        if (arm_beep_time == 0) {
@@ -218,6 +215,21 @@ ao_pad_enable(void)
        ao_wakeup (&ao_pad_disabled);
 }
 
+#if HAS_74HC165
+static uint8_t
+ao_pad_read_box(void)
+{
+       uint8_t         byte = ao_74hc165_read();
+       uint8_t         h, l;
+
+       h = byte >> 4;
+       l = byte & 0xf;
+       return h * 10 + l;
+}
+#else
+#define ao_pad_read_box()      0
+#endif
+
 static void
 ao_pad(void)
 {
@@ -236,8 +248,10 @@ ao_pad(void)
                if (ret != AO_RADIO_CMAC_OK)
                        continue;
                
-               PRINTD ("tick %d box %d cmd %d channels %02x\n",
-                       command.tick, command.box, command.cmd, command.channels);
+               ao_pad_box = ao_pad_read_box();
+
+               PRINTD ("tick %d box %d (me %d) cmd %d channels %02x\n",
+                       command.tick, command.box, ao_pad_box, command.cmd, command.channels);
 
                switch (command.cmd) {
                case AO_LAUNCH_ARM:
@@ -327,7 +341,7 @@ ao_pad_test(void)
        }
 
        for (c = 0; c < AO_PAD_NUM; c++) {
-               printf ("Pad %d: ");
+               printf ("Pad %d: ", c);
                switch (query.igniter_status[c]) {
                case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED:     printf ("No igniter. Relay closed\n"); break;
                case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN:       printf ("No igniter. Relay open\n"); break;
@@ -362,6 +376,26 @@ ao_pad_set_debug(void)
        if (ao_cmd_status == ao_cmd_success)
                ao_pad_debug = ao_cmd_lex_i != 0;
 }
+
+
+static void
+ao_pad_alarm_debug(void)
+{
+       uint8_t which, value;
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       which = ao_cmd_lex_i;
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       value = ao_cmd_lex_i;
+       printf ("Set %s to %d\n", which ? "siren" : "strobe", value);
+       if (which)
+               ao_siren(value);
+       else
+               ao_strobe(value);
+}
 #endif
 
 __code struct ao_cmds ao_pad_cmds[] = {
@@ -369,6 +403,7 @@ __code struct ao_cmds ao_pad_cmds[] = {
        { ao_pad_manual,        "i <key> <n>\0Fire igniter. <key> is doit with D&I" },
 #if DEBUG
        { ao_pad_set_debug,     "D <0 off, 1 on>\0Debug" },
+       { ao_pad_alarm_debug,   "S <0 strobe, 1 siren> <0 off, 1 on>\0Set alarm output" },
 #endif
        { 0, NULL }
 };
index 6cc2467a44ba2449121faaffcf4451d9401d0fe0..d07488d08d4f9307b661a0f690f9447dab4fec73 100644 (file)
 #include <ao.h>
 #include <ao_quadrature.h>
 #include <ao_exti.h>
-#if AO_EVENT
+#include <ao_fast_timer.h>
 #include <ao_event.h>
-#define ao_quadrature_queue(q) ao_event_put_isr(AO_EVENT_QUADRATURE, q, ao_quadrature_count[q])
-#else
-#define ao_quadrature_queue(q)
-#endif
 
 __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
-
 static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT];
+static int8_t  ao_quadrature_raw[AO_QUADRATURE_COUNT];
 
 #define BIT(a,b)       ((a) | ((b) << 1))
 #define STATE(old_a, old_b, new_a, new_b)      (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b)))
@@ -35,41 +31,76 @@ static uint8_t      ao_quadrature_state[AO_QUADRATURE_COUNT];
 #define port(q)        AO_QUADRATURE_ ## q ## _PORT
 #define bita(q) AO_QUADRATURE_ ## q ## _A
 #define bitb(q) AO_QUADRATURE_ ## q ## _B
+#define pina(q) AO_QUADRATURE_ ## q ## _A ## _PIN
+#define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN
+#define isr(q)  ao_quadrature_isr_ ## q
 
-#define ao_quadrature_update(q) do {                                   \
-               ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); \
-               ao_quadrature_state[q] |= ao_gpio_get(port(q), bita(q), 0); \
-               ao_quadrature_state[q] |= ao_gpio_get(port(q), bitb(q), 0) << 1; \
-       } while (0)
-       
+static inline uint16_t
+ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b) {
+       uint16_t        v = stm_gpio_get_all(gpio);
+
+       return ~((((v >> pin_a) & 1) | (((v >> pin_b) & 1) << 1))) & 3;
+}
+
+#define _ao_quadrature_get(q)  ao_quadrature_read(port(q), bita(q), bitb(q))
 
 static void
-ao_quadrature_isr(void)
+_ao_quadrature_queue(uint8_t q, int8_t step)
 {
-       uint8_t q;
-#if AO_QUADRATURE_COUNT > 0
-       ao_quadrature_update(0);
-#endif
-#if AO_QUADRATURE_COUNT > 1
-       ao_quadrature_update(1);
+       ao_quadrature_count[q] += step;
+#if AO_EVENT
+       ao_event_put_isr(AO_EVENT_QUADRATURE, q, step);
 #endif
+       ao_wakeup(&ao_quadrature_count[q]);
+}
 
-       for (q = 0; q < AO_QUADRATURE_COUNT; q++) {
-               switch (ao_quadrature_state[q]) {
-               case STATE(0, 1, 0, 0):
-                       ao_quadrature_count[q]++;
-                       break;
-               case STATE(1, 0, 0, 0):
-                       ao_quadrature_count[q]--;
-                       break;
-               default:
-                       continue;
-               }
-               ao_quadrature_queue(q);
-               ao_wakeup(&ao_quadrature_count[q]);
+static const int8_t    step[16] = {
+       [STATE(0,0,0,0)] = 0,
+       [STATE(0,0,0,1)] = -1,
+       [STATE(0,0,1,0)] = 1,
+       [STATE(0,0,1,1)] = 0,
+       [STATE(0,1,0,0)] = 1,
+       [STATE(0,1,1,0)] = 0,
+       [STATE(0,1,1,1)] = -1,
+       [STATE(1,0,0,0)] = -1,
+       [STATE(1,0,0,1)] = 0,
+       [STATE(1,0,1,0)] = 0,
+       [STATE(1,0,1,1)] = 1,
+       [STATE(1,1,0,0)] = 0,
+       [STATE(1,1,0,1)] = 1,
+       [STATE(1,1,1,0)] = -1,
+       [STATE(1,1,1,1)] = 0
+};
+
+static void
+_ao_quadrature_set(uint8_t q, uint8_t value) {
+       uint8_t v;
+       
+       v = ao_quadrature_state[q] & 3;
+       value = value & 3;
+
+       if (v == value)
+               return;
+       
+       ao_quadrature_state[q] = (v << 2) | value;
+
+       ao_quadrature_raw[q] += step[ao_quadrature_state[q]];
+       if (value == 0) {
+               if (ao_quadrature_raw[q] == 4)
+                       _ao_quadrature_queue(q, 1);
+               else if (ao_quadrature_raw[q] == -4)
+                       _ao_quadrature_queue(q, -1);
+               ao_quadrature_raw[q] = 0;
        }
 }
 
+static void
+ao_quadrature_isr(void)
+{
+       _ao_quadrature_set(0, _ao_quadrature_get(0));
+       _ao_quadrature_set(1, _ao_quadrature_get(1));
+}
+
 int32_t
 ao_quadrature_poll(uint8_t q)
 {
@@ -92,6 +123,15 @@ ao_quadrature_test(void)
 
        ao_cmd_decimal();
        q = ao_cmd_lex_i;
+       if (q >= AO_QUADRATURE_COUNT) {
+               ao_cmd_status = ao_cmd_syntax_error;
+               return;
+       }
+       printf ("count %d state %x raw %d\n",
+               ao_quadrature_count[q],
+               ao_quadrature_state[q],
+               ao_quadrature_raw[q]);
+#if 0
        for (;;) {
                int32_t c;
                flush();
@@ -100,6 +140,7 @@ ao_quadrature_test(void)
                if (c == 100)
                        break;
        }
+#endif
 }
 
 static const struct ao_cmds ao_quadrature_cmds[] = {
@@ -107,18 +148,9 @@ static const struct ao_cmds ao_quadrature_cmds[] = {
        { 0, NULL }
 };
 
-#define init(q) do {                                                   \
-               ao_enable_port(port(q));                                \
-                                                                       \
-               ao_exti_setup(port(q), bita(q),                         \
-                             AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
-                             ao_quadrature_isr);                       \
-               ao_exti_enable(port(q), bita(q));                       \
-                                                                       \
-               ao_exti_setup(port(q), bitb(q),                         \
-                             AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
-                             ao_quadrature_isr);                       \
-               ao_exti_enable(port(q), bitb(q));                       \
+#define init(q) do {                                   \
+               ao_enable_input(port(q), bita(q), 0);   \
+               ao_enable_input(port(q), bitb(q), 0);   \
        } while (0)
 
 void
@@ -130,5 +162,7 @@ ao_quadrature_init(void)
 #if AO_QUADRATURE_COUNT > 1
        init(1);
 #endif
+       ao_fast_timer_init();
+       ao_fast_timer_on(ao_quadrature_isr);
        ao_cmd_register(&ao_quadrature_cmds[0]);
 }
index d1f825db7cc0baf886eb59ff144e321b98ae2647..48fa07ebf5240b881dfdaada8ee76f63e743a325 100644 (file)
@@ -36,10 +36,7 @@ ALTOS_SRC = \
        ao_data.c \
        ao_i2c_stm.c \
        ao_usb_stm.c \
-       ao_exti_stm.c \
-       ao_event.c \
-       ao_quadrature.c \
-       ao_button.c
+       ao_exti_stm.c
 
 PRODUCT=StmDemo-v0.0
 PRODUCT_DEF=-DSTM_DEMO
index 5677cdf46d3b5ed2261b94f5a10ce21aab21fdb0..58cf651b472471bef053a180e525fd321740bef6 100644 (file)
@@ -153,6 +153,7 @@ ao_temp (void)
        printf ("temp: %d\n", temp);
 }
 
+#if 0
 static void
 ao_event(void)
 {
@@ -168,6 +169,7 @@ ao_event(void)
        }
 
 }
+#endif
 
 __code struct ao_cmds ao_demo_cmds[] = {
        { ao_dma_test,  "D\0DMA test" },
@@ -175,7 +177,7 @@ __code struct ao_cmds ao_demo_cmds[] = {
        { ao_spi_read, "R\0SPI read" },
        { ao_i2c_write, "i\0I2C write" },
        { ao_temp, "t\0Show temp" },
-       { ao_event, "e\0Monitor event queue" },
+/*     { ao_event, "e\0Monitor event queue" }, */
        { 0, NULL }
 };
 
diff --git a/src/stm/ao_fast_timer.c b/src/stm/ao_fast_timer.c
new file mode 100644 (file)
index 0000000..d61b40c
--- /dev/null
@@ -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 (file)
index 0000000..90fb393
--- /dev/null
@@ -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_ */
index 63bde0f8b29b475d887ddd2624c43fcc70395040..1868468f45ad5cf3f5ddcb5dce591bbfef04361a 100644 (file)
@@ -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;
diff --git a/src/telefire-v0.2/Makefile b/src/telefire-v0.2/Makefile
new file mode 100644 (file)
index 0000000..3353bc1
--- /dev/null
@@ -0,0 +1,103 @@
+#
+# TeleFire build file
+#
+
+TELEFIRE_VER=0.2
+TELEFIRE_DEF=0_2
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pad.h \
+       cc1111.h \
+       ao_product.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_convert.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_stdio.c \
+       ao_storage.c \
+       ao_task.c \
+       ao_freq.c
+
+CC1111_SRC = \
+       ao_adc.c \
+       ao_aes.c \
+       ao_beep.c \
+       ao_dma.c \
+       ao_intflash.c \
+       ao_radio.c \
+       ao_radio_cmac.c \
+       ao_romconfig.c \
+       ao_serial.c \
+       ao_spi.c \
+       ao_string.c \
+       ao_timer.c \
+       ao_usb.c \
+       _bp.c
+
+DRIVER_SRC = \
+       ao_pca9922.c \
+       ao_74hc165.c \
+       ao_pad.c \
+       ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+       ao_telefire.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC)
+
+PROGNAME = telefire-v$(TELEFIRE_VER)
+PROG = $(PROGNAME)-$(VERSION).ihx
+PRODUCT=TeleFire-v$(TELEFIRE_VER)
+PRODUCT_DEF=-DTELEFIRE_V_$(TELEFIRE_DEF)
+IDPRODUCT=0x000f
+CODESIZE=0x6700
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM)  || rm $@
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean: clean-cc1111
+
+install:
+
+uninstall:
+
diff --git a/src/telefire-v0.2/ao_pins.h b/src/telefire-v0.2/ao_pins.h
new file mode 100644 (file)
index 0000000..f405072
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2010 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_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO      1
+
+#define HAS_FLIGHT             0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_GPS                        0
+#define HAS_SERIAL_1           0
+#define HAS_ADC                        1
+#define HAS_DBG                        0
+#define HAS_EEPROM             1
+#define HAS_LOG                        0
+#define HAS_PAD                        1
+#define USE_INTERNAL_FLASH     1
+#define DBG_ON_P1              0
+#define IGNITE_ON_P2           0
+#define IGNITE_ON_P1           1
+#define IGNITE_ON_P0           0
+#define PACKET_HAS_MASTER      0
+#define PACKET_HAS_SLAVE       0
+
+#define AO_LED_CONTINUITY(c)   (1 << (c))
+#define AO_LED_CONTINUITY_MASK (0xf)
+#define AO_LED_RX              0x10
+#define AO_LED_TX              0x20
+#define AO_LED_ARMED           0x40
+#define AO_LED_POWER           0x80
+
+#define AO_LED_RED             AO_LED_TX
+#define AO_LED_GREEN           AO_LED_RX
+
+#define LEDS_AVAILABLE         (0xff)
+#define HAS_EXTERNAL_TEMP      0
+#define HAS_ACCEL_REF          0
+#define SPI_CS_ON_P1           1
+#define HAS_AES                        1
+#define DMA_SHARE_AES_RADIO    1
+
+#define SPI_CS_PORT    P1
+#define SPI_CS_SEL     P1SEL
+#define SPI_CS_DIR     P1DIR
+
+#define SPI_CONST      0x00
+
+#define HAS_SPI_0              0
+#define HAS_SPI_1              1
+#define SPI_1_ALT_1            0
+#define SPI_1_ALT_2            1
+
+#define HAS_74HC165            1
+#define AO_74HC165_CS_PORT     P1
+#define AO_74HC165_CS_PIN      4
+#define AO_74HC165_CS          P1_4
+
+#define AO_PCA9922_CS_PORT     P2
+#define AO_PCA9922_CS_PIN      0
+#define AO_PCA9922_CS          P2_0
+
+#define AO_PAD_NUM             4
+#define        AO_PAD_PORT             P1
+#define AO_PAD_DIR             P1DIR
+
+#define AO_PAD_PIN_0           0
+#define AO_PAD_0               P1_0
+#define AO_PAD_ADC_0           0
+
+#define AO_PAD_PIN_1           1
+#define AO_PAD_1               P1_1
+#define AO_PAD_ADC_1           1
+
+#define AO_PAD_PIN_2           2
+#define AO_PAD_2               P1_2
+#define AO_PAD_ADC_2           2
+
+#define AO_PAD_PIN_3           3
+#define AO_PAD_3               P1_3
+#define AO_PAD_ADC_3           3
+
+#define AO_PAD_ALL_PINS                ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3))
+#define AO_PAD_ALL_CHANNELS    ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
+
+#define AO_SIREN_PORT          P2
+#define AO_SIREN_DIR           P2DIR
+#define AO_SIREN_PIN           3
+#define AO_SIREN               P2_3
+
+#define AO_STROBE_PORT         P2
+#define AO_STROBE_DIR          P2DIR
+#define AO_STROBE_PIN          4
+#define AO_STROBE              P2_4
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED    3524
+#define AO_PAD_NO_IGNITER      16904
+#define AO_PAD_GOOD_IGNITER    22514
+
+#define AO_PAD_ADC_PYRO                4
+#define AO_PAD_ADC_BATT                5
+
+#define AO_ADC_FIRST_PIN       0
+
+struct ao_adc {
+       int16_t         sense[AO_PAD_NUM];
+       int16_t         pyro;
+       int16_t         batt;
+};
+
+#define AO_ADC_DUMP(p)                                                 \
+       printf ("tick: %5u 0: %5d 1: %5d 2: %5d 3: %5d pyro: %5d batt %5d\n", \
+               (p)->tick,                                              \
+               (p)->adc.sense[0],                                      \
+               (p)->adc.sense[1],                                      \
+               (p)->adc.sense[2],                                      \
+               (p)->adc.sense[3],                                      \
+               (p)->adc.pyro,                                          \
+               (p)->adc.batt)
+
+#define AO_ADC_PINS    ((1 << AO_PAD_ADC_0) | \
+                        (1 << AO_PAD_ADC_1) | \
+                        (1 << AO_PAD_ADC_2) | \
+                        (1 << AO_PAD_ADC_3) | \
+                        (1 << AO_PAD_ADC_PYRO) | \
+                        (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefire-v0.2/ao_telefire.c b/src/telefire-v0.2/ao_telefire.c
new file mode 100644 (file)
index 0000000..f27ca5e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2012 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_pad.h>
+#include <ao_74hc165.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init(LEDS_AVAILABLE);
+
+       ao_task_init();
+
+       ao_timer_init();
+       ao_adc_init();
+       ao_cmd_init();
+       ao_spi_init();
+       ao_74hc165_init();
+       ao_storage_init();
+       ao_usb_init();
+       ao_radio_init();
+       ao_aes_init();
+       ao_pad_init();
+//     ao_radio_cmac_cmd_init();
+       ao_config_init();
+       ao_start_scheduler();
+}
index cc6e62c4a2502480e1be827ba645d697515104eb..f78ca9e25f6c06b93d3335b398fd96c945504ba8 100644 (file)
@@ -21,6 +21,7 @@ INC = \
        ao_radio_spi.h \
        ao_radio_cmac.h \
        ao_cc1120_CC1120.h \
+       ao_debounce.h \
        stm32l.h
 
 #
@@ -49,6 +50,7 @@ ALTOS_SRC = \
        ao_beep_stm.c \
        ao_storage.c \
        ao_eeprom_stm.c \
+       ao_fast_timer.c \
        ao_lcd_stm.c \
        ao_usb_stm.c \
        ao_exti_stm.c \
@@ -59,6 +61,7 @@ ALTOS_SRC = \
        ao_fec_tx.c \
        ao_fec_rx.c \
        ao_seven_segment.c \
+       ao_debounce.c \
        ao_quadrature.c \
        ao_button.c \
        ao_event.c \
index 418c0509539e34dfc65a4d5707e23c60e4468b14..e8d16ca93cfdaf24b0c9a237b2f407571bb0899e 100644 (file)
@@ -49,16 +49,16 @@ static uint16_t     ao_lco_tick_offset;
 static struct ao_pad_query     ao_pad_query;
 
 static void
-ao_lco_set_pad(void)
+ao_lco_set_pad(uint8_t pad)
 {
-       ao_seven_segment_set(AO_LCO_PAD_DIGIT, ao_lco_pad + 1);
+       ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad + 1);
 }
 
 static void
-ao_lco_set_box(void)
+ao_lco_set_box(uint8_t box)
 {
-       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, ao_lco_box % 10);
-       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, ao_lco_box / 10);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, box / 10);
 }
 
 #define MASK_SIZE(n)   (((n) + 7) >> 3)
@@ -103,8 +103,6 @@ ao_lco_input(void)
        int8_t  dir, new_box, new_pad;
 
        ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
-       ao_lco_set_pad();
-       ao_lco_set_box();
        for (;;) {
                ao_event_get(&event);
                PRINTD("event type %d unit %d value %d\n",
@@ -114,11 +112,9 @@ ao_lco_input(void)
                        switch (event.unit) {
                        case AO_QUADRATURE_PAD:
                                if (!ao_lco_armed) {
-                                       if (event.value == ao_lco_pad)
-                                               break;
-                                       dir = ((int8_t) event.value - (int8_t) ao_lco_pad) > 0 ? 1 : -1;
-                                       new_pad = event.value;
-                                       while (!ao_lco_pad_present(new_pad)) {
+                                       dir = (int8_t) event.value;
+                                       new_pad = ao_lco_pad;
+                                       do {
                                                new_pad += dir;
                                                if (new_pad > AO_PAD_MAX_CHANNELS)
                                                        new_pad = 0;
@@ -126,34 +122,30 @@ ao_lco_input(void)
                                                        new_pad = AO_PAD_MAX_CHANNELS - 1;
                                                if (new_pad == ao_lco_pad)
                                                        break;
-                                       }
+                                       } while (!ao_lco_pad_present(new_pad));
                                        if (new_pad != ao_lco_pad) {
                                                ao_lco_pad = new_pad;
-                                               ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad;
-                                               ao_lco_set_pad();
+                                               ao_lco_set_pad(ao_lco_pad);
                                        }
                                }
                                break;
                        case AO_QUADRATURE_BOX:
                                if (!ao_lco_armed) {
-                                       if (event.value == ao_lco_box)
-                                               break;
-                                       dir = ((int8_t) event.value - (int8_t) ao_lco_box) > 0 ? 1 : -1;
-                                       new_box = event.value;
-                                       while (!ao_lco_box_present(new_box)) {
+                                       dir = (int8_t) event.value;
+                                       new_box = ao_lco_box;
+                                       do {
                                                new_box += dir;
                                                if (new_box > ao_lco_max_box)
                                                        new_box = ao_lco_min_box;
                                                else if (new_box < ao_lco_min_box)
-                                                       new_box = ao_lco_min_box;
+                                                       new_box = ao_lco_max_box;
                                                if (new_box == ao_lco_box)
                                                        break;
-                                       }
-                                       ao_quadrature_count[AO_QUADRATURE_PAD] = new_box;
+                                       } while (!ao_lco_box_present(new_box));
                                        if (ao_lco_box != new_box) {
                                                ao_lco_box = new_box;
                                                ao_lco_got_channels = 0;
-                                               ao_lco_set_box();
+                                               ao_lco_set_box(ao_lco_box);
                                        }
                                }
                                break;
@@ -219,7 +211,7 @@ ao_lco_update(void)
                ao_lco_valid = 1;
                if (!c) {
                        ao_lco_pad = ao_lco_pad_first();
-                       ao_lco_set_pad();
+                       ao_lco_set_pad(ao_lco_pad);
                }
        } else
                ao_lco_valid = 0;
@@ -232,13 +224,24 @@ ao_lco_update(void)
               query.igniter_status[2],
               query.igniter_status[3]);
 #endif
-
        ao_wakeup(&ao_pad_query);
 }
 
+static void
+ao_lco_box_reset_present(void)
+{
+       ao_lco_min_box = 0xff;
+       ao_lco_max_box = 0x00;
+       memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask));
+}
+
 static void
 ao_lco_box_set_present(uint8_t box)
 {
+       if (box < ao_lco_min_box)
+               ao_lco_min_box = box;
+       if (box > ao_lco_max_box)
+               ao_lco_max_box = box;
        if (box >= AO_PAD_MAX_BOXES)
                return;
        ao_lco_box_mask[MASK_ID(box)] |= 1 << MASK_SHIFT(box);
@@ -249,19 +252,18 @@ ao_lco_search(void)
 {
        uint16_t        tick_offset;
        int8_t          r;
-
-       ao_lco_min_box = 0xff;
-       ao_lco_max_box = 0x00;
-       for (ao_lco_box = 0; ao_lco_box < AO_PAD_MAX_BOXES; ao_lco_box++) {
-               if ((ao_lco_box % 10) == 0)
-                       ao_lco_set_box();
-               r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset);
+       uint8_t         box;
+
+       ao_lco_box_reset_present();
+       for (box = 0; box < AO_PAD_MAX_BOXES; box++) {
+               if ((box % 10) == 0)
+                       ao_lco_set_box(box);
+               tick_offset = 0;
+               r = ao_lco_query(box, &ao_pad_query, &tick_offset);
+               PRINTD("box %d result %d\n", box, r);
                if (r == AO_RADIO_CMAC_OK) {
-                       if (ao_lco_box < ao_lco_min_box)
-                               ao_lco_min_box = ao_lco_box;
-                       if (ao_lco_box > ao_lco_max_box)
-                               ao_lco_max_box = ao_lco_box;
-                       ao_lco_box_set_present(ao_lco_box);
+                       ao_lco_box_set_present(box);
+                       ao_delay(AO_MS_TO_TICKS(30));
                }
        }
        if (ao_lco_min_box <= ao_lco_max_box)
@@ -271,6 +273,8 @@ ao_lco_search(void)
        ao_lco_valid = 0;
        ao_lco_got_channels = 0;
        ao_lco_pad = 0;
+       ao_lco_set_pad(ao_lco_pad);
+       ao_lco_set_box(ao_lco_box);
 }
 
 static void
@@ -382,6 +386,7 @@ ao_lco_set_debug(void)
 
 __code struct ao_cmds ao_lco_cmds[] = {
        { ao_lco_set_debug,     "D <0 off, 1 on>\0Debug" },
+       { ao_lco_search,        "s\0Search for pad boxes" },
        { 0, NULL }
 };
 #endif
index 07ea1b4594f893ff7620f655f629eb100d4f4267..d86782f3393b4d64754dc350490ba7cc0a43fc5e 100644 (file)
  */
 
 #define AO_QUADRATURE_COUNT    2
-#define AO_QUADRATURE_MODE     0
 
 #define AO_QUADRATURE_0_PORT   &stm_gpioe
 #define AO_QUADRATURE_0_A      3
index 4c645871fe758d6f6159da4aa49e38ef2823e936..78e887c37b23697d4dfce46fe59dc1b14535a148 100644 (file)
 /* Number of general purpose pyro channels available */
 #define AO_PYRO_NUM    4
 
+#define AO_SENSE_PYRO(a,p)     ((a)->adc.sense[(p) + 2])
+
 #define AO_IGNITER_SET_DROGUE(v)       stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v)
 #define AO_IGNITER_SET_MAIN(v)         stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v)
 
index bace585336cca1235b3edeb3e05774cd1d9725d8..a5a9eaf43d8bd8ac5dff72b6258039795bed4ece 100644 (file)
 #define HAS_IGNITE             1
 #define HAS_IGNITE_REPORT      1
 
+#define AO_SENSE_PYRO(p,n)     ((p)->adc.sense[n])
 #define AO_SENSE_DROGUE(p)     ((p)->adc.sense[4])
 #define AO_SENSE_MAIN(p)       ((p)->adc.sense[5])
 #define AO_IGNITER_CLOSED      400