Get value from protected member of class

Hi, i'm really new to Arduino.
I have Arduino Mega, a USB host shield and a barcode scanner. I'm using this library >> link and modified it example so barcode scanner worked (Got it from here) to read what barcode scanner scanned and it worked just fine.

#include <usbhid.h>
#include <usbhub.h>
#include <hiduniversal.h>
#include <hidboot.h>
#include <SPI.h>

class MyParser : public HIDReportParser {
  public:
    MyParser();
    void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
  protected:
    uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key);
    virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key);
    virtual void OnScanFinished();
};

MyParser::MyParser() {}

void MyParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
  // If error or empty, return
  if (buf[2] == 1 || buf[2] == 0) return;

  for (uint8_t i = 7; i >= 2; i--) {
    // If empty, skip
    if (buf[i] == 0) continue;

    // If enter signal emitted, scan finished
    if (buf[i] == UHS_HID_BOOT_KEY_ENTER) {
      OnScanFinished();
    }

    // If not, continue normally
    else {
      // If bit position not in 2, it's uppercase words
      OnKeyScanned(i > 2, buf, buf[i]);
    }

    return;
  }
}

uint8_t MyParser::KeyToAscii(bool upper, uint8_t mod, uint8_t key) {
  // Letters
  if (VALUE_WITHIN(key, 0x04, 0x1d)) {
    if (upper) return (key - 4 + 'A');
    else return (key - 4 + 'a');
  }

  // Numbers
  else if (VALUE_WITHIN(key, 0x1e, 0x27)) {
    return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');
  }

  return 0;
}

void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) {
  uint8_t ascii = KeyToAscii(upper, mod, key);
  Serial.print((char)ascii);
}

void MyParser::OnScanFinished() {
  Serial.println(" - Finished");
}

USB          Usb;
USBHub       Hub(&Usb);
HIDUniversal Hid(&Usb);
MyParser     Parser;

void setup() {
  Serial.begin( 115200 );
  Serial.println("Start");

  if (Usb.Init() == -1) {
    Serial.println("OSC did not start.");
  }

  delay( 200 );

  Hid.SetReportParser(0, &Parser);
}

void loop() {
  Usb.Task();
}

So, I want to get the value from (char)ascii, store to char on loop and run it.

void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) {
  uint8_t ascii = KeyToAscii(upper, mod, key);
  Serial.print((char)ascii);
}

I've trying to get the value with itoa, store it to char array and still no luck. I've been stuck for days.

Any help would be appreciated.
Thank you.

Add a public function that returns the value

Hi @UKHeliBob, i tried it but still no luck. I tried this:

uint8_t MyParser::getValue() {
  uint8_t getAscii;
  bool upper; uint8_t mod; uint8_t key;
  getAscii = KeyToAscii(upper, mod, key);
  return getAscii;
}

and called it in loop:

void loop() {
  Usb.Task();
  uint8_t abcd = Parser.getValue();
  char c = (char)abcd;
  Serial.print(c);
}

Is there something wrong with my code? Thank you.

Is there something wrong with my code?

That is for you to tell us. Are there errors? Post the entire text of the error. The code does not do what you want? Explain what the code actually does and how that differs from what you want.

class MyParser : public HIDReportParser {
  private:
    bool keyReady;
    uint8_t scannedKey;
  public:
    MyParser();
    void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
    bool GetKey(uint8_t&);
  protected:
    uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key);
    virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key);
    virtual void OnScanFinished();
};

void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) {
  scannedKey= KeyToAscii(upper, mod, key);
  keyReady = true;
}

//Return status indicating if there's a key available
//If not, the paremeterized value is undefined
bool MyParser::GetKey(uint8_t &key)
{
  if (keyReady) {
    key = scannedKey;
    keyReady = false;
    return true;
  }
  return false;
}

Basically, you want to create two members variables, one to keep track if there's a key has been scanned; the other one is the key itself.
The GetKey() will return true if there's a key; and the key is copied to the argument.

void loop()
{
   ...
   uint8_t key;
   if (Parser.GetKey(key)) {
      //use "key" here
   }
   ...
}

Or you can also doing this via callback interface.

class MyParser : public HIDReportParser {
    using m_cb = void (*)(uint8_t);
  private:
    m_cb action;
  public:
    MyParser(m_cb  act);
    void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
  protected:
    uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key);
    virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key);
    virtual void OnScanFinished();
};

MyParser::MyParser(m_cb  act) : action(act)
{
}

void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) 
{
  uint8_t ascii = KeyToAscii(upper, mod, key);
  action(ascii); //invoke callback
}

.ino

void OnKeyScanned(uint8_t key)
{
   Serial.println(key);
}
MyParser     Parser(OnKeyScanned);
void loop()
{
   ...
   ...
}

Hi @groundFungus thanks for replied. There are no errors but does not appear on loop.

Wow Thanks @arduino_new it worked like a charm. Thank you!

Noted!

arduino_new:
Basically, you want to create two members variables, one to keep track if there's a key has been scanned; the other one is the key itself.
The GetKey() will return true if there's a key; and the key is copied to the argument.