1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     hid_PadReader.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 30621 $
14  *---------------------------------------------------------------------------*/
15 
16 /*! @file
17     @brief      PadReader クラスを定義します。
18 
19 */
20 #ifndef NN_HID_CTR_HID_PADREADER_H_
21 #define NN_HID_CTR_HID_PADREADER_H_
22 
23 #include <nn/Handle.h>
24 #include <nn/Result.h>
25 #include <nn/types.h>
26 #include <nn/hid/CTR/hid_Result.h>
27 #include <nn/hid/CTR/hid_Api.h>
28 #include <nn/hid/CTR/hid_pad.h>
29 #include <nn/hid/CTR/hid_DeviceStatus.h>
30 #include <nn/util/util_SizedEnum.h>
31 #include <nn/util/util_NonCopyable.h>
32 
33 namespace nn {
34 namespace hid {
35 namespace CTR {
36 
37 const f32 DEFAULT_SCALE_OF_NORMALIZE_STICK     = 1.5f;
38 const s16 DEFAULT_THRESHOLD_OF_NORMALIZE_STICK = 141;
39 
40 /*!
41   @brief アナログスティックの円形クランプの遊びとして、適切な最小値です。
42 */
43 const s16   MIN_OF_STICK_CLAMP_MODE_CIRCLE  = 40;
44 
45 /*!
46   @brief アナログスティックの十字形クランプの遊びとして、適切な最小値です。
47 */
48 const s16   MIN_OF_STICK_CLAMP_MODE_CROSS   = 36;
49 
50 /*!
51   @brief アナログスティックのクランプの上限です。
52 */
53 const s16   LIMIT_OF_STICK_CLAMP_MAX              = 145;
54 
55 /*! @brief ゲームパッド(ボタン、アナログスティック)のサンプリングデータを読み込むクラスです。
56 
57              ゲームパッドは 4 msec 周期でサンプリングされます。
58 
59 */
60 
61 class PadReader : private nn::util::NonCopyable<PadReader>
62 {
63 public:
64     /*!
65       @enum     StickClampMode
66       @brief    SetStickClampMode( )  で設定するアナログスティックのクランプ方法を示す列挙体です。
67 
68 ・STICK_CLAMP_MODE_CIRCLE ( 円形クランプ )<BR>
69   内側と外側を円形にクランプします。<BR>
70   min と  max をそれぞれ SetStickClamp( ) で設定されるクランプの下限値、上限値とした場合<BR>
71   アナログスティックの入力座標 (x, y) の原点 からの距離 d に応じ、以下のようにクランプされた座標 (x', y') を得ます。 <BR>
72     d <= min の場合、 (x', y') = (0, 0)<BR>
73     min < d < max の場合、 (x', y') =   (d - min) / d * (x, y)<BR>
74     d >= max の 場合、 (x', y') =   (max - min) / d * (x, y)<BR><BR>
75 ・STICK_CLAMP_MODE_CROSS ( 十字形クランプ )<BR>
76   内側を十字形に、外側を円形にクランプします。 <BR>
77    まず、アナログスティックの入力座標 ( x, y ) に対し x, y 個別に 以下のようにクランプします。<BR>
78     x < 0 の場合、 x' = x + min  (0 以上になりません)<BR>
79     x >= 0 の場合、 x' = x - min  (0以下になりません)<BR>
80   さらに、座標 (x', y') の 原点からの距離 d が max - min より大きい場合は以下のようにクランプされた座標 (x', y') を得ます。<BR>
81     (x', y') = (max - min) / d * (x,' y')<BR><BR>
82 ・STICK_CLAMP_MODE_MINIMUM ( 最小クランプ )<BR>
83   内側クランプ領域を最小とするモードです。
84   内側に関して円形クランプと十字クランプを下限値に設定したときの
85   より小さい方のエリアでのクランプを行います。
86   形状としては円形の上下左右の一部を直線で切り取ったような形になります。<BR>
87   外側は円形クランプとなり、SetStickClamp( ) で設定されるmax値が反映されます。<BR>
88 
89     */
90     typedef enum
91     {
92         /*! @brief 円形クランプです。 詳しくは、本ページの説明を参照してください。 */
93         STICK_CLAMP_MODE_CIRCLE = 0,
94         /*! @brief 十字形クランプ です。 詳しくは、本ページの説明を参照してください。*/
95         STICK_CLAMP_MODE_CROSS,
96         /*! @brief 最小クランプ です。 詳しくは、本ページの説明を参照してください。*/
97         STICK_CLAMP_MODE_MINIMUM
98     } StickClampMode;
99 
100     /*!
101     @brief          コンストラクタです。
102 
103                     インスタンスを生成する前に @ref nn::hid::CTR::Initialize( ) で初期化してください。
104 
105     */
106     PadReader(Pad& pad=GetPad( ));
107 
108     /*!
109     @brief          デストラクタです。
110 
111     */
~PadReader()112     ~PadReader( ) {};
113 
114     /*!
115       @brief        ゲームパッドのサンプリングデータを新しいものから順に読み込みます。以前に読み込んだデータは読み込まれません。
116 
117                     アナログスティックは触れていない状態でも入力がありますので、 nn::hid::CTR::PadReader::SetStickClamp( ) で適切な遊びを設定してください。<BR>
118                     また、アナログスティックの入力座標と原点間の距離は最大値を得ることができません。これはクランプ処理の際に、丸めが発生するためです。<BR>
119                     この最大値を閾値などに使用しないでください。
120 
121       @param[out]   pBufs       新しいものから順にサンプリングデータが読み込まれます。
122       @param[out]   pReadLen    読み込んだサンプリングデータの数です。
123       @param[in]    bufLen      pBufs に読み込めるサンプリングデータの数を指定します。
124       @return       なし。
125 
126     */
127     void Read(PadStatus* pBufs, s32* pReadLen, s32 bufLen);
128 
129     /*!
130       @brief        最新のゲームパッドのサンプリングデータを読み込みます。 nn::hid::CTR::PadReader::Read( ) とちがい同じサンプリングデータを読み込むことが出来ます。
131 
132       trigger、release は前回の ReadLatest( ) の読み込み結果に対して生成されます。<BR><BR>
133                     アナログスティックは触れていない状態でも入力がありますので、 nn::hid::CTR::PadReader::SetStickClamp( ) で適切な遊びを設定してください。<BR>
134                     また、アナログスティックの入力座標と原点間の距離は最大値を得ることができません。これはクランプ処理の際に、丸めが発生するためです。<BR>
135                     この最大値を閾値などに使用しないでください。
136 
137       @param[out]   pBuf        サンプリングデータが読み込まれます。
138       @return       サンプリングデータの読み込み結果を返します。<BR>
139                       true ・・・ 読み込めました。<BR>
140                       false ・・・ 読み込めませんでした。(システム起動後あるいはスリープ復帰後の最初のサンプリングが行われ次第、読み込めます。)
141 
142     */
143     bool ReadLatest(PadStatus* pBuf);
144 
145     /*!
146       @brief        アナログスティックのクランプ値の設定を行います。
147 
148                     max値は @ref nn::hid::CTR::LIMIT_OF_STICK_CLAMP_MAX 以下の値を設定してください。<BR>
149                     min値は SetStickClampMode() で設定されるクランプ方法によって、指定可能な値が異なります。<BR>
150                     円形クランプは @ref nn::hid::CTR::MIN_OF_STICK_CLAMP_MODE_CIRCLE 以上の値が指定できます。<BR>
151                     十字形クランプは @ref nn::hid::CTR::MIN_OF_STICK_CLAMP_MODE_CROSS 以上の値が指定できます。<BR>
152                     最小クランプ時の min値は @ref nn::hid::CTR::MIN_OF_STICK_CLAMP_MODE_CIRCLE 固定となり設定値は無視されます。<BR>
153                     制限値を超える値を指定した場合、制限値に補正され適用されます。<BR>
154                     max値及びmin値はクランプ方法毎に別々に管理されます。
155 
156       @param[in]    min   クランプの下限です。 デフォルト値は円形クランプの場合 @ref nn::hid::CTR::MIN_OF_STICK_CLAMP_MODE_CIRCLE 、十字クランプの場合 @ref nn::hid::CTR::MIN_OF_STICK_CLAMP_MODE_CROSS です。
157       @param[in]    max   クランプの上限です。デフォルト値は @ref nn::hid::CTR::LIMIT_OF_STICK_CLAMP_MAX です。
158       @return       なし
159 
160     */
161     void SetStickClamp(s16 min, s16 max);
162 
163     /*!
164       @brief        アナログスティックの現在のクランプ方法におけるクランプ値を取得します。
165 
166       @param[out]   pMin   クランプの下限が返されます。
167       @param[out]   pMax   クランプの上限が返されます。
168       @return       なし。
169 
170       @date         2009/11/20 const メンバ関数に変更しました。
171       @since        2009/11/01 初版
172     */
173     void GetStickClamp(s16* pMin, s16* pMax) const;
174 
175     /*!
176       @brief        アナログスティックのクランプ方法を取得します。
177 
178       @return       現在設定されているクランプ方法を返します。
179 
180       @date         2009/11/20 const メンバ関数に変更しました。
181       @since        2009/11/01 初版
182     */
183     StickClampMode GetStickClampMode( ) const;
184 
185     /*!
186       @brief        アナログスティックのクランプ方法を設定します。
187 
188                     Read( ) と ReadLatest( ) で 得られるアナログスティックの値が設定された方法でクランプされます。クランプの詳細は、@ref nn::hid::CTR::PadReader::StickClampMode を参照してください。<BR>
189                     円形クランプ がデフォルトで設定されています。
190 
191       @param[in]    mode   設定するクランプ方法です。
192       @return       なし。
193 
194     */
195     void SetStickClampMode(StickClampMode mode);
196 
197     /*!
198       @brief        Read( ) と ReadLatest( ) で得られるアナログスティック の値を、-1.0 ~ 1.0 の浮動小数点数に正規化して返します。
199 
200                      クランプの上限と下限の 差を 1.0 とします。
201 
202       @param[in]    x       アナログスティックの値
203       @return       正規化された値
204     */
205     f32 NormalizeStick(s16 x);
206 
207     /*!
208       @brief        Read( ) と ReadLatest( ) で得られるアナログスティック の値を、-1.0 ~ 1.0 の浮動小数点数に正規化して返します。感度調整機能付きです。
209 
210                      内部では感度を調整するための特殊な処理が行われます。
211                      詳細については SetNormalizeStickScaleSettings( ) の説明を参照してください。
212 
213       @param[out]   normalized_x       正規化後x
214       @param[out]   normalized_y       正規化後y
215       @param[in]    x                  正規化前x
216       @param[in]    y                  正規化前y
217       @return       なし
218     */
219     void NormalizeStickWithScale( f32* normalized_x, f32* normalized_y, s16 x, s16 y );
220 
221     /*!
222       @brief        NormalizeStickWithScale( ) の設定を行います。
223 
224                       スライドパッドの可動範囲がscale倍あるかのように振る舞います。<BR>
225                       スライドパッドの値がthresholdに満たない場合 NormalizeStickWithScale( ) <BR>
226                       で得られる正規化値は 1/scale になります。<BR>
227                       スライドパッドの値がthreshold以上である場合 NormalizeStickWithScale( ) <BR>
228                       で得られる正規化値は徐々に ±1.0 に近づきます。<BR>
229                       thresholdには @ref nn::hid::CTR::LIMIT_OF_STICK_CLAMP_MAX 以下の値を設定してください。
230 
231       @param[in]    scale               感度調整パラメータ(デフォルトは1.5)
232       @param[in]    threshold           内部処理閾値 (デフォルトは141)
233       @return       なし
234     */
235     void SetNormalizeStickScaleSettings( f32 scale, s16 threshold  );
236 
237     /*!
238       @brief        NormalizeStickWithScale( ) の設定を取得します。
239 
240       @param[in]    scale              感度調整パラメータが返されます。
241       @param[in]    threshold          内部処理閾値が返されます。
242       @return       なし
243     */
244     void GetNormalizeStickScaleSettings( f32* scale, s16* threshold  ) const;
245 
246 
247 protected:
248     Pad&                m_Pad;
249     s32                 m_IndexOfRead;
250     bit32               m_LatestHold;
251     s16                 m_MinOfStickClampCircle;
252     s16                 m_MinOfStickClampCross;
253     s16                 m_MinOfStickClampMinimum;
254     s16                 m_MaxOfStickClampCircle;
255     s16                 m_MaxOfStickClampCross;
256     s16                 m_MaxOfStickClampMinimum;
257     bool                m_IsReadLatestFirst;
258     nn::util::SizedEnum1<StickClampMode>      m_StickClampMode;
259     s16                 m_Threshold;
260     f32                 m_Scale;
261     f32                 m_Stroke;
262     f32                 m_StrokeVelocity;
263     f32                 m_LastLength;
264     f32                 m_LastDiff;
265     s64                 m_TickOfRead;
266 };
267 
268 
269 // inline 定義
GetStickClamp(s16 * pMin,s16 * pMax)270 inline void PadReader::GetStickClamp(s16* pMin, s16* pMax) const
271 {
272 	if (m_StickClampMode == STICK_CLAMP_MODE_CIRCLE)
273 	{
274  	   *pMin = m_MinOfStickClampCircle;
275        *pMax = m_MaxOfStickClampCircle;
276  	}
277  	else if (m_StickClampMode == STICK_CLAMP_MODE_CROSS)
278  	{
279  	   *pMin = m_MinOfStickClampCross;
280        *pMax = m_MaxOfStickClampCross;
281 	}
282 	else
283 	{
284 		*pMin = m_MinOfStickClampMinimum;
285 		*pMax = m_MaxOfStickClampMinimum;
286 	}
287 }
288 
GetStickClampMode()289 inline PadReader::StickClampMode PadReader::GetStickClampMode( ) const
290 {
291     return m_StickClampMode;
292 }
293 
SetStickClampMode(StickClampMode mode)294 inline void PadReader::SetStickClampMode(StickClampMode mode)
295 {
296     m_StickClampMode = mode;
297 }
298 
299 } // namespace CTR {
300 } // namespace hid {
301 } // namespace nn {
302 
303 #endif  // #ifndef NN_HID_CTR_HID_PADREADER_H_
304