summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/pcm_playback.h2
-rw-r--r--firmware/pcm_playback.c133
2 files changed, 80 insertions, 55 deletions
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index 6010293bbd..f6612095e0 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -19,10 +19,12 @@
19#ifndef PCM_PLAYBACK_H 19#ifndef PCM_PLAYBACK_H
20#define PCM_PLAYBACK_H 20#define PCM_PLAYBACK_H
21 21
22void pcm_init(void);
22void pcm_set_frequency(unsigned int frequency); 23void pcm_set_frequency(unsigned int frequency);
23void pcm_play_data(const unsigned char* start, int size, 24void pcm_play_data(const unsigned char* start, int size,
24 void (*get_more)(unsigned char** start, long* size)); 25 void (*get_more)(unsigned char** start, long* size));
25void pcm_play_stop(void); 26void pcm_play_stop(void);
27void pcm_play_pause(bool play);
26bool pcm_is_playing(void); 28bool pcm_is_playing(void);
27void pcm_set_volume(int volume); 29void pcm_set_volume(int volume);
28 30
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index bc2218be69..e1afea949d 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -42,57 +42,37 @@
42#include <string.h> 42#include <string.h>
43 43
44static bool pcm_playing; 44static bool pcm_playing;
45static int pcm_freq = 0x6; // 44.1 in default 45static bool pcm_paused;
46static int pcm_freq = 0x6; /* 44.1 is default */
46 47
47/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ 48/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
48static void dma_start(const void *addr_r, long size) 49static void dma_start(const void *addr, long size)
49{ 50{
50 pcm_playing = 1; 51 pcm_playing = true;
51 int i;
52
53 int align;
54 align = 4;
55
56 void* addr = (void*)((((unsigned int)addr_r) >> 2) << 2); // always align data, never pass unaligned data
57 size = (size >> 2) << 2; // size shoudl also be always multiple of 4
58 52
59 BUSMASTER_CTRL = 0x81; /* PARK[1,0]=10 + BCR24BIT */ 53 addr = (void *)((unsigned long)addr & ~3); /* Align data */
54 size &= ~3; /* Size must be multiple of 4 */
60 55
56 /* Reset the audio FIFO */
57 IIS2CONFIG = 0x800;
58
61 /* Set up DMA transfer */ 59 /* Set up DMA transfer */
62 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ 60 SAR0 = ((unsigned long)addr); /* Source address */
63 SAR0 = ((unsigned long)addr) + align*4; /* Source address */ 61 DAR0 = (unsigned long)&PDOR3; /* Destination address */
64 DAR0 = (unsigned long)&PDOR3; /* Destination address */ 62 BCR0 = size; /* Bytes to transfer */
65 BCR0 = size-(align*4); /* Bytes to transfer */
66 DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1;
67 DMACONFIG = 1; /* Enable DMA0Req => set DMAROUTE |= DMA0_REQ_AUDIO_1 */
68
69 /* Start transfer when requested */
70 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_SINC;
71
72 /* Enable interrupt at level 7, priority 0 */
73 ICR4 = (ICR4 & 0xffff00ff) | 0x00001c00;
74 IMR &= ~(1<<14); /* bit 14 is DMA0 */
75 63
76 IIS2CONFIG = (pcm_freq << 12) | 0x300; /* CLOCKSEL for right frequency + data source = PDOR3 */ 64 /* Enable the FIFO and force one write to it */
77 65 IIS2CONFIG = (pcm_freq << 12) | 0x300;
78 for(i = 0; i < align; i++) 66 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_SINC | DMA_START;
79 PDOR3 = ((unsigned int*)(addr))[i]; /* These are needed to generate FIFO empty request to DMA.. */
80} 67}
81 68
82/* Stops the DMA transfer and interrupt */ 69/* Stops the DMA transfer and interrupt */
83static void dma_stop(void) 70static void dma_stop(void)
84{ 71{
85 pcm_playing = 0; 72 pcm_playing = false;
86 DCR0 = 0;
87
88/* DMAROUTE &= 0xffffff00;
89 DMACONFIG = 0;*/
90 73
74 /* Reset the FIFO */
91 IIS2CONFIG = 0x800; 75 IIS2CONFIG = 0x800;
92
93 /* Disable DMA0 interrupt */
94 IMR |= (1<<14);
95 ICR4 &= 0xffff00ff;
96} 76}
97 77
98 78
@@ -113,8 +93,8 @@ void pcm_set_volume(int volume)
113/* sets frequency of input to DAC */ 93/* sets frequency of input to DAC */
114void pcm_set_frequency(unsigned int frequency) 94void pcm_set_frequency(unsigned int frequency)
115{ 95{
116 switch(frequency) 96 switch(frequency)
117 { 97 {
118 case 11025: 98 case 11025:
119 pcm_freq = 0x2; 99 pcm_freq = 0x2;
120 break; 100 break;
@@ -126,7 +106,8 @@ void pcm_set_frequency(unsigned int frequency)
126 break; 106 break;
127 default: 107 default:
128 pcm_freq = 0x6; 108 pcm_freq = 0x6;
129 } 109 break;
110 }
130} 111}
131 112
132/* the registered callback function to ask for more mp3 data */ 113/* the registered callback function to ask for more mp3 data */
@@ -145,6 +126,23 @@ void pcm_play_stop(void)
145 dma_stop(); 126 dma_stop();
146} 127}
147 128
129void pcm_play_pause(bool play)
130{
131 if(pcm_paused && play)
132 {
133 /* Enable the FIFO and force one write to it */
134 IIS2CONFIG = (pcm_freq << 12) | 0x300;
135 DCR0 |= DMA_START;
136
137 pcm_paused = false;
138 }
139 else if(!pcm_paused && !play)
140 {
141 IIS2CONFIG = 0x800;
142 pcm_paused = true;
143 }
144}
145
148bool pcm_is_playing(void) 146bool pcm_is_playing(void)
149{ 147{
150 return pcm_playing; 148 return pcm_playing;
@@ -161,26 +159,51 @@ void DMA0(void)
161 159
162 DSR0 = 1; /* Clear interrupt */ 160 DSR0 = 1; /* Clear interrupt */
163 161
164 if(res == 0x41) 162 /* Stop on error */
163 if(res & 0x70)
165 { 164 {
166 dma_stop(); 165 dma_stop();
167 } 166 }
168
169 if (callback_for_more)
170 {
171 callback_for_more(&start, &size);
172 }
173
174 if(size)
175 {
176 SAR0 = (unsigned long)start; /* Source address */
177 BCR0 = size; /* Bytes to transfer */
178 }
179 else 167 else
180 { 168 {
181 /* Finished playing */ 169 if (callback_for_more)
182 dma_stop(); 170 {
171 callback_for_more(&start, &size);
172 }
173
174 if(size)
175 {
176 SAR0 = (unsigned long)start; /* Source address */
177 BCR0 = size; /* Bytes to transfer */
178 }
179 else
180 {
181 /* Finished playing */
182 dma_stop();
183 }
183 } 184 }
184 185
185 IPR |= (1<<14); /* Clear pending interrupt request */ 186 IPR |= (1<<14); /* Clear pending interrupt request */
186} 187}
188
189void pcm_init(void)
190{
191 pcm_playing = false;
192 pcm_paused = false;
193
194 uda1380_init();
195
196 BUSMASTER_CTRL = 0x81; /* PARK[1,0]=10 + BCR24BIT */
197 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
198 DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1;
199 DMACONFIG = 1; /* DMA0Req = PDOR3 */
200
201 /* Reset the audio FIFO */
202 IIS2CONFIG = 0x800;
203
204 /* Enable interrupt at level 7, priority 0 */
205 ICR4 = (ICR4 & 0xffff00ff) | 0x00001c00;
206 IMR &= ~(1<<14); /* bit 14 is DMA0 */
207
208 pcm_set_frequency(44100);
209}