mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
The SPP Class now inherit from the Arduino Stream library
This commit is contained in:
parent
305eeb0820
commit
e6a557870b
5 changed files with 83 additions and 379 deletions
200
SPP.cpp
200
SPP.cpp
|
@ -67,6 +67,7 @@ void SPP::Reset() {
|
|||
l2cap_sdp_state = L2CAP_SDP_WAIT;
|
||||
l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
|
||||
l2cap_event_flag = 0;
|
||||
sppIndex = 0;
|
||||
}
|
||||
|
||||
void SPP::disconnect() {
|
||||
|
@ -381,6 +382,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
|
|||
waitForLastCommand = false;
|
||||
creditSent = false;
|
||||
connected = true; // The RFCOMM channel is now established
|
||||
sppIndex = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else if (rfcommChannelType != RFCOMM_DISC) {
|
||||
|
@ -413,7 +415,9 @@ void SPP::Run() {
|
|||
creditSent = false;
|
||||
waitForLastCommand = false;
|
||||
connected = true; // The RFCOMM channel is now established
|
||||
sppIndex = 0;
|
||||
}
|
||||
send(); // Send all bytes currently in the buffer
|
||||
}
|
||||
|
||||
void SPP::SDP_task() {
|
||||
|
@ -725,22 +729,21 @@ uint8_t SPP::calcFcs(uint8_t *data) {
|
|||
}
|
||||
|
||||
/* Serial commands */
|
||||
void SPP::print(const String &str) {
|
||||
uint8_t length = str.length(); // Get the length of the string
|
||||
uint8_t buf[length];
|
||||
|
||||
for(uint8_t i = 0; i < length; i++)
|
||||
buf[i] = str[i];
|
||||
|
||||
print(buf,length);
|
||||
size_t SPP::write(uint8_t data) {
|
||||
return write(&data,1);
|
||||
}
|
||||
|
||||
void SPP::print(const char* str) {
|
||||
print((uint8_t*) str, strlen(str));
|
||||
size_t SPP::write(const uint8_t* data, size_t size) {
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if(sppIndex >= sizeof(sppOutputBuffer)/sizeof(sppOutputBuffer[0]))
|
||||
return i; // Don't send any more if buffer is already full
|
||||
sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void SPP::print(uint8_t* array, uint8_t stringLength) {
|
||||
if (!connected)
|
||||
void SPP::send() {
|
||||
if (!connected || !sppIndex)
|
||||
return;
|
||||
uint8_t length; // This is the length of the string we are sending
|
||||
uint8_t offset = 0; // This is used to keep track of where we are in the string
|
||||
|
@ -748,177 +751,42 @@ void SPP::print(uint8_t* array, uint8_t stringLength) {
|
|||
l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
|
||||
l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
|
||||
|
||||
while (stringLength) { // We will run this while loop until this variable is 0
|
||||
if (stringLength > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger that the outgoing buffer
|
||||
while (sppIndex) { // We will run this while loop until this variable is 0
|
||||
if (sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer
|
||||
length = sizeof (l2capoutbuf) - 4;
|
||||
else
|
||||
length = stringLength;
|
||||
length = sppIndex;
|
||||
|
||||
l2capoutbuf[2] = length << 1 | 1; // Length
|
||||
uint8_t i = 0;
|
||||
for (; i < length; i++)
|
||||
l2capoutbuf[i + 3] = array[i + offset];
|
||||
l2capoutbuf[i + 3] = sppOutputBuffer[i + offset];
|
||||
l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
|
||||
|
||||
RFCOMM_Command(l2capoutbuf, length + 4);
|
||||
|
||||
stringLength -= length;
|
||||
sppIndex -= length;
|
||||
offset += length; // Increment the offset
|
||||
}
|
||||
}
|
||||
|
||||
void SPP::println(const String &str) {
|
||||
String output = str + "\r\n";
|
||||
print(output);
|
||||
int SPP::available(void) {
|
||||
return rfcommAvailable;
|
||||
};
|
||||
|
||||
void SPP::flush(void) {
|
||||
rfcommAvailable = 0;
|
||||
}
|
||||
|
||||
void SPP::println(const char* str) {
|
||||
char output[strlen(str) + 3];
|
||||
strcpy(output, str);
|
||||
strcat(output, "\r\n");
|
||||
print(output);
|
||||
}
|
||||
|
||||
void SPP::println(uint8_t data) {
|
||||
uint8_t buf[3] = {data, '\r', '\n'};
|
||||
print(buf, 3);
|
||||
}
|
||||
|
||||
void SPP::println(uint8_t* array, uint8_t length) {
|
||||
uint8_t buf[length + 2];
|
||||
memcpy(buf, array, length);
|
||||
buf[length] = '\r';
|
||||
buf[length + 1] = '\n';
|
||||
print(buf, length + 2);
|
||||
}
|
||||
|
||||
void SPP::printFlashString(const __FlashStringHelper *ifsh, bool newline) {
|
||||
const char PROGMEM *p = (const char PROGMEM *)ifsh;
|
||||
uint8_t size = 0;
|
||||
while (1) { // Calculate the size of the string
|
||||
uint8_t c = pgm_read_byte(p + size);
|
||||
if (c == 0)
|
||||
break;
|
||||
size++;
|
||||
}
|
||||
uint8_t buf[size + 2]; // Add two extra in case it needs to print a newline and carriage return
|
||||
|
||||
for (uint8_t i = 0; i < size; i++)
|
||||
buf[i] = pgm_read_byte(p++);
|
||||
|
||||
if (newline) {
|
||||
buf[size] = '\r';
|
||||
buf[size + 1] = '\n';
|
||||
print(buf, size + 2);
|
||||
} else
|
||||
print(buf, size);
|
||||
}
|
||||
|
||||
void SPP::println(void) {
|
||||
uint8_t buf[2] = {'\r', '\n'};
|
||||
print(buf, 2);
|
||||
}
|
||||
|
||||
/* These must be used to print numbers */
|
||||
void SPP::printNumber(uint32_t n) {
|
||||
char output[11];
|
||||
intToString(n, output);
|
||||
print(output);
|
||||
}
|
||||
|
||||
void SPP::printNumberln(uint32_t n) {
|
||||
char output[13];
|
||||
intToString(n, output);
|
||||
strcat(output, "\r\n");
|
||||
print(output);
|
||||
}
|
||||
|
||||
void SPP::printNumber(int32_t n) {
|
||||
char output[12];
|
||||
intToString(n, output);
|
||||
print(output);
|
||||
}
|
||||
|
||||
void SPP::printNumberln(int32_t n) {
|
||||
char output[14];
|
||||
intToString(n, output);
|
||||
strcat(output, "\r\n");
|
||||
print(output);
|
||||
}
|
||||
|
||||
void SPP::intToString(int32_t input, char* output) {
|
||||
if (input < 0) {
|
||||
char buf[11];
|
||||
intToString((uint32_t)(input*-1), buf);
|
||||
strcpy(output, "-");
|
||||
strcat(output, buf);
|
||||
} else
|
||||
intToString((uint32_t)input, output);
|
||||
}
|
||||
|
||||
void SPP::intToString(uint32_t input, char* output) {
|
||||
uint32_t temp = input;
|
||||
uint8_t digits = 0;
|
||||
while (temp) {
|
||||
temp /= 10;
|
||||
digits++;
|
||||
}
|
||||
if (digits == 0)
|
||||
strcpy(output, "0");
|
||||
else {
|
||||
for (uint8_t i = 1; i <= digits; i++) {
|
||||
output[digits - i] = input % 10 + '0'; // Get number and convert to ASCII Character
|
||||
input /= 10;
|
||||
}
|
||||
output[digits] = '\0'; // Add null character
|
||||
}
|
||||
}
|
||||
|
||||
void SPP::printNumber(double n, uint8_t digits) {
|
||||
char output[13 + digits];
|
||||
doubleToString(n, output, digits);
|
||||
print(output);
|
||||
}
|
||||
|
||||
void SPP::printNumberln(double n, uint8_t digits) {
|
||||
char output[15 + digits];
|
||||
doubleToString(n, output, digits);
|
||||
strcat(output, "\r\n");
|
||||
print(output);
|
||||
}
|
||||
|
||||
void SPP::doubleToString(double input, char* output, uint8_t digits) {
|
||||
char buffer[13 + digits];
|
||||
if (input < 0) {
|
||||
strcpy(output, "-");
|
||||
input = -input;
|
||||
} else
|
||||
strcpy(output, "");
|
||||
|
||||
// Round correctly
|
||||
double rounding = 0.5;
|
||||
for (uint8_t i = 0; i < digits; i++)
|
||||
rounding /= 10.0;
|
||||
input += rounding;
|
||||
|
||||
uint32_t intpart = (uint32_t)input;
|
||||
intToString(intpart, buffer); // Convert to string
|
||||
strcat(output, buffer);
|
||||
strcat(output, ".");
|
||||
double fractpart = (input - (double)intpart);
|
||||
fractpart *= pow(10, digits);
|
||||
for (uint8_t i = 1; i < digits; i++) { // Put zeros in front of number
|
||||
if (fractpart < pow(10, digits - i)) {
|
||||
strcat(output, "0");
|
||||
}
|
||||
}
|
||||
intToString((uint32_t)fractpart, buffer); // Convert to string
|
||||
strcat(output, buffer);
|
||||
}
|
||||
|
||||
uint8_t SPP::read() {
|
||||
int SPP::peek(void) {
|
||||
if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer
|
||||
return 0;
|
||||
return -1;
|
||||
return rfcommDataBuffer[0];
|
||||
}
|
||||
|
||||
int SPP::read(void) {
|
||||
if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer
|
||||
return -1;
|
||||
uint8_t output = rfcommDataBuffer[0];
|
||||
for (uint8_t i = 1; i < rfcommAvailable; i++)
|
||||
rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left
|
||||
|
|
246
SPP.h
246
SPP.h
|
@ -90,7 +90,7 @@
|
|||
*/
|
||||
|
||||
/** This BluetoothService class implements the Serial Port Protocol (SPP). */
|
||||
class SPP : public BluetoothService {
|
||||
class SPP : public BluetoothService, public Stream {
|
||||
public:
|
||||
/**
|
||||
* Constructor for the SPP class.
|
||||
|
@ -118,217 +118,51 @@ public:
|
|||
bool connected;
|
||||
|
||||
/** @name Serial port profile (SPP) Print functions */
|
||||
/**
|
||||
* Used to send Arduino String data type.
|
||||
* @param str String to send.
|
||||
*/
|
||||
void print(const String &str);
|
||||
/**
|
||||
* Same as print(const String &str), but will include newline and carriage return.
|
||||
* @param str String to send.
|
||||
*/
|
||||
void println(const String &str);
|
||||
|
||||
/**
|
||||
* Used to send standard strings.
|
||||
* @param str String to send.
|
||||
*/
|
||||
void print(const char* str);
|
||||
/**
|
||||
* Same as print(const char* str), but will include newline and carriage return.
|
||||
* @param str String to send.
|
||||
*/
|
||||
void println(const char* str);
|
||||
|
||||
/**
|
||||
* Used to send single bytes.
|
||||
* @param data Data to send.
|
||||
*/
|
||||
void print(uint8_t data) {
|
||||
print(&data, 1);
|
||||
};
|
||||
/**
|
||||
* Same as print(uint8_t data), but will include newline and carriage return.
|
||||
* @param data Data to send.
|
||||
*/
|
||||
void println(uint8_t data);
|
||||
|
||||
/**
|
||||
* Used to send arrays.
|
||||
* @param array Array to send.
|
||||
* @param length Number of bytes to send.
|
||||
*/
|
||||
void print(uint8_t* array, uint8_t length);
|
||||
/**
|
||||
* Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return.
|
||||
* @param array Array to send.
|
||||
* @param length Number of bytes to send.
|
||||
*/
|
||||
void println(uint8_t* array, uint8_t length);
|
||||
|
||||
/**
|
||||
* Used to print strings stored in flash.
|
||||
* Use "SerialBT.print(F("String"));" to print a string stored in flash.
|
||||
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
|
||||
*/
|
||||
void print(const __FlashStringHelper *ifsh) {
|
||||
printFlashString(ifsh, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as print(const __FlashStringHelper *ifsh), but will include newline and carriage return.
|
||||
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
|
||||
*/
|
||||
void println(const __FlashStringHelper *ifsh) {
|
||||
printFlashString(ifsh, true);
|
||||
};
|
||||
/**
|
||||
* Helper function to print a string stored in flash.
|
||||
* @param ifsh String stored in flash you want to print.
|
||||
* @param newline Set this to true to include newline and carriage return.
|
||||
*/
|
||||
void printFlashString(const __FlashStringHelper *ifsh, bool newline);
|
||||
|
||||
|
||||
/** Use this to print newline and carriage return. */
|
||||
void println(void);
|
||||
|
||||
/**
|
||||
* Used to print unsigned integers.
|
||||
* @param n Unsigned integer to send.
|
||||
*/
|
||||
void printNumber(uint8_t n) {
|
||||
printNumber((uint32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as printNumber(uint8_t n), but will include newline and carriage return.
|
||||
* @param n Unsigned integer to send.
|
||||
*/
|
||||
void printNumberln(uint8_t n) {
|
||||
printNumberln((uint32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to print signed integers.
|
||||
* @param n Signed integer to send.
|
||||
*/
|
||||
void printNumber(int8_t n) {
|
||||
printNumber((int32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as printNumber(int8_t n), but will include newline and carriage return.
|
||||
* @param n Signed integer to send.
|
||||
*/
|
||||
void printNumberln(int8_t n) {
|
||||
printNumberln((int32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to print unsigned integers.
|
||||
* @param n Unsigned integer to send.
|
||||
*/
|
||||
void printNumber(uint16_t n) {
|
||||
printNumber((uint32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as printNumber(uint16_t n), but will include newline and carriage return.
|
||||
* @param n Unsigned integer to send.
|
||||
*/
|
||||
void printNumberln(uint16_t n) {
|
||||
printNumberln((uint32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to print signed integers.
|
||||
* @param n Signed integer to send.
|
||||
*/
|
||||
void printNumber(int16_t n) {
|
||||
printNumber((int32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as printNumber(int16_t n), but will include newline and carriage return.
|
||||
* @param n Signed integer to send.
|
||||
*/
|
||||
void printNumberln(int16_t n) {
|
||||
printNumberln((int32_t) n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to print unsigned integers.
|
||||
* @param n Unsigned integer to send.
|
||||
*/
|
||||
void printNumber(uint32_t n);
|
||||
/**
|
||||
* Same as printNumber(uint32_t n), but will include newline and carriage return.
|
||||
* @param n Unsigned integer to send.
|
||||
*/
|
||||
void printNumberln(uint32_t n);
|
||||
|
||||
/**
|
||||
* Used to print signed integers.
|
||||
* @param n Signed integer to send.
|
||||
*/
|
||||
void printNumber(int32_t n);
|
||||
/**
|
||||
* Same as printNumber(int32_t n), but will include newline and carriage return.
|
||||
* @param n Signed integer to send.
|
||||
*/
|
||||
void printNumberln(int32_t n);
|
||||
|
||||
/**
|
||||
* Helper function to convert from an unsigned integer to a string.
|
||||
* @param input Unsigned integer to convert.
|
||||
* @param output Output buffer.
|
||||
*/
|
||||
void intToString(int32_t input, char* output);
|
||||
/**
|
||||
* Helper function to convert from a signed integer to a string.
|
||||
* @param input Signed integer to convert.
|
||||
* @param output Output buffer.
|
||||
*/
|
||||
void intToString(uint32_t input, char* output);
|
||||
|
||||
/**
|
||||
* Used to print floating-point numbers.
|
||||
* @param n Floating-point number to print.
|
||||
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used.
|
||||
*/
|
||||
void printNumber(double n, uint8_t digits = 2);
|
||||
/**
|
||||
* Same as printNumber(double n, uint8_t digits), but will include newline and carriage return.
|
||||
* @param n Floating-point number to print.
|
||||
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used.
|
||||
*/
|
||||
void printNumberln(double n, uint8_t digits = 2);
|
||||
/**
|
||||
* Helper function to convert from a double to a string.
|
||||
* @param input Floating-point number to convert.
|
||||
* @param output Output buffer.
|
||||
* @param digits Number of digits to convert. If argument is omitted, then 2 digits will be used.
|
||||
*/
|
||||
void doubleToString(double input, char* output, uint8_t digits = 2);
|
||||
|
||||
/**
|
||||
* Get number of bytes waiting to be read.
|
||||
* @return Return the number of bytes ready to be read.
|
||||
*/
|
||||
uint8_t available() {
|
||||
return rfcommAvailable;
|
||||
};
|
||||
virtual int available(void);
|
||||
/** Discard all the bytes in the buffer. */
|
||||
virtual void flush(void);
|
||||
/**
|
||||
* Used to read the next value in the buffer without advancing to the next one.
|
||||
* @return Return the byte. Will return -1 if no byte is available.
|
||||
*/
|
||||
virtual int peek(void);
|
||||
/**
|
||||
* Used to read the buffer.
|
||||
* @return Return the byte. Will return 0 if no byte is available.
|
||||
* @return Return the byte. Will return -1 if no byte is available.
|
||||
*/
|
||||
uint8_t read();
|
||||
|
||||
/** Discard all the bytes in the buffer. */
|
||||
void flush() {
|
||||
rfcommAvailable = 0;
|
||||
};
|
||||
virtual int read(void);
|
||||
/**
|
||||
* Writes the byte to send to a buffer. The message is send when either send(const uint8_t* data, size_t size) or after Usb.Task() is called.
|
||||
* @param data The byte to write.
|
||||
* @return Return the number of bytes written.
|
||||
*/
|
||||
virtual size_t write(uint8_t data);
|
||||
/**
|
||||
* Writes the bytes to send to a buffer. The message is send when either send(const uint8_t* data, size_t size) or after Usb.Task() is called.
|
||||
* @param data The data array to send.
|
||||
* @param size Size of the data.
|
||||
* @return Return the number of bytes written.
|
||||
*/
|
||||
virtual size_t write(const uint8_t* data, size_t size);
|
||||
/** Pull in write(const char *str) from Print */
|
||||
using Print::write;
|
||||
/**
|
||||
* This will send all the bytes in the buffer.
|
||||
* This is called whenever Usb.Task() is called,
|
||||
* but can also be called via this function.
|
||||
*/
|
||||
void send(void);
|
||||
/**
|
||||
* Used to provide Boolean tests for the class.
|
||||
* @return Return true if SPP communication is connected.
|
||||
*/
|
||||
operator bool() {
|
||||
return connected;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
private:
|
||||
|
@ -369,6 +203,8 @@ private:
|
|||
bool creditSent;
|
||||
|
||||
uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
|
||||
uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data
|
||||
uint8_t sppIndex;
|
||||
uint8_t rfcommAvailable;
|
||||
|
||||
bool firstMessage; // Used to see if it's the first SDP request received
|
||||
|
|
|
@ -21,7 +21,7 @@ PS3BT PS3(&Btd); // This will just create the instance
|
|||
//PS3BT PS3(&Btd,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch
|
||||
|
||||
boolean firstMessage = true;
|
||||
String output = ""; // We will store the data in this string so we doesn't overflow the dongle
|
||||
String output = ""; // We will store the data in this string
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); // This wil lprint the debugging from the libraries
|
||||
|
@ -33,7 +33,7 @@ void setup() {
|
|||
output.reserve(200); // Reserve 200 bytes for the output string
|
||||
}
|
||||
void loop() {
|
||||
Usb.Task();
|
||||
Usb.Task(); // The SPP data is actually not send until Usb.Task() is called
|
||||
|
||||
if(SerialBT.connected) {
|
||||
if(firstMessage) {
|
||||
|
@ -41,7 +41,7 @@ void loop() {
|
|||
SerialBT.println(F("Hello from Arduino")); // Send welcome message
|
||||
}
|
||||
if(Serial.available())
|
||||
SerialBT.print(Serial.read());
|
||||
SerialBT.write(Serial.read());
|
||||
if(SerialBT.available())
|
||||
Serial.write(SerialBT.read());
|
||||
}
|
||||
|
|
|
@ -22,14 +22,14 @@ void setup() {
|
|||
Serial.print(F("\r\nSPP Bluetooth Library Started"));
|
||||
}
|
||||
void loop() {
|
||||
Usb.Task();
|
||||
Usb.Task(); // The SPP data is actually not send until Usb.Task() is called
|
||||
if(SerialBT.connected) {
|
||||
if(firstMessage) {
|
||||
firstMessage = false;
|
||||
SerialBT.println(F("Hello from Arduino")); // Send welcome message
|
||||
}
|
||||
if(Serial.available())
|
||||
SerialBT.print(Serial.read());
|
||||
SerialBT.write(Serial.read());
|
||||
if(SerialBT.available())
|
||||
Serial.write(SerialBT.read());
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ void setup() {
|
|||
Serial.print(F("\r\nSPP Bluetooth Library Started"));
|
||||
}
|
||||
void loop() {
|
||||
Usb.Task();
|
||||
Usb.Task(); // The SPP data is actually not send until Usb.Task() is called
|
||||
for(uint8_t i=0;i<length;i++) {
|
||||
if(SerialBT[i]->connected) {
|
||||
if(firstMessage[i]) {
|
||||
|
@ -61,7 +61,7 @@ void loop() {
|
|||
if(SerialBT[id]->connected) { // Check if a device is actually connected
|
||||
for(uint8_t i2 = 0; i2 < i-1; i2++) // Don't include the first character
|
||||
buffer[i2] = buffer[i2+1];
|
||||
SerialBT[id]->println(buffer,i-1); // Send the data
|
||||
SerialBT[id]->write(buffer,i-1); // Send the data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue