diff options
| author | Keith Packard <keithp@keithp.com> | 2011-09-21 11:36:11 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2011-09-21 11:45:04 -0700 | 
| commit | abf17522c206b465375b73a004a6d67bfa714ba3 (patch) | |
| tree | cc6fed16722b2dbe296c3f141662747bc9a56edc | |
| parent | b2d4e49bfe88aa61ca36fb1af8f3088c5754304c (diff) | |
altos: SPI slave code is now per-product
We can't write general purpose SPI slave code as we must eliminate
any latency because the SPI ports have no buffering.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | src/avr/ao_pins.h | 7 | ||||
| -rw-r--r-- | src/avr/ao_spi_slave.c | 99 | ||||
| -rw-r--r-- | src/core/ao.h | 13 | ||||
| -rw-r--r-- | src/drivers/ao_science_slave.c | 62 | ||||
| -rw-r--r-- | src/telescience-v0.1/Makefile | 1 | 
5 files changed, 118 insertions, 64 deletions
| diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 56435f18..88f03829 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -52,6 +52,13 @@  	#define SPI_CS_DIR		DDRE  	#define M25_CS_MASK		(1 << PORTE6)  	#define M25_MAX_CHIPS		1 + +	#define SPI_SLAVE_CS_PORT	PORTB +	#define SPI_SLAVE_CS_PIN	PINB +	#define SPI_SLAVE_CS_PIN_NO	PINB0 + +	#define SPI_SLAVE_PIN_0_3	1 +	#define SPI_SLAVE_PIN_2_5	0  #endif  #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index e4d866a8..76f574c6 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -16,18 +16,8 @@   */  #include "ao.h" -#include "ao_product.h" -struct ao_companion_command	ao_companion_command; - -static const struct ao_companion_setup	ao_telescience_setup = { -	.board_id 		= AO_idProduct_NUMBER, -	.board_id_inverse	= ~AO_idProduct_NUMBER, -	.update_period		= 50, -	.channels		= AO_LOG_TELESCIENCE_NUM_ADC, -}; - -static uint8_t +uint8_t  ao_spi_read(uint8_t *buf, uint8_t len)  {  	while (len--) { @@ -39,7 +29,7 @@ ao_spi_read(uint8_t *buf, uint8_t len)  	return 1;  } -static void +void  ao_spi_write(uint8_t *buf, uint8_t len)  {  	while (len--) { @@ -52,66 +42,38 @@ ao_spi_write(uint8_t *buf, uint8_t len)  	(void) SPDR;  } -static uint8_t ao_spi_slave_recv(void) -{ -	if (!ao_spi_read((uint8_t *) &ao_companion_command, -			 sizeof (ao_companion_command))) -		return 0; - -	/* Figure out the outbound data */ -	switch (ao_companion_command.command) { -	case AO_COMPANION_SETUP: -		ao_spi_write((uint8_t *) &ao_telescience_setup, -			     sizeof (ao_telescience_setup)); -		break; -	case AO_COMPANION_FETCH: -		ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, -			     AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); -		break; -	case AO_COMPANION_NOTIFY: -		break; -	default: -		return 0; -	} - -	ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; -	if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { -		ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; -		return 1; -	} -	return 0; -} -  static uint8_t ao_spi_slave_running;  ISR(PCINT0_vect)  { -	if ((PINB & (1 << PINB0)) == 0) { +	cli(); +#if SPI_SLAVE_PIN_0_3 +	if ((PINB & (1 << PORTB0)) == 0) +#endif +#if SPI_SLAVE_PIN_2_5 +	if ((PINB & (1 << PORTB2)) == 0) +#endif +	{  		if (!ao_spi_slave_running) { -			uint8_t	changed;  			ao_spi_slave_running = 1; -			cli(); -			changed = ao_spi_slave_recv(); -			sei(); -			if (changed && ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { -				if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) -					ao_log_single_start(); -				else -					ao_log_single_stop(); -			} +			ao_spi_slave();  		}  	} else {  		ao_spi_slave_running = 0;  	} -} - -void ao_spi_slave_debug(void) { -	printf ("slave running %d\n", ao_spi_slave_running); +	sei();  }  void  ao_spi_slave_init(void)  { +	/* We'd like to have a pull-up on SS so that disconnecting the +	 * TM would cause any SPI transaction to abort. However, when +	 * I tried that, SPI transactions would spontaneously abort, +	 * making me assume that we needed a less aggressive pull-up +	 * than is offered inside the AVR +	 */ +#if SPI_SLAVE_PIN_0_3  	PCMSK0 |= (1 << PCINT0);	/* Enable PCINT0 pin change */  	PCICR |= (1 << PCIE0);		/* Enable pin change interrupt */ @@ -121,17 +83,28 @@ ao_spi_slave_init(void)  		(0 << 1) |		/* SCK, input */  		(0 << 0));		/* SS, input */ -	/* We'd like to have a pull-up on SS so that disconnecting the -	 * TM would cause any SPI transaction to abort. However, when -	 * I tried that, SPI transactions would spontaneously abort, -	 * making me assume that we needed a less aggressive pull-up -	 * than is offered inside the AVR -	 */  	PORTB = ((PORTB & 0xf0) |  		 (1 << 3) |		/* MISO, output */  		 (0 << 2) |		/* MOSI, no pull-up */  		 (0 << 1) |		/* SCK, no pull-up */  		 (0 << 0));		/* SS, no pull-up */ +#endif +#if SPI_SLAVE_PIN_2_5 +	PCMSK0 |= (1 << PCINT2);	/* Enable PCINT2 pin change */ +	PCICR |= (1 << PCIE0);		/* Enable pin change interrupt */ + +	DDRB = ((DDRB & 0xf0) | +		(0 << 5) |		/* SCK, input */ +		(1 << 4) |		/* MISO, output */ +		(0 << 3) |		/* MOSI, input */ +		(0 << 2));		/* SS, input */ + +	PORTB = ((PORTB & 0xf0) | +		 (0 << 5) |		/* SCK, no pull-up */ +		 (1 << 4) |		/* MISO, output */ +		 (0 << 3) |		/* MOSI, no pull-up */ +		 (0 << 2));		/* SS, no pull-up */ +#endif	  	SPCR = (0 << SPIE) |		/* Disable SPI interrupts */  		(1 << SPE) |		/* Enable SPI */ diff --git a/src/core/ao.h b/src/core/ao.h index a541d8ac..1d5769cb 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -974,12 +974,23 @@ ao_spi_init(void);   * ao_spi_slave.c   */ +uint8_t +ao_spi_read(uint8_t *buf, uint8_t len); +  void -ao_spi_slave_debug(void); +ao_spi_write(uint8_t *buf, uint8_t len);  void  ao_spi_slave_init(void); +/* This must be defined by the product; it will get called when chip + * select goes low, at which point it should use ao_spi_read and + * ao_spi_write to deal with the request + */ + +void +ao_spi_slave(void); +  /*   * ao_telemetry.c   */ diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c new file mode 100644 index 00000000..e902318f --- /dev/null +++ b/src/drivers/ao_science_slave.c @@ -0,0 +1,62 @@ +/* + * 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_product.h" + +struct ao_companion_command	ao_companion_command; + +static const struct ao_companion_setup	ao_telescience_setup = { +	.board_id 		= AO_idProduct_NUMBER, +	.board_id_inverse	= ~AO_idProduct_NUMBER, +	.update_period		= 50, +	.channels		= AO_LOG_TELESCIENCE_NUM_ADC, +}; + +void ao_spi_slave(void) +{ +	if (!ao_spi_read((uint8_t *) &ao_companion_command, +			 sizeof (ao_companion_command))) +		return; + +	/* Figure out the outbound data */ +	switch (ao_companion_command.command) { +	case AO_COMPANION_SETUP: +		ao_spi_write((uint8_t *) &ao_telescience_setup, +			     sizeof (ao_telescience_setup)); +		break; +	case AO_COMPANION_FETCH: +		ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, +			     AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); +		break; +	case AO_COMPANION_NOTIFY: +		break; +	default: +		return; +	} + +	ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; +	if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { +		ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; +		if (ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { +			if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) +				ao_log_single_start(); +			else +				ao_log_single_stop(); +		} +	} +} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 28620242..a6797cbe 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -46,6 +46,7 @@ ALTOS_SRC = \  	ao_romconfig.c \  	ao_usb_avr.c \  	ao_adc_avr.c \ +	ao_science_slave.c \  	ao_spi_slave.c \  	ao_log_single.c \  	ao_log_telescience.c \ | 
