3

I am trying to make a small keyboard class to handle two buttons(in the future >2) that are connected to my arduino UNO. The buttons being pressed are detected using interrupts. Here is the code:

Timer

class Timer{
  private:
    uint32_t start_time;
  public:
    Timer(){
      start_time=millis();
    }
    void mark(){
      start_time=millis();
    }
    uint32_t lapsed(){
      return millis()-start_time;
    }
};

Keyboard

class KeyboardBtn{
  private:
    const static byte clicksDelay=255;      //255 ms max
    struct btn{
      byte state=0;   //0->nothing;1-click;2-dblClick
      Timer clickDelay;
    };
    volatile static btn buttons[2];         //only two buttons for now

  public:
    KeyboardBtn(){
      attachInterrupt(digitalPinToInterrupt(2),this->int_handler_btn0,FALLING);       //Initially the pins are set to HIGH(pullup behaviour)
      attachInterrupt(digitalPinToInterrupt(3),this->int_handler_btn1,FALLING);
    }

    static void int_handler_btn0(){
      btns_handler(0);
    }
    static void int_handler_btn1(){
      btns_handler(1);
    }
    static void btns_handler(byte key){
        if(buttons[key].state==1 && buttons[key].clickDelay.lapsed()<=clicksDelay){
          buttons[key].state=2;
        }else{
          buttons[key].state=1;
          buttons[key].clickDelay.mark(); //Pressed one time? mark this and wait for second press
        }
    }
    byte stateChanged(byte key){
      //Function called to get key status
      byte temp_state=buttons[key].state;
      if(temp_state==1 && buttons[key].clickDelay.lapsed()<clicksDelay){
        return 0; //We still wait:don't know if it's a dblClick or single
      }else{
        buttons[key].state=0;
        return temp_state;
      }
    }
};
volatile KeyboardBtn::btn KeyboardBtn::buttons[2];

But the compiler gives me headaches(of course my code is wrong somewhere but he could just have kept quite about it):

C:\Users....\Humidity.ino: In static member function 'static void KeyboardBtn::btns_handler(byte)':

C:\Users...\Humidity\Humidity.ino:74:68: warning: passing 'volatile Timer' as 'this' argument of 'uint32_t Timer::lapsed()' discards qualifiers [-fpermissive]

     if(buttons[key].state==1 && buttons[key].clickDelay.lapsed()<=clicksDelay){

                                                                ^

C:\Users...\Humidity\Humidity.ino:78:40: warning: passing 'volatile Timer' as 'this' argument of 'void Timer::mark()' discards qualifiers [-fpermissive]

       buttons[key].clickDelay.mark();

                                    ^

C:\Users....\Humidity\Humidity.ino: In member function 'byte KeyboardBtn::stateChanged(byte)':

C:\Users....\Humidity\Humidity.ino:83:58: warning: passing 'volatile Timer' as 'this' argument of 'uint32_t Timer::lapsed()' discards qualifiers [-fpermissive]

   if(temp_state==1 && buttons[key].clickDelay.lapsed()<clicksDelay){

                                                      ^

What is the problem? Note:It does allow me to upload the code but I am almost certain it will generate some errors while running...

3

If you want to use an instantiated object as volatile then the functions within it also have to be marked as volatile. That tells the compiler that the instance pointer you will be passing to the function (the auto-inserted this parameter) is volatile:

class Timer{
  private:
    uint32_t start_time;
  public:
    Timer(){
      start_time=millis();
    }
    void mark() volatile {
      start_time=millis();
    }
    uint32_t lapsed() volatile { 
      return millis()-start_time;
    }
};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.