summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2014-09-01 19:58:25 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2014-09-01 19:58:25 +0200
commit4b4c5bb3fa573c3c2f34605bbbc0936925d4360d (patch)
treef7b55337adb6e14497b89252b8d82af25fe42827
parent31bda341e14c2248ca00ec89c3380349c23c0a34 (diff)
More I2S driver work.
-rw-r--r--firmware/drivers/i2s.c662
-rw-r--r--firmware/drivers/i2s.h134
-rw-r--r--firmware/drivers/wm8523.c14
3 files changed, 606 insertions, 204 deletions
diff --git a/firmware/drivers/i2s.c b/firmware/drivers/i2s.c
index 0085e1d..7c87133 100644
--- a/firmware/drivers/i2s.c
+++ b/firmware/drivers/i2s.c
@@ -1,159 +1,503 @@
-/****************************************************************************
- * $Id:: i2s.c 5797 2010-12-03 00:27:00Z usb00423 $
- * Project: NXP LPC17xx I2S example
- *
- * Description:
- * This file contains I2S code example which include I2S initialization,
- * I2C interrupt handler, and APIs for I2S access.
- *
- ****************************************************************************
- * Software that is described herein is for illustrative purposes only
- * which provides customers with programming information regarding the
- * products. This software is supplied "AS IS" without any warranties.
- * NXP Semiconductors assumes no responsibility or liability for the
- * use of the software, conveys no license or title under any patent,
- * copyright, or mask work right to the product. NXP Semiconductors
- * reserves the right to make changes in the software without
- * notification. NXP Semiconductors also make no representation or
- * warranty that such application will be suitable for the specified
- * use without further testing or modification.
-****************************************************************************/
-#include <LPC17xx.h>
-//#include "type.h"
-#include "i2s.h"
-#include "dma.h"
-
-/* treat I2S TX and RX as a constant address, make the code and buffer
-easier for both DMA and non-DMA test */
-volatile uint8_t *I2STXBuffer = (uint8_t *)(DMA_SRC);
-volatile uint8_t *I2SRXBuffer = (uint8_t *)(DMA_DST);
-volatile uint32_t I2SReadLength = 0;
-volatile uint32_t I2SWriteLength = 0;
-volatile uint32_t I2SRXDone = 0, I2STXDone = 0;
-
-/*****************************************************************************
-** Function name: I2S_IRQHandler
-**
-** Descriptions: I2S interrupt handler, only RX interrupt is enabled
-** for simplicity.
-**
-** parameters: None
-** Returned value: None
-**
-*****************************************************************************/
-void I2S_IRQHandler (void)
-{
- uint32_t RxCount = 0;
-
- if ( LPC_I2S->I2SSTATE & 0x01 )
- {
- RxCount = (LPC_I2S->I2SSTATE >> 8) & 0xFF;
- if ( (RxCount != RXFIFO_EMPTY) && !I2SRXDone )
- {
- while ( RxCount > 0 )
- {
- if ( I2SReadLength == BUFSIZE )
- {
- LPC_I2S->I2SDAI |= ((0x01 << 3) | (0x01 << 4));
- LPC_I2S->I2SIRQ &= ~(0x01 << 0); /* Disable RX */
- I2SRXDone = 1;
- break;
- }
- else
- {
- I2SRXBuffer[I2SReadLength++] = LPC_I2S->I2SRXFIFO;
- }
- RxCount--;
- }
- }
- }
- return;
-}
-
-/*****************************************************************************
-** Function name: I2SStart
-**
-** Descriptions: Start I2S DAI and DAO
-**
-** parameters: None
-** Returned value: None
-**
-*****************************************************************************/
-void I2SStart( void )
-{
- uint32_t DAIValue, DAOValue;
-
- /* Audio output is the master, audio input is the slave, */
- /* 16 bit data, stereo, reset, master mode, not mute. */
- DAOValue = LPC_I2S->I2SDAO;
- DAIValue = LPC_I2S->I2SDAI;
- LPC_I2S->I2SDAO = DAOValue & (~((0x01 << 4)|(0x01 <<3)));
- /* 16 bit data, stereo, reset, slave mode, not mute. */
- LPC_I2S->I2SDAI = DAIValue & (~((0x01 << 4)|(0x01 <<3)));
- return;
-}
-
-/*****************************************************************************
-** Function name: I2SStop
-**
-** Descriptions: Stop I2S DAI and DAO
-**
-** parameters: None
-** Returned value: None
-**
-*****************************************************************************/
-void I2SStop( void )
-{
- uint32_t DAIValue, DAOValue;
-
- /* Stop the I2S to start. Audio output is master, audio input is the slave. */
- /* 16 bit data, set STOP and RESET bits to reset the channels */
- DAOValue = LPC_I2S->I2SDAO;
- /* Switch to master mode, TX channel, no mute */
- DAOValue &= ~((0x01 << 5)|(0x01 << 15));
- DAIValue = LPC_I2S->I2SDAI;
- DAIValue &= ~(0x01 << 15);
- LPC_I2S->I2SDAO = (0x01 << 4) | (0x01 << 3) | DAOValue; /* Master */
- LPC_I2S->I2SDAI = (0x01 << 4) | (0x01 << 3) | DAIValue; /* Slave */
- return;
-}
-
-/*****************************************************************************
-** Function name: I2SInit
-**
-** Descriptions: Initialize I2S controller
-**
-** parameters: None
-** Returned value: true or false, return false if the I2S
-** interrupt handler was not installed correctly
-**
-*****************************************************************************/
-void I2SInit( void )
-{
-
- /*enable I2S in the PCONP register. I2S is disabled on reset*/
- LPC_SC->PCONP |= (1 << 27);
-
- /*connect the I2S sigals to port pins(P0.4-P0.9)*/
- LPC_PINCON->PINSEL0 &= ~0x000FFF00;
- LPC_PINCON->PINSEL0 |= 0x00055500;
-
- /* Please note, in order to generate accurate TX/RX clock rate for I2S,
- PCLK and CCLK needs to be carefully reconsidered. For this test
- program, the TX is looped back to RX without external I2S device,
- clock rate is not critical in this matter. */
- LPC_I2S->I2STXRATE = //0x241;
- (100 << 0) | // Y
- (49 << 8) // X
- ;
-
- // LPC_I2S->I2SRXRATE = 0x241;
-
- I2SStop();
- return;
-}
-
-/******************************************************************************
-** End Of File
-******************************************************************************/
-
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * i2s.c
+ *
+ * Thu Aug 21 18:09:54 CEST 2014
+ * Copyright 2014 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pedal2Metal.
+ *
+ * Pedal2Metal 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pedal2Metal 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 Pedal2Metal; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "i2s.h"
+
+static void i2s_set_power(int power)
+{
+ // 1. Enable I²S in PCONP register. Set PCI2S to 1 (see table 46, pg. 64)
+ // Remark: On reset, the I²S interface is disabled (PCI2S = 0).
+ uint32_t *pconp = (uint32_t *)0x400FC0C4;
+ *pconp &= ~(0b1 << 27); // Clear bit
+ *pconp |= ~( (power & 0b1) << 27); // Set bit
+}
+
+typedef enum {
+ I2S_CCLK_4 = 0b00, // PCLK_peripheral = CCLK/4
+ I2S_CCLK = 0b01, // PCLK_peripheral = CCLK
+ I2S_CCLK_2 = 0b10, // PCLK_peripheral = CCLK/2
+ I2S_CCLK_8 = 0b11, // PCLK_peripheral = CCLK/8, except for CAN1, CAN2, and
+ // CAN filtering when 0b11 selects = CCLK/6.
+} i2s_clksel_t;
+
+static void i2s_set_clksel(i2s_clksel_t sel)
+{
+ // 2. Clock: In PCLKSEL1 select PCLK_I2S. (see table 41, pg. 57)
+ uint32_t *pclksel1 = (uint32_t*)0x400FC1AC;
+ *pclksel1 &= ~(0b11 << 22); // Clear bits
+ *pclksel1 |= ( (sel & 0b11) << 22); // Set bits
+}
+
+static void i2s_set_pinsel()
+{
+ //3. Pins: Select I²S pins and their modes in PINSEL0 to PINSEL4 and PINMODE0
+ // to PINMODE4 (see Section 8.5).
+
+ // See table 79, pg. 108
+ uint32_t *pinsel0 = (uint32_t*)0x4002C000;
+
+ // Reset ports
+ *pinsel0 &=
+ ~(
+ /* // We only do TX
+ (0b11 << 8) | // P0.4
+ (0b11 << 10) | // P0.5
+ (0b11 << 12) | // P0.6
+ */
+ (0b11 << 14) | // P0.7
+ (0b11 << 16) | // P0.8
+ (0b11 << 18)) // P0.9
+ ;
+
+ // Set ports
+ *pinsel0 |=
+ (
+ /* // We only do TX
+ (0b01 << 8) | // P0.4: I2SRX_CLK
+ (0b01 << 10) | // P0.5: I2SRX_WS
+ (0b01 << 12) | // P0.6: I2SRX_SDA
+ */
+ (0b01 << 14) | // P0.7: I2STX_CLK
+ (0b01 << 16) | // P0.8: I2STX_WS
+ (0b01 << 18)) // P0.9: I2STX_SDA
+ ;
+
+ // See table 85, pg. 111
+ uint32_t *pinsel9 = (uint32_t *)0x4002C024;
+
+ // Reset
+ *pinsel9 &=
+ ~(0b11 << 26) // P4.28
+ ;
+
+ // Set port
+ *pinsel9 |=
+ (0b01 << 26) // P4.28: TX_MCLK
+ ;
+}
+
+typedef enum {
+ WW_8_BIT = 0b00, // 8-bit data
+ WW_16_BIT = 0b01, // 16-bit data
+ WW_RESERVED = 0b10, // Reserved, do not use this setting
+ WW_32_BIT = 0b11, // 32-bit data
+} wordwidth_t;
+
+typedef enum {
+ CH_MONO = 0b1, // Data is mono format
+ CH_STEREO = 0b0, // Data is stereo format
+} channels_t;
+
+/**
+ * Sets DAO register values and stops/resets the bus.
+ */
+static void i2s_set_dao_register(wordwidth_t ww,
+ channels_t ch)
+{
+ // See table 405, pg. 476
+ uint32_t *i2sdao = (uint32_t*)0x400A8000;
+ *i2sdao =
+ (ww << 0) | // Set bit word width
+ (ch << 2) | // stereo
+ (0b1 << 3) | // stop bit
+ (0b1 << 4) | // reset
+ (0b0 << 5) | // ws_sel in master mode
+ (0x1f << 6) | // ws_halfperiod ... default for now
+ (0b0 << 15) // no mute
+ ;
+}
+
+/*
+**
+ * Sets DAI register values and stops/resets the bus.
+ *
+static void i2s_set_dai_register(wordwidth_t ww,
+ channels_t ch)
+{
+ // See table 406, pg. 477
+ uint32_t *i2sdai = (uint32_t*)0x400A8004;
+ *i2sdai =
+ (ww << 0) | // Set bit word width
+ (ch << 2) | // stereo
+ (0b1 << 3) | // stop bit
+ (0b1 << 4) | // reset
+ (0b0 << 5) | // ws_sel in master mode
+ (0x1f << 6) | // ws_halfperiod ... default for now
+ (0b0 << 15) // no mute
+ ;
+}
+*/
+
+/**
+ * I2STXMCLK = PCLK_I2S * (X/Y) /2
+ */
+static void i2s_set_tx_rate(uint8_t y_div, uint8_t x_div)
+{
+ // See table 413, pg. 480
+ uint32_t *i2stxrate = (uint32_t*)0x400A8020;
+ *i2stxrate = y_div | (x_div << 8);
+}
+
+/*
+static void i2s_set_rx_rate(uint8_t y_div, uint8_t x_div)
+{
+ // See table 414, pg. 481
+ uint32_t *i2srxrate = (uint32_t*)0x400A8024;
+ *i2srxrate = y_div | (x_div << 8);
+}
+*/
+
+/**
+ * I²S transmit bit rate. This value plus one is used to divide TX_MCLK to
+ * produce the transmit bit clock.
+ */
+static void i2s_set_tx_clock_bitrate(uint8_t bitrate)
+{
+ // See table 415, pg. 481
+ uint32_t *i2stxbitrate = (uint32_t*)0x400A8028;
+ *i2stxbitrate = (bitrate & 0b111111);
+}
+
+/*
+static void i2s_set_rx_clock_bitrate(uint8_t bitrate)
+{
+ // See table 416, pg. 481
+ uint32_t *i2srxbitrate = (uint32_t*)0x400A802C;
+ *i2srxbitrate = (bitrate & 0b111111);
+}
+*/
+
+typedef enum {
+ CLK_TX_SRC = 0b00, // Select the TX fractional rate divider clock output as the source
+ CLK_RX_MCLK = 0b10, // Select the RX_MCLK signal as the TX_MCLK clock source
+} clksel_t;
+
+static void i2s_set_tx_mode_control(clksel_t c, int _4pin, int mcena)
+{
+ // See table 417, pg 482
+ uint32_t *i2stxmode = (uint32_t*)0x400A8030;
+ *i2stxmode = c |
+ ((_4pin & 0b1) << 2) |
+ ((mcena & 0b1) << 3)
+ ;
+}
+
+/*
+static void i2s_set_rx_mode_control(clksel_t c, int _4pin, int mcena)
+{
+ // See table 418, pg 483
+ uint32_t *i2srxmode = (uint32_t*)0x400A8034;
+ *i2stxmode = c |
+ ((_4pin & 0b1) << 2) |
+ ((mcena & 0b1) << 3)
+ ;
+}
+*/
+
+static void i2s_tx_reset()
+{
+ // See table 405, pg. 476
+ uint32_t *i2sdao = (uint32_t*)0x400A8000;
+ *i2sdao |=
+ (0b1 << 4) // reset
+ ;
+}
+
+void i2s_tx_stop()
+{
+ // See table 405, pg. 476
+ uint32_t *i2sdao = (uint32_t*)0x400A8000;
+ *i2sdao |=
+ (0b1 << 3) // stop bit
+ ;
+}
+
+void i2s_tx_start()
+{
+ // See table 405, pg. 476
+ uint32_t *i2sdao = (uint32_t*)0x400A8000;
+ *i2sdao &=
+ ~((0b1 << 3) | // unset stop bit (start)
+ (0b1 << 15)) // unset mute bit (unmute)
+ ;
+}
+
+/*
+static void i2s_rx_reset()
+{
+ // See table 406, pg. 477
+ uint32_t *i2sdai = (uint32_t*)0x400A8004;
+ *i2sdai |=
+ (0b1 << 4) // reset
+ ;
+}
+*/
+
+/*
+static void i2s_rx_stop()
+{
+ // See table 406, pg. 477
+ uint32_t *i2sdai = (uint32_t*)0x400A8004;
+ *i2sdai |=
+ (0b1 << 3) // stop bit
+ ;
+}
+*/
+/*
+static void i2s_rx_start()
+{
+ // See table 406, pg. 477
+ uint32_t *i2sdai = (uint32_t*)0x400A8004;
+ *i2sdai &=
+ ~(0b1 << 3) // stop bit
+ ;
+}
+ */
+/*
+ * A data sample in the FIFO consists of:
+ * - 1×32 bits in 8-bit or 16-bit stereo modes.
+ * - 1×32 bits in mono modes.
+ * - 2×32 bits, first left data, second right data, in 32-bit stereo modes.
+ *
+ * I2STXFIFO: 0x400A 8008 - 8 x 32 bit
+ * I2SRXFIFO: 0x400A 800C - 8 x 32 bit
+ *
+ * See figure 113, pg. 489, for examples.
+ */
+
+/**
+ * This bit reflects the presence of Receive Interrupt or Transmit Interrupt.
+ * This is determined by comparing the current FIFO levels to the rx_depth_irq
+ * and tx_depth_irq fields in the I2SIRQ register.
+ */
+int i2s_get_state_irq()
+{
+ // See table 409, pg.478
+ uint32_t *i2sstate = (uint32_t*)0x400A8010;
+ return (*i2sstate >> 0) & 0b1; // bit 0
+}
+
+/**
+ * This bit reflects the presence of Receive or Transmit DMA Request 1. This is
+ * determined by comparing the current FIFO levels to the rx_depth_dma1 and
+ * tx_depth_dma1 fields in the I2SDMA1 register.
+ */
+int i2s_get_state_dmareq1()
+{
+ // See table 409, pg.478
+ uint32_t *i2sstate = (uint32_t*)0x400A8010;
+ return (*i2sstate >> 1) & 0b1; // bit 1
+}
+
+/**
+ * This bit reflects the presence of Receive or Transmit DMA Request 2. This is
+ * determined by comparing the current FIFO levels to the rx_depth_dma2 and
+ * tx_depth_dma2 fields in the I2SDMA2 register.
+ */
+int i2s_get_state_dmareq2()
+{
+ // See table 409, pg.478
+ uint32_t *i2sstate = (uint32_t*)0x400A8010;
+ return (*i2sstate >> 2) & 0b1; // bit 2
+}
+
+/**
+ * Reflects the current level of the Receive FIFO.
+ */
+int i2s_get_state_rx_level()
+{
+ // See table 409, pg.478
+ uint32_t *i2sstate = (uint32_t*)0x400A8010;
+ return (*i2sstate >> 8) & 0b1111; // bit 8-11
+}
+
+/**
+ * Reflects the current level of the Transmit FIFO.
+ */
+int i2s_get_state_tx_level()
+{
+ // See table 409, pg.478
+ uint32_t *i2sstate = (uint32_t*)0x400A8010;
+ return (*i2sstate >> 16) & 0b1111; // bit 16-19
+}
+
+void i2s_init()
+{
+ i2s_set_power(1);
+ i2s_set_clksel(I2S_CCLK_2);
+ i2s_set_pinsel();
+ i2s_set_dao_register(WW_16_BIT, CH_STEREO);
+ i2s_set_tx_rate(1, 1);
+ i2s_set_tx_clock_bitrate(7);
+ i2s_set_tx_mode_control(CLK_TX_SRC, 1, 1);
+
+ i2s_tx_reset();
+ i2s_tx_stop();
+
+ int i;
+ i = i2s_get_state_irq();
+ i = i2s_get_state_dmareq1();
+ i = i2s_get_state_dmareq2();
+ i = i2s_get_state_rx_level();
+ i = i2s_get_state_tx_level();
+ (void)i;
+}
+
+#if 0
+#include <LPC17xx.h>
+//#include "type.h"
+#include "dma.h"
+
+/* treat I²S TX and RX as a constant address, make the code and buffer
+easier for both DMA and non-DMA test */
+volatile uint8_t *I2STXBuffer = (uint8_t *)(DMA_SRC);
+volatile uint8_t *I2SRXBuffer = (uint8_t *)(DMA_DST);
+volatile uint32_t I2SReadLength = 0;
+volatile uint32_t I2SWriteLength = 0;
+volatile uint32_t I2SRXDone = 0, I2STXDone = 0;
+
+/*****************************************************************************
+** Function name: I2S_IRQHandler
+**
+** Descriptions: I²S interrupt handler, only RX interrupt is enabled
+** for simplicity.
+**
+** parameters: None
+** Returned value: None
+**
+*****************************************************************************/
+void I2S_IRQHandler (void)
+{
+ uint32_t RxCount = 0;
+
+ if ( LPC_I2S->I2SSTATE & 0x01 )
+ {
+ RxCount = (LPC_I2S->I2SSTATE >> 8) & 0xFF;
+ if ( (RxCount != RXFIFO_EMPTY) && !I2SRXDone )
+ {
+ while ( RxCount > 0 )
+ {
+ if ( I2SReadLength == BUFSIZE )
+ {
+ LPC_I2S->I2SDAI |= ((0x01 << 3) | (0x01 << 4));
+ LPC_I2S->I2SIRQ &= ~(0x01 << 0); /* Disable RX */
+ I2SRXDone = 1;
+ break;
+ }
+ else
+ {
+ I2SRXBuffer[I2SReadLength++] = LPC_I2S->I2SRXFIFO;
+ }
+ RxCount--;
+ }
+ }
+ }
+ return;
+}
+
+/*****************************************************************************
+** Function name: I2SStart
+**
+** Descriptions: Start I²S DAI and DAO
+**
+** parameters: None
+** Returned value: None
+**
+*****************************************************************************/
+void I2SStart( void )
+{
+ uint32_t DAIValue, DAOValue;
+
+ /* Audio output is the master, audio input is the slave, */
+ /* 16 bit data, stereo, reset, master mode, not mute. */
+ DAOValue = LPC_I2S->I2SDAO;
+ DAIValue = LPC_I2S->I2SDAI;
+ LPC_I2S->I2SDAO = DAOValue & (~((0x01 << 4)|(0x01 <<3)));
+ /* 16 bit data, stereo, reset, slave mode, not mute. */
+ LPC_I2S->I2SDAI = DAIValue & (~((0x01 << 4)|(0x01 <<3)));
+ return;
+}
+
+/*****************************************************************************
+** Function name: I2SStop
+**
+** Descriptions: Stop I²S DAI and DAO
+**
+** parameters: None
+** Returned value: None
+**
+*****************************************************************************/
+void I2SStop( void )
+{
+ uint32_t DAIValue, DAOValue;
+
+ /* Stop the I²S to start. Audio output is master, audio input is the slave. */
+ /* 16 bit data, set STOP and RESET bits to reset the channels */
+ DAOValue = LPC_I2S->I2SDAO;
+ /* Switch to master mode, TX channel, no mute */
+ DAOValue &= ~((0x01 << 5)|(0x01 << 15));
+ DAIValue = LPC_I2S->I2SDAI;
+ DAIValue &= ~(0x01 << 15);
+ LPC_I2S->I2SDAO = (0x01 << 4) | (0x01 << 3) | DAOValue; /* Master */
+ LPC_I2S->I2SDAI = (0x01 << 4) | (0x01 << 3) | DAIValue; /* Slave */
+ return;
+}
+
+/*****************************************************************************
+** Function name: I2SInit
+**
+** Descriptions: Initialize I²S controller
+**
+** parameters: None
+** Returned value: true or false, return false if the I²S
+** interrupt handler was not installed correctly
+**
+*****************************************************************************/
+void I2SInit( void )
+{
+
+ /*enable I²S in the PCONP register. I²S is disabled on reset*/
+ LPC_SC->PCONP |= (1 << 27);
+
+ /*connect the I²S sigals to port pins(P0.4-P0.9)*/
+ LPC_PINCON->PINSEL0 &= ~0x000FFF00;
+ LPC_PINCON->PINSEL0 |= 0x00055500;
+
+ /* Please note, in order to generate accurate TX/RX clock rate for I²S,
+ PCLK and CCLK needs to be carefully reconsidered. For this test
+ program, the TX is looped back to RX without external I²S device,
+ clock rate is not critical in this matter. */
+ LPC_I2S->I2STXRATE = //0x241;
+ (100 << 0) | // Y
+ (49 << 8) // X
+ ;
+
+ // LPC_I2S->I2SRXRATE = 0x241;
+
+ I2SStop();
+ return;
+}
+#endif
diff --git a/firmware/drivers/i2s.h b/firmware/drivers/i2s.h
index dbbb6f2..6e3acf2 100644
--- a/firmware/drivers/i2s.h
+++ b/firmware/drivers/i2s.h
@@ -1,41 +1,93 @@
-/****************************************************************************
- * $Id:: i2s.h 5797 2010-12-03 00:27:00Z usb00423 $
- * Project: NXP LPC17xx I2S example
- *
- * Description:
- * This file contains I2S code header definition.
- *
- ****************************************************************************
- * Software that is described herein is for illustrative purposes only
- * which provides customers with programming information regarding the
- * products. This software is supplied "AS IS" without any warranties.
- * NXP Semiconductors assumes no responsibility or liability for the
- * use of the software, conveys no license or title under any patent,
- * copyright, or mask work right to the product. NXP Semiconductors
- * reserves the right to make changes in the software without
- * notification. NXP Semiconductors also make no representation or
- * warranty that such application will be suitable for the specified
- * use without further testing or modification.
-****************************************************************************/
-#ifndef __I2S_H
-#define __I2S_H
-
-//#include "../src/sample.h"
-
-#define I2S_DMA_ENABLED 1
-
-#define BUFSIZE 0x200
-//(1097 * sizeof(short) * 2)/*stereo*/
-//((int)(sizeof(samples) * 2/*stereo*/))
-#define RXFIFO_EMPTY 0
-#define TXFIFO_FULL 8
-
-extern void I2S_IRQHandler( void );
-extern void I2SStart( void );
-extern void I2SStop( void );
-extern void I2SInit( void );
-
-#endif /* end __I2S_H */
-/****************************************************************************
-** End Of File
-*****************************************************************************/
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * i2s.h
+ *
+ * Thu Aug 21 18:09:54 CEST 2014
+ * Copyright 2014 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pedal2Metal.
+ *
+ * Pedal2Metal 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pedal2Metal 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 Pedal2Metal; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PEDAL2METAL_I2S_H__
+#define __PEDAL2METAL_I2S_H__
+
+#include <stdint.h>
+
+void i2s_init();
+
+/**
+ * Enables accesses on FIFOs, places the transmit channel in unmute mode.
+ */
+void i2s_tx_start();
+
+/**
+ * Disables accesses on FIFOs, places the transmit channel in mute mode.
+ */
+void i2s_tx_stop();
+
+/**
+ * This bit reflects the presence of Receive Interrupt or Transmit Interrupt.
+ * This is determined by comparing the current FIFO levels to the rx_depth_irq
+ * and tx_depth_irq fields in the I2SIRQ register.
+ */
+int i2s_get_state_irq();
+
+/**
+ * This bit reflects the presence of Receive or Transmit DMA Request 1. This is
+ * determined by comparing the current FIFO levels to the rx_depth_dma1 and
+ * tx_depth_dma1 fields in the I2SDMA1 register.
+ */
+int i2s_get_state_dmareq1();
+
+/**
+ * This bit reflects the presence of Receive or Transmit DMA Request 2. This is
+ * determined by comparing the current FIFO levels to the rx_depth_dma2 and
+ * tx_depth_dma2 fields in the I2SDMA2 register.
+ */
+int i2s_get_state_dmareq2();
+
+/**
+ * Reflects the current level of the Receive FIFO.
+ */
+int i2s_get_state_rx_level();
+
+/**
+ * Reflects the current level of the Transmit FIFO.
+ */
+int i2s_get_state_tx_level();
+
+
+#if 0
+
+#define I2S_DMA_ENABLED 1
+
+#define BUFSIZE 0x200
+//(1097 * sizeof(short) * 2)/*stereo*/
+//((int)(sizeof(samples) * 2/*stereo*/))
+#define RXFIFO_EMPTY 0
+#define TXFIFO_FULL 8
+
+extern void I2S_IRQHandler( void );
+extern void I2SStart( void );
+extern void I2SStop( void );
+extern void I2SInit( void );
+
+#endif
+
+#endif/*__PEDAL2METAL_I2S_H__*/
diff --git a/firmware/drivers/wm8523.c b/firmware/drivers/wm8523.c
index 96d5cae..e1711fd 100644
--- a/firmware/drivers/wm8523.c
+++ b/firmware/drivers/wm8523.c
@@ -113,6 +113,10 @@ void wm8523_init(uint8_t portnum, wm8523_samplerate_t fs)
if(portnum == 0) SSP0Init();
else SSP1Init();
+#if 1
+ i2s_init();
+ (void)fs;
+#else
I2SInit();
// pg. 482
@@ -138,8 +142,8 @@ void wm8523_init(uint8_t portnum, wm8523_samplerate_t fs)
// I2STXBITRATE 0x400A 8028
// bit 0-5 I2S transmit bit rate. This value plus one is used to divide TX_MCLK to produce the transmit bit clock.
// set to 31 (divide by 32): stereo (2) * 16bit
- uint32_t *i2stxbirate = (uint32_t *)0x400a8028;
- *i2stxbirate = 7;
+ uint32_t *i2stxbitrate = (uint32_t *)0x400a8028;
+ *i2stxbitrate = 7;
// bitclock = mclock / (divider+1)
// samplerate = mclock / bitclock
@@ -179,7 +183,8 @@ void wm8523_init(uint8_t portnum, wm8523_samplerate_t fs)
(0b1111 << 4) | // Divide by 16
(0b1 << 8) // Enable
;
- */
+ */
+#endif
}
unsigned short wm8523_get_chip_id(uint8_t portnum)
@@ -315,7 +320,8 @@ void wm8523_tone()
NVIC_EnableIRQ(I2S_IRQn);
// RX FIFO depth is 1, TX FIFO depth is 8.
- I2SStart();
+ //I2SStart();
+ i2s_tx_start();
LPC_I2S->I2SIRQ = (8 << 16) | (1 << 8) | (0x01 << 0);
//uint32_t val = 0;