First contrib taken from Qt MiniDisplayManager.
authorsl
Tue, 17 Jun 2014 09:55:20 +0200
changeset 00f874d9e4130
child 1 dd5eef0de75a
First contrib taken from Qt MiniDisplayManager.
BitArray.cpp
BitArray.h
FutabaVfd.cpp
FutabaVfd.h
HidDevice.cpp
HidDevice.h
HidReport.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/BitArray.cpp	Tue Jun 17 09:55:20 2014 +0200
     1.3 @@ -0,0 +1,1020 @@
     1.4 +/***************************************************************************
     1.5 +*                         Arrays of Arbitrary Bit Length
     1.6 +*
     1.7 +*   File    : bitarray.cpp
     1.8 +*   Purpose : Provides object with methods for creation and manipulation of
     1.9 +*             arbitrary length arrays of bits.
    1.10 +*
    1.11 +*             Bit arrays are implemented as vectors of unsigned chars.  Bit
    1.12 +*             0 is the MSB of char 0, and the last bit is the least
    1.13 +*             significant (non-spare) bit of the last unsigned char.
    1.14 +*
    1.15 +*             Example: array of 20 bits (0 through 19) with 8 bit unsigned
    1.16 +*                      chars requires 3 unsigned chars (0 through 2) to
    1.17 +*                      store all the bits.
    1.18 +*
    1.19 +*                        char       0       1         2
    1.20 +*                               +--------+--------+--------+
    1.21 +*                               |        |        |        |
    1.22 +*                               +--------+--------+--------+
    1.23 +*                        bit     01234567 8911111111111XXXX
    1.24 +*                                           012345 6789
    1.25 +*
    1.26 +*   Author  : Michael Dipperstein
    1.27 +*   Date    : July 23, 2004
    1.28 +*
    1.29 +****************************************************************************
    1.30 +*   HISTORY
    1.31 +*
    1.32 +*   $Id: bitarray.cpp,v 1.7 2010/02/04 03:31:43 michael Exp $
    1.33 +*   $Log: bitarray.cpp,v $
    1.34 +*   Revision 1.7  2010/02/04 03:31:43  michael
    1.35 +*   Replaced vector<unsigned char> with an array of unsigned char.
    1.36 +*
    1.37 +*   Made updates for GCC 4.4.
    1.38 +*
    1.39 +*   Revision 1.5  2007/08/06 05:23:29  michael
    1.40 +*   Updated for LGPL Version 3.
    1.41 +*
    1.42 +*   All methods that don't modify object have been made
    1.43 +*   const to increase functionality of const bit_array_c.
    1.44 +*
    1.45 +*   All assignment operators return a reference to the object being assigned a value so that operator chaining will work.
    1.46 +*
    1.47 +*   Added >> and << operators.
    1.48 +*
    1.49 +*   Revision 1.3  2006/04/30 23:34:07  michael
    1.50 +*   Improved performance by incorporating Benjamin Schindler's
    1.51 +*   <bschindler@student.ethz.ch> changes to pass arguments as a reference.
    1.52 +*
    1.53 +*   Revision 1.2  2004/08/05 22:16:49  michael
    1.54 +*   Add overloads for bitwise operators returning values.
    1.55 +*   Add a more natural looking way to set bit values.
    1.56 +*
    1.57 +*   Revision 1.1.1.1  2004/08/04 13:28:20  michael
    1.58 +*   bit_array_c
    1.59 +*
    1.60 +****************************************************************************
    1.61 +*
    1.62 +* Bitarray: An ANSI C++ class for manipulating arbitrary length bit arrays
    1.63 +* Copyright (C) 2004, 2006-2007, 2010 by
    1.64 +*       Michael Dipperstein (mdipper@alumni.engr.ucsb.edu)
    1.65 +*
    1.66 +* This file is part of the bit array library.
    1.67 +*
    1.68 +* The bit array library is free software; you can redistribute it and/or
    1.69 +* modify it under the terms of the GNU Lesser General Public License as
    1.70 +* published by the Free Software Foundation; either version 3 of the
    1.71 +* License, or (at your option) any later version.
    1.72 +*
    1.73 +* The bit array library is distributed in the hope that it will be useful,
    1.74 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.75 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
    1.76 +* General Public License for more details.
    1.77 +*
    1.78 +* You should have received a copy of the GNU Lesser General Public License
    1.79 +* along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.80 +*
    1.81 +***************************************************************************/
    1.82 +
    1.83 +/***************************************************************************
    1.84 +*                             INCLUDED FILES
    1.85 +***************************************************************************/
    1.86 +#include <iostream>
    1.87 +#include <climits>
    1.88 +#include "bitarray.h"
    1.89 +
    1.90 +using namespace std;
    1.91 +
    1.92 +/***************************************************************************
    1.93 +*                                 MACROS
    1.94 +***************************************************************************/
    1.95 +
    1.96 +/* make CHAR_BIT 8 if it's not defined in limits.h */
    1.97 +#ifndef CHAR_BIT
    1.98 +#warning CHAR_BIT not defined.  Assuming 8 bits.
    1.99 +#define CHAR_BIT 8
   1.100 +#endif
   1.101 +
   1.102 +/* position of bit within character */
   1.103 +#define BIT_CHAR(bit)         ((bit) / CHAR_BIT)
   1.104 +
   1.105 +/* array index for character containing bit */
   1.106 +//SL: We had to change that macro since bits in our frame buffer are the other way around
   1.107 +//TODO: Find a solution to tackle that problem
   1.108 +//#define BIT_IN_CHAR(bit)      (1 << (CHAR_BIT - 1 - ((bit)  % CHAR_BIT)))
   1.109 +#define BIT_IN_CHAR(bit)      (1 << (((bit)  % CHAR_BIT)))
   1.110 +
   1.111 +/* number of characters required to contain number of bits */
   1.112 +#define BITS_TO_CHARS(bits)   ((((bits) - 1) / CHAR_BIT) + 1)
   1.113 +
   1.114 +/* most significant bit in a character */
   1.115 +#define MS_BIT                (1 << (CHAR_BIT - 1))
   1.116 +
   1.117 +/***************************************************************************
   1.118 +*                                 METHODS
   1.119 +***************************************************************************/
   1.120 +
   1.121 +/***************************************************************************
   1.122 +*   Method     : bit_array_c - constructor
   1.123 +*   Description: This is the bit_array_c constructor.  It reserves memory
   1.124 +*                for the vector storing the array.
   1.125 +*   Parameters : numBits - number of bits in the array
   1.126 +*   Effects    : Allocates vectory for array bits
   1.127 +*   Returned   : None
   1.128 +***************************************************************************/
   1.129 +BitArray::BitArray(const int numBits):
   1.130 +    m_NumBits(numBits),
   1.131 +    m_Array(NULL),
   1.132 +    m_OwnsBuffer(true)
   1.133 +{
   1.134 +    m_SizeInBytes = BITS_TO_CHARS(numBits);
   1.135 +
   1.136 +
   1.137 +    /* allocate space for bit array */
   1.138 +    m_Array = new unsigned char[m_SizeInBytes];
   1.139 +
   1.140 +    /* set all bits to 0 */
   1.141 +    fill_n(m_Array, m_SizeInBytes, 0);
   1.142 +}
   1.143 +
   1.144 +/***************************************************************************
   1.145 +*   Method     : bit_array_c - constructor
   1.146 +*   Description: This is the bit_array_c constructor.  It copies the
   1.147 +*                for contents of a vector of unsigned char into the
   1.148 +*                bitarray.
   1.149 +*   Parameters : vect - vector to be copied
   1.150 +*                numBits - number of bits in the array
   1.151 +*   Effects    : Allocates vectory for array bits
   1.152 +*   Returned   : None
   1.153 +***************************************************************************/
   1.154 +BitArray::BitArray(unsigned char *array, const int numBits,bool aOwnsBuffer):
   1.155 +    m_NumBits(numBits),
   1.156 +    m_Array(array),
   1.157 +    m_OwnsBuffer(aOwnsBuffer)
   1.158 +{
   1.159 +
   1.160 +}
   1.161 +
   1.162 +/***************************************************************************
   1.163 +*   Method     : ~bit_array_c - destructor
   1.164 +*   Description: This is the bit_array_c destructor.  At this point it's
   1.165 +*                just a place holder.
   1.166 +*   Parameters : None
   1.167 +*   Effects    : None
   1.168 +*   Returned   : None
   1.169 +***************************************************************************/
   1.170 +BitArray::~BitArray(void)
   1.171 +{
   1.172 +    if (m_OwnsBuffer)
   1.173 +    {
   1.174 +        delete[] m_Array;
   1.175 +        m_Array = NULL;
   1.176 +    }
   1.177 +}
   1.178 +
   1.179 +/***************************************************************************
   1.180 +*   Method     : Dump
   1.181 +*   Description: This method dumps the conents of a bit array to stdout.
   1.182 +*                The format of the dump is a series of bytes represented in
   1.183 +*                hexadecimal.
   1.184 +*   Parameters : outStream - stream to write to
   1.185 +*   Effects    : Array contents are dumped to stdout
   1.186 +*   Returned   : None
   1.187 +***************************************************************************/
   1.188 +void BitArray::Dump(std::ostream &outStream)
   1.189 +{
   1.190 +    int size;
   1.191 +
   1.192 +    size = BITS_TO_CHARS(m_NumBits);
   1.193 +
   1.194 +    outStream.width(2);
   1.195 +    outStream.fill('0');
   1.196 +    outStream << uppercase << hex << (int)(m_Array[0]);  /* first byte */
   1.197 +
   1.198 +    for (int i = 1; i < size; i++)
   1.199 +    {
   1.200 +        /* remaining bytes with a leading space */
   1.201 +        outStream << " ";
   1.202 +        outStream.width(2);
   1.203 +        outStream.fill('0');
   1.204 +        outStream << (int)(m_Array[i]);
   1.205 +    }
   1.206 +
   1.207 +    outStream << dec;
   1.208 +}
   1.209 +
   1.210 +/***************************************************************************
   1.211 +*   Method     : SetAll
   1.212 +*   Description: This method sets every bit in the bit array to 1.  This
   1.213 +*                method uses UCHAR_MAX to determine what it means to set
   1.214 +*                all bits in an unsigned char, so it is crucial that the
   1.215 +*                machine implementation of unsigned char utilizes all of
   1.216 +*                the bits in the memory allocated for an unsigned char.
   1.217 +*   Parameters : None
   1.218 +*   Effects    : Each of the bits used in the bit array are set to 1.
   1.219 +*                Unused (spare) bits are set to 0.
   1.220 +*   Returned   : None
   1.221 +***************************************************************************/
   1.222 +void BitArray::SetAll(void)
   1.223 +{
   1.224 +    int bits, size;
   1.225 +    unsigned char mask;
   1.226 +
   1.227 +    size = BITS_TO_CHARS(m_NumBits);
   1.228 +
   1.229 +    /* set bits in all bytes to 1 */
   1.230 +    fill_n(m_Array, size, UCHAR_MAX);
   1.231 +
   1.232 +    /* zero any spare bits so increment and decrement are consistent */
   1.233 +    bits = m_NumBits % CHAR_BIT;
   1.234 +    if (bits != 0)
   1.235 +    {
   1.236 +        mask = UCHAR_MAX << (CHAR_BIT - bits);
   1.237 +        m_Array[BIT_CHAR(m_NumBits - 1)] = mask;
   1.238 +    }
   1.239 +}
   1.240 +
   1.241 +/***************************************************************************
   1.242 +*   Method     : ClearAll
   1.243 +*   Description: This method sets every bit in the bit array to 0.
   1.244 +*   Parameters : None
   1.245 +*   Effects    : Each of the bits in the bit array are set to 0.
   1.246 +*   Returned   : None
   1.247 +***************************************************************************/
   1.248 +void BitArray::ClearAll(void)
   1.249 +{
   1.250 +    int size;
   1.251 +
   1.252 +    size = BITS_TO_CHARS(m_NumBits);
   1.253 +
   1.254 +    /* set bits in all bytes to 0 */
   1.255 +    fill_n(m_Array, size, 0);
   1.256 +}
   1.257 +
   1.258 +/***************************************************************************
   1.259 +*   Method     : SetBit
   1.260 +*   Description: This method sets a bit in the bit array to 1.
   1.261 +*   Parameters : bit - the number of the bit to set
   1.262 +*   Effects    : The specified bit will be set to 1.
   1.263 +*   Returned   : None
   1.264 +***************************************************************************/
   1.265 +void BitArray::SetBit(const unsigned int bit)
   1.266 +{
   1.267 +    if (m_NumBits <= bit)
   1.268 +    {
   1.269 +        return;         /* bit out of range */
   1.270 +    }
   1.271 +
   1.272 +    m_Array[BIT_CHAR(bit)] |= BIT_IN_CHAR(bit);
   1.273 +}
   1.274 +
   1.275 +/**
   1.276 +*/
   1.277 +void BitArray::SetBitValue(const unsigned int bit, bool aValue)
   1.278 +	{
   1.279 +	if (aValue)
   1.280 +		{
   1.281 +		SetBit(bit);
   1.282 +		}
   1.283 +	else
   1.284 +		{
   1.285 +		ClearBit(bit);
   1.286 +		}
   1.287 +	}
   1.288 +
   1.289 +/***************************************************************************
   1.290 +*   Method     : ClearBit
   1.291 +*   Description: This method sets a bit in the bit array to 0.
   1.292 +*   Parameters : bit - the number of the bit to clear
   1.293 +*   Effects    : The specified bit will be set to 0.
   1.294 +*   Returned   : None
   1.295 +***************************************************************************/
   1.296 +void BitArray::ClearBit(const unsigned int bit)
   1.297 +{
   1.298 +    unsigned char mask;
   1.299 +
   1.300 +    if (m_NumBits <= bit)
   1.301 +    {
   1.302 +        return;         /* bit out of range */
   1.303 +    }
   1.304 +
   1.305 +    /* create a mask to zero out desired bit */
   1.306 +    mask =  BIT_IN_CHAR(bit);
   1.307 +    mask = ~mask;
   1.308 +
   1.309 +    m_Array[BIT_CHAR(bit)] &= mask;
   1.310 +}
   1.311 +
   1.312 +/***************************************************************************
   1.313 +*   Method     : operator()
   1.314 +*   Description: Overload of the () operator.  This method approximates
   1.315 +*                array indices used for assignment.  It returns a
   1.316 +*                bit_array_index_c which includes an = method used to
   1.317 +*                set bit values.
   1.318 +*   Parameters : bit - index of array bit
   1.319 +*   Effects    : None
   1.320 +*   Returned   : bit_array_index_c (pointer to bit)
   1.321 +***************************************************************************/
   1.322 +BitArrayIndex BitArray::operator()(const unsigned int bit)
   1.323 +{
   1.324 +    BitArrayIndex result(this, bit);
   1.325 +
   1.326 +    return result;
   1.327 +}
   1.328 +
   1.329 +/***************************************************************************
   1.330 +*   Method     : operator[]
   1.331 +*   Description: Overload of the [] operator.  This method returns the
   1.332 +*                value of a bit in the bit array.
   1.333 +*   Parameters : bit - index of array bit
   1.334 +*   Effects    : None
   1.335 +*   Returned   : The value of the specified bit.
   1.336 +***************************************************************************/
   1.337 +bool BitArray::operator[](const unsigned int bit) const
   1.338 +{
   1.339 +    return((m_Array[BIT_CHAR(bit)] & BIT_IN_CHAR(bit)) != 0);
   1.340 +}
   1.341 +
   1.342 +/***************************************************************************
   1.343 +*   Method     : operator==
   1.344 +*   Description: overload of the == operator
   1.345 +*   Parameters : other - bit array to compare
   1.346 +*   Effects    : None
   1.347 +*   Returned   : True if this == other.  Otherwise false.
   1.348 +***************************************************************************/
   1.349 +bool BitArray::operator==(const BitArray &other) const
   1.350 +{
   1.351 +    if (m_NumBits != other.m_NumBits)
   1.352 +    {
   1.353 +        /* unequal sizes */
   1.354 +        return false;
   1.355 +    }
   1.356 +
   1.357 +    return (this->m_Array == other.m_Array);
   1.358 +}
   1.359 +
   1.360 +/***************************************************************************
   1.361 +*   Method     : operator!=
   1.362 +*   Description: overload of the != operator
   1.363 +*   Parameters : other - bit array to compare
   1.364 +*   Effects    : None
   1.365 +*   Returned   : True if this != other.  Otherwise false.
   1.366 +***************************************************************************/
   1.367 +bool BitArray::operator!=(const BitArray &other) const
   1.368 +{
   1.369 +    if (m_NumBits != other.m_NumBits)
   1.370 +    {
   1.371 +        /* unequal sizes */
   1.372 +        return true;
   1.373 +    }
   1.374 +
   1.375 +    return (this->m_Array != other.m_Array);
   1.376 +}
   1.377 +
   1.378 +/***************************************************************************
   1.379 +*   Method     : operator<
   1.380 +*   Description: overload of the < operator
   1.381 +*   Parameters : other - bit array to compare
   1.382 +*   Effects    : None
   1.383 +*   Returned   : True if this < other.  Otherwise false.
   1.384 +***************************************************************************/
   1.385 +bool BitArray::operator<(const BitArray &other) const
   1.386 +{
   1.387 +    if (m_NumBits != other.m_NumBits)
   1.388 +    {
   1.389 +        /* unequal sizes */
   1.390 +        return false;
   1.391 +    }
   1.392 +
   1.393 +    return (this->m_Array < other.m_Array);
   1.394 +}
   1.395 +
   1.396 +/***************************************************************************
   1.397 +*   Method     : operator<=
   1.398 +*   Description: overload of the <= operator
   1.399 +*   Parameters : other - bit array to compare
   1.400 +*   Effects    : None
   1.401 +*   Returned   : True if this <= other.  Otherwise false.
   1.402 +***************************************************************************/
   1.403 +bool BitArray::operator<=(const BitArray &other) const
   1.404 +{
   1.405 +    if (m_NumBits != other.m_NumBits)
   1.406 +    {
   1.407 +        /* unequal sizes */
   1.408 +        return false;
   1.409 +    }
   1.410 +
   1.411 +    return (this->m_Array <= other.m_Array);
   1.412 +}
   1.413 +
   1.414 +/***************************************************************************
   1.415 +*   Method     : operator>
   1.416 +*   Description: overload of the > operator
   1.417 +*   Parameters : other - bit array to compare
   1.418 +*   Effects    : None
   1.419 +*   Returned   : True if this > other.  Otherwise false.
   1.420 +***************************************************************************/
   1.421 +bool BitArray::operator>(const BitArray &other) const
   1.422 +{
   1.423 +    if (m_NumBits != other.m_NumBits)
   1.424 +    {
   1.425 +        /* unequal sizes */
   1.426 +        return false;
   1.427 +    }
   1.428 +
   1.429 +    return (this->m_Array > other.m_Array);
   1.430 +}
   1.431 +
   1.432 +/***************************************************************************
   1.433 +*   Method     : operator>=
   1.434 +*   Description: overload of the >= operator
   1.435 +*   Parameters : other - bit array to compare
   1.436 +*   Effects    : None
   1.437 +*   Returned   : True if this >= other.  Otherwise false.
   1.438 +***************************************************************************/
   1.439 +bool BitArray::operator>=(const BitArray &other) const
   1.440 +{
   1.441 +    if (m_NumBits != other.m_NumBits)
   1.442 +    {
   1.443 +        /* unequal sizes */
   1.444 +        return false;
   1.445 +    }
   1.446 +
   1.447 +    return (this->m_Array >= other.m_Array);
   1.448 +}
   1.449 +
   1.450 +/***************************************************************************
   1.451 +*   Method     : operator~
   1.452 +*   Description: overload of the ~ operator.  Negates all non-spare bits in
   1.453 +*                bit array
   1.454 +*   Parameters : None
   1.455 +*   Effects    : None
   1.456 +*   Returned   : value of this after bitwise not
   1.457 +***************************************************************************/
   1.458 +BitArray BitArray::operator~(void) const
   1.459 +{
   1.460 +    BitArray result(this->m_NumBits);
   1.461 +    result = *this;
   1.462 +    result.Not();
   1.463 +
   1.464 +    return result;
   1.465 +}
   1.466 +
   1.467 +/***************************************************************************
   1.468 +*   Method     : operator&
   1.469 +*   Description: overload of the & operator.  Performs a bitwise and
   1.470 +*                between the source array and this bit array.
   1.471 +*   Parameters : other - bit array on righthand side of &
   1.472 +*   Effects    : None
   1.473 +*   Returned   : value of bitwise and of this and other.
   1.474 +***************************************************************************/
   1.475 +BitArray BitArray::operator&(const BitArray &other) const
   1.476 +{
   1.477 +    BitArray result(this->m_NumBits);
   1.478 +    result = *this;
   1.479 +    result &= other;
   1.480 +
   1.481 +    return result;
   1.482 +}
   1.483 +
   1.484 +
   1.485 +/***************************************************************************
   1.486 +*   Method     : operator^
   1.487 +*   Description: overload of the ^ operator.  Performs a bitwise xor
   1.488 +*                between the source array and this bit array.
   1.489 +*   Parameters : other - bit array on righthand side of ^
   1.490 +*   Effects    : None
   1.491 +*   Returned   : value of bitwise xor of this and other.
   1.492 +***************************************************************************/
   1.493 +BitArray BitArray::operator^(const BitArray &other) const
   1.494 +{
   1.495 +    BitArray result(this->m_NumBits);
   1.496 +    result = *this;
   1.497 +    result ^= other;
   1.498 +
   1.499 +    return result;
   1.500 +}
   1.501 +
   1.502 +/***************************************************************************
   1.503 +*   Method     : operator|
   1.504 +*   Description: overload of the | operator.  Performs a bitwise or
   1.505 +*                between the source array and this bit array.
   1.506 +*   Parameters : other - bit array on righthand side of |
   1.507 +*   Effects    : None
   1.508 +*   Returned   : value of bitwise or of this and other.
   1.509 +***************************************************************************/
   1.510 +BitArray BitArray::operator|(const BitArray &other) const
   1.511 +{
   1.512 +    BitArray result(this->m_NumBits);
   1.513 +    result = *this;
   1.514 +    result |= other;
   1.515 +
   1.516 +    return result;
   1.517 +}
   1.518 +
   1.519 +/***************************************************************************
   1.520 +*   Method     : operator<<
   1.521 +*   Description: overload of the << operator.  Performs a bitwise left
   1.522 +*                shift of this bit array.
   1.523 +*   Parameters : count - the number of bits to shift left
   1.524 +*   Effects    : None
   1.525 +*   Returned   : result of bitwise left shift
   1.526 +***************************************************************************/
   1.527 +BitArray BitArray::operator<<(const unsigned int count) const
   1.528 +{
   1.529 +    BitArray result(this->m_NumBits);
   1.530 +    result = *this;
   1.531 +    result <<= count;
   1.532 +
   1.533 +    return result;
   1.534 +}
   1.535 +
   1.536 +/***************************************************************************
   1.537 +*   Method     : operator>>
   1.538 +*   Description: overload of the >> operator.  Performs a bitwise right
   1.539 +*                shift of this bit array.
   1.540 +*   Parameters : count - the number of bits to shift right
   1.541 +*   Effects    : None
   1.542 +*   Returned   : result of bitwise right shift
   1.543 +***************************************************************************/
   1.544 +BitArray BitArray::operator>>(const unsigned int count) const
   1.545 +{
   1.546 +    BitArray result(this->m_NumBits);
   1.547 +    result = *this;
   1.548 +    result >>= count;
   1.549 +
   1.550 +    return result;
   1.551 +}
   1.552 +
   1.553 +/***************************************************************************
   1.554 +*   Method     : operator++ (prefix)
   1.555 +*   Description: overload of the ++ operator.  Increments the contents of
   1.556 +*                a bit array.  Overflows cause rollover.
   1.557 +*   Parameters : None
   1.558 +*   Effects    : Bit array contents are incremented
   1.559 +*   Returned   : Reference to this array after increment
   1.560 +***************************************************************************/
   1.561 +BitArray& BitArray::operator++(void)
   1.562 +{
   1.563 +    int i;
   1.564 +    unsigned char maxValue;     /* maximum value for current char */
   1.565 +    unsigned char one;          /* least significant bit in current char */
   1.566 +
   1.567 +    if (m_NumBits == 0)
   1.568 +    {
   1.569 +        return *this;           /* nothing to increment */
   1.570 +    }
   1.571 +
   1.572 +    /* handle arrays that don't use every bit in the last character */
   1.573 +    i = (m_NumBits % CHAR_BIT);
   1.574 +    if (i != 0)
   1.575 +    {
   1.576 +        maxValue = UCHAR_MAX << (CHAR_BIT - i);
   1.577 +        one = 1 << (CHAR_BIT - i);
   1.578 +    }
   1.579 +    else
   1.580 +    {
   1.581 +        maxValue = UCHAR_MAX;
   1.582 +        one = 1;
   1.583 +    }
   1.584 +
   1.585 +    for (i = BIT_CHAR(m_NumBits - 1); i >= 0; i--)
   1.586 +    {
   1.587 +        if (m_Array[i] != maxValue)
   1.588 +        {
   1.589 +            m_Array[i] = m_Array[i] + one;
   1.590 +            return *this;
   1.591 +        }
   1.592 +        else
   1.593 +        {
   1.594 +            /* need to carry to next byte */
   1.595 +            m_Array[i] = 0;
   1.596 +
   1.597 +            /* remaining characters must use all bits */
   1.598 +            maxValue = UCHAR_MAX;
   1.599 +            one = 1;
   1.600 +        }
   1.601 +    }
   1.602 +
   1.603 +    return *this;
   1.604 +}
   1.605 +
   1.606 +/***************************************************************************
   1.607 +*   Method     : operator++ (postfix)
   1.608 +*   Description: overload of the ++ operator.  Increments the contents of
   1.609 +*                a bit array.  Overflows cause rollover.
   1.610 +*   Parameters : dumy - needed for postfix increment
   1.611 +*   Effects    : Bit array contents are incremented
   1.612 +*   Returned   : Reference to this array after increment
   1.613 +***************************************************************************/
   1.614 +BitArray& BitArray::operator++(int dummy)
   1.615 +{
   1.616 +    ++(*this);
   1.617 +    return *this;
   1.618 +}
   1.619 +
   1.620 +/***************************************************************************
   1.621 +*   Method     : operator-- (prefix)
   1.622 +*   Description: overload of the -- operator.  Decrements the contents of
   1.623 +*                a bit array.  Underflows cause rollover.
   1.624 +*   Parameters : None
   1.625 +*   Effects    : Bit array contents are decremented
   1.626 +*   Returned   : None
   1.627 +***************************************************************************/
   1.628 +BitArray& BitArray::operator--(void)
   1.629 +{
   1.630 +    int i;
   1.631 +    unsigned char maxValue;     /* maximum value for current char */
   1.632 +    unsigned char one;          /* least significant bit in current char */
   1.633 +
   1.634 +    if (m_NumBits == 0)
   1.635 +    {
   1.636 +        return *this;           /* nothing to decrement */
   1.637 +    }
   1.638 +
   1.639 +    /* handle arrays that don't use every bit in the last character */
   1.640 +    i = (m_NumBits % CHAR_BIT);
   1.641 +    if (i != 0)
   1.642 +    {
   1.643 +        maxValue = UCHAR_MAX << (CHAR_BIT - i);
   1.644 +        one = 1 << (CHAR_BIT - i);
   1.645 +    }
   1.646 +    else
   1.647 +    {
   1.648 +        maxValue = UCHAR_MAX;
   1.649 +        one = 1;
   1.650 +    }
   1.651 +
   1.652 +    for (i = BIT_CHAR(m_NumBits - 1); i >= 0; i--)
   1.653 +    {
   1.654 +        if (m_Array[i] >= one)
   1.655 +        {
   1.656 +            m_Array[i] = m_Array[i] - one;
   1.657 +            return *this;
   1.658 +        }
   1.659 +        else
   1.660 +        {
   1.661 +            /* need to borrow from the next byte */
   1.662 +            m_Array[i] = maxValue;
   1.663 +
   1.664 +            /* remaining characters must use all bits */
   1.665 +            maxValue = UCHAR_MAX;
   1.666 +            one = 1;
   1.667 +        }
   1.668 +    }
   1.669 +
   1.670 +    return *this;
   1.671 +}
   1.672 +
   1.673 +/***************************************************************************
   1.674 +*   Method     : operator-- (postfix)
   1.675 +*   Description: overload of the -- operator.  Decrements the contents of
   1.676 +*                a bit array.  Underflows cause rollover.
   1.677 +*   Parameters : dumy - needed for postfix decrement
   1.678 +*   Effects    : Bit array contents are decremented
   1.679 +*   Returned   : None
   1.680 +***************************************************************************/
   1.681 +BitArray& BitArray::operator--(int dummy)
   1.682 +{
   1.683 +    --(*this);
   1.684 +    return *this;
   1.685 +}
   1.686 +
   1.687 +/***************************************************************************
   1.688 +*   Method     : operator=
   1.689 +*   Description: overload of the = operator.  Copies source contents into
   1.690 +*                this bit array.
   1.691 +*   Parameters : src - Source bit array
   1.692 +*   Effects    : Source bit array contents are copied into this array
   1.693 +*   Returned   : Reference to this array after copy
   1.694 +***************************************************************************/
   1.695 +BitArray& BitArray::operator=(const BitArray &src)
   1.696 +{
   1.697 +    if (*this == src)
   1.698 +    {
   1.699 +        /* don't do anything for a self assignment */
   1.700 +        return *this;
   1.701 +    }
   1.702 +
   1.703 +    if (m_NumBits != src.m_NumBits)
   1.704 +    {
   1.705 +        /* don't do assignment with different array sizes */
   1.706 +        return *this;
   1.707 +    }
   1.708 +
   1.709 +    if ((m_NumBits == 0) || (src.m_NumBits == 0))
   1.710 +    {
   1.711 +        /* don't do assignment with unallocated array */
   1.712 +        return *this;
   1.713 +    }
   1.714 +
   1.715 +    /* copy bits from source */
   1.716 +    int size;
   1.717 +    size = BITS_TO_CHARS(m_NumBits);
   1.718 +
   1.719 +    copy(src.m_Array, &src.m_Array[size], this->m_Array);
   1.720 +    return *this;
   1.721 +}
   1.722 +
   1.723 +/***************************************************************************
   1.724 +*   Method     : operator&=
   1.725 +*   Description: overload of the &= operator.  Performs a bitwise and
   1.726 +*                between the source array and this bit array.  This bit
   1.727 +*                array will contain the result.
   1.728 +*   Parameters : src - Source bit array
   1.729 +*   Effects    : Results of bitwise and are stored in this array
   1.730 +*   Returned   : Reference to this array after and
   1.731 +***************************************************************************/
   1.732 +BitArray& BitArray::operator&=(const BitArray &src)
   1.733 +{
   1.734 +    int size;
   1.735 +
   1.736 +    size = BITS_TO_CHARS(m_NumBits);
   1.737 +
   1.738 +    if (m_NumBits != src.m_NumBits)
   1.739 +    {
   1.740 +        /* don't do assignment with different array sizes */
   1.741 +        return *this;
   1.742 +    }
   1.743 +
   1.744 +    /* AND array one unsigned char at a time */
   1.745 +    for(int i = 0; i < size; i++)
   1.746 +    {
   1.747 +        m_Array[i] = m_Array[i] & src.m_Array[i];
   1.748 +    }
   1.749 +
   1.750 +    return *this;
   1.751 +}
   1.752 +
   1.753 +/***************************************************************************
   1.754 +*   Method     : operator^=
   1.755 +*   Description: overload of the ^= operator.  Performs a bitwise xor
   1.756 +*                between the source array and this bit array.  This bit
   1.757 +*                array will contain the result.
   1.758 +*   Parameters : src - Source bit array
   1.759 +*   Effects    : Results of bitwise xor are stored in this array
   1.760 +*   Returned   : Reference to this array after xor
   1.761 +***************************************************************************/
   1.762 +BitArray& BitArray::operator^=(const BitArray &src)
   1.763 +{
   1.764 +    int size;
   1.765 +
   1.766 +    size = BITS_TO_CHARS(m_NumBits);
   1.767 +
   1.768 +    if (m_NumBits != src.m_NumBits)
   1.769 +    {
   1.770 +        /* don't do assignment with different array sizes */
   1.771 +        return *this;
   1.772 +    }
   1.773 +
   1.774 +    /* XOR array one unsigned char at a time */
   1.775 +    for(int i = 0; i < size; i++)
   1.776 +    {
   1.777 +        m_Array[i] = m_Array[i] ^ src.m_Array[i];
   1.778 +    }
   1.779 +
   1.780 +    return *this;
   1.781 +}
   1.782 +
   1.783 +/***************************************************************************
   1.784 +*   Method     : operator|=
   1.785 +*   Description: overload of the |= operator.  Performs a bitwise or
   1.786 +*                between the source array and this bit array.  This bit
   1.787 +*                array will contain the result.
   1.788 +*   Parameters : src - Source bit array
   1.789 +*   Effects    : Results of bitwise or are stored in this array
   1.790 +*   Returned   : Reference to this array after or
   1.791 +***************************************************************************/
   1.792 +BitArray& BitArray::operator|=(const BitArray &src)
   1.793 +{
   1.794 +    int size;
   1.795 +
   1.796 +    size = BITS_TO_CHARS(m_NumBits);
   1.797 +
   1.798 +    if (m_NumBits != src.m_NumBits)
   1.799 +    {
   1.800 +        /* don't do assignment with different array sizes */
   1.801 +        return *this;
   1.802 +    }
   1.803 +
   1.804 +    /* OR array one unsigned char at a time */
   1.805 +    for(int i = 0; i < size; i++)
   1.806 +    {
   1.807 +        m_Array[i] = m_Array[i] | src.m_Array[i];
   1.808 +    }
   1.809 +
   1.810 +    return *this;
   1.811 +}
   1.812 +
   1.813 +/***************************************************************************
   1.814 +*   Method     : Not
   1.815 +*   Description: Negates all non-spare bits in bit array.
   1.816 +*   Parameters : None
   1.817 +*   Effects    : Contents of bit array are negated.  Any spare bits are
   1.818 +*                left at 0.
   1.819 +*   Returned   : Reference to this array after not
   1.820 +***************************************************************************/
   1.821 +BitArray& BitArray::Not(void)
   1.822 +{
   1.823 +    int bits;
   1.824 +    unsigned char mask;
   1.825 +    int size;
   1.826 +
   1.827 +    size = BITS_TO_CHARS(m_NumBits);
   1.828 +
   1.829 +    if (m_NumBits == 0)
   1.830 +    {
   1.831 +        /* don't do not with unallocated array */
   1.832 +        return *this;
   1.833 +    }
   1.834 +
   1.835 +    /* NOT array one unsigned char at a time */
   1.836 +    for(int i = 0; i < size; i++)
   1.837 +    {
   1.838 +        m_Array[i] = ~m_Array[i];
   1.839 +    }
   1.840 +
   1.841 +    /* zero any spare bits so increment and decrement are consistent */
   1.842 +    bits = m_NumBits % CHAR_BIT;
   1.843 +    if (bits != 0)
   1.844 +    {
   1.845 +        mask = UCHAR_MAX << (CHAR_BIT - bits);
   1.846 +        m_Array[BIT_CHAR(m_NumBits - 1)] &= mask;
   1.847 +    }
   1.848 +
   1.849 +    return *this;
   1.850 +}
   1.851 +
   1.852 +/***************************************************************************
   1.853 +*   Method     : operator<<=
   1.854 +*   Description: overload of the <<= operator.  Performs a left shift on
   1.855 +*                this bit array.  This bit array will contain the result.
   1.856 +*   Parameters : shifts - number of bit positions to shift
   1.857 +*   Effects    : Results of the shifts are stored in this array
   1.858 +*   Returned   : Reference to this array after shift
   1.859 +***************************************************************************/
   1.860 +BitArray& BitArray::operator<<=(const unsigned int shifts)
   1.861 +{
   1.862 +    int i;
   1.863 +    int chars = shifts / CHAR_BIT; /* number of whole byte shifts */
   1.864 +
   1.865 +    if (shifts >= m_NumBits)
   1.866 +    {
   1.867 +        /* all bits have been shifted off */
   1.868 +        this->ClearAll();
   1.869 +        return *this;
   1.870 +    }
   1.871 +
   1.872 +    /* first handle big jumps of bytes */
   1.873 +    if (chars > 0)
   1.874 +    {
   1.875 +        int size;
   1.876 +
   1.877 +        size = BITS_TO_CHARS(m_NumBits);
   1.878 +
   1.879 +        for (i = 0; (i + chars) < size; i++)
   1.880 +        {
   1.881 +            m_Array[i] = m_Array[i + chars];
   1.882 +        }
   1.883 +
   1.884 +        /* now zero out new bytes on the right */
   1.885 +        for (i = size; chars > 0; chars--)
   1.886 +        {
   1.887 +            m_Array[i - chars] = 0;
   1.888 +        }
   1.889 +    }
   1.890 +
   1.891 +    /* now we have at most CHAR_BIT - 1 bit shifts across the whole array */
   1.892 +    for (i = 0; i < (int)(shifts % CHAR_BIT); i++)
   1.893 +    {
   1.894 +        for (unsigned int j = 0; j < BIT_CHAR(m_NumBits - 1); j++)
   1.895 +        {
   1.896 +            m_Array[j] <<= 1;
   1.897 +
   1.898 +            /* handle shifts across byte bounds */
   1.899 +            if (m_Array[j + 1] & MS_BIT)
   1.900 +            {
   1.901 +                m_Array[j] |= 0x01;
   1.902 +            }
   1.903 +        }
   1.904 +
   1.905 +        m_Array[BIT_CHAR(m_NumBits - 1)] <<= 1;
   1.906 +    }
   1.907 +
   1.908 +    return *this;
   1.909 +}
   1.910 +
   1.911 +/***************************************************************************
   1.912 +*   Method     : operator>>=
   1.913 +*   Description: overload of the >>= operator.  Performs a right shift on
   1.914 +*                this bit array.  This bit array will contain the result.
   1.915 +*   Parameters : shifts - number of bit positions to shift
   1.916 +*   Effects    : Results of the shifts are stored in this array
   1.917 +*   Returned   : Reference to this array after shift
   1.918 +***************************************************************************/
   1.919 +BitArray& BitArray::operator>>=(const unsigned int shifts)
   1.920 +{
   1.921 +    int i;
   1.922 +    char mask;
   1.923 +    int chars = shifts / CHAR_BIT;  /* number of whole byte shifts */
   1.924 +
   1.925 +    if (shifts >= m_NumBits)
   1.926 +    {
   1.927 +        /* all bits have been shifted off */
   1.928 +        this->ClearAll();
   1.929 +        return *this;
   1.930 +    }
   1.931 +
   1.932 +    /* first handle big jumps of bytes */
   1.933 +    if (chars > 0)
   1.934 +    {
   1.935 +        for (i = BIT_CHAR(m_NumBits - 1); (i - chars) >= 0; i--)
   1.936 +        {
   1.937 +            m_Array[i] = m_Array[i - chars];
   1.938 +        }
   1.939 +
   1.940 +        /* now zero out new bytes on the right */
   1.941 +        for (; chars > 0; chars--)
   1.942 +        {
   1.943 +            m_Array[chars - 1] = 0;
   1.944 +        }
   1.945 +    }
   1.946 +
   1.947 +    /* now we have at most CHAR_BIT - 1 bit shifts across the whole array */
   1.948 +    for (i = 0; i < (int)(shifts % CHAR_BIT); i++)
   1.949 +    {
   1.950 +        for (unsigned int j = BIT_CHAR(m_NumBits - 1); j > 0; j--)
   1.951 +        {
   1.952 +            m_Array[j] >>= 1;
   1.953 +
   1.954 +            /* handle shifts across byte bounds */
   1.955 +            if (m_Array[j - 1] & 0x01)
   1.956 +            {
   1.957 +                m_Array[j] |= MS_BIT;
   1.958 +            }
   1.959 +        }
   1.960 +
   1.961 +        m_Array[0] >>= 1;
   1.962 +    }
   1.963 +
   1.964 +    /***********************************************************************
   1.965 +    * zero any spare bits that are shifted beyond the end of the bit array
   1.966 +    * so that increment and decrement are consistent.
   1.967 +    ***********************************************************************/
   1.968 +    i = m_NumBits % CHAR_BIT;
   1.969 +    if (i != 0)
   1.970 +    {
   1.971 +        mask = UCHAR_MAX << (CHAR_BIT - i);
   1.972 +        m_Array[BIT_CHAR(m_NumBits - 1)] &= mask;
   1.973 +    }
   1.974 +
   1.975 +    return *this;
   1.976 +}
   1.977 +
   1.978 +/***************************************************************************
   1.979 +*   Method     : bit_array_index_c - constructor
   1.980 +*   Description: This is the bit_array_index_c constructor.  It stores a
   1.981 +*                pointer to the bit array and the bit index.
   1.982 +*   Parameters : array - pointer to bit array
   1.983 +*                index - index of bit in array
   1.984 +*   Effects    : Pointer to bit array and bit index are stored.
   1.985 +*   Returned   : None
   1.986 +***************************************************************************/
   1.987 +BitArrayIndex::BitArrayIndex(BitArray *array,
   1.988 +    const unsigned int index)
   1.989 +{
   1.990 +    m_BitArray = array;
   1.991 +    m_Index = index;
   1.992 +}
   1.993 +
   1.994 +/***************************************************************************
   1.995 +*   Method     : operator=
   1.996 +*   Description: overload of the = operator.  Sets the bit array bit to
   1.997 +*                the value of src.
   1.998 +*   Parameters : src - bit value
   1.999 +*   Effects    : Bit pointed to by this object is set to the value of
  1.1000 +*                source.
  1.1001 +*   Returned   : None
  1.1002 +***************************************************************************/
  1.1003 +void BitArrayIndex::operator=(const bool src)
  1.1004 +{
  1.1005 +    if (m_BitArray == NULL)
  1.1006 +    {
  1.1007 +        return;     /* no array */
  1.1008 +    }
  1.1009 +
  1.1010 +    if (m_BitArray->SizeInBits() <= m_Index)
  1.1011 +    {
  1.1012 +        return;     /* index is out of bounds */
  1.1013 +    }
  1.1014 +
  1.1015 +    if (src)
  1.1016 +    {
  1.1017 +        m_BitArray->SetBit(m_Index);
  1.1018 +    }
  1.1019 +    else
  1.1020 +    {
  1.1021 +        m_BitArray->ClearBit(m_Index);
  1.1022 +    }
  1.1023 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/BitArray.h	Tue Jun 17 09:55:20 2014 +0200
     2.3 @@ -0,0 +1,161 @@
     2.4 +/***************************************************************************
     2.5 +*                         Arrays of Arbitrary Bit Length
     2.6 +*
     2.7 +*   File    : bitarray.h
     2.8 +*   Purpose : Header file for class supporting the creation and
     2.9 +*             manipulation of arbitrary length arrays of bits.
    2.10 +*   Author  : Michael Dipperstein
    2.11 +*   Date    : July 23, 2004
    2.12 +*
    2.13 +****************************************************************************
    2.14 +*   HISTORY
    2.15 +*
    2.16 +*   $Id: bitarray.h,v 1.5 2010/02/04 03:31:43 michael Exp $
    2.17 +*   $Log: bitarray.h,v $
    2.18 +*   Revision 1.5  2010/02/04 03:31:43  michael
    2.19 +*   Replaced vector<unsigned char> with an array of unsigned char.
    2.20 +*
    2.21 +*   Made updates for GCC 4.4.
    2.22 +*
    2.23 +*   Revision 1.4  2007/08/06 05:23:12  michael
    2.24 +*   Updated for LGPL Version 3.
    2.25 +*
    2.26 +*   All methods that don't modify object have been made
    2.27 +*   const to increase functionality of const bit_array_c.
    2.28 +*
    2.29 +*   All assignment operators return a reference to the object being assigned a value so that operator chaining will work.
    2.30 +*
    2.31 +*   Added >> and << operators.
    2.32 +*
    2.33 +*   Revision 1.3  2006/04/30 23:34:07  michael
    2.34 +*   Improved performance by incorporating Benjamin Schindler's
    2.35 +*   <bschindler@student.ethz.ch> changes to pass arguments as a reference.
    2.36 +*
    2.37 +*   Revision 1.2  2004/08/05 22:17:04  michael
    2.38 +*   Add overloads for bitwise operators returning values.
    2.39 +*   Add a more natural looking way to set bit values.
    2.40 +*
    2.41 +*   Revision 1.1.1.1  2004/08/04 13:28:20  michael
    2.42 +*   bit_array_c
    2.43 +*
    2.44 +****************************************************************************
    2.45 +*
    2.46 +* Bitarray: An ANSI C++ class for manipulating arbitrary length bit arrays
    2.47 +* Copyright (C) 2004, 2006-2007, 2010 by
    2.48 +*       Michael Dipperstein (mdipper@alumni.engr.ucsb.edu)
    2.49 +*
    2.50 +* This file is part of the bit array library.
    2.51 +*
    2.52 +* The bit array library is free software; you can redistribute it and/or
    2.53 +* modify it under the terms of the GNU Lesser General Public License as
    2.54 +* published by the Free Software Foundation; either version 3 of the
    2.55 +* License, or (at your option) any later version.
    2.56 +*
    2.57 +* The bit array library is distributed in the hope that it will be useful,
    2.58 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.59 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
    2.60 +* General Public License for more details.
    2.61 +*
    2.62 +* You should have received a copy of the GNU Lesser General Public License
    2.63 +* along with this program.  If not, see <http://www.gnu.org/licenses/>.
    2.64 +*
    2.65 +***************************************************************************/
    2.66 +#ifndef BIT_ARRAY_H
    2.67 +#define BIT_ARRAY_H
    2.68 +
    2.69 +/***************************************************************************
    2.70 +*                             INCLUDED FILES
    2.71 +***************************************************************************/
    2.72 +#include <ostream>
    2.73 +
    2.74 +/***************************************************************************
    2.75 +*                            TYPE DEFINITIONS
    2.76 +***************************************************************************/
    2.77 +class BitArray;
    2.78 +
    2.79 +/**
    2.80 +*/
    2.81 +class BitArrayIndex
    2.82 +{
    2.83 +    public:
    2.84 +        BitArrayIndex(BitArray *array, const unsigned int index);
    2.85 +
    2.86 +        /* assignment */
    2.87 +        void operator=(const bool src);
    2.88 +
    2.89 +    private:
    2.90 +        BitArray *m_BitArray;        /* array index applies to */
    2.91 +        unsigned int m_Index;           /* index of bit in array */
    2.92 +};
    2.93 +
    2.94 +/**
    2.95 +TODO: Derive a Bit Frame class from this one for X Y access to pixels.
    2.96 +*/
    2.97 +class BitArray
    2.98 +{
    2.99 +    public:
   2.100 +        BitArray(const int numBits);
   2.101 +        BitArray(unsigned char *array, const int numBits, bool aOwnsBuffer);
   2.102 +
   2.103 +        virtual ~BitArray(void);
   2.104 +
   2.105 +        void Dump(std::ostream &outStream);
   2.106 +
   2.107 +        const unsigned int SizeInBits() { return m_NumBits; }
   2.108 +        const unsigned int SizeInBytes() { return m_SizeInBytes; }
   2.109 +
   2.110 +        /* set/clear functions */
   2.111 +        void SetAll(void);
   2.112 +        void ClearAll(void);
   2.113 +        void SetBit(const unsigned int bit);
   2.114 +		void SetBitValue(const unsigned int bit, bool aValue);
   2.115 +        void ClearBit(const unsigned int bit);
   2.116 +
   2.117 +        BitArrayIndex operator()(const unsigned int bit);
   2.118 +
   2.119 +        /* boolean operator */
   2.120 +        bool operator[](const unsigned int bit) const;
   2.121 +        bool operator==(const BitArray &other) const;
   2.122 +        bool operator!=(const BitArray &other) const;
   2.123 +        bool operator<(const BitArray &other) const;
   2.124 +        bool operator<=(const BitArray &other) const;
   2.125 +        bool operator>(const BitArray &other) const;
   2.126 +        bool operator>=(const BitArray &other) const;
   2.127 +
   2.128 +        /* bitwise operators */
   2.129 +        BitArray operator&(const BitArray &other) const;
   2.130 +        BitArray operator^(const BitArray &other) const;
   2.131 +        BitArray operator|(const BitArray &other) const;
   2.132 +        BitArray operator~(void) const;
   2.133 +
   2.134 +        BitArray operator<<(const unsigned int count) const;
   2.135 +        BitArray operator>>(const unsigned int count) const;
   2.136 +
   2.137 +        /* increment/decrement */
   2.138 +        BitArray& operator++(void);          /* prefix */
   2.139 +        BitArray& operator++(int dummy);     /* postfix */
   2.140 +        BitArray& operator--(void);          /* prefix */
   2.141 +        BitArray& operator--(int dummy);     /* postfix */
   2.142 +
   2.143 +        /* assignments */
   2.144 +        BitArray& operator=(const BitArray &src);
   2.145 +
   2.146 +        BitArray& operator&=(const BitArray &src);
   2.147 +        BitArray& operator^=(const BitArray &src);
   2.148 +        BitArray& operator|=(const BitArray &src);
   2.149 +        BitArray& Not(void);                 /* negate (~=) */
   2.150 +
   2.151 +        BitArray& operator<<=(unsigned const int shifts);
   2.152 +        BitArray& operator>>=(unsigned const int shifts);
   2.153 +
   2.154 +		unsigned char* Ptr(){return m_Array;}
   2.155 +		const unsigned char* Ptr() const{return m_Array;}
   2.156 +
   2.157 +    protected:
   2.158 +        unsigned int m_NumBits;                 /* number of bits in the array */
   2.159 +		unsigned int m_SizeInBytes;
   2.160 +        unsigned char *m_Array;                 /* vector of characters */
   2.161 +        bool m_OwnsBuffer;
   2.162 +};
   2.163 +
   2.164 +#endif  /* ndef BIT_ARRAY_H */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/FutabaVfd.cpp	Tue Jun 17 09:55:20 2014 +0200
     3.3 @@ -0,0 +1,699 @@
     3.4 +
     3.5 +#include "FutabaVfd.h"
     3.6 +//#include <stdlib.h>
     3.7 +#include <string.h>
     3.8 +
     3.9 +
    3.10 +#ifdef DEBUG_FRAME_DIFF
    3.11 +#include <QImage>
    3.12 +#include <QTextStream>
    3.13 +#endif
    3.14 +
    3.15 +
    3.16 +const int KNumberOfFrameBeforeDiffAlgo = 3;
    3.17 +
    3.18 +//
    3.19 +//
    3.20 +//
    3.21 +
    3.22 +FutabaVfdCommand::FutabaVfdCommand():/*iBuffer(NULL),*/iSize(0),iMaxSize(0)
    3.23 +    {
    3.24 +    }
    3.25 +
    3.26 +FutabaVfdCommand::~FutabaVfdCommand()
    3.27 +    {
    3.28 +    //Delete();
    3.29 +    }
    3.30 +
    3.31 +
    3.32 +/**
    3.33 +
    3.34 +*/
    3.35 +void FutabaVfdCommand::Reset()
    3.36 +    {
    3.37 +    memset(iReports,0,sizeof(iReports));
    3.38 +    }
    3.39 +
    3.40 +
    3.41 +
    3.42 +/**
    3.43 +
    3.44 +*/
    3.45 +/*
    3.46 +void FutabaVfdCommand::Create(int aMaxSize)
    3.47 +    {
    3.48 +    iBuffer=new unsigned char[aMaxSize];
    3.49 +    if (iBuffer)
    3.50 +        {
    3.51 +        iMaxSize = aMaxSize;
    3.52 +        iSize = 0;
    3.53 +        }
    3.54 +    }
    3.55 +*/
    3.56 +
    3.57 +/**
    3.58 +
    3.59 +*/
    3.60 +/*
    3.61 +void FutabaVfdCommand::Delete()
    3.62 +{
    3.63 +    delete[] iBuffer;
    3.64 +    iBuffer = NULL;
    3.65 +    iMaxSize = 0;
    3.66 +    iSize = 0;
    3.67 +}
    3.68 +*/
    3.69 +
    3.70 +
    3.71 +
    3.72 +
    3.73 +//
    3.74 +// class GP1212A01A
    3.75 +//
    3.76 +
    3.77 +GP1212A01A::GP1212A01A():
    3.78 +	iDisplayPositionX(0),iDisplayPositionY(0),
    3.79 +    iOffScreenMode(true),
    3.80 +    iUseFrameDifferencing(true),
    3.81 +    iFrameNext(NULL),
    3.82 +    iFrameCurrent(NULL),
    3.83 +    iFramePrevious(NULL),
    3.84 +    iFrameAlpha(NULL),
    3.85 +    iFrameBeta(NULL),
    3.86 +    iFrameGamma(NULL),
    3.87 +    iNeedFullFrameUpdate(0),
    3.88 +    iRequest(ERequestNone),iPowerOn(false)
    3.89 +	{
    3.90 +	//ResetBuffers();
    3.91 +	}
    3.92 +
    3.93 +/**
    3.94 +*/
    3.95 +GP1212A01A::~GP1212A01A()
    3.96 +	{
    3.97 +    delete iFrameAlpha;
    3.98 +    iFrameAlpha=NULL;
    3.99 +    //
   3.100 +    delete iFrameBeta;
   3.101 +    iFrameBeta=NULL;
   3.102 +    //
   3.103 +    delete iFrameGamma;
   3.104 +    iFrameGamma=NULL;
   3.105 +    //
   3.106 +    iFrameNext=NULL;
   3.107 +    iFrameCurrent=NULL;
   3.108 +    iFramePrevious=NULL;
   3.109 +    //
   3.110 +    iNeedFullFrameUpdate=0;
   3.111 +	}
   3.112 +
   3.113 +/**
   3.114 +*/
   3.115 +int GP1212A01A::Open()
   3.116 +	{
   3.117 +	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
   3.118 +	if (success)
   3.119 +		{
   3.120 +        //Allocate both frames
   3.121 +        delete iFrameAlpha;
   3.122 +        iFrameAlpha=NULL;
   3.123 +        iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount);
   3.124 +        //
   3.125 +        delete iFrameBeta;
   3.126 +        iFrameBeta=NULL;
   3.127 +        iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount);
   3.128 +        //
   3.129 +        delete iFrameGamma;
   3.130 +        iFrameGamma=NULL;
   3.131 +        iFrameGamma=new BitArray(KGP12xFrameBufferPixelCount);
   3.132 +        //
   3.133 +        iFrameNext=iFrameAlpha;
   3.134 +        iFrameCurrent=iFrameBeta;
   3.135 +        iFramePrevious=iFrameGamma;
   3.136 +
   3.137 +
   3.138 +        //To make sure it is synced properly
   3.139 +        iNeedFullFrameUpdate=0;
   3.140 +        //
   3.141 +		SetNonBlocking(1);
   3.142 +        //Since we can't get our display position we force it to our default
   3.143 +		//This makes sure frames are in sync from the start
   3.144 +        //Clever clients will have taken care of putting back frame (0,0) before closing
   3.145 +		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
   3.146 +		}
   3.147 +	return success;
   3.148 +	}
   3.149 +
   3.150 +/**
   3.151 +*/
   3.152 +void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
   3.153 +	{
   3.154 +	//
   3.155 +	//int byteOffset=(aX*HeightInPixels()+aY)/8;
   3.156 +	//int bitOffset=(aX*HeightInPixels()+aY)%8;
   3.157 +    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
   3.158 +
   3.159 +    if (iOffScreenMode)
   3.160 +        {
   3.161 +        if (aOn)
   3.162 +            {
   3.163 +            iFrameNext->SetBit(aX*HeightInPixels()+aY);
   3.164 +            }
   3.165 +        else
   3.166 +            {
   3.167 +            iFrameNext->ClearBit(aX*HeightInPixels()+aY);
   3.168 +            }
   3.169 +        }
   3.170 +    else
   3.171 +        {
   3.172 +        //Just specify a one pixel block
   3.173 +        SetPixelBlock(aX,aY,0x00,0x01,aOn);
   3.174 +        }
   3.175 +	}
   3.176 +
   3.177 +/**
   3.178 +*/
   3.179 +void GP1212A01A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
   3.180 +	{
   3.181 +	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
   3.182 +	for (int i=0;i<aSrcWidth;i++)
   3.183 +		{
   3.184 +		for (int j=0;j<aSrcHeight;j++)
   3.185 +			{
   3.186 +            iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
   3.187 +			}
   3.188 +		}
   3.189 +	}
   3.190 +
   3.191 +/**
   3.192 +Clear our client side back buffer.
   3.193 +Call to SwapBuffers must follow to actually clear the display.
   3.194 +*/
   3.195 +void GP1212A01A::Clear()
   3.196 +    {
   3.197 +    //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
   3.198 +    if (iOffScreenMode)
   3.199 +        {
   3.200 +        iFrameNext->ClearAll();
   3.201 +        }
   3.202 +    else
   3.203 +        {
   3.204 +        SendClearCommand();
   3.205 +        }
   3.206 +    }
   3.207 +
   3.208 +/**
   3.209 +Set all pixels on our screen to the desired value.
   3.210 +This operation is performed off screen to avoid tearing.
   3.211 +@param 8 pixels pattern
   3.212 +*/
   3.213 +void GP1212A01A::SetAllPixels(unsigned char aPattern)
   3.214 +	{
   3.215 +	//With a single buffer
   3.216 +	//unsigned char screen[2048]; //One screen worth of pixels
   3.217 +	//memset(screen,0xFF,sizeof(screen));
   3.218 +	//SetPixelBlock(0,0,63,sizeof(screen),screen);
   3.219 +
   3.220 +
   3.221 +    if (iOffScreenMode)
   3.222 +        {
   3.223 +        memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
   3.224 +        }
   3.225 +    else
   3.226 +        {
   3.227 +        //Using pattern SetPixelBlock variant.
   3.228 +        SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
   3.229 +        }
   3.230 +	//
   3.231 +	}
   3.232 +
   3.233 +
   3.234 +/**
   3.235 +Set the defined pixel block to the given value.
   3.236 +@param X coordinate of our pixel block starting point.
   3.237 +@param Y coordinate of our pixel block starting point.
   3.238 +@param The height of our pixel block.
   3.239 +@param The size of our pixel data. Number of pixels divided by 8.
   3.240 +@param The value set to 8 pixels used as a pattern.
   3.241 +*/
   3.242 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
   3.243 +	{
   3.244 +	OffScreenTranslation(aX,aY);
   3.245 +    FutabaVfdReport report;
   3.246 +    report[0]=0x00; //Report ID
   3.247 +    report[1]=(aSize<=report.Size()-10?aSize+0x08:64); //Report length. -10 is for our header first 10 bytes. +8 is for our Futaba header size
   3.248 +    report[2]=0x1B; //Command ID
   3.249 +    report[3]=0x5B; //Command ID
   3.250 +    report[4]=0xF0; //Command ID
   3.251 +    report[5]=aX;   //X
   3.252 +    report[6]=aY;   //Y
   3.253 +    report[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
   3.254 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   3.255 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   3.256 +    int sizeWritten=MIN(aSize,report.Size()-10);
   3.257 +    memset(report.Buffer()+10, aValue, sizeWritten);
   3.258 +    Write(report);
   3.259 +
   3.260 +    int remainingSize=aSize;
   3.261 +    //We need to keep on sending our pixel data until we are done
   3.262 +    while (report[1]==64)
   3.263 +        {
   3.264 +        report.Reset();
   3.265 +        remainingSize-=sizeWritten;
   3.266 +        report[0]=0x00; //Report ID
   3.267 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   3.268 +        sizeWritten=(report[1]==64?63:report[1]);
   3.269 +        memset(report.Buffer()+2, aValue, sizeWritten);
   3.270 +        Write(report);
   3.271 +        }
   3.272 +	}
   3.273 +
   3.274 +/**
   3.275 +Set the defined pixel block to the given value.
   3.276 +@param X coordinate of our pixel block starting point.
   3.277 +@param Y coordinate of our pixel block starting point.
   3.278 +@param The height of our pixel block.
   3.279 +@param The size of our pixel data. Number of pixels divided by 8.
   3.280 +@param Pointer to our pixel data.
   3.281 +*/
   3.282 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
   3.283 +    {
   3.284 +	OffScreenTranslation(aX,aY);
   3.285 +    FutabaVfdReport report;
   3.286 +    report[0]=0x00; //Report ID
   3.287 +    report[1]=(aSize<=report.Size()-10?aSize+0x08:64); //Report length. -10 is for our header first 10 bytes. +8 is for our Futaba header size
   3.288 +    report[2]=0x1B; //Command ID
   3.289 +    report[3]=0x5B; //Command ID
   3.290 +    report[4]=0xF0; //Command ID
   3.291 +    report[5]=aX;   //X
   3.292 +    report[6]=aY;   //Y
   3.293 +    report[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
   3.294 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   3.295 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   3.296 +    int sizeWritten=MIN(aSize,report.Size()-10);
   3.297 +    memcpy(report.Buffer()+10, aPixels, sizeWritten);
   3.298 +    Write(report);
   3.299 +
   3.300 +    int remainingSize=aSize;
   3.301 +    //We need to keep on sending our pixel data until we are done
   3.302 +    while (report[1]==64)
   3.303 +        {
   3.304 +        report.Reset();
   3.305 +        remainingSize-=sizeWritten;
   3.306 +        report[0]=0x00; //Report ID
   3.307 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   3.308 +        sizeWritten=(report[1]==64?63:report[1]);
   3.309 +        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
   3.310 +        Write(report);
   3.311 +        }
   3.312 +    }
   3.313 +
   3.314 +/**
   3.315 +Using this function is advised against as is causes tearing.
   3.316 +Use Clear instead.
   3.317 +*/
   3.318 +void GP1212A01A::SendClearCommand()
   3.319 +	{
   3.320 +    //1BH,5BH,32H,4AH
   3.321 +    //Send Clear Display Command
   3.322 +	FutabaVfdReport report;
   3.323 +	report[0]=0x00; //Report ID
   3.324 +	report[1]=0x04; //Report length
   3.325 +	report[2]=0x1B; //Command ID
   3.326 +	report[3]=0x5B; //Command ID
   3.327 +	report[4]=0x32; //Command ID
   3.328 +	report[5]=0x4A; //Command ID
   3.329 +	Write(report);
   3.330 +	}
   3.331 +
   3.332 +/**
   3.333 +Change our display position within our buffer.
   3.334 +*/
   3.335 +void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
   3.336 +    {
   3.337 +    //1BH,5BH,Dw,Px,Py
   3.338 +    //Send Display Position Settings Command
   3.339 +    FutabaVfdReport report;
   3.340 +    report[0]=0x00; //Report ID
   3.341 +    report[1]=0x05; //Report length
   3.342 +    report[2]=0x1B; //Command ID
   3.343 +    report[3]=0x5B; //Command ID
   3.344 +    report[4]=aDw;  //Specify our DW
   3.345 +    report[5]=aX;   //X coordinate of our DW top-left corner
   3.346 +    report[6]=aY;   //Y coordinate of our DW top-left corner
   3.347 +    Write(report);
   3.348 +    }
   3.349 +
   3.350 +/**
   3.351 +Change our display position within our buffer.
   3.352 +*/
   3.353 +void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
   3.354 +	{
   3.355 +	//Specs apparently says both DW should remain the same
   3.356 +	//Just don't ask
   3.357 +    SetDisplayPosition(GP1212A01A::DW1,aX,aY);
   3.358 +    SetDisplayPosition(GP1212A01A::DW2,aX,aY);
   3.359 +	iDisplayPositionX=aX;
   3.360 +	iDisplayPositionY=aY;
   3.361 +	}
   3.362 +
   3.363 +/**
   3.364 +Provide Y coordinate of our off screen buffer.
   3.365 +*/
   3.366 +unsigned char GP1212A01A::OffScreenY() const
   3.367 +	{
   3.368 +	//Overflowing is fine this is just what we want
   3.369 +	return iDisplayPositionY+HeightInPixels();
   3.370 +	}
   3.371 +
   3.372 +/**
   3.373 +Put our off screen buffer on screen.
   3.374 +On screen buffer goes off screen.
   3.375 +*/
   3.376 +void GP1212A01A::SwapBuffers()
   3.377 +	{
   3.378 +	//Only perform buffer swapping if off screen mode is enabled
   3.379 +	if (OffScreenMode())
   3.380 +		{
   3.381 +		//Send host back buffer to device back buffer
   3.382 +        if (!iUseFrameDifferencing || iNeedFullFrameUpdate<KNumberOfFrameBeforeDiffAlgo)
   3.383 +            {
   3.384 +            iNeedFullFrameUpdate++;
   3.385 +            SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameNext->Ptr());
   3.386 +            }
   3.387 +        else
   3.388 +            {
   3.389 +            //Frame diff algo is enabled
   3.390 +            //We are going to send to our device only the differences between next frame and previous frame
   3.391 +            SendModifiedPixelBlocks();
   3.392 +            }
   3.393 +		//Swap device front and back buffer
   3.394 +		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   3.395 +
   3.396 +        //Cycle through our frame buffers
   3.397 +        //We keep track of previous frame which is in fact our device back buffer.
   3.398 +        //We can then compare previous and next frame and send only the differences to our device.
   3.399 +        //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
   3.400 +        //Keep our previous frame pointer
   3.401 +        BitArray* previousFrame=iFramePrevious;
   3.402 +        //Current frame becomes the previous one
   3.403 +        iFramePrevious = iFrameCurrent;
   3.404 +        //Next frame becomes the current one
   3.405 +        iFrameCurrent = iFrameNext;
   3.406 +        //Next frame is now our former previous
   3.407 +        iFrameNext = previousFrame;
   3.408 +		}
   3.409 +	}
   3.410 +
   3.411 +
   3.412 +//Define the edge of our pixel block
   3.413 +//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
   3.414 +//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
   3.415 +const int KPixelBlockEdge = 32;
   3.416 +const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
   3.417 +const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
   3.418 +
   3.419 +
   3.420 +/**
   3.421 + * @brief GP1212A01A::SendModifiedPixelBlocks
   3.422 + * Compare our back and front buffer and send to the device only the modified pixels.
   3.423 + */
   3.424 +void GP1212A01A::SendModifiedPixelBlocks()
   3.425 +    {
   3.426 +    int w=WidthInPixels();
   3.427 +    int h=HeightInPixels();
   3.428 +
   3.429 +
   3.430 +    //TODO: optimize with memcmp and 16 inc
   3.431 +    /*
   3.432 +
   3.433 +    for (int i=0;i<w;i++)
   3.434 +        {
   3.435 +        for (int j=0;j<h;j++)
   3.436 +            {
   3.437 +            //aX*HeightInPixels()+aY
   3.438 +            if ((*iFrameNext)[i*h+j]!=(*iFramePrevious)[i*h+j])
   3.439 +                {
   3.440 +                //We need to update that pixel
   3.441 +                SetPixelBlock(i,j,0,1,((*iFrameNext)[i*h+j]?0x01:0x00));
   3.442 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   3.443 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   3.444 +
   3.445 +                //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
   3.446 +                }
   3.447 +            }
   3.448 +        }
   3.449 +    */
   3.450 +
   3.451 +    BitArray nextBlock(KPixelBlockSizeInBits);
   3.452 +    BitArray previousBlock(KPixelBlockSizeInBits);
   3.453 +
   3.454 +    for (int i=0;i<w;i+=KPixelBlockEdge)
   3.455 +        {
   3.456 +        for (int j=0;j<h;j+=KPixelBlockEdge)
   3.457 +            {
   3.458 +            //aX*HeightInPixels()+aY
   3.459 +            //int offset=(i*w/8)+(j/8);
   3.460 +
   3.461 +#ifdef DEBUG_FRAME_DIFF
   3.462 +            QImage imagePrevious(KPixelBlockEdge,KPixelBlockEdge,QImage::Format_RGB32);
   3.463 +            QImage imageNext(KPixelBlockEdge,KPixelBlockEdge,QImage::Format_RGB32);
   3.464 +#endif
   3.465 +
   3.466 +            //Get both our blocks from our buffers
   3.467 +            for (int x=i;x<i+KPixelBlockEdge;x++)
   3.468 +                {
   3.469 +                for (int y=j;y<j+KPixelBlockEdge;y++)
   3.470 +                    {
   3.471 +                    int blockOffset=(x-i)*KPixelBlockEdge+(y-j);
   3.472 +                    int frameOffset=x*h+y;
   3.473 +                    nextBlock.SetBitValue(blockOffset,(*iFrameNext)[frameOffset]);
   3.474 +                    previousBlock.SetBitValue(blockOffset,(*iFramePrevious)[frameOffset]);
   3.475 +
   3.476 +#ifdef DEBUG_FRAME_DIFF
   3.477 +                    imageNext.setPixel(x-i,y-j,(nextBlock[blockOffset]?0xFFFFFFFF:0x00000000));
   3.478 +                    imagePrevious.setPixel(x-i,y-j,(previousBlock[blockOffset]?0xFFFFFFFF:0x00000000));
   3.479 +#endif
   3.480 +                    }
   3.481 +                }
   3.482 +
   3.483 +#ifdef DEBUG_FRAME_DIFF
   3.484 +            QString previousName;
   3.485 +            QString nextName;
   3.486 +            QTextStream(&previousName) << "p" << i << "x" << j << ".png";
   3.487 +            QTextStream(&nextName) << "n" << i << "x" << j << ".png";
   3.488 +            imagePrevious.save(previousName);
   3.489 +            imageNext.save(nextName);
   3.490 +#endif
   3.491 +
   3.492 +
   3.493 +            //if (memcmp(iFrameNext->Ptr()+offset,iFramePrevious->Ptr()+offset,32 )) //32=(16*16/8)
   3.494 +            if (memcmp(nextBlock.Ptr(),previousBlock.Ptr(),KPixelBlockSizeInBytes)!=0)
   3.495 +                {
   3.496 +                //We need to update that block
   3.497 +                SetPixelBlock(i,j,KPixelBlockEdge-1,KPixelBlockSizeInBytes,nextBlock.Ptr());
   3.498 +                //SetPixelBlock(i,j,15,32,0xFF/*nextBlock.Ptr()*/);
   3.499 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   3.500 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   3.501 +
   3.502 +                //SetPixelBlock(i,j,15,32,iFrameNext->Ptr()+offset);
   3.503 +                }
   3.504 +            }
   3.505 +        }
   3.506 +
   3.507 +    }
   3.508 +
   3.509 +/**
   3.510 +Translate the given pixel coordinate according to our off screen mode.
   3.511 +*/
   3.512 +void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
   3.513 +	{
   3.514 +	if (OffScreenMode())
   3.515 +		{
   3.516 +		aX+=WidthInPixels()-iDisplayPositionX;
   3.517 +		aY+=HeightInPixels()-iDisplayPositionY;
   3.518 +		}
   3.519 +	}
   3.520 +
   3.521 +
   3.522 +/**
   3.523 +*/
   3.524 +void GP1212A01A::ResetBuffers()
   3.525 +	{
   3.526 +    //iNextFrame->ClearAll();
   3.527 +    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
   3.528 +	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
   3.529 +	}
   3.530 +
   3.531 +/**
   3.532 +*/
   3.533 +void GP1212A01A::RequestDeviceId()
   3.534 +    {
   3.535 +    if (RequestPending())
   3.536 +        {
   3.537 +        //Abort silently for now
   3.538 +        return;
   3.539 +        }
   3.540 +
   3.541 +    //1BH,5BH,63H,49H,44H
   3.542 +    //Send Read ID command
   3.543 +    FutabaVfdReport report;
   3.544 +    report[0]=0x00; //Report ID
   3.545 +    report[1]=0x05; //Report length
   3.546 +    report[2]=0x1B; //Command ID
   3.547 +    report[3]=0x5B; //Command ID
   3.548 +    report[4]=0x63; //Command ID
   3.549 +    report[5]=0x49; //Command ID
   3.550 +    report[6]=0x44; //Command ID
   3.551 +    if (Write(report)==report.Size())
   3.552 +        {
   3.553 +        iRequest=ERequestDeviceId;
   3.554 +        }
   3.555 +    }
   3.556 +
   3.557 +/**
   3.558 +*/
   3.559 +void GP1212A01A::RequestFirmwareRevision()
   3.560 +    {
   3.561 +    if (RequestPending())
   3.562 +        {
   3.563 +        //Abort silently for now
   3.564 +        return;
   3.565 +        }
   3.566 +
   3.567 +    //1BH,5BH,63H,46H,52H
   3.568 +    //Send Software Revision Read Command
   3.569 +    FutabaVfdReport report;
   3.570 +    report[0]=0x00; //Report ID
   3.571 +    report[1]=0x05; //Report length
   3.572 +    report[2]=0x1B; //Command ID
   3.573 +    report[3]=0x5B; //Command ID
   3.574 +    report[4]=0x63; //Command ID
   3.575 +    report[5]=0x46; //Command ID
   3.576 +    report[6]=0x52; //Command ID
   3.577 +    if (Write(report)==report.Size())
   3.578 +        {
   3.579 +        iRequest=ERequestFirmwareRevision;
   3.580 +        }
   3.581 +    }
   3.582 +
   3.583 +/**
   3.584 +*/
   3.585 +void GP1212A01A::RequestPowerSupplyStatus()
   3.586 +    {
   3.587 +    if (RequestPending())
   3.588 +        {
   3.589 +        //Abort silently for now
   3.590 +        return;
   3.591 +        }
   3.592 +    //1BH,5BH,63H,50H,4DH
   3.593 +    //Send Power Suppply Monitor Command
   3.594 +    FutabaVfdReport report;
   3.595 +    report[0]=0x00; //Report ID
   3.596 +    report[1]=0x05; //Report length
   3.597 +    report[2]=0x1B; //Command ID
   3.598 +    report[3]=0x5B; //Command ID
   3.599 +    report[4]=0x63; //Command ID
   3.600 +    report[5]=0x50; //Command ID
   3.601 +    report[6]=0x4D; //Command ID
   3.602 +    if (Write(report)==report.Size())
   3.603 +        {
   3.604 +        iRequest=ERequestPowerSupplyStatus;
   3.605 +        }
   3.606 +    }
   3.607 +
   3.608 +
   3.609 +/**
   3.610 +This is for development purposes only.
   3.611 +Production application should stick to off-screen mode to avoid tearing.
   3.612 +*/
   3.613 +void GP1212A01A::ToggleOffScreenMode()
   3.614 +	{
   3.615 +    SetOffScreenMode(!iOffScreenMode);
   3.616 +	}
   3.617 +
   3.618 +/**
   3.619 + * @brief GP1212A01A::SetOffScreenMode
   3.620 + * @param aOn
   3.621 + * @return
   3.622 + */
   3.623 +void GP1212A01A::SetOffScreenMode(bool aOn)
   3.624 +    {
   3.625 +    if (aOn==iOffScreenMode)
   3.626 +    {
   3.627 +        //Nothing to do here
   3.628 +        return;
   3.629 +    }
   3.630 +
   3.631 +    iOffScreenMode=aOn;
   3.632 +
   3.633 +    //Clean up our buffers upon switching modes
   3.634 +    SetDisplayPosition(0,0);
   3.635 +    Clear();
   3.636 +    SwapBuffers();
   3.637 +    Clear();
   3.638 +    }
   3.639 +
   3.640 +/**
   3.641 + */
   3.642 +GP1212A01A::Request GP1212A01A::AttemptRequestCompletion()
   3.643 +    {
   3.644 +    if (!RequestPending())
   3.645 +        {
   3.646 +        return ERequestNone;
   3.647 +        }
   3.648 +
   3.649 +    int res=Read(iInputReport);
   3.650 +
   3.651 +    if (!res)
   3.652 +        {
   3.653 +        return ERequestNone;
   3.654 +        }
   3.655 +
   3.656 +    //Process our request
   3.657 +    if (CurrentRequest()==GP1212A01A::ERequestPowerSupplyStatus)
   3.658 +        {
   3.659 +        if (iInputReport[1]==0x4F && iInputReport[2]==0x4E)
   3.660 +            {
   3.661 +            iPowerOn = true;
   3.662 +            }
   3.663 +        else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46)
   3.664 +            {
   3.665 +            iPowerOn = false;
   3.666 +            }
   3.667 +        }
   3.668 +
   3.669 +    Request completed=iRequest;
   3.670 +    //Our request was completed
   3.671 +    iRequest=ERequestNone;
   3.672 +
   3.673 +    return completed;
   3.674 +    }
   3.675 +
   3.676 +
   3.677 +/**
   3.678 +Set our screen brightness.
   3.679 +@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
   3.680 +*/
   3.681 +void GP1212A01A::SetBrightness(int aBrightness)
   3.682 +    {
   3.683 +    if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
   3.684 +        {
   3.685 +        //Brightness out of range.
   3.686 +        //Just ignore that request.
   3.687 +        return;
   3.688 +        }
   3.689 +
   3.690 +    FutabaVfdReport report;
   3.691 +    report[0]=0x00; //Report ID
   3.692 +    report[1]=0x06; //Report size
   3.693 +    report[2]=0x1B; //Command ID
   3.694 +    report[3]=0x5C; //Command ID
   3.695 +    report[4]=0x3F; //Command ID
   3.696 +    report[5]=0x4C; //Command ID
   3.697 +    report[6]=0x44; //Command ID
   3.698 +    report[7]=0x30+aBrightness; //Brightness level
   3.699 +    Write(report);
   3.700 +    }
   3.701 +
   3.702 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/FutabaVfd.h	Tue Jun 17 09:55:20 2014 +0200
     4.3 @@ -0,0 +1,217 @@
     4.4 +//
     4.5 +//
     4.6 +//
     4.7 +
     4.8 +#ifndef FUTABA_VFD_H
     4.9 +#define FUTABA_VFD_H
    4.10 +
    4.11 +#include "hidapi.h"
    4.12 +#include "HidDevice.h"
    4.13 +#include "BitArray.h"
    4.14 +
    4.15 +#ifndef MIN
    4.16 +#define MIN(a,b) (((a)<(b))?(a):(b))
    4.17 +#endif
    4.18 +
    4.19 +#ifndef MAX
    4.20 +#define MAX(a,b) (((a)>(b))?(a):(b))
    4.21 +#endif
    4.22 +
    4.23 +
    4.24 +//This was computed from our number of pixels as follow 256x64/8/64 = 32 + 1 = 33
    4.25 +//+1 was added for our header
    4.26 +const int KFutabaMaxCommandOutputReport = 33;
    4.27 +//TODO: Get ride of that constant once we figure out a way to get it from hidapi
    4.28 +const int KFutabaMaxHidReportSize = 65;
    4.29 +
    4.30 +const int KHidReportIdIndex=0;
    4.31 +const int KFutabaHidReportSizeIndex=1;
    4.32 +//Define Futaba vendor ID to filter our list of device
    4.33 +const unsigned short KFutabaVendorId = 0x1008;
    4.34 +const unsigned short KFutabaProductIdGP1212A01A = 0x100C;
    4.35 +const unsigned short KFutabaProductIdGP1212A02A = 0x1013; //Or is it 0x1015
    4.36 +const int KGP12xWidthInPixels = 256;
    4.37 +const int KGP12xHeightInPixels = 64;
    4.38 +const int KGP12xPixelsPerByte = 8;
    4.39 +const int KGP12xFrameBufferSizeInBytes = KGP12xWidthInPixels*KGP12xHeightInPixels/KGP12xPixelsPerByte; //256*64/8=2048
    4.40 +const int KGP12xFrameBufferPixelCount = KGP12xWidthInPixels*KGP12xHeightInPixels;
    4.41 +
    4.42 +//typedef struct hid_device_info HidDeviceInfo;
    4.43 +
    4.44 +/**
    4.45 +Define a Futaba HID report.
    4.46 +*/
    4.47 +class FutabaVfdReport: public HidReport<KFutabaMaxHidReportSize>
    4.48 +	{
    4.49 +
    4.50 +private:
    4.51 +
    4.52 +	};
    4.53 +
    4.54 +
    4.55 +/**
    4.56 +Define a generic Futaba VFD command.
    4.57 +*/
    4.58 +class FutabaVfdCommand
    4.59 +    {
    4.60 +public:
    4.61 +    FutabaVfdCommand();
    4.62 +    ~FutabaVfdCommand();
    4.63 +    //
    4.64 +    //void Create(int aMaxSize);
    4.65 +    //void Delete();
    4.66 +
    4.67 +    //inline unsigned char& operator[](int aIndex){return iBuffer[aIndex];}
    4.68 +
    4.69 +    void Reset();
    4.70 +
    4.71 +private:
    4.72 +    //unsigned char* iBuffer;
    4.73 +    FutabaVfdReport iReports[KFutabaMaxCommandOutputReport];
    4.74 +    int iSize;
    4.75 +    int iMaxSize;
    4.76 +    };
    4.77 +
    4.78 +/**
    4.79 +*/
    4.80 +class FutabaVfd : public HidDevice
    4.81 +	{
    4.82 +public:
    4.83 +	virtual int MinBrightness() const=0;
    4.84 +	virtual int MaxBrightness() const=0;
    4.85 +	virtual void SetBrightness(int aBrightness)=0;
    4.86 +	virtual void Clear()=0;
    4.87 +	};
    4.88 +
    4.89 +
    4.90 +/**
    4.91 +*/
    4.92 +class FutabaGraphicVfd : public FutabaVfd
    4.93 +	{
    4.94 +public:
    4.95 +	virtual int WidthInPixels() const=0;
    4.96 +	virtual int HeightInPixels() const=0;
    4.97 +	virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn)=0;
    4.98 +	virtual void SetAllPixels(unsigned char aOn)=0;
    4.99 +	virtual int FrameBufferSizeInBytes() const=0;
   4.100 +	//virtual int BitBlit(unsigned char* aSrc, unsigned char aSrcWidth, unsigned char aSrcHeight, unsigned char aTargetX, unsigned char aTargetY) const=0;
   4.101 +
   4.102 +	};
   4.103 +
   4.104 +/**
   4.105 +Common functionality between GP1212A01A and GP1212A02A
   4.106 +*/
   4.107 +class GP1212XXXX : public FutabaGraphicVfd
   4.108 +	{
   4.109 +public:
   4.110 +	//From FutabaVfd
   4.111 +    virtual int MinBrightness() const {return 0;}
   4.112 +    virtual int MaxBrightness() const {return 5;}
   4.113 +	};
   4.114 +
   4.115 +/**
   4.116 +GP1212A01A is a graphic display module using a FUTABA 256x64dots VFD.
   4.117 +The module do not include character ROM, the customer will compile the character
   4.118 +by themselves (from main system).
   4.119 +*/
   4.120 +class GP1212A01A : public GP1212XXXX
   4.121 +	{
   4.122 +public:
   4.123 +    enum Request
   4.124 +        {
   4.125 +        ERequestNone,
   4.126 +        ERequestDeviceId,
   4.127 +        ERequestFirmwareRevision,
   4.128 +        ERequestPowerSupplyStatus
   4.129 +        };
   4.130 +
   4.131 +public:
   4.132 +    GP1212A01A();
   4.133 +    ~GP1212A01A();
   4.134 +
   4.135 +	//
   4.136 +	int Open();
   4.137 +	//From FutabaGraphicVfd
   4.138 +    virtual int WidthInPixels() const {return KGP12xWidthInPixels;}
   4.139 +    virtual int HeightInPixels() const {return KGP12xHeightInPixels;}
   4.140 +	virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn);
   4.141 +	virtual void SetAllPixels(unsigned char aPattern);
   4.142 +    virtual int FrameBufferSizeInBytes() const {return KGP12xFrameBufferSizeInBytes;}
   4.143 +    virtual void BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const;
   4.144 +	//From FutabaVfd
   4.145 +	virtual void SetBrightness(int aBrightness);
   4.146 +	virtual void Clear();
   4.147 +
   4.148 +	//Specific to GP1212A01A
   4.149 +	void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue);
   4.150 +    void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels);
   4.151 +    //Define display position within our display RAM
   4.152 +	void SetDisplayPosition(unsigned char aX, unsigned char aY);
   4.153 +    unsigned char DisplayPositionX() const {return iDisplayPositionX;}
   4.154 +    unsigned char DisplayPositionY() const {return iDisplayPositionY;}
   4.155 +    //
   4.156 +	void SwapBuffers();
   4.157 +    //
   4.158 +    void RequestDeviceId();
   4.159 +    void RequestFirmwareRevision();
   4.160 +    void RequestPowerSupplyStatus();
   4.161 +	//
   4.162 +	void ToggleOffScreenMode();
   4.163 +    void SetOffScreenMode(bool aOn);
   4.164 +    bool OffScreenMode() const {return iOffScreenMode;}
   4.165 +    //
   4.166 +    void SetFrameDifferencing(bool aOn){iUseFrameDifferencing=aOn;}
   4.167 +    bool FrameDifferencing() const {return iUseFrameDifferencing;}
   4.168 +    //
   4.169 +    bool RequestPending(){return iRequest!=ERequestNone;}
   4.170 +    Request CurrentRequest(){return iRequest;}
   4.171 +    void CancelRequest(){iRequest=ERequestNone;}
   4.172 +    Request AttemptRequestCompletion();
   4.173 +    FutabaVfdReport& InputReport() {return iInputReport;}
   4.174 +    bool PowerOn(){return iPowerOn;}
   4.175 +
   4.176 +private:
   4.177 +	enum DW
   4.178 +		{
   4.179 +        DW1=0xC0,
   4.180 +        DW2=0xD0
   4.181 +		};
   4.182 +
   4.183 +	void SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY);
   4.184 +	unsigned char OffScreenY() const;
   4.185 +	void SendClearCommand();
   4.186 +	void OffScreenTranslation(unsigned char& aX, unsigned char& aY);
   4.187 +	void ResetBuffers();
   4.188 +    void SendModifiedPixelBlocks();
   4.189 +
   4.190 +private:
   4.191 +	unsigned char iDisplayPositionX;
   4.192 +	unsigned char iDisplayPositionY;
   4.193 +	///Off screen mode is the recommended default settings to avoid tearing.
   4.194 +	///Though turning it off can be useful for debugging
   4.195 +	bool iOffScreenMode;
   4.196 +    ///Frame differences algo is used to reduce USB bus traffic and improve frame rate in typical use case
   4.197 +    bool iUseFrameDifferencing;
   4.198 +	///
   4.199 +	//FutabaVfdReport iReport;
   4.200 +	///
   4.201 +	//unsigned char iFrameBuffer[256*64];
   4.202 +    BitArray* iFrameNext;
   4.203 +    BitArray* iFrameCurrent;
   4.204 +    BitArray* iFramePrevious;
   4.205 +    //
   4.206 +    BitArray* iFrameAlpha;
   4.207 +    BitArray* iFrameBeta;
   4.208 +    BitArray* iFrameGamma;
   4.209 +    //
   4.210 +    int iNeedFullFrameUpdate;
   4.211 +	//unsigned char iFrameBeta[256*64];
   4.212 +	//unsigned char *iFrontBuffer;
   4.213 +	//unsigned char *iBackBuffer;
   4.214 +    Request iRequest;
   4.215 +    FutabaVfdReport iInputReport;
   4.216 +    bool iPowerOn;
   4.217 +	};
   4.218 +
   4.219 +
   4.220 +#endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/HidDevice.cpp	Tue Jun 17 09:55:20 2014 +0200
     5.3 @@ -0,0 +1,122 @@
     5.4 +//
     5.5 +//
     5.6 +//
     5.7 +
     5.8 +#include "HidDevice.h"
     5.9 +
    5.10 +
    5.11 +
    5.12 +//
    5.13 +// class HidDevice
    5.14 +//
    5.15 +
    5.16 +HidDevice::HidDevice():iHidDevice(NULL)
    5.17 +    {
    5.18 +    Close();
    5.19 +    }
    5.20 +
    5.21 +/**
    5.22 +*/
    5.23 +int HidDevice::Open(const char* aPath)
    5.24 +	{
    5.25 +	Close();
    5.26 +
    5.27 +	iHidDevice =  hid_open_path(aPath);
    5.28 +
    5.29 +	if (!iHidDevice)
    5.30 +		{
    5.31 +		//Fail to connect our device
    5.32 +		return 0;
    5.33 +		}
    5.34 +
    5.35 +    FetchStrings();
    5.36 +
    5.37 +	return 1;
    5.38 +	}
    5.39 +
    5.40 +/**
    5.41 +See hidapi documentation.
    5.42 +*/
    5.43 +int HidDevice::Open(unsigned short aVendorId, unsigned short aProductId, const wchar_t* aSerialNumber)
    5.44 +	{
    5.45 +    Close();
    5.46 +
    5.47 +	iHidDevice = hid_open(aVendorId, aProductId, aSerialNumber);
    5.48 +
    5.49 +	if (!iHidDevice)
    5.50 +		{
    5.51 +		//Fail to connect our device
    5.52 +		return 0;
    5.53 +		}
    5.54 +
    5.55 +    FetchStrings();
    5.56 +
    5.57 +	return 1;
    5.58 +	}
    5.59 +
    5.60 +/**
    5.61 +*/
    5.62 +void HidDevice::Close()
    5.63 +	{
    5.64 +	hid_close(iHidDevice);
    5.65 +	iHidDevice=NULL;
    5.66 +    //
    5.67 +    memset(iVendor,0,sizeof(iVendor));
    5.68 +    memset(iProduct,0,sizeof(iProduct));
    5.69 +    memset(iSerialNumber,0,sizeof(iSerialNumber));
    5.70 +	}
    5.71 +
    5.72 +/**
    5.73 +*/
    5.74 +bool HidDevice::IsOpen()
    5.75 +    {
    5.76 +    return iHidDevice!=NULL;
    5.77 +    }
    5.78 +
    5.79 +
    5.80 +/**
    5.81 +*/
    5.82 +const wchar_t* HidDevice::Error()
    5.83 +	{
    5.84 +	return hid_error(iHidDevice);
    5.85 +	}
    5.86 +
    5.87 +/**
    5.88 +*/
    5.89 +int HidDevice::SetNonBlocking(int aNonBlocking)
    5.90 +	{
    5.91 +	//Success we are now connected to our HID device
    5.92 +	//Set read operation as non blocking
    5.93 +	return hid_set_nonblocking(iHidDevice, aNonBlocking);
    5.94 +	}
    5.95 +
    5.96 +/**
    5.97 +*/
    5.98 +wchar_t* HidDevice::Vendor()
    5.99 +    {
   5.100 +    return iVendor;
   5.101 +    }
   5.102 +
   5.103 +/**
   5.104 +*/
   5.105 +wchar_t* HidDevice::Product()
   5.106 +    {
   5.107 +    return iProduct;
   5.108 +    }
   5.109 +
   5.110 +/**
   5.111 +*/
   5.112 +wchar_t* HidDevice::SerialNumber()
   5.113 +    {
   5.114 +    return iSerialNumber;
   5.115 +    }
   5.116 +
   5.117 +/**
   5.118 +
   5.119 +*/
   5.120 +void HidDevice::FetchStrings()
   5.121 +    {
   5.122 +    hid_get_manufacturer_string(iHidDevice,iVendor,sizeof(iVendor));
   5.123 +    hid_get_product_string(iHidDevice,iProduct,sizeof(iProduct));
   5.124 +    hid_get_serial_number_string(iHidDevice,iSerialNumber,sizeof(iSerialNumber));
   5.125 +    }
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/HidDevice.h	Tue Jun 17 09:55:20 2014 +0200
     6.3 @@ -0,0 +1,69 @@
     6.4 +//
     6.5 +//
     6.6 +//
     6.7 +
     6.8 +#ifndef HID_DEVICE_H
     6.9 +#define HID_DEVICE_H
    6.10 +
    6.11 +#include "HidReport.h"
    6.12 +#include "hidapi.h"
    6.13 +
    6.14 +const int KMaxHidStringChar=256;
    6.15 +
    6.16 +/**
    6.17 +TODO: move to another header
    6.18 +*/
    6.19 +class HidDevice
    6.20 +    {
    6.21 +public:
    6.22 +    HidDevice();
    6.23 +    int Open(const char* aPath);
    6.24 +    int Open(unsigned short aVendorId, unsigned short aProductId, const wchar_t* aSerialNumber);
    6.25 +    void Close();
    6.26 +    bool IsOpen();
    6.27 +    //
    6.28 +    int SetNonBlocking(int aNonBlocking);
    6.29 +    //Read
    6.30 +    template<int S>
    6.31 +    int Read(HidReport<S>& aInputReport);
    6.32 +    //Write
    6.33 +    template<int S>
    6.34 +    int Write(const HidReport<S>& aOutputReport);
    6.35 +    //
    6.36 +    const wchar_t* Error();
    6.37 +    //
    6.38 +    wchar_t* Vendor();
    6.39 +    wchar_t* Product();
    6.40 +    wchar_t* SerialNumber();
    6.41 +
    6.42 +private:
    6.43 +    void FetchStrings();
    6.44 +
    6.45 +private:
    6.46 +    ///Our USB HID device
    6.47 +    hid_device* iHidDevice;
    6.48 +    //
    6.49 +    wchar_t iVendor[KMaxHidStringChar];
    6.50 +    wchar_t iProduct[KMaxHidStringChar];
    6.51 +    wchar_t iSerialNumber[KMaxHidStringChar];
    6.52 +    };
    6.53 +
    6.54 +
    6.55 +/**
    6.56 +*/
    6.57 +template<int S>
    6.58 +int HidDevice::Write(const HidReport<S>& aOutputReport)
    6.59 +    {
    6.60 +    return hid_write(iHidDevice,aOutputReport.Buffer(),S);
    6.61 +    }
    6.62 +
    6.63 +/**
    6.64 +*/
    6.65 +template<int S>
    6.66 +int HidDevice::Read(HidReport<S>& aInputReport)
    6.67 +    {
    6.68 +    return hid_read(iHidDevice,aInputReport.Buffer(),S);
    6.69 +    }
    6.70 +
    6.71 +
    6.72 +#endif
    6.73 \ No newline at end of file
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/HidReport.h	Tue Jun 17 09:55:20 2014 +0200
     7.3 @@ -0,0 +1,31 @@
     7.4 +#ifndef HID_REPORT_H
     7.5 +#define HID_REPORT_H
     7.6 +
     7.7 +#include <string.h>
     7.8 +
     7.9 +/**
    7.10 +Define an HID report.
    7.11 +Can be used as input and output.
    7.12 +*/
    7.13 +template <int S>
    7.14 +class HidReport
    7.15 +    {
    7.16 +public:
    7.17 +    HidReport(){Reset();}
    7.18 +    void Reset();
    7.19 +    inline unsigned char& operator[](int aIndex){return iBuffer[aIndex];}
    7.20 +    const unsigned char* Buffer() const {return iBuffer;}
    7.21 +    unsigned char* Buffer() {return iBuffer;}
    7.22 +    int Size() {return S;}
    7.23 +protected:
    7.24 +    unsigned char iBuffer[S];
    7.25 +    };
    7.26 +
    7.27 +template <int S>
    7.28 +void HidReport<S>::Reset()
    7.29 +    {
    7.30 +    memset(iBuffer,0,sizeof(iBuffer));
    7.31 +    }
    7.32 +
    7.33 +
    7.34 +#endif