diff options
| -rw-r--r-- | ao.h | 212 | ||||
| -rw-r--r-- | ao_adc.c | 44 | ||||
| -rw-r--r-- | ao_panic.c | 30 | ||||
| -rw-r--r-- | ao_task.c | 4 | ||||
| -rw-r--r-- | ao_timer.c | 46 | 
5 files changed, 245 insertions, 91 deletions
| @@ -23,118 +23,234 @@  #include <string.h>  #include "cc1111.h" +/* Convert a __data pointer into an __xdata pointer */  #define DATA_TO_XDATA(a)	((void __xdata *) ((uint8_t) (a) | 0xff00)) -#define AO_STACK_START	0x34 +/* Stack runs from above the allocated __data space to 0xfe, which avoids + * writing to 0xff as that triggers the stack overflow indicator + */ +#define AO_STACK_START	0x28  #define AO_STACK_END	0xfe  #define AO_STACK_SIZE	(AO_STACK_END - AO_STACK_START + 1) +/* An AltOS task */  struct ao_task { -	__xdata void	*wchan; -	uint8_t	stack[AO_STACK_SIZE]; -	uint8_t	stack_count; +	__xdata void *wchan;		/* current wait channel (NULL if running) */ +	uint8_t	stack_count;		/* amount of saved stack */ +	uint8_t	stack[AO_STACK_SIZE];	/* saved stack */  }; -#define AO_NUM_TASKS	10 - -#define AO_ERROR_NO_TASK	1 +#define AO_NUM_TASKS		10	/* maximum number of tasks */  #define ao_interrupt_disable()	(EA = 0)  #define ao_interrupt_enable()	(EA = 1) -/* ao_task.c */ -int ao_sleep(__xdata void *wchan); -int ao_wakeup(__xdata void *wchan); -void ao_add_task(__xdata struct ao_task * task, void (*start)(void)); -void ao_start_scheduler(void); -void ao_yield(void) _naked; -void ao_panic(uint8_t reason); +/* + ao_task.c + */ + +/* Suspend the current task until wchan is awoken */ +int +ao_sleep(__xdata void *wchan); + +/* Wake all tasks sleeping on wchan */ +int +ao_wakeup(__xdata void *wchan); + +/* Yield the processor to another task */ +void +ao_yield(void) _naked; + +/* Add a task to the run queue */ +void +ao_add_task(__xdata struct ao_task * task, void (*start)(void)); + +/* Start the scheduler. This will not return */ +void +ao_start_scheduler(void); + +/* + * ao_panic.c + */ + +#define AO_PANIC_NO_TASK	1	/* AO_NUM_TASKS is not large enough */ -/* ao_timer.c */ +/* Stop the operating system, beeping and blinking the reason */ +void +ao_panic(uint8_t reason); -volatile __data uint16_t ao_time; +/* + * ao_timer.c + */ +/* Our timer runs at 100Hz */  #define AO_MS_TO_TICKS(ms)	((ms) / 10)  #define AO_SEC_TO_TICKS(s)	((s) * 100) -void ao_timer_isr(void) interrupt 9; -void ao_timer_init(void); -uint16_t ao_time_atomic(void); -void ao_delay(uint16_t ticks); +/* Returns the current time in ticks */ +uint16_t +ao_time(void); + +/* Suspend the current task until ticks time has passed */ +void +ao_delay(uint16_t ticks); + +/* Timer interrupt */ +void +ao_timer_isr(void) interrupt 9; + +/* Initialize the timer */ +void +ao_timer_init(void); -/* ao_adc.c */ +/* + * ao_adc.c + */ -#define ADC_RING	32 +#define ADC_RING	128 +/* + * One set of samples read from the A/D converter + */  struct ao_adc { -	uint16_t	tick; -	int16_t		accel; -	int16_t		pres; -	int16_t		temp; -	int16_t		v_batt; -	int16_t		sense_d; -	int16_t		sense_m; +	uint16_t	tick;		/* tick when the sample was read */ +	int16_t		accel;		/* accelerometer */ +	int16_t		pres;		/* pressure sensor */ +	int16_t		temp;		/* temperature sensor */ +	int16_t		v_batt;		/* battery voltage */ +	int16_t		sense_d;	/* drogue continuity sense */ +	int16_t		sense_m;	/* main continuity sense */  }; +/* + * A/D data is stored in a ring, with the next sample to be written + * at ao_adc_head + */  extern volatile __xdata struct ao_adc	ao_adc_ring[ADC_RING];  extern volatile __data uint8_t		ao_adc_head; -void ao_adc_isr(void) interrupt 1; -void ao_adc_init(void); -void ao_adc_poll(void); -void ao_adc_get(__xdata struct ao_adc *packet); +/* Trigger a conversion sequence (called from the timer interrupt) */ +void +ao_adc_poll(void); +  +/* Suspend the current task until another A/D sample is converted */ +void +ao_adc_sleep(void); -/* ao_beep.c */ +/* Get a copy of the last complete A/D sample set */ +void +ao_adc_get(__xdata struct ao_adc *packet); -#define AO_BEEP_LOW	150 -#define AO_BEEP_MID	94 -#define AO_BEEP_HIGH	75 -#define AO_BEEP_OFF	0 +/* The A/D interrupt handler */ +void +ao_adc_isr(void) interrupt 1; +/* Initialize the A/D converter */  void -ao_beep_init(void); +ao_adc_init(void); + +/* + * ao_beep.c + */ + +/* + * Various pre-defined beep frequencies + * + * frequency = 1/2 (24e6/32) / beep + */ +#define AO_BEEP_LOW	150	/* 2500Hz */ +#define AO_BEEP_MID	94	/* 3989Hz */ +#define AO_BEEP_HIGH	75	/* 5000Hz */ +#define AO_BEEP_OFF	0	/* off */ + +#define AO_BEEP_g	240	/* 1562.5Hz */ +#define AO_BEEP_gs	227	/* 1652Hz (1655Hz) */ +#define AO_BEEP_aa	214	/* 1752Hz (1754Hz) */ +#define AO_BEEP_bbf	202	/* 1856Hz (1858Hz) */ +#define AO_BEEP_bb	190	/* 1974Hz (1969Hz) */ +#define AO_BEEP_cc	180	/* 2083Hz (2086Hz) */ +#define AO_BEEP_ccs	170	/* 2205Hz (2210Hz) */ +#define AO_BEEP_dd	160	/* 2344Hz (2341Hz) */ +#define AO_BEEP_eef	151	/* 2483Hz (2480Hz) */ +#define AO_BEEP_ee	143	/* 2622Hz (2628Hz) */ +#define AO_BEEP_ff	135	/* 2778Hz (2784Hz) */ +#define AO_BEEP_ffs	127	/* 2953Hz (2950Hz) */ +#define AO_BEEP_gg	120	/* 3125Hz */ +#define AO_BEEP_ggs	113	/* 3319Hz (3311Hz) */ +#define AO_BEEP_aaa	107	/* 3504Hz (3508Hz) */ +#define AO_BEEP_bbbf	101	/* 3713Hz (3716Hz) */ +#define AO_BEEP_bbb	95	/* 3947Hz (3937Hz) */ +#define AO_BEEP_ccc	90	/* 4167Hz (4171Hz) */ +#define AO_BEEP_cccs	85	/* 4412Hz (4419Hz) */ +#define AO_BEEP_ddd	80	/* 4688Hz (4682Hz) */ +#define AO_BEEP_eeef	76	/* 4934Hz (4961Hz) */ +#define AO_BEEP_eee	71	/* 5282Hz (5256Hz) */ +#define AO_BEEP_fff	67	/* 5597Hz (5568Hz) */ +#define AO_BEEP_fffs	64	/* 5859Hz (5899Hz) */ +#define AO_BEEP_ggg	60	/* 6250Hz */ + +/* Set the beeper to the specified tone */  void  ao_beep(uint8_t beep); +/* Turn on the beeper for the specified time */  void  ao_beep_for(uint8_t beep, uint16_t ticks); -/* ao_led.c */ +/* Initialize the beeper */ +void +ao_beep_init(void); + +/* + * ao_led.c + */  #define AO_LED_NONE	0  #define AO_LED_GREEN	1  #define AO_LED_RED	2 -void -ao_led_init(void); - +/* Turn on the specified LEDs */  void  ao_led_on(uint8_t colors); +/* Turn off the specified LEDs */  void  ao_led_off(uint8_t colors); +/* Set all of the LEDs to the specified state */  void  ao_led_set(uint8_t colors); +/* Turn on the specified LEDs for the indicated interval */  void  ao_led_for(uint8_t colors, uint16_t ticks); -/* ao_usb.c */ - +/* Initialize the LEDs */  void -ao_usb_isr(void) interrupt 6; +ao_led_init(void); -void -ao_usb_flush(void); +/* + * ao_usb.c + */ +/* Put one character to the USB output queue */  void  ao_usb_putchar(uint8_t c); +/* Get one character from the USB input queue */  uint8_t  ao_usb_getchar(void); +/* Flush the USB output queue */ +void +ao_usb_flush(void); + +/* USB interrupt handler */ +void +ao_usb_isr(void) interrupt 6; + +/* Initialize the USB system */  void  ao_usb_init(void); @@ -21,7 +21,30 @@  volatile __xdata struct ao_adc	ao_adc_ring[ADC_RING];  volatile __data uint8_t		ao_adc_head; -void ao_adc_isr(void) interrupt 1 +void +ao_adc_poll(void) +{ +	ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; +} + +void +ao_adc_sleep(void) +{ +	ao_sleep(&ao_adc_ring); +} + +void +ao_adc_get(__xdata struct ao_adc *packet) +{ +	uint8_t	i = ao_adc_head; +	if (i == 0) +		i = ADC_RING; +	i--; +	memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +void +ao_adc_isr(void) interrupt 1  {  	uint8_t sequence;  	uint8_t	__xdata *a; @@ -35,7 +58,7 @@ void ao_adc_isr(void) interrupt 1  		ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1);  	} else {  		/* record this conversion series */ -		ao_adc_ring[ao_adc_head].tick = ao_time; +		ao_adc_ring[ao_adc_head].tick = ao_time();  		ao_adc_head++;  		if (ao_adc_head == ADC_RING)  			ao_adc_head = 0; @@ -43,7 +66,8 @@ void ao_adc_isr(void) interrupt 1  	}  } -void ao_adc_init(void) +void +ao_adc_init(void)  {  	ADCCFG = ((1 << 0) |	/* acceleration */  		  (1 << 1) |	/* pressure */ @@ -57,17 +81,3 @@ void ao_adc_init(void)  	IEN0 |= IEN0_ADCIE;  } -void ao_adc_poll(void) -{ -	ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; -} - -void ao_adc_get(__xdata struct ao_adc *packet) -{ -	uint8_t	i = ao_adc_head; -	if (i == 0) -		i = ADC_RING; -	i--; -	memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); -} - @@ -17,8 +17,36 @@  #include "ao.h" +static void +ao_panic_delay(uint8_t n) +{ +	uint8_t	i = 0; + +	while (n--) +		while (--i) +			_asm nop _endasm; +} +  void  ao_panic(uint8_t reason)  { -	(void) reason; +	uint8_t	n; +	 +	for (;;) { +		ao_led_on(AO_LED_RED); +		ao_beep(AO_BEEP_MID); +		ao_panic_delay(2); +		ao_led_off(AO_LED_RED); +		ao_beep(AO_BEEP_OFF); +		ao_panic_delay(2); +		for (n = 0; n < reason; n++) { +			ao_led_on(AO_LED_RED); +			ao_beep(AO_BEEP_MID); +			ao_panic_delay(1); +			ao_led_off(AO_LED_RED); +			ao_beep(AO_BEEP_OFF); +			ao_panic_delay(1); +		} +		ao_panic_delay(2); +	}  } @@ -29,7 +29,7 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void))  {  	uint8_t	__xdata *stack;  	if (ao_num_tasks == AO_NUM_TASKS) -		ao_panic(AO_ERROR_NO_TASK); +		ao_panic(AO_PANIC_NO_TASK);  	ao_tasks[ao_num_tasks++] = task;  	/*  	 * Construct a stack frame so that it will 'return' @@ -162,7 +162,9 @@ ao_yield(void) _naked  int  ao_sleep(__xdata void *wchan)  { +	ao_interrupt_disable();  	ao_cur_task->wchan = wchan; +	ao_interrupt_enable();  	ao_yield();  } @@ -17,32 +17,38 @@  #include "ao.h" -volatile __data uint16_t ao_time; +static volatile __data uint16_t ao_tick_count; -void ao_timer_isr(void) interrupt 9 +uint16_t ao_time(void)  { -	++ao_time; -	ao_adc_poll(); -	ao_wakeup(DATA_TO_XDATA(&ao_time)); +	volatile bit ea_save; +	__data uint16_t ret; +	 +	ea_save = EA; +	ret = ao_tick_count; +	EA = ea_save; +	return ret;  } -uint16_t ao_time_atomic(void) +void +ao_delay(uint16_t ticks)  { -	uint8_t ret1; -	uint16_t ret2; -	 -	for (;;) { -		ret1 = ao_time >> 8; -		ret2 = ao_time; -		if (ret1 == ((__xdata uint8_t *)(&ret2))[1]) -			break; -	} -	return ret2; +	uint16_t until = ao_time() + ticks; + +	while ((int16_t) (until - ao_time()) > 0) +		ao_sleep(DATA_TO_XDATA(&ao_tick_count));  }  #define T1_CLOCK_DIVISOR	8	/* 24e6/8 = 3e6 */  #define T1_SAMPLE_TIME		30000	/* 3e6/30000 = 100 */ +void ao_timer_isr(void) interrupt 9 +{ +	++ao_tick_count; +	ao_adc_poll(); +	ao_wakeup(DATA_TO_XDATA(&ao_tick_count)); +} +  void  ao_timer_init(void)  { @@ -71,11 +77,3 @@ ao_timer_init(void)  	T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8;  } -void -ao_delay(uint16_t ticks) -{ -	uint16_t until = ao_time_atomic() + ticks; - -	while ((int16_t) (until - ao_time_atomic()) > 0) -		ao_sleep(DATA_TO_XDATA(&ao_time)); -} | 
