altos: SPI slave code is now per-product
authorKeith Packard <keithp@keithp.com>
Wed, 21 Sep 2011 18:36:11 +0000 (11:36 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 21 Sep 2011 18:45:04 +0000 (11:45 -0700)
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>
src/avr/ao_pins.h
src/avr/ao_spi_slave.c
src/core/ao.h
src/drivers/ao_science_slave.c [new file with mode: 0644]
src/telescience-v0.1/Makefile

index 56435f18714b3fd463f6ff8b0b137b79459c931c..88f03829ec74b9e2108c59fb5f43f2693391ed7e 100644 (file)
        #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_ */
index e4d866a823ab11501314cb7c6071b4e087a213fd..76f574c6480f6ac1012f9a43295d1c75fa4a765b 100644 (file)
  */
 
 #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 */
index a541d8acad0f73b822034db9c179063d9f68d05f..1d5769cb0f6b5c62f77588e9341aec59c6ea4e76 100644 (file)
@@ -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 (file)
index 0000000..e902318
--- /dev/null
@@ -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();
+               }
+       }
+}
index 28620242107249b0b9418495a68bf19d5ea25a7b..a6797cbe900ea1b432b2865a5e5408ecf6db1335 100644 (file)
@@ -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 \