-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathadc_io.hpp
177 lines (149 loc) · 4.46 KB
/
adc_io.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#pragma once
//=====================================================================//
/*! @file
@brief R8C グループ・A/D 制御
@author 平松邦仁 ([email protected])
@copyright Copyright (C) 2015, 2021 Kunihito Hiramatsu @n
Released under the MIT license @n
https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "common/vect.h"
#include "M120AN/adc.hpp"
#include "M120AN/intr.hpp"
#include "M120AN/system.hpp"
namespace device {
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief A/D 制御クラス
@param[in] TASK A/D 変換終了時起動タスク
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
template <class TASK>
class adc_io {
static TASK task_;
static volatile uint8_t intr_count_;
public:
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief チャネル・タイプ
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
enum class CH_TYPE : uint8_t {
CH0, //< チャネル0のみ
CH1, //< チャネル1のみ
CH0_CH1 //< 0,1チャネル
};
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief チャネル・グループ
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
enum class CH_GROUP : uint8_t {
AN0_AN1, //< AN0, AN1
AN2_AN3, //< AN2, AN3
AN4_AN7 //< AN4, AN7
};
static inline void itask() {
++intr_count_;
task_();
// IR 関係フラグは必ず mov 命令で・・
volatile uint8_t r = ADICSR();
ADICSR = 0x00;
}
private:
uint8_t level_;
uint8_t count_;
// ※同期が必要なら、実装する
void sleep_() const {
asm("nop");
}
public:
//-----------------------------------------------------------------//
/*!
@brief コンストラクター
*/
//-----------------------------------------------------------------//
adc_io() noexcept : level_(0), count_(0) { }
//-----------------------------------------------------------------//
/*!
@brief 変換開始
@param[in] ct チャネル・タイプ
@param[in] grp チャネル・グループ
@param[in] cycle 繰り返し変換の場合「true」
@param[in] level 割り込みレベル(0の場合割り込みを使用しない)
*/
//-----------------------------------------------------------------//
void start(CH_TYPE ct, CH_GROUP cg, bool cycle, uint8_t level = 0) noexcept
{
level_ = level;
MSTCR.MSTAD = 0;
ADCON0.ADST = 0;
uint8_t md = 0b00;
if(ct == CH_TYPE::CH0_CH1) md = 0b10;
if(cycle) md |= 0b01;
ADMOD = ADMOD.CKS.b(0b011) | ADMOD.MD.b(md) | ADMOD.ADCAP.b(0b00);
uint8_t chn = 0;
if(ct == CH_TYPE::CH1) chn = 1;
ADINSEL = ADINSEL.CH0.b(chn) | ADINSEL.ADGSEL.b(static_cast<uint8_t>(cg));
ILVL7.B01 = level_;
}
//-----------------------------------------------------------------//
/*!
@brief 変換開始
@param[in] f 変換停止の場合「false」
*/
//-----------------------------------------------------------------//
void scan(bool f = true) noexcept
{
count_ = intr_count_;
if(f && level_ > 0) {
ADICSR.ADIE = 1;
}
ADCON0.ADST = f;
}
//-----------------------------------------------------------------//
/*!
@brief 変換終了検査
@return 変換終了なら「true」
*/
//-----------------------------------------------------------------//
bool get_state() const noexcept
{
if(level_ == 0) {
bool f = ADICSR.ADF();
if(f) ADICSR.ADF = 0;
return f;
} else {
return count_ != intr_count_;
}
}
//-----------------------------------------------------------------//
/*!
@brief 変換終了を同期
*/
//-----------------------------------------------------------------//
void sync() const noexcept {
while(!get_state()) sleep_();
}
//-----------------------------------------------------------------//
/*!
@brief 変換結果の取得
@param[in] chanel チャネル(0、1)
@return 変換結果
*/
//-----------------------------------------------------------------//
uint16_t get_value(bool chanel) const noexcept {
if(chanel) {
return AD1();
} else {
return AD0();
}
}
};
// スタティック実態定義
template<class TASK>
TASK adc_io<TASK>::task_;
template<class TASK>
volatile uint8_t adc_io<TASK>::intr_count_ = 0;
}