/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*          SSS                                                              */
/*         SSSSS                                                             */
/*    SSSSSS SSSS                                                            */
/*     SSSSSSSSS                                                             */
/*          SSSS                                       ___   ___             */
/*          SSS         -----------------------       /   \ /   \            */
/*         SSSA        | R o b o D u c k _ B T |     (  -  x  +  )           */
/*        SSSSSSN       -----------------------       \___/ \___/            */
/*        SSSSSSSN                                      ARDUINO              */
/*       SSSSSSSSSSSA                                                        */
/*       SSSSSSSSSSSSSSSSSSS                                                 */
/*        SSSSSSSSSSSSSSSSS                                                  */
/*          SSSSSSSSSSS                                                      */
/*              S S                                                          */
/*            SSSSS                                                          */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*------------------------- [c]2020 - D. Ottensmeyer ------------------------*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~
 ~ Target:    Arduino NANO with RoboDuck (created by the "Fakultät für Physik
 ~            der Universität Regensburg", Germany, in 2019).
 ~            Link: http://www.physik.uni-regensburg.de/rsl/roboduck.html
 ~            With Bluetooth module HC-05 or HC-06 connected to RoboDuck
 ~            and with an Android Bluetooth Control app.
 ~ Library:   RoboDuck_BT Source
 ~ Version:   0.90
 ~ Author(s): D. Ottensmeyer
 ~
 ~ Description:
 ~ This is our new Library that contains basic routines and functions for
 ~ accessing the HC-05 or HC-06 Bluetooth module connected to RoboDuck.
 */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// RoboDuck additional component:
// - Bluetooth module HC-05 or HC-06

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Includes:
#include "RoboDuck_BT.h"
#include <NeoSWSerial.h>

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Constants:
#define KEY_DELAY 500

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Variables:

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Bluetooth module HC-05 or HC-06:
// Bluetooth module setup:
/*~
 ~ Assigns Arduino Nano ports to the
 ~ Bluetooth module.
 ~
 ~   PD6 -> Arduino RX
 ~   PD7 -> Arduino TX
 ~
 ~ Hint: Be sure that the module is connected
 ~       correctly! Otherwise it could be
 ~       destroyed!
 ~       VERY IMPORTANT: The connection from
 ~       Arduino TX (pin 7) to the Bluetooth
 ~       module RX pin has to be done through
 ~       a voltage divider!
 ~
 */
NeoSWSerial BT(RX_PIN, TX_PIN);

// Functions:
/*~
 ~ Sets the baudrate used for the Bluetooth
 ~ communication.
 ~
 ~ Input: Baudrate [9600, 19200, 31250, 38400]
 ~
 ~ Hint: Default baudrate is 9600.
 ~
 */
void BT_Begin(uint16_t baudRate = 9600)
{
  BT.begin(baudRate);
}

/*~
 ~ Returns the number of characters in the
 ~ RX buffer.
 ~
 ~ Hint: If this function returns zero (0),
 ~       the RX buffer is empty.
 ~
 ~ Example:
 ~   if(BT_Available()) {char c = BT_Read();}
 ~ 
 */
uint8_t BT_Available()
{
  return BT.available();
}

/*~
 ~ Returns a single character from the
 ~ RX buffer.
 ~
 ~ Output: Character received
 ~
 ~ Hint: You have to call BT_Available()
 ~       before reading a character!
 ~
 ~ Example:
 ~   if(BT_Available()) {char c = BT_Read();}
 ~ 
 */
uint8_t BT_Read()
{
  return BT.read();
}

/*~
 ~ Transmits a single character.
 ~
 */
void BT_Write(uint8_t txChar)
{
  BT.write(txChar);
}

/*~
 ~ Transmits a string.
 ~
 */
void BT_WriteString(char *str)
{
  while (*str) {
    BT.write(*str++);
  }
}

/*~
 ~ This function is used to remote RoboDuck.
 ~ It reads single characters over BT. If a
 ~ character is sent more than once in a
 ~ row, the number of identical characters
 ~ is counted in keyCnt. The character is
 ~ stored in key, if another character is
 ~ sent or at timeout (no further character
 ~ sent for KEY_DELAY ms).
 ~ 
 ~ Output: New char received -> true  [1]
 ~         Else              -> false [0]
 ~
 ~ Examples:
 ~   Four example output values, if the
 ~   function returns true:
 ~
 ~   key   keyCnt   Meaning
 ~   -------------------------------
 ~    1     1       '1' sent once
 ~    2     4       '2' sent 4 times
 ~    3     6       '3' sent 6 times
 ~    4     1       '4' sent once
 ~
 ~ Hints: - This function must be called
 ~          frequently out of the main
 ~          loop!
 ~        - If this function returns true,
 ~          the global variables addressed
 ~          with *key and *keyCnt contain
 ~          the result and can be read.
 ~        - key can be any printable char.
 ~        - Max. value for keyCnt is 10.
 ~        - Don't use this function
 ~          together with BT_Available()
 ~          and/or BT_Read()!
 ~
 */
bool BT_Control(char *key, uint8_t *keyCnt)
{
  static uint8_t timerActive = 0;
  static uint8_t charCnt = 0;
  static char lastc = 0;
  static unsigned long oldmillis;
  static char c = 31;
  uint8_t rdy;

  rdy = 0;
  if(BT.available() > 0)
  {
    c = BT.read();
    oldmillis = millis();
    timerActive = 1;
    if(c == lastc)
    {
      charCnt++;
      if(charCnt > 10) charCnt = 0;
    }
    else  // c != lastc
    {
      if(charCnt > 0)
      {
        *key = lastc;
        *keyCnt = charCnt;
        rdy = 1;
      }
      lastc = c;
      charCnt = 1;
    }
  }
  else    // BT NOT available
  {
    if(timerActive)
    {
      if(millis() > (oldmillis + KEY_DELAY))
      {   // Timeout
        *key = c;
        *keyCnt = charCnt;
        rdy = 1;
        timerActive = 0;
        charCnt = 0;
      }
    }
  }
  return rdy;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/




/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~ Additional info
 ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~ Changelog:
 ~ - v. 0.9  (initial release) 03.10.2020 by D. Ottensmeyer
 ~
 ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
