diff options
| author | Bdale Garbee <bdale@gag.com> | 2013-07-30 00:15:06 -0600 | 
|---|---|---|
| committer | Bdale Garbee <bdale@gag.com> | 2013-07-30 00:15:06 -0600 | 
| commit | 01f8df088759ee7e6bc3900a013e0ea4fafaf984 (patch) | |
| tree | 3821af32f96f1ac1be04e48e0b1dee953fac7d62 /src | |
| parent | e2ebe60adf061479a1259a5c68b9cd5f5bacf644 (diff) | |
| parent | 15063cbb8f76bffea71575d295ca87b7ceca36d8 (diff) | |
Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 11 | ||||
| -rw-r--r-- | src/cc1111/ao_adc.c | 2 | ||||
| -rw-r--r-- | src/core/ao.h | 3 | ||||
| -rw-r--r-- | src/core/ao_debounce.c | 163 | ||||
| -rw-r--r-- | src/core/ao_debounce.h | 74 | ||||
| -rw-r--r-- | src/core/ao_ignite.c | 45 | ||||
| -rw-r--r-- | src/core/ao_pyro.c | 57 | ||||
| -rw-r--r-- | src/core/ao_pyro.h | 6 | ||||
| -rw-r--r-- | src/drivers/ao_74hc165.c | 58 | ||||
| -rw-r--r-- | src/drivers/ao_74hc165.h | 27 | ||||
| -rw-r--r-- | src/drivers/ao_button.c | 83 | ||||
| -rw-r--r-- | src/drivers/ao_event.c | 17 | ||||
| -rw-r--r-- | src/drivers/ao_event.h | 6 | ||||
| -rw-r--r-- | src/drivers/ao_pad.c | 51 | ||||
| -rw-r--r-- | src/drivers/ao_quadrature.c | 122 | ||||
| -rw-r--r-- | src/stm-demo/Makefile | 5 | ||||
| -rw-r--r-- | src/stm-demo/ao_demo.c | 4 | ||||
| -rw-r--r-- | src/stm/ao_fast_timer.c | 120 | ||||
| -rw-r--r-- | src/stm/ao_fast_timer.h | 34 | ||||
| -rw-r--r-- | src/stm/stm32l.h | 5 | ||||
| -rw-r--r-- | src/telefire-v0.2/Makefile | 103 | ||||
| -rw-r--r-- | src/telefire-v0.2/ao_pins.h | 144 | ||||
| -rw-r--r-- | src/telefire-v0.2/ao_telefire.c | 45 | ||||
| -rw-r--r-- | src/telelco-v0.2/Makefile | 3 | ||||
| -rw-r--r-- | src/telelco-v0.2/ao_lco.c | 81 | ||||
| -rw-r--r-- | src/telelco-v0.2/ao_pins.h | 1 | ||||
| -rw-r--r-- | src/telemega-v0.1/ao_pins.h | 2 | ||||
| -rw-r--r-- | src/telemega-v0.3/ao_pins.h | 1 | 
28 files changed, 1098 insertions, 175 deletions
| diff --git a/src/Makefile b/src/Makefile index 7ffc52d6..ee76c325 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 \ diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index ed76179b..4a58023d 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -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; diff --git a/src/core/ao.h b/src/core/ao.h index 7f344736..caa0ec19 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -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 index 00000000..b9d67729 --- /dev/null +++ b/src/core/ao_debounce.c @@ -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 index 00000000..19c620f5 --- /dev/null +++ b/src/core/ao_debounce.h @@ -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_ */ diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index 74bd0c5a..9f2ec0a7 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -17,7 +17,11 @@  #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]);  } diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 39f40dfa..531e1f50 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -33,6 +33,40 @@  #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 diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h index 1f838542..0c5642d6 100644 --- a/src/core/ao_pyro.h +++ b/src/core/ao_pyro.h @@ -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 index 00000000..f24fce37 --- /dev/null +++ b/src/drivers/ao_74hc165.c @@ -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 index 00000000..3ae51353 --- /dev/null +++ b/src/drivers/ao_74hc165.h @@ -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_ */ diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index a507c909..25c0cd5c 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -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) @@ -25,55 +26,71 @@  #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();  } diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c index 440ef2de..c428125d 100644 --- a/src/drivers/ao_event.c +++ b/src/drivers/ao_event.c @@ -25,11 +25,6 @@  #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););  } diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h index 25c49c35..ed9a7433 100644 --- a/src/drivers/ao_event.h +++ b/src/drivers/ao_event.h @@ -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_ */ diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 6cec98ab..e205f99b 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -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 }  }; diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 6cc2467a..d07488d0 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -18,16 +18,12 @@  #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]);  } diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index d1f825db..48fa07eb 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -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 diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 5677cdf4..58cf651b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -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 index 00000000..d61b40c9 --- /dev/null +++ b/src/stm/ao_fast_timer.c @@ -0,0 +1,120 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <ao.h> +#include <ao_fast_timer.h> + +static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void); +static uint8_t ao_fast_timer_count; +static uint8_t ao_fast_timer_users; + +static void +ao_fast_timer_enable(void) +{ +	stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | +			(0 << STM_TIM67_CR1_OPM) | +			(1 << STM_TIM67_CR1_URS) | +			(0 << STM_TIM67_CR1_UDIS) | +			(1 << STM_TIM67_CR1_CEN)); +} + +static void +ao_fast_timer_disable(void) +{ +	stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | +			(0 << STM_TIM67_CR1_OPM) | +			(1 << STM_TIM67_CR1_URS) | +			(0 << STM_TIM67_CR1_UDIS) | +			(0 << STM_TIM67_CR1_CEN)); +} + +void +ao_fast_timer_on(void (*callback)(void)) +{ +	ao_fast_timer_callback[ao_fast_timer_count] = callback; +	if (!ao_fast_timer_count++) +		ao_fast_timer_enable(); +} + +void +ao_fast_timer_off(void (*callback)(void)) +{ +	uint8_t	n; + +	for (n = 0; n < ao_fast_timer_count; n++) +		if (ao_fast_timer_callback[n] == callback) { +			for (; n < ao_fast_timer_count-1; n++) { +				ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1]; +			} +			if (!--ao_fast_timer_count) +				ao_fast_timer_disable(); +			break; +		} +} + +void stm_tim6_isr(void) +{ +	uint8_t	i; +	if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { +		stm_tim6.sr = 0; + +		for (i = 0; i < ao_fast_timer_count; i++) +			(*ao_fast_timer_callback[i])(); +	} +} + +/* + * According to the STM clock-configuration, timers run + * twice as fast as the APB1 clock *if* the APB1 prescaler + * is greater than 1. + */ + +#if AO_APB1_PRESCALER > 1 +#define TIMER_23467_SCALER 2 +#else +#define TIMER_23467_SCALER 1 +#endif + +#define TIMER_10kHz	((AO_PCLK1 * TIMER_23467_SCALER) / 10000) + +void +ao_fast_timer_init(void) +{ +	if (!ao_fast_timer_users) { +		stm_nvic_set_enable(STM_ISR_TIM6_POS); +		stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); + +		/* Turn on timer 6 */ +		stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + +		stm_tim6.psc = TIMER_10kHz; +		stm_tim6.arr = 9; +		stm_tim6.cnt = 0; + +		/* Enable update interrupt */ +		stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + +		/* Poke timer to reload values */ +		stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + +		stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); +		ao_fast_timer_disable(); +	} +	if (ao_fast_timer_users == AO_FAST_TIMER_MAX) +		ao_panic(AO_PANIC_FAST_TIMER); +	ao_fast_timer_users++; +} + diff --git a/src/stm/ao_fast_timer.h b/src/stm/ao_fast_timer.h new file mode 100644 index 00000000..90fb3930 --- /dev/null +++ b/src/stm/ao_fast_timer.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FAST_TIMER_H_ +#define _AO_FAST_TIMER_H_ + +void +ao_fast_timer_init(void); + +#ifndef AO_FAST_TIMER_MAX +#define AO_FAST_TIMER_MAX	2 +#endif + +void +ao_fast_timer_on(void (*callback)(void)); + +void +ao_fast_timer_off(void (*callback)(void)); + +#endif /* _AO_FAST_TIMER_H_ */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 63bde0f8..1868468f 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -171,6 +171,11 @@ stm_gpio_get(struct stm_gpio *gpio, int pin) {  	return (gpio->idr >> pin) & 1;  } +static inline uint16_t +stm_gpio_get_all(struct stm_gpio *gpio) { +	return gpio->idr; +} +  extern struct stm_gpio stm_gpioa;  extern struct stm_gpio stm_gpiob;  extern struct stm_gpio stm_gpioc; diff --git a/src/telefire-v0.2/Makefile b/src/telefire-v0.2/Makefile new file mode 100644 index 00000000..3353bc1a --- /dev/null +++ b/src/telefire-v0.2/Makefile @@ -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 index 00000000..f4050722 --- /dev/null +++ b/src/telefire-v0.2/ao_pins.h @@ -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 index 00000000..f27ca5e8 --- /dev/null +++ b/src/telefire-v0.2/ao_telefire.c @@ -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(); +} diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index cc6e62c4..f78ca9e2 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -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 \ diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c index 418c0509..e8d16ca9 100644 --- a/src/telelco-v0.2/ao_lco.c +++ b/src/telelco-v0.2/ao_lco.c @@ -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 diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index 07ea1b45..d86782f3 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -235,7 +235,6 @@   */  #define AO_QUADRATURE_COUNT	2 -#define AO_QUADRATURE_MODE	0  #define AO_QUADRATURE_0_PORT	&stm_gpioe  #define AO_QUADRATURE_0_A	3 diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 4c645871..78e887c3 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -146,6 +146,8 @@  /* 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) diff --git a/src/telemega-v0.3/ao_pins.h b/src/telemega-v0.3/ao_pins.h index bace5853..a5a9eaf4 100644 --- a/src/telemega-v0.3/ao_pins.h +++ b/src/telemega-v0.3/ao_pins.h @@ -121,6 +121,7 @@  #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 | 
