v1.1.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Modules Pages
bluetooth.h
1 /* -*- mode: C; c-basic-offset: 4; intent-tabs-mode: nil -*-
2  *
3  * Sifteo SDK
4  *
5  * Copyright <c> 2013 Sifteo, Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #pragma once
27 #ifdef NOT_USERSPACE
28 # error This is a userspace-only header, not allowed by the current build.
29 #endif
30 
31 #include <sifteo/abi.h>
32 
33 namespace Sifteo {
34 
72 class Bluetooth {
73 public:
74 
86  static bool isAvailable()
87  {
88  if ((_SYS_getFeatures() & _SYS_FEATURE_BLUETOOTH) == 0) {
89  return false;
90  }
91 
92  return _SYS_bt_isAvailable();
93  }
94 
108  static bool isConnected()
109  {
110  return _SYS_bt_isConnected();
111  }
112 
135  static void advertiseState(const uint8_t *bytes, unsigned length)
136  {
137  _SYS_bt_advertiseState(bytes, length);
138  };
139 
148  template <typename T>
149  static void advertiseState(const T &object)
150  {
151  advertiseState(reinterpret_cast<const uint8_t*>(&object), sizeof object);
152  }
153 };
154 
155 
164  _SYSBluetoothPacket sys;
165 
166  // Implicit conversions
167  operator _SYSBluetoothPacket* () { return &sys; }
168  operator const _SYSBluetoothPacket* () const { return &sys; }
169 
171  static unsigned capacity() {
172  return _SYS_BT_PACKET_BYTES;
173  }
174 
176  void clear() {
177  resize(0);
178  setType(0);
179  }
180 
182  unsigned size() const {
183  return sys.length;
184  }
185 
187  void resize(unsigned bytes) {
188  ASSERT(bytes <= capacity());
189  sys.length = bytes;
190  }
191 
193  bool empty() const {
194  return size() == 0;
195  }
196 
198  uint8_t *bytes() {
199  return sys.bytes;
200  }
201  const uint8_t *bytes() const {
202  return sys.bytes;
203  }
204 
206  unsigned type() const {
207  return sys.type;
208  }
209 
211  void setType(unsigned type) {
212  ASSERT(type <= 127);
213  sys.type = type;
214  }
215 };
216 
217 
235 template < unsigned tCapacity >
237  struct SysType {
238  union {
239  _SYSBluetoothQueueHeader header;
240  uint32_t header32;
241  };
242  _SYSBluetoothPacket packets[tCapacity + 1];
243  } sys;
244 
245  // Implicit conversions
246  operator _SYSBluetoothQueue* () { return reinterpret_cast<_SYSBluetoothQueue*>(&sys); }
247  operator const _SYSBluetoothQueue* () const { return reinterpret_cast<const _SYSBluetoothQueue*>(&sys); }
248 
250  void clear()
251  {
252  unsigned lastIndex = tCapacity;
253 
254  STATIC_ASSERT(sizeof sys.header == sizeof sys.header32);
255  STATIC_ASSERT(lastIndex >= 1);
256  STATIC_ASSERT(lastIndex <= 255);
257 
258  sys.header32 = lastIndex << 16;
259 
260  ASSERT(sys.header.head == 0);
261  ASSERT(sys.header.tail == 0);
262  ASSERT(sys.header.last == lastIndex);
263  }
264 
275  unsigned count() const
276  {
277  unsigned size = tCapacity + 1;
278  unsigned head = sys.header.head;
279  unsigned tail = sys.header.tail;
280  ASSERT(head < size);
281  ASSERT(tail < size);
282  return (tail - head) % size;
283  }
284 
286  unsigned readAvailable() const
287  {
288  return count();
289  }
290 
292  unsigned writeAvailable() const
293  {
294  return tCapacity - count();
295  }
296 
307  void read(BluetoothPacket &buffer)
308  {
309  buffer = peek();
310  pop();
311  }
312 
324  const BluetoothPacket &peek() const
325  {
326  ASSERT(readAvailable() > 0);
327  unsigned head = sys.header.head;
328  ASSERT(head <= tCapacity);
329  return *reinterpret_cast<const BluetoothPacket *>(&sys.packets[head]);
330  }
331 
338  void pop()
339  {
340  ASSERT(readAvailable() > 0);
341  unsigned head = sys.header.head + 1;
342  if (head > tCapacity)
343  head = 0;
344  sys.header.head = head;
345 
346  /*
347  * Notify the system that we have more space for reading. This may
348  * communicate additional flow control tokens to our peer if this
349  * queue is the current read pipe.
350  *
351  * This is only absolutely necessary if the queue transitioned
352  * from being totally full to being less-than-totally full, but
353  * we'd also like to give the system a chance to send flow control
354  * tokens speculatively if it wants.
355  */
356  _SYS_bt_queueReadHint();
357  }
358 
369  void write(const BluetoothPacket &buffer)
370  {
371  reserve() = buffer;
372  commit();
373  }
374 
388  {
389  ASSERT(writeAvailable() > 0);
390  unsigned tail = sys.header.tail;
391  ASSERT(tail <= tCapacity);
392  return *reinterpret_cast<BluetoothPacket *>(&sys.packets[tail]);
393  }
394 
401  void commit()
402  {
403  ASSERT(writeAvailable() > 0);
404  unsigned tail = sys.header.tail + 1;
405  if (tail > tCapacity)
406  tail = 0;
407  sys.header.tail = tail;
408 
409  /*
410  * Poke the system to look at our queue, in case it's ready to
411  * transmit immediately. Has no effect if this queue isn't
412  * attached as the current TX pipe.
413  *
414  * This wakeup is only necessary when the queue transitions
415  * from empty to full, but we have no way of knowing for sure when
416  * this happens. If we see that the queue is non-empty when we
417  * commit(), there's no way to know that the system hasn't dequeued
418  * the packet during this function's execution.
419  */
420  _SYS_bt_queueWriteHint();
421  }
422 };
423 
424 
465 template < unsigned tSendCapacity = 4, unsigned tReceiveCapacity = 4 >
467 
470 
473 
491  void attach() {
492  sendQueue.clear();
493  receiveQueue.clear();
494  _SYS_bt_setPipe(sendQueue, receiveQueue);
495  }
496 
504  void detach() {
505  _SYS_bt_setPipe(0, 0);
506  }
507 
517  bool write(const BluetoothPacket &buffer)
518  {
519  if (sendQueue.writeAvailable()) {
520  sendQueue.write(buffer);
521  return true;
522  }
523  return false;
524  }
525 
532  bool read(BluetoothPacket &buffer)
533  {
534  if (receiveQueue.readAvailable()) {
535  receiveQueue.read(buffer);
536  return true;
537  }
538  return false;
539  }
540 
542  unsigned readAvailable() const
543  {
544  return receiveQueue.readAvailable();
545  }
546 
548  unsigned writeAvailable() const
549  {
550  return sendQueue.writeAvailable();
551  }
552 };
553 
554 
569 {
570  _SYSBluetoothCounters current;
571  _SYSBluetoothCounters base;
572 
579  void reset() {
580  _SYS_bt_counters(&base, sizeof base);
581  }
582 
586  void capture() {
587  _SYS_bt_counters(&current, sizeof current);
588  }
589 
591  uint32_t receivedPackets() {
592  return current.rxPackets - base.rxPackets;
593  }
594 
596  uint32_t sentPackets() {
597  return current.txPackets - base.txPackets;
598  }
599 
601  uint32_t receivedBytes() {
602  return current.rxBytes - base.rxBytes;
603  }
604 
606  uint32_t sentBytes() {
607  return current.txBytes - base.txBytes;
608  }
609 
617  uint32_t userPacketsDropped() {
618  return current.rxUserDropped - base.rxUserDropped;
619  }
620 };
621 
622 
627 } // namespace Sifteo
static bool isAvailable()
Is Bluetooth support available on this hardware?
Definition: bluetooth.h:86
void resize(unsigned bytes)
Change the size of this packet, in bytes.
Definition: bluetooth.h:187
unsigned count() const
How many packets are sitting in the queue right now?
Definition: bluetooth.h:275
uint32_t sentPackets()
Total sent packets.
Definition: bluetooth.h:596
uint32_t sentBytes()
Total sent bytes.
Definition: bluetooth.h:606
uint32_t userPacketsDropped()
Total user-defined packets dropped.
Definition: bluetooth.h:617
static unsigned capacity()
Retrieve the capacity of a packet, in bytes. (19)
Definition: bluetooth.h:171
void write(const BluetoothPacket &buffer)
Copy a new packet into the queue, from a provided buffer.
Definition: bluetooth.h:369
#define ASSERT(_x)
Runtime debug assertion.
Definition: macros.h:205
static void advertiseState(const uint8_t *bytes, unsigned length)
Set the current advertised game state.
Definition: bluetooth.h:135
unsigned type() const
Return the packet's 7-bit type code.
Definition: bluetooth.h:206
unsigned readAvailable() const
How many packets are available to read from this queue right now?
Definition: bluetooth.h:542
BluetoothQueue< tReceiveCapacity > receiveQueue
Queue for packets that have been received but not yet processed.
Definition: bluetooth.h:472
bool empty() const
Is this packet's payload empty?
Definition: bluetooth.h:193
A memory buffer which holds a queue of Bluetooth packets.
Definition: bluetooth.h:236
void attach()
Attach this pipe to the system.
Definition: bluetooth.h:491
uint32_t receivedPackets()
Total received packets.
Definition: bluetooth.h:591
A container for one Bluetooth packet's data.
Definition: bluetooth.h:163
Global Bluetooth operations.
Definition: bluetooth.h:72
void commit()
Finish writing a packet that was started with reserve()
Definition: bluetooth.h:401
void reset()
Reset all counters back to zero.
Definition: bluetooth.h:579
void pop()
Dequeue the oldest packet.
Definition: bluetooth.h:338
void detach()
Detach all pipes from the system.
Definition: bluetooth.h:504
Diagnostic counters for the Bluetooth subsystem.
Definition: bluetooth.h:568
static void advertiseState(const T &object)
Template wrapper around advertiseState()
Definition: bluetooth.h:149
unsigned size() const
Retrieve the size of this packet, in bytes.
Definition: bluetooth.h:182
static bool isConnected()
Is a device currently connected via the Sifteo Bluetooth API?
Definition: bluetooth.h:108
void clear()
Set the packet's length and type to zero.
Definition: bluetooth.h:176
unsigned writeAvailable() const
How many free buffers are available for writing right now?
Definition: bluetooth.h:292
void read(BluetoothPacket &buffer)
Read the oldest queued packet into a provided buffer.
Definition: bluetooth.h:307
Definition: array.h:34
bool write(const BluetoothPacket &buffer)
Write one packet to the send queue, if space is available.
Definition: bluetooth.h:517
uint8_t * bytes()
Return a pointer to this packet's payload bytes.
Definition: bluetooth.h:198
void setType(unsigned type)
Set a packet's 7-bit type.
Definition: bluetooth.h:211
BluetoothPacket & reserve()
Access a buffer slot where a new packet can be written.
Definition: bluetooth.h:387
void capture()
Update the state of all counters.
Definition: bluetooth.h:586
unsigned writeAvailable() const
How many free buffers are available for writing right now?
Definition: bluetooth.h:548
void clear()
Initializes this queue's header, and marks it as empty.
Definition: bluetooth.h:250
unsigned readAvailable() const
How many packets are available to read from this queue right now?
Definition: bluetooth.h:286
uint32_t receivedBytes()
Total received bytes.
Definition: bluetooth.h:601
#define STATIC_ASSERT(_x)
Definition: macros.h:342
A memory buffer for bidirectional Bluetooth communications.
Definition: bluetooth.h:466
BluetoothQueue< tSendCapacity > sendQueue
Queue for packets we're waiting to send.
Definition: bluetooth.h:469
const BluetoothPacket & peek() const
Access the oldest queued packet without copying it.
Definition: bluetooth.h:324
bool read(BluetoothPacket &buffer)
If a packet is available in the queue, read it.
Definition: bluetooth.h:532