8f3d7a651098048abbe708bca03b39cfe574f797
[bertos.git] / boards / sam3x-ek / examples / sam3x-ek_codec / main.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \author Stefano Federico <aleph@develer.com>
34  *
35  * \brief Empty project.
36  *
37  * This is a minimalist project, it just initializes the hardware of the
38  * supported board and proposes an empty main.
39  */
40
41 #include "hw/hw_led.h"
42 #include "hw/hw_sd.h"
43 #include "cfg/cfg_i2s.h"
44
45 #include <cfg/debug.h>
46
47 #include <cpu/irq.h>
48 #include <cpu/byteorder.h>
49
50 #include <io/kfile.h>
51 #include <io/kfile_block.h>
52
53 #include <drv/i2c.h>
54 #include <drv/i2s.h>
55 #include <drv/sd.h>
56 #include <drv/eeprom.h>
57 #include <drv/timer.h>
58 #include <drv/lcd_hx8347.h>
59 #include <drv/adc.h>
60 #include <drv/wm8731.h>
61 #include <drv/dmac_sam3.h>
62
63 #include <fs/fat.h>
64
65 #include <verstag.h>
66 #include <buildrev.h>
67
68 #include <string.h>
69
70 /*
71  * Codec has 7-bit address, the eighth is the R/W bit, so we
72  * write the codec address with one bit shifted left
73  */
74 #define CODEC_ADDR 0x36
75
76 // SD fat filesystem context
77 FATFS fs;
78 FatFile log_file;
79 FatFile acq_file;
80
81 static I2c i2c;
82 static I2s i2s;
83 //static Wm8731 wm8731_ctx;
84
85 static void init(void)
86 {
87         IRQ_ENABLE;
88         kdbg_init();
89         kprintf("sam3x %s: %d times\n", VERS_HOST, VERS_BUILD);
90
91         timer_init();
92         LED_INIT();
93
94         dmac_init();
95         i2c_init(&i2c, I2C_BITBANG0, CONFIG_I2C_FREQ);
96         i2s_init(&i2s, SSC0);
97         adc_init();
98
99 //      wm8731_init(&wm8731_ctx, &i2c, CODEC_ADDR);
100 //      wm8731_setVolume(&wm8731_ctx, WM8731_HEADPHONE, (uint8_t)ADC_RANGECONV(adc_read(1), 0, 100));
101 }
102
103 typedef struct WavHdr
104 {
105         char chunk_id[4];
106         uint32_t chunk_size;
107         char format[4];
108
109         char subchunk1_id[4];
110         uint32_t subchunk1_size;
111         uint16_t audio_format;
112         uint16_t num_channels;
113         uint32_t sample_rate;
114         uint32_t byte_rate;
115         uint16_t block_align;
116         uint16_t bits_per_sample;
117
118         uint8_t subchunk2[8];
119 } WavHdr;
120
121
122 //#define FILE_NAME  "input0.wav"
123 #define FILE_NAME  "sample.wav"
124 //#define FILE_NAME  "testaa"
125 #define ACQ_FILE_NAME  "acq.wav"
126 uint8_t uno[512];
127 uint8_t tre[512];
128 int16_t due[5120];
129 size_t count = 0;
130 static void codec(struct I2s *i2s, void *_buf, size_t len)
131 {
132         count += kfile_read(&log_file.fd, _buf, len);
133         if (count >= log_file.fat_file.fsize - sizeof(WavHdr))
134         {
135                 kprintf("stop %d\n", count);
136                 i2s_dmaTxStop(i2s);
137                 count = 0;
138         }
139 }
140
141
142 static int wav_check(KFile *fd)
143 {
144
145         WavHdr header;
146
147         if (kfile_read(fd, &header, sizeof(header)) != sizeof(header))
148         {
149                 kputs("Error reading wave file header\n");
150                 return EOF;
151         }
152
153         if (strncmp(header.chunk_id, "RIFF", 4))
154         {
155                 kputs("RIFF tag not found\n");
156                 goto error;
157         }
158
159         if (strncmp(header.format, "WAVE", 4))
160         {
161                 kputs("WAVE tag not found\n");
162                 goto error;
163         }
164
165         if (le16_to_cpu(header.audio_format) != 1)
166         {
167                 kprintf("Audio format not valid, found [%d]\n", le16_to_cpu(header.audio_format));
168                 goto error;
169         }
170
171         if (le16_to_cpu(header.num_channels) != 2)
172         {
173                 kprintf("Channels number not valid, found [%d]\n", le16_to_cpu(header.num_channels));
174                 goto error;
175         }
176
177
178         if (le32_to_cpu(header.sample_rate) != 48000)
179         {
180                 kprintf("Sample rate not valid, found [%ld]\n", le32_to_cpu(header.sample_rate));
181                 goto error;
182         }
183
184         if (le16_to_cpu(header.bits_per_sample) != 16)
185         {
186                 kprintf("Bits per sample not valid, found [%d]\n", le16_to_cpu(header.bits_per_sample));
187                 goto error;
188         }
189         return 0;
190
191 error:
192         return 1;
193 }
194
195 #include <drv/eeprom.h>
196 static Eeprom eep;
197 int main(void)
198 {
199         init();
200
201         eeprom_init(&eep, &i2c, EEPROM_24XX512, 0x51, false);
202
203         for (;;)
204         {
205
206                 if (SD_CARD_PRESENT())
207                 {
208
209                         memset(uno, 0xcc, eep.blk.blk_size);
210 //                      kblock_write(&eep.blk, 0, uno, 0, eep.blk.blk_size);
211
212                         memset(tre, 0xaa, eep.blk.blk_size);
213                         kblock_read(&eep.blk, 0, uno, 0, eep.blk.blk_size);
214
215                         kprintf("blk[%d]\n", eep.blk.blk_size);
216                         if (!memcmp(uno, tre, eep.blk.blk_size))
217                         {
218                                 kputs("ok!\n");
219                                 for (size_t i = 0; i < eep.blk.blk_size; i++)
220                                         kprintf("%x ", tre[i]);
221                                 kputs("fine\n");
222                         }
223                         else
224                                 kputs("Error\n");
225                                 for (size_t i = 0; i < eep.blk.blk_size; i++)
226                                         kprintf("%x ", tre[i]);
227                                 kputs("fine\n");
228 /*
229                         uint16_t vol = ADC_RANGECONV(adc_read(1), 0, 100);
230                         if (prev != vol)
231                         {
232                                 prev = vol;
233                                 wm8731_setVolume(&wm8731_ctx, WM8731_HEADPHONE, (uint8_t)vol);
234                         }
235 */
236                         timer_delay(10);
237                         Sd sd;
238                         bool sd_ok = sd_init(&sd, NULL, 0);
239                         FRESULT result;
240
241                         memset(due, 0xbb, sizeof(due));
242                         if (sd_ok)
243                         {
244                                 kprintf("Mount FAT filesystem.\n");
245                                 result = f_mount(0, &fs);
246                                 if (result != FR_OK)
247                                 {
248                                         kprintf("Mounting FAT volumes error[%d]\n", result);
249                                         sd_ok = false;
250                                 }
251
252                                 if (sd_ok)
253                                 {
254                                         result = fatfile_open(&log_file, FILE_NAME,  FA_OPEN_EXISTING | FA_READ);
255                                         if (result == FR_OK)
256                                         {
257                                                 kprintf("Opened log file '%s' size %ld\n", FILE_NAME, log_file.fat_file.fsize);
258                                                 if (wav_check(&log_file.fd) >= 0)
259                                                 {
260                                                         //int len = kfile_read(&log_file.fd, due, 1024);
261                                                         //i2s_dmaTxBuffer(&i2s, due, len);
262
263                                                         /*
264                                                         kprintf("len %d\n", len);
265                                                         for (size_t i=0; i < sizeof(due); i++)
266                                                                 kprintf("%x ", due[i]);
267                                                         kputs("\n");
268                                                          */
269
270                                                         //count = log_file.fat_file.fsize - sizeof(WavHdr);
271                                                         //count = log_file.fat_file.fsize;
272                                                         while (count)
273                                                         {
274                                                                 int len = kfile_read(&log_file.fd, due, sizeof(due));
275                                                                 i2s_dmaTxBuffer(&i2s, due, len);
276                                                                 i2s_dmaTxWait(&i2s);
277                                                                 //for (int i = 0; i < len / 2; i++)
278                                                                         //i2s_write(&i2s, (due[i]));
279                                                                 count -= len;
280                                                         }
281
282                                                         i2s_dmaStartTxStreaming(&i2s, due, sizeof(due), 1024, codec);
283                                                 }
284
285                                                 // Flush data and close the files.
286                                                 kfile_flush(&log_file.fd);
287                                                 kfile_close(&log_file.fd);
288                                         }
289                                         else
290                                         {
291                                                 kprintf("Unable to open file: '%s' error[%d]\n", FILE_NAME, result);
292                                         }
293
294                                         //Unmount always to prevent accidental sd remove.
295                                         f_mount(0, NULL);
296                                         kprintf("Umount\n");
297
298                                 }
299                                 f_mount(0, NULL);
300                         }
301                         timer_delay(5000);
302                 }
303                 else
304                 {
305                         kputs("No card insert..\n");
306                         timer_delay(500);
307                 }
308         }
309
310         return 0;
311 }
312
313
314
315
316
317