
i2s tester
Revision 0:bf80bb548613, committed 2017-02-02
- Comitter:
- UHSLMarcus
- Date:
- Thu Feb 02 10:14:27 2017 +0000
- Commit message:
- procedural test
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gitignore Thu Feb 02 10:14:27 2017 +0000 @@ -0,0 +1,4 @@ +.build +.mbed +projectfiles +*.py*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Feb 02 10:14:27 2017 +0000 @@ -0,0 +1,282 @@ +#include "mbed.h" +#include "MK64F12.h" +#include "system_MK64F12.h" + +#define I2S_CONFIG_MCLKFREQ 12288000 // Hz +#define I2S_CONFIG_WORDWIDTH 16 // Bits +#define I2S_CONFIG_SAMPLERATE 32000 // Hz +#define I2S_CONFIG_FRAMEWIDTH 2 // Words +#define I2S_CONFIG_INTERUPT_THRESH 4 + +#define I2S_CONFIG_MAX_BCLK_DIV 255 +#define I2S_CONFIG_MAX_MCLK_DIV 512 +#define I2S_CONFIG_MAX_MCLK_FRACT 255 + + +Serial pc(USBTX, USBRX); + +const char *byte_to_binary(uint8_t in) +{ + static char b[9]; + b[0] = '\0'; + + int z; + for (z = 128; z > 0; z >>= 1) + { + strcat(b, ((in & z) == z) ? "1" : "0"); + } + + return b; +} + + +volatile bool itr_flag = false; +void _i2s_itr(void) { + itr_flag = true; + I2S0->TCSR &= ~I2S_TCSR_FRIE_MASK; +} + +int main() +{ + pc.baud(115200); + pc.printf("Starting...\r"); + pc.printf("System core clock: %luhz\r", (unsigned long)SystemCoreClock); + + pc.printf("Disabling I2S interupt..."); + NVIC_DisableIRQ (I2S0_Tx_IRQn); + pc.printf("Done.\rReplacing I2S interupt service routine address..."); + NVIC_SetVector (I2S0_Tx_IRQn, (uint32_t)&_i2s_itr); + pc.printf("Done.\rEnabling I2S interupts..."); + NVIC_EnableIRQ (I2S0_Tx_IRQn); + pc.printf("Done.\r"); + + pc.printf("Setting pins MUX to I2S..."); + + // Set PORTC and PORTB to clocked gate control to allow register access without hanging the MCU + SIM->SCGC5 |= SIM_SCGC5_PORTC(0x1); // Set PORTC clocked gate control to enabled + SIM->SCGC5 |= SIM_SCGC5_PORTB(0x1); // Set PORTC clocked gate control to enabled + + PORTC->PCR[8] &= ~PORT_PCR_MUX_MASK; // Clear PTC8 + PORTC->PCR[8] |= PORT_PCR_MUX(0x04); // Set PTC8 to 4, I2S0_MCLK + + PORTC->PCR[1] &= ~PORT_PCR_MUX_MASK; // Clear PTC1 + PORTC->PCR[1] |= PORT_PCR_MUX(0x04); // Set PTC1 to 4, I2S0_TXD0 + + PORTB->PCR[18] &= ~PORT_PCR_MUX_MASK; // Clear PTB18 + PORTB->PCR[18] |= PORT_PCR_MUX(0x04); // Set PTB18 to 4, I2S0_TX_BCLK + + PORTB->PCR[19] &= ~PORT_PCR_MUX_MASK; // Clear PTB19 + PORTB->PCR[19] |= PORT_PCR_MUX(0x04); // Set PTB19 to 4, I2S0_TX_FS + + pc.printf("Set\r \tPTC8=%d\r \tPTC1=%d\r \tPTB18=%d\r \tPTB19=%d\r", + (PORTC->PCR[8] >> PORT_PCR_MUX_SHIFT) & 0b111, + (PORTC->PCR[1] >> PORT_PCR_MUX_SHIFT) & 0b111, + (PORTB->PCR[18] >> PORT_PCR_MUX_SHIFT) & 0b111, + (PORTB->PCR[19] >> PORT_PCR_MUX_SHIFT) & 0b111); + + pc.printf("Starting I2S init...\r"); + SIM->SCGC6 |= SIM_SCGC6_I2S(0x1); // Set I2S clocked gate control to enabled + + pc.printf("Setting I2S Master Clock Fraction and Divider..."); + + //output = input *[(I2SFRAC+1) / (I2SDIV+1) ] = (120mhz * 0.1024) = (120M* (?/?)) = 12.288 MHz + + float target = (float)I2S_CONFIG_MCLKFREQ/(float)SystemCoreClock; // target result from the division + float least_difference = 1; // store the lowest error + int best_numerator = 0; // store the numerator which produced the lowest error + int best_denominator = 0; // store the denominator which produced the lowest error + + for (int denominator = 1; denominator < I2S_CONFIG_MAX_MCLK_DIV; denominator++) { + int numerator = int(denominator * target); + if (numerator > 0 && numerator < I2S_CONFIG_MAX_MCLK_DIV) { + float diff = abs((float)((float)numerator/(float)denominator) - target); + if (diff < least_difference) { + least_difference = diff; + best_numerator = numerator; + best_denominator = denominator; + } + if (diff == 0) break; + } + } + I2S0->MDR |= I2S_MDR_FRACT(best_numerator-1) | I2S_MDR_DIVIDE(best_denominator-1); + + pc.printf("Set. MDR[FRACT]=%d, MDR[DIVIDE]=%d, Error=%f\r", (I2S0->MDR >> I2S_MDR_FRACT_SHIFT) & 0xff, (I2S0->MDR >> I2S_MDR_DIVIDE_SHIFT) & 0xfff, least_difference); + + pc.printf("Setting I2S Master Clock..."); + I2S0->MCR |= I2S_MCR_MOE(1); + pc.printf("Set. MCR[MOE] (MCLK Output Enable) = %d, MCR[MICS] (MCLK Input Clock Select) = %d\r", (I2S0->MCR >> I2S_MCR_MOE_SHIFT) & 1, (I2S0->MCR >> I2S_MCR_MICS_SHIFT) & 0b11); + + pc.printf("Setting Bit Clock Divider..."); + + //Bit clock = sample frequency * words in a frame * bits in a word = 32000*2*16 = 1.024 MHz = 12.288 MHz/12 + int bit_clock_div = I2S_CONFIG_MCLKFREQ/(I2S_CONFIG_SAMPLERATE*I2S_CONFIG_FRAMEWIDTH*I2S_CONFIG_WORDWIDTH); + + //12 = (DIV+1)*2 => DIV+1 = 12/2 = 6 => DIV = 6-1 = 5 + int DIV = (bit_clock_div/2)-1; + I2S0->TCR2 |= I2S_TCR2_DIV(DIV); + pc.printf("Set. TCR2[DIV] (Bit Clock Divide) = %d\r", (I2S0->TCR2 >> I2S_TCR2_DIV_SHIFT) & 0xff); + + pc.printf("Setting I2S Configuration Registers...\r"); + + + pc.printf("Clearing TSCR[TE] (Trasmiitter Enable)..."); + I2S0->TCSR &= ~I2S_TCSR_TE_MASK; + pc.printf("Cleared. TSCR[TE]=%d\r", (I2S0->TCSR >> I2S_TCSR_TE_SHIFT) & 1); + + pc.printf("Setting TCR1[TFW] (Transmit FIFO Watermark) to 4..."); + I2S0->TCR1 |= I2S_TCR1_TFW(I2S_CONFIG_INTERUPT_THRESH); // threshold for generating FIFO request + pc.printf("Set. TCR1[TFW]=%d\r", (I2S0->TCR1 >> I2S_TCR1_TFW_SHIFT) & 0b111); + + pc.printf("Setting TCR2..."); + I2S0->TCR2 &= ~I2S_TCR2_SYNC_MASK; // Sync to 00 + I2S0->TCR2 |= I2S_TCR2_MSEL(1) // MSEL to MCLK 1 + | I2S_TCR2_BCD(1); // Bit Clock Direction to output (internal MCLK) + pc.printf("Set.\r \t[SYNC] Synchronous Mode = %d\r \t[MSEL] MCLK Select = %d\r \t[BCP] Bit Clock Polarity = %d\r \t[BCD] Bit Clock Direction = %d\r", + (I2S0->TCR2 >> I2S_TCR2_SYNC_SHIFT) & 0b11, + (I2S0->TCR2 >> I2S_TCR2_MSEL_SHIFT) & 1, + (I2S0->TCR2 >> I2S_TCR2_BCP_SHIFT) & 1, + (I2S0->TCR2 >> I2S_TCR2_BCD_SHIFT) & 1); + + pc.printf("Setting TCR3[TCE] (Transmit Channel Enable) to 1 (channel 0 enable)..."); + I2S0->TCR3 |= I2S_TCR3_TCE(1); + pc.printf("Set. TCR1[TFW]=%d\r", (I2S0->TCR3 >> I2S_TCR3_TCE_SHIFT) & 0b11); + + pc.printf("Setting TCR4..."); + I2S0->TCR4 |= I2S_TCR4_FRSZ(I2S_CONFIG_FRAMEWIDTH-1) // Frame width (number of words -1) + | I2S_TCR4_SYWD(I2S_CONFIG_WORDWIDTH-1) // Sync width (bits in word0 -1) (don't fully understand this one) + | I2S_TCR4_MF(1) // MSB Transmitted first + | I2S_TCR4_FSD(1); // Frame sync clock to output (master) + pc.printf("Set.\r \t[FRSZ] Frame size = %d\r \t[SYWD] Sync Width = %d\r \t[MF] MSB First = %d\r", + (I2S0->TCR4 >> I2S_TCR4_FRSZ_SHIFT) & 0b11111, + (I2S0->TCR4 >> I2S_TCR4_SYWD_SHIFT) & 0b11111, + (I2S0->TCR4 >> I2S_TCR4_MF_SHIFT) & 1); + pc.printf(" \t[FSE] Frame Sync Early = %d\r \t[FSP] Frame Sync Polarity = %d\r \t[FSD] Frame Sync Direction = %d\r", + (I2S0->TCR4 >> I2S_TCR4_FSE_SHIFT) & 1, + (I2S0->TCR4 >> I2S_TCR4_FSP_SHIFT) & 1, + (I2S0->TCR4 >> I2S_TCR4_FSD_SHIFT) & 1); + + pc.printf("Setting TCR5..."); + I2S0->TCR5 |= I2S_TCR5_WNW(I2S_CONFIG_WORDWIDTH-1) + | I2S_TCR5_W0W(I2S_CONFIG_WORDWIDTH-1) + | I2S_TCR5_FBT(I2S_CONFIG_WORDWIDTH+1); + pc.printf("Set\r \t[WNW] Word N Width = %d\r \t[W0W] Word 0 Width = %d\r \t[FBT] First Bit Shifted = %d\r", + (I2S0->TCR5 >> I2S_TCR5_WNW_SHIFT) & 0b11111, + (I2S0->TCR5 >> I2S_TCR5_W0W_SHIFT) & 0b11111, + (I2S0->TCR5 >> I2S_TCR5_FBT_SHIFT) & 0b11111); + + pc.printf("Setting TSCR[TE] (Trasmiitter Enable) & TSCR[BCE] (Bit Clock Enable) & TSCR[FRIE] (FIFO Request Interrupt Enabled)..."); + I2S0->TCSR |= I2S_TCSR_TE(1) | I2S_TCSR_BCE(1) | I2S_TCSR_FRIE(1); + pc.printf("Set\r \tTSCR[TE] = %d\r \tTSCR[BCE] = %d\r \tTSCR[FRIE] = %d\r", + (I2S0->TCSR >> I2S_TCSR_TE_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_BCE_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FRIE_SHIFT) & 1); + + + pc.printf("I2S Init Complete\rStarting loop...\r"); + + for (int i = 0; i < 9; i++) { + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d\r", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + + if (I2S0->TCSR & I2S_TCSR_WSF_MASK) I2S0->TCSR |= I2S_TCSR_WSF(1); // clear flags... + if (I2S0->TCSR & I2S_TCSR_SEF_MASK) I2S0->TCSR |= I2S_TCSR_SEF(1); + if (I2S0->TCSR & I2S_TCSR_FEF_MASK) I2S0->TCSR |= I2S_TCSR_FEF(1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + } + + + /*while (true) { + if (itr_flag) { + itr_flag = false; + pc.printf("I2S interupt triggered\r"); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + pc.printf("Transmit FIFO Register Read Pointer: %s\r", byte_to_binary(I2S0->TFR[0] & 0xF)); + pc.printf("Transmit FIFO Register Write Pointer: %s\r", byte_to_binary((I2S0->TFR[0] >> I2S_TFR_WFP_SHIFT) & 0xF)); + pc.printf("FRF: %d, WSF: %d, SEF: %d, FEF: %d, FWF: %d", + (I2S0->TCSR >> I2S_TCSR_FRF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_WSF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_SEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FEF_SHIFT) & 1, + (I2S0->TCSR >> I2S_TCSR_FWF_SHIFT) & 1); + I2S0->TDR[0] = I2S_TDR_TDR(20); + } + }*/ +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Thu Feb 02 10:14:27 2017 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#269f58d75b752a4e67a6a2d8c5c698635ffd6752