Sending modifiers (KEY_LEFT_CTRL) + keystroke in an array? Also keyboard repeat.

Hello there, newbie here.

I currently have this code which works to debounce a set of simple push buttons so when pressed they simply send keystronkes (a, b, c, etc respectively)

I have two questions

• I was shown this method of setting button output which works really well for a 3rd party program I’m writing to configure the buttons. The problem is I don’t know how to send key modifiers (like adding ctrl to ‘z’ to perform an undo command) with the way it currently is. I know the arduino modifier is KEY_LEFT_CTRL. Say I wanted to change the button below that delivers ‘A’ to act as ctrl+z instead. I am looking to swap out {0, sw0, ‘A’} for something like {0, sw0, KEY_LEFT_CTRL + ‘z’} (which doesn’t work obviously) to make this happen in order to keep this array format in tact for easy configuring. Is this possible? I looked for a way to inject the hex even like 0x80+z but that was also a no go.

• The current method delivers one keystroke per press but stops output even if you hold the button down. I’d like to change it to act like a keyboard (press and hold delivers one keystroke, waits a second, then starts repeating the keystroke until you let go.) I don’t know where to begin with that.

Any help would be awesome and appreciated, thanks!

enum { sw0=3, sw1=4, sw2=5, sw3=6, sw4=7, sw5=8, sw6=9, sw7=10}; // Switchbutton lines
enum { nSwitches=8, bounceMillis=42}; // # of switches; debounce delay
struct ButtonStruct {
  unsigned long int bounceEnd;  // Debouncing-flag and end-time
  // Switch number, press-action, release-action, and prev reading
  byte swiNum, swiActP, swiActR, swiPrev;
};

struct ButtonStruct buttons[nSwitches] = {
  {0, sw0, 'A'}, 
  {0, sw1, 'B'}, 
  {0, sw2, 'C'}, 
  {0, sw3, 'D'},
  {0, sw4, 'E'},
  {0, sw5, 'F'},
  {0, sw6, 'G'},
  {0, sw7, 'H'}};
//--------------------------------------------------------
void setup() {
  for (int i=0; i<nSwitches; ++i)
    pinMode(buttons[i].swiNum, INPUT_PULLUP);
Keyboard.begin();
}
//--------------------------------------------------------
byte readSwitch (byte swiNum) {
  // Following inverts the pin reading (assumes pulldown = pressed)
  return 1 - digitalRead(swiNum);
}
//--------------------------------------------------------
void doAction(byte swin, char code, char action) {
  Keyboard.write(action);
}
//--------------------------------------------------------
void doButton(byte bn) {
  struct ButtonStruct *b = buttons + bn;
  if (b->bounceEnd) { // Was button changing?
    // It was changing, see if debounce time is done.
      if (b->bounceEnd < millis()) {
    b->bounceEnd = 0;    // Debounce time is done, so clear flag
    // See if the change was real, or a glitch
    if (readSwitch(b->swiNum) == b->swiPrev) {
      // Current reading is same as trigger reading, so do it
      if (b->swiPrev) {
        doAction(b->swiNum, 'P', b->swiActP);
      } else {
        doAction(b->swiNum, 'R', b->swiActR);
      }
    }
      }
  } else {  // It wasn't changing; but see if it's changing now
    if (b->swiPrev != readSwitch(b->swiNum)) {
      b->swiPrev = readSwitch(b->swiNum);
      b->bounceEnd = millis()+bounceMillis; // Set the Debounce flag
    }
  }
}
//--------------------------------------------------------
long int seconds, prevSec=0;
void loop() {
  for (int i=0; i<nSwitches; ++i)
    doButton(i);
}

It sounds like in some cases you want to send one key and in other cases you want to send more than one key. That is going to require a change in the struct that defines what to do AND in the function(s) that actually send the keystroke(s).

doAction() is a stupid name for a function. You might as well call it f18327() for all the information we can discern about what the function actually does.

doButton() isn't any better.

The press/release concept works for the modifying keys just like for the normal keys.

So to see a Ctrl-A on the receiving side you have to send Ctrl-press, A-press, A-release, Ctrl-release.
Same for the other modifying keys like l/r-shift, l/r-control, l/r-alt.

You could make the fields in the structure longer (wasting a lot of space),
you could use pointers to keysequences/lists in the structure,
or handle the modifying keys seperate from the normal keys,
building some current-shift-state.

Whandall:
The press/release concept works for the modifying keys just like for the normal keys.

So to see a Ctrl-A on the receiving side you have to send Ctrl-press, A-press, A-release, Ctrl-release.
Same for the other modifying keys like l/r-shift, l/r-control, l/r-alt.

You could make the fields in the structure longer (wasting a lot of space),
you could use pointers to keysequences/lists in the structure,
or handle the modifying keys seperate from the normal keys,
building some current-shift-state.

So I understand the fields of the current struct, what is the syntax to put a ctrl+z in its current state? From my newbie understanding I thought I'd have to declare another byte action, another doAction below the else doAction, and maybe something like

{0, sw0, Keyboard.press(ctrlKey),Keyboard.press('z'),delay(100),Keyboard.release(ctrlKey),Keyboard.release('z')}

but that's probably way off? I'm pretty new to structuring stuff properly.

The pointers to a keystroke sequence also sounds promising but again I'm having trouble finding syntax online, something like KEY_LEFT_CTRL->z; or declaring that inside a single char variable or something? My apologies, pretty new to this level of arduino~

So I understand the fields of the current struct, what is the syntax to put a ctrl+z in its current state?

Your question reads like "Which ONE key do I press to get the combination of Ctrl and Z". I think that the answer to that it pretty obvious.

PaulS:
Your question reads like "Which ONE key do I press to get the combination of Ctrl and Z". I think that the answer to that it pretty obvious.

I don't understand this response. My question is not "what ONE key do I press to get the combination of ctrl and z." My question is what code in the place of {0, sw0, 'A'} will deliver a ctrl-z keystroke instead of an A, which is not at all obvious to me because I'm new at this, can't find it online, and can't seem to get an answer on if it's even possible. The closest I can think is using the hex value of ctrl-z in the place of 'A' found here http://www.nthelp.com/ascii.htm but that isn't getting me anywhere.

There is no single key that represents Ctrl-Z.

To see a Ctrl-Z on the receiving side, you have to send 4 keys, in the following order.

Ctrl(R/L)-down, Z-down, Z-up, Ctrl(R/L)-up.