summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/ao.h12
-rw-r--r--src/kernel/ao_config.c48
-rw-r--r--src/kernel/ao_config.h6
-rw-r--r--src/kernel/ao_data.h4
-rw-r--r--src/kernel/ao_fast_timer.h34
-rw-r--r--src/kernel/ao_flight.c2
-rw-r--r--src/kernel/ao_log.h1
-rw-r--r--src/kernel/ao_log_mini.c2
-rw-r--r--src/kernel/ao_panic.c11
-rw-r--r--src/kernel/ao_power.c80
-rw-r--r--src/kernel/ao_power.h53
-rw-r--r--src/kernel/ao_product.c67
-rw-r--r--src/kernel/ao_task.c4
-rw-r--r--src/kernel/ao_task.h4
-rw-r--r--src/kernel/ao_usb.h17
15 files changed, 325 insertions, 20 deletions
diff --git a/src/kernel/ao.h b/src/kernel/ao.h
index 59a469ae..6ed0299e 100644
--- a/src/kernel/ao.h
+++ b/src/kernel/ao.h
@@ -124,6 +124,16 @@ ao_timer_init(void);
void
ao_clock_init(void);
+#if AO_POWER_MANAGEMENT
+/* Go to low power clock */
+void
+ao_clock_suspend(void);
+
+/* Restart full-speed clock */
+void
+ao_clock_resume(void);
+#endif
+
/*
* ao_mutex.c
*/
@@ -810,6 +820,8 @@ struct ao_fifo {
} while(0)
#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
+#define ao_fifo_mostly(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 3 / 4))
+#define ao_fifo_barely(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 1 / 4))
#define ao_fifo_empty(f) ((f).insert == (f).remove)
#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE
diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c
index b0d3e541..f95ca893 100644
--- a/src/kernel/ao_config.c
+++ b/src/kernel/ao_config.c
@@ -224,6 +224,12 @@ _ao_config_get(void)
if (minor < 22)
ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;
#endif
+#if HAS_FIXED_PAD_BOX
+ if (minor < 22)
+ ao_config.pad_box = 1;
+ if (minor < 23)
+ ao_config.pad_idle = 120;
+#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
}
@@ -899,6 +905,42 @@ ao_config_aprs_format_show(void)
}
#endif /* HAS_APRS */
+#if HAS_FIXED_PAD_BOX
+void
+ao_config_pad_box_show(void)
+{
+ printf ("Pad box: %d\n", ao_config.pad_box);
+}
+
+void
+ao_config_pad_box_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_box = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+
+void
+ao_config_pad_idle_show(void)
+{
+ printf ("Idle timeout: %d\n", ao_config.pad_idle);
+}
+
+void
+ao_config_pad_idle_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_idle = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+#endif
+
struct ao_config_var {
__code char *str;
void (*set)(void) __reentrant;
@@ -993,6 +1035,12 @@ __code struct ao_config_var ao_config_vars[] = {
{ "C <0 compressed, 1 uncompressed>\0APRS format",
ao_config_aprs_format_set, ao_config_aprs_format_show },
#endif
+#if HAS_FIXED_PAD_BOX
+ { "B <box>\0Set pad box (1-99)",
+ ao_config_pad_box_set, ao_config_pad_box_show },
+ { "i <seconds>\0Set idle timeout (0 disable)",
+ ao_config_pad_idle_set, ao_config_pad_idle_show },
+#endif
{ "s\0Show",
ao_config_show, 0 },
#if HAS_EEPROM
diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h
index cfe8555c..3c73ea49 100644
--- a/src/kernel/ao_config.h
+++ b/src/kernel/ao_config.h
@@ -57,7 +57,7 @@
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 22
+#define AO_CONFIG_MINOR 23
#define AO_AES_LEN 16
@@ -118,6 +118,10 @@ struct ao_config {
#if HAS_APRS
uint8_t aprs_format; /* minor version 22 */
#endif
+#if HAS_FIXED_PAD_BOX
+ uint8_t pad_box; /* minor version 22 */
+ uint8_t pad_idle; /* minor version 23 */
+#endif
};
#define AO_APRS_FORMAT_COMPRESSED 0
diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h
index 8f75ad87..6ee0965d 100644
--- a/src/kernel/ao_data.h
+++ b/src/kernel/ao_data.h
@@ -269,6 +269,10 @@ typedef int16_t accel_t;
#define AO_ACCEL_INVERT 4095
+#ifndef AO_MMA655X_INVERT
+#error AO_MMA655X_INVERT not defined
+#endif
+
#define ao_data_accel(packet) ((packet)->mma655x)
#if AO_MMA655X_INVERT
#define ao_data_accel_cook(packet) (AO_ACCEL_INVERT - (packet)->mma655x)
diff --git a/src/kernel/ao_fast_timer.h b/src/kernel/ao_fast_timer.h
new file mode 100644
index 00000000..90fb3930
--- /dev/null
+++ b/src/kernel/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/kernel/ao_flight.c b/src/kernel/ao_flight.c
index 251dbc02..9ba02bb8 100644
--- a/src/kernel/ao_flight.c
+++ b/src/kernel/ao_flight.c
@@ -370,8 +370,10 @@ ao_flight(void)
{
ao_flight_state = ao_flight_landed;
+#if HAS_ADC
/* turn off the ADC capture */
ao_timer_set_adc_interval(0);
+#endif
ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
}
diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h
index f86fb359..fdd428c2 100644
--- a/src/kernel/ao_log.h
+++ b/src/kernel/ao_log.h
@@ -49,6 +49,7 @@ extern __pdata enum ao_flight_state ao_log_state;
#define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */
#define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */
#define AO_LOG_FORMAT_TELEMEGA 10 /* 32 byte typed telemega records with 32 bit gyro cal */
+#define AO_LOG_FORMAT_DETHERM 11 /* 16-byte MS5607 baro only, no ADC */
#define AO_LOG_FORMAT_NONE 127 /* No log at all */
extern __code uint8_t ao_log_format;
diff --git a/src/kernel/ao_log_mini.c b/src/kernel/ao_log_mini.c
index 0ca3ed06..844f38aa 100644
--- a/src/kernel/ao_log_mini.c
+++ b/src/kernel/ao_log_mini.c
@@ -110,9 +110,11 @@ ao_log(void)
ao_data_ring[ao_log_data_pos].ms5607_raw.pres);
ao_log_pack24(log.u.sensor.temp,
ao_data_ring[ao_log_data_pos].ms5607_raw.temp);
+#if AO_LOG_FORMAT != AO_LOG_FORMAT_DETHERM
log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a;
log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m;
log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
+#endif
ao_log_mini(&log);
if (ao_log_state <= ao_flight_coast)
next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
diff --git a/src/kernel/ao_panic.c b/src/kernel/ao_panic.c
index c29cd8fe..e280f98c 100644
--- a/src/kernel/ao_panic.c
+++ b/src/kernel/ao_panic.c
@@ -38,10 +38,15 @@ ao_panic_delay(uint8_t n)
{
uint8_t i = 0, j = 0;
- while (n--)
+ while (n--) {
+#ifdef AO_PANIC_DELAY_SCALE
+ uint8_t s = AO_PANIC_DELAY_SCALE;
+ while (s--)
+#endif
while (--j)
while (--i)
ao_arch_nop();
+ }
}
void
@@ -56,16 +61,16 @@ ao_panic(uint8_t reason)
ao_arch_block_interrupts();
for (;;) {
ao_panic_delay(20);
+#if HAS_BEEP
for (n = 0; n < 5; n++) {
- ao_led_on(AO_LED_PANIC);
ao_beep(AO_BEEP_HIGH);
ao_panic_delay(1);
- ao_led_off(AO_LED_PANIC);
ao_beep(AO_BEEP_LOW);
ao_panic_delay(1);
}
ao_beep(AO_BEEP_OFF);
ao_panic_delay(2);
+#endif
#ifdef SDCC
#pragma disable_warning 126
diff --git a/src/kernel/ao_power.c b/src/kernel/ao_power.c
new file mode 100644
index 00000000..bead5944
--- /dev/null
+++ b/src/kernel/ao_power.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2016 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_power.h>
+
+static struct ao_power *head, *tail;
+
+void
+ao_power_register(struct ao_power *power)
+{
+ if (power->registered)
+ return;
+ power->registered = TRUE;
+ if (tail) {
+ tail->next = power;
+ power->prev = tail;
+ tail = power;
+ } else {
+ head = tail = power;
+ }
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
+void
+ao_power_unregister(struct ao_power *power)
+{
+ if (!power->registered)
+ return;
+ power->registered = FALSE;
+ if (power->prev)
+ power->prev->next = power->next;
+ else
+ head = power->next;
+ if (power->next)
+ power->next->prev = power->prev;
+ else
+ tail = power->prev;
+}
+
+void
+ao_power_suspend(void)
+{
+ struct ao_power *p;
+
+#ifdef AO_LED_POWER
+ ao_led_off(AO_LED_POWER);
+#endif
+ for (p = tail; p; p = p->prev)
+ p->suspend(p->arg);
+}
+
+void
+ao_power_resume(void)
+{
+ struct ao_power *p;
+
+ for (p = head; p; p = p->next)
+ p->resume(p->arg);
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
diff --git a/src/kernel/ao_power.h b/src/kernel/ao_power.h
new file mode 100644
index 00000000..98a8c1c7
--- /dev/null
+++ b/src/kernel/ao_power.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2016 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_POWER_H_
+#define _AO_POWER_H_
+
+#if AO_POWER_MANAGEMENT
+
+struct ao_power {
+ struct ao_power *prev, *next;
+
+ void (*suspend)(void *arg);
+ void (*resume)(void *arg);
+ void *arg;
+ uint8_t registered;
+};
+
+void
+ao_power_register(struct ao_power *power);
+
+void
+ao_power_unregister(struct ao_power *power);
+
+void
+ao_power_suspend(void);
+
+void
+ao_power_resume(void);
+
+#else /* AO_POWER_MANAGEMENT */
+
+#define ao_power_register(power)
+#define ao_power_unregister(power)
+#define ao_power_suspend()
+#define ao_power_resume()
+
+#endif /* else AO_POWER_MANAGEMENT */
+
+#endif /* _AO_POWER_H_ */
diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c
index c711a4d2..3a829b3a 100644
--- a/src/kernel/ao_product.c
+++ b/src/kernel/ao_product.c
@@ -33,11 +33,32 @@ const char ao_product[] = AO_iProduct_STRING;
#define AO_USB_MAX_POWER 100
#endif
-#ifndef AO_USB_INTERFACE_CLASS
-#define AO_USB_INTERFACE_CLASS 0x02
+#ifndef AO_USB_SELF_POWER
+#define AO_USB_SELF_POWER 1
+#endif
+
+#define AO_USB_DEVICE_CLASS_COMMUNICATION 0x02
+#define AO_USB_INTERFACE_CLASS_CONTROL_CDC 0x02
+#define AO_USB_INTERFACE_CLASS_DATA_CDC 0x0A
+
+#ifndef AO_USB_DEVICE_CLASS
+#define AO_USB_DEVICE_CLASS AO_USB_DEVICE_CLASS_COMMUNICATION
+#endif
+
+#ifndef AO_USB_INTERFACE_CLASS_DATA
+#define AO_USB_INTERFACE_CLASS_CONTROL AO_USB_INTERFACE_CLASS_CONTROL_CDC
+#define AO_USB_INTERFACE_CLASS_DATA AO_USB_INTERFACE_CLASS_DATA_CDC
#endif
#include "ao_usb.h"
+
+#define HEADER_LEN 9
+#define CONTROL_CLASS_LEN 35
+#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2)
+
+#define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)
+#define NUM_INTERFACES (AO_USB_HAS_INT + 1)
+
/* USB descriptors in one giant block of bytes */
AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
{
@@ -45,7 +66,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x12,
AO_USB_DESC_DEVICE,
LE_WORD(0x0110), /* bcdUSB */
- 0x02, /* bDeviceClass */
+ AO_USB_DEVICE_CLASS, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
AO_USB_CONTROL_SIZE, /* bMaxPacketSize */
@@ -60,20 +81,21 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
/* Configuration descriptor */
0x09,
AO_USB_DESC_CONFIGURATION,
- LE_WORD(67), /* wTotalLength */
- 0x02, /* bNumInterfaces */
+ LE_WORD(TOTAL_LENGTH), /* wTotalLength */
+ NUM_INTERFACES, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
- 0xC0, /* bmAttributes */
+ 0x80 | (AO_USB_SELF_POWER << 6), /* bmAttributes */
AO_USB_MAX_POWER >> 1, /* bMaxPower, 2mA units */
+#if AO_USB_HAS_INT
/* Control class interface */
0x09,
AO_USB_DESC_INTERFACE,
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndPoints */
- AO_USB_INTERFACE_CLASS, /* bInterfaceClass */
+ AO_USB_INTERFACE_CLASS_CONTROL, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
0x00, /* iInterface */
@@ -111,18 +133,20 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x03, /* bmAttributes = intr */
LE_WORD(8), /* wMaxPacketSize */
0xff, /* bInterval */
+#endif
/* Data class interface descriptor */
0x09,
AO_USB_DESC_INTERFACE,
- 0x01, /* bInterfaceNumber */
- 0x00, /* bAlternateSetting */
- 0x02, /* bNumEndPoints */
- 0x0A, /* bInterfaceClass = data */
- 0x00, /* bInterfaceSubClass */
- 0x00, /* bInterfaceProtocol */
- 0x00, /* iInterface */
-
+ AO_USB_HAS_INT, /* bInterfaceNumber */
+ 0x00, /* bAlternateSetting */
+ AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2, /* bNumEndPoints */
+ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */
+ 0x00, /* bInterfaceSubClass */
+ 0x00, /* bInterfaceProtocol */
+ 0x00, /* iInterface */
+
+#if AO_USB_HAS_OUT
/* Data EP OUT */
0x07,
AO_USB_DESC_ENDPOINT,
@@ -130,7 +154,9 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+#if AO_USB_HAS_IN
/* Data EP in */
0x07,
AO_USB_DESC_ENDPOINT,
@@ -138,6 +164,17 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+
+#if AO_USB_HAS_IN2
+ /* Data EP in 2 */
+ 0x07,
+ AO_USB_DESC_ENDPOINT,
+ AO_USB_IN2_EP|0x80, /* bEndpointAddress */
+ 0x02, /* bmAttributes = bulk */
+ LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
+ 0x00, /* bInterval */
+#endif
/* String descriptors */
0x04,
diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c
index 55e423bb..e430edc6 100644
--- a/src/kernel/ao_task.c
+++ b/src/kernel/ao_task.c
@@ -355,7 +355,6 @@ ao_yield(void) ao_arch_naked_define
*/
if (ao_cur_task->wchan == NULL)
ao_task_to_run_queue(ao_cur_task);
- ao_cur_task = NULL;
for (;;) {
ao_arch_memory_barrier();
if (!ao_list_is_empty(&run_queue))
@@ -425,6 +424,7 @@ ao_sleep(__xdata void *wchan)
void
ao_wakeup(__xdata void *wchan) __reentrant
{
+ ao_validate_cur_stack();
#if HAS_TASK_QUEUE
struct ao_task *sleep, *next;
struct ao_list *sleep_queue;
@@ -442,10 +442,12 @@ ao_wakeup(__xdata void *wchan) __reentrant
}
ao_arch_irqrestore(flags);
#else
+ {
uint8_t i;
for (i = 0; i < ao_num_tasks; i++)
if (ao_tasks[i]->wchan == wchan)
ao_tasks[i]->wchan = NULL;
+ }
#endif
ao_check_stack();
}
diff --git a/src/kernel/ao_task.h b/src/kernel/ao_task.h
index c6bec0e3..0e353fe8 100644
--- a/src/kernel/ao_task.h
+++ b/src/kernel/ao_task.h
@@ -56,6 +56,10 @@ extern __data uint8_t ao_num_tasks;
extern __xdata struct ao_task *__data ao_cur_task;
extern __data uint8_t ao_task_minimize_latency; /* Reduce IRQ latency */
+#ifndef HAS_ARCH_VALIDATE_CUR_STACK
+#define ao_validate_cur_stack()
+#endif
+
/*
ao_task.c
*/
diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h
index 1ce4f82f..8f3e7813 100644
--- a/src/kernel/ao_usb.h
+++ b/src/kernel/ao_usb.h
@@ -105,6 +105,23 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
#ifndef AO_USB_OUT_EP
#define AO_USB_OUT_EP 4
#define AO_USB_IN_EP 5
+#define AO_USB_IN2_EP 6
+#endif
+
+#ifndef AO_USB_HAS_OUT
+#define AO_USB_HAS_OUT 1
+#endif
+
+#ifndef AO_USB_HAS_IN
+#define AO_USB_HAS_IN 1
+#endif
+
+#ifndef AO_USB_HAS_INT
+#define AO_USB_HAS_INT 1
+#endif
+
+#ifndef AO_USB_HAS_IN2
+#define AO_USB_HAS_IN2 0
#endif
/*