if (!s51_tty) {
if (!s51_device)
s51_device = getenv("AO_DBG_DEVICE");
- s51_tty = cc_usbdevs_find_by_arg(s51_device, "TIDongle");
+ s51_tty = cc_usbdevs_find_by_arg(s51_device, "TeleDongle");
}
s51_dbg = ccdbg_open (s51_tty);
if (!s51_dbg)
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.2.9.1)
+AC_INIT([altos], 1.2.9.2)
AC_CONFIG_SRCDIR([src/core/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
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
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
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,
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
if (sequence) {
/* Start next conversion */
ADCCON3 = sequence;
+ return;
}
#endif /* telemini || telenano */
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 */
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
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_ */
* 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)
* 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;
#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
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 { \
#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)
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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_ */
#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
*/
#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
* 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
* 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
* 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);
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
}
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
*/
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
}
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
}
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:
ao_cmd_hex(void);
void
-ao_cmd_decimal(void);
+ao_cmd_decimal(void) __reentrant;
/* Read a single hex nibble off stdin. */
uint8_t
}
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();
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)
{
#endif
memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data));
}
+#endif
* 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 */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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_ */
__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;
ao_log(void)
{
__pdata uint16_t next_sensor, next_other;
- uint8_t i;
ao_storage_setup();
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;
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;
}
void
-ao_wakeup(__xdata void *wchan)
+ao_wakeup(__xdata void *wchan) __reentrant
{
#if HAS_TASK_QUEUE
struct ao_task *sleep, *next;
#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];
/* 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
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;
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;
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;
ao_aprs_time = time;
#endif
while (ao_telemetry_interval) {
-
#if HAS_APRS
if (!(ao_config.radio_enable & AO_RADIO_DISABLE_TELEMETRY))
#endif
#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)
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 */
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) {
/* 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 */
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;
};
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;
}
#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) {
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();
}
}
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++;
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);
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
#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)
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();
}
}
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));
}
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);
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_ */
--- /dev/null
+/*
+ * 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;
+}
/* 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
--- /dev/null
+#
+# 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:
+
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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();
+}
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
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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}