I'm trying to use a pointer in a function argument to read a variable from a class, like this:
void Function(int (*Argument)) {
Variable = Object*Argument.ClassVariable;
}
Note: the reason I want to do this is so that I can set the value of a rotary encoder position equal to the value a class variable was previously at, prior to allowing the user to change that class variable value. This way, when the user cycles through the class variables to set them, the starting position for each variable is the saved value.
Class objects are named Object1
, Object2
, etc.
The variable I want to read from each object is named ClassVariable
.
When I call the function, i will useFunction(ClassNumber);
If ClassNumber
is 13
at the time the function is called, I want Variable
to be made equal to Object13.ClassVariable
Is this possible?
Further Info:
The entire class is public.
Constructor for class objects (note, this is arduino, byte
is 8-bit unsigned):
Modes(byte hue, byte sat, byte val, int del, bool hROal, bool hset, bool sset, bool vset, bool dset) {
hueVal = hue;
satVal = sat;
valVal = val;
delVal = del;
hueROallow = hROal;
hSet = hset;
sSet = sset;
vSet = vset;
dSet = dset;
}
Each class object is a separate 'mode' that the user can select. The Argument
i intend using in the function is the 'mode number' currently selected.
FULL CODE (very much a work in progress)
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>
const byte Button2 = 8;
const byte EncApin = 3; // EncApin **MUST BE interrupt**
const byte EncBpin = 4; // These are the three pins the encoder A/B & button are connected to
const byte EncButt = 2; //
static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // array to set encoder H/L sequence
byte encVal; // initialises reading from encoder
Adafruit_SH1106 display(0); // Initialise display? (On SPI OLED screens this sets the MOSI/CLK/DC/RST/CS pins)
int displayVal; // to store the current output value for display
String displayMode;
byte mode = 1; // set mode 0 at beginning
byte qtyModes = 3; // set number of modes that may be selected here
byte setMode = 1;
byte qtySetModes = 4; // set number of sub-modes for setting values
///// FUNCTION PROTOTYPES ///////// must be declared here to allow the class to use them
void EncReading();
void EncReadingRO();
////////////////////////////////////////////////////////
////////////// ******** CLASSES ********* //////////////
////////////////////////////////////////////////////////
class Modes {
public: // everything in the class below this will be available to the program outside of the class
// Class Member Variables
// These are initialized at startup
byte hueVal;
byte satVal;
byte valVal;
int delVal;
bool hueROallow;
bool hSet;
bool sSet;
bool vSet;
bool dSet;
byte CLdisplayVal;
String displayDesc;
// These maintain the current state
unsigned long prevMillis; // will store last time LED was updated
// Constructor - creates a Mode & initializes the member variables and state
// additional options for whether rollover of values allowed needed
Modes(byte hue, byte sat, byte val, int del, bool hROal, bool hset, bool sset, bool vset, bool dset) {
hueVal = hue;
satVal = sat;
valVal = val;
delVal = del;
hueROallow = hROal;
hSet = hset;
sSet = sset;
vSet = vset;
dSet = dset;
}
void Update() {
switch (setMode) {
case 1: // case 1 for hue update
if (hSet == 0) {
displayDesc = F(" HUE (FIXED)");
CLdisplayVal = hueVal;
break;
}
if (hueROallow == 1) EncReadingRO();
else EncReading();
hueVal = encVal;
CLdisplayVal = encVal;
displayDesc = F(" HUE");
break;
case 2: // saturation update
if (sSet == 0) {
displayDesc = F(" SATURATION (FIXED)");
CLdisplayVal = satVal;
break;
}
EncReading();
satVal = encVal;
CLdisplayVal = encVal;
displayDesc = F(" SATURATION");
break;
case 3: // value update
if (vSet == 0) {
displayDesc = F(" BRIGHTNESS (FIXED)");
CLdisplayVal = valVal;
break;
}
EncReading();
valVal = encVal;
CLdisplayVal = encVal;
displayDesc = F(" BRIGHTNESS");
break;
case 4: // delay update
if (dSet == 0) {
displayDesc = F(" TIMING (FIXED)");
CLdisplayVal = delVal;
break;
}
EncReading();
delVal = encVal;
CLdisplayVal = encVal;
displayDesc = F(" TIMING");
break;
}
displayReading();
}
void displayReading() {
unsigned long currMillis = millis(); // These four lines are to
static unsigned long prevMillis; // act as a delay, except
if (currMillis - prevMillis >= 100) { // without holding the execution // note: encoder reading sensitive to delal changes, 100 not bad
prevMillis = currMillis; // of other code
display.fillRect(39, 30, 54, 24, BLACK);
display.fillRect(0, 0, 128, 18, WHITE);
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(1,1);
display.println(displayMode);
display.setCursor(1,10);
display.println(displayDesc);
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(39,30);
display.println(CLdisplayVal);
display.display();
}
}
};
////////// Construct objects - this sets up the objects we want of the class 'Modes'
// Modes modex(Hue0-255, Sat0-255, Val0-255, Del0-255, Hue rollover0/1, Hue settable0/1, Sset0/1, Vset0/1, Dse0/1
Modes mode1(50, 100, 150, 100, 1, 1, 1, 1, 1); // object 'mode1', initializing with H50, S100, V150, D100, hue rollover & settable options ON
Modes mode2(55, 105, 155, 105, 0, 1, 1, 1, 1);
Modes mode3(63, 73, 83, 93, 0, 1, 1, 1, 1);
////////////////////////////////////////////////////////
////////// ******** SETUP / LOOP ********* /////////////
////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
display.clearDisplay();
display.display();
pinMode(EncApin, INPUT_PULLUP); // Turn on internal pullup resistors for encoder pins & buttons
pinMode(EncBpin, INPUT_PULLUP);
pinMode(Button2, INPUT_PULLUP);
pinMode(EncButt, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(EncApin), read_encoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(EncButt), encButtPress, FALLING);
pciSetup(Button2); // set up encApin for pin change interrupt
encVal = mode1.hueVal; // initialize the encoder to the mode1 setmode1 value
}
void loop() {
switch(mode) {
case 1:
displayMode = F("MODE:Call it anything");
mode1.Update();
// add call to the mode 1 LED display function here, using mode1.xyz variables
break;
case 2:
displayMode = F("MODE:Second");
mode2.Update();
// add call to the mode 2 LED display function here, using mode2.xyz variables
break;
case 3:
displayMode = F("MODE:Third");
mode3.Update();
// add call to the mode 2 LED display function here, using mode2.xyz variables
break;
}
Serial.print(F("Enc: "));
Serial.print(encVal);
Serial.print(F(" M1 H: "));
Serial.print(mode1.hueVal);
Serial.print(F(" S: "));
Serial.print(mode1.satVal);
Serial.print(F(" V: "));
Serial.print(mode1.valVal);
Serial.print(F(" D: "));
Serial.print(mode1.delVal);
Serial.print(F(" M2 H: "));
Serial.print(mode2.hueVal);
Serial.print(F(" S: "));
Serial.print(mode2.satVal);
Serial.print(F(" V: "));
Serial.print(mode2.valVal);
Serial.print(F(" D: "));
Serial.println(mode2.delVal);
// Serial.print(F("freeMemory()="));
// Serial.println(freeMemory());
}
////////////////////////////////////////////////////////
//////////// ******** FUNCTIONS ********* //////////////
////////////////////////////////////////////////////////
///// Function to set encVal, 0-255, NO rollover
void EncReading() {
int8_t encoderdata;
encoderdata = read_encoder(); // returns the +- value from the read_encoder function
if (encoderdata) { // if not equal to zero
if (encVal+encoderdata>255 || encVal+encoderdata<0); // these if/else statements clamp encVal to prevent byte rollover
else {
encVal += encoderdata;
} // end else
}
}
///// Function to set encVal, 0-255, WITH rollover
void EncReadingRO() {
int8_t encoderdata;
encoderdata = read_encoder(); // returns the +- value from the read_encoder function
if (encoderdata) { // if not equal to zero
encVal += encoderdata;
}
}
////////////////////////////////////////////////////////
//////////// ******** INTERRUPTS ********* /////////////
////////////////////////////////////////////////////////
/////// Pin Change Interrupt Setup Function /////////// called in void setup to set the selected pin as a PCI
void pciSetup(byte pin)
{
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}
//////////// PCI Interrupt Sub Routines////////
// ISR (PCINT0_vect) is ISR for D8-13 // ISR (PCINT2_vect) is ISR for A0-5 // ISR (PCINT2_vect) is ISR for D0-7 //
ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here, depending on which are set in void setup
{
if(digitalRead(Button2) == LOW)
buttonPress();
}
//////// Func for ENCODER button press ISR ****** CHANGE 'setMode' ***** ///////////////
void encButtPress() {
static unsigned long prevInterrTime = 0;
unsigned long interrTime = millis();
if (interrTime - prevInterrTime > 200) {
setMode++;
// *** ADD HERE *** need to set encVal to whatever the existing value is in the setMode being switched to
if (setMode > qtySetModes) setMode = 1;
prevInterrTime = interrTime;
setPrevEncVal(mode);
}
}
void setPrevEncVal(byte (*modeNum)) {
switch (setMode) {
case 1: encVal = mode&modeNum.hueVal; break;
case 2: encVal = mode1.satVal; break;
case 3: encVal = mode1.valVal; break;
case 4: encVal = mode1.delVal; break;
}
}
//////// Func for button press ISR ****** CHANGE 'mode' ***** ///////////////
void buttonPress() {
static unsigned long prevInterrTime = 0;
unsigned long interrTime = millis();
if (interrTime - prevInterrTime > 200) {
mode++; // increment 'mode'
setMode = 1; // reset 'setMode'
}
if (mode > qtyModes) mode = 1;
prevInterrTime = interrTime;
}
//////// Func for +1/-1 encoder reading ISR ///////
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder() {
static uint8_t old_AB = 0;
old_AB <<= 2;
old_AB |= ((digitalRead(EncBpin))?(1<<1):0) | ((digitalRead(EncApin))?(1<<0):0);
return ( enc_states[( old_AB & 0x0f )]);
}