// to UPLOAD: connect DFU withl 3,3 Volt PIN -> hit the "ON" key after power-up (once)!

#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

bool hasKeyPressed = false;

#define hp48_AR17 SCK
#define hp48_A16 MOSI 
#define hp48_A15 MISO
#define hp48_A14 15
#define hp48_A13 7
#define hp48_A12 11
#define hp48_A11 27
#define hp48_A10 25  //SDA
#define hp48_A9 26   //SCL

//inputs: 
//hp48_A0-A5 und ON 
#define hp48_A0 16 //A0 was not working with my (damaged) keyboard
#define hp48_ON 20 //PIN_DFU
  


// variables for loop measuring:

unsigned long time;
unsigned long time2 = 0;


bool left = false;
bool left2 = false;
bool right = false;
bool right2 = false;
uint8_t keycode[6]= { HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE};
uint8_t keycode2[6]= { HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE};
bool keyused[6]= { false, false, false, false, false, false};
int news;
byte charcount = 40;
byte alphaseq = 0;


//debugging
#define serial_each_key true
#define enter_chs_eex true

void setup() 
{
  Serial.begin(1000000);
  while ( !Serial ) delay(1);   // for nrf52840 with native usb

  Serial.println("bluetooth48G keyboard");
  Serial.println("-2019-07-Rel05--mike-");
  Serial.println("Hit a key:");
  Serial.println();  

  Bluefruit.begin();
  Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values
  Bluefruit.setName("bluetooth48G");

  // Configure and Start Device Information Service
  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit Feather 52");
  bledis.begin();

  /* Start BLE HID
   * Note: Apple requires BLE device must have min connection interval >= 20m
   * ( The smaller the connection interval the faster we could send data).
   * However for HID and MIDI device, Apple could accept min connection interval 
   * up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
   * connection interval to 11.25  ms and 15 ms respectively for best performance.
   */
  blehid.begin();

  // Set callback for set LED from central
  blehid.setKeyboardLedCallback(set_keyboard_led);

  /* Set connection interval (min, max) to your perferred value.
   * Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
   * min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms 
   */
  /* Bluefruit.Periph.setConnInterval(9, 12); */

  // Set up and start advertising
  startAdv();
}

void startAdv(void)
{  
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
  
  // Include BLE HID service
  Bluefruit.Advertising.addService(blehid);

  // There is enough room for the dev name in the advertising packet
  Bluefruit.Advertising.addName();
  
  /* Start Advertising
   * - Enable auto advertising if disconnected
   * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   * 
   * For recommended advertising interval
   * https://developer.apple.com/library/content/qa/qa1931/_index.html   
   */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds


  digitalWrite(hp48_AR17,LOW);
  digitalWrite(hp48_A16,LOW);
  digitalWrite(hp48_A15,LOW);
  digitalWrite(hp48_A14,LOW);
  digitalWrite(hp48_A13,LOW);
  digitalWrite(hp48_A12,LOW);
  digitalWrite(hp48_A11,LOW);
  digitalWrite(hp48_A10,LOW);
  digitalWrite(hp48_A9,LOW);

}

void loop() 
{
     left = false;
     right = false;
     if (digitalRead(hp48_ON) == HIGH) 
     {
      if (serial_each_key) Serial.print("ON");
      list_6(41); //41=ON (ESC)
     };

    pinMode(hp48_AR17,OUTPUT);
    digitalWrite(hp48_AR17,HIGH); // AR17: 5keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-F 
    {
      if (serial_each_key) Serial.print("F ");
      list_6(HID_KEY_F);
    };
    if (digitalRead(A1))                      //hp48-E 
    {
      if (serial_each_key) Serial.print("E ");
      list_6(HID_KEY_E);
    };
    if (digitalRead(A2))                      //hp48-D 
    {
      if (serial_each_key) Serial.print("D ");
      list_6(HID_KEY_D);
    };
    if (digitalRead(A3))                      //hp48-C
    {
      if (serial_each_key) Serial.print("C ");
      list_6(HID_KEY_C);
    };
    if (digitalRead(A4))                      //hp48-B
    {
      if (serial_each_key) Serial.print("B ");
      list_6(HID_KEY_B);
    };
    digitalWrite(hp48_AR17,LOW);
    pinMode(hp48_AR17,INPUT);


    
    pinMode(hp48_A16,OUTPUT);
    digitalWrite(hp48_A16,HIGH); // A16: 5keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-L 
    {
      if (serial_each_key) Serial.print("L ");
      list_6(HID_KEY_L);
    };
    if (digitalRead(A1))                      //hp48-K 
    {
      if (serial_each_key) Serial.print("K ");
      list_6(HID_KEY_K);
    };
    if (digitalRead(A2))                      //hp48-J 
    {
      if (serial_each_key) Serial.print("J ");
      list_6(HID_KEY_J);
    };
    if (digitalRead(A3))                      //hp48-I
    {
      if (serial_each_key) Serial.print("I ");
      list_6(HID_KEY_I);
    };
    if (digitalRead(A4))                      //hp48-H
    {
      if (serial_each_key) Serial.print("H ");
      list_6(HID_KEY_H);
    };
    digitalWrite(hp48_A16,LOW);
    pinMode(hp48_A16,INPUT);

    
    pinMode(hp48_A15,OUTPUT);
    digitalWrite(hp48_A15,HIGH); // A15: 5keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-R 
    {
      if (serial_each_key) Serial.print("R ");
      list_6(HID_KEY_R);
    };
    if (digitalRead(A1))                      //hp48-Q 
    {
      if (serial_each_key) Serial.print("Q ");
      list_6(HID_KEY_Q);
    };
    if (digitalRead(A2))                      //hp48-P 
    {
      if (serial_each_key) Serial.print("P ");
      list_6(HID_KEY_P);
    };
    if (digitalRead(A3))                      //hp48-O
    {
      if (serial_each_key) Serial.print("O ");
      list_6(HID_KEY_O);
    };
    if (digitalRead(A4))                      //hp48-N
    {
      if (serial_each_key) Serial.print("N ");
      list_6(HID_KEY_N);
    };
    digitalWrite(hp48_A15,LOW);
    pinMode(hp48_A15,INPUT);


    
    pinMode(hp48_A14,OUTPUT);
    digitalWrite(hp48_A14,HIGH); // A14: 5keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-X
    {
      if (serial_each_key) Serial.print("X ");
      list_6(HID_KEY_X);
    };
    if (digitalRead(A1))                      //hp48-W 
    {
      if (serial_each_key) Serial.print("W ");
      list_6(HID_KEY_W);
    };
    if (enter_chs_eex==false)
    {    
      if (digitalRead(A2))                      //hp48-V 
      {
        if (serial_each_key) Serial.print("V ");
        list_6(HID_KEY_V);
      };
      if (digitalRead(A3))                      //hp48-U
      {
        if (serial_each_key) Serial.print("U ");
        list_6(HID_KEY_U);
      };
      if (digitalRead(A4))                      //hp48-T
      {
        if (serial_each_key) Serial.print("T ");
        list_6(HID_KEY_T);
      };
    }
    else
    {
      if (digitalRead(A2))                      //hp48-V
      {
        if (serial_each_key) Serial.print("down ");
        list_6(charcount);
        Serial.print(charcount);
        Serial.println("__");
        charcount--;
        delay(200);
      };
      if (digitalRead(A3))                      //hp48-U
      {
        if (serial_each_key) Serial.print("now ");
        //list_6(HID_KEY_Y);
        list_6(charcount); // 42=BACK 41=ESC 43=TABULATOR   85=MULTI 86=MINUS 87=PLUS 55=PUNKT
        Serial.print(charcount);
        Serial.println("__");
        delay(200);
      };
      if (digitalRead(A4))                      //hp48-T
      {
        if (serial_each_key) Serial.print("up ");
        list_6(charcount); //22=S
        Serial.print(charcount);
        Serial.println("__");
        charcount++;
        delay(200);
      };
    };    
    digitalWrite(hp48_A14,LOW);
    pinMode(hp48_A14,INPUT);


    
    pinMode(hp48_A13,OUTPUT);
    digitalWrite(hp48_A13,HIGH); // A13: 5keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-BACKSPACE
    {
      if (serial_each_key) Serial.print("back ");
      list_6(42); //42=back
    };
    if (digitalRead(A1))                      //hp48-del
    {
      if (serial_each_key) Serial.print("del ");
      list_6(76); //53=del_PC 76=del_android
    };
    if (digitalRead(A2))                      //hp48-Z 
    {
      if (serial_each_key) Serial.print("Z ");
      list_6(HID_KEY_Z);
    };
    if (digitalRead(A3))                      //hp48-Y
    {
      if (serial_each_key) Serial.print("Y ");
      list_6(HID_KEY_Y);
    };
    if (digitalRead(A4))                      //hp48-enter
    {
      if (serial_each_key) Serial.print("enter ");
      list_6(40); //40=enter
    };
    digitalWrite(hp48_A13,LOW);
    pinMode(hp48_A13,INPUT);


    
    pinMode(hp48_A12,OUTPUT);
    digitalWrite(hp48_A12,HIGH); // A12: 6keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-div
    {
      if (serial_each_key) Serial.print("div ");
      list_6(84); //84=div
    };
    if (digitalRead(A1))                      //hp48-9 
    {
      if (serial_each_key) Serial.print("9 ");
      list_6(HID_KEY_9);
    };
    if (digitalRead(A2))                      //hp48-8 
    {
      if (serial_each_key) Serial.print("8 ");
      list_6(HID_KEY_8);
    };
    if (digitalRead(A3))                      //hp48-7
    {
      if (serial_each_key) Serial.print("7 ");
      list_6(HID_KEY_7);
    };
    if (digitalRead(A4))                      //hp48-S
    {
      if (serial_each_key) Serial.print("S ");
      list_6(HID_KEY_S);
    };
    if (digitalRead(A5))                      //hp48-alpha
    {
      if (serial_each_key) Serial.print("alpha ");
     list_6(43); //43=alpha (TAB)
    } 
    else
    {
      if (alphaseq == 5) alphaseq = 10;
    }
    digitalWrite(hp48_A12,LOW);
    pinMode(hp48_A12,INPUT);



    pinMode(hp48_A11,OUTPUT);
    digitalWrite(hp48_A11,HIGH); // A11: 6keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-mul
    {
      if (serial_each_key) Serial.print("mul ");
      list_6(85); //85=mul
    };
    if (digitalRead(A1))                      //hp48-6 
    {
      if (serial_each_key) Serial.print("6 ");
      list_6(HID_KEY_6);
    };
    if (digitalRead(A2))                      //hp48-5 
    {
      if (serial_each_key) Serial.print("5 ");
      list_6(HID_KEY_5);
    };
    if (digitalRead(A3))                      //hp48-4
    {
      if (serial_each_key) Serial.print("4 ");
      list_6(HID_KEY_4);
    };
    if (digitalRead(A4))                      //hp48-G
    {
      if (serial_each_key) Serial.print("G ");
      list_6(HID_KEY_G);
    };
    if (digitalRead(A5))                      //hp48-ls
    {
      if (serial_each_key) Serial.print("ls ");
      left = true;
    };
    digitalWrite(hp48_A11,LOW);
    pinMode(hp48_A11,INPUT);


    
    pinMode(hp48_A10,OUTPUT);
    digitalWrite(hp48_A10,HIGH); // A10: 6keys
    delay(1);
    if (digitalRead(hp48_A0))                      //hp48-minus
    {
      if (serial_each_key) Serial.print("minus ");
      list_6(86); //86=minus
    };
    if (digitalRead(A1))                      //hp48-3 
    {
      if (serial_each_key) Serial.print("3 ");
      list_6(HID_KEY_3);
    };
    if (digitalRead(A2))                      //hp48-2 
    {
      if (serial_each_key) Serial.print("2 ");
      list_6(HID_KEY_2);
    };
    if (digitalRead(A3))                      //hp48-1
    {
      if (serial_each_key) Serial.print("1 ");
      list_6(HID_KEY_1);
    };
    if (digitalRead(A4))                      //hp48-A
    {
      if (serial_each_key) Serial.print("A ");
      list_6(HID_KEY_A);
    };
    if (digitalRead(A5))                      //hp48-rs
    {
      if (serial_each_key) Serial.print("rs ");
      right = true;
    };
    digitalWrite(hp48_A10,LOW);
    pinMode(hp48_A10,INPUT);


    
    pinMode(hp48_A9,OUTPUT);
    digitalWrite(hp48_A9,HIGH); // A9: 5keys
    delay(1);
    if (digitalRead(hp48_A0) )                      //hp48-plus
    {
      if (serial_each_key) Serial.print("plus ");
      list_6(87); //87=plus
    };
    if (digitalRead(A1))                      //hp48-spc 
    {
      if (serial_each_key) Serial.print("spc ");
      list_6(44); //44=spc
    };
    if (digitalRead(A2))                      //hp48-dot 
    {
      if (serial_each_key) Serial.print("dot ");
      list_6(55); //55=dot
    };
    if (digitalRead(A3))                      //hp48-0 (zero)
    {
      if (serial_each_key) Serial.print("0zero ");
      list_6(HID_KEY_0);
    };
    if (digitalRead(A4))                      //hp48-M
    {
      if (serial_each_key) Serial.print("M ");
      list_6(HID_KEY_M);
    };
    digitalWrite(hp48_A9,LOW);
    pinMode(hp48_A9,INPUT);
    
}

void list_6(uint8_t HID_CODE)
{
   for (int x = 0; x < 6; x++)
   {
     if (keycode[x]==HID_KEY_NONE)
     {
       keycode[x]=HID_CODE;
       x=6;
       break;
     };
     if (keycode[x]==HID_CODE) break;
   };
}


void update_6()
{
   keyused[0]=false;
   keyused[1]=false;
   keyused[2]=false;
   keyused[3]=false;
   keyused[4]=false;
   keyused[5]=false;
   int n2 = 0;
   news= -1;
   do
   {
     if (keycode2[n2]==HID_KEY_NONE) //no key
     {
       for (int xxx = 0; xxx < 6; xxx++)
       {
         if (keyused[xxx]==false)
         {
           Serial.print("N"); 
           news++;
           keycode2[n2]=keycode[xxx];
           keyused[xxx]=true;
           if (keycode2[n2]==HID_KEY_NONE) n2=6; //no key
           break;
         };
       };
     }
     else // keycode2[n2] <> HID_KEY_NONE
     {
       if (keycode2[n2]==keycode[0]) keyused[0]=true;
       if (keycode2[n2]==keycode[1]) keyused[1]=true;
       if (keycode2[n2]==keycode[2]) keyused[2]=true;
       if (keycode2[n2]==keycode[3]) keyused[3]=true;
       if (keycode2[n2]==keycode[4]) keyused[4]=true;
       if (keycode2[n2]==keycode[5]) keyused[5]=true;
       if ((keycode2[n2]==keycode[0]) || (keycode2[n2]==keycode[1]) || (keycode2[n2]==keycode[2]) || (keycode2[n2]==keycode[3]) || (keycode2[n2]==keycode[4]) ||(keycode2[n2]==keycode[5])) 
       {
        Serial.print("v");
       }
       else
       {
        news++;
        Serial.print("c"); 
         for (int xx = n2; xx < 5; xx++)
         {
           keycode2[xx]=keycode2[xx+1];
         };
         keycode2[5]=HID_KEY_NONE;
         keyused[5]=false;
         n2--;
       };
     };
     n2++;
   } while (n2<6);
   Serial.print(news);
   Serial.print("    ");

   if (left2 != left)
   {
     left2 = left;
     news++;
   };
   if (right2 != right)
   {
     right2 = right;
     news++;
   };

   if (news>0) 
   {
     //modifier = KEYBOARD_MODIFIER_LEFTSHIFT; //left
     //modifier = KEYBOARD_MODIFIER_LEFTCTRL; // right
     if (left2 && right2) blehid.keyboardReport(KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_LEFTSHIFT, keycode2);
     else 
     {
       if (left2) blehid.keyboardReport(KEYBOARD_MODIFIER_LEFTSHIFT, keycode2);
       else if (right2) blehid.keyboardReport(KEYBOARD_MODIFIER_LEFTCTRL,keycode2);
       else  blehid.keyboardReport(0, keycode2);
     };

   };

}
/**
 * Callback invoked when received Set LED from central.
 * Must be set previously with setKeyboardLedCallback()
 *
 * The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
 *    Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
 */
void set_keyboard_led(uint16_t conn_handle, uint8_t led_bitmap)
{
  (void) conn_handle;
  
  // light up Red Led if any bits is set
  if ( led_bitmap )
  {
    ledOn( LED_RED );
  }
  else
  {
    ledOff( LED_RED );
  }
}
