diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 62f0eed..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,5 +0,0 @@ -# See more here https://help.github.com/en/articles/about-code-owners - -* @bakercp - -src/Encoding/SLIP.h @avilleret \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index b7f421e..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: bakercp -custom: https://paypal.me/bakercp diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 344b7fb..0000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,35 +0,0 @@ -# New Issue Guidelines - -_Your issue may already be reported! Please search on the [Issue Tracker](../) before creating one._ - -## Expected Behavior - - - -## Current Behavior - - - -## Possible Solution - - - -## Steps to Reproduce (for bugs) - - - -1. Step 1. -2. Step 2. -3. Step 3. -4. etc. - -## Context - - - -## Your Environment - -* Version used: -* IDE Name and version: -* Operating System and version (desktop or mobile): -* Link to your project: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 8812b5a..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,24 +0,0 @@ -# New Pull Request Guidelines - -_A similar PR may already be submitted! Please search among the [Pull Requests](../) before creating one._ - -## This Pull-Request Fixes the Following Issue(s) - -- Fixes # _the issue number here_ -- Fixes # _etc_ - -## Proposed Changes - -- _Change 1._ -- _Change 2._ -- _Change 3._ -- _etc._ - -## Testing Procedure - -_How do we test it?_ - -- _Test 1._ -- _Test 2._ -- _Test 3._ -- _etc._ diff --git a/.github/REPOSITORY_NOTES.md b/.github/REPOSITORY_NOTES.md deleted file mode 100644 index 39ad47f..0000000 --- a/.github/REPOSITORY_NOTES.md +++ /dev/null @@ -1,15 +0,0 @@ - -# Github Documentation Help - -- [README.md](https://help.github.com/en/articles/about-readmes) -- [CODE_OF_CONDUCT.md](https://help.github.com/en/articles/adding-a-code-of-conduct-to-your-project) -- [CODEONWERS](https://help.github.com/en/articles/about-code-owners) -- [CONTRIBUTING.md](https://help.github.com/en/articles/setting-guidelines-for-repository-contributors) -- [ISSUE_TEMPLATE.md](https://help.github.com/en/articles/about-issue-and-pull-request-templates) -- [PULL_REQUEST_TEMPLATE.md](https://help.github.com/en/articles/about-issue-and-pull-request-templates) -- [FUNDING.yml](https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository) - - Enable in settings. -- [SECURITY.md](https://help.github.com/en/articles/adding-a-security-policy-to-your-repository) -- [SUPPORT.md](https://help.github.com/en/articles/adding-support-resources-to-your-project) -- [LICENSE.md](https://help.github.com/en/articles/adding-a-license-to-a-repository) - \ No newline at end of file diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index 87f6977..0000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,3 +0,0 @@ -# Security - -If an exploitable security issue is discovered, please contact the repository owner at [info@christopherbaker.net](mailto:info@christopherbaker.net) before creating an issue. diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 5aacce5..0000000 --- a/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -*.mode1v3 - -docs/html -docs/tagfile.xml - -# xcode -*.pbxuser -*.perspectivev3 -xcuserdata -build -*.app -#*.a - -# OSX -.DS_Store - -# codeblocks -*.layout -example/obj - -# Win -*.exe -*.dll diff --git a/examples/PacketSerialReverseEchoAdvanced/.due.test.skip b/.nojekyll similarity index 100% rename from examples/PacketSerialReverseEchoAdvanced/.due.test.skip rename to .nojekyll diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b4b3c22..0000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -language: c -sudo: false -cache: - directories: - - ~/arduino_ide - - ~/.arduino15/packages/ -before_install: - - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) -install: - - arduino --install-library "ArduinoUnit" -script: - - build_main_platforms -notifications: - email: - on_success: change - on_failure: change - -jobs: - include: - - stage: Deploy Documentation - script: - - source <(curl -SLs https://raw.githubusercontent.com/bakercp/ci/master/deploy_documentation.sh) - deploy: - provider: pages - skip_cleanup: true - github_token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable - keep_history: false - local_dir: docs/html - on: - branch: master diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 8ecd1de..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Christopher Baker - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/PacketSerial_8h_source.html b/PacketSerial_8h_source.html new file mode 100644 index 0000000..96a54ef --- /dev/null +++ b/PacketSerial_8h_source.html @@ -0,0 +1,121 @@ + + + + + + + +PacketSerial: /home/travis/build/bakercp/PacketSerial/src/PacketSerial.h Source File + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
PacketSerial.h
+
+
+
1 //
2 // Copyright (c) 2013 Christopher Baker <https://christopherbaker.net>
3 //
4 // SPDX-License-Identifier: MIT
5 //
6 
7 
8 #pragma once
9 
10 
11 #include <Arduino.h>
12 #include "Encoding/COBS.h"
13 #include "Encoding/SLIP.h"
14 
15 
27 template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
29 {
30 public:
39  typedef void (*PacketHandlerFunction)(const uint8_t* buffer, size_t size);
40 
50  typedef void (*PacketHandlerFunctionWithSender)(const void* sender, const uint8_t* buffer, size_t size);
51 
54  _receiveBufferIndex(0),
55  _stream(nullptr),
56  _onPacketFunction(nullptr),
57  _onPacketFunctionWithSender(nullptr)
58  {
59  }
60 
63  {
64  }
65 
84  void begin(unsigned long speed)
85  {
86  Serial.begin(speed);
87  #if ARDUINO >= 100 && !defined(CORE_TEENSY)
88  while (!Serial) {;}
89  #endif
90  setStream(&Serial);
91  }
92 
97  void begin(unsigned long speed, size_t port) __attribute__ ((deprecated))
98  {
99  switch(port)
100  {
101  #if defined(UBRR1H)
102  case 1:
103  Serial1.begin(speed);
104  #if ARDUINO >= 100 && !defined(CORE_TEENSY)
105  while (!Serial1) {;}
106  #endif
107  setStream(&Serial1);
108  break;
109  #endif
110  #if defined(UBRR2H)
111  case 2:
112  Serial2.begin(speed);
113  #if ARDUINO >= 100 && !defined(CORE_TEENSY)
114  while (!Serial1) {;}
115  #endif
116  setStream(&Serial2);
117  break;
118  #endif
119  #if defined(UBRR3H)
120  case 3:
121  Serial3.begin(speed);
122  #if ARDUINO >= 100 && !defined(CORE_TEENSY)
123  while (!Serial3) {;}
124  #endif
125  setStream(&Serial3);
126  break;
127  #endif
128  default:
129  begin(speed);
130  }
131  }
132 
136  void begin(Stream* stream) __attribute__ ((deprecated))
137  {
138  _stream = stream;
139  }
140 
169  void setStream(Stream* stream)
170  {
171  _stream = stream;
172  }
173 
181  Stream* getStream()
182  {
183  return _stream;
184  }
185 
193  const Stream* getStream() const
194  {
195  return _stream;
196  }
197 
209  void update()
210  {
211  if (_stream == nullptr) return;
212 
213  while (_stream->available() > 0)
214  {
215  uint8_t data = _stream->read();
216 
217  if (data == PacketMarker)
218  {
219  if (_onPacketFunction || _onPacketFunctionWithSender)
220  {
221  uint8_t _decodeBuffer[_receiveBufferIndex];
222 
223  size_t numDecoded = EncoderType::decode(_receiveBuffer,
224  _receiveBufferIndex,
225  _decodeBuffer);
226 
227  if (_onPacketFunction)
228  {
229  _onPacketFunction(_decodeBuffer, numDecoded);
230  }
231  else if (_onPacketFunctionWithSender)
232  {
233  _onPacketFunctionWithSender(this, _decodeBuffer, numDecoded);
234  }
235  }
236 
237  _receiveBufferIndex = 0;
238  _recieveBufferOverflow = false;
239  }
240  else
241  {
242  if ((_receiveBufferIndex + 1) < ReceiveBufferSize)
243  {
244  _receiveBuffer[_receiveBufferIndex++] = data;
245  }
246  else
247  {
248  // The buffer will be in an overflowed state if we write
249  // so set a buffer overflowed flag.
250  _recieveBufferOverflow = true;
251  }
252  }
253  }
254  }
255 
270  void send(const uint8_t* buffer, size_t size) const
271  {
272  if(_stream == nullptr || buffer == nullptr || size == 0) return;
273 
274  uint8_t _encodeBuffer[EncoderType::getEncodedBufferSize(size)];
275 
276  size_t numEncoded = EncoderType::encode(buffer,
277  size,
278  _encodeBuffer);
279 
280  _stream->write(_encodeBuffer, numEncoded);
281  _stream->write(PacketMarker);
282  }
283 
302  {
303  _onPacketFunction = onPacketFunction;
304  _onPacketFunctionWithSender = nullptr;
305  }
306 
339  void setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender)
340  {
341  _onPacketFunction = nullptr;
342  _onPacketFunctionWithSender = onPacketFunctionWithSender;
343  }
344 
369  bool overflow() const
370  {
371  return _recieveBufferOverflow;
372  }
373 
374 private:
376  PacketSerial_& operator = (const PacketSerial_&);
377 
378  bool _recieveBufferOverflow = false;
379 
380  uint8_t _receiveBuffer[ReceiveBufferSize];
381  size_t _receiveBufferIndex = 0;
382 
383  Stream* _stream = nullptr;
384 
385  PacketHandlerFunction _onPacketFunction = nullptr;
386  PacketHandlerFunctionWithSender _onPacketFunctionWithSender = nullptr;
387 };
388 
389 
392 
395 
void(* PacketHandlerFunctionWithSender)(const void *sender, const uint8_t *buffer, size_t size)
A typedef describing the packet handler method.
Definition: PacketSerial.h:50
+
void begin(unsigned long speed, size_t port) __attribute__((deprecated))
Deprecated. Use setStream() to configure a non-default port.
Definition: PacketSerial.h:97
+
void setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender)
Set the function that will receive decoded packets.
Definition: PacketSerial.h:339
+
const Stream * getStream() const
Get a pointer to the current stream.
Definition: PacketSerial.h:193
+
void(* PacketHandlerFunction)(const uint8_t *buffer, size_t size)
A typedef describing the packet handler method.
Definition: PacketSerial.h:39
+
bool overflow() const
Check to see if the receive buffer overflowed.
Definition: PacketSerial.h:369
+
void setPacketHandler(PacketHandlerFunction onPacketFunction)
Set the function that will receive decoded packets.
Definition: PacketSerial.h:301
+
Stream * getStream()
Get a pointer to the current stream.
Definition: PacketSerial.h:181
+
~PacketSerial_()
Destroy the PacketSerial_ device.
Definition: PacketSerial.h:62
+
void update()
The update function services the serial connection.
Definition: PacketSerial.h:209
+
void setStream(Stream *stream)
Attach PacketSerial to an existing Arduino Stream.
Definition: PacketSerial.h:169
+
PacketSerial_()
Construct a default PacketSerial_ device.
Definition: PacketSerial.h:53
+
void begin(unsigned long speed)
Begin a default serial connection with the given speed.
Definition: PacketSerial.h:84
+
void begin(Stream *stream) __attribute__((deprecated))
Deprecated. Use setStream() to configure a non-default port.
Definition: PacketSerial.h:136
+
A template class enabling packet-based Serial communication.
Definition: PacketSerial.h:28
+
void send(const uint8_t *buffer, size_t size) const
Set a packet of data.
Definition: PacketSerial.h:270
+
+
+ + + + diff --git a/README.md b/README.md deleted file mode 100644 index f9ea068..0000000 --- a/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# PacketSerial - -[![Build Status](https://travis-ci.org/bakercp/PacketSerial.svg?branch=master)](https://travis-ci.org/bakercp/PacketSerial) - -An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding. - -## Features - -_PacketSerial_ is an small, efficient, library that allows [Arduinos](http://www.arduino.cc/) to send and receive serial data packets (with COBS, SLIP or a user-defined encoding) that include bytes of any value (0 - 255). -A _packet_ is simply an array of bytes. - -## Documentation - -If you're asking _Why do I need this?_, read the [background introduction](docs/BACKGROUND.md) page. If you're ready to get started, check out the [getting started](docs/GETTING_STARTED.md) page. You can also learn a lot by reading through the [examples](./examples/). Finally, if you're interested in learning more about how the code works, read the comments in the [source code](./src/) and check out the [API documentation](https://bakercp.github.io/PacketSerial/). - -## Support - -If you're looking for help, read the [support](docs/SUPPORT.md) page. - -## Compatibility - -### Requrements - -- [Arduino IDE](https://www.arduino.cc/en/main/software) (version 1.5+) - -### Other Platforms - -This project has been used successfully with [openFrameworks](https://openframeworks.cc/) using the [ofxSerial](https://github.com/bakercp/ofxSerial) addon. In particular, see the `ofx::IO::PacketSerial` object. Additionally this project has been used with Python using the [PySerial](https://pythonhosted.org/pyserial/index.html) package. In particular, check out the [COBS](https://pythonhosted.org/cobs/) (see [this discussion](https://github.com/bakercp/PacketSerial/issues/10)) and [SLIP](https://pypi.python.org/pypi/sliplib/0.0.1) packages. - -Ultimately, any library that correctly implements a COBS or SLIP encoding scheme should be compatible with this project. - -### Continuous Integration - -Continuous integration tests are carried out on a variety of common Arduino platforms. See [this script](https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) for a list. - -## Licensing - -This project is licensed under the [MIT License](LICENSE.md). - -## Project Management - -### Repository - -[https://github.com/bakercp/PacketSerial](https://github.com/bakercp/PacketSerial) - -### Contributing - -If you'd like to contribute to this project, please check out the [Code of Conduct](docs/CODE_OF_CONDUCT.md) and the [contributing](docs/CONTRIBUTING.md) guide. - -### Versioning - -This project uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html). You can check out recent changes in the [changelog](CHANGELOG.md). diff --git a/annotated.html b/annotated.html new file mode 100644 index 0000000..0cafdc5 --- /dev/null +++ b/annotated.html @@ -0,0 +1,109 @@ + + + + + + + +PacketSerial: Class List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+ + +
 CPacketSerial_A template class enabling packet-based Serial communication
+
+
+
+ + + + diff --git a/annotated_dup.js b/annotated_dup.js new file mode 100644 index 0000000..11b00d3 --- /dev/null +++ b/annotated_dup.js @@ -0,0 +1,4 @@ +var annotated_dup = +[ + [ "PacketSerial_", "classPacketSerial__.html", "classPacketSerial__" ] +]; \ No newline at end of file diff --git a/bc_s.png b/bc_s.png new file mode 100644 index 0000000..224b29a Binary files /dev/null and b/bc_s.png differ diff --git a/bdwn.png b/bdwn.png new file mode 100644 index 0000000..940a0b9 Binary files /dev/null and b/bdwn.png differ diff --git a/classPacketSerial__-members.html b/classPacketSerial__-members.html new file mode 100644 index 0000000..6c9e895 --- /dev/null +++ b/classPacketSerial__-members.html @@ -0,0 +1,122 @@ + + + + + + + +PacketSerial: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize > Member List
+
+
+ +

This is the complete list of members for PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >, including all inherited members.

+ + + + + + + + + + + + + + + + +
begin(unsigned long speed)PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
begin(unsigned long speed, size_t port) __attribute__((deprecated))PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
begin(Stream *stream) __attribute__((deprecated))PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
getStream()PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
getStream() constPacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
overflow() constPacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
PacketHandlerFunction typedefPacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >
PacketHandlerFunctionWithSender typedefPacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >
PacketSerial_()PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
send(const uint8_t *buffer, size_t size) constPacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
setPacketHandler(PacketHandlerFunction onPacketFunction)PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender)PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
setStream(Stream *stream)PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
update()PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
~PacketSerial_()PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >inline
+
+ + + + diff --git a/classPacketSerial__.html b/classPacketSerial__.html new file mode 100644 index 0000000..71c17c5 --- /dev/null +++ b/classPacketSerial__.html @@ -0,0 +1,695 @@ + + + + + + + +PacketSerial: PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize > Class Template Reference + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize > Class Template Reference
+
+
+ +

A template class enabling packet-based Serial communication. + More...

+ +

#include <PacketSerial.h>

+ + + + + + + + +

+Public Types

typedef void(* PacketHandlerFunction) (const uint8_t *buffer, size_t size)
 A typedef describing the packet handler method. More...
 
typedef void(* PacketHandlerFunctionWithSender) (const void *sender, const uint8_t *buffer, size_t size)
 A typedef describing the packet handler method. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

PacketSerial_ ()
 Construct a default PacketSerial_ device.
 
~PacketSerial_ ()
 Destroy the PacketSerial_ device.
 
void begin (unsigned long speed)
 Begin a default serial connection with the given speed. More...
 
void begin (unsigned long speed, size_t port) __attribute__((deprecated))
 Deprecated. Use setStream() to configure a non-default port. More...
 
void begin (Stream *stream) __attribute__((deprecated))
 Deprecated. Use setStream() to configure a non-default port. More...
 
void setStream (Stream *stream)
 Attach PacketSerial to an existing Arduino Stream. More...
 
Stream * getStream ()
 Get a pointer to the current stream. More...
 
const Stream * getStream () const
 Get a pointer to the current stream. More...
 
void update ()
 The update function services the serial connection. More...
 
void send (const uint8_t *buffer, size_t size) const
 Set a packet of data. More...
 
void setPacketHandler (PacketHandlerFunction onPacketFunction)
 Set the function that will receive decoded packets. More...
 
void setPacketHandler (PacketHandlerFunctionWithSender onPacketFunctionWithSender)
 Set the function that will receive decoded packets. More...
 
bool overflow () const
 Check to see if the receive buffer overflowed. More...
 
+

Detailed Description

+

template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+class PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >

+ +

A template class enabling packet-based Serial communication.

+

Typically one of the typedefined versions are used, for example, COBSPacketSerial or SLIPPacketSerial.

+

The template parameters allow the user to define their own packet encoder / decoder, custom packet marker and receive buffer size.

+
Template Parameters
+ + + + +
EncoderTypeThe static packet encoder class name.
PacketMarkerThe byte value used to mark the packet boundary.
BufferSizeThe number of bytes allocated for the receive buffer.
+
+
+

Member Typedef Documentation

+ +

◆ PacketHandlerFunction

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + +
typedef void(* PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::PacketHandlerFunction) (const uint8_t *buffer, size_t size)
+
+ +

A typedef describing the packet handler method.

+

The packet handler method usually has the form:

void onPacketReceived(const uint8_t* buffer, size_t size);
+

where buffer is a pointer to the incoming buffer array, and size is the number of bytes in the incoming buffer.

+ +
+
+ +

◆ PacketHandlerFunctionWithSender

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + +
typedef void(* PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::PacketHandlerFunctionWithSender) (const void *sender, const uint8_t *buffer, size_t size)
+
+ +

A typedef describing the packet handler method.

+

The packet handler method usually has the form:

void onPacketReceived(void* sender, const uint8_t* buffer, size_t size);
+

where sender is a pointer to the PacketSerial_ instance that recieved the buffer, buffer is a pointer to the incoming buffer array, and size is the number of bytes in the incoming buffer.

+ +
+
+

Member Function Documentation

+ +

◆ begin() [1/3]

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::begin (unsigned long speed)
+
+inline
+
+ +

Begin a default serial connection with the given speed.

+

The default Serial port Serial and default config SERIAL_8N1 will be used. For example:

PacketSerial myPacketSerial;
+
+void setup()
+{
+    myPacketSerial.begin(9600);
+}
+

This is a convenience method. For more complex Serial port configurations, use the setStream() function to set an arbitrary Arduino Stream.

+
Parameters
+ + +
speedThe serial data transmission speed in bits / second (baud).
+
+
+
See also
https://www.arduino.cc/en/Serial/Begin
+ +
+
+ +

◆ begin() [2/3]

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::begin (unsigned long speed,
size_t port 
)
+
+inline
+
+ +

Deprecated. Use setStream() to configure a non-default port.

+
Parameters
+ + + +
speedThe serial data transmission speed in bits / second (baud).
portThe Serial port number (e.g. 0 is Serial, 1 is Serial1).
+
+
+
Deprecated:
Use setStream() to configure a non-default port.
+ +
+
+ +

◆ begin() [3/3]

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::begin (Stream * stream)
+
+inline
+
+ +

Deprecated. Use setStream() to configure a non-default port.

+
Parameters
+ + +
streamA pointer to an Arduino Stream.
+
+
+
Deprecated:
Use setStream() to configure a non-default port.
+ +
+
+ +

◆ getStream() [1/2]

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + +
Stream* PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::getStream ()
+
+inline
+
+ +

Get a pointer to the current stream.

+
Warning
Reading from or writing to the stream managed by PacketSerial_ may break the packet-serial protocol if not done so with care. Access to the stream is allowed because PacketSerial_ never takes ownership of the stream and thus does not have exclusive access to the stream anyway.
+
Returns
a non-const pointer to the stream, or nullptr if unset.
+ +
+
+ +

◆ getStream() [2/2]

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + +
const Stream* PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::getStream () const
+
+inline
+
+ +

Get a pointer to the current stream.

+
Warning
Reading from or writing to the stream managed by PacketSerial_ may break the packet-serial protocol if not done so with care. Access to the stream is allowed because PacketSerial_ never takes ownership of the stream and thus does not have exclusive access to the stream anyway.
+
Returns
a const pointer to the stream, or nullptr if unset.
+ +
+
+ +

◆ overflow()

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + +
bool PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::overflow () const
+
+inline
+
+ +

Check to see if the receive buffer overflowed.

+

This must be called often, directly after the update() function.

void loop()
+{
+    // Other program code.
+    myPacketSerial.update();
+
+    // Check for a receive buffer overflow.
+    if (myPacketSerial.overflow())
+    {
+        // Send an alert via a pin (e.g. make an overflow LED) or return a
+        // user-defined packet to the sender.
+        //
+        // Ultimately you may need to just increase your recieve buffer via the
+        // template parameters.
+    }
+}
+

The state is reset every time a new packet marker is received NOT when overflow() method is called.

+
Returns
true if the receive buffer overflowed.
+ +
+
+ +

◆ send()

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::send (const uint8_t * buffer,
size_t size 
) const
+
+inline
+
+ +

Set a packet of data.

+

This function will encode and send an arbitrary packet of data. After sending, it will send the specified PacketMarker defined in the template parameters.

// Make an array.
+uint8_t myPacket[2] = { 255, 10 };
+
+// Send the array.
+myPacketSerial.send(myPacket, 2);
+
Parameters
+ + + +
bufferA pointer to a data buffer.
sizeThe number of bytes in the data buffer.
+
+
+ +
+
+ +

◆ setPacketHandler() [1/2]

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::setPacketHandler (PacketHandlerFunction onPacketFunction)
+
+inline
+
+ +

Set the function that will receive decoded packets.

+

This function will be called when data is read from the serial stream connection and a packet is decoded. The decoded packet will be passed to the packet handler. The packet handler must have the form:

+

The packet handler method usually has the form:

void onPacketReceived(const uint8_t* buffer, size_t size);
+

The packet handler would then be registered like this:

myPacketSerial.setPacketHandler(&onPacketReceived);
+

Setting a packet handler will remove all other packet handlers.

+
Parameters
+ + +
onPacketFunctionA pointer to the packet handler function.
+
+
+ +
+
+ +

◆ setPacketHandler() [2/2]

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::setPacketHandler (PacketHandlerFunctionWithSender onPacketFunctionWithSender)
+
+inline
+
+ +

Set the function that will receive decoded packets.

+

This function will be called when data is read from the serial stream connection and a packet is decoded. The decoded packet will be passed to the packet handler. The packet handler must have the form:

+

The packet handler method usually has the form:

void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size);
+

To determine the sender, compare the pointer to the known possible PacketSerial senders.

void onPacketReceived(void* sender, const uint8_t* buffer, size_t size)
+{
+    if (sender == &myPacketSerial)
+    {
+        // Do something with the packet from myPacketSerial.
+    }
+    else if (sender == &myOtherPacketSerial)
+    {
+        // Do something with the packet from myOtherPacketSerial.
+    }
+}
+

The packet handler would then be registered like this:

myPacketSerial.setPacketHandler(&onPacketReceived);
+

Setting a packet handler will remove all other packet handlers.

+
Parameters
+ + +
onPacketFunctionWithSenderA pointer to the packet handler function.
+
+
+ +
+
+ +

◆ setStream()

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::setStream (Stream * stream)
+
+inline
+
+ +

Attach PacketSerial to an existing Arduino Stream.

+

This Stream could be a standard Serial Stream with a non-default configuration such as:

PacketSerial myPacketSerial;
+
+void setup()
+{
+    Serial.begin(300, SERIAL_7N1);
+    myPacketSerial.setStream(&Serial);
+}
+

Or it might be a SoftwareSerial Stream such as:

PacketSerial myPacketSerial;
+SoftwareSerial mySoftwareSerial(10, 11);
+
+void setup()
+{
+    mySoftwareSerial.begin(38400);
+    myPacketSerial.setStream(&mySoftwareSerial);
+}
+

Any class that implements the Stream interface should work, which includes some network objects.

+
Parameters
+ + +
streamA pointer to an Arduino Stream.
+
+
+ +
+
+ +

◆ update()

+ +
+
+
+template<typename EncoderType, uint8_t PacketMarker = 0, size_t ReceiveBufferSize = 256>
+ + + + + +
+ + + + + + + +
void PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::update ()
+
+inline
+
+ +

The update function services the serial connection.

+

This must be called often, ideally once per loop(), e.g.:

void loop()
+{
+    // Other program code.
+
+    myPacketSerial.update();
+}
+
+
+
+
The documentation for this class was generated from the following file: +
+
+ + + + diff --git a/classPacketSerial__.js b/classPacketSerial__.js new file mode 100644 index 0000000..1f65903 --- /dev/null +++ b/classPacketSerial__.js @@ -0,0 +1,18 @@ +var classPacketSerial__ = +[ + [ "PacketHandlerFunction", "classPacketSerial__.html#ac785ebf3c4a6db69410a9f5c0c9e2f93", null ], + [ "PacketHandlerFunctionWithSender", "classPacketSerial__.html#ad5ecd69bb92489c37b10aade1910bfce", null ], + [ "PacketSerial_", "classPacketSerial__.html#a6ceae595e084513c69a04e65ceeda465", null ], + [ "~PacketSerial_", "classPacketSerial__.html#a0895f7e9c6afb25e540cdee47ff3b442", null ], + [ "begin", "classPacketSerial__.html#adc487966aa9ba70927543acb76186f02", null ], + [ "begin", "classPacketSerial__.html#ac7134ee41cd2d0d62baa210d308fd9f2", null ], + [ "begin", "classPacketSerial__.html#a3e86627000aa86b08cc28efa63f29c03", null ], + [ "getStream", "classPacketSerial__.html#ad7fc82f471d87bb25f7fbbed00be4f33", null ], + [ "getStream", "classPacketSerial__.html#ac39ae40250556096c6bacd071637f5bf", null ], + [ "overflow", "classPacketSerial__.html#a2c76159bdebb3af109c4a23274e03e7c", null ], + [ "send", "classPacketSerial__.html#a74b43e5a07e8ef713b0257ee3e249184", null ], + [ "setPacketHandler", "classPacketSerial__.html#a3a6ebc9f594a7eb79414af0dd77a34e9", null ], + [ "setPacketHandler", "classPacketSerial__.html#aa991deb15a468ad9a5a8e315d7c03504", null ], + [ "setStream", "classPacketSerial__.html#aae3f10852c7d878d2f48bdf5d44bbaab", null ], + [ "update", "classPacketSerial__.html#a4085f92c326368720a5e9b28a2933106", null ] +]; \ No newline at end of file diff --git a/classes.html b/classes.html new file mode 100644 index 0000000..d932b68 --- /dev/null +++ b/classes.html @@ -0,0 +1,113 @@ + + + + + + + +PacketSerial: Class Index + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Class Index
+
+
+ + + + + + +
  p  
+
PacketSerial_   
+ +
+
+ + + + diff --git a/closed.png b/closed.png new file mode 100644 index 0000000..98cc2c9 Binary files /dev/null and b/closed.png differ diff --git a/deprecated.html b/deprecated.html new file mode 100644 index 0000000..96ee409 --- /dev/null +++ b/deprecated.html @@ -0,0 +1,111 @@ + + + + + + + +PacketSerial: Deprecated List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Deprecated List
+
+
+
+
Member PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::begin (unsigned long speed, size_t port) __attribute__((deprecated))
+
Use setStream() to configure a non-default port.
+
Member PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >::begin (Stream *stream) __attribute__((deprecated))
+
Use setStream() to configure a non-default port.
+
+
+
+
+ + + + diff --git a/dir_68267d1309a1af8e8297ef4c3efbcdba.html b/dir_68267d1309a1af8e8297ef4c3efbcdba.html new file mode 100644 index 0000000..df506b8 --- /dev/null +++ b/dir_68267d1309a1af8e8297ef4c3efbcdba.html @@ -0,0 +1,105 @@ + + + + + + + +PacketSerial: /home/travis/build/bakercp/PacketSerial/src Directory Reference + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
src Directory Reference
+
+
+
+
+ + + + diff --git a/dir_68267d1309a1af8e8297ef4c3efbcdba.js b/dir_68267d1309a1af8e8297ef4c3efbcdba.js new file mode 100644 index 0000000..4a32d49 --- /dev/null +++ b/dir_68267d1309a1af8e8297ef4c3efbcdba.js @@ -0,0 +1,4 @@ +var dir_68267d1309a1af8e8297ef4c3efbcdba = +[ + [ "PacketSerial.h", "PacketSerial_8h_source.html", null ] +]; \ No newline at end of file diff --git a/doc.png b/doc.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/doc.png differ diff --git a/docs/BACKGROUND.md b/docs/BACKGROUND.md deleted file mode 100644 index a1e4afd..0000000 --- a/docs/BACKGROUND.md +++ /dev/null @@ -1,54 +0,0 @@ -# Background - -_Why do I need this?_ you may ask. The truth is that you may not need it if you are converting your values to ASCII strings and separating them with a known character (like a carriage return `\r` and a line feed `\n`) before sending them. This is what happens if you call and `Serial.println();`. For instance, if you just want to send a byte with the value of 255 and follow it with a new line character (i.e. `Serial.println(255);`) the Arduino automatically converts the number to the equivalent printable ASCII characters, sending 5 bytes total. As a result the receiver won't just receive a byte for the number and two bytes for the carriage return and new line character. Instead it will receive a stream of 5 bytes: - -```console -50 // ASCII '2' -53 // ASCII '5' -53 // ASCII '5' -13 // ASCII '\r' -10 // ASCII '\n' -``` - -The receiver must then collect the 3 ASCII characters { '2', '5', '5' }, combine them and convert them back into a single byte with a value of `255`. This process can get complicated when the user wants to send large quantities of structured data between the Arduino and a receiver. - -One way to send a _packet_ of data without this library is to send each byte separated by a comma or space and terminate the sequence with a new line character. Thus, to send the value `255` and the value `10`, one might call: - -```cpp -Serial.print(255); -Serial.print(','); -Serial.print(10); -Serial.print('\n'); -``` - -The receiver will actually see a stream of 7 bytes: - -```console -50 // ASCII '2' -53 // ASCII '5' -53 // ASCII '5' -44 // ASCII ',' -49 // ASCII '1' -48 // ASCII '0' -10 // ASCII '\n' -``` - -In this case, the receiver must then collect the ASCII characters, combine them, skip the delimiter (the comma in this case) and then process the packet when a new line is encountered. While effective, this method doesn't scale particularly well. Bytes with values larger than 9 are encoded as 2 bytes and bytes with values larger than 99 are encoded as 3 bytes, etc. If the user would like to send the number 4,294,967,295 (the maximum value of a 4 byte `unsigned long`), it would be encoded as 10 bytes. This means that there is an overhead of 6 extra bytes to transmit a 4 byte `unsigned long`. - -An alternative to ASCII encoding is to write the bytes directly to using the `Serial.write()` methods. These methods do not convert the byte values to ASCII. So if the user wants to send a single byte with the value of `255` and follow it with a new line character: - -```cpp -Serial.write(255); -Serial.write('\n'); -``` - -the receiver will see a stream of 2 bytes: - -```console -255 // The value transmitted. -10 // The new line character (\n). -``` - -This is much more compact but can create problems when the user wants to send a _packet_ of data. If the user wants to send a packet consisting of two values such as 255 and 10, we run into problems if we also use the new line (`\n` ASCII 10) character as a packet boundary. This essentially means that the receiver will incorrectly think that a new packet is beginning when it receives the _value_ of 10. Thus, to use this more compact form of sending bytes while reserving one value for a packet boundary marker. Several unambiguous packet boundary marking encodings exist, but one with a small predictable overhead is called [Consistent Overhead Byte Stuffing](http://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing). For a raw packet of length `SIZE`, the maximum encoded buffer size will only be `SIZE + SIZE / 254 + 1`. This is significantly less than ASCII encoding and the encoding / decoding algorithm is simple and fast. In its default mode, the COBS encoding process simply removes all _zeros_ from the packet, allowing the sender and receiver to use the value of _zero_ as a packet boundary marker. - -Another encoding available in `PacketSerial` is [Serial Line Internet Protocol](https://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol) which is often used to send OSC over serial or TCP connections. To use SLIP encoding instead of COBS, use `SLIPPacketSerial` instead of `PacketSerial`. You can find an openFrameworks example of sending OSC data over serial in the [ofxSerial](https://github.com/bakercp/ofxSerial) repository. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md deleted file mode 100644 index 029798a..0000000 --- a/docs/CHANGELOG.md +++ /dev/null @@ -1,102 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -### Added - -- None - -### Changed - -- None - -### Removed - -- None - -### Fixed - -- None - -### Security - -- None - -## [1.4.0] 2019-07-26 - -### Added - -- Added `const Stream* getStream() const` and `Stream* getStream()` methods. Thanks @orgicus. - -### Changed - -- Updated README. - -## [1.3.0] 2019-07-25 - -### Removed - -- Remove the `void begin(unsigned long speed, size_t port)` function. -- Remove the `void begin(Stream* stream)` function. -- `while(!SerialX)` line when `CORE_TEENSY` is defined. This was leading to unexpected behavior where programs would not start until a serial connection was opened. - -### Added - -- Lambda function packetHandler examples and documentation. -- Add `bool overflow() const` to check for a receive buffer overflow. -- Added API documentation @ [http://bakercp.github.io/PacketSerial/](http://bakercp.github.io/PacketSerial/) - -### Changed - -- Updated README.md, fixed spelling error, added links, docs. -- Rewrote SLIP enum in terms of decimal notation for consistency. -- Updated documentation folder, .github structure. -- Updated CI testing. - -## [1.2.0] 2017-11-09 - -### Added - -- An additional PacketHandler pointer type that includes the sender's pointer e.g. `void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size)`. Either functions can be set. Calling `setPacketHandler()` will always remove all previous function pointers. - -### Removed - -- Deprecated all but one basic `void begin(Stream* stream)` function. Use `void setStream(Stream* stream)` instead. -- Reverted void `PacketSerial_::begin(unsigned long speed, uint8_t config, size_t port)`. - -### Changed - -- Updated README.md, fixed errors, spelling and updated examples. - -## [1.1.0] 2017-11-09 - -### Added - -- Additional inline documentation. -- Added doxygen configuration file. -- Added CHANGELOG.md file. -- Added the `void PacketSerial_::begin(unsigned long speed, uint8_t config, size_t port)` method to avoid confusion with the standard `Serial.begin(unsigned long speed, uint8_t config)`. - -### Changed - -- Updated README.md, fixed errors, spelling, byte counts, etc. -- Updated documentation / comments in documentation for clarity. - -### Removed - -- Deprecated the `void begin(unsigned long speed, size_t port)` method because it could be confused with the standard `Serial.begin(unsigned long speed, uint8_t config)` method. - -### Fixed - -- Fixed Duplicated SLIP END Packet #[11](https://github.com/bakercp/PacketSerial/issues/11) -- Fix types to remove warnings in examples. -- Add `const` qualifier to the `send()` method. - -### Security - -- None diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md deleted file mode 100644 index 06e0fe1..0000000 --- a/docs/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,73 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies within all project spaces, and it also applies when -an individual is representing the project or its community in public spaces. -Examples of representing a project or community include using an official -project e-mail address, posting via an official social media account, or acting -as an appointed representative at an online or offline event. Representation of -a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [info@christopherbaker.net](mailto:info@christopherbaker.net?subject=[GitHub]%20Code%20Of%20Conduct). All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][[homepage](https://www.contributor-covenant.org)], version 1.4, -available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html). - -For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md deleted file mode 100644 index 1d16a63..0000000 --- a/docs/CONTRIBUTING.md +++ /dev/null @@ -1,25 +0,0 @@ -# Contributing - -## Code of Conduct - -First, please see the [Code of Conduct](CODE_OF_CONDUCT.md). - -## How to Help - -Check out the [Todo](TODO.md) list to see if there are any planned items. - -Check out the [Help Wanted](../../../issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) tag in the issues section for specific ideas or propose your own new ideas. - -## Making Pull Requests - -Pull Requests are always welcome, so if you make any improvements please feel free to float them back upstream :) - -1. Fork this repository. -2. Create your feature branch (`git checkout -b my-new-feature`). -3. Commit your changes (`git commit -am 'Add some feature'`). -4. Push to the branch (`git push origin my-new-feature`). -5. Create new Pull Request. - -New features should include tests (if possible) to confirm functionality. - -All code should be documented inline using [Doxygen](http://www.doxygen.nl/manual/docblocks.html) documentation. See the project's source for examples of the preferred style. diff --git a/docs/CONTRIBUTORS.md b/docs/CONTRIBUTORS.md deleted file mode 100644 index 9d4d42a..0000000 --- a/docs/CONTRIBUTORS.md +++ /dev/null @@ -1,9 +0,0 @@ -# Contributors - -- Christopher Baker [@bakercp](https://github.com/bakercp) - Primary author. -- Antoine Villeret [@avilleret](https://github.com/avilleret) - SLIP Encoding. -- Anton Viktorov [@latonita](https://github.com/latonita) - Bugfixes. -- [@per1234](https://github.com/per1234) - Metadata. -- George Profenza [@orgicus](https://github.com/orgicus) - API Suggestions. - -_For and up-to-date list of contributors, see [contributors](../graphs/contributors)._ diff --git a/docs/Doxyfile b/docs/Doxyfile deleted file mode 100644 index a4824b1..0000000 --- a/docs/Doxyfile +++ /dev/null @@ -1,18 +0,0 @@ -PROJECT_NAME = PacketSerial -PROJECT_BRIEF = "An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding." -INPUT = ../src \ - . -FILE_PATTERNS = *.c \ - *.cpp \ - *.h \ - *.hpp \ - *.md \ - *.ino \ - *.pde -EXCLUDE = ./html -EXCLUDE_PATTERNS = *.bak -USE_MDFILE_AS_MAINPAGE = README.md -HTML_OUTPUT = html -GENERATE_TREEVIEW = YES -GENERATE_TAGFILE = PacketSerial.xml -GENERATE_LATEX = NO diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md deleted file mode 100644 index 9a7fb6d..0000000 --- a/docs/GETTING_STARTED.md +++ /dev/null @@ -1,268 +0,0 @@ -# Getting Started - -First, it might be worth it to read the [background introduction](BACKGROUND.md). - -## Installation - -This project can be installed using the Arduino IDE. Navigate to the _Tools > Manage Libraries ..._ menu item and search for `PacketSerial`. - -Alternatively, this library can be downloaded or cloned from github and to your Arduino `libraries` folder. - -## Use - -`PacketSerial` class wraps the Arduino `Stream` class to automatically encode and decode byte packets that are sent and received. Typically serial communication uses the default `Serial` object, which implements the `Stream` class. In most cases, `PacketSerial` should be given exclusive access to the serial `Stream` (e.g. for a default setup using `Serial`, users should avoid calling functions like `Serial.print()`, `Serial.write()`, etc directly). Data should be sent via the `send(const uint8_t* buffer, size_t size) const` method and received in a `PacketSerial` callback function (see below). - -## Setup - -### Basic - -To use the default `Serial` object and the default communication settings (usually `SERIAL_8N1`), set up `PacketSerial` like this: - -```cpp -PacketSerial myPacketSerial; - -void setup() -{ - myPacketSerial.begin(9600); - myPacketSerial.setPacketHandler(&onPacketReceived); -} -``` - -### Advanced - -For a non-default Serial connection, a class implementing the `Stream` interface should be configured and then set for the `PacketSerial` instance. - -#### Using A Non-Standard Serial Configuration - -```cpp -PacketSerial myPacketSerial; - -void setup() -{ - Serial.begin(300, SERIAL_7N1); - myPacketSerial.setStream(&Serial); - myPacketSerial.setPacketHandler(&onPacketReceived); -} -``` - -#### Using Secondary Serial Ports (e.g. Serial1, Serial2, etc) - -```cpp -PacketSerial myPacketSerial; - -void setup() -{ - Serial1.begin(9600); - myPacketSerial.setStream(&Serial1); - myPacketSerial.setPacketHandler(&onPacketReceived); -} -``` - -#### Using SoftwareSerial - -```cpp -PacketSerial myPacketSerial; -SoftwareSerial mySoftwareSerial(10, 11); - -void setup() -{ - mySoftwareSerial.begin(38400); - myPacketSerial.setStream(&mySoftwareSerial); - myPacketSerial.setPacketHandler(&onPacketReceived); -} -``` - -#### Other Streams - -Any class that correctly implements the `Stream` interface should work, which includes some network communication objects. - -### Loop - -In order to processing incoming serial packets, the user must call the `update()` method at the end of the `loop()` method. - -```cpp -void loop() -{ - // Your program here. - - - // Call update to receive, decode and process incoming packets. - myPacketSerial.update(); -} - -``` - -### Receiving Packets - -All packets are received via handler functions. A typical handler function would be registered in the `void setup()` function like: - -```cpp -PacketSerial myPacketSerial; - -void setup() -{ - myPacketSerial.begin(9600); - myPacketSerial.setPacketHandler(&onPacketReceived); -} -``` - -The `onPacketReceived` function can take two forms. The simplest looks like this: - -```cpp -void onPacketReceived(const uint8_t* buffer, size_t size) -{ - // Process your decoded incoming packet here. -} -``` - -For more advanced programs with multiple PacketSerial instances and a shared handler, it may be useful to know which PacketSerial instance received the packet. In this case you could define a callback like this: - -```cpp -void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size) -{ - if (sender == &myPacketSerial) - { - // Do something with the packet from myPacketSerial. - } - else if (sender == &myOtherPacketSerial) - { - // Do something with the packet from myOtherPacketSerial. - } -} -``` - -Finally, it is also possible to set arbitrary packet handlers that point to member functions of a given class instance using lambda functions. For example: - -```cpp -// Instances of this class can receive data packets when registered. -class MyClass -{ -public: - void processPacketFromSender(const PacketSerial& sender, const uint8_t* buffer, size_t size) - { - // Just send the buffer back to the sender. - sender.send(buffer, size); - } -}; - - -MyClass myClassInstance; -PacketSerial myPacketSerial; - -void setup() -{ - myPacketSerial.begin(115200); - myPacketSerial.setPacketHandler([](const uint8_t* buffer, size_t size) { - myClassInstance.processPacketFromSender(myPacketSerial, buffer, size); - }); -} -``` - -### Sending Packets - -To send packets call the `send()` method. The send method will take a packet (an array of bytes), encode it, transmit it and send the packet boundary marker. To send the values `255` and `10`, one might do the following: - -```cpp - -// Make an array. -uint8_t myPacket[2] = { 255, 10 }; - -// Send the array. -myPacketSerial.send(myPacket, 2); -``` - -### Multiple Streams - -On boards with multiple serial ports, this strategy can also be used to set up two Serial streams, one for packets and one for debug ASCII (see [this discussion](https://github.com/bakercp/PacketSerial/issues/10) for more). - -### Checking for Receive Buffer Overflows - -In some cases the receive buffer may not be large enough for an incoming encoded packet. - -To check for overflows, call the `receiveBufferOverflowed()` method after calling `update()`. - -For example: - -```cpp -void loop() -{ - // Other program code. - myPacketSerial.update(); - - // Check for a receive buffer overflow. - if (myPacketSerial.overflow()) - { - // Send an alert via a pin (e.g. make an overflow LED) or return a - // user-defined packet to the sender. - // - // Ultimately you may need to just increase your recieve buffer via the - // template parameters. - } -} -``` - -The state of the overflow flag is reset every time a new packet marker is detected, NOT when the `overflow()` method is called. - -### Customizing the PacketSerial Class - -The `PacketSerial_` class is a templated class that allows us to statically set the encoder type, packet marker and buffer size at compile time. - -The the template parameters are as follows: - -```cpp -template -class PacketSerial_ - -(...) -``` - -The `PacketMarker` has a default of `0` while the `BufferSize` has a default of `256` bytes. - -Thus, if you define your class as: - -```cpp -PacketSerial_ myPacketSerial; -``` - -You will use the `COBS` encoder type and a default PacketMarker of `0` and buffer size of `256`. - -Currently there are three default `PacketSerial_` types defined via `typedef` for convenience: - -```cpp -/// \brief A typedef for the default COBS PacketSerial class. -typedef PacketSerial_ PacketSerial; - -/// \brief A typedef for a PacketSerial type with COBS encoding. -typedef PacketSerial_ COBSPacketSerial; - -/// \brief A typedef for a PacketSerial type with SLIP encoding. -typedef PacketSerial_ SLIPPacketSerial; -``` - -### Changing the EncoderType Type - -To use a custom encoding type, the `EncoderType` class must implement the following functions: - -```cpp - static size_t encode(const uint8_t* buffer, size_t size, uint8_t* encodedBuffer); - static size_t decode(const uint8_t* encodedBuffer, size_t size, uint8_t* decodedBuffer); - static size_t getEncodedBufferSize(size_t unencodedBufferSize); -``` - -See the `Encoding/COBS.h` and `Encoding/SLIP.h` for examples and further documentation. - -### Changing the Packet Marker Byte and Receive Buffer Size - -For example, to increase the buffer size for a standard `COBS` encoder to 512, one can defined the templated class like this: - -```cpp -PacketSerial_ myPacketSerial; -``` - -This uses the COBS encoder type, a PacketMarker of 0 and a buffer size of 512. - -Likewise, a custom `SLIP` encoder with a buffer size of 512 bytes would be defined like this: - -```cpp -PacketSerial_ myPacketSerial; -``` \ No newline at end of file diff --git a/docs/SUPPORT.md b/docs/SUPPORT.md deleted file mode 100644 index 98b7f4b..0000000 --- a/docs/SUPPORT.md +++ /dev/null @@ -1,5 +0,0 @@ -# Support - -First, read the [Getting Started](GETTING_STARTED.md) guide and see the [Troubleshooting](TROUBLESHOOTING.md) guide. You might also check and see if there are any [existing issues](../../../issues?utf8=✓&q=is%3Aissue) that are helpful to you. If those don't help and you, create a new [issue](../../../issues). - -Please do not email the author directly with questions. diff --git a/docs/TODO.md b/docs/TODO.md deleted file mode 100644 index 8d5b46b..0000000 --- a/docs/TODO.md +++ /dev/null @@ -1,7 +0,0 @@ -# TODO - -First check out the [Help Wanted](../../../issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) tag in the issues section for specific ideas. - -## Future Plans - -Right now the encoder / decoder works by encoding or decoding a full buffer. SLIP (and COBS?) encoding, for instance, can be encoded / decoded on the fly, allowing for a smaller buffer allocation. https://github.com/CNMAT/OSC uses an "on-the-fly" approach, rather than a large buffer approach. It would be interesting to investigate this. diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md deleted file mode 100644 index c64ad25..0000000 --- a/docs/TROUBLESHOOTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Troubleshooting - -There are no additional _Troubleshooting_ notes at steps time. diff --git a/doxygen.css b/doxygen.css new file mode 100644 index 0000000..e251592 --- /dev/null +++ b/doxygen.css @@ -0,0 +1,1764 @@ +/* The standard CSS for doxygen 1.8.15 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +p.reference, p.definition { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +p.interli { +} + +p.interdd { +} + +p.intertd { +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #FFFFFF; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #FFFFFF; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +ul { + overflow: hidden; /*Fixed: list item bullets overlap floating elements*/ +} + +#side-nav ul { + overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ +} + +#main-nav ul { + overflow: visible; /* reset ul rule for the navigation bar drop down lists */ +} + +.fragment { + text-align: left; + direction: ltr; + overflow-x: auto; /*Fixed: fragment lines overlap floating elements*/ + overflow-y: hidden; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/ + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +div.ah, span.ah { + background-color: black; + font-weight: bold; + color: #FFFFFF; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%); +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl, img.inline { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +blockquote.DocNodeRTL { + border-left: 0; + border-right: 2px solid #9CAFD4; + margin: 0 4px 0 24px; + padding: 0 16px 0 12px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtitle { + padding: 8px; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url('nav_f.png'); + background-repeat: repeat-x; + background-color: #E2E8F2; + line-height: 1.25; + font-weight: 300; + float:left; +} + +.permalink +{ + font-size: 65%; + display: inline-block; + vertical-align: middle; +} + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: 400; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-color: #DFE5F1; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + +} + +.overload { + font-family: "courier new",courier,monospace; + font-size: 65%; +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname, .tparams .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype, .tparams .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir, .tparams .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + font-weight: 400; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +.PageDocRTL-title div.headertitle { + text-align: right; + direction: rtl; +} + +dl { + padding: 0 0 0 0; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */ +dl.section { + margin-left: 0px; + padding-left: 0px; +} + +dl.section.DocNodeRTL { + margin-right: 0px; + padding-right: 0px; +} + +dl.note { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #D0C000; +} + +dl.note.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #FF0000; +} + +dl.warning.DocNodeRTL, dl.attention.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00D000; +} + +dl.pre.DocNodeRTL, dl.post.DocNodeRTL, dl.invariant.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #00D000; +} + +dl.deprecated { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #505050; +} + +dl.deprecated.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #505050; +} + +dl.todo { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00C0E0; +} + +dl.todo.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #00C0E0; +} + +dl.test { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #3030E0; +} + +dl.test.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #3030E0; +} + +dl.bug { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #C08050; +} + +dl.bug.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.plantumlgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +.PageDocRTL-title div.toc { + float: left !important; + text-align: right; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +.PageDocRTL-title div.toc li { + background-position-x: right !important; + padding-left: 0 !important; + padding-right: 10px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.PageDocRTL-title div.toc li.level1 { + margin-left: 0 !important; + margin-right: 0; +} + +.PageDocRTL-title div.toc li.level2 { + margin-left: 0 !important; + margin-right: 15px; +} + +.PageDocRTL-title div.toc li.level3 { + margin-left: 0 !important; + margin-right: 30px; +} + +.PageDocRTL-title div.toc li.level4 { + margin-left: 0 !important; + margin-right: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #FFFFFF; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #FFFFFF; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #FFFFFF; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #FFFFFF; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* @group Markdown */ + +/* +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTableHead tr { +} + +table.markdownTableBodyLeft td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft { + text-align: left +} + +th.markdownTableHeadRight { + text-align: right +} + +th.markdownTableHeadCenter { + text-align: center +} +*/ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + +.DocNodeRTL { + text-align: right; + direction: rtl; +} + +.DocNodeLTR { + text-align: left; + direction: ltr; +} + +table.DocNodeRTL { + width: auto; + margin-right: 0; + margin-left: auto; +} + +table.DocNodeLTR { + width: auto; + margin-right: auto; + margin-left: 0; +} + +tt, code, kbd, samp +{ + display: inline-block; + direction:ltr; +} +/* @end */ + +u { + text-decoration: underline; +} + diff --git a/doxygen.png b/doxygen.png new file mode 100644 index 0000000..3ff17d8 Binary files /dev/null and b/doxygen.png differ diff --git a/dynsections.js b/dynsections.js new file mode 100644 index 0000000..ea0a7b3 --- /dev/null +++ b/dynsections.js @@ -0,0 +1,120 @@ +/* + @licstart The following is the entire license notice for the + JavaScript code in this file. + + Copyright (C) 1997-2017 by Dimitri van Heesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + @licend The above is the entire license notice + for the JavaScript code in this file + */ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} + +function toggleLevel(level) +{ + $('table.directory tr').each(function() { + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l -// -// SPDX-License-Identifier: MIT -// - - -#include - - -// By default, PacketSerial automatically wraps the built-in `Serial` object. -// While it is still possible to use the Serial object directly, it is -// recommended that the user let the PacketSerial object manage all serial -// communication. Thus the user should not call Serial.write(), Serial.print(), -// etc. Additionally the user should not use the serialEvent() framework. -// -// By default, PacketSerial uses COBS encoding and has a 256 byte receive -// buffer. This can be adjusted by the user by replacing `PacketSerial` with -// a variation of the `PacketSerial_` template found in -// PacketSerial.h. -PacketSerial myPacketSerial; - - -void setup() -{ - // We begin communication with our PacketSerial object by setting the - // communication speed in bits / second (baud). - myPacketSerial.begin(115200); - - // If we want to receive packets, we must specify a packet handler function. - // The packet handler is a custom function with a signature like the - // onPacketReceived function below. - myPacketSerial.setPacketHandler(&onPacketReceived); -} - - -void loop() -{ - // Do your program-specific loop() work here as usual. - - // The PacketSerial::update() method attempts to read in any incoming serial - // data and emits received and decoded packets via the packet handler - // function specified by the user in the void setup() function. - // - // The PacketSerial::update() method should be called once per loop(). Failure - // to call the PacketSerial::update() frequently enough may result in buffer - // serial overflows. - myPacketSerial.update(); - - // Check for a receive buffer overflow (optional). - if (myPacketSerial.overflow()) - { - // Send an alert via a pin (e.g. make an overflow LED) or return a - // user-defined packet to the sender. - // - // Ultimately you may need to just increase your recieve buffer via the - // template parameters (see the README.md). - } -} - -// This is our handler callback function. -// When an encoded packet is received and decoded, it will be delivered here. -// The `buffer` is a pointer to the decoded byte array. `size` is the number of -// bytes in the `buffer`. -void onPacketReceived(const uint8_t* buffer, size_t size) -{ - // In this example, we will simply reverse the contents of the array and send - // it back to the sender. - - // Make a temporary buffer. - uint8_t tempBuffer[size]; - - // Copy the packet into our temporary buffer. - memcpy(tempBuffer, buffer, size); - - // Reverse our temporaray buffer. - reverse(tempBuffer, size); - - // Send the reversed buffer back to the sender. The send() method will encode - // the whole buffer as as single packet, set packet markers, etc. - // The `tempBuffer` is a pointer to the `tempBuffer` array and `size` is the - // number of bytes to send in the `tempBuffer`. - myPacketSerial.send(tempBuffer, size); -} - -// This function takes a byte buffer and reverses it. -void reverse(uint8_t* buffer, size_t size) -{ - uint8_t tmp; - - for (size_t i = 0; i < size / 2; i++) - { - tmp = buffer[i]; - buffer[i] = buffer[size - i - 1]; - buffer[size - i - 1] = tmp; - } -} diff --git a/examples/PacketSerialReverseEchoAdvanced/.esp32.test.skip b/examples/PacketSerialReverseEchoAdvanced/.esp32.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/PacketSerialReverseEchoAdvanced/.m4.test.skip b/examples/PacketSerialReverseEchoAdvanced/.m4.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/PacketSerialReverseEchoAdvanced/.zero.test.skip b/examples/PacketSerialReverseEchoAdvanced/.zero.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/PacketSerialReverseEchoAdvanced/PacketSerialReverseEchoAdvanced.ino b/examples/PacketSerialReverseEchoAdvanced/PacketSerialReverseEchoAdvanced.ino deleted file mode 100644 index 99f68e3..0000000 --- a/examples/PacketSerialReverseEchoAdvanced/PacketSerialReverseEchoAdvanced.ino +++ /dev/null @@ -1,139 +0,0 @@ -// -// Copyright (c) 2012 Christopher Baker -// -// SPDX-License-Identifier: MIT -// - - -#include -#include - - -// Instances of this class can recieve data packets when registered. -class MyClass -{ -public: - void processPacketFromSender(const PacketSerial& sender, const uint8_t* buffer, size_t size) - { - // Just send the buffer back to the sender. - sender.send(buffer, size); - } -}; - -// By default, PacketSerial automatically wraps the built-in `Serial` object. -// While it is still possible to use the Serial object directly, it is -// recommended that the user let the PacketSerial object manage all serial -// communication. Thus the user should not call Serial.write(), Serial.print(), -// etc. Additionally the user should not use the serialEvent() framework. -// -// By default, PacketSerial uses COBS encoding and has a 256 byte receive -// buffer. This can be adjusted by the user by replacing `PacketSerial` with -// a variation of the `PacketSerial_` template found in -// PacketSerial.h. -PacketSerial myPacketSerial; - - -// Note that SoftwareSerial is not compatible with SAMD_ZERO - -// An additional PacketSerial instance. -SoftwareSerial mySoftwareSerial(10, 11); -PacketSerial myOtherPacketSerial; - -// An instance of our custom class. -MyClass myClassInstance; - -void setup() -{ - // We begin communication with our PacketSerial object by setting the - // communication speed in bits / second (baud). - myPacketSerial.begin(115200); - - // If we want to receive packets, we must specify a packet handler function. - // The packet handler is a custom function with a signature like the - // onPacketReceived function below. - myPacketSerial.setPacketHandler(&onPacketReceived); - - // Set up a scond custom Serial connection on Serial1. - mySoftwareSerial.begin(9600); - myOtherPacketSerial.setStream(&mySoftwareSerial); - - // Here we set the packet handler to be a member of the given instance of - // MyClass using a lambda function. Static variables (e.g. myClassInstance) - // don't need to be captured. Additionally the member function of MyClass - // that processes the packet isn't required to match the packet handler - // function signature. - myOtherPacketSerial.setPacketHandler([](const uint8_t* buffer, size_t size) { - myClassInstance.processPacketFromSender(myOtherPacketSerial, buffer, size); - }); -} - - -void loop() -{ - // Do your program-specific loop() work here as usual. - - // The PacketSerial::update() method attempts to read in any incoming serial - // data and emits received and decoded packets via the packet handler - // function specified by the user in the void setup() function. - // - // The PacketSerial::update() method should be called once per loop(). Failure - // to call the PacketSerial::update() frequently enough may result in buffer - // serial overflows. - myPacketSerial.update(); - - // Check for a receive buffer overflow (optional). - if (myPacketSerial.overflow()) - { - // Send an alert via a pin (e.g. make an overflow LED) or return a - // user-defined packet to the sender. - // - // Ultimately you may need to just increase your recieve buffer via the - // template parameters (see the README.md). - } -} - -// This is our handler callback function. -// When an encoded packet is received and decoded, it will be delivered here. -// The sender is a pointer to the sending PacketSerial instance. The `buffer` is -// a pointer to the decoded byte array. `size` is the number of bytes in the -// `buffer`. -void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size) -{ - if (sender == &myPacketSerial) - { - // In this example, we will simply reverse the contents of the array and send - // it back to the sender. - // Make a temporary buffer. - uint8_t tempBuffer[size]; - - // Copy the packet into our temporary buffer. - memcpy(tempBuffer, buffer, size); - - // Reverse our temporaray buffer. - reverse(tempBuffer, size); - - // Send the reversed buffer back to the sender. The send() method will encode - // the whole buffer as as single packet, set packet markers, etc. - // The `tempBuffer` is a pointer to the `tempBuffer` array and `size` is the - // number of bytes to send in the `tempBuffer`. - myPacketSerial.send(tempBuffer, size); - } - else if (sender == &myOtherPacketSerial) - { - // Just send it back without reversing it. - myOtherPacketSerial.send(buffer, size); - } -} - -// This function takes a byte buffer and reverses it. -void reverse(uint8_t* buffer, size_t size) -{ - uint8_t tmp; - - for (size_t i = 0; i < size / 2; i++) - { - tmp = buffer[i]; - buffer[i] = buffer[size - i - 1]; - buffer[size - i - 1] = tmp; - } -} diff --git a/examples/PacketSerialReverseEchoAdvanced/README.md b/examples/PacketSerialReverseEchoAdvanced/README.md deleted file mode 100644 index be267dc..0000000 --- a/examples/PacketSerialReverseEchoAdvanced/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Note - -This example will not compile on boards that don't support `SoftwareSerial`. This includes DUE, Zero, etc. - -That said, the concept of setting a custom `Stream` output will apply to any `Stream` supported by those boards. diff --git a/examples/PacketSerialReverseEchoClass/PacketSerialReverseEchoClass.ino b/examples/PacketSerialReverseEchoClass/PacketSerialReverseEchoClass.ino deleted file mode 100644 index 59744f3..0000000 --- a/examples/PacketSerialReverseEchoClass/PacketSerialReverseEchoClass.ino +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (c) 2012 Christopher Baker -// -// SPDX-License-Identifier: MIT -// - -// This example is PacketSerialReverseEcho modified to use PacketSerial from within a class - -#include - -// This function takes a byte buffer and reverses it. -void reverse(uint8_t* buffer, size_t size) -{ - uint8_t tmp; - - for (size_t i = 0; i < size / 2; i++) - { - tmp = buffer[i]; - buffer[i] = buffer[size - i - 1]; - buffer[size - i - 1] = tmp; - } -} - -class EchoClass { - public: - void begin(unsigned long speed) { - // If we want to receive packets, we must specify a packet handler function. - // The packet handler is a custom function with a signature like the - // onPacketReceived function below. - myPacketSerial.setPacketHandler(&onPacketReceived, this); - - myPacketSerial.begin(speed); - } - - void loop() { - // The PacketSerial::update() method attempts to read in any incoming serial - // data and emits received and decoded packets via the packet handler - // function specified by the user in the void setup() function. - // - // The PacketSerial::update() method should be called once per loop(). Failure - // to call the PacketSerial::update() frequently enough may result in buffer - // serial overflows. - myPacketSerial.update(); - - // Check for a receive buffer overflow (optional). - if (myPacketSerial.overflow()) - { - // Send an alert via a pin (e.g. make an overflow LED) or return a - // user-defined packet to the sender. - // - // Ultimately you may need to just increase your recieve buffer via the - // template parameters (see the README.md). - } - } - - private: - // C-style callbacks can't use non-static methods, so we use a static method that receives "this" as the sender argument: https://wiki.c2.com/?VirtualStaticIdiom - static void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size) { - ((EchoClass*)sender)->onPacketReceived(buffer, size); - } - - // This is our handler callback function. - // When an encoded packet is received and decoded, it will be delivered here. - // The `buffer` is a pointer to the decoded byte array. `size` is the number of - // bytes in the `buffer`. - void onPacketReceived(const uint8_t* buffer, size_t size) { - // In this example, we will simply reverse the contents of the array and send - // it back to the sender. - - // Make a temporary buffer. - uint8_t tempBuffer[size]; - - // Copy the packet into our temporary buffer. - memcpy(tempBuffer, buffer, size); - - // Reverse our temporaray buffer. - reverse(tempBuffer, size); - - // Send the reversed buffer back to the sender. The send() method will encode - // the whole buffer as as single packet, set packet markers, etc. - // The `tempBuffer` is a pointer to the `tempBuffer` array and `size` is the - // number of bytes to send in the `tempBuffer`. - myPacketSerial.send(tempBuffer, size); - } - - PacketSerial myPacketSerial; -}; - -// By default, PacketSerial automatically wraps the built-in `Serial` object. -// While it is still possible to use the Serial object directly, it is -// recommended that the user let the PacketSerial object manage all serial -// communication. Thus the user should not call Serial.write(), Serial.print(), -// etc. Additionally the user should not use the serialEvent() framework. -// -// By default, PacketSerial uses COBS encoding and has a 256 byte receive -// buffer. This can be adjusted by the user by replacing `PacketSerial` with -// a variation of the `PacketSerial_` template found in -// PacketSerial.h. - -EchoClass myEchoClass; - -void setup() -{ - // We begin communication with our PacketSerial object by setting the - // communication speed in bits / second (baud). - myEchoClass.begin(115200); -} - - -void loop() -{ - // Do your program-specific loop() work here as usual. - - myEchoClass.loop(); -} diff --git a/examples/PacketSerialReverseEchoSLIP/PacketSerialReverseEchoSLIP.ino b/examples/PacketSerialReverseEchoSLIP/PacketSerialReverseEchoSLIP.ino deleted file mode 100644 index 15cfb8a..0000000 --- a/examples/PacketSerialReverseEchoSLIP/PacketSerialReverseEchoSLIP.ino +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (c) 2012 Christopher Baker -// -// SPDX-License-Identifier: MIT -// - - -#include - - -// By default, PacketSerial automatically wraps the built-in `Serial` object. -// While it is still possible to use the Serial object directly, it is -// recommended that the user let the PacketSerial object manage all serial -// communication. Thus the user should not call Serial.write(), Serial.print(), -// etc. Additionally the user should not use the serialEvent() framework. -// -// By default, SLIPPacketSerial uses SLIP encoding and has a 256 byte receive -// buffer. This can be adjusted by the user by replacing `SLIPPacketSerial` -// with a variation of the `PacketSerial_` template -// found in PacketSerial.h. -SLIPPacketSerial myPacketSerial; - - -void setup() -{ - // We begin communication with our PacketSerial object by setting the - // communication speed in bits / second (baud). - myPacketSerial.begin(115200); - - // If we want to receive packets, we must specify a packet handler function. - // The packet handler is a custom function with a signature like the - // onPacketReceived function below. - myPacketSerial.setPacketHandler(&onPacketReceived); -} - - -void loop() -{ - // Do your program-specific loop() work here as usual. - - // The PacketSerial::update() method attempts to read in any incoming serial - // data and emits received and decoded packets via the packet handler - // function specified by the user in the void setup() function. - // - // The PacketSerial::update() method should be called once per loop(). Failure - // to call the PacketSerial::update() frequently enough may result in buffer - // serial overflows. - myPacketSerial.update(); - - // Check for a receive buffer overflow (optional). - if (myPacketSerial.overflow()) - { - // Send an alert via a pin (e.g. make an overflow LED) or return a - // user-defined packet to the sender. - // - // Ultimately you may need to just increase your recieve buffer via the - // template parameters (see the README.md). - } -} - -// This is our handler callback function. -// When an encoded packet is received and decoded, it will be delivered here. -// The `buffer` is a pointer to the decoded byte array. `size` is the number of -// bytes in the `buffer`. -void onPacketReceived(const uint8_t* buffer, size_t size) -{ - // In this example, we will simply reverse the contents of the array and send - // it back to the sender. - - // Make a temporary buffer. - uint8_t tempBuffer[size]; - - // Copy the packet into our temporary buffer. - memcpy(tempBuffer, buffer, size); - - // Reverse our temporaray buffer. - reverse(tempBuffer, size); - - // Send the reversed buffer back to the sender. The send() method will encode - // the whole buffer as as single packet, set packet markers, etc. - // The `tempBuffer` is a pointer to the `tempBuffer` array and `size` is the - // number of bytes to send in the `tempBuffer`. - myPacketSerial.send(tempBuffer, size); -} - -// This function takes a byte buffer and reverses it. -void reverse(uint8_t* buffer, size_t size) -{ - uint8_t tmp; - - for (size_t i = 0; i < size / 2; i++) - { - tmp = buffer[i]; - buffer[i] = buffer[size - i - 1]; - buffer[size - i - 1] = tmp; - } -} diff --git a/files.html b/files.html new file mode 100644 index 0000000..4476caa --- /dev/null +++ b/files.html @@ -0,0 +1,110 @@ + + + + + + + +PacketSerial: File List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+
[detail level 12]
+ + +
  src
 PacketSerial.h
+
+
+
+ + + + diff --git a/files_dup.js b/files_dup.js new file mode 100644 index 0000000..c3b39c4 --- /dev/null +++ b/files_dup.js @@ -0,0 +1,4 @@ +var files_dup = +[ + [ "src", "dir_68267d1309a1af8e8297ef4c3efbcdba.html", "dir_68267d1309a1af8e8297ef4c3efbcdba" ] +]; \ No newline at end of file diff --git a/folderclosed.png b/folderclosed.png new file mode 100644 index 0000000..bb8ab35 Binary files /dev/null and b/folderclosed.png differ diff --git a/folderopen.png b/folderopen.png new file mode 100644 index 0000000..d6c7f67 Binary files /dev/null and b/folderopen.png differ diff --git a/functions.html b/functions.html new file mode 100644 index 0000000..6752a7f --- /dev/null +++ b/functions.html @@ -0,0 +1,135 @@ + + + + + + + +PacketSerial: Class Members + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ + + + + + diff --git a/functions_func.html b/functions_func.html new file mode 100644 index 0000000..310a17d --- /dev/null +++ b/functions_func.html @@ -0,0 +1,129 @@ + + + + + + + +PacketSerial: Class Members - Functions + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ + + + + + diff --git a/functions_type.html b/functions_type.html new file mode 100644 index 0000000..7077752 --- /dev/null +++ b/functions_type.html @@ -0,0 +1,108 @@ + + + + + + + +PacketSerial: Class Members - Typedefs + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ + +
+ + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..8a15880 --- /dev/null +++ b/index.html @@ -0,0 +1,133 @@ + + + + + + + +PacketSerial: PacketSerial + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
PacketSerial
+
+
+

Build Status +

+

An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.

+

Features

+

PacketSerial is an small, efficient, library that allows Arduinos to send and receive serial data packets (with COBS, SLIP or a user-defined encoding) that include bytes of any value (0 - 255). A packet is simply an array of bytes.

+

Documentation

+

If you're asking Why do I need this?, read the background introduction page. If you're ready to get started, check out the getting started page. You can also learn a lot by reading through the examples. Finally, if you're interested in learning more about how the code works, read the comments in the source code and check out the API documentation.

+

Support

+

If you're looking for help, read the support page.

+

Compatibility

+

Requrements

+ +

Other Platforms

+

This project has been used successfully with openFrameworks using the ofxSerial addon. In particular, see the ofx::IO::PacketSerial object. Additionally this project has been used with Python using the PySerial package. In particular, check out the COBS (see this discussion) and SLIP packages.

+

Ultimately, any library that correctly implements a COBS or SLIP encoding scheme should be compatible with this project.

+

Continuous Integration

+

Continuous integration tests are carried out on a variety of common Arduino platforms. See this script for a list.

+

Licensing

+

This project is licensed under the MIT License.

+

Project Management

+

Repository

+

https://github.com/bakercp/PacketSerial

+

Contributing

+

If you'd like to contribute to this project, please check out the Code of Conduct and the contributing guide.

+

Versioning

+

This project uses Semantic Versioning. You can check out recent changes in the changelog.

+
+
+
+ + + + diff --git a/jquery.js b/jquery.js new file mode 100644 index 0000000..1ee895c --- /dev/null +++ b/jquery.js @@ -0,0 +1,87 @@ +/*! + * jQuery JavaScript Library v1.7.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Wed Mar 21 12:46:34 2012 -0700 + */ +(function(bd,L){var av=bd.document,bu=bd.navigator,bm=bd.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bd.jQuery,bH=bd.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bd.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bd.attachEvent("onload",bF.ready);var b0=false;try{b0=bd.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0!=null&&b0==b0.window},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bd.JSON&&bd.JSON.parse){return bd.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){if(typeof b2!=="string"||!b2){return null}var b0,b1;try{if(bd.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bd.execScript||function(b1){bd["eval"].call(bd,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aK.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aK.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bH=bv.getElementsByTagName("*");bE=bv.getElementsByTagName("a")[0];if(!bH||!bH.length||!bE){return{}}bF=av.createElement("select");bx=bF.appendChild(av.createElement("option"));bD=bv.getElementsByTagName("input")[0];bI={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bE.getAttribute("style")),hrefNormalized:(bE.getAttribute("href")==="/a"),opacity:/^0.55/.test(bE.style.opacity),cssFloat:!!bE.style.cssFloat,checkOn:(bD.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true,pixelMargin:true};b.boxModel=bI.boxModel=(av.compatMode==="CSS1Compat");bD.checked=true;bI.noCloneChecked=bD.cloneNode(true).checked;bF.disabled=true;bI.optDisabled=!bx.disabled;try{delete bv.test}catch(bB){bI.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bI.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bD=av.createElement("input");bD.value="t";bD.setAttribute("type","radio");bI.radioValue=bD.value==="t";bD.setAttribute("checked","checked");bD.setAttribute("name","t");bv.appendChild(bD);bC=av.createDocumentFragment();bC.appendChild(bv.lastChild);bI.checkClone=bC.cloneNode(true).cloneNode(true).lastChild.checked;bI.appendChecked=bD.checked;bC.removeChild(bD);bC.appendChild(bv);if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bA="on"+by;bw=(bA in bv);if(!bw){bv.setAttribute(bA,"return;");bw=(typeof bv[bA]==="function")}bI[by+"Bubbles"]=bw}}bC.removeChild(bv);bC=bF=bx=bv=bD=null;b(function(){var bM,bV,bW,bU,bO,bP,bR,bL,bK,bQ,bN,e,bT,bS=av.getElementsByTagName("body")[0];if(!bS){return}bL=1;bT="padding:0;margin:0;border:";bN="position:absolute;top:0;left:0;width:1px;height:1px;";e=bT+"0;visibility:hidden;";bK="style='"+bN+bT+"5px solid #000;";bQ="
";bM=av.createElement("div");bM.style.cssText=e+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bS.insertBefore(bM,bS.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bI.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);if(bd.getComputedStyle){bv.innerHTML="";bR=av.createElement("div");bR.style.width="0";bR.style.marginRight="0";bv.style.width="2px";bv.appendChild(bR);bI.reliableMarginRight=(parseInt((bd.getComputedStyle(bR,null)||{marginRight:0}).marginRight,10)||0)===0}if(typeof bv.style.zoom!=="undefined"){bv.innerHTML="";bv.style.width=bv.style.padding="1px";bv.style.border=0;bv.style.overflow="hidden";bv.style.display="inline";bv.style.zoom=1;bI.inlineBlockNeedsLayout=(bv.offsetWidth===3);bv.style.display="block";bv.style.overflow="visible";bv.innerHTML="
";bI.shrinkWrapBlocks=(bv.offsetWidth!==3)}bv.style.cssText=bN+e;bv.innerHTML=bQ;bV=bv.firstChild;bW=bV.firstChild;bO=bV.nextSibling.firstChild.firstChild;bP={doesNotAddBorder:(bW.offsetTop!==5),doesAddBorderForTableAndCells:(bO.offsetTop===5)};bW.style.position="fixed";bW.style.top="20px";bP.fixedPosition=(bW.offsetTop===20||bW.offsetTop===15);bW.style.position=bW.style.top="";bV.style.overflow="hidden";bV.style.position="relative";bP.subtractsBorderForOverflowNotVisible=(bW.offsetTop===-5);bP.doesNotIncludeMarginInBodyOffset=(bS.offsetTop!==bL);if(bd.getComputedStyle){bv.style.marginTop="1%";bI.pixelMargin=(bd.getComputedStyle(bv,null)||{marginTop:0}).marginTop!=="1%"}if(typeof bM.style.zoom!=="undefined"){bM.style.zoom=1}bS.removeChild(bM);bR=bv=bM=null;b.extend(bI,bP)});return bI})();var aT=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA1,null,false)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function a6(bx,bw,by){if(by===L&&bx.nodeType===1){var bv="data-"+bw.replace(aA,"-$1").toLowerCase();by=bx.getAttribute(bv);if(typeof by==="string"){try{by=by==="true"?true:by==="false"?false:by==="null"?null:b.isNumeric(by)?+by:aT.test(by)?b.parseJSON(by):by}catch(bz){}b.data(bx,bw,by)}else{by=L}}return by}function S(bv){for(var e in bv){if(e==="data"&&b.isEmptyObject(bv[e])){continue}if(e!=="toJSON"){return false}}return true}function bj(by,bx,bA){var bw=bx+"defer",bv=bx+"queue",e=bx+"mark",bz=b._data(by,bw);if(bz&&(bA==="queue"||!b._data(by,bv))&&(bA==="mark"||!b._data(by,e))){setTimeout(function(){if(!b._data(by,bv)&&!b._data(by,e)){b.removeData(by,bw,true);bz.fire()}},0)}}b.extend({_mark:function(bv,e){if(bv){e=(e||"fx")+"mark";b._data(bv,e,(b._data(bv,e)||0)+1)}},_unmark:function(by,bx,bv){if(by!==true){bv=bx;bx=by;by=false}if(bx){bv=bv||"fx";var e=bv+"mark",bw=by?0:((b._data(bx,e)||1)-1);if(bw){b._data(bx,e,bw)}else{b.removeData(bx,e,true);bj(bx,bv,"mark")}}},queue:function(bv,e,bx){var bw;if(bv){e=(e||"fx")+"queue";bw=b._data(bv,e);if(bx){if(!bw||b.isArray(bx)){bw=b._data(bv,e,b.makeArray(bx))}else{bw.push(bx)}}return bw||[]}},dequeue:function(by,bx){bx=bx||"fx";var bv=b.queue(by,bx),bw=bv.shift(),e={};if(bw==="inprogress"){bw=bv.shift()}if(bw){if(bx==="fx"){bv.unshift("inprogress")}b._data(by,bx+".run",e);bw.call(by,function(){b.dequeue(by,bx)},e)}if(!bv.length){b.removeData(by,bx+"queue "+bx+".run",true);bj(by,bx,"queue")}}});b.fn.extend({queue:function(e,bv){var bw=2;if(typeof e!=="string"){bv=e;e="fx";bw--}if(arguments.length1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,bv){return b.access(this,b.prop,e,bv,arguments.length>1)},removeProp:function(e){e=b.propFix[e]||e;return this.each(function(){try{this[e]=L;delete this[e]}catch(bv){}})},addClass:function(by){var bA,bw,bv,bx,bz,bB,e;if(b.isFunction(by)){return this.each(function(bC){b(this).addClass(by.call(this,bC,this.className))})}if(by&&typeof by==="string"){bA=by.split(ag);for(bw=0,bv=this.length;bw-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.type]||b.valHooks[bw.nodeName.toLowerCase()];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aV,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aZ:bf)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(by,bA){var bz,bB,bw,e,bv,bx=0;if(bA&&by.nodeType===1){bB=bA.toLowerCase().split(ag);e=bB.length;for(;bx=0)}}})});var be=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/(?:^|\s)hover(\.\S+)?\b/,aP=/^key/,bg=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler;by=bv.selector}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bd,bI])}}for(bC=0;bCbC){bv.push({elem:this,matches:bD.slice(bC)})}for(bJ=0;bJ0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aP.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bg.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}bE.match.globalPOS=bD;var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(B(bx[0])||B(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function B(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||bb.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aH(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aS.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aS="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ah=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,v=/]","i"),o=/checked\s*(?:[^=]|=\s*.checked.)/i,bn=/\/(java|ecma)script/i,aO=/^\s*",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){return b.access(this,function(bv){return bv===L?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(bv))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(e){return b.access(this,function(by){var bx=this[0]||{},bw=0,bv=this.length;if(by===L){return bx.nodeType===1?bx.innerHTML.replace(ah,""):null}if(typeof by==="string"&&!ae.test(by)&&(b.support.leadingWhitespace||!ar.test(by))&&!ax[(d.exec(by)||["",""])[1].toLowerCase()]){by=by.replace(R,"<$1>");try{for(;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bh(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function D(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function am(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||b.isXMLDoc(by)||!ai.test("<"+by.nodeName+">")?by.cloneNode(true):am(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){aj(by,bz);e=bh(by);bv=bh(bz);for(bx=0;e[bx];++bx){if(bv[bx]){aj(e[bx],bv[bx])}}}if(bA){s(by,bz);if(bw){e=bh(by);bv=bh(bz);for(bx=0;e[bx];++bx){s(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bI,bw,bv,bx){var bA,bH,bD,bJ=[];bw=bw||av;if(typeof bw.createElement==="undefined"){bw=bw.ownerDocument||bw[0]&&bw[0].ownerDocument||av}for(var bE=0,bG;(bG=bI[bE])!=null;bE++){if(typeof bG==="number"){bG+=""}if(!bG){continue}if(typeof bG==="string"){if(!W.test(bG)){bG=bw.createTextNode(bG)}else{bG=bG.replace(R,"<$1>");var bN=(d.exec(bG)||["",""])[1].toLowerCase(),bz=ax[bN]||ax._default,bK=bz[0],bB=bw.createElement("div"),bL=ac.childNodes,bM;if(bw===av){ac.appendChild(bB)}else{a(bw).appendChild(bB)}bB.innerHTML=bz[1]+bG+bz[2];while(bK--){bB=bB.lastChild}if(!b.support.tbody){var by=v.test(bG),e=bN==="table"&&!by?bB.firstChild&&bB.firstChild.childNodes:bz[1]===""&&!by?bB.childNodes:[];for(bD=e.length-1;bD>=0;--bD){if(b.nodeName(e[bD],"tbody")&&!e[bD].childNodes.length){e[bD].parentNode.removeChild(e[bD])}}}if(!b.support.leadingWhitespace&&ar.test(bG)){bB.insertBefore(bw.createTextNode(ar.exec(bG)[0]),bB.firstChild)}bG=bB.childNodes;if(bB){bB.parentNode.removeChild(bB);if(bL.length>0){bM=bL[bL.length-1];if(bM&&bM.parentNode){bM.parentNode.removeChild(bM)}}}}}var bF;if(!b.support.appendChecked){if(bG[0]&&typeof(bF=bG.length)==="number"){for(bD=0;bD1)};b.extend({cssHooks:{opacity:{get:function(bw,bv){if(bv){var e=Z(bw,"opacity");return e===""?"1":e}else{return bw.style.opacity}}}},cssNumber:{fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(bx,bw,bD,by){if(!bx||bx.nodeType===3||bx.nodeType===8||!bx.style){return}var bB,bC,bz=b.camelCase(bw),bv=bx.style,bE=b.cssHooks[bz];bw=b.cssProps[bz]||bz;if(bD!==L){bC=typeof bD;if(bC==="string"&&(bB=I.exec(bD))){bD=(+(bB[1]+1)*+bB[2])+parseFloat(b.css(bx,bw));bC="number"}if(bD==null||bC==="number"&&isNaN(bD)){return}if(bC==="number"&&!b.cssNumber[bz]){bD+="px"}if(!bE||!("set" in bE)||(bD=bE.set(bx,bD))!==L){try{bv[bw]=bD}catch(bA){}}}else{if(bE&&"get" in bE&&(bB=bE.get(bx,false,by))!==L){return bB}return bv[bw]}},css:function(by,bx,bv){var bw,e;bx=b.camelCase(bx);e=b.cssHooks[bx];bx=b.cssProps[bx]||bx;if(bx==="cssFloat"){bx="float"}if(e&&"get" in e&&(bw=e.get(by,true,bv))!==L){return bw}else{if(Z){return Z(by,bx)}}},swap:function(by,bx,bz){var e={},bw,bv;for(bv in bx){e[bv]=by.style[bv];by.style[bv]=bx[bv]}bw=bz.call(by);for(bv in bx){by.style[bv]=e[bv]}return bw}});b.curCSS=b.css;if(av.defaultView&&av.defaultView.getComputedStyle){aJ=function(bA,bw){var bv,bz,e,by,bx=bA.style;bw=bw.replace(y,"-$1").toLowerCase();if((bz=bA.ownerDocument.defaultView)&&(e=bz.getComputedStyle(bA,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(bA.ownerDocument.documentElement,bA)){bv=b.style(bA,bw)}}if(!b.support.pixelMargin&&e&&aE.test(bw)&&a1.test(bv)){by=bx.width;bx.width=bv;bv=e.width;bx.width=by}return bv}}if(av.documentElement.currentStyle){aY=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv==null&&bx&&(by=bx[bw])){bv=by}if(a1.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":bv;bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aJ||aY;function af(by,bw,bv){var bz=bw==="width"?by.offsetWidth:by.offsetHeight,bx=bw==="width"?1:0,e=4;if(bz>0){if(bv!=="border"){for(;bx=1&&b.trim(bw.replace(al,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=al.test(bw)?bw.replace(al,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bv,e){return b.swap(bv,{display:"inline-block"},function(){if(e){return Z(bv,"margin-right")}else{return bv.style.marginRight}})}}}});if(b.expr&&b.expr.filters){b.expr.filters.hidden=function(bw){var bv=bw.offsetWidth,e=bw.offsetHeight;return(bv===0&&e===0)||(!b.support.reliableHiddenOffsets&&((bw.style&&bw.style.display)||b.css(bw,"display"))==="none")};b.expr.filters.visible=function(e){return !b.expr.filters.hidden(e)}}b.each({margin:"",padding:"",border:"Width"},function(e,bv){b.cssHooks[e+bv]={expand:function(by){var bx,bz=typeof by==="string"?by.split(" "):[by],bw={};for(bx=0;bx<4;bx++){bw[e+G[bx]+bv]=bz[bx]||bz[bx-2]||bz[0]}return bw}}});var k=/%20/g,ap=/\[\]$/,bs=/\r?\n/g,bq=/#.*$/,aD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,a0=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,aN=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,aR=/^(?:GET|HEAD)$/,c=/^\/\//,M=/\?/,a7=/)<[^<]*)*<\/script>/gi,p=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,z=b.fn.load,aa={},q={},aF,r,aW=["*/"]+["*"];try{aF=bm.href}catch(aw){aF=av.createElement("a");aF.href="";aF=aF.href}r=K.exec(aF.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a7,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||p.test(this.nodeName)||a0.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){an(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}an(bv,e);return bv},ajaxSettings:{url:aF,isLocal:aN.test(r[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bd.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(q),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bk(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=F(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,r[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=r[1]||bI[2]!=r[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(r[3]||(r[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aX(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aR.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aW+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aX(q,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){u(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function u(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{u(bw+"["+(typeof bz==="object"?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&b.type(by)==="object"){for(var e in by){u(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bk(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function F(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!ba){ba=av.createElement("iframe");ba.frameBorder=ba.width=ba.height=0}e.appendChild(ba);if(!m||!ba.createElement){m=(ba.contentWindow||ba.contentDocument).document;m.write((b.support.boxModel?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(ba)}Q[bx]=bw}return Q[bx]}var a8,V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){a8=function(by,bH,bw,bB){try{bB=by.getBoundingClientRect()}catch(bF){}if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aL(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{a8=function(bz,bE,bx){var bC,bw=bz.offsetParent,bv=bz,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.fn.offset=function(e){if(arguments.length){return e===L?this:this.each(function(bx){b.offset.setOffset(this,e,bx)})}var bv=this[0],bw=bv&&bv.ownerDocument;if(!bw){return null}if(bv===bw.body){return b.offset.bodyOffset(bv)}return a8(bv,bw,bw.documentElement)};b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(bw,bv){var e=/Y/.test(bv);b.fn[bw]=function(bx){return b.access(this,function(by,bB,bA){var bz=aL(by);if(bA===L){return bz?(bv in bz)?bz[bv]:b.support.boxModel&&bz.document.documentElement[bB]||bz.document.body[bB]:by[bB]}if(bz){bz.scrollTo(!e?bA:b(bz).scrollLeft(),e?bA:b(bz).scrollTop())}else{by[bB]=bA}},bw,bx,arguments.length,null)}});function aL(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each({Height:"height",Width:"width"},function(bw,bx){var bv="client"+bw,e="scroll"+bw,by="offset"+bw;b.fn["inner"+bw]=function(){var bz=this[0];return bz?bz.style?parseFloat(b.css(bz,bx,"padding")):this[bx]():null};b.fn["outer"+bw]=function(bA){var bz=this[0];return bz?bz.style?parseFloat(b.css(bz,bx,bA?"margin":"border")):this[bx]():null};b.fn[bx]=function(bz){return b.access(this,function(bC,bB,bD){var bF,bE,bG,bA;if(b.isWindow(bC)){bF=bC.document;bE=bF.documentElement[bv];return b.support.boxModel&&bE||bF.body&&bF.body[bv]||bE}if(bC.nodeType===9){bF=bC.documentElement;if(bF[bv]>=bF[e]){return bF[bv]}return Math.max(bC.body[e],bF[e],bC.body[by],bF[by])}if(bD===L){bG=b.css(bC,bB);bA=parseFloat(bG);return b.isNumeric(bA)?bA:bG}b(bC).css(bB,bD)},bx,bz,arguments.length,null)}});bd.jQuery=bd.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g
');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(hl.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null;p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*! + * jQuery hashchange event - v1.3 - 7/21/2010 + * http://benalman.com/projects/jquery-hashchange-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$(' + + +
+
+
Background
+
+
+

Why do I need this? you may ask. The truth is that you may not need it if you are converting your values to ASCII strings and separating them with a known character (like a carriage return \r and a line feed \n) before sending them. This is what happens if you call and Serial.println();. For instance, if you just want to send a byte with the value of 255 and follow it with a new line character (i.e. Serial.println(255);) the Arduino automatically converts the number to the equivalent printable ASCII characters, sending 5 bytes total. As a result the receiver won't just receive a byte for the number and two bytes for the carriage return and new line character. Instead it will receive a stream of 5 bytes:

+
50 // ASCII '2'
53 // ASCII '5'
53 // ASCII '5'
13 // ASCII '\r'
10 // ASCII '\n'

The receiver must then collect the 3 ASCII characters { '2', '5', '5' }, combine them and convert them back into a single byte with a value of 255. This process can get complicated when the user wants to send large quantities of structured data between the Arduino and a receiver.

+

One way to send a packet of data without this library is to send each byte separated by a comma or space and terminate the sequence with a new line character. Thus, to send the value 255 and the value 10, one might call:

+
Serial.print(255);
Serial.print(',');
Serial.print(10);
Serial.print('\n');

The receiver will actually see a stream of 7 bytes:

+
50 // ASCII '2'
53 // ASCII '5'
53 // ASCII '5'
44 // ASCII ','
49 // ASCII '1'
48 // ASCII '0'
10 // ASCII '\n'

In this case, the receiver must then collect the ASCII characters, combine them, skip the delimiter (the comma in this case) and then process the packet when a new line is encountered. While effective, this method doesn't scale particularly well. Bytes with values larger than 9 are encoded as 2 bytes and bytes with values larger than 99 are encoded as 3 bytes, etc. If the user would like to send the number 4,294,967,295 (the maximum value of a 4 byte unsigned long), it would be encoded as 10 bytes. This means that there is an overhead of 6 extra bytes to transmit a 4 byte unsigned long.

+

An alternative to ASCII encoding is to write the bytes directly to using the Serial.write() methods. These methods do not convert the byte values to ASCII. So if the user wants to send a single byte with the value of 255 and follow it with a new line character:

+
Serial.write(255);
Serial.write('\n');

the receiver will see a stream of 2 bytes:

+
255 // The value transmitted.
10 // The new line character (\n).

This is much more compact but can create problems when the user wants to send a packet of data. If the user wants to send a packet consisting of two values such as 255 and 10, we run into problems if we also use the new line (\n ASCII 10) character as a packet boundary. This essentially means that the receiver will incorrectly think that a new packet is beginning when it receives the value of 10. Thus, to use this more compact form of sending bytes while reserving one value for a packet boundary marker. Several unambiguous packet boundary marking encodings exist, but one with a small predictable overhead is called Consistent Overhead Byte Stuffing. For a raw packet of length SIZE, the maximum encoded buffer size will only be SIZE + SIZE / 254 + 1. This is significantly less than ASCII encoding and the encoding / decoding algorithm is simple and fast. In its default mode, the COBS encoding process simply removes all zeros from the packet, allowing the sender and receiver to use the value of zero as a packet boundary marker.

+

Another encoding available in PacketSerial is Serial Line Internet Protocol which is often used to send OSC over serial or TCP connections. To use SLIP encoding instead of COBS, use SLIPPacketSerial instead of PacketSerial. You can find an openFrameworks example of sending OSC data over serial in the ofxSerial repository.

+
+
+ + + + + diff --git a/md_CHANGELOG.html b/md_CHANGELOG.html new file mode 100644 index 0000000..23fd6c9 --- /dev/null +++ b/md_CHANGELOG.html @@ -0,0 +1,198 @@ + + + + + + + +PacketSerial: Changelog + + + + + + + + + + + + + + +
+
+
+ + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+ + + + + + + + + +
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Changelog
+
+
+

All notable changes to this project will be documented in this file.

+

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

+

[Unreleased]

+

Added

+
    +
  • None
  • +
+

Changed

+
    +
  • None
  • +
+

Removed

+
    +
  • None
  • +
+

Fixed

+
    +
  • None
  • +
+

Security

+
    +
  • None
  • +
+

[1.4.0] 2019-07-26

+

Added

+
    +
  • Added const Stream* getStream() const and Stream* getStream() methods. Thanks @orgicus.
  • +
+

Changed

+
    +
  • Updated README.
  • +
+

[1.3.0] 2019-07-25

+

Removed

+
    +
  • Remove the void begin(unsigned long speed, size_t port) function.
  • +
  • Remove the void begin(Stream* stream) function.
  • +
  • while(!SerialX) line when CORE_TEENSY is defined. This was leading to unexpected behavior where programs would not start until a serial connection was opened.
  • +
+

Added

+
    +
  • Lambda function packetHandler examples and documentation.
  • +
  • Add bool overflow() const to check for a receive buffer overflow.
  • +
  • Added API documentation @ http://bakercp.github.io/PacketSerial/
  • +
+

Changed

+
    +
  • Updated README.md, fixed spelling error, added links, docs.
  • +
  • Rewrote SLIP enum in terms of decimal notation for consistency.
  • +
  • Updated documentation folder, .github structure.
  • +
  • Updated CI testing.
  • +
+

[1.2.0] 2017-11-09

+

Added

+
    +
  • An additional PacketHandler pointer type that includes the sender's pointer e.g. void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size). Either functions can be set. Calling setPacketHandler() will always remove all previous function pointers.
  • +
+

Removed

+
    +
  • Deprecated all but one basic void begin(Stream* stream) function. Use void setStream(Stream* stream) instead.
  • +
  • Reverted void PacketSerial_::begin(unsigned long speed, uint8_t config, size_t port).
  • +
+

Changed

+
    +
  • Updated README.md, fixed errors, spelling and updated examples.
  • +
+

[1.1.0] 2017-11-09

+

Added

+
    +
  • Additional inline documentation.
  • +
  • Added doxygen configuration file.
  • +
  • Added CHANGELOG.md file.
  • +
  • Added the void PacketSerial_::begin(unsigned long speed, uint8_t config, size_t port) method to avoid confusion with the standard Serial.begin(unsigned long speed, uint8_t config).
  • +
+

Changed

+
    +
  • Updated README.md, fixed errors, spelling, byte counts, etc.
  • +
  • Updated documentation / comments in documentation for clarity.
  • +
+

Removed

+
    +
  • Deprecated the void begin(unsigned long speed, size_t port) method because it could be confused with the standard Serial.begin(unsigned long speed, uint8_t config) method.
  • +
+

Fixed

+
    +
  • Fixed Duplicated SLIP END Packet #11
  • +
  • Fix types to remove warnings in examples.
  • +
  • Add const qualifier to the send() method.
  • +
+

Security

+
    +
  • None
  • +
+
+
+
+ + + + diff --git a/md_CODE_OF_CONDUCT.html b/md_CODE_OF_CONDUCT.html new file mode 100644 index 0000000..d71849b --- /dev/null +++ b/md_CODE_OF_CONDUCT.html @@ -0,0 +1,135 @@ + + + + + + + +PacketSerial: Contributor Covenant Code of Conduct + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Contributor Covenant Code of Conduct
+
+
+

Our Pledge

+

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

+

Our Standards

+

Examples of behavior that contributes to creating a positive environment include:

+
    +
  • Using welcoming and inclusive language
  • +
  • Being respectful of differing viewpoints and experiences
  • +
  • Gracefully accepting constructive criticism
  • +
  • Focusing on what is best for the community
  • +
  • Showing empathy towards other community members
  • +
+

Examples of unacceptable behavior by participants include:

+
    +
  • The use of sexualized language or imagery and unwelcome sexual attention or advances
  • +
  • Trolling, insulting/derogatory comments, and personal or political attacks
  • +
  • Public or private harassment
  • +
  • Publishing others' private information, such as a physical or electronic address, without explicit permission
  • +
  • Other conduct which could reasonably be considered inappropriate in a professional setting
  • +
+

Our Responsibilities

+

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

+

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

+

Scope

+

This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

+

Enforcement

+

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@christopherbaker.net. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

+

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

+

Attribution

+

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html.

+

For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq.

+
+
+
+ + + + diff --git a/md_CONTRIBUTING.html b/md_CONTRIBUTING.html new file mode 100644 index 0000000..800a00c --- /dev/null +++ b/md_CONTRIBUTING.html @@ -0,0 +1,121 @@ + + + + + + + +PacketSerial: Contributing + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Contributing
+
+
+

Code of Conduct

+

First, please see the Code of Conduct.

+

How to Help

+

Check out the Todo list to see if there are any planned items.

+

Check out the Help Wanted tag in the issues section for specific ideas or propose your own new ideas.

+

Making Pull Requests

+

Pull Requests are always welcome, so if you make any improvements please feel free to float them back upstream :)

+
    +
  1. Fork this repository.
  2. +
  3. Create your feature branch (git checkout -b my-new-feature).
  4. +
  5. Commit your changes (‘git commit -am 'Add some feature’).
  6. +
  7. Push to the branch (git push origin my-new-feature`).
  8. +
  9. Create new Pull Request.
  10. +
+

New features should include tests (if possible) to confirm functionality.

+

All code should be documented inline using Doxygen documentation. See the project's source for examples of the preferred style.

+
+
+
+ + + + diff --git a/md_CONTRIBUTORS.html b/md_CONTRIBUTORS.html new file mode 100644 index 0000000..a40cbd1 --- /dev/null +++ b/md_CONTRIBUTORS.html @@ -0,0 +1,113 @@ + + + + + + + +PacketSerial: Contributors + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Contributors
+
+
+
+

For and up-to-date list of contributors, see contributors.

+
+
+
+ + + + diff --git a/md_GETTING_STARTED.html b/md_GETTING_STARTED.html new file mode 100644 index 0000000..3092f3b --- /dev/null +++ b/md_GETTING_STARTED.html @@ -0,0 +1,151 @@ + + + + + + + +PacketSerial: Getting Started + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Getting Started
+
+
+

First, it might be worth it to read the background introduction.

+

Installation

+

This project can be installed using the Arduino IDE. Navigate to the Tools > Manage Libraries ... menu item and search for PacketSerial.

+

Alternatively, this library can be downloaded or cloned from github and to your Arduino libraries folder.

+

Use

+

PacketSerial class wraps the Arduino Stream class to automatically encode and decode byte packets that are sent and received. Typically serial communication uses the default Serial object, which implements the Stream class. In most cases, PacketSerial should be given exclusive access to the serial Stream (e.g. for a default setup using Serial, users should avoid calling functions like Serial.print(), Serial.write(), etc directly). Data should be sent via the send(const uint8_t* buffer, size_t size) const method and received in a PacketSerial callback function (see below).

+

Setup

+

Basic

+

To use the default Serial object and the default communication settings (usually SERIAL_8N1), set up PacketSerial like this:

+
PacketSerial myPacketSerial;
void setup()
{
myPacketSerial.begin(9600);
myPacketSerial.setPacketHandler(&onPacketReceived);
}

Advanced

+

For a non-default Serial connection, a class implementing the Stream interface should be configured and then set for the PacketSerial instance.

+

Using A Non-Standard Serial Configuration

+
PacketSerial myPacketSerial;
void setup()
{
Serial.begin(300, SERIAL_7N1);
myPacketSerial.setStream(&Serial);
myPacketSerial.setPacketHandler(&onPacketReceived);
}

Using Secondary Serial Ports (e.g. Serial1, Serial2, etc)

+
PacketSerial myPacketSerial;
void setup()
{
Serial1.begin(9600);
myPacketSerial.setStream(&Serial1);
myPacketSerial.setPacketHandler(&onPacketReceived);
}

Using SoftwareSerial

+
PacketSerial myPacketSerial;
SoftwareSerial mySoftwareSerial(10, 11);
void setup()
{
mySoftwareSerial.begin(38400);
myPacketSerial.setStream(&mySoftwareSerial);
myPacketSerial.setPacketHandler(&onPacketReceived);
}

Other Streams

+

Any class that correctly implements the Stream interface should work, which includes some network communication objects.

+

Loop

+

In order to processing incoming serial packets, the user must call the update() method at the end of the loop() method.

+
void loop()
{
// Your program here.
// Call update to receive, decode and process incoming packets.
myPacketSerial.update();
}

Receiving Packets

+

All packets are received via handler functions. A typical handler function would be registered in the void setup() function like:

+
PacketSerial myPacketSerial;
void setup()
{
myPacketSerial.begin(9600);
myPacketSerial.setPacketHandler(&onPacketReceived);
}

The onPacketReceived function can take two forms. The simplest looks like this:

+
void onPacketReceived(const uint8_t* buffer, size_t size)
{
// Process your decoded incoming packet here.
}

For more advanced programs with multiple PacketSerial instances and a shared handler, it may be useful to know which PacketSerial instance received the packet. In this case you could define a callback like this:

+
void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size)
{
if (sender == &myPacketSerial)
{
// Do something with the packet from myPacketSerial.
}
else if (sender == &myOtherPacketSerial)
{
// Do something with the packet from myOtherPacketSerial.
}
}

Finally, it is also possible to set arbitrary packet handlers that point to member functions of a given class instance using lambda functions. For example:

+
// Instances of this class can receive data packets when registered.
class MyClass
{
public:
void processPacketFromSender(const PacketSerial& sender, const uint8_t* buffer, size_t size)
{
// Just send the buffer back to the sender.
sender.send(buffer, size);
}
};
MyClass myClassInstance;
PacketSerial myPacketSerial;
void setup()
{
myPacketSerial.begin(115200);
myPacketSerial.setPacketHandler([](const uint8_t* buffer, size_t size) {
myClassInstance.processPacketFromSender(myPacketSerial, buffer, size);
});
}

Sending Packets

+

To send packets call the send() method. The send method will take a packet (an array of bytes), encode it, transmit it and send the packet boundary marker. To send the values 255 and 10, one might do the following:

+
// Make an array.
uint8_t myPacket[2] = { 255, 10 };
// Send the array.
myPacketSerial.send(myPacket, 2);

Multiple Streams

+

On boards with multiple serial ports, this strategy can also be used to set up two Serial streams, one for packets and one for debug ASCII (see this discussion for more).

+

Checking for Receive Buffer Overflows

+

In some cases the receive buffer may not be large enough for an incoming encoded packet.

+

To check for overflows, call the receiveBufferOverflowed() method after calling update().

+

For example:

+
void loop()
{
// Other program code.
myPacketSerial.update();
// Check for a receive buffer overflow.
if (myPacketSerial.overflow())
{
// Send an alert via a pin (e.g. make an overflow LED) or return a
// user-defined packet to the sender.
//
// Ultimately you may need to just increase your recieve buffer via the
// template parameters.
}
}

The state of the overflow flag is reset every time a new packet marker is detected, NOT when the overflow() method is called.

+

Customizing the PacketSerial Class

+

The PacketSerial_ class is a templated class that allows us to statically set the encoder type, packet marker and buffer size at compile time.

+

The the template parameters are as follows:

+
template<typename EncoderType, uint8_t PacketMarker = 0, size_t BufferSize = 256>
(https://github.com/bakercp/PacketSerial.)

The PacketMarker has a default of 0 while the BufferSize has a default of 256 bytes.

+

Thus, if you define your class as:

+
PacketSerial_<COBS> myPacketSerial;

You will use the COBS encoder type and a default PacketMarker of 0 and buffer size of 256.

+

Currently there are three default PacketSerial_ types defined via typedef for convenience:

+

Changing the EncoderType Type

+

To use a custom encoding type, the EncoderType class must implement the following functions:

+
static size_t encode(const uint8_t* buffer, size_t size, uint8_t* encodedBuffer);
static size_t decode(const uint8_t* encodedBuffer, size_t size, uint8_t* decodedBuffer);
static size_t getEncodedBufferSize(size_t unencodedBufferSize);

See the Encoding/COBS.h and Encoding/SLIP.h for examples and further documentation.

+

Changing the Packet Marker Byte and Receive Buffer Size

+

For example, to increase the buffer size for a standard COBS encoder to 512, one can defined the templated class like this:

+

This uses the COBS encoder type, a PacketMarker of 0 and a buffer size of 512.

+

Likewise, a custom SLIP encoder with a buffer size of 512 bytes would be defined like this:

+
+
+
+ + + + diff --git a/md_LICENSE.html b/md_LICENSE.html new file mode 100644 index 0000000..16f5537 --- /dev/null +++ b/md_LICENSE.html @@ -0,0 +1,110 @@ + + + + + + + +PacketSerial: LICENSE + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
LICENSE
+
+
+

MIT License

+

Copyright (c) 2017 Christopher Baker https://christopherbaker.net

+

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+
+
+
+ + + + diff --git a/md_SUPPORT.html b/md_SUPPORT.html new file mode 100644 index 0000000..455a88a --- /dev/null +++ b/md_SUPPORT.html @@ -0,0 +1,107 @@ + + + + + + + +PacketSerial: Support + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Support
+
+
+

First, read the Getting Started guide and see the Troubleshooting guide. You might also check and see if there are any existing issues that are helpful to you. If those don't help and you, create a new issue.

+

Please do not email the author directly with questions.

+
+
+
+ + + + diff --git a/md_TODO.html b/md_TODO.html new file mode 100644 index 0000000..92e18cd --- /dev/null +++ b/md_TODO.html @@ -0,0 +1,108 @@ + + + + + + + +PacketSerial: TODO + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
TODO
+
+
+

First check out the Help Wanted tag in the issues section for specific ideas.

+

Future Plans

+

Right now the encoder / decoder works by encoding or decoding a full buffer. SLIP (and COBS?) encoding, for instance, can be encoded / decoded on the fly, allowing for a smaller buffer allocation. https://github.com/CNMAT/OSC uses an "on-the-fly" approach, rather than a large buffer approach. It would be interesting to investigate this.

+
+
+
+ + + + diff --git a/md_TROUBLESHOOTING.html b/md_TROUBLESHOOTING.html new file mode 100644 index 0000000..374c58f --- /dev/null +++ b/md_TROUBLESHOOTING.html @@ -0,0 +1,106 @@ + + + + + + + +PacketSerial: Troubleshooting + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PacketSerial +
+
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Troubleshooting
+
+
+

There are no additional Troubleshooting notes at steps time.

+
+
+
+ + + + diff --git a/menu.js b/menu.js new file mode 100644 index 0000000..433c15b --- /dev/null +++ b/menu.js @@ -0,0 +1,50 @@ +/* + @licstart The following is the entire license notice for the + JavaScript code in this file. + + Copyright (C) 1997-2017 by Dimitri van Heesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + @licend The above is the entire license notice + for the JavaScript code in this file + */ +function initMenu(relPath,searchEnabled,serverSide,searchPage,search) { + function makeTree(data,relPath) { + var result=''; + if ('children' in data) { + result+=''; + } + return result; + } + + $('#main-nav').append(makeTree(menudata,relPath)); + $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu'); + if (searchEnabled) { + if (serverSide) { + $('#main-menu').append('
  • '); + } else { + $('#main-menu').append('
  • '); + } + } + $('#main-menu').smartmenus(); +} +/* @license-end */ diff --git a/menudata.js b/menudata.js new file mode 100644 index 0000000..5f8e21d --- /dev/null +++ b/menudata.js @@ -0,0 +1,35 @@ +/* +@ @licstart The following is the entire license notice for the +JavaScript code in this file. + +Copyright (C) 1997-2017 by Dimitri van Heesch + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +@licend The above is the entire license notice +for the JavaScript code in this file +*/ +var menudata={children:[ +{text:"Main Page",url:"index.html"}, +{text:"Related Pages",url:"pages.html"}, +{text:"Classes",url:"annotated.html",children:[ +{text:"Class List",url:"annotated.html"}, +{text:"Class Index",url:"classes.html"}, +{text:"Class Members",url:"functions.html",children:[ +{text:"All",url:"functions.html"}, +{text:"Functions",url:"functions_func.html"}, +{text:"Typedefs",url:"functions_type.html"}]}]}, +{text:"Files",url:"files.html",children:[ +{text:"File List",url:"files.html"}]}]} diff --git a/nav_f.png b/nav_f.png new file mode 100644 index 0000000..72a58a5 Binary files /dev/null and b/nav_f.png differ diff --git a/nav_g.png b/nav_g.png new file mode 100644 index 0000000..2093a23 Binary files /dev/null and b/nav_g.png differ diff --git a/nav_h.png b/nav_h.png new file mode 100644 index 0000000..33389b1 Binary files /dev/null and b/nav_h.png differ diff --git a/navtree.css b/navtree.css new file mode 100644 index 0000000..33341a6 --- /dev/null +++ b/navtree.css @@ -0,0 +1,146 @@ +#nav-tree .children_ul { + margin:0; + padding:4px; +} + +#nav-tree ul { + list-style:none outside none; + margin:0px; + padding:0px; +} + +#nav-tree li { + white-space:nowrap; + margin:0px; + padding:0px; +} + +#nav-tree .plus { + margin:0px; +} + +#nav-tree .selected { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +#nav-tree img { + margin:0px; + padding:0px; + border:0px; + vertical-align: middle; +} + +#nav-tree a { + text-decoration:none; + padding:0px; + margin:0px; + outline:none; +} + +#nav-tree .label { + margin:0px; + padding:0px; + font: 12px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +#nav-tree .label a { + padding:2px; +} + +#nav-tree .selected a { + text-decoration:none; + color:#fff; +} + +#nav-tree .children_ul { + margin:0px; + padding:0px; +} + +#nav-tree .item { + margin:0px; + padding:0px; +} + +#nav-tree { + padding: 0px 0px; + background-color: #FAFAFF; + font-size:14px; + overflow:auto; +} + +#doc-content { + overflow:auto; + display:block; + padding:0px; + margin:0px; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#side-nav { + padding:0 6px 0 0; + margin: 0px; + display:block; + position: absolute; + left: 0px; + width: 250px; +} + +.ui-resizable .ui-resizable-handle { + display:block; +} + +.ui-resizable-e { + background-image:url("splitbar.png"); + background-size:100%; + background-repeat:repeat-y; + background-attachment: scroll; + cursor:ew-resize; + height:100%; + right:0; + top:0; + width:6px; +} + +.ui-resizable-handle { + display:none; + font-size:0.1px; + position:absolute; + z-index:1; +} + +#nav-tree-contents { + margin: 6px 0px 0px 0px; +} + +#nav-tree { + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#nav-sync { + position:absolute; + top:5px; + right:24px; + z-index:0; +} + +#nav-sync img { + opacity:0.3; +} + +#nav-sync img:hover { + opacity:0.9; +} + +@media print +{ + #nav-tree { display: none; } + div.ui-resizable-handle { display: none; position: relative; } +} + diff --git a/navtree.js b/navtree.js new file mode 100644 index 0000000..7ce2935 --- /dev/null +++ b/navtree.js @@ -0,0 +1,540 @@ +/* + @licstart The following is the entire license notice for the + JavaScript code in this file. + + Copyright (C) 1997-2017 by Dimitri van Heesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + @licend The above is the entire license notice + for the JavaScript code in this file + */ +var navTreeSubIndices = new Array(); +var arrowDown = '▼'; +var arrowRight = '►'; + +function getData(varName) +{ + var i = varName.lastIndexOf('/'); + var n = i>=0 ? varName.substring(i+1) : varName; + return eval(n.replace(/\-/g,'_')); +} + +function stripPath(uri) +{ + return uri.substring(uri.lastIndexOf('/')+1); +} + +function stripPath2(uri) +{ + var i = uri.lastIndexOf('/'); + var s = uri.substring(i+1); + var m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; +} + +function hashValue() +{ + return $(location).attr('hash').substring(1).replace(/[^\w\-]/g,''); +} + +function hashUrl() +{ + return '#'+hashValue(); +} + +function pathName() +{ + return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]/g, ''); +} + +function localStorageSupported() +{ + try { + return 'localStorage' in window && window['localStorage'] !== null && window.localStorage.getItem; + } + catch(e) { + return false; + } +} + + +function storeLink(link) +{ + if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) { + window.localStorage.setItem('navpath',link); + } +} + +function deleteLink() +{ + if (localStorageSupported()) { + window.localStorage.setItem('navpath',''); + } +} + +function cachedLink() +{ + if (localStorageSupported()) { + return window.localStorage.getItem('navpath'); + } else { + return ''; + } +} + +function getScript(scriptName,func,show) +{ + var head = document.getElementsByTagName("head")[0]; + var script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = func; + script.src = scriptName+'.js'; + if ($.browser.msie && $.browser.version<=8) { + // script.onload does not work with older versions of IE + script.onreadystatechange = function() { + if (script.readyState=='complete' || script.readyState=='loaded') { + func(); if (show) showRoot(); + } + } + } + head.appendChild(script); +} + +function createIndent(o,domNode,node,level) +{ + var level=-1; + var n = node; + while (n.parentNode) { level++; n=n.parentNode; } + if (node.childrenData) { + var imgNode = document.createElement("span"); + imgNode.className = 'arrow'; + imgNode.style.paddingLeft=(16*level).toString()+'px'; + imgNode.innerHTML=arrowRight; + node.plus_img = imgNode; + node.expandToggle = document.createElement("a"); + node.expandToggle.href = "javascript:void(0)"; + node.expandToggle.onclick = function() { + if (node.expanded) { + $(node.getChildrenUL()).slideUp("fast"); + node.plus_img.innerHTML=arrowRight; + node.expanded = false; + } else { + expandNode(o, node, false, false); + } + } + node.expandToggle.appendChild(imgNode); + domNode.appendChild(node.expandToggle); + } else { + var span = document.createElement("span"); + span.className = 'arrow'; + span.style.width = 16*(level+1)+'px'; + span.innerHTML = ' '; + domNode.appendChild(span); + } +} + +var animationInProgress = false; + +function gotoAnchor(anchor,aname,updateLocation) +{ + var pos, docContent = $('#doc-content'); + var ancParent = $(anchor.parent()); + if (ancParent.hasClass('memItemLeft') || + ancParent.hasClass('fieldname') || + ancParent.hasClass('fieldtype') || + ancParent.is(':header')) + { + pos = ancParent.position().top; + } else if (anchor.position()) { + pos = anchor.position().top; + } + if (pos) { + var dist = Math.abs(Math.min( + pos-docContent.offset().top, + docContent[0].scrollHeight- + docContent.height()-docContent.scrollTop())); + animationInProgress=true; + docContent.animate({ + scrollTop: pos + docContent.scrollTop() - docContent.offset().top + },Math.max(50,Math.min(500,dist)),function(){ + if (updateLocation) window.location.href=aname; + animationInProgress=false; + }); + } +} + +function newNode(o, po, text, link, childrenData, lastNode) +{ + var node = new Object(); + node.children = Array(); + node.childrenData = childrenData; + node.depth = po.depth + 1; + node.relpath = po.relpath; + node.isLast = lastNode; + + node.li = document.createElement("li"); + po.getChildrenUL().appendChild(node.li); + node.parentNode = po; + + node.itemDiv = document.createElement("div"); + node.itemDiv.className = "item"; + + node.labelSpan = document.createElement("span"); + node.labelSpan.className = "label"; + + createIndent(o,node.itemDiv,node,0); + node.itemDiv.appendChild(node.labelSpan); + node.li.appendChild(node.itemDiv); + + var a = document.createElement("a"); + node.labelSpan.appendChild(a); + node.label = document.createTextNode(text); + node.expanded = false; + a.appendChild(node.label); + if (link) { + var url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + link = url; + } else { + url = node.relpath+link; + } + a.className = stripPath(link.replace('#',':')); + if (link.indexOf('#')!=-1) { + var aname = '#'+link.split('#')[1]; + var srcPage = stripPath(pathName()); + var targetPage = stripPath(link.split('#')[0]); + a.href = srcPage!=targetPage ? url : "javascript:void(0)"; + a.onclick = function(){ + storeLink(link); + if (!$(a).parent().parent().hasClass('selected')) + { + $('.item').removeClass('selected'); + $('.item').removeAttr('id'); + $(a).parent().parent().addClass('selected'); + $(a).parent().parent().attr('id','selected'); + } + var anchor = $(aname); + gotoAnchor(anchor,aname,true); + }; + } else { + a.href = url; + a.onclick = function() { storeLink(link); } + } + } else { + if (childrenData != null) + { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + } + + node.childrenUL = null; + node.getChildrenUL = function() { + if (!node.childrenUL) { + node.childrenUL = document.createElement("ul"); + node.childrenUL.className = "children_ul"; + node.childrenUL.style.display = "none"; + node.li.appendChild(node.childrenUL); + } + return node.childrenUL; + }; + + return node; +} + +function showRoot() +{ + var headerHeight = $("#top").height(); + var footerHeight = $("#nav-path").height(); + var windowHeight = $(window).height() - headerHeight - footerHeight; + (function (){ // retry until we can scroll to the selected item + try { + var navtree=$('#nav-tree'); + navtree.scrollTo('#selected',0,{offset:-windowHeight/2}); + } catch (err) { + setTimeout(arguments.callee, 0); + } + })(); +} + +function expandNode(o, node, imm, showRoot) +{ + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + var varName = node.childrenData; + getScript(node.relpath+varName,function(){ + node.childrenData = getData(varName); + expandNode(o, node, imm, showRoot); + }, showRoot); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } if (imm || ($.browser.msie && $.browser.version>8)) { + // somehow slideDown jumps to the start of tree for IE9 :-( + $(node.getChildrenUL()).show(); + } else { + $(node.getChildrenUL()).slideDown("fast"); + } + node.plus_img.innerHTML = arrowDown; + node.expanded = true; + } + } +} + +function glowEffect(n,duration) +{ + n.addClass('glow').delay(duration).queue(function(next){ + $(this).removeClass('glow');next(); + }); +} + +function highlightAnchor() +{ + var aname = hashUrl(); + var anchor = $(aname); + if (anchor.parent().attr('class')=='memItemLeft'){ + var rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); + glowEffect(rows.children(),300); // member without details + } else if (anchor.parent().attr('class')=='fieldname'){ + glowEffect(anchor.parent().parent(),1000); // enum value + } else if (anchor.parent().attr('class')=='fieldtype'){ + glowEffect(anchor.parent().parent(),1000); // struct field + } else if (anchor.parent().is(":header")) { + glowEffect(anchor.parent(),1000); // section header + } else { + glowEffect(anchor.next(),1000); // normal member + } + gotoAnchor(anchor,aname,false); +} + +function selectAndHighlight(hash,n) +{ + var a; + if (hash) { + var link=stripPath(pathName())+':'+hash.substring(1); + a=$('.item a[class$="'+link+'"]'); + } + if (a && a.length) { + a.parent().parent().addClass('selected'); + a.parent().parent().attr('id','selected'); + highlightAnchor(); + } else if (n) { + $(n.itemDiv).addClass('selected'); + $(n.itemDiv).attr('id','selected'); + } + if ($('#nav-tree-contents .item:first').hasClass('selected')) { + $('#nav-sync').css('top','30px'); + } else { + $('#nav-sync').css('top','5px'); + } + showRoot(); +} + +function showNode(o, node, index, hash) +{ + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + var varName = node.childrenData; + getScript(node.relpath+varName,function(){ + node.childrenData = getData(varName); + showNode(o,node,index,hash); + },true); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).css({'display':'block'}); + node.plus_img.innerHTML = arrowDown; + node.expanded = true; + var n = node.children[o.breadcrumbs[index]]; + if (index+11) hash = '#'+parts[1].replace(/[^\w\-]/g,''); + else hash=''; + } + if (hash.match(/^#l\d+$/)) { + var anchor=$('a[name='+hash.substring(1)+']'); + glowEffect(anchor.parent(),1000); // line number + hash=''; // strip line number anchors + } + var url=root+hash; + var i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function(){ + navTreeSubIndices[i] = eval('NAVTREEINDEX'+i); + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + },true); + } +} + +function showSyncOff(n,relpath) +{ + n.html(''); +} + +function showSyncOn(n,relpath) +{ + n.html(''); +} + +function toggleSyncButton(relpath) +{ + var navSync = $('#nav-sync'); + if (navSync.hasClass('sync')) { + navSync.removeClass('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.addClass('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } +} + +function initNavTree(toroot,relpath) +{ + var o = new Object(); + o.toroot = toroot; + o.node = new Object(); + o.node.li = document.getElementById("nav-tree-contents"); + o.node.childrenData = NAVTREE; + o.node.children = new Array(); + o.node.childrenUL = document.createElement("ul"); + o.node.getChildrenUL = function() { return o.node.childrenUL; }; + o.node.li.appendChild(o.node.childrenUL); + o.node.depth = 0; + o.node.relpath = relpath; + o.node.expanded = false; + o.node.isLast = true; + o.node.plus_img = document.createElement("span"); + o.node.plus_img.className = 'arrow'; + o.node.plus_img.innerHTML = arrowRight; + + if (localStorageSupported()) { + var navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.removeClass('sync'); + } else { + showSyncOn(navSync,relpath); + } + navSync.click(function(){ toggleSyncButton(relpath); }); + } + + $(window).load(function(){ + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + }); + + $(window).bind('hashchange', function(){ + if (window.location.hash && window.location.hash.length>1){ + var a; + if ($(location).attr('hash')){ + var clslink=stripPath(pathName())+':'+hashValue(); + a=$('.item a[class$="'+clslink.replace(/ + + + + + + +PacketSerial: Related Pages + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    PacketSerial +
    +
    An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
    +
    +
    + + + + + + + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    + +
    + +
    +
    +
    Related Pages
    +
    +
    +
    Here is a list of all related documentation pages:
    +
    +
    + + + + diff --git a/resize.js b/resize.js new file mode 100644 index 0000000..6617aee --- /dev/null +++ b/resize.js @@ -0,0 +1,136 @@ +/* + @licstart The following is the entire license notice for the + JavaScript code in this file. + + Copyright (C) 1997-2017 by Dimitri van Heesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + @licend The above is the entire license notice + for the JavaScript code in this file + */ +function initResizable() +{ + var cookie_namespace = 'doxygen'; + var sidenav,navtree,content,header,collapsed,collapsedWidth=0,barWidth=6,desktop_vp=768,titleHeight; + + function readCookie(cookie) + { + var myCookie = cookie_namespace+"_"+cookie+"="; + if (document.cookie) { + var index = document.cookie.indexOf(myCookie); + if (index != -1) { + var valStart = index + myCookie.length; + var valEnd = document.cookie.indexOf(";", valStart); + if (valEnd == -1) { + valEnd = document.cookie.length; + } + var val = document.cookie.substring(valStart, valEnd); + return val; + } + } + return 0; + } + + function writeCookie(cookie, val, expiration) + { + if (val==undefined) return; + if (expiration == null) { + var date = new Date(); + date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week + expiration = date.toGMTString(); + } + document.cookie = cookie_namespace + "_" + cookie + "=" + val + "; expires=" + expiration+"; path=/"; + } + + function resizeWidth() + { + var windowWidth = $(window).width() + "px"; + var sidenavWidth = $(sidenav).outerWidth(); + content.css({marginLeft:parseInt(sidenavWidth)+"px"}); + writeCookie('width',sidenavWidth-barWidth, null); + } + + function restoreWidth(navWidth) + { + var windowWidth = $(window).width() + "px"; + content.css({marginLeft:parseInt(navWidth)+barWidth+"px"}); + sidenav.css({width:navWidth + "px"}); + } + + function resizeHeight() + { + var headerHeight = header.outerHeight(); + var footerHeight = footer.outerHeight(); + var windowHeight = $(window).height() - headerHeight - footerHeight; + content.css({height:windowHeight + "px"}); + navtree.css({height:windowHeight + "px"}); + sidenav.css({height:windowHeight + "px"}); + var width=$(window).width(); + if (width!=collapsedWidth) { + if (width=desktop_vp) { + if (!collapsed) { + collapseExpand(); + } + } else if (width>desktop_vp && collapsedWidth0) { + restoreWidth(0); + collapsed=true; + } + else { + var width = readCookie('width'); + if (width>200 && width<$(window).width()) { restoreWidth(width); } else { restoreWidth(200); } + collapsed=false; + } + } + + header = $("#top"); + sidenav = $("#side-nav"); + content = $("#doc-content"); + navtree = $("#nav-tree"); + footer = $("#nav-path"); + $(".side-nav-resizable").resizable({resize: function(e, ui) { resizeWidth(); } }); + $(sidenav).resizable({ minWidth: 0 }); + $(window).resize(function() { resizeHeight(); }); + var device = navigator.userAgent.toLowerCase(); + var touch_device = device.match(/(iphone|ipod|ipad|android)/); + if (touch_device) { /* wider split bar for touch only devices */ + $(sidenav).css({ paddingRight:'20px' }); + $('.ui-resizable-e').css({ width:'20px' }); + $('#nav-sync').css({ right:'34px' }); + barWidth=20; + } + var width = readCookie('width'); + if (width) { restoreWidth(width); } else { resizeWidth(); } + resizeHeight(); + var url = location.href; + var i=url.indexOf("#"); + if (i>=0) window.location.hash=url.substr(i); + var _preventDefault = function(evt) { evt.preventDefault(); }; + $("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault); + $(".ui-resizable-handle").dblclick(collapseExpand); + $(window).load(resizeHeight); +} +/* @license-end */ diff --git a/search/all_0.html b/search/all_0.html new file mode 100644 index 0000000..5330204 --- /dev/null +++ b/search/all_0.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_0.js b/search/all_0.js new file mode 100644 index 0000000..fce4c2d --- /dev/null +++ b/search/all_0.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['begin',['begin',['../classPacketSerial__.html#adc487966aa9ba70927543acb76186f02',1,'PacketSerial_::begin(unsigned long speed)'],['../classPacketSerial__.html#ac7134ee41cd2d0d62baa210d308fd9f2',1,'PacketSerial_::begin(unsigned long speed, size_t port) __attribute__((deprecated))'],['../classPacketSerial__.html#a3e86627000aa86b08cc28efa63f29c03',1,'PacketSerial_::begin(Stream *stream) __attribute__((deprecated))']]], + ['background',['Background',['../md_BACKGROUND.html',1,'']]] +]; diff --git a/search/all_1.html b/search/all_1.html new file mode 100644 index 0000000..2f46793 --- /dev/null +++ b/search/all_1.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_1.js b/search/all_1.js new file mode 100644 index 0000000..16a77b0 --- /dev/null +++ b/search/all_1.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['changelog',['Changelog',['../md_CHANGELOG.html',1,'']]], + ['contributor_20covenant_20code_20of_20conduct',['Contributor Covenant Code of Conduct',['../md_CODE_OF_CONDUCT.html',1,'']]], + ['contributing',['Contributing',['../md_CONTRIBUTING.html',1,'']]], + ['contributors',['Contributors',['../md_CONTRIBUTORS.html',1,'']]] +]; diff --git a/search/all_2.html b/search/all_2.html new file mode 100644 index 0000000..4c33d85 --- /dev/null +++ b/search/all_2.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_2.js b/search/all_2.js new file mode 100644 index 0000000..038da54 --- /dev/null +++ b/search/all_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['deprecated_20list',['Deprecated List',['../deprecated.html',1,'']]] +]; diff --git a/search/all_3.html b/search/all_3.html new file mode 100644 index 0000000..b634070 --- /dev/null +++ b/search/all_3.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_3.js b/search/all_3.js new file mode 100644 index 0000000..32c3b2b --- /dev/null +++ b/search/all_3.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['getstream',['getStream',['../classPacketSerial__.html#ad7fc82f471d87bb25f7fbbed00be4f33',1,'PacketSerial_::getStream()'],['../classPacketSerial__.html#ac39ae40250556096c6bacd071637f5bf',1,'PacketSerial_::getStream() const']]], + ['getting_20started',['Getting Started',['../md_GETTING_STARTED.html',1,'']]] +]; diff --git a/search/all_4.html b/search/all_4.html new file mode 100644 index 0000000..dd062ae --- /dev/null +++ b/search/all_4.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_4.js b/search/all_4.js new file mode 100644 index 0000000..f64cf37 --- /dev/null +++ b/search/all_4.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['license',['LICENSE',['../md_LICENSE.html',1,'']]] +]; diff --git a/search/all_5.html b/search/all_5.html new file mode 100644 index 0000000..f0780fd --- /dev/null +++ b/search/all_5.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_5.js b/search/all_5.js new file mode 100644 index 0000000..32d18c3 --- /dev/null +++ b/search/all_5.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['overflow',['overflow',['../classPacketSerial__.html#a2c76159bdebb3af109c4a23274e03e7c',1,'PacketSerial_']]] +]; diff --git a/search/all_6.html b/search/all_6.html new file mode 100644 index 0000000..39b0f55 --- /dev/null +++ b/search/all_6.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_6.js b/search/all_6.js new file mode 100644 index 0000000..226abc2 --- /dev/null +++ b/search/all_6.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['packetserial',['PacketSerial',['../index.html',1,'']]], + ['packethandlerfunction',['PacketHandlerFunction',['../classPacketSerial__.html#ac785ebf3c4a6db69410a9f5c0c9e2f93',1,'PacketSerial_']]], + ['packethandlerfunctionwithsender',['PacketHandlerFunctionWithSender',['../classPacketSerial__.html#ad5ecd69bb92489c37b10aade1910bfce',1,'PacketSerial_']]], + ['packetserial_5f',['PacketSerial_',['../classPacketSerial__.html',1,'PacketSerial_< EncoderType, PacketMarker, ReceiveBufferSize >'],['../classPacketSerial__.html#a6ceae595e084513c69a04e65ceeda465',1,'PacketSerial_::PacketSerial_()']]] +]; diff --git a/search/all_7.html b/search/all_7.html new file mode 100644 index 0000000..9cd0196 --- /dev/null +++ b/search/all_7.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_7.js b/search/all_7.js new file mode 100644 index 0000000..3675ead --- /dev/null +++ b/search/all_7.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['support',['Support',['../md_SUPPORT.html',1,'']]], + ['send',['send',['../classPacketSerial__.html#a74b43e5a07e8ef713b0257ee3e249184',1,'PacketSerial_']]], + ['setpackethandler',['setPacketHandler',['../classPacketSerial__.html#a3a6ebc9f594a7eb79414af0dd77a34e9',1,'PacketSerial_::setPacketHandler(PacketHandlerFunction onPacketFunction)'],['../classPacketSerial__.html#aa991deb15a468ad9a5a8e315d7c03504',1,'PacketSerial_::setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender)']]], + ['setstream',['setStream',['../classPacketSerial__.html#aae3f10852c7d878d2f48bdf5d44bbaab',1,'PacketSerial_']]] +]; diff --git a/search/all_8.html b/search/all_8.html new file mode 100644 index 0000000..1e8fb9c --- /dev/null +++ b/search/all_8.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_8.js b/search/all_8.js new file mode 100644 index 0000000..ddf7ae5 --- /dev/null +++ b/search/all_8.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['todo',['TODO',['../md_TODO.html',1,'']]], + ['troubleshooting',['Troubleshooting',['../md_TROUBLESHOOTING.html',1,'']]] +]; diff --git a/search/all_9.html b/search/all_9.html new file mode 100644 index 0000000..27df366 --- /dev/null +++ b/search/all_9.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_9.js b/search/all_9.js new file mode 100644 index 0000000..0543e4f --- /dev/null +++ b/search/all_9.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['update',['update',['../classPacketSerial__.html#a4085f92c326368720a5e9b28a2933106',1,'PacketSerial_']]] +]; diff --git a/search/all_a.html b/search/all_a.html new file mode 100644 index 0000000..63f9254 --- /dev/null +++ b/search/all_a.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/all_a.js b/search/all_a.js new file mode 100644 index 0000000..f15fb61 --- /dev/null +++ b/search/all_a.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['_7epacketserial_5f',['~PacketSerial_',['../classPacketSerial__.html#a0895f7e9c6afb25e540cdee47ff3b442',1,'PacketSerial_']]] +]; diff --git a/search/classes_0.html b/search/classes_0.html new file mode 100644 index 0000000..b3c6ec6 --- /dev/null +++ b/search/classes_0.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/classes_0.js b/search/classes_0.js new file mode 100644 index 0000000..fb8d5f1 --- /dev/null +++ b/search/classes_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['packetserial_5f',['PacketSerial_',['../classPacketSerial__.html',1,'']]] +]; diff --git a/search/close.png b/search/close.png new file mode 100644 index 0000000..9342d3d Binary files /dev/null and b/search/close.png differ diff --git a/search/functions_0.html b/search/functions_0.html new file mode 100644 index 0000000..bc73761 --- /dev/null +++ b/search/functions_0.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/functions_0.js b/search/functions_0.js new file mode 100644 index 0000000..808609f --- /dev/null +++ b/search/functions_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['begin',['begin',['../classPacketSerial__.html#adc487966aa9ba70927543acb76186f02',1,'PacketSerial_::begin(unsigned long speed)'],['../classPacketSerial__.html#ac7134ee41cd2d0d62baa210d308fd9f2',1,'PacketSerial_::begin(unsigned long speed, size_t port) __attribute__((deprecated))'],['../classPacketSerial__.html#a3e86627000aa86b08cc28efa63f29c03',1,'PacketSerial_::begin(Stream *stream) __attribute__((deprecated))']]] +]; diff --git a/search/functions_1.html b/search/functions_1.html new file mode 100644 index 0000000..bfcf880 --- /dev/null +++ b/search/functions_1.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/functions_1.js b/search/functions_1.js new file mode 100644 index 0000000..52680f2 --- /dev/null +++ b/search/functions_1.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['getstream',['getStream',['../classPacketSerial__.html#ad7fc82f471d87bb25f7fbbed00be4f33',1,'PacketSerial_::getStream()'],['../classPacketSerial__.html#ac39ae40250556096c6bacd071637f5bf',1,'PacketSerial_::getStream() const']]] +]; diff --git a/search/functions_2.html b/search/functions_2.html new file mode 100644 index 0000000..2b44474 --- /dev/null +++ b/search/functions_2.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/functions_2.js b/search/functions_2.js new file mode 100644 index 0000000..32d18c3 --- /dev/null +++ b/search/functions_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['overflow',['overflow',['../classPacketSerial__.html#a2c76159bdebb3af109c4a23274e03e7c',1,'PacketSerial_']]] +]; diff --git a/search/functions_3.html b/search/functions_3.html new file mode 100644 index 0000000..3dca367 --- /dev/null +++ b/search/functions_3.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/functions_3.js b/search/functions_3.js new file mode 100644 index 0000000..05160fc --- /dev/null +++ b/search/functions_3.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['packetserial_5f',['PacketSerial_',['../classPacketSerial__.html#a6ceae595e084513c69a04e65ceeda465',1,'PacketSerial_']]] +]; diff --git a/search/functions_4.html b/search/functions_4.html new file mode 100644 index 0000000..e713f28 --- /dev/null +++ b/search/functions_4.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/functions_4.js b/search/functions_4.js new file mode 100644 index 0000000..85e48e6 --- /dev/null +++ b/search/functions_4.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['send',['send',['../classPacketSerial__.html#a74b43e5a07e8ef713b0257ee3e249184',1,'PacketSerial_']]], + ['setpackethandler',['setPacketHandler',['../classPacketSerial__.html#a3a6ebc9f594a7eb79414af0dd77a34e9',1,'PacketSerial_::setPacketHandler(PacketHandlerFunction onPacketFunction)'],['../classPacketSerial__.html#aa991deb15a468ad9a5a8e315d7c03504',1,'PacketSerial_::setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender)']]], + ['setstream',['setStream',['../classPacketSerial__.html#aae3f10852c7d878d2f48bdf5d44bbaab',1,'PacketSerial_']]] +]; diff --git a/search/functions_5.html b/search/functions_5.html new file mode 100644 index 0000000..cfe6b17 --- /dev/null +++ b/search/functions_5.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/functions_5.js b/search/functions_5.js new file mode 100644 index 0000000..0543e4f --- /dev/null +++ b/search/functions_5.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['update',['update',['../classPacketSerial__.html#a4085f92c326368720a5e9b28a2933106',1,'PacketSerial_']]] +]; diff --git a/search/functions_6.html b/search/functions_6.html new file mode 100644 index 0000000..a78ec13 --- /dev/null +++ b/search/functions_6.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/functions_6.js b/search/functions_6.js new file mode 100644 index 0000000..f15fb61 --- /dev/null +++ b/search/functions_6.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['_7epacketserial_5f',['~PacketSerial_',['../classPacketSerial__.html#a0895f7e9c6afb25e540cdee47ff3b442',1,'PacketSerial_']]] +]; diff --git a/search/mag_sel.png b/search/mag_sel.png new file mode 100644 index 0000000..39c0ed5 Binary files /dev/null and b/search/mag_sel.png differ diff --git a/search/nomatches.html b/search/nomatches.html new file mode 100644 index 0000000..4377320 --- /dev/null +++ b/search/nomatches.html @@ -0,0 +1,12 @@ + + + + + + + +
    +
    No Matches
    +
    + + diff --git a/search/pages_0.html b/search/pages_0.html new file mode 100644 index 0000000..3d06b05 --- /dev/null +++ b/search/pages_0.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_0.js b/search/pages_0.js new file mode 100644 index 0000000..c63be7e --- /dev/null +++ b/search/pages_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['background',['Background',['../md_BACKGROUND.html',1,'']]] +]; diff --git a/search/pages_1.html b/search/pages_1.html new file mode 100644 index 0000000..06f1e40 --- /dev/null +++ b/search/pages_1.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_1.js b/search/pages_1.js new file mode 100644 index 0000000..16a77b0 --- /dev/null +++ b/search/pages_1.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['changelog',['Changelog',['../md_CHANGELOG.html',1,'']]], + ['contributor_20covenant_20code_20of_20conduct',['Contributor Covenant Code of Conduct',['../md_CODE_OF_CONDUCT.html',1,'']]], + ['contributing',['Contributing',['../md_CONTRIBUTING.html',1,'']]], + ['contributors',['Contributors',['../md_CONTRIBUTORS.html',1,'']]] +]; diff --git a/search/pages_2.html b/search/pages_2.html new file mode 100644 index 0000000..703f781 --- /dev/null +++ b/search/pages_2.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_2.js b/search/pages_2.js new file mode 100644 index 0000000..038da54 --- /dev/null +++ b/search/pages_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['deprecated_20list',['Deprecated List',['../deprecated.html',1,'']]] +]; diff --git a/search/pages_3.html b/search/pages_3.html new file mode 100644 index 0000000..299228a --- /dev/null +++ b/search/pages_3.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_3.js b/search/pages_3.js new file mode 100644 index 0000000..60fe2bb --- /dev/null +++ b/search/pages_3.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['getting_20started',['Getting Started',['../md_GETTING_STARTED.html',1,'']]] +]; diff --git a/search/pages_4.html b/search/pages_4.html new file mode 100644 index 0000000..021d277 --- /dev/null +++ b/search/pages_4.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_4.js b/search/pages_4.js new file mode 100644 index 0000000..f64cf37 --- /dev/null +++ b/search/pages_4.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['license',['LICENSE',['../md_LICENSE.html',1,'']]] +]; diff --git a/search/pages_5.html b/search/pages_5.html new file mode 100644 index 0000000..f57b343 --- /dev/null +++ b/search/pages_5.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_5.js b/search/pages_5.js new file mode 100644 index 0000000..bd51612 --- /dev/null +++ b/search/pages_5.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['packetserial',['PacketSerial',['../index.html',1,'']]] +]; diff --git a/search/pages_6.html b/search/pages_6.html new file mode 100644 index 0000000..49cce0c --- /dev/null +++ b/search/pages_6.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_6.js b/search/pages_6.js new file mode 100644 index 0000000..71b2a5e --- /dev/null +++ b/search/pages_6.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['support',['Support',['../md_SUPPORT.html',1,'']]] +]; diff --git a/search/pages_7.html b/search/pages_7.html new file mode 100644 index 0000000..7867da6 --- /dev/null +++ b/search/pages_7.html @@ -0,0 +1,30 @@ + + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/pages_7.js b/search/pages_7.js new file mode 100644 index 0000000..ddf7ae5 --- /dev/null +++ b/search/pages_7.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['todo',['TODO',['../md_TODO.html',1,'']]], + ['troubleshooting',['Troubleshooting',['../md_TROUBLESHOOTING.html',1,'']]] +]; diff --git a/search/search.css b/search/search.css new file mode 100644 index 0000000..3cf9df9 --- /dev/null +++ b/search/search.css @@ -0,0 +1,271 @@ +/*---------------- Search Box */ + +#FSearchBox { + float: left; +} + +#MSearchBox { + white-space : nowrap; + float: none; + margin-top: 8px; + right: 0px; + width: 170px; + height: 24px; + z-index: 102; +} + +#MSearchBox .left +{ + display:block; + position:absolute; + left:10px; + width:20px; + height:19px; + background:url('search_l.png') no-repeat; + background-position:right; +} + +#MSearchSelect { + display:block; + position:absolute; + width:20px; + height:19px; +} + +.left #MSearchSelect { + left:4px; +} + +.right #MSearchSelect { + right:5px; +} + +#MSearchField { + display:block; + position:absolute; + height:19px; + background:url('search_m.png') repeat-x; + border:none; + width:115px; + margin-left:20px; + padding-left:4px; + color: #909090; + outline: none; + font: 9pt Arial, Verdana, sans-serif; + -webkit-border-radius: 0px; +} + +#FSearchBox #MSearchField { + margin-left:15px; +} + +#MSearchBox .right { + display:block; + position:absolute; + right:10px; + top:8px; + width:20px; + height:19px; + background:url('search_r.png') no-repeat; + background-position:left; +} + +#MSearchClose { + display: none; + position: absolute; + top: 4px; + background : none; + border: none; + margin: 0px 4px 0px 0px; + padding: 0px 0px; + outline: none; +} + +.left #MSearchClose { + left: 6px; +} + +.right #MSearchClose { + right: 2px; +} + +.MSearchBoxActive #MSearchField { + color: #000000; +} + +/*---------------- Search filter selection */ + +#MSearchSelectWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #90A5CE; + background-color: #F9FAFC; + z-index: 10001; + padding-top: 4px; + padding-bottom: 4px; + -moz-border-radius: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +.SelectItem { + font: 8pt Arial, Verdana, sans-serif; + padding-left: 2px; + padding-right: 12px; + border: 0px; +} + +span.SelectionMark { + margin-right: 4px; + font-family: monospace; + outline-style: none; + text-decoration: none; +} + +a.SelectItem { + display: block; + outline-style: none; + color: #000000; + text-decoration: none; + padding-left: 6px; + padding-right: 12px; +} + +a.SelectItem:focus, +a.SelectItem:active { + color: #000000; + outline-style: none; + text-decoration: none; +} + +a.SelectItem:hover { + color: #FFFFFF; + background-color: #3D578C; + outline-style: none; + text-decoration: none; + cursor: pointer; + display: block; +} + +/*---------------- Search results window */ + +iframe#MSearchResults { + width: 60ex; + height: 15em; +} + +#MSearchResultsWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #000; + background-color: #EEF1F7; + z-index:10000; +} + +/* ----------------------------------- */ + + +#SRIndex { + clear:both; + padding-bottom: 15px; +} + +.SREntry { + font-size: 10pt; + padding-left: 1ex; +} + +.SRPage .SREntry { + font-size: 8pt; + padding: 1px 5px; +} + +body.SRPage { + margin: 5px 2px; +} + +.SRChildren { + padding-left: 3ex; padding-bottom: .5em +} + +.SRPage .SRChildren { + display: none; +} + +.SRSymbol { + font-weight: bold; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRScope { + display: block; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRSymbol:focus, a.SRSymbol:active, +a.SRScope:focus, a.SRScope:active { + text-decoration: underline; +} + +span.SRScope { + padding-left: 4px; +} + +.SRPage .SRStatus { + padding: 2px 5px; + font-size: 8pt; + font-style: italic; +} + +.SRResult { + display: none; +} + +DIV.searchresults { + margin-left: 10px; + margin-right: 10px; +} + +/*---------------- External search page results */ + +.searchresult { + background-color: #F0F3F8; +} + +.pages b { + color: white; + padding: 5px 5px 3px 5px; + background-image: url("../tab_a.png"); + background-repeat: repeat-x; + text-shadow: 0 1px 1px #000000; +} + +.pages { + line-height: 17px; + margin-left: 4px; + text-decoration: none; +} + +.hl { + font-weight: bold; +} + +#searchresults { + margin-bottom: 20px; +} + +.searchpages { + margin-top: 10px; +} + diff --git a/search/search.js b/search/search.js new file mode 100644 index 0000000..a554ab9 --- /dev/null +++ b/search/search.js @@ -0,0 +1,814 @@ +/* + @licstart The following is the entire license notice for the + JavaScript code in this file. + + Copyright (C) 1997-2017 by Dimitri van Heesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + @licend The above is the entire license notice + for the JavaScript code in this file + */ +function convertToId(search) +{ + var result = ''; + for (i=0;i do a search + { + this.Search(); + } + } + + this.OnSearchSelectKey = function(evt) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==40 && this.searchIndex0) // Up + { + this.searchIndex--; + this.OnSelectItem(this.searchIndex); + } + else if (e.keyCode==13 || e.keyCode==27) + { + this.OnSelectItem(this.searchIndex); + this.CloseSelectionWindow(); + this.DOMSearchField().focus(); + } + return false; + } + + // --------- Actions + + // Closes the results window. + this.CloseResultsWindow = function() + { + this.DOMPopupSearchResultsWindow().style.display = 'none'; + this.DOMSearchClose().style.display = 'none'; + this.Activate(false); + } + + this.CloseSelectionWindow = function() + { + this.DOMSearchSelectWindow().style.display = 'none'; + } + + // Performs a search. + this.Search = function() + { + this.keyTimeout = 0; + + // strip leading whitespace + var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + + var code = searchValue.toLowerCase().charCodeAt(0); + var idxChar = searchValue.substr(0, 1).toLowerCase(); + if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair + { + idxChar = searchValue.substr(0, 2); + } + + var resultsPage; + var resultsPageWithSearch; + var hasResultsPage; + + var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar); + if (idx!=-1) + { + var hexCode=idx.toString(16); + resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html'; + resultsPageWithSearch = resultsPage+'?'+escape(searchValue); + hasResultsPage = true; + } + else // nothing available for this search term + { + resultsPage = this.resultsPath + '/nomatches.html'; + resultsPageWithSearch = resultsPage; + hasResultsPage = false; + } + + window.frames.MSearchResults.location = resultsPageWithSearch; + var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + + if (domPopupSearchResultsWindow.style.display!='block') + { + var domSearchBox = this.DOMSearchBox(); + this.DOMSearchClose().style.display = 'inline'; + if (this.insideFrame) + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + domPopupSearchResultsWindow.style.position = 'relative'; + domPopupSearchResultsWindow.style.display = 'block'; + var width = document.body.clientWidth - 8; // the -8 is for IE :-( + domPopupSearchResultsWindow.style.width = width + 'px'; + domPopupSearchResults.style.width = width + 'px'; + } + else + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth; + var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1; + domPopupSearchResultsWindow.style.display = 'block'; + left -= domPopupSearchResults.offsetWidth; + domPopupSearchResultsWindow.style.top = top + 'px'; + domPopupSearchResultsWindow.style.left = left + 'px'; + } + } + + this.lastSearchValue = searchValue; + this.lastResultsPage = resultsPage; + } + + // -------- Activation Functions + + // Activates or deactivates the search panel, resetting things to + // their default values if necessary. + this.Activate = function(isActive) + { + if (isActive || // open it + this.DOMPopupSearchResultsWindow().style.display == 'block' + ) + { + this.DOMSearchBox().className = 'MSearchBoxActive'; + + var searchField = this.DOMSearchField(); + + if (searchField.value == this.searchLabel) // clear "Search" term upon entry + { + searchField.value = ''; + this.searchActive = true; + } + } + else if (!isActive) // directly remove the panel + { + this.DOMSearchBox().className = 'MSearchBoxInactive'; + this.DOMSearchField().value = this.searchLabel; + this.searchActive = false; + this.lastSearchValue = '' + this.lastResultsPage = ''; + } + } +} + +// ----------------------------------------------------------------------- + +// The class that handles everything on the search results page. +function SearchResults(name) +{ + // The number of matches from the last run of . + this.lastMatchCount = 0; + this.lastKey = 0; + this.repeatOn = false; + + // Toggles the visibility of the passed element ID. + this.FindChildElement = function(id) + { + var parentElement = document.getElementById(id); + var element = parentElement.firstChild; + + while (element && element!=parentElement) + { + if (element.nodeName == 'DIV' && element.className == 'SRChildren') + { + return element; + } + + if (element.nodeName == 'DIV' && element.hasChildNodes()) + { + element = element.firstChild; + } + else if (element.nextSibling) + { + element = element.nextSibling; + } + else + { + do + { + element = element.parentNode; + } + while (element && element!=parentElement && !element.nextSibling); + + if (element && element!=parentElement) + { + element = element.nextSibling; + } + } + } + } + + this.Toggle = function(id) + { + var element = this.FindChildElement(id); + if (element) + { + if (element.style.display == 'block') + { + element.style.display = 'none'; + } + else + { + element.style.display = 'block'; + } + } + } + + // Searches for the passed string. If there is no parameter, + // it takes it from the URL query. + // + // Always returns true, since other documents may try to call it + // and that may or may not be possible. + this.Search = function(search) + { + if (!search) // get search word from URL + { + search = window.location.search; + search = search.substring(1); // Remove the leading '?' + search = unescape(search); + } + + search = search.replace(/^ +/, ""); // strip leading spaces + search = search.replace(/ +$/, ""); // strip trailing spaces + search = search.toLowerCase(); + search = convertToId(search); + + var resultRows = document.getElementsByTagName("div"); + var matches = 0; + + var i = 0; + while (i < resultRows.length) + { + var row = resultRows.item(i); + if (row.className == "SRResult") + { + var rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' + + if (search.length<=rowMatchName.length && + rowMatchName.substr(0, search.length)==search) + { + row.style.display = 'block'; + matches++; + } + else + { + row.style.display = 'none'; + } + } + i++; + } + document.getElementById("Searching").style.display='none'; + if (matches == 0) // no results + { + document.getElementById("NoMatches").style.display='block'; + } + else // at least one result + { + document.getElementById("NoMatches").style.display='none'; + } + this.lastMatchCount = matches; + return true; + } + + // return the first item with index index or higher that is visible + this.NavNext = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index++; + } + return focusItem; + } + + this.NavPrev = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index--; + } + return focusItem; + } + + this.ProcessKeys = function(e) + { + if (e.type == "keydown") + { + this.repeatOn = false; + this.lastKey = e.keyCode; + } + else if (e.type == "keypress") + { + if (!this.repeatOn) + { + if (this.lastKey) this.repeatOn = true; + return false; // ignore first keypress after keydown + } + } + else if (e.type == "keyup") + { + this.lastKey = 0; + this.repeatOn = false; + } + return this.lastKey!=0; + } + + this.Nav = function(evt,itemIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + var newIndex = itemIndex-1; + var focusItem = this.NavPrev(newIndex); + if (focusItem) + { + var child = this.FindChildElement(focusItem.parentNode.parentNode.id); + if (child && child.style.display == 'block') // children visible + { + var n=0; + var tmpElem; + while (1) // search for last child + { + tmpElem = document.getElementById('Item'+newIndex+'_c'+n); + if (tmpElem) + { + focusItem = tmpElem; + } + else // found it! + { + break; + } + n++; + } + } + } + if (focusItem) + { + focusItem.focus(); + } + else // return focus to search field + { + parent.document.getElementById("MSearchField").focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = itemIndex+1; + var focusItem; + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem && elem.style.display == 'block') // children visible + { + focusItem = document.getElementById('Item'+itemIndex+'_c0'); + } + if (!focusItem) focusItem = this.NavNext(newIndex); + if (focusItem) focusItem.focus(); + } + else if (this.lastKey==39) // Right + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'block'; + } + else if (this.lastKey==37) // Left + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'none'; + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } + + this.NavChild = function(evt,itemIndex,childIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + if (childIndex>0) + { + var newIndex = childIndex-1; + document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); + } + else // already at first child, jump to parent + { + document.getElementById('Item'+itemIndex).focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = childIndex+1; + var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); + if (!elem) // last child, jump to parent next parent + { + elem = this.NavNext(itemIndex+1); + } + if (elem) + { + elem.focus(); + } + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } +} + +function setKeyActions(elem,action) +{ + elem.setAttribute('onkeydown',action); + elem.setAttribute('onkeypress',action); + elem.setAttribute('onkeyup',action); +} + +function setClassAttr(elem,attr) +{ + elem.setAttribute('class',attr); + elem.setAttribute('className',attr); +} + +function createResults() +{ + var results = document.getElementById("SRResults"); + for (var e=0; e + + + + + + + + +
    +
    Loading...
    +
    + +
    Searching...
    +
    No Matches
    + +
    + + diff --git a/search/typedefs_0.js b/search/typedefs_0.js new file mode 100644 index 0000000..cb48c0c --- /dev/null +++ b/search/typedefs_0.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['packethandlerfunction',['PacketHandlerFunction',['../classPacketSerial__.html#ac785ebf3c4a6db69410a9f5c0c9e2f93',1,'PacketSerial_']]], + ['packethandlerfunctionwithsender',['PacketHandlerFunctionWithSender',['../classPacketSerial__.html#ad5ecd69bb92489c37b10aade1910bfce',1,'PacketSerial_']]] +]; diff --git a/splitbar.png b/splitbar.png new file mode 100644 index 0000000..fe895f2 Binary files /dev/null and b/splitbar.png differ diff --git a/src/Encoding/COBS.h b/src/Encoding/COBS.h deleted file mode 100644 index 5723e43..0000000 --- a/src/Encoding/COBS.h +++ /dev/null @@ -1,129 +0,0 @@ -// -// Copyright (c) 2011 Christopher Baker -// Copyright (c) 2011 Jacques Fortier -// -// SPDX-License-Identifier: MIT -// - - -#pragma once - - -#include "Arduino.h" - - -/// \brief A Consistent Overhead Byte Stuffing (COBS) Encoder. -/// -/// Consistent Overhead Byte Stuffing (COBS) is an encoding that removes all 0 -/// bytes from arbitrary binary data. The encoded data consists only of bytes -/// with values from 0x01 to 0xFF. This is useful for preparing data for -/// transmission over a serial link (RS-232 or RS-485 for example), as the 0 -/// byte can be used to unambiguously indicate packet boundaries. COBS also has -/// the advantage of adding very little overhead (at least 1 byte, plus up to an -/// additional byte per 254 bytes of data). For messages smaller than 254 bytes, -/// the overhead is constant. -/// -/// \sa http://conferences.sigcomm.org/sigcomm/1997/papers/p062.pdf -/// \sa http://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing -/// \sa https://github.com/jacquesf/COBS-Consistent-Overhead-Byte-Stuffing -/// \sa http://www.jacquesf.com/2011/03/consistent-overhead-byte-stuffing -class COBS -{ -public: - /// \brief Encode a byte buffer with the COBS encoder. - /// \param buffer A pointer to the unencoded buffer to encode. - /// \param size The number of bytes in the \p buffer. - /// \param encodedBuffer The buffer for the encoded bytes. - /// \returns The number of bytes written to the \p encodedBuffer. - /// \warning The encodedBuffer must have at least getEncodedBufferSize() - /// allocated. - static size_t encode(const uint8_t* buffer, - size_t size, - uint8_t* encodedBuffer) - { - size_t read_index = 0; - size_t write_index = 1; - size_t code_index = 0; - uint8_t code = 1; - - while (read_index < size) - { - if (buffer[read_index] == 0) - { - encodedBuffer[code_index] = code; - code = 1; - code_index = write_index++; - read_index++; - } - else - { - encodedBuffer[write_index++] = buffer[read_index++]; - code++; - - if (code == 0xFF) - { - encodedBuffer[code_index] = code; - code = 1; - code_index = write_index++; - } - } - } - - encodedBuffer[code_index] = code; - - return write_index; - } - - - /// \brief Decode a COBS-encoded buffer. - /// \param encodedBuffer A pointer to the \p encodedBuffer to decode. - /// \param size The number of bytes in the \p encodedBuffer. - /// \param decodedBuffer The target buffer for the decoded bytes. - /// \returns The number of bytes written to the \p decodedBuffer. - /// \warning decodedBuffer must have a minimum capacity of size. - static size_t decode(const uint8_t* encodedBuffer, - size_t size, - uint8_t* decodedBuffer) - { - if (size == 0) - return 0; - - size_t read_index = 0; - size_t write_index = 0; - uint8_t code = 0; - uint8_t i = 0; - - while (read_index < size) - { - code = encodedBuffer[read_index]; - - if (read_index + code > size && code != 1) - { - return 0; - } - - read_index++; - - for (i = 1; i < code; i++) - { - decodedBuffer[write_index++] = encodedBuffer[read_index++]; - } - - if (code != 0xFF && read_index != size) - { - decodedBuffer[write_index++] = '\0'; - } - } - - return write_index; - } - - /// \brief Get the maximum encoded buffer size for an unencoded buffer size. - /// \param unencodedBufferSize The size of the buffer to be encoded. - /// \returns the maximum size of the required encoded buffer. - static size_t getEncodedBufferSize(size_t unencodedBufferSize) - { - return unencodedBufferSize + unencodedBufferSize / 254 + 1; - } - -}; diff --git a/src/Encoding/SLIP.h b/src/Encoding/SLIP.h deleted file mode 100644 index bbd1c70..0000000 --- a/src/Encoding/SLIP.h +++ /dev/null @@ -1,158 +0,0 @@ -// -// Copyright (c) 2010 Christopher Baker -// Copyright (c) 2016 Antoine Villeret -// -// SPDX-License-Identifier: MIT -// - - -#pragma once - - -#include "Arduino.h" - - -/// \brief A Serial Line Internet Protocol (SLIP) Encoder. -/// -/// Serial Line Internet Protocol (SLIP) is a packet framing protocol: SLIP -/// defines a sequence of characters that frame IP packets on a serial line and -/// nothing more. It provides no addressing, packet type identification, error -/// detection, correction or compression mechanisms. Because the protocol does -/// so little its implementation is trivial and fast. -/// -/// \sa http://tools.ietf.org/html/rfc1055 -class SLIP -{ -public: - /// \brief Encode a byte buffer with the SLIP encoder. - /// \param buffer A pointer to the unencoded buffer to encode. - /// \param size The number of bytes in the \p buffer. - /// \param encodedBuffer The buffer for the encoded bytes. - /// \returns The number of bytes written to the \p encodedBuffer. - /// \warning The encodedBuffer must have at least getEncodedBufferSize() - /// allocated. - static size_t encode(const uint8_t* buffer, - size_t size, - uint8_t* encodedBuffer) - { - if (size == 0) - return 0; - - size_t read_index = 0; - size_t write_index = 0; - - // Double-ENDed, flush any data that may have accumulated due to line - // noise. - encodedBuffer[write_index++] = END; - - while (read_index < size) - { - if(buffer[read_index] == END) - { - encodedBuffer[write_index++] = ESC; - encodedBuffer[write_index++] = ESC_END; - read_index++; - } - else if(buffer[read_index] == ESC) - { - encodedBuffer[write_index++] = ESC; - encodedBuffer[write_index++] = ESC_ESC; - read_index++; - } - else - { - encodedBuffer[write_index++] = buffer[read_index++]; - } - } - - return write_index; - } - - /// \brief Decode a SLIP-encoded buffer. - /// \param encodedBuffer A pointer to the \p encodedBuffer to decode. - /// \param size The number of bytes in the \p encodedBuffer. - /// \param decodedBuffer The target buffer for the decoded bytes. - /// \returns The number of bytes written to the \p decodedBuffer. - /// \warning decodedBuffer must have a minimum capacity of size. - static size_t decode(const uint8_t* encodedBuffer, - size_t size, - uint8_t* decodedBuffer) - { - if (size == 0) - return 0; - - size_t read_index = 0; - size_t write_index = 0; - - while (read_index < size) - { - if (encodedBuffer[read_index] == END) - { - // flush or done - read_index++; - } - else if (encodedBuffer[read_index] == ESC) - { - if (encodedBuffer[read_index+1] == ESC_END) - { - decodedBuffer[write_index++] = END; - read_index += 2; - } - else if (encodedBuffer[read_index+1] == ESC_ESC) - { - decodedBuffer[write_index++] = ESC; - read_index += 2; - } - else - { - // This case is considered a protocol violation. - } - } - else - { - decodedBuffer[write_index++] = encodedBuffer[read_index++]; - } - } - - return write_index; - } - - /// \brief Get the maximum encoded buffer size for an unencoded buffer size. - /// - /// SLIP has a start and end markers (192 and 219). Marker value is - /// replaced by 2 bytes in the encoded buffer. So in the worst case of - /// sending a buffer with only '192' or '219', the encoded buffer length - /// will be 2 * buffer.size() + 2. - /// - /// \param unencodedBufferSize The size of the buffer to be encoded. - /// \returns the maximum size of the required encoded buffer. - static size_t getEncodedBufferSize(size_t unencodedBufferSize) - { - return unencodedBufferSize * 2 + 2; - } - - /// \brief Key constants used in the SLIP protocol. - enum - { - /// \brief The decimal END character (octal 0300). - /// - /// Indicates the end of a packet. - END = 192, - - /// \brief The decimal ESC character (octal 0333). - /// - /// Indicates byte stuffing. - ESC = 219, - - /// \brief The decimal ESC_END character (octal 0334). - /// - /// ESC ESC_END means END data byte. - ESC_END = 220, - - /// \brief The decimal ESC_ESC character (ocatal 0335). - /// - /// ESC ESC_ESC means ESC data byte. - ESC_ESC = 221 - }; - -}; diff --git a/src/PacketSerial.h b/src/PacketSerial.h deleted file mode 100644 index 67de570..0000000 --- a/src/PacketSerial.h +++ /dev/null @@ -1,434 +0,0 @@ -// -// Copyright (c) 2013 Christopher Baker -// -// SPDX-License-Identifier: MIT -// - - -#pragma once - - -#include -#include "Encoding/COBS.h" -#include "Encoding/SLIP.h" - - -/// \brief A template class enabling packet-based Serial communication. -/// -/// Typically one of the typedefined versions are used, for example, -/// `COBSPacketSerial` or `SLIPPacketSerial`. -/// -/// The template parameters allow the user to define their own packet encoder / -/// decoder, custom packet marker and receive buffer size. -/// -/// \tparam EncoderType The static packet encoder class name. -/// \tparam PacketMarker The byte value used to mark the packet boundary. -/// \tparam BufferSize The number of bytes allocated for the receive buffer. -template -class PacketSerial_ -{ -public: - /// \brief A typedef describing the packet handler method. - /// - /// The packet handler method usually has the form: - /// - /// void onPacketReceived(const uint8_t* buffer, size_t size); - /// - /// where buffer is a pointer to the incoming buffer array, and size is the - /// number of bytes in the incoming buffer. - typedef void (*PacketHandlerFunction)(const uint8_t* buffer, size_t size); - - /// \brief A typedef describing the packet handler method. - /// - /// The packet handler method usually has the form: - /// - /// void onPacketReceived(void* sender, const uint8_t* buffer, size_t size); - /// - /// where sender is a pointer to the PacketSerial_ instance that recieved - /// the buffer, buffer is a pointer to the incoming buffer array, and size - /// is the number of bytes in the incoming buffer. - typedef void (*PacketHandlerFunctionWithSender)(const void* sender, const uint8_t* buffer, size_t size); - - /// \brief Construct a default PacketSerial_ device. - PacketSerial_(): - _receiveBufferIndex(0), - _stream(nullptr), - _onPacketFunction(nullptr), - _onPacketFunctionWithSender(nullptr), - _senderPtr(nullptr) - { - } - - /// \brief Destroy the PacketSerial_ device. - ~PacketSerial_() - { - } - - /// \brief Begin a default serial connection with the given speed. - /// - /// The default Serial port `Serial` and default config `SERIAL_8N1` will be - /// used. For example: - /// - /// PacketSerial myPacketSerial; - /// - /// void setup() - /// { - /// myPacketSerial.begin(9600); - /// } - /// - /// This is a convenience method. For more complex Serial port - /// configurations, use the `setStream()` function to set an arbitrary - /// Arduino Stream. - /// - /// \param speed The serial data transmission speed in bits / second (baud). - /// \sa https://www.arduino.cc/en/Serial/Begin - void begin(unsigned long speed) - { - Serial.begin(speed); - #if ARDUINO >= 100 && !defined(CORE_TEENSY) - while (!Serial) {;} - #endif - setStream(&Serial); - } - - /// \brief Deprecated. Use setStream() to configure a non-default port. - /// \param speed The serial data transmission speed in bits / second (baud). - /// \param port The Serial port number (e.g. 0 is Serial, 1 is Serial1). - /// \deprecated Use setStream() to configure a non-default port. - void begin(unsigned long speed, size_t port) __attribute__ ((deprecated)) - { - switch(port) - { - #if defined(UBRR1H) - case 1: - Serial1.begin(speed); - #if ARDUINO >= 100 && !defined(CORE_TEENSY) - while (!Serial1) {;} - #endif - setStream(&Serial1); - break; - #endif - #if defined(UBRR2H) - case 2: - Serial2.begin(speed); - #if ARDUINO >= 100 && !defined(CORE_TEENSY) - while (!Serial1) {;} - #endif - setStream(&Serial2); - break; - #endif - #if defined(UBRR3H) - case 3: - Serial3.begin(speed); - #if ARDUINO >= 100 && !defined(CORE_TEENSY) - while (!Serial3) {;} - #endif - setStream(&Serial3); - break; - #endif - default: - begin(speed); - } - } - - /// \brief Deprecated. Use setStream() to configure a non-default port. - /// \param stream A pointer to an Arduino `Stream`. - /// \deprecated Use setStream() to configure a non-default port. - void begin(Stream* stream) __attribute__ ((deprecated)) - { - _stream = stream; - } - - /// \brief Attach PacketSerial to an existing Arduino `Stream`. - /// - /// This `Stream` could be a standard `Serial` `Stream` with a non-default - /// configuration such as: - /// - /// PacketSerial myPacketSerial; - /// - /// void setup() - /// { - /// Serial.begin(300, SERIAL_7N1); - /// myPacketSerial.setStream(&Serial); - /// } - /// - /// Or it might be a `SoftwareSerial` `Stream` such as: - /// - /// PacketSerial myPacketSerial; - /// SoftwareSerial mySoftwareSerial(10, 11); - /// - /// void setup() - /// { - /// mySoftwareSerial.begin(38400); - /// myPacketSerial.setStream(&mySoftwareSerial); - /// } - /// - /// Any class that implements the `Stream` interface should work, which - /// includes some network objects. - /// - /// \param stream A pointer to an Arduino `Stream`. - void setStream(Stream* stream) - { - _stream = stream; - } - - /// \brief Get a pointer to the current stream. - /// \warning Reading from or writing to the stream managed by PacketSerial_ - /// may break the packet-serial protocol if not done so with care. - /// Access to the stream is allowed because PacketSerial_ never - /// takes ownership of the stream and thus does not have exclusive - /// access to the stream anyway. - /// \returns a non-const pointer to the stream, or nullptr if unset. - Stream* getStream() - { - return _stream; - } - - /// \brief Get a pointer to the current stream. - /// \warning Reading from or writing to the stream managed by PacketSerial_ - /// may break the packet-serial protocol if not done so with care. - /// Access to the stream is allowed because PacketSerial_ never - /// takes ownership of the stream and thus does not have exclusive - /// access to the stream anyway. - /// \returns a const pointer to the stream, or nullptr if unset. - const Stream* getStream() const - { - return _stream; - } - - /// \brief The update function services the serial connection. - /// - /// This must be called often, ideally once per `loop()`, e.g.: - /// - /// void loop() - /// { - /// // Other program code. - /// - /// myPacketSerial.update(); - /// } - /// - void update() - { - if (_stream == nullptr) return; - - while (_stream->available() > 0) - { - uint8_t data = _stream->read(); - - if (data == PacketMarker) - { - if (_onPacketFunction || _onPacketFunctionWithSender) - { - uint8_t _decodeBuffer[_receiveBufferIndex]; - - size_t numDecoded = EncoderType::decode(_receiveBuffer, - _receiveBufferIndex, - _decodeBuffer); - - // clear the index here so that the callback function can call update() if needed and receive more data - _receiveBufferIndex = 0; - _recieveBufferOverflow = false; - - if (_onPacketFunction) - { - _onPacketFunction(_decodeBuffer, numDecoded); - } - else if (_onPacketFunctionWithSender) - { - _onPacketFunctionWithSender(_senderPtr, _decodeBuffer, numDecoded); - } - - } else { - _receiveBufferIndex = 0; - _recieveBufferOverflow = false; - } - } - else - { - if ((_receiveBufferIndex + 1) < ReceiveBufferSize) - { - _receiveBuffer[_receiveBufferIndex++] = data; - } - else - { - // The buffer will be in an overflowed state if we write - // so set a buffer overflowed flag. - _recieveBufferOverflow = true; - } - } - } - } - - /// \brief Set a packet of data. - /// - /// This function will encode and send an arbitrary packet of data. After - /// sending, it will send the specified `PacketMarker` defined in the - /// template parameters. - /// - /// // Make an array. - /// uint8_t myPacket[2] = { 255, 10 }; - /// - /// // Send the array. - /// myPacketSerial.send(myPacket, 2); - /// - /// \param buffer A pointer to a data buffer. - /// \param size The number of bytes in the data buffer. - void send(const uint8_t* buffer, size_t size) const - { - if(_stream == nullptr || buffer == nullptr || size == 0) return; - - uint8_t _encodeBuffer[EncoderType::getEncodedBufferSize(size)]; - - size_t numEncoded = EncoderType::encode(buffer, - size, - _encodeBuffer); - - _stream->write(_encodeBuffer, numEncoded); - _stream->write(PacketMarker); - } - - /// \brief Set the function that will receive decoded packets. - /// - /// This function will be called when data is read from the serial stream - /// connection and a packet is decoded. The decoded packet will be passed - /// to the packet handler. The packet handler must have the form: - /// - /// The packet handler method usually has the form: - /// - /// void onPacketReceived(const uint8_t* buffer, size_t size); - /// - /// The packet handler would then be registered like this: - /// - /// myPacketSerial.setPacketHandler(&onPacketReceived); - /// - /// Setting a packet handler will remove all other packet handlers. - /// - /// \param onPacketFunction A pointer to the packet handler function. - void setPacketHandler(PacketHandlerFunction onPacketFunction) - { - _onPacketFunction = onPacketFunction; - _onPacketFunctionWithSender = nullptr; - _senderPtr = nullptr; - } - - /// \brief Set the function that will receive decoded packets. - /// - /// This function will be called when data is read from the serial stream - /// connection and a packet is decoded. The decoded packet will be passed - /// to the packet handler. The packet handler must have the form: - /// - /// The packet handler method usually has the form: - /// - /// void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size); - /// - /// To determine the sender, compare the pointer to the known possible - /// PacketSerial senders. - /// - /// void onPacketReceived(void* sender, const uint8_t* buffer, size_t size) - /// { - /// if (sender == &myPacketSerial) - /// { - /// // Do something with the packet from myPacketSerial. - /// } - /// else if (sender == &myOtherPacketSerial) - /// { - /// // Do something with the packet from myOtherPacketSerial. - /// } - /// } - /// - /// The packet handler would then be registered like this: - /// - /// myPacketSerial.setPacketHandler(&onPacketReceived); - /// - /// You can also register an arbitrary void* pointer to be passed to your packet handler method. - /// This is most useful when PacketSerial is used inside a class, to pass a pointer to - /// the containing class: - /// - /// class EchoClass { - /// public: - /// void begin(unsigned long speed) { - /// myPacketSerial.setPacketHandler(&onPacketReceived, this); - /// myPacketSerial.begin(speed); - /// } - /// - /// // C-style callbacks can't use non-static methods, - /// // so we use a static method that receives "this" as the sender argument: - /// // https://wiki.c2.com/?VirtualStaticIdiom - /// static void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size) { - /// ((EchoClass*)sender)->onPacketReceived(buffer, size); - /// } - /// - /// void onPacketReceived(const uint8_t* buffer, size_t size) { - /// // we can now use myPacketSerial as needed here - /// } - /// - /// PacketSerial myPacketSerial; - /// }; - /// - /// Setting a packet handler will remove all other packet handlers. - /// - /// \param onPacketFunctionWithSender A pointer to the packet handler function. - /// \param senderPtr Optional pointer to a void* pointer, default argument will pass a pointer to the sending PacketSerial instance to the callback - void setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender, void * senderPtr = nullptr) - { - _onPacketFunction = nullptr; - _onPacketFunctionWithSender = onPacketFunctionWithSender; - _senderPtr = senderPtr; - // for backwards compatibility, the default _senderPtr is "this", but you can't use "this" as a default argument - if(!senderPtr) _senderPtr = this; - } - - /// \brief Check to see if the receive buffer overflowed. - /// - /// This must be called often, directly after the `update()` function. - /// - /// void loop() - /// { - /// // Other program code. - /// myPacketSerial.update(); - /// - /// // Check for a receive buffer overflow. - /// if (myPacketSerial.overflow()) - /// { - /// // Send an alert via a pin (e.g. make an overflow LED) or return a - /// // user-defined packet to the sender. - /// // - /// // Ultimately you may need to just increase your recieve buffer via the - /// // template parameters. - /// } - /// } - /// - /// The state is reset every time a new packet marker is received NOT when - /// overflow() method is called. - /// - /// \returns true if the receive buffer overflowed. - bool overflow() const - { - return _recieveBufferOverflow; - } - -private: - PacketSerial_(const PacketSerial_&); - PacketSerial_& operator = (const PacketSerial_&); - - bool _recieveBufferOverflow = false; - - uint8_t _receiveBuffer[ReceiveBufferSize]; - size_t _receiveBufferIndex = 0; - - Stream* _stream = nullptr; - - PacketHandlerFunction _onPacketFunction = nullptr; - PacketHandlerFunctionWithSender _onPacketFunctionWithSender = nullptr; - void* _senderPtr = nullptr; -}; - - -/// \brief A typedef for the default COBS PacketSerial class. -typedef PacketSerial_ PacketSerial; - -/// \brief A typedef for a PacketSerial type with COBS encoding. -typedef PacketSerial_ COBSPacketSerial; - -/// \brief A typedef for a PacketSerial type with SLIP encoding. -typedef PacketSerial_ SLIPPacketSerial; diff --git a/sync_off.png b/sync_off.png new file mode 100644 index 0000000..3b443fc Binary files /dev/null and b/sync_off.png differ diff --git a/sync_on.png b/sync_on.png new file mode 100644 index 0000000..e08320f Binary files /dev/null and b/sync_on.png differ diff --git a/tab_a.png b/tab_a.png new file mode 100644 index 0000000..3b725c4 Binary files /dev/null and b/tab_a.png differ diff --git a/tab_b.png b/tab_b.png new file mode 100644 index 0000000..e2b4a86 Binary files /dev/null and b/tab_b.png differ diff --git a/tab_h.png b/tab_h.png new file mode 100644 index 0000000..fd5cb70 Binary files /dev/null and b/tab_h.png differ diff --git a/tab_s.png b/tab_s.png new file mode 100644 index 0000000..ab478c9 Binary files /dev/null and b/tab_s.png differ diff --git a/tabs.css b/tabs.css new file mode 100644 index 0000000..8ea7d54 --- /dev/null +++ b/tabs.css @@ -0,0 +1 @@ +.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0 1px 1px rgba(255,255,255,0.9);color:#283a5d;outline:0}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a.current{color:#d23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px;border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0;border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media(min-width:768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283a5d transparent transparent transparent;background:transparent;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;-moz-border-radius:0 !important;-webkit-border-radius:0;border-radius:0 !important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a:hover span.sub-arrow{border-color:white transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;-moz-border-radius:5px !important;-webkit-border-radius:5px;border-radius:5px !important;-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0 !important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent white}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #d23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#d23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}} \ No newline at end of file