3 * @brief オーディオDMAに同期して動くタスク
5 * @ref dma_intr_handler からのSEM_I2SDMA セマフォ・シグナルを受けて
6 * しかるべきデータ・バッファを特定し、信号処理を行う。
8 * なお、このタスクはシステム起動時にはインアクティブである。
9 * 明示的にアクティベートして始めて動作を開始する。
11 * 内蔵I2SペリフェラルとDMAを使って外部のオーディオ・コーデック
12 * からデータを取り込み、内部でコピーして再度オーディオ・コーデックに
13 * 出力する。内部コピーは \ref process_audio 関数で行っており
14 * 内部を書き換えることでどのようなアルゴリズムでも実装できる。
16 * audio_taskはDMA割り込みハンドラ \ref dma_intr_handler からの
17 * シグナルに同期して動作し、ピンポンバッファを使ってDMAと
20 * このプログラムが使用しているコーデックはTI社のTLV320AIC23Bである。
21 * 初期化データ列は \ref codec_init ルーチンから送出している。
23 * なお、LPC1768のDMAは、何らかのDMA管理機構を使ってチャンネル割り当てを
24 * すべきだが、このプログラムではその操作を省いている。
31 #include "kernel_cfg.h"
32 #include "audio_common.h"
33 #include "audio_effect.h"
34 #include "i2s_subsystem.h"
35 #include "i2c_subsystem.h"
36 #include "codec_subsystem.h"
38 #include "task_audio.h"
39 #include "task_display.h"
41 #define MSG_TARGET(n) (((n) & 0xF000) >> 12)
42 #define MSG_VALUE(n) (((n) & 0x0FFF) >> 0)
45 * \param file ソースコードのファイル名
46 * \param line ソースコードの行番号
47 * \param expr サービスコールのテキスト表現
48 * \param ercd サービスコールの結果(エラー値)
49 * \brief サービスコールのエラーのログ出力を行う補助関数
51 * TOPPERS/ASPのサービスコールのエラー出力を行うためのサポート関数。
52 * \ref SVC_PERROR マクロの中から使う。
55 svc_perror(const char *file, int_t line, const char *expr, ER ercd)
58 t_perror(LOG_ERROR, file, line, expr, ercd);
63 * \brief サービスコールのエラー出力マクロ
64 * \param expr サービスコールの式
66 * exprとして与えたサービスコールのソースコード上の表現と
68 * サービスコールに限らず値を持つ式ならなんでもよい。
70 #define SVC_PERROR(expr) svc_perror(__FILE__, __LINE__, #expr, (expr))
75 * このハンドラは全DMAに対して共通に呼ばれる.
77 * 呼ばれると、DMAのバッファ終了割り込みステータスを確認する。
78 * それがI2S DMAバッファの終了割り込みなら、割り込みをクリアして
81 * DMAチャンネルの番号は決め打ちである。
82 * 適切なDMA管理機構を使った方式への変更が必要である。
84 void dma_intr_handler(intptr_t exinf)
86 i2s_dma_intr_handler();
92 * DMAのLLIやバッファなどはすべてこの変数にパッケージしている。
93 * こうすることで、グローバル空間に名前が散らかることを阻止できる。
95 struct I2S_AUDIO_DATA audio_data;
97 struct I2S_AUDIO_DATA* get_audio_data(void)
102 void task_audio(intptr_t exinf)
105 const AUDIOSAMPLE *rxbuf;
107 AUDIOSAMPLE lm_left, lm_right;
109 effect_param_t effect_param;
111 const effect_param_t *param,
112 const AUDIOSAMPLE *in_left,
113 const AUDIOSAMPLE *in_right,
114 AUDIOSAMPLE *out_left,
115 AUDIOSAMPLE *out_right);
127 i2s_dma_init(get_audio_data());
131 * i2s_start()を呼ぶとDMA割り込みの無限ループに陥る。
132 * 現象が発生するのはコールドスタートの時だけ。要調査。
137 * リアルタイム・ステータス用のテストピンを出力にする。
141 effect_func = audio_effect_through;
145 // 外部タスクからパラメータを取得する。
146 if (prcv_dtq(DTQ_AUDIOPARAM, (intptr_t *)&msg) == E_OK) {
147 switch (MSG_TARGET(msg)) {
148 case AUDIO_PARAM_MODE:
149 switch (MSG_VALUE(msg)) {
150 case AUDIO_VALUE_MODE_THROUGH:
151 effect_func = audio_effect_through;
153 case AUDIO_VALUE_MODE_VOCAL_CANCEL:
154 effect_func = audio_effect_vocal_cancel;
156 case AUDIO_VALUE_MODE_FIR:
157 effect_func = audio_effect_fir;
159 case AUDIO_VALUE_MODE_IIR:
160 effect_func = audio_effect_iir;
164 "Unknown effect mode %d.",
169 case AUDIO_PARAM_VAR0:
170 effect_param.var0 = MSG_VALUE(msg);
172 case AUDIO_PARAM_VAR1:
173 effect_param.var1 = MSG_VALUE(msg);
175 case AUDIO_PARAM_VAR2:
176 effect_param.var2 = MSG_VALUE(msg);
178 case AUDIO_PARAM_VAR3:
179 effect_param.var3 = MSG_VALUE(msg);
189 // プログラムが使用してもよいバッファのアドレスを取得する。
190 txbuf = i2s_getTxBuf();
191 rxbuf = i2s_getRxBuf();
193 // 同期状態を示すためのテストピン信号を作成する。
194 testpin_tp1_write(1);
198 for (index = 0; index < AUDIOBUFSIZE; index+=2) {
201 rxbuf + (index + 0), rxbuf + (index + 1),
202 txbuf + (index + 0), txbuf + (index + 1));
203 lm_left = (lm_left >> 1) + (*(txbuf + (index + 0)) >> 1);
204 lm_right = (lm_right >> 1) + (*(txbuf + (index + 1)) >> 1);
207 // 同期状態を示すためのテストピン信号を作成する
208 testpin_tp1_write(0);