diff options
Diffstat (limited to 'src')
95 files changed, 5481 insertions, 883 deletions
diff --git a/src/Makefile b/src/Makefile index 8420b376..0dafb5ec 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,6 +25,7 @@ SDCCDIRS=\  	telerepeat-v1.0  ARMM3DIRS=\ +	fox1ihu fox1ihu/flash-loader \  	easymega-v1.0 easymega-v1.0/flash-loader \  	telemega-v0.1 telemega-v0.1/flash-loader \  	telemega-v1.0 telemega-v1.0/flash-loader \ @@ -36,13 +37,16 @@ ARMM3DIRS=\  	telegps-v1.0 telegps-v1.0/flash-loader \  	telegps-v2.0 telegps-v2.0/flash-loader \  	telelco-v0.2 telelco-v0.2/flash-loader \ +	telelco-v0.2-cc1200 telelco-v0.2-cc1200/flash-loader \  	telelco-v0.3 telelco-v0.3/flash-loader \ +	telelco-v2.0 telelco-v2.0/flash-loader \  	teledongle-v3.0 teledongle-v3.0/flash-loader \  	teleballoon-v2.0 \  	telebt-v3.0 telebt-v3.0/flash-loader \  	telebt-v4.0 telebt-v4.0/flash-loader \  	telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \  	telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \ +	telefireeight-v1.0 telefireeight-v1.0/flash-loader   ARMM0DIRS=\  	easymini-v1.0 easymini-v1.0/flash-loader \ diff --git a/src/chaoskey-v1.0/Makefile b/src/chaoskey-v1.0/Makefile index dea5b483..c6cf45bd 100644 --- a/src/chaoskey-v1.0/Makefile +++ b/src/chaoskey-v1.0/Makefile @@ -14,6 +14,7 @@ INC = \  	ao_task.h \  	ao_adc_fast.h \  	ao_power.h \ +	ao_flash_readout.h \  	ao_crc.h \  	stm32f0.h @@ -34,6 +35,7 @@ ALTOS_SRC = \  	ao_boot_chain.c \  	ao_usb_stm.c \  	ao_trng_send.c \ +	ao_flash_readout.c \  	ao_task.c \  	ao_power.c \  	ao_gpio.c \ @@ -84,7 +86,7 @@ check: $(METAINFO)  distclean:	clean  clean: -	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx *.bin  	rm -f ao_product.h  	rm -f *.cab diff --git a/src/chaoskey-v1.0/ao_chaoskey.c b/src/chaoskey-v1.0/ao_chaoskey.c index c3acd441..1165e454 100644 --- a/src/chaoskey-v1.0/ao_chaoskey.c +++ b/src/chaoskey-v1.0/ao_chaoskey.c @@ -20,6 +20,7 @@  #include <ao_adc_fast.h>  #include <ao_crc.h>  #include <ao_trng_send.h> +#include <ao_flash_readout.h>  void main(void)  { @@ -30,6 +31,7 @@ void main(void)  	ao_dma_init();  	ao_adc_init();  	ao_crc_init(); +	ao_flash_readout_init();  	ao_usb_init(); diff --git a/src/chaoskey-v1.0/ao_pins.h b/src/chaoskey-v1.0/ao_pins.h index f2c46d8b..22861d9d 100644 --- a/src/chaoskey-v1.0/ao_pins.h +++ b/src/chaoskey-v1.0/ao_pins.h @@ -50,6 +50,7 @@  #define AO_USB_HAS_OUT			0  #define AO_USB_HAS_IN			1  #define AO_USB_HAS_IN2			1 +#define AO_USB_HAS_IN3			1  #define AO_USB_HAS_INT			0  #define AO_USB_SELF_POWER		0  #define AO_USB_DEVICE_ID_SERIAL		1 @@ -58,6 +59,9 @@  #define IS_FLASH_LOADER	0 +#define AO_FLASH_READOUT		1 +#define ao_flash_readout_putchar(c)	ao_usb_putchar3(c) +  /* ADC */  #define AO_ADC_PIN0_PORT	(&stm_gpioa) diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index 07e92c67..f6a9676b 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -69,6 +69,39 @@ _ao_button_get(uint8_t b)  #if AO_BUTTON_COUNT > 4  	case 4: return ao_button_value(4);  #endif +#if AO_BUTTON_COUNT > 5 +	case 5: return ao_button_value(5); +#endif +#if AO_BUTTON_COUNT > 6 +	case 6: return ao_button_value(6); +#endif +#if AO_BUTTON_COUNT > 7 +	case 7: return ao_button_value(7); +#endif +#if AO_BUTTON_COUNT > 8 +	case 8: return ao_button_value(8); +#endif +#if AO_BUTTON_COUNT > 9 +	case 9: return ao_button_value(9); +#endif +#if AO_BUTTON_COUNT > 10 +	case 10: return ao_button_value(10); +#endif +#if AO_BUTTON_COUNT > 11 +	case 11: return ao_button_value(11); +#endif +#if AO_BUTTON_COUNT > 12 +	case 12: return ao_button_value(12); +#endif +#if AO_BUTTON_COUNT > 13 +	case 13: return ao_button_value(13); +#endif +#if AO_BUTTON_COUNT > 14 +	case 14: return ao_button_value(14); +#endif +#if AO_BUTTON_COUNT > 15 +	case 15: return ao_button_value(15); +#endif  	}  	return 0;  } @@ -144,4 +177,40 @@ ao_button_init(void)  #if AO_BUTTON_COUNT > 4  	init(4);  #endif +#if AO_BUTTON_COUNT > 5 +	init(5); +#endif +#if AO_BUTTON_COUNT > 6 +	init(6); +#endif +#if AO_BUTTON_COUNT > 7 +	init(7); +#endif +#if AO_BUTTON_COUNT > 8 +	init(8); +#endif +#if AO_BUTTON_COUNT > 9 +	init(9); +#endif +#if AO_BUTTON_COUNT > 10 +	init(10); +#endif +#if AO_BUTTON_COUNT > 11 +	init(11); +#endif +#if AO_BUTTON_COUNT > 12 +	init(12); +#endif +#if AO_BUTTON_COUNT > 13 +	init(13); +#endif +#if AO_BUTTON_COUNT > 14 +	init(14); +#endif +#if AO_BUTTON_COUNT > 15 +	init(15); +#endif +#if AO_BUTTON_COUNT > 16 +	#error too many buttons +#endif  } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index efe5f996..2f091485 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -1447,7 +1447,9 @@ ao_radio_test_recv(void)  static void  ao_radio_aprs(void)  { +#if PACKET_HAS_SLAVE  	ao_packet_slave_stop(); +#endif  	ao_aprs_send();  }  #endif diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index e1806ca3..e892c8c0 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -23,14 +23,8 @@  #include <ao_quadrature.h>  #include <ao_lco_func.h>  #include <ao_radio_cmac.h> - -#define DEBUG	1 - -#if DEBUG -static uint8_t	ao_lco_debug; -#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) -#else -#define PRINTD(...)  +#if HAS_ADC_SINGLE +#include <ao_adc_single.h>  #endif  #define AO_LCO_PAD_DIGIT	0 @@ -40,32 +34,16 @@ static uint8_t	ao_lco_debug;  #define AO_LCO_DRAG_RACE_START_TIME	AO_SEC_TO_TICKS(5)  #define AO_LCO_DRAG_RACE_STOP_TIME	AO_SEC_TO_TICKS(2) -#define AO_LCO_VALID_LAST	1 -#define AO_LCO_VALID_EVER	2 - -static uint8_t	ao_lco_min_box, ao_lco_max_box; -static uint8_t	ao_lco_selected[AO_PAD_MAX_BOXES]; -static uint8_t	ao_lco_valid[AO_PAD_MAX_BOXES]; -static uint8_t	ao_lco_channels[AO_PAD_MAX_BOXES]; -static uint16_t	ao_lco_tick_offset[AO_PAD_MAX_BOXES]; +#define AO_LCO_BOX_DRAG		0x1000  /* UI values */ -static uint8_t	ao_lco_armed; -static uint8_t	ao_lco_firing;  static uint16_t	ao_lco_fire_tick;  static uint8_t	ao_lco_fire_down; -static uint8_t	ao_lco_drag_race; -static uint8_t	ao_lco_pad; -static int16_t	ao_lco_box; - -#define AO_LCO_BOX_DRAG		0x1000 - -static struct ao_pad_query	ao_pad_query;  static uint8_t	ao_lco_display_mutex; -static void -ao_lco_set_pad(uint8_t pad) +void +ao_lco_show_pad(uint8_t pad)  {  	ao_mutex_get(&ao_lco_display_mutex);  	ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad | (ao_lco_drag_race << 4)); @@ -89,8 +67,8 @@ ao_lco_set_pad(uint8_t pad)  				 (0 << 5) |	\  				 (0 << 6)) -static void -ao_lco_set_box(uint16_t box) +void +ao_lco_show_box(uint16_t box)  {  	ao_mutex_get(&ao_lco_display_mutex);  	if (box == AO_LCO_BOX_DRAG) { @@ -104,7 +82,7 @@ ao_lco_set_box(uint16_t box)  }  static void -ao_lco_set_voltage(uint16_t decivolts) +ao_lco_show_voltage(uint16_t decivolts)  {  	uint8_t	tens, ones, tenths; @@ -118,27 +96,21 @@ ao_lco_set_voltage(uint16_t decivolts)  	ao_mutex_put(&ao_lco_display_mutex);  } -static void -ao_lco_set_display(void) +void +ao_lco_show(void)  { -	if (ao_lco_pad == 0 && ao_lco_box != AO_LCO_BOX_DRAG) { -		ao_lco_set_voltage(ao_pad_query.battery); +	if (ao_lco_pad == AO_LCO_PAD_VOLTAGE && ao_lco_box != AO_LCO_BOX_DRAG) { +		ao_lco_show_voltage(ao_pad_query.battery);  	} else {  		if (ao_lco_box == AO_LCO_BOX_DRAG) -			ao_lco_set_pad(ao_lco_drag_race); +			ao_lco_show_pad(ao_lco_drag_race);  		else -			ao_lco_set_pad(ao_lco_pad); -		ao_lco_set_box(ao_lco_box); +			ao_lco_show_pad(ao_lco_pad); +		ao_lco_show_box(ao_lco_box);  	}  } -#define MASK_SIZE(n)	(((n) + 7) >> 3) -#define MASK_ID(n)	((n) >> 3) -#define MASK_SHIFT(n)	((n) & 7) - -static uint8_t	ao_lco_box_mask[MASK_SIZE(AO_PAD_MAX_BOXES)]; - -static uint8_t +uint8_t  ao_lco_box_present(uint16_t box)  {  	if (box == AO_LCO_BOX_DRAG) @@ -146,117 +118,11 @@ ao_lco_box_present(uint16_t box)  	if (box >= AO_PAD_MAX_BOXES)  		return 0; -	return (ao_lco_box_mask[MASK_ID(box)] >> MASK_SHIFT(box)) & 1; -} - -static uint8_t -ao_lco_pad_present(uint8_t box, uint8_t pad) -{ -	/* voltage measurement is always valid */ -	if (pad == 0) -		return 1; -	if (!ao_lco_channels[box]) -		return 0; -	if (pad > AO_PAD_MAX_CHANNELS) -		return 0; -	return (ao_lco_channels[box] >> (pad - 1)) & 1; -} - -static uint8_t -ao_lco_pad_first(uint8_t box) -{ -	uint8_t	pad; - -	for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++) -		if (ao_lco_pad_present(box, pad)) -			return pad; -	return 0; +	return (ao_lco_box_mask[AO_LCO_MASK_ID(box)] >> AO_LCO_MASK_SHIFT(box)) & 1;  }  static struct ao_task	ao_lco_drag_task;  static uint8_t		ao_lco_drag_active; -static uint8_t		ao_lco_drag_beep_count; -static uint8_t		ao_lco_drag_beep_on; -static uint16_t		ao_lco_drag_beep_time; -static uint16_t		ao_lco_drag_warn_time; - -#define AO_LCO_DRAG_BEEP_TIME	AO_MS_TO_TICKS(50) -#define AO_LCO_DRAG_WARN_TIME	AO_SEC_TO_TICKS(5) - -static void -ao_lco_drag_beep_start(void) -{ -	ao_beep(AO_BEEP_HIGH); -	PRINTD("beep start\n"); -	ao_lco_drag_beep_on = 1; -	ao_lco_drag_beep_time = ao_time() + AO_LCO_DRAG_BEEP_TIME; -} - -static void -ao_lco_drag_beep_stop(void) -{ -	ao_beep(0); -	PRINTD("beep stop\n"); -	ao_lco_drag_beep_on = 0; -	if (ao_lco_drag_beep_count) { -		--ao_lco_drag_beep_count; -		if (ao_lco_drag_beep_count) -			ao_lco_drag_beep_time = ao_time() + AO_LCO_DRAG_BEEP_TIME; -	} -} - -static void -ao_lco_drag_beep(uint8_t beeps) -{ -	PRINTD("beep %d\n", beeps); -	if (!ao_lco_drag_beep_count) -		ao_lco_drag_beep_start(); -	ao_lco_drag_beep_count += beeps; -} - -static uint16_t -ao_lco_drag_beep_check(uint16_t now, uint16_t delay) -{ -	PRINTD("beep check count %d delta %d\n", -	       ao_lco_drag_beep_count, -	       (int16_t) (now - ao_lco_drag_beep_time)); -	if (ao_lco_drag_beep_count) { -		if ((int16_t) (now - ao_lco_drag_beep_time) >= 0) { -			if (ao_lco_drag_beep_on) -				ao_lco_drag_beep_stop(); -			else -				ao_lco_drag_beep_start(); -		} -	} - -	if (ao_lco_drag_beep_count) { -		if (delay > AO_LCO_DRAG_BEEP_TIME) -			delay = AO_LCO_DRAG_BEEP_TIME; -	} -	return delay; -} - -static void -ao_lco_drag_enable(void) -{ -	PRINTD("Drag enable\n"); -	ao_lco_drag_race = 1; -	memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); -	ao_lco_drag_beep(5); -	ao_lco_set_display(); -	ao_lco_fire_down = 0; -} - -static void -ao_lco_drag_disable(void) -{ -	PRINTD("Drag disable\n"); -	ao_lco_drag_race = 0; -	memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); -	ao_lco_drag_beep(2); -	ao_lco_set_display(); -	ao_lco_fire_down = 0; -}  static uint16_t  ao_lco_drag_button_check(uint16_t now, uint16_t delay) @@ -269,13 +135,17 @@ ao_lco_drag_button_check(uint16_t now, uint16_t delay)  	 */  	if (ao_lco_fire_down) {  		if (ao_lco_drag_race) { -			if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_STOP_TIME) +			if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_STOP_TIME) {  				ao_lco_drag_disable(); +				ao_lco_fire_down = 0; +			}  			else  				button_delay = ao_lco_fire_tick + AO_LCO_DRAG_RACE_STOP_TIME - now;  		} else { -			if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_START_TIME) +			if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_START_TIME) {  				ao_lco_drag_enable(); +				ao_lco_fire_down = 0; +			}  			else  				button_delay = ao_lco_fire_tick + AO_LCO_DRAG_RACE_START_TIME - now;  		} @@ -285,35 +155,20 @@ ao_lco_drag_button_check(uint16_t now, uint16_t delay)  	return delay;  } -static uint16_t -ao_lco_drag_warn_check(uint16_t now, uint16_t delay) -{ -	uint16_t	warn_delay = ~0; - -	if (ao_lco_drag_race) { -		if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) { -			ao_lco_drag_beep(1); -			ao_lco_drag_warn_time = now + AO_LCO_DRAG_WARN_TIME; -		} -		warn_delay = ao_lco_drag_warn_time - now; -	} -	if (delay > warn_delay) -		delay = warn_delay; -	return delay; -} -  static void  ao_lco_drag_monitor(void)  {  	uint16_t	delay = ~0;  	uint16_t	now; +	ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));  	for (;;) { -		PRINTD("Drag monitor active %d delay %d\n", ao_lco_drag_active, delay); +		PRINTD("Drag monitor count %d active %d delay %d\n", +		       ao_lco_drag_beep_count, ao_lco_drag_active, delay);  		if (delay == (uint16_t) ~0) -			ao_sleep(&ao_lco_drag_active); +			ao_sleep(&ao_lco_drag_beep_count);  		else -			ao_sleep_for(&ao_lco_drag_active, delay); +			ao_sleep_for(&ao_lco_drag_beep_count, delay);  		delay = ~0;  		if (!ao_lco_drag_active) @@ -333,13 +188,33 @@ ao_lco_drag_monitor(void)  }  static void +ao_lco_step_box(int8_t dir) +{ +	int16_t new_box = ao_lco_box; +	do { +		if (new_box == AO_LCO_BOX_DRAG) { +			if (dir < 0) +				new_box = ao_lco_max_box; +			else +				new_box = ao_lco_min_box; +		} else { +			new_box += dir; +			if (new_box > ao_lco_max_box) +				new_box = AO_LCO_BOX_DRAG; +			else if (new_box < ao_lco_min_box) +				new_box = AO_LCO_BOX_DRAG; +		} +		if (new_box == ao_lco_box) +			break; +	} while (!ao_lco_box_present(new_box)); +	ao_lco_set_box(new_box); +} + +static void  ao_lco_input(void)  {  	static struct ao_event	event; -	int8_t		dir, new_pad; -	int16_t		new_box; -	ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));  	for (;;) {  		ao_event_get(&event);  		PRINTD("event type %d unit %d value %d\n", @@ -348,106 +223,38 @@ ao_lco_input(void)  		case AO_EVENT_QUADRATURE:  			switch (event.unit) {  			case AO_QUADRATURE_PAD: -				if (!ao_lco_armed) { -					dir = (int8_t) event.value; -					new_pad = ao_lco_pad; -					do { -						new_pad += dir; -						if (new_pad > AO_PAD_MAX_CHANNELS) -							new_pad = 0; -						if (new_pad < 0) -							new_pad = AO_PAD_MAX_CHANNELS; -						if (new_pad == ao_lco_pad) -							break; -					} while (!ao_lco_pad_present(ao_lco_box, new_pad)); -					if (new_pad != ao_lco_pad) { -						ao_lco_pad = new_pad; -						ao_lco_set_display(); -					} -				} +				if (!ao_lco_armed) +					ao_lco_step_pad((int8_t) event.value);  				break;  			case AO_QUADRATURE_BOX: -				if (!ao_lco_armed) { -					dir = (int8_t) event.value; -					new_box = ao_lco_box; -					do { -						if (new_box == AO_LCO_BOX_DRAG) { -							if (dir < 0) -								new_box = ao_lco_max_box; -							else -								new_box = ao_lco_min_box; -						} else { -							new_box += dir; -							if (new_box > ao_lco_max_box) -								new_box = AO_LCO_BOX_DRAG; -							else if (new_box < ao_lco_min_box) -								new_box = AO_LCO_BOX_DRAG; -						} -						if (new_box == ao_lco_box) -							break; -					} while (!ao_lco_box_present(new_box)); -					if (ao_lco_box != new_box) { -						ao_lco_box = new_box; -						ao_lco_pad = 1; -						if (ao_lco_box != AO_LCO_BOX_DRAG) -							ao_lco_channels[ao_lco_box] = 0; -						ao_lco_set_display(); -					} -				} +				if (!ao_lco_armed) +					ao_lco_step_box((int8_t) event.value);  				break;  			}  			break;  		case AO_EVENT_BUTTON:  			switch (event.unit) {  			case AO_BUTTON_ARM: -				ao_lco_armed = event.value; -				PRINTD("Armed %d\n", ao_lco_armed); -				if (ao_lco_armed) { -					if (ao_lco_drag_race) { -						uint8_t	box; - -						for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) { -							if (ao_lco_selected[box]) { -								ao_wakeup(&ao_lco_armed); -								break; -							} -						} -					} else { -						memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); -						if (ao_lco_pad != 0 && ao_lco_box != AO_LCO_BOX_DRAG) -							ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1)); -						else -							ao_lco_armed = 0; -					} -				} -				ao_wakeup(&ao_lco_armed); +				ao_lco_set_armed(event.value);  				break;  			case AO_BUTTON_FIRE:  				if (ao_lco_armed) {  					ao_lco_fire_down = 0; -					ao_lco_firing = event.value; -					PRINTD("Firing %d\n", ao_lco_firing); -					ao_wakeup(&ao_lco_armed); +					ao_lco_set_firing(event.value);  				} else {  					if (event.value) {  						if (ao_lco_box == AO_LCO_BOX_DRAG) {  							ao_lco_fire_down = 1;  							ao_lco_fire_tick = ao_time();  							ao_lco_drag_active = 1; +							ao_wakeup(&ao_lco_drag_beep_count); +						} else { +							ao_lco_toggle_drag();  						} -						if (ao_lco_drag_race) { -							if (ao_lco_pad != 0 && ao_lco_box != AO_LCO_BOX_DRAG) { -								ao_lco_selected[ao_lco_box] ^= (1 << (ao_lco_pad - 1)); -								PRINTD("Toggle box %d pad %d (pads now %x) to drag race\n", -								       ao_lco_pad, ao_lco_box, ao_lco_selected[ao_lco_box]); -								ao_lco_drag_beep(ao_lco_pad); -							} -						} -						ao_wakeup(&ao_lco_drag_active);  					} else {  						ao_lco_fire_down = 0;  						if (ao_lco_drag_active) -							ao_wakeup(&ao_lco_drag_active); +							ao_wakeup(&ao_lco_drag_beep_count);  					}  				}  				break; @@ -457,188 +264,36 @@ ao_lco_input(void)  	}  } -static AO_LED_TYPE	continuity_led[AO_LED_CONTINUITY_NUM] = { -#ifdef AO_LED_CONTINUITY_0 -	AO_LED_CONTINUITY_0, -#endif -#ifdef AO_LED_CONTINUITY_1 -	AO_LED_CONTINUITY_1, -#endif -#ifdef AO_LED_CONTINUITY_2 -	AO_LED_CONTINUITY_2, -#endif -#ifdef AO_LED_CONTINUITY_3 -	AO_LED_CONTINUITY_3, -#endif -#ifdef AO_LED_CONTINUITY_4 -	AO_LED_CONTINUITY_4, -#endif -#ifdef AO_LED_CONTINUITY_5 -	AO_LED_CONTINUITY_5, -#endif -#ifdef AO_LED_CONTINUITY_6 -	AO_LED_CONTINUITY_6, -#endif -#ifdef AO_LED_CONTINUITY_7 -	AO_LED_CONTINUITY_7, -#endif -}; - -static uint8_t -ao_lco_get_channels(uint8_t box, struct ao_pad_query *query) -{ -	int8_t			r; - -	r = ao_lco_query(box, query, &ao_lco_tick_offset[box]); -	if (r == AO_RADIO_CMAC_OK) { -		ao_lco_channels[box] = query->channels; -		ao_lco_valid[box] = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER; -	} else -		ao_lco_valid[box] &= ~AO_LCO_VALID_LAST; -	PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box]); -	ao_wakeup(&ao_pad_query); -	return ao_lco_valid[box]; -} - -static void -ao_lco_update(void) -{ -	if (ao_lco_box != AO_LCO_BOX_DRAG) { -		uint8_t	previous_valid = ao_lco_valid[ao_lco_box]; - -		if (ao_lco_get_channels(ao_lco_box, &ao_pad_query) & AO_LCO_VALID_LAST) { -			if (!(previous_valid & AO_LCO_VALID_EVER)) { -				if (ao_lco_pad != 0) -					ao_lco_pad = ao_lco_pad_first(ao_lco_box); -				ao_lco_set_display(); -			} -			if (ao_lco_pad == 0) -				ao_lco_set_display(); -		} -	} -} - -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); -} - +/* + * Light up everything for a second at power on to let the user + * visually inspect the system for correct operation + */  static void -ao_lco_search(void) +ao_lco_display_test()  { -	int8_t		r; -	int8_t		try; -	uint8_t		box; -	uint8_t		boxes = 0; - -	ao_lco_box_reset_present(); -	ao_lco_set_pad(0); -	for (box = 0; box < AO_PAD_MAX_BOXES; box++) { -		if ((box % 10) == 0) -			ao_lco_set_box(box); -		for (try = 0; try < 3; try++) { -			ao_lco_tick_offset[box] = 0; -			r = ao_lco_query(box, &ao_pad_query, &ao_lco_tick_offset[box]); -			PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]); -			if (r == AO_RADIO_CMAC_OK) { -				++boxes; -				ao_lco_box_set_present(box); -				ao_lco_set_pad(boxes % 10); -				ao_delay(AO_MS_TO_TICKS(30)); -				break; -			} -		} -	} -	if (ao_lco_min_box <= ao_lco_max_box) -		ao_lco_box = ao_lco_min_box; -	else -		ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0; -	memset(ao_lco_valid, 0, sizeof (ao_lco_valid)); -	memset(ao_lco_channels, 0, sizeof (ao_lco_channels)); -	ao_lco_pad = 1; -	ao_lco_set_display(); +	ao_mutex_get(&ao_lco_display_mutex); +	ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, 8 | 0x10); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 8 | 0x10); +	ao_mutex_put(&ao_lco_display_mutex); +	ao_led_on(LEDS_AVAILABLE); +	ao_delay(AO_MS_TO_TICKS(1000)); +	ao_led_off(LEDS_AVAILABLE);  } +#if HAS_ADC_SINGLE  static void -ao_lco_igniter_status(void) +ao_lco_batt_voltage(void)  { -	uint8_t		c; -	uint8_t		t = 0; - -	for (;;) { -		ao_sleep(&ao_pad_query); -		PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_box == AO_LCO_BOX_DRAG ? -1 : ao_lco_valid[ao_lco_box]); -		if (ao_lco_box == AO_LCO_BOX_DRAG) { -			ao_led_off(AO_LED_RED|AO_LED_GREEN|AO_LED_AMBER); -			for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) -				ao_led_off(continuity_led[c]); -		} else { -			if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) { -				ao_led_on(AO_LED_RED); -				ao_led_off(AO_LED_GREEN|AO_LED_AMBER); -				continue; -			} -			if (ao_radio_cmac_rssi < -90) { -				ao_led_on(AO_LED_AMBER); -				ao_led_off(AO_LED_RED|AO_LED_GREEN); -			} else { -				ao_led_on(AO_LED_GREEN); -				ao_led_off(AO_LED_RED|AO_LED_AMBER); -			} -			if (ao_pad_query.arm_status) -				ao_led_on(AO_LED_REMOTE_ARM); -			else -				ao_led_off(AO_LED_REMOTE_ARM); - -			for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { -				uint8_t	status; +	struct ao_adc	packet; +	int16_t		decivolt; -				if (ao_lco_drag_race) { -					if (ao_lco_selected[ao_lco_box] & (1 << c) && t) -						ao_led_on(continuity_led[c]); -					else -						ao_led_off(continuity_led[c]); -				} else { -					if (ao_pad_query.channels & (1 << c)) -						status = ao_pad_query.igniter_status[c]; -					else -						status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; -					if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) -						ao_led_on(continuity_led[c]); -					else -						ao_led_off(continuity_led[c]); -				} -			} -			t = 1-t; -		} -	} -} - -static void -ao_lco_arm_warn(void) -{ -	for (;;) { -		while (!ao_lco_armed) -			ao_sleep(&ao_lco_armed); -		ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -		ao_delay(AO_MS_TO_TICKS(200)); -	} +	ao_adc_single_get(&packet); +	decivolt = ao_battery_decivolt(packet.v_batt); +	ao_lco_show_voltage(decivolt); +	ao_delay(AO_MS_TO_TICKS(1000));  } +#endif  static struct ao_task ao_lco_input_task;  static struct ao_task ao_lco_monitor_task; @@ -646,43 +301,18 @@ static struct ao_task ao_lco_arm_warn_task;  static struct ao_task ao_lco_igniter_status_task;  static void -ao_lco_monitor(void) +ao_lco_main(void)  { -	uint16_t		delay; -	uint8_t			box; - +	ao_lco_display_test(); +#if HAS_ADC_SINGLE +	ao_lco_batt_voltage(); +#endif  	ao_lco_search();  	ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");  	ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");  	ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");  	ao_add_task(&ao_lco_drag_task, ao_lco_drag_monitor, "drag race"); -	for (;;) { -		PRINTD("monitor armed %d firing %d\n", -		       ao_lco_armed, ao_lco_firing); - -		if (ao_lco_armed && ao_lco_firing) { -			ao_lco_ignite(AO_PAD_FIRE); -		} else { -			ao_lco_update(); -			if (ao_lco_armed) { -				for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) { -					if (ao_lco_selected[box]) { -						PRINTD("Arming box %d pads %x\n", -						       box, ao_lco_selected[box]); -						if (ao_lco_valid[box] & AO_LCO_VALID_EVER) { -							ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]); -							ao_delay(AO_MS_TO_TICKS(10)); -						} -					} -				} -			} -		} -		if (ao_lco_armed && ao_lco_firing) -			delay = AO_MS_TO_TICKS(100); -		else -			delay = AO_SEC_TO_TICKS(1); -		ao_sleep_for(&ao_lco_armed, delay); -	} +	ao_lco_monitor();  }  #if DEBUG @@ -704,7 +334,7 @@ __code struct ao_cmds ao_lco_cmds[] = {  void  ao_lco_init(void)  { -	ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); +	ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");  #if DEBUG  	ao_cmd_register(&ao_lco_cmds[0]);  #endif diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h index 5721eed5..2958fbcc 100644 --- a/src/drivers/ao_lco.h +++ b/src/drivers/ao_lco.h @@ -19,7 +19,126 @@  #ifndef _AO_LCO_H_  #define _AO_LCO_H_ +#include <ao_lco_func.h> + +#ifndef AO_LCO_DRAG +#define AO_LCO_DRAG	1 +#endif + +#define DEBUG	1 + +#if DEBUG +extern uint8_t	ao_lco_debug; +#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) +#else +#define PRINTD(...)  +#endif + +#if AO_LCO_DRAG +extern uint8_t	ao_lco_drag_race;	/* TRUE when drag race mode enabled */ +#endif + +extern uint8_t	ao_lco_pad;		/* Currently selected pad */ +extern int16_t	ao_lco_box;		/* Currently selected box */ + +extern uint8_t	ao_lco_armed;		/* armed mode active */ +extern uint8_t	ao_lco_firing;		/* fire button pressed */ + +extern struct ao_pad_query	ao_pad_query;	/* Last received QUERY from pad */ + +#define AO_LCO_PAD_VOLTAGE	0		/* Pad number to show box voltage */ + +extern uint8_t	ao_lco_min_box, ao_lco_max_box; + +#define AO_LCO_MASK_SIZE(n)	(((n) + 7) >> 3) +#define AO_LCO_MASK_ID(n)	((n) >> 3) +#define AO_LCO_MASK_SHIFT(n)	((n) & 7) + +extern uint8_t	ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)]; + +/* + * Shared functions + */ + +void +ao_lco_igniter_status(void); + +void +ao_lco_update(void); + +uint8_t +ao_lco_pad_present(uint8_t box, uint8_t pad); + +uint8_t +ao_lco_pad_first(uint8_t box); + +void +ao_lco_set_pad(uint8_t new_pad); + +void +ao_lco_step_pad(int8_t dir); + +void +ao_lco_set_box(uint16_t new_box); + +void +ao_lco_set_armed(uint8_t armed); + +void +ao_lco_set_firing(uint8_t firing); + +void +ao_lco_toggle_drag(void); + +void +ao_lco_search(void); + +void +ao_lco_monitor(void); + +extern uint8_t			ao_lco_drag_beep_count; + +/* enable drag race mode */ +void +ao_lco_drag_enable(void); + +/* disable drag race mode */ +void +ao_lco_drag_disable(void); + +/* Handle drag beeps, return new delay */ +uint16_t +ao_lco_drag_beep_check(uint16_t now, uint16_t delay); + +/* Check if it's time to beep during drag race. Return new delay */ +uint16_t +ao_lco_drag_warn_check(uint16_t now, uint16_t delay); + +/* Request 'beeps' additional drag race beeps */ +void +ao_lco_drag_add_beeps(uint8_t beeps); + +/* task function for beeping while arm is active */ +void +ao_lco_arm_warn(void); + +/* + * Provided by the hw-specific driver code + */ + +void +ao_lco_show_pad(uint8_t pad); + +void +ao_lco_show_box(uint16_t box); + +void +ao_lco_show(void); +  void  ao_lco_init(void); +uint8_t +ao_lco_box_present(uint16_t box); +  #endif /* _AO_LCO_H_ */ diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c new file mode 100644 index 00000000..6e50e44d --- /dev/null +++ b/src/drivers/ao_lco_bits.c @@ -0,0 +1,501 @@ +/* + * Copyright © 2018 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +#include <ao.h> +#include <ao_lco.h> +#include <ao_radio_cmac.h> + +uint8_t		ao_lco_debug; + +uint8_t		ao_lco_pad; +int16_t		ao_lco_box; + +uint8_t		ao_lco_armed;					/* arm active */ +uint8_t		ao_lco_firing;					/* fire active */ + +uint8_t		ao_lco_min_box, ao_lco_max_box; + +#if AO_LCO_DRAG +uint8_t		ao_lco_drag_race; +#endif + +struct ao_pad_query	ao_pad_query;				/* latest query response */ + +static uint8_t		ao_lco_channels[AO_PAD_MAX_BOXES];	/* pad channels available on each box */ +static uint16_t		ao_lco_tick_offset[AO_PAD_MAX_BOXES];	/* offset from local to remote tick count */ +static uint8_t		ao_lco_selected[AO_PAD_MAX_BOXES];	/* pads selected to fire */ + +#define AO_LCO_VALID_LAST	1 +#define AO_LCO_VALID_EVER	2 + +static uint8_t		ao_lco_valid[AO_PAD_MAX_BOXES];		/* AO_LCO_VALID bits per box */ + +static const AO_LED_TYPE	continuity_led[AO_LED_CONTINUITY_NUM] = { +#ifdef AO_LED_CONTINUITY_0 +	AO_LED_CONTINUITY_0, +#endif +#ifdef AO_LED_CONTINUITY_1 +	AO_LED_CONTINUITY_1, +#endif +#ifdef AO_LED_CONTINUITY_2 +	AO_LED_CONTINUITY_2, +#endif +#ifdef AO_LED_CONTINUITY_3 +	AO_LED_CONTINUITY_3, +#endif +#ifdef AO_LED_CONTINUITY_4 +	AO_LED_CONTINUITY_4, +#endif +#ifdef AO_LED_CONTINUITY_5 +	AO_LED_CONTINUITY_5, +#endif +#ifdef AO_LED_CONTINUITY_6 +	AO_LED_CONTINUITY_6, +#endif +#ifdef AO_LED_CONTINUITY_7 +	AO_LED_CONTINUITY_7, +#endif +}; + +/* Set LEDs to match remote box status */ +void +ao_lco_igniter_status(void) +{ +	uint8_t		c; +	uint8_t		t = 0; + +	for (;;) { +#if AO_LCO_DRAG +		if (ao_lco_drag_race) +			ao_sleep_for(&ao_pad_query, AO_MS_TO_TICKS(50)); +		else +#endif +			ao_sleep(&ao_pad_query); +		PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid[ao_lco_box]); +		if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) { +			ao_led_on(AO_LED_RED); +			ao_led_off(AO_LED_GREEN|AO_LED_AMBER); +			continue; +		} +		if (ao_radio_cmac_rssi < -90) { +			ao_led_on(AO_LED_AMBER); +			ao_led_off(AO_LED_RED|AO_LED_GREEN); +		} else { +			ao_led_on(AO_LED_GREEN); +			ao_led_off(AO_LED_RED|AO_LED_AMBER); +		} +		if (ao_pad_query.arm_status) +			ao_led_on(AO_LED_REMOTE_ARM); +		else +			ao_led_off(AO_LED_REMOTE_ARM); + +		for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { +			uint8_t	status; + +			if (ao_pad_query.channels & (1 << c)) +				status = ao_pad_query.igniter_status[c]; +			else +				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + +#if AO_LCO_DRAG +			if (ao_lco_drag_race && (ao_lco_selected[ao_lco_box] & (1 << c))) { +				uint8_t	on = 0; +				if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) { +					if (t) +						on = 1; +				} else { +					if (t == 1) +						on = 1; +				} +				if (on) +					ao_led_on(continuity_led[c]); +				else +					ao_led_off(continuity_led[c]); +			} else +#endif +			{ +				if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) +					ao_led_on(continuity_led[c]); +				else +					ao_led_off(continuity_led[c]); +			} +		} +		t = (t + 1) & 3; +	} +} + +uint8_t +ao_lco_pad_present(uint8_t box, uint8_t pad) +{ +	/* voltage measurement is always valid */ +	if (pad == AO_LCO_PAD_VOLTAGE) +		return 1; +	if (!ao_lco_channels[box]) +		return 0; +	if (pad > AO_PAD_MAX_CHANNELS) +		return 0; +	return (ao_lco_channels[box] >> (pad - 1)) & 1; +} + +uint8_t +ao_lco_pad_first(uint8_t box) +{ +	uint8_t	pad; + +	for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++) +		if (ao_lco_pad_present(box, pad)) +			return pad; +	return 0; +} + +static uint8_t +ao_lco_get_channels(uint8_t box, struct ao_pad_query *query) +{ +	int8_t			r; + +	r = ao_lco_query(box, query, &ao_lco_tick_offset[box]); +	if (r == AO_RADIO_CMAC_OK) { +		ao_lco_channels[box] = query->channels; +		ao_lco_valid[box] = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER; +	} else +		ao_lco_valid[box] &= ~AO_LCO_VALID_LAST; +	PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box]); +	ao_wakeup(&ao_pad_query); +	return ao_lco_valid[box]; +} + +void +ao_lco_update(void) +{ +	uint8_t	previous_valid = ao_lco_valid[ao_lco_box]; + +	if (ao_lco_get_channels(ao_lco_box, &ao_pad_query) & AO_LCO_VALID_LAST) { +		if (!(previous_valid & AO_LCO_VALID_EVER)) { +			if (ao_lco_pad != AO_LCO_PAD_VOLTAGE) +				ao_lco_set_pad(ao_lco_pad_first(ao_lco_box)); +		} +		if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) +			ao_lco_show(); +	} +} + +uint8_t	ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)]; + +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[AO_LCO_MASK_ID(box)] |= 1 << AO_LCO_MASK_SHIFT(box); +} + +void +ao_lco_set_pad(uint8_t new_pad) +{ +	ao_lco_pad = new_pad; +	ao_lco_show(); +} + +void +ao_lco_set_box(uint16_t new_box) +{ +	ao_lco_box = new_box; +	if (ao_lco_box < AO_PAD_MAX_BOXES) +		ao_lco_channels[ao_lco_box] = 0; +	ao_lco_pad = 1; +	ao_lco_show(); +} + +void +ao_lco_step_pad(int8_t dir) +{ +	int8_t	new_pad; + +	new_pad = ao_lco_pad; +	do { +		new_pad += dir; +		if (new_pad > AO_PAD_MAX_CHANNELS) +			new_pad = AO_LCO_PAD_VOLTAGE; +		if (new_pad < 0) +			new_pad = AO_PAD_MAX_CHANNELS; +		if (new_pad == ao_lco_pad) +			break; +	} while (!ao_lco_pad_present(ao_lco_box, new_pad)); +	ao_lco_set_pad(new_pad); +} + +void +ao_lco_set_armed(uint8_t armed) +{ +	ao_lco_armed = armed; +	PRINTD("Armed %d\n", ao_lco_armed); +	if (ao_lco_armed) { +#if AO_LCO_DRAG +		if (ao_lco_drag_race) { +			uint8_t	box; + +			for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) +				if (ao_lco_selected[box]) +					break; +			if (box > ao_lco_max_box) +				ao_lco_armed = 0; +		} else +#endif +		{ +			memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); +			if (ao_lco_pad != 0) +				ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1)); +			else +				ao_lco_armed = 0; +		} +	} +	ao_wakeup(&ao_lco_armed); +} + +void +ao_lco_set_firing(uint8_t firing) +{ +	ao_lco_firing = firing; +	PRINTD("Firing %d\n", ao_lco_firing); +	ao_wakeup(&ao_lco_armed); +} + +void +ao_lco_search(void) +{ +	int8_t		r; +	int8_t		try; +	uint8_t		box; +	uint8_t		boxes = 0; + +	ao_lco_box_reset_present(); +	ao_lco_show_box(0); +	ao_lco_show_pad(0); +	for (box = 0; box < AO_PAD_MAX_BOXES; box++) { +		if ((box % 10) == 0) +			ao_lco_show_box(box); +		for (try = 0; try < 3; try++) { +			ao_lco_tick_offset[box] = 0; +			r = ao_lco_query(box, &ao_pad_query, &ao_lco_tick_offset[box]); +			PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]); +			if (r == AO_RADIO_CMAC_OK) { +				++boxes; +				ao_lco_box_set_present(box); +				ao_lco_show_pad(boxes % 10); +				ao_delay(AO_MS_TO_TICKS(30)); +				break; +			} +		} +	} +	if (ao_lco_min_box <= ao_lco_max_box) +		ao_lco_box = ao_lco_min_box; +	else +		ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0; +	memset(ao_lco_valid, 0, sizeof (ao_lco_valid)); +	memset(ao_lco_channels, 0, sizeof (ao_lco_channels)); +	ao_lco_set_box(ao_lco_min_box); +} + +void +ao_lco_monitor(void) +{ +	uint16_t		delay; +	uint8_t			box; + +	for (;;) { +		PRINTD("monitor armed %d firing %d\n", +		       ao_lco_armed, ao_lco_firing); + +		if (ao_lco_armed && ao_lco_firing) { +			ao_lco_ignite(AO_PAD_FIRE); +		} else { +			ao_lco_update(); +			if (ao_lco_armed) { +				for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) { +					if (ao_lco_selected[box]) { +						PRINTD("Arming box %d pads %x\n", +						       box, ao_lco_selected[box]); +						if (ao_lco_valid[box] & AO_LCO_VALID_EVER) { +							ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]); +							ao_delay(AO_MS_TO_TICKS(10)); +						} +					} +				} +			} +		} +		if (ao_lco_armed && ao_lco_firing) +			delay = AO_MS_TO_TICKS(100); +		else +			delay = AO_SEC_TO_TICKS(1); +		ao_sleep_for(&ao_lco_armed, delay); +	} +} + +#if AO_LCO_DRAG + +uint8_t			ao_lco_drag_beep_count; +static uint8_t		ao_lco_drag_beep_on; +static uint16_t		ao_lco_drag_beep_time; +static uint16_t		ao_lco_drag_warn_time; + +#define AO_LCO_DRAG_BEEP_TIME	AO_MS_TO_TICKS(50) +#define AO_LCO_DRAG_WARN_TIME	AO_SEC_TO_TICKS(5) + +/* Request 'beeps' additional drag race beeps */ +void +ao_lco_drag_add_beeps(uint8_t beeps) +{ +	PRINTD("beep %d\n", beeps); +	if (ao_lco_drag_beep_count == 0) +		ao_lco_drag_beep_time = ao_time(); +	ao_lco_drag_beep_count += beeps; +	ao_wakeup(&ao_lco_drag_beep_count); +} + +/* Toggle current pad in drag set */ +void +ao_lco_toggle_drag(void) +{ +	if (ao_lco_drag_race && ao_lco_pad != AO_LCO_PAD_VOLTAGE) { +		ao_lco_selected[ao_lco_box] ^= (1 << (ao_lco_pad - 1)); +		PRINTD("Toggle box %d pad %d (pads now %x) to drag race\n", +		       ao_lco_pad, ao_lco_box, ao_lco_selected[ao_lco_box]); +		ao_lco_drag_add_beeps(ao_lco_pad); +	} +} + +/* Check whether it's time to change the beeper status, then either + * turn it on or off as necessary and bump the remaining beep counts + */ + +uint16_t +ao_lco_drag_beep_check(uint16_t now, uint16_t delay) +{ +	PRINTD("beep check count %d delta %d\n", +	       ao_lco_drag_beep_count, +	       (int16_t) (now - ao_lco_drag_beep_time)); +	if (ao_lco_drag_beep_count) { +		if ((int16_t) (now - ao_lco_drag_beep_time) >= 0) { +			if (ao_lco_drag_beep_on) { +				ao_beep(0); +				PRINTD("beep stop\n"); +				ao_lco_drag_beep_on = 0; +				if (ao_lco_drag_beep_count) { +					--ao_lco_drag_beep_count; +					if (ao_lco_drag_beep_count) +						ao_lco_drag_beep_time = now + AO_LCO_DRAG_BEEP_TIME; +				} +			} else { +				ao_beep(AO_BEEP_HIGH); +				PRINTD("beep start\n"); +				ao_lco_drag_beep_on = 1; +				ao_lco_drag_beep_time = now + AO_LCO_DRAG_BEEP_TIME; +			} +		} +	} + +	if (ao_lco_drag_beep_count) { +		uint16_t beep_delay = 0; + +		if (ao_lco_drag_beep_time > now) +			beep_delay = ao_lco_drag_beep_time - now; + +		if (delay > beep_delay) +			delay = beep_delay; +	} +	return delay; +} + +void +ao_lco_drag_enable(void) +{ +	if (!ao_lco_drag_race) { +		PRINTD("Drag enable\n"); +		ao_lco_drag_race = 1; +		memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); +#ifdef AO_LED_DRAG +		ao_led_on(AO_LED_DRAG); +#endif +		ao_lco_drag_add_beeps(5); +		ao_lco_show(); +	} +} + +void +ao_lco_drag_disable(void) +{ +	if (ao_lco_drag_race) { +		PRINTD("Drag disable\n"); +		ao_lco_drag_race = 0; +#ifdef AO_LED_DRAG +		ao_led_off(AO_LED_DRAG); +#endif +		memset(ao_lco_selected, 0, sizeof (ao_lco_selected)); +		ao_lco_drag_add_beeps(2); +		ao_lco_show(); +	} +} + +/* add a beep if it's time to warn the user that drag race mode is + * active + */ + +uint16_t +ao_lco_drag_warn_check(uint16_t now, uint16_t delay) +{ +	if (ao_lco_drag_race) { +		uint16_t	warn_delay; + +		if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) { +			ao_lco_drag_add_beeps(1); +			ao_lco_drag_warn_time = now + AO_LCO_DRAG_WARN_TIME; +		} +		warn_delay = ao_lco_drag_warn_time - now; +		if (delay > warn_delay) +			delay = warn_delay; +	} +	return delay; +} +#endif /* AO_LCO_DRAG */ + +/* task function for beeping while arm is active */ +void +ao_lco_arm_warn(void) +{ +	for (;;) { +		while (!ao_lco_armed) { +#ifdef AO_LED_FIRE +			ao_led_off(AO_LED_FIRE); +#endif +			ao_sleep(&ao_lco_armed); +		} +#ifdef AO_LED_FIRE +		ao_led_on(AO_LED_FIRE); +#endif +		ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +		ao_delay(AO_MS_TO_TICKS(200)); +	} +} diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c index 8de21fb6..dba9a76a 100644 --- a/src/drivers/ao_lco_cmd.c +++ b/src/drivers/ao_lco_cmd.c @@ -22,6 +22,10 @@  #include <ao_lco_func.h>  #include <ao_radio_cmac.h> +#ifndef HAS_STATIC_TEST +#define HAS_STATIC_TEST	1 +#endif +  static __pdata uint16_t	lco_box;  static __pdata uint8_t	lco_channels;  static __pdata uint16_t	tick_offset; @@ -150,6 +154,7 @@ lco_fire_cmd(void) __reentrant  	}  } +#if HAS_STATIC_TEST  static void  lco_static_cmd(void) __reentrant  { @@ -182,6 +187,7 @@ lco_static_cmd(void) __reentrant  		ao_delay(AO_MS_TO_TICKS(100));  	}  } +#endif  static void  lco_arm_cmd(void) __reentrant @@ -208,18 +214,21 @@ lco_ignite_cmd(void) __reentrant  } +#if HAS_STATIC_TEST  static void  lco_endstatic_cmd(void) __reentrant  {  	lco_ignite(AO_PAD_ENDSTATIC);  } +#endif  static __code struct ao_cmds ao_lco_cmds[] = {  	{ lco_report_cmd,	"l <box> <channel>\0Get remote status" },  	{ lco_fire_cmd,		"F <box> <channel> <secs>\0Fire remote igniters" }, -	{ lco_fire_cmd,		"F <box> <channel> <secs>\0Fire remote igniters" }, +#if HAS_STATIC_TEST  	{ lco_static_cmd,	"S <box> <channel> <secs>\0Initiate static test" },  	{ lco_endstatic_cmd,	"D\0End static test (and download someday)" }, +#endif  	{ lco_arm_cmd,		"a <box> <channel>\0Arm remote igniter" },  	{ lco_ignite_cmd,	"i <box> <channel>\0Pulse remote igniter" },  	{ 0, NULL }, diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c index e2f86745..6f2d81ff 100644 --- a/src/drivers/ao_lco_two.c +++ b/src/drivers/ao_lco_two.c @@ -23,64 +23,13 @@  #include <ao_lco_func.h>  #include <ao_radio_cmac.h> -#define DEBUG	1 - -#if DEBUG -static uint8_t	ao_lco_debug; -#define DEBUG_EVENT	1 -#define DEBUG_STATUS	2 -#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) -#else -#define PRINTD(l,...) -#endif - -#define AO_LCO_VALID_LAST	1 -#define AO_LCO_VALID_EVER	2 -  static uint8_t	ao_lco_suspended; -static uint8_t	ao_lco_valid; -static uint8_t	ao_lco_channels; -static uint16_t	ao_lco_tick_offset; - -/* UI values */ -static uint8_t	ao_lco_armed; -static uint8_t	ao_lco_firing; -static uint8_t	ao_lco_box; - -static struct ao_pad_query	ao_pad_query; - -/* TeleFireTwo boxes have a single pad */ -#define ao_lco_pad	0 - -static void -ao_lco_set_box(int box) -{ -	ao_lco_box = ao_config.pad_box + box; -	ao_lco_valid = 0; -	ao_lco_armed = 0; -	ao_wakeup(&ao_lco_armed); -} - -static void -ao_lco_set_armed(int armed) -{ -	uint8_t	bit = (1 << ao_lco_pad); - -	if (armed) { -		ao_lco_armed = bit; -	} else { -		ao_lco_armed = 0; -	} -	PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_armed 0x%x\n", -	       ao_lco_pad, bit, armed, ao_lco_armed); -	ao_wakeup(&ao_lco_armed); -}  static void  ao_lco_suspend(void)  {  	if (!ao_lco_suspended) { -		PRINTD(DEBUG_EVENT, "suspend\n"); +		PRINTD("suspend\n");  		ao_lco_suspended = 1;  		ao_lco_armed = 0;  		ao_wakeup(&ao_pad_query); @@ -96,6 +45,23 @@ ao_lco_wakeup(void)  	}  } +void +ao_lco_show_pad(uint8_t pad) +{ +	(void) pad; +} + +void +ao_lco_show_box(uint16_t box) +{ +	(void) box; +} + +void +ao_lco_show(void) +{ +} +  static void  ao_lco_input(void)  { @@ -113,23 +79,21 @@ ao_lco_input(void)  			ao_event_get(&event);  		}  		ao_lco_wakeup(); -		PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n", +		PRINTD("event type %d unit %d value %d\n",  		       event.type, event.unit, event.value);  		switch (event.type) {  		case AO_EVENT_BUTTON:  			switch (event.unit) {  			case AO_BUTTON_BOX:  				ao_lco_set_box(event.value); +				ao_lco_set_armed(0);  				break;  			case AO_BUTTON_ARM:  				ao_lco_set_armed(event.value);  				break;  			case AO_BUTTON_FIRE: -				if (ao_lco_armed) { -					ao_lco_firing = event.value; -					PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing); -					ao_wakeup(&ao_lco_armed); -				} +				if (ao_lco_armed) +					ao_lco_set_firing(event.value);  				break;  			}  			break; @@ -137,140 +101,14 @@ ao_lco_input(void)  	}  } -static AO_LED_TYPE	continuity_led[AO_LED_CONTINUITY_NUM] = { -#ifdef AO_LED_CONTINUITY_0 -	AO_LED_CONTINUITY_0, -#endif -#ifdef AO_LED_CONTINUITY_1 -	AO_LED_CONTINUITY_1, -#endif -#ifdef AO_LED_CONTINUITY_2 -	AO_LED_CONTINUITY_2, -#endif -#ifdef AO_LED_CONTINUITY_3 -	AO_LED_CONTINUITY_3, -#endif -#ifdef AO_LED_CONTINUITY_4 -	AO_LED_CONTINUITY_4, -#endif -#ifdef AO_LED_CONTINUITY_5 -	AO_LED_CONTINUITY_5, -#endif -#ifdef AO_LED_CONTINUITY_6 -	AO_LED_CONTINUITY_6, -#endif -#ifdef AO_LED_CONTINUITY_7 -	AO_LED_CONTINUITY_7, -#endif -}; - -static uint8_t -ao_lco_get_channels(void) -{ -	int8_t			r; - -	r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); -	if (r == AO_RADIO_CMAC_OK) { -		ao_lco_channels = ao_pad_query.channels; -		ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER; -	} else -		ao_lco_valid &= ~AO_LCO_VALID_LAST; -	PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset); -	ao_wakeup(&ao_pad_query); -	return ao_lco_valid; -} - -static void -ao_lco_igniter_status(void) -{ -	uint8_t		c; -	uint8_t		t = 0; - -	for (;;) { -		uint8_t	all_status; -		ao_sleep(&ao_pad_query); -		while (ao_lco_suspended) { -			ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM); -			for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) -				ao_led_off(continuity_led[c]); -			ao_sleep(&ao_lco_suspended); -		} -		PRINTD(DEBUG_STATUS, "RSSI %d VALID %d channels %d arm_status %d\n", -		       ao_radio_cmac_rssi, ao_lco_valid, -		       ao_lco_channels, ao_pad_query.arm_status); -		if (!(ao_lco_valid & AO_LCO_VALID_LAST)) { -			ao_led_on(AO_LED_RED); -			ao_led_off(AO_LED_GREEN|AO_LED_AMBER); -			memset(&ao_pad_query, '\0', sizeof (ao_pad_query)); -		} else if (ao_radio_cmac_rssi < -90) { -			ao_led_on(AO_LED_AMBER); -			ao_led_off(AO_LED_RED|AO_LED_GREEN); -		} else { -			ao_led_on(AO_LED_GREEN); -			ao_led_off(AO_LED_RED|AO_LED_AMBER); -		} -		if (ao_pad_query.arm_status) -			ao_led_on(AO_LED_REMOTE_ARM); -		else -			ao_led_off(AO_LED_REMOTE_ARM); - -		all_status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; -		for (c = 0; c < 8; c++) { -			if (ao_pad_query.channels & (1 << c)) { -				uint8_t status = ao_pad_query.igniter_status[c]; -				if (status > all_status) -					all_status = status; -				PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status); -			} -		} -		for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { -			uint8_t	on = 0; -			if (c == (ao_lco_box - ao_config.pad_box) % AO_LED_CONTINUITY_NUM) { -				switch (all_status) { -				case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN: -					on = 1; -					break; -				case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED: -				case AO_PAD_IGNITER_STATUS_UNKNOWN: -					on = t & 1; -				} -			} -			if (on) -				ao_led_on(continuity_led[c]); -			else -				ao_led_off(continuity_led[c]); -		} -		t = 1-t; -	} -} - -static void -ao_lco_arm_warn(void) -{ -	int	i; -	for (;;) { -		while (ao_lco_suspended) -			ao_sleep(&ao_lco_suspended); -		while (!ao_lco_armed) -			ao_sleep(&ao_lco_armed); -		for (i = 0; i < ao_lco_armed; i++) { -			ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); -			ao_delay(AO_MS_TO_TICKS(100)); -		} -		ao_delay(AO_MS_TO_TICKS(300)); -	} -} -  static struct ao_task ao_lco_input_task;  static struct ao_task ao_lco_monitor_task;  static struct ao_task ao_lco_arm_warn_task;  static struct ao_task ao_lco_igniter_status_task;  static void -ao_lco_monitor(void) +ao_lco_main(void)  { -	uint16_t		delay; -  	ao_config_get();  	ao_lco_set_box(ao_button_get(AO_BUTTON_BOX));  	ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); @@ -279,33 +117,7 @@ ao_lco_monitor(void)  	ao_led_on(~0);  	ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));  	ao_led_off(~0); -	for (;;) { -		while (ao_lco_suspended) -			ao_sleep(&ao_lco_suspended); - -		PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n", -		       ao_lco_armed, ao_lco_firing); - -		if (ao_lco_armed && ao_lco_firing) { -			ao_lco_ignite(AO_PAD_FIRE); -		} else { -			ao_lco_get_channels(); -			if (ao_lco_armed) { -				PRINTD(DEBUG_STATUS, "Arming pads %x\n", -				       ao_lco_armed); -				if (ao_lco_valid & AO_LCO_VALID_EVER) { -					ao_lco_arm(ao_lco_box, ao_lco_armed, ao_lco_tick_offset); -					ao_delay(AO_MS_TO_TICKS(10)); -				} -			} -		} -		if (ao_lco_armed && ao_lco_firing) -			delay = AO_MS_TO_TICKS(100); -		else { -			delay = AO_SEC_TO_TICKS(1); -		} -		ao_sleep_for(&ao_lco_armed, delay); -	} +	ao_lco_monitor();  }  #if DEBUG @@ -326,7 +138,7 @@ __code struct ao_cmds ao_lco_cmds[] = {  void  ao_lco_init(void)  { -	ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); +	ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");  #if DEBUG  	ao_cmd_register(&ao_lco_cmds[0]);  #endif diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 16b4ae60..c6efc311 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -17,6 +17,7 @@   */  #include <ao.h> +#include <ao_exti.h>  #include <ao_pad.h>  #include <ao_74hc165.h>  #include <ao_radio_cmac.h> @@ -69,10 +70,20 @@ ao_strobe(uint8_t v)  #endif  } +#ifdef AO_PAD_PORT_0 +#define pins_pad(pad)	(*((AO_PAD_ ## pad ## _PORT) == AO_PAD_PORT_0 ? (&pins0) : (&pins1))) +#else +#define pins_pad(pad)	pins0 +#define AO_PAD_PORT_0 AO_PAD_PORT +#endif +  static void  ao_pad_run(void)  { -	AO_PORT_TYPE	pins; +	AO_PORT_TYPE	pins0; +#ifdef AO_PAD_PORT_1 +	AO_PORT_TYPE	pins1; +#endif  	for (;;) {  		while (!ao_pad_ignite) @@ -80,58 +91,116 @@ ao_pad_run(void)  		/*  		 * Actually set the pad bits  		 */ -		pins = 0; +		pins0 = 0; +#ifdef AO_PAD_PORT_1 +		pins1 = 0; +#endif  #if AO_PAD_NUM > 0  		if (ao_pad_ignite & (1 << 0)) -			pins |= (1 << AO_PAD_PIN_0); +			pins_pad(0) |= (1 << AO_PAD_PIN_0);  #endif  #if AO_PAD_NUM > 1  		if (ao_pad_ignite & (1 << 1)) -			pins |= (1 << AO_PAD_PIN_1); +			pins_pad(1) |= (1 << AO_PAD_PIN_1);  #endif  #if AO_PAD_NUM > 2  		if (ao_pad_ignite & (1 << 2)) -			pins |= (1 << AO_PAD_PIN_2); +			pins_pad(2) |= (1 << AO_PAD_PIN_2);  #endif  #if AO_PAD_NUM > 3  		if (ao_pad_ignite & (1 << 3)) -			pins |= (1 << AO_PAD_PIN_3); +			pins_pad(3) |= (1 << AO_PAD_PIN_3); +#endif +#if AO_PAD_NUM > 4 +		if (ao_pad_ignite & (1 << 4)) +			pins_pad(4) |= (1 << AO_PAD_PIN_4); +#endif +#if AO_PAD_NUM > 5 +		if (ao_pad_ignite & (1 << 5)) +			pins_pad(5) |= (1 << AO_PAD_PIN_5); +#endif +#if AO_PAD_NUM > 6 +		if (ao_pad_ignite & (1 << 6)) +			pins_pad(6) |= (1 << AO_PAD_PIN_6); +#endif +#if AO_PAD_NUM > 7 +		if (ao_pad_ignite & (1 << 7)) +			pins_pad(7) |= (1 << AO_PAD_PIN_7); +#endif +#ifdef AO_PAD_PORT_1 +		PRINTD("ignite pins 0x%x 0x%x\n", pins0, pins1); +		ao_gpio_set_bits(AO_PAD_PORT_0, pins0); +		ao_gpio_set_bits(AO_PAD_PORT_1, pins1); +#else +		PRINTD("ignite pins 0x%x\n", pins0); +		ao_gpio_set_bits(AO_PAD_PORT_0, pins0);  #endif -		PRINTD("ignite pins 0x%x\n", pins); -		ao_gpio_set_bits(AO_PAD_PORT, pins);  		while (ao_pad_ignite) {  			ao_pad_ignite = 0;  			ao_delay(AO_PAD_FIRE_TIME);  		} -		ao_gpio_clr_bits(AO_PAD_PORT, pins); -		PRINTD("turn off pins 0x%x\n", pins); +#ifdef AO_PAD_PORT_1 +		ao_gpio_clr_bits(AO_PAD_PORT_0, pins0); +		ao_gpio_clr_bits(AO_PAD_PORT_1, pins1); +		PRINTD("turn off pins 0x%x 0x%x\n", pins0, pins1); +#else +		ao_gpio_set_bits(AO_PAD_PORT_0, pins0); +		PRINTD("turn off pins 0x%x\n", pins0); +#endif  	}  }  #define AO_PAD_ARM_SIREN_INTERVAL	200 -#ifndef AO_PYRO_R_PYRO_SENSE -#define AO_PYRO_R_PYRO_SENSE	100 -#define AO_PYRO_R_SENSE_GND	27 -#define AO_FIRE_R_POWER_FET	100 -#define AO_FIRE_R_FET_SENSE	100 -#define AO_FIRE_R_SENSE_GND	27 -#endif +/* Resistor values needed for various voltage test ratios: + * + *	Net names involved: + * + *	V_BATT		Battery power, after the initial power switch + *	V_PYRO		Pyro power, after the pyro power switch (and initial power switch) + *	PYRO_SENSE	ADC input to sense V_PYRO voltage + *	BATT_SENSE	ADC input to sense V_BATT voltage + *	IGNITER		FET output to pad (the other pad lead hooks to V_PYRO) + *	IGNITER_SENSE	ADC input to sense igniter voltage + * + *	AO_PAD_R_V_BATT_BATT_SENSE	Resistor from battery rail to battery sense input + *	AO_PAD_R_BATT_SENSE_GND		Resistor from battery sense input to ground + * + *	AO_PAD_R_V_BATT_V_PYRO		Resistor from battery rail to pyro rail + *	AO_PAD_R_V_PYRO_PYRO_SENSE	Resistor from pyro rail to pyro sense input + *	AO_PAD_R_PYRO_SENSE_GND		Resistor from pyro sense input to ground + * + *	AO_PAD_R_V_PYRO_IGNITER		Optional resistors from pyro rail to FET igniter output + *	AO_PAD_R_IGNITER_IGNITER_SENSE	Resistors from FET igniter output to igniter sense ADC inputs + *	AO_PAD_R_IGNITER_SENSE_GND	Resistors from igniter sense ADC inputs to ground + */ + +int16_t +ao_pad_decivolt(int16_t adc, int16_t r_plus, int16_t r_minus) +{ +	int32_t	mul = (int32_t) AO_ADC_REFERENCE_DV * (r_plus + r_minus); +	int32_t div = (int32_t) AO_ADC_MAX * r_minus; +	return ((int32_t) adc * mul + mul/2) / div; +}  static void  ao_pad_monitor(void)  {  	uint8_t			c;  	uint8_t			sample; -	__pdata uint8_t		prev = 0, cur = 0; +	__pdata AO_LED_TYPE	prev = 0, cur = 0;  	__pdata uint8_t		beeping = 0;  	__xdata volatile struct ao_data	*packet;  	__pdata uint16_t	arm_beep_time = 0;  	sample = ao_data_head; +	ao_led_set(LEDS_AVAILABLE); +	ao_delay(AO_MS_TO_TICKS(1000)); +	ao_led_set(0);  	for (;;) {  		__pdata int16_t			pyro; +  		ao_arch_critical(  			while (sample == ao_data_head)  				ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); @@ -141,28 +210,18 @@ ao_pad_monitor(void)  		packet = &ao_data_ring[sample];  		sample = ao_data_ring_next(sample); -		pyro = packet->adc.pyro; - -#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \ -					    (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX))) - +		/* Reply battery voltage */ +		query.battery = ao_pad_decivolt(packet->adc.batt, AO_PAD_R_V_BATT_BATT_SENSE, AO_PAD_R_BATT_SENSE_GND); -#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \ -					    (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX))) +		/* Current pyro voltage */ +		pyro = ao_pad_decivolt(packet->adc.pyro, +				       AO_PAD_R_V_PYRO_PYRO_SENSE, +				       AO_PAD_R_PYRO_SENSE_GND); -		/* convert ADC value to voltage in tenths, then add .2 for the diode drop */ -		query.battery = (packet->adc.batt + 96) / 192 + 2;  		cur = 0; -		if (pyro > VOLTS_TO_PYRO(10)) { +		if (pyro > query.battery * 7 / 8) {  			query.arm_status = AO_PAD_ARM_STATUS_ARMED;  			cur |= AO_LED_ARMED; -#if AO_FIRE_R_POWER_FET -		} else if (pyro > VOLTS_TO_PYRO(5)) { -			if ((ao_time() % 100) < 50) -				cur |= AO_LED_ARMED; -			query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN; -			arm_beep_time = 0; -#endif  		} else {  			query.arm_status = AO_PAD_ARM_STATUS_DISARMED;  			arm_beep_time = 0; @@ -175,54 +234,50 @@ ao_pad_monitor(void)  			cur |= AO_LED_GREEN;  		for (c = 0; c < AO_PAD_NUM; c++) { -			int16_t		sense = packet->adc.sense[c]; +			int16_t		sense = ao_pad_decivolt(packet->adc.sense[c], +								AO_PAD_R_IGNITER_IGNITER_SENSE, +								AO_PAD_R_IGNITER_SENSE_GND);  			uint8_t	status = AO_PAD_IGNITER_STATUS_UNKNOWN;  			/* -			 *	pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20 -			 *	v_pyro = pyro * 127 / 27 +			 *	Here's the resistor stack on each +			 *	igniter channel. Note that +			 *	AO_PAD_R_V_PYRO_IGNITER is optional  			 * -			 *		v_pyro \ -			 *	100k		igniter -			 *		output / -			 *	100k           \ -			 *		sense   relay -			 *	27k            / -			 *		gnd --- +			 *					v_pyro \ +			 *	AO_PAD_R_V_PYRO_IGNITER			igniter +			 *					output / +			 *	AO_PAD_R_IGNITER_IGNITER_SENSE         \ +			 *					sense   relay +			 *	AO_PAD_R_IGNITER_SENSE_GND	       / +			 *					gnd ---  			 * -			 *		v_pyro \ -			 *	200k		igniter -			 *		output / -			 *	200k           \ -			 *		sense   relay -			 *	22k            / -			 *		gnd --- -			 * -			 *	If the relay is closed, then sense will be 0 -			 *	If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2 -			 *	If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro  			 */ -#if AO_FIRE_R_POWER_FET +#ifdef AO_PAD_R_V_PYRO_IGNITER  			if (sense <= pyro / 8) { +				/* close to zero → relay is closed */  				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;  				if ((ao_time() % 100) < 50)  					cur |= AO_LED_CONTINUITY(c); -			} else -			if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) -				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; -			else if (pyro / 8 * 7 <= sense) { -				status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; -				cur |= AO_LED_CONTINUITY(c); -			} -#else -			if (sense >= pyro / 8 * 5) { -				status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; -				cur |= AO_LED_CONTINUITY(c); -			} else { -				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;  			} +			else  #endif +			{ +				if (sense >= (pyro * 7) / 8) { + +					/* sense close to pyro voltage; igniter is good +					 */ +					status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; +					cur |= AO_LED_CONTINUITY(c); +				} else { + +					/* relay not shorted (if we can tell), +					 * and igniter not obviously present +					 */ +					status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; +				} +			}  			query.igniter_status[c] = status;  		}  		if (cur != prev) { @@ -284,6 +339,23 @@ ao_pad_read_box(void)  }  #endif +#ifdef AO_PAD_SELECTOR_PORT +static int ao_pad_read_box(void) { +	AO_PORT_TYPE	value = ao_gpio_get_all(AO_PAD_SELECTOR_PORT); +	unsigned	pin; +	int		select = 1; + +	for (pin = 0; pin < sizeof (AO_PORT_TYPE) * 8; pin++) { +		if (AO_PAD_SELECTOR_PINS & (1 << pin)) { +			if ((value & (1 << pin)) == 0) +				return select; +			select++; +		} +	} +	return ao_config.pad_box; +} +#else +  #if HAS_FIXED_PAD_BOX  #define ao_pad_read_box()	ao_config.pad_box  #endif @@ -292,6 +364,8 @@ ao_pad_read_box(void)  #define ao_pad_read_box()	PAD_BOX  #endif +#endif +  static void  ao_pad(void)  { @@ -299,7 +373,6 @@ ao_pad(void)  	int8_t	ret;  	ao_pad_box = 0; -	ao_led_set(0);  	for (;;) {  		FLUSHD();  		while (ao_pad_disabled) @@ -497,20 +570,51 @@ __code struct ao_cmds ao_pad_cmds[] = {  	{ 0, NULL }  }; +#ifndef AO_PAD_PORT_1 +#define AO_PAD_0_PORT	AO_PAD_PORT +#define AO_PAD_1_PORT	AO_PAD_PORT +#define AO_PAD_2_PORT	AO_PAD_PORT +#define AO_PAD_3_PORT	AO_PAD_PORT +#define AO_PAD_4_PORT	AO_PAD_PORT +#define AO_PAD_5_PORT	AO_PAD_PORT +#define AO_PAD_6_PORT	AO_PAD_PORT +#define AO_PAD_7_PORT	AO_PAD_PORT +#endif +  void  ao_pad_init(void)  { +#ifdef AO_PAD_SELECTOR_PORT +	unsigned pin; + +	for (pin = 0; pin < sizeof (AO_PORT_TYPE) * 8; pin++) { +		if (AO_PAD_SELECTOR_PINS & (1 << pin)) +			ao_enable_input(AO_PAD_SELECTOR_PORT, pin, AO_EXTI_MODE_PULL_UP); +	} +#endif  #if AO_PAD_NUM > 0 -	ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0); +	ao_enable_output(AO_PAD_0_PORT, AO_PAD_PIN_0, AO_PAD_0, 0);  #endif  #if AO_PAD_NUM > 1 -	ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0); +	ao_enable_output(AO_PAD_1_PORT, AO_PAD_PIN_1, AO_PAD_1, 0);  #endif  #if AO_PAD_NUM > 2 -	ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0); +	ao_enable_output(AO_PAD_2_PORT, AO_PAD_PIN_2, AO_PAD_2, 0);  #endif  #if AO_PAD_NUM > 3 -	ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); +	ao_enable_output(AO_PAD_3_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); +#endif +#if AO_PAD_NUM > 4 +	ao_enable_output(AO_PAD_4_PORT, AO_PAD_PIN_4, AO_PAD_4, 0); +#endif +#if AO_PAD_NUM > 5 +	ao_enable_output(AO_PAD_5_PORT, AO_PAD_PIN_5, AO_PAD_5, 0); +#endif +#if AO_PAD_NUM > 5 +	ao_enable_output(AO_PAD_6_PORT, AO_PAD_PIN_6, AO_PAD_6, 0); +#endif +#if AO_PAD_NUM > 7 +	ao_enable_output(AO_PAD_7_PORT, AO_PAD_PIN_7, AO_PAD_7, 0);  #endif  #ifdef AO_STROBE  	ao_enable_output(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, 0); diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index deecfb79..250e035f 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -23,6 +23,10 @@  #include <ao_event.h>  __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; +#ifndef AO_QUADRATURE_SINGLE_CODE +static int8_t ao_quadrature_step[AO_QUADRATURE_COUNT]; +#endif +  static uint8_t  ao_quadrature_state[AO_QUADRATURE_COUNT];  struct ao_debounce { @@ -39,20 +43,25 @@ static struct ao_debounce ao_debounce_state[AO_QUADRATURE_COUNT][2];  #define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN  #define isr(q)  ao_quadrature_isr_ ## q -#define DEBOUNCE	10 +#ifndef AO_QUADRATURE_DEBOUNCE +#error must define AO_QUADRATURE_DEBOUNCE +#endif  static uint8_t  ao_debounce(uint8_t cur, struct ao_debounce *debounce)  { -	if (cur == debounce->state) -		debounce->count = 0; -	else { -		if (++debounce->count == DEBOUNCE) { -			debounce->state = cur; -			debounce->count = 0; -		} +#if AO_QUADRATURE_DEBOUNCE > 0 +	if (debounce->count > 0) { +		debounce->count--; +	} else if (cur != debounce->state) { +		debounce->state = cur; +		debounce->count = AO_QUADRATURE_DEBOUNCE;  	}  	return debounce->state; +#else +	(void) debounce; +	return cur; +#endif  }  static uint16_t @@ -70,8 +79,21 @@ ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b, struct a  #define _ao_quadrature_get(q)	ao_quadrature_read(port(q), bita(q), bitb(q), ao_debounce_state[q])  static void -_ao_quadrature_queue(uint8_t q, int8_t step) +_ao_quadrature_step(uint8_t q, int8_t step)  { +#ifndef AO_QUADRATURE_SINGLE_CODE +	ao_quadrature_step[q] += step; +	if (ao_quadrature_state[q] != 0) +		return; +	if (ao_quadrature_step[q] >= 4) { +		ao_quadrature_step[q] = 0; +		step = 1; +	} else if (ao_quadrature_step[q] <= -4) { +		ao_quadrature_step[q] = 0; +		step = -1; +	} else +		return; +#endif  	ao_quadrature_count[q] += step;  #if AO_EVENT  	ao_event_put_isr(AO_EVENT_QUADRATURE, q, step); @@ -79,17 +101,29 @@ _ao_quadrature_queue(uint8_t q, int8_t step)  	ao_wakeup(&ao_quadrature_count[q]);  } +static const struct { +	uint8_t prev, next; +} ao_quadrature_steps[4] = { +	[0] { .prev = 2, .next = 1 }, +	[1] { .prev = 0, .next = 3 }, +	[3] { .prev = 1, .next = 2 }, +	[2] { .prev = 3, .next = 0 }, +}; +  static void -_ao_quadrature_set(uint8_t q, uint8_t new) { -	uint8_t	old = ao_quadrature_state[q]; - -	if (old != new && new == 0) { -		if (old & 2) -			_ao_quadrature_queue(q, 1); -		else if (old & 1) -			_ao_quadrature_queue(q, -1); -	} +_ao_quadrature_set(uint8_t q, uint8_t new) +{ +	uint8_t	old; + +	ao_arch_block_interrupts(); +	old = ao_quadrature_state[q];  	ao_quadrature_state[q] = new; +	ao_arch_release_interrupts(); + +	if (new == ao_quadrature_steps[old].next) +		_ao_quadrature_step(q, 1); +	else if (new == ao_quadrature_steps[old].prev) +		_ao_quadrature_step(q, -1);  }  static void @@ -103,6 +137,14 @@ ao_quadrature_isr(void)  #endif  } +static void +_ao_quadrature_start_one(uint8_t q, uint8_t new) +{ +	ao_arch_block_interrupts(); +	ao_quadrature_state[q] = new; +	ao_arch_release_interrupts(); +} +  int32_t  ao_quadrature_poll(uint8_t q)  { @@ -124,21 +166,32 @@ ao_quadrature_test(void)  	uint8_t	q;  	int32_t	c;  	uint8_t	s; +#ifndef AO_QUADRATURE_SINGLE_CODE +	int8_t t = 0; +#endif  	ao_cmd_decimal();  	q = ao_cmd_lex_i; -	if (q >= AO_QUADRATURE_COUNT) { +	if (q >= AO_QUADRATURE_COUNT)  		ao_cmd_status = ao_cmd_syntax_error; +	if (ao_cmd_status != ao_cmd_success)  		return; -	}  	c = -10000;  	s = 0;  	while (ao_quadrature_count[q] != 10) {  		if (ao_quadrature_count[q] != c || -		    ao_quadrature_state[q] != s) { +#ifndef AO_QUADRATURE_SINGLE_CODE +		    ao_quadrature_step[q] != t || +#endif +		    ao_quadrature_state[q] != s) +		{  			c = ao_quadrature_count[q];  			s = ao_quadrature_state[q]; +#ifndef AO_QUADRATURE_SINGLE_CODE +			t = ao_quadrature_step[q]; +			printf("step %3d ", t); +#endif  			printf ("count %3d state %2x\n", c, s);  			flush();  		} @@ -160,9 +213,10 @@ static const struct ao_cmds ao_quadrature_cmds[] = {  	{ 0, NULL }  }; -#define init(q) do {					\ -		ao_enable_input(port(q), bita(q), 0);	\ -		ao_enable_input(port(q), bitb(q), 0);	\ +#define init(q) do {							\ +		ao_enable_input(port(q), bita(q), 0);			\ +		ao_enable_input(port(q), bitb(q), 0);			\ +		_ao_quadrature_start_one(q, _ao_quadrature_get(q));	\  	} while (0)  void diff --git a/src/fox1ihu/.gitignore b/src/fox1ihu/.gitignore new file mode 100644 index 00000000..538cf8b2 --- /dev/null +++ b/src/fox1ihu/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +fox1ihu-*.elf diff --git a/src/fox1ihu/Makefile b/src/fox1ihu/Makefile new file mode 100644 index 00000000..e3226a24 --- /dev/null +++ b/src/fox1ihu/Makefile @@ -0,0 +1,89 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_watchdog.h \ +	ao_storage.h \ +	ao_task.h \ +	stm32l.h \ +	ao_sdcard.h \ +	ao_bufio.h \ +	ao_fat.h \ +	Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +#	ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_adc_stm.c \ +	ao_data.c \ +	ao_storage.c \ +	ao_mr25.c \ +	ao_sdcard.c \ +	ao_bufio.c \ +	ao_fat.c \ +	ao_watchdog.c + +PRODUCT=Fox1IHU-v2 +PRODUCT_DEF=-DFOX +IDPRODUCT=0x0024 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=fox1ihu-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_fox1ihu.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(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 $(PROGNAME)-*.elf +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/fox1ihu/ao_fox1ihu.c b/src/fox1ihu/ao_fox1ihu.c new file mode 100644 index 00000000..2e1a2fdf --- /dev/null +++ b/src/fox1ihu/ao_fox1ihu.c @@ -0,0 +1,56 @@ +/* + * 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_exti.h> +#include <ao_watchdog.h> +#include <ao_storage.h> +#include <ao_fat.h> + +int +main(void) +{ +	ao_clock_init(); +	 +#if HAS_STACK_GUARD +	ao_mpu_init(); +#endif + +	ao_task_init(); +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_RED|AO_LED_GREEN|AO_LED_RED_2|AO_LED_GREEN_2); +	ao_timer_init(); + +	ao_spi_init(); +	ao_dma_init(); +	ao_exti_init(); + +	ao_adc_init(); + +	ao_cmd_init(); + +	ao_usb_init(); + +	ao_storage_init(); + +	ao_watchdog_init(); + +	ao_fat_init(); + +	ao_start_scheduler(); +	return 0; +} diff --git a/src/fox1ihu/ao_pins.h b/src/fox1ihu/ao_pins.h new file mode 100644 index 00000000..b5dd7283 --- /dev/null +++ b/src/fox1ihu/ao_pins.h @@ -0,0 +1,317 @@ +/* + * 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 HAS_TASK_QUEUE		1 + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1		1 +#define USE_SERIAL_1_STDIN	0 +#define SERIAL_1_PB6_PB7	0 +#define SERIAL_1_PA9_PA10	1 + +#define HAS_SERIAL_2		0 +#define USE_SERIAL_2_STDIN	0 +#define SERIAL_2_PA2_PA3	0 +#define SERIAL_2_PD5_PD6	0 + +#define HAS_SERIAL_3		0 +#define USE_SERIAL_3_STDIN	0 +#define SERIAL_3_PB10_PB11	0 +#define SERIAL_3_PC10_PC11	1 +#define SERIAL_3_PD8_PD9	0 + +#define HAS_EEPROM		0 +#define USE_INTERNAL_FLASH	0 +#define HAS_USB			1 +#define HAS_BEEP		0 +#define HAS_RADIO		0 +#define HAS_TELEMETRY		0 + +#define HAS_SPI_1		1 +#define SPI_1_PA5_PA6_PA7	0 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	1	/* */ +#define SPI_1_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_SPI_2		1 +#define SPI_2_PB13_PB14_PB15	1	/* */ +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz +#define HAS_STORAGE_DEBUG	1 + +#define SPI_2_PORT		(&stm_gpiob) +#define SPI_2_SCK_PIN		13 +#define SPI_2_MISO_PIN		14 +#define SPI_2_MOSI_PIN		15 + +#define HAS_I2C_1		1 +#define I2C_1_PB6_PB7		1 +#define I2C_1_PB8_PB9		0 + +#define HAS_I2C_2		1 +#define I2C_2_PB10_PB11		1 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define LOW_LEVEL_DEBUG		0 + +#define LED_PORT_0_ENABLE	STM_RCC_AHBENR_GPIOCEN +#define LED_PORT_0		(&stm_gpioc) +#define LED_PORT_0_MASK		(0xff) +#define LED_PORT_0_SHIFT	0 +#define LED_PIN_RED		6 +#define LED_PIN_GREEN		7 +#define LED_PIN_RED_2		8 +#define LED_PIN_GREEN_2		9 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) +#define AO_LED_RED_2		(1 << LED_PIN_RED_2) +#define AO_LED_GREEN_2		(1 << LED_PIN_GREEN_2) + +#define LEDS_AVAILABLE		(AO_LED_RED | AO_LED_GREEN | AO_LED_RED_2 | AO_LED_GREEN_2) + +#define HAS_GPS			0 +#define HAS_FLIGHT		0 +#define HAS_ADC			1 +#define HAS_ADC_TEMP		1 +#define HAS_LOG			0 + +/* + * ADC + */ +#define AO_DATA_RING		32 + +struct ao_adc { +	int16_t			tx_pa_current;	/* 0 ADC_IN0 */ +	int16_t			tx_temp;	/* 1 ADC_IN1 */ +	int16_t			exp4_temp;	/* 2 ADC_IN2 */ +	int16_t			rx_temp;	/* 3 ADC_IN3 */ +	int16_t			tx_analog_1;	/* 4 ADC_IN4 */ +	int16_t			sense_batt;	/* 5 ADC_IN5 */ +	int16_t			rx_analog_1;	/* 6 ADC_IN6 */ +	int16_t			rx_rssi;	/* 7 ADC_IN8 */ +	int16_t			rx_cd;		/* 8 ADC_IN9 */ +	int16_t			ant_sense_1;	/* 9 ADC_IN10 */ +	int16_t			ant_sense_2;	/* 10 ADC_IN11 */ +	int16_t			gyro_x_1;	/* 11 ADC_IN12 */ +	int16_t			gyro_z_1;	/* 12 ADC_IN13 */ +	int16_t			gyro_vref_1;	/* 13 ADC_IN24 */ +	int16_t			gyro_x_2;	/* 14 ADC_IN14 */ +	int16_t			gyro_z_2;	/* 15 ADC_IN15 */ +	int16_t			gyro_vref_2;	/* 16 ADC_IN25 */ +}; + +#define AO_ADC_TX_PA_CURRENT		0 +#define AO_ADC_TX_PA_CURRENT_PORT	(&stm_gpioa) +#define AO_ADC_TX_PA_CURRENT_PIN	0 + +#define AO_ADC_TX_TEMP			1 +#define AO_ADC_TX_TEMP_PORT		(&stm_gpioa) +#define AO_ADC_TX_TEMP_PIN		1 + +#define AO_ADC_EXP4_TEMP		2 +#define AO_ADC_EXP4_TEMP_PORT		(&stm_gpioa) +#define AO_ADC_EXP4_TEMP_PIN		2 + +#define AO_ADC_RX_TEMP			3 +#define AO_ADC_RX_TEMP_PORT		(&stm_gpioa) +#define AO_ADC_RX_TEMP_PIN		3 + +#define AO_ADC_TX_ANALOG_1		4 +#define AO_ADC_TX_ANALOG_1_PORT		(&stm_gpioa) +#define AO_ADC_TX_ANALOG_1_PIN		4 + +#define AO_ADC_SENSE_BATT		5 +#define AO_ADC_SENSE_BATT_PORT		(&stm_gpioa) +#define AO_ADC_SENSE_BATT_PIN		5 + +#define AO_ADC_RX_ANALOG_1		6 +#define AO_ADC_RX_ANALOG_1_PORT		(&stm_gpioa) +#define AO_ADC_RX_ANALOG_1_PIN		6 + +#define AO_ADC_RX_RSSI			8 +#define AO_ADC_RX_RSSI_PORT		(&stm_gpiob) +#define AO_ADC_RX_RSSI_PIN		0 + +#define AO_ADC_RX_CD			9 +#define AO_ADC_RX_CD_PORT		(&stm_gpiob) +#define AO_ADC_RX_CD_PIN		1 + +#define AO_ADC_ANT_SENSE_1		10 +#define AO_ADC_ANT_SENSE_1_PORT		(&stm_gpioc) +#define AO_ADC_ANT_SENSE_1_PIN		0 + +#define AO_ADC_ANT_SENSE_2		11 +#define AO_ADC_ANT_SENSE_2_PORT		(&stm_gpioc) +#define AO_ADC_ANT_SENSE_2_PIN		1 + +#define AO_ADC_GYRO_X_1			12 +#define AO_ADC_GYRO_X_1_PORT		(&stm_gpioc) +#define AO_ADC_GYRO_X_1_PIN		2 + +#define AO_ADC_GYRO_Z_1			13 +#define AO_ADC_GYRO_Z_1_PORT		(&stm_gpioc) +#define AO_ADC_GYRO_Z_1_PIN		3 + +#define AO_ADC_GYRO_VREF_1		24 +#define AO_ADC_GYRO_VREF_1_PORT		(&stm_gpioe) +#define AO_ADC_GYRO_VREF_1_PIN		9 + +#define AO_ADC_GYRO_X_2			14 +#define AO_ADC_GYRO_X_2_PORT		(&stm_gpioc) +#define AO_ADC_GYRO_X_2_PIN		4 + +#define AO_ADC_GYRO_Z_2			15 +#define AO_ADC_GYRO_Z_2_PORT		(&stm_gpioc) +#define AO_ADC_GYRO_Z_2_PIN		5 + +#define AO_ADC_GYRO_VREF_2		25 +#define AO_ADC_GYRO_VREF_2_PORT		(&stm_gpioe) +#define AO_ADC_GYRO_VREF_2_PIN		10 + +#define AO_ADC_TEMP			16 + +#define AO_ADC_RCC_AHBENR	((1 << STM_RCC_AHBENR_GPIOAEN) | \ +				 (1 << STM_RCC_AHBENR_GPIOBEN) | \ +				 (1 << STM_RCC_AHBENR_GPIOCEN) | \ +				 (1 << STM_RCC_AHBENR_GPIOEEN)) + +#define AO_NUM_ADC_PIN		(17) + +#define AO_ADC_PIN0_PORT	AO_ADC_TX_PA_CURRENT_PORT +#define AO_ADC_PIN0_PIN		AO_ADC_TX_PA_CURRENT_PIN +#define AO_ADC_PIN1_PORT	AO_ADC_TX_TEMP_PORT +#define AO_ADC_PIN1_PIN		AO_ADC_TX_TEMP_PIN +#define AO_ADC_PIN2_PORT	AO_ADC_EXP4_TEMP_PORT +#define AO_ADC_PIN2_PIN		AO_ADC_EXP4_TEMP_PIN +#define AO_ADC_PIN3_PORT	AO_ADC_RX_TEMP_PORT +#define AO_ADC_PIN3_PIN		AO_ADC_RX_TEMP_PIN +#define AO_ADC_PIN4_PORT	AO_ADC_TX_ANALOG_1_PORT +#define AO_ADC_PIN4_PIN		AO_ADC_TX_ANALOG_1_PIN +#define AO_ADC_PIN5_PORT	AO_ADC_SENSE_BATT_PORT +#define AO_ADC_PIN5_PIN		AO_ADC_SENSE_BATT_PIN +#define AO_ADC_PIN6_PORT	AO_ADC_RX_ANALOG_1_PORT +#define AO_ADC_PIN6_PIN		AO_ADC_RX_ANALOG_1_PIN +#define AO_ADC_PIN7_PORT	AO_ADC_RX_RSSI_PORT +#define AO_ADC_PIN7_PIN		AO_ADC_RX_RSSI_PIN +#define AO_ADC_PIN8_PORT	AO_ADC_RX_CD_PORT +#define AO_ADC_PIN8_PIN		AO_ADC_RX_CD_PIN +#define AO_ADC_PIN9_PORT	AO_ADC_ANT_SENSE_1_PORT +#define AO_ADC_PIN9_PIN		AO_ADC_ANT_SENSE_1_PIN +#define AO_ADC_PIN10_PORT	AO_ADC_ANT_SENSE_2_PORT +#define AO_ADC_PIN10_PIN	AO_ADC_ANT_SENSE_2_PIN +#define AO_ADC_PIN11_PORT	AO_ADC_GYRO_X_1_PORT +#define AO_ADC_PIN11_PIN	AO_ADC_GYRO_X_1_PIN +#define AO_ADC_PIN12_PORT	AO_ADC_GYRO_Z_1_PORT +#define AO_ADC_PIN12_PIN	AO_ADC_GYRO_Z_1_PIN +#define AO_ADC_PIN13_PORT	AO_ADC_GYRO_VREF_1_PORT +#define AO_ADC_PIN13_PIN	AO_ADC_GYRO_VREF_1_PIN +#define AO_ADC_PIN14_PORT	AO_ADC_GYRO_X_2_PORT +#define AO_ADC_PIN14_PIN	AO_ADC_GYRO_X_2_PIN +#define AO_ADC_PIN15_PORT	AO_ADC_GYRO_Z_2_PORT +#define AO_ADC_PIN15_PIN	AO_ADC_GYRO_Z_2_PIN +#define AO_ADC_PIN16_PORT	AO_ADC_GYRO_VREF_2_PORT +#define AO_ADC_PIN16_PIN	AO_ADC_GYRO_VREF_2_PIN + +#define AO_NUM_ADC	       	(AO_NUM_ADC_PIN + 1)	/* Add internal temp sensor */ + +#define AO_ADC_SQ1		AO_ADC_TX_PA_CURRENT +#define AO_ADC_SQ1_NAME		"tx_pa_current" +#define AO_ADC_SQ2		AO_ADC_TX_TEMP +#define AO_ADC_SQ2_NAME		"tx_temp" +#define AO_ADC_SQ3		AO_ADC_EXP4_TEMP +#define AO_ADC_SQ3_NAME		"expr_temp" +#define AO_ADC_SQ4		AO_ADC_RX_TEMP +#define AO_ADC_SQ4_NAME		"rx_temp" +#define AO_ADC_SQ5		AO_ADC_TX_ANALOG_1 +#define AO_ADC_SQ5_NAME		"tx_analog_1" +#define AO_ADC_SQ6		AO_ADC_SENSE_BATT +#define AO_ADC_SQ6_NAME		"sense_batt" +#define AO_ADC_SQ7		AO_ADC_RX_ANALOG_1 +#define AO_ADC_SQ7_NAME		"rx_analog_1" +#define AO_ADC_SQ8		AO_ADC_RX_RSSI +#define AO_ADC_SQ8_NAME		"rx_rssi" +#define AO_ADC_SQ9		AO_ADC_RX_CD +#define AO_ADC_SQ9_NAME		"rx_cd" +#define AO_ADC_SQ10		AO_ADC_ANT_SENSE_1 +#define AO_ADC_SQ10_NAME	"ant_sense_1" +#define AO_ADC_SQ11		AO_ADC_ANT_SENSE_2 +#define AO_ADC_SQ11_NAME	"ant_sense_2" +#define AO_ADC_SQ12		AO_ADC_GYRO_X_1 +#define AO_ADC_SQ12_NAME	"gyro_x_1" +#define AO_ADC_SQ13		AO_ADC_GYRO_Z_1 +#define AO_ADC_SQ13_NAME	"gyro_z_1" +#define AO_ADC_SQ14		AO_ADC_GYRO_VREF_1 +#define AO_ADC_SQ14_NAME	"gyro_vref_1" +#define AO_ADC_SQ15		AO_ADC_GYRO_X_2 +#define AO_ADC_SQ15_NAME	"gyro_x_2" +#define AO_ADC_SQ16		AO_ADC_GYRO_Z_2 +#define AO_ADC_SQ16_NAME	"gyro_z_2" +#define AO_ADC_SQ17		AO_ADC_GYRO_VREF_2 +#define AO_ADC_SQ17_NAME	"gyro_vref_2" +#define AO_ADC_SQ18		AO_ADC_TEMP +#define AO_ADC_SQ18_NAME	"temp" + +/* Watchdog timer */ + +#define AO_WATCHDOG_INTERVAL	AO_MS_TO_TICKS(40) +#define AO_WATCHDOG_PORT	(&stm_gpiod) +#define AO_WATCHDOG_BIT		3 + +/* MRAM device */ + +#define AO_MR25_SPI_CS_PORT	(&stm_gpiod) +#define AO_MR25_SPI_CS_PIN	0 +#define AO_MR25_SPI_BUS		AO_SPI_2_PB13_PB14_PB15 + +/* SD card */ + +#define AO_SDCARD_SPI_CS_PORT	(&stm_gpiod) +#define AO_SDCARD_SPI_CS_PIN	1 +#define AO_SDCARD_SPI_BUS	AO_SPI_2_PB13_PB14_PB15 +#define AO_SDCARD_SPI_PORT	(&stm_gpiob) +#define AO_SDCARD_SPI_SCK_PIN	13 +#define AO_SDCARD_SPI_MISO_PIN	14 +#define AO_SDCARD_SPI_MOSI_PIN	15 + +#endif /* _AO_PINS_H_ */ diff --git a/src/fox1ihu/flash-loader/Makefile b/src/fox1ihu/flash-loader/Makefile new file mode 100644 index 00000000..454bc6fb --- /dev/null +++ b/src/fox1ihu/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=fox1ihu +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/fox1ihu/flash-loader/ao_pins.h b/src/fox1ihu/flash-loader/ao_pins.h new file mode 100644 index 00000000..19f29b08 --- /dev/null +++ b/src/fox1ihu/flash-loader/ao_pins.h @@ -0,0 +1,59 @@ +/* + * 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_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#define AO_WATCHDOG_PORT	(&stm_gpiod) +#define AO_WATCHDOG_PORT_BIT	(1 << STM_RCC_AHBENR_GPIODEN) +#define AO_WATCHDOG_BIT		3 +#define AO_WATCHDOG_VALUE	0 + +#define AO_RADIO_CONTROL_PORT		(&stm_gpioe) +#define AO_RADIO_CONTROL_PORT_BIT	(1 << STM_RCC_AHBENR_GPIOEEN) +#define AO_RADIO_CONTROL_BIT		12 +#define AO_RADIO_CONTROL_VALUE		1 + +#define AO_FLASH_LOADER_INIT do {					\ +		stm_rcc.ahbenr |= AO_WATCHDOG_PORT_BIT | AO_RADIO_CONTROL_PORT_BIT; \ +									\ +		stm_gpio_set(AO_WATCHDOG_PORT, AO_WATCHDOG_BIT, AO_WATCHDOG_VALUE); \ +		stm_moder_set(AO_WATCHDOG_PORT, AO_WATCHDOG_BIT, STM_MODER_OUTPUT); \ +									\ +		stm_gpio_set(AO_RADIO_CONTROL_PORT, AO_RADIO_CONTROL_BIT, AO_RADIO_CONTROL_VALUE); \ +		stm_moder_set(AO_RADIO_CONTROL_PORT, AO_RADIO_CONTROL_BIT, STM_MODER_OUTPUT); \ +	} while (0) + +#define AO_TIMER_HOOK	do {						\ +		AO_WATCHDOG_PORT->odr ^= (1 << AO_WATCHDOG_BIT);	\ +	} while (0) + +#define HAS_TICK		1 +#include <ao_flash_stm_pins.h> + +/* Attached signal, PB8 */ + +#define AO_BOOT_PIN		1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiob +#define AO_BOOT_APPLICATION_PIN		8 +#define AO_BOOT_APPLICATION_VALUE	0 +#define AO_BOOT_APPLICATION_MODE	0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/kernel/ao_flash_readout.c b/src/kernel/ao_flash_readout.c new file mode 100644 index 00000000..46b5ba7a --- /dev/null +++ b/src/kernel/ao_flash_readout.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2018 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +#include <ao.h> +#include <ao_usb.h> +#include <ao_flash_readout.h> + +#ifndef AO_FLASH_READOUT_BASE +#define AO_FLASH_READOUT_BASE	AO_BOOT_LOADER_BASE +#define AO_FLASH_READOUT_BOUND	AO_BOOT_APPLICATION_BOUND +#endif + +static void +ao_flash_readout(void) +{ +	uint8_t	*base = (uint8_t *) AO_FLASH_READOUT_BASE; +	uint8_t	*bound = (uint8_t *) AO_FLASH_READOUT_BOUND; +	uint8_t	*p = base; + +	for (;;) { +		ao_arch_block_interrupts(); +		while (!ao_usb_running) { +			p = base; +			ao_sleep(&ao_usb_running); +		} +		ao_arch_release_interrupts(); +		ao_flash_readout_putchar(*p++); +		if (p == bound) +			p = base; +	} +} + +static struct ao_task	ao_flash_readout_task; + +void +ao_flash_readout_init(void) +{ +	ao_add_task(&ao_flash_readout_task, ao_flash_readout, "flash_readout"); +} diff --git a/src/kernel/ao_flash_readout.h b/src/kernel/ao_flash_readout.h new file mode 100644 index 00000000..5eee53cc --- /dev/null +++ b/src/kernel/ao_flash_readout.h @@ -0,0 +1,20 @@ +/* + * Copyright © 2018 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +#ifndef _AO_FLASH_READOUT_H_ +#define _AO_FLASH_READOUT_H_ + +void	ao_flash_readout_init(void); + +#endif /* _AO_FLASH_READOUT_H_ */ diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index cb02c454..c2700d20 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -48,7 +48,8 @@  /* Main flight thread. */  __pdata enum ao_flight_state	ao_flight_state;	/* current flight state */ -__pdata uint16_t		ao_boost_tick;		/* time of launch detect */ +__pdata uint16_t		ao_boost_tick;		/* time of most recent boost detect */ +__pdata uint16_t		ao_launch_tick;		/* time of first boost detect */  __pdata uint16_t		ao_motor_number;	/* number of motors burned so far */  #if HAS_SENSOR_ERRORS @@ -199,7 +200,7 @@ ao_flight(void)  				)  			{  				ao_flight_state = ao_flight_boost; -				ao_boost_tick = ao_sample_tick; +				ao_launch_tick = ao_boost_tick = ao_sample_tick;  				/* start logging data */  				ao_log_start(); @@ -233,7 +234,7 @@ ao_flight(void)  			 * deceleration, or by waiting until the maximum burn duration  			 * (15 seconds) has past.  			 */ -			if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || +			if ((ao_accel < AO_MSS_TO_ACCEL(-2.5)) ||  			    (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX)  			{  #if HAS_ACCEL @@ -269,7 +270,7 @@ ao_flight(void)  			 * number of seconds.  			 */  			if (ao_config.apogee_lockout) { -				if ((int16_t) (ao_sample_tick - ao_boost_tick) < +				if ((int16_t) (ao_sample_tick - ao_launch_tick) <  				    AO_SEC_TO_TICKS(ao_config.apogee_lockout))  					break;  			} @@ -310,7 +311,7 @@ ao_flight(void)  #if HAS_ACCEL  			else {  			check_re_boost: -				ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); +				ao_coast_avg_accel = ao_coast_avg_accel + ((ao_accel - ao_coast_avg_accel) >> 5);  				if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) {  					ao_boost_tick = ao_sample_tick;  					ao_flight_state = ao_flight_boost; diff --git a/src/kernel/ao_flight.h b/src/kernel/ao_flight.h index 6894fe59..005c7e84 100644 --- a/src/kernel/ao_flight.h +++ b/src/kernel/ao_flight.h @@ -40,6 +40,7 @@ enum ao_flight_state {  extern __pdata enum ao_flight_state	ao_flight_state;  extern __pdata uint16_t			ao_boost_tick; +extern __pdata uint16_t			ao_launch_tick;  extern __pdata uint16_t			ao_motor_number;  #if HAS_IMU || HAS_MMA655X diff --git a/src/kernel/ao_kalman.c b/src/kernel/ao_kalman.c index ac41085d..e4cc6d4b 100644 --- a/src/kernel/ao_kalman.c +++ b/src/kernel/ao_kalman.c @@ -45,7 +45,11 @@ static __pdata ao_k_t		ao_avg_height_scaled;  __xdata ao_v_t			ao_avg_height;  __pdata ao_v_t			ao_error_h; -#if !HAS_ACCEL +#if !HAS_ACCEL || AO_FLIGHT_TEST +#define AO_ERROR_H_SQ_AVG	1 +#endif + +#if AO_ERROR_H_SQ_AVG  __pdata ao_v_t			ao_error_h_sq_avg;  #endif @@ -85,7 +89,7 @@ ao_kalman_predict(void)  static void  ao_kalman_err_height(void)  { -#if !HAS_ACCEL +#if AO_ERROR_H_SQ_AVG  	ao_v_t	e;  #endif  	ao_v_t height_distrust; @@ -95,7 +99,7 @@ ao_kalman_err_height(void)  	ao_error_h = ao_sample_height - (ao_v_t) (ao_k_height >> 16); -#if !HAS_ACCEL +#if AO_ERROR_H_SQ_AVG  	e = ao_error_h;  	if (e < 0)  		e = -e; diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c index c4df9f26..4c2d83ef 100644 --- a/src/kernel/ao_product.c +++ b/src/kernel/ao_product.c @@ -55,7 +55,7 @@ const char ao_product[] = AO_iProduct_STRING;  #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 DATA_LEN		(9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2 + 7 * AO_USB_HAS_IN3)  #define TOTAL_LENGTH		(HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)  #define NUM_INTERFACES		(AO_USB_HAS_INT + 1) @@ -141,7 +141,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  	AO_USB_DESC_INTERFACE,  	AO_USB_HAS_INT,			/* bInterfaceNumber */  	0x00,				/* bAlternateSetting */ -	AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2,	/* bNumEndPoints */ +	AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2 + AO_USB_HAS_IN3,	/* bNumEndPoints */  	AO_USB_INTERFACE_CLASS_DATA,	/* bInterfaceClass = data */  	0x00,				/* bInterfaceSubClass */  	0x00,				/* bInterfaceProtocol */ @@ -177,6 +177,16 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  	0x00,			/* bInterval */  #endif +#if AO_USB_HAS_IN3 +	/* Data EP in 3 */ +	0x07, +	AO_USB_DESC_ENDPOINT, +	AO_USB_IN3_EP|0x80,	/* bEndpointAddress */ +	0x02,			/* bmAttributes = bulk */ +	LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ +	0x00,			/* bInterval */ +#endif +  	/* String descriptors */  	0x04,  	AO_USB_DESC_STRING, diff --git a/src/kernel/ao_pyro.c b/src/kernel/ao_pyro.c index e5c30eec..527112ac 100644 --- a/src/kernel/ao_pyro.c +++ b/src/kernel/ao_pyro.c @@ -81,6 +81,19 @@ int pyro_dbg;  #define DBG(...)  #endif +static angle_t +ao_sample_max_orient(void) +{ +	uint8_t	i; +	angle_t	max = ao_sample_orients[0]; + +	for (i = 1; i < AO_NUM_ORIENT; i++) { +		angle_t a = ao_sample_orients[i]; +		if (a > max) +			max = a; +	} +	return max; +}  /*   * Given a pyro structure, figure out   * if the current flight state satisfies all @@ -90,6 +103,9 @@ static uint8_t  ao_pyro_ready(struct ao_pyro *pyro)  {  	enum ao_pyro_flag flag, flags; +#if HAS_GYRO +	angle_t max_orient; +#endif  	flags = pyro->flags;  	while (flags != ao_pyro_none) { @@ -130,26 +146,28 @@ ao_pyro_ready(struct ao_pyro *pyro)  #if HAS_GYRO  		case ao_pyro_orient_less: -			if (ao_sample_orient <= pyro->orient_less) +			max_orient = ao_sample_max_orient(); +			if (max_orient <= pyro->orient_less)  				continue; -			DBG("orient %d > %d\n", ao_sample_orient, pyro->orient_less); +			DBG("orient %d > %d\n", max_orient, pyro->orient_less);  			break;  		case ao_pyro_orient_greater: -			if (ao_sample_orient >= pyro->orient_greater) +			max_orient = ao_sample_max_orient(); +			if (max_orient >= pyro->orient_greater)  				continue; -			DBG("orient %d < %d\n", ao_sample_orient, pyro->orient_greater); +			DBG("orient %d < %d\n", max_orient, pyro->orient_greater);  			break;  #endif  		case ao_pyro_time_less: -			if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less) +			if ((int16_t) (ao_time() - ao_launch_tick) <= pyro->time_less)  				continue; -			DBG("time %d > %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_less); +			DBG("time %d > %d\n", (int16_t)(ao_time() - ao_launch_tick), pyro->time_less);  			break;  		case ao_pyro_time_greater: -			if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater) +			if ((int16_t) (ao_time() - ao_launch_tick) >= pyro->time_greater)  				continue; -			DBG("time %d < %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_greater); +			DBG("time %d < %d\n", (int16_t)(ao_time() - ao_launch_tick), pyro->time_greater);  			break;  		case ao_pyro_ascending: @@ -164,7 +182,7 @@ ao_pyro_ready(struct ao_pyro *pyro)  			break;  		case ao_pyro_after_motor: -			if (ao_motor_number == pyro->motor) +			if (ao_motor_number >= pyro->motor)  				continue;  			DBG("motor %d != %d\n", ao_motor_number, pyro->motor);  			break; diff --git a/src/kernel/ao_sample.c b/src/kernel/ao_sample.c index 61519478..f8012e34 100644 --- a/src/kernel/ao_sample.c +++ b/src/kernel/ao_sample.c @@ -50,6 +50,8 @@ __pdata gyro_t		ao_sample_roll;  __pdata gyro_t		ao_sample_pitch;  __pdata gyro_t		ao_sample_yaw;  __pdata angle_t		ao_sample_orient; +__pdata angle_t		ao_sample_orients[AO_NUM_ORIENT]; +__pdata uint8_t		ao_sample_orient_pos;  #endif  __data uint8_t		ao_sample_data; @@ -115,6 +117,53 @@ ao_sample_preflight_add(void)  	++nsamples;  } +#if HAS_GYRO +static void +ao_sample_set_all_orients(void) +{ +	int i; +	for (i = 0; i < AO_NUM_ORIENT; i++) +		ao_sample_orients[i] = ao_sample_orient; +	ao_sample_orient_pos = 0; +} + +static void +ao_sample_set_one_orient(void) +{ +	ao_sample_orients[ao_sample_orient_pos] = ao_sample_orient; +	ao_sample_orient_pos = (ao_sample_orient_pos + 1) % AO_NUM_ORIENT; +} + +static void +ao_sample_compute_orient(void) +{ +	/* Compute pitch angle from vertical by taking the pad +	 * orientation vector and rotating it by the current total +	 * rotation value. That will be a unit vector pointing along +	 * the airframe axis. The Z value will be the cosine of the +	 * change in the angle from vertical since boost. +	 * +	 * rot = ao_rotation * vertical * ao_rotation° +	 * rot = ao_rotation * (0,0,0,1) * ao_rotation° +	 *     = ((a.z, a.y, -a.x, a.r) * (a.r, -a.x, -a.y, -a.z)) .z +	 * +	 *     = (-a.z * -a.z) + (a.y * -a.y) - (-a.x * -a.x) + (a.r * a.r) +	 *     = a.z² - a.y² - a.x² + a.r² +	 * +	 * rot = ao_rotation * (0, 0, 0, -1) * ao_rotation° +	 *     = ((-a.z, -a.y, a.x, -a.r) * (a.r, -a.x, -a.y, -a.z)) .z +	 * +	 *     = (a.z * -a.z) + (-a.y * -a.y) - (a.x * -a.x) + (-a.r * a.r) +	 *     = -a.z² + a.y² + a.x² - a.r² +	 */ + +	float rotz; +	rotz = ao_rotation.z * ao_rotation.z - ao_rotation.y * ao_rotation.y - ao_rotation.x * ao_rotation.x + ao_rotation.r * ao_rotation.r; + +	ao_sample_orient = acosf(rotz) * (float) (180.0/M_PI); +} +#endif /* HAS_GYRO */ +  static void  ao_sample_preflight_set(void)  { @@ -138,7 +187,7 @@ ao_sample_preflight_set(void)  	ao_sample_pitch_sum = 0;  	ao_sample_yaw_sum = 0;  	ao_sample_roll_sum = 0; -	ao_sample_orient = 0; +	ao_sample_set_all_orients();  	struct ao_quaternion	orient; @@ -168,6 +217,9 @@ ao_sample_preflight_set(void)  	if (ao_orient_test)  		printf("\n\treset\n");  #endif	 + +	ao_sample_compute_orient(); +	ao_sample_set_all_orients();  #endif  	nsamples = 0;  } @@ -195,31 +247,6 @@ ao_sample_rotate(void)  	/* And normalize to make sure it remains a unit vector */  	ao_quaternion_normalize(&ao_rotation, &ao_rotation); -	/* Compute pitch angle from vertical by taking the pad -	 * orientation vector and rotating it by the current total -	 * rotation value. That will be a unit vector pointing along -	 * the airframe axis. The Z value will be the cosine of the -	 * change in the angle from vertical since boost. -	 * -	 * rot = ao_rotation * vertical * ao_rotation° -	 * rot = ao_rotation * (0,0,0,1) * ao_rotation° -	 *     = ((a.z, a.y, -a.x, a.r) * (a.r, -a.x, -a.y, -a.z)) .z -	 * -	 *     = (-a.z * -a.z) + (a.y * -a.y) - (-a.x * -a.x) + (a.r * a.r) -	 *     = a.z² - a.y² - a.x² + a.r² -	 * -	 * rot = ao_rotation * (0, 0, 0, -1) * ao_rotation° -	 *     = ((-a.z, -a.y, a.x, -a.r) * (a.r, -a.x, -a.y, -a.z)) .z -	 * -	 *     = (a.z * -a.z) + (-a.y * -a.y) - (a.x * -a.x) + (-a.r * a.r) -	 *     = -a.z² + a.y² + a.x² - a.r² -	 */ - -	float rotz; -	rotz = ao_rotation.z * ao_rotation.z - ao_rotation.y * ao_rotation.y - ao_rotation.x * ao_rotation.x + ao_rotation.r * ao_rotation.r; - -	ao_sample_orient = acosf(rotz) * (float) (180.0/M_PI); -  #if HAS_FLIGHT_DEBUG  	if (ao_orient_test) {  		printf ("rot %d %d %d orient %d     \r", @@ -229,7 +256,8 @@ ao_sample_rotate(void)  			ao_sample_orient);  	}  #endif - +	ao_sample_compute_orient(); +	ao_sample_set_one_orient();  }  #endif @@ -367,6 +395,7 @@ ao_sample_init(void)  	ao_sample_yaw = 0;  	ao_sample_roll = 0;  	ao_sample_orient = 0; +	ao_sample_set_all_orients();  #endif  	ao_sample_data = ao_data_head;  	ao_preflight = TRUE; diff --git a/src/kernel/ao_sample.h b/src/kernel/ao_sample.h index fbef031d..5ae389be 100644 --- a/src/kernel/ao_sample.h +++ b/src/kernel/ao_sample.h @@ -146,7 +146,10 @@ extern __pdata accel_t	ao_sample_accel_through;  extern __pdata gyro_t	ao_sample_roll;  extern __pdata gyro_t	ao_sample_pitch;  extern __pdata gyro_t	ao_sample_yaw; +#define AO_NUM_ORIENT	64  extern __pdata angle_t	ao_sample_orient; +extern __pdata angle_t	ao_sample_orients[AO_NUM_ORIENT]; +extern __pdata uint8_t	ao_sample_orient_pos;  #endif  void ao_sample_init(void); diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h index 936d939b..40516de1 100644 --- a/src/kernel/ao_usb.h +++ b/src/kernel/ao_usb.h @@ -41,7 +41,23 @@ ao_usb_pollchar(void);  void  ao_usb_flush(void); +#if AO_USB_HAS_IN2 +void +ao_usb_flush2(void); + +void +ao_usb_putchar2(char c); +#endif + +#if AO_USB_HAS_IN3 +void +ao_usb_flush3(void); + +void +ao_usb_putchar3(char c); +#endif  /* Enable the USB controller */ +  void  ao_usb_enable(void); @@ -107,6 +123,7 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];  #define AO_USB_OUT_EP		4  #define AO_USB_IN_EP		5  #define AO_USB_IN2_EP		6 +#define AO_USB_IN3_EP		7  #endif  #ifndef AO_USB_HAS_OUT @@ -125,6 +142,10 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];  #define AO_USB_HAS_IN2	0  #endif +#ifndef AO_USB_HAS_IN3 +#define AO_USB_HAS_IN3	0 +#endif +  /*   * USB bulk packets can only come in 8, 16, 32 and 64   * byte sizes, so we'll use 64 for everything diff --git a/src/mpusb-v3.0/.gitignore b/src/mpusb-v3.0/.gitignore new file mode 100644 index 00000000..7c1cb599 --- /dev/null +++ b/src/mpusb-v3.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +mpusb-v3.0-* diff --git a/src/mpusb-v3.0/Makefile b/src/mpusb-v3.0/Makefile new file mode 100644 index 00000000..96156741 --- /dev/null +++ b/src/mpusb-v3.0/Makefile @@ -0,0 +1,68 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_boot.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_task.h \ +	ao_whiten.h \ +	stm32f0.h \ +	Makefile + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_dma_stm.c \ +	ao_task.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_usb_stm.c \ +	ao_power.c \ +	ao_gpio.c \ +	ao_serial_stm.c + +PRODUCT=MicroPeakUSB-v3.0 +PRODUCT_DEF=-DMPUSB +IDPRODUCT=0x002b + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g + +PROGNAME=mpusb-v3.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_mpusb.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/mpusb-v3.0/ao_mpusb.c b/src/mpusb-v3.0/ao_mpusb.c new file mode 100644 index 00000000..dc30e197 --- /dev/null +++ b/src/mpusb-v3.0/ao_mpusb.c @@ -0,0 +1,61 @@ +/* + * 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_serial.h> + +static struct ao_task ao_report_task; + +static void +ao_report(void) +{ +	int	c; +	ao_up_set_speed(AO_SERIAL_SPEED_9600); +	for (;;) { +		ao_arch_block_interrupts(); +		c = _ao_up_pollchar(); +		ao_arch_release_interrupts(); +		if (c == AO_READ_AGAIN) { +			flush(); +			c = ao_up_getchar(); +		} +		putchar(c); +	} +} + +int +main(void) +{ +	ao_clock_init(); + +	ao_task_init(); + +	ao_timer_init(); + +	ao_serial_init(); + +	ao_dma_init(); + +	ao_cmd_init(); + +	ao_usb_init(); + +	ao_add_task(&ao_report_task, ao_report, "report"); + +	ao_start_scheduler(); +	return 0; +} diff --git a/src/mpusb-v3.0/ao_pins.h b/src/mpusb-v3.0/ao_pins.h new file mode 100644 index 00000000..3e79aad3 --- /dev/null +++ b/src/mpusb-v3.0/ao_pins.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/* Using TeleMetrum v1.9 board */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE		1 + +#define IS_FLASH_LOADER	0 + +#define AO_POWER_MANAGEMENT	1 + +/* 48MHz clock based on USB */ +#define AO_HSI48	1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER	1 +#define AO_RCC_CFGR_PPRE_DIV	STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_EEPROM		0 +#define USE_INTERNAL_FLASH	0 +#define USE_STORAGE_CONFIG	0 +#define USE_EEPROM_CONFIG	0 + +#define HAS_BEEP		0 + +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 + +#define HAS_SPI_0		0 + +#define LOW_LEVEL_DEBUG		0 + +#define HAS_SERIAL_2		1 +#define USE_SERIAL_2_STDIN	0 +#define SERIAL_2_PA2_PA3	1 +#define SERIAL_2_SWAP		0 +#define USE_SERIAL_2_FLOW	0 +#define USE_SERIAL_2_SW_FLOW	0 + +#define ao_up_getchar		ao_serial2_getchar +#define ao_up_putchar		ao_serial2_putchar +#define _ao_up_pollchar		_ao_serial2_pollchar +#define ao_up_set_speed		ao_serial2_set_speed + +#endif /* _AO_PINS_H_ */ diff --git a/src/mpusb-v3.0/flash-loader/.gitignore b/src/mpusb-v3.0/flash-loader/.gitignore new file mode 100644 index 00000000..1f8b3545 --- /dev/null +++ b/src/mpusb-v3.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +mpusb* diff --git a/src/mpusb-v3.0/flash-loader/Makefile b/src/mpusb-v3.0/flash-loader/Makefile new file mode 100644 index 00000000..8d0f9e42 --- /dev/null +++ b/src/mpusb-v3.0/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=mpusb-v3.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/mpusb-v3.0/flash-loader/ao_pins.h b/src/mpusb-v3.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..7feb9362 --- /dev/null +++ b/src/mpusb-v3.0/flash-loader/ao_pins.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_PINS_H_ +#define _AO_PINS_H_ + +#include <ao_flash_stm_pins.h> + +/* Debug port PA15 (pin 23) */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	(stm_gpioa) +#define AO_BOOT_APPLICATION_PIN		15 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/product/ao_flash_pins.h b/src/product/ao_flash_pins.h index ff8d3273..019b5425 100644 --- a/src/product/ao_flash_pins.h +++ b/src/product/ao_flash_pins.h @@ -25,6 +25,7 @@  #define HAS_USB			1  #define USE_USB_STDIO		0 +#define HAS_USB_DISABLE		0  #define HAS_BEEP		0  #define HAS_TASK		0  #define HAS_ECHO		0 diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 869fb32f..d4569c1a 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -30,6 +30,8 @@ ALTOS_SRC = \  	ao_lcd_stm.c \  	ao_lcd_font.c \  	ao_mutex.c \ +	ao_storage.c \ +	ao_m25.c \  	ao_dma_stm.c \  	ao_spi_stm.c \  	ao_adc_stm.c \ diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index db432c2a..f6c8e3df 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -223,11 +223,12 @@ main(void)  	ao_cmd_init();  //	ao_lcd_stm_init();  //	ao_lcd_font_init(); -//	ao_spi_init(); +	ao_spi_init();  //	ao_i2c_init();  //	ao_exti_init();  //	ao_quadrature_init();  //	ao_button_init(); +	ao_storage_init();  //	ao_timer_set_adc_interval(100); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 233537df..2b4c5ab0 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -59,11 +59,14 @@  #define SERIAL_3_PC10_PC11	0  #define SERIAL_3_PD8_PD9	1 -#define HAS_SPI_1		1 +#define HAS_SPI_1		0  #define SPI_1_PB3_PB4_PB5	1  #define SPI_1_OSPEEDR		STM_OSPEEDR_10MHz -#define HAS_SPI_2		0 +#define HAS_SPI_2		1 +#define SPI_2_PB13_PB14_PB15	1	/* Flash, Companion, Radio */ +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz  #define HAS_USB			1  #define HAS_BEEP		0 @@ -200,4 +203,11 @@ struct ao_adc {  #define AO_TICK_TYPE		uint32_t  #define AO_TICK_SIGNED		int32_t +#define M25_MAX_CHIPS		1 +#define AO_M25_SPI_CS_PORT	(&stm_gpiob) +#define AO_M25_SPI_CS_MASK	(1 << 12) +#define AO_M25_SPI_BUS		AO_SPI_2_PB13_PB14_PB15 + +#define AO_LOG_FORMAT				AO_LOG_FORMAT_TELEMEGA +  #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_adc_single.h b/src/stm/ao_adc_single.h new file mode 100644 index 00000000..f9d953ca --- /dev/null +++ b/src/stm/ao_adc_single.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2018 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +#ifndef _AO_ADC_SINGLE_H_ +#define _AO_ADC_SINGLE_H_ + +void +ao_adc_single_get(struct ao_adc *packet); + +void +ao_adc_single_init(void); + +#endif /* _AO_ADC_SINGLE_H_ */ diff --git a/src/stm/ao_adc_single_stm.c b/src/stm/ao_adc_single_stm.c new file mode 100644 index 00000000..8a7fda4a --- /dev/null +++ b/src/stm/ao_adc_single_stm.c @@ -0,0 +1,297 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_data.h> + +static uint8_t			ao_adc_ready; + +#define AO_ADC_CR2_VAL		((0 << STM_ADC_CR2_SWSTART) |		\ +				 (STM_ADC_CR2_EXTEN_DISABLE << STM_ADC_CR2_EXTEN) | \ +				 (0 << STM_ADC_CR2_EXTSEL) |		\ +				 (0 << STM_ADC_CR2_JWSTART) |		\ +				 (STM_ADC_CR2_JEXTEN_DISABLE << STM_ADC_CR2_JEXTEN) | \ +				 (0 << STM_ADC_CR2_JEXTSEL) |		\ +				 (0 << STM_ADC_CR2_ALIGN) |		\ +				 (0 << STM_ADC_CR2_EOCS) |		\ +				 (1 << STM_ADC_CR2_DDS) |		\ +				 (1 << STM_ADC_CR2_DMA) |		\ +				 (STM_ADC_CR2_DELS_UNTIL_READ << STM_ADC_CR2_DELS) | \ +				 (0 << STM_ADC_CR2_CONT) |		\ +				 (1 << STM_ADC_CR2_ADON)) + +/* + * Callback from DMA ISR + * + * Shut down DMA engine, signal anyone waiting + */ +static void ao_adc_done(int index) +{ +	(void) index; +	ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); +	ao_adc_ready = 1; +	ao_wakeup((void *) &ao_adc_ready); +} + +/* + * Start the ADC sequence using the DMA engine + */ +static void +ao_adc_poll(struct ao_adc *packet) +{ +	ao_adc_ready = 0; +	stm_adc.sr = 0; +	ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), +			    &stm_adc.dr, +			    (void *) packet, +			    AO_NUM_ADC, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) | +			    (1 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); +	ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), ao_adc_done); +	ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + +	stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART); +} + +/* + * Fetch a copy of the most recent ADC data + */ +void +ao_adc_single_get(struct ao_adc *packet) +{ +	ao_adc_poll(packet); +	ao_arch_block_interrupts(); +	while (!ao_adc_ready) +		ao_sleep(&ao_adc_ready); +	ao_arch_release_interrupts(); +} + +static void +ao_adc_dump(void) +{ +	struct ao_adc	packet; +	ao_adc_single_get(&packet); +	AO_ADC_DUMP(&packet); +} + +__code struct ao_cmds ao_adc_cmds[] = { +	{ ao_adc_dump,	"a\0Display current ADC values" }, +	{ 0, NULL }, +}; + +void +ao_adc_single_init(void) +{ +#ifdef AO_ADC_PIN0_PORT +	stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR; +#endif + +#ifdef AO_ADC_PIN0_PORT +	stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN1_PORT +	stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN2_PORT +	stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN3_PORT +	stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN4_PORT +	stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN5_PORT +	stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN6_PORT +	stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN7_PORT +	stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN8_PORT +	stm_moder_set(AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN9_PORT +	stm_moder_set(AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN10_PORT +	stm_moder_set(AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN11_PORT +	stm_moder_set(AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN12_PORT +	stm_moder_set(AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN13_PORT +	stm_moder_set(AO_ADC_PIN13_PORT, AO_ADC_PIN13_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN14_PORT +	stm_moder_set(AO_ADC_PIN14_PORT, AO_ADC_PIN14_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN15_PORT +	stm_moder_set(AO_ADC_PIN15_PORT, AO_ADC_PIN15_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN16_PORT +	stm_moder_set(AO_ADC_PIN16_PORT, AO_ADC_PIN16_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN17_PORT +	stm_moder_set(AO_ADC_PIN17_PORT, AO_ADC_PIN17_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN18_PORT +	stm_moder_set(AO_ADC_PIN18_PORT, AO_ADC_PIN18_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN19_PORT +	stm_moder_set(AO_ADC_PIN19_PORT, AO_ADC_PIN19_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN20_PORT +	stm_moder_set(AO_ADC_PIN20_PORT, AO_ADC_PIN20_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN21_PORT +	stm_moder_set(AO_ADC_PIN21_PORT, AO_ADC_PIN21_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN22_PORT +	stm_moder_set(AO_ADC_PIN22_PORT, AO_ADC_PIN22_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN23_PORT +	stm_moder_set(AO_ADC_PIN23_PORT, AO_ADC_PIN23_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN24_PORT +	#error "Too many ADC ports" +#endif + +	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); + +	/* Turn off ADC during configuration */ +	stm_adc.cr2 = 0; + +	stm_adc.cr1 = ((0 << STM_ADC_CR1_OVRIE ) | +		       (STM_ADC_CR1_RES_12 << STM_ADC_CR1_RES ) | +		       (0 << STM_ADC_CR1_AWDEN ) | +		       (0 << STM_ADC_CR1_JAWDEN ) | +		       (0 << STM_ADC_CR1_PDI ) | +		       (0 << STM_ADC_CR1_PDD ) | +		       (0 << STM_ADC_CR1_DISCNUM ) | +		       (0 << STM_ADC_CR1_JDISCEN ) | +		       (0 << STM_ADC_CR1_DISCEN ) | +		       (0 << STM_ADC_CR1_JAUTO ) | +		       (0 << STM_ADC_CR1_AWDSGL ) | +		       (1 << STM_ADC_CR1_SCAN ) | +		       (0 << STM_ADC_CR1_JEOCIE ) | +		       (0 << STM_ADC_CR1_AWDIE ) | +		       (0 << STM_ADC_CR1_EOCIE ) | +		       (0 << STM_ADC_CR1_AWDCH )); + +	/* 384 cycle sample time for everyone */ +	stm_adc.smpr1 = 0x3ffff; +	stm_adc.smpr2 = 0x3fffffff; +	stm_adc.smpr3 = 0x3fffffff; + +	stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20); +	stm_adc.sqr2 = 0; +	stm_adc.sqr3 = 0; +	stm_adc.sqr4 = 0; +	stm_adc.sqr5 = 0; +#if AO_NUM_ADC > 0 +	stm_adc.sqr5 |= (AO_ADC_SQ1 << 0); +#endif +#if AO_NUM_ADC > 1 +	stm_adc.sqr5 |= (AO_ADC_SQ2 << 5); +#endif +#if AO_NUM_ADC > 2 +	stm_adc.sqr5 |= (AO_ADC_SQ3 << 10); +#endif +#if AO_NUM_ADC > 3 +	stm_adc.sqr5 |= (AO_ADC_SQ4 << 15); +#endif +#if AO_NUM_ADC > 4 +	stm_adc.sqr5 |= (AO_ADC_SQ5 << 20); +#endif +#if AO_NUM_ADC > 5 +	stm_adc.sqr5 |= (AO_ADC_SQ6 << 25); +#endif +#if AO_NUM_ADC > 6 +	stm_adc.sqr4 |= (AO_ADC_SQ7 << 0); +#endif +#if AO_NUM_ADC > 7 +	stm_adc.sqr4 |= (AO_ADC_SQ8 << 5); +#endif +#if AO_NUM_ADC > 8 +	stm_adc.sqr4 |= (AO_ADC_SQ9 << 10); +#endif +#if AO_NUM_ADC > 9 +	stm_adc.sqr4 |= (AO_ADC_SQ10 << 15); +#endif +#if AO_NUM_ADC > 10 +	stm_adc.sqr4 |= (AO_ADC_SQ11 << 20); +#endif +#if AO_NUM_ADC > 11 +	stm_adc.sqr4 |= (AO_ADC_SQ12 << 25); +#endif +#if AO_NUM_ADC > 12 +	stm_adc.sqr3 |= (AO_ADC_SQ13 << 0); +#endif +#if AO_NUM_ADC > 13 +	stm_adc.sqr3 |= (AO_ADC_SQ14 << 5); +#endif +#if AO_NUM_ADC > 14 +	stm_adc.sqr3 |= (AO_ADC_SQ15 << 10); +#endif +#if AO_NUM_ADC > 15 +	stm_adc.sqr3 |= (AO_ADC_SQ16 << 15); +#endif +#if AO_NUM_ADC > 16 +	stm_adc.sqr3 |= (AO_ADC_SQ17 << 20); +#endif +#if AO_NUM_ADC > 17 +	stm_adc.sqr3 |= (AO_ADC_SQ18 << 25); +#endif +#if AO_NUM_ADC > 18 +#error "need to finish stm_adc.sqr settings" +#endif + +	/* Turn ADC on */ +	stm_adc.cr2 = AO_ADC_CR2_VAL; + +	/* Wait for ADC to be ready */ +	while (!(stm_adc.sr & (1 << STM_ADC_SR_ADONS))) +		; + +#ifndef HAS_ADC_TEMP +#error Please define HAS_ADC_TEMP +#endif +#if HAS_ADC_TEMP +	stm_adc.ccr = ((1 << STM_ADC_CCR_TSVREFE)); +#else +	stm_adc.ccr = 0; +#endif +	/* Clear any stale status bits */ +	stm_adc.sr = 0; + +	ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + +	ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 5f033b66..679dba44 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -30,8 +30,6 @@  #define AO_STACK_SIZE	512  #endif -#define AO_LED_TYPE	uint16_t -  #ifndef AO_TICK_TYPE  #define AO_TICK_TYPE	uint16_t  #define AO_TICK_SIGNED	int16_t @@ -153,6 +151,10 @@ ao_adc_init();  #define AO_BOOT_LOADER_BASE		((uint32_t *) 0x08000000)  #define HAS_BOOT_LOADER			1 +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint16_t +#endif +  #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c index 0f39befb..a7033dbb 100644 --- a/src/stm/ao_led.c +++ b/src/stm/ao_led.c @@ -18,11 +18,73 @@  #include "ao.h" -__pdata uint16_t ao_led_enable; +#if LED_PER_LED +static const struct { +	struct stm_gpio	*port; +	uint16_t	pin; +} ao_leds[] = { +#ifdef LED_0_PORT +    [0] { LED_0_PORT, LED_0_PIN }, +#endif +#ifdef LED_1_PORT +    [1] { LED_1_PORT, LED_1_PIN }, +#endif +#ifdef LED_2_PORT +    [2] { LED_2_PORT, LED_2_PIN }, +#endif +#ifdef LED_3_PORT +    [3] { LED_3_PORT, LED_3_PIN }, +#endif +#ifdef LED_4_PORT +    [4] { LED_4_PORT, LED_4_PIN }, +#endif +#ifdef LED_5_PORT +    [5] { LED_5_PORT, LED_5_PIN }, +#endif +#ifdef LED_6_PORT +    [6] { LED_6_PORT, LED_6_PIN }, +#endif +#ifdef LED_7_PORT +    [7] { LED_7_PORT, LED_7_PIN }, +#endif +#ifdef LED_8_PORT +    [8] { LED_8_PORT, LED_8_PIN }, +#endif +#ifdef LED_9_PORT +    [9] { LED_9_PORT, LED_9_PIN }, +#endif +#ifdef LED_10_PORT +    [10] { LED_10_PORT, LED_10_PIN }, +#endif +#ifdef LED_11_PORT +    [11] { LED_11_PORT, LED_11_PIN }, +#endif +#ifdef LED_12_PORT +    [12] { LED_12_PORT, LED_12_PIN }, +#endif +#ifdef LED_13_PORT +    [13] { LED_13_PORT, LED_13_PIN }, +#endif +#ifdef LED_14_PORT +    [14] { LED_14_PORT, LED_14_PIN }, +#endif +#ifdef LED_15_PORT +    [15] { LED_15_PORT, LED_15_PIN }, +#endif +}; +#define N_LED	(sizeof (ao_leds)/sizeof(ao_leds[0])) +#endif +static AO_LED_TYPE ao_led_enable;  void -ao_led_on(uint16_t colors) +ao_led_on(AO_LED_TYPE colors)  { +#ifdef LED_PER_LED +	AO_LED_TYPE i; +	for (i = 0; i < N_LED; i++) +		if (colors & (1 << i)) +			ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, foo, 1); +#else  #ifdef LED_PORT  	LED_PORT->bsrr = (colors & ao_led_enable);  #else @@ -33,11 +95,18 @@ ao_led_on(uint16_t colors)  	LED_PORT_1->bsrr = ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;  #endif  #endif +#endif  }  void -ao_led_off(uint16_t colors) +ao_led_off(AO_LED_TYPE colors)  { +#ifdef LED_PER_LED +	AO_LED_TYPE i; +	for (i = 0; i < N_LED; i++) +		if (colors & (1 << i)) +			ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, foo, 0); +#else  #ifdef LED_PORT  	LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16;  #else @@ -48,21 +117,28 @@ ao_led_off(uint16_t colors)  	LED_PORT_1->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_1_MASK) << (LED_PORT_1_SHIFT + 16);  #endif  #endif +#endif  }  void -ao_led_set(uint16_t colors) +ao_led_set(AO_LED_TYPE colors)  { -	uint16_t	on = colors & ao_led_enable; -	uint16_t	off = ~colors & ao_led_enable; +	AO_LED_TYPE	on = colors & ao_led_enable; +	AO_LED_TYPE	off = ~colors & ao_led_enable;  	ao_led_off(off);  	ao_led_on(on);  }  void -ao_led_toggle(uint16_t colors) +ao_led_toggle(AO_LED_TYPE colors)  { +#ifdef LED_PER_LED +	AO_LED_TYPE i; +	for (i = 0; i < N_LED; i++) +		if (colors & (1 << i)) +			ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, foo, ~ao_gpio_get(ao_leds[i].port, ao_leds[i].pin, foo)); +#else  #ifdef LED_PORT  	LED_PORT->odr ^= (colors & ao_led_enable);  #else @@ -73,10 +149,11 @@ ao_led_toggle(uint16_t colors)  	LED_PORT_1->odr ^= ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;  #endif  #endif +#endif  }  void -ao_led_for(uint16_t colors, uint16_t ticks) __reentrant +ao_led_for(AO_LED_TYPE colors, AO_LED_TYPE ticks) __reentrant  {  	ao_led_on(colors);  	ao_delay(ticks); @@ -89,11 +166,15 @@ ao_led_for(uint16_t colors, uint16_t ticks) __reentrant  	} while (0)  void -ao_led_init(uint16_t enable) +ao_led_init(AO_LED_TYPE enable)  { -	int	bit; +	AO_LED_TYPE	bit;  	ao_led_enable = enable; +#if LED_PER_LED +	for (bit = 0; bit < N_LED; bit++) +		ao_enable_output(ao_leds[bit].port, ao_leds[bit].pin, foo, 0); +#else  #ifdef LED_PORT  	stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE);  	LED_PORT->odr &= ~enable; @@ -106,6 +187,10 @@ ao_led_init(uint16_t enable)  	stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE);  	LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;  #endif +#ifdef LED_PORT_2 +	stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE); +	LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; +#endif  #endif  	for (bit = 0; bit < 16; bit++) {  		if (enable & (1 << bit)) { @@ -120,7 +205,12 @@ ao_led_init(uint16_t enable)  			if (LED_PORT_1_MASK & (1 << bit))  				init_led_pin(LED_PORT_1, bit + LED_PORT_1_SHIFT);  #endif +#ifdef LED_PORT_2 +			if (LED_PORT_2_MASK & (1 << bit)) +				init_led_pin(LED_PORT_2, bit + LED_PORT_2_SHIFT); +#endif  #endif  		}  	} +#endif  } diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c index 9d5fd6fb..63a48bec 100644 --- a/src/stm/ao_romconfig.c +++ b/src/stm/ao_romconfig.c @@ -24,5 +24,6 @@ AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0;  #ifndef AO_RADIO_CAL_DEFAULT  #define AO_RADIO_CAL_DEFAULT 0x01020304  #endif +#if HAS_RADIO  AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; - +#endif diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 1576a6c9..7b526902 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -149,7 +149,7 @@ ao_clock_init(void)  #define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK	(0 << STM_RCC_CFGR_PLLSRC)  #endif -#if !AO_HSE || HAS_ADC +#if !AO_HSE || HAS_ADC || HAS_ADC_SINGLE  	/* Enable HSI RC clock 16MHz */  	stm_rcc.cr |= (1 << STM_RCC_CR_HSION);  	while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 595bddac..b06814d2 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -446,15 +446,11 @@ ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset)  }  static void -ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t bytes)  { +	uint16_t offset = 0;  	if (!bytes)  		return; -	if (offset & 1) { -		debug_data (" %02x", src[0]); -		ao_usb_write_byte(*src++, base, offset++); -		bytes--; -	}  	while (bytes >= 2) {  		debug_data (" %02x %02x", src[0], src[1]);  		ao_usb_write_short((src[1] << 8) | src[0], base, offset); @@ -531,7 +527,7 @@ ao_usb_ep0_flush(void)  	ao_usb_ep0_in_len -= this_len;  	debug_data ("Flush EP0 len %d:", this_len); -	ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); +	ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len);  	debug_data ("\n");  	ao_usb_ep0_in_data += this_len; @@ -850,7 +846,7 @@ _ao_usb_in_send(void)  	ao_usb_in_pending = 1;  	if (ao_usb_tx_count != AO_USB_IN_SIZE)  		ao_usb_in_flushed = 1; -	ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); +	ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count);  	ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count;  	ao_usb_tx_count = 0;  	_ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); @@ -974,6 +970,11 @@ ao_usb_getchar(void)  	return c;  } +#ifndef HAS_USB_DISABLE +#define HAS_USB_DISABLE 1 +#endif + +#if HAS_USB_DISABLE  void  ao_usb_disable(void)  { @@ -991,6 +992,7 @@ ao_usb_disable(void)  	stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN);  	ao_arch_release_interrupts();  } +#endif  void  ao_usb_enable(void) diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 201f4f36..1da817e7 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1454,6 +1454,9 @@ struct stm_adc {  extern struct stm_adc stm_adc; +#define STM_ADC_SQ_TEMP		16 +#define STM_ADC_SQ_V_REF	17 +  #define STM_ADC_SR_JCNR		9  #define STM_ADC_SR_RCNR		8  #define STM_ADC_SR_ADONS	6 diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 56a3bc75..96c033f9 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -171,10 +171,12 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s  #define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)  #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus) +#if AO_POWER_MANAGEMENT  extern struct ao_power	ao_power_gpioa;  extern struct ao_power	ao_power_gpiob;  extern struct ao_power	ao_power_gpioc;  extern struct ao_power	ao_power_gpiof; +#endif  static inline void ao_enable_port(struct stm_gpio *port)  { diff --git a/src/stmf0/ao_flash_loader_stm.c b/src/stmf0/ao_flash_loader_stm.c index a8d1701b..18bf272c 100644 --- a/src/stmf0/ao_flash_loader_stm.c +++ b/src/stmf0/ao_flash_loader_stm.c @@ -34,7 +34,7 @@ main(void)  #ifdef AO_FLASH_LOADER_INIT  	AO_FLASH_LOADER_INIT; -#endif	 +#endif  	ao_flash_task();  	return 0;  } diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c index fcd330f1..a67f6f1a 100644 --- a/src/stmf0/ao_interrupt.c +++ b/src/stmf0/ao_interrupt.c @@ -69,20 +69,24 @@ stm_flash_size(void) {  void start(void)  { -#ifdef AO_BOOT_CHAIN +#if AO_BOOT_CHAIN  	if (ao_boot_check_chain()) { -#ifdef AO_BOOT_PIN +#if AO_BOOT_PIN  		ao_boot_check_pin();  #endif  	}  #endif -#if RELOCATE_INTERRUPT  	/* Turn on syscfg */  	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN); +#if RELOCATE_INTERRUPT  	memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);  	stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |  		(STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE); +#else +	/* Switch to Main Flash mode (DFU loader leaves us in System mode) */ +	stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) | +		(STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH << STM_SYSCFG_CFGR1_MEM_MODE);  #endif  	memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);  	memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index bf08abc1..c4860d8e 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -113,6 +113,12 @@ static uint8_t	ao_usb_in_tx2_which;  static uint8_t	ao_usb_tx2_count;  #endif +#if AO_USB_HAS_IN3 +static uint16_t ao_usb_in_tx3_offset; +static uint8_t	ao_usb_in_tx3_which; +static uint8_t	ao_usb_tx3_count; +#endif +  /*   * End point register indices   */ @@ -122,6 +128,7 @@ static uint8_t	ao_usb_tx2_count;  #define AO_USB_OUT_EPR		2  #define AO_USB_IN_EPR		3  #define AO_USB_IN2_EPR		4 +#define AO_USB_IN3_EPR		5  /* Marks when we don't need to send an IN packet.   * This happens only when the last IN packet is not full, @@ -146,6 +153,16 @@ static uint16_t	in2_count;  static uint8_t	ao_usb_in2_flushed;  #endif +#if AO_USB_HAS_IN3 +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ +static uint8_t	ao_usb_in3_pending; +static uint16_t	in3_count; +static uint8_t	ao_usb_in3_flushed; +#endif +  /* Marks when an OUT packet has been received by the hardware   * but not pulled to the shadow buffer.   */ @@ -423,6 +440,11 @@ ao_usb_alloc_buffers(void)  	ao_usb_in_tx2_offset = sram_addr;  	sram_addr += AO_USB_IN_SIZE * 2;  #endif +#if AO_USB_HAS_IN3 +	sram_addr += (sram_addr & 1); +	ao_usb_in_tx3_offset = sram_addr; +	sram_addr += AO_USB_IN_SIZE * 2; +#endif  }  static void @@ -558,6 +580,25 @@ ao_usb_set_configuration(void)  	ao_usb_in_tx2_which = 0;  #endif +#if AO_USB_HAS_IN3 +	/* Set up the IN3 end point */ +	stm_usb_bdt[AO_USB_IN3_EPR].double_tx[0].addr = ao_usb_in_tx3_offset; +	stm_usb_bdt[AO_USB_IN3_EPR].double_tx[0].count = 0; +	stm_usb_bdt[AO_USB_IN3_EPR].double_tx[1].addr = ao_usb_in_tx3_offset + AO_USB_IN_SIZE; +	stm_usb_bdt[AO_USB_IN3_EPR].double_tx[1].count = 0; + +	ao_usb_init_ep(AO_USB_IN3_EPR, +		       AO_USB_IN3_EP, +		       STM_USB_EPR_EP_TYPE_BULK, +		       STM_USB_EPR_STAT_RX_DISABLED, +		       STM_USB_EPR_STAT_TX_NAK, +		       STM_USB_EPR_EP_KIND_DBL_BUF, +		       0, 1); + +	/* First transmit data goes to buffer 0 */ +	ao_usb_in_tx3_which = 0; +#endif +  	ao_usb_in_flushed = 0;  	ao_usb_in_pending = 0;  	ao_wakeup(&ao_usb_in_pending); @@ -567,6 +608,12 @@ ao_usb_set_configuration(void)  	ao_wakeup(&ao_usb_in2_pending);  #endif +#if AO_USB_HAS_IN3 +	ao_usb_in3_flushed = 0; +	ao_usb_in3_pending = 0; +	ao_wakeup(&ao_usb_in3_pending); +#endif +  	ao_usb_out_avail = 0;  	ao_usb_configuration = 0; @@ -996,6 +1043,16 @@ stm_usb_isr(void)  			}  			break;  #endif +#if AO_USB_HAS_IN3 +		case AO_USB_IN3_EPR: +			++in3_count; +			_tx_dbg1("TX3 ISR", epr); +			if (ao_usb_epr_ctr_tx(epr)) { +				ao_usb_in3_pending = 0; +				ao_wakeup(&ao_usb_in3_pending); +			} +			break; +#endif  		case AO_USB_INT_EPR:  #if USB_STATUS  			++int_count; @@ -1132,6 +1189,9 @@ _ao_usb_in2_send(void)  	/* Toggle our usage */  	ao_usb_in_tx2_which = 1 - ao_usb_in_tx2_which; +	/* Toggle the SW_BUF flag */ +	_ao_usb_toggle_dtog(AO_USB_IN2_EPR, 1, 0); +  	/* Mark the outgoing buffer as valid */  	_ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID); @@ -1199,6 +1259,94 @@ ao_usb_putchar2(char c)  }  #endif +#if AO_USB_HAS_IN3 +/* Queue the current IN buffer for transmission */ +static void +_ao_usb_in3_send(void) +{ +	_tx_dbg0("in3_send start"); +	debug ("send3 %d\n", ao_usb_tx3_count); +	while (ao_usb_in3_pending) +		ao_sleep(&ao_usb_in3_pending); +	ao_usb_in3_pending = 1; +	if (ao_usb_tx3_count != AO_USB_IN_SIZE) +		ao_usb_in3_flushed = 1; +	stm_usb_bdt[AO_USB_IN3_EPR].double_tx[ao_usb_in_tx3_which].count = ao_usb_tx3_count; +	ao_usb_tx3_count = 0; + +	/* Toggle our usage */ +	ao_usb_in_tx3_which = 1 - ao_usb_in_tx3_which; + +	/* Toggle the SW_BUF flag */ +	_ao_usb_toggle_dtog(AO_USB_IN3_EPR, 1, 0); + +	/* Mark the outgoing buffer as valid */ +	_ao_usb_set_stat_tx(AO_USB_IN3_EPR, STM_USB_EPR_STAT_TX_VALID); + +	_tx_dbg0("in3_send end"); +} + +/* Wait for a free IN buffer. Interrupts are blocked */ +static void +_ao_usb_in3_wait(void) +{ +	for (;;) { +		/* Check if the current buffer is writable */ +		if (ao_usb_tx3_count < AO_USB_IN_SIZE) +			break; + +		_tx_dbg0("in3_wait top"); +		/* Wait for an IN buffer to be ready */ +		while (ao_usb_in3_pending) +			ao_sleep(&ao_usb_in3_pending); +		_tx_dbg0("in_wait bottom"); +	} +} + +void +ao_usb_flush3(void) +{ +	if (!ao_usb_running) +		return; + +	/* Anytime we've sent a character since +	 * the last time we flushed, we'll need +	 * to send a packet -- the only other time +	 * we would send a packet is when that +	 * packet was full, in which case we now +	 * want to send an empty packet +	 */ +	ao_arch_block_interrupts(); +	while (!ao_usb_in3_flushed) { +		_tx_dbg0("flush3 top"); +		_ao_usb_in3_send(); +		_tx_dbg0("flush3 end"); +	} +	ao_arch_release_interrupts(); +} + +void +ao_usb_putchar3(char c) +{ +	if (!ao_usb_running) +		return; + +	ao_arch_block_interrupts(); +	_ao_usb_in3_wait(); + +	ao_usb_in3_flushed = 0; +	ao_usb_tx_byte(ao_usb_in_tx3_offset + AO_USB_IN_SIZE * ao_usb_in_tx3_which + ao_usb_tx3_count++, c); + +	/* Send the packet when full */ +	if (ao_usb_tx3_count == AO_USB_IN_SIZE) { +		_tx_dbg0("putchar3 full"); +		_ao_usb_in3_send(); +		_tx_dbg0("putchar3 flushed"); +	} +	ao_arch_release_interrupts(); +} +#endif +  #if AO_USB_HAS_OUT  static void  _ao_usb_out_recv(void) @@ -1447,7 +1595,7 @@ ao_usb_enable(void)  	ao_arch_release_interrupts(); -	for (t = 0; t < 1000; t++) +	for (t = 0; t < 50000; t++)  		ao_arch_nop();  	/* Enable USB pull-up */ @@ -1541,9 +1689,9 @@ struct ao_usb_dbg {  #endif  }; -#define NUM_USB_DBG	128 +#define NUM_USB_DBG	16 -struct ao_usb_dbg dbg[128]; +struct ao_usb_dbg dbg[NUM_USB_DBG];  int dbg_i;  static void _dbg(int line, char *msg, uint32_t value) @@ -1555,11 +1703,11 @@ static void _dbg(int line, char *msg, uint32_t value)  	asm("mrs %0,primask" : "=&r" (primask));  	dbg[dbg_i].primask = primask;  #if TX_DBG -	dbg[dbg_i].in_count = in_count; -	dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR]; -	dbg[dbg_i].in_pending = ao_usb_in_pending; -	dbg[dbg_i].tx_count = ao_usb_tx_count; -	dbg[dbg_i].in_flushed = ao_usb_in_flushed; +	dbg[dbg_i].in_count = in3_count; +	dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN3_EPR].r; +	dbg[dbg_i].in_pending = ao_usb_in3_pending; +	dbg[dbg_i].tx_count = ao_usb_tx3_count; +	dbg[dbg_i].in_flushed = ao_usb_in3_flushed;  #endif  #if RX_DBG  	dbg[dbg_i].rx_count = ao_usb_rx_count; diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index ee0ca716..8266589e 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -100,10 +100,17 @@  #define AO_STROBE_PIN		1  #define AO_STROBE		P1_1 -/* 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_ADC_REFERENCE_DV	33 +#define AO_PAD_R_V_BATT_BATT_SENSE	100 +#define AO_PAD_R_BATT_SENSE_GND		27 + +#define AO_PAD_R_V_BATT_V_PYRO		100 +#define AO_PAD_R_V_PYRO_PYRO_SENSE	100 +#define AO_PAD_R_PYRO_SENSE_GND		27 + +#define AO_PAD_R_V_PYRO_IGNITER		100 +#define AO_PAD_R_IGNITER_IGNITER_SENSE	100 +#define AO_PAD_R_IGNITER_SENSE_GND	27  #define AO_PAD_ADC_PYRO		4  #define AO_PAD_ADC_BATT		5 diff --git a/src/telefire-v0.2/ao_pins.h b/src/telefire-v0.2/ao_pins.h index 4faeb65f..65f5bdcc 100644 --- a/src/telefire-v0.2/ao_pins.h +++ b/src/telefire-v0.2/ao_pins.h @@ -111,15 +111,24 @@  #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 +#define AO_ADC_REFERENCE_DV	33 +#define AO_PAD_R_V_BATT_BATT_SENSE	100 +#define AO_PAD_R_BATT_SENSE_GND		27 + +#define AO_PAD_R_V_BATT_V_PYRO		100 +#define AO_PAD_R_V_PYRO_PYRO_SENSE	100 +#define AO_PAD_R_PYRO_SENSE_GND		27 + +#define AO_PAD_R_V_PYRO_IGNITER		100 +#define AO_PAD_R_IGNITER_IGNITER_SENSE	100 +#define AO_PAD_R_IGNITER_SENSE_GND	27 + +  struct ao_adc {  	int16_t		sense[AO_PAD_NUM];  	int16_t		pyro; diff --git a/src/telefireeight-v1.0/.gitignore b/src/telefireeight-v1.0/.gitignore new file mode 100644 index 00000000..22f7e9ef --- /dev/null +++ b/src/telefireeight-v1.0/.gitignore @@ -0,0 +1,2 @@ +telefireeight-* +ao_product.h diff --git a/src/telefireeight-v1.0/Makefile b/src/telefireeight-v1.0/Makefile new file mode 100644 index 00000000..200c3150 --- /dev/null +++ b/src/telefireeight-v1.0/Makefile @@ -0,0 +1,90 @@ +# +# TeleFire build file +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_pins.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pad.h \ +	ao_product.h \ +	ao_radio_spi.h \ +	ao_radio_cmac.h \ +	ao_cc1200_CC1200.h \ +	ao_cc1200.h \ +	stm32l.h +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_adc_stm.c \ +	ao_data.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_beep_stm.c \ +	ao_eeprom_stm.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_cc1200.c \ +	ao_radio_cmac.c \ +	ao_aes.c \ +	ao_aes_tables.c \ +	ao_pad.c \ +	ao_radio_cmac_cmd.c + +PRODUCT_SRC = \ +	ao_telefireeight.c + +PRODUCT=TeleFireEight-v1.0 +PRODUCT_DEF=-DTELEFIREEIGHT_V_1_0 +IDPRODUCT=0x000f + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME = telefireeight-v1.0 +PROG = $(PROGNAME)-$(VERSION).elf +HEX = $(PROGNAME)-$(VERSION).ihx + +SRC = $(ALTOS_SRC) $(PRODUCT_SRC) +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(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 $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: + diff --git a/src/telefireeight-v1.0/ao_pins.h b/src/telefireeight-v1.0/ao_pins.h new file mode 100644 index 00000000..15e1fa11 --- /dev/null +++ b/src/telefireeight-v1.0/ao_pins.h @@ -0,0 +1,341 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_RADIO_RATE		1 +#define HAS_TELEMETRY		0 +#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 IGNITE_ON_P0		0 +#define PACKET_HAS_MASTER	0 +#define PACKET_HAS_SLAVE	0 +#define AO_DATA_RING		32 +#define USE_EEPROM_CONFIG	1 +#define USE_STORAGE_CONFIG	0 +#define HAS_AES			1 + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC		40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SPI_1		1 +#define SPI_1_PA5_PA6_PA7	0 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	1 +#define SPI_1_GPIO		(&stm_gpioe) +#define SPI_1_SCK		13 +#define SPI_1_MISO		14 +#define SPI_1_MOSI		15 +#define SPI_1_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_SPI_2		0 +#define SPI_2_PB13_PB14_PB15	0 +#define SPI_2_PD1_PD3_PD4	0 + +#define HAS_I2C_1		0 + +#define HAS_I2C_2		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define FAST_TIMER_FREQ		10000	/* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 	5695733 + +#define AO_CC1200_SPI_CS_PORT	(&stm_gpioe) +#define AO_CC1200_SPI_CS_PIN	11 +#define AO_CC1200_SPI_BUS	AO_SPI_1_PE13_PE14_PE15 +#define AO_CC1200_SPI		stm_spi1 +#define AO_CC1200_SPI_SPEED	AO_SPI_SPEED_FAST + +#define AO_CC1200_INT_PORT	(&stm_gpioe) +#define AO_CC1200_INT_PIN	(12) + +#define AO_CC1200_INT_GPIO	2 +#define AO_CC1200_INT_GPIO_IOCFG	CC1200_IOCFG2 + +#define LED_PER_LED		1 +#define LED_TYPE		uint16_t + +/* Continuity leds 1-8 */ +#define LED_0_PORT		(&stm_gpiob) +#define LED_0_PIN		13 +#define LED_1_PORT		(&stm_gpiob) +#define LED_1_PIN		12 +#define LED_2_PORT		(&stm_gpiob) +#define LED_2_PIN		11 +#define LED_3_PORT		(&stm_gpiob) +#define LED_3_PIN		10 +#define LED_4_PORT		(&stm_gpioc) +#define LED_4_PIN		9 +#define LED_5_PORT		(&stm_gpioa) +#define LED_5_PIN		8 +#define LED_6_PORT		(&stm_gpioa) +#define LED_6_PIN		9 +#define LED_7_PORT		(&stm_gpioa) +#define LED_7_PIN		10 + +#define LED_PIN_CONTINUITY_0	0 +#define LED_PIN_CONTINUITY_1	1 +#define LED_PIN_CONTINUITY_2	2 +#define LED_PIN_CONTINUITY_3	3 +#define LED_PIN_CONTINUITY_4	4 +#define LED_PIN_CONTINUITY_5	5 +#define LED_PIN_CONTINUITY_6	6 +#define LED_PIN_CONTINUITY_7	7 + +/* ARM */ +#define LED_8_PORT		(&stm_gpioe) +#define LED_8_PIN		3 + +#define LED_PIN_ARMED		8 + +/* RF good/marginal/poor */ +#define LED_9_PORT		(&stm_gpioe) +#define LED_9_PIN		4 +#define LED_10_PORT		(&stm_gpioe) +#define LED_10_PIN		5 +#define LED_11_PORT		(&stm_gpioe) +#define LED_11_PIN		6 + +#define LED_PIN_GREEN		9 +#define LED_PIN_AMBER		10 +#define LED_PIN_RED		11 + +#define AO_LED_CONTINUITY(c)	(1 << (c)) +#define AO_LED_CONTINUITY_MASK	(0xff) + +#define AO_LED_ARMED		(1 << LED_PIN_ARMED) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) +#define AO_LED_AMBER		(1 << LED_PIN_AMBER) +#define AO_LED_RED		(1 << LED_PIN_RED) + +#define LEDS_AVAILABLE		(0xfff) + +/* Alarm A */ +#define AO_SIREN +#define AO_SIREN_PORT		(&stm_gpiod) +#define AO_SIREN_PIN		10 + +/* Alarm B */ +#define AO_STROBE +#define AO_STROBE_PORT		(&stm_gpiod) +#define AO_STROBE_PIN		11 + +/* Pad selector is on PD0-7 */ + +#define HAS_FIXED_PAD_BOX	1 +#define AO_PAD_SELECTOR_PORT	(&stm_gpiod) +#define AO_PAD_SELECTOR_PINS	(0xff) + +#define SPI_CONST	0x00 + +#define AO_PAD_NUM		8 +#define	AO_PAD_PORT_0		(&stm_gpiod) +#define	AO_PAD_PORT_1		(&stm_gpiob) + +#define AO_PAD_PIN_0		9 +#define AO_PAD_0_PORT		(&stm_gpiod) +#define AO_ADC_SENSE_PAD_0	3 +#define AO_ADC_SENSE_PAD_0_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_0_PIN	3 + +#define AO_PAD_PIN_1		8 +#define AO_PAD_1_PORT		(&stm_gpiod) +#define AO_ADC_SENSE_PAD_1	2 +#define AO_ADC_SENSE_PAD_1_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_1_PIN	2 + +#define AO_PAD_PIN_2		15 +#define AO_PAD_2_PORT		(&stm_gpiob) +#define AO_ADC_SENSE_PAD_2	1 +#define AO_ADC_SENSE_PAD_2_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_2_PIN	1 + +#define AO_PAD_PIN_3		14 +#define AO_PAD_3_PORT		(&stm_gpiob) +#define AO_ADC_SENSE_PAD_3	0 +#define AO_ADC_SENSE_PAD_3_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_3_PIN	0 + +#define AO_PAD_PIN_4		12 +#define AO_PAD_4_PORT		(&stm_gpiod) +#define AO_ADC_SENSE_PAD_4	7 +#define AO_ADC_SENSE_PAD_4_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_4_PIN	7 + +#define AO_PAD_PIN_5		13 +#define AO_PAD_5_PORT		(&stm_gpiod) +#define AO_ADC_SENSE_PAD_5	6 +#define AO_ADC_SENSE_PAD_5_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_5_PIN	6 + +#define AO_PAD_PIN_6		14 +#define AO_PAD_6_PORT		(&stm_gpiod) +#define AO_ADC_SENSE_PAD_6	5 +#define AO_ADC_SENSE_PAD_6_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_6_PIN	5 + +#define AO_PAD_PIN_7		15 +#define AO_PAD_7_PORT		(&stm_gpiod) +#define AO_ADC_SENSE_PAD_7	4 +#define AO_ADC_SENSE_PAD_7_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_PAD_7_PIN	4 + +#define AO_ADC_PYRO		8 +#define AO_ADC_PYRO_PORT	(&stm_gpiob) +#define AO_ADC_PYRO_PIN		0 + +#define AO_ADC_BATT		15 +#define AO_ADC_BATT_PORT	(&stm_gpioc) +#define AO_ADC_BATT_PIN		5 + +#define AO_ADC_PIN0_PORT	AO_ADC_SENSE_PAD_0_PORT +#define AO_ADC_PIN0_PIN		AO_ADC_SENSE_PAD_0_PIN + +#define AO_ADC_PIN1_PORT	AO_ADC_SENSE_PAD_1_PORT +#define AO_ADC_PIN1_PIN		AO_ADC_SENSE_PAD_1_PIN + +#define AO_ADC_PIN2_PORT	AO_ADC_SENSE_PAD_2_PORT +#define AO_ADC_PIN2_PIN		AO_ADC_SENSE_PAD_2_PIN + +#define AO_ADC_PIN3_PORT	AO_ADC_SENSE_PAD_3_PORT +#define AO_ADC_PIN3_PIN		AO_ADC_SENSE_PAD_3_PIN + +#define AO_ADC_PIN4_PORT	AO_ADC_SENSE_PAD_4_PORT +#define AO_ADC_PIN4_PIN		AO_ADC_SENSE_PAD_4_PIN + +#define AO_ADC_PIN5_PORT	AO_ADC_SENSE_PAD_5_PORT +#define AO_ADC_PIN5_PIN		AO_ADC_SENSE_PAD_5_PIN + +#define AO_ADC_PIN6_PORT	AO_ADC_SENSE_PAD_6_PORT +#define AO_ADC_PIN6_PIN		AO_ADC_SENSE_PAD_6_PIN + +#define AO_ADC_PIN7_PORT	AO_ADC_SENSE_PAD_7_PORT +#define AO_ADC_PIN7_PIN		AO_ADC_SENSE_PAD_7_PIN + +#define AO_ADC_PIN8_PORT	AO_ADC_PYRO_PORT +#define AO_ADC_PIN8_PIN		AO_ADC_PYRO_PIN + +#define AO_ADC_PIN9_PORT	AO_ADC_BATT_PORT +#define AO_ADC_PIN9_PIN		AO_ADC_BATT_PIN + +#define AO_PAD_ALL_CHANNELS	(0xff) + +/* 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_ADC_FIRST_PIN	0 + +#define AO_NUM_ADC		10 + +#define AO_ADC_SQ1		AO_ADC_SENSE_PAD_0 +#define AO_ADC_SQ2		AO_ADC_SENSE_PAD_1 +#define AO_ADC_SQ3		AO_ADC_SENSE_PAD_2 +#define AO_ADC_SQ4		AO_ADC_SENSE_PAD_3 +#define AO_ADC_SQ5		AO_ADC_SENSE_PAD_4 +#define AO_ADC_SQ6		AO_ADC_SENSE_PAD_5 +#define AO_ADC_SQ7		AO_ADC_SENSE_PAD_6 +#define AO_ADC_SQ8		AO_ADC_SENSE_PAD_7 +#define AO_ADC_SQ9		AO_ADC_PYRO +#define AO_ADC_SQ10		AO_ADC_BATT + +#define AO_ADC_REFERENCE_DV	33 + +#define AO_ADC_RCC_AHBENR	((1 << STM_RCC_AHBENR_GPIOAEN) | \ +				 (1 << STM_RCC_AHBENR_GPIOBEN) | \ +				 (1 << STM_RCC_AHBENR_GPIOCEN)) + + +#define AO_PAD_R_V_BATT_BATT_SENSE	200 +#define AO_PAD_R_BATT_SENSE_GND		22 + +#define AO_PAD_R_V_BATT_V_PYRO		200 +#define AO_PAD_R_V_PYRO_PYRO_SENSE	200 +#define AO_PAD_R_PYRO_SENSE_GND		22 + +#undef AO_PAD_R_V_PYRO_IGNITER +#define AO_PAD_R_IGNITER_IGNITER_SENSE	200 +#define AO_PAD_R_IGNITER_SENSE_GND	22 + +#define HAS_ADC_TEMP		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 "				\ +		"4: %5d 5: %5d 6: %5d 7: %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.sense[4],					\ +		(p)->adc.sense[5],					\ +		(p)->adc.sense[6],					\ +		(p)->adc.sense[7],					\ +		(p)->adc.pyro,						\ +		(p)->adc.batt) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefireeight-v1.0/ao_telefireeight.c b/src/telefireeight-v1.0/ao_telefireeight.c new file mode 100644 index 00000000..bdcf3213 --- /dev/null +++ b/src/telefireeight-v1.0/ao_telefireeight.c @@ -0,0 +1,55 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_exti.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_spi_init(); +	ao_dma_init(); +	ao_exti_init(); + +	ao_cmd_init(); + +	ao_adc_init(); + +	ao_eeprom_init(); + +	ao_radio_init(); + +	ao_usb_init(); + +	ao_config_init(); + +	ao_pad_init(); + +//	ao_radio_cmac_cmd_init(); + +	ao_start_scheduler(); +} diff --git a/src/telefireeight-v1.0/flash-loader/.gitignore b/src/telefireeight-v1.0/flash-loader/.gitignore new file mode 100644 index 00000000..65fe7eab --- /dev/null +++ b/src/telefireeight-v1.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.ihx diff --git a/src/telefireeight-v1.0/flash-loader/Makefile b/src/telefireeight-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..baf0e3f3 --- /dev/null +++ b/src/telefireeight-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telefireeight-v1.0 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telefireeight-v1.0/flash-loader/ao_pins.h b/src/telefireeight-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..889feef6 --- /dev/null +++ b/src/telefireeight-v1.0/flash-loader/ao_pins.h @@ -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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioe +#define AO_BOOT_APPLICATION_PIN		2 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h index 1e5c0d09..dedd0fad 100644 --- a/src/telefiretwo-v0.1/ao_pins.h +++ b/src/telefiretwo-v0.1/ao_pins.h @@ -191,6 +191,19 @@  #define HAS_ADC_TEMP		0 +#define AO_ADC_REFERENCE_DV	33 + +#define AO_PAD_R_V_BATT_BATT_SENSE	200 +#define AO_PAD_R_BATT_SENSE_GND		22 + +#define AO_PAD_R_V_BATT_V_PYRO		200 +#define AO_PAD_R_V_PYRO_PYRO_SENSE	200 +#define AO_PAD_R_PYRO_SENSE_GND		22 + +#undef AO_PAD_R_V_PYRO_IGNITER +#define AO_PAD_R_IGNITER_IGNITER_SENSE	200 +#define AO_PAD_R_IGNITER_SENSE_GND	22 +  struct ao_adc {  	int16_t		sense[AO_PAD_NUM];  	int16_t		pyro; diff --git a/src/telelco-v0.2-cc1200/Makefile b/src/telelco-v0.2-cc1200/Makefile new file mode 100644 index 00000000..4ccf494c --- /dev/null +++ b/src/telelco-v0.2-cc1200/Makefile @@ -0,0 +1,109 @@ +# +# AltOS build for TeleLCO +# +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_boot.h \ +	ao_companion.h \ +	ao_data.h \ +	ao_sample.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_seven_segment.h \ +	ao_lco.h \ +	ao_lco_cmd.h \ +	ao_lco_func.h \ +	ao_radio_spi.h \ +	ao_radio_cmac.h \ +	ao_cc1200_CC1200.h \ +	ao_cc1200.h \ +	stm32l.h + +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_beep_stm.c \ +	ao_eeprom_stm.c \ +	ao_adc_single_stm.c \ +	ao_convert_volt.c \ +	ao_fast_timer.c \ +	ao_lcd_stm.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_cc1200.c \ +	ao_radio_cmac.c \ +	ao_aes.c \ +	ao_aes_tables.c \ +	ao_fec_tx.c \ +	ao_fec_rx.c \ +	ao_seven_segment.c \ +	ao_quadrature.c \ +	ao_button.c \ +	ao_event.c \ +	ao_lco.c \ +	ao_lco_bits.c \ +	ao_lco_cmd.c \ +	ao_lco_func.c \ +	ao_radio_cmac_cmd.c + +PRODUCT=TeleLCO-v0.2 +PRODUCT_DEF=-DTELELCO +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telelco-v0.2 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telelco.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +../altitude.h: make-altitude +	nickle $< > $@ + +$(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 $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telelco-v0.2-cc1200/ao_pins.h b/src/telelco-v0.2-cc1200/ao_pins.h new file mode 100644 index 00000000..bc325e06 --- /dev/null +++ b/src/telelco-v0.2-cc1200/ao_pins.h @@ -0,0 +1,324 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_ + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC		32000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	1 +#define USE_EEPROM_CONFIG	1 +#define USE_STORAGE_CONFIG	0 +#define HAS_USB			1 +#define HAS_BEEP		1 +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0 +#define HAS_AES			1 +#define HAS_STATIC_TEST		0 + + +#define HAS_SPI_1		0 +#define SPI_1_PA5_PA6_PA7	0 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	0 + +#define HAS_SPI_2		1	/* CC1120 */ +#define SPI_2_PB13_PB14_PB15	0 +#define SPI_2_PD1_PD3_PD4	1 +#define SPI_2_GPIO		(&stm_gpiod) +#define SPI_2_SCK		1 +#define SPI_2_MISO		3 +#define SPI_2_MOSI		4 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_I2C_1		0 + +#define HAS_I2C_2		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define FAST_TIMER_FREQ		10000	/* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 	5695733 + +#define AO_FEC_DEBUG		0 +#define AO_CC1200_SPI_CS_PORT	(&stm_gpiod) +#define AO_CC1200_SPI_CS_PIN	0 +#define AO_CC1200_SPI_BUS	AO_SPI_2_PD1_PD3_PD4 +#define AO_CC1200_SPI		stm_spi2 +#define AO_CC1200_SPI_SPEED	AO_SPI_SPEED_FAST + +#define AO_CC1200_INT_PORT		(&stm_gpioc) +#define AO_CC1200_INT_PIN		(15) + +#define AO_CC1200_INT_GPIO	2 +#define AO_CC1200_INT_GPIO_IOCFG	CC1200_IOCFG2 + +#define LOW_LEVEL_DEBUG		0 + +#define LED_PORT_ENABLE		STM_RCC_AHBENR_GPIOCEN +#define LED_PORT		(&stm_gpioc) +#define LED_PIN_RED		7 +#define LED_PIN_AMBER		8 +#define LED_PIN_GREEN		9 +#define LED_PIN_CONTINUITY_3	10 +#define LED_PIN_CONTINUITY_2	11 +#define LED_PIN_CONTINUITY_1	12 +#define LED_PIN_CONTINUITY_0	13 +#define LED_PIN_REMOTE_ARM	14 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_AMBER		(1 << LED_PIN_AMBER) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) +#define AO_LED_CONTINUITY_3	(1 << LED_PIN_CONTINUITY_3) +#define AO_LED_CONTINUITY_2	(1 << LED_PIN_CONTINUITY_2) +#define AO_LED_CONTINUITY_1	(1 << LED_PIN_CONTINUITY_1) +#define AO_LED_CONTINUITY_0	(1 << LED_PIN_CONTINUITY_0) + +#define AO_LED_CONTINUITY_NUM	4 + +#define AO_LED_REMOTE_ARM	(1 << LED_PIN_REMOTE_ARM) + +#define LEDS_AVAILABLE		(AO_LED_RED |		\ +				 AO_LED_AMBER |		\ +				 AO_LED_GREEN |		\ +				 AO_LED_CONTINUITY_3 |	\ +				 AO_LED_CONTINUITY_2 |	\ +				 AO_LED_CONTINUITY_1 |	\ +				 AO_LED_CONTINUITY_0 |	\ +				 AO_LED_REMOTE_ARM) + +/* LCD displays */ + +#define LCD_DEBUG		0 +#define SEVEN_SEGMENT_DEBUG	0 + +#define AO_LCD_STM_SEG_ENABLED_0 (		\ +		(1 << 0) | /* PA1 */		\ +		(1 << 1) | /* PA2 */		\ +		(1 << 2) | /* PA3 */		\ +		(1 << 3) | /* PA6 */		\ +		(1 << 4) | /* PA7 */		\ +		(1 << 5) | /* PB0 */		\ +		(1 << 6) | /* PB1 */		\ +		(1 << 7) | /* PB3 */		\ +		(1 << 8) | /* PB4 */		\ +		(1 << 9) | /* PB5 */		\ +		(1 << 10) | /* PB10 */		\ +		(1 << 11) | /* PB11 */		\ +		(1 << 12) | /* PB12 */		\ +		(1 << 13) | /* PB13 */		\ +		(1 << 14) | /* PB14 */		\ +		(1 << 15) | /* PB15 */		\ +		(1 << 16) | /* PB8 */		\ +		(1 << 17) | /* PA15 */		\ +		(1 << 18) | /* PC0 */		\ +		(1 << 19) | /* PC1 */		\ +		(1 << 20) | /* PC2 */		\ +		(1 << 21) | /* PC3 */		\ +		(1 << 22) | /* PC4 */		\ +		(1 << 23) | /* PC5 */		\ +		(0 << 24) | /* PC6 */		\ +		(0 << 25) | /* PC7 */		\ +		(0 << 26) | /* PC8 */		\ +		(0 << 27) | /* PC9 */		\ +		(0 << 28) | /* PC10 or PD8 */	\ +		(0 << 29) | /* PC11 or PD9 */	\ +		(0 << 30) | /* PC12 or PD10 */	\ +		(0 << 31))  /* PD2 or PD11 */ + +#define AO_LCD_STM_SEG_ENABLED_1 (		\ +		(0 << 0) | /* PD12 */		\ +		(0 << 1) | /* PD13 */		\ +		(0 << 2) | /* PD14 */		\ +		(0 << 3) | /* PD15 */		\ +		(0 << 4) | /* PE0 */		\ +		(0 << 5) | /* PE1 */		\ +		(0 << 6) | /* PE2 */		\ +		(0 << 7))  /* PE3 */ + +#define AO_LCD_STM_COM_ENABLED (		\ +		(1 << 0) | /* PA8 */		\ +		(0 << 1) | /* PA9 */		\ +		(0 << 2) | /* PA10 */		\ +		(0 << 3) | /* PB9 */		\ +		(0 << 4) | /* PC10 */		\ +		(0 << 5) | /* PC11 */		\ +		(0 << 6)) /* PC12 */ + +#define AO_LCD_28_ON_C	0 + +#define AO_LCD_DUTY	STM_LCD_CR_DUTY_STATIC + +#define AO_LCD_PER_DIGIT	1 + +#define AO_LCD_DIGITS		3 +#define AO_LCD_SEGMENTS		8 + +#define AO_SEGMENT_MAP {			\ +		/* pad segments */		\ +		{ 0, 14 },			\ +		{ 0, 13 },			\ +		{ 0, 15 },			\ +		{ 0, 17 },			\ +		{ 0, 16 },			\ +		{ 0, 8 },			\ +		{ 0, 9 },			\ +		{ 0, 7 },			\ +		/* box1 segments */		\ +		{ 0, 10 },			\ +		{ 0, 6 },			\ +		{ 0, 11 },			\ +		{ 0, 12 },			\ +		{ 0, 21 },			\ +		{ 0, 19 },			\ +		{ 0, 20 },			\ +		{ 0, 18 },			\ +		/* box0 segments */		\ +		{ 0, 22 },			\ +		{ 0, 4 },			\ +		{ 0, 23 },			\ +		{ 0, 5 },			\ +		{ 0, 3 },			\ +		{ 0, 1 },			\ +		{ 0, 2 },			\ +		{ 0, 0 },			\ +} + +/* + * Use event queue for input devices + */ + +#define AO_EVENT		1 + +/* + * Knobs + */ + +#define AO_QUADRATURE_COUNT	2 + +#define AO_QUADRATURE_0_PORT	&stm_gpioe +#define AO_QUADRATURE_0_A	3 +#define AO_QUADRATURE_0_B	2 + +#define AO_QUADRATURE_PAD	0 + +#define AO_QUADRATURE_1_PORT	&stm_gpioe +#define AO_QUADRATURE_1_A	1 +#define AO_QUADRATURE_1_B	0 + +#define AO_QUADRATURE_BOX	1 +#define AO_QUADRATURE_DEBOUNCE	10 + +/* + * Buttons + */ + +#define AO_BUTTON_COUNT		2 +#define AO_BUTTON_MODE		AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_0_PORT	&stm_gpioe +#define AO_BUTTON_0		4 + +#define AO_BUTTON_ARM		0 + +#define AO_BUTTON_1_PORT	&stm_gpioe +#define AO_BUTTON_1		5 + +#define AO_BUTTON_FIRE		1 + +/* ADC */ + +#define HAS_ADC_SINGLE		1 +#define HAS_BATTERY_REPORT	1 + +struct ao_adc { +	int16_t		v_batt; +	int16_t		temp; +	int16_t		v_ref; +}; + +#if HAS_ADC_SINGLE +#define AO_ADC_DUMP(p) \ +	printf("batt: %5d temp: %5d v_ref: %5d\n", \ +	       (p)->v_batt, (p)->temp, (p)->v_ref) +#endif +#if HAS_ADC +#define AO_ADC_DUMP(p) \ +	printf("%5d: batt: %5d temp %5d v_ref %5d\n", \ +	       (p)->tick, (p)->adc.v_batt, (p)->adc.temp, (p)->adc.v_ref) +#endif + +#define HAS_ADC_TEMP		1 + +#define AO_ADC_V_BATT		0 +#define AO_ADC_V_BATT_PORT	(&stm_gpioa) +#define AO_ADC_V_BATT_PIN	0 + +#define AO_ADC_RCC_AHBENR	(1 << STM_RCC_AHBENR_GPIOAEN) + +#define AO_ADC_PIN0_PORT	AO_ADC_V_BATT_PORT +#define AO_ADC_PIN0_PIN		AO_ADC_V_BATT_PIN + +#define AO_ADC_SQ1		AO_ADC_V_BATT +#define AO_ADC_SQ2		STM_ADC_SQ_TEMP +#define AO_ADC_SQ3		STM_ADC_SQ_V_REF + +#define AO_NUM_ADC		3 + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS	15	/* 15k */ +#define AO_BATTERY_DIV_MINUS	27	/* 27k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV	33 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v0.2-cc1200/ao_telelco.c b/src/telelco-v0.2-cc1200/ao_telelco.c new file mode 100644 index 00000000..3266da00 --- /dev/null +++ b/src/telelco-v0.2-cc1200/ao_telelco.c @@ -0,0 +1,79 @@ +/* + * Copyright © 2011 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_packet.h> +#include <ao_companion.h> +#include <ao_profile.h> +#include <ao_pyro.h> +#include <ao_aes.h> +#include <ao_seven_segment.h> +#include <ao_quadrature.h> +#include <ao_button.h> +#include <ao_lco.h> +#include <ao_lco_cmd.h> +#include <ao_radio_cmac_cmd.h> +#include <ao_eeprom.h> +#if HAS_ADC_SINGLE +#include <ao_adc_single.h> +#endif +#if HAS_ADC +#include <ao_adc.h> +#endif + +int +main(void) +{ +	ao_clock_init(); +	ao_task_init(); +	ao_timer_init(); +	ao_dma_init(); + +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_GREEN); + + +	ao_spi_init(); +	ao_exti_init(); + +	ao_beep_init(); +	ao_cmd_init(); + +	ao_lcd_stm_init(); +	ao_seven_segment_init(); +	ao_quadrature_init(); +	ao_button_init(); + +	ao_adc_single_init(); + +	ao_eeprom_init(); + +	ao_radio_init(); + +	ao_usb_init(); + +	ao_config_init(); + +	ao_lco_init(); +	ao_lco_cmd_init(); +//	ao_radio_cmac_cmd_init(); + +	ao_start_scheduler(); +	return 0; +} diff --git a/src/telelco-v0.2-cc1200/flash-loader/.gitignore b/src/telelco-v0.2-cc1200/flash-loader/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelco-v0.2-cc1200/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelco-v0.2-cc1200/flash-loader/Makefile b/src/telelco-v0.2-cc1200/flash-loader/Makefile new file mode 100644 index 00000000..679e61ba --- /dev/null +++ b/src/telelco-v0.2-cc1200/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telelco-v0.2 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telelco-v0.2-cc1200/flash-loader/ao_pins.h b/src/telelco-v0.2-cc1200/flash-loader/ao_pins.h new file mode 100644 index 00000000..72f840c0 --- /dev/null +++ b/src/telelco-v0.2-cc1200/flash-loader/ao_pins.h @@ -0,0 +1,35 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Arm switch. Press at power on to get boot loader */ + +#define AO_BOOT_PIN		1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioe +#define AO_BOOT_APPLICATION_PIN		4 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 8c1ced6c..8279cac1 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -64,6 +64,7 @@ ALTOS_SRC = \  	ao_button.c \  	ao_event.c \  	ao_lco.c \ +	ao_lco_bits.c \  	ao_lco_cmd.c \  	ao_lco_func.c \  	ao_radio_cmac_cmd.c diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index b90fca8b..f0da4fe4 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -253,6 +253,7 @@  #define AO_QUADRATURE_1_B	0  #define AO_QUADRATURE_BOX	1 +#define AO_QUADRATURE_DEBOUNCE	10  /*   * Buttons diff --git a/src/telelco-v0.3/Makefile b/src/telelco-v0.3/Makefile index 0bb0f9dc..c2592bf8 100644 --- a/src/telelco-v0.3/Makefile +++ b/src/telelco-v0.3/Makefile @@ -65,6 +65,7 @@ ALTOS_SRC = \  	ao_button.c \  	ao_event.c \  	ao_lco.c \ +	ao_lco_bits.c \  	ao_lco_cmd.c \  	ao_lco_func.c \  	ao_radio_cmac_cmd.c diff --git a/src/telelco-v0.3/ao_pins.h b/src/telelco-v0.3/ao_pins.h index dd4aaafb..6023739c 100644 --- a/src/telelco-v0.3/ao_pins.h +++ b/src/telelco-v0.3/ao_pins.h @@ -54,6 +54,8 @@  #define HAS_RADIO_RATE		1  #define HAS_TELEMETRY		0  #define HAS_AES			1 +#define HAS_STATIC_TEST		0 +  #define HAS_SPI_1		0  #define SPI_1_PA5_PA6_PA7	0 @@ -250,6 +252,7 @@  #define AO_QUADRATURE_1_B	0  #define AO_QUADRATURE_BOX	1 +#define AO_QUADRATURE_DEBOUNCE	10  /*   * Buttons diff --git a/src/telelco-v2.0/.gitignore b/src/telelco-v2.0/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelco-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelco-v2.0/Makefile b/src/telelco-v2.0/Makefile new file mode 100644 index 00000000..43295fd3 --- /dev/null +++ b/src/telelco-v2.0/Makefile @@ -0,0 +1,106 @@ +# +# AltOS build for TeleLCO v2.0 +# +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_boot.h \ +	ao_companion.h \ +	ao_data.h \ +	ao_sample.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_seven_segment.h \ +	ao_lco.h \ +	ao_lco_cmd.h \ +	ao_lco_func.h \ +	ao_radio_spi.h \ +	ao_radio_cmac.h \ +	ao_cc1200_CC1200.h \ +	ao_cc1200.h \ +	stm32l.h + +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_beep_stm.c \ +	ao_eeprom_stm.c \ +	ao_adc_single_stm.c \ +	ao_convert_volt.c \ +	ao_fast_timer.c \ +	ao_lcd_stm.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_cc1200.c \ +	ao_radio_cmac.c \ +	ao_aes.c \ +	ao_aes_tables.c \ +	ao_fec_tx.c \ +	ao_fec_rx.c \ +	ao_seven_segment.c \ +	ao_quadrature.c \ +	ao_button.c \ +	ao_event.c \ +	ao_lco_bits.c \ +	ao_lco_v2.c \ +	ao_lco_cmd.c \ +	ao_lco_func.c \ +	ao_radio_cmac_cmd.c + +PRODUCT=TeleLCO-v2.0 +PRODUCT_DEF=-DTELELCO +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telelco-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telelco.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(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 $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c new file mode 100644 index 00000000..a9933d59 --- /dev/null +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -0,0 +1,304 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_lco.h> +#include <ao_event.h> +#include <ao_seven_segment.h> +#include <ao_quadrature.h> +#include <ao_radio_cmac.h> +#include <ao_adc_single.h> + +#define AO_LCO_PAD_DIGIT	0 +#define AO_LCO_BOX_DIGIT_1	1 +#define AO_LCO_BOX_DIGIT_10	2 + +#define AO_LCO_DRAG_RACE_START_TIME	AO_SEC_TO_TICKS(5) +#define AO_LCO_DRAG_RACE_STOP_TIME	AO_SEC_TO_TICKS(2) + +/* UI values */ +static uint8_t	ao_lco_select_mode; +#define AO_LCO_SELECT_PAD	0 +#define AO_LCO_SELECT_BOX	1 + +static uint8_t	ao_lco_display_mutex; + +void +ao_lco_show_pad(uint8_t pad) +{ +	ao_mutex_get(&ao_lco_display_mutex); +	ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad | (ao_lco_drag_race << 4)); +	ao_mutex_put(&ao_lco_display_mutex); +} + +#define SEVEN_SEGMENT_d		((0 << 0) |	\ +				 (0 << 1) |	\ +				 (1 << 2) |	\ +				 (1 << 3) |	\ +				 (1 << 4) |	\ +				 (1 << 5) |	\ +				 (1 << 6)) + + +#define SEVEN_SEGMENT_r		((0 << 0) |	\ +				 (0 << 1) |	\ +				 (0 << 2) |	\ +				 (1 << 3) |	\ +				 (1 << 4) |	\ +				 (0 << 5) |	\ +				 (0 << 6)) + +void +ao_lco_show_box(uint16_t box) +{ +	ao_mutex_get(&ao_lco_display_mutex); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10 | (ao_lco_drag_race << 4)); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, box / 10 | (ao_lco_drag_race << 4)); +	ao_mutex_put(&ao_lco_display_mutex); +} + +static void +ao_lco_show_voltage(uint16_t decivolts) +{ +	uint8_t	tens, ones, tenths; + +	PRINTD("voltage %d\n", decivolts); +	tenths = decivolts % 10; +	ones = (decivolts / 10) % 10; +	tens = (decivolts / 100) % 10; +	ao_mutex_get(&ao_lco_display_mutex); +	ao_seven_segment_set(AO_LCO_PAD_DIGIT, tenths); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, ones | 0x10); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, tens); +	ao_mutex_put(&ao_lco_display_mutex); +} + +void +ao_lco_show(void) +{ +	if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) { +		ao_lco_show_voltage(ao_pad_query.battery); +	} else { +		ao_lco_show_pad(ao_lco_pad); +		ao_lco_show_box(ao_lco_box); +	} +} + +uint8_t +ao_lco_box_present(uint16_t box) +{ +	if (box >= AO_PAD_MAX_BOXES) +		return 0; +	return (ao_lco_box_mask[AO_LCO_MASK_ID(box)] >> AO_LCO_MASK_SHIFT(box)) & 1; +} + +static void +ao_lco_set_select(void) +{ +	if (ao_lco_armed) { +		ao_led_off(AO_LED_PAD); +		ao_led_off(AO_LED_BOX); +	} else { +		switch (ao_lco_select_mode) { +		case AO_LCO_SELECT_PAD: +			ao_led_off(AO_LED_BOX); +			ao_led_on(AO_LED_PAD); +			break; +		case AO_LCO_SELECT_BOX: +			ao_led_off(AO_LED_PAD); +			ao_led_on(AO_LED_BOX); +			break; +		default: +			break; +		} +	} +} + +static void +ao_lco_step_box(int8_t dir) +{ +	int16_t 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_max_box; +		if (new_box == ao_lco_box) +			break; +	} while (!ao_lco_box_present(new_box)); +	ao_lco_set_box(new_box); +} + +static struct ao_task	ao_lco_drag_task; + +static void +ao_lco_drag_monitor(void) +{ +	uint16_t	delay = ~0; +	uint16_t	now; + +	ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +	for (;;) { +		PRINTD("Drag monitor count %d delay %d\n", ao_lco_drag_beep_count, delay); +		if (delay == (uint16_t) ~0) +			ao_sleep(&ao_lco_drag_beep_count); +		else +			ao_sleep_for(&ao_lco_drag_beep_count, delay); + +		delay = ~0; +		now = ao_time(); +		delay = ao_lco_drag_warn_check(now, delay); +		delay = ao_lco_drag_beep_check(now, delay); +	} +} + +static void +ao_lco_input(void) +{ +	static struct ao_event	event; + +	for (;;) { +		ao_event_get(&event); +		PRINTD("event type %d unit %d value %d\n", +		       event.type, event.unit, event.value); +		switch (event.type) { +		case AO_EVENT_QUADRATURE: +			switch (event.unit) { +			case AO_QUADRATURE_SELECT: +				if (!ao_lco_armed) { +					switch (ao_lco_select_mode) { +					case AO_LCO_SELECT_PAD: +						ao_lco_step_pad((int8_t) event.value); +						break; +					case AO_LCO_SELECT_BOX: +						ao_lco_step_box((int8_t) event.value); +						break; +					default: +						break; +					} +				} +				break; +			} +			break; +		case AO_EVENT_BUTTON: +			switch (event.unit) { +			case AO_BUTTON_ARM: +				ao_lco_set_armed(event.value); +				ao_lco_set_select(); +				break; +			case AO_BUTTON_FIRE: +				if (ao_lco_armed) +					ao_lco_set_firing(event.value); +				break; +			case AO_BUTTON_DRAG_SELECT: +				if (event.value) +					ao_lco_toggle_drag(); +				break; +			case AO_BUTTON_DRAG_MODE: +				if (event.value) +					ao_lco_drag_enable(); +				else +					ao_lco_drag_disable(); +				break; +			case AO_BUTTON_ENCODER_SELECT: +				if (event.value) { +					if (!ao_lco_armed) { +						ao_lco_select_mode = 1 - ao_lco_select_mode; +						ao_lco_set_select(); +					} +				} +				break; +			} +			break; +		} +	} +} + +/* + * Light up everything for a second at power on to let the user + * visually inspect the system for correct operation + */ +static void +ao_lco_display_test() +{ +	ao_mutex_get(&ao_lco_display_mutex); +	ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, 8 | 0x10); +	ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 8 | 0x10); +	ao_mutex_put(&ao_lco_display_mutex); +	ao_led_on(LEDS_AVAILABLE); +	ao_delay(AO_MS_TO_TICKS(1000)); +	ao_led_off(LEDS_AVAILABLE); +} + +static void +ao_lco_batt_voltage(void) +{ +	struct ao_adc	packet; +	int16_t		decivolt; + +	ao_adc_single_get(&packet); +	decivolt = ao_battery_decivolt(packet.v_batt); +	ao_lco_show_voltage(decivolt); +	ao_delay(AO_MS_TO_TICKS(1000)); +} + +static struct ao_task ao_lco_input_task; +static struct ao_task ao_lco_monitor_task; +static struct ao_task ao_lco_arm_warn_task; +static struct ao_task ao_lco_igniter_status_task; + +static void +ao_lco_main(void) +{ +	ao_lco_display_test(); +	ao_lco_batt_voltage(); +	ao_lco_search(); +	ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); +	ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn"); +	ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status"); +	ao_add_task(&ao_lco_drag_task, ao_lco_drag_monitor, "drag race"); +	ao_lco_monitor(); +} + +#if DEBUG +void +ao_lco_set_debug(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_status == ao_cmd_success) +		ao_lco_debug = ao_cmd_lex_i != 0; +} + +__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 + +void +ao_lco_init(void) +{ +	ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor"); +#if DEBUG +	ao_cmd_register(&ao_lco_cmds[0]); +#endif +} diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h new file mode 100644 index 00000000..95998dc7 --- /dev/null +++ b/src/telelco-v2.0/ao_pins.h @@ -0,0 +1,398 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_ + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC		40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	1 +#define USE_EEPROM_CONFIG	1 +#define USE_STORAGE_CONFIG	0 +#define HAS_USB			1 +#define HAS_BEEP		1 +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0 +#define HAS_AES			1 +#define HAS_STATIC_TEST		0 + +#define HAS_SPI_1		0 +#define SPI_1_PA5_PA6_PA7	0 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	0 + +#define HAS_SPI_2		1	/* CC1200 */ +#define SPI_2_PB13_PB14_PB15	0 +#define SPI_2_PD1_PD3_PD4	1 +#define SPI_2_GPIO		(&stm_gpiod) +#define SPI_2_SCK		1 +#define SPI_2_MISO		3 +#define SPI_2_MOSI		4 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_I2C_1		0 + +#define HAS_I2C_2		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define FAST_TIMER_FREQ		10000	/* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 	5695733 + +#define AO_CC1200_SPI_CS_PORT	(&stm_gpiod) +#define AO_CC1200_SPI_CS_PIN	0 +#define AO_CC1200_SPI_BUS	AO_SPI_2_PD1_PD3_PD4 +#define AO_CC1200_SPI		stm_spi2 +#define AO_CC1200_SPI_SPEED	AO_SPI_SPEED_FAST + +#define AO_CC1200_INT_PORT		(&stm_gpiod) +#define AO_CC1200_INT_PIN		(5) + +#define AO_CC1200_INT_GPIO	2 +#define AO_CC1200_INT_GPIO_IOCFG	CC1200_IOCFG2 + +#define LOW_LEVEL_DEBUG		0 + +#define LED_PER_LED		1 +#define LED_TYPE		uint16_t + +#define LED_ENABLE_BITS		((1 << STM_RCC_AHBENR_GPIOAEN) |	\ +				 (1 << STM_RCC_AHBENR_GPIOCEN) |	\ +				 (1 << STM_RCC_AHBENR_GPIODEN) |	\ +				 (1 << STM_RCC_AHBENR_GPIOEEN)) + +/* PC7 - PC9, LED 0 - 2 */ +#define LED_0_PORT		(&stm_gpioc) +#define LED_0_PIN		7 +#define LED_1_PORT		(&stm_gpioc) +#define LED_1_PIN		8 +#define LED_2_PORT		(&stm_gpioc) +#define LED_2_PIN		9 + +/* PD8 - PD10, LED 3 - 5 */ +#define LED_3_PORT		(&stm_gpiod) +#define LED_3_PIN		8 +#define LED_4_PORT		(&stm_gpiod) +#define LED_4_PIN		9 +#define LED_5_PORT		(&stm_gpiod) +#define LED_5_PIN		10 + +/* PE2 - PE11 (not PE6), LED 6-14 */ +#define LED_6_PORT		(&stm_gpioe) +#define LED_6_PIN		2 +#define LED_7_PORT		(&stm_gpioe) +#define LED_7_PIN		3 +#define LED_8_PORT		(&stm_gpioe) +#define LED_8_PIN		4 +#define LED_9_PORT		(&stm_gpioe) +#define LED_9_PIN		5 +#define LED_10_PORT		(&stm_gpioe) +#define LED_10_PIN		7 +#define LED_11_PORT		(&stm_gpioe) +#define LED_11_PIN		8 +#define LED_12_PORT		(&stm_gpioe) +#define LED_12_PIN		9 +#define LED_13_PORT		(&stm_gpioe) +#define LED_13_PIN		10 +#define LED_14_PORT		(&stm_gpioe) +#define LED_14_PIN		11 + +/* PA5, LED 15 */ +#define LED_15_PORT		(&stm_gpioa) +#define LED_15_PIN		5 + +#define LED_PIN_RED		0 +#define LED_PIN_AMBER		1 +#define LED_PIN_GREEN		2 +#define LED_PIN_BOX		3 +#define LED_PIN_PAD		4 +#define LED_PIN_DRAG		5 +#define LED_PIN_CONTINUITY_7	6 +#define LED_PIN_CONTINUITY_6	7 +#define LED_PIN_CONTINUITY_5	8 +#define LED_PIN_CONTINUITY_4	9 +#define LED_PIN_CONTINUITY_3	10 +#define LED_PIN_CONTINUITY_2	11 +#define LED_PIN_CONTINUITY_1	12 +#define LED_PIN_CONTINUITY_0	13 +#define LED_PIN_REMOTE_ARM	14 +#define LED_PIN_FIRE		15 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_AMBER		(1 << LED_PIN_AMBER) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) +#define AO_LED_BOX		(1 << LED_PIN_BOX) +#define AO_LED_PAD		(1 << LED_PIN_PAD) +#define AO_LED_DRAG		(1 << LED_PIN_DRAG) +#define AO_LED_CONTINUITY_7	(1 << LED_PIN_CONTINUITY_7) +#define AO_LED_CONTINUITY_6	(1 << LED_PIN_CONTINUITY_6) +#define AO_LED_CONTINUITY_5	(1 << LED_PIN_CONTINUITY_5) +#define AO_LED_CONTINUITY_4	(1 << LED_PIN_CONTINUITY_4) +#define AO_LED_CONTINUITY_3	(1 << LED_PIN_CONTINUITY_3) +#define AO_LED_CONTINUITY_2	(1 << LED_PIN_CONTINUITY_2) +#define AO_LED_CONTINUITY_1	(1 << LED_PIN_CONTINUITY_1) +#define AO_LED_CONTINUITY_0	(1 << LED_PIN_CONTINUITY_0) +#define AO_LED_CONTINUITY_NUM	8 +#define AO_LED_REMOTE_ARM	(1 << LED_PIN_REMOTE_ARM) +#define AO_LED_FIRE		(1 << LED_PIN_FIRE) + +#define LEDS_AVAILABLE		(AO_LED_RED |		\ +				 AO_LED_AMBER |		\ +				 AO_LED_GREEN |		\ +				 AO_LED_BOX |		\ +				 AO_LED_PAD |		\ +				 AO_LED_DRAG |		\ +				 AO_LED_CONTINUITY_7 |	\ +				 AO_LED_CONTINUITY_6 |	\ +				 AO_LED_CONTINUITY_5 |	\ +				 AO_LED_CONTINUITY_4 |	\ +				 AO_LED_CONTINUITY_3 |	\ +				 AO_LED_CONTINUITY_2 |	\ +				 AO_LED_CONTINUITY_1 |	\ +				 AO_LED_CONTINUITY_0 |	\ +				 AO_LED_REMOTE_ARM |	\ +				 AO_LED_FIRE) + +/* LCD displays */ + +#define LCD_DEBUG		0 +#define SEVEN_SEGMENT_DEBUG	0 + +#define AO_LCD_STM_SEG_ENABLED_0 (		\ +		(1 << 0) | /* PA1 */		\ +		(1 << 1) | /* PA2 */		\ +		(1 << 2) | /* PA3 */		\ +		(1 << 3) | /* PA6 */		\ +		(1 << 4) | /* PA7 */		\ +		(1 << 5) | /* PB0 */		\ +		(1 << 6) | /* PB1 */		\ +		(1 << 7) | /* PB3 */		\ +		(1 << 8) | /* PB4 */		\ +		(1 << 9) | /* PB5 */		\ +		(1 << 10) | /* PB10 */		\ +		(1 << 11) | /* PB11 */		\ +		(1 << 12) | /* PB12 */		\ +		(1 << 13) | /* PB13 */		\ +		(1 << 14) | /* PB14 */		\ +		(1 << 15) | /* PB15 */		\ +		(1 << 16) | /* PB8 */		\ +		(1 << 17) | /* PA15 */		\ +		(1 << 18) | /* PC0 */		\ +		(1 << 19) | /* PC1 */		\ +		(1 << 20) | /* PC2 */		\ +		(1 << 21) | /* PC3 */		\ +		(1 << 22) | /* PC4 */		\ +		(1 << 23) | /* PC5 */		\ +		(0 << 24) | /* PC6 */		\ +		(0 << 25) | /* PC7 */		\ +		(0 << 26) | /* PC8 */		\ +		(0 << 27) | /* PC9 */		\ +		(0 << 28) | /* PC10 or PD8 */	\ +		(0 << 29) | /* PC11 or PD9 */	\ +		(0 << 30) | /* PC12 or PD10 */	\ +		(0 << 31))  /* PD2 or PD11 */ + +#define AO_LCD_STM_SEG_ENABLED_1 (		\ +		(0 << 0) | /* PD12 */		\ +		(0 << 1) | /* PD13 */		\ +		(0 << 2) | /* PD14 */		\ +		(0 << 3) | /* PD15 */		\ +		(0 << 4) | /* PE0 */		\ +		(0 << 5) | /* PE1 */		\ +		(0 << 6) | /* PE2 */		\ +		(0 << 7))  /* PE3 */ + +#define AO_LCD_STM_COM_ENABLED (		\ +		(1 << 0) | /* PA8 */		\ +		(0 << 1) | /* PA9 */		\ +		(0 << 2) | /* PA10 */		\ +		(0 << 3) | /* PB9 */		\ +		(0 << 4) | /* PC10 */		\ +		(0 << 5) | /* PC11 */		\ +		(0 << 6)) /* PC12 */ + +#define AO_LCD_28_ON_C	0 + +#define AO_LCD_DUTY	STM_LCD_CR_DUTY_STATIC + +#define AO_LCD_PER_DIGIT	1 + +#define AO_LCD_DIGITS		3 +#define AO_LCD_SEGMENTS		8 + +#define AO_SEGMENT_MAP {			\ +		/* pad segments */		\ +		{ 0, 14 },			\ +		{ 0, 13 },			\ +		{ 0, 15 },			\ +		{ 0, 17 },			\ +		{ 0, 16 },			\ +		{ 0, 8 },			\ +		{ 0, 9 },			\ +		{ 0, 7 },			\ +		/* box1 segments */		\ +		{ 0, 10 },			\ +		{ 0, 6 },			\ +		{ 0, 11 },			\ +		{ 0, 12 },			\ +		{ 0, 21 },			\ +		{ 0, 19 },			\ +		{ 0, 20 },			\ +		{ 0, 18 },			\ +		/* box0 segments */		\ +		{ 0, 22 },			\ +		{ 0, 4 },			\ +		{ 0, 23 },			\ +		{ 0, 5 },			\ +		{ 0, 3 },			\ +		{ 0, 1 },			\ +		{ 0, 2 },			\ +		{ 0, 0 },			\ +} + +/* + * Use event queue for input devices + */ + +#define AO_EVENT		1 + +/* + * Knobs + */ + +#define AO_QUADRATURE_COUNT	1 +#define AO_QUADRATURE_DEBOUNCE	0 +#define AO_QUADRATURE_SINGLE_CODE	1 + +#define AO_QUADRATURE_0_PORT	&stm_gpioe +#define AO_QUADRATURE_0_A	15 +#define AO_QUADRATURE_0_B	14 + +#define AO_QUADRATURE_SELECT	0 + +/* + * Buttons + */ + +#define AO_BUTTON_COUNT		9 +#define AO_BUTTON_MODE		AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_DRAG_MODE	0 +#define AO_BUTTON_0_PORT	&stm_gpioe +#define AO_BUTTON_0		1 + +#define AO_BUTTON_DRAG_SELECT	1 +#define AO_BUTTON_1_PORT	&stm_gpioe +#define AO_BUTTON_1		0 + +#define AO_BUTTON_SPARE1       	2 +#define AO_BUTTON_2_PORT	&stm_gpiob +#define AO_BUTTON_2		9 + +#define AO_BUTTON_SPARE2      	3 +#define AO_BUTTON_3_PORT	&stm_gpiob +#define AO_BUTTON_3		7 + +#define AO_BUTTON_SPARE3       	4 +#define AO_BUTTON_4_PORT	&stm_gpiob +#define AO_BUTTON_4		6 + +#define AO_BUTTON_ARM		5 +#define AO_BUTTON_5_PORT	&stm_gpioe +#define AO_BUTTON_5		12 + +#define AO_BUTTON_FIRE		6 +#define AO_BUTTON_6_PORT	&stm_gpioa +#define AO_BUTTON_6		4 + +#define AO_BUTTON_SPARE4	7 +#define AO_BUTTON_7_PORT	&stm_gpiod +#define AO_BUTTON_7		11 + +#define AO_BUTTON_ENCODER_SELECT	8 +#define AO_BUTTON_8_PORT	&stm_gpioe +#define AO_BUTTON_8		13 + +/* ADC */ + +struct ao_adc { +	int16_t		v_batt; +}; + +#define AO_ADC_DUMP(p) \ +	printf("batt: %5d\n", (p)->v_batt) + +#define HAS_ADC_SINGLE		1 +#define HAS_ADC_TEMP		0 +#define HAS_BATTERY_REPORT	1 + +#define AO_ADC_V_BATT		0 +#define AO_ADC_V_BATT_PORT	(&stm_gpioa) +#define AO_ADC_V_BATT_PIN	0 + +#define AO_ADC_RCC_AHBENR	(1 << STM_RCC_AHBENR_GPIOAEN) + +#define AO_ADC_PIN0_PORT	AO_ADC_V_BATT_PORT +#define AO_ADC_PIN0_PIN		AO_ADC_V_BATT_PIN + +#define AO_ADC_SQ1		AO_ADC_V_BATT + +#define AO_NUM_ADC		1 + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS	15	/* 15k */ +#define AO_BATTERY_DIV_MINUS	27	/* 27k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV	33 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v2.0/ao_telelco.c b/src/telelco-v2.0/ao_telelco.c new file mode 100644 index 00000000..9693c657 --- /dev/null +++ b/src/telelco-v2.0/ao_telelco.c @@ -0,0 +1,73 @@ +/* + * Copyright © 2011 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_packet.h> +#include <ao_companion.h> +#include <ao_profile.h> +#include <ao_pyro.h> +#include <ao_aes.h> +#include <ao_seven_segment.h> +#include <ao_quadrature.h> +#include <ao_button.h> +#include <ao_lco.h> +#include <ao_lco_cmd.h> +#include <ao_radio_cmac_cmd.h> +#include <ao_eeprom.h> +#include <ao_adc_single.h> + +int +main(void) +{ +	ao_clock_init(); +	 +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_GREEN); +	ao_task_init(); + +	ao_timer_init(); + +	ao_spi_init(); +	ao_dma_init(); +	ao_exti_init(); +	ao_adc_single_init(); + +	ao_beep_init(); +	ao_cmd_init(); + +	ao_lcd_stm_init(); +	ao_seven_segment_init(); +	ao_quadrature_init(); +	ao_button_init(); + +	ao_eeprom_init(); +	 +	ao_radio_init(); + +	ao_usb_init(); + +	ao_config_init(); +	 +	ao_lco_init(); +	ao_lco_cmd_init(); +//	ao_radio_cmac_cmd_init(); +	 +	ao_start_scheduler(); +	return 0; +} diff --git a/src/telelco-v2.0/flash-loader/.gitignore b/src/telelco-v2.0/flash-loader/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelco-v2.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelco-v2.0/flash-loader/Makefile b/src/telelco-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..b4ec2dad --- /dev/null +++ b/src/telelco-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telelco-v2.0 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telelco-v2.0/flash-loader/ao_pins.h b/src/telelco-v2.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..2292f03c --- /dev/null +++ b/src/telelco-v2.0/flash-loader/ao_pins.h @@ -0,0 +1,35 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Drag race select button. Press at power on to get boot loader */ + +#define AO_BOOT_PIN		1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioe +#define AO_BOOT_APPLICATION_PIN		0 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelcotwo-v0.1/Makefile b/src/telelcotwo-v0.1/Makefile index 42188bb2..c68f3eb5 100644 --- a/src/telelcotwo-v0.1/Makefile +++ b/src/telelcotwo-v0.1/Makefile @@ -58,6 +58,7 @@ ALTOS_SRC = \  	ao_button.c \  	ao_event.c \  	ao_lco_two.c \ +	ao_lco_bits.c \  	ao_lco_func.c \  	ao_lco_cmd.c \  	ao_radio_cmac_cmd.c diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h index 60e94c67..1941e03d 100644 --- a/src/telelcotwo-v0.1/ao_pins.h +++ b/src/telelcotwo-v0.1/ao_pins.h @@ -141,6 +141,8 @@  				 AO_LED_CONTINUITY_0 |	\  				 AO_LED_REMOTE_ARM) +#define AO_LCO_DRAG		0 +  /*   * Use event queue for input devices   */ diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 2d862f82..746a6814 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -305,7 +305,7 @@ struct ao_task {  #define AO_MS_TO_TICKS(ms)	((ms) / 10)  #define AO_SEC_TO_TICKS(s)	((s) * 100) -#define AO_FLIGHT_TEST +#define AO_FLIGHT_TEST	1  int	ao_flight_debug; @@ -438,10 +438,6 @@ static uint16_t	pyros_fired;  static struct ao_mpu6000_sample	ao_ground_mpu6000;  #endif -#if HAS_ACCEL -int ao_error_h_sq_avg; -#endif -  void  ao_test_exit(void)  { @@ -504,7 +500,7 @@ ao_insert(void)  	ao_data_ring[ao_data_head] = ao_data_static;  	if (ao_flight_state != ao_flight_startup) {  #if HAS_ACCEL -		double  accel = ((ao_flight_ground_accel - ao_data_accel_cook(&ao_data_static)) * GRAVITY * 2.0) / +		double  accel = ((ao_flight_ground_accel - ao_data_accel(&ao_data_static)) * GRAVITY * 2.0) /  			(ao_config.accel_minus_g - ao_config.accel_plus_g);  #else  		double	accel = 0.0; @@ -515,7 +511,12 @@ ao_insert(void)  			tick_offset = -ao_data_static.tick;  		if ((prev_tick - ao_data_static.tick) > 0x400)  			tick_offset += 65536; -		simple_speed += accel * (ao_data_static.tick - prev_tick) / 100.0; +		if (prev_tick) { +			int ticks = ao_data_static.tick - prev_tick; +			if (ticks < 0) +				ticks += 65536; +			simple_speed += accel * ticks / 100.0; +		}  		prev_tick = ao_data_static.tick;  		time = (double) (ao_data_static.tick + tick_offset) / 100; @@ -653,7 +654,7 @@ ao_insert(void)  #if 1  			printf("%7.2f height %8.2f accel %8.3f accel_speed %8.3f " -			       "state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d" +			       "state %d k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d"  #if TELEMEGA  			       " angle %5d "  			       "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d " @@ -663,7 +664,7 @@ ao_insert(void)  			       height,  			       accel,  			       simple_speed > -100.0 ? simple_speed : -100.0, -			       ao_state_names[ao_flight_state], +			       ao_flight_state * 10,  			       ao_k_height / 65536.0,  			       ao_k_speed / 65536.0 / 16.0,  			       ao_k_accel / 65536.0 / 16.0, diff --git a/src/test/plottest b/src/test/plottest index 95337f10..5b30cfa5 100755 --- a/src/test/plottest +++ b/src/test/plottest @@ -1,17 +1,33 @@ +#!/bin/bash + +LINEWIDTH=2 +  gnuplot -persist << EOF +set title "$1"  set ylabel "altitude (m)"  set y2label "velocity (m/s), acceleration(m/s²)"  set xlabel "time (s)"  set xtics border out nomirror  set ytics border out nomirror  set y2tics border out nomirror -plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ -"$1" using 1:5 with lines axes x1y2 title "raw accel",\ -"$1" using 1:7 with lines axes x1y2 title "accel speed",\ -"$1" using 1:11 with lines axes x1y1 title "height",\ -"$1" using 1:13 with lines axes x1y2 title "speed",\ -"$1" using 1:15 with lines axes x1y2 title "accel",\ -"$1" using 1:19 with lines axes x1y1 title "drogue",\ -"$1" using 1:21 with lines axes x1y1 title "main",\ -"$1" using 1:23 with lines axes x1y1 title "error" +set style line 1 linewidth $LINEWIDTH +set style line 2 linewidth $LINEWIDTH +set style line 3 linewidth $LINEWIDTH +set style line 4 linewidth $LINEWIDTH +set style line 5 linewidth $LINEWIDTH +set style line 6 linewidth $LINEWIDTH +set style line 7 linewidth $LINEWIDTH dashtype 2 +set style line 8 linewidth $LINEWIDTH dashtype 2 +set style line 9 linewidth $LINEWIDTH dashtype 2 +set style line 10 linewidth $LINEWIDTH dashtype 2 +plot "$1" using 1:3 with lines axes x1y1 title "raw height" ls 1,\ +"$1" using 1:5 with lines axes x1y2 title "raw accel" ls 2,\ +"$1" using 1:7 with lines axes x1y2 title "accel speed" ls 3,\ +"$1" using 1:11 with lines axes x1y1 title "height" ls 4,\ +"$1" using 1:13 with lines axes x1y2 title "speed" ls 5,\ +"$1" using 1:15 with lines axes x1y2 title "accel" ls 6,\ +"$1" using 1:19 with lines axes x1y1 title "drogue" ls 7,\ +"$1" using 1:21 with lines axes x1y1 title "main" ls 8,\ +"$1" using 1:23 with lines axes x1y1 title "error" ls 9,\ +"$1" using 1:9 with lines axes x1y2 title "state" ls 10  EOF diff --git a/src/tmgps-v2.0/.gitignore b/src/tmgps-v2.0/.gitignore new file mode 100644 index 00000000..611e845e --- /dev/null +++ b/src/tmgps-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +tmgps-*.elf diff --git a/src/tmgps-v2.0/Makefile b/src/tmgps-v2.0/Makefile new file mode 100644 index 00000000..9e3965c6 --- /dev/null +++ b/src/tmgps-v2.0/Makefile @@ -0,0 +1,117 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_boot.h \ +	ao_companion.h \ +	ao_data.h \ +	ao_sample.h \ +	ao_pins.h \ +	ao_kalman.h \ +	ao_product.h \ +	ao_cc1120_CC1120.h \ +	ao_profile.h \ +	ao_task.h \ +	ao_whiten.h \ +	ao_sample_profile.h \ +	ao_mpu.h \ +	stm32l.h \ +	Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +#	ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +MATH_SRC=\ +	ef_log.c + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_serial_stm.c \ +	ao_gps_ublox.c \ +	ao_gps_show.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_cc1120.c \ +	ao_fec_tx.c \ +	ao_fec_rx.c \ +	ao_data.c \ +	ao_adc_stm.c \ +	ao_storage.c \ +	ao_m25.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_eeprom_stm.c \ +	ao_convert_volt.c \ +	ao_log.c \ +	ao_log_gps.c \ +	ao_distance.c \ +	ao_sqrt.c \ +	ao_tracker.c \ +	ao_telemetry.c \ +	ao_aprs.c \ +	$(MATH_SRC) \ +	$(PROFILE) \ +	$(SAMPLE_PROFILE) \ +	$(STACK_GUARD) + +PRODUCT=TMGPS-v2.0 +PRODUCT_DEF=-DTMGPS_V_2_0 +IDPRODUCT=0x0025 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=tmgps-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_tmgps.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +../altitude-pa.h: make-altitude-pa +	nickle $< > $@ + +$(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 $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/tmgps-v2.0/ao_pins.h b/src/tmgps-v2.0/ao_pins.h new file mode 100644 index 00000000..b4dcc10c --- /dev/null +++ b/src/tmgps-v2.0/ao_pins.h @@ -0,0 +1,236 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_TASK_QUEUE		1 + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1		0 +#define USE_SERIAL_1_STDIN	0 +#define SERIAL_1_PB6_PB7	0 +#define SERIAL_1_PA9_PA10	1 + +#define HAS_SERIAL_2		0 +#define USE_SERIAL_2_STDIN	0 +#define SERIAL_2_PA2_PA3	0 +#define SERIAL_2_PD5_PD6	0 + +#define HAS_SERIAL_3		1 +#define USE_SERIAL_3_STDIN	0 +#define SERIAL_3_PB10_PB11	1 +#define SERIAL_3_PC10_PC11	0 +#define SERIAL_3_PD8_PD9	0 + +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	(512 * 1024) +#define AO_CONFIG_MAX_SIZE			1024 +#define LOG_ERASE_MARK				0x55 +#define LOG_MAX_ERASE				128 + +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	0 +#define USE_EEPROM_CONFIG	1 +#define USE_STORAGE_CONFIG	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_COMPANION		0 + +#define HAS_SPI_1		1 +#define SPI_1_PA5_PA6_PA7	1	/* Barometer */ +#define SPI_1_PB3_PB4_PB5	1	/* Accelerometer */ +#define SPI_1_PE13_PE14_PE15	0 +#define SPI_1_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_SPI_2		1 +#define SPI_2_PB13_PB14_PB15	1	/* Flash, Companion, Radio */ +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz + +#define SPI_2_PORT		(&stm_gpiob) +#define SPI_2_SCK_PIN		13 +#define SPI_2_MISO_PIN		14 +#define SPI_2_MOSI_PIN		15 + +#define HAS_I2C_1		0 +#define I2C_1_PB8_PB9		0 + +#define HAS_I2C_2		0 +#define I2C_2_PB10_PB11		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define LOW_LEVEL_DEBUG		0 + +#define LED_PORT_ENABLE		STM_RCC_AHBENR_GPIOCEN +#define LED_PORT		(&stm_gpioc) +#define LED_PIN_RED		14 +#define LED_PIN_GREEN		15 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) + +#define AO_LED_PANIC	AO_LED_RED +#define AO_LED_GPS_LOCK	AO_LED_GREEN + +#define LEDS_AVAILABLE		(AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS			1 +#define HAS_FLIGHT		0 +#define HAS_ADC			1 +#define HAS_ADC_TEMP		0 +#define HAS_LOG			1 +#define HAS_TRACKER		1 +#define LOG_ADC			0 +#define AO_LOG_FORMAT				AO_LOG_FORMAT_TELEGPS + +/* + * ADC + */ +#define AO_DATA_RING		32 +#define AO_ADC_NUM_SENSE	2 + +struct ao_adc { +	int16_t			v_batt; +}; + +#define AO_ADC_DUMP(p) \ +	printf("tick: %5u batt: %5d\n", \ +	       (p)->tick, \ +	       (p)->adc.v_batt); + +#define AO_ADC_V_BATT		8 +#define AO_ADC_V_BATT_PORT	(&stm_gpiob) +#define AO_ADC_V_BATT_PIN	0 + +#define AO_ADC_RCC_AHBENR	((1 << STM_RCC_AHBENR_GPIOBEN)) + +#define AO_NUM_ADC_PIN		1 + +#define AO_ADC_PIN0_PORT	AO_ADC_V_BATT_PORT +#define AO_ADC_PIN0_PIN		AO_ADC_V_BATT_PIN + +#define AO_NUM_ADC	       	(AO_NUM_ADC_PIN) + +#define AO_ADC_SQ1		AO_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 + +/* + * GPS + */ + +#define AO_SERIAL_SPEED_UBLOX	AO_SERIAL_SPEED_9600 + +#define ao_gps_getchar		ao_serial3_getchar +#define ao_gps_putchar		ao_serial3_putchar +#define ao_gps_set_speed	ao_serial3_set_speed +#define ao_gps_fifo		(ao_stm_usart3.rx_fifo) + +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS		1 +#define AO_M25_SPI_CS_PORT	(&stm_gpiob) +#define AO_M25_SPI_CS_MASK	(1 << 8) +#define AO_M25_SPI_BUS		AO_SPI_2_PB13_PB14_PB15 + +/* + * Radio (cc1120) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 	0x6ca333 + +#define AO_FEC_DEBUG		0 +#define AO_CC1120_SPI_CS_PORT	(&stm_gpioa) +#define AO_CC1120_SPI_CS_PIN	2 +#define AO_CC1120_SPI_BUS	AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1120_SPI		stm_spi2 + +#define AO_CC1120_INT_PORT		(&stm_gpioa) +#define AO_CC1120_INT_PIN		(3) +#define AO_CC1120_MCU_WAKEUP_PORT	(&stm_gpioa) +#define AO_CC1120_MCU_WAKEUP_PIN	(4) + +#define AO_CC1120_INT_GPIO	2 +#define AO_CC1120_INT_GPIO_IOCFG	CC1120_IOCFG2 + +#define AO_CC1120_MARC_GPIO	3 +#define AO_CC1120_MARC_GPIO_IOCFG	CC1120_IOCFG3 + +#define HAS_BOOT_RADIO		0 + +#define NUM_CMDS		16 + +/* + * Monitor + */ + +#define HAS_MONITOR		0 +#define LEGACY_MONITOR		0 +#define HAS_MONITOR_PUT		1 +#define AO_MONITOR_LED		0 +#define HAS_RSSI		0 + +/* + * Profiling Viterbi decoding + */ + +#ifndef AO_PROFILE +#define AO_PROFILE	       	0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/tmgps-v2.0/ao_tmgps.c b/src/tmgps-v2.0/ao_tmgps.c new file mode 100644 index 00000000..cbd58eb2 --- /dev/null +++ b/src/tmgps-v2.0/ao_tmgps.c @@ -0,0 +1,81 @@ +/* + * Copyright © 2011 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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_log.h> +#include <ao_exti.h> +#include <ao_tracker.h> +#include <ao_eeprom.h> +#include <ao_profile.h> +#if HAS_SAMPLE_PROFILE +#include <ao_sample_profile.h> +#endif +#if HAS_STACK_GUARD +#include <ao_mpu.h> +#endif + +int +main(void) +{ +	ao_clock_init(); + +#if HAS_STACK_GUARD +	ao_mpu_init(); +#endif + +	ao_task_init(); +	ao_cmd_init(); +	ao_config_init(); + +	/* Turn on all of the LEDs to test them */ +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(LEDS_AVAILABLE); + +	/* Internal systems */ +	ao_timer_init(); +	ao_dma_init(); +	ao_exti_init(); + +	/* SoC hardware */ +	ao_spi_init(); +	ao_adc_init(); +	ao_serial_init(); +	ao_usb_init(); +	ao_eeprom_init(); + +	/* External hardware */ +	ao_storage_init(); +	ao_radio_init(); +	ao_gps_init(); + +	/* Services */ +	ao_log_init(); +	ao_telemetry_init(); +	ao_tracker_init(); + +#if AO_PROFILE +	ao_profile_init(); +#endif +#if HAS_SAMPLE_PROFILE +	ao_sample_profile_init(); +#endif +	ao_led_off(LEDS_AVAILABLE); + +	ao_start_scheduler(); +	return 0; +} diff --git a/src/vidtime/.gitignore b/src/vidtime/.gitignore new file mode 100644 index 00000000..471b7fd9 --- /dev/null +++ b/src/vidtime/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +vidtime-* diff --git a/src/vidtime/Makefile b/src/vidtime/Makefile new file mode 100644 index 00000000..327614bc --- /dev/null +++ b/src/vidtime/Makefile @@ -0,0 +1,65 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_boot.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_task.h \ +	stm32f0.h \ +	Makefile + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_dma_stm.c \ +	ao_exti_stm.c \ +	ao_task.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_usb_stm.c + +PRODUCT=VidTime +PRODUCT_DEF=-DVIDTIME +IDPRODUCT=0x002b + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g + +PROGNAME=vidtime-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_vidtime.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/vidtime/ao_pins.h b/src/vidtime/ao_pins.h new file mode 100644 index 00000000..fe9d3879 --- /dev/null +++ b/src/vidtime/ao_pins.h @@ -0,0 +1,56 @@ +/* + * 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 HAS_TASK_QUEUE		1 + +#define IS_FLASH_LOADER	0 + +#define AO_POWER_MANAGEMENT	0 + +/* 48MHz clock based on USB */ +#define AO_HSI48	1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER	1 +#define AO_RCC_CFGR_PPRE_DIV	STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_EEPROM		0 +#define USE_INTERNAL_FLASH	0 +#define USE_STORAGE_CONFIG	0 +#define USE_EEPROM_CONFIG	0 + +#define HAS_BEEP		0 + +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 + +#define HAS_SPI_0		0 + +#define AO_SENSOR_PORT		(&stm_gpioa) +#define AO_SENSOR_PIN		3 + +#define LOW_LEVEL_DEBUG		0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/vidtime/ao_vidtime.c b/src/vidtime/ao_vidtime.c new file mode 100644 index 00000000..1b9b9e1c --- /dev/null +++ b/src/vidtime/ao_vidtime.c @@ -0,0 +1,97 @@ +/* + * 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_exti.h> + +static uint8_t	sensor_value; +static uint8_t	vidtime_monitor; + +static void +vidtime(void) +{ +	uint8_t	old = 0, got; + +	ao_exti_enable(AO_SENSOR_PORT, AO_SENSOR_PIN); +	for (;;) { +		while (!vidtime_monitor) +			ao_sleep(&vidtime_monitor); +		while ((got = sensor_value) == old) +			ao_sleep(&sensor_value); +		printf("%d\n", got); +		flush(); +		old = got; +	} +} + +static void +sensor_interrupt(void) +{ +	sensor_value = ao_gpio_get(AO_SENSOR_PORT, AO_SENSOR_PIN, foo); +	ao_wakeup(&sensor_value); +} + +static struct ao_task	vidtime_task; + +static void +ao_init_vidtime(void) +{ +	ao_enable_port(AO_SENSOR_PORT); +	ao_exti_setup(AO_SENSOR_PORT, AO_SENSOR_PIN, +		      AO_EXTI_MODE_RISING| +		      AO_EXTI_MODE_FALLING| +		      AO_EXTI_MODE_PULL_NONE| +		      AO_EXTI_PRIORITY_MED, +		      sensor_interrupt); +	ao_add_task(&vidtime_task, vidtime, "vidtime"); +} + +static void +ao_set_vidtime(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_status == ao_cmd_success) { +		vidtime_monitor = ao_cmd_lex_i != 0; +		ao_wakeup(&vidtime_monitor); +	} +} + +const struct ao_cmds	ao_vidtime_cmds[] = { +	{ ao_set_vidtime, "V <0 off, 1 on>\0Enable/disable timing monitor" }, +	{ 0, NULL } +}; + +void main(void) +{ +	ao_clock_init(); + +	ao_task_init(); + +	ao_timer_init(); + +	ao_dma_init(); + +	ao_init_vidtime(); + +	ao_usb_init(); + +	ao_cmd_init(); + +	ao_cmd_register(&ao_vidtime_cmds[0]); + +	ao_start_scheduler(); +} diff --git a/src/vidtime/flash-loader/.gitignore b/src/vidtime/flash-loader/.gitignore new file mode 100644 index 00000000..05f1a4dc --- /dev/null +++ b/src/vidtime/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +vidtime* diff --git a/src/vidtime/flash-loader/Makefile b/src/vidtime/flash-loader/Makefile new file mode 100644 index 00000000..57c65b5e --- /dev/null +++ b/src/vidtime/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=vidtime-v1.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/vidtime/flash-loader/ao_pins.h b/src/vidtime/flash-loader/ao_pins.h new file mode 100644 index 00000000..7feb9362 --- /dev/null +++ b/src/vidtime/flash-loader/ao_pins.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_PINS_H_ +#define _AO_PINS_H_ + +#include <ao_flash_stm_pins.h> + +/* Debug port PA15 (pin 23) */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	(stm_gpioa) +#define AO_BOOT_APPLICATION_PIN		15 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 + +#endif /* _AO_PINS_H_ */  | 
