codec.c 15.9 KB
Newer Older
B
bernard.xiong 已提交
1 2 3
#include <rthw.h>
#include <rtthread.h>
#include "stm32f10x.h"
4
#include "codec.h"
B
bernard.xiong 已提交
5

6 7
#define CODEC_MASTER_MODE	0

B
bernard.xiong 已提交
8 9
/*
SCLK  PA5  SPI1_SCK
wuyangyong's avatar
wuyangyong 已提交
10
SDIN  PA7  SPI1_MOSI
B
bernard.xiong 已提交
11 12
CSB   PC5
*/
13 14 15 16 17 18
#define CODEC_CSB_PORT		GPIOC
#define CODEC_CSB_PIN		GPIO_Pin_5
#define codec_set_csb()		do { CODEC_CSB_PORT->BSRR = CODEC_CSB_PIN; } while (0)
#define codec_reset_csb()	do { CODEC_CSB_PORT->BRR = CODEC_CSB_PIN; } while (0)

void vol(uint16_t v);
19
static void codec_send(rt_uint16_t s_data);
B
bernard.xiong 已提交
20 21 22

#define DATA_NODE_MAX 5
/* data node for Tx Mode */
23
struct codec_data_node
B
bernard.xiong 已提交
24 25 26 27 28
{
    rt_uint16_t *data_ptr;
    rt_size_t  data_size;
};

29
struct codec_device
B
bernard.xiong 已提交
30 31 32 33 34
{
    /* inherit from rt_device */
    struct rt_device parent;

    /* pcm data list */
35
    struct codec_data_node data_list[DATA_NODE_MAX];
B
bernard.xiong 已提交
36 37 38 39 40
    rt_uint16_t read_index, put_index;

    /* transmitted offset of current data node */
    rt_size_t offset;
};
41 42
struct codec_device codec;

43 44
static uint16_t r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8;
static uint16_t zero = 0;
B
bernard.xiong 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

static void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    /* SPI2 IRQ Channel configuration */
    NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* DMA1 IRQ Channel configuration */
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

static void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

69 70 71 72 73 74 75 76 77
	/* Disable the JTAG interface and enable the SWJ interface */
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

	/* PC5 CODEC CS */
	GPIO_InitStructure.GPIO_Pin = CODEC_CSB_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(CODEC_CSB_PORT, &GPIO_InitStructure);

78 79 80 81 82 83 84 85 86 87 88 89 90
#if CODEC_MASTER_MODE
	// WS, CK
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	// SD
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
#else
91 92
	/* Configure SPI2 pins: CK, WS and SD */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
93
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
94 95
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
96
#endif
97 98 99 100 101 102 103 104 105

#ifdef CODEC_USE_MCO
	/*    MCO    configure */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	RCC_MCOConfig(RCC_MCO_HSE);
B
bernard.xiong 已提交
106 107 108 109 110
#endif
}

static void DMA_Configuration(rt_uint32_t addr, rt_size_t size)
{
111 112 113 114 115 116 117 118 119 120 121 122
    DMA_InitTypeDef DMA_InitStructure;

	/* DMA1 Channel2 configuration ----------------------------------------------*/
	DMA_Cmd(DMA1_Channel5, DISABLE);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI2->DR));
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) addr;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	DMA_InitStructure.DMA_BufferSize = size;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
123
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
124 125
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
126 127 128 129
#if CODEC_MASTER_MODE
	while ((SPI2->SR & SPI_SR_CHSIDE) == 1);
	DMA_ClearFlag(DMA1_FLAG_TC5);
#endif
130 131 132 133 134 135 136
	DMA_Init(DMA1_Channel5, &DMA_InitStructure);

	/* Enable SPI2 DMA Tx request */
	SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

	DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
	DMA_Cmd(DMA1_Channel5, ENABLE);
B
bernard.xiong 已提交
137 138
}

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
#if CODEC_MASTER_MODE
static void DMA_ZeroFill_I2S()
{
    DMA_InitTypeDef DMA_InitStructure;

	/* DMA1 Channel2 configuration ----------------------------------------------*/
	DMA_Cmd(DMA1_Channel5, DISABLE);
	DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, DISABLE);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI2->DR));
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &zero;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	DMA_InitStructure.DMA_BufferSize = 1;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel5, &DMA_InitStructure);

	/* Enable SPI2 DMA Tx request */
	SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

	//DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
	DMA_Cmd(DMA1_Channel5, ENABLE);
}
#endif

B
bernard.xiong 已提交
168 169
static void I2S_Configuration(void)
{
170 171 172 173 174 175 176
	I2S_InitTypeDef I2S_InitStructure;

	/* I2S peripheral configuration */
	I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
	I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
	I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
	I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k;
177
	I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
178 179

	/* I2S2 configuration */
180 181 182 183 184
#if CODEC_MASTER_MODE
	I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveTx;
#else
	I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
#endif
185
	I2S_Init(SPI2, &I2S_InitStructure);
B
bernard.xiong 已提交
186 187
}

188
uint8_t SPI_WriteByte(unsigned char data)
B
bernard.xiong 已提交
189
{
190 191 192 193 194 195 196 197 198 199 200 201 202
	//Wait until the transmit buffer is empty
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
	// Send the byte
	SPI_I2S_SendData(SPI1, data);

	//Wait until a data is received
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
	// Get the received data
	data = SPI_I2S_ReceiveData(SPI1);

	// Return the shifted data
	return data;
}
wuyangyong's avatar
wuyangyong 已提交
203

204 205 206 207 208 209 210
static void codec_send(rt_uint16_t s_data)
{
	codec_reset_csb();
	SPI_WriteByte((s_data >> 8) & 0xFF);
	SPI_WriteByte(s_data & 0xFF);
	codec_set_csb();
}
wuyangyong's avatar
wuyangyong 已提交
211

212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
static rt_err_t codec_init(rt_device_t dev)
{
	codec_send(REG_SOFTWARE_RESET);

	// 1.5x boost power up sequence.
	// Mute all outputs.
	codec_send(REG_LOUT1_VOL | LOUT1MUTE);
	codec_send(REG_ROUT1_VOL | ROUT1MUTE);
	codec_send(REG_LOUT2_VOL | LOUT2MUTE);
	codec_send(REG_ROUT2_VOL | ROUT2MUTE);
	// Enable unused output chosen from L/ROUT2, OUT3 or OUT4.
	codec_send(REG_POWER_MANAGEMENT3 | OUT4EN);
	// Set BUFDCOPEN=1 and BUFIOEN=1 in register R1
	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN);
	// Set SPKBOOST=1 in register R49.
	codec_send(REG_OUTPUT | SPKBOOST);
	// Set VMIDSEL[1:0] to required value in register R1.
	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K);
	// Set L/RMIXEN=1 and DACENL/R=1 in register R3.
	codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR);
	// Set BIASEN=1 in register R1.
	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN);
	// Set L/ROUT2EN=1 in register R3.
	codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR | LOUT2EN | ROUT2EN);
	// Enable other mixers as required.
	// Enable other outputs as required.
	codec_send(REG_POWER_MANAGEMENT2 | LOUT1EN | ROUT1EN | BOOSTENL | BOOSTENR | INPPGAENL | INPPGAENR);

	// Digital inferface setup.
	codec_send(REG_AUDIO_INTERFACE | BCP_NORMAL | LRP_NORMAL | WL_16BITS | FMT_I2S);

	// PLL setup.
	// fs = 44.1KHz / 256fs = 11.2896MHz
	// F_PLL = 11.2896MHz * 4 * 2 = 90.3168MHz
	// R = 90.3168MHz / 12.288MHz = 7.35
	// PLL_N = 7
248
	// PLL_K = 5872026 (5921370 for STM32's 44.117KHz fs generated from 72MHz clock)
249 250
	codec_send(REG_PLL_N | 7);
	codec_send(REG_PLL_K1 | 0x16);
251 252
	codec_send(REG_PLL_K2 | 0x12D);
	codec_send(REG_PLL_K3 | 0x5A);
253
	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN | PLLEN);
254
	codec_send(r06);
255 256 257 258 259 260 261 262

	// Enable DAC 128x oversampling.
	codec_send(REG_DAC | DACOSR128);

	// Set LOUT2/ROUT2 in BTL operation.
	codec_send(REG_BEEP | INVROUT2);

	// Set output volume to -22dB.
263
	vol(20);
264 265 266 267 268 269

	return RT_EOK;
}

// Exported functions
#include <finsh.h>
wuyangyong's avatar
wuyangyong 已提交
270

271 272 273 274 275 276 277
void vol(uint16_t v)
{
	v = (v & VOL_MASK) << VOL_POS;
	codec_send(REG_LOUT1_VOL | v);
	codec_send(REG_ROUT1_VOL | HPVU | v);
	codec_send(REG_LOUT2_VOL | v);
	codec_send(REG_ROUT2_VOL | SPKVU | v);
B
bernard.xiong 已提交
278 279
}

280
void eq1(uint8_t freq, uint8_t gain, uint8_t mode)
B
bernard.xiong 已提交
281
{
282
	codec_send(REG_EQ1 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (mode ? EQ3DMODE_DAC : EQ3DMODE_ADC));
B
bernard.xiong 已提交
283 284
}

285
void eq2(uint8_t freq, uint8_t gain, uint8_t bw)
B
bernard.xiong 已提交
286
{
287 288
	codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ2BW_WIDE : EQ2BW_NARROW));
}
wuyangyong's avatar
wuyangyong 已提交
289

290 291 292
void eq3(uint8_t freq, uint8_t gain, uint8_t bw)
{
	codec_send(REG_EQ3 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ3BW_WIDE : EQ3BW_NARROW));
B
bernard.xiong 已提交
293 294
}

295
void eq4(uint8_t freq, uint8_t gain, uint8_t bw)
B
bernard.xiong 已提交
296
{
297
	codec_send(REG_EQ4 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ4BW_WIDE : EQ4BW_NARROW));
B
bernard.xiong 已提交
298 299
}

300
void eq5(uint8_t freq, uint8_t gain)
B
bernard.xiong 已提交
301
{
302 303
	codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS));
}
B
bernard.xiong 已提交
304

305 306 307
void eq3d(uint8_t depth)
{
	codec_send(REG_3D | ((depth & DEPTH3D_MASK) << DEPTH3D_POS));
B
bernard.xiong 已提交
308 309
}

310
void sample_rate(uint8_t sr)
B
bernard.xiong 已提交
311
{
312 313 314
	if (sr == 44)
	{
		codec_send(REG_ADDITIONAL | SR_48KHZ);
315 316
		r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS);
		codec_send(r06);
317 318 319 320 321 322 323
	}
	else
	{
		switch (sr)
		{
		case 8:
			codec_send(REG_ADDITIONAL | SR_8KHZ);
324
			r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV6 | BCLK_DIV8 | (r06 & MS);
325 326 327 328
			break;

		case 12:
			codec_send(REG_ADDITIONAL | SR_12KHZ);
329
			r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS);
330 331 332 333
			break;

		case 16:
			codec_send(REG_ADDITIONAL | SR_16KHZ);
334
			r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV3 | BCLK_DIV8 | (r06 & MS);
335 336 337 338
			break;

		case 24:
			codec_send(REG_ADDITIONAL | SR_24KHZ);
339
			r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS);
340 341 342 343
			break;

		case 32:
			codec_send(REG_ADDITIONAL | SR_32KHZ);
344
			r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1_5 | BCLK_DIV8 | (r06 & MS);
345 346 347 348
			break;

		case 48:
			codec_send(REG_ADDITIONAL | SR_48KHZ);
349
			r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1 | BCLK_DIV8 | (r06 & MS);
350 351 352 353 354
			break;

		default:
			return;
		}
355
		codec_send(r06);
356 357 358 359 360 361 362 363 364 365 366
	}
}

FINSH_FUNCTION_EXPORT(vol, Set volume);
FINSH_FUNCTION_EXPORT(eq1, Set EQ1(Cut-off, Gain, Mode));
FINSH_FUNCTION_EXPORT(eq2, Set EQ2(Center, Gain, Bandwidth));
FINSH_FUNCTION_EXPORT(eq3, Set EQ3(Center, Gain, Bandwidth));
FINSH_FUNCTION_EXPORT(eq4, Set EQ4(Center, Gain, Bandwidth));
FINSH_FUNCTION_EXPORT(eq5, Set EQ5(Cut-off, Gain));
FINSH_FUNCTION_EXPORT(eq3d, Set 3D(Depth));
FINSH_FUNCTION_EXPORT(sample_rate, Set sample rate);
B
bernard.xiong 已提交
367

368 369 370 371
static rt_err_t codec_open(rt_device_t dev, rt_uint16_t oflag)
{
	/* enable I2S */
	I2S_Cmd(SPI2, ENABLE);
B
bernard.xiong 已提交
372

373 374 375 376 377 378 379
#if CODEC_MASTER_MODE
	DMA_ZeroFill_I2S();

	r06 |= MS;
	codec_send(r06);
#endif

380
	return RT_EOK;
B
bernard.xiong 已提交
381 382
}

383
static rt_err_t codec_close(rt_device_t dev)
B
bernard.xiong 已提交
384
{
385 386 387 388 389 390
	/* interrupt mode */
	if (dev->flag & RT_DEVICE_FLAG_INT_TX)
	{
		/* Disable the I2S2 */
		I2S_Cmd(SPI2, DISABLE);
	}
391 392 393 394 395 396 397 398 399 400
#if CODEC_MASTER_MODE
	else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
	{
		DMA_Cmd(DMA1_Channel5, DISABLE);
		I2S_Cmd(SPI2, DISABLE);

		r06 &= ~MS;
		codec_send(r06);
	}
#endif
401 402 403 404

	/* remove all data node */

	return RT_EOK;
B
bernard.xiong 已提交
405 406
}

407
static rt_err_t codec_control(rt_device_t dev, rt_uint8_t cmd, void *args)
B
bernard.xiong 已提交
408
{
409 410
	/* rate control */
	return RT_EOK;
B
bernard.xiong 已提交
411 412
}

413 414
static rt_size_t codec_write(rt_device_t dev, rt_off_t pos,
		const void* buffer, rt_size_t size)
B
bernard.xiong 已提交
415
{
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
	struct codec_device* device;
	struct codec_data_node* node;
	rt_uint32_t level;
	rt_uint16_t next_index;

	device = (struct codec_device*) dev;
	RT_ASSERT(device != RT_NULL);

	next_index = device->put_index + 1;
	if (next_index >= DATA_NODE_MAX)
		next_index = 0;

	/* check data_list full */
	if (next_index == device->read_index)
	{
		rt_set_errno(-RT_EFULL);
		return 0;
	}

	level = rt_hw_interrupt_disable();
	node = &device->data_list[device->put_index];
	device->put_index = next_index;

	// rt_kprintf("+\n");
	/* set node attribute */
	node->data_ptr = (rt_uint16_t*) buffer;
	node->data_size = size >> 1; /* size is byte unit, convert to half word unit */

	next_index = device->read_index + 1;
	if (next_index >= DATA_NODE_MAX)
		next_index = 0;

	/* check data list whether is empty */
	if (next_index == device->put_index)
	{
		if (dev->flag & RT_DEVICE_FLAG_INT_TX)
		{
			device->offset = 0;
			/* enable I2S interrupt */
			SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
		}
		else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
		{
			DMA_Configuration((rt_uint32_t) node->data_ptr, node->data_size);
		}
	}
	rt_hw_interrupt_enable(level);

	return size;
B
bernard.xiong 已提交
465 466
}

467
rt_err_t codec_hw_init(void)
B
bernard.xiong 已提交
468
{
469 470 471 472 473 474 475 476 477 478 479
	rt_device_t dev;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

	NVIC_Configuration();
	GPIO_Configuration();
	I2S_Configuration();

	dev = (rt_device_t) &codec;
480
	dev->type = RT_Device_Class_Sound;
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
	dev->rx_indicate = RT_NULL;
	dev->tx_complete = RT_NULL;
	dev->init = codec_init;
	dev->open = codec_open;
	dev->close = codec_close;
	dev->read = RT_NULL;
	dev->write = codec_write;
	dev->control = codec_control;
	dev->private = RT_NULL;

	/* set read_index and put index to 0 */
	codec.read_index = 0;
	codec.put_index = 0;

	/* unselect */
	codec_set_csb();

	/* register the device */
	return rt_device_register(&codec.parent, "snd", RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX);
B
bernard.xiong 已提交
500 501
}

502
void codec_isr()
B
bernard.xiong 已提交
503
{
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
	struct codec_data_node* node;
	node = &codec.data_list[codec.read_index]; /* get current data node */

	if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_TXE) == SET)
	{
		SPI_I2S_SendData(SPI2, node->data_ptr[codec.offset++]);
	}

	if (codec.offset == node->data_size)
	{
		/* move to next node */
		rt_uint16_t next_index;

		next_index = codec.read_index + 1;
		if (next_index >= DATA_NODE_MAX)
			next_index = 0;

		/* notify transmitted complete. */
		if (codec.parent.tx_complete != RT_NULL)
		{
			codec.parent.tx_complete(&codec.parent,
					codec.data_list[codec.read_index].data_ptr);
			rt_kprintf("-\n");
		}

		codec.offset = 0;
		codec.read_index = next_index;
		if (next_index == codec.put_index)
		{
			/* no data on the list, disable I2S interrupt */
			SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);

			rt_kprintf("*\n");
		}
	}
B
bernard.xiong 已提交
539 540
}

541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
void codec_dma_isr()
{
	/* switch to next buffer */
	rt_uint16_t next_index;
	void* data_ptr;

	next_index = codec.read_index + 1;
	if (next_index >= DATA_NODE_MAX)
		next_index = 0;

	/* save current data pointer */
	data_ptr = codec.data_list[codec.read_index].data_ptr;

	codec.read_index = next_index;
	if (next_index != codec.put_index)
	{
		/* enable next dma request */
		DMA_Configuration((rt_uint32_t) codec.data_list[codec.read_index].data_ptr, codec.data_list[codec.read_index].data_size);
	}
	else
	{
562 563 564 565
#if CODEC_MASTER_MODE
		DMA_ZeroFill_I2S();
#endif

566 567 568 569 570 571 572 573 574 575
		rt_kprintf("*\n");
	}

	/* notify transmitted complete. */
	if (codec.parent.tx_complete != RT_NULL)
	{
		codec.parent.tx_complete(&codec.parent, data_ptr);
		// rt_kprintf("-\n");
	}
}