altos: Hacks to get telegps v1.0 running
authorKeith Packard <keithp@keithp.com>
Wed, 21 May 2014 21:38:00 +0000 (14:38 -0700)
committerKeith Packard <keithp@keithp.com>
Sat, 31 May 2014 00:32:53 +0000 (17:32 -0700)
Mine is busted, and there are a lot of cc115l kludges in here

Signed-off-by: Keith Packard <keithp@keithp.com>
14 files changed:
src/Makefile
src/drivers/ao_cc115l.c
src/kernel/ao_distance.c [new file with mode: 0644]
src/kernel/ao_distance.h [new file with mode: 0644]
src/kernel/ao_log.c
src/kernel/ao_log_mega.c
src/lpc/ao_spi_lpc.c
src/product/ao_tracker.c [new file with mode: 0644]
src/telegps-v1.0/.gitignore [new file with mode: 0644]
src/telegps-v1.0/Makefile [new file with mode: 0644]
src/telegps-v1.0/ao_pins.h [new file with mode: 0644]
src/telegps-v1.0/ao_telegps.c [new file with mode: 0644]
src/telegps-v1.0/flash-loader/Makefile [new file with mode: 0644]
src/telegps-v1.0/flash-loader/ao_pins.h [new file with mode: 0644]

index ae128b7cd9de90fd5435f0e6c1d7353d01cf4a06..87db6a6878487d1d785c7fdcd7c71f7c44511eb2 100644 (file)
@@ -30,7 +30,7 @@ ARMM3DIRS=\
        telemega-v1.0 telemega-v1.0/flash-loader \
        telemetrum-v2.0 telemetrum-v2.0/flash-loader \
        megadongle-v0.1 megadongle-v0.1/flash-loader \
-       telegps-v0.3 telegps-v0.3/flash-loader \
+       telegps-v1.0 telegps-v1.0/flash-loader \
        telelco-v0.2 telelco-v0.2/flash-loader \
        telescience-v0.2 telescience-v0.2/flash-loader \
        teleballoon-v2.0
index d9b9a89b7f29649a147203abe06277711a95f367..829ac60b0738138724aab0ebb2d2f3166e9d5844 100644 (file)
@@ -45,17 +45,70 @@ static uint8_t ao_radio_abort;              /* radio operation should abort */
 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC115L_SPI_BUS)
 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC115L_SPI_BUS)
 
+#if CC115L_DEBUG
 struct ao_cc115l_reg {
        uint16_t        addr;
        char            *name;
 };
 
-#if CC115L_TRACE
+static const struct ao_cc115l_reg ao_cc115l_reg[] = {
+       { .addr = CC115L_IOCFG2, .name = "IOCFG2" },
+       { .addr = CC115L_IOCFG1, .name = "IOCFG1" },
+       { .addr = CC115L_IOCFG0, .name = "IOCFG0" },
+       { .addr = CC115L_FIFOTHR, .name = "FIFOTHR" },
+       { .addr = CC115L_SYNC1, .name = "SYNC1" },
+       { .addr = CC115L_SYNC0, .name = "SYNC0" },
+       { .addr = CC115L_PKTLEN, .name = "PKTLEN" },
+       { .addr = CC115L_PKTCTRL0, .name = "PKTCTRL0" },
+       { .addr = CC115L_CHANNR, .name = "CHANNR" },
+       { .addr = CC115L_FSCTRL0, .name = "FSCTRL0" },
+       { .addr = CC115L_FREQ2, .name = "FREQ2" },
+       { .addr = CC115L_FREQ1, .name = "FREQ1" },
+       { .addr = CC115L_FREQ0, .name = "FREQ0" },
+       { .addr = CC115L_MDMCFG4, .name = "MDMCFG4" },
+       { .addr = CC115L_MDMCFG3, .name = "MDMCFG3" },
+       { .addr = CC115L_MDMCFG2, .name = "MDMCFG2" },
+       { .addr = CC115L_MDMCFG1, .name = "MDMCFG1" },
+       { .addr = CC115L_MDMCFG0, .name = "MDMCFG0" },
+       { .addr = CC115L_DEVIATN, .name = "DEVIATN" },
+       { .addr = CC115L_MCSM1, .name = "MCSM1" },
+       { .addr = CC115L_MCSM0, .name = "MCSM0" },
+       { .addr = CC115L_RESERVED_0X20, .name = "RESERVED_0X20" },
+       { .addr = CC115L_FREND0, .name = "FREND0" },
+       { .addr = CC115L_FSCAL3, .name = "FSCAL3" },
+       { .addr = CC115L_FSCAL2, .name = "FSCAL2" },
+       { .addr = CC115L_FSCAL1, .name = "FSCAL1" },
+       { .addr = CC115L_FSCAL0, .name = "FSCAL0" },
+       { .addr = CC115L_RESERVED_0X29, .name = "RESERVED_0X29" },
+       { .addr = CC115L_RESERVED_0X2A, .name = "RESERVED_0X2A" },
+       { .addr = CC115L_RESERVED_0X2B, .name = "RESERVED_0X2B" },
+       { .addr = CC115L_TEST2, .name = "TEST2" },
+       { .addr = CC115L_TEST1, .name = "TEST1" },
+       { .addr = CC115L_TEST0, .name = "TEST0" },
+       { .addr = CC115L_PARTNUM, .name = "PARTNUM" },
+       { .addr = CC115L_VERSION, .name = "VERSION" },
+       { .addr = CC115L_MARCSTATE, .name = "MARCSTATE" },
+       { .addr = CC115L_PKTSTATUS, .name = "PKTSTATUS" },
+       { .addr = CC115L_TXBYTES, .name = "TXBYTES" },
+       { .addr = CC115L_PA, .name = "PA" },
+};
 
-static const struct ao_cc115l_reg ao_cc115l_reg[];
-static const char *cc115l_state_name[];
+#define AO_NUM_CC115L_REG      (sizeof ao_cc115l_reg / sizeof ao_cc115l_reg[0])
+
+static const char *cc115l_state_name[8] = {
+       [CC115L_STATUS_STATE_IDLE] = "IDLE",
+       [CC115L_STATUS_STATE_TX] = "TX",
+       [CC115L_STATUS_STATE_FSTXON] = "FSTXON",
+       [CC115L_STATUS_STATE_CALIBRATE] = "CALIBRATE",
+       [CC115L_STATUS_STATE_SETTLING] = "SETTLING",
+       [CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW] = "TX_FIFO_UNDERFLOW",
+};
+#endif
+
+#if CC115L_TRACE
 
 enum ao_cc115l_trace_type {
+       trace_empty,
        trace_strobe,
        trace_read,
        trace_write,
@@ -63,14 +116,17 @@ enum ao_cc115l_trace_type {
        trace_line,
 };
 
+static const char trace_type_letter[] = "ESRWDL";
+
 struct ao_cc115l_trace {
        enum ao_cc115l_trace_type       type;
+       int16_t                         time;
        int16_t                         addr;
        int16_t                         value;
        const char                      *comment;
 };
 
-#define NUM_TRACE      256
+#define NUM_TRACE      128
 
 static struct ao_cc115l_trace  trace[NUM_TRACE];
 static int                     trace_i;
@@ -78,12 +134,18 @@ static int                 trace_disable;
 
 static void trace_add(enum ao_cc115l_trace_type type, int16_t addr, int16_t value, const char *comment)
 {
+       unsigned int    i;
        if (trace_disable)
                return;
        switch (type) {
        case trace_read:
        case trace_write:
-               comment = ao_cc115l_reg[addr].name;
+               comment = "UNKNOWN";
+               for (i = 0; i < AO_NUM_CC115L_REG; i++)
+                       if (ao_cc115l_reg[i].addr == addr) {
+                               comment = ao_cc115l_reg[i].name;
+                               break;
+                       }
                break;
        case trace_strobe:
                comment = cc115l_state_name[(value >> 4) & 0x7];
@@ -91,6 +153,9 @@ static void trace_add(enum ao_cc115l_trace_type type, int16_t addr, int16_t valu
        default:
                break;
        }
+       if (comment == NULL)
+               comment = "no comment";
+       trace[trace_i].time = ao_time();
        trace[trace_i].type = type;
        trace[trace_i].addr = addr;
        trace[trace_i].value = value;
@@ -98,6 +163,29 @@ static void trace_add(enum ao_cc115l_trace_type type, int16_t addr, int16_t valu
        if (++trace_i == NUM_TRACE)
                trace_i = 0;
 }
+
+static void
+trace_dump(void)
+{
+       int     i, j;
+
+       for (j = 0; j < NUM_TRACE; j++) {
+               i = j + trace_i;
+               if (i >= NUM_TRACE)
+                       i -= NUM_TRACE;
+               if (trace[i].type != trace_empty) {
+                       printf ("%3d %5d %c addr %04x value %04x comment %s\n",
+                               j,
+                               trace[i].time,
+                               trace_type_letter[trace[i].type],
+                               trace[i].addr,
+                               trace[i].value,
+                               trace[i].comment);
+                       flush();
+               }
+       }
+}
+
 #else
 #define trace_add(t,a,v,c)
 #endif
@@ -131,6 +219,9 @@ ao_radio_reg_write(uint8_t addr, uint8_t value)
        ao_radio_select();
        ao_radio_spi_send(data, 2);
        ao_radio_deselect();
+#if CC115L_TRACE
+       (void) ao_radio_reg_read(addr);
+#endif
 }
 
 #if UNUSED
@@ -610,18 +701,25 @@ ao_radio_rdf_abort(void)
        ao_wakeup(&ao_radio_wake);
 }
 
-#define POWER_STEP     0x08
+static uint8_t ao_cc115l_power_on[] = { 0x03, 0x17, 0x50, 0xc5, 0xc0 };
 
 static void
 ao_radio_stx(void)
 {
        uint8_t power;
+#if HAS_RADIO_POWER
        ao_radio_pa_on();
+#endif
        ao_radio_reg_write(CC115L_PA, 0);
        ao_radio_strobe(CC115L_STX);
+#if HAS_RADIO_POWER
        for (power = POWER_STEP; power < ao_config.radio_power; power += POWER_STEP)
                ao_radio_reg_write(CC115L_PA, power);
        ao_radio_reg_write(CC115L_PA, ao_config.radio_power);
+#else
+       for (power = 0; power < sizeof (ao_cc115l_power_on); power++)
+               ao_radio_reg_write(CC115L_PA, ao_cc115l_power_on[power]);
+#endif
 }
 
 static void
@@ -819,59 +917,6 @@ ao_radio_send_aprs(ao_radio_fill_func fill)
 }
 
 #if CC115L_DEBUG
-static const char *cc115l_state_name[] = {
-       [CC115L_STATUS_STATE_IDLE] = "IDLE",
-       [CC115L_STATUS_STATE_TX] = "TX",
-       [CC115L_STATUS_STATE_FSTXON] = "FSTXON",
-       [CC115L_STATUS_STATE_CALIBRATE] = "CALIBRATE",
-       [CC115L_STATUS_STATE_SETTLING] = "SETTLING",
-       [CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW] = "TX_FIFO_UNDERFLOW",
-};
-
-static const struct ao_cc115l_reg ao_cc115l_reg[] = {
-       { .addr = CC115L_IOCFG2, .name = "IOCFG2" },
-       { .addr = CC115L_IOCFG1, .name = "IOCFG1" },
-       { .addr = CC115L_IOCFG0, .name = "IOCFG0" },
-       { .addr = CC115L_FIFOTHR, .name = "FIFOTHR" },
-       { .addr = CC115L_SYNC1, .name = "SYNC1" },
-       { .addr = CC115L_SYNC0, .name = "SYNC0" },
-       { .addr = CC115L_PKTLEN, .name = "PKTLEN" },
-       { .addr = CC115L_PKTCTRL0, .name = "PKTCTRL0" },
-       { .addr = CC115L_CHANNR, .name = "CHANNR" },
-       { .addr = CC115L_FSCTRL0, .name = "FSCTRL0" },
-       { .addr = CC115L_FREQ2, .name = "FREQ2" },
-       { .addr = CC115L_FREQ1, .name = "FREQ1" },
-       { .addr = CC115L_FREQ0, .name = "FREQ0" },
-       { .addr = CC115L_MDMCFG4, .name = "MDMCFG4" },
-       { .addr = CC115L_MDMCFG3, .name = "MDMCFG3" },
-       { .addr = CC115L_MDMCFG2, .name = "MDMCFG2" },
-       { .addr = CC115L_MDMCFG1, .name = "MDMCFG1" },
-       { .addr = CC115L_MDMCFG0, .name = "MDMCFG0" },
-       { .addr = CC115L_DEVIATN, .name = "DEVIATN" },
-       { .addr = CC115L_MCSM1, .name = "MCSM1" },
-       { .addr = CC115L_MCSM0, .name = "MCSM0" },
-       { .addr = CC115L_RESERVED_0X20, .name = "RESERVED_0X20" },
-       { .addr = CC115L_FREND0, .name = "FREND0" },
-       { .addr = CC115L_FSCAL3, .name = "FSCAL3" },
-       { .addr = CC115L_FSCAL2, .name = "FSCAL2" },
-       { .addr = CC115L_FSCAL1, .name = "FSCAL1" },
-       { .addr = CC115L_FSCAL0, .name = "FSCAL0" },
-       { .addr = CC115L_RESERVED_0X29, .name = "RESERVED_0X29" },
-       { .addr = CC115L_RESERVED_0X2A, .name = "RESERVED_0X2A" },
-       { .addr = CC115L_RESERVED_0X2B, .name = "RESERVED_0X2B" },
-       { .addr = CC115L_TEST2, .name = "TEST2" },
-       { .addr = CC115L_TEST1, .name = "TEST1" },
-       { .addr = CC115L_TEST0, .name = "TEST0" },
-       { .addr = CC115L_PARTNUM, .name = "PARTNUM" },
-       { .addr = CC115L_VERSION, .name = "VERSION" },
-       { .addr = CC115L_MARCSTATE, .name = "MARCSTATE" },
-       { .addr = CC115L_PKTSTATUS, .name = "PKTSTATUS" },
-       { .addr = CC115L_TXBYTES, .name = "TXBYTES" },
-       { .addr = CC115L_PA, .name = "PA" },
-};
-
-#define AO_NUM_CC115L_REG      (sizeof ao_cc115l_reg / sizeof ao_cc115l_reg[0])
-
 static void ao_radio_show(void) {
        uint8_t status = ao_radio_status();
        unsigned int    i;
@@ -931,6 +976,9 @@ static const struct ao_cmds ao_radio_cmds[] = {
        { ao_radio_show,        "R\0Show CC115L status" },
        { ao_radio_beep,        "b\0Emit an RDF beacon" },
        { ao_radio_packet,      "p\0Send a test packet" },
+#if CC115L_TRACE
+       { trace_dump,           "D\0Dump CC115L trace" },
+#endif
 #endif
        { 0, NULL }
 };
@@ -945,6 +993,8 @@ ao_radio_init(void)
        ao_radio_configured = 0;
        ao_spi_init_cs (AO_CC115L_SPI_CS_PORT, (1 << AO_CC115L_SPI_CS_PIN));
 
+       ao_enable_output(0, 23, PIN, 1);
+
 #if 0
        AO_CC115L_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC115L_SPI_CS_PIN));
        for (i = 0; i < 10000; i++) {
diff --git a/src/kernel/ao_distance.c b/src/kernel/ao_distance.c
new file mode 100644 (file)
index 0000000..ba7d59f
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2014 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_distance.h>
+
+static uint32_t
+ao_dist(int32_t a, int32_t b)
+{
+       int32_t d = a - b;
+       if (d < 0)
+               d = -d;
+       return (uint32_t) ((int64_t) d * 111198 / 10000000);
+}
+
+static uint32_t
+ao_lat_dist(int32_t lat_a, int32_t lat_b)
+{
+       return ao_dist(lat_a, lat_b);
+}
+
+static const uint8_t cos_table[] = {
+   0, /*  0 */
+   0, /*  1 */
+   0, /*  2 */
+ 255, /*  3 */
+ 254, /*  4 */
+ 253, /*  5 */
+ 252, /*  6 */
+ 251, /*  7 */
+ 249, /*  8 */
+ 247, /*  9 */
+ 245, /* 10 */
+ 243, /* 11 */
+ 240, /* 12 */
+ 238, /* 13 */
+ 235, /* 14 */
+ 232, /* 15 */
+ 228, /* 16 */
+ 225, /* 17 */
+ 221, /* 18 */
+ 217, /* 19 */
+ 213, /* 20 */
+ 209, /* 21 */
+ 205, /* 22 */
+ 200, /* 23 */
+ 195, /* 24 */
+ 190, /* 25 */
+ 185, /* 26 */
+ 180, /* 27 */
+ 175, /* 28 */
+ 169, /* 29 */
+ 163, /* 30 */
+ 158, /* 31 */
+ 152, /* 32 */
+ 145, /* 33 */
+ 139, /* 34 */
+ 133, /* 35 */
+ 126, /* 36 */
+ 120, /* 37 */
+ 113, /* 38 */
+ 106, /* 39 */
+ 100, /* 40 */
+  93, /* 41 */
+  86, /* 42 */
+  79, /* 43 */
+  71, /* 44 */
+  64, /* 45 */
+  57, /* 46 */
+  49, /* 47 */
+  42, /* 48 */
+  35, /* 49 */
+  27, /* 50 */
+  20, /* 51 */
+  12, /* 52 */
+   5, /* 53 */
+   1, /* 54 */
+};
+
+static uint32_t
+ao_lon_dist(int32_t lon_a, int32_t lon_b)
+{
+       uint8_t         c = cos_table[lon_a >> 24];
+       uint32_t        lon_dist;
+
+       /* check if it's shorter to go the other way around */
+       if (lon_a < lon_b - 1800000000)
+               lon_a += 3600000000;
+       lon_dist = ao_dist(lon_a, lon_b);
+       if (c) {
+               if (lon_dist & 0x7f800000)
+                       lon_dist = (lon_dist >> 8) * c;
+               else
+                       lon_dist = (lon_dist * (int16_t) c) >> 8;
+       }
+       return lon_dist;
+}
+
+static uint32_t sqr(uint32_t x) { return x * x; }
+
+uint32_t
+ao_distance(int32_t lat_a, int32_t lon_a, int32_t lat_b, int32_t lon_b)
+{
+       uint32_t        lat_dist = ao_lat_dist(lat_a, lat_b);
+       uint32_t        lon_dist = ao_lon_dist(lon_a, lon_b);
+
+       return ao_sqrt (sqr(lat_dist) + sqr(lon_dist));
+}
diff --git a/src/kernel/ao_distance.h b/src/kernel/ao_distance.h
new file mode 100644 (file)
index 0000000..6762434
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2014 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_DISTANCE_H_
+#define _AO_DISTANCE_H_
+#include <stdint.h>
+
+uint32_t
+ao_distance(int32_t lat_a, int32_t lon_a, int32_t lat_b, int32_t lon_b);
+
+#endif /* _AO_DISTANCE_H_ */
index 20febefe27f2df4693ad4cd02b6f31b96aaa20ea..d60485e0d7f2fb962cda1f8c08ead66325b351e8 100644 (file)
@@ -196,7 +196,11 @@ ao_log_full(void)
        return ao_log_current_pos == ao_log_end_pos;
 }
 
-#if HAS_ADC
+#ifndef LOG_ADC
+#define LOG_ADC        HAS_ADC
+#endif
+
+#if LOG_ADC
 static __xdata struct ao_task ao_log_task;
 #endif
 
@@ -284,7 +288,7 @@ ao_log_init(void)
 #ifndef HAS_ADC
 #error Define HAS_ADC for ao_log.c
 #endif
-#if HAS_ADC
+#if LOG_ADC
        /* Create a task to log events to eeprom */
        ao_add_task(&ao_log_task, ao_log, "log");
 #endif
index 768947d541728159f7e86d16c30d2122ad4a4914..8997fd0596f19f63b7a3cab772ceefaa12f03941 100644 (file)
@@ -65,7 +65,7 @@ ao_log_dump_check_data(void)
        return 1;
 }
 
-#if HAS_ADC
+#if HAS_FLIGHT
 static __data uint8_t  ao_log_data_pos;
 
 /* a hack to make sure that ao_log_megas fill the eeprom block in even units */
@@ -100,9 +100,9 @@ ao_log(void)
        log.u.flight.ground_accel_along = ao_ground_accel_along;
        log.u.flight.ground_accel_across = ao_ground_accel_across;
        log.u.flight.ground_accel_through = ao_ground_accel_through;
+       log.u.flight.ground_roll = ao_ground_roll;
        log.u.flight.ground_pitch = ao_ground_pitch;
        log.u.flight.ground_yaw = ao_ground_yaw;
-       log.u.flight.ground_roll = ao_ground_roll;
 #endif
        log.u.flight.ground_pres = ao_ground_pres;
        log.u.flight.flight = ao_flight_number;
@@ -183,7 +183,7 @@ ao_log(void)
                        ao_sleep(&ao_log_running);
        }
 }
-#endif
+#endif /* HAS_FLIGHT */
 
 uint16_t
 ao_log_flight(uint8_t slot)
index e72b8286634adfbb0fe3b8e3f97bcfbbf2c92d3e..4c0f571427db2643d52f147777d672a32f6a2bf6 100644 (file)
@@ -103,8 +103,8 @@ ao_spi_channel_init(uint8_t id)
 
        lpc_ssp->cr0 = ((LPC_SSP_CR0_DSS_8 << LPC_SSP_CR0_DSS) |
                        (LPC_SSP_CR0_FRF_SPI << LPC_SSP_CR0_FRF) |
-                       (0 << LPC_SSP_CR0_CPOL) |
-                       (0 << LPC_SSP_CR0_CPHA) |
+                       (1 << LPC_SSP_CR0_CPOL) |
+                       (1 << LPC_SSP_CR0_CPHA) |
                        (0 << LPC_SSP_CR0_SCR));
 
        /* Enable the device */
diff --git a/src/product/ao_tracker.c b/src/product/ao_tracker.c
new file mode 100644 (file)
index 0000000..74372c3
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2014 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_flight.h>
+#include <ao_distance.h>
+#include <ao_exti.h>
+
+enum ao_flight_state   ao_flight_state;
+
+/* Speeds for the various modes */
+#define AO_TRACKER_NOT_MOVING  100
+
+static uint8_t ao_tracker_force_telem;
+
+#if HAS_USB_CONNECT
+static inline uint8_t
+ao_usb_connected(void)
+{
+       return ao_gpio_get(AO_USB_CONNECT_PORT, AO_USB_CONNECT_PIN, AO_USB_CONNECT) != 0;
+}
+#else
+#define ao_usb_connected()     1
+#endif
+
+static void
+ao_tracker(void)
+{
+       uint16_t        telem_rate = AO_SEC_TO_TICKS(1), new_telem_rate;
+       uint8_t         gps_rate = 1, new_gps_rate;
+       uint8_t         telem_enabled = 1, new_telem_enabled;
+       int32_t         start_latitude = 0, start_longitude = 0;
+       int16_t         start_altitude = 0;
+       uint32_t        ground_distance;
+       int16_t         height;
+       uint16_t        speed;
+
+       ao_timer_set_adc_interval(100);
+
+       ao_flight_state = ao_flight_startup;
+       for (;;) {
+               ao_sleep(&ao_gps_new);
+
+               new_gps_rate = gps_rate;
+               new_telem_rate = telem_rate;
+
+               new_telem_enabled = ao_tracker_force_telem || !ao_usb_connected();
+
+               ao_mutex_get(&ao_gps_mutex);
+
+               /* Don't change anything if GPS isn't locked */
+               if ((ao_gps_data.flags & (AO_GPS_VALID|AO_GPS_COURSE_VALID)) ==
+                   (AO_GPS_VALID|AO_GPS_COURSE_VALID))
+               {
+                       switch (ao_flight_state) {
+                       case ao_flight_startup:
+                               /* startup to pad when GPS locks */
+                               ao_flight_state = ao_flight_pad;
+                               start_latitude = ao_gps_data.longitude;
+                               start_longitude = ao_gps_data.latitude;
+                               start_altitude = ao_gps_data.altitude;
+                               break;
+                       case ao_flight_pad:
+#if 0
+                               ground_distance = ao_distance(ao_gps_data.latitude,
+                                                             start_latitude,
+                                                             ao_gps_data.longitude,
+                                                             start_longitude);
+#else
+                               (void) start_latitude;
+                               (void) start_longitude;
+                               ground_distance = 0xffff;
+#endif
+                               height = ao_gps_data.altitude - start_altitude;
+                               if (height < 0)
+                                       height = -height;
+                               if (ground_distance >= ao_config.tracker_start_horiz ||
+                                   height >= ao_config.tracker_start_vert)
+                               {
+                                       ao_flight_state = ao_flight_drogue;
+                                       ao_log_start();
+                               }
+                               break;
+                       case ao_flight_drogue:
+
+                               /* Modulate data rates based on speed (in cm/s) */
+                               if (ao_gps_data.climb_rate < 0)
+                                       speed = -ao_gps_data.climb_rate;
+                               else
+                                       speed = ao_gps_data.climb_rate;
+                               speed += ao_gps_data.ground_speed;
+
+                               if (speed < AO_TRACKER_NOT_MOVING) {
+                                       new_telem_rate = AO_SEC_TO_TICKS(10);
+                                       new_gps_rate = 10;
+                               } else {
+                                       new_telem_rate = AO_SEC_TO_TICKS(1);
+                                       new_gps_rate = 1;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               ao_mutex_put(&ao_gps_mutex);
+
+               if (new_telem_rate != telem_rate || new_telem_enabled != telem_enabled) {
+#if 0
+                       if (new_telem_enabled)
+                               ao_telemetry_set_interval(new_telem_rate);
+                       else
+                               ao_telemetry_set_interval(0);
+#endif
+                       telem_rate = new_telem_rate;
+                       telem_enabled = new_telem_enabled;
+               }
+
+               if (new_gps_rate != gps_rate) {
+#if 0
+                       ao_gps_set_rate(new_gps_rate);
+#endif
+                       gps_rate = new_gps_rate;
+               }
+       }
+}
+
+static struct ao_task ao_tracker_task;
+
+static void
+ao_tracker_set_telem(void)
+{
+       ao_cmd_hex();
+       if (ao_cmd_status == ao_cmd_success)
+               ao_tracker_force_telem = ao_cmd_lex_i;
+}
+
+static const struct ao_cmds ao_tracker_cmds[] = {
+       { ao_tracker_set_telem, "t <d>\0Set telem on USB" },
+       { 0, NULL },
+};
+
+void
+ao_tracker_init(void)
+{
+#if HAS_USB_CONNECT
+       ao_enable_input(AO_USB_CONNECT_PORT, AO_USB_CONNECT_PIN, 0);
+#endif
+       ao_cmd_register(&ao_tracker_cmds[0]);
+       ao_add_task(&ao_tracker_task, ao_tracker, "tracker");
+}
diff --git a/src/telegps-v1.0/.gitignore b/src/telegps-v1.0/.gitignore
new file mode 100644 (file)
index 0000000..892c3ac
--- /dev/null
@@ -0,0 +1,3 @@
+ao_product.h
+ao_serial_lpc.h
+*.elf
diff --git a/src/telegps-v1.0/Makefile b/src/telegps-v1.0/Makefile
new file mode 100644 (file)
index 0000000..507ff65
--- /dev/null
@@ -0,0 +1,90 @@
+#
+# AltOS build
+#
+#
+
+include ../lpc/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       ao_whiten.h \
+       ao_cc115l.h \
+       ao_fec.h \
+       lpc.h \
+       Makefile
+
+
+ALTOS_SRC = \
+       ao_interrupt.c \
+       ao_boot_chain.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer_lpc.c \
+       ao_data.c \
+       ao_convert_volt.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_spi_lpc.c \
+       ao_usb_lpc.c \
+       ao_exti_lpc.c \
+       ao_serial_lpc.c \
+       ao_gps_ublox.c \
+       ao_gps_show.c \
+       ao_cc115l.c \
+       ao_fec_tx.c \
+       ao_aprs.c \
+       ao_adc_lpc.c \
+       ao_tracker.c \
+       ao_telemetry.c \
+       ao_storage.c \
+       ao_m25.c \
+       ao_log.c \
+       ao_log_mega.c \
+       ao_gps_report_mega.c \
+       ao_distance.c \
+       ao_sqrt.c \
+       $(SAMPLE_PROFILE)
+
+PRODUCT=TeleGPS-v1.0
+PRODUCT_DEF=-DTELEGPS
+IDPRODUCT=0x0025
+
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telegps-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+
+SRC=$(ALTOS_SRC) ao_telegps.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG)
+
+LDFLAGS=-L../lpc -Wl,-Taltos.ld
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o ao_serial_lpc.h $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telegps-v1.0/ao_pins.h b/src/telegps-v1.0/ao_pins.h
new file mode 100644 (file)
index 0000000..8392eef
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_STACK_SIZE  448
+
+#define IS_FLASH_LOADER                0
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN   12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT  48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK  24000000
+
+#define HAS_SERIAL_0           1
+#define SERIAL_0_18_19         1
+#define USE_SERIAL_0_STDIN     0
+
+#define ao_gps_getchar         ao_serial0_getchar
+#define ao_gps_putchar         ao_serial0_putchar
+#define ao_gps_set_speed       ao_serial0_set_speed
+#define ao_gps_fifo            (ao_usart_rx_fifo)
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          1
+#define HAS_RDF                        1
+#define HAS_APRS               1
+#define HAS_RADIO_RECV         0
+#define HAS_TRACKER            1
+#define HAS_TASK_QUEUE         0
+
+#define HAS_USB_PULLUP         1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      7
+#define HAS_USB_CONNECT                1
+#define AO_USB_CONNECT_PORT    1
+#define AO_USB_CONNECT_PIN     19
+
+/* Flash part */
+#define HAS_SPI_0              1
+#define SPI_SCK0_P0_6          1
+#define SPI_0_OSPEEDR          AO_SPI_OSPEED_12MHz
+
+/* Radio */
+#define HAS_SPI_1              1
+#define SPI_SCK1_P1_15         1
+#define SPI_MISO1_P0_22                1
+#define SPI_MOSI1_P0_21                1
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             0
+#define HAS_LOG                        1
+
+#define AO_CONFIG_DEFAULT_APRS_INTERVAL        5
+#define AO_CONFIG_DEFAULT_RADIO_POWER          0xc0
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX  AO_SERIAL_SPEED_9600
+
+/*
+ * Radio (cc115l)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   0x10b6a5
+
+#define HAS_RADIO_POWER                0
+#define AO_FEC_DEBUG           0
+#define AO_CC115L_SPI_CS_PORT  0
+#define AO_CC115L_SPI_CS_PIN   3
+#define AO_CC115L_SPI_BUS      0
+
+#define AO_CC115L_FIFO_INT_GPIO_IOCFG  CC115L_IOCFG2
+#define AO_CC115L_FIFO_INT_PORT                0
+#define AO_CC115L_FIFO_INT_PIN         20
+
+#define AO_CC115L_DONE_INT_GPIO_IOCFG  CC115L_IOCFG0
+#define AO_CC115L_DONE_INT_PORT                0
+#define AO_CC115L_DONE_INT_PIN         2
+
+/*
+ * Flash (M25)
+ */
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     0
+#define AO_M25_SPI_CS_MASK     (1 << 23)
+#define AO_M25_SPI_BUS         1
+
+#define PACKET_HAS_SLAVE       0
+
+/*
+ * ADC
+ */
+
+#define HAS_ADC                        1
+#define LOG_ADC                        0
+
+#define AO_DATA_RING           4
+
+#define AO_ADC_3               1
+
+struct ao_adc {
+       int16_t                 v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5u batt: %5d\n", \
+              (p)->tick, \
+              (p)->adc.v_batt)
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telegps-v1.0/ao_telegps.c b/src/telegps-v1.0/ao_telegps.c
new file mode 100644 (file)
index 0000000..d7dd90a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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_exti.h>
+#include <ao_tracker.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_exti_init();
+
+       ao_storage_init();
+
+       ao_serial_init();
+
+       ao_cmd_init();
+
+       ao_usb_init();
+       ao_radio_init();
+
+       ao_adc_init();
+
+       ao_gps_init();
+#if HAS_LOG
+       ao_gps_report_mega_init();
+       ao_log_init();
+#endif
+
+       ao_tracker_init();
+
+       ao_telemetry_init();
+       ao_telemetry_set_interval(AO_SEC_TO_TICKS(1));
+
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+       ao_config_init();
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telegps-v1.0/flash-loader/Makefile b/src/telegps-v1.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..5283f55
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telegps-v1.0
+include $(TOPDIR)/lpc/Makefile-flash.defs
diff --git a/src/telegps-v1.0/flash-loader/ao_pins.h b/src/telegps-v1.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..91097a2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_lpc_pins.h>
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       0
+#define AO_BOOT_APPLICATION_PIN                19
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP         1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      7
+
+#endif /* _AO_PINS_H_ */