Author Topic: About DigiKeyboard  (Read 9966 times)

mkHeinzen

  • Newbie
  • *
  • Posts: 8
About DigiKeyboard
« on: June 28, 2015, 01:39:44 am »
Is it possible to have something to hold/persist the keyboard input generated by DigiKeyboard?

The behavior I get from:

Code: [Select]
  while(btnState == HIGH)
  {
    digitalWrite(LED1, LOW);
    DigiKeyboard.sendKeyStroke(4);
  }
  digitalWrite(LED1, HIGH);

or

Code: [Select]
  if(btnState == HIGH)
  {
    digitalWrite(LED1, LOW);
    DigiKeyboard.sendKeyStroke(4);
  }
  else digitalWrite(LED1, HIGH);

Is essentially the same. Obviously this way implies that it checks once for the input, sends the keystroke, loops again.

But is there anyhow to make this input being async (not sure if interruptions work in this case, but I am assuming they don't) to everything else and/or make the input persist instead of sending a LOT of inputs per second?

mkHeinzen

  • Newbie
  • *
  • Posts: 8
Re: About DigiKeyboard
« Reply #1 on: June 28, 2015, 11:22:03 am »
I found out that Arduino Leonardo has a lib that supports this feature (Keyboard.h), though I can't get to use it's functions in DigiSpark. Is it possible to rewrite these or import the lib to work in DigiSpark?

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: About DigiKeyboard
« Reply #2 on: June 29, 2015, 10:26:27 pm »
You could use a timer to send it (some posts on here about how to use the timers) - I imagine that is what the leonardo library does

mkHeinzen

  • Newbie
  • *
  • Posts: 8
Re: About DigiKeyboard
« Reply #3 on: July 02, 2015, 06:24:35 am »
You could use a timer to send it (some posts on here about how to use the timers) - I imagine that is what the leonardo library does

Thanks for the reply. I can't really see how the timer would do this. I thought I would have to write a blocking function until the input was changed again.

I will give it a try and post results back.

Edit: Apparently I found the respective code. I can't see anything that wouldn't allow me to rewrite it to DigiSpark. Can someone double check and see if there's anything that would restrict me in doing this?

Code: [Select]
size_t Keyboard_::press(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1<<(k-128));
k = 0;
} else { // it's a printing key
k = _asciimap[k];
if (!k) {
setWriteError();
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
}

// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {

for (i=0; i<6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
}
}
sendReport(&_keyReport);
return 1;
}


Edit2: Does DigiSpark use the default Arduino HID library? Wiki says nothing on this.

If so, I could just use this, right?
« Last Edit: July 02, 2015, 10:09:04 am by mkHeinzen »

mkHeinzen

  • Newbie
  • *
  • Posts: 8
Re: About DigiKeyboard
« Reply #4 on: July 03, 2015, 06:34:20 am »
Hi,

I am not sure if I understood the problem, but if you want to send only ONE "a" when the button is pressed and stays pressed, and want the next "a" sent only after the button is released and pressed again, you only need a variable which remembers the button state.

But you have to append a DigiKeyboard.sendKeyStroke(0) after the DigiKeyboard.sendKeyStroke(4), otherwise the PC keyboard driver will handle the keystroke(4) with autorepeat, producing a row of "a's" by itself  (proof: the row of "a's" even does not stop if you remove the DigiSpark).

Code: [Select]
#include <DigiKeyboard.h>

char PIN_BUTTON = 0;
char ButtonPressed = 0;

void setup()
{
    // button pin as inputs
    pinMode(PIN_BUTTON, INPUT);
    // activate internal pull-up resistor
    digitalWrite(PIN_BUTTON, HIGH);
}

void loop()
{
    DigiKeyboard.sendKeyStroke(0);

    if (digitalRead(PIN_BUTTON) == LOW)
    {
        if (ButtonPressed ==0)
        {
            // send "a"
            DigiKeyboard.sendKeyStroke(4);
            // send  "Stop last Keystroke", otherwise the PC keyboard driver
            // produces a row of "a's"
            DigiKeyboard.sendKeyStroke(0);
             // only one "a" until Button is released
            ButtonPressed = 1;
        }
    }

       if (digitalRead(PIN_BUTTON) == HIGH)
        // Button released
        {
        ButtonPressed = 0;
        }
}

Thanks for the reply. This seems to be easier than I thought it would be. Maybe I just didn't know what sendKeyStroke(0) is, after all :P

I will give it a go whenever I get home later today!


Edit: Now that I am taking a look at it again, I think this is going to send one 'a', then send nothing while the button is pressed, is that correct? If so that's not the behavior I am expecting.

I need something like Keyboard.press('A') while the button is pushed and then Keyboard.release() when it goes HIGH (as seen in Leonardo-compatible boards).

Which, in other words, would be a persistent signal instead of a single input and the idle
« Last Edit: July 03, 2015, 09:45:45 am by mkHeinzen »

mkHeinzen

  • Newbie
  • *
  • Posts: 8
Re: About DigiKeyboard
« Reply #5 on: July 03, 2015, 01:34:55 pm »
Quote
Edit: Now that I am taking a look at it again, I think this is going to send one 'a', then send nothing while the button is pressed, is that correct? If so that's not the behavior I am expecting.

Yeah, that's correct.

I think (but I'm not 100% sure, to be honest) the Arduino Leonardo Keyboard does more or less the same, but the names are different.

DigiKeyboard.sendKeyStroke(4) sends an "a" and the PC keyboard driver autorepeats it, untl you send DigiKeyboard.sendKeyStroke(0).  You may also send a modifier, like digiKeyboard.sendKeyStroke(4,MOD_SHIFT_LEFT) to get an "A".

 I do not fully understand HID.cpp of the Arduino Core, but  to me it seems that the main difference is that you send the key and the modifier in two commands, while it's one command when using DigiKeyboard.h.


Ralf


I just tried it out and it indeed sends a single input and one sends another one when the button is released. Still not the hold effect :(

mkHeinzen

  • Newbie
  • *
  • Posts: 8
Re: About DigiKeyboard
« Reply #6 on: July 04, 2015, 09:58:27 am »
Quote
Still not the hold effect :(

Perhaps DigiKeyboard is the wrong tool. There's a saying "When you only have a hammer, every problem looks like a nail", but it's a bit difficult to cut a rope with a hammer ;)

Ralf

Well, I read somewhere in the forums digistump saying that this feature is possible to implement. I made a thread in the project ideas to get some help implementing that. I just don't know a lot about V-USB, thus I won't know how to write it all by myself :(

Thanks for your help anyway