Dawn Framework 1.0
Universal data acquisition framework for embedded systems
adc_base.cxx
1// dawn/src/io/adc_base.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/io/adc_base.hxx"
7
8#include <cerrno>
9#include <cinttypes>
10#include <cstdio>
11#include <cstring>
12#include <new>
13
14using namespace dawn;
15
16CIOAdcBase::~CIOAdcBase()
17{
18 deinit();
19}
20
21int CIOAdcBase::configureCommonDesc(const CDescObject &desc)
22{
23 const SObjectCfg::SObjectCfgItem *item = nullptr;
24 size_t offset = 0;
25
26 for (size_t i = 0; i < desc.getSize(); i++)
27 {
28 item = desc.objectCfgItemAtOffset(offset);
29
31 {
32 DAWNERR("Unsupported ADC config 0x%08" PRIx32 "\n", item->cfgid.v);
33 return -EINVAL;
34 }
35
36 offset += cfgCmnOffset(item);
37 }
38
39 return OK;
40}
41
42int CIOAdcBase::configureDevice()
43{
44 int ret;
45
46 if (getCmnDevno() == -1)
47 {
48 DAWNERR("ADC device number not configured\n");
49 return -EINVAL;
50 }
51
52 std::snprintf(path, sizeof(path), ADC_PATH_FMT, getCmnDevno());
53
54 fd = adc_open(path);
55 if (fd < 0)
56 {
57 DAWNERR("failed to open ADC device %d\n", -fd);
58 return fd;
59 }
60
61 ret = adc_get_nchans(fd);
62 if (ret <= 0)
63 {
64 adc_close(fd);
65 fd = -1;
66 DAWNERR("invalid number of channels %d\n", ret);
67 return ret < 0 ? ret : -EIO;
68 }
69
70 chans = static_cast<uint8_t>(ret);
71 return OK;
72}
73
75{
76 int ret;
77
78 ret = configureCommonDesc(getDesc());
79 if (ret != OK)
80 {
81 DAWNERR("ADC configure failed (error %d)\n", ret);
82 return ret;
83 }
84
85 return configureDevice();
86}
87
89{
91 {
92 DAWNERR("ADC requires DTYPE_INT32\n");
93 return -EINVAL;
94 }
95
96 return OK;
97}
98
100{
101 delete[] rdata;
102 rdata = nullptr;
103 batch = 0;
104
105 adc_close(fd);
106 fd = -1;
107 chans = 0;
108
109 return OK;
110}
111
113{
114 return chans * tlen;
115}
116
118{
119 return chans;
120}
121
122int CIOAdcBase::ensureReadBuffer(size_t samples)
123{
125
126 if (samples == 0)
127 {
128 return -EINVAL;
129 }
130
131 if (chans == 0)
132 {
133 return -EACCES;
134 }
135
136 if (rdata != nullptr && batch >= samples)
137 {
138 return OK;
139 }
140
141 tmp = new (std::nothrow) dawn::porting::adc_read_s[samples * chans]();
142 if (tmp == nullptr)
143 {
144 return -ENOMEM;
145 }
146
147 delete[] rdata;
148 rdata = tmp;
149 batch = samples;
150
151 return OK;
152}
153
154int CIOAdcBase::readSamples(IODataCmn &data, size_t len)
155{
156 size_t bytesPerBatch;
157 size_t expected;
158 size_t total;
159 uint8_t *dst;
160 int ret;
161
162 if (len == 0)
163 {
164 return -EINVAL;
165 }
166
167 if (data.getItems() < chans)
168 {
169 return -ENOMEM;
170 }
171
172 bytesPerBatch = getDataSize();
173 expected = len * bytesPerBatch;
174 total = 0;
175
176 if (!data.hasTimestamp())
177 {
178 dst = static_cast<uint8_t *>(data.getDataPtr());
179 }
180 else
181 {
182 ret = ensureReadBuffer(len);
183 if (ret < 0)
184 {
185 return ret;
186 }
187
188 dst = reinterpret_cast<uint8_t *>(rdata);
189 }
190
191 while (total < expected)
192 {
193 ret =
194 adc_read(fd, reinterpret_cast<dawn::porting::adc_read_s *>(dst + total), expected - total);
195 if (ret < 0)
196 {
197 return ret;
198 }
199
200 if (ret == 0)
201 {
202 return -EIO;
203 }
204
205 total += static_cast<size_t>(ret);
206 }
207
208 if (data.hasTimestamp())
209 {
210 for (size_t i = 0; i < len; i++)
211 {
212 std::memcpy(data.getDataPtr(i), &rdata[i * chans], bytesPerBatch);
213
214#ifdef CONFIG_DAWN_IO_TIMESTAMP
215 data.getTs(i) = getTimestamp();
216#endif
217 }
218 }
219#ifdef CONFIG_DAWN_IO_TIMESTAMP
220 else if (isTimestamp())
221 {
222 for (size_t i = 0; i < len; i++)
223 {
224 data.getTs(i) = getTimestamp();
225 }
226 }
227#endif
228
229 return OK;
230}
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemAtOffset(size_t offset) const
Get configuration item at specified offset.
int init()
One-time initialize object after bindings are resolved.
Definition adc_base.cxx:88
int deinit()
De-initialize object.
Definition adc_base.cxx:99
size_t getDataDim() const
Get data vector dimension.
Definition adc_base.cxx:117
int configure()
Configure object from descriptor data.
Definition adc_base.cxx:74
size_t getDataSize() const
Get data size in bytes.
Definition adc_base.cxx:112
uint64_t getTimestamp()
Get current timestamp.
Definition common.cxx:194
bool isTimestamp() const
Check if I/O supports timestamp.
Definition common.cxx:189
int getCmnDevno() const
Get device number for this I/O.
Definition common.hxx:798
size_t cfgCmnOffset(const SObjectCfg::SObjectCfgItem *cfg)
Get offset of configuration item in descriptor.
Definition common.cxx:144
@ IO_CLASS_ANY
Any I/O class.
Definition common.hxx:86
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Base interface for I/O data buffers (static and dynamic).
Definition idata.hxx:21
virtual bool hasTimestamp()=0
Check if this data buffer has per-batch timestamp storage.
virtual size_t getItems()=0
Get number of items per batch.
virtual void * getDataPtr(size_t batch=0)=0
Get pointer to data only (skips timestamp if present).
virtual uint64_t & getTs(size_t batch=0)=0
Get timestamp reference for batch.
Single configuration item within object.
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
@ DTYPE_INT32
Signed 32-bit integer (-2147483648 to 2147483647).
Definition objectid.hxx:92
ADC read data.
Definition adc.hxx:23
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
Definition objectcfg.hxx:82
uint32_t cls
Object class (bits 21-29, max 511).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.