Open FFBoard
Open source force feedback firmware
ADS111X.cpp
Go to the documentation of this file.
1/*
2 * ADS111X.cpp
3 *
4 * Created on: 21.04.2022
5 * Author: Yannick
6 */
7
8#include "ADS111X.h"
9#ifdef I2C_PORT
10ADS111X::ADS111X(I2CPort &port,uint8_t address) : port(port), address(address) {
11 port.takePort(this);
12}
13
15 port.freePort(this);
16}
17
18
19void ADS111X::readRegIT(const uint8_t reg,uint16_t* data){
21 port.readMemIT(this, address, reg, 1, (uint8_t*)data, 2);
22}
23
24uint16_t ADS111X::readReg(const uint8_t reg){
25 uint16_t buf=0;
27 port.readMem(this, address, reg, 1, (uint8_t*)&buf, 2,100);
28 return buf;
29}
30
31void ADS111X::writeRegIT(const uint8_t reg,uint16_t data){
32 writeItBuffer = __REV16(data);
34
35 port.writeMemIT(this, address, reg, 1, (uint8_t*)&writeItBuffer, 2);
36}
37
38void ADS111X::writeReg(const uint8_t reg,uint16_t data){
39 writeItBuffer = __REV16(data);
41 port.writeMem(this, address, reg, 1, (uint8_t*)&writeItBuffer, 2,100);
42}
43
44void ADS111X::setThresh(uint16_t lowTh, uint16_t highTh){
45 registers.lothresh = lowTh;
46 registers.hithresh = highTh;
47 writeRegIT(0x02, registers.lothresh);
48 writeRegIT(0x03, registers.hithresh);
49}
50
60void ADS111X::setGain(uint16_t gain){
61 this->gain = clip<uint16_t,uint16_t>(gain, 0, 5);
62// this->registers.config &= ~0x0E00;
63// this->registers.config |= this->gain << 9;
64// writeRegIT(0x01, this->registers.config);
65}
66
67
79void ADS111X::setDatarate(uint16_t rate){
80 datarate = clip<uint16_t,uint16_t>(rate, 0, 7);
81}
82
83
98void ADS111X::startConversion(uint8_t channel, bool differential){
99 uint16_t mux = 0;
100 if(differential){
101 switch(channel)
102 {
103 default:
104 case 0:
105 mux = 0x0000;
106 break;
107 case 1:
108 mux = 0x3000;
109 break;
110 case 2:
111 mux = 0x1000;
112 break;
113 case 3:
114 mux = 0x2000;
115 break;
116
117 }
118 }else{
119 switch(channel)
120 {
121 default:
122 case 0:
123 mux = 0x4000;
124 break;
125 case 1:
126 mux = 0x5000;
127 break;
128 case 2:
129 mux = 0x6000;
130 break;
131 case 3:
132 mux = 0x7000;
133 break;
134
135 }
136 }
137 this->registers.config = 0x103; // Default settings. Single conversion 103
138 this->registers.config |= mux;
139 this->registers.config |= 0x8000; // Start conversion
140 this->registers.config |= datarate << 5; // Read datarate from separate variable to make sure it is updated if connection was interrupted
141 this->registers.config |= gain << 9;
142 writeRegIT(0x01, this->registers.config);
143}
144
145
146
148 //port->takeSemaphore(); // Take semaphore before setting buffers
149}
150
152 port->giveSemaphore(); // Take semaphore before setting buffers
153}
154
155
156
157
158// ---------------------------------------------------------------------- //
159#ifdef ADS111XANALOG
161 .name = "ADS111X ADC" ,
162 .id=CLSID_ANALOG_ADS111X,
163 };
165 return info;
166}
167
168
169const std::array<std::pair<uint16_t,uint16_t>,4> minMaxValAddr = {
170 std::pair<uint16_t,uint16_t>(ADR_ADS111X_MIN_0,ADR_ADS111X_MAX_0),
171 std::pair<uint16_t,uint16_t>(ADR_ADS111X_MIN_1,ADR_ADS111X_MAX_1),
172 std::pair<uint16_t,uint16_t>(ADR_ADS111X_MIN_2,ADR_ADS111X_MAX_2),
173 std::pair<uint16_t,uint16_t>(ADR_ADS111X_MIN_3,ADR_ADS111X_MAX_3),
174
175};
176
177ADS111X_AnalogSource::ADS111X_AnalogSource() : ADS111X(i2cport) , CommandHandler("adsAnalog", CLSID_ANALOG_ADS111X, 0),AnalogAxisProcessing(4,this,this, true,true,true,true), Thread("ads111x", 64, 25) {
180 registerCommand("inputs", ADS111X_AnalogSource_commands::axes, "Amount of inputs (1-4 or 1-2 if differential)",CMDFLAG_GET | CMDFLAG_SET);
181 //registerCommand("addr", ADS111X_AnalogSource_commands::address, "Address",CMDFLAG_GET | CMDFLAG_SET);
182 registerCommand("diff", ADS111X_AnalogSource_commands::differential, "Differential mode (Ch0= 0p 1n Ch1= 2p 3n)",CMDFLAG_GET | CMDFLAG_SET);
183 registerCommand("gain", ADS111X_AnalogSource_commands::gain, "PGA scale (0-5)",CMDFLAG_GET | CMDFLAG_SET | CMDFLAG_INFOSTRING);
184 registerCommand("rate", ADS111X_AnalogSource_commands::rate, "Data rate (0-7)",CMDFLAG_GET | CMDFLAG_SET | CMDFLAG_INFOSTRING);
185 restoreFlash();
186 this->Start();
187}
188
190
191}
192
195 uint16_t data = axes & 0x7;
196 data |= (gain & 0x7) << 3;
197 data |= (datarate & 0x7) << 6;
198 data |= (differentialMode) << 9;
200 Flash_Write(ADR_ADS111X_CONF1, data);
201}
202
205 uint16_t data;
206 if(Flash_Read(ADR_ADS111X_CONF1, &data)){
207 setAxes(data & 0x7, ((data >> 9) & 0x1) != 0);
208 setGain((data >> 3) & 0x7);
209 setDatarate((data >> 6) & 0x7);
211 }
212}
213
215 // Must not be called in constructor
216 //setThresh(0,0x8000);
217 lastSuccess = HAL_GetTick();
218 port.resetPort();
219 lastAxis = 0;
221}
222
225 port->resetPort();
226}
227
228// Handles starting next transfer for >1 byte transfers
230 while(true){
231
232
233 /*
234 * Sequence:
235 * Start sampling at channel 0
236 * Wait until request done
237 * Poll if sampling is done
238 * Wait until request done and possibly repeat polling
239 * Read sample and store in buffer when request done
240 *
241 */
242
244 initialize();
245 }
246
248
249 if(lastAxis < this->axes){
250 // Next transfer
252 ADS111X::startConversion(lastAxis,differentialMode); // Change channel and sample
253
255 // Check if done
256 Delay(1); // Sampling takes at least 1ms so we sleep before polling
258
260
261 // if done read sample
263 ADS111X::readRegIT(0x00, (uint16_t*)&sampleBuffer); // Read last conversion
264 }
265
266 }else{
267 // Last conversion done. store in buffer
268 lastAxis = 0;
269 lastSuccess = HAL_GetTick();
270
272
273 }
274 }
275}
276
281 if(port != &this->port || state == ADS111X_AnalogSource_state::idle){
282 return;
283 }
285 // Check config reg if conversion is done yet
286 configRegBuf = __REV16(configRegBuf);
287 if((configRegBuf & 0x8000) != 0){
288 // Done
290 }
292 sampleBuffer = __REV16(sampleBuffer); // Reverse buffer
293 if(!differentialMode){
294 sampleBuffer = (clip<int16_t,int16_t>(sampleBuffer,0,0x7fff) - 0x3fff) * 2 - 1; // Shift because we can't go below GND anyways
295 }
296 rawbuf[lastAxis] = (int16_t)sampleBuffer;
297 lastAxis++;
298 state = ADS111X_AnalogSource_state::beginSampling; // Begin next sample or go idle
299 }
300
302}
307 if(port != &this->port || state == ADS111X_AnalogSource_state::idle){
308 return;
309 }
310
311 if(state == ADS111X_AnalogSource_state::beginSampling){ // Last command started the sampling and was sent out. We are now waiting
313 }
314
316}
317
318std::vector<int32_t>* ADS111X_AnalogSource::getAxes(){
319
321 //Begin transfer
322 lastAxis = 0;
324 Notify();
325 }
326
327 if(HAL_GetTick() - lastSuccess > 4000){
329 Notify();
330 }
331 buf = rawbuf;
332 AnalogAxisProcessing::processAxes(buf); // Do processing every call to keep filter samplerate steady
333 return &this->buf;
334}
335
336void ADS111X_AnalogSource::setAxes(uint8_t axes,bool differential){
337 differentialMode = differential;
338 this->axes = clip<uint16_t,uint16_t>(axes,1,differentialMode ? 2 : 4);
339 this->buf.resize(this->axes,0);
340 this->rawbuf.resize(this->axes,0);
341}
342
343CommandStatus ADS111X_AnalogSource::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
344
345 switch(static_cast<ADS111X_AnalogSource_commands>(cmd.cmdId)){
346
348 if(cmd.type == CMDtype::set){
350 }else if(cmd.type == CMDtype::get){
351 replies.emplace_back(axes);
352 }
353 break;
354
356 if(cmd.type == CMDtype::set){
357 this->setGain(cmd.val);
358 }else if(cmd.type == CMDtype::get){
359 replies.emplace_back(gain);
360 }else if(cmd.type == CMDtype::info){
361 //replies.emplace_back("2/3x:0,1x:1,2x:2,4x:3,8x:4,16x:5");
362 replies.emplace_back("6.144V:0,4.096V:1,2.048V:2,1.024V:3,0.512V:4,0.256V:5");
363 }
364 break;
365
367 if(cmd.type == CMDtype::set){
368 setAxes(axes,cmd.val != 0); // Limit axes
369 }else if(cmd.type == CMDtype::get){
370 replies.emplace_back(differentialMode);
371 }
372 break;
373
375 if(cmd.type == CMDtype::set){
376 setDatarate(cmd.val);
377 }else if(cmd.type == CMDtype::get){
378 replies.emplace_back(datarate);
379 }else if(cmd.type == CMDtype::info){
380 replies.emplace_back("8 SPS:0,16 SPS:1,32 SPS:2,64 SPS:3,128 SPS:4,250 SPS:5,475 SPS:6,860 SPS:7");
381 }
382 break;
383 case ADS111X_AnalogSource_commands::address: // No option yet
384 default:
385 return AnalogAxisProcessing::command(cmd, replies); // Try processing command
386 }
387 return CommandStatus::OK;
388}
389#endif
390#endif
const std::array< std::pair< uint16_t, uint16_t >, 4 > minMaxValAddr
Definition: ADS111X.cpp:169
CommandStatus
uint16_t configRegBuf
Definition: ADS111X.h:101
void setAxes(uint8_t axes, bool differential)
Definition: ADS111X.cpp:336
void i2cTxCompleted(I2CPort *port)
Definition: ADS111X.cpp:306
static ClassIdentifier info
Definition: ADS111X.h:89
std::vector< int32_t > rawbuf
Definition: ADS111X.h:106
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
Definition: ADS111X.cpp:343
int16_t sampleBuffer
Definition: ADS111X.h:100
void i2cRxCompleted(I2CPort *port)
Definition: ADS111X.cpp:280
void i2cError(I2CPort *port)
Definition: ADS111X.cpp:223
uint32_t lastSuccess
Definition: ADS111X.h:104
virtual const ClassIdentifier getInfo()
Definition: ADS111X.cpp:164
std::vector< int32_t > * getAxes()
Definition: ADS111X.cpp:318
volatile ADS111X_AnalogSource_state state
Definition: ADS111X.h:107
struct ADS111X::@675 registers
void startI2CTransfer(I2CPort *port)
Definition: ADS111X.cpp:147
uint8_t gain
Definition: ADS111X.h:51
void setGain(uint16_t gain)
Definition: ADS111X.cpp:60
virtual ~ADS111X()
Definition: ADS111X.cpp:14
uint16_t writeItBuffer
Definition: ADS111X.h:60
void endI2CTransfer(I2CPort *port)
Definition: ADS111X.cpp:151
void writeReg(const uint8_t reg, uint16_t data)
Definition: ADS111X.cpp:38
void writeRegIT(const uint8_t reg, uint16_t data)
Definition: ADS111X.cpp:31
void setThresh(uint16_t loTh, uint16_t hiTh)
Definition: ADS111X.cpp:44
ADS111X(I2CPort &port, uint8_t address=0x48)
Definition: ADS111X.cpp:10
I2CPort & port
Definition: ADS111X.h:46
uint8_t address
Definition: ADS111X.h:49
void startConversion(uint8_t channel, bool differential=false)
Definition: ADS111X.cpp:98
uint16_t readReg(const uint8_t reg)
Definition: ADS111X.cpp:24
void readRegIT(const uint8_t reg, uint16_t *data)
Definition: ADS111X.cpp:19
void setDatarate(uint16_t rate)
Definition: ADS111X.cpp:79
uint8_t datarate
Definition: ADS111X.h:50
void saveMinMaxValues(const std::array< std::pair< uint16_t, uint16_t >, size > &minMaxAddresses)
void processAxes(std::vector< int32_t > &buf)
static AnalogProcessingConfig decodeAnalogProcessingConfFromInt(uint16_t val)
AnalogProcessingConfig & getAnalogProcessingConfig()
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
void restoreMinMaxValues(const std::array< std::pair< uint16_t, uint16_t >, size > &minMaxAddresses)
static uint16_t encodeAnalogProcessingConfToInt(AnalogProcessingConfig &conf)
void setAnalogProcessingConfig(AnalogProcessingConfig conf)
std::vector< int32_t > buf
Definition: AnalogSource.h:31
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
Definition: I2C.h:43
bool writeMemIT(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:224
void takeSemaphore()
Definition: I2C.cpp:280
void giveSemaphore()
Definition: I2C.cpp:293
bool readMem(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, const uint32_t timeout, bool shiftAddr=true)
Definition: I2C.cpp:208
void freePort(I2CDevice *device)
Definition: I2C.cpp:132
bool readMemIT(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:216
void takePort(I2CDevice *device)
Definition: I2C.cpp:117
bool writeMem(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, const uint32_t timeout, bool shiftAddr=true)
Definition: I2C.cpp:200
void resetPort()
Definition: I2C.cpp:108
bool isTaken()
Definition: I2C.cpp:276
uint32_t WaitForNotification(TickType_t Timeout=portMAX_DELAY)
Definition: thread.hpp:246
void Delay(const TickType_t Delay)
Definition: thread.hpp:352
I2CPort i2cport
static struct @612 data
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
const char * name
uint32_t cmdId