diff options
Diffstat (limited to 'src')
35 files changed, 1380 insertions, 204 deletions
| diff --git a/src/Makefile b/src/Makefile index ee76c325..af2630fc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,8 @@ SDCCDIRS=\  	telemini-v1.0 \  	telebt-v1.0 \  	teleterra-v0.2 teleshield-v0.1 \ -	telefire-v0.1 telefire-v0.2 +	telefire-v0.1 telefire-v0.2 \ +	telemini-v2.0  AVRDIRS=\  	telescience-v0.1 telescience-pwm micropeak @@ -29,10 +30,11 @@ ARMDIRS=\  	telemega-v0.1 telemega-v0.1/flash-loader \  	telemega-v0.3 telemega-v0.3/flash-loader \  	megadongle-v0.1 megadongle-v0.1/flash-loader \ -	telegps-v0.1 telegps-v0.1/flash-loader \ +	telegps-v0.3 telegps-v0.3/flash-loader \  	stm-bringup stm-demo \  	telelco-v0.2 telelco-v0.2/flash-loader \ -	telescience-v0.2 telescience-v0.2/flash-loader +	telescience-v0.2 telescience-v0.2/flash-loader \ +	easymini-v0.1 easymini-v0.1/flash-loader  ARMM0DIRS=\  	easymini-v0.1 diff --git a/src/attiny/ao_arch_funcs.h b/src/attiny/ao_arch_funcs.h index 76dc7820..d4584a9f 100644 --- a/src/attiny/ao_arch_funcs.h +++ b/src/attiny/ao_arch_funcs.h @@ -41,6 +41,8 @@  			PORTB &= ~(1 << bit);	\  	} while (0) +#define ao_gpio_get(port, bit, pin)	((PORTB >> (bit)) & 1) +  /*   * The SPI mutex must be held to call either of these   * functions -- this mutex covers the entire SPI operation, diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 4a58023d..15429677 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -19,23 +19,26 @@  volatile __xdata struct ao_data	ao_data_ring[AO_DATA_RING];  volatile __data uint8_t		ao_data_head; +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) +volatile __data uint8_t		ao_data_present; +#endif + +#ifdef TELENANO_V_0_1 +# define AO_ADC_FIRST_PIN	1 +#endif + +#if HAS_ACCEL_REF +# define AO_ADC_FIRST_PIN	2 +#endif  #ifndef AO_ADC_FIRST_PIN -#define AO_ADC_FIRST_PIN	0 +# define AO_ADC_FIRST_PIN	0  #endif  void  ao_adc_poll(void)  { -#if HAS_ACCEL_REF -	ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; -#else -# ifdef TELENANO_V_0_1 -	ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; -# else  	ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | AO_ADC_FIRST_PIN; -# endif -#endif  }  void @@ -141,6 +144,7 @@ ao_adc_isr(void) __interrupt 1  	if (sequence) {  		/* Start next conversion */  		ADCCON3 = sequence; +		return;  	}  #endif /* telemini || telenano */ @@ -148,8 +152,10 @@ ao_adc_isr(void) __interrupt 1  	a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence - AO_ADC_FIRST_PIN);  	a[0] = ADCL;  	a[1] = ADCH; -	if (sequence < 5) +	if (sequence < 5) {  		ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); +		return; +	}  #define GOT_ADC  #endif /* TELEFIRE_V_0_1 */ @@ -157,21 +163,22 @@ ao_adc_isr(void) __interrupt 1  	a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.batt);  	a[0] = ADCL;  	a[1] = ADCH; -	if (0) -		;  #define GOT_ADC  #endif	 +#ifdef FETCH_ADC +	FETCH_ADC(); +#define GOT_ADC +#endif +  #ifndef GOT_ADC  #error No known ADC configuration set  #endif -	else { -		/* record this conversion series */ -		ao_data_ring[ao_data_head].tick = ao_time(); -		ao_data_head = ao_data_ring_next(ao_data_head); -		ao_wakeup(DATA_TO_XDATA(&ao_data_head)); -	} +	/* record this conversion series */ +	ao_data_ring[ao_data_head].tick = ao_time(); +	ao_data_head = ao_data_ring_next(ao_data_head); +	ao_wakeup(DATA_TO_XDATA(&ao_data_head));  }  static void diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 9097557f..34235b08 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -321,4 +321,9 @@ void  ao_serial1_tx_isr(void) ao_arch_interrupt(14);  #endif +#if HAS_EXTI_0 +void +ao_p0_isr(void) __interrupt(13); +#endif +  #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 8f1cc094..ea340dfd 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -19,46 +19,74 @@   * ao_spi.c   */ -extern __xdata uint8_t	ao_spi_mutex; +#if !HAS_SPI_0 && !HAS_SPI_1 +#define HAS_SPI_0	1 +#define SPI_0_ALT_2	1 +#endif + +#if HAS_SPI_0 && HAS_SPI_1 +#define MULTI_SPI	1 +#define N_SPI		2 +#else +#define MULTI_SPI	0 +#define N_SPI		1 +#endif + +extern __xdata uint8_t	ao_spi_mutex[N_SPI]; + +#if MULTI_SPI +#define ao_spi_get(bus)	ao_mutex_get(&ao_spi_mutex[bus]) +#define ao_spi_put(bus)	ao_mutex_put(&ao_spi_mutex[bus]) +#else +#define ao_spi_get(bus)	ao_mutex_get(&ao_spi_mutex[0]) +#define ao_spi_put(bus)	ao_mutex_put(&ao_spi_mutex[0]) +#endif  #define AO_SPI_SPEED_FAST	17  #define AO_SPI_SPEED_200kHz	13 -#define ao_spi_set_speed(speed) (U0GCR = (UxGCR_CPOL_NEGATIVE |		\ -					  UxGCR_CPHA_FIRST_EDGE |	\ -					  UxGCR_ORDER_MSB |		\ -					  ((speed) << UxGCR_BAUD_E_SHIFT))) +#if MULTI_SPI +#define ao_spi_set_speed(bus,speed) (*(bus ? &U1GCR : &U0GCR) =(UxGCR_CPOL_NEGATIVE | \ +								UxGCR_CPHA_FIRST_EDGE |	\ +								UxGCR_ORDER_MSB | \ +								((speed) << UxGCR_BAUD_E_SHIFT))) +#else +#define ao_spi_set_speed(bus,speed) (U0GCR = (UxGCR_CPOL_NEGATIVE |	\ +					      UxGCR_CPHA_FIRST_EDGE |	\ +					      UxGCR_ORDER_MSB |		\ +					      ((speed) << UxGCR_BAUD_E_SHIFT))) +#endif  #define ao_spi_get_slave(bus) do {			\ -		ao_mutex_get(&ao_spi_mutex);		\ -		ao_spi_set_speed(AO_SPI_SPEED_FAST);	\ +		ao_spi_get(bus);			\ +		ao_spi_set_speed(bus,AO_SPI_SPEED_FAST);	\  	} while (0)  #define ao_spi_put_slave(bus) do {		\ -		ao_mutex_put(&ao_spi_mutex);	\ +		ao_spi_put(bus);		\  	} while (0)  #define ao_spi_get_mask(reg,mask,bus,speed) do {	\ -		ao_mutex_get(&ao_spi_mutex);		\ -		ao_spi_set_speed(speed);		\ +		ao_spi_get(bus);			\ +		ao_spi_set_speed(bus,speed);		\  		(reg) &= ~(mask);			\  	} while (0)  #define ao_spi_put_mask(reg,mask,bus) do {		\  	(reg) |= (mask); \ -	ao_mutex_put(&ao_spi_mutex); \ +	ao_spi_put(bus); \  	} while (0)  #define ao_spi_get_bit(reg,bit,pin,bus,speed) do {	\ -		ao_mutex_get(&ao_spi_mutex);	\ -		ao_spi_set_speed(speed);	\ -		pin = 0;			\ +		ao_spi_get(bus);			\ +		ao_spi_set_speed(bus,speed);		\ +		pin = 0;				\  	} while (0)  #define ao_spi_put_bit(reg,bit,pin,bus) do {	\  		pin = 1;			\ -		ao_mutex_put(&ao_spi_mutex);	\ +		ao_spi_put(bus);		\  	} while (0) @@ -68,6 +96,13 @@ extern __xdata uint8_t	ao_spi_mutex;   * from chip select low to chip select high   */ +#if MULTI_SPI +void +ao_spi_send(void __xdata *block, uint16_t len, uint8_t bus) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len, uint8_t bus) __reentrant; +#else  void  ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; @@ -76,6 +111,7 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant;  #define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len)  #define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) +#endif  #if AO_SPI_SLAVE  void @@ -88,10 +124,15 @@ ao_spi_recv_wait(void);  void  ao_spi_init(void); -#define ao_spi_init_cs(port, mask) do {		\ -		SPI_CS_PORT |= mask;		\ -		SPI_CS_DIR |= mask;		\ -		SPI_CS_SEL &= ~mask;		\ +#define token_paster(x,y)	x ## y +#define token_paster3(x,y,z)	x ## y ## z +#define token_evaluator(x,y)	token_paster(x,y) +#define token_evaluator3(x,y,z)	token_paster3(x,y,z) + +#define ao_spi_init_cs(port, mask) do {			\ +		port |= mask;				\ +		token_evaluator(port,DIR) |= mask;	\ +		token_evaluator(port,SEL) &= ~mask;	\  	} while (0)  #define cc1111_enable_output(port,dir,sel,pin,bit,v) do {	\ @@ -102,7 +143,7 @@ ao_spi_init(void);  #define disable_unreachable	_Pragma("disable_warning 126") -#define token_paster(x,y)	x ## y -#define token_evaluator(x,y)	token_paster(x,y)  #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)  #define ao_gpio_set(port, bit, pin, v) ((pin) = (v)) +#define ao_gpio_get(port, bit, pin) (pin) + diff --git a/src/cc1111/ao_exti.c b/src/cc1111/ao_exti.c new file mode 100644 index 00000000..537f6252 --- /dev/null +++ b/src/cc1111/ao_exti.c @@ -0,0 +1,33 @@ +/* + * 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> + +#if HAS_EXTI_0 +__xdata void 	(*ao_int_callback)(void); + +void +ao_p0_isr(void) __interrupt(13) +{ +	if (P0IF && (P0IFG & (AO_MS5607_MISO_MASK))) { +		(*ao_int_callback)(); +	} +	P0IFG = 0; +	P0IF = 0; +} +#endif diff --git a/src/cc1111/ao_exti.h b/src/cc1111/ao_exti.h new file mode 100644 index 00000000..49fca5d2 --- /dev/null +++ b/src/cc1111/ao_exti.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_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING	1 +#define AO_EXTI_MODE_FALLING	2 +#define AO_EXTI_MODE_PULL_UP	4 +#define AO_EXTI_MODE_PULL_DOWN	8 +#define AO_EXTI_PRIORITY_LOW	16 +#define AO_EXTI_PRIORITY_MED	0 +#define AO_EXTI_PRIORITY_HIGH	32 + +extern void 	(*ao_int_callback)(void); + +#define ao_exti_setup(gpio, pin, mode, callback) do { \ +		ao_int_callback = callback;	      \ +	} while (0) + +#define ao_exti_set_mode(gpio, pin, mode) do { \ +	} while (0) + +#define ao_exti_set_callback(port, pin, callback) do {	\ +		ao_int_callback = callback;		\ +	} while (0) + +#define ao_exti_init() + +#define ao_exti_enable(port, pin) do {		\ +		P0IFG &= ~(1 << pin);		\ +		P0IF = 0;			\ +		PICTL |= PICTL_P0IENL;		\ +		IEN1 |= IEN1_P0IE;		\ +	} while (0) + +#define ao_exti_disable(port, pin) do {		\ +		IEN1 &= ~IEN1_P0IE;		\ +		PICTL &= ~PICTL_P0IENL;		\ +	} while (0) + +#endif /* _AO_EXTI_H_ */ diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index cdef6bda..fb08f3f5 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -18,10 +18,6 @@  #include "ao.h"  /* Default pin usage for existing Altus Metrum devices */ -#if !HAS_SPI_0 && !HAS_SPI_1 -#define HAS_SPI_0	1 -#define SPI_0_ALT_2	1 -#endif  #ifndef SPI_CONST  #define SPI_CONST	0xff @@ -61,62 +57,107 @@   */  #if HAS_SPI_0 -#define SPI_CSR		U0CSR -#define SPI_BUF		U0DBUFXADDR -#define SPI_BAUD	U0BAUD -#define SPI_GCR		U0GCR -#define SPI_CFG_MASK	PERCFG_U0CFG_ALT_MASK -#define SPI_DMA_TX	DMA_CFG0_TRIGGER_UTX0 -#define SPI_DMA_RX	DMA_CFG0_TRIGGER_URX0 +#define SPI_BUF_0	&U0DBUFXADDR +#define SPI_CSR_0	U0CSR +#define SPI_BAUD_0	U0BAUD +#define SPI_GCR_0	U0GCR +#define SPI_CFG_MASK_0	PERCFG_U0CFG_ALT_MASK +#define SPI_DMA_TX_0	DMA_CFG0_TRIGGER_UTX0 +#define SPI_DMA_RX_0	DMA_CFG0_TRIGGER_URX0  #if SPI_0_ALT_1 -#define SPI_CFG		PERCFG_U0CFG_ALT_1 -#define SPI_SEL		P0SEL -#define SPI_BITS	(1 << 3) | (1 << 2) | (1 << 5) -#define SPI_CSS_BIT	(1 << 4) +#define SPI_CFG_0	PERCFG_U0CFG_ALT_1 +#define SPI_SEL_0	P0SEL +#define SPI_BITS_0	(1 << 3) | (1 << 2) | (1 << 5) +#define SPI_CSS_BIT_0	(1 << 4)  #endif  #if SPI_0_ALT_2 -#define SPI_CFG		PERCFG_U0CFG_ALT_2 -#define SPI_SEL		P1SEL -#define SPI_PRI		P2SEL_PRI3P1_USART0 -#define SPI_BITS	(1 << 5) | (1 << 4) | (1 << 3) -#define SPI_CSS_BIT	(1 << 2) +#define SPI_CFG_0	PERCFG_U0CFG_ALT_2 +#define SPI_SEL_0	P1SEL +#define SPI_PRI_0	P2SEL_PRI3P1_USART0 +#define SPI_BITS_0	(1 << 5) | (1 << 4) | (1 << 3) +#define SPI_CSS_BIT_0	(1 << 2)  #endif  #endif  #if HAS_SPI_1 -#define SPI_CSR		U1CSR -#define SPI_BUF		U1DBUFXADDR -#define SPI_BAUD	U1BAUD -#define SPI_GCR		U1GCR -#define SPI_CFG_MASK	PERCFG_U1CFG_ALT_MASK -#define SPI_DMA_TX	DMA_CFG0_TRIGGER_UTX1 -#define SPI_DMA_RX	DMA_CFG0_TRIGGER_URX1 +#define SPI_BUF_1	&U1DBUFXADDR +#define SPI_CSR_1	U1CSR +#define SPI_BAUD_1	U1BAUD +#define SPI_GCR_1	U1GCR +#define SPI_CFG_MASK_1	PERCFG_U1CFG_ALT_MASK +#define SPI_DMA_TX_1	DMA_CFG0_TRIGGER_UTX1 +#define SPI_DMA_RX_1	DMA_CFG0_TRIGGER_URX1  #if SPI_1_ALT_1 -#define SPI_CFG		PERCFG_U1CFG_ALT_1 -#define SPI_SEL		P0SEL -#define SPI_BITS	(1 << 4) | (1 << 5) | (1 << 3) -#define SPI_CSS_BIT	(1 << 2) +#define SPI_CFG_1	PERCFG_U1CFG_ALT_1 +#define SPI_SEL_1	P0SEL +#define SPI_BITS_1	(1 << 4) | (1 << 5) | (1 << 3) +#define SPI_CSS_BIT_1	(1 << 2)  #endif  #if SPI_1_ALT_2 -#define SPI_CFG		PERCFG_U1CFG_ALT_2 -#define SPI_SEL		P1SEL -#define SPI_PRI		P2SEL_PRI3P1_USART1 -#define SPI_BITS	(1 << 6) | (1 << 7) | (1 << 5) -#define SPI_CSS_BIT	(1 << 4) +#define SPI_CFG_1	PERCFG_U1CFG_ALT_2 +#define SPI_SEL_1	P1SEL +#define SPI_PRI_1	P2SEL_PRI3P1_USART1 +#define SPI_BITS_1	(1 << 6) | (1 << 7) | (1 << 5) +#define SPI_CSS_BIT_1	(1 << 4)  #endif  #endif +#if MULTI_SPI + +#define SPI_BUF(bus)		((bus) ? SPI_BUF_1 : SPI_BUF_0) +#define SPI_CSR(bus)		((bus) ? SPI_CSR_1 : SPI_CSR_0) +#define SPI_BAUD(bus)		((bus) ? SPI_BAUD_1 : SPI_BAUD_0) +#define SPI_GCR(bus)		((bus) ? SPI_GCR_1 : SPI_GCR_0) +#define SPI_CFG_MASK(bus)	((bus) ? SPI_CFG_MASK_1 : SPI_CFG_MASK_0) +#define SPI_DMA_TX(bus)		((bus) ? SPI_DMA_TX_1 : SPI_DMA_TX_0) +#define SPI_DMA_RX(bus)		((bus) ? SPI_DMA_RX_1 : SPI_DMA_RX_0) +#define SPI_CFG(bus)		((bus) ? SPI_CFG_1 : SPI_CFG_0) +#define SPI_SEL(bus)		((bus) ? SPI_SEL_1 : SPI_SEL_0) +#define SPI_BITS(bus)		((bus) ? SPI_BITS_1 : SPI_BITS_0) +#define SPI_CSS_BIT(bus)	((bus) ? SPI_CSS_BIT_1 : SPI_CSS_BIT_0) + +#else + +#if HAS_SPI_0 +#define SPI_BUF(bus)		SPI_BUF_0 +#define SPI_CSR(bus)		SPI_CSR_0 +#define SPI_BAUD(bus)		SPI_BAUD_0 +#define SPI_GCR(bus)		SPI_GCR_0 +#define SPI_CFG_MASK(bus)	SPI_CFG_MASK_0 +#define SPI_DMA_TX(bus)		SPI_DMA_TX_0 +#define SPI_DMA_RX(bus)		SPI_DMA_RX_0 +#define SPI_CFG(bus)		SPI_CFG_0 +#define SPI_SEL(bus)		SPI_SEL_0 +#define SPI_BITS(bus)		SPI_BITS_0 +#define SPI_CSS_BIT(bus)	SPI_CSS_BIT_0 +#endif +#if HAS_SPI_1 +#define SPI_BUF(bus)		SPI_BUF_1 +#define SPI_CSR(bus)		SPI_CSR_1 +#define SPI_BAUD(bus)		SPI_BAUD_1 +#define SPI_GCR(bus)		SPI_GCR_1 +#define SPI_CFG_MASK(bus)	SPI_CFG_MASK_1 +#define SPI_DMA_TX(bus)		SPI_DMA_TX_1 +#define SPI_DMA_RX(bus)		SPI_DMA_RX_1 +#define SPI_CFG(bus)		SPI_CFG_1 +#define SPI_SEL(bus)		SPI_SEL_1 +#define SPI_BITS(bus)		SPI_BITS_1 +#define SPI_CSS_BIT(bus)	SPI_CSS_BIT_1 +#endif + +#endif /* MULTI_SPI */ +  #if AO_SPI_SLAVE -#define CSS		SPI_CSS_BIT +#define CSS(bus)		SPI_CSS_BIT(bus)  #define UxCSR_DIRECTION	UxCSR_SLAVE  #else -#define CSS		0 +#define CSS(bus)		0  #define UxCSR_DIRECTION	UxCSR_MASTER  #endif @@ -124,15 +165,16 @@   * operation, from CS low to CS high. This means that any SPI   * user must protect the SPI bus with this mutex   */ -__xdata uint8_t	ao_spi_mutex; -__xdata uint8_t ao_spi_dma_in_done; -__xdata uint8_t ao_spi_dma_out_done; +__xdata uint8_t	ao_spi_mutex[N_SPI]; +__xdata uint8_t ao_spi_dma_in_done[N_SPI]; +__xdata uint8_t ao_spi_dma_out_done[N_SPI]; -uint8_t	ao_spi_dma_out_id; -uint8_t ao_spi_dma_in_id; +uint8_t	ao_spi_dma_out_id[N_SPI]; +uint8_t ao_spi_dma_in_id[N_SPI];  static __xdata uint8_t ao_spi_const; +  /* Send bytes over SPI.   *   * This sets up two DMA engines, one writing the data and another reading @@ -140,45 +182,52 @@ static __xdata uint8_t ao_spi_const;   * is complete, as the transmit register is double buffered and hence signals   * completion one byte before the transfer is actually complete   */ +#if MULTI_SPI +void +ao_spi_send(void __xdata *block, uint16_t len, uint8_t bus) __reentrant +#else  void  ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant +#define bus	0 +#endif  { -	ao_dma_set_transfer(ao_spi_dma_in_id, -			    &SPI_BUF, +	ao_dma_set_transfer(ao_spi_dma_in_id[bus], +			    SPI_BUF(bus),  			    &ao_spi_const,  			    len,  			    DMA_CFG0_WORDSIZE_8 |  			    DMA_CFG0_TMODE_SINGLE | -			    SPI_DMA_RX, +			    SPI_DMA_RX(bus),  			    DMA_CFG1_SRCINC_0 |  			    DMA_CFG1_DESTINC_0 |  			    DMA_CFG1_PRIORITY_NORMAL); -	ao_dma_set_transfer(ao_spi_dma_out_id, +	ao_dma_set_transfer(ao_spi_dma_out_id[bus],  			    block, -			    &SPI_BUF, +			    SPI_BUF(bus),  			    len,  			    DMA_CFG0_WORDSIZE_8 |  			    DMA_CFG0_TMODE_SINGLE | -			    SPI_DMA_TX, +			    SPI_DMA_TX(bus),  			    DMA_CFG1_SRCINC_1 |  			    DMA_CFG1_DESTINC_0 |  			    DMA_CFG1_PRIORITY_NORMAL); -	ao_dma_start(ao_spi_dma_in_id); -	ao_dma_start(ao_spi_dma_out_id); -	ao_dma_trigger(ao_spi_dma_out_id); +	ao_dma_start(ao_spi_dma_in_id[bus]); +	ao_dma_start(ao_spi_dma_out_id[bus]); +	ao_dma_trigger(ao_spi_dma_out_id[bus]);  #if !AO_SPI_SLAVE -	__critical while (!ao_spi_dma_in_done) -		ao_sleep(&ao_spi_dma_in_done); +	__critical while (!ao_spi_dma_in_done[bus]) +		ao_sleep(&ao_spi_dma_in_done[bus]);  #endif +#undef bus  }  #if AO_SPI_SLAVE  void  ao_spi_send_wait(void)  { -	__critical while (!ao_spi_dma_in_done) -		ao_sleep(&ao_spi_dma_in_done); +	__critical while (!ao_spi_dma_in_done[0]) +		ao_sleep(&ao_spi_dma_in_done[0]);  }  #endif @@ -188,16 +237,22 @@ ao_spi_send_wait(void)   * writing constant values to the SPI transmitter as that is what   * clocks the data coming in.   */ +#if MULTI_SPI +void +ao_spi_recv(void __xdata *block, uint16_t len, uint8_t bus) __reentrant +#else  void  ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant +#define bus 0 +#endif  { -	ao_dma_set_transfer(ao_spi_dma_in_id, -			    &SPI_BUF, +	ao_dma_set_transfer(ao_spi_dma_in_id[bus], +			    SPI_BUF(bus),  			    block,  			    len,  			    DMA_CFG0_WORDSIZE_8 |  			    DMA_CFG0_TMODE_SINGLE | -			    SPI_DMA_RX, +			    SPI_DMA_RX(bus),  			    DMA_CFG1_SRCINC_0 |  			    DMA_CFG1_DESTINC_1 |  			    DMA_CFG1_PRIORITY_NORMAL); @@ -205,24 +260,24 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant  	ao_spi_const = SPI_CONST;  #if !AO_SPI_SLAVE -	ao_dma_set_transfer(ao_spi_dma_out_id, +	ao_dma_set_transfer(ao_spi_dma_out_id[bus],  			    &ao_spi_const, -			    &SPI_BUF, +			    SPI_BUF(bus),  			    len,  			    DMA_CFG0_WORDSIZE_8 |  			    DMA_CFG0_TMODE_SINGLE | -			    SPI_DMA_TX, +			    SPI_DMA_TX(bus),  			    DMA_CFG1_SRCINC_0 |  			    DMA_CFG1_DESTINC_0 |  			    DMA_CFG1_PRIORITY_NORMAL);  #endif -	ao_dma_start(ao_spi_dma_in_id); +	ao_dma_start(ao_spi_dma_in_id[bus]);  #if !AO_SPI_SLAVE -	ao_dma_start(ao_spi_dma_out_id); -	ao_dma_trigger(ao_spi_dma_out_id); -	__critical while (!ao_spi_dma_in_done) -		ao_sleep(&ao_spi_dma_in_done); +	ao_dma_start(ao_spi_dma_out_id[bus]); +	ao_dma_trigger(ao_spi_dma_out_id[bus]); +	__critical while (!ao_spi_dma_in_done[bus]) +		ao_sleep(&ao_spi_dma_in_done[bus]);  #endif  } @@ -230,17 +285,43 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant  void  ao_spi_recv_wait(void)  { -	__critical while (!ao_spi_dma_in_done) -		ao_sleep(&ao_spi_dma_in_done); +	__critical while (!ao_spi_dma_in_done[0]) +		ao_sleep(&ao_spi_dma_in_done[0]);  }  #endif +/* Set up the USART. + * + * SPI master/slave mode + */ +/* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock. + * Every peripheral I've ever seen goes faster than that, + * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) + */ +#define SPI_INIT(bus,o)	do {						\ +		/* Set up the USART pin assignment */			\ +		PERCFG = (PERCFG & ~SPI_CFG_MASK(bus)) | SPI_CFG(bus);	\ +									\ +		/* Make the SPI pins be controlled by the USART peripheral */ \ +		SPI_SEL(bus) |= SPI_BITS(bus) | CSS(bus);		\ +		SPI_CSR(bus) = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); \ +		SPI_BAUD(bus) = 0;					\ +		SPI_GCR(bus) = (UxGCR_CPOL_NEGATIVE |			\ +				UxGCR_CPHA_FIRST_EDGE |			\ +				UxGCR_ORDER_MSB |			\ +				(17 << UxGCR_BAUD_E_SHIFT));		\ +		/* Set up OUT DMA */					\ +		ao_spi_dma_out_id[o] = ao_dma_alloc(&ao_spi_dma_out_done[o]); \ +									\ +		/* Set up IN DMA */					\ +		ao_spi_dma_in_id[o] = ao_dma_alloc(&ao_spi_dma_in_done[o]);	\ +	} while (0) +  void  ao_spi_init(void)  { -	/* Set up the USART pin assignment */ -	PERCFG = (PERCFG & ~SPI_CFG_MASK) | SPI_CFG; -  	/* Ensure that SPI USART takes precidence over the other USART  	 * for pins that they share  	 */ @@ -248,30 +329,10 @@ ao_spi_init(void)  	P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | SPI_PRI;  #endif -	/* Make the SPI pins be controlled by the USART peripheral */ -	SPI_SEL |= SPI_BITS | CSS; - -	/* Set up OUT DMA */ -	ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); - -	/* Set up IN DMA */ -	ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); - -	/* Set up the USART. -	 * -	 * SPI master/slave mode -	 */ -	SPI_CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); - -	/* Set the baud rate and signal parameters -	 * -	 * The cc1111 is limited to a 24/8 MHz SPI clock. -	 * Every peripheral I've ever seen goes faster than that, -	 * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) -	 */ -	SPI_BAUD = 0; -	SPI_GCR = (UxGCR_CPOL_NEGATIVE | -		   UxGCR_CPHA_FIRST_EDGE | -		   UxGCR_ORDER_MSB | -		   (17 << UxGCR_BAUD_E_SHIFT)); +#if HAS_SPI_0 +	SPI_INIT(0, 0); +#endif +#if HAS_SPI_1 +	SPI_INIT(1, MULTI_SPI); +#endif  } diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index a64b5aba..54af9605 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -39,6 +39,9 @@ void ao_timer_isr(void) __interrupt 9  	if (++ao_adc_count == ao_adc_interval) {  		ao_adc_count = 0;  		ao_adc_poll(); +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) +		ao_wakeup(DATA_TO_XDATA(&ao_adc_count)); +#endif  	}  #endif  } diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index a655d1be..b0ab409d 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -201,6 +201,11 @@ ao_usb_ep0_setup(void)  				ao_usb_ep0_queue_byte(0);  				break;  			case AO_USB_REQ_SET_ADDRESS: +#if USB_FORCE_FLIGHT_IDLE +				/* Go to idle mode if USB is connected +				 */ +				ao_flight_force_idle = 1; +#endif  				ao_usb_set_address(ao_usb_setup.value);  				break;  			case AO_USB_REQ_GET_DESCRIPTOR: diff --git a/src/core/ao.h b/src/core/ao.h index caa0ec19..e7320327 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -182,7 +182,7 @@ void  ao_cmd_hex(void);  void -ao_cmd_decimal(void); +ao_cmd_decimal(void) __reentrant;  /* Read a single hex nibble off stdin. */  uint8_t diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 5113548b..4ebaa607 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -206,9 +206,9 @@ ao_cmd_hex(void)  }  void -ao_cmd_decimal(void) +ao_cmd_decimal(void) __reentrant  { -	__pdata uint8_t	r = ao_cmd_lex_error; +	uint8_t	r = ao_cmd_lex_error;  	ao_cmd_lex_u32 = 0;  	ao_cmd_white(); diff --git a/src/core/ao_data.c b/src/core/ao_data.c index 38d2f7ff..6a3d02a1 100644 --- a/src/core/ao_data.c +++ b/src/core/ao_data.c @@ -22,6 +22,7 @@ volatile __xdata struct ao_data	ao_data_ring[AO_DATA_RING];  volatile __data uint8_t		ao_data_head;  volatile __data uint8_t		ao_data_present; +#ifndef ao_data_count  void  ao_data_get(__xdata struct ao_data *packet)  { @@ -32,3 +33,4 @@ ao_data_get(__xdata struct ao_data *packet)  #endif  	memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data));  } +#endif diff --git a/src/core/ao_data.h b/src/core/ao_data.h index c873e9d3..339afe69 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -101,7 +101,7 @@ extern volatile __data uint8_t		ao_data_count;   * signaled by the timer tick   */  #define AO_DATA_WAIT() do {				\ -		ao_sleep((void *) &ao_data_count);	\ +		ao_sleep(DATA_TO_XDATA ((void *) &ao_data_count));	\  	} while (0)  #endif /* AO_DATA_RING */ diff --git a/src/core/ao_int64.c b/src/core/ao_int64.c new file mode 100644 index 00000000..aa23dbe0 --- /dev/null +++ b/src/core/ao_int64.c @@ -0,0 +1,158 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao_int64.h> + +__pdata ao_int64_t *__data ao_64r, *__data ao_64a, *__data ao_64b; + +void ao_plus64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, __pdata ao_int64_t *b) __FATTR { +	__LOCAL uint32_t	t; + +	r->high = a->high + b->high; +	t = a->low + b->low; +	if (t < a->low) +		r->high++; +	r->low = t; +} + +void ao_minus64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, __pdata ao_int64_t *b) __FATTR { +	__LOCAL uint32_t	t; + +	r->high = a->high - b->high; +	t = a->low - b->low; +	if (t > a->low) +		r->high--; +	r->low = t; +} + +void ao_rshift64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, uint8_t d) __FATTR { +	if (d < 32) { +		r->low = a->low >> d; +		if (d) +			r->low |= a->high << (32 - d); +		r->high = (int32_t) a->high >> d; +	} else { +		d &= 0x1f; +		r->low = (int32_t) a->high >> d; +		r->high = 0; +	} +} + +void ao_lshift64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, uint8_t d) __FATTR { +	if (d < 32) { +		r->high = a->high << d; +		if (d) +			r->high |= a->low >> (32 - d); +		r->low = a->low << d; +	} else { +		d &= 0x1f; +		r->high = a->low << d; +		r->low = 0; +	} +} + +static void ao_umul64_32_32(__ARG ao_int64_t *r, uint32_t a, uint32_t b) __reentrant { +	__LOCAL uint32_t	s; +	__LOCAL ao_int64_t	t; +	r->low = (uint32_t) (uint16_t) a * (uint16_t) b; +	r->high = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) (b >> 16); + +	s = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) b; + +	t.high = s >> 16; +	t.low = s << 16; +	ao_plus64(r, r, &t); + +	s = (uint32_t) (uint16_t) a * (uint16_t) (b >> 16); + +	t.high = s >> 16; +	t.low = s << 16; +	ao_plus64(r, r, &t); +} + +void ao_neg64(__pdata ao_int64_t *r, __pdata ao_int64_t *a) __FATTR { +	r->high = ~a->high; +	if (!(r->low = ~a->low + 1)) +		r->high++; +} + +void ao_mul64_32_32(__ARG ao_int64_t *r, int32_t a, int32_t b) __FATTR { +	uint8_t		negative = 0; + +	if (a < 0) { +		a = -a; +		++negative; +	} +	if (b < 0) { +		b = -b; +		--negative; +	} +	ao_umul64_32_32(r, a, b); +	if (negative) +		ao_neg64(r, r); +} + +static void ao_umul64(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG ao_int64_t *b) __reentrant { +	__LOCAL ao_int64_t	r2, r3; + +	ao_umul64_32_32(&r2, a->high, b->low); +	ao_umul64_32_32(&r3, a->low, b->high); +	ao_umul64_32_32(r, a->low, b->low); + +	r->high += r2.low + r3.low; +} + +static __ARG ao_int64_t	ap, bp; + +void ao_mul64(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG ao_int64_t *b) __FATTR { +	uint8_t	negative = 0; + +	if (ao_int64_negativep(a)) { +		ao_neg64(&ap, a); +		a = ≈ +		++negative; +	} +	if (ao_int64_negativep(b)) { +		ao_neg64(&bp, b); +		b = &bp; +		--negative; +	} +	ao_umul64(r, a, b); +	if (negative) +		ao_neg64(r, r); +} + +static void ao_umul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, uint16_t b) __reentrant { +	__LOCAL uint32_t h; + +	h = a->high * b; +	ao_umul64_32_32(r, a->low, b); +	r->high += h; +} + +void ao_mul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG uint16_t b) __FATTR { +	uint8_t		negative = 0; + +	if ((int32_t) a->high < 0) { +		ao_neg64(&ap, a); +		a = ≈ +		negative++; +	} else +		ao_umul64_64_16(r, a, b); +	if (negative) +		ao_neg64(r, r); +} diff --git a/src/core/ao_int64.h b/src/core/ao_int64.h new file mode 100644 index 00000000..b16db58c --- /dev/null +++ b/src/core/ao_int64.h @@ -0,0 +1,48 @@ +/* + * 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_INT64_H_ +#define _AO_INT64_H_ + +#include <stdint.h> + +typedef struct { +	uint32_t	high; +	uint32_t	low; +} ao_int64_t; + +#define __FATTR +#define __ARG __pdata +#define __LOCAL static __pdata + +void ao_plus64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, __pdata ao_int64_t *ao_64b) __FATTR; +void ao_minus64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, __pdata ao_int64_t *ao_64b) __FATTR; +void ao_neg64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a) __FATTR; +void ao_rshift64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, uint8_t d) __FATTR; +void ao_lshift64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, uint8_t d) __FATTR; +void ao_mul64_32_32(__ARG ao_int64_t *r, __ARG int32_t a, __ARG int32_t b) __FATTR; +void ao_mul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG uint16_t b) __FATTR; +void ao_mul64(__ARG ao_int64_t * __ARG r, __ARG ao_int64_t * __ARG a, __ARG ao_int64_t *__ARG b) __FATTR; + +#define ao_int64_init32(r, a) (((r)->high = 0), (r)->low = (a)) +#define ao_int64_init64(r, a, b) (((r)->high = (a)), (r)->low = (b)) + +#define ao_cast64(a) (((int64_t) (a)->high << 32) | (a)->low) + +#define ao_int64_negativep(a)	(((int32_t) (a)->high) < 0) + +#endif /* _AO_INT64_H_ */ diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index 59ffd8b2..762b2c0a 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -40,9 +40,9 @@ static __pdata int32_t		ao_k_accel;  __pdata int16_t			ao_height;  __pdata int16_t			ao_speed;  __pdata int16_t			ao_accel; -__pdata int16_t			ao_max_height; +__xdata int16_t			ao_max_height;  static __pdata int32_t		ao_avg_height_scaled; -__pdata int16_t			ao_avg_height; +__xdata int16_t			ao_avg_height;  __pdata int16_t			ao_error_h;  __pdata int16_t			ao_error_h_sq_avg; diff --git a/src/core/ao_log_mini.c b/src/core/ao_log_mini.c index 1273b0e3..46b285f3 100644 --- a/src/core/ao_log_mini.c +++ b/src/core/ao_log_mini.c @@ -79,7 +79,6 @@ void  ao_log(void)  {  	__pdata uint16_t	next_sensor, next_other; -	uint8_t			i;  	ao_storage_setup(); diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 23ebf7dd..095aca37 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -23,7 +23,7 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY;  static __data uint8_t			ao_log_monitor_pos;  __pdata enum ao_flight_state		ao_flight_state; -__pdata int16_t				ao_max_height;	/* max of ao_height */ +__xdata int16_t				ao_max_height;	/* max of ao_height */  __pdata int16_t				sense_d, sense_m;  __pdata uint8_t				ao_igniter_present; diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index a2dac979..5bd29536 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -136,8 +136,8 @@ uint8_t ao_sample(void);  extern __pdata int16_t			ao_height;	/* meters */  extern __pdata int16_t			ao_speed;	/* m/s * 16 */  extern __pdata int16_t			ao_accel;	/* m/s² * 16 */ -extern __pdata int16_t			ao_max_height;	/* max of ao_height */ -extern __pdata int16_t			ao_avg_height;	/* running average of height */ +extern __xdata int16_t			ao_max_height;	/* max of ao_height */ +extern __xdata int16_t			ao_avg_height;	/* running average of height */  extern __pdata int16_t			ao_error_h;  extern __pdata int16_t			ao_error_h_sq_avg; diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 4f48e32d..bafb4943 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -423,7 +423,7 @@ ao_sleep(__xdata void *wchan)  }  void -ao_wakeup(__xdata void *wchan) +ao_wakeup(__xdata void *wchan) __reentrant  {  #if HAS_TASK_QUEUE  	struct ao_task	*sleep, *next; diff --git a/src/core/ao_task.h b/src/core/ao_task.h index 1a4b5b6b..9c56b480 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -45,7 +45,10 @@ struct ao_task {  #endif  }; +#ifndef AO_NUM_TASKS  #define AO_NUM_TASKS		16	/* maximum number of tasks */ +#endif +  #define AO_NO_TASK		0	/* no task id */  extern __xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; @@ -67,7 +70,7 @@ ao_sleep(__xdata void *wchan);  /* Wake all tasks sleeping on wchan */  void -ao_wakeup(__xdata void *wchan); +ao_wakeup(__xdata void *wchan) __reentrant;  /* set an alarm to go off in 'delay' ticks */  void diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 65d7d08f..cd95aa6b 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -181,8 +181,7 @@ static void  ao_send_metrum_sensor(void)  {  	__xdata	struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; -			 -	telemetry.generic.tick = packet->tick; +  	telemetry.generic.type = AO_TELEMETRY_METRUM_SENSOR;  	telemetry.metrum_sensor.state = ao_flight_state; @@ -213,7 +212,7 @@ ao_send_metrum_data(void)  		uint8_t	i;  		telemetry.generic.tick = packet->tick; -		telemetry.generic.type = AO_TELEMETRY_MEGA_DATA; +		telemetry.generic.type = AO_TELEMETRY_METRUM_DATA;  		telemetry.metrum_data.ground_pres = ao_ground_pres;  		telemetry.metrum_data.ground_accel = ao_ground_accel; @@ -224,7 +223,37 @@ ao_send_metrum_data(void)  		ao_telemetry_metrum_data_cur = ao_telemetry_metrum_data_max;  	}  } -#endif /* AO_SEND_MEGA */ +#endif /* AO_SEND_METRUM */ + +#ifdef AO_SEND_MINI + +static void +ao_send_mini(void) +{ +	__xdata	struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; +			 +	telemetry.generic.tick = packet->tick; +	telemetry.generic.type = AO_TELEMETRY_MINI; + +	telemetry.mini.state = ao_flight_state; + +	telemetry.mini.v_batt = packet->adc.v_batt; +	telemetry.mini.sense_a = packet->adc.sense_a; +	telemetry.mini.sense_m = packet->adc.sense_m; + +	telemetry.mini.pres = ao_data_pres(packet); +	telemetry.mini.temp = ao_data_temp(packet); + +	telemetry.mini.acceleration = ao_accel; +	telemetry.mini.speed = ao_speed; +	telemetry.mini.height = ao_height; + +	telemetry.mini.ground_pres = ao_ground_pres; + +	ao_radio_send(&telemetry, sizeof (telemetry)); +} + +#endif /* AO_SEND_MINI */  #ifdef AO_SEND_ALL_BARO  static uint8_t		ao_baro_sample; @@ -369,7 +398,6 @@ ao_telemetry(void)  		ao_aprs_time = time;  #endif  		while (ao_telemetry_interval) { -  #if HAS_APRS  			if (!(ao_config.radio_enable & AO_RADIO_DISABLE_TELEMETRY))  #endif @@ -377,19 +405,23 @@ ao_telemetry(void)  #ifdef AO_SEND_ALL_BARO  				ao_send_baro();  #endif +  #if HAS_FLIGHT -#ifdef AO_SEND_MEGA +# ifdef AO_SEND_MEGA  				ao_send_mega_sensor();  				ao_send_mega_data(); -#else -#ifdef AO_SEND_METRUM +# endif +# ifdef AO_SEND_METRUM  				ao_send_metrum_sensor();  				ao_send_metrum_data(); -#else +# endif +# ifdef AO_SEND_MINI +				ao_send_mini(); +# endif +# ifdef AO_TELEMETRY_SENSOR  				ao_send_sensor(); -#endif -#endif -#endif +# endif +#endif /* HAS_FLIGHT */  #if HAS_COMPANION  				if (ao_companion_running) @@ -406,18 +438,18 @@ ao_telemetry(void)  			if (ao_rdf &&  #if HAS_APRS  			    !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF) && -#endif +#endif /* HAS_APRS */  			    (int16_t) (ao_time() - ao_rdf_time) >= 0)  			{  #if HAS_IGNITE_REPORT  				uint8_t	c; -#endif +#endif /* HAS_IGNITE_REPORT */  				ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;  #if HAS_IGNITE_REPORT  				if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter()))  					ao_radio_continuity(c);  				else -#endif +#endif /* HAS_IGNITE_REPORT*/  					ao_radio_rdf();  			}  #endif /* HAS_RDF */ @@ -428,8 +460,8 @@ ao_telemetry(void)  				ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);  				ao_aprs_send();  			} -#endif -#endif +#endif /* HAS_APRS */ +#endif /* !AO_SEND_ALL_BARO */  			time += ao_telemetry_interval;  			delay = time - ao_time();  			if (delay > 0) { diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h index 17dc3e93..fd6b76b3 100644 --- a/src/core/ao_telemetry.h +++ b/src/core/ao_telemetry.h @@ -248,6 +248,30 @@ struct ao_telemetry_metrum_data {  	/* 32 */  }; +#define AO_TELEMETRY_MINI		0x10 + +struct ao_telemetry_mini { +	uint16_t	serial;		/*  0 */ +	uint16_t	tick;		/*  2 */ +	uint8_t		type;		/*  4 */ + +	uint8_t         state;          /*  5 flight state */ +	int16_t		v_batt;		/*  6 battery voltage */ +	int16_t		sense_a;	/*  8 apogee continuity */ +	int16_t		sense_m;	/* 10 main continuity */ + +	int32_t		pres;		/* 12 Pa * 10 */ +	int16_t		temp;		/* 16 °C * 100 */ + +	int16_t         acceleration;   /* 18 m/s² * 16 */ +	int16_t         speed;          /* 20 m/s * 16 */ +	int16_t         height;         /* 22 m */ + +	int32_t		ground_pres;	/* 24 average pres on pad */ + +	int32_t		pad28;		/* 28 */ +	/* 32 */ +};  /* #define AO_SEND_ALL_BARO */ @@ -284,6 +308,7 @@ union ao_telemetry_all {  	struct ao_telemetry_mega_data		mega_data;  	struct ao_telemetry_metrum_sensor	metrum_sensor;  	struct ao_telemetry_metrum_data		metrum_data; +	struct ao_telemetry_mini		mini;  	struct ao_telemetry_baro		baro;  }; diff --git a/src/drivers/ao_74hc165.c b/src/drivers/ao_74hc165.c index f24fce37..143f4e3f 100644 --- a/src/drivers/ao_74hc165.c +++ b/src/drivers/ao_74hc165.c @@ -27,12 +27,12 @@ uint8_t  ao_74hc165_read(void)  {  	static __xdata state; -	ao_mutex_get(&ao_spi_mutex); -	ao_spi_set_speed(AO_SPI_SPEED_FAST); +	ao_spi_get(AO_74HC165_SPI_BUS); +	ao_spi_set_speed(AO_74HC165_SPI_BUS, AO_SPI_SPEED_FAST);  	AO_74HC165_CS = 1;  	ao_spi_recv(&state, 1, AO_74HC165_SPI_BUS);  	AO_74HC165_CS = 0; -	ao_mutex_put(&ao_spi_mutex); +	ao_spi_put(AO_74HC165_SPI_BUS);  	return state;  } diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 8f1dcbe1..58ab9197 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -21,8 +21,8 @@  #if HAS_MS5607 || HAS_MS5611 -static struct ao_ms5607_prom	ms5607_prom; -static uint8_t	  		ms5607_configured; +static __xdata struct ao_ms5607_prom	ms5607_prom; +static __xdata uint8_t	  		ms5607_configured;  static void  ao_ms5607_start(void) { @@ -40,7 +40,7 @@ ao_ms5607_reset(void) {  	cmd = AO_MS5607_RESET;  	ao_ms5607_start(); -	ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); +	ao_spi_send(DATA_TO_XDATA(&cmd), 1, AO_MS5607_SPI_INDEX);  	ao_delay(AO_MS_TO_TICKS(10));  	ao_ms5607_stop();  } @@ -69,17 +69,17 @@ ao_ms5607_crc(uint8_t *prom)  }  static void -ao_ms5607_prom_read(struct ao_ms5607_prom *prom) +ao_ms5607_prom_read(__xdata struct ao_ms5607_prom *prom)  { -	uint8_t		addr; -	uint8_t		crc; -	uint16_t	*r; +	uint8_t			addr; +	uint8_t			crc; +	__xdata uint16_t	*r; -	r = (uint16_t *) prom; +	r = (__xdata uint16_t *) prom;  	for (addr = 0; addr < 8; addr++) {  		uint8_t	cmd = AO_MS5607_PROM_READ(addr);  		ao_ms5607_start(); -		ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); +		ao_spi_send(DATA_TO_XDATA(&cmd), 1, AO_MS5607_SPI_INDEX);  		ao_spi_recv(r, 2, AO_MS5607_SPI_INDEX);  		ao_ms5607_stop();  		r++; @@ -114,25 +114,25 @@ ao_ms5607_setup(void)  	ao_ms5607_prom_read(&ms5607_prom);  } -static volatile uint8_t	ao_ms5607_done; +static __xdata volatile uint8_t	ao_ms5607_done;  static void  ao_ms5607_isr(void)  {  	ao_exti_disable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN);  	ao_ms5607_done = 1; -	ao_wakeup((void *) &ao_ms5607_done); +	ao_wakeup((__xdata void *) &ao_ms5607_done);  }  static uint32_t  ao_ms5607_get_sample(uint8_t cmd) { -	uint8_t	reply[3]; -	uint8_t read; +	__xdata uint8_t	reply[3]; +	__xdata uint8_t read;  	ao_ms5607_done = 0;  	ao_ms5607_start(); -	ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); +	ao_spi_send(DATA_TO_XDATA(&cmd), 1, AO_MS5607_SPI_INDEX);  	ao_exti_enable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); @@ -140,7 +140,8 @@ ao_ms5607_get_sample(uint8_t cmd) {  	ao_spi_put(AO_MS5607_SPI_INDEX);  #endif  	ao_arch_block_interrupts(); -	while (!ao_ms5607_done) +	while (!ao_gpio_get(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN, AO_MS5607_MISO) && +	       !ao_ms5607_done)  		ao_sleep((void *) &ao_ms5607_done);  	ao_arch_release_interrupts();  #if AO_MS5607_PRIVATE_PINS @@ -173,16 +174,20 @@ ao_ms5607_get_sample(uint8_t cmd) {  #define AO_CONVERT_D2	token_evaluator(AO_MS5607_CONVERT_D2_, AO_MS5607_TEMP_OVERSAMPLE)  void -ao_ms5607_sample(struct ao_ms5607_sample *sample) +ao_ms5607_sample(__xdata struct ao_ms5607_sample *sample)  {  	sample->pres = ao_ms5607_get_sample(AO_CONVERT_D1);  	sample->temp = ao_ms5607_get_sample(AO_CONVERT_D2);  } +#ifdef _CC1111_H_ +#include "ao_ms5607_convert_8051.c" +#else  #include "ao_ms5607_convert.c" +#endif  #if HAS_TASK -struct ao_ms5607_sample	ao_ms5607_current; +__xdata struct ao_ms5607_sample	ao_ms5607_current;  static void  ao_ms5607(void) @@ -191,10 +196,10 @@ ao_ms5607(void)  	for (;;)  	{  		ao_ms5607_sample(&ao_ms5607_current); -		ao_arch_critical( -			AO_DATA_PRESENT(AO_DATA_MS5607); -			AO_DATA_WAIT(); -			); +		ao_arch_block_interrupts(); +		AO_DATA_PRESENT(AO_DATA_MS5607); +		AO_DATA_WAIT(); +		ao_arch_release_interrupts();  	}  } @@ -216,11 +221,11 @@ ao_ms5607_info(void)  static void  ao_ms5607_dump(void)  { -	struct ao_ms5607_value value; +	__xdata struct ao_ms5607_value value;  	ao_ms5607_convert(&ao_ms5607_current, &value); -	printf ("Pressure:    %8u %8d\n", ao_ms5607_current.pres, value.pres); -	printf ("Temperature: %8u %8d\n", ao_ms5607_current.temp, value.temp); +	printf ("Pressure:    %8lu %8ld\n", ao_ms5607_current.pres, value.pres); +	printf ("Temperature: %8lu %8ld\n", ao_ms5607_current.temp, value.temp);  	printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres));  } diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index b2f98a59..206efd64 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -56,7 +56,7 @@ struct ao_ms5607_value {  	int32_t		temp;	/* in °C * 100 */  }; -extern struct ao_ms5607_sample	ao_ms5607_current; +extern __xdata struct ao_ms5607_sample	ao_ms5607_current;  void  ao_ms5607_setup(void); @@ -68,12 +68,13 @@ void  ao_ms5607_info(void);  void -ao_ms5607_sample(struct ao_ms5607_sample *sample); +ao_ms5607_sample(__xdata struct ao_ms5607_sample *sample);  void -ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value); +ao_ms5607_convert(__xdata struct ao_ms5607_sample *sample, +		  __xdata struct ao_ms5607_value *value);  void -ao_ms5607_get_prom(struct ao_ms5607_prom *prom); +ao_ms5607_get_prom(__data struct ao_ms5607_prom *prom);  #endif /* _AO_MS5607_H_ */ diff --git a/src/drivers/ao_ms5607_convert_8051.c b/src/drivers/ao_ms5607_convert_8051.c new file mode 100644 index 00000000..f3a48c46 --- /dev/null +++ b/src/drivers/ao_ms5607_convert_8051.c @@ -0,0 +1,136 @@ +/* + * 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_ms5607.h> +#include <ao_int64.h> + +#if HAS_MS5611 +#define SHIFT_OFF	16 +#define SHIFT_TCO	7 +#define SHIFT_SENS	15 +#define SHFIT_TCS	8 +#else +#define SHIFT_OFF	17 +#define SHIFT_TCO	6 +#define SHIFT_SENS	16 +#define SHIFT_TCS	7 +#endif + +void +ao_ms5607_convert(__xdata struct ao_ms5607_sample *sample, +		  __xdata struct ao_ms5607_value *value) +{ +	__LOCAL int32_t	dT; +	__LOCAL int32_t TEMP; +	__LOCAL ao_int64_t OFF; +	__LOCAL ao_int64_t SENS; +	__LOCAL ao_int64_t a; + +	dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); +	 +	/* TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); */ +	ao_mul64_32_32(&a, dT, ms5607_prom.tempsens); +	ao_rshift64(&a, &a, 23); +	TEMP = 2000 + a.low; +	/* */ + +	/* OFF = ((int64_t) ms5607_prom.off << SHIFT_OFF) + (((int64_t) ms5607_prom.tco * dT) >> SHIFT_TCO);*/ +#if SHIFT_OFF > 16 +	OFF.high = ms5607_prom.off >> (32 - SHIFT_OFF); +#else +	OFF.high = 0; +#endif +	OFF.low = (uint32_t) ms5607_prom.off << SHIFT_OFF; +	ao_mul64_32_32(&a, ms5607_prom.tco, dT); +	ao_rshift64(&a, &a, SHIFT_TCO); +	ao_plus64(&OFF, &OFF, &a); +	/**/ + +	/* SENS = ((int64_t) ms5607_prom.sens << SHIFT_SENS) + (((int64_t) ms5607_prom.tcs * dT) >> SHIFT_TCS); */ +	SENS.high = 0; +	SENS.low = (uint32_t) ms5607_prom.sens << SHIFT_SENS; +	ao_mul64_32_32(&a, ms5607_prom.tcs, dT); +	ao_rshift64(&a, &a, SHIFT_TCS); +	ao_plus64(&SENS, &SENS, &a); +	/**/ + +	if (TEMP < 2000) { +		__LOCAL int32_t	T2; +		__LOCAL int32_t TEMPM; +		__LOCAL ao_int64_t OFF2; +		__LOCAL ao_int64_t SENS2; + +		/* T2 = ((int64_t) dT * (int64_t) dT) >> 31; */ +		ao_mul64_32_32(&a, dT, dT); +		T2 = (a.low >> 31) | (a.high << 1); +		/**/ + +		TEMPM = TEMP - 2000; + +		/* OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; */ +		ao_mul64_32_32(&OFF2, TEMPM, TEMPM); +		ao_mul64_64_16(&OFF2, &OFF2, 61); +		ao_rshift64(&OFF2, &OFF2, 4); +		/**/ +		 +		/* SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; */ +		ao_mul64_32_32(&SENS2, TEMPM, TEMPM); +		ao_lshift64(&SENS2, &SENS2, 1); +		/**/ + +		if (TEMP < -1500) { +			int32_t TEMPP; +			int32_t TEMPP2; + +			TEMPP = TEMP + 1500; +			TEMPP2 = TEMPP * TEMPP; + +			/* OFF2 = OFF2 + 15 * TEMPP2; */ +			ao_mul64_32_32(&a, 15, TEMPP2); +			ao_plus64(&OFF2, &OFF2, &a); +			/**/ + +			/* SENS2 = SENS2 + 8 * TEMPP2; */ +			a.high = 0; +			a.low = TEMPP2; +			ao_lshift64(&a, &a, 3); +			ao_plus64(&SENS2, &SENS2, &a); +			/**/ +		} +		TEMP -= T2; + +		/* OFF -= OFF2; */ +		ao_minus64(&OFF, &OFF, &OFF2); +		/**/ + +		/* SENS -= SENS2; */ +		ao_minus64(&SENS, &SENS, &SENS2); +		/**/ +	} + +	/* value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; */ +	a.high = 0; +	a.low = sample->pres; +	ao_mul64(&a, &a, &SENS); +	ao_rshift64(&a, &a, 21); +	ao_minus64(&a, &a, &OFF); +	ao_rshift64(&a, &a, 15); +	value->pres = a.low; +	/**/ +	 +	value->temp = TEMP; +} diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c index fe070b88..d376b968 100644 --- a/src/drivers/ao_pca9922.c +++ b/src/drivers/ao_pca9922.c @@ -30,12 +30,12 @@ ao_led_apply(void)  	/* Don't try the SPI bus during initialization */  	if (!ao_cur_task)  		return; -	ao_mutex_get(&ao_spi_mutex); -	ao_spi_set_speed(AO_SPI_SPEED_FAST); +	ao_spi_get(AO_PCA9922_SPI_BUS); +	ao_spi_set_speed(AO_PCA9922_SPI_BUS,AO_SPI_SPEED_FAST);  	AO_PCA9922_CS = 1;  	ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS);  	AO_PCA9922_CS = 0; -	ao_mutex_put(&ao_spi_mutex); +	ao_spi_put(AO_PCA9922_SPI_BUS);  }  void diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile new file mode 100644 index 00000000..40878778 --- /dev/null +++ b/src/telemini-v2.0/Makefile @@ -0,0 +1,115 @@ +# +# TeleMini build file +# + +TELEMINI_VER=2.0 +TELEMINI_DEF=2_0 + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ +	ao.h \ +	ao_pins.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	cc1111.h \ +	ao_ms5607.h \ +	ao_ms5607_convert_8051.c \ +	ao_product.h \ +	ao_int64.h \ +	ao_sample.h \ +	ao_exti.h \ +	ao_task.h + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_convert.c \ +	ao_flight.c \ +	ao_kalman.c \ +	ao_log.c \ +	ao_log_mini.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_report.c \ +	ao_sample.c \ +	ao_stdio.c \ +	ao_storage.c \ +	ao_task.c \ +	ao_telemetry.c \ +	ao_freq.c \ +	ao_int64.c + +CC1111_SRC = \ +	ao_adc.c \ +	ao_dma.c \ +	ao_ignite.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_slave.c \ +	ao_radio.c \ +	ao_romconfig.c \ +	ao_string.c \ +	ao_spi.c \ +	ao_usb.c \ +	ao_convert_pa.c \ +	ao_beep.c \ +	ao_timer.c \ +	ao_exti.c \ +	_bp.c + +DRIVER_SRC = \ +	ao_ms5607.c \ +	ao_m25.c + +PRODUCT_SRC = \ +	ao_telemini.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROGNAME = telemini-v$(TELEMINI_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleMini-v$(TELEMINI_VER) +PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) +IDPRODUCT=0x000a + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf "  $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +	$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: clean-cc1111 + +install: + +uninstall: + diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h new file mode 100644 index 00000000..264ad16d --- /dev/null +++ b/src/telemini-v2.0/ao_pins.h @@ -0,0 +1,160 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO	1 + +#define HAS_FLIGHT		1 +#define HAS_USB			1 +#define USB_FORCE_FLIGHT_IDLE	1 +#define HAS_BEEP		1 +#define HAS_GPS			0 +#define HAS_SERIAL_1		0 +#define HAS_EEPROM		1 +#define HAS_LOG			1 +#define USE_INTERNAL_FLASH	0 +#define HAS_DBG			0 +#define PACKET_HAS_SLAVE	1 + +#define AO_LED_GREEN		1 +#define AO_LED_RED		2 +#define LEDS_AVAILABLE		(AO_LED_RED|AO_LED_GREEN) +#define HAS_EXTERNAL_TEMP	0 +#define HAS_ACCEL		0 +#define HAS_IGNITE		1 +#define HAS_IGNITE_REPORT 1 +#define HAS_MONITOR		0 + +/* + * SPI + */ + +#define HAS_SPI_0		1 +#define SPI_0_ALT_1		1 +#define HAS_SPI_1		1 +#define SPI_1_ALT_2		1 +#define SPI_CS_PORT		P1 +#define SPI_CS_SEL		P1SEL +#define SPI_CS_DIR		P1DIR + +/* + * Flash + */ +#define AO_M25_SPI_BUS		1 +#define AO_M25_SPI_CS_PORT	SPI_CS_PORT +#define AO_M25_SPI_CS_MASK	0x04	/* cs_flash is P1_2 */ +#define M25_MAX_CHIPS		1 + +/* + * MS5607 + */ + +#define HAS_MS5607		1 +#define HAS_MS5611		0 +#define AO_MS5607_PRIVATE_PINS	0 +#define AO_MS5607_CS_PORT	P1 +#define AO_MS5607_CS_PIN	3 +#define AO_MS5607_CS		P1_3 +#define AO_MS5607_CS_MASK	(1 << AO_MS5607_CS_PIN) +#define AO_MS5607_MISO_PORT	P0 +#define AO_MS5607_MISO_PIN	2 +#define AO_MS5607_MISO		P0_2 +#define AO_MS5607_MISO_MASK	(1 << AO_MS5607_MISO_PIN) +#define AO_MS5607_SPI_INDEX	0 +#define HAS_EXTI_0		1 + +/* + * Igniters + */ +#define AO_IGNITER_PORT		P2 +#define AO_IGNITER_DROGUE_PORT	AO_IGNITER_PORT +#define AO_IGNITER_DROGUE	P2_3 +#define AO_IGNITER_MAIN		P2_4 +#define AO_IGNITER_DIR		P2DIR +#define AO_IGNITER_DROGUE_BIT	(1 << 3) +#define AO_IGNITER_MAIN_BIT	(1 << 4) +#define AO_IGNITER_DROGUE_PIN	3 +#define AO_IGNITER_MAIN_PIN	4 + +#define AO_IGNITER_DROGUE_PORT	AO_IGNITER_PORT +#define AO_IGNITER_MAIN_PORT	AO_IGNITER_PORT + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN		1000 +#define AO_IGNITER_CLOSED	7000 +#define AO_IGNITER_FIRE_TIME	AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME	AO_MS_TO_TICKS(2000) + +#define AO_SEND_MINI + +/* + * ADC + */ + +#define HAS_ADC			1 +#define AO_ADC_FIRST_PIN	0 + +struct ao_adc { +	int16_t		sense_a;	/* apogee continuity sense */ +	int16_t		sense_m;	/* main continuity sense */ +	int16_t		v_batt;		/* battery voltage */ +}; + +#define ao_data_count	ao_adc_count + +#define AO_SENSE_DROGUE(p)	((p)->adc.sense_a) +#define AO_SENSE_MAIN(p)	((p)->adc.sense_m) + +#define AO_NUM_TASKS	10 + +#define AO_ADC_DUMP(p) \ +	printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ +	       (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) + +#define AO_ADC_PINS	((1 << 0) | (1 << 1) | (1 << 4)) + +#define FETCH_ADC() do {						\ +		a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc); \ +		switch (sequence) {					\ +		case 4:							\ +			a += 4;						\ +			sequence = 0;					\ +			break;						\ +		case 1:							\ +			a += 2;						\ +			sequence = 4;					\ +			break;						\ +		case 0:							\ +			sequence = 1;					\ +			break;						\ +		}							\ +		a[0] = ADCL;						\ +		a[1] = ADCH;						\ +		if (sequence) {						\ +			ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; \ +			return;						\ +		}							\ +		AO_DATA_PRESENT(AO_DATA_ADC);				\ +		if (ao_data_present != AO_DATA_ALL)			\ +			return;						\ +		ao_data_ring[ao_data_head].ms5607_raw.pres = ao_ms5607_current.pres; \ +		ao_data_ring[ao_data_head].ms5607_raw.temp = ao_ms5607_current.temp; \ +	} while (0) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telemini-v2.0/ao_telemini.c b/src/telemini-v2.0/ao_telemini.c new file mode 100644 index 00000000..294f768a --- /dev/null +++ b/src/telemini-v2.0/ao_telemini.c @@ -0,0 +1,59 @@ +/* + * 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; 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_pins.h" +#include <ao_exti.h> + +__xdata uint8_t ao_force_freq; + +void +main(void) +{ +	/* +	 * Reduce the transient on the ignite pins at startup by +	 * pulling the pins low as soon as possible at power up +	 */ +	ao_ignite_set_pins(); + +	ao_clock_init(); + +	/* Turn on the red LED until the system is stable */ +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_RED); + +	ao_task_init(); + +	ao_timer_init(); +	ao_adc_init(); +	ao_beep_init(); +	ao_cmd_init(); +	ao_spi_init(); +	ao_exti_init(); +	ao_ms5607_init(); +	ao_storage_init(); +	ao_flight_init(); +	ao_log_init(); +	ao_report_init(); +	ao_usb_init(); +	ao_telemetry_init(); +	ao_radio_init(); +	ao_packet_slave_init(TRUE); +	ao_igniter_init(); +	ao_config_init(); +	ao_start_scheduler(); +} diff --git a/src/test/Makefile b/src/test/Makefile index 75b1f848..5eee6bbb 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -2,7 +2,8 @@ vpath % ..:../core:../drivers:../util:../micropeak:../aes  PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \  	ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \ -	ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test +	ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \ +	ao_ms5607_convert_test  INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h @@ -73,3 +74,9 @@ ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c  ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c  	cc $(CFLAGS) -o $@ ao_aes_test.c + +ao_int64_test: ao_int64_test.c ao_int64.c ao_int64.h +	cc $(CFLAGS) -o $@ ao_int64_test.c + +ao_ms5607_convert_test: ao_ms5607_convert_test.c ao_ms5607_convert_8051.c ao_int64.c ao_int64.h +	cc $(CFLAGS) -o $@ ao_ms5607_convert_test.c diff --git a/src/test/ao_int64_test.c b/src/test/ao_int64_test.c new file mode 100644 index 00000000..8557a1c7 --- /dev/null +++ b/src/test/ao_int64_test.c @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#define __data +#define __pdata +#define __xdata +#define __reentrant + +#include <ao_int64.h> +#include <ao_int64.c> +#include <stdio.h> +#include <stdlib.h> + +int	errors; + +#define test_o(op,func,mod,a,b,ao_a,ao_b) do {				\ +		r = (a) op (b);						\ +		func(&ao_r, ao_a, ao_b);				\ +		c = ao_cast64(&ao_r);					\ +		if (c != r) {						\ +			printf ("trial %4d: %lld " #func mod " %lld = %lld (should be %lld)\n", \ +				trial, (int64_t) (a), (int64_t) b, c, r); \ +			++errors;					\ +		}							\ +	} while (0) + +#define test(op,func,a,b,ao_a,ao_b) test_o(op,func,"",a,b,ao_a,ao_b) + +#define test_a(op,func,a,b,ao_a,ao_b) do {	\ +		ao_r = *ao_a;			\ +		test_o(op,func,"_a",a,b,&ao_r,ao_b);	\ +	} while (0) + +#define test_b(op,func,a,b,ao_a,ao_b) do {	\ +		ao_r = *ao_b;			\ +		test_o(op,func,"_b",a,b,ao_a,&ao_r);	\ +	} while (0) + +#define test_x(op,func,a,b,ao_a,ao_b) do {	\ +		ao_r = *ao_a;			\ +		test_o(op,func,"_xa",a,a,&ao_r,&ao_r);	\ +		ao_r = *ao_b;			\ +		test_o(op,func,"_xb",b,b,&ao_r,&ao_r);	\ +	} while (0) + +void +do_test(int trial, int64_t a, int64_t b) +{ +	int64_t	r, c; +	ao_int64_t	ao_a, ao_b, ao_r; + +	ao_int64_init64(&ao_a, a >> 32, a); +	ao_int64_init64(&ao_b, b >> 32, b); + +	test(+, ao_plus64, a, b, &ao_a, &ao_b); +	test_a(+, ao_plus64, a, b, &ao_a, &ao_b); +	test_b(+, ao_plus64, a, b, &ao_a, &ao_b); +	test_x(+, ao_plus64, a, b, &ao_a, &ao_b); +	test(-, ao_minus64, a, b, &ao_a, &ao_b); +	test_a(-, ao_minus64, a, b, &ao_a, &ao_b); +	test_b(-, ao_minus64, a, b, &ao_a, &ao_b); +	test_x(-, ao_minus64, a, b, &ao_a, &ao_b); +	test(*, ao_mul64_32_32,(int64_t) (int32_t) a, (int32_t) b, (int32_t) a, (int32_t) b); +	test(*, ao_mul64, a, b, &ao_a, &ao_b); +	test_a(*, ao_mul64, a, b, &ao_a, &ao_b); +	test_b(*, ao_mul64, a, b, &ao_a, &ao_b); +	test_x(*, ao_mul64, a, b, &ao_a, &ao_b); +	test(*, ao_mul64_64_16, a, (uint16_t) b, &ao_a, (uint16_t) b); +	test_a(*, ao_mul64_64_16, a, (uint16_t) b, &ao_a, (uint16_t) b); +	test(>>, ao_rshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); +	test_a(>>, ao_rshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); +	test(<<, ao_lshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); +	test_a(<<, ao_lshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); +} + +#define TESTS	10000000 + +static int64_t +random64(void) +{ +	return (int64_t) random() + ((int64_t) random() << 31) /* + ((int64_t) random() << 33) */; +} + +int +main (int argc, char **argv) +{ +	int	i, start; + +	if (argv[1]) +		start = atoi(argv[1]); +	else +		start = 0; +	srandom(1000); +	for (i = 0; i < TESTS; i++) { +		int64_t a = random64(); +		int64_t b = random64(); +		if (i >= start) +			do_test(i, a, b); +	} +	return errors; +} diff --git a/src/test/ao_ms5607_convert_test.c b/src/test/ao_ms5607_convert_test.c new file mode 100644 index 00000000..ad593204 --- /dev/null +++ b/src/test/ao_ms5607_convert_test.c @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#define __xdata +#define __data +#define __pdata +#define __reentrant + +#include <stdint.h> +#include <ao_ms5607.h> + +struct ao_ms5607_prom ms5607_prom = { +	0x002c, +	0xa6e0, +	0x988e, +	0x6814, +	0x5eff, +	0x8468, +	0x6c86, +	0xa271, +}; + +int32_t D1_mm = 6179630; +int32_t D2_mm = 8933155; + +#include <ao_ms5607_convert.c> +#define ao_ms5607_convert ao_ms5607_convert_8051 +#include <ao_ms5607_convert_8051.c> +#include <ao_int64.c> +#include <stdio.h> +#include <stdlib.h> + +struct ao_ms5607_sample ao_sample = { +	6179630, +	8933155 +}; + +int errors; + +void test(int trial, struct ao_ms5607_sample *sample) +{ +	struct ao_ms5607_value	value, value_8051; + +	ao_ms5607_convert(sample, &value); +	ao_ms5607_convert_8051(sample, &value_8051); +	if (value.temp != value_8051.temp || value.pres != value_8051.pres) { +		++errors; +		printf ("trial %d: %d, %d -> %d, %d (should be %d, %d)\n", +			trial, +			sample->pres, sample->temp, +			value_8051.pres, value_8051.temp, +			value.pres, value.temp); +	} +} + +#define TESTS	10000000 + +#include <stdlib.h> + +static int32_t rand24(void) { return random() & 0xffffff; } + +int +main(int argc, char **argv) +{ +	struct ao_ms5607_sample sample; +	int	i, start; + +	if (argv[1]) +		start = atoi(argv[1]); +	else +		start = 0; + +	srandom(10000); +	test(-1, &ao_sample); +	for (i = 0; i < TESTS; i++) { +		sample.pres = rand24(); +		sample.temp = rand24(); +		if (i >= start) +			test(i, &sample); +	} +	return errors; +} | 
