5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
25 #define VS_WRITE_COMMAND 0x02
26 #define VS_READ_COMMAND 0x03
29 #define SPI_STATUS 0x01
31 #define SPI_CLOCKF 0x03
32 #define SPI_DECODE_TIME 0x04
33 #define SPI_AUDATA 0x05
35 #define SPI_WRAMADDR 0x07
36 #define SPI_HDAT0 0x08
37 #define SPI_HDAT1 0x09
38 #define SPI_AIADDR 0x0a
40 #define SPI_AICTRL0 0x0c
41 #define SPI_AICTRL1 0x0d
42 #define SPI_AICTRL2 0x0e
43 #define SPI_AICTRL3 0x0f
46 #define SM_LAYER12 0x02
48 #define SM_CANCEL 0x08
49 #define SM_EARSPEAKER_LO 0x10
51 #define SM_STREAM 0x40
52 #define SM_EARSPEAKER_HI 0x80
54 #define SM_SDIORD 0x200
55 #define SM_SDISHARE 0x400
56 #define SM_SDINEW 0x800
57 #define SM_ADPCM 0x1000
58 #define SM_LINE1 0x4000
59 #define SM_CLK_RANGE 0x8000
64 #define SPI_SPEED_16 3
65 #define SPI_SPEED_32 4
66 #define SPI_SPEED_64 5
67 #define SPI_SPEED_128 6
68 #define SPI_SPEED_256 7
70 #define MP3_BUFFER_SIZE 32
72 #define CS_HIGH() do { AUDIO_CS_GPIO->BSRRL = AUDIO_CS_GPIO_PIN; } while (0)
73 #define CS_LOW() do { AUDIO_CS_GPIO->BSRRH = AUDIO_CS_GPIO_PIN; } while (0)
74 #define XDCS_HIGH() do { AUDIO_XDCS_GPIO->BSRRL = AUDIO_XDCS_GPIO_PIN; } while (0)
75 #define XDCS_LOW() do { AUDIO_XDCS_GPIO->BSRRH = AUDIO_XDCS_GPIO_PIN; } while (0)
76 #define RST_HIGH() do { AUDIO_RST_GPIO->BSRRL = AUDIO_RST_GPIO_PIN; } while (0)
77 #define RST_LOW() do { AUDIO_RST_GPIO->BSRRH = AUDIO_RST_GPIO_PIN; } while (0)
79 #define READ_DREQ() (GPIO_ReadInputDataBit(AUDIO_DREQ_GPIO, AUDIO_DREQ_GPIO_PIN))
81 void audioSpiInit(void)
83 GPIO_InitTypeDef GPIO_InitStructure
;
84 SPI_InitTypeDef SPI_InitStructure
;
86 GPIO_InitStructure
.GPIO_Pin
= AUDIO_SPI_MISO_GPIO_PIN
;
87 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
88 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_AF
;
89 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
90 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_NOPULL
;
91 GPIO_Init(AUDIO_SPI_MISO_GPIO
, &GPIO_InitStructure
);
93 GPIO_InitStructure
.GPIO_Pin
= AUDIO_SPI_SCK_GPIO_PIN
;
94 GPIO_Init(AUDIO_SPI_SCK_GPIO
, &GPIO_InitStructure
);
96 GPIO_InitStructure
.GPIO_Pin
= AUDIO_SPI_MOSI_GPIO_PIN
;
97 GPIO_Init(AUDIO_SPI_MOSI_GPIO
, &GPIO_InitStructure
);
99 GPIO_InitStructure
.GPIO_Pin
= AUDIO_CS_GPIO_PIN
;
100 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_OUT
;
101 GPIO_Init(AUDIO_CS_GPIO
, &GPIO_InitStructure
);
103 GPIO_InitStructure
.GPIO_Pin
= AUDIO_XDCS_GPIO_PIN
;
104 GPIO_Init(AUDIO_XDCS_GPIO
, &GPIO_InitStructure
);
106 GPIO_InitStructure
.GPIO_Pin
= AUDIO_RST_GPIO_PIN
;
107 GPIO_Init(AUDIO_RST_GPIO
, &GPIO_InitStructure
);
109 GPIO_InitStructure
.GPIO_Pin
= AUDIO_DREQ_GPIO_PIN
;
110 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_IN
;
111 GPIO_Init(AUDIO_DREQ_GPIO
, &GPIO_InitStructure
);
113 GPIO_PinAFConfig(AUDIO_SPI_SCK_GPIO
, AUDIO_SPI_SCK_GPIO_PinSource
, AUDIO_SPI_GPIO_AF
);
114 GPIO_PinAFConfig(AUDIO_SPI_MISO_GPIO
, AUDIO_SPI_MISO_GPIO_PinSource
, AUDIO_SPI_GPIO_AF
);
115 GPIO_PinAFConfig(AUDIO_SPI_MOSI_GPIO
, AUDIO_SPI_MOSI_GPIO_PinSource
, AUDIO_SPI_GPIO_AF
);
117 RCC_ClocksTypeDef RCC_Clocks
;
118 RCC_GetClocksFreq(&RCC_Clocks
);
120 SPI_I2S_DeInit(AUDIO_SPI
);
121 SPI_InitStructure
.SPI_Direction
= SPI_Direction_2Lines_FullDuplex
;
122 SPI_InitStructure
.SPI_Mode
= SPI_Mode_Master
;
123 SPI_InitStructure
.SPI_DataSize
= SPI_DataSize_8b
;
124 SPI_InitStructure
.SPI_CPOL
= SPI_CPOL_Low
;
125 SPI_InitStructure
.SPI_CPHA
= SPI_CPHA_1Edge
;
126 SPI_InitStructure
.SPI_NSS
= SPI_NSS_Soft
;
127 SPI_InitStructure
.SPI_BaudRatePrescaler
= SPI_BaudRatePrescaler_2
;
128 SPI_InitStructure
.SPI_FirstBit
= SPI_FirstBit_MSB
;
129 SPI_InitStructure
.SPI_CRCPolynomial
= 7;
130 SPI_Init(AUDIO_SPI
, &SPI_InitStructure
);
131 SPI_Cmd(AUDIO_SPI
, ENABLE
);
133 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_RXNE
);
134 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_TXE
);
137 void audioSpiSetSpeed(uint8_t speed
)
139 AUDIO_SPI
->CR1
&= 0xFFC7; // Fsck=Fcpu/256
142 AUDIO_SPI
->CR1
|= 0x00 << 3; // Fsck=Fpclk/2=36Mhz
145 AUDIO_SPI
->CR1
|= 0x01 << 3; // Fsck=Fpclk/4=18Mhz
148 AUDIO_SPI
->CR1
|= 0x02 << 3; // Fsck=Fpclk/8=9Mhz
151 AUDIO_SPI
->CR1
|= 0x03 << 3; // Fsck=Fpclk/16=4.5Mhz
154 AUDIO_SPI
->CR1
|= 0x04 << 3; // Fsck=Fpclk/32=2.25Mhz
157 AUDIO_SPI
->CR1
|= 0x05 << 3; // Fsck=Fpclk/16=1.125Mhz
160 AUDIO_SPI
->CR1
|= 0x06 << 3; // Fsck=Fpclk/16=562.5Khz
163 AUDIO_SPI
->CR1
|= 0x07 << 3; // Fsck=Fpclk/16=281.25Khz
166 AUDIO_SPI
->CR1
|= 0x01 << 6;
169 uint8_t audioSpiReadWriteByte(uint8_t value
)
171 uint16_t time_out
= 0x0FFF;
172 while (SPI_I2S_GetFlagStatus(AUDIO_SPI
, SPI_I2S_FLAG_TXE
) == RESET
) {
173 if (--time_out
== 0) {
175 SPI_Cmd(AUDIO_SPI
, DISABLE
);
176 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_OVR
);
177 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_BSY
);
178 SPI_I2S_ClearFlag(AUDIO_SPI
, I2S_FLAG_UDR
);
179 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_TIFRFE
);
180 SPI_Cmd(AUDIO_SPI
, ENABLE
);
184 SPI_I2S_SendData(AUDIO_SPI
, value
);
187 while (SPI_I2S_GetFlagStatus(AUDIO_SPI
, SPI_I2S_FLAG_RXNE
) == RESET
) {
188 if (--time_out
== 0) {
190 SPI_Cmd(AUDIO_SPI
, DISABLE
);
191 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_OVR
);
192 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_BSY
);
193 SPI_I2S_ClearFlag(AUDIO_SPI
, I2S_FLAG_UDR
);
194 SPI_I2S_ClearFlag(AUDIO_SPI
, SPI_I2S_FLAG_TIFRFE
);
195 SPI_Cmd(AUDIO_SPI
, ENABLE
);
199 return SPI_I2S_ReceiveData(AUDIO_SPI
);
202 uint8_t audioWaitDreq(int32_t delay_us
)
204 while (READ_DREQ() == 0) {
205 if (delay_us
-- == 0) return 0;
211 uint16_t audioSpiReadReg(uint8_t address
)
213 if (!audioWaitDreq(100))
216 audioSpiSetSpeed(SPI_SPEED_64
);
219 audioSpiReadWriteByte(VS_READ_COMMAND
);
220 audioSpiReadWriteByte(address
);
221 uint16_t result
= audioSpiReadWriteByte(0xff) << 8;
222 result
+= audioSpiReadWriteByte(0xff);
223 delay_01us(100); // 10us
225 audioSpiSetSpeed(SPI_SPEED_8
);
229 uint16_t audioSpiReadCmd(uint8_t address
)
231 if (!audioWaitDreq(100))
234 audioSpiSetSpeed(SPI_SPEED_64
);
237 audioSpiReadWriteByte(VS_READ_COMMAND
);
238 audioSpiReadWriteByte(address
);
239 uint16_t result
= audioSpiReadWriteByte(0) << 8;
240 result
|= audioSpiReadWriteByte(0);
241 delay_01us(50); // 5us
243 audioSpiSetSpeed(SPI_SPEED_8
);
247 uint8_t audioSpiWriteCmd(uint8_t address
, uint16_t data
)
249 if (!audioWaitDreq(100))
252 audioSpiSetSpeed(SPI_SPEED_64
);
255 audioSpiReadWriteByte(VS_WRITE_COMMAND
);
256 audioSpiReadWriteByte(address
);
257 audioSpiReadWriteByte(data
>> 8);
258 audioSpiReadWriteByte(data
);
259 delay_01us(50); // 5us
261 audioSpiSetSpeed(SPI_SPEED_8
);
265 void audioResetDecodeTime(void)
267 audioSpiWriteCmd(SPI_DECODE_TIME
, 0x0000);
268 audioSpiWriteCmd(SPI_DECODE_TIME
, 0x0000);
271 uint8_t audioHardReset(void)
276 delay_ms(100); // 100ms
279 if (!audioWaitDreq(100))
282 delay_ms(20); // 20ms
286 uint8_t audioSoftReset(void)
288 audioSpiSetSpeed(SPI_SPEED_64
);
289 if (!audioWaitDreq(100))
292 audioSpiReadWriteByte(0x00); // start the transfer
294 audioSpiWriteCmd(SPI_MODE
, 0x0816); // SOFT RESET, new model
295 if (!audioWaitDreq(100))
298 // wait for set up successful
300 while (audioSpiReadReg(SPI_CLOCKF
) != 0x9800 && retry
< 100) {
302 audioSpiWriteCmd(SPI_CLOCKF
, 0x9800);
305 audioResetDecodeTime(); // reset the decoding time
306 audioSpiSetSpeed(SPI_SPEED_8
);
308 audioSpiReadWriteByte(0X0);
309 audioSpiReadWriteByte(0X0);
310 audioSpiReadWriteByte(0X0);
311 audioSpiReadWriteByte(0X0);
312 delay_01us(100); // 10us
317 uint32_t audioSpiWriteData(const uint8_t * buffer
, uint32_t size
)
322 while (index
< size
&& READ_DREQ() != 0) {
323 for (int i
=0; i
<MP3_BUFFER_SIZE
&& index
<size
; i
++) {
324 audioSpiReadWriteByte(buffer
[index
++]);
330 void audioSpiWriteBuffer(const uint8_t * buffer
, uint32_t size
)
332 const uint8_t * p
= buffer
;
334 uint32_t written
= audioSpiWriteData(p
, size
);
340 const uint8_t RiffHeader
[] = {
341 0x52, 0x49, 0x46, 0x46, 0xff, 0xff, 0xff, 0xff, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20,
342 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00,
343 0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 void audioSendRiffHeader()
349 audioSpiWriteBuffer(RiffHeader
, sizeof(RiffHeader
));
353 void audioShutdownInit()
355 GPIO_InitTypeDef GPIO_InitStructure
;
356 GPIO_InitStructure
.GPIO_Pin
= AUDIO_SHUTDOWN_GPIO_PIN
;
357 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_OUT
;
358 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
359 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
360 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_UP
;
361 GPIO_Init(AUDIO_SHUTDOWN_GPIO
, &GPIO_InitStructure
);
362 GPIO_SetBits(AUDIO_SHUTDOWN_GPIO
, AUDIO_SHUTDOWN_GPIO_PIN
); // we never RESET it, there is a 2s delay on STARTUP
370 // TODO X10 code missing
376 audioSpiSetSpeed(SPI_SPEED_8
);
378 audioSendRiffHeader();
381 uint8_t * currentBuffer
= nullptr;
382 uint32_t currentSize
= 0;
383 int16_t newVolume
= -1;
385 void audioSetCurrentBuffer(const AudioBuffer
* buffer
)
388 currentBuffer
= (uint8_t *)buffer
->data
;
389 currentSize
= buffer
->size
* 2;
392 currentBuffer
= nullptr;
397 void audioConsumeCurrentBuffer()
399 if (newVolume
>= 0) {
400 uint8_t value
= newVolume
;
401 audioSpiWriteCmd(SPI_VOL
, (value
<< 8) + value
);
402 // audioSendRiffHeader();
406 if (!currentBuffer
) {
407 audioSetCurrentBuffer(audioQueue
.buffersFifo
.getNextFilledBuffer());
411 uint32_t written
= audioSpiWriteData(currentBuffer
, currentSize
);
412 currentBuffer
+= written
;
413 currentSize
-= written
;
414 if (currentSize
== 0) {
415 audioQueue
.buffersFifo
.freeNextFilledBuffer();
416 currentBuffer
= nullptr;
422 // adjust this value for a volume level just above the silence
423 // values is attenuation in dB, higher value - less volume
425 #define VOLUME_MIN_DB 40
427 void setScaledVolume(uint8_t volume
)
429 if (volume
> VOLUME_LEVEL_MAX
) {
430 volume
= VOLUME_LEVEL_MAX
;
432 // maximum volume is 0x00 and total silence is 0xFE
434 setVolume(0xFE); // silence
437 uint32_t vol
= (VOLUME_MIN_DB
* 2) - ((uint32_t)volume
* (VOLUME_MIN_DB
* 2)) / VOLUME_LEVEL_MAX
;
442 void setVolume(uint8_t volume
)