altosdroid: Implement voice just like altosui
[fw/altos] / src / stm / ao_spi_stm.c
index 92747d87c94bca49f9403704ce19050d4ff28586..547de9e50ca0b887864ecaab28986d923b2ed572 100644 (file)
@@ -23,7 +23,7 @@ struct ao_spi_stm_info {
        struct stm_spi *stm_spi;
 };
 
-uint8_t        ao_spi_mutex[STM_NUM_SPI];
+uint8_t                ao_spi_mutex[STM_NUM_SPI];
 
 static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
        {
@@ -96,6 +96,62 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index)
        ao_dma_done_transfer(miso_dma_index);
 }
 
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+       struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+
+       /* Set up the transmit DMA to deliver data */
+       ao_dma_set_transfer(mosi_dma_index,
+                           &stm_spi->dr,
+                           &value,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (0 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       /* Set up the receive DMA -- when this is done, we know the SPI unit
+        * is idle. Without this, we'd have to poll waiting for the BSY bit to
+        * be cleared
+        */
+       ao_dma_set_transfer(miso_dma_index,
+                           &stm_spi->dr,
+                           &spi_dev_null,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (0 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (1 << STM_SPI_CR2_TXDMAEN) |
+                       (1 << STM_SPI_CR2_RXDMAEN));
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
 {
@@ -154,7 +210,64 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
 }
 
 void
-ao_spi_get(uint8_t spi_index)
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
+{
+       struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+
+       /* Set up transmit DMA to send data */
+       ao_dma_set_transfer(mosi_dma_index,
+                           &stm_spi->dr,
+                           out,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
+
+       /* Clear RXNE */
+       (void) stm_spi->dr;
+
+       /* Set up the receive DMA to capture data */
+       ao_dma_set_transfer(miso_dma_index,
+                           &stm_spi->dr,
+                           in,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (1 << STM_SPI_CR2_TXDMAEN) |
+                       (1 << STM_SPI_CR2_RXDMAEN));
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+
+       /* Wait until the SPI unit is done */
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed)
 {
        struct stm_spi  *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
 
@@ -167,9 +280,9 @@ ao_spi_get(uint8_t spi_index)
                        (0 << STM_SPI_CR1_RXONLY) |
                        (1 << STM_SPI_CR1_SSM) |                        /* Software SS handling */
                        (1 << STM_SPI_CR1_SSI) |                        /*  ... */
-                       (0 << STM_SPI_CR1_LSBFIRST) |                   /* Little endian */
+                       (0 << STM_SPI_CR1_LSBFIRST) |                   /* Big endian */
                        (1 << STM_SPI_CR1_SPE) |                        /* Enable SPI unit */
-                       (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) |     /* baud rate to pclk/4 */
+                       (speed << STM_SPI_CR1_BR) |     /* baud rate to pclk/4 */
                        (1 << STM_SPI_CR1_MSTR) |
                        (0 << STM_SPI_CR1_CPOL) |                       /* Format 0 */
                        (0 << STM_SPI_CR1_CPHA));
@@ -229,9 +342,6 @@ ao_spi_init(void)
        stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
 
        ao_spi_channel_init(0);
-
-       stm_nvic_set_enable(STM_ISR_SPI1_POS);
-       stm_nvic_set_priority(STM_ISR_SPI1_POS, 3);
 #endif
 
 #if HAS_SPI_2
@@ -254,8 +364,5 @@ ao_spi_init(void)
        stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
 
        ao_spi_channel_init(1);
-
-       stm_nvic_set_enable(STM_ISR_SPI2_POS);
-       stm_nvic_set_priority(STM_ISR_SPI2_POS, 3);
 #endif
 }