OSDN Git Service

42528be8fcada723a8f44b28b0a2d9e8cc99dfcf
[uzume/uzume_bfin.git] / uzumeapp / kernel / uzume / ad7999.c
1 /**
2  * @file ad7999.c
3  * @author: suikan
4  * @brief AD799x I2C ADCからデータを読み込み、API経由でアプリケーションへ渡す
5  */
6
7
8 #include <t_services.h>
9 #include <s_services.h>
10 #include <i2c_subsystem.h>
11 #include "kernel_id.h"
12 #include "uzume.h"
13 #include "ad7999.h"
14
15 /**
16  * @brief AD7999のチャンネル数 UZUME_AD7999_I2C_ADRS_2が宣言されている場合にはチャンネル数を2にする。
17  */
18 #ifdef UZUME_AD7999_I2C_ADRS_2
19 #define NUM_CH 8
20 #else
21 #define NUM_CH 4
22 #endif
23
24 /**
25  * @brief ADC変換値保存用配列
26  * @details
27  * 変換値を保存する。アクセスは排他的でなければならない。値は符号付き左詰めである。
28  * 整数部はないので、1ビットの符号の右に小数部が連なる。
29  */
30 static fract32 values[NUM_CH];
31
32 /*
33  * ADCのI2Cポート。
34  * AD7999が接続されているI2Cペリフェラルのポート番号。デフォルトは0である。他のポートを使いたい時には
35  * sys_config.hで宣言すると良い。なお、I2Cコントローラ・ペリフェラルがひとつしかない場合には0を指定
36  * する。
37  */
38 #ifndef UZUME_AD7999_I2C_PORT
39 #define UZUME_AD7999_I2C_PORT 0x00
40 #endif
41
42 /*
43  * ADCのI2Cアドレス。
44  * AD7999の7bit I2Cアドレスはデフォルトで0x29と決め打ちしている。他のアドレスを使いたい時には
45  * sys_config.hで宣言すると良い
46  */
47 #ifndef UZUME_AD7999_I2C_ADRS
48 #define UZUME_AD7999_I2C_ADRS 0x29
49 #endif
50
51 /**
52  * @brief ADU999 制御タスク
53  * @param exinf タスク引数。ADC799xが持つ7bitのI2Cアドレスを指定する。
54  */
55 void ad7999_task(VP_INT exinf)
56 {
57     unsigned int ch;
58     unsigned char adcbuf[2];
59
60
61     while(1)
62     {
63         i2ccall(i2c_master_read(UZUME_AD7999_I2C_PORT, UZUME_AD7999_I2C_ADRS, adcbuf, 2));
64
65             /* 上位バイトのbit 5:4 をチャンネル番号として受け取る */
66         ch = ( adcbuf[0] & 0x30 ) >> 4;
67             /*上位バイトのbit 3;0と下位バイトから12bitのADCデータを作る。そのデータを32bitに左詰めする */
68
69         /* 排他区間開始 */
70         syscall(wai_sem(AD7999_SEM));
71         values[ch] = ( (( adcbuf[0] & 0x0F )<<8 ) | adcbuf[1] ) << 19;
72         syscall(sig_sem(AD7999_SEM));
73         /* 排他区間終了 */
74
75 #ifdef UZUME_AD7999_I2C_ADRS_2
76         i2ccall(i2c_master_read(UZUME_AD7999_I2C_PORT, UZUME_AD7999_I2C_ADRS_2, adcbuf, 2));
77
78             /* 上位バイトのbit 5:4 をチャンネル番号として受け取る。2番目のADCなのでオフセットは4 */
79         ch = (( adcbuf[0] & 0x30 ) >> 4) + 4;
80             /*上位バイトのbit 3;0と下位バイトから12bitのADCデータを作る。そのデータを32bitに左詰めする */
81
82         /* 排他区間開始 */
83         syscall(wai_sem(AD7999_SEM));
84         values[ch] = ( (( adcbuf[0] & 0x0F )<<8 ) | adcbuf[1] ) << 19;
85         syscall(sig_sem(AD7999_SEM));
86         /* 排他区間終了 */
87
88 #endif
89
90         tslp_tsk(1);
91     }
92 }
93
94 /**
95  * @brief ボリューム値の取得
96  * @param ch 0から始まるチャンネル指定番号。AD7999は3まで
97  * @return 32bit符号付き固定小数点数のボリューム値
98  */
99
100 fract32 ad7999_get_volume(unsigned int ch)
101 {
102     fract32 retval;
103
104         // パラメータチェック
105     if (ch >= NUM_CH)
106         ch = NUM_CH - 1;
107
108     /* 排他区間開始 */
109     syscall(wai_sem(AD7999_SEM));
110     retval = values[ch];
111     syscall(sig_sem(AD7999_SEM));
112     /* 排他区間終了 */
113
114     return retval;
115 }