-
-
Notifications
You must be signed in to change notification settings - Fork 21
/
FAMIPAD.hpp
139 lines (123 loc) · 3.81 KB
/
FAMIPAD.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once
//=====================================================================//
/*! @file
@brief ファミリーコンピューター JOY PAD 読み込み @n
CMOS 4021B Shift Register @n
ファミコン互換パッド:@n
赤:Vcc、黄:Vss、青:P/S、茶:CLK、白:OUT @n
※互換パッドは高速なので遅延は少なくても OK (10)
NES パッド:@n
白:Vcc、茶:GND、橙:P/S、赤:CLK、黄:OUT @n
※ NES パッドの場合 3.3V で動かす為、クロックの遅延が重要 (20)
@author 平松邦仁 (hira@rvf-rc45.net)
@copyright Copyright (C) 2018 Kunihito Hiramatsu @n
Released under the MIT license @n
https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/delay.hpp"
namespace chip {
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief PAD 情報型
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
enum class FAMIPAD_ST : uint8_t {
RIGHT = 0b00000001,
LEFT = 0b00000010,
DOWN = 0b00000100,
UP = 0b00001000,
START = 0b00010000,
SELECT = 0b00100000,
B = 0b01000000,
A = 0b10000000,
};
//---------------------------------------------------------------------//
/*!
@brief 状態を検査
@param[in] data パッドの状態
@param[in] pad 検査パッド
*/
//---------------------------------------------------------------------//
static inline bool on(uint8_t data, FAMIPAD_ST pad) noexcept
{
return data & static_cast<uint8_t>(pad);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief FAMIPAD テンプレートクラス
@param[in] P_S P/S ポート
@param[in] CLK CLK ポート
@param[in] OUT OUT ポート
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
template <class P_S, class CLK, class OUT>
class FAMIPAD {
uint8_t data_;
public:
//-----------------------------------------------------------------//
/*!
@brief コンストラクタ
*/
//-----------------------------------------------------------------//
FAMIPAD() noexcept : data_(0) { }
//-----------------------------------------------------------------//
/*!
@brief 開始
@param[in] pullup 「OUT」信号入力をプルアップする場合
*/
//-----------------------------------------------------------------//
void start(bool pullup = false) noexcept
{
P_S::DIR = 1;
CLK::DIR = 1;
OUT::DIR = 0;
if(pullup) OUT::PU = 1;
update();
}
//-----------------------------------------------------------------//
/*!
@brief 最新の状態に更新
@param[in] cnt パルス幅遅延数 @n
※20で「1200us」くらいと思う
@return 状態データ
*/
//-----------------------------------------------------------------//
uint8_t update(uint32_t cnt = 20) noexcept
{
P_S::P = 0; // seirial
uint8_t d = 0;
for(uint8_t i = 0; i < 8; ++i) {
d <<= 1;
if(!OUT::P()) ++d;
CLK::P = 1;
utils::delay::loop(cnt);
CLK::P = 0;
utils::delay::loop(cnt);
}
P_S::P = 1; // parallel
data_ = d;
return data_;
}
//-----------------------------------------------------------------//
/*!
@brief 状態を検査
@param[in] pad 検査パッド
*/
//-----------------------------------------------------------------//
bool on(FAMIPAD_ST pad) const noexcept
{
return data_ & static_cast<uint8_t>(pad);
}
//-----------------------------------------------------------------//
/*!
@brief [] オペレーター
@param[in] pad 検査パッド
*/
//-----------------------------------------------------------------//
bool operator [] (FAMIPAD_ST pad) const noexcept
{
return on(pad);
}
};
}