I have to simulate an ADC that behaves as aan I2C slave. The simulated values that the ADC shall expose are sent over serial, saved on an attribute and are requested by a master device over I2C.
A simplified solution is the following. I have a struct ADC that describes the converter:
struct ADC
{
uint32_t register_1;
void write(uint32_t data){
register_1 = data;
}
uint8_t read(){
return register_1;
}
// some other methods to setup...
};
In loop(), I read the serial in order to update the ADC::register value and in the onRequest handler I eventually send the requested data by accessing ADC::register:
ADC adc{};
void setup(){
// setup adc, Wire and Serial here
Wire.onRequest(slaveTransmitterHandler)
}
void loop(){
if (Serial.available() > 0)
{
// read serial, parse received data and check them
uint32_t data = parse_serial(); // do anything is needed to check data...
// update adc attribute
uint8_t oldSREG = SREG;
noInterrupts(); // disable interrupts to update uint32
adc.write(data);
SREG = oldSREG;
}
}
void slaveTransmitterHandler(){
Wire.beginTransmission(ADDRESS);
Wire.write(adc.read());
Wire.endTransmission();
}
I'm not sure if I have to declare the adc object as volatile (this would mean to declare all ADC methods and variables as volatile). Is it safe to use an object inside the I2C handler called by the I2C interrupt?
As far as I know, it is not (I can find no reason why it should be different from non class variables), but I have always worked with non class variables and never with cpp objects. Also, I can't find any information about this topic.
It could be possible that I'm wrong with the whole design, even if it seems to me to be very consistent. I'm open to change it for something better, so please if this design is nonsense, comment on that! I'm here to learn :)
Thanks.
Luca