OSDN Git Service

e404e1a237e71623e4fa82223a96c24086e6d74d
[bluetank/bluetank.git] / firm / bare_metal / uzume.c
1 /**
2  * @file uzume.c
3  * @brief BlueTank ACB-BF592 Application Sample Codes.
4  * @author Copyright(C) 2012 Shinichiro Nakamura
5  */
6
7 #include <stdint.h>
8 #include <string.h>
9 #include <cdefBF592-A.h>
10 #include <builtins.h>
11 #include <sys/exception.h>
12 #include "lcd.h"
13 #include "led.h"
14 #include "pff.h"
15 #include "ssm2603.h"
16 #include "uzume.h"
17
18 #define SCLOCK_HZ           (100000000) /**< システムクロック(100MHz) */
19 #define DMA_SAMPLE_SIZE     (256)       /**< 1回のサンプルサイズ */
20
21 typedef __attribute__((interrupt_handler)) void (*ex_handler_fn_gcc)(void);
22
23 static void setup_pll(uint8_t mul_val, uint8_t div_val);
24 static void __attribute__((interrupt_handler)) sport_rx_isr();
25
26 /**
27  * SPORT受信バッファ(ダブルバッファ)
28  */
29 static int32_t sport_buffer_rx[2][DMA_SAMPLE_SIZE];
30 /**
31  * SPORT受信バッファ(ダブルバッファ)
32  */
33 static int32_t sport_buffer_tx[2][DMA_SAMPLE_SIZE];
34 /**
35  * DMAがどのバッファ使用をしているか
36  */
37 static volatile int32_t bufidx_dma_target;
38 /**
39  * データ転送完了フラグ
40  */
41 static volatile int32_t data_ready;
42
43 static void setup_pll(uint8_t mul_val, uint8_t div_val)
44 {
45     *pSIC_IWR = IWR_ENABLE(0);  /* PLLのみIWRを許す */
46     *pPLL_DIV = div_val;
47     *pPLL_CTL = (mul_val) << 9;
48     asm("cli r0; csync; idle; sti r0;": : :"R0");
49     *pSIC_IWR = IWR_ENABLE_ALL;
50 }
51
52 static void __attribute__((interrupt_handler)) sport_rx_isr()
53 {
54     *pDMA1_IRQ_STATUS = DMA_DONE;
55     ssync();
56     /* オーディオコーデックからデータ到着 */
57     data_ready = 1;
58     /* DMAが使用するバッファを変更 */
59     bufidx_dma_target = (bufidx_dma_target ^ 1) & 1;
60 }
61
62 static void vdsp_register_handler(interrupt_kind kind, ex_handler_fn_gcc fn)
63 {
64     uint32_t mask;
65
66     if ((ik_emulation > kind) || (kind > ik_ivg15)) {
67         return;
68     }
69
70     *((ex_handler_fn_gcc*)&(((uint32_t*)EVT0)[(int32_t)kind])) = fn;
71     mask  = cli();
72     mask |= 1u << (int32_t)kind;
73     sti(mask);
74 }
75
76 void uzume_init(UZUME *p)
77 {
78     FATFS fatfs;
79 #if 0
80     DIR dir;
81     FILINFO finfo;
82 #endif
83
84     p->effect = NULL;
85     p->system = NULL;
86
87     /*
88      * PLLを設定する。
89      */
90     setup_pll(16, 4);
91
92     /*
93      * LEDを初期化する。
94      */
95     led_init();
96     led_write(LedTargetR, 1);
97     led_write(LedTargetG, 0);
98
99     /*
100      * LCDを初期化する。
101      */
102     lcd_init();
103     lcd_clear();
104     lcd_goto(0, 0);
105     lcd_puts("BlueTank");
106     lcd_goto(0, 1);
107     lcd_puts("Init....");
108
109     /*
110      * オーディオコーデックを初期化する。
111      * 初期化された時点ではミュートされている。
112      */
113     ssm2603_init();
114
115     /*
116      * SDカードをマウントする。
117      */
118     if (pf_mount(&fatfs) == FR_OK) {
119         lcd_goto(0, 0);
120         lcd_puts("MT:  OK ");
121     } else {
122         lcd_goto(0, 0);
123         lcd_puts("MT: FAIL");
124     }
125
126     /*
127      * バッファをクリアする。
128      */
129     memset(sport_buffer_rx, 0 , sizeof(sport_buffer_rx));
130     memset(sport_buffer_tx, 0 , sizeof(sport_buffer_tx));
131     bufidx_dma_target = 0;
132     data_ready = 0;
133
134     /*
135      * 割り込みハンドラの登録。
136      * IVG9が登録先。
137      */
138     vdsp_register_handler(ik_ivg9, sport_rx_isr);
139     *pSIC_IMASK |= IRQ_DMA1;
140
141     /*
142      * SPORT RXの設定
143      * 外部クロック、外部SYNC、MSB First
144      * 24ビットデータ、 ステレオ
145      */
146     *pSPORT0_RCR1 = RFSR | RCKFE;
147     *pSPORT0_RCR2 = SLEN(31) | RSFSE;
148
149     /*
150      * SPORT TXの設定
151      * 外部クロック、外部SYNC、MSB First
152      * 24ビットデータ、 ステレオ
153      */
154     *pSPORT0_TCR1 = TFSR | TCKFE;
155     *pSPORT0_TCR2 = SLEN(31) | TSFSE;
156
157     /*
158      * DMA1(SPORT0 RX)の設定
159      */
160     *pDMA1_PERIPHERAL_MAP = 0x1000;
161     *pDMA1_CONFIG = FLOW_AUTO | DI_EN | DI_SEL | DMA2D | WDSIZE_32 | WNR;
162     *pDMA1_START_ADDR = sport_buffer_rx;
163     *pDMA1_X_COUNT = DMA_SAMPLE_SIZE;
164     *pDMA1_X_MODIFY = sizeof(int32_t);
165     *pDMA1_Y_COUNT = 2;
166     *pDMA1_Y_MODIFY = sizeof(int32_t);
167
168     /*
169      * DMA2(SPORT0 TX)の設定
170      */
171     *pDMA2_PERIPHERAL_MAP = 0x2000;
172     *pDMA2_CONFIG = FLOW_AUTO | DMA2D | WDSIZE_32;
173     *pDMA2_START_ADDR = sport_buffer_tx;
174     *pDMA2_X_COUNT = DMA_SAMPLE_SIZE;
175     *pDMA2_X_MODIFY = sizeof(int32_t);
176     *pDMA2_Y_COUNT = 2;
177     *pDMA2_Y_MODIFY = sizeof(int32_t);
178     ssync();
179
180     /*
181      * DMAを有効
182      */
183     *pDMA1_IRQ_STATUS = DMA_DONE;
184     *pDMA1_CONFIG |= DMAEN;
185     *pDMA2_CONFIG |= DMAEN;
186     ssync();
187
188     /*
189      * SPORT0を有効
190      */
191     *pSPORT0_TCR1 |= TSPEN;
192     *pSPORT0_RCR1 |= RSPEN;
193     ssync();
194
195     /*
196      * 初期化の完了をユーザに通知する。
197      */
198     led_write(LedTargetR, 0);
199     led_write(LedTargetG, 1);
200     lcd_goto(0, 1);
201     lcd_puts("InitDone");
202
203     /*
204      * ミュートを解除する。
205      */
206     ssm2603_mute(false);
207 }
208
209 void uzume_set_effect(UZUME *p, UZUME_EFFECT_FUNC effect)
210 {
211     p->effect = effect;
212 }
213
214 void uzume_set_system(UZUME *p, UZUME_SYSTEM_FUNC system)
215 {
216     p->system = system;
217 }
218
219 void uzume_execute(UZUME *p)
220 {
221     int32_t bufidx_dma_done;
222
223     while (1) {
224         asm("idle;");
225         if (0 != data_ready) {
226             /*
227              * フラグをクリアする。
228              */
229             data_ready = 0;
230
231             /*
232              * DMAが完了したバッファを使用してオーディオ処理を行なう。
233              */
234             bufidx_dma_done = bufidx_dma_target ^ 1;
235             if (p->effect != NULL) {
236                 p->effect(
237                         p,
238                         sport_buffer_rx[bufidx_dma_done],
239                         sport_buffer_tx[bufidx_dma_done],
240                         DMA_SAMPLE_SIZE);
241             }
242             /*
243              *
244              */
245             led_write(LedTargetR, 1);
246         }
247         if (p->system != NULL) {
248             p->system(p);
249         }
250     }
251 }
252